pwm: Changes for v4.2-rc1
This has a couple of fixes for Atmel, Samsung and Broadcom drivers. Some preparatory patches for more upcoming Intel work is included as well. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJVevH0AAoJEN0jrNd/PrOhUDsP/0N3DTBrwHGY2TRtniXK5PsX Dz9Txm1dUlSRc/4QmYfmBPB3GzgtbKMAXP/SJBJ5SP48RZYvzjfHLxEKEoJqkMg+ h9btE1fReQ50H0HmH4L8+jkjSsA15m39T5yuX+KR5P6Uxv7WFMyVDgBw4dmARIzK wOwuy8r+6ZtAdsj+o0eSoOxs64HgUiJRN/9FDJi9fPGi27smAXH2Nef5uja9upnt CR+ntOxYXXRJM2JnW9ObPK87wvZsiIJw1QrRIWPRaUesZjXxH+11eTKS4YaSjnhz 93aLDWXVBm9goXeYnqe+aRq0PHIRIHcND6Fh4+cb42dVYdINnW6h9Y9WBSUeVHwx cKumJUU6wBbTSUUWKnvGi1NFmrMvxbf3knE0maQjswHOf5SEdCh0q/VNh/HWGGPI sglqjl5KmJPx9Afr97RNNqymYS9ECT0yHajY+5ivgvD4XlPFam2NPpyi1CjJaqaU rnwhabnpnpq7zeD78f5gvLSENWvwnYCVQTwp0YLkJ2o+9gGPh+FuJ6KcZ3m7LGXC jb1VuAy+0896eP3VlK1LqwDkyBVFkWZQqwuLnER6zHuMTetx0tfosj8Nenv0z+fv VccUDgYuh8G/SHYNDVdpRmHDIb34ZpMjSxbXaFOKTPsxAhlNfu4ylcrKZijIkK+a YmYJgj9pGqww50LVK0R/ =VmI2 -----END PGP SIGNATURE----- Merge tag 'pwm/for-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm Pull pwm updates from Thierry Reding: "This has a couple of fixes for Atmel, Samsung and Broadcom drivers. Some preparatory patches for more upcoming Intel work is included as well" * tag 'pwm/for-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm: pwm: lpss: pci: Add support for Broxton platform pwm: bcm-kona: Don't set polarity in probe pwm: Add pwmchip_add_with_polarity() API pwm: atmel: Fix incorrect CDTY value after disabling pwm: atmel: Fix incorrect CDTY value after enabling pwm: samsung: Use MODULE_DEVICE_TABLE() to include OF modalias pwm: Add support to remove registered consumer lookup tables
This commit is contained in:
commit
c70c5fb2b9
|
@ -223,13 +223,16 @@ void *pwm_get_chip_data(struct pwm_device *pwm)
|
||||||
EXPORT_SYMBOL_GPL(pwm_get_chip_data);
|
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
|
* @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
|
* 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;
|
struct pwm_device *pwm;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
@ -259,6 +262,7 @@ int pwmchip_add(struct pwm_chip *chip)
|
||||||
pwm->chip = chip;
|
pwm->chip = chip;
|
||||||
pwm->pwm = chip->base + i;
|
pwm->pwm = chip->base + i;
|
||||||
pwm->hwpwm = i;
|
pwm->hwpwm = i;
|
||||||
|
pwm->polarity = polarity;
|
||||||
|
|
||||||
radix_tree_insert(&pwm_tree, pwm->pwm, pwm);
|
radix_tree_insert(&pwm_tree, pwm->pwm, pwm);
|
||||||
}
|
}
|
||||||
|
@ -279,6 +283,19 @@ out:
|
||||||
mutex_unlock(&pwm_lock);
|
mutex_unlock(&pwm_lock);
|
||||||
return ret;
|
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);
|
EXPORT_SYMBOL_GPL(pwmchip_add);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -585,6 +602,23 @@ void pwm_add_table(struct pwm_lookup *table, size_t num)
|
||||||
mutex_unlock(&pwm_lookup_lock);
|
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
|
* pwm_get() - look up and request a PWM device
|
||||||
* @dev: device for PWM consumer
|
* @dev: device for PWM consumer
|
||||||
|
|
|
@ -8,9 +8,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
@ -21,6 +23,7 @@
|
||||||
#define PWM_ENA 0x04
|
#define PWM_ENA 0x04
|
||||||
#define PWM_DIS 0x08
|
#define PWM_DIS 0x08
|
||||||
#define PWM_SR 0x0C
|
#define PWM_SR 0x0C
|
||||||
|
#define PWM_ISR 0x1C
|
||||||
/* Bit field in SR */
|
/* Bit field in SR */
|
||||||
#define PWM_SR_ALL_CH_ON 0x0F
|
#define PWM_SR_ALL_CH_ON 0x0F
|
||||||
|
|
||||||
|
@ -60,6 +63,9 @@ struct atmel_pwm_chip {
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
void __iomem *base;
|
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,
|
void (*config)(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||||
unsigned long dty, unsigned long prd);
|
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);
|
val = (val & ~PWM_CMR_CPRE_MSK) | (pres & PWM_CMR_CPRE_MSK);
|
||||||
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
|
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
|
||||||
atmel_pwm->config(chip, pwm, dty, prd);
|
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);
|
clk_disable(atmel_pwm->clk);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -155,24 +165,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);
|
struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
|
||||||
unsigned int val;
|
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);
|
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CUPD, dty);
|
||||||
val &= ~PWM_CMR_UPD_CDTY;
|
|
||||||
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
|
val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR);
|
||||||
} else {
|
val &= ~PWM_CMR_UPD_CDTY;
|
||||||
/*
|
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
|
||||||
* If the PWM channel is disabled, write value to duty and
|
|
||||||
* period registers directly.
|
/*
|
||||||
*/
|
* If the PWM channel is enabled, only update CDTY by using the update
|
||||||
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CDTY, dty);
|
* register, it needs to set bit 10 of CMR to 0
|
||||||
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CPRD, prd);
|
*/
|
||||||
}
|
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,
|
static void atmel_pwm_config_v2(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||||
|
@ -242,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)
|
static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||||
{
|
{
|
||||||
struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
|
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);
|
atmel_pwm_writel(atmel_pwm, PWM_DIS, 1 << pwm->hwpwm);
|
||||||
|
|
||||||
clk_disable(atmel_pwm->clk);
|
clk_disable(atmel_pwm->clk);
|
||||||
|
@ -357,6 +383,8 @@ static int atmel_pwm_probe(struct platform_device *pdev)
|
||||||
atmel_pwm->chip.npwm = 4;
|
atmel_pwm->chip.npwm = 4;
|
||||||
atmel_pwm->chip.can_sleep = true;
|
atmel_pwm->chip.can_sleep = true;
|
||||||
atmel_pwm->config = data->config;
|
atmel_pwm->config = data->config;
|
||||||
|
atmel_pwm->updated_pwms = 0;
|
||||||
|
mutex_init(&atmel_pwm->isr_lock);
|
||||||
|
|
||||||
ret = pwmchip_add(&atmel_pwm->chip);
|
ret = pwmchip_add(&atmel_pwm->chip);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -378,6 +406,7 @@ static int atmel_pwm_remove(struct platform_device *pdev)
|
||||||
struct atmel_pwm_chip *atmel_pwm = platform_get_drvdata(pdev);
|
struct atmel_pwm_chip *atmel_pwm = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
clk_unprepare(atmel_pwm->clk);
|
clk_unprepare(atmel_pwm->clk);
|
||||||
|
mutex_destroy(&atmel_pwm->isr_lock);
|
||||||
|
|
||||||
return pwmchip_remove(&atmel_pwm->chip);
|
return pwmchip_remove(&atmel_pwm->chip);
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,18 +266,15 @@ static int kona_pwmc_probe(struct platform_device *pdev)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set smooth mode, push/pull, and normal polarity for all channels */
|
/* Set push/pull for all channels */
|
||||||
for (chan = 0; chan < kp->chip.npwm; chan++) {
|
for (chan = 0; chan < kp->chip.npwm; chan++)
|
||||||
value |= (1 << PWM_CONTROL_SMOOTH_SHIFT(chan));
|
|
||||||
value |= (1 << PWM_CONTROL_TYPE_SHIFT(chan));
|
value |= (1 << PWM_CONTROL_TYPE_SHIFT(chan));
|
||||||
value |= (1 << PWM_CONTROL_POLARITY_SHIFT(chan));
|
|
||||||
}
|
|
||||||
|
|
||||||
writel(value, kp->base + PWM_CONTROL_OFFSET);
|
writel(value, kp->base + PWM_CONTROL_OFFSET);
|
||||||
|
|
||||||
clk_disable_unprepare(kp->clk);
|
clk_disable_unprepare(kp->clk);
|
||||||
|
|
||||||
ret = pwmchip_add(&kp->chip);
|
ret = pwmchip_add_with_polarity(&kp->chip, PWM_POLARITY_INVERSED);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
|
dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
|
||||||
|
|
||||||
|
|
|
@ -44,8 +44,10 @@ static void pwm_lpss_remove_pci(struct pci_dev *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct pci_device_id pwm_lpss_pci_ids[] = {
|
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, 0x0f08), (unsigned long)&pwm_lpss_byt_info},
|
||||||
{ PCI_VDEVICE(INTEL, 0x0f09), (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, 0x2288), (unsigned long)&pwm_lpss_bsw_info},
|
||||||
{ PCI_VDEVICE(INTEL, 0x2289), (unsigned long)&pwm_lpss_bsw_info},
|
{ PCI_VDEVICE(INTEL, 0x2289), (unsigned long)&pwm_lpss_bsw_info},
|
||||||
{ },
|
{ },
|
||||||
|
|
|
@ -456,6 +456,7 @@ static const struct of_device_id samsung_pwm_matches[] = {
|
||||||
{ .compatible = "samsung,exynos4210-pwm", .data = &s5p64x0_variant },
|
{ .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)
|
static int pwm_samsung_parse_dt(struct samsung_pwm_chip *chip)
|
||||||
{
|
{
|
||||||
|
|
|
@ -182,6 +182,8 @@ struct pwm_chip {
|
||||||
int pwm_set_chip_data(struct pwm_device *pwm, void *data);
|
int pwm_set_chip_data(struct pwm_device *pwm, void *data);
|
||||||
void *pwm_get_chip_data(struct pwm_device *pwm);
|
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_add(struct pwm_chip *chip);
|
||||||
int pwmchip_remove(struct pwm_chip *chip);
|
int pwmchip_remove(struct pwm_chip *chip);
|
||||||
struct pwm_device *pwm_request_from_chip(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;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int pwmchip_add_inversed(struct pwm_chip *chip)
|
||||||
|
{
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int pwmchip_remove(struct pwm_chip *chip)
|
static inline int pwmchip_remove(struct pwm_chip *chip)
|
||||||
{
|
{
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -290,10 +297,15 @@ struct pwm_lookup {
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_PWM)
|
#if IS_ENABLED(CONFIG_PWM)
|
||||||
void pwm_add_table(struct pwm_lookup *table, size_t num);
|
void pwm_add_table(struct pwm_lookup *table, size_t num);
|
||||||
|
void pwm_remove_table(struct pwm_lookup *table, size_t num);
|
||||||
#else
|
#else
|
||||||
static inline void pwm_add_table(struct pwm_lookup *table, size_t num)
|
static inline void pwm_add_table(struct pwm_lookup *table, size_t num)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void pwm_remove_table(struct pwm_lookup *table, size_t num)
|
||||||
|
{
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PWM_SYSFS
|
#ifdef CONFIG_PWM_SYSFS
|
||||||
|
|
Loading…
Reference in New Issue