1 /*
2  * Copyright (c) 2017 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nordic_nrf_sw_pwm
8 
9 #include <soc.h>
10 #include <zephyr/drivers/pwm.h>
11 #include <zephyr/dt-bindings/gpio/gpio.h>
12 #include <nrfx_gpiote.h>
13 #include <helpers/nrfx_gppi.h>
14 #include <hal/nrf_gpio.h>
15 #include <hal/nrf_rtc.h>
16 #include <hal/nrf_timer.h>
17 
18 #include <zephyr/logging/log.h>
19 
20 LOG_MODULE_REGISTER(pwm_nrf_sw, CONFIG_PWM_LOG_LEVEL);
21 
22 #define GENERATOR_NODE	DT_INST_PHANDLE(0, generator)
23 #define GENERATOR_CC_NUM	DT_PROP(GENERATOR_NODE, cc_num)
24 
25 #if DT_NODE_HAS_COMPAT(GENERATOR_NODE, nordic_nrf_rtc)
26 #define USE_RTC		1
27 #define GENERATOR_ADDR	((NRF_RTC_Type *) DT_REG_ADDR(GENERATOR_NODE))
28 #define GENERATOR_BITS	24
29 BUILD_ASSERT(DT_INST_PROP(0, clock_prescaler) == 0,
30 	     "Only clock-prescaler = <0> is supported when used with RTC");
31 #else
32 #define USE_RTC		0
33 #define GENERATOR_ADDR	((NRF_TIMER_Type *) DT_REG_ADDR(GENERATOR_NODE))
34 #define GENERATOR_BITS	DT_PROP(GENERATOR_NODE, max_bit_width)
35 #endif
36 
37 #define PWM_0_MAP_SIZE DT_INST_PROP_LEN(0, channel_gpios)
38 
39 /* One compare channel is needed to set the PWM period, hence +1. */
40 #if ((PWM_0_MAP_SIZE + 1) > GENERATOR_CC_NUM)
41 #error "Invalid number of PWM channels configured."
42 #endif
43 
44 #if defined(PPI_FEATURE_FORKS_PRESENT) || defined(DPPI_PRESENT)
45 #define PPI_FORK_AVAILABLE 1
46 #else
47 #define PPI_FORK_AVAILABLE 0
48 #endif
49 
50 /* When RTC is used, one more PPI task endpoint is required for clearing
51  * the counter, so when FORK feature is not available, one more PPI channel
52  * needs to be used.
53  */
54 #if USE_RTC && !PPI_FORK_AVAILABLE
55 #define PPI_PER_CH 3
56 #else
57 #define PPI_PER_CH 2
58 #endif
59 
60 struct pwm_config {
61 	union {
62 		NRF_RTC_Type *rtc;
63 		NRF_TIMER_Type *timer;
64 	};
65 	nrfx_gpiote_t gpiote[PWM_0_MAP_SIZE];
66 	uint8_t psel_ch[PWM_0_MAP_SIZE];
67 	uint8_t initially_inverted;
68 	uint8_t map_size;
69 	uint8_t prescaler;
70 };
71 
72 struct pwm_data {
73 	uint32_t period_cycles;
74 	uint32_t pulse_cycles[PWM_0_MAP_SIZE];
75 	uint8_t ppi_ch[PWM_0_MAP_SIZE][PPI_PER_CH];
76 	uint8_t gpiote_ch[PWM_0_MAP_SIZE];
77 };
78 
pwm_config_rtc(const struct pwm_config * config)79 static inline NRF_RTC_Type *pwm_config_rtc(const struct pwm_config *config)
80 {
81 #if USE_RTC
82 	return config->rtc;
83 #else
84 	return NULL;
85 #endif
86 }
87 
pwm_config_timer(const struct pwm_config * config)88 static inline NRF_TIMER_Type *pwm_config_timer(const struct pwm_config *config)
89 {
90 #if !USE_RTC
91 	return config->timer;
92 #else
93 	return NULL;
94 #endif
95 }
96 
pwm_period_check(struct pwm_data * data,uint8_t map_size,uint32_t channel,uint32_t period_cycles,uint32_t pulse_cycles)97 static uint32_t pwm_period_check(struct pwm_data *data, uint8_t map_size,
98 				 uint32_t channel, uint32_t period_cycles,
99 				 uint32_t pulse_cycles)
100 {
101 	uint8_t i;
102 
103 	/* allow 0% and 100% duty cycle, as it does not use PWM. */
104 	if ((pulse_cycles == 0U) || (pulse_cycles == period_cycles)) {
105 		return 0;
106 	}
107 
108 	/* fail if requested period does not match already running period */
109 	for (i = 0U; i < map_size; i++) {
110 		if ((i != channel) &&
111 		    (data->pulse_cycles[i] != 0U) &&
112 		    (period_cycles != data->period_cycles)) {
113 			return -EINVAL;
114 		}
115 	}
116 
117 	return 0;
118 }
119 
pwm_nrf_sw_set_cycles(const struct device * dev,uint32_t channel,uint32_t period_cycles,uint32_t pulse_cycles,pwm_flags_t flags)120 static int pwm_nrf_sw_set_cycles(const struct device *dev, uint32_t channel,
121 				 uint32_t period_cycles, uint32_t pulse_cycles,
122 				 pwm_flags_t flags)
123 {
124 	const struct pwm_config *config = dev->config;
125 	NRF_TIMER_Type *timer = pwm_config_timer(config);
126 	NRF_RTC_Type *rtc = pwm_config_rtc(config);
127 	NRF_GPIOTE_Type *gpiote;
128 	struct pwm_data *data = dev->data;
129 	uint32_t ppi_mask;
130 	uint8_t active_level;
131 	uint8_t psel_ch;
132 	uint8_t gpiote_ch;
133 	const uint8_t *ppi_chs;
134 	int ret;
135 
136 	if (channel >= config->map_size) {
137 		LOG_ERR("Invalid channel: %u.", channel);
138 		return -EINVAL;
139 	}
140 
141 	/* check if requested period is allowed while other channels are
142 	 * active.
143 	 */
144 	ret = pwm_period_check(data, config->map_size, channel, period_cycles,
145 			       pulse_cycles);
146 	if (ret) {
147 		LOG_ERR("Incompatible period");
148 		return ret;
149 	}
150 
151 	if (USE_RTC) {
152 		/* pulse_cycles - 1 is written to 24-bit CC */
153 		if (period_cycles > BIT_MASK(24) + 1) {
154 			LOG_ERR("Too long period (%u)!", period_cycles);
155 			return -EINVAL;
156 		}
157 	} else {
158 		if (GENERATOR_BITS < 32 &&
159 		    period_cycles > BIT_MASK(GENERATOR_BITS)) {
160 			LOG_ERR("Too long period (%u), adjust PWM prescaler!",
161 				period_cycles);
162 			return -EINVAL;
163 		}
164 	}
165 
166 	gpiote = config->gpiote[channel].p_reg;
167 	psel_ch = config->psel_ch[channel];
168 	gpiote_ch = data->gpiote_ch[channel];
169 	ppi_chs = data->ppi_ch[channel];
170 
171 	LOG_DBG("channel %u, period %u, pulse %u",
172 		channel, period_cycles, pulse_cycles);
173 
174 	/* clear PPI used */
175 	ppi_mask = BIT(ppi_chs[0]) | BIT(ppi_chs[1]) |
176 		   (PPI_PER_CH > 2 ? BIT(ppi_chs[2]) : 0);
177 	nrfx_gppi_channels_disable(ppi_mask);
178 
179 	active_level = (flags & PWM_POLARITY_INVERTED) ? 0 : 1;
180 
181 	/*
182 	 * If the duty cycle is 0% or 100%, there is no need to generate
183 	 * the PWM signal, just	keep the output pin in inactive or active
184 	 * state, respectively.
185 	 */
186 	if (pulse_cycles == 0 || pulse_cycles == period_cycles) {
187 		nrf_gpio_pin_write(psel_ch,
188 			pulse_cycles == 0 ? !active_level
189 					  :  active_level);
190 
191 		/* clear GPIOTE config */
192 		nrf_gpiote_te_default(gpiote, gpiote_ch);
193 
194 		/* No PWM generation for this channel. */
195 		data->pulse_cycles[channel] = 0U;
196 
197 		/* Check if PWM signal is generated on any channel. */
198 		for (uint8_t i = 0; i < config->map_size; i++) {
199 			if (data->pulse_cycles[i]) {
200 				return 0;
201 			}
202 		}
203 
204 		/* No PWM generation needed, stop the timer. */
205 		if (USE_RTC) {
206 			nrf_rtc_task_trigger(rtc, NRF_RTC_TASK_STOP);
207 		} else {
208 			nrf_timer_task_trigger(timer, NRF_TIMER_TASK_STOP);
209 		}
210 
211 		return 0;
212 	}
213 
214 	/* configure RTC / TIMER */
215 	if (USE_RTC) {
216 		nrf_rtc_event_clear(rtc,
217 			nrf_rtc_compare_event_get(1 + channel));
218 		nrf_rtc_event_clear(rtc,
219 			nrf_rtc_compare_event_get(0));
220 
221 		/*
222 		 * '- 1' adjusts pulse and period cycles to the fact that CLEAR
223 		 * task event is generated always one LFCLK cycle after period
224 		 * COMPARE value is reached.
225 		 */
226 		nrf_rtc_cc_set(rtc, 1 + channel, pulse_cycles - 1);
227 		nrf_rtc_cc_set(rtc, 0, period_cycles - 1);
228 		nrf_rtc_task_trigger(rtc, NRF_RTC_TASK_CLEAR);
229 	} else {
230 		nrf_timer_event_clear(timer,
231 			nrf_timer_compare_event_get(1 + channel));
232 		nrf_timer_event_clear(timer,
233 			nrf_timer_compare_event_get(0));
234 
235 		nrf_timer_cc_set(timer, 1 + channel, pulse_cycles);
236 		nrf_timer_cc_set(timer, 0, period_cycles);
237 		nrf_timer_task_trigger(timer, NRF_TIMER_TASK_CLEAR);
238 	}
239 
240 	/* Configure GPIOTE - toggle task with proper initial output value. */
241 	gpiote->CONFIG[gpiote_ch] =
242 		(GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) |
243 		((uint32_t)psel_ch << 8) |
244 		(GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos) |
245 		((uint32_t)active_level << GPIOTE_CONFIG_OUTINIT_Pos);
246 
247 	/* setup PPI */
248 	uint32_t pulse_end_event_address, period_end_event_address;
249 	nrf_gpiote_task_t pulse_end_task, period_end_task;
250 #if defined(GPIOTE_FEATURE_SET_PRESENT) && defined(GPIOTE_FEATURE_CLR_PRESENT)
251 	if (active_level == 0) {
252 		pulse_end_task  = nrf_gpiote_set_task_get(gpiote_ch);
253 		period_end_task = nrf_gpiote_clr_task_get(gpiote_ch);
254 	} else {
255 		pulse_end_task  = nrf_gpiote_clr_task_get(gpiote_ch);
256 		period_end_task = nrf_gpiote_set_task_get(gpiote_ch);
257 	}
258 #else
259 	pulse_end_task = period_end_task = nrf_gpiote_out_task_get(gpiote_ch);
260 #endif
261 	uint32_t pulse_end_task_address =
262 		nrf_gpiote_task_address_get(gpiote, pulse_end_task);
263 	uint32_t period_end_task_address =
264 		nrf_gpiote_task_address_get(gpiote, period_end_task);
265 
266 	if (USE_RTC) {
267 		uint32_t clear_task_address =
268 			nrf_rtc_event_address_get(rtc, NRF_RTC_TASK_CLEAR);
269 
270 		pulse_end_event_address =
271 			nrf_rtc_event_address_get(rtc,
272 				nrf_rtc_compare_event_get(1 + channel));
273 		period_end_event_address =
274 			nrf_rtc_event_address_get(rtc,
275 				nrf_rtc_compare_event_get(0));
276 
277 #if PPI_FORK_AVAILABLE
278 		nrfx_gppi_fork_endpoint_setup(ppi_chs[1],
279 					      clear_task_address);
280 #else
281 		nrfx_gppi_channel_endpoints_setup(ppi_chs[2],
282 						  period_end_event_address,
283 						  clear_task_address);
284 #endif
285 	} else {
286 		pulse_end_event_address =
287 			nrf_timer_event_address_get(timer,
288 				nrf_timer_compare_event_get(1 + channel));
289 		period_end_event_address =
290 			nrf_timer_event_address_get(timer,
291 				nrf_timer_compare_event_get(0));
292 	}
293 
294 	nrfx_gppi_channel_endpoints_setup(ppi_chs[0],
295 					  pulse_end_event_address,
296 					  pulse_end_task_address);
297 	nrfx_gppi_channel_endpoints_setup(ppi_chs[1],
298 					  period_end_event_address,
299 					  period_end_task_address);
300 	nrfx_gppi_channels_enable(ppi_mask);
301 
302 	/* start timer, hence PWM */
303 	if (USE_RTC) {
304 		nrf_rtc_task_trigger(rtc, NRF_RTC_TASK_START);
305 	} else {
306 		nrf_timer_task_trigger(timer, NRF_TIMER_TASK_START);
307 	}
308 
309 	/* store the period and pulse cycles */
310 	data->period_cycles = period_cycles;
311 	data->pulse_cycles[channel] = pulse_cycles;
312 
313 	return 0;
314 }
315 
pwm_nrf_sw_get_cycles_per_sec(const struct device * dev,uint32_t channel,uint64_t * cycles)316 static int pwm_nrf_sw_get_cycles_per_sec(const struct device *dev,
317 					 uint32_t channel, uint64_t *cycles)
318 {
319 	const struct pwm_config *config = dev->config;
320 
321 	if (USE_RTC) {
322 		/*
323 		 * RTC frequency is derived from 32768Hz source without any
324 		 * prescaler
325 		 */
326 		*cycles = 32768UL;
327 	} else {
328 		/*
329 		 * HF timer frequency is derived from 16MHz source with a
330 		 * prescaler
331 		 */
332 		*cycles = 16000000UL / BIT(config->prescaler);
333 	}
334 
335 	return 0;
336 }
337 
338 static const struct pwm_driver_api pwm_nrf_sw_drv_api_funcs = {
339 	.set_cycles = pwm_nrf_sw_set_cycles,
340 	.get_cycles_per_sec = pwm_nrf_sw_get_cycles_per_sec,
341 };
342 
pwm_nrf_sw_init(const struct device * dev)343 static int pwm_nrf_sw_init(const struct device *dev)
344 {
345 	const struct pwm_config *config = dev->config;
346 	struct pwm_data *data = dev->data;
347 	NRF_TIMER_Type *timer = pwm_config_timer(config);
348 	NRF_RTC_Type *rtc = pwm_config_rtc(config);
349 
350 	for (uint32_t i = 0; i < config->map_size; i++) {
351 		nrfx_err_t err;
352 
353 		/* Allocate resources. */
354 		for (uint32_t j = 0; j < PPI_PER_CH; j++) {
355 			err = nrfx_gppi_channel_alloc(&data->ppi_ch[i][j]);
356 			if (err != NRFX_SUCCESS) {
357 				/* Do not free allocated resource. It is a fatal condition,
358 				 * system requires reconfiguration.
359 				 */
360 				LOG_ERR("Failed to allocate PPI channel");
361 				return -ENOMEM;
362 			}
363 		}
364 
365 		err = nrfx_gpiote_channel_alloc(&config->gpiote[i],
366 						&data->gpiote_ch[i]);
367 		if (err != NRFX_SUCCESS) {
368 			/* Do not free allocated resource. It is a fatal condition,
369 			 * system requires reconfiguration.
370 			 */
371 			LOG_ERR("Failed to allocate GPIOTE channel");
372 			return -ENOMEM;
373 		}
374 
375 		/* Set initial state of the output pins. */
376 		nrf_gpio_pin_write(config->psel_ch[i],
377 			(config->initially_inverted & BIT(i)) ? 1 : 0);
378 		nrf_gpio_cfg_output(config->psel_ch[i]);
379 	}
380 
381 	if (USE_RTC) {
382 		/* setup RTC */
383 		nrf_rtc_prescaler_set(rtc, 0);
384 		nrf_rtc_event_enable(rtc, NRF_RTC_INT_COMPARE0_MASK |
385 					  NRF_RTC_INT_COMPARE1_MASK |
386 					  NRF_RTC_INT_COMPARE2_MASK |
387 					  NRF_RTC_INT_COMPARE3_MASK);
388 	} else {
389 		/* setup HF timer */
390 		nrf_timer_mode_set(timer, NRF_TIMER_MODE_TIMER);
391 		nrf_timer_prescaler_set(timer, config->prescaler);
392 		nrf_timer_bit_width_set(timer,
393 			GENERATOR_BITS == 32 ? NRF_TIMER_BIT_WIDTH_32
394 					     : NRF_TIMER_BIT_WIDTH_16);
395 		nrf_timer_shorts_enable(timer,
396 			NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK);
397 	}
398 
399 	return 0;
400 }
401 
402 #define PSEL_AND_COMMA(_node_id, _prop, _idx) \
403 	NRF_DT_GPIOS_TO_PSEL_BY_IDX(_node_id, _prop, _idx),
404 
405 #define ACTIVE_LOW_BITS(_node_id, _prop, _idx) \
406 	((DT_GPIO_FLAGS_BY_IDX(_node_id, _prop, _idx) & GPIO_ACTIVE_LOW) \
407 	 ? BIT(_idx) : 0) |
408 
409 #define GPIOTE_AND_COMMA(_node_id, _prop, _idx) \
410 	NRFX_GPIOTE_INSTANCE(NRF_DT_GPIOTE_INST_BY_IDX(_node_id, _prop, _idx)),
411 
412 static const struct pwm_config pwm_nrf_sw_0_config = {
413 	COND_CODE_1(USE_RTC, (.rtc), (.timer)) = GENERATOR_ADDR,
414 	.gpiote = {
415 		DT_INST_FOREACH_PROP_ELEM(0, channel_gpios, GPIOTE_AND_COMMA)
416 	},
417 	.psel_ch = {
418 		DT_INST_FOREACH_PROP_ELEM(0, channel_gpios, PSEL_AND_COMMA)
419 	},
420 	.initially_inverted =
421 		DT_INST_FOREACH_PROP_ELEM(0, channel_gpios, ACTIVE_LOW_BITS) 0,
422 	.map_size = PWM_0_MAP_SIZE,
423 	.prescaler = DT_INST_PROP(0, clock_prescaler),
424 };
425 
426 static struct pwm_data pwm_nrf_sw_0_data;
427 
428 DEVICE_DT_INST_DEFINE(0,
429 		    pwm_nrf_sw_init,
430 		    NULL,
431 		    &pwm_nrf_sw_0_data,
432 		    &pwm_nrf_sw_0_config,
433 		    POST_KERNEL,
434 		    CONFIG_PWM_INIT_PRIORITY,
435 		    &pwm_nrf_sw_drv_api_funcs);
436