Skip to content

Commit c70c5fb

Browse files
committed
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
2 parents 44d21c3 + 361c106 commit c70c5fb

File tree

6 files changed

+101
-26
lines changed

6 files changed

+101
-26
lines changed

drivers/pwm/core.c

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,13 +223,16 @@ void *pwm_get_chip_data(struct pwm_device *pwm)
223223
EXPORT_SYMBOL_GPL(pwm_get_chip_data);
224224

225225
/**
226-
* pwmchip_add() - register a new PWM chip
226+
* pwmchip_add_with_polarity() - register a new PWM chip
227227
* @chip: the PWM chip to add
228+
* @polarity: initial polarity of PWM channels
228229
*
229230
* Register a new PWM chip. If chip->base < 0 then a dynamically assigned base
230-
* will be used.
231+
* will be used. The initial polarity for all channels is specified by the
232+
* @polarity parameter.
231233
*/
232-
int pwmchip_add(struct pwm_chip *chip)
234+
int pwmchip_add_with_polarity(struct pwm_chip *chip,
235+
enum pwm_polarity polarity)
233236
{
234237
struct pwm_device *pwm;
235238
unsigned int i;
@@ -259,6 +262,7 @@ int pwmchip_add(struct pwm_chip *chip)
259262
pwm->chip = chip;
260263
pwm->pwm = chip->base + i;
261264
pwm->hwpwm = i;
265+
pwm->polarity = polarity;
262266

263267
radix_tree_insert(&pwm_tree, pwm->pwm, pwm);
264268
}
@@ -279,6 +283,19 @@ int pwmchip_add(struct pwm_chip *chip)
279283
mutex_unlock(&pwm_lock);
280284
return ret;
281285
}
286+
EXPORT_SYMBOL_GPL(pwmchip_add_with_polarity);
287+
288+
/**
289+
* pwmchip_add() - register a new PWM chip
290+
* @chip: the PWM chip to add
291+
*
292+
* Register a new PWM chip. If chip->base < 0 then a dynamically assigned base
293+
* will be used. The initial polarity for all channels is normal.
294+
*/
295+
int pwmchip_add(struct pwm_chip *chip)
296+
{
297+
return pwmchip_add_with_polarity(chip, PWM_POLARITY_NORMAL);
298+
}
282299
EXPORT_SYMBOL_GPL(pwmchip_add);
283300

284301
/**
@@ -585,6 +602,23 @@ void pwm_add_table(struct pwm_lookup *table, size_t num)
585602
mutex_unlock(&pwm_lookup_lock);
586603
}
587604

605+
/**
606+
* pwm_remove_table() - unregister PWM device consumers
607+
* @table: array of consumers to unregister
608+
* @num: number of consumers in table
609+
*/
610+
void pwm_remove_table(struct pwm_lookup *table, size_t num)
611+
{
612+
mutex_lock(&pwm_lookup_lock);
613+
614+
while (num--) {
615+
list_del(&table->list);
616+
table++;
617+
}
618+
619+
mutex_unlock(&pwm_lookup_lock);
620+
}
621+
588622
/**
589623
* pwm_get() - look up and request a PWM device
590624
* @dev: device for PWM consumer

drivers/pwm/pwm-atmel.c

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
*/
99

1010
#include <linux/clk.h>
11+
#include <linux/delay.h>
1112
#include <linux/err.h>
1213
#include <linux/io.h>
1314
#include <linux/module.h>
15+
#include <linux/mutex.h>
1416
#include <linux/of.h>
1517
#include <linux/of_device.h>
1618
#include <linux/platform_device.h>
@@ -21,6 +23,7 @@
2123
#define PWM_ENA 0x04
2224
#define PWM_DIS 0x08
2325
#define PWM_SR 0x0C
26+
#define PWM_ISR 0x1C
2427
/* Bit field in SR */
2528
#define PWM_SR_ALL_CH_ON 0x0F
2629

