Received: by 2002:a25:8b12:0:0:0:0:0 with SMTP id i18csp3423951ybl; Mon, 19 Aug 2019 18:44:27 -0700 (PDT) X-Google-Smtp-Source: APXvYqyAbodb9nnkQueHLRH8Sab8iItVlKp3Q1v0+RZr8+aiAhBVySvrkKm+m/EnShQ0Z23LPILe X-Received: by 2002:a17:902:ff05:: with SMTP id f5mr24727823plj.116.1566265467159; Mon, 19 Aug 2019 18:44:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1566265467; cv=none; d=google.com; s=arc-20160816; b=r4HhhGLAjbjvDh4WazZNLPhlzV4gEism58Z6vwvzEPccLxOTp6tlzAouSDTrP0HGtj Eh+CrRlmrIFuLduqe6uhMpy0Fb+AMuIv2BjXk4Vd9wBIWxonsQd6O0crNPeOfAhFOhzm 3xUnqvWGI6i2h6XXKg5Nz0gAiLlOHhLrx1Crr29UKoEpNrXgTeqri/Sf1rRAfGdPm+M5 iWja4un9mQA1HEwQKTyDn1Qh/IGDVZyw1uFFw+9gp0VRN1loPl5l3nN96H0uXCvGSL7b OdpCFy0RUMdUrjk9kw27sOdUuneFV9Pu6iWhr5w8c8UziG2VFDHQwULOq7o2NBD80nW+ eAGA== 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; bh=IWKQpUIG+ZK85MPQqxw+Tbw9H6FcpHC1MtDmozHnsn8=; b=v/ai72powQrGBlP0+6TCSJuQMUF1/vOCbFxG2wqXRs2O/G7q+jrL2KJi+bpG5mlurX v2yndauBGKQLs1WphMBvxCvpFXo2ZdYvdzzM/gmhs41ko1zwXnLOFiedfHtWu8OieP1g CzVxT9WlWtCBSevYGoHyZExvzyqC2WVC8GBQxH+iGgVcY7K/L1HsxeDS4K9NOz1yKD+Q CmebCcV6M7KcsuLXTbTReX76L8Gg3eZrbBeZopmvnsTEYqEBMdlUwo1IawY6O4JDDXdV eZz9nM5WqB/qD+4SKHmN0XNS/XTCXHCf/oBCaEfuOgZNh2FZ+ZDLmUaRD5/6I5YG7Ku6 8Cuw== 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mediatek.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b6si11202943pla.196.2019.08.19.18.44.12; Mon, 19 Aug 2019 18:44:27 -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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mediatek.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729013AbfHTBmI (ORCPT + 99 others); Mon, 19 Aug 2019 21:42:08 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:3200 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1728929AbfHTBmH (ORCPT ); Mon, 19 Aug 2019 21:42:07 -0400 X-UUID: 5e7145ab3c2c465b9df9ee402378f479-20190820 X-UUID: 5e7145ab3c2c465b9df9ee402378f479-20190820 Received: from mtkcas08.mediatek.inc [(172.21.101.126)] by mailgw02.mediatek.com (envelope-from ) (Cellopoint E-mail Firewall v4.1.10 Build 0707 with TLS) with ESMTP id 731626874; Tue, 20 Aug 2019 09:42:01 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs08n1.mediatek.inc (172.21.101.55) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Tue, 20 Aug 2019 09:41:58 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via Frontend Transport; Tue, 20 Aug 2019 09:41:58 +0800 From: Sam Shih To: Rob Herring , Mark Rutland , Matthias Brugger , Thierry Reding CC: Ryder Lee , John Crispin , , , , , Sam Shih Subject: [PATCH v4 3/10] pwm: mediatek: allocate the clks array dynamically and fix mt7628 pwm Date: Tue, 20 Aug 2019 09:40:18 +0800 Message-ID: <1566265225-27452-4-git-send-email-sam.shih@mediatek.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1566265225-27452-1-git-send-email-sam.shih@mediatek.com> References: <1566265225-27452-1-git-send-email-sam.shih@mediatek.com> MIME-Version: 1.0 Content-Type: text/plain X-MTK: N Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ryder Lee Instead of using fixed size of arrays, allocate the memory for them based on the information we get from the chips. Also fix mt7628 pwm during configure from userspace. The SoC is legacy MIPS and has no complex clock tree. This patch add property clock-frequency to the SoC specific data and legacy MIPS SoC need to configure it in DT. This property is use for period calculation. Signed-off-by: Ryder Lee Signed-off-by: Sam Shih --- Changes since v4: - Follow reviewers's comments 1. use pc->soc->has_clks to check clocks exist or not. 2. Add error message when probe() unable to get clks - Fixes bug when SoC is old mips which has no complex clock tree. if clocks not exist, use the new property from DT to apply period caculation; otherwise, use clk_get_rate to get clock frequency and apply period caculation. --- drivers/pwm/pwm-mediatek.c | 94 +++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 38 deletions(-) diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c index f9d67fb66adb..a70b69a975c1 100644 --- a/drivers/pwm/pwm-mediatek.c +++ b/drivers/pwm/pwm-mediatek.c @@ -35,25 +35,6 @@ #define PWM_CLK_DIV_MAX 7 -enum { - MTK_CLK_MAIN = 0, - MTK_CLK_TOP, - MTK_CLK_PWM1, - MTK_CLK_PWM2, - MTK_CLK_PWM3, - MTK_CLK_PWM4, - MTK_CLK_PWM5, - MTK_CLK_PWM6, - MTK_CLK_PWM7, - MTK_CLK_PWM8, - MTK_CLK_MAX, -}; - -static const char * const mtk_pwm_clk_name[MTK_CLK_MAX] = { - "main", "top", "pwm1", "pwm2", "pwm3", "pwm4", "pwm5", "pwm6", "pwm7", - "pwm8" -}; - struct mtk_pwm_platform_data { unsigned int fallback_npwms; bool pwm45_fixup; @@ -64,12 +45,17 @@ struct mtk_pwm_platform_data { * struct mtk_pwm_chip - struct representing PWM chip * @chip: linux PWM chip representation * @regs: base address of PWM chip - * @clks: list of clocks + * @clk_top: the top clock generator + * @clk_main: the clock used by PWM core + * @clk_pwms: the clock used by each PWM channel */ struct mtk_pwm_chip { struct pwm_chip chip; void __iomem *regs; - struct clk *clks[MTK_CLK_MAX]; + struct clk *clk_top; + struct clk *clk_main; + struct clk **clk_pwms; + unsigned int clk_freq; const struct mtk_pwm_platform_data *soc; }; @@ -90,24 +76,24 @@ static int mtk_pwm_clk_enable(struct pwm_chip *chip, struct pwm_device *pwm) if (!pc->soc->has_clks) return 0; - ret = clk_prepare_enable(pc->clks[MTK_CLK_TOP]); + ret = clk_prepare_enable(pc->clk_top); if (ret < 0) return ret; - ret = clk_prepare_enable(pc->clks[MTK_CLK_MAIN]); + ret = clk_prepare_enable(pc->clk_main); if (ret < 0) goto disable_clk_top; - ret = clk_prepare_enable(pc->clks[MTK_CLK_PWM1 + pwm->hwpwm]); + ret = clk_prepare_enable(pc->clk_pwms[pwm->hwpwm]); if (ret < 0) goto disable_clk_main; return 0; disable_clk_main: - clk_disable_unprepare(pc->clks[MTK_CLK_MAIN]); + clk_disable_unprepare(pc->clk_main); disable_clk_top: - clk_disable_unprepare(pc->clks[MTK_CLK_TOP]); + clk_disable_unprepare(pc->clk_top); return ret; } @@ -119,9 +105,9 @@ static void mtk_pwm_clk_disable(struct pwm_chip *chip, struct pwm_device *pwm) if (!pc->soc->has_clks) return; - clk_disable_unprepare(pc->clks[MTK_CLK_PWM1 + pwm->hwpwm]); - clk_disable_unprepare(pc->clks[MTK_CLK_MAIN]); - clk_disable_unprepare(pc->clks[MTK_CLK_TOP]); + clk_disable_unprepare(pc->clk_pwms[pwm->hwpwm]); + clk_disable_unprepare(pc->clk_main); + clk_disable_unprepare(pc->clk_top); } static inline u32 mtk_pwm_readl(struct mtk_pwm_chip *chip, unsigned int num, @@ -141,19 +127,24 @@ static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, int duty_ns, int period_ns) { struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); - struct clk *clk = pc->clks[MTK_CLK_PWM1 + pwm->hwpwm]; + unsigned int clk_freq; u32 clkdiv = 0, cnt_period, cnt_duty, reg_width = PWMDWIDTH, reg_thres = PWMTHRES; u64 resolution; int ret; + if (pc->soc->has_clks) + clk_freq = clk_get_rate(pc->clk_pwms[pwm->hwpwm]); + else + clk_freq = pc->clk_freq; + ret = mtk_pwm_clk_enable(chip, pwm); if (ret < 0) return ret; /* Using resolution in picosecond gets accuracy higher */ resolution = (u64)NSEC_PER_SEC * 1000; - do_div(resolution, clk_get_rate(clk)); + do_div(resolution, clk_freq); cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000, resolution); while (cnt_period > 8191) { @@ -229,7 +220,8 @@ static int mtk_pwm_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct mtk_pwm_chip *pc; struct resource *res; - unsigned int i, npwms; + unsigned int npwms; + unsigned int clk_freq; int ret; pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); @@ -255,13 +247,40 @@ static int mtk_pwm_probe(struct platform_device *pdev) } } - for (i = 0; i < npwms + 2 && pc->soc->has_clks; i++) { - pc->clks[i] = devm_clk_get(&pdev->dev, mtk_pwm_clk_name[i]); - if (IS_ERR(pc->clks[i])) { - dev_err(&pdev->dev, "clock: %s fail: %ld\n", - mtk_pwm_clk_name[i], PTR_ERR(pc->clks[i])); - return PTR_ERR(pc->clks[i]); + if (pc->soc->has_clks) { + int i; + + pc->clk_pwms = devm_kcalloc(&pdev->dev, npwms, + sizeof(*pc->clk_pwms), GFP_KERNEL); + if (!pc->clk_pwms) + return -ENOMEM; + + pc->clk_top = devm_clk_get(&pdev->dev, "top"); + if (IS_ERR(pc->clk_top)) + return PTR_ERR(pc->clk_top); + + pc->clk_main = devm_clk_get(&pdev->dev, "main"); + if (IS_ERR(pc->clk_main)) + return PTR_ERR(pc->clk_main); + + for (i = 0; i < npwms; i++) { + char name[8]; + + snprintf(name, sizeof(name), "pwm%d", i + 1); + pc->clk_pwms[i] = devm_clk_get(&pdev->dev, name); + if (IS_ERR(pc->clk_pwms[i])) { + dev_err(&pdev->dev, "failed to get %s\n", name); + return PTR_ERR(pc->clk_pwms[i]); + } + } + } else { + ret = of_property_read_u32(np, "clock-frequency", + &clk_freq); + if (ret < 0) { + dev_err(&pdev->dev, "failed to get clk_freq\n"); + return ret; } + pc->clk_freq = clk_freq; } platform_set_drvdata(pdev, pc); -- 2.17.1