diff mbox series

[v5,03/13] pwm: mediatek: add a property "clock-frequency"

Message ID 1566457123-20791-4-git-send-email-sam.shih@mediatek.com
State Superseded
Headers show
Series Add mt7629 and fix mt7628 pwm | expand

Commit Message

Sam Shih Aug. 22, 2019, 6:58 a.m. UTC
This 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.

We will improve this fix by droping has-clks attribute and using
clock-frequency to do the same thing in a new patch.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Sam Shih <sam.shih@mediatek.com>
---
Changes since v5:
1. Follow reviewer's comments
Make the changes of fix mt7628 pwm as a single patch

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.

Change-Id: Ibbe6d7a4f80b30f60725bcbeca1d02ce7834d28c
---
 drivers/pwm/pwm-mediatek.c | 39 ++++++++++++++++++++++++++++++--------
 1 file changed, 31 insertions(+), 8 deletions(-)

Comments

Uwe Kleine-König Aug. 24, 2019, 12:32 a.m. UTC | #1
Hello Sam,

On Thu, Aug 22, 2019 at 02:58:33PM +0800, Sam Shih wrote:
> This 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.
> 
> We will improve this fix by droping has-clks attribute and using
> clock-frequency to do the same thing in a new patch.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> Signed-off-by: Sam Shih <sam.shih@mediatek.com>

I wonder if instead the platform could provide some dummy and optional
clocks.

You could add a fixed-clock for the clk that is used to determine the
clock rate and switch to devm_clk_get_optional for the others.

Best regards
Uwe
diff mbox series

Patch

diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c
index ebd62629e3fe..1f18bff4800c 100644
--- a/drivers/pwm/pwm-mediatek.c
+++ b/drivers/pwm/pwm-mediatek.c
@@ -65,11 +65,13 @@  struct mtk_pwm_platform_data {
  * @chip: linux PWM chip representation
  * @regs: base address of PWM chip
  * @clks: list of clocks
+ * @clk_freq: the fix clock frequency of legacy MIPS SoC
  */
 struct mtk_pwm_chip {
 	struct pwm_chip chip;
 	void __iomem *regs;
 	struct clk *clks[MTK_CLK_MAX];
+	unsigned int clk_freq;
 	const struct mtk_pwm_platform_data *soc;
 };
 
@@ -141,19 +143,27 @@  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) {
+		struct clk *clk = pc->clks[MTK_CLK_PWM1 + pwm->hwpwm];
+
+		clk_freq = clk_get_rate(clk);
+	} 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) {
@@ -262,13 +272,26 @@  static int mtk_pwm_probe(struct platform_device *pdev)
 		npwms = MTK_CLK_MAX - 2;
 	}
 
-	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) {
+		for (i = 0; i < npwms + 2 ; 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]);
+			}
+		}
+	} else {
+		unsigned int clk_freq;
+
+		ret = of_property_read_u32(np, "clock-frequency", &clk_freq);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "failed to get clock_frequency\n");
+			return ret;
 		}
+		pc->clk_freq = clk_freq;
 	}
 
 	platform_set_drvdata(pdev, pc);