@@ -60,6 +63,9 @@ struct atmel_pwm_chip {
6063
struct clk *clk;
6164
void __iomem *base;
6265

66+
unsigned int updated_pwms;
67+
struct mutex isr_lock; /* ISR is cleared when read, ensure only one thread does that */
68+
6369
void (*config)(struct pwm_chip *chip, struct pwm_device *pwm,
6470
unsigned long dty, unsigned long prd);
6571
};
@@ -144,6 +150,10 @@ static int atmel_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
144150
val = (val & ~PWM_CMR_CPRE_MSK) | (pres & PWM_CMR_CPRE_MSK);
145151
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
146152
atmel_pwm->config(chip, pwm, dty, prd);
153+
mutex_lock(&atmel_pwm->isr_lock);
154+
atmel_pwm->updated_pwms |= atmel_pwm_readl(atmel_pwm, PWM_ISR);
155+
atmel_pwm->updated_pwms &= ~(1 << pwm->hwpwm);
156+
mutex_unlock(&atmel_pwm->isr_lock);
147157

148158
clk_disable(atmel_pwm->clk);
149159
return ret;
@@ -155,24 +165,25 @@ static void atmel_pwm_config_v1(struct pwm_chip *chip, struct pwm_device *pwm,
155165
struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
156166
unsigned int val;
157167

158-
if (test_bit(PWMF_ENABLED, &pwm->flags)) {
159-
/*
160-
* If the PWM channel is enabled, using the update register,
161-
* it needs to set bit 10 of CMR to 0
162-
*/
163-
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CUPD, dty);
164168

165-
val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR);
166-
val &= ~PWM_CMR_UPD_CDTY;
167-
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
168-
} else {
169-
/*
170-
* If the PWM channel is disabled, write value to duty and
171-
* period registers directly.
172-
*/
173-
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CDTY, dty);
174-
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CPRD, prd);
175-
}
169+
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CUPD, dty);
170+
171+
val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR);
172+
val &= ~PWM_CMR_UPD_CDTY;
173+
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
174+
175+
/*
176+
* If the PWM channel is enabled, only update CDTY by using the update
177+
* register, it needs to set bit 10 of CMR to 0
178+
*/
179+
if (test_bit(PWMF_ENABLED, &pwm->flags))
180+
return;
181+
/*
182+
* If the PWM channel is disabled, write value to duty and period
183+
* registers directly.
184+
*/
185+
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CDTY, dty);
186+
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CPRD, prd);
176187
}
177188

178189
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)
242253
static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
243254
{
244255
struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
256+
unsigned long timeout = jiffies + 2 * HZ;
257+
258+
/*
259+
* Wait for at least a complete period to have passed before disabling a
260+
* channel to be sure that CDTY has been updated
261+
*/
262+
mutex_lock(&atmel_pwm->isr_lock);
263+
atmel_pwm->updated_pwms |= atmel_pwm_readl(atmel_pwm, PWM_ISR);
264+
265+
while (!(atmel_pwm->updated_pwms & (1 << pwm->hwpwm)) &&
266+
time_before(jiffies, timeout)) {
267+
usleep_range(10, 100);
268+
atmel_pwm->updated_pwms |= atmel_pwm_readl(atmel_pwm, PWM_ISR);
269+
}
245270

271+
mutex_unlock(&atmel_pwm->isr_lock);
246272
atmel_pwm_writel(atmel_pwm, PWM_DIS, 1 << pwm->hwpwm);
247273

248274
clk_disable(atmel_pwm->clk);
@@ -357,6 +383,8 @@ static int atmel_pwm_probe(struct platform_device *pdev)
357383
atmel_pwm->chip.npwm = 4;
358384
atmel_pwm->chip.can_sleep = true;
359385
atmel_pwm->config = data->config;
386+
atmel_pwm->updated_pwms = 0;
387+
mutex_init(&atmel_pwm->isr_lock);
360388

361389
ret = pwmchip_add(&atmel_pwm->chip);
362390
if (ret < 0) {
@@ -378,6 +406,7 @@ static int atmel_pwm_remove(struct platform_device *pdev)
378406
struct atmel_pwm_chip *atmel_pwm = platform_get_drvdata(pdev);
379407

380408
clk_unprepare(atmel_pwm->clk);
409+
mutex_destroy(&atmel_pwm->isr_lock);
381410

382411
return pwmchip_remove(&atmel_pwm->chip);
383412
}

drivers/pwm/pwm-bcm-kona.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -266,18 +266,15 @@ static int kona_pwmc_probe(struct platform_device *pdev)
266266
return ret;
267267
}
268268

