Commit | Line | Data |
---|---|---|
254d3a72 BD |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
3 | * Renesas RZ/G2L MTU3a PWM Timer driver | |
4 | * | |
5 | * Copyright (C) 2023 Renesas Electronics Corporation | |
6 | * | |
7 | * Hardware manual for this IP can be found here | |
8 | * https://www.renesas.com/eu/en/document/mah/rzg2l-group-rzg2lc-group-users-manual-hardware-0?language=en | |
9 | * | |
10 | * Limitations: | |
11 | * - When PWM is disabled, the output is driven to Hi-Z. | |
12 | * - While the hardware supports both polarities, the driver (for now) | |
13 | * only handles normal polarity. | |
14 | * - HW uses one counter and two match components to configure duty_cycle | |
15 | * and period. | |
16 | * - Multi-Function Timer Pulse Unit (a.k.a MTU) has 7 HW channels for PWM | |
17 | * operations. (The channels are MTU{0..4, 6, 7}.) | |
18 | * - MTU{1, 2} channels have a single IO, whereas all other HW channels have | |
19 | * 2 IOs. | |
20 | * - Each IO is modelled as an independent PWM channel. | |
21 | * - rz_mtu3_channel_io_map table is used to map the PWM channel to the | |
22 | * corresponding HW channel as there are difference in number of IOs | |
23 | * between HW channels. | |
24 | */ | |
25 | ||
26 | #include <linux/bitfield.h> | |
27 | #include <linux/clk.h> | |
28 | #include <linux/limits.h> | |
29 | #include <linux/mfd/rz-mtu3.h> | |
30 | #include <linux/module.h> | |
31 | #include <linux/platform_device.h> | |
32 | #include <linux/pm_runtime.h> | |
33 | #include <linux/pwm.h> | |
34 | #include <linux/time.h> | |
35 | ||
36 | #define RZ_MTU3_MAX_PWM_CHANNELS 12 | |
37 | #define RZ_MTU3_MAX_HW_CHANNELS 7 | |
38 | ||
39 | /** | |
40 | * struct rz_mtu3_channel_io_map - MTU3 pwm channel map | |
41 | * | |
42 | * @base_pwm_number: First PWM of a channel | |
bdebe27e | 43 | * @num_channel_ios: number of IOs on the HW channel. |
254d3a72 BD |
44 | */ |
45 | struct rz_mtu3_channel_io_map { | |
46 | u8 base_pwm_number; | |
47 | u8 num_channel_ios; | |
48 | }; | |
49 | ||
50 | /** | |
51 | * struct rz_mtu3_pwm_channel - MTU3 pwm channel data | |
52 | * | |
53 | * @mtu: MTU3 channel data | |
54 | * @map: MTU3 pwm channel map | |
55 | */ | |
56 | struct rz_mtu3_pwm_channel { | |
57 | struct rz_mtu3_channel *mtu; | |
58 | const struct rz_mtu3_channel_io_map *map; | |
59 | }; | |
60 | ||
61 | /** | |
62 | * struct rz_mtu3_pwm_chip - MTU3 pwm private data | |
63 | * | |
254d3a72 BD |
64 | * @clk: MTU3 module clock |
65 | * @lock: Lock to prevent concurrent access for usage count | |
66 | * @rate: MTU3 clock rate | |
67 | * @user_count: MTU3 usage count | |
68 | * @enable_count: MTU3 enable count | |
69 | * @prescale: MTU3 prescale | |
70 | * @channel_data: MTU3 pwm channel data | |
71 | */ | |
72 | ||
73 | struct rz_mtu3_pwm_chip { | |
254d3a72 BD |
74 | struct clk *clk; |
75 | struct mutex lock; | |
76 | unsigned long rate; | |
77 | u32 user_count[RZ_MTU3_MAX_HW_CHANNELS]; | |
78 | u32 enable_count[RZ_MTU3_MAX_HW_CHANNELS]; | |
79 | u8 prescale[RZ_MTU3_MAX_HW_CHANNELS]; | |
80 | struct rz_mtu3_pwm_channel channel_data[RZ_MTU3_MAX_HW_CHANNELS]; | |
81 | }; | |
82 | ||
83 | /* | |
84 | * The MTU channels are {0..4, 6, 7} and the number of IO on MTU1 | |
85 | * and MTU2 channel is 1 compared to 2 on others. | |
86 | */ | |
87 | static const struct rz_mtu3_channel_io_map channel_map[] = { | |
88 | { 0, 2 }, { 2, 1 }, { 3, 1 }, { 4, 2 }, { 6, 2 }, { 8, 2 }, { 10, 2 } | |
89 | }; | |
90 | ||
91 | static inline struct rz_mtu3_pwm_chip *to_rz_mtu3_pwm_chip(struct pwm_chip *chip) | |
92 | { | |
a629a77e | 93 | return pwmchip_get_drvdata(chip); |
254d3a72 BD |
94 | } |
95 | ||
96 | static void rz_mtu3_pwm_read_tgr_registers(struct rz_mtu3_pwm_channel *priv, | |
97 | u16 reg_pv_offset, u16 *pv_val, | |
98 | u16 reg_dc_offset, u16 *dc_val) | |
99 | { | |
100 | *pv_val = rz_mtu3_16bit_ch_read(priv->mtu, reg_pv_offset); | |
101 | *dc_val = rz_mtu3_16bit_ch_read(priv->mtu, reg_dc_offset); | |
102 | } | |
103 | ||
104 | static void rz_mtu3_pwm_write_tgr_registers(struct rz_mtu3_pwm_channel *priv, | |
105 | u16 reg_pv_offset, u16 pv_val, | |
106 | u16 reg_dc_offset, u16 dc_val) | |
107 | { | |
108 | rz_mtu3_16bit_ch_write(priv->mtu, reg_pv_offset, pv_val); | |
109 | rz_mtu3_16bit_ch_write(priv->mtu, reg_dc_offset, dc_val); | |
110 | } | |
111 | ||
112 | static u8 rz_mtu3_pwm_calculate_prescale(struct rz_mtu3_pwm_chip *rz_mtu3, | |
113 | u64 period_cycles) | |
114 | { | |
115 | u32 prescaled_period_cycles; | |
116 | u8 prescale; | |
117 | ||
118 | /* | |
119 | * Supported prescale values are 1, 4, 16 and 64. | |
120 | * TODO: Support prescale values 2, 8, 32, 256 and 1024. | |
121 | */ | |
122 | prescaled_period_cycles = period_cycles >> 16; | |
123 | if (prescaled_period_cycles >= 16) | |
124 | prescale = 3; | |
125 | else | |
126 | prescale = (fls(prescaled_period_cycles) + 1) / 2; | |
127 | ||
128 | return prescale; | |
129 | } | |
130 | ||
131 | static struct rz_mtu3_pwm_channel * | |
132 | rz_mtu3_get_channel(struct rz_mtu3_pwm_chip *rz_mtu3_pwm, u32 hwpwm) | |
133 | { | |
134 | struct rz_mtu3_pwm_channel *priv = rz_mtu3_pwm->channel_data; | |
135 | unsigned int ch; | |
136 | ||
137 | for (ch = 0; ch < RZ_MTU3_MAX_HW_CHANNELS; ch++, priv++) { | |
138 | if (priv->map->base_pwm_number + priv->map->num_channel_ios > hwpwm) | |
139 | break; | |
140 | } | |
141 | ||
142 | return priv; | |
143 | } | |
144 | ||
145 | static bool rz_mtu3_pwm_is_ch_enabled(struct rz_mtu3_pwm_chip *rz_mtu3_pwm, | |
146 | u32 hwpwm) | |
147 | { | |
148 | struct rz_mtu3_pwm_channel *priv; | |
149 | bool is_channel_en; | |
150 | u8 val; | |
151 | ||
152 | priv = rz_mtu3_get_channel(rz_mtu3_pwm, hwpwm); | |
153 | is_channel_en = rz_mtu3_is_enabled(priv->mtu); | |
154 | if (!is_channel_en) | |
155 | return false; | |
156 | ||
157 | if (priv->map->base_pwm_number == hwpwm) | |
158 | val = rz_mtu3_8bit_ch_read(priv->mtu, RZ_MTU3_TIORH); | |
159 | else | |
160 | val = rz_mtu3_8bit_ch_read(priv->mtu, RZ_MTU3_TIORL); | |
161 | ||
162 | return val & RZ_MTU3_TIOR_IOA; | |
163 | } | |
164 | ||
165 | static int rz_mtu3_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) | |
166 | { | |
167 | struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip); | |
168 | struct rz_mtu3_pwm_channel *priv; | |
169 | bool is_mtu3_channel_available; | |
170 | u32 ch; | |
171 | ||
172 | priv = rz_mtu3_get_channel(rz_mtu3_pwm, pwm->hwpwm); | |
173 | ch = priv - rz_mtu3_pwm->channel_data; | |
174 | ||
175 | mutex_lock(&rz_mtu3_pwm->lock); | |
176 | /* | |
177 | * Each channel must be requested only once, so if the channel | |
178 | * serves two PWMs and the other is already requested, skip over | |
179 | * rz_mtu3_request_channel() | |
180 | */ | |
181 | if (!rz_mtu3_pwm->user_count[ch]) { | |
182 | is_mtu3_channel_available = rz_mtu3_request_channel(priv->mtu); | |
183 | if (!is_mtu3_channel_available) { | |
184 | mutex_unlock(&rz_mtu3_pwm->lock); | |
185 | return -EBUSY; | |
186 | } | |
187 | } | |
188 | ||
189 | rz_mtu3_pwm->user_count[ch]++; | |
190 | mutex_unlock(&rz_mtu3_pwm->lock); | |
191 | ||
192 | return 0; | |
193 | } | |
194 | ||
195 | static void rz_mtu3_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) | |
196 | { | |
197 | struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip); | |
198 | struct rz_mtu3_pwm_channel *priv; | |
199 | u32 ch; | |
200 | ||
201 | priv = rz_mtu3_get_channel(rz_mtu3_pwm, pwm->hwpwm); | |
202 | ch = priv - rz_mtu3_pwm->channel_data; | |
203 | ||
204 | mutex_lock(&rz_mtu3_pwm->lock); | |
205 | rz_mtu3_pwm->user_count[ch]--; | |
206 | if (!rz_mtu3_pwm->user_count[ch]) | |
207 | rz_mtu3_release_channel(priv->mtu); | |
208 | ||
209 | mutex_unlock(&rz_mtu3_pwm->lock); | |
210 | } | |
211 | ||
dfec83b4 | 212 | static int rz_mtu3_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) |
254d3a72 | 213 | { |
dfec83b4 | 214 | struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip); |
254d3a72 BD |
215 | struct rz_mtu3_pwm_channel *priv; |
216 | u32 ch; | |
217 | u8 val; | |
218 | int rc; | |
219 | ||
dfec83b4 | 220 | rc = pm_runtime_resume_and_get(pwmchip_parent(chip)); |
254d3a72 BD |
221 | if (rc) |
222 | return rc; | |
223 | ||
224 | priv = rz_mtu3_get_channel(rz_mtu3_pwm, pwm->hwpwm); | |
225 | ch = priv - rz_mtu3_pwm->channel_data; | |
226 | val = RZ_MTU3_TIOR_OC_IOB_TOGGLE | RZ_MTU3_TIOR_OC_IOA_H_COMP_MATCH; | |
227 | ||
228 | rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TMDR1, RZ_MTU3_TMDR1_MD_PWMMODE1); | |
229 | if (priv->map->base_pwm_number == pwm->hwpwm) | |
230 | rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TIORH, val); | |
231 | else | |
232 | rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TIORL, val); | |
233 | ||
234 | mutex_lock(&rz_mtu3_pwm->lock); | |
235 | if (!rz_mtu3_pwm->enable_count[ch]) | |
236 | rz_mtu3_enable(priv->mtu); | |
237 | ||
238 | rz_mtu3_pwm->enable_count[ch]++; | |
239 | mutex_unlock(&rz_mtu3_pwm->lock); | |
240 | ||
241 | return 0; | |
242 | } | |
243 | ||
dfec83b4 | 244 | static void rz_mtu3_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) |
254d3a72 | 245 | { |
dfec83b4 | 246 | struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip); |
254d3a72 BD |
247 | struct rz_mtu3_pwm_channel *priv; |
248 | u32 ch; | |
249 | ||
250 | priv = rz_mtu3_get_channel(rz_mtu3_pwm, pwm->hwpwm); | |
251 | ch = priv - rz_mtu3_pwm->channel_data; | |
252 | ||
253 | /* Disable output pins of MTU3 channel */ | |
254 | if (priv->map->base_pwm_number == pwm->hwpwm) | |
255 | rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TIORH, RZ_MTU3_TIOR_OC_RETAIN); | |
256 | else | |
257 | rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TIORL, RZ_MTU3_TIOR_OC_RETAIN); | |
258 | ||
259 | mutex_lock(&rz_mtu3_pwm->lock); | |
260 | rz_mtu3_pwm->enable_count[ch]--; | |
261 | if (!rz_mtu3_pwm->enable_count[ch]) | |
262 | rz_mtu3_disable(priv->mtu); | |
263 | ||
264 | mutex_unlock(&rz_mtu3_pwm->lock); | |
265 | ||
dfec83b4 | 266 | pm_runtime_put_sync(pwmchip_parent(chip)); |
254d3a72 BD |
267 | } |
268 | ||
269 | static int rz_mtu3_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, | |
270 | struct pwm_state *state) | |
271 | { | |
272 | struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip); | |
273 | int rc; | |
274 | ||
27262029 | 275 | rc = pm_runtime_resume_and_get(pwmchip_parent(chip)); |
254d3a72 BD |
276 | if (rc) |
277 | return rc; | |
278 | ||
279 | state->enabled = rz_mtu3_pwm_is_ch_enabled(rz_mtu3_pwm, pwm->hwpwm); | |
280 | if (state->enabled) { | |
281 | struct rz_mtu3_pwm_channel *priv; | |
282 | u8 prescale, val; | |
283 | u16 dc, pv; | |
284 | u64 tmp; | |
285 | ||
286 | priv = rz_mtu3_get_channel(rz_mtu3_pwm, pwm->hwpwm); | |
287 | if (priv->map->base_pwm_number == pwm->hwpwm) | |
288 | rz_mtu3_pwm_read_tgr_registers(priv, RZ_MTU3_TGRA, &pv, | |
289 | RZ_MTU3_TGRB, &dc); | |
290 | else | |
291 | rz_mtu3_pwm_read_tgr_registers(priv, RZ_MTU3_TGRC, &pv, | |
292 | RZ_MTU3_TGRD, &dc); | |
293 | ||
294 | val = rz_mtu3_8bit_ch_read(priv->mtu, RZ_MTU3_TCR); | |
295 | prescale = FIELD_GET(RZ_MTU3_TCR_TPCS, val); | |
296 | ||
297 | /* With prescale <= 7 and pv <= 0xffff this doesn't overflow. */ | |
298 | tmp = NSEC_PER_SEC * (u64)pv << (2 * prescale); | |
299 | state->period = DIV_ROUND_UP_ULL(tmp, rz_mtu3_pwm->rate); | |
300 | tmp = NSEC_PER_SEC * (u64)dc << (2 * prescale); | |
301 | state->duty_cycle = DIV_ROUND_UP_ULL(tmp, rz_mtu3_pwm->rate); | |
302 | ||
303 | if (state->duty_cycle > state->period) | |
304 | state->duty_cycle = state->period; | |
305 | } | |
306 | ||
307 | state->polarity = PWM_POLARITY_NORMAL; | |
27262029 | 308 | pm_runtime_put(pwmchip_parent(chip)); |
254d3a72 BD |
309 | |
310 | return 0; | |
311 | } | |
312 | ||
313 | static u16 rz_mtu3_pwm_calculate_pv_or_dc(u64 period_or_duty_cycle, u8 prescale) | |
314 | { | |
315 | return min(period_or_duty_cycle >> (2 * prescale), (u64)U16_MAX); | |
316 | } | |
317 | ||
318 | static int rz_mtu3_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |
319 | const struct pwm_state *state) | |
320 | { | |
321 | struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip); | |
322 | struct rz_mtu3_pwm_channel *priv; | |
323 | u64 period_cycles; | |
324 | u64 duty_cycles; | |
325 | u8 prescale; | |
326 | u16 pv, dc; | |
327 | u8 val; | |
328 | u32 ch; | |
329 | ||
330 | priv = rz_mtu3_get_channel(rz_mtu3_pwm, pwm->hwpwm); | |
331 | ch = priv - rz_mtu3_pwm->channel_data; | |
332 | ||
333 | period_cycles = mul_u64_u32_div(state->period, rz_mtu3_pwm->rate, | |
334 | NSEC_PER_SEC); | |
335 | prescale = rz_mtu3_pwm_calculate_prescale(rz_mtu3_pwm, period_cycles); | |
336 | ||
337 | /* | |
338 | * Prescalar is shared by multiple channels, so prescale can | |
339 | * NOT be modified when there are multiple channels in use with | |
340 | * different settings. Modify prescalar if other PWM is off or handle | |
341 | * it, if current prescale value is less than the one we want to set. | |
342 | */ | |
343 | if (rz_mtu3_pwm->enable_count[ch] > 1) { | |
344 | if (rz_mtu3_pwm->prescale[ch] > prescale) | |
345 | return -EBUSY; | |
346 | ||
347 | prescale = rz_mtu3_pwm->prescale[ch]; | |
348 | } | |
349 | ||
350 | pv = rz_mtu3_pwm_calculate_pv_or_dc(period_cycles, prescale); | |
351 | ||
352 | duty_cycles = mul_u64_u32_div(state->duty_cycle, rz_mtu3_pwm->rate, | |
353 | NSEC_PER_SEC); | |
354 | dc = rz_mtu3_pwm_calculate_pv_or_dc(duty_cycles, prescale); | |
355 | ||
356 | /* | |
357 | * If the PWM channel is disabled, make sure to turn on the clock | |
358 | * before writing the register. | |
359 | */ | |
360 | if (!pwm->state.enabled) { | |
361 | int rc; | |
362 | ||
27262029 | 363 | rc = pm_runtime_resume_and_get(pwmchip_parent(chip)); |
254d3a72 BD |
364 | if (rc) |
365 | return rc; | |
366 | } | |
367 | ||
368 | val = RZ_MTU3_TCR_CKEG_RISING | prescale; | |
369 | ||
370 | /* Counter must be stopped while updating TCR register */ | |
371 | if (rz_mtu3_pwm->prescale[ch] != prescale && rz_mtu3_pwm->enable_count[ch]) | |
372 | rz_mtu3_disable(priv->mtu); | |
373 | ||
374 | if (priv->map->base_pwm_number == pwm->hwpwm) { | |
375 | rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TCR, | |
376 | RZ_MTU3_TCR_CCLR_TGRA | val); | |
377 | rz_mtu3_pwm_write_tgr_registers(priv, RZ_MTU3_TGRA, pv, | |
378 | RZ_MTU3_TGRB, dc); | |
379 | } else { | |
380 | rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TCR, | |
381 | RZ_MTU3_TCR_CCLR_TGRC | val); | |
382 | rz_mtu3_pwm_write_tgr_registers(priv, RZ_MTU3_TGRC, pv, | |
383 | RZ_MTU3_TGRD, dc); | |
384 | } | |
385 | ||
386 | if (rz_mtu3_pwm->prescale[ch] != prescale) { | |
387 | /* | |
388 | * Prescalar is shared by multiple channels, we cache the | |
389 | * prescalar value from first enabled channel and use the same | |
390 | * value for both channels. | |
391 | */ | |
392 | rz_mtu3_pwm->prescale[ch] = prescale; | |
393 | ||
394 | if (rz_mtu3_pwm->enable_count[ch]) | |
395 | rz_mtu3_enable(priv->mtu); | |
396 | } | |
397 | ||
398 | /* If the PWM is not enabled, turn the clock off again to save power. */ | |
399 | if (!pwm->state.enabled) | |
27262029 | 400 | pm_runtime_put(pwmchip_parent(chip)); |
254d3a72 BD |
401 | |
402 | return 0; | |
403 | } | |
404 | ||
405 | static int rz_mtu3_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | |
406 | const struct pwm_state *state) | |
407 | { | |
408 | struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip); | |
409 | bool enabled = pwm->state.enabled; | |
410 | int ret; | |
411 | ||
412 | if (state->polarity != PWM_POLARITY_NORMAL) | |
413 | return -EINVAL; | |
414 | ||
415 | if (!state->enabled) { | |
416 | if (enabled) | |
dfec83b4 | 417 | rz_mtu3_pwm_disable(chip, pwm); |
254d3a72 BD |
418 | |
419 | return 0; | |
420 | } | |
421 | ||
422 | mutex_lock(&rz_mtu3_pwm->lock); | |
423 | ret = rz_mtu3_pwm_config(chip, pwm, state); | |
424 | mutex_unlock(&rz_mtu3_pwm->lock); | |
425 | if (ret) | |
426 | return ret; | |
427 | ||
428 | if (!enabled) | |
dfec83b4 | 429 | ret = rz_mtu3_pwm_enable(chip, pwm); |
254d3a72 BD |
430 | |
431 | return ret; | |
432 | } | |
433 | ||
434 | static const struct pwm_ops rz_mtu3_pwm_ops = { | |
435 | .request = rz_mtu3_pwm_request, | |
436 | .free = rz_mtu3_pwm_free, | |
437 | .get_state = rz_mtu3_pwm_get_state, | |
438 | .apply = rz_mtu3_pwm_apply, | |
254d3a72 BD |
439 | }; |
440 | ||
441 | static int rz_mtu3_pwm_pm_runtime_suspend(struct device *dev) | |
442 | { | |
dfec83b4 UKK |
443 | struct pwm_chip *chip = dev_get_drvdata(dev); |
444 | struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip); | |
254d3a72 BD |
445 | |
446 | clk_disable_unprepare(rz_mtu3_pwm->clk); | |
447 | ||
448 | return 0; | |
449 | } | |
450 | ||
451 | static int rz_mtu3_pwm_pm_runtime_resume(struct device *dev) | |
452 | { | |
dfec83b4 UKK |
453 | struct pwm_chip *chip = dev_get_drvdata(dev); |
454 | struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip); | |
254d3a72 BD |
455 | |
456 | return clk_prepare_enable(rz_mtu3_pwm->clk); | |
457 | } | |
458 | ||
459 | static DEFINE_RUNTIME_DEV_PM_OPS(rz_mtu3_pwm_pm_ops, | |
460 | rz_mtu3_pwm_pm_runtime_suspend, | |
461 | rz_mtu3_pwm_pm_runtime_resume, NULL); | |
462 | ||
463 | static void rz_mtu3_pwm_pm_disable(void *data) | |
464 | { | |
dfec83b4 UKK |
465 | struct pwm_chip *chip = data; |
466 | struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip); | |
254d3a72 BD |
467 | |
468 | clk_rate_exclusive_put(rz_mtu3_pwm->clk); | |
dfec83b4 UKK |
469 | pm_runtime_disable(pwmchip_parent(chip)); |
470 | pm_runtime_set_suspended(pwmchip_parent(chip)); | |
254d3a72 BD |
471 | } |
472 | ||
473 | static int rz_mtu3_pwm_probe(struct platform_device *pdev) | |
474 | { | |
475 | struct rz_mtu3 *parent_ddata = dev_get_drvdata(pdev->dev.parent); | |
476 | struct rz_mtu3_pwm_chip *rz_mtu3_pwm; | |
dfec83b4 | 477 | struct pwm_chip *chip; |
254d3a72 BD |
478 | struct device *dev = &pdev->dev; |
479 | unsigned int i, j = 0; | |
480 | int ret; | |
481 | ||
a629a77e UKK |
482 | chip = devm_pwmchip_alloc(&pdev->dev, RZ_MTU3_MAX_PWM_CHANNELS, |
483 | sizeof(*rz_mtu3_pwm)); | |
484 | if (IS_ERR(chip)) | |
485 | return PTR_ERR(chip); | |
486 | rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip); | |
254d3a72 BD |
487 | |
488 | rz_mtu3_pwm->clk = parent_ddata->clk; | |
489 | ||
490 | for (i = 0; i < RZ_MTU_NUM_CHANNELS; i++) { | |
491 | if (i == RZ_MTU3_CHAN_5 || i == RZ_MTU3_CHAN_8) | |
492 | continue; | |
493 | ||
494 | rz_mtu3_pwm->channel_data[j].mtu = &parent_ddata->channels[i]; | |
495 | rz_mtu3_pwm->channel_data[j].mtu->dev = dev; | |
496 | rz_mtu3_pwm->channel_data[j].map = &channel_map[j]; | |
497 | j++; | |
498 | } | |
499 | ||
500 | mutex_init(&rz_mtu3_pwm->lock); | |
dfec83b4 | 501 | platform_set_drvdata(pdev, chip); |
254d3a72 BD |
502 | ret = clk_prepare_enable(rz_mtu3_pwm->clk); |
503 | if (ret) | |
504 | return dev_err_probe(dev, ret, "Clock enable failed\n"); | |
505 | ||
506 | clk_rate_exclusive_get(rz_mtu3_pwm->clk); | |
507 | ||
508 | rz_mtu3_pwm->rate = clk_get_rate(rz_mtu3_pwm->clk); | |
509 | /* | |
510 | * Refuse clk rates > 1 GHz to prevent overflow later for computing | |
511 | * period and duty cycle. | |
512 | */ | |
513 | if (rz_mtu3_pwm->rate > NSEC_PER_SEC) { | |
514 | ret = -EINVAL; | |
515 | clk_rate_exclusive_put(rz_mtu3_pwm->clk); | |
516 | goto disable_clock; | |
517 | } | |
518 | ||
519 | pm_runtime_set_active(&pdev->dev); | |
520 | pm_runtime_enable(&pdev->dev); | |
254d3a72 | 521 | ret = devm_add_action_or_reset(&pdev->dev, rz_mtu3_pwm_pm_disable, |
dfec83b4 | 522 | chip); |
254d3a72 BD |
523 | if (ret < 0) |
524 | return ret; | |
525 | ||
dfec83b4 | 526 | chip->ops = &rz_mtu3_pwm_ops; |
dfec83b4 | 527 | ret = devm_pwmchip_add(&pdev->dev, chip); |
254d3a72 BD |
528 | if (ret) |
529 | return dev_err_probe(&pdev->dev, ret, "failed to add PWM chip\n"); | |
530 | ||
531 | pm_runtime_idle(&pdev->dev); | |
532 | ||
533 | return 0; | |
534 | ||
535 | disable_clock: | |
536 | clk_disable_unprepare(rz_mtu3_pwm->clk); | |
537 | return ret; | |
538 | } | |
539 | ||
540 | static struct platform_driver rz_mtu3_pwm_driver = { | |
541 | .driver = { | |
542 | .name = "pwm-rz-mtu3", | |
543 | .pm = pm_ptr(&rz_mtu3_pwm_pm_ops), | |
544 | }, | |
545 | .probe = rz_mtu3_pwm_probe, | |
546 | }; | |
547 | module_platform_driver(rz_mtu3_pwm_driver); | |
548 | ||
549 | MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>"); | |
550 | MODULE_ALIAS("platform:pwm-rz-mtu3"); | |
551 | MODULE_DESCRIPTION("Renesas RZ/G2L MTU3a PWM Timer Driver"); | |
552 | MODULE_LICENSE("GPL"); |