Merge tag 'pwm/for-4.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 23 Aug 2018 22:51:09 +0000 (15:51 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 23 Aug 2018 22:51:09 +0000 (15:51 -0700)
Pull pwm updates from Thierry Reding:
 "This contains mostly minor bug fixes as well as some new chip support
  for existing drivers"

* tag 'pwm/for-4.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm:
  pwm: mediatek: Add MT7628 support
  dt-bindings: pwm: Add MT7628 information
  dt-bindings: pwm: rcar: Add bindings for R-Car E3 support
  pwm: meson: Fix mux clock names
  pwm: stm32-lp: Remove useless loop in stm32_pwm_lp_remove()
  pwm: omap-dmtimer: Return -EPROBE_DEFER if no dmtimer platform data
  pwm: mxs: Switch to SPDX identifier
  dt-bindings: pwm: fsl-ftm: Add compatible string for i.MX8QM
  pwm: fsl-ftm: Enable support for the new SoC i.MX8QM
  pwm: fsl-ftm: Added the support of per-compatible data
  pwm: fsl-ftm: Added a dedicated IP interface clock
  pwm: cros-ec: Switch to SPDX identifier
  pwm: imx: Switch to SPDX identifier
  pwm: tiehrpwm: Fix disabling of output of PWMs
  pwm: tiehrpwm: Don't use emulation mode bits to control PWM output
  pwm: berlin: Don't use broken prescaler values

14 files changed:
Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt
Documentation/devicetree/bindings/pwm/pwm-mediatek.txt
Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt
drivers/pwm/Kconfig
drivers/pwm/pwm-berlin.c
drivers/pwm/pwm-cros-ec.c
drivers/pwm/pwm-fsl-ftm.c
drivers/pwm/pwm-imx.c
drivers/pwm/pwm-mediatek.c
drivers/pwm/pwm-meson.c
drivers/pwm/pwm-mxs.c
drivers/pwm/pwm-omap-dmtimer.c
drivers/pwm/pwm-stm32-lp.c
drivers/pwm/pwm-tiehrpwm.c

index 3899d6a..576ad00 100644 (file)
@@ -16,7 +16,10 @@ modes in device tree.
 
 
 Required properties:
-- compatible: Should be "fsl,vf610-ftm-pwm".
+- compatible : should be "fsl,<soc>-ftm-pwm" and one of the following
+   compatible strings:
+  - "fsl,vf610-ftm-pwm" for PWM compatible with the one integrated on VF610
+  - "fsl,imx8qm-ftm-pwm" for PWM compatible with the one integrated on i.MX8QM
 - reg: Physical base address and length of the controller's registers
 - #pwm-cells: Should be 3. See pwm.txt in this directory for a description of
   the cells format.
index ef8bd3c..991728c 100644 (file)
@@ -5,11 +5,13 @@ Required properties:
    - "mediatek,mt2712-pwm": found on mt2712 SoC.
    - "mediatek,mt7622-pwm": found on mt7622 SoC.
    - "mediatek,mt7623-pwm": found on mt7623 SoC.
+   - "mediatek,mt7628-pwm": found on mt7628 SoC.
  - reg: physical base address and length of the controller's registers.
  - #pwm-cells: must be 2. See pwm.txt in this directory for a description of
    the cell format.
  - clocks: phandle and clock specifier of the PWM reference clock.
- - clock-names: must contain the following:
+ - clock-names: must contain the following, except for MT7628 which
+                has no clocks
    - "top": the top clock generator
    - "main": clock used by the PWM core
    - "pwm1-8": the eight per PWM clocks for mt2712
index 35a3b97..e1ef6af 100644 (file)
@@ -12,6 +12,7 @@ Required Properties:
  - "renesas,pwm-r8a7795": for R-Car H3
  - "renesas,pwm-r8a7796": for R-Car M3-W
  - "renesas,pwm-r8a77965": for R-Car M3-N
+ - "renesas,pwm-r8a77990": for R-Car E3
  - "renesas,pwm-r8a77995": for R-Car D3
 - reg: base address and length of the registers block for the PWM.
 - #pwm-cells: should be 2. See pwm.txt in this directory for a description of
