1 /*
2 * Copyright (c) 2024 Renesas Electronics Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/device.h>
9 #include <zephyr/irq.h>
10 #include <zephyr/drivers/pwm.h>
11 #include <zephyr/drivers/pinctrl.h>
12 #include <zephyr/dt-bindings/pwm/renesas_rz_pwm.h>
13 #include "r_gpt.h"
14 #include "r_gpt_cfg.h"
15 #include <zephyr/logging/log.h>
16
17 LOG_MODULE_REGISTER(pwm_renesas_rz_gpt, CONFIG_PWM_LOG_LEVEL);
18
19 #define DT_DRV_COMPAT renesas_rz_gpt_pwm
20
21 #define GPT_PRV_GTIO_HIGH_COMPARE_MATCH_LOW_CYCLE_END 0x6U
22 #define GPT_PRV_GTIO_LOW_COMPARE_MATCH_HIGH_CYCLE_END 0x9U
23 #define GPT_PRV_GTIOR_INITIAL_LEVEL_BIT 4
24
25 #define CAPTURE_BOTH_MODE_FIRST_EVENT_IS_CAPTURE_PULSE 1
26 #define CAPTURE_BOTH_MODE_SECOND_EVENT_IS_CAPTURE_PERIOD 2
27
28 struct pwm_rz_gpt_capture_data {
29 pwm_capture_callback_handler_t callback;
30 void *user_data;
31 uint64_t period;
32 uint64_t pulse;
33 uint16_t capture_type_flag;
34 uint32_t capture_both_event_count;
35 bool is_busy;
36 uint32_t overflows;
37 bool continuous;
38 uint32_t capture_channel;
39 };
40
41 struct pwm_rz_gpt_data {
42 timer_cfg_t *fsp_cfg;
43 gpt_instance_ctrl_t *fsp_ctrl;
44 #ifdef CONFIG_PWM_CAPTURE
45 struct pwm_rz_gpt_capture_data capture;
46 #endif /* CONFIG_PWM_CAPTURE */
47 };
48
49 struct pwm_rz_gpt_config {
50 const struct pinctrl_dev_config *pincfg;
51 const timer_api_t *fsp_api;
52 };
53
pwm_rz_gpt_gtior_calculate(gpt_pin_level_t const stop_level)54 static uint32_t pwm_rz_gpt_gtior_calculate(gpt_pin_level_t const stop_level)
55 {
56 /* The stop level is used as both the initial level and the stop level. */
57 uint32_t gtior = R_GPT0_GTIOR_OAE_Msk | ((uint32_t)stop_level << R_GPT0_GTIOR_OADFLT_Pos) |
58 ((uint32_t)stop_level << GPT_PRV_GTIOR_INITIAL_LEVEL_BIT);
59
60 uint32_t gtion = GPT_PRV_GTIO_LOW_COMPARE_MATCH_HIGH_CYCLE_END;
61
62 /* Calculate the gtior value for PWM mode only */
63 gtior |= gtion;
64
65 return gtior;
66 }
67
pwm_rz_gpt_apply_gtior_config(gpt_instance_ctrl_t * const p_ctrl,timer_cfg_t const * const p_cfg)68 static int pwm_rz_gpt_apply_gtior_config(gpt_instance_ctrl_t *const p_ctrl,
69 timer_cfg_t const *const p_cfg)
70 {
71 gpt_extended_cfg_t *p_extend = (gpt_extended_cfg_t *)p_cfg->p_extend;
72 uint32_t gtior = p_extend->gtior_setting.gtior;
73
74 #if GPT_CFG_OUTPUT_SUPPORT_ENABLE
75 /* Check if custom GTIOR settings are provided. */
76 if (p_extend->gtior_setting.gtior == 0) {
77 /* If custom GTIOR settings are not provided, calculate GTIOR. */
78 if (p_extend->gtioca.output_enabled) {
79 uint32_t gtioca_gtior =
80 pwm_rz_gpt_gtior_calculate(p_extend->gtioca.stop_level);
81 gtior |= gtioca_gtior << R_GPT0_GTIOR_GTIOA_Pos;
82 }
83
84 if (p_extend->gtiocb.output_enabled) {
85 uint32_t gtiocb_gtior =
86 pwm_rz_gpt_gtior_calculate(p_extend->gtiocb.stop_level);
87 gtior |= gtiocb_gtior << R_GPT0_GTIOR_GTIOB_Pos;
88 }
89 }
90 #endif
91
92 /* Check if custom GTIOR settings are provided. */
93 if (p_extend->gtior_setting.gtior == 0) {
94 /*
95 * If custom GTIOR settings are not provided, configure the noise filter for
96 * the GTIOC pins.
97 */
98 gtior |= (uint32_t)(p_extend->capture_filter_gtioca << R_GPT0_GTIOR_NFAEN_Pos);
99 gtior |= (uint32_t)(p_extend->capture_filter_gtiocb << R_GPT0_GTIOR_NFBEN_Pos);
100 }
101
102 /* Set the I/O control register. */
103 p_ctrl->p_reg->GTIOR = gtior;
104
105 return 0;
106 }
107
pwm_rz_gpt_set_cycles(const struct device * dev,uint32_t channel,uint32_t period_cycles,uint32_t pulse_cycles,pwm_flags_t flags)108 static int pwm_rz_gpt_set_cycles(const struct device *dev, uint32_t channel, uint32_t period_cycles,
109 uint32_t pulse_cycles, pwm_flags_t flags)
110 {
111 const struct pwm_rz_gpt_config *cfg = dev->config;
112 struct pwm_rz_gpt_data *data = dev->data;
113 gpt_extended_cfg_t *fsp_cfg_extend = (gpt_extended_cfg_t *)data->fsp_cfg->p_extend;
114 uint32_t pulse;
115 fsp_err_t err;
116 uint32_t pin;
117
118 /* gtioca and gtiocb setting */
119 if (channel == RZ_PWM_GPT_IO_A) {
120 pin = GPT_IO_PIN_GTIOCA;
121 fsp_cfg_extend->gtioca.output_enabled = true;
122 } else if (channel == RZ_PWM_GPT_IO_B) {
123 pin = GPT_IO_PIN_GTIOCB;
124 fsp_cfg_extend->gtiocb.output_enabled = true;
125 } else {
126 LOG_ERR("Valid only for RZ_PWM_GPT_IO_A and RZ_PWM_GPT_IO_B pins");
127 return -EINVAL;
128 }
129
130 if ((data->fsp_ctrl->variant == TIMER_VARIANT_16_BIT && period_cycles > UINT16_MAX) ||
131 (data->fsp_ctrl->variant == TIMER_VARIANT_32_BIT && period_cycles > UINT32_MAX)) {
132 LOG_ERR("Out of range period cycles are not valid");
133 return -EINVAL;
134 }
135
136 pulse = (flags & PWM_POLARITY_INVERTED) ? period_cycles - pulse_cycles : pulse_cycles;
137
138 /* Apply gtio output setting */
139 pwm_rz_gpt_apply_gtior_config(data->fsp_ctrl, data->fsp_cfg);
140
141 /* Stop timer */
142 err = cfg->fsp_api->stop(data->fsp_ctrl);
143 if (err != FSP_SUCCESS) {
144 return -EIO;
145 }
146
147 /* Update period cycles, reflected at an overflow */
148 err = cfg->fsp_api->periodSet(data->fsp_ctrl, period_cycles);
149 if (err != FSP_SUCCESS) {
150 return -EIO;
151 }
152
153 /* Update pulse cycles, reflected at an overflow */
154 err = cfg->fsp_api->dutyCycleSet(data->fsp_ctrl, pulse, pin);
155 if (err != FSP_SUCCESS) {
156 return -EIO;
157 }
158
159 /* Start timer */
160 err = cfg->fsp_api->start(data->fsp_ctrl);
161 if (err != FSP_SUCCESS) {
162 return -EIO;
163 }
164
165 return 0;
166 };
167
pwm_rz_gpt_get_cycles_per_sec(const struct device * dev,uint32_t channel,uint64_t * cycles)168 static int pwm_rz_gpt_get_cycles_per_sec(const struct device *dev, uint32_t channel,
169 uint64_t *cycles)
170 {
171 const struct pwm_rz_gpt_config *cfg = dev->config;
172 struct pwm_rz_gpt_data *data = dev->data;
173 timer_info_t info;
174 fsp_err_t err;
175
176 if (!(channel == RZ_PWM_GPT_IO_A || channel == RZ_PWM_GPT_IO_B)) {
177 LOG_ERR("Valid only for RZ_PWM_GPT_IO_A and RZ_PWM_GPT_IO_B pins");
178 return -EINVAL;
179 }
180
181 err = cfg->fsp_api->infoGet(data->fsp_ctrl, &info);
182 if (err != FSP_SUCCESS) {
183 return -EIO;
184 }
185 *cycles = (uint64_t)info.clock_frequency;
186
187 return 0;
188 };
189
190 extern void gpt_capture_a_isr(void);
191 extern void gpt_capture_b_isr(void);
192 extern void gpt_counter_overflow_isr(void);
193
194 #ifdef CONFIG_PWM_CAPTURE
195
pwm_rz_gpt_configure_capture(const struct device * dev,uint32_t channel,pwm_flags_t flags,pwm_capture_callback_handler_t cb,void * user_data)196 static int pwm_rz_gpt_configure_capture(const struct device *dev, uint32_t channel,
197 pwm_flags_t flags, pwm_capture_callback_handler_t cb,
198 void *user_data)
199 {
200 struct pwm_rz_gpt_data *data = dev->data;
201 gpt_extended_cfg_t *fsp_cfg_extend = (gpt_extended_cfg_t *)data->fsp_cfg->p_extend;
202
203 if (!(flags & PWM_CAPTURE_TYPE_MASK)) {
204 LOG_ERR("No PWWM capture type specified");
205 return -EINVAL;
206 }
207 data->capture.capture_type_flag = flags & PWM_CAPTURE_TYPE_MASK;
208 data->capture.capture_channel = channel;
209 if (data->capture.is_busy) {
210 LOG_ERR("Capture already active on this pin");
211 return -EBUSY;
212 }
213 if (channel == RZ_PWM_GPT_IO_A) {
214 if (data->capture.capture_type_flag == PWM_CAPTURE_TYPE_BOTH) {
215 data->capture.capture_both_event_count = 0;
216 if (flags & PWM_POLARITY_INVERTED) {
217 fsp_cfg_extend->start_source =
218 (gpt_source_t)(GPT_SOURCE_GTIOCA_FALLING_WHILE_GTIOCB_LOW |
219 GPT_SOURCE_GTIOCA_FALLING_WHILE_GTIOCB_HIGH |
220 GPT_SOURCE_NONE);
221 } else {
222 fsp_cfg_extend->start_source =
223 (gpt_source_t)(GPT_SOURCE_GTIOCA_RISING_WHILE_GTIOCB_LOW |
224 GPT_SOURCE_GTIOCA_RISING_WHILE_GTIOCB_HIGH |
225 GPT_SOURCE_NONE);
226 }
227 fsp_cfg_extend->capture_a_source =
228 (gpt_source_t)(GPT_SOURCE_GTIOCA_RISING_WHILE_GTIOCB_LOW |
229 GPT_SOURCE_GTIOCA_RISING_WHILE_GTIOCB_HIGH |
230 GPT_SOURCE_GTIOCA_FALLING_WHILE_GTIOCB_LOW |
231 GPT_SOURCE_GTIOCA_FALLING_WHILE_GTIOCB_HIGH |
232 GPT_SOURCE_NONE);
233 } else if (data->capture.capture_type_flag == PWM_CAPTURE_TYPE_PERIOD) {
234 if (flags & PWM_POLARITY_INVERTED) {
235 fsp_cfg_extend->start_source =
236 (gpt_source_t)(GPT_SOURCE_GTIOCA_FALLING_WHILE_GTIOCB_LOW |
237 GPT_SOURCE_GTIOCA_FALLING_WHILE_GTIOCB_HIGH |
238 GPT_SOURCE_NONE);
239 fsp_cfg_extend->capture_a_source = fsp_cfg_extend->start_source;
240 } else {
241 fsp_cfg_extend->start_source =
242 (gpt_source_t)(GPT_SOURCE_GTIOCA_RISING_WHILE_GTIOCB_LOW |
243 GPT_SOURCE_GTIOCA_RISING_WHILE_GTIOCB_HIGH |
244 GPT_SOURCE_NONE);
245 fsp_cfg_extend->capture_a_source = fsp_cfg_extend->start_source;
246 }
247 } else {
248 if (flags & PWM_POLARITY_INVERTED) {
249 fsp_cfg_extend->start_source =
250 (gpt_source_t)(GPT_SOURCE_GTIOCA_FALLING_WHILE_GTIOCB_LOW |
251 GPT_SOURCE_GTIOCA_FALLING_WHILE_GTIOCB_HIGH |
252 GPT_SOURCE_NONE);
253 fsp_cfg_extend->capture_a_source =
254 (gpt_source_t)(GPT_SOURCE_GTIOCA_RISING_WHILE_GTIOCB_LOW |
255 GPT_SOURCE_GTIOCA_RISING_WHILE_GTIOCB_HIGH |
256 GPT_SOURCE_NONE);
257 } else {
258 fsp_cfg_extend->start_source =
259 (gpt_source_t)(GPT_SOURCE_GTIOCA_RISING_WHILE_GTIOCB_LOW |
260 GPT_SOURCE_GTIOCA_RISING_WHILE_GTIOCB_HIGH |
261 GPT_SOURCE_NONE);
262 fsp_cfg_extend->capture_a_source =
263 (gpt_source_t)(GPT_SOURCE_GTIOCA_FALLING_WHILE_GTIOCB_LOW |
264 GPT_SOURCE_GTIOCA_FALLING_WHILE_GTIOCB_HIGH |
265 GPT_SOURCE_NONE);
266 }
267 }
268 } else if (channel == RZ_PWM_GPT_IO_B) {
269 if (data->capture.capture_type_flag == PWM_CAPTURE_TYPE_BOTH) {
270 data->capture.capture_both_event_count = 0;
271 if (flags & PWM_POLARITY_INVERTED) {
272 fsp_cfg_extend->start_source =
273 (gpt_source_t)(GPT_SOURCE_GTIOCB_FALLING_WHILE_GTIOCA_LOW |
274 GPT_SOURCE_GTIOCB_FALLING_WHILE_GTIOCA_HIGH |
275 GPT_SOURCE_NONE);
276 } else {
277 fsp_cfg_extend->start_source =
278 (gpt_source_t)(GPT_SOURCE_GTIOCB_RISING_WHILE_GTIOCA_LOW |
279 GPT_SOURCE_GTIOCB_RISING_WHILE_GTIOCA_HIGH |
280 GPT_SOURCE_NONE);
281 }
282 fsp_cfg_extend->capture_b_source =
283 (gpt_source_t)(GPT_SOURCE_GTIOCB_RISING_WHILE_GTIOCA_LOW |
284 GPT_SOURCE_GTIOCB_RISING_WHILE_GTIOCA_HIGH |
285 GPT_SOURCE_GTIOCB_FALLING_WHILE_GTIOCA_LOW |
286 GPT_SOURCE_GTIOCB_FALLING_WHILE_GTIOCA_HIGH |
287 GPT_SOURCE_NONE);
288 } else if (data->capture.capture_type_flag == PWM_CAPTURE_TYPE_PERIOD) {
289 if (flags & PWM_POLARITY_INVERTED) {
290 fsp_cfg_extend->start_source =
291 (gpt_source_t)(GPT_SOURCE_GTIOCB_FALLING_WHILE_GTIOCA_LOW |
292 GPT_SOURCE_GTIOCB_FALLING_WHILE_GTIOCA_HIGH |
293 GPT_SOURCE_NONE);
294 fsp_cfg_extend->capture_b_source = fsp_cfg_extend->start_source;
295 } else {
296 fsp_cfg_extend->start_source =
297 (gpt_source_t)(GPT_SOURCE_GTIOCB_RISING_WHILE_GTIOCA_LOW |
298 GPT_SOURCE_GTIOCB_RISING_WHILE_GTIOCA_HIGH |
299 GPT_SOURCE_NONE);
300 fsp_cfg_extend->capture_b_source = fsp_cfg_extend->start_source;
301 }
302 } else {
303 if (flags & PWM_POLARITY_INVERTED) {
304 fsp_cfg_extend->start_source =
305 (gpt_source_t)(GPT_SOURCE_GTIOCB_FALLING_WHILE_GTIOCA_LOW |
306 GPT_SOURCE_GTIOCB_FALLING_WHILE_GTIOCA_HIGH |
307 GPT_SOURCE_NONE);
308 fsp_cfg_extend->capture_b_source =
309 (gpt_source_t)(GPT_SOURCE_GTIOCB_RISING_WHILE_GTIOCA_LOW |
310 GPT_SOURCE_GTIOCB_RISING_WHILE_GTIOCA_HIGH |
311 GPT_SOURCE_NONE);
312 } else {
313 fsp_cfg_extend->start_source =
314 (gpt_source_t)(GPT_SOURCE_GTIOCB_RISING_WHILE_GTIOCA_LOW |
315 GPT_SOURCE_GTIOCB_RISING_WHILE_GTIOCA_HIGH |
316 GPT_SOURCE_NONE);
317 fsp_cfg_extend->capture_b_source =
318 (gpt_source_t)(GPT_SOURCE_GTIOCB_FALLING_WHILE_GTIOCA_LOW |
319 GPT_SOURCE_GTIOCB_FALLING_WHILE_GTIOCA_HIGH |
320 GPT_SOURCE_NONE);
321 }
322 }
323 }
324
325 data->capture.callback = cb;
326 data->capture.user_data = user_data;
327 data->capture.continuous = flags & PWM_CAPTURE_MODE_CONTINUOUS;
328 if (data->capture.continuous) {
329 if (channel == RZ_PWM_GPT_IO_A) {
330 fsp_cfg_extend->stop_source = fsp_cfg_extend->capture_a_source;
331 } else if (channel == RZ_PWM_GPT_IO_B) {
332 fsp_cfg_extend->stop_source = fsp_cfg_extend->capture_b_source;
333 }
334 fsp_cfg_extend->clear_source = fsp_cfg_extend->start_source;
335 }
336
337 else {
338 fsp_cfg_extend->stop_source = (gpt_source_t)(GPT_SOURCE_NONE);
339 fsp_cfg_extend->clear_source = (gpt_source_t)(GPT_SOURCE_NONE);
340 }
341
342 return 0;
343 }
344
pwm_rz_gpt_enable_capture(const struct device * dev,uint32_t channel)345 static int pwm_rz_gpt_enable_capture(const struct device *dev, uint32_t channel)
346 {
347 const struct pwm_rz_gpt_config *cfg = dev->config;
348 struct pwm_rz_gpt_data *data = dev->data;
349 gpt_extended_cfg_t *fsp_cfg_extend = (gpt_extended_cfg_t *)data->fsp_cfg->p_extend;
350 fsp_err_t err;
351
352 data->capture.capture_channel = channel;
353
354 if (data->capture.is_busy) {
355 LOG_ERR("Capture already active on this pin");
356 return -EBUSY;
357 }
358
359 if (!data->capture.callback) {
360 LOG_ERR("PWM capture not configured");
361 return -EINVAL;
362 }
363
364 data->capture.is_busy = true;
365
366 /* Enable capture source */
367 err = cfg->fsp_api->enable(data->fsp_ctrl);
368 if (err != FSP_SUCCESS) {
369 return -EIO;
370 }
371
372 /* Enable interruption */
373 irq_enable(data->fsp_cfg->cycle_end_irq);
374 if (channel == RZ_PWM_GPT_IO_A) {
375 irq_enable(fsp_cfg_extend->capture_a_irq);
376 } else if (channel == RZ_PWM_GPT_IO_B) {
377 irq_enable(fsp_cfg_extend->capture_b_irq);
378 }
379
380 return 0;
381 }
382
pwm_rz_gpt_disable_capture(const struct device * dev,uint32_t channel)383 static int pwm_rz_gpt_disable_capture(const struct device *dev, uint32_t channel)
384 {
385 const struct pwm_rz_gpt_config *cfg = dev->config;
386 struct pwm_rz_gpt_data *data = dev->data;
387 fsp_err_t err;
388 gpt_extended_cfg_t *fsp_cfg_extend = (gpt_extended_cfg_t *)data->fsp_cfg->p_extend;
389
390 data->capture.capture_channel = channel;
391 data->capture.is_busy = false;
392
393 /* Disable interruption */
394 irq_disable(data->fsp_cfg->cycle_end_irq);
395 if (channel == RZ_PWM_GPT_IO_A) {
396 irq_disable(fsp_cfg_extend->capture_a_irq);
397 } else if (channel == RZ_PWM_GPT_IO_B) {
398 irq_disable(fsp_cfg_extend->capture_b_irq);
399 }
400
401 /* Disable capture source */
402 err = cfg->fsp_api->disable(data->fsp_ctrl);
403 if (err != FSP_SUCCESS) {
404 return -EIO;
405 }
406
407 /* Stop timer */
408 err = cfg->fsp_api->stop(data->fsp_ctrl);
409 if (err != FSP_SUCCESS) {
410 return -EIO;
411 }
412
413 /* Clear timer */
414 err = cfg->fsp_api->reset(data->fsp_ctrl);
415 if (err != FSP_SUCCESS) {
416 return -EIO;
417 }
418
419 return 0;
420 }
421
fsp_callback(timer_callback_args_t * p_args)422 static void fsp_callback(timer_callback_args_t *p_args)
423 {
424 const struct device *dev = p_args->p_context;
425 const struct pwm_rz_gpt_config *cfg = dev->config;
426 struct pwm_rz_gpt_data *data = dev->data;
427 timer_info_t info;
428
429 (void)cfg->fsp_api->infoGet(data->fsp_ctrl, &info);
430
431 uint64_t period = info.period_counts;
432
433 /* The maximum period is one more than the maximum 16,32-bit number, but will be reflected
434 * as 0
435 */
436 if (period == 0U) {
437 if (data->fsp_ctrl->variant == TIMER_VARIANT_16_BIT) {
438 period = UINT16_MAX + 1U;
439 } else {
440 period = UINT32_MAX + 1U;
441 }
442 }
443
444 /* Capture event */
445 if (p_args->event == TIMER_EVENT_CAPTURE_A) {
446 if (p_args->capture != 0U) {
447 bool check_disable_capture = false;
448
449 if (data->capture.capture_type_flag == PWM_CAPTURE_TYPE_BOTH) {
450 data->capture.capture_both_event_count++;
451 if (data->capture.capture_both_event_count ==
452 CAPTURE_BOTH_MODE_FIRST_EVENT_IS_CAPTURE_PULSE) {
453 data->capture.pulse = (data->capture.overflows * period) +
454 p_args->capture;
455 }
456 if (data->capture.capture_both_event_count ==
457 CAPTURE_BOTH_MODE_SECOND_EVENT_IS_CAPTURE_PERIOD) {
458 data->capture.capture_both_event_count = 0;
459 data->capture.period = (data->capture.overflows * period) +
460 p_args->capture;
461 data->capture.callback(
462 dev, GPT_IO_PIN_GTIOCA, data->capture.period,
463 data->capture.pulse, 0, data->capture.user_data);
464
465 check_disable_capture = true;
466 }
467 } else if (data->capture.capture_type_flag == PWM_CAPTURE_TYPE_PULSE) {
468 data->capture.pulse =
469 (data->capture.overflows * period) + p_args->capture;
470 data->capture.callback(dev, GPT_IO_PIN_GTIOCA, 0,
471 data->capture.pulse, 0,
472 data->capture.user_data);
473
474 check_disable_capture = true;
475 } else {
476 data->capture.period =
477 (data->capture.overflows * period) + p_args->capture;
478 data->capture.callback(dev, GPT_IO_PIN_GTIOCA, data->capture.period,
479 0, 0, data->capture.user_data);
480
481 check_disable_capture = true;
482 }
483 if (check_disable_capture) {
484 data->capture.overflows = 0U;
485 /* Disable capture in single mode */
486 if (data->capture.continuous == false) {
487 pwm_rz_gpt_disable_capture(dev, GPT_IO_PIN_GTIOCA);
488 }
489 }
490 }
491 } else if (p_args->event == TIMER_EVENT_CAPTURE_B) {
492 if (p_args->capture != 0U) {
493 bool check_disable_capture = false;
494
495 if (data->capture.capture_type_flag == PWM_CAPTURE_TYPE_BOTH) {
496 data->capture.capture_both_event_count++;
497 if (data->capture.capture_both_event_count ==
498 CAPTURE_BOTH_MODE_FIRST_EVENT_IS_CAPTURE_PULSE) {
499 data->capture.pulse = (data->capture.overflows * period) +
500 p_args->capture;
501 }
502 if (data->capture.capture_both_event_count ==
503 CAPTURE_BOTH_MODE_SECOND_EVENT_IS_CAPTURE_PERIOD) {
504 data->capture.capture_both_event_count = 0;
505 data->capture.period = (data->capture.overflows * period) +
506 p_args->capture;
507 data->capture.callback(
508 dev, GPT_IO_PIN_GTIOCB, data->capture.period,
509 data->capture.pulse, 0, data->capture.user_data);
510
511 check_disable_capture = true;
512 }
513 } else if (data->capture.capture_type_flag == PWM_CAPTURE_TYPE_PULSE) {
514 data->capture.pulse =
515 (data->capture.overflows * period) + p_args->capture;
516 data->capture.callback(dev, GPT_IO_PIN_GTIOCB, 0,
517 data->capture.pulse, 0,
518 data->capture.user_data);
519
520 check_disable_capture = true;
521 } else {
522 data->capture.period =
523 (data->capture.overflows * period) + p_args->capture;
524 data->capture.callback(dev, GPT_IO_PIN_GTIOCB, data->capture.period,
525 0, 0, data->capture.user_data);
526
527 check_disable_capture = true;
528 }
529 if (check_disable_capture) {
530 data->capture.overflows = 0U;
531 /* Disable capture in single mode */
532 if (data->capture.continuous == false) {
533 pwm_rz_gpt_disable_capture(dev, GPT_IO_PIN_GTIOCB);
534 }
535 }
536 }
537 } else if (p_args->event == TIMER_EVENT_CYCLE_END) {
538 data->capture.overflows++;
539 } else {
540 if (data->capture.capture_channel == RZ_PWM_GPT_IO_A) {
541 data->capture.callback(dev, GPT_IO_PIN_GTIOCA, 0, 0, -ECANCELED,
542 data->capture.user_data);
543 } else if (data->capture.capture_channel == RZ_PWM_GPT_IO_B) {
544 data->capture.callback(dev, GPT_IO_PIN_GTIOCB, 0, 0, -ECANCELED,
545 data->capture.user_data);
546 }
547 }
548 }
549
550 #endif /* CONFIG_PWM_CAPTURE */
551
552 static DEVICE_API(pwm, pwm_rz_gpt_driver_api) = {
553 .get_cycles_per_sec = pwm_rz_gpt_get_cycles_per_sec,
554 .set_cycles = pwm_rz_gpt_set_cycles,
555 #ifdef CONFIG_PWM_CAPTURE
556 .configure_capture = pwm_rz_gpt_configure_capture,
557 .enable_capture = pwm_rz_gpt_enable_capture,
558 .disable_capture = pwm_rz_gpt_disable_capture,
559 #endif /* CONFIG_PWM_CAPTURE */
560 };
561
pwm_rz_gpt_init(const struct device * dev)562 static int pwm_rz_gpt_init(const struct device *dev)
563 {
564 const struct pwm_rz_gpt_config *cfg = dev->config;
565 struct pwm_rz_gpt_data *data = dev->data;
566 gpt_extended_cfg_t *fsp_cfg_extend = (gpt_extended_cfg_t *)data->fsp_cfg->p_extend;
567 int err;
568
569 err = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT);
570 if (err) {
571 LOG_ERR("Failed to configure pins for PWM (%d)", err);
572 return err;
573 }
574
575 #if defined(CONFIG_PWM_CAPTURE)
576 data->fsp_cfg->p_callback = fsp_callback;
577 data->fsp_cfg->p_context = dev;
578 #endif /* defined(CONFIG_PWM_CAPTURE) */
579
580 err = cfg->fsp_api->open(data->fsp_ctrl, data->fsp_cfg);
581 if (err != FSP_SUCCESS) {
582 return -EIO;
583 }
584
585 irq_disable(data->fsp_cfg->cycle_end_irq);
586 irq_disable(fsp_cfg_extend->capture_a_irq);
587 irq_disable(fsp_cfg_extend->capture_b_irq);
588
589 return 0;
590 }
591
592 #define GPT(idx) DT_INST_PARENT(idx)
593
594 #define PWM_RZ_IRQ_CONFIG_INIT(inst) \
595 do { \
596 IRQ_CONNECT(DT_IRQ_BY_NAME(GPT(inst), ccmpa, irq), \
597 DT_IRQ_BY_NAME(GPT(inst), ccmpa, priority), gpt_capture_a_isr, NULL, \
598 0); \
599 IRQ_CONNECT(DT_IRQ_BY_NAME(GPT(inst), ccmpb, irq), \
600 DT_IRQ_BY_NAME(GPT(inst), ccmpb, priority), gpt_capture_b_isr, NULL, \
601 0); \
602 IRQ_CONNECT(DT_IRQ_BY_NAME(GPT(inst), ovf, irq), \
603 DT_IRQ_BY_NAME(GPT(inst), ovf, priority), gpt_counter_overflow_isr, \
604 NULL, 0); \
605 } while (0)
606
607 #define PWM_RZG_INIT(inst) \
608 PINCTRL_DT_INST_DEFINE(inst); \
609 static gpt_instance_ctrl_t g_timer##inst##_ctrl; \
610 static gpt_extended_cfg_t g_timer##inst##_extend = { \
611 .gtioca = \
612 { \
613 .output_enabled = false, \
614 .stop_level = GPT_PIN_LEVEL_LOW, \
615 }, \
616 .gtiocb = \
617 { \
618 .output_enabled = false, \
619 .stop_level = GPT_PIN_LEVEL_LOW, \
620 }, \
621 .start_source = (gpt_source_t)(GPT_SOURCE_NONE), \
622 .stop_source = (gpt_source_t)(GPT_SOURCE_NONE), \
623 .clear_source = (gpt_source_t)(GPT_SOURCE_NONE), \
624 .count_up_source = (gpt_source_t)(GPT_SOURCE_NONE), \
625 .count_down_source = (gpt_source_t)(GPT_SOURCE_NONE), \
626 .capture_a_source = (gpt_source_t)(GPT_SOURCE_NONE), \
627 .capture_b_source = (gpt_source_t)(GPT_SOURCE_NONE), \
628 .capture_a_ipl = DT_IRQ_BY_NAME(GPT(inst), ccmpa, priority), \
629 .capture_b_ipl = DT_IRQ_BY_NAME(GPT(inst), ccmpb, priority), \
630 .capture_a_irq = DT_IRQ_BY_NAME(GPT(inst), ccmpa, irq), \
631 .capture_b_irq = DT_IRQ_BY_NAME(GPT(inst), ccmpb, irq), \
632 .capture_filter_gtioca = GPT_CAPTURE_FILTER_NONE, \
633 .capture_filter_gtiocb = GPT_CAPTURE_FILTER_NONE, \
634 .p_pwm_cfg = NULL, \
635 .gtior_setting.gtior = (0x0U), \
636 }; \
637 static timer_cfg_t g_timer##inst##_cfg = { \
638 .mode = TIMER_MODE_PWM, \
639 .channel = DT_PROP(GPT(inst), channel), \
640 .source_div = DT_ENUM_IDX(GPT(inst), prescaler), \
641 .cycle_end_ipl = DT_IRQ_BY_NAME(GPT(inst), ovf, priority), \
642 .cycle_end_irq = DT_IRQ_BY_NAME(GPT(inst), ovf, irq), \
643 .p_extend = &g_timer##inst##_extend, \
644 }; \
645 static const struct pwm_rz_gpt_config pwm_rz_gpt_config_##inst = { \
646 .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
647 .fsp_api = &g_timer_on_gpt, \
648 }; \
649 static struct pwm_rz_gpt_data pwm_rz_gpt_data_##inst = { \
650 .fsp_cfg = &g_timer##inst##_cfg, .fsp_ctrl = &g_timer##inst##_ctrl}; \
651 static int pwm_rz_gpt_init_##inst(const struct device *dev) \
652 { \
653 PWM_RZ_IRQ_CONFIG_INIT(inst); \
654 int err = pwm_rz_gpt_init(dev); \
655 if (err != 0) { \
656 return err; \
657 } \
658 return 0; \
659 } \
660 DEVICE_DT_INST_DEFINE(inst, pwm_rz_gpt_init_##inst, NULL, &pwm_rz_gpt_data_##inst, \
661 &pwm_rz_gpt_config_##inst, POST_KERNEL, CONFIG_PWM_INIT_PRIORITY, \
662 &pwm_rz_gpt_driver_api);
663
664 DT_INST_FOREACH_STATUS_OKAY(PWM_RZG_INIT);
665