Skip to content

Commit 41652aa

Browse files
committed
Merge tag 'pwm/for-5.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm
Pull pwm updates from Thierry Reding: "This contains a number of nice cleanups and improvements for the core and various drivers, as well as a minor tweak to the json-schema device tree bindings" * tag 'pwm/for-5.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm: dt-bindings: pwm: Avoid selecting schema on node name match pwm: img: Use only a single idiom to get a runtime PM reference pwm: vt8500: Implement .apply() callback pwm: img: Implement .apply() callback pwm: twl: Implement .apply() callback pwm: Restore initial state if a legacy callback fails pwm: Prevent a glitch for legacy drivers pwm: Move legacy driver handling into a dedicated function
2 parents fa2e1ba + 3f05654 commit 41652aa

File tree

5 files changed

+213
-82
lines changed

5 files changed

+213
-82
lines changed

Documentation/devicetree/bindings/pwm/pwm.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ title: PWM controllers (providers)
99
maintainers:
1010
- Thierry Reding <[email protected]>
1111

12+
select: false
13+
1214
properties:
1315
$nodename:
1416
pattern: "^pwm(@.*|-[0-9a-f])*$"

drivers/pwm/core.c

Lines changed: 79 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,73 @@ static void pwm_apply_state_debug(struct pwm_device *pwm,
548548
}
549549
}
550550

551+
static int pwm_apply_legacy(struct pwm_chip *chip, struct pwm_device *pwm,
552+
const struct pwm_state *state)
553+
{
554+
int err;
555+
struct pwm_state initial_state = pwm->state;
556+
557+
if (state->polarity != pwm->state.polarity) {
558+
if (!chip->ops->set_polarity)
559+
return -EINVAL;
560+
561+
/*
562+
* Changing the polarity of a running PWM is only allowed when
563+
* the PWM driver implements ->apply().
564+
*/
565+
if (pwm->state.enabled) {
566+
chip->ops->disable(chip, pwm);
567+
568+
/*
569+
* Update pwm->state already here in case
570+
* .set_polarity() or another callback depend on that.
571+
*/
572+
pwm->state.enabled = false;
573+
}
574+
575+
err = chip->ops->set_polarity(chip, pwm, state->polarity);
576+
if (err)
577+
goto rollback;
578+
579+
pwm->state.polarity = state->polarity;
580+
}
581+
582+
if (!state->enabled) {
583+
if (pwm->state.enabled)
584+
chip->ops->disable(chip, pwm);
585+
586+
return 0;
587+
}
588+
589+
/*
590+
* We cannot skip calling ->config even if state->period ==
591+
* pwm->state.period && state->duty_cycle == pwm->state.duty_cycle
592+
* because we might have exited early in the last call to
593+
* pwm_apply_state because of !state->enabled and so the two values in
594+
* pwm->state might not be configured in hardware.
595+
*/
596+
err = chip->ops->config(pwm->chip, pwm,
597+
state->duty_cycle,
598+
state->period);
599+
if (err)
600+
goto rollback;
601+
602+
pwm->state.period = state->period;
603+
pwm->state.duty_cycle = state->duty_cycle;
604+
605+
if (!pwm->state.enabled) {
606+
err = chip->ops->enable(chip, pwm);
607+
if (err)
608+
goto rollback;
609+
}
610+
611+
return 0;
612+
613+
rollback:
614+
pwm->state = initial_state;
615+
return err;
616+
}
617+
551618
/**
552619
* pwm_apply_state() - atomically apply a new state to a PWM device
553620
* @pwm: PWM device
@@ -580,70 +647,22 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
580647
state->usage_power == pwm->state.usage_power)
581648
return 0;
582649

583-
if (chip->ops->apply) {
650+
if (chip->ops->apply)
584651
err = chip->ops->apply(chip, pwm, state);
585-
if (err)
586-
return err;
587-
588-
trace_pwm_apply(pwm, state);
589-
590-
pwm->state = *state;
591-
592-
/*
593-
* only do this after pwm->state was applied as some
594-
* implementations of .get_state depend on this
595-
*/
596-
pwm_apply_state_debug(pwm, state);
597-
} else {
598-
/*
599-
* FIXME: restore the initial state in case of error.
600-
*/
601-
if (state->polarity != pwm->state.polarity) {
602-
if (!chip->ops->set_polarity)
603-
return -EINVAL;
652+
else
653+
err = pwm_apply_legacy(chip, pwm, state);
654+
if (err)
655+
return err;
604656

605-
/*
606-
* Changing the polarity of a running PWM is
607-
* only allowed when the PWM driver implements
608-
* ->apply().
609-
*/
610-
if (pwm->state.enabled) {
611-
chip->ops->disable(chip, pwm);
612-
pwm->state.enabled = false;
613-
}
657+
trace_pwm_apply(pwm, state);
614658

615-
err = chip->ops->set_polarity(chip, pwm,
616-
state->polarity);
617-
if (err)
618-
return err;
659+
pwm->state = *state;
619660

620-
pwm->state.polarity = state->polarity;
621-
}
622-
623-
if (state->period != pwm->state.period ||
624-
state->duty_cycle != pwm->state.duty_cycle) {
625-
err = chip->ops->config(pwm->chip, pwm,
626-
state->duty_cycle,
627-
state->period);
628-
if (err)
629-
return err;
630-
631-
pwm->state.duty_cycle = state->duty_cycle;
632-
pwm->state.period = state->period;
633-
}
634-
635-
if (state->enabled != pwm->state.enabled) {
636-
if (state->enabled) {
637-
err = chip->ops->enable(chip, pwm);
638-
if (err)
639-
return err;
640-
} else {
641-
chip->ops->disable(chip, pwm);
642-
}
643-
644-
pwm->state.enabled = state->enabled;
645-
}
646-
}
661+
/*
662+
* only do this after pwm->state was applied as some
663+
* implementations of .get_state depend on this
664+
*/
665+
pwm_apply_state_debug(pwm, state);
647666