index a4d262d..504d252 100644 (file)
@@ -286,7 +286,7 @@ config PWM_MTK_DISP
 
 config PWM_MEDIATEK
        tristate "MediaTek PWM support"
-       depends on ARCH_MEDIATEK || COMPILE_TEST
+       depends on ARCH_MEDIATEK || RALINK || COMPILE_TEST
        help
          Generic PWM framework driver for Mediatek ARM SoC.
 
index 771859a..7c8d6a1 100644 (file)
 #define BERLIN_PWM_EN                  0x0
 #define  BERLIN_PWM_ENABLE             BIT(0)
 #define BERLIN_PWM_CONTROL             0x4
-#define  BERLIN_PWM_PRESCALE_MASK      0x7
-#define  BERLIN_PWM_PRESCALE_MAX       4096
+/*
+ * The prescaler claims to support 8 different moduli, configured using the
+ * low three bits of PWM_CONTROL. (Sequentially, they are 1, 4, 8, 16, 64,
+ * 256, 1024, and 4096.)  However, the moduli from 4 to 1024 appear to be
+ * implemented by internally shifting TCNT left without adding additional
+ * bits. So, the max TCNT that actually works for a modulus of 4 is 0x3fff;
+ * for 8, 0x1fff; and so on. This means that those moduli are entirely
+ * useless, as we could just do the shift ourselves. The 4096 modulus is
+ * implemented with a real prescaler, so we do use that, but we treat it
+ * as a flag instead of pretending the modulus is actually configurable.
+ */
+#define  BERLIN_PWM_PRESCALE_4096      0x7
 #define  BERLIN_PWM_INVERT_POLARITY    BIT(3)
 #define BERLIN_PWM_DUTY                        0x8
 #define BERLIN_PWM_TCNT                        0xc
@@ -46,10 +56,6 @@ static inline struct berlin_pwm_chip *to_berlin_pwm_chip(struct pwm_chip *chip)
        return container_of(chip, struct berlin_pwm_chip, chip);
 }
 
-static const u32 prescaler_table[] = {
-       1, 4, 8, 16, 64, 256, 1024, 4096
-};
-
 static inline u32 berlin_pwm_readl(struct berlin_pwm_chip *chip,
                                   unsigned int channel, unsigned long offset)
 {
@@ -86,33 +92,32 @@ static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm_dev,
                             int duty_ns, int period_ns)
 {
        struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip);
-       unsigned int prescale;
+       bool prescale_4096 = false;
        u32 value, duty, period;
-       u64 cycles, tmp;
+       u64 cycles;
 
        cycles = clk_get_rate(pwm->clk);
        cycles *= period_ns;
        do_div(cycles, NSEC_PER_SEC);
 
-       for (prescale = 0; prescale < ARRAY_SIZE(prescaler_table); prescale++) {
-               tmp = cycles;
-               do_div(tmp, prescaler_table[prescale]);
+       if (cycles > BERLIN_PWM_MAX_TCNT) {
+               prescale_4096 = true;
+               cycles >>= 12; // Prescaled by 4096
 
-               if (tmp <= BERLIN_PWM_MAX_TCNT)
-                       break;
+               if (cycles > BERLIN_PWM_MAX_TCNT)
+                       return -ERANGE;
        }
 
-       if (tmp > BERLIN_PWM_MAX_TCNT)
-               return -ERANGE;
-
-       period = tmp;
-       cycles = tmp * duty_ns;
+       period = cycles;
+       cycles *= duty_ns;
        do_div(cycles, period_ns);
        duty = cycles;
 
        value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL);
-       value &= ~BERLIN_PWM_PRESCALE_MASK;
-       value |= prescale;
+       if (prescale_4096)
+               value |= BERLIN_PWM_PRESCALE_4096;
+       else
+               value &= ~BERLIN_PWM_PRESCALE_4096;
        berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_CONTROL);
 
        berlin_pwm_writel(pwm, pwm_dev->hwpwm, duty, BERLIN_PWM_DUTY);
