From d7a131d3a4a20e7f03de30e85ae082dd68b4e11c Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Tue, 5 Dec 2017 15:57:21 +0100 Subject: pwm: stm32: Adopt SPDX identifier Add SPDX identifier to make it easier to determine the license of the file. Signed-off-by: Benjamin Gaignard Acked-by: Philippe Ombredanne Signed-off-by: Thierry Reding --- drivers/pwm/pwm-stm32-lp.c | 3 +-- drivers/pwm/pwm-stm32.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/pwm/pwm-stm32-lp.c b/drivers/pwm/pwm-stm32-lp.c index 1ac9e4384142..cbd271e80c3c 100644 --- a/drivers/pwm/pwm-stm32-lp.c +++ b/drivers/pwm/pwm-stm32-lp.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * STM32 Low-Power Timer PWM driver * @@ -5,8 +6,6 @@ * * Author: Gerald Baeza * - * License terms: GNU General Public License (GPL), version 2 - * * Inspired by Gerald Baeza's pwm-stm32 driver */ diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c index 6139512aab7b..be56d7af89c9 100644 --- a/drivers/pwm/pwm-stm32.c +++ b/drivers/pwm/pwm-stm32.c @@ -1,10 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) STMicroelectronics 2016 * * Author: Gerald Baeza * - * License terms: GNU General Public License (GPL), version 2 - * * Inspired by timer-stm32.c from Maxime Coquelin * pwm-atmel.c from Bo Shen */ -- cgit From 6106d888a050567b00cd36933ae80e9a3087e3bb Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 15 Dec 2017 18:29:49 +0100 Subject: pwm: puv3: Delete an error message for a failed memory allocation Omit an extra message for a memory allocation failure in this function. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Thierry Reding --- drivers/pwm/pwm-puv3.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/pwm/pwm-puv3.c b/drivers/pwm/pwm-puv3.c index ed6007b27585..754fd9a98f6b 100644 --- a/drivers/pwm/pwm-puv3.c +++ b/drivers/pwm/pwm-puv3.c @@ -107,10 +107,8 @@ static int pwm_probe(struct platform_device *pdev) int ret; puv3 = devm_kzalloc(&pdev->dev, sizeof(*puv3), GFP_KERNEL); - if (puv3 == NULL) { - dev_err(&pdev->dev, "failed to allocate memory\n"); + if (!puv3) return -ENOMEM; - } puv3->clk = devm_clk_get(&pdev->dev, "OST_CLK"); if (IS_ERR(puv3->clk)) -- cgit From 708aa931bd09459bd3c1bcbcbf1e335087b0c951 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 15 Dec 2017 18:55:11 +0100 Subject: pwm: atmel-tcb: Delete an error message for a failed memory allocation Omit an extra message for a memory allocation failure in this function. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Thierry Reding --- drivers/pwm/pwm-atmel-tcb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c index acd3ce8ecf3f..4fb1be246c44 100644 --- a/drivers/pwm/pwm-atmel-tcb.c +++ b/drivers/pwm/pwm-atmel-tcb.c @@ -401,7 +401,6 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev) tcbpwm = devm_kzalloc(&pdev->dev, sizeof(*tcbpwm), GFP_KERNEL); if (tcbpwm == NULL) { err = -ENOMEM; - dev_err(&pdev->dev, "failed to allocate memory\n"); goto err_free_tc; } -- cgit From 3ba111a0182265b65e303c969294b8033ce9d122 Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Tue, 19 Dec 2017 13:34:59 +0000 Subject: dt-bindings: pwm: renesas-tpu: Document r8a774[35] support Document r8a774[35] specific compatible strings. No driver change is needed as the fallback compatible string "renesas,tpu" activates the right code in the driver. Signed-off-by: Fabrizio Castro Reviewed-by: Biju Das Reviewed-by: Rob Herring Reviewed-by: Geert Uytterhoeven Reviewed-by: Simon Horman Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt index 1aadc804dae4..16e574821668 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt +++ b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt @@ -5,8 +5,10 @@ Required Properties: - compatible: should be one of the following. - "renesas,tpu-r8a73a4": for R8A77A4 (R-Mobile APE6) compatible PWM controller. - "renesas,tpu-r8a7740": for R8A7740 (R-Mobile A1) compatible PWM controller. + - "renesas,tpu-r8a7743": for R8A7743 (RZ/G1M) compatible PWM controller. + - "renesas,tpu-r8a7745": for R8A7745 (RZ/G1E) compatible PWM controller. - "renesas,tpu-r8a7790": for R8A7790 (R-Car H2) compatible PWM controller. - - "renesas,tpu": for generic R-Car TPU PWM controller. + - "renesas,tpu": for generic R-Car and RZ/G1 TPU PWM controller. - reg: Base address and length of each memory resource used by the PWM controller hardware module. -- cgit From 9d7e72858d9d84abbbb49e98e2dafeee2f7fd9b6 Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 20 Dec 2017 11:15:43 +0000 Subject: dt-bindings: pwm: rcar: Document r8a774[35] PWM bindings This patch adds compatible strings specific to r8a774[35], no driver change is needed as the fallback compatible string will activate the right code. Also, this patch replaces the example with a DT snippet used for adding PWM0 support to an r8a7743 based platform as the r8a7743 is now the first platform fully compatible with this driver and its PWM DT nodes refer to up-to-date code. Signed-off-by: Fabrizio Castro Reviewed-by: Biju Das Reviewed-by: Rob Herring Reviewed-by: Geert Uytterhoeven Reviewed-by: Simon Horman Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt index 74c118015980..f3bba592d419 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt +++ b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt @@ -2,6 +2,8 @@ Required Properties: - compatible: should be "renesas,pwm-rcar" and one of the following. + - "renesas,pwm-r8a7743": for RZ/G1M + - "renesas,pwm-r8a7745": for RZ/G1E - "renesas,pwm-r8a7778": for R-Car M1A - "renesas,pwm-r8a7779": for R-Car H1 - "renesas,pwm-r8a7790": for R-Car H2 @@ -17,13 +19,15 @@ Required Properties: - pinctrl-0: phandle, referring to a default pin configuration node. - pinctrl-names: Set to "default". -Example: R8A7790 (R-Car H2) PWM Timer node +Example: R8A7743 (RZ/G1M) PWM Timer node pwm0: pwm@e6e30000 { - compatible = "renesas,pwm-r8a7790", "renesas,pwm-rcar"; + compatible = "renesas,pwm-r8a7743", "renesas,pwm-rcar"; reg = <0 0xe6e30000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A7743_PD_ALWAYS_ON>; + resets = <&cpg 523>; #pwm-cells = <2>; - clocks = <&mstp5_clks R8A7790_CLK_PWM>; pinctrl-0 = <&pwm0_pins>; pinctrl-names = "default"; }; -- cgit From 3b8ad2c1effedf2fed4ad989612386b5cff11289 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 19 Dec 2017 17:02:06 +0100 Subject: dt-bindings: pwm: renesas-tpu: Correct example TPU register block size The Timer Pulse Unit on R-Mobile A1 has registers that lie outside the declared register block. Enlarge the register block size to fix this. Signed-off-by: Geert Uytterhoeven Reviewed-by: Simon Horman Reviewed-by: Rob Herring Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt index 16e574821668..d52e30ed8072 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt +++ b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt @@ -24,6 +24,6 @@ Example: R8A7740 (R-Car A1) TPU controller node tpu: pwm@e6600000 { compatible = "renesas,tpu-r8a7740", "renesas,tpu"; - reg = <0xe6600000 0x100>; + reg = <0xe6600000 0x148>; #pwm-cells = <3>; }; -- cgit From 204e17baa6fd2ec02deca08cdcb60aad77cbd043 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 2 Mar 2018 15:39:45 +0100 Subject: dt-bindings: pwm: renesas-tpu: Correct SoC part numbers and family names R8A73A4 (not R8A77A4) is R-Mobile APE6, R8A7740 is R-Mobile (not R-Car) A1. Signed-off-by: Geert Uytterhoeven Acked-by: Simon Horman Reviewed-by: Rob Herring Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt index d52e30ed8072..d53a16715da6 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt +++ b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt @@ -3,7 +3,7 @@ Required Properties: - compatible: should be one of the following. - - "renesas,tpu-r8a73a4": for R8A77A4 (R-Mobile APE6) compatible PWM controller. + - "renesas,tpu-r8a73a4": for R8A73A4 (R-Mobile APE6) compatible PWM controller. - "renesas,tpu-r8a7740": for R8A7740 (R-Mobile A1) compatible PWM controller. - "renesas,tpu-r8a7743": for R8A7743 (RZ/G1M) compatible PWM controller. - "renesas,tpu-r8a7745": for R8A7745 (RZ/G1E) compatible PWM controller. @@ -20,7 +20,7 @@ Required Properties: Please refer to pwm.txt in this directory for details of the common PWM bindings used by client devices. -Example: R8A7740 (R-Car A1) TPU controller node +Example: R8A7740 (R-Mobile A1) TPU controller node tpu: pwm@e6600000 { compatible = "renesas,tpu-r8a7740", "renesas,tpu"; -- cgit From 1f6eefeb7cd45360397fb5d3f08ce9ec41e80b17 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 2 Jan 2018 11:01:59 -0200 Subject: pwm: imx: Let PWM be active during suspend On a imx6q-cubox-i board, which has an LED driven by PWM, when the system goes into suspend the PWM block is disabled by default, then the PWM pin goes to logic level zero and turn on the LED during suspend, which is not really the behaviour we want to see. By keeping the PWM enabled during suspend via STOPEN bit, the pwm-leds driver sets the brightness to zero in suspend and then the LED is turned off as expected. So always set the STOPEN to fix the PWM behaviour in suspend. Signed-off-by: Fabio Estevam Signed-off-by: Thierry Reding --- drivers/pwm/pwm-imx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c index 2ba5c3a398ff..08cbe8120588 100644 --- a/drivers/pwm/pwm-imx.c +++ b/drivers/pwm/pwm-imx.c @@ -35,6 +35,7 @@ #define MX3_PWMSAR 0x0C /* PWM Sample Register */ #define MX3_PWMPR 0x10 /* PWM Period Register */ #define MX3_PWMCR_PRESCALER(x) ((((x) - 1) & 0xFFF) << 4) +#define MX3_PWMCR_STOPEN (1 << 25) #define MX3_PWMCR_DOZEEN (1 << 24) #define MX3_PWMCR_WAITEN (1 << 23) #define MX3_PWMCR_DBGEN (1 << 22) @@ -210,7 +211,7 @@ static int imx_pwm_apply_v2(struct pwm_chip *chip, struct pwm_device *pwm, writel(period_cycles, imx->mmio_base + MX3_PWMPR); cr = MX3_PWMCR_PRESCALER(prescale) | - MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN | + MX3_PWMCR_STOPEN | MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN | MX3_PWMCR_DBGEN | MX3_PWMCR_CLKSRC_IPG_HIGH | MX3_PWMCR_EN; -- cgit From df56b1712d57863e9686673bb13803dcd8a82f7a Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Sat, 6 Jan 2018 17:58:40 +0100 Subject: pwm: jz4740: Make disable operation compatible with TCU2 mode On the JZ4750 and later SoCs, channel 1 and 2 operate in a different way (TCU2 mode) as the other channels. If a TCU2 mode counter is stopped before its PWM functionality is disabled, the output is not guaranteed to return to the initial level. Signed-off-by: Maarten ter Huurne Signed-off-by: Thierry Reding --- drivers/pwm/pwm-jz4740.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c index a75ff3622450..2e41ba213f39 100644 --- a/drivers/pwm/pwm-jz4740.c +++ b/drivers/pwm/pwm-jz4740.c @@ -71,9 +71,15 @@ static void jz4740_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) { uint32_t ctrl = jz4740_timer_get_ctrl(pwm->hwpwm); + /* Disable PWM output. + * In TCU2 mode (channel 1/2 on JZ4750+), this must be done before the + * counter is stopped, while in TCU1 mode the order does not matter. + */ ctrl &= ~JZ_TIMER_CTRL_PWM_ENABLE; - jz4740_timer_disable(pwm->hwpwm); jz4740_timer_set_ctrl(pwm->hwpwm, ctrl); + + /* Stop counter */ + jz4740_timer_disable(pwm->hwpwm); } static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, -- cgit From 174dcc8eaec5fd53f9d6f3aa3068e8415a9c0d35 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sat, 6 Jan 2018 17:58:41 +0100 Subject: pwm: jz4740: Implement ->set_polarity() This permits clients of this driver to specify the polarity to use for their PWM channel. Signed-off-by: Paul Cercueil Signed-off-by: Thierry Reding --- drivers/pwm/pwm-jz4740.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c index 2e41ba213f39..6539c001fe32 100644 --- a/drivers/pwm/pwm-jz4740.c +++ b/drivers/pwm/pwm-jz4740.c @@ -130,10 +130,29 @@ static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, return 0; } +static int jz4740_pwm_set_polarity(struct pwm_chip *chip, + struct pwm_device *pwm, enum pwm_polarity polarity) +{ + uint32_t ctrl = jz4740_timer_get_ctrl(pwm->pwm); + + switch (polarity) { + case PWM_POLARITY_NORMAL: + ctrl &= ~JZ_TIMER_CTRL_PWM_ACTIVE_LOW; + break; + case PWM_POLARITY_INVERSED: + ctrl |= JZ_TIMER_CTRL_PWM_ACTIVE_LOW; + break; + } + + jz4740_timer_set_ctrl(pwm->hwpwm, ctrl); + return 0; +} + static const struct pwm_ops jz4740_pwm_ops = { .request = jz4740_pwm_request, .free = jz4740_pwm_free, .config = jz4740_pwm_config, + .set_polarity = jz4740_pwm_set_polarity, .enable = jz4740_pwm_enable, .disable = jz4740_pwm_disable, .owner = THIS_MODULE, -- cgit From cc20173304e4f54c0ccabe0c0636b05c2410a4be Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sat, 6 Jan 2018 17:58:42 +0100 Subject: pwm: jz4740: Add support for devicetree Add support for probing the pwm-jz4740 directly from devicetree. Signed-off-by: Paul Cercueil Reviewed-by: Rob Herring Signed-off-by: Thierry Reding --- .../devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt | 25 ++++++++++++++++++++++ drivers/pwm/pwm-jz4740.c | 14 ++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 Documentation/devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt diff --git a/Documentation/devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt b/Documentation/devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt new file mode 100644 index 000000000000..7d9d3f90641b --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt @@ -0,0 +1,25 @@ +Ingenic JZ47xx PWM Controller +============================= + +Required properties: +- compatible: One of: + * "ingenic,jz4740-pwm" + * "ingenic,jz4770-pwm" + * "ingenic,jz4780-pwm" +- #pwm-cells: Should be 3. See pwm.txt in this directory for a description + of the cells format. +- clocks : phandle to the external clock. +- clock-names : Should be "ext". + + +Example: + + pwm: pwm@10002000 { + compatible = "ingenic,jz4740-pwm"; + reg = <0x10002000 0x1000>; + + #pwm-cells = <3>; + + clocks = <&ext>; + clock-names = "ext"; + }; diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c index 6539c001fe32..a7b134af5e04 100644 --- a/drivers/pwm/pwm-jz4740.c +++ b/drivers/pwm/pwm-jz4740.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -174,6 +175,8 @@ static int jz4740_pwm_probe(struct platform_device *pdev) jz4740->chip.ops = &jz4740_pwm_ops; jz4740->chip.npwm = NUM_PWM; jz4740->chip.base = -1; + jz4740->chip.of_xlate = of_pwm_xlate_with_flags; + jz4740->chip.of_pwm_n_cells = 3; platform_set_drvdata(pdev, jz4740); @@ -187,9 +190,20 @@ static int jz4740_pwm_remove(struct platform_device *pdev) return pwmchip_remove(&jz4740->chip); } +#ifdef CONFIG_OF +static const struct of_device_id jz4740_pwm_dt_ids[] = { + { .compatible = "ingenic,jz4740-pwm", }, + { .compatible = "ingenic,jz4770-pwm", }, + { .compatible = "ingenic,jz4780-pwm", }, + {}, +}; +MODULE_DEVICE_TABLE(of, jz4740_pwm_dt_ids); +#endif + static struct platform_driver jz4740_pwm_driver = { .driver = { .name = "jz4740-pwm", + .of_match_table = of_match_ptr(jz4740_pwm_dt_ids), }, .probe = jz4740_pwm_probe, .remove = jz4740_pwm_remove, -- cgit From b419006275dbc05d73c5659b62c635b47a410a19 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sat, 6 Jan 2018 17:58:43 +0100 Subject: pwm: jz4740: Enable for all Ingenic SoCs This driver works perfectly with all the versions of the SoCs from Ingenic that are supported upstream. This makes the driver usable on JZ4740, JZ4770 and JZ4780 SoCs. Signed-off-by: Paul Cercueil Signed-off-by: Thierry Reding --- drivers/pwm/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 763ee50ea57d..f4209302401c 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -209,10 +209,10 @@ config PWM_IMX will be called pwm-imx. config PWM_JZ4740 - tristate "Ingenic JZ4740 PWM support" - depends on MACH_JZ4740 + tristate "Ingenic JZ47xx PWM support" + depends on MACH_INGENIC help - Generic PWM framework driver for Ingenic JZ4740 based + Generic PWM framework driver for Ingenic JZ47xx based machines. To compile this driver as a module, choose M here: the module -- cgit From 360cc036563db27881ce08049f69138438f2ddd0 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Thu, 1 Mar 2018 16:19:12 +0800 Subject: pwm: mediatek: Fix up PWM4 and PWM5 malfunction on MT7623 Since the offset for both registers, PWMDWIDTH and PWMTHRES, used to control PWM4 or PWM5 are distinct from the other PWMs, whose wrong programming on PWM hardware causes waveform cannot be output as expected. Thus, the patch adds the extra condition for fixing up the weird case to let PWM4 or PWM5 able to work on MT7623. v1 -> v2: use pwm45_fixup naming instead of pwm45_quirk v2 -> v3: add more tags for Reviewed-by, Fixes, and Cc stable Cc: stable@vger.kernel.org Fixes: caf065f8fd58 ("pwm: Add MediaTek PWM support") Signed-off-by: Sean Wang Reviewed-by: Matthias Brugger Cc: Zhi Mao Cc: John Crispin Cc: Matthias Brugger Signed-off-by: Thierry Reding --- drivers/pwm/pwm-mediatek.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c index f5d97e0ad52b..796baea7e8fe 100644 --- a/drivers/pwm/pwm-mediatek.c +++ b/drivers/pwm/pwm-mediatek.c @@ -29,7 +29,9 @@ #define PWMGDUR 0x0c #define PWMWAVENUM 0x28 #define PWMDWIDTH 0x2c +#define PWM45DWIDTH_FIXUP 0x30 #define PWMTHRES 0x30 +#define PWM45THRES_FIXUP 0x34 #define PWM_CLK_DIV_MAX 7 @@ -54,6 +56,7 @@ static const char * const mtk_pwm_clk_name[MTK_CLK_MAX] = { struct mtk_pwm_platform_data { unsigned int num_pwms; + bool pwm45_fixup; }; /** @@ -66,6 +69,7 @@ struct mtk_pwm_chip { struct pwm_chip chip; void __iomem *regs; struct clk *clks[MTK_CLK_MAX]; + const struct mtk_pwm_platform_data *soc; }; static const unsigned int mtk_pwm_reg_offset[] = { @@ -131,7 +135,8 @@ static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, { struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); struct clk *clk = pc->clks[MTK_CLK_PWM1 + pwm->hwpwm]; - u32 resolution, clkdiv = 0; + u32 resolution, clkdiv = 0, reg_width = PWMDWIDTH, + reg_thres = PWMTHRES; int ret; ret = mtk_pwm_clk_enable(chip, pwm); @@ -151,9 +156,18 @@ static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, return -EINVAL; } + if (pc->soc->pwm45_fixup && pwm->hwpwm > 2) { + /* + * PWM[4,5] has distinct offset for PWMDWIDTH and PWMTHRES + * from the other PWMs on MT7623. + */ + reg_width = PWM45DWIDTH_FIXUP; + reg_thres = PWM45THRES_FIXUP; + } + mtk_pwm_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | clkdiv); - mtk_pwm_writel(pc, pwm->hwpwm, PWMDWIDTH, period_ns / resolution); - mtk_pwm_writel(pc, pwm->hwpwm, PWMTHRES, duty_ns / resolution); + mtk_pwm_writel(pc, pwm->hwpwm, reg_width, period_ns / resolution); + mtk_pwm_writel(pc, pwm->hwpwm, reg_thres, duty_ns / resolution); mtk_pwm_clk_disable(chip, pwm); @@ -211,6 +225,7 @@ static int mtk_pwm_probe(struct platform_device *pdev) data = of_device_get_match_data(&pdev->dev); if (data == NULL) return -EINVAL; + pc->soc = data; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); pc->regs = devm_ioremap_resource(&pdev->dev, res); @@ -251,14 +266,17 @@ 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, }; static const struct mtk_pwm_platform_data mt7622_pwm_data = { .num_pwms = 6, + .pwm45_fixup = false, }; static const struct mtk_pwm_platform_data mt7623_pwm_data = { .num_pwms = 5, + .pwm45_fixup = true, }; static const struct of_device_id mtk_pwm_of_match[] = { -- cgit From f3617876364c0471b4779a0d05539f210693e45f Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Mon, 26 Mar 2018 18:02:01 +0800 Subject: pwm: mediatek: Remove redundant MODULE_ALIAS entries MODULE_ALIAS exports information to allow the module to be auto-loaded at boot for the drivers registered using legacy platform registration. However, currently the driver is always used by DT-only platform, MODULE_ALIAS is redundant and should be removed properly. Signed-off-by: Sean Wang Signed-off-by: Thierry Reding --- drivers/pwm/pwm-mediatek.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c index 796baea7e8fe..502c366c7d7c 100644 --- a/drivers/pwm/pwm-mediatek.c +++ b/drivers/pwm/pwm-mediatek.c @@ -298,5 +298,4 @@ static struct platform_driver mtk_pwm_driver = { module_platform_driver(mtk_pwm_driver); MODULE_AUTHOR("John Crispin "); -MODULE_ALIAS("platform:mtk-pwm"); MODULE_LICENSE("GPL"); -- cgit From 04c0a4e00dc11fedc0b0a8593adcf0f4310505d4 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Fri, 2 Mar 2018 16:49:14 +0800 Subject: pwm: mediatek: Improve precision in rate calculation Add a way that turning resolution from in nanosecond into in picosecond to improve noticeably almost 4.5% precision. It's necessary to hold the new resolution with type u64 and thus related operations on u64 are applied instead in those rate calculations. And the patch has a dependency on [1]. [1] http://lists.infradead.org/pipermail/linux-mediatek/2018-March/012225.html Cc: stable@vger.kernel.org Fixes: caf065f8fd58 ("pwm: Add MediaTek PWM support") Signed-off-by: Sean Wang Signed-off-by: Thierry Reding --- drivers/pwm/pwm-mediatek.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c index 502c366c7d7c..328c124773b2 100644 --- a/drivers/pwm/pwm-mediatek.c +++ b/drivers/pwm/pwm-mediatek.c @@ -135,19 +135,25 @@ static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, { struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); struct clk *clk = pc->clks[MTK_CLK_PWM1 + pwm->hwpwm]; - u32 resolution, clkdiv = 0, reg_width = PWMDWIDTH, + u32 clkdiv = 0, cnt_period, cnt_duty, reg_width = PWMDWIDTH, reg_thres = PWMTHRES; + u64 resolution; int ret; ret = mtk_pwm_clk_enable(chip, pwm); if (ret < 0) return ret; - resolution = NSEC_PER_SEC / clk_get_rate(clk); + /* Using resolution in picosecond gets accuracy higher */ + resolution = (u64)NSEC_PER_SEC * 1000; + do_div(resolution, clk_get_rate(clk)); - while (period_ns / resolution > 8191) { + cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000, resolution); + while (cnt_period > 8191) { resolution *= 2; clkdiv++; + cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000, + resolution); } if (clkdiv > PWM_CLK_DIV_MAX) { @@ -165,9 +171,10 @@ static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, reg_thres = PWM45THRES_FIXUP; } + cnt_duty = DIV_ROUND_CLOSEST_ULL((u64)duty_ns * 1000, resolution); mtk_pwm_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | clkdiv); - mtk_pwm_writel(pc, pwm->hwpwm, reg_width, period_ns / resolution); - mtk_pwm_writel(pc, pwm->hwpwm, reg_thres, duty_ns / resolution); + mtk_pwm_writel(pc, pwm->hwpwm, reg_width, cnt_period); + mtk_pwm_writel(pc, pwm->hwpwm, reg_thres, cnt_duty); mtk_pwm_clk_disable(chip, pwm); -- cgit From 3af0bdd1d027292d40c7f1d13420bc298b3e1660 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Wed, 14 Feb 2018 11:04:32 +0100 Subject: pwm: stm32: Remove unused struct device dev is never assigned or used. Remove it. Fixes: 7edf7369205b ("pwm: Add driver for STM32 plaftorm") Signed-off-by: Fabrice Gasnier Reviewed-by: Benjamin Gaignard Signed-off-by: Thierry Reding --- drivers/pwm/pwm-stm32.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c index be56d7af89c9..014e2a759fa6 100644 --- a/drivers/pwm/pwm-stm32.c +++ b/drivers/pwm/pwm-stm32.c @@ -20,7 +20,6 @@ struct stm32_pwm { struct pwm_chip chip; - struct device *dev; struct clk *clk; struct regmap *regmap; u32 max_arr; -- cgit From 4eb67a209645a87b8aca070aa9735eed90177829 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Wed, 14 Feb 2018 11:04:33 +0100 Subject: pwm: stm32: Protect common prescaler for all channels There may be a race, when configuring two PWM channels, with different prescaler values, when there's no active channel yet. Add mutex lock to avoid concurrent access on PWM apply state. This is also precursor patch for PWM capture support. Signed-off-by: Fabrice Gasnier Reviewed-by: Benjamin Gaignard Signed-off-by: Thierry Reding --- drivers/pwm/pwm-stm32.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c index 014e2a759fa6..2708212933f7 100644 --- a/drivers/pwm/pwm-stm32.c +++ b/drivers/pwm/pwm-stm32.c @@ -20,6 +20,7 @@ struct stm32_pwm { struct pwm_chip chip; + struct mutex lock; /* protect pwm config/enable */ struct clk *clk; struct regmap *regmap; u32 max_arr; @@ -212,9 +213,23 @@ static int stm32_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, return ret; } +static int stm32_pwm_apply_locked(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) +{ + struct stm32_pwm *priv = to_stm32_pwm_dev(chip); + int ret; + + /* protect common prescaler for all active channels */ + mutex_lock(&priv->lock); + ret = stm32_pwm_apply(chip, pwm, state); + mutex_unlock(&priv->lock); + + return ret; +} + static const struct pwm_ops stm32pwm_ops = { .owner = THIS_MODULE, - .apply = stm32_pwm_apply, + .apply = stm32_pwm_apply_locked, }; static int stm32_pwm_set_breakinput(struct stm32_pwm *priv, @@ -334,6 +349,7 @@ static int stm32_pwm_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; + mutex_init(&priv->lock); priv->regmap = ddata->regmap; priv->clk = ddata->clk; priv->max_arr = ddata->max_arr; -- cgit From e7c4b02c2642a5ff3704bd86ff23a6a7a0f4e279 Mon Sep 17 00:00:00 2001 From: Gerald Baeza Date: Fri, 23 Feb 2018 14:36:03 +0100 Subject: dt-bindings: pwm-stm32-lp: Add #pwm-cells STM32 Low-Power Timer supports generic 3 cells PWM to encode PWM number, period and polarity. Signed-off-by: Gerald Baeza Signed-off-by: Fabrice Gasnier Reviewed-by: Rob Herring Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/pwm/pwm-stm32-lp.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/pwm/pwm-stm32-lp.txt b/Documentation/devicetree/bindings/pwm/pwm-stm32-lp.txt index f8338d11fd2b..bd23302e84be 100644 --- a/Documentation/devicetree/bindings/pwm/pwm-stm32-lp.txt +++ b/Documentation/devicetree/bindings/pwm/pwm-stm32-lp.txt @@ -7,6 +7,8 @@ See ../mfd/stm32-lptimer.txt for details about the parent node. Required parameters: - compatible: Must be "st,stm32-pwm-lp". +- #pwm-cells: Should be set to 3. This PWM chip uses the default 3 cells + bindings defined in pwm.txt. Optional properties: - pinctrl-names: Set to "default". @@ -18,6 +20,7 @@ Example: ... pwm { compatible = "st,stm32-pwm-lp"; + #pwm-cells = <3>; pinctrl-names = "default"; pinctrl-0 = <&lppwm1_pins>; }; -- cgit From f6ea025f6ea1fb1455e59e2008d88f5c72f0d210 Mon Sep 17 00:00:00 2001 From: Gerald Baeza Date: Fri, 23 Feb 2018 14:36:04 +0100 Subject: pwm: stm32: LPTimer: Use 3 cells ->of_xlate() STM32 Low-Power Timer supports generic 3 cells PWM to encode PWM number, period and polarity. Signed-off-by: Gerald Baeza Signed-off-by: Fabrice Gasnier Signed-off-by: Thierry Reding --- drivers/pwm/pwm-stm32-lp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pwm/pwm-stm32-lp.c b/drivers/pwm/pwm-stm32-lp.c index cbd271e80c3c..7c13e2505080 100644 --- a/drivers/pwm/pwm-stm32-lp.c +++ b/drivers/pwm/pwm-stm32-lp.c @@ -202,6 +202,8 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev) priv->chip.dev = &pdev->dev; priv->chip.ops = &stm32_pwm_lp_ops; priv->chip.npwm = 1; + priv->chip.of_xlate = of_pwm_xlate_with_flags; + priv->chip.of_pwm_n_cells = 3; ret = pwmchip_add(&priv->chip); if (ret < 0) -- cgit From 120cc2fff40096fb99d96d8671ad7469dd44862f Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Thu, 18 Jan 2018 20:58:14 +0100 Subject: pwm: Remove depends on AVR32 AVR32 is gone, so no more need to depend on it. Signed-off-by: Corentin Labbe Signed-off-by: Thierry Reding --- drivers/pwm/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index f4209302401c..db4501d1dc1a 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -43,7 +43,7 @@ config PWM_AB8500 config PWM_ATMEL tristate "Atmel PWM support" - depends on ARCH_AT91 || AVR32 + depends on ARCH_AT91 help Generic PWM framework driver for Atmel SoC. -- cgit From 989ae7a5b2f965dc5e6de132f1d8c0ea8c23c3c5 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sun, 25 Feb 2018 02:55:58 +0100 Subject: pwm: sun4i: Properly check current state Correctly extract the prescaler value from CTRL_REG before comparing it to PWM_PRESCAL_MASK. Also, check that both PWM_CLK_GATING and PWM_EN to ensure the PWM is enabled instead of relying on only one of those. Fixes: 93e0dfb2c52f ("pwm: sun4i: Improve hardware read out") Signed-off-by: Alexandre Belloni Signed-off-by: Thierry Reding --- drivers/pwm/pwm-sun4i.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c index 334199c58f1d..42e6f0873d1c 100644 --- a/drivers/pwm/pwm-sun4i.c +++ b/drivers/pwm/pwm-sun4i.c @@ -117,7 +117,8 @@ static void sun4i_pwm_get_state(struct pwm_chip *chip, val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG); - if ((val == PWM_PRESCAL_MASK) && sun4i_pwm->data->has_prescaler_bypass) + if ((PWM_REG_PRESCAL(val, pwm->hwpwm) == PWM_PRESCAL_MASK) && + sun4i_pwm->data->has_prescaler_bypass) prescaler = 1; else prescaler = prescaler_table[PWM_REG_PRESCAL(val, pwm->hwpwm)]; @@ -130,7 +131,8 @@ static void sun4i_pwm_get_state(struct pwm_chip *chip, else state->polarity = PWM_POLARITY_INVERSED; - if (val & BIT_CH(PWM_CLK_GATING | PWM_EN, pwm->hwpwm)) + if ((val & BIT_CH(PWM_CLK_GATING | PWM_EN, pwm->hwpwm)) == + BIT_CH(PWM_CLK_GATING | PWM_EN, pwm->hwpwm)) state->enabled = true; else state->enabled = false; -- cgit From 6a89bb6cc021ce5938c8edfa57b61cff38553c51 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Sun, 18 Mar 2018 23:28:44 +0000 Subject: pwm: sun4i: Drop unused .has_rdy member Commit a054c4d68408 ("pwm: sun4i: Drop legacy callbacks") dropped the only user of the .has_rdy member in our sun4i_pwm_data struct. Consequently we don't need to store this anymore for the various SoCs, which paves the way for further simplifications. Signed-off-by: Andre Przywara Acked-by: Maxime Ripard Signed-off-by: Thierry Reding --- drivers/pwm/pwm-sun4i.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c index 42e6f0873d1c..d6c1b3a5f2a6 100644 --- a/drivers/pwm/pwm-sun4i.c +++ b/drivers/pwm/pwm-sun4i.c @@ -73,7 +73,6 @@ static const u32 prescaler_table[] = { struct sun4i_pwm_data { bool has_prescaler_bypass; - bool has_rdy; unsigned int npwm; }; @@ -315,31 +314,26 @@ static const struct pwm_ops sun4i_pwm_ops = { static const struct sun4i_pwm_data sun4i_pwm_data_a10 = { .has_prescaler_bypass = false, - .has_rdy = false, .npwm = 2, }; static const struct sun4i_pwm_data sun4i_pwm_data_a10s = { .has_prescaler_bypass = true, - .has_rdy = true, .npwm = 2, }; static const struct sun4i_pwm_data sun4i_pwm_data_a13 = { .has_prescaler_bypass = true, - .has_rdy = true, .npwm = 1, }; static const struct sun4i_pwm_data sun4i_pwm_data_a20 = { .has_prescaler_bypass = true, - .has_rdy = true, .npwm = 2, }; static const struct sun4i_pwm_data sun4i_pwm_data_h3 = { .has_prescaler_bypass = true, - .has_rdy = true, .npwm = 1, }; -- cgit From 7b4c7c567d77dabbf7f5d561ba26425902cfafca Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Sun, 18 Mar 2018 23:28:45 +0000 Subject: pwm: sun4i: Simplify controller mapping At the moment we assign our supported compatible strings to a respective instance of our sun4i_pwm_data structure, even though some of them are the same. To avoid further clutter, split out the three different combinations of features we have at the moment and name them accordingly. This should make it more obvious which compatible string to use for new SoCs. Signed-off-by: Andre Przywara Acked-by: Maxime Ripard Signed-off-by: Thierry Reding --- drivers/pwm/pwm-sun4i.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c index d6c1b3a5f2a6..470d4f71e7eb 100644 --- a/drivers/pwm/pwm-sun4i.c +++ b/drivers/pwm/pwm-sun4i.c @@ -312,27 +312,17 @@ static const struct pwm_ops sun4i_pwm_ops = { .owner = THIS_MODULE, }; -static const struct sun4i_pwm_data sun4i_pwm_data_a10 = { +static const struct sun4i_pwm_data sun4i_pwm_dual_nobypass = { .has_prescaler_bypass = false, .npwm = 2, }; -static const struct sun4i_pwm_data sun4i_pwm_data_a10s = { +static const struct sun4i_pwm_data sun4i_pwm_dual_bypass = { .has_prescaler_bypass = true, .npwm = 2, }; -static const struct sun4i_pwm_data sun4i_pwm_data_a13 = { - .has_prescaler_bypass = true, - .npwm = 1, -}; - -static const struct sun4i_pwm_data sun4i_pwm_data_a20 = { - .has_prescaler_bypass = true, - .npwm = 2, -}; - -static const struct sun4i_pwm_data sun4i_pwm_data_h3 = { +static const struct sun4i_pwm_data sun4i_pwm_single_bypass = { .has_prescaler_bypass = true, .npwm = 1, }; @@ -340,19 +330,19 @@ static const struct sun4i_pwm_data sun4i_pwm_data_h3 = { static const struct of_device_id sun4i_pwm_dt_ids[] = { { .compatible = "allwinner,sun4i-a10-pwm", - .data = &sun4i_pwm_data_a10, + .data = &sun4i_pwm_dual_nobypass, }, { .compatible = "allwinner,sun5i-a10s-pwm", - .data = &sun4i_pwm_data_a10s, + .data = &sun4i_pwm_dual_bypass, }, { .compatible = "allwinner,sun5i-a13-pwm", - .data = &sun4i_pwm_data_a13, + .data = &sun4i_pwm_single_bypass, }, { .compatible = "allwinner,sun7i-a20-pwm", - .data = &sun4i_pwm_data_a20, + .data = &sun4i_pwm_dual_bypass, }, { .compatible = "allwinner,sun8i-h3-pwm", - .data = &sun4i_pwm_data_h3, + .data = &sun4i_pwm_single_bypass, }, { /* sentinel */ }, -- cgit From 8422c7439ea9c4e08198cec7edd5faf3890c4dd7 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Sun, 18 Mar 2018 23:28:46 +0000 Subject: dt-bindings: pwm: sunxi: Add new compatible strings The PWM controllers found in the Allwinner A64 and H5 SoCs are fully compatible to the PWM controllers found in the A13 and H3. Add new compatible strings for those SoCs to the binding document, so that they can be safely used, together with a fallback string (preferably "allwinner,sun5i-a13-pwm"). Signed-off-by: Andre Przywara Acked-by: Maxime Ripard Reviewed-by: Rob Herring Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/pwm/pwm-sun4i.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt b/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt index 51ff54c8b8ef..2a1affbff45e 100644 --- a/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt +++ b/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt @@ -7,6 +7,8 @@ Required properties: - "allwinner,sun5i-a13-pwm" - "allwinner,sun7i-a20-pwm" - "allwinner,sun8i-h3-pwm" + - "allwinner,sun50i-a64-pwm", "allwinner,sun5i-a13-pwm" + - "allwinner,sun50i-h5-pwm", "allwinner,sun5i-a13-pwm" - 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. -- cgit From 8bbf5b426160343b554117eb9abdf4dad9a50e65 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Thu, 8 Mar 2018 15:27:37 +0530 Subject: pwm: sysfs: Use put_device() instead of kfree() Never directly free @dev after calling device_register(), even if it returned an error! Always use put_device() to give up the reference initialized. Signed-off-by: Arvind Yadav Signed-off-by: Thierry Reding --- drivers/pwm/sysfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 83f2b0b15712..7c71cdb8a9d8 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -273,7 +273,8 @@ static int pwm_export_child(struct device *parent, struct pwm_device *pwm) ret = device_register(&export->child); if (ret) { clear_bit(PWMF_EXPORTED, &pwm->flags); - kfree(export); + put_device(&export->child); + export = NULL; return ret; } -- cgit From 6225f9c64b40bc8a22503e9cda70f55d7a9dd3c6 Mon Sep 17 00:00:00 2001 From: Ryo Kodama Date: Fri, 9 Mar 2018 20:24:21 +0900 Subject: pwm: rcar: Fix a condition to prevent mismatch value setting to duty This patch fixes an issue that is possible to set mismatch value to duty for R-Car PWM if we input the following commands: # cd /sys/class/pwm// # echo 0 > export # cd pwm0 # echo 30 > period # echo 30 > duty_cycle # echo 0 > duty_cycle # cat duty_cycle 0 # echo 1 > enable --> Then, the actual duty_cycle is 30, not 0. So, this patch adds a condition into rcar_pwm_config() to fix this issue. Signed-off-by: Ryo Kodama [shimoda: revise the commit log and add Fixes and Cc tags] Fixes: ed6c1476bf7f ("pwm: Add support for R-Car PWM Timer") Cc: Cc: # v4.4+ Signed-off-by: Yoshihiro Shimoda Signed-off-by: Thierry Reding --- drivers/pwm/pwm-rcar.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c index 1c85ecc9e7ac..0fcf94ffad32 100644 --- a/drivers/pwm/pwm-rcar.c +++ b/drivers/pwm/pwm-rcar.c @@ -156,8 +156,12 @@ static int rcar_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, if (div < 0) return div; - /* Let the core driver set pwm->period if disabled and duty_ns == 0 */ - if (!pwm_is_enabled(pwm) && !duty_ns) + /* + * Let the core driver set pwm->period if disabled and duty_ns == 0. + * But, this driver should prevent to set the new duty_ns if current + * duty_cycle is not set + */ + if (!pwm_is_enabled(pwm) && !duty_ns && !pwm->state.duty_cycle) return 0; rcar_pwm_update(rp, RCAR_PWMCR_SYNC, RCAR_PWMCR_SYNC, RCAR_PWMCR); -- cgit From aa7c49328bd84cda3c4674b70eb10db0a94f89ab Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Fri, 9 Mar 2018 20:53:17 +0900 Subject: dt-bindings: pwm: rcar: Add bindings for R-Car M3N support This patch adds bindings for R-Car M3N. No driver update is needed. Signed-off-by: Yoshihiro Shimoda Reviewed-by: Geert Uytterhoeven Reviewed-by: Simon Horman Reviewed-by: Rob Herring Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt index f3bba592d419..35a3b9761ee5 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt +++ b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt @@ -11,6 +11,7 @@ Required Properties: - "renesas,pwm-r8a7794": for R-Car E2 - "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-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 -- cgit From f2e6142cdc10b1b7edea8d65b07293f152e4d110 Mon Sep 17 00:00:00 2001 From: Hien Dang Date: Tue, 13 Mar 2018 17:18:17 +0900 Subject: pwm: rcar: Use PM Runtime to control module clock Runtime PM API (pm_runtime_get_sync/pm_runtime_put) should be used to control module clock instead of clk_prepare_enable and clk_disable_unprepare. Signed-off-by: Hien Dang Signed-off-by: Yoshihiro Shimoda Reviewed-by: Geert Uytterhoeven Signed-off-by: Thierry Reding --- drivers/pwm/pwm-rcar.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c index 0fcf94ffad32..f4d8767f804e 100644 --- a/drivers/pwm/pwm-rcar.c +++ b/drivers/pwm/pwm-rcar.c @@ -134,16 +134,12 @@ static int rcar_pwm_set_counter(struct rcar_pwm_chip *rp, int div, int duty_ns, static int rcar_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) { - struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip); - - return clk_prepare_enable(rp->clk); + return pm_runtime_get_sync(chip->dev); } static void rcar_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) { - struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip); - - clk_disable_unprepare(rp->clk); + pm_runtime_put(chip->dev); } static int rcar_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, -- cgit From 6873842235d678a245a378669f35e145df2441b9 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 13 Mar 2018 17:18:18 +0900 Subject: pwm: rcar: Add suspend/resume support This patch adds suspend/resume support for Renesas PWM driver. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Thierry Reding --- drivers/pwm/pwm-rcar.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c index f4d8767f804e..91d11f2e2fef 100644 --- a/drivers/pwm/pwm-rcar.c +++ b/drivers/pwm/pwm-rcar.c @@ -258,11 +258,53 @@ static const struct of_device_id rcar_pwm_of_table[] = { }; MODULE_DEVICE_TABLE(of, rcar_pwm_of_table); +#ifdef CONFIG_PM_SLEEP +static struct pwm_device *rcar_pwm_dev_to_pwm_dev(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rcar_pwm_chip *rcar_pwm = platform_get_drvdata(pdev); + struct pwm_chip *chip = &rcar_pwm->chip; + + return &chip->pwms[0]; +} + +static int rcar_pwm_suspend(struct device *dev) +{ + struct pwm_device *pwm = rcar_pwm_dev_to_pwm_dev(dev); + + if (!test_bit(PWMF_REQUESTED, &pwm->flags)) + return 0; + + pm_runtime_put(dev); + + return 0; +} + +static int rcar_pwm_resume(struct device *dev) +{ + struct pwm_device *pwm = rcar_pwm_dev_to_pwm_dev(dev); + + if (!test_bit(PWMF_REQUESTED, &pwm->flags)) + return 0; + + pm_runtime_get_sync(dev); + + rcar_pwm_config(pwm->chip, pwm, pwm->state.duty_cycle, + pwm->state.period); + if (pwm_is_enabled(pwm)) + rcar_pwm_enable(pwm->chip, pwm); + + return 0; +} +#endif /* CONFIG_PM_SLEEP */ +static SIMPLE_DEV_PM_OPS(rcar_pwm_pm_ops, rcar_pwm_suspend, rcar_pwm_resume); + static struct platform_driver rcar_pwm_driver = { .probe = rcar_pwm_probe, .remove = rcar_pwm_remove, .driver = { .name = "pwm-rcar", + .pm = &rcar_pwm_pm_ops, .of_match_table = of_match_ptr(rcar_pwm_of_table), } }; -- cgit