648667
return 0;
649668
}

drivers/pwm/pwm-img.c

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,9 @@ static int img_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
128128

129129
duty = DIV_ROUND_UP(timebase * duty_ns, period_ns);
130130

131-
ret = pm_runtime_get_sync(chip->dev);
132-
if (ret < 0) {
133-
pm_runtime_put_autosuspend(chip->dev);
131+
ret = pm_runtime_resume_and_get(chip->dev);
132+
if (ret < 0)
134133
return ret;
135-
}
136134

137135
val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG);
138136
val &= ~(PWM_CTRL_CFG_DIV_MASK << PWM_CTRL_CFG_DIV_SHIFT(pwm->hwpwm));
@@ -184,10 +182,33 @@ static void img_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
184182
pm_runtime_put_autosuspend(chip->dev);
185183
}
186184

185+
static int img_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
186+
const struct pwm_state *state)
187+
{
188+
int err;
189+
190+
if (state->polarity != PWM_POLARITY_NORMAL)
191+
return -EINVAL;
192+
193+
if (!state->enabled) {
194+
if (pwm->state.enabled)
195+
img_pwm_disable(chip, pwm);
196+
197+
return 0;
198+
}
199+
200+
err = img_pwm_config(pwm->chip, pwm, state->duty_cycle, state->period);
201+
if (err)
202+
return err;
203+
204+
if (!pwm->state.enabled)
205+
err = img_pwm_enable(chip, pwm);
206+
207+
return err;
208+
}
209+
187210
static const struct pwm_ops img_pwm_ops = {
188-
.config = img_pwm_config,
189-
.enable = img_pwm_enable,
190-
.disable = img_pwm_disable,
211+
.apply = img_pwm_apply,
191212
.owner = THIS_MODULE,
192213
};
193214

drivers/pwm/pwm-twl.c

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ static inline struct twl_pwm_chip *to_twl(struct pwm_chip *chip)
5858
}
5959

6060
static int twl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
61-
int duty_ns, int period_ns)
61+
u64 duty_ns, u64 period_ns)
6262
{
63-
int duty_cycle = DIV_ROUND_UP(duty_ns * TWL_PWM_MAX, period_ns) + 1;
63+
int duty_cycle = DIV64_U64_ROUND_UP(duty_ns * TWL_PWM_MAX, period_ns) + 1;
6464
u8 pwm_config[2] = { 1, 0 };
6565
int base, ret;
6666

@@ -279,19 +279,65 @@ static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
279279
mutex_unlock(&twl->mutex);
280280
}
281281