index 9c13694..98f6ac6 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (C) 2016 Google, Inc
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2, as published by
- * the Free Software Foundation.
- *
  * Expose a PWM controlled by the ChromeOS EC to the host processor.
+ *
+ * Copyright (C) 2016 Google, Inc.
  */
 
 #include <linux/module.h>
index 557b4ea..883378d 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/pwm.h>
@@ -75,6 +76,10 @@ enum fsl_pwm_clk {
        FSL_PWM_CLK_MAX
 };
 
+struct fsl_ftm_soc {
+       bool has_enable_bits;
+};
+
 struct fsl_pwm_chip {
        struct pwm_chip chip;
 
@@ -87,7 +92,10 @@ struct fsl_pwm_chip {
 
        int period_ns;
 
+       struct clk *ipg_clk;
        struct clk *clk[FSL_PWM_CLK_MAX];
+
+       const struct fsl_ftm_soc *soc;
 };
 
 static inline struct fsl_pwm_chip *to_fsl_chip(struct pwm_chip *chip)
@@ -97,16 +105,32 @@ static inline struct fsl_pwm_chip *to_fsl_chip(struct pwm_chip *chip)
 
 static int fsl_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
 {
+       int ret;
        struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
 
-       return clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]);
+       ret = clk_prepare_enable(fpc->ipg_clk);
+       if (!ret && fpc->soc->has_enable_bits) {
+               mutex_lock(&fpc->lock);
+               regmap_update_bits(fpc->regmap, FTM_SC, BIT(pwm->hwpwm + 16),
+                                  BIT(pwm->hwpwm + 16));
+               mutex_unlock(&fpc->lock);
+       }
+
+       return ret;
 }
 
 static void fsl_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 {
        struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
 
-       clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]);
+       if (fpc->soc->has_enable_bits) {
+               mutex_lock(&fpc->lock);
+               regmap_update_bits(fpc->regmap, FTM_SC, BIT(pwm->hwpwm + 16),
+                                  0);
+               mutex_unlock(&fpc->lock);
+       }
+
+       clk_disable_unprepare(fpc->ipg_clk);
 }
 
 static int fsl_pwm_calculate_default_ps(struct fsl_pwm_chip *fpc,
@@ -363,7 +387,7 @@ static int fsl_pwm_init(struct fsl_pwm_chip *fpc)
 {
        int ret;
 
-       ret = clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]);
+       ret = clk_prepare_enable(fpc->ipg_clk);
        if (ret)
                return ret;
 
@@ -371,7 +395,7 @@ static int fsl_pwm_init(struct fsl_pwm_chip *fpc)
        regmap_write(fpc->regmap, FTM_OUTINIT, 0x00);
        regmap_write(fpc->regmap, FTM_OUTMASK, 0xFF);
 
-       clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]);
+       clk_disable_unprepare(fpc->ipg_clk);
 
        return 0;
 }
@@ -408,6 +432,7 @@ static int fsl_pwm_probe(struct platform_device *pdev)
 
        mutex_init(&fpc->lock);
 
+       fpc->soc = of_device_get_match_data(&pdev->dev);
        fpc->chip.dev = &pdev->dev;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -441,6 +466,15 @@ static int fsl_pwm_probe(struct platform_device *pdev)
        if (IS_ERR(fpc->clk[FSL_PWM_CLK_CNTEN]))
                return PTR_ERR(fpc->clk[FSL_PWM_CLK_CNTEN]);
 
+       /*
+        * ipg_clk is the interface clock for the IP. If not provided, use the
+        * ftm_sys clock as the default.
+        */
+       fpc->ipg_clk = devm_clk_get(&pdev->dev, "ipg");
+       if (IS_ERR(fpc->ipg_clk))
+               fpc->ipg_clk = fpc->clk[FSL_PWM_CLK_SYS];
+
+
        fpc->chip.ops = &fsl_pwm_ops;
        fpc->chip.of_xlate = of_pwm_xlate_with_flags;
        fpc->chip.of_pwm_n_cells = 3;
