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(-) (limited to 'drivers/pwm') 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(-) (limited to 'drivers/pwm') 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(-) (limited to 'drivers/pwm') 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 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(-) (limited to 'drivers/pwm') 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(-) (limited to 'drivers/pwm') 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(+) (limited to 'drivers/pwm') 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 --- drivers/pwm/pwm-jz4740.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/pwm') 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(-) (limited to 'drivers/pwm') 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(-) (limited to 'drivers/pwm') 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(-) (limited to 'drivers/pwm') 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(-) (limited to 'drivers/pwm') 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(-) (limited to 'drivers/pwm') 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(-) (limited to 'drivers/pwm') 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 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(+) (limited to 'drivers/pwm') 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(-) (limited to 'drivers/pwm') 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(-) (limited to 'drivers/pwm') 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(-) (limited to 'drivers/pwm') 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(-) (limited to 'drivers/pwm') 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 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(-) (limited to 'drivers/pwm') 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(-) (limited to 'drivers/pwm') 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 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(-) (limited to 'drivers/pwm') 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(+) (limited to 'drivers/pwm') 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