aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-05-25 13:40:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-25 13:40:15 -0400
commitecc5fbd5ef472a4c659dc56a5739b3f041c0530c (patch)
treeeec1c3ddd6082e6391d7d27ae78d813a8f6c216c /drivers/pwm
parent1f93d2abf488c6a41bdd5e6caf80b559493eea8d (diff)
parent18c588786c08458f5d965d8735ab48f9e51e0b4b (diff)
Merge tag 'pwm/for-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm
Pull pwm updates from Thierry Reding: "This set of changes introduces an atomic API to the PWM subsystem. This is influenced by the DRM atomic API that was introduced a while back, though it is obviously a lot simpler. The fundamental idea remains the same, though: drivers provide a single callback to implement the atomic configuration of a PWM channel. As a side-effect the PWM subsystem gains the ability for initial state retrieval, so that the logical state mirrors that of the hardware. Many use-cases don't care about this, but for others it is essential. These new features require changes in all users, which these patches take care of. The core is transitioned to use the atomic callback if available and provides a fallback mechanism for other drivers. Changes to transition users and drivers to the atomic API are postponed to v4.8" * tag 'pwm/for-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm: (30 commits) pwm: Add information about polarity, duty cycle and period to debugfs pwm: Switch to the atomic API pwm: Update documentation pwm: Add core infrastructure to allow atomic updates pwm: Add hardware readout infrastructure pwm: Move the enabled/disabled info into pwm_state pwm: Introduce the pwm_state concept pwm: Keep PWM state in sync with hardware state ARM: Explicitly apply PWM config extracted from pwm_args drm: i915: Explicitly apply PWM config extracted from pwm_args input: misc: pwm-beeper: Explicitly apply PWM config extracted from pwm_args input: misc: max8997: Explicitly apply PWM config extracted from pwm_args backlight: lm3630a: explicitly apply PWM config extracted from pwm_args backlight: lp855x: Explicitly apply PWM config extracted from pwm_args backlight: lp8788: Explicitly apply PWM config extracted from pwm_args backlight: pwm_bl: Use pwm_get_args() where appropriate fbdev: ssd1307fb: Use pwm_get_args() where appropriate regulator: pwm: Use pwm_get_args() where appropriate leds: pwm: Use pwm_get_args() where appropriate input: misc: max77693: Use pwm_get_args() where appropriate ...
Diffstat (limited to 'drivers/pwm')
-rw-r--r--drivers/pwm/core.c224
-rw-r--r--drivers/pwm/pwm-crc.c2
-rw-r--r--drivers/pwm/pwm-lpc18xx-sct.c2
-rw-r--r--drivers/pwm/pwm-omap-dmtimer.c2
-rw-r--r--drivers/pwm/pwm-rcar.c2
-rw-r--r--drivers/pwm/pwm-sun4i.c3
-rw-r--r--drivers/pwm/sysfs.c70
7 files changed, 199 insertions, 106 deletions
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 680fbc795a0a..dba3843c53b8 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -75,6 +75,7 @@ static void free_pwms(struct pwm_chip *chip)
75 75
76 for (i = 0; i < chip->npwm; i++) { 76 for (i = 0; i < chip->npwm; i++) {
77 struct pwm_device *pwm = &chip->pwms[i]; 77 struct pwm_device *pwm = &chip->pwms[i];
78
78 radix_tree_delete(&pwm_tree, pwm->pwm); 79 radix_tree_delete(&pwm_tree, pwm->pwm);
79 } 80 }
80 81
@@ -128,13 +129,6 @@ static int pwm_device_request(struct pwm_device *pwm, const char *label)
128 set_bit(PWMF_REQUESTED, &pwm->flags); 129 set_bit(PWMF_REQUESTED, &pwm->flags);
129 pwm->label = label; 130 pwm->label = label;
130 131
131 /*
132 * FIXME: This should be removed once all PWM users properly make use
133 * of struct pwm_args to initialize the PWM device. As long as this is
134 * here, the PWM state and hardware state can get out of sync.
135 */
136 pwm_apply_args(pwm);
137
138 return 0; 132 return 0;
139} 133}
140 134
@@ -233,6 +227,19 @@ void *pwm_get_chip_data(struct pwm_device *pwm)
233} 227}
234EXPORT_SYMBOL_GPL(pwm_get_chip_data); 228EXPORT_SYMBOL_GPL(pwm_get_chip_data);
235 229
230static bool pwm_ops_check(const struct pwm_ops *ops)
231{
232 /* driver supports legacy, non-atomic operation */
233 if (ops->config && ops->enable && ops->disable)
234 return true;
235
236 /* driver supports atomic operation */
237 if (ops->apply)
238 return true;
239
240 return false;
241}
242
236/** 243/**
237 * pwmchip_add_with_polarity() - register a new PWM chip 244 * pwmchip_add_with_polarity() - register a new PWM chip
238 * @chip: the PWM chip to add 245 * @chip: the PWM chip to add
@@ -251,8 +258,10 @@ int pwmchip_add_with_polarity(struct pwm_chip *chip,
251 unsigned int i; 258 unsigned int i;
252 int ret; 259 int ret;
253 260
254 if (!chip || !chip->dev || !chip->ops || !chip->ops->config || 261 if (!chip || !chip->dev || !chip->ops || !chip->npwm)
255 !chip->ops->enable || !chip->ops->disable || !chip->npwm) 262 return -EINVAL;
263
264 if (!pwm_ops_check(chip->ops))
256 return -EINVAL; 265 return -EINVAL;
257 266
258 mutex_lock(&pwm_lock); 267 mutex_lock(&pwm_lock);
@@ -261,7 +270,7 @@ int pwmchip_add_with_polarity(struct pwm_chip *chip,
261 if (ret < 0) 270 if (ret < 0)
262 goto out; 271 goto out;
263 272
264 chip->pwms = kzalloc(chip->npwm * sizeof(*pwm), GFP_KERNEL); 273 chip->pwms = kcalloc(chip->npwm, sizeof(*pwm), GFP_KERNEL);
265 if (!chip->pwms) { 274 if (!chip->pwms) {
266 ret = -ENOMEM; 275 ret = -ENOMEM;
267 goto out; 276 goto out;
@@ -275,8 +284,10 @@ int pwmchip_add_with_polarity(struct pwm_chip *chip,
275 pwm->chip = chip; 284 pwm->chip = chip;
276 pwm->pwm = chip->base + i; 285 pwm->pwm = chip->base + i;
277 pwm->hwpwm = i; 286 pwm->hwpwm = i;
278 pwm->polarity = polarity; 287 pwm->state.polarity = polarity;
279 mutex_init(&pwm->lock); 288
289 if (chip->ops->get_state)
290 chip->ops->get_state(chip, pwm, &pwm->state);
280 291
281 radix_tree_insert(&pwm_tree, pwm->pwm, pwm); 292 radix_tree_insert(&pwm_tree, pwm->pwm, pwm);
282 } 293 }
@@ -436,107 +447,138 @@ void pwm_free(struct pwm_device *pwm)
436EXPORT_SYMBOL_GPL(pwm_free); 447EXPORT_SYMBOL_GPL(pwm_free);
437 448
438/** 449/**
439 * pwm_config() - change a PWM device configuration 450 * pwm_apply_state() - atomically apply a new state to a PWM device
440 * @pwm: PWM device 451 * @pwm: PWM device
441 * @duty_ns: "on" time (in nanoseconds) 452 * @state: new state to apply. This can be adjusted by the PWM driver
442 * @period_ns: duration (in nanoseconds) of one cycle 453 * if the requested config is not achievable, for example,
443 * 454 * ->duty_cycle and ->period might be approximated.
444 * Returns: 0 on success or a negative error code on failure.
445 */ 455 */
446int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) 456int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state)
447{ 457{
448 int err; 458 int err;
449 459
450 if (!pwm || duty_ns < 0 || period_ns <= 0 || duty_ns > period_ns) 460 if (!pwm)
451 return -EINVAL; 461 return -EINVAL;
452 462
453 err = pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns); 463 if (!memcmp(state, &pwm->state, sizeof(*state)))
454 if (err) 464 return 0;
455 return err;
456
457 pwm->duty_cycle = duty_ns;
458 pwm->period = period_ns;
459 465
460 return 0; 466 if (pwm->chip->ops->apply) {
461} 467 err = pwm->chip->ops->apply(pwm->chip, pwm, state);
462EXPORT_SYMBOL_GPL(pwm_config); 468 if (err)
469 return err;
463 470
464/** 471 pwm->state = *state;
465 * pwm_set_polarity() - configure the polarity of a PWM signal 472 } else {
466 * @pwm: PWM device 473 /*
467 * @polarity: new polarity of the PWM signal 474 * FIXME: restore the initial state in case of error.
468 * 475 */
469 * Note that the polarity cannot be configured while the PWM device is 476 if (state->polarity != pwm->state.polarity) {
470 * enabled. 477 if (!pwm->chip->ops->set_polarity)
471 * 478 return -ENOTSUPP;
472 * Returns: 0 on success or a negative error code on failure. 479
473 */ 480 /*
474int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity) 481 * Changing the polarity of a running PWM is
475{ 482 * only allowed when the PWM driver implements
476 int err; 483 * ->apply().
484 */
485 if (pwm->state.enabled) {
486 pwm->chip->ops->disable(pwm->chip, pwm);
487 pwm->state.enabled = false;
488 }
489
490 err = pwm->chip->ops->set_polarity(pwm->chip, pwm,
491 state->polarity);
492 if (err)
493 return err;
494
495 pwm->state.polarity = state->polarity;
496 }
477 497
478 if (!pwm || !pwm->chip->ops) 498 if (state->period != pwm->state.period ||
479 return -EINVAL; 499 state->duty_cycle != pwm->state.duty_cycle) {
500 err = pwm->chip->ops->config(pwm->chip, pwm,
501 state->duty_cycle,
502 state->period);
503 if (err)
504 return err;
480 505
481 if (!pwm->chip->ops->set_polarity) 506 pwm->state.duty_cycle = state->duty_cycle;
482 return -ENOSYS; 507 pwm->state.period = state->period;
508 }
483 509
484 mutex_lock(&pwm->lock); 510 if (state->enabled != pwm->state.enabled) {
511 if (state->enabled) {
512 err = pwm->chip->ops->enable(pwm->chip, pwm);
513 if (err)
514 return err;
515 } else {
516 pwm->chip->ops->disable(pwm->chip, pwm);
517 }
485 518
486 if (pwm_is_enabled(pwm)) { 519 pwm->state.enabled = state->enabled;
487 err = -EBUSY; 520 }
488 goto unlock;
489 } 521 }
490 522
491 err = pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity); 523 return 0;
492 if (err)
493 goto unlock;
494
495 pwm->polarity = polarity;
496
497unlock:
498 mutex_unlock(&pwm->lock);
499 return err;
500} 524}
501EXPORT_SYMBOL_GPL(pwm_set_polarity); 525EXPORT_SYMBOL_GPL(pwm_apply_state);
502 526
503/** 527/**
504 * pwm_enable() - start a PWM output toggling 528 * pwm_adjust_config() - adjust the current PWM config to the PWM arguments
505 * @pwm: PWM device 529 * @pwm: PWM device
506 * 530 *
507 * Returns: 0 on success or a negative error code on failure. 531 * This function will adjust the PWM config to the PWM arguments provided
532 * by the DT or PWM lookup table. This is particularly useful to adapt
533 * the bootloader config to the Linux one.
508 */ 534 */
509int pwm_enable(struct pwm_device *pwm) 535int pwm_adjust_config(struct pwm_device *pwm)
510{ 536{
511 int err = 0; 537 struct pwm_state state;
538 struct pwm_args pargs;
512 539
513 if (!pwm) 540 pwm_get_args(pwm, &pargs);
514 return -EINVAL; 541 pwm_get_state(pwm, &state);
515 542
516 mutex_lock(&pwm->lock); 543 /*
544 * If the current period is zero it means that either the PWM driver
545 * does not support initial state retrieval or the PWM has not yet
546 * been configured.
547 *
548 * In either case, we setup the new period and polarity, and assign a
549 * duty cycle of 0.
550 */
551 if (!state.period) {
552 state.duty_cycle = 0;
553 state.period = pargs.period;
554 state.polarity = pargs.polarity;
517 555
518 if (!test_and_set_bit(PWMF_ENABLED, &pwm->flags)) { 556 return pwm_apply_state(pwm, &state);
519 err = pwm->chip->ops->enable(pwm->chip, pwm);
520 if (err)
521 clear_bit(PWMF_ENABLED, &pwm->flags);
522 } 557 }
523 558
524 mutex_unlock(&pwm->lock); 559 /*
560 * Adjust the PWM duty cycle/period based on the period value provided
561 * in PWM args.
562 */
563 if (pargs.period != state.period) {
564 u64 dutycycle = (u64)state.duty_cycle * pargs.period;
525 565
526 return err; 566 do_div(dutycycle, state.period);
527} 567 state.duty_cycle = dutycycle;
528EXPORT_SYMBOL_GPL(pwm_enable); 568 state.period = pargs.period;
569 }
529 570
530/** 571 /*
531 * pwm_disable() - stop a PWM output toggling 572 * If the polarity changed, we should also change the duty cycle.
532 * @pwm: PWM device 573 */
533 */ 574 if (pargs.polarity != state.polarity) {
534void pwm_disable(struct pwm_device *pwm) 575 state.polarity = pargs.polarity;
535{ 576 state.duty_cycle = state.period - state.duty_cycle;
536 if (pwm && test_and_clear_bit(PWMF_ENABLED, &pwm->flags)) 577 }
537 pwm->chip->ops->disable(pwm->chip, pwm); 578
579 return pwm_apply_state(pwm, &state);
538} 580}
539EXPORT_SYMBOL_GPL(pwm_disable); 581EXPORT_SYMBOL_GPL(pwm_adjust_config);
540 582
541static struct pwm_chip *of_node_to_pwmchip(struct device_node *np) 583static struct pwm_chip *of_node_to_pwmchip(struct device_node *np)
542{ 584{
@@ -754,13 +796,13 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
754 if (!chip) 796 if (!chip)
755 goto out; 797 goto out;
756 798
757 pwm->args.period = chosen->period;
758 pwm->args.polarity = chosen->polarity;
759
760 pwm = pwm_request_from_chip(chip, chosen->index, con_id ?: dev_id); 799 pwm = pwm_request_from_chip(chip, chosen->index, con_id ?: dev_id);
761 if (IS_ERR(pwm)) 800 if (IS_ERR(pwm))
762 goto out; 801 goto out;
763 802
803 pwm->args.period = chosen->period;
804 pwm->args.polarity = chosen->polarity;
805
764out: 806out:
765 mutex_unlock(&pwm_lookup_lock); 807 mutex_unlock(&pwm_lookup_lock);
766 return pwm; 808 return pwm;
@@ -907,15 +949,23 @@ static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s)
907 949
908 for (i = 0; i < chip->npwm; i++) { 950 for (i = 0; i < chip->npwm; i++) {
909 struct pwm_device *pwm = &chip->pwms[i]; 951 struct pwm_device *pwm = &chip->pwms[i];
952 struct pwm_state state;
953
954 pwm_get_state(pwm, &state);
910 955
911 seq_printf(s, " pwm-%-3d (%-20.20s):", i, pwm->label); 956 seq_printf(s, " pwm-%-3d (%-20.20s):", i, pwm->label);
912 957
913 if (test_bit(PWMF_REQUESTED, &pwm->flags)) 958 if (test_bit(PWMF_REQUESTED, &pwm->flags))
914 seq_puts(s, " requested"); 959 seq_puts(s, " requested");
915 960
916 if (pwm_is_enabled(pwm)) 961 if (state.enabled)
917 seq_puts(s, " enabled"); 962 seq_puts(s, " enabled");
918 963
964 seq_printf(s, " period: %u ns", state.period);
965 seq_printf(s, " duty: %u ns", state.duty_cycle);
966 seq_printf(s, " polarity: %s",
967 state.polarity ? "inverse" : "normal");
968
919 seq_puts(s, "\n"); 969 seq_puts(s, "\n");
920 } 970 }
921} 971}
diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c
index 7101c7020bf4..bd0ebd04856a 100644
--- a/drivers/pwm/pwm-crc.c
+++ b/drivers/pwm/pwm-crc.c
@@ -75,7 +75,7 @@ static int crc_pwm_config(struct pwm_chip *c, struct pwm_device *pwm,
75 return -EINVAL; 75 return -EINVAL;
76 } 76 }
77 77
78 if (pwm->period != period_ns) { 78 if (pwm_get_period(pwm) != period_ns) {
79 int clk_div; 79 int clk_div;
80 80
81 /* changing the clk divisor, need to disable fisrt */ 81 /* changing the clk divisor, need to disable fisrt */
diff --git a/drivers/pwm/pwm-lpc18xx-sct.c b/drivers/pwm/pwm-lpc18xx-sct.c
index 9861fed4e67d..19dc64cab2f0 100644
--- a/drivers/pwm/pwm-lpc18xx-sct.c
+++ b/drivers/pwm/pwm-lpc18xx-sct.c
@@ -249,7 +249,7 @@ static int lpc18xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
249 LPC18XX_PWM_EVSTATEMSK(lpc18xx_data->duty_event), 249 LPC18XX_PWM_EVSTATEMSK(lpc18xx_data->duty_event),
250 LPC18XX_PWM_EVSTATEMSK_ALL); 250 LPC18XX_PWM_EVSTATEMSK_ALL);
251 251
252 if (pwm->polarity == PWM_POLARITY_NORMAL) { 252 if (pwm_get_polarity(pwm) == PWM_POLARITY_NORMAL) {
253 set_event = lpc18xx_pwm->period_event; 253 set_event = lpc18xx_pwm->period_event;
254 clear_event = lpc18xx_data->duty_event; 254 clear_event = lpc18xx_data->duty_event;
255 res_action = LPC18XX_PWM_RES_SET; 255 res_action = LPC18XX_PWM_RES_SET;
diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c
index b7e6ecba7d5c..3e95090cd7cf 100644
--- a/drivers/pwm/pwm-omap-dmtimer.c
+++ b/drivers/pwm/pwm-omap-dmtimer.c
@@ -192,7 +192,7 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
192 load_value, load_value, match_value, match_value); 192 load_value, load_value, match_value, match_value);
193 193
194 omap->pdata->set_pwm(omap->dm_timer, 194 omap->pdata->set_pwm(omap->dm_timer,
195 pwm->polarity == PWM_POLARITY_INVERSED, 195 pwm_get_polarity(pwm) == PWM_POLARITY_INVERSED,
196 true, 196 true,
197 PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE); 197 PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE);
198 198
diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c
index 7b8ac0678137..1c85ecc9e7ac 100644
--- a/drivers/pwm/pwm-rcar.c
+++ b/drivers/pwm/pwm-rcar.c
@@ -157,7 +157,7 @@ static int rcar_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
157 return div; 157 return div;
158 158
159 /* Let the core driver set pwm->period if disabled and duty_ns == 0 */ 159 /* Let the core driver set pwm->period if disabled and duty_ns == 0 */
160 if (!test_bit(PWMF_ENABLED, &pwm->flags) && !duty_ns) 160 if (!pwm_is_enabled(pwm) && !duty_ns)
161 return 0; 161 return 0;
162 162
163 rcar_pwm_update(rp, RCAR_PWMCR_SYNC, RCAR_PWMCR_SYNC, RCAR_PWMCR); 163 rcar_pwm_update(rp, RCAR_PWMCR_SYNC, RCAR_PWMCR_SYNC, RCAR_PWMCR);
diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c
index 67af9f62361f..03a99a53c39e 100644
--- a/drivers/pwm/pwm-sun4i.c
+++ b/drivers/pwm/pwm-sun4i.c
@@ -354,7 +354,8 @@ static int sun4i_pwm_probe(struct platform_device *pdev)
354 val = sun4i_pwm_readl(pwm, PWM_CTRL_REG); 354 val = sun4i_pwm_readl(pwm, PWM_CTRL_REG);
355 for (i = 0; i < pwm->chip.npwm; i++) 355 for (i = 0; i < pwm->chip.npwm; i++)
356 if (!(val & BIT_CH(PWM_ACT_STATE, i))) 356 if (!(val & BIT_CH(PWM_ACT_STATE, i)))
357 pwm->chip.pwms[i].polarity = PWM_POLARITY_INVERSED; 357 pwm_set_polarity(&pwm->chip.pwms[i],
358 PWM_POLARITY_INVERSED);
358 clk_disable_unprepare(pwm->clk); 359 clk_disable_unprepare(pwm->clk);
359 360
360 return 0; 361 return 0;
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
index 9c90886f4123..d98599249a05 100644
--- a/drivers/pwm/sysfs.c
+++ b/drivers/pwm/sysfs.c
@@ -26,6 +26,7 @@
26struct pwm_export { 26struct pwm_export {
27 struct device child; 27 struct device child;
28 struct pwm_device *pwm; 28 struct pwm_device *pwm;
29 struct mutex lock;
29}; 30};
30 31
31static struct pwm_export *child_to_pwm_export(struct device *child) 32static struct pwm_export *child_to_pwm_export(struct device *child)
@@ -45,15 +46,20 @@ static ssize_t period_show(struct device *child,
45 char *buf) 46 char *buf)
46{ 47{
47 const struct pwm_device *pwm = child_to_pwm_device(child); 48 const struct pwm_device *pwm = child_to_pwm_device(child);
49 struct pwm_state state;
48 50
49 return sprintf(buf, "%u\n", pwm_get_period(pwm)); 51 pwm_get_state(pwm, &state);
52
53 return sprintf(buf, "%u\n", state.period);
50} 54}
51 55
52static ssize_t period_store(struct device *child, 56static ssize_t period_store(struct device *child,
53 struct device_attribute *attr, 57 struct device_attribute *attr,
54 const char *buf, size_t size) 58 const char *buf, size_t size)
55{ 59{
56 struct pwm_device *pwm = child_to_pwm_device(child); 60 struct pwm_export *export = child_to_pwm_export(child);
61 struct pwm_device *pwm = export->pwm;
62 struct pwm_state state;
57 unsigned int val; 63 unsigned int val;
58 int ret; 64 int ret;
59 65
@@ -61,7 +67,11 @@ static ssize_t period_store(struct device *child,
61 if (ret) 67 if (ret)
62 return ret; 68 return ret;
63 69
64 ret = pwm_config(pwm, pwm_get_duty_cycle(pwm), val); 70 mutex_lock(&export->lock);
71 pwm_get_state(pwm, &state);
72 state.period = val;
73 ret = pwm_apply_state(pwm, &state);
74 mutex_unlock(&export->lock);
65 75
66 return ret ? : size; 76 return ret ? : size;
67} 77}
@@ -71,15 +81,20 @@ static ssize_t duty_cycle_show(struct device *child,
71 char *buf) 81 char *buf)
72{ 82{
73 const struct pwm_device *pwm = child_to_pwm_device(child); 83 const struct pwm_device *pwm = child_to_pwm_device(child);
84 struct pwm_state state;
85
86 pwm_get_state(pwm, &state);
74 87
75 return sprintf(buf, "%u\n", pwm_get_duty_cycle(pwm)); 88 return sprintf(buf, "%u\n", state.duty_cycle);
76} 89}
77 90
78static ssize_t duty_cycle_store(struct device *child, 91static ssize_t duty_cycle_store(struct device *child,
79 struct device_attribute *attr, 92 struct device_attribute *attr,
80 const char *buf, size_t size) 93 const char *buf, size_t size)
81{ 94{
82 struct pwm_device *pwm = child_to_pwm_device(child); 95 struct pwm_export *export = child_to_pwm_export(child);
96 struct pwm_device *pwm = export->pwm;
97 struct pwm_state state;
83 unsigned int val; 98 unsigned int val;
84 int ret; 99 int ret;
85 100
@@ -87,7 +102,11 @@ static ssize_t duty_cycle_store(struct device *child,
87 if (ret) 102 if (ret)
88 return ret; 103 return ret;
89 104
90 ret = pwm_config(pwm, val, pwm_get_period(pwm)); 105 mutex_lock(&export->lock);
106 pwm_get_state(pwm, &state);
107 state.duty_cycle = val;
108 ret = pwm_apply_state(pwm, &state);
109 mutex_unlock(&export->lock);
91 110
92 return ret ? : size; 111 return ret ? : size;
93} 112}
@@ -97,33 +116,46 @@ static ssize_t enable_show(struct device *child,
97 char *buf) 116 char *buf)
98{ 117{
99 const struct pwm_device *pwm = child_to_pwm_device(child); 118 const struct pwm_device *pwm = child_to_pwm_device(child);
119 struct pwm_state state;
120
121 pwm_get_state(pwm, &state);
100 122
101 return sprintf(buf, "%d\n", pwm_is_enabled(pwm)); 123 return sprintf(buf, "%d\n", state.enabled);
102} 124}
103 125
104static ssize_t enable_store(struct device *child, 126static ssize_t enable_store(struct device *child,
105 struct device_attribute *attr, 127 struct device_attribute *attr,
106 const char *buf, size_t size) 128 const char *buf, size_t size)
107{ 129{
108 struct pwm_device *pwm = child_to_pwm_device(child); 130 struct pwm_export *export = child_to_pwm_export(child);
131 struct pwm_device *pwm = export->pwm;
132 struct pwm_state state;
109 int val, ret; 133 int val, ret;
110 134
111 ret = kstrtoint(buf, 0, &val); 135 ret = kstrtoint(buf, 0, &val);
112 if (ret) 136 if (ret)
113 return ret; 137 return ret;
114 138
139 mutex_lock(&export->lock);
140
141 pwm_get_state(pwm, &state);
142
115 switch (val) { 143 switch (val) {
116 case 0: 144 case 0:
117 pwm_disable(pwm); 145 state.enabled = false;
118 break; 146 break;
119 case 1: 147 case 1:
120 ret = pwm_enable(pwm); 148 state.enabled = true;
121 break; 149 break;
122 default: 150 default:
123 ret = -EINVAL; 151 ret = -EINVAL;
124 break; 152 goto unlock;
125 } 153 }
126 154
155 pwm_apply_state(pwm, &state);
156
157unlock:
158 mutex_unlock(&export->lock);
127 return ret ? : size; 159 return ret ? : size;
128} 160}
129 161
@@ -133,8 +165,11 @@ static ssize_t polarity_show(struct device *child,
133{ 165{
134 const struct pwm_device *pwm = child_to_pwm_device(child); 166 const struct pwm_device *pwm = child_to_pwm_device(child);
135 const char *polarity = "unknown"; 167 const char *polarity = "unknown";
168 struct pwm_state state;
169
170 pwm_get_state(pwm, &state);
136 171
137 switch (pwm_get_polarity(pwm)) { 172 switch (state.polarity) {
138 case PWM_POLARITY_NORMAL: 173 case PWM_POLARITY_NORMAL:
139 polarity = "normal"; 174 polarity = "normal";
140 break; 175 break;
@@ -151,8 +186,10 @@ static ssize_t polarity_store(struct device *child,
151 struct device_attribute *attr, 186 struct device_attribute *attr,
152 const char *buf, size_t size) 187 const char *buf, size_t size)
153{ 188{
154 struct pwm_device *pwm = child_to_pwm_device(child); 189 struct pwm_export *export = child_to_pwm_export(child);
190 struct pwm_device *pwm = export->pwm;
155 enum pwm_polarity polarity; 191 enum pwm_polarity polarity;
192 struct pwm_state state;
156 int ret; 193 int ret;
157 194
158 if (sysfs_streq(buf, "normal")) 195 if (sysfs_streq(buf, "normal"))
@@ -162,7 +199,11 @@ static ssize_t polarity_store(struct device *child,
162 else 199 else
163 return -EINVAL; 200 return -EINVAL;
164 201
165 ret = pwm_set_polarity(pwm, polarity); 202 mutex_lock(&export->lock);
203 pwm_get_state(pwm, &state);
204 state.polarity = polarity;
205 ret = pwm_apply_state(pwm, &state);
206 mutex_unlock(&export->lock);
166 207
167 return ret ? : size; 208 return ret ? : size;
168} 209}
@@ -203,6 +244,7 @@ static int pwm_export_child(struct device *parent, struct pwm_device *pwm)
203 } 244 }
204 245
205 export->pwm = pwm; 246 export->pwm = pwm;
247 mutex_init(&export->lock);
206 248
207 export->child.release = pwm_export_release; 249 export->child.release = pwm_export_release;
208 export->child.parent = parent; 250 export->child.parent = parent;