Received: by 2002:ac0:bc90:0:0:0:0:0 with SMTP id a16csp437567img; Wed, 20 Mar 2019 03:59:02 -0700 (PDT) X-Google-Smtp-Source: APXvYqw8DbLsGIfhA1wnzH0c5KK+A/bih78rvfWIxsT2SGCU4wWciAxaqiCCTFejTkEyir8bOwm3 X-Received: by 2002:a17:902:8690:: with SMTP id g16mr7293715plo.284.1553079542519; Wed, 20 Mar 2019 03:59:02 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1553079542; cv=none; d=google.com; s=arc-20160816; b=tKIC+6FmDSTLV8d+x8xMha3ZiomDgmmrfKAxzCpLgcB1MHKCrvbQYO2Uux9a8f2ZDa BUBVQOJiQSJiaIPp+JNMgtMXvbq5ZPc19wHHKnvjR2+7/2vFjU1Tu6GitcWg57X+W6O2 mCOIJLKdMmbq6VUmj2FVsszavNx/nrodTGDwsX56DuvW2SJoCwaFgBC68CRZYBmDHDRG FxnsY9aSb3Lw4LYVrENWtxyrUBr8tK3fc5Ptcilu1I8t0dOvR58eHHT0hWjYLJFOlIVa OoBr2ELZv4jJ7Q3yg19X3vY7usO4ZDRj+YfqwiTYtDJEIVCF9+D7mg4dJhA5aN7NHaAV T/Jg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-transfer-encoding:content-disposition:mime-version :references:message-id:subject:cc:to:from:date; bh=zdpT8zrnFoU58IORllVsMPGOxCEzxvFxDcyq3wy6MDk=; b=cgv3L1BO6zzYJro0pcXSgv0AZ+GYpmzSui9xB1I/xgSGYNLZKO/FzF+CUi3zCGKFv/ AoIj0PMdn7O0qWrL8SM+IdYSzZCmkoBuu7Spyi4c7WclAXFfcejZ30tDvSeBlWtgQs28 fIMlPFGQAX791Hpi1FoC+9kdnJd0pZhE+RJs2sCnYpw43ZgagUCnd3S/ZXkNHBSaZICy 3wUW+3I7bX152LGnX9PJ0O9BA3o0nbLGApmQIey+fclwKxI+ph0aj1fVh0modhKAqb6B nvOqDXNMDTDCFrQ6WGtt/xSQ9XXZI3FvL4ovtetZW7W/PtGrfWYB3vkstd0dUccFV+7/ G5FQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id k74si1422840pfb.32.2019.03.20.03.58.46; Wed, 20 Mar 2019 03:59:02 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727868AbfCTK5z (ORCPT + 99 others); Wed, 20 Mar 2019 06:57:55 -0400 Received: from metis.ext.pengutronix.de ([85.220.165.71]:53733 "EHLO metis.ext.pengutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727363AbfCTK5y (ORCPT ); Wed, 20 Mar 2019 06:57:54 -0400 Received: from pty.hi.pengutronix.de ([2001:67c:670:100:1d::c5]) by metis.ext.pengutronix.de with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1h6Yum-0001P8-FD; Wed, 20 Mar 2019 11:57:44 +0100 Received: from ukl by pty.hi.pengutronix.de with local (Exim 4.89) (envelope-from ) id 1h6Yuk-0008QV-Se; Wed, 20 Mar 2019 11:57:42 +0100 Date: Wed, 20 Mar 2019 11:57:42 +0100 From: Uwe =?iso-8859-1?Q?Kleine-K=F6nig?= To: Anson Huang Cc: "thierry.reding@gmail.com" , "robh+dt@kernel.org" , "mark.rutland@arm.com" , "shawnguo@kernel.org" , "s.hauer@pengutronix.de" , "kernel@pengutronix.de" , "festevam@gmail.com" , "linux@armlinux.org.uk" , "otavio@ossystems.com.br" , "stefan@agner.ch" , Leonard Crestez , "schnitzeltony@gmail.com" , Robin Gong , "linux-pwm@vger.kernel.org" , "devicetree@vger.kernel.org" , "linux-arm-kernel@lists.infradead.org" , "linux-kernel@vger.kernel.org" , dl-linux-imx Subject: Re: [PATCH V7 2/5] pwm: Add i.MX TPM PWM driver support Message-ID: <20190320105742.jdabsbcoebbyftqr@pengutronix.de> References: <1553058067-18793-1-git-send-email-Anson.Huang@nxp.com> <1553058067-18793-3-git-send-email-Anson.Huang@nxp.com> <20190320081856.wkw55pmw57i4ifdj@pengutronix.de> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: User-Agent: NeoMutt/20170113 (1.7.2) X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::c5 X-SA-Exim-Mail-From: ukl@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hello Anson, On Wed, Mar 20, 2019 at 10:17:50AM +0000, Anson Huang wrote: > > On Wed, Mar 20, 2019 at 05:06:21AM +0000, Anson Huang wrote: > > > + /* make sure counter is disabled for programming prescale */ > > > + val = readl(tpm->base + PWM_IMX_TPM_SC); > > > + saved_cmod = FIELD_GET(PWM_IMX_TPM_SC_CMOD, val); > > > + if (saved_cmod) { > > > + val &= ~PWM_IMX_TPM_SC_CMOD; > > > + writel(val, tpm->base + PWM_IMX_TPM_SC); > > > > I thought we agreed on not stopping the counter if the PS field isn't changed? > > If the PS field no need to change, the round state should already return the period > equal to current period settings, so this function will NOT be called, right? > > if (real_state.period != tpm->real_period) { > if (tpm->user_count > 1) { > ret = -EBUSY; > goto exit; > } > > pwm_imx_tpm_setup_period(chip, param); > tpm->real_period = real_state.period; > } If the PS field is already right .period might still not match as its value depends on SC.PS and MOD.MOD. > > > + val &= ~PWM_IMX_TPM_SC_PS; > > > + val |= FIELD_PREP(PWM_IMX_TPM_SC_PS, p.prescale); > > > + writel(val, tpm->base + PWM_IMX_TPM_SC); > > > + > > > + /* > > > + * set period count: according to RM, the MOD register is > > > + * updated immediately after CMOD[1:0] = 2b'00 above > > > + */ > > > > So the current period isn't completed? That's wrong. > > So you mean we have to wait for the current period to finish here? > I did NOT know this, so we have to compare the counter value with Yeah, see https://patchwork.ozlabs.org/patch/1021566/ which documents this but waits for feedback by Thierry since some time. > the MOD value until they match then proceed the period change? If the hardware doesn't support you here (usually it does) I think it's not reliable enough to try to sync in software. I assume you can get the right wave form if you don't change SC.PS but only MOD.MOD? So maybe the sanest approach is to refuse changing SC.PS if the PWM is running. Or disable (which also should wait for the current period to finish), poll for the end (or use an irq?) and then setup the new configuration. > > > +{ > > > + struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip); > > > + struct pwm_state c; > > > + u32 val, sc_val; > > > + u64 tmp; > > > + > > > + pwm_imx_tpm_get_state(chip, pwm, &c); > > > + > > > + if (state.duty_cycle != c.duty_cycle) { > > > + /* set duty counter */ > > > + tmp = readl(tpm->base + PWM_IMX_TPM_MOD) & PWM_IMX_TPM_MOD_MOD; > > > + tmp *= state.duty_cycle; > > > + val = DIV_ROUND_CLOSEST_ULL(tmp, state.period); > > > + writel(val, tpm->base + PWM_IMX_TPM_CnV(pwm->hwpwm)); > > > + } > > > + > > > + if (state.enabled != c.enabled) { > > > > This is wrong. If the PWM was running (c.enabled == true) and you are > > supposed to disable (state.enabled == false) you enable the hardware once > > more. > > A little confused here, as the case you assume, inside this block, there is another > check for state.enabled, if it is false, the polarity will be set to channel disabled mode, > the polarity setting is combined together with the enable status here, am I wrong? Ah, you're right. I missed that probably because I saw register accesses after the state.enabled != c.enabled check. > > > + val |= (state.polarity == PWM_POLARITY_NORMAL) ? > > > + FIELD_PREP(PWM_IMX_TPM_CnSC_ELS, 0x2) : > > > + FIELD_PREP(PWM_IMX_TPM_CnSC_ELS, 0x1); > > > > Introduce PWM_IMX_TPM_CnSC_ELS_POLARITY_NORMAL and use it > > together with PWM_IMX_TPM_CnSC_ELS_POLARITY_INVERSED here. If you > > put the FIELD_PREP into the definition the line doesn't get excessively long. > > > > I put the FIELD_PREP into definition, the line still long, but I agree using definition is better. > > #define PWM_IMX_TPM_CnSC_ELS_INVERSED FIELD_PREP(PWM_IMX_TPM_CnSC_ELS, 1) > #define PWM_IMX_TPM_CnSC_ELS_NORMAL FIELD_PREP(PWM_IMX_TPM_CnSC_ELS, 2) > > val |= (state->polarity == PWM_POLARITY_NORMAL) ? > PWM_IMX_TPM_CnSC_ELS_NORMAL : > PWM_IMX_TPM_CnSC_ELS_INVERSED; > > > Maybe also add > > > > #define PWM_IMX_TPM_CnSC_ELS_INACTIVE FIELD_PREP(PWM_IMX_TPM_CnSC_ELS, 0) > > > > I did NOT use the FIELD_PREP(PWM_IMX_TPM_CnSC_ELS, 0) at all, so why add it? > I don't quite understand. You use it implicitly in pwm_imx_tpm_apply_hw() if state.enabled == false and c.enabled == true: val = readl(tpm->base + PWM_IMX_TPM_CnSC(pwm->hwpwm)); val &= ~(PWM_IMX_TPM_CnSC_ELS | ...); ... writel(val, tpm->base + PWM_IMX_TPM_CnSC(pwm->hwpwm)); > > > +static int pwm_imx_tpm_apply(struct pwm_chip *chip, > > > + struct pwm_device *pwm, > > > + struct pwm_state *state) > > > +{ > > > + struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip); > > > + struct imx_tpm_pwm_param param; > > > + struct pwm_state real_state; > > > + int ret; > > > + > > > + ret = pwm_imx_tpm_round_state(chip, ¶m, state, &real_state); > > > + if (ret) > > > + return -EINVAL; > > > + > > > + mutex_lock(&tpm->lock); > > > + > > > + /* > > > + * TPM counter is shared by multiple channels, so > > > + * prescale and period can NOT be modified when > > > + * there are multiple channels in use with different > > > + * period settings. > > > + */ > > > + if (real_state.period != tpm->real_period) { > > > + if (tpm->user_count > 1) { > > > + ret = -EBUSY; > > > + goto exit; > > > + } > > > + > > > + pwm_imx_tpm_config_counter(chip, param); > > > + tpm->real_period = real_state.period; > > > + } > > > > Maybe add a comment that this could still be optimized. For example if > > pwm_imx_tpm_round_state returned prescale = 5 but prescale is currently 6, > > you might still be able to configure > > You meant for multiple users request different period case? In this block, if there is > ONLY one user and the requested period can be met by HW, it will anyway re-configure > the HW for the prescale and period I think, or I did NOT get your point? My idea has a flaw. I thought that if there is another user, the duty_cycle can still be represented if the actually used prescale value is slightly higher. But then there is still a problem with the period length that I missed. So my remark was wrong, sorry for that. Best regards Uwe -- Pengutronix e.K. | Uwe Kleine-K?nig | Industrial Linux Solutions | http://www.pengutronix.de/ |