From efb0de55b6a2ec15fc424e660601f22ae2fa487a Mon Sep 17 00:00:00 2001 From: Shobhit Kumar Date: Tue, 5 May 2015 15:04:18 +0530 Subject: pwm: Add support to remove registered consumer lookup tables In case some drivers are unloading, they can remove lookup tables which they had registered during their load time to avoid redundant entries if loaded again. CC: Samuel Ortiz Cc: Linus Walleij Cc: Alexandre Courbot Cc: Thierry Reding Signed-off-by: Shobhit Kumar Signed-off-by: Thierry Reding --- drivers/pwm/core.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers/pwm') diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index ba34c7d89042..27cd58d16881 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -585,6 +585,23 @@ void pwm_add_table(struct pwm_lookup *table, size_t num) mutex_unlock(&pwm_lookup_lock); } +/** + * pwm_remove_table() - unregister PWM device consumers + * @table: array of consumers to unregister + * @num: number of consumers in table + */ +void pwm_remove_table(struct pwm_lookup *table, size_t num) +{ + mutex_lock(&pwm_lookup_lock); + + while (num--) { + list_del(&table->list); + table++; + } + + mutex_unlock(&pwm_lookup_lock); +} + /** * pwm_get() - look up and request a PWM device * @dev: device for PWM consumer -- cgit v1.2.3 From cccb94543c8299e0bc7564cc6f8b26e0f15bafde Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 14 May 2015 02:32:31 +0200 Subject: pwm: samsung: Use MODULE_DEVICE_TABLE() to include OF modalias If the pwm-samsung driver is built as a module, modalias information is not filled so the module is not autoloaded. Use the MODULE_DEVICE_TABLE() macro to export the OF device ID so the module contains that information. Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Signed-off-by: Thierry Reding --- drivers/pwm/pwm-samsung.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/pwm') diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c index ff201e1b9219..ada2d326dc3e 100644 --- a/drivers/pwm/pwm-samsung.c +++ b/drivers/pwm/pwm-samsung.c @@ -456,6 +456,7 @@ static const struct of_device_id samsung_pwm_matches[] = { { .compatible = "samsung,exynos4210-pwm", .data = &s5p64x0_variant }, {}, }; +MODULE_DEVICE_TABLE(of, samsung_pwm_matches); static int pwm_samsung_parse_dt(struct samsung_pwm_chip *chip) { -- cgit v1.2.3 From 4c027f7ba8520df088d34ae045205a6f8e2a1d76 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 25 May 2015 15:19:55 +0200 Subject: pwm: atmel: Fix incorrect CDTY value after enabling CUPD is not flushed before enabling the channel so it will update CDTY/CPRD just after one period. So we always set CUPD, even when the channel is not enabled. Signed-off-by: Alexandre Belloni Acked-by: Nicolas Ferre Signed-off-by: Thierry Reding --- drivers/pwm/pwm-atmel.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) (limited to 'drivers/pwm') diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c index d3c22de9ee47..89f9ca41d9af 100644 --- a/drivers/pwm/pwm-atmel.c +++ b/drivers/pwm/pwm-atmel.c @@ -155,24 +155,25 @@ static void atmel_pwm_config_v1(struct pwm_chip *chip, struct pwm_device *pwm, struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); unsigned int val; - if (test_bit(PWMF_ENABLED, &pwm->flags)) { - /* - * If the PWM channel is enabled, using the update register, - * it needs to set bit 10 of CMR to 0 - */ - atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CUPD, dty); - val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR); - val &= ~PWM_CMR_UPD_CDTY; - atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val); - } else { - /* - * If the PWM channel is disabled, write value to duty and - * period registers directly. - */ - atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CDTY, dty); - atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CPRD, prd); - } + atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CUPD, dty); + + val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR); + val &= ~PWM_CMR_UPD_CDTY; + atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val); + + /* + * If the PWM channel is enabled, only update CDTY by using the update + * register, it needs to set bit 10 of CMR to 0 + */ + if (test_bit(PWMF_ENABLED, &pwm->flags)) + return; + /* + * If the PWM channel is disabled, write value to duty and period + * registers directly. + */ + atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CDTY, dty); + atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CPRD, prd); } static void atmel_pwm_config_v2(struct pwm_chip *chip, struct pwm_device *pwm, -- cgit v1.2.3 From 472ac3dcac108d6648ee28616c6de1e3b0bb361f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 25 May 2015 18:11:49 +0200 Subject: pwm: atmel: Fix incorrect CDTY value after disabling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pwm-leds calls .config() and .disable() in a row. This exhibits that it may happen that the channel gets disabled before CDTY has been updated with CUPD. The issue gets quite worse with long periods. So, ensure that at least one period has past before disabling the channel by polling ISR. Signed-off-by: Alexandre Belloni Acked-by: Nicolas Ferre Tested-by: Gaƫl PORTAY Signed-off-by: Thierry Reding --- drivers/pwm/pwm-atmel.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers/pwm') diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c index 89f9ca41d9af..a947c9095d9d 100644 --- a/drivers/pwm/pwm-atmel.c +++ b/drivers/pwm/pwm-atmel.c @@ -8,9 +8,11 @@ */ #include +#include #include #include #include +#include #include #include #include @@ -21,6 +23,7 @@ #define PWM_ENA 0x04 #define PWM_DIS 0x08 #define PWM_SR 0x0C +#define PWM_ISR 0x1C /* Bit field in SR */ #define PWM_SR_ALL_CH_ON 0x0F @@ -60,6 +63,9 @@ struct atmel_pwm_chip { struct clk *clk; void __iomem *base; + unsigned int updated_pwms; + struct mutex isr_lock; /* ISR is cleared when read, ensure only one thread does that */ + void (*config)(struct pwm_chip *chip, struct pwm_device *pwm, unsigned long dty, unsigned long prd); }; @@ -144,6 +150,10 @@ static int atmel_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, val = (val & ~PWM_CMR_CPRE_MSK) | (pres & PWM_CMR_CPRE_MSK); atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val); atmel_pwm->config(chip, pwm, dty, prd); + mutex_lock(&atmel_pwm->isr_lock); + atmel_pwm->updated_pwms |= atmel_pwm_readl(atmel_pwm, PWM_ISR); + atmel_pwm->updated_pwms &= ~(1 << pwm->hwpwm); + mutex_unlock(&atmel_pwm->isr_lock); clk_disable(atmel_pwm->clk); return ret; @@ -243,7 +253,22 @@ static int atmel_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) { struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); + unsigned long timeout = jiffies + 2 * HZ; + + /* + * Wait for at least a complete period to have passed before disabling a + * channel to be sure that CDTY has been updated + */ + mutex_lock(&atmel_pwm->isr_lock); + atmel_pwm->updated_pwms |= atmel_pwm_readl(atmel_pwm, PWM_ISR); + + while (!(atmel_pwm->updated_pwms & (1 << pwm->hwpwm)) && + time_before(jiffies, timeout)) { + usleep_range(10, 100); + atmel_pwm->updated_pwms |= atmel_pwm_readl(atmel_pwm, PWM_ISR); + } + mutex_unlock(&atmel_pwm->isr_lock); atmel_pwm_writel(atmel_pwm, PWM_DIS, 1 << pwm->hwpwm); clk_disable(atmel_pwm->clk); @@ -358,6 +383,8 @@ static int atmel_pwm_probe(struct platform_device *pdev) atmel_pwm->chip.npwm = 4; atmel_pwm->chip.can_sleep = true; atmel_pwm->config = data->config; + atmel_pwm->updated_pwms = 0; + mutex_init(&atmel_pwm->isr_lock); ret = pwmchip_add(&atmel_pwm->chip); if (ret < 0) { @@ -379,6 +406,7 @@ static int atmel_pwm_remove(struct platform_device *pdev) struct atmel_pwm_chip *atmel_pwm = platform_get_drvdata(pdev); clk_unprepare(atmel_pwm->clk); + mutex_destroy(&atmel_pwm->isr_lock); return pwmchip_remove(&atmel_pwm->chip); } -- cgit v1.2.3 From b6a00fae9760a49114016e4764d09e522a5ba5b6 Mon Sep 17 00:00:00 2001 From: Tim Kryger Date: Tue, 26 May 2015 13:08:16 -0700 Subject: pwm: Add pwmchip_add_with_polarity() API Add a new function to register a PWM chip with channels that have their initial polarity as specified by an additional parameter. This benefits drivers of controllers that by default operate with inversed polarity by removing the need to modify the polarity during initialization. Signed-off-by: Tim Kryger Signed-off-by: Jonathan Richardson [thierry.reding@gmail.com: export pwmchip_add_with_polarity()] Signed-off-by: Thierry Reding --- drivers/pwm/core.c | 23 ++++++++++++++++++++--- include/linux/pwm.h | 7 +++++++ 2 files changed, 27 insertions(+), 3 deletions(-) (limited to 'drivers/pwm') diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 27cd58d16881..3a7769fe53de 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -223,13 +223,16 @@ void *pwm_get_chip_data(struct pwm_device *pwm) EXPORT_SYMBOL_GPL(pwm_get_chip_data); /** - * pwmchip_add() - register a new PWM chip + * pwmchip_add_with_polarity() - register a new PWM chip * @chip: the PWM chip to add + * @polarity: initial polarity of PWM channels * * Register a new PWM chip. If chip->base < 0 then a dynamically assigned base - * will be used. + * will be used. The initial polarity for all channels is specified by the + * @polarity parameter. */ -int pwmchip_add(struct pwm_chip *chip) +int pwmchip_add_with_polarity(struct pwm_chip *chip, + enum pwm_polarity polarity) { struct pwm_device *pwm; unsigned int i; @@ -259,6 +262,7 @@ int pwmchip_add(struct pwm_chip *chip) pwm->chip = chip; pwm->pwm = chip->base + i; pwm->hwpwm = i; + pwm->polarity = polarity; radix_tree_insert(&pwm_tree, pwm->pwm, pwm); } @@ -279,6 +283,19 @@ out: mutex_unlock(&pwm_lock); return ret; } +EXPORT_SYMBOL_GPL(pwmchip_add_with_polarity); + +/** + * pwmchip_add() - register a new PWM chip + * @chip: the PWM chip to add + * + * Register a new PWM chip. If chip->base < 0 then a dynamically assigned base + * will be used. The initial polarity for all channels is normal. + */ +int pwmchip_add(struct pwm_chip *chip) +{ + return pwmchip_add_with_polarity(chip, PWM_POLARITY_NORMAL); +} EXPORT_SYMBOL_GPL(pwmchip_add); /** diff --git a/include/linux/pwm.h b/include/linux/pwm.h index cfe2d8df5be0..36262d08a9da 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -182,6 +182,8 @@ struct pwm_chip { int pwm_set_chip_data(struct pwm_device *pwm, void *data); void *pwm_get_chip_data(struct pwm_device *pwm); +int pwmchip_add_with_polarity(struct pwm_chip *chip, + enum pwm_polarity polarity); int pwmchip_add(struct pwm_chip *chip); int pwmchip_remove(struct pwm_chip *chip); struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip, @@ -217,6 +219,11 @@ static inline int pwmchip_add(struct pwm_chip *chip) return -EINVAL; } +static inline int pwmchip_add_inversed(struct pwm_chip *chip) +{ + return -EINVAL; +} + static inline int pwmchip_remove(struct pwm_chip *chip) { return -EINVAL; -- cgit v1.2.3 From e23db65f3dac944d51ba97c8c03a17cfc12390cd Mon Sep 17 00:00:00 2001 From: Arun Ramamurthy Date: Tue, 26 May 2015 13:08:17 -0700 Subject: pwm: bcm-kona: Don't set polarity in probe Omit setting the polarity to normal during probe and instead use the new pwmchip_add_with_polarity() function to register a PWM chip with inverse polarity by default for all channels to reflect the hardware default. Signed-off-by: Arun Ramamurthy Reviewed-by: Ray Jui Signed-off-by: Scott Branden Signed-off-by: Tim Kryger Signed-off-by: Jonathan Richardson [thierry.reding@gmail.com: use pwmchip_add_with_polarity()] Signed-off-by: Thierry Reding --- drivers/pwm/pwm-bcm-kona.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/pwm') diff --git a/drivers/pwm/pwm-bcm-kona.c b/drivers/pwm/pwm-bcm-kona.c index 02bc048892a9..7af8fea2dc5b 100644 --- a/drivers/pwm/pwm-bcm-kona.c +++ b/drivers/pwm/pwm-bcm-kona.c @@ -266,18 +266,15 @@ static int kona_pwmc_probe(struct platform_device *pdev) return ret; } - /* Set smooth mode, push/pull, and normal polarity for all channels */ - for (chan = 0; chan < kp->chip.npwm; chan++) { - value |= (1 << PWM_CONTROL_SMOOTH_SHIFT(chan)); + /* Set push/pull for all channels */ + for (chan = 0; chan < kp->chip.npwm; chan++) value |= (1 << PWM_CONTROL_TYPE_SHIFT(chan)); - value |= (1 << PWM_CONTROL_POLARITY_SHIFT(chan)); - } writel(value, kp->base + PWM_CONTROL_OFFSET); clk_disable_unprepare(kp->clk); - ret = pwmchip_add(&kp->chip); + ret = pwmchip_add_with_polarity(&kp->chip, PWM_POLARITY_INVERSED); if (ret < 0) dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret); -- cgit v1.2.3 From 361c1066c939a88e3bb59364f47055b2a5fb3fd4 Mon Sep 17 00:00:00 2001 From: Qipeng Zha Date: Thu, 12 Mar 2015 22:28:28 +0800 Subject: pwm: lpss: pci: Add support for Broxton platform Add PCI device IDs for Broxton platform. Signed-off-by: Qipeng Zha Acked-by: Mika Westerberg Signed-off-by: Thierry Reding --- drivers/pwm/pwm-lpss-pci.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/pwm') diff --git a/drivers/pwm/pwm-lpss-pci.c b/drivers/pwm/pwm-lpss-pci.c index cf20d2beacdd..45042c1b2046 100644 --- a/drivers/pwm/pwm-lpss-pci.c +++ b/drivers/pwm/pwm-lpss-pci.c @@ -44,8 +44,10 @@ static void pwm_lpss_remove_pci(struct pci_dev *pdev) } static const struct pci_device_id pwm_lpss_pci_ids[] = { + { PCI_VDEVICE(INTEL, 0x0ac8), (unsigned long)&pwm_lpss_bsw_info}, { PCI_VDEVICE(INTEL, 0x0f08), (unsigned long)&pwm_lpss_byt_info}, { PCI_VDEVICE(INTEL, 0x0f09), (unsigned long)&pwm_lpss_byt_info}, + { PCI_VDEVICE(INTEL, 0x1ac8), (unsigned long)&pwm_lpss_bsw_info}, { PCI_VDEVICE(INTEL, 0x2288), (unsigned long)&pwm_lpss_bsw_info}, { PCI_VDEVICE(INTEL, 0x2289), (unsigned long)&pwm_lpss_bsw_info}, { }, -- cgit v1.2.3