Skip to content

Commit 1c1283d

Browse files
Uwe Kleine-Königthierryreding
authored andcommitted
pwm: bcm-kona: Implement .apply() callback
To eventually get rid of all legacy drivers convert this driver to the modern world implementing .apply(). The conversion wasn't quite straight forward because .config() and .enable() were special to effectively swap their usual order. This resulted in calculating the required values twice in some cases when pwm_apply_state() was called. This is optimized en passant, and the order of the callbacks is preserved without special jumping through hoops. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
1 parent 5f027d9 commit 1c1283d

1 file changed

Lines changed: 58 additions & 32 deletions

File tree

drivers/pwm/pwm-bcm-kona.c

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,10 @@ static void kona_pwmc_apply_settings(struct kona_pwmc *kp, unsigned int chan)
109109
}
110110

111111
static int kona_pwmc_config(struct pwm_chip *chip, struct pwm_device *pwm,
112-
int duty_ns, int period_ns)
112+
u64 duty_ns, u64 period_ns)
113113
{
114114
struct kona_pwmc *kp = to_kona_pwmc(chip);
115-
u64 val, div, rate;
115+
u64 div, rate;
116116
unsigned long prescale = PRESCALE_MIN, pc, dc;
117117
unsigned int value, chan = pwm->hwpwm;
118118

@@ -132,10 +132,8 @@ static int kona_pwmc_config(struct pwm_chip *chip, struct pwm_device *pwm,
132132
while (1) {
133133
div = 1000000000;
134134
div *= 1 + prescale;
135-
val = rate * period_ns;
136-
pc = div64_u64(val, div);
137-
val = rate * duty_ns;
138-
dc = div64_u64(val, div);
135+
pc = mul_u64_u64_div_u64(rate, period_ns, div);
136+
dc = mul_u64_u64_div_u64(rate, duty_ns, div);
139137

140138
/* If duty_ns or period_ns are not achievable then return */
141139
if (pc < PERIOD_COUNT_MIN)
@@ -150,25 +148,18 @@ static int kona_pwmc_config(struct pwm_chip *chip, struct pwm_device *pwm,
150148
return -EINVAL;
151149
}
152150

153-
/*
154-
* Don't apply settings if disabled. The period and duty cycle are
155-
* always calculated above to ensure the new values are
156-
* validated immediately instead of on enable.
157-
*/
158-
if (pwm_is_enabled(pwm)) {
159-
kona_pwmc_prepare_for_settings(kp, chan);
151+
kona_pwmc_prepare_for_settings(kp, chan);
160152

161-
value = readl(kp->base + PRESCALE_OFFSET);
162-
value &= ~PRESCALE_MASK(chan);
163-
value |= prescale << PRESCALE_SHIFT(chan);
164-
writel(value, kp->base + PRESCALE_OFFSET);
153+
value = readl(kp->base + PRESCALE_OFFSET);
154+
value &= ~PRESCALE_MASK(chan);
155+
value |= prescale << PRESCALE_SHIFT(chan);
156+
writel(value, kp->base + PRESCALE_OFFSET);
165157

166-
writel(pc, kp->base + PERIOD_COUNT_OFFSET(chan));
158+
writel(pc, kp->base + PERIOD_COUNT_OFFSET(chan));
167159

168-
writel(dc, kp->base + DUTY_CYCLE_HIGH_OFFSET(chan));
160+
writel(dc, kp->base + DUTY_CYCLE_HIGH_OFFSET(chan));
169161

170-
kona_pwmc_apply_settings(kp, chan);
171-
}
162+
kona_pwmc_apply_settings(kp, chan);
172163

173164
return 0;
174165
}
@@ -216,13 +207,6 @@ static int kona_pwmc_enable(struct pwm_chip *chip, struct pwm_device *pwm)
216207
return ret;
217208
}
218209

219-
ret = kona_pwmc_config(chip, pwm, pwm_get_duty_cycle(pwm),
220-
pwm_get_period(pwm));
221-
if (ret < 0) {
222-
clk_disable_unprepare(kp->clk);
223-
return ret;
224-
}
225-
226210
return 0;
227211
}
228212

@@ -248,11 +232,53 @@ static void kona_pwmc_disable(struct pwm_chip *chip, struct pwm_device *pwm)
248232
clk_disable_unprepare(kp->clk);
249233
}
250234

235+
static int kona_pwmc_apply(struct pwm_chip *chip, struct pwm_device *pwm,
236+
const struct pwm_state *state)
237+
{
238+
int err;
239+
struct kona_pwmc *kp = to_kona_pwmc(chip);
240+
bool enabled = pwm->state.enabled;
241+
242+
if (state->polarity != pwm->state.polarity) {
243+
if (enabled) {
244+
kona_pwmc_disable(chip, pwm);
245+
enabled = false;
246+
}
247+
248+
err = kona_pwmc_set_polarity(chip, pwm, state->polarity);
249+
if (err)
250+
return err;
251+
252+
pwm->state.polarity = state->polarity;
253+
}
254+
255+
if (!state->enabled) {
256+
if (enabled)
257+
kona_pwmc_disable(chip, pwm);
258+
return 0;
259+
} else if (!enabled) {
260+
/*
261+
* This is a bit special here, usually the PWM should only be
262+
* enabled when duty and period are setup. But before this
263+
* driver was converted to .apply it was done the other way
264+
* around and so this behaviour was kept even though this might
265+
* result in a glitch. This might be improvable by someone with
266+
* hardware and/or documentation.
267+
*/
268+
err = kona_pwmc_enable(chip, pwm);
269+
if (err)
270+
return err;
271+
}
272+
273+
err = kona_pwmc_config(pwm->chip, pwm, state->duty_cycle, state->period);
274+
if (err && !pwm->state.enabled)
275+
clk_disable_unprepare(kp->clk);
276+
277+
return err;
278+
}
279+
251280
static const struct pwm_ops kona_pwm_ops = {
252-
.config = kona_pwmc_config,
253-
.set_polarity = kona_pwmc_set_polarity,
254-
.enable = kona_pwmc_enable,
255-
.disable = kona_pwmc_disable,
281+
.apply = kona_pwmc_apply,
256282
.owner = THIS_MODULE,
257283
};
258284

0 commit comments

Comments
 (0)