@@ -480,7 +514,7 @@ static int fsl_pwm_suspend(struct device *dev)
                if (!test_bit(PWMF_REQUESTED, &pwm->flags))
                        continue;
 
-               clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]);
+               clk_disable_unprepare(fpc->ipg_clk);
 
                if (!pwm_is_enabled(pwm))
                        continue;
@@ -503,7 +537,7 @@ static int fsl_pwm_resume(struct device *dev)
                if (!test_bit(PWMF_REQUESTED, &pwm->flags))
                        continue;
 
-               clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]);
+               clk_prepare_enable(fpc->ipg_clk);
 
                if (!pwm_is_enabled(pwm))
                        continue;
@@ -524,8 +558,17 @@ static const struct dev_pm_ops fsl_pwm_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(fsl_pwm_suspend, fsl_pwm_resume)
 };
 
+static const struct fsl_ftm_soc vf610_ftm_pwm = {
+       .has_enable_bits = false,
+};
+
+static const struct fsl_ftm_soc imx8qm_ftm_pwm = {
+       .has_enable_bits = true,
+};
+
 static const struct of_device_id fsl_pwm_dt_ids[] = {
-       { .compatible = "fsl,vf610-ftm-pwm", },
+       { .compatible = "fsl,vf610-ftm-pwm", .data = &vf610_ftm_pwm },
+       { .compatible = "fsl,imx8qm-ftm-pwm", .data = &imx8qm_ftm_pwm },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, fsl_pwm_dt_ids);
index 08cbe81..1d5242c 100644 (file)
@@ -1,10 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * simple driver for PWM (Pulse Width Modulator) controller
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
  * Derived from pxa PWM driver by eric miao <eric.miao@marvell.com>
  */
 
