.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * PWM driver for Rockchip SoCs |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> |
---|
5 | 6 | * Copyright (C) 2014 ROCKCHIP, Inc. |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or |
---|
8 | | - * modify it under the terms of the GNU General Public License |
---|
9 | | - * version 2 as published by the Free Software Foundation. |
---|
10 | 7 | */ |
---|
11 | 8 | |
---|
12 | 9 | #include <linux/clk.h> |
---|
| 10 | +#include <linux/interrupt.h> |
---|
13 | 11 | #include <linux/io.h> |
---|
| 12 | +#include <linux/iopoll.h> |
---|
| 13 | +#include <linux/irq.h> |
---|
14 | 14 | #include <linux/module.h> |
---|
15 | 15 | #include <linux/of.h> |
---|
16 | 16 | #include <linux/of_device.h> |
---|
.. | .. |
---|
18 | 18 | #include <linux/platform_device.h> |
---|
19 | 19 | #include <linux/pwm.h> |
---|
20 | 20 | #include <linux/time.h> |
---|
| 21 | +#include "pwm-rockchip.h" |
---|
| 22 | + |
---|
| 23 | +#define PWM_MAX_CHANNEL_NUM 4 |
---|
21 | 24 | |
---|
22 | 25 | #define PWM_CTRL_TIMER_EN (1 << 0) |
---|
23 | 26 | #define PWM_CTRL_OUTPUT_EN (1 << 3) |
---|
24 | 27 | |
---|
25 | 28 | #define PWM_ENABLE (1 << 0) |
---|
26 | | -#define PWM_CONTINUOUS (1 << 1) |
---|
| 29 | +#define PWM_MODE_SHIFT 1 |
---|
| 30 | +#define PWM_MODE_MASK (0x3 << PWM_MODE_SHIFT) |
---|
| 31 | +#define PWM_ONESHOT (0 << PWM_MODE_SHIFT) |
---|
| 32 | +#define PWM_CONTINUOUS (1 << PWM_MODE_SHIFT) |
---|
| 33 | +#define PWM_CAPTURE (2 << PWM_MODE_SHIFT) |
---|
27 | 34 | #define PWM_DUTY_POSITIVE (1 << 3) |
---|
28 | 35 | #define PWM_DUTY_NEGATIVE (0 << 3) |
---|
29 | 36 | #define PWM_INACTIVE_NEGATIVE (0 << 4) |
---|
.. | .. |
---|
33 | 40 | #define PWM_OUTPUT_CENTER (1 << 5) |
---|
34 | 41 | #define PWM_LOCK_EN (1 << 6) |
---|
35 | 42 | #define PWM_LP_DISABLE (0 << 8) |
---|
| 43 | +#define PWM_CLK_SEL_SHIFT 9 |
---|
| 44 | +#define PWM_CLK_SEL_MASK (1 << PWM_CLK_SEL_SHIFT) |
---|
| 45 | +#define PWM_SEL_NO_SCALED_CLOCK (0 << PWM_CLK_SEL_SHIFT) |
---|
| 46 | +#define PWM_SEL_SCALED_CLOCK (1 << PWM_CLK_SEL_SHIFT) |
---|
| 47 | +#define PWM_PRESCELE_SHIFT 12 |
---|
| 48 | +#define PWM_PRESCALE_MASK (0x3 << PWM_PRESCELE_SHIFT) |
---|
| 49 | +#define PWM_SCALE_SHIFT 16 |
---|
| 50 | +#define PWM_SCALE_MASK (0xff << PWM_SCALE_SHIFT) |
---|
36 | 51 | |
---|
37 | 52 | #define PWM_ONESHOT_COUNT_SHIFT 24 |
---|
| 53 | +#define PWM_ONESHOT_COUNT_MASK (0xff << PWM_ONESHOT_COUNT_SHIFT) |
---|
38 | 54 | #define PWM_ONESHOT_COUNT_MAX 256 |
---|
| 55 | + |
---|
| 56 | +#define PWM_REG_INTSTS(n) ((3 - (n)) * 0x10 + 0x10) |
---|
| 57 | +#define PWM_REG_INT_EN(n) ((3 - (n)) * 0x10 + 0x14) |
---|
| 58 | + |
---|
| 59 | +#define PWM_CH_INT(n) BIT(n) |
---|
39 | 60 | |
---|
40 | 61 | struct rockchip_pwm_chip { |
---|
41 | 62 | struct pwm_chip chip; |
---|
.. | .. |
---|
48 | 69 | unsigned long clk_rate; |
---|
49 | 70 | bool vop_pwm_en; /* indicate voppwm mirror register state */ |
---|
50 | 71 | bool center_aligned; |
---|
51 | | - bool oneshot; |
---|
| 72 | + bool oneshot_en; |
---|
| 73 | + int channel_id; |
---|
| 74 | + int irq; |
---|
52 | 75 | }; |
---|
53 | 76 | |
---|
54 | 77 | struct rockchip_pwm_regs { |
---|
.. | .. |
---|
81 | 104 | u32 enable_conf = pc->data->enable_conf; |
---|
82 | 105 | u64 tmp; |
---|
83 | 106 | u32 val; |
---|
| 107 | + u32 dclk_div; |
---|
84 | 108 | int ret; |
---|
85 | 109 | |
---|
86 | | - ret = clk_enable(pc->pclk); |
---|
87 | | - if (ret) |
---|
88 | | - return; |
---|
| 110 | + if (!pc->oneshot_en) { |
---|
| 111 | + ret = clk_enable(pc->pclk); |
---|
| 112 | + if (ret) |
---|
| 113 | + return; |
---|
| 114 | + } |
---|
| 115 | + |
---|
| 116 | + dclk_div = pc->oneshot_en ? 2 : 1; |
---|
89 | 117 | |
---|
90 | 118 | tmp = readl_relaxed(pc->base + pc->data->regs.period); |
---|
91 | | - tmp *= pc->data->prescaler * NSEC_PER_SEC; |
---|
| 119 | + tmp *= dclk_div * pc->data->prescaler * NSEC_PER_SEC; |
---|
92 | 120 | state->period = DIV_ROUND_CLOSEST_ULL(tmp, pc->clk_rate); |
---|
93 | 121 | |
---|
94 | 122 | tmp = readl_relaxed(pc->base + pc->data->regs.duty); |
---|
95 | | - tmp *= pc->data->prescaler * NSEC_PER_SEC; |
---|
| 123 | + tmp *= dclk_div * pc->data->prescaler * NSEC_PER_SEC; |
---|
96 | 124 | state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, pc->clk_rate); |
---|
97 | 125 | |
---|
98 | 126 | val = readl_relaxed(pc->base + pc->data->regs.ctrl); |
---|
99 | | - if (pc->data->supports_polarity) |
---|
100 | | - state->enabled = ((val & enable_conf) != enable_conf) ? |
---|
101 | | - false : true; |
---|
| 127 | + if (pc->oneshot_en) |
---|
| 128 | + enable_conf &= ~PWM_CONTINUOUS; |
---|
| 129 | + state->enabled = (val & enable_conf) == enable_conf; |
---|
| 130 | + |
---|
| 131 | + if (pc->data->supports_polarity && !(val & PWM_DUTY_POSITIVE)) |
---|
| 132 | + state->polarity = PWM_POLARITY_INVERSED; |
---|
102 | 133 | else |
---|
103 | | - state->enabled = ((val & enable_conf) == enable_conf) ? |
---|
104 | | - true : false; |
---|
| 134 | + state->polarity = PWM_POLARITY_NORMAL; |
---|
105 | 135 | |
---|
106 | | - if (pc->data->supports_polarity) { |
---|
107 | | - if (!(val & PWM_DUTY_POSITIVE)) |
---|
108 | | - state->polarity = PWM_POLARITY_INVERSED; |
---|
109 | | - } |
---|
| 136 | + if (!pc->oneshot_en) |
---|
| 137 | + clk_disable(pc->pclk); |
---|
| 138 | +} |
---|
110 | 139 | |
---|
111 | | - clk_disable(pc->pclk); |
---|
| 140 | +static irqreturn_t rockchip_pwm_oneshot_irq(int irq, void *data) |
---|
| 141 | +{ |
---|
| 142 | + struct rockchip_pwm_chip *pc = data; |
---|
| 143 | + struct pwm_state state; |
---|
| 144 | + unsigned int id = pc->channel_id; |
---|
| 145 | + int val; |
---|
| 146 | + |
---|
| 147 | + if (id > 3) |
---|
| 148 | + return IRQ_NONE; |
---|
| 149 | + val = readl_relaxed(pc->base + PWM_REG_INTSTS(id)); |
---|
| 150 | + |
---|
| 151 | + if ((val & PWM_CH_INT(id)) == 0) |
---|
| 152 | + return IRQ_NONE; |
---|
| 153 | + |
---|
| 154 | + writel_relaxed(PWM_CH_INT(id), pc->base + PWM_REG_INTSTS(id)); |
---|
| 155 | + |
---|
| 156 | + /* |
---|
| 157 | + * Set pwm state to disabled when the oneshot mode finished. |
---|
| 158 | + */ |
---|
| 159 | + pwm_get_state(&pc->chip.pwms[0], &state); |
---|
| 160 | + state.enabled = false; |
---|
| 161 | + pwm_apply_state(&pc->chip.pwms[0], &state); |
---|
| 162 | + |
---|
| 163 | + rockchip_pwm_oneshot_callback(&pc->chip.pwms[0], &state); |
---|
| 164 | + |
---|
| 165 | + return IRQ_HANDLED; |
---|
112 | 166 | } |
---|
113 | 167 | |
---|
114 | 168 | static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, |
---|
115 | | - struct pwm_state *state) |
---|
| 169 | + const struct pwm_state *state) |
---|
116 | 170 | { |
---|
117 | 171 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); |
---|
118 | | - unsigned long period, duty; |
---|
| 172 | + unsigned long period, duty, delay_ns; |
---|
119 | 173 | unsigned long flags; |
---|
120 | 174 | u64 div; |
---|
121 | 175 | u32 ctrl; |
---|
| 176 | + u8 dclk_div = 1; |
---|
| 177 | + |
---|
| 178 | +#ifdef CONFIG_PWM_ROCKCHIP_ONESHOT |
---|
| 179 | + if (state->oneshot_count > 0 && state->oneshot_count <= PWM_ONESHOT_COUNT_MAX) |
---|
| 180 | + dclk_div = 2; |
---|
| 181 | +#endif |
---|
122 | 182 | |
---|
123 | 183 | /* |
---|
124 | 184 | * Since period and duty cycle registers have a width of 32 |
---|
.. | .. |
---|
126 | 186 | * default prescaler value for all practical clock rate values. |
---|
127 | 187 | */ |
---|
128 | 188 | div = (u64)pc->clk_rate * state->period; |
---|
129 | | - period = DIV_ROUND_CLOSEST_ULL(div, |
---|
130 | | - pc->data->prescaler * NSEC_PER_SEC); |
---|
| 189 | + period = DIV_ROUND_CLOSEST_ULL(div, dclk_div * pc->data->prescaler * NSEC_PER_SEC); |
---|
131 | 190 | |
---|
132 | 191 | div = (u64)pc->clk_rate * state->duty_cycle; |
---|
133 | | - duty = DIV_ROUND_CLOSEST_ULL(div, pc->data->prescaler * NSEC_PER_SEC); |
---|
| 192 | + duty = DIV_ROUND_CLOSEST_ULL(div, dclk_div * pc->data->prescaler * NSEC_PER_SEC); |
---|
| 193 | + |
---|
| 194 | + if (pc->data->supports_lock) { |
---|
| 195 | + div = (u64)10 * NSEC_PER_SEC * dclk_div * pc->data->prescaler; |
---|
| 196 | + delay_ns = DIV_ROUND_UP_ULL(div, pc->clk_rate); |
---|
| 197 | + } |
---|
134 | 198 | |
---|
135 | 199 | local_irq_save(flags); |
---|
136 | | - /* |
---|
137 | | - * Lock the period and duty of previous configuration, then |
---|
138 | | - * change the duty and period, that would not be effective. |
---|
139 | | - */ |
---|
| 200 | + |
---|
140 | 201 | ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); |
---|
141 | 202 | if (pc->data->vop_pwm) { |
---|
142 | 203 | if (pc->vop_pwm_en) |
---|
.. | .. |
---|
146 | 207 | } |
---|
147 | 208 | |
---|
148 | 209 | #ifdef CONFIG_PWM_ROCKCHIP_ONESHOT |
---|
149 | | - if (state->oneshot_count > PWM_ONESHOT_COUNT_MAX) { |
---|
150 | | - pc->oneshot = false; |
---|
151 | | - dev_err(chip->dev, "Oneshot_count value overflow.\n"); |
---|
152 | | - } else if (state->oneshot_count > 0) { |
---|
153 | | - pc->oneshot = true; |
---|
| 210 | + if (state->oneshot_count > 0 && state->oneshot_count <= PWM_ONESHOT_COUNT_MAX) { |
---|
| 211 | + u32 int_ctrl; |
---|
| 212 | + |
---|
| 213 | + /* |
---|
| 214 | + * This is a workaround, an uncertain waveform will be |
---|
| 215 | + * generated after oneshot ends. It is needed to enable |
---|
| 216 | + * the dclk scale function to resolve it. It doesn't |
---|
| 217 | + * matter what the scale factor is, just make sure the |
---|
| 218 | + * scale function is turned on, for which we set scale |
---|
| 219 | + * factor to 2. |
---|
| 220 | + */ |
---|
| 221 | + ctrl &= ~PWM_SCALE_MASK; |
---|
| 222 | + ctrl |= (dclk_div / 2) << PWM_SCALE_SHIFT; |
---|
| 223 | + ctrl &= ~PWM_CLK_SEL_MASK; |
---|
| 224 | + ctrl |= PWM_SEL_SCALED_CLOCK; |
---|
| 225 | + |
---|
| 226 | + pc->oneshot_en = true; |
---|
| 227 | + ctrl &= ~PWM_MODE_MASK; |
---|
| 228 | + ctrl |= PWM_ONESHOT; |
---|
| 229 | + |
---|
| 230 | + ctrl &= ~PWM_ONESHOT_COUNT_MASK; |
---|
154 | 231 | ctrl |= (state->oneshot_count - 1) << PWM_ONESHOT_COUNT_SHIFT; |
---|
| 232 | + |
---|
| 233 | + int_ctrl = readl_relaxed(pc->base + PWM_REG_INT_EN(pc->channel_id)); |
---|
| 234 | + int_ctrl |= PWM_CH_INT(pc->channel_id); |
---|
| 235 | + writel_relaxed(int_ctrl, pc->base + PWM_REG_INT_EN(pc->channel_id)); |
---|
155 | 236 | } else { |
---|
156 | | - pc->oneshot = false; |
---|
| 237 | + u32 int_ctrl; |
---|
| 238 | + |
---|
| 239 | + ctrl &= ~PWM_SCALE_MASK; |
---|
| 240 | + ctrl &= ~PWM_CLK_SEL_MASK; |
---|
| 241 | + ctrl |= PWM_SEL_NO_SCALED_CLOCK; |
---|
| 242 | + |
---|
| 243 | + if (state->oneshot_count) |
---|
| 244 | + dev_err(chip->dev, "Oneshot_count must be between 1 and 256.\n"); |
---|
| 245 | + |
---|
| 246 | + pc->oneshot_en = false; |
---|
| 247 | + ctrl &= ~PWM_MODE_MASK; |
---|
157 | 248 | ctrl |= PWM_CONTINUOUS; |
---|
| 249 | + |
---|
| 250 | + ctrl &= ~PWM_ONESHOT_COUNT_MASK; |
---|
| 251 | + |
---|
| 252 | + int_ctrl = readl_relaxed(pc->base + PWM_REG_INT_EN(pc->channel_id)); |
---|
| 253 | + int_ctrl &= ~PWM_CH_INT(pc->channel_id); |
---|
| 254 | + writel_relaxed(int_ctrl, pc->base + PWM_REG_INT_EN(pc->channel_id)); |
---|
158 | 255 | } |
---|
159 | 256 | #endif |
---|
160 | 257 | |
---|
| 258 | + /* |
---|
| 259 | + * Lock the period and duty of previous configuration, then |
---|
| 260 | + * change the duty and period, that would not be effective. |
---|
| 261 | + */ |
---|
161 | 262 | if (pc->data->supports_lock) { |
---|
162 | 263 | ctrl |= PWM_LOCK_EN; |
---|
163 | 264 | writel_relaxed(ctrl, pc->base + pc->data->regs.ctrl); |
---|
.. | .. |
---|
175 | 276 | } |
---|
176 | 277 | |
---|
177 | 278 | /* |
---|
178 | | - * Unlock and set polarity at the same time, |
---|
179 | | - * the configuration of duty, period and polarity |
---|
180 | | - * would be effective together at next period. |
---|
| 279 | + * Unlock and set polarity at the same time, the configuration of duty, |
---|
| 280 | + * period and polarity would be effective together at next period. It |
---|
| 281 | + * takes 10 dclk cycles to make sure lock works before unlocking. |
---|
181 | 282 | */ |
---|
182 | | - if (pc->data->supports_lock) |
---|
| 283 | + if (pc->data->supports_lock) { |
---|
183 | 284 | ctrl &= ~PWM_LOCK_EN; |
---|
| 285 | + ndelay(delay_ns); |
---|
| 286 | + } |
---|
184 | 287 | |
---|
185 | 288 | writel(ctrl, pc->base + pc->data->regs.ctrl); |
---|
186 | 289 | local_irq_restore(flags); |
---|
.. | .. |
---|
211 | 314 | |
---|
212 | 315 | if (enable) { |
---|
213 | 316 | val |= enable_conf; |
---|
214 | | - if (pc->oneshot) |
---|
| 317 | + if (pc->oneshot_en) |
---|
215 | 318 | val &= ~PWM_CONTINUOUS; |
---|
216 | 319 | } else { |
---|
217 | 320 | val &= ~enable_conf; |
---|
.. | .. |
---|
228 | 331 | } |
---|
229 | 332 | |
---|
230 | 333 | static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
---|
231 | | - struct pwm_state *state) |
---|
| 334 | + const struct pwm_state *state) |
---|
232 | 335 | { |
---|
233 | 336 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); |
---|
234 | 337 | struct pwm_state curstate; |
---|
235 | 338 | bool enabled; |
---|
236 | 339 | int ret = 0; |
---|
237 | 340 | |
---|
238 | | - ret = clk_enable(pc->pclk); |
---|
239 | | - if (ret) |
---|
240 | | - return ret; |
---|
| 341 | + if (!pc->oneshot_en) { |
---|
| 342 | + ret = clk_enable(pc->pclk); |
---|
| 343 | + if (ret) |
---|
| 344 | + return ret; |
---|
| 345 | + } |
---|
241 | 346 | |
---|
242 | 347 | pwm_get_state(pwm, &curstate); |
---|
243 | 348 | enabled = curstate.enabled; |
---|
.. | .. |
---|
257 | 362 | goto out; |
---|
258 | 363 | } |
---|
259 | 364 | |
---|
260 | | - /* |
---|
261 | | - * Update the state with the real hardware, which can differ a bit |
---|
262 | | - * because of period/duty_cycle approximation. |
---|
263 | | - */ |
---|
264 | | - rockchip_pwm_get_state(chip, pwm, state); |
---|
265 | | - |
---|
266 | | - if (state->enabled || pc->oneshot) |
---|
| 365 | + if (state->enabled) |
---|
267 | 366 | ret = pinctrl_select_state(pc->pinctrl, pc->active_state); |
---|
268 | 367 | out: |
---|
269 | | - clk_disable(pc->pclk); |
---|
| 368 | + if (!pc->oneshot_en) |
---|
| 369 | + clk_disable(pc->pclk); |
---|
270 | 370 | |
---|
271 | 371 | return ret; |
---|
272 | 372 | } |
---|
.. | .. |
---|
349 | 449 | }; |
---|
350 | 450 | MODULE_DEVICE_TABLE(of, rockchip_pwm_dt_ids); |
---|
351 | 451 | |
---|
| 452 | +static int rockchip_pwm_get_channel_id(const char *name) |
---|
| 453 | +{ |
---|
| 454 | + int len = strlen(name); |
---|
| 455 | + |
---|
| 456 | + return name[len - 2] - '0'; |
---|
| 457 | +} |
---|
| 458 | + |
---|
352 | 459 | static int rockchip_pwm_probe(struct platform_device *pdev) |
---|
353 | 460 | { |
---|
354 | 461 | const struct of_device_id *id; |
---|
355 | 462 | struct rockchip_pwm_chip *pc; |
---|
356 | 463 | struct resource *r; |
---|
| 464 | + u32 enable_conf, ctrl; |
---|
| 465 | + bool enabled; |
---|
357 | 466 | int ret, count; |
---|
358 | 467 | |
---|
359 | 468 | id = of_match_device(rockchip_pwm_dt_ids, &pdev->dev); |
---|
.. | .. |
---|
373 | 482 | pc->clk = devm_clk_get(&pdev->dev, "pwm"); |
---|
374 | 483 | if (IS_ERR(pc->clk)) { |
---|
375 | 484 | pc->clk = devm_clk_get(&pdev->dev, NULL); |
---|
376 | | - if (IS_ERR(pc->clk)) { |
---|
377 | | - ret = PTR_ERR(pc->clk); |
---|
378 | | - if (ret != -EPROBE_DEFER) |
---|
379 | | - dev_err(&pdev->dev, "Can't get bus clk: %d\n", |
---|
380 | | - ret); |
---|
381 | | - return ret; |
---|
382 | | - } |
---|
| 485 | + if (IS_ERR(pc->clk)) |
---|
| 486 | + return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk), |
---|
| 487 | + "Can't get bus clk\n"); |
---|
383 | 488 | } |
---|
384 | 489 | |
---|
385 | 490 | count = of_count_phandle_with_args(pdev->dev.of_node, |
---|
.. | .. |
---|
402 | 507 | return ret; |
---|
403 | 508 | } |
---|
404 | 509 | |
---|
405 | | - ret = clk_prepare(pc->pclk); |
---|
| 510 | + ret = clk_prepare_enable(pc->pclk); |
---|
406 | 511 | if (ret) { |
---|
407 | | - dev_err(&pdev->dev, "Can't prepare APB clk: %d\n", ret); |
---|
| 512 | + dev_err(&pdev->dev, "Can't prepare enable APB clk: %d\n", ret); |
---|
408 | 513 | goto err_clk; |
---|
| 514 | + } |
---|
| 515 | + |
---|
| 516 | + pc->channel_id = rockchip_pwm_get_channel_id(pdev->dev.of_node->full_name); |
---|
| 517 | + if (pc->channel_id < 0 || pc->channel_id >= PWM_MAX_CHANNEL_NUM) { |
---|
| 518 | + dev_err(&pdev->dev, "Channel id is out of range: %d\n", pc->channel_id); |
---|
| 519 | + ret = -EINVAL; |
---|
| 520 | + goto err_pclk; |
---|
| 521 | + } |
---|
| 522 | + |
---|
| 523 | + if (IS_ENABLED(CONFIG_PWM_ROCKCHIP_ONESHOT)) { |
---|
| 524 | + pc->irq = platform_get_irq(pdev, 0); |
---|
| 525 | + if (pc->irq < 0) { |
---|
| 526 | + dev_err(&pdev->dev, "Get oneshot mode irq failed\n"); |
---|
| 527 | + ret = pc->irq; |
---|
| 528 | + goto err_pclk; |
---|
| 529 | + } |
---|
| 530 | + |
---|
| 531 | + ret = devm_request_irq(&pdev->dev, pc->irq, rockchip_pwm_oneshot_irq, |
---|
| 532 | + IRQF_NO_SUSPEND | IRQF_SHARED, |
---|
| 533 | + "rk_pwm_oneshot_irq", pc); |
---|
| 534 | + if (ret) { |
---|
| 535 | + dev_err(&pdev->dev, "Claim oneshot IRQ failed\n"); |
---|
| 536 | + goto err_pclk; |
---|
| 537 | + } |
---|
409 | 538 | } |
---|
410 | 539 | |
---|
411 | 540 | pc->pinctrl = devm_pinctrl_get(&pdev->dev); |
---|
412 | 541 | if (IS_ERR(pc->pinctrl)) { |
---|
413 | 542 | dev_err(&pdev->dev, "Get pinctrl failed!\n"); |
---|
414 | | - return PTR_ERR(pc->pinctrl); |
---|
| 543 | + ret = PTR_ERR(pc->pinctrl); |
---|
| 544 | + goto err_pclk; |
---|
415 | 545 | } |
---|
416 | 546 | |
---|
417 | 547 | pc->active_state = pinctrl_lookup_state(pc->pinctrl, "active"); |
---|
418 | 548 | if (IS_ERR(pc->active_state)) { |
---|
419 | 549 | dev_err(&pdev->dev, "No active pinctrl state\n"); |
---|
420 | | - return PTR_ERR(pc->active_state); |
---|
| 550 | + ret = PTR_ERR(pc->active_state); |
---|
| 551 | + goto err_pclk; |
---|
421 | 552 | } |
---|
422 | 553 | |
---|
423 | 554 | platform_set_drvdata(pdev, pc); |
---|
.. | .. |
---|
425 | 556 | pc->data = id->data; |
---|
426 | 557 | pc->chip.dev = &pdev->dev; |
---|
427 | 558 | pc->chip.ops = &rockchip_pwm_ops; |
---|
428 | | - pc->chip.base = -1; |
---|
| 559 | + pc->chip.base = of_alias_get_id(pdev->dev.of_node, "pwm"); |
---|
429 | 560 | pc->chip.npwm = 1; |
---|
430 | 561 | pc->clk_rate = clk_get_rate(pc->clk); |
---|
431 | 562 | |
---|
.. | .. |
---|
433 | 564 | pc->chip.of_xlate = of_pwm_xlate_with_flags; |
---|
434 | 565 | pc->chip.of_pwm_n_cells = 3; |
---|
435 | 566 | } |
---|
| 567 | + |
---|
| 568 | + enable_conf = pc->data->enable_conf; |
---|
| 569 | + ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); |
---|
| 570 | + enabled = (ctrl & enable_conf) == enable_conf; |
---|
436 | 571 | |
---|
437 | 572 | pc->center_aligned = |
---|
438 | 573 | device_property_read_bool(&pdev->dev, "center-aligned"); |
---|
.. | .. |
---|
444 | 579 | } |
---|
445 | 580 | |
---|
446 | 581 | /* Keep the PWM clk enabled if the PWM appears to be up and running. */ |
---|
447 | | - if (!pwm_is_enabled(pc->chip.pwms)) |
---|
| 582 | + if (!enabled) |
---|
448 | 583 | clk_disable(pc->clk); |
---|
| 584 | + |
---|
| 585 | + clk_disable(pc->pclk); |
---|
449 | 586 | |
---|
450 | 587 | return 0; |
---|
451 | 588 | |
---|
452 | 589 | err_pclk: |
---|
453 | | - clk_unprepare(pc->pclk); |
---|
| 590 | + clk_disable_unprepare(pc->pclk); |
---|
454 | 591 | err_clk: |
---|
455 | 592 | clk_disable_unprepare(pc->clk); |
---|
456 | 593 | |
---|
.. | .. |
---|
460 | 597 | static int rockchip_pwm_remove(struct platform_device *pdev) |
---|
461 | 598 | { |
---|
462 | 599 | struct rockchip_pwm_chip *pc = platform_get_drvdata(pdev); |
---|
| 600 | + struct pwm_state state; |
---|
| 601 | + u32 val; |
---|
463 | 602 | |
---|
| 603 | + /* |
---|
| 604 | + * For oneshot mode, it is needed to wait for bit PWM_ENABLE |
---|
| 605 | + * to 0, which is automatic if all periods have been sent. |
---|
| 606 | + */ |
---|
| 607 | + pwm_get_state(&pc->chip.pwms[0], &state); |
---|
| 608 | + if (state.enabled) { |
---|
| 609 | + if (pc->oneshot_en) { |
---|
| 610 | + if (readl_poll_timeout(pc->base + pc->data->regs.ctrl, |
---|
| 611 | + val, !(val & PWM_ENABLE), 1000, 10 * 1000)) |
---|
| 612 | + dev_err(&pdev->dev, "Wait for oneshot to complete failed\n"); |
---|
| 613 | + } else { |
---|
| 614 | + state.enabled = false; |
---|
| 615 | + pwm_apply_state(&pc->chip.pwms[0], &state); |
---|
| 616 | + } |
---|
| 617 | + } |
---|
| 618 | + |
---|
| 619 | + if (pc->oneshot_en) |
---|
| 620 | + clk_disable(pc->pclk); |
---|
464 | 621 | clk_unprepare(pc->pclk); |
---|
465 | 622 | clk_unprepare(pc->clk); |
---|
466 | 623 | |
---|