1 /*
2  * Copyright (c) 2019 Christian Taedcke <hacking@taedcke.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT silabs_gecko_spi_usart
8 
9 #define LOG_LEVEL CONFIG_SPI_LOG_LEVEL
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_REGISTER(spi_gecko);
12 #include "spi_context.h"
13 
14 #include <zephyr/sys/sys_io.h>
15 #include <zephyr/device.h>
16 #include <zephyr/drivers/spi.h>
17 #include <zephyr/drivers/spi/rtio.h>
18 #include <soc.h>
19 
20 #include "em_cmu.h"
21 #include "em_usart.h"
22 
23 #include <stdbool.h>
24 
25 #ifdef CONFIG_PINCTRL
26 #include <zephyr/drivers/pinctrl.h>
27 #else
28 #ifndef CONFIG_SOC_GECKO_HAS_INDIVIDUAL_PIN_LOCATION
29 #error "Individual pin location support is required"
30 #endif
31 #endif /* CONFIG_PINCTRL */
32 
33 #ifdef CONFIG_CLOCK_CONTROL
34 #include <zephyr/drivers/clock_control.h>
35 #include <zephyr/drivers/clock_control/clock_control_silabs.h>
36 #define GET_GECKO_USART_CLOCK(idx)                            \
37 	.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(idx)), \
38 	.clock_cfg = SILABS_DT_INST_CLOCK_CFG(idx),
39 #elif DT_NODE_HAS_PROP(n, peripheral_id)
40 #define CLOCK_USART(id) _CONCAT(cmuClock_USART, id)
41 #define GET_GECKO_USART_CLOCK(n) \
42 	.clock = CLOCK_USART(DT_INST_PROP(n, peripheral_id)),
43 #else
44 #if (USART_COUNT == 1)
45 #define CLOCK_USART(ref)	(((ref) == USART0) ? cmuClock_USART0 \
46 			       : -1)
47 #elif (USART_COUNT == 2)
48 #define CLOCK_USART(ref)	(((ref) == USART0) ? cmuClock_USART0 \
49 			       : ((ref) == USART1) ? cmuClock_USART1 \
50 			       : -1)
51 #elif (USART_COUNT == 3)
52 #define CLOCK_USART(ref)	(((ref) == USART0) ? cmuClock_USART0 \
53 			       : ((ref) == USART1) ? cmuClock_USART1 \
54 			       : ((ref) == USART2) ? cmuClock_USART2 \
55 			       : -1)
56 #elif (USART_COUNT == 4)
57 #define CLOCK_USART(ref)	(((ref) == USART0) ? cmuClock_USART0 \
58 			       : ((ref) == USART1) ? cmuClock_USART1 \
59 			       : ((ref) == USART2) ? cmuClock_USART2 \
60 			       : ((ref) == USART3) ? cmuClock_USART3 \
61 			       : -1)
62 #elif (USART_COUNT == 5)
63 #define CLOCK_USART(ref)	(((ref) == USART0) ? cmuClock_USART0 \
64 			       : ((ref) == USART1) ? cmuClock_USART1 \
65 			       : ((ref) == USART2) ? cmuClock_USART2 \
66 			       : ((ref) == USART3) ? cmuClock_USART3 \
67 			       : ((ref) == USART4) ? cmuClock_USART4 \
68 			       : -1)
69 #elif (USART_COUNT == 6)
70 #define CLOCK_USART(ref)	(((ref) == USART0) ? cmuClock_USART0 \
71 			       : ((ref) == USART1) ? cmuClock_USART1 \
72 			       : ((ref) == USART2) ? cmuClock_USART2 \
73 			       : ((ref) == USART3) ? cmuClock_USART3 \
74 			       : ((ref) == USART4) ? cmuClock_USART4 \
75 			       : ((ref) == USART5) ? cmuClock_USART5 \
76 			       : -1)
77 #else
78 #error "Undefined number of USARTs."
79 #endif /* USART_COUNT */
80 #define GET_GECKO_USART_CLOCK(id) \
81 	.clock = CLOCK_USART((USART_TypeDef *)DT_INST_REG_ADDR(id)),
82 #endif /* DT_NODE_HAS_PROP(n, peripheral_id) */
83 
84 
85 #define SPI_WORD_SIZE 8
86 
87 /* Structure Declarations */
88 
89 struct spi_gecko_data {
90 	struct spi_context ctx;
91 };
92 
93 struct spi_gecko_config {
94 	USART_TypeDef *base;
95 #ifdef CONFIG_CLOCK_CONTROL
96 	const struct device *clock_dev;
97 	const struct silabs_clock_control_cmu_config clock_cfg;
98 #else
99 	CMU_Clock_TypeDef clock;
100 #endif
101 	uint32_t clock_frequency;
102 #ifdef CONFIG_PINCTRL
103 	const struct pinctrl_dev_config *pcfg;
104 #else
105 	struct soc_gpio_pin pin_rx;
106 	struct soc_gpio_pin pin_tx;
107 	struct soc_gpio_pin pin_clk;
108 	uint8_t loc_rx;
109 	uint8_t loc_tx;
110 	uint8_t loc_clk;
111 #endif /* CONFIG_PINCTRL */
112 };
113 
114 
115 /* Helper Functions */
spi_config(const struct device * dev,const struct spi_config * config,uint16_t * control)116 static int spi_config(const struct device *dev,
117 		      const struct spi_config *config,
118 		      uint16_t *control)
119 {
120 	const struct spi_gecko_config *gecko_config = dev->config;
121 	struct spi_gecko_data *data = dev->data;
122 	mem_addr_t ctrl_reg = (mem_addr_t)&gecko_config->base->CTRL;
123 	uint32_t spi_frequency;
124 
125 #ifdef CONFIG_CLOCK_CONTROL
126 	int err;
127 
128 	err = clock_control_get_rate(gecko_config->clock_dev,
129 				     (clock_control_subsys_t)&gecko_config->clock_cfg,
130 				     &spi_frequency);
131 	if (err) {
132 		return err;
133 	}
134 	/* Max supported SPI frequency is half the source clock */
135 	spi_frequency /= 2;
136 #else
137 	spi_frequency = CMU_ClockFreqGet(gecko_config->clock) / 2;
138 #endif
139 
140 	if (config->operation & SPI_HALF_DUPLEX) {
141 		LOG_ERR("Half-duplex not supported");
142 		return -ENOTSUP;
143 	}
144 
145 	if (SPI_WORD_SIZE_GET(config->operation) != SPI_WORD_SIZE) {
146 		LOG_ERR("Word size must be %d", SPI_WORD_SIZE);
147 		return -ENOTSUP;
148 	}
149 
150 	if (config->operation & SPI_CS_ACTIVE_HIGH) {
151 		sys_set_bit(ctrl_reg, _USART_CTRL_CSINV_SHIFT);
152 	} else {
153 		sys_clear_bit(ctrl_reg, _USART_CTRL_CSINV_SHIFT);
154 	}
155 
156 	if (IS_ENABLED(CONFIG_SPI_EXTENDED_MODES) &&
157 	    (config->operation & SPI_LINES_MASK) != SPI_LINES_SINGLE) {
158 		LOG_ERR("Only supports single mode");
159 		return -ENOTSUP;
160 	}
161 
162 	if (config->operation & SPI_TRANSFER_LSB) {
163 		sys_clear_bit(ctrl_reg, _USART_CTRL_MSBF_SHIFT);
164 	} else {
165 		sys_set_bit(ctrl_reg, _USART_CTRL_MSBF_SHIFT);
166 	}
167 
168 	if (config->operation & SPI_OP_MODE_SLAVE) {
169 		LOG_ERR("Slave mode not supported");
170 		return -ENOTSUP;
171 	}
172 
173 	/* Set frequency to the minimum of what the device supports, what the
174 	 * user has configured the controller to, and the max frequency for the
175 	 * transaction.
176 	 */
177 	if (gecko_config->clock_frequency > spi_frequency) {
178 		LOG_ERR("SPI clock-frequency too high");
179 		return -EINVAL;
180 	}
181 	spi_frequency = MIN(gecko_config->clock_frequency, spi_frequency);
182 	if (config->frequency) {
183 		spi_frequency = MIN(config->frequency, spi_frequency);
184 	}
185 	USART_BaudrateSyncSet(gecko_config->base, 0, spi_frequency);
186 
187 	/* Set Loopback */
188 	if (config->operation & SPI_MODE_LOOP) {
189 		gecko_config->base->CTRL |= USART_CTRL_LOOPBK;
190 	} else {
191 		gecko_config->base->CTRL &= ~USART_CTRL_LOOPBK;
192 	}
193 
194 	/* Set CPOL */
195 	if (config->operation & SPI_MODE_CPOL) {
196 		gecko_config->base->CTRL |= USART_CTRL_CLKPOL;
197 	} else {
198 		gecko_config->base->CTRL &= ~USART_CTRL_CLKPOL;
199 	}
200 
201 	/* Set CPHA */
202 	if (config->operation & SPI_MODE_CPHA) {
203 		gecko_config->base->CTRL |= USART_CTRL_CLKPHA;
204 	} else {
205 		gecko_config->base->CTRL &= ~USART_CTRL_CLKPHA;
206 	}
207 
208 	/* Set word size */
209 	gecko_config->base->FRAME = usartDatabits8
210 	    | USART_FRAME_STOPBITS_DEFAULT
211 	    | USART_FRAME_PARITY_DEFAULT;
212 
213 	/* At this point, it's mandatory to set this on the context! */
214 	data->ctx.config = config;
215 
216 	return 0;
217 }
218 
spi_gecko_send(USART_TypeDef * usart,uint8_t frame)219 static void spi_gecko_send(USART_TypeDef *usart, uint8_t frame)
220 {
221 	/* Write frame to register */
222 	USART_Tx(usart, frame);
223 
224 	/* Wait until the transfer ends */
225 	while (!(usart->STATUS & USART_STATUS_TXC)) {
226 	}
227 }
228 
spi_gecko_recv(USART_TypeDef * usart)229 static uint8_t spi_gecko_recv(USART_TypeDef *usart)
230 {
231 	/* Return data inside rx register */
232 	return (uint8_t)usart->RXDATA;
233 }
234 
spi_gecko_transfer_ongoing(struct spi_gecko_data * data)235 static bool spi_gecko_transfer_ongoing(struct spi_gecko_data *data)
236 {
237 	return spi_context_tx_on(&data->ctx) || spi_context_rx_on(&data->ctx);
238 }
239 
spi_gecko_next_tx(struct spi_gecko_data * data)240 static inline uint8_t spi_gecko_next_tx(struct spi_gecko_data *data)
241 {
242 	uint8_t tx_frame = 0;
243 
244 	if (spi_context_tx_buf_on(&data->ctx)) {
245 		tx_frame = UNALIGNED_GET((uint8_t *)(data->ctx.tx_buf));
246 	}
247 
248 	return tx_frame;
249 }
250 
spi_gecko_shift_frames(USART_TypeDef * usart,struct spi_gecko_data * data)251 static int spi_gecko_shift_frames(USART_TypeDef *usart,
252 				  struct spi_gecko_data *data)
253 {
254 	uint8_t tx_frame;
255 	uint8_t rx_frame;
256 
257 	tx_frame = spi_gecko_next_tx(data);
258 	spi_gecko_send(usart, tx_frame);
259 	spi_context_update_tx(&data->ctx, 1, 1);
260 
261 	rx_frame = spi_gecko_recv(usart);
262 
263 	if (spi_context_rx_buf_on(&data->ctx)) {
264 		UNALIGNED_PUT(rx_frame, (uint8_t *)data->ctx.rx_buf);
265 	}
266 	spi_context_update_rx(&data->ctx, 1, 1);
267 	return 0;
268 }
269 
270 
spi_gecko_xfer(const struct device * dev,const struct spi_config * config)271 static void spi_gecko_xfer(const struct device *dev,
272 			   const struct spi_config *config)
273 {
274 	int ret;
275 	struct spi_gecko_data *data = dev->data;
276 	struct spi_context *ctx = &data->ctx;
277 	const struct spi_gecko_config *gecko_config = dev->config;
278 
279 	spi_context_cs_control(ctx, true);
280 
281 	do {
282 		ret = spi_gecko_shift_frames(gecko_config->base, data);
283 	} while (!ret && spi_gecko_transfer_ongoing(data));
284 
285 	spi_context_cs_control(ctx, false);
286 	spi_context_complete(ctx, dev, 0);
287 }
288 
289 #ifndef CONFIG_PINCTRL
spi_gecko_init_pins(const struct device * dev)290 static void spi_gecko_init_pins(const struct device *dev)
291 {
292 	const struct spi_gecko_config *config = dev->config;
293 
294 	GPIO_PinModeSet(config->pin_rx.port, config->pin_rx.pin,
295 			 config->pin_rx.mode, config->pin_rx.out);
296 	GPIO_PinModeSet(config->pin_tx.port, config->pin_tx.pin,
297 			 config->pin_tx.mode, config->pin_tx.out);
298 	GPIO_PinModeSet(config->pin_clk.port, config->pin_clk.pin,
299 			 config->pin_clk.mode, config->pin_clk.out);
300 
301 	/* disable all pins while configuring */
302 	config->base->ROUTEPEN = 0;
303 
304 	config->base->ROUTELOC0 =
305 		(config->loc_tx << _USART_ROUTELOC0_TXLOC_SHIFT) |
306 		(config->loc_rx << _USART_ROUTELOC0_RXLOC_SHIFT) |
307 		(config->loc_clk << _USART_ROUTELOC0_CLKLOC_SHIFT);
308 
309 	config->base->ROUTELOC1 = _USART_ROUTELOC1_RESETVALUE;
310 
311 	config->base->ROUTEPEN = USART_ROUTEPEN_RXPEN | USART_ROUTEPEN_TXPEN |
312 		USART_ROUTEPEN_CLKPEN;
313 }
314 #endif /* !CONFIG_PINCTRL */
315 
316 
317 /* API Functions */
318 
spi_gecko_init(const struct device * dev)319 static int spi_gecko_init(const struct device *dev)
320 {
321 	int err;
322 	const struct spi_gecko_config *config = dev->config;
323 	struct spi_gecko_data *data = dev->data;
324 	USART_InitSync_TypeDef usartInit = USART_INITSYNC_DEFAULT;
325 
326 	/* The peripheral and gpio clock are already enabled from soc and gpio
327 	 * driver
328 	 */
329 
330 	usartInit.enable = usartDisable;
331 	usartInit.baudrate = 1000000;
332 	usartInit.databits = usartDatabits8;
333 	usartInit.master = 1;
334 	usartInit.msbf = 1;
335 	usartInit.clockMode = usartClockMode0;
336 #if defined(USART_INPUT_RXPRS) && defined(USART_TRIGCTRL_AUTOTXTEN)
337 	usartInit.prsRxEnable = 0;
338 	usartInit.prsRxCh = 0;
339 	usartInit.autoTx = 0;
340 #endif
341 
342 	/* Enable USART clock */
343 #ifdef CONFIG_CLOCK_CONTROL
344 	err = clock_control_on(config->clock_dev, (clock_control_subsys_t)&config->clock_cfg);
345 	if (err < 0) {
346 		return err;
347 	}
348 #else
349 	CMU_ClockEnable(config->clock, true);
350 #endif
351 
352 	/* Init USART */
353 	USART_InitSync(config->base, &usartInit);
354 
355 #ifdef CONFIG_PINCTRL
356 	err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
357 	if (err < 0) {
358 		return err;
359 	}
360 #else
361 	/* Initialize USART pins */
362 	spi_gecko_init_pins(dev);
363 #endif /* CONFIG_PINCTRL */
364 
365 	err = spi_context_cs_configure_all(&data->ctx);
366 	if (err < 0) {
367 		return err;
368 	}
369 
370 	/* Enable the peripheral */
371 	config->base->CMD = (uint32_t) usartEnable;
372 
373 	spi_context_unlock_unconditionally(&data->ctx);
374 
375 	return 0;
376 }
377 
spi_gecko_transceive(const struct device * dev,const struct spi_config * config,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs)378 static int spi_gecko_transceive(const struct device *dev,
379 				const struct spi_config *config,
380 				const struct spi_buf_set *tx_bufs,
381 				const struct spi_buf_set *rx_bufs)
382 {
383 	struct spi_gecko_data *data = dev->data;
384 	uint16_t control = 0;
385 	int ret;
386 
387 	spi_context_lock(&data->ctx, false, NULL, NULL, config);
388 
389 	ret = spi_config(dev, config, &control);
390 	if (ret < 0) {
391 		spi_context_release(&data->ctx, ret);
392 		return ret;
393 	}
394 
395 	spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1);
396 	spi_gecko_xfer(dev, config);
397 
398 	spi_context_release(&data->ctx, ret);
399 
400 	return 0;
401 }
402 
403 #ifdef CONFIG_SPI_ASYNC
spi_gecko_transceive_async(const struct device * dev,const struct spi_config * config,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs,struct k_poll_signal * async)404 static int spi_gecko_transceive_async(const struct device *dev,
405 				      const struct spi_config *config,
406 				      const struct spi_buf_set *tx_bufs,
407 				      const struct spi_buf_set *rx_bufs,
408 				      struct k_poll_signal *async)
409 {
410 	return -ENOTSUP;
411 }
412 #endif /* CONFIG_SPI_ASYNC */
413 
spi_gecko_release(const struct device * dev,const struct spi_config * config)414 static int spi_gecko_release(const struct device *dev,
415 			     const struct spi_config *config)
416 {
417 	struct spi_gecko_data *data = dev->data;
418 
419 	spi_context_unlock_unconditionally(&data->ctx);
420 
421 	return 0;
422 }
423 
424 /* Device Instantiation */
425 static DEVICE_API(spi, spi_gecko_api) = {
426 	.transceive = spi_gecko_transceive,
427 #ifdef CONFIG_SPI_ASYNC
428 	.transceive_async = spi_gecko_transceive_async,
429 #endif /* CONFIG_SPI_ASYNC */
430 #ifdef CONFIG_SPI_RTIO
431 	.iodev_submit = spi_rtio_iodev_default_submit,
432 #endif
433 	.release = spi_gecko_release,
434 };
435 
436 #ifdef CONFIG_PINCTRL
437 #define SPI_INIT(n)				    \
438 	PINCTRL_DT_INST_DEFINE(n);			    \
439 	static struct spi_gecko_data spi_gecko_data_##n = { \
440 		SPI_CONTEXT_INIT_LOCK(spi_gecko_data_##n, ctx), \
441 		SPI_CONTEXT_INIT_SYNC(spi_gecko_data_##n, ctx), \
442 		SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(n), ctx)	\
443 	}; \
444 	static struct spi_gecko_config spi_gecko_cfg_##n = { \
445 	    .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
446 	    .base = (USART_TypeDef *) \
447 		 DT_INST_REG_ADDR(n), \
448 	    GET_GECKO_USART_CLOCK(n) \
449 	    .clock_frequency = DT_INST_PROP_OR(n, clock_frequency, 1000000) \
450 	}; \
451 	SPI_DEVICE_DT_INST_DEFINE(n, \
452 			spi_gecko_init, \
453 			NULL, \
454 			&spi_gecko_data_##n, \
455 			&spi_gecko_cfg_##n, \
456 			POST_KERNEL, \
457 			CONFIG_SPI_INIT_PRIORITY, \
458 			&spi_gecko_api);
459 #else
460 #define SPI_INIT(n)				    \
461 	static struct spi_gecko_data spi_gecko_data_##n = { \
462 		SPI_CONTEXT_INIT_LOCK(spi_gecko_data_##n, ctx), \
463 		SPI_CONTEXT_INIT_SYNC(spi_gecko_data_##n, ctx), \
464 		SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(n), ctx)	\
465 	}; \
466 	static struct spi_gecko_config spi_gecko_cfg_##n = { \
467 	    .base = (USART_TypeDef *) \
468 		 DT_INST_REG_ADDR(n), \
469 	    GET_GECKO_USART_CLOCK(n) \
470 	    .clock_frequency = DT_INST_PROP_OR(n, clock_frequency, 1000000), \
471 	    .pin_rx = { DT_INST_PROP_BY_IDX(n, location_rx, 1), \
472 			DT_INST_PROP_BY_IDX(n, location_rx, 2), \
473 			gpioModeInput, 1},				\
474 	    .pin_tx = { DT_INST_PROP_BY_IDX(n, location_tx, 1), \
475 			DT_INST_PROP_BY_IDX(n, location_tx, 2), \
476 			gpioModePushPull, 1},				\
477 	    .pin_clk = { DT_INST_PROP_BY_IDX(n, location_clk, 1), \
478 			DT_INST_PROP_BY_IDX(n, location_clk, 2), \
479 			gpioModePushPull, 1},				\
480 	    .loc_rx = DT_INST_PROP_BY_IDX(n, location_rx, 0), \
481 	    .loc_tx = DT_INST_PROP_BY_IDX(n, location_tx, 0), \
482 	    .loc_clk = DT_INST_PROP_BY_IDX(n, location_clk, 0), \
483 	}; \
484 	SPI_DEVICE_DT_INST_DEFINE(n, \
485 			spi_gecko_init, \
486 			NULL, \
487 			&spi_gecko_data_##n, \
488 			&spi_gecko_cfg_##n, \
489 			POST_KERNEL, \
490 			CONFIG_SPI_INIT_PRIORITY, \
491 			&spi_gecko_api);
492 #endif /* CONFIG_PINCTRL */
493 
494 DT_INST_FOREACH_STATUS_OKAY(SPI_INIT)
495