Skip to content

Commit ce1f9ce

Browse files
pcercueithierryreding
authored andcommitted
pwm: jz4740: Use clocks from TCU driver
The ingenic-timer "TCU" driver provides us with clocks, that can be (un)gated, reparented or reclocked from devicetree, instead of having these settings hardcoded in this driver. The new code now uses a clk pointer per PWM (instead of a clk per pwm-chip before). So the pointer is stored in per-pwm data now. The calls to arch-specific timer code is replaced with standard clock API calls to start and stop each channel's clock. While this driver is devicetree-compatible, it is never (as of now) probed from devicetree, so this change does not introduce a ABI problem with current devicetree files. Signed-off-by: Paul Cercueil <[email protected]> Tested-by: Mathieu Malaterre <[email protected]> Tested-by: Artur Rojek <[email protected]> Signed-off-by: Thierry Reding <[email protected]>
1 parent d3817a6 commit ce1f9ce

File tree

2 files changed

+41
-14
lines changed

2 files changed

+41
-14
lines changed

drivers/pwm/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ config PWM_IMX_TPM
235235
config PWM_JZ4740
236236
tristate "Ingenic JZ47xx PWM support"
237237
depends on MACH_INGENIC
238+
depends on COMMON_CLK
238239
help
239240
Generic PWM framework driver for Ingenic JZ47xx based
240241
machines.

drivers/pwm/pwm-jz4740.c

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424

2525
struct jz4740_pwm_chip {
2626
struct pwm_chip chip;
27-
struct clk *clk;
2827
};
2928

3029
static inline struct jz4740_pwm_chip *to_jz4740(struct pwm_chip *chip)
@@ -34,23 +33,45 @@ static inline struct jz4740_pwm_chip *to_jz4740(struct pwm_chip *chip)
3433

3534
static int jz4740_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
3635
{
36+
struct jz4740_pwm_chip *jz = to_jz4740(chip);
37+
struct clk *clk;
38+
char name[16];
39+
int err;
40+
3741
/*
3842
* Timers 0 and 1 are used for system tasks, so they are unavailable
3943
* for use as PWMs.
4044
*/
4145
if (pwm->hwpwm < 2)
4246
return -EBUSY;
4347

44-
jz4740_timer_start(pwm->hwpwm);
48+
snprintf(name, sizeof(name), "timer%u", pwm->hwpwm);
49+
50+
clk = clk_get(chip->dev, name);
51+
if (IS_ERR(clk)) {
52+
if (PTR_ERR(clk) != -EPROBE_DEFER)
53+
dev_err(chip->dev, "Failed to get clock: %pe", clk);
54+
55+
return PTR_ERR(clk);
56+
}
57+
58+
err = clk_prepare_enable(clk);
59+
if (err < 0) {
60+
clk_put(clk);
61+
return err;
62+
}
63+
64+
pwm_set_chip_data(pwm, clk);
4565

4666
return 0;
4767
}
4868

4969
static void jz4740_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
5070
{
51-
jz4740_timer_set_ctrl(pwm->hwpwm, 0);
71+
struct clk *clk = pwm_get_chip_data(pwm);
5272

53-
jz4740_timer_stop(pwm->hwpwm);
73+
clk_disable_unprepare(clk);
74+
clk_put(clk);
5475
}
5576

5677
static int jz4740_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
@@ -91,17 +112,22 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
91112
const struct pwm_state *state)
92113
{
93114
struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip);
115+
struct clk *clk = pwm_get_chip_data(pwm),
116+
*parent_clk = clk_get_parent(clk);
117+
unsigned long rate, period, duty;
94118
unsigned long long tmp;
95-
unsigned long period, duty;
96119
unsigned int prescaler = 0;
97120
uint16_t ctrl;
121+
int err;
98122

99-
tmp = (unsigned long long)clk_get_rate(jz4740->clk) * state->period;
123+
rate = clk_get_rate(parent_clk);
124+
tmp = (unsigned long long)rate * state->period;
100125
do_div(tmp, 1000000000);
101126
period = tmp;
102127

103128
while (period > 0xffff && prescaler < 6) {
104129
period >>= 2;
130+
rate >>= 2;
105131
++prescaler;
106132
}
107133

@@ -117,14 +143,18 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
117143

118144
jz4740_pwm_disable(chip, pwm);
119145

146+
err = clk_set_rate(clk, rate);
147+
if (err) {
148+
dev_err(chip->dev, "Unable to set rate: %d", err);
149+
return err;
150+
}
151+
120152
jz4740_timer_set_count(pwm->hwpwm, 0);
121153
jz4740_timer_set_duty(pwm->hwpwm, duty);
122154
jz4740_timer_set_period(pwm->hwpwm, period);
123155

124-
ctrl = JZ_TIMER_CTRL_PRESCALER(prescaler) | JZ_TIMER_CTRL_SRC_EXT |
125-
JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN;
126-
127-
jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
156+
ctrl = jz4740_timer_get_ctrl(pwm->hwpwm);
157+
ctrl |= JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN;
128158

129159
switch (state->polarity) {
130160
case PWM_POLARITY_NORMAL:
@@ -158,10 +188,6 @@ static int jz4740_pwm_probe(struct platform_device *pdev)
158188
if (!jz4740)
159189
return -ENOMEM;
160190

161-
jz4740->clk = devm_clk_get(&pdev->dev, "ext");
162-
if (IS_ERR(jz4740->clk))
163-
return PTR_ERR(jz4740->clk);
164-
165191
jz4740->chip.dev = &pdev->dev;
166192
jz4740->chip.ops = &jz4740_pwm_ops;
167193
jz4740->chip.npwm = NUM_PWM;

0 commit comments

Comments
 (0)