282+
static int twl4030_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
283+
const struct pwm_state *state)
284+
{
285+
int err;
286+
287+
if (state->polarity != PWM_POLARITY_NORMAL)
288+
return -EINVAL;
289+
290+
if (!state->enabled) {
291+
if (pwm->state.enabled)
292+
twl4030_pwm_disable(chip, pwm);
293+
294+
return 0;
295+
}
296+
297+
err = twl_pwm_config(pwm->chip, pwm, state->duty_cycle, state->period);
298+
if (err)
299+
return err;
300+
301+
if (!pwm->state.enabled)
302+
err = twl4030_pwm_enable(chip, pwm);
303+
304+
return err;
305+
}
306+
307+
static int twl6030_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
308+
const struct pwm_state *state)
309+
{
310+
int err;
311+
312+
if (state->polarity != PWM_POLARITY_NORMAL)
313+
return -EINVAL;
314+
315+
if (!state->enabled) {
316+
if (pwm->state.enabled)
317+
twl6030_pwm_disable(chip, pwm);
318+
319+
return 0;
320+
}
321+
322+
err = twl_pwm_config(pwm->chip, pwm, state->duty_cycle, state->period);
323+
if (err)
324+
return err;
325+
326+
if (!pwm->state.enabled)
327+
err = twl6030_pwm_enable(chip, pwm);
328+
329+
return err;
330+
}
331+
282332
static const struct pwm_ops twl4030_pwm_ops = {
283-
.config = twl_pwm_config,
284-
.enable = twl4030_pwm_enable,
285-
.disable = twl4030_pwm_disable,
333+
.apply = twl4030_pwm_apply,
286334
.request = twl4030_pwm_request,
287335
.free = twl4030_pwm_free,
288336
.owner = THIS_MODULE,
289337
};
290338

291339
static const struct pwm_ops twl6030_pwm_ops = {
292-
.config = twl_pwm_config,
293-
.enable = twl6030_pwm_enable,
294-
.disable = twl6030_pwm_disable,
340+
.apply = twl6030_pwm_apply,
295341
.owner = THIS_MODULE,
296342
};
297343

drivers/pwm/pwm-vt8500.c

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ static inline void vt8500_pwm_busy_wait(struct vt8500_chip *vt8500, int nr, u8 b
7070
}
7171

7272
static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
73-
int duty_ns, int period_ns)
73+
u64 duty_ns, u64 period_ns)
7474
{
7575
struct vt8500_chip *vt8500 = to_vt8500_chip(chip);
7676
unsigned long long c;
@@ -102,8 +102,8 @@ static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
102102
}
103103

104104
c = (unsigned long long)pv * duty_ns;
105-
do_div(c, period_ns);
106-
dc = c;
105+
106+
dc = div64_u64(c, period_ns);
107107

108108
writel(prescale, vt8500->base + REG_SCALAR(pwm->hwpwm));
109109
vt8500_pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_SCALAR_UPDATE);
@@ -176,11 +176,54 @@ static int vt8500_pwm_set_polarity(struct pwm_chip *chip,
176176
return 0;
177177
}
178178

179+
static int vt8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
180+
const struct pwm_state *state)
181+
{
182+
int err;
183+
bool enabled = pwm->state.enabled;
184+
185+
if (state->polarity != pwm->state.polarity) {
186+
/*
187+
* Changing the polarity of a running PWM is only allowed when
188+
* the PWM driver implements ->apply().
189+
*/
190+
if (enabled) {
191+
vt8500_pwm_disable(chip, pwm);
192+
193+
enabled = false;
194+
}
195+
196+
err = vt8500_pwm_set_polarity(chip, pwm, state->polarity);
197+
if (err)
198+
return err;
199+
}
200+
201+
if (!state->enabled) {
202+
if (enabled)
203+
vt8500_pwm_disable(chip, pwm);
204+
205+
return 0;
206+
}
207+
208+
/*
209+
* We cannot skip calling ->config even if state->period ==
210+
* pwm->state.period && state->duty_cycle == pwm->state.duty_cycle
211+
* because we might have exited early in the last call to
212+
* pwm_apply_state because of !state->enabled and so the two values in
213+
* pwm->state might not be configured in hardware.
214+
*/
215+
err = vt8500_pwm_config(pwm->chip, pwm, state->duty_cycle, state->period);
216+
if (err)
217+
return err;
218+
219+
if (!enabled)
220+
err = vt8500_pwm_enable(chip, pwm);
221+
222+
return err;
223+
}
224+
179225
static const struct pwm_ops vt8500_pwm_ops = {
180-
.enable = vt8500_pwm_enable,
181-
.disable = vt8500_pwm_disable,
182-
.config = vt8500_pwm_config,
183-
.set_polarity = vt8500_pwm_set_polarity,
226+
.apply = vt8500_pwm_apply,
184227
.owner = THIS_MODULE,
185228
};
186229

0 commit comments

Comments
 (0)