269-
/* Set smooth mode, push/pull, and normal polarity for all channels */
270-
for (chan = 0; chan < kp->chip.npwm; chan++) {
271-
value |= (1 << PWM_CONTROL_SMOOTH_SHIFT(chan));
269+
/* Set push/pull for all channels */
270+
for (chan = 0; chan < kp->chip.npwm; chan++)
272271
value |= (1 << PWM_CONTROL_TYPE_SHIFT(chan));
273-
value |= (1 << PWM_CONTROL_POLARITY_SHIFT(chan));
274-
}
275272

276273
writel(value, kp->base + PWM_CONTROL_OFFSET);
277274

278275
clk_disable_unprepare(kp->clk);
279276

280-
ret = pwmchip_add(&kp->chip);
277+
ret = pwmchip_add_with_polarity(&kp->chip, PWM_POLARITY_INVERSED);
281278
if (ret < 0)
282279
dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
283280

drivers/pwm/pwm-lpss-pci.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ static void pwm_lpss_remove_pci(struct pci_dev *pdev)
4444
}
4545

4646
static const struct pci_device_id pwm_lpss_pci_ids[] = {
47+
{ PCI_VDEVICE(INTEL, 0x0ac8), (unsigned long)&pwm_lpss_bsw_info},
4748
{ PCI_VDEVICE(INTEL, 0x0f08), (unsigned long)&pwm_lpss_byt_info},
4849
{ PCI_VDEVICE(INTEL, 0x0f09), (unsigned long)&pwm_lpss_byt_info},
50+
{ PCI_VDEVICE(INTEL, 0x1ac8), (unsigned long)&pwm_lpss_bsw_info},
4951
{ PCI_VDEVICE(INTEL, 0x2288), (unsigned long)&pwm_lpss_bsw_info},
5052
{ PCI_VDEVICE(INTEL, 0x2289), (unsigned long)&pwm_lpss_bsw_info},
5153
{ },

drivers/pwm/pwm-samsung.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,7 @@ static const struct of_device_id samsung_pwm_matches[] = {
456456
{ .compatible = "samsung,exynos4210-pwm", .data = &s5p64x0_variant },
457457
{},
458458
};
459+
MODULE_DEVICE_TABLE(of, samsung_pwm_matches);
459460

460461
static int pwm_samsung_parse_dt(struct samsung_pwm_chip *chip)
461462
{

include/linux/pwm.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ struct pwm_chip {
182182
int pwm_set_chip_data(struct pwm_device *pwm, void *data);
183183
void *pwm_get_chip_data(struct pwm_device *pwm);
184184

185+
int pwmchip_add_with_polarity(struct pwm_chip *chip,
186+
enum pwm_polarity polarity);
185187
int pwmchip_add(struct pwm_chip *chip);
186188
int pwmchip_remove(struct pwm_chip *chip);
187189
struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
@@ -217,6 +219,11 @@ static inline int pwmchip_add(struct pwm_chip *chip)
217219
return -EINVAL;
218220
}
219221

222+
static inline int pwmchip_add_inversed(struct pwm_chip *chip)
223+
{
224+
return -EINVAL;
225+
}
226+
220227
static inline int pwmchip_remove(struct pwm_chip *chip)
221228
{
222229
return -EINVAL;
@@ -290,10 +297,15 @@ struct pwm_lookup {
290297

291298
#if IS_ENABLED(CONFIG_PWM)
292299
void pwm_add_table(struct pwm_lookup *table, size_t num);
300+
void pwm_remove_table(struct pwm_lookup *table, size_t num);
293301
#else
294302
static inline void pwm_add_table(struct pwm_lookup *table, size_t num)
295303
{
296304
}
305+
306+
static inline void pwm_remove_table(struct pwm_lookup *table, size_t num)
307+
{
308+
}
297309
#endif
298310

299311
#ifdef CONFIG_PWM_SYSFS

0 commit comments

Comments
 (0)