Received: by 10.192.165.156 with SMTP id m28csp68698imm; Tue, 17 Apr 2018 06:42:59 -0700 (PDT) X-Google-Smtp-Source: AIpwx4/dzl14jSQMvnwuGeFYYfQ4GIkA2+ghCvLJ/lt3Aqd5fbopFndQsB7S+zoRmQ1d8G0xsrUJ X-Received: by 10.101.101.136 with SMTP id u8mr1888928pgv.333.1523972578944; Tue, 17 Apr 2018 06:42:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1523972578; cv=none; d=google.com; s=arc-20160816; b=MnlSmKLGC30l/h41+VPwN8H3PtYXPEuxSAFTzJn8+WNSLdTrPmuHS5tbbd9QKJ4gTh rXKt1OjyW2+JDPqsRxWaQjMsxxit1qNzd6vY2DUt6dkT5jek03G1xBNVJK6ySwgcaniB 77zpLWsfn/JCQQVqWlB8/2AS9PJxzTgWY+SHdvvoZEnCWl2U0E+nXIgWoow4eWxYYfk3 NMFJZbOhl/d9E5FnFw33PaE2MiqNu1KLVN96Uh0+h36Cci23YsqQwC3hhO7wrzq5uL0I 8jH2muAAgIc6fq077lxOCFcXSwqjmNohtVH05OwUV+1Fh4hQdcLjV7f2YVEg1ZbWKV4i DvsA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=eXKPGCAocPOGD64fPrGKD1JaolODADL6ArIAmoXJSYU=; b=RK+q1SffkE2Ms6J/QYxQwo5tEMHzhIbofNPPmmW0PqHfsj4MOHfYrZeYde7T0FLhZP U+hk49fvPnSExpbP2+Ud0bCmUT87A2g0jt+y40BgQns6PGphhvIAss4AFoifqucD72Dy UOKiIWGTLNleuCg8EksR9B7Cza4rJ1qVccpjHmXZe0+2s3utpW4peOB5oQuHlCdfqQ25 /4p9JXvjNPz23TYK3hLbg3z2Lfrxg3KkinGrSRxolB4gl0QMrkBXIfrTYVgkxAOuKs+8 4oDYgxRrwSNusrpm3OuW2fBvZpzHYKVdTCiG1Z4D2bRVF/xp6/O4HURAbcBZqFWMiXOH E7/A== 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 1-v6si13808963plz.279.2018.04.17.06.42.44; Tue, 17 Apr 2018 06:42:58 -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 S1753937AbeDQNkz (ORCPT + 99 others); Tue, 17 Apr 2018 09:40:55 -0400 Received: from mx07-00178001.pphosted.com ([62.209.51.94]:47299 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753537AbeDQNjl (ORCPT ); Tue, 17 Apr 2018 09:39:41 -0400 Received: from pps.filterd (m0046668.ppops.net [127.0.0.1]) by mx07-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w3HDcnBB021170; Tue, 17 Apr 2018 15:39:06 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 2hbd6cy2uw-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Tue, 17 Apr 2018 15:39:06 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 9CE9843; Tue, 17 Apr 2018 13:39:04 +0000 (GMT) Received: from Webmail-eu.st.com (gpxdag5node6.st.com [10.75.127.79]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 7AA9A4ECE; Tue, 17 Apr 2018 13:39:04 +0000 (GMT) Received: from localhost (10.75.127.121) by GPXDAG5NODE6.st.com (10.75.127.79) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Tue, 17 Apr 2018 15:39:03 +0200 From: Fabrice Gasnier To: , CC: , , , , , , , , , , , , Subject: [PATCH v5 5/6] pwm: stm32: use input prescaler to improve period capture Date: Tue, 17 Apr 2018 15:38:32 +0200 Message-ID: <1523972313-28765-6-git-send-email-fabrice.gasnier@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1523972313-28765-1-git-send-email-fabrice.gasnier@st.com> References: <1523972313-28765-1-git-send-email-fabrice.gasnier@st.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.75.127.121] X-ClientProxiedBy: GPXDAG1NODE5.st.com (10.75.127.66) To GPXDAG5NODE6.st.com (10.75.127.79) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-04-17_07:,, signatures=0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Using input prescaler, capture unit will trigger DMA once every configurable /2, /4 or /8 events (rising edge). This helps improve period (only) capture accuracy at high rates. Signed-off-by: Fabrice Gasnier Reviewed-by: Benjamin Gaignard Acked-by: Thierry Reding --- Changes in v2: - Adopt DMA read from MFD core. --- drivers/pwm/pwm-stm32.c | 63 ++++++++++++++++++++++++++++++++++++++-- include/linux/mfd/stm32-timers.h | 1 + 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c index 9a50acd..60bfc07 100644 --- a/drivers/pwm/pwm-stm32.c +++ b/drivers/pwm/pwm-stm32.c @@ -8,6 +8,7 @@ * pwm-atmel.c from Bo Shen */ +#include #include #include #include @@ -168,7 +169,7 @@ static int stm32_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm, struct stm32_pwm *priv = to_stm32_pwm_dev(chip); unsigned long long prd, div, dty; unsigned long rate; - unsigned int psc = 0, scale; + unsigned int psc = 0, icpsc, scale; u32 raw_prd, raw_dty; int ret = 0; @@ -222,6 +223,7 @@ static int stm32_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm, /* * Got a capture. Try to improve accuracy at high rates: * - decrease counter clock prescaler, scale up to max rate. + * - use input prescaler, capture once every /2 /4 or /8 edges. */ if (raw_prd) { u32 max_arr = priv->max_arr - 0x1000; /* arbitrary margin */ @@ -241,8 +243,65 @@ static int stm32_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm, goto stop; } + /* Compute intermediate period not to exceed timeout at low rates */ prd = (unsigned long long)raw_prd * (psc + 1) * NSEC_PER_SEC; - result->period = DIV_ROUND_UP_ULL(prd, rate); + do_div(prd, rate); + + for (icpsc = 0; icpsc < MAX_TIM_ICPSC ; icpsc++) { + /* input prescaler: also keep arbitrary margin */ + if (raw_prd >= (priv->max_arr - 0x1000) >> (icpsc + 1)) + break; + if (prd >= (tmo_ms * NSEC_PER_MSEC) >> (icpsc + 2)) + break; + } + + if (!icpsc) + goto done; + + /* Last chance to improve period accuracy, using input prescaler */ + regmap_update_bits(priv->regmap, + pwm->hwpwm < 2 ? TIM_CCMR1 : TIM_CCMR2, + TIM_CCMR_IC1PSC | TIM_CCMR_IC2PSC, + FIELD_PREP(TIM_CCMR_IC1PSC, icpsc) | + FIELD_PREP(TIM_CCMR_IC2PSC, icpsc)); + + ret = stm32_pwm_raw_capture(priv, pwm, tmo_ms, &raw_prd, &raw_dty); + if (ret) + goto stop; + + if (raw_dty >= (raw_prd >> icpsc)) { + /* + * We may fall here using input prescaler, when input + * capture starts on high side (before falling edge). + * Example with icpsc to capture on each 4 events: + * + * start 1st capture 2nd capture + * v v v + * ___ _____ _____ _____ _____ ____ + * TI1..4 |__| |__| |__| |__| |__| + * v v . . . . . v v + * icpsc1/3: . 0 . 1 . 2 . 3 . 0 + * icpsc2/4: 0 1 2 3 0 + * v v v v + * CCR1/3 ......t0..............................t2 + * CCR2/4 ..t1..............................t1'... + * . . . + * Capture0: .<----------------------------->. + * Capture1: .<-------------------------->. . + * . . . + * Period: .<------> . . + * Low side: .<>. + * + * Result: + * - Period = Capture0 / icpsc + * - Duty = Period - Low side = Period - (Capture0 - Capture1) + */ + raw_dty = (raw_prd >> icpsc) - (raw_prd - raw_dty); + } + +done: + prd = (unsigned long long)raw_prd * (psc + 1) * NSEC_PER_SEC; + result->period = DIV_ROUND_UP_ULL(prd, rate << icpsc); dty = (unsigned long long)raw_dty * (psc + 1) * NSEC_PER_SEC; result->duty_cycle = DIV_ROUND_UP_ULL(dty, rate); stop: diff --git a/include/linux/mfd/stm32-timers.h b/include/linux/mfd/stm32-timers.h index d46f550..9da1d7e 100644 --- a/include/linux/mfd/stm32-timers.h +++ b/include/linux/mfd/stm32-timers.h @@ -82,6 +82,7 @@ #define TIM_DCR_DBL GENMASK(12, 8) /* DMA burst len */ #define MAX_TIM_PSC 0xFFFF +#define MAX_TIM_ICPSC 0x3 #define TIM_CR2_MMS_SHIFT 4 #define TIM_CR2_MMS2_SHIFT 20 #define TIM_SMCR_TS_SHIFT 4 -- 1.9.1