index 328c124..eb6674c 100644 (file)
@@ -57,6 +57,7 @@ static const char * const mtk_pwm_clk_name[MTK_CLK_MAX] = {
 struct mtk_pwm_platform_data {
        unsigned int num_pwms;
        bool pwm45_fixup;
+       bool has_clks;
 };
 
 /**
@@ -86,6 +87,9 @@ static int mtk_pwm_clk_enable(struct pwm_chip *chip, struct pwm_device *pwm)
        struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip);
        int ret;
 
+       if (!pc->soc->has_clks)
+               return 0;
+
        ret = clk_prepare_enable(pc->clks[MTK_CLK_TOP]);
        if (ret < 0)
                return ret;
@@ -112,6 +116,9 @@ static void mtk_pwm_clk_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
        struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip);
 
+       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]);
@@ -239,7 +246,7 @@ static int mtk_pwm_probe(struct platform_device *pdev)
        if (IS_ERR(pc->regs))
                return PTR_ERR(pc->regs);
 
-       for (i = 0; i < data->num_pwms + 2; i++) {
+       for (i = 0; i < data->num_pwms + 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",
@@ -274,22 +281,32 @@ static int mtk_pwm_remove(struct platform_device *pdev)
 static const struct mtk_pwm_platform_data mt2712_pwm_data = {
        .num_pwms = 8,
        .pwm45_fixup = false,
+       .has_clks = true,
 };
 
 static const struct mtk_pwm_platform_data mt7622_pwm_data = {
        .num_pwms = 6,
        .pwm45_fixup = false,
+       .has_clks = true,
 };
 
 static const struct mtk_pwm_platform_data mt7623_pwm_data = {
        .num_pwms = 5,
        .pwm45_fixup = true,
+       .has_clks = true,
+};
+
+static const struct mtk_pwm_platform_data mt7628_pwm_data = {
+       .num_pwms = 4,
+       .pwm45_fixup = true,
+       .has_clks = false,
 };
 
 static const struct of_device_id mtk_pwm_of_match[] = {
        { .compatible = "mediatek,mt2712-pwm", .data = &mt2712_pwm_data },
        { .compatible = "mediatek,mt7622-pwm", .data = &mt7622_pwm_data },
        { .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data },
+       { .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data },
        { },
 };
 MODULE_DEVICE_TABLE(of, mtk_pwm_of_match);
index 822860b..c1ed641 100644 (file)
@@ -458,7 +458,6 @@ static int meson_pwm_init_channels(struct meson_pwm *meson,
                                   struct meson_pwm_channel *channels)
 {
        struct device *dev = meson->chip.dev;
-       struct device_node *np = dev->of_node;
        struct clk_init_data init;
        unsigned int i;
        char name[255];
@@ -467,7 +466,7 @@ static int meson_pwm_init_channels(struct meson_pwm *meson,
        for (i = 0; i < meson->chip.npwm; i++) {
                struct meson_pwm_channel *channel = &channels[i];
 
-               snprintf(name, sizeof(name), "%pOF#mux%u", np, i);
+               snprintf(name, sizeof(name), "%s#mux%u", dev_name(dev), i);
 
                init.name = name;
                init.ops = &clk_mux_ops;
index a6017ad..04c0f6b 100644 (file)
@@ -1,12 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2012 Freescale Semiconductor, Inc.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
  */
 
 #include <linux/clk.h>
index 665da3c..f457986 100644 (file)
@@ -264,8 +264,9 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
 
        timer_pdata = dev_get_platdata(&timer_pdev->dev);
        if (!timer_pdata) {
-               dev_err(&pdev->dev, "dmtimer pdata structure NULL\n");
-               ret = -EINVAL;
+               dev_dbg(&pdev->dev,
+                        "dmtimer pdata structure NULL, deferring probe\n");
+               ret = -EPROBE_DEFER;
                goto put;
        }
 
index 7c13e25..0059b24 100644 (file)
@@ -217,10 +217,8 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev)
 static int stm32_pwm_lp_remove(struct platform_device *pdev)
 {
        struct stm32_pwm_lp *priv = platform_get_drvdata(pdev);
-       unsigned int i;
 
-       for (i = 0; i < priv->chip.npwm; i++)
-               pwm_disable(&priv->chip.pwms[i]);
+       pwm_disable(&priv->chip.pwms[0]);
 
        return pwmchip_remove(&priv->chip);
 }
index 4c22cb3..f7b8a86 100644 (file)
 #define TBCTL                  0x00
 #define TBPRD                  0x0A
 
-#define TBCTL_RUN_MASK         (BIT(15) | BIT(14))
-#define TBCTL_STOP_NEXT                0
-#define TBCTL_STOP_ON_CYCLE    BIT(14)
-#define TBCTL_FREE_RUN         (BIT(15) | BIT(14))
 #define TBCTL_PRDLD_MASK       BIT(3)
 #define TBCTL_PRDLD_SHDW       0
 #define TBCTL_PRDLD_IMDT       BIT(3)
@@ -360,7 +356,7 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
        /* Channels polarity can be configured from action qualifier module */
        configure_polarity(pc, pwm->hwpwm);
 
-       /* Enable TBCLK before enabling PWM device */
+       /* Enable TBCLK */
        ret = clk_enable(pc->tbclk);
        if (ret) {
                dev_err(chip->dev, "Failed to enable TBCLK for %s: %d\n",
@@ -368,9 +364,6 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
                return ret;
        }
 
-       /* Enable time counter for free_run */
-       ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN);
-
        return 0;
 }
 
@@ -388,6 +381,8 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
                aqcsfrc_mask = AQCSFRC_CSFA_MASK;
        }
 
+       /* Update shadow register first before modifying active register */
+       ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
        /*
         * Changes to immediate action on Action Qualifier. This puts
         * Action Qualifier control on PWM output from next TBCLK
@@ -400,9 +395,6 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
        /* Disabling TBCLK on PWM disable */
        clk_disable(pc->tbclk);
 
-       /* Stop Time base counter */
-       ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_STOP_NEXT);
-
        /* Disable clock on PWM disable */
        pm_runtime_put_sync(chip->dev);
 }