1 /*
2  * Copyright (c) 2023 Stephen Boylan <stephen.boylan@beechwoods.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT raspberrypi_pico_spi_pio
8 
9 #define LOG_LEVEL CONFIG_SPI_LOG_LEVEL
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_REGISTER(spi_pico_pio);
12 
13 #include <zephyr/sys/util.h>
14 #include <zephyr/sys/sys_io.h>
15 #include <zephyr/sys/byteorder.h>
16 #include <zephyr/drivers/clock_control.h>
17 #include <zephyr/drivers/spi.h>
18 #include <zephyr/drivers/pinctrl.h>
19 #include "spi_context.h"
20 
21 #include <zephyr/drivers/misc/pio_rpi_pico/pio_rpi_pico.h>
22 
23 #include <hardware/pio.h>
24 #include "hardware/clocks.h"
25 
26 #define SPI_RPI_PICO_PIO_HALF_DUPLEX_ENABLED DT_ANY_INST_HAS_PROP_STATUS_OKAY(sio_gpios)
27 
28 #define PIO_CYCLES     (4)
29 #define PIO_FIFO_DEPTH (4)
30 
31 struct spi_pico_pio_config {
32 	const struct device *piodev;
33 	const struct pinctrl_dev_config *pin_cfg;
34 	struct gpio_dt_spec clk_gpio;
35 	struct gpio_dt_spec mosi_gpio;
36 	struct gpio_dt_spec miso_gpio;
37 	struct gpio_dt_spec sio_gpio;
38 	const struct device *clk_dev;
39 	clock_control_subsys_t clk_id;
40 };
41 
42 struct spi_pico_pio_data {
43 	struct spi_context spi_ctx;
44 	uint32_t tx_count;
45 	uint32_t rx_count;
46 	PIO pio;
47 	size_t pio_sm;
48 	uint32_t pio_tx_offset;
49 	uint32_t pio_rx_offset;
50 	uint32_t pio_rx_wrap_target;
51 	uint32_t pio_rx_wrap;
52 	uint32_t bits;
53 	uint32_t dfs;
54 };
55 
56 /* ------------ */
57 /* spi_mode_0_0 */
58 /* ------------ */
59 
60 #define SPI_MODE_0_0_WRAP_TARGET 0
61 #define SPI_MODE_0_0_WRAP        1
62 #define SPI_MODE_0_0_CYCLES      4
63 
64 RPI_PICO_PIO_DEFINE_PROGRAM(spi_mode_0_0, SPI_MODE_0_0_WRAP_TARGET, SPI_MODE_0_0_WRAP,
65 			    /*     .wrap_target */
66 			    0x6101, /*  0: out    pins, 1         side 0 [1] */
67 			    0x5101, /*  1: in     pins, 1         side 1 [1] */
68 				    /*     .wrap */
69 );
70 
71 /* ------------ */
72 /* spi_mode_1_1 */
73 /* ------------ */
74 
75 #define SPI_MODE_1_1_WRAP_TARGET 0
76 #define SPI_MODE_1_1_WRAP        2
77 #define SPI_MODE_1_1_CYCLES      4
78 
79 RPI_PICO_PIO_DEFINE_PROGRAM(spi_mode_1_1, SPI_MODE_1_1_WRAP_TARGET, SPI_MODE_1_1_WRAP,
80 			    /*     .wrap_target */
81 			    0x7021, /*  0: out    x, 1            side 1 */
82 			    0xa101, /*  1: mov    pins, x         side 0 [1] */
83 			    0x5001, /*  2: in     pins, 1         side 1 */
84 				    /*     .wrap */
85 );
86 
87 #if SPI_RPI_PICO_PIO_HALF_DUPLEX_ENABLED
88 /* ------------------- */
89 /* spi_sio_mode_0_0_tx */
90 /* ------------------- */
91 
92 #define SPI_SIO_MODE_0_0_TX_WRAP_TARGET 0
93 #define SPI_SIO_MODE_0_0_TX_WRAP        2
94 #define SPI_SIO_MODE_0_0_TX_CYCLES      2
95 
96 RPI_PICO_PIO_DEFINE_PROGRAM(spi_sio_mode_0_0_tx, SPI_SIO_MODE_0_0_TX_WRAP_TARGET,
97 			    SPI_SIO_MODE_0_0_TX_WRAP,
98 			    /*     .wrap_target */
99 			    0x80a0, /*  0: pull   block           side 0  */
100 			    0x6001, /*  1: out    pins, 1         side 0  */
101 			    0x10e1, /*  2: jmp    !osre, 1        side 1  */
102 				    /*     .wrap */
103 );
104 
105 /* ------------------------- */
106 /* spi_sio_mode_0_0_rx */
107 /* ------------------------- */
108 
109 #define SPI_SIO_MODE_0_0_RX_WRAP_TARGET 0
110 #define SPI_SIO_MODE_0_0_RX_WRAP        3
111 #define SPI_SIO_MODE_0_0_RX_CYCLES      2
112 
113 RPI_PICO_PIO_DEFINE_PROGRAM(spi_sio_mode_0_0_rx, SPI_SIO_MODE_0_0_RX_WRAP_TARGET,
114 			    SPI_SIO_MODE_0_0_RX_WRAP,
115 			    /*     .wrap_target */
116 			    0x80a0, /*  0: pull   block           side 0 */
117 			    0x6020, /*  1: out    x, 32           side 0 */
118 			    0x5001, /*  2: in     pins, 1         side 1 */
119 			    0x0042, /*  3: jmp    x--, 2          side 0 */
120 				    /*     .wrap */
121 );
122 #endif /* SPI_RPI_PICO_PIO_HALF_DUPLEX_ENABLED */
123 
spi_pico_pio_clock_divisor(const uint32_t clock_freq,int cycles,uint32_t spi_frequency)124 static float spi_pico_pio_clock_divisor(const uint32_t clock_freq, int cycles,
125 					uint32_t spi_frequency)
126 {
127 	return (float)clock_freq / (float)(cycles * spi_frequency);
128 }
129 
spi_pico_pio_maximum_clock_frequency(const uint32_t clock_freq,int cycles)130 static uint32_t spi_pico_pio_maximum_clock_frequency(const uint32_t clock_freq, int cycles)
131 {
132 	return clock_freq / cycles;
133 }
134 
spi_pico_pio_minimum_clock_frequency(const uint32_t clock_freq,int cycles)135 static uint32_t spi_pico_pio_minimum_clock_frequency(const uint32_t clock_freq, int cycles)
136 {
137 	return clock_freq / (cycles * 65536);
138 }
139 
spi_pico_pio_transfer_ongoing(struct spi_pico_pio_data * data)140 static inline bool spi_pico_pio_transfer_ongoing(struct spi_pico_pio_data *data)
141 {
142 	return spi_context_tx_on(&data->spi_ctx) || spi_context_rx_on(&data->spi_ctx);
143 }
144 
spi_pico_pio_sm_put8(PIO pio,uint sm,uint8_t data)145 static inline void spi_pico_pio_sm_put8(PIO pio, uint sm, uint8_t data)
146 {
147 	/* Do 8 bit accesses on FIFO, so that write data is byte-replicated. This */
148 	/* gets us the left-justification for free (for MSB-first shift-out) */
149 	io_rw_8 *txfifo = (io_rw_8 *)&pio->txf[sm];
150 
151 	*txfifo = data;
152 }
153 
spi_pico_pio_sm_get8(PIO pio,uint sm)154 static inline uint8_t spi_pico_pio_sm_get8(PIO pio, uint sm)
155 {
156 	/* Do 8 bit accesses on FIFO, so that write data is byte-replicated. This */
157 	/* gets us the left-justification for free (for MSB-first shift-out) */
158 	io_rw_8 *rxfifo = (io_rw_8 *)&pio->rxf[sm];
159 
160 	return *rxfifo;
161 }
162 
spi_pico_pio_sm_put16(PIO pio,uint sm,uint16_t data)163 static inline void spi_pico_pio_sm_put16(PIO pio, uint sm, uint16_t data)
164 {
165 	/* Do 16 bit accesses on FIFO, so that write data is halfword-replicated. This */
166 	/* gets us the left-justification for free (for MSB-first shift-out) */
167 	io_rw_16 *txfifo = (io_rw_16 *)&pio->txf[sm];
168 
169 	*txfifo = data;
170 }
171 
spi_pico_pio_sm_get16(PIO pio,uint sm)172 static inline uint16_t spi_pico_pio_sm_get16(PIO pio, uint sm)
173 {
174 	io_rw_16 *rxfifo = (io_rw_16 *)&pio->rxf[sm];
175 
176 	return *rxfifo;
177 }
178 
spi_pico_pio_sm_put32(PIO pio,uint sm,uint32_t data)179 static inline void spi_pico_pio_sm_put32(PIO pio, uint sm, uint32_t data)
180 {
181 	io_rw_32 *txfifo = (io_rw_32 *)&pio->txf[sm];
182 
183 	*txfifo = data;
184 }
185 
spi_pico_pio_sm_get32(PIO pio,uint sm)186 static inline uint32_t spi_pico_pio_sm_get32(PIO pio, uint sm)
187 {
188 	io_rw_32 *rxfifo = (io_rw_32 *)&pio->rxf[sm];
189 
190 	return *rxfifo;
191 }
192 
spi_pico_pio_sm_complete(struct spi_pico_pio_data * data)193 static inline int spi_pico_pio_sm_complete(struct spi_pico_pio_data *data)
194 {
195 	return ((data->pio->sm[data->pio_sm].addr == data->pio_tx_offset) &&
196 		pio_sm_is_tx_fifo_empty(data->pio, data->pio_sm));
197 }
198 
spi_pico_pio_configure(const struct spi_pico_pio_config * dev_cfg,struct spi_pico_pio_data * data,const struct spi_config * spi_cfg)199 static int spi_pico_pio_configure(const struct spi_pico_pio_config *dev_cfg,
200 				  struct spi_pico_pio_data *data, const struct spi_config *spi_cfg)
201 {
202 	const struct gpio_dt_spec *clk = NULL;
203 	pio_sm_config sm_config;
204 	bool lsb = false;
205 	uint32_t cpol = 0;
206 	uint32_t cpha = 0;
207 	uint32_t rc = 0;
208 	uint32_t clock_freq;
209 
210 	rc = clock_control_on(dev_cfg->clk_dev, dev_cfg->clk_id);
211 	if (rc < 0) {
212 		LOG_ERR("Failed to enable the clock");
213 		return rc;
214 	}
215 
216 	rc = clock_control_get_rate(dev_cfg->clk_dev, dev_cfg->clk_id, &clock_freq);
217 	if (rc < 0) {
218 		LOG_ERR("Failed to get clock frequency");
219 		return rc;
220 	}
221 
222 	if (spi_context_configured(&data->spi_ctx, spi_cfg)) {
223 		return 0;
224 	}
225 
226 	if (spi_cfg->operation & SPI_OP_MODE_SLAVE) {
227 		LOG_ERR("Slave mode not supported");
228 		return -ENOTSUP;
229 	}
230 
231 	/* Note that SPI_TRANSFER_LSB controls the direction of shift, not the */
232 	/* "endianness" of the data.  In MSB mode, the high-order bit of the   */
233 	/* most significant byte is sent first;  in LSB mode, the low-order    */
234 	/* bit of the least-significant byte is sent first.                    */
235 	if (spi_cfg->operation & SPI_TRANSFER_LSB) {
236 		lsb = true;
237 	}
238 
239 #if defined(CONFIG_SPI_EXTENDED_MODES)
240 	if (spi_cfg->operation & (SPI_LINES_DUAL | SPI_LINES_QUAD | SPI_LINES_OCTAL)) {
241 		LOG_ERR("Unsupported configuration");
242 		return -ENOTSUP;
243 	}
244 #endif /* CONFIG_SPI_EXTENDED_MODES */
245 
246 	data->bits = SPI_WORD_SIZE_GET(spi_cfg->operation);
247 
248 	if ((data->bits != 8) && (data->bits != 16) && (data->bits != 32)) {
249 		LOG_ERR("Only 8, 16, and 32 bit word sizes are supported");
250 		return -ENOTSUP;
251 	}
252 
253 	data->dfs = ((data->bits - 1) / 8) + 1;
254 
255 	if (spi_cfg->operation & SPI_CS_ACTIVE_HIGH) {
256 		gpio_set_outover(data->spi_ctx.config->cs.gpio.pin, GPIO_OVERRIDE_INVERT);
257 	}
258 
259 	if (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPOL) {
260 		cpol = 1;
261 	}
262 	if (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPHA) {
263 		cpha = 1;
264 	}
265 	if (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_LOOP) {
266 		LOG_ERR("Loopback not supported");
267 		return -ENOTSUP;
268 	}
269 
270 #if SPI_RPI_PICO_PIO_HALF_DUPLEX_ENABLED
271 	if (spi_cfg->operation & SPI_HALF_DUPLEX) {
272 		if ((cpol != 0) || (cpha != 0)) {
273 			LOG_ERR("Only mode (0, 0) supported in 3-wire SIO");
274 			return -ENOTSUP;
275 		}
276 
277 		if ((spi_cfg->frequency > spi_pico_pio_maximum_clock_frequency(
278 						  clock_freq, SPI_SIO_MODE_0_0_TX_CYCLES)) ||
279 		    (spi_cfg->frequency < spi_pico_pio_minimum_clock_frequency(
280 						  clock_freq, SPI_SIO_MODE_0_0_TX_CYCLES))) {
281 			LOG_ERR("clock-frequency out of range");
282 			return -EINVAL;
283 		}
284 	} else if (dev_cfg->sio_gpio.port) {
285 		LOG_ERR("SPI_HALF_DUPLEX operation needed for sio-gpios");
286 		return -EINVAL;
287 	}
288 #else
289 	if (spi_cfg->operation & SPI_HALF_DUPLEX) {
290 		LOG_ERR("No sio-gpios defined, half-duplex not enabled");
291 		return -EINVAL;
292 	}
293 #endif /* SPI_RPI_PICO_PIO_HALF_DUPLEX_ENABLED */
294 
295 	clk = &dev_cfg->clk_gpio;
296 	data->pio = pio_rpi_pico_get_pio(dev_cfg->piodev);
297 	rc = pio_rpi_pico_allocate_sm(dev_cfg->piodev, &data->pio_sm);
298 	if (rc < 0) {
299 		return rc;
300 	}
301 
302 	if (dev_cfg->sio_gpio.port) {
303 #if SPI_RPI_PICO_PIO_HALF_DUPLEX_ENABLED
304 		const struct gpio_dt_spec *sio = &dev_cfg->sio_gpio;
305 
306 		float clock_div = spi_pico_pio_clock_divisor(clock_freq, SPI_SIO_MODE_0_0_TX_CYCLES,
307 							     spi_cfg->frequency);
308 
309 		data->pio_tx_offset =
310 			pio_add_program(data->pio, RPI_PICO_PIO_GET_PROGRAM(spi_sio_mode_0_0_tx));
311 
312 		data->pio_rx_offset =
313 			pio_add_program(data->pio, RPI_PICO_PIO_GET_PROGRAM(spi_sio_mode_0_0_rx));
314 		data->pio_rx_wrap_target =
315 			data->pio_rx_offset + RPI_PICO_PIO_GET_WRAP_TARGET(spi_sio_mode_0_0_rx);
316 		data->pio_rx_wrap =
317 			data->pio_rx_offset + RPI_PICO_PIO_GET_WRAP(spi_sio_mode_0_0_rx);
318 
319 		sm_config = pio_get_default_sm_config();
320 
321 		sm_config_set_clkdiv(&sm_config, clock_div);
322 		sm_config_set_in_pins(&sm_config, sio->pin);
323 		sm_config_set_in_shift(&sm_config, lsb, true, data->bits);
324 		sm_config_set_out_pins(&sm_config, sio->pin, 1);
325 		sm_config_set_out_shift(&sm_config, lsb, false, data->bits);
326 		hw_set_bits(&data->pio->input_sync_bypass, 1u << sio->pin);
327 
328 		sm_config_set_sideset_pins(&sm_config, clk->pin);
329 		sm_config_set_sideset(&sm_config, 1, false, false);
330 		sm_config_set_wrap(
331 			&sm_config,
332 			data->pio_tx_offset + RPI_PICO_PIO_GET_WRAP_TARGET(spi_sio_mode_0_0_tx),
333 			data->pio_tx_offset + RPI_PICO_PIO_GET_WRAP(spi_sio_mode_0_0_tx));
334 
335 		pio_sm_set_pindirs_with_mask(data->pio, data->pio_sm,
336 					     (BIT(clk->pin) | BIT(sio->pin)),
337 					     (BIT(clk->pin) | BIT(sio->pin)));
338 		pio_sm_set_pins_with_mask(data->pio, data->pio_sm, 0,
339 					  BIT(clk->pin) | BIT(sio->pin));
340 		pio_gpio_init(data->pio, sio->pin);
341 		pio_gpio_init(data->pio, clk->pin);
342 
343 		pio_sm_init(data->pio, data->pio_sm, data->pio_tx_offset, &sm_config);
344 		pio_sm_set_enabled(data->pio, data->pio_sm, true);
345 #else
346 		LOG_ERR("SIO pin requires half-duplex support");
347 		return -EINVAL;
348 #endif /* SPI_RPI_PICO_PIO_HALF_DUPLEX_ENABLED */
349 	} else {
350 		/* 4-wire mode */
351 		const struct gpio_dt_spec *miso = miso = &dev_cfg->miso_gpio;
352 		const struct gpio_dt_spec *mosi = &dev_cfg->mosi_gpio;
353 		const pio_program_t *program;
354 		uint32_t wrap_target;
355 		uint32_t wrap;
356 		int cycles;
357 
358 		if ((cpol == 0) && (cpha == 0)) {
359 			program = RPI_PICO_PIO_GET_PROGRAM(spi_mode_0_0);
360 			wrap_target = RPI_PICO_PIO_GET_WRAP_TARGET(spi_mode_0_0);
361 			wrap = RPI_PICO_PIO_GET_WRAP(spi_mode_0_0);
362 			cycles = SPI_MODE_0_0_CYCLES;
363 		} else if ((cpol == 1) && (cpha == 1)) {
364 			program = RPI_PICO_PIO_GET_PROGRAM(spi_mode_1_1);
365 			wrap_target = RPI_PICO_PIO_GET_WRAP_TARGET(spi_mode_1_1);
366 			wrap = RPI_PICO_PIO_GET_WRAP(spi_mode_1_1);
367 			cycles = SPI_MODE_1_1_CYCLES;
368 		} else {
369 			LOG_ERR("Not supported:  cpol=%d, cpha=%d\n", cpol, cpha);
370 			return -ENOTSUP;
371 		}
372 
373 		if ((spi_cfg->frequency >
374 		     spi_pico_pio_maximum_clock_frequency(clock_freq, cycles)) ||
375 		    (spi_cfg->frequency <
376 		     spi_pico_pio_minimum_clock_frequency(clock_freq, cycles))) {
377 			LOG_ERR("clock-frequency out of range");
378 			return -EINVAL;
379 		}
380 
381 		float clock_div =
382 			spi_pico_pio_clock_divisor(clock_freq, cycles, spi_cfg->frequency);
383 
384 		if (!pio_can_add_program(data->pio, program)) {
385 			return -EBUSY;
386 		}
387 
388 		data->pio_tx_offset = pio_add_program(data->pio, program);
389 		sm_config = pio_get_default_sm_config();
390 
391 		sm_config_set_clkdiv(&sm_config, clock_div);
392 		sm_config_set_in_pins(&sm_config, miso->pin);
393 		sm_config_set_in_shift(&sm_config, lsb, true, data->bits);
394 		sm_config_set_out_pins(&sm_config, mosi->pin, 1);
395 		sm_config_set_out_shift(&sm_config, lsb, true, data->bits);
396 		sm_config_set_sideset_pins(&sm_config, clk->pin);
397 		sm_config_set_sideset(&sm_config, 1, false, false);
398 		sm_config_set_wrap(&sm_config, data->pio_tx_offset + wrap_target,
399 				   data->pio_tx_offset + wrap);
400 
401 		pio_sm_set_consecutive_pindirs(data->pio, data->pio_sm, miso->pin, 1, false);
402 		pio_sm_set_pindirs_with_mask(data->pio, data->pio_sm,
403 					     (BIT(clk->pin) | BIT(mosi->pin)),
404 					     (BIT(clk->pin) | BIT(mosi->pin)));
405 		pio_sm_set_pins_with_mask(data->pio, data->pio_sm, (cpol << clk->pin),
406 					  BIT(clk->pin) | BIT(mosi->pin));
407 		pio_gpio_init(data->pio, mosi->pin);
408 		pio_gpio_init(data->pio, miso->pin);
409 		pio_gpio_init(data->pio, clk->pin);
410 
411 		pio_sm_init(data->pio, data->pio_sm, data->pio_tx_offset, &sm_config);
412 		pio_sm_set_enabled(data->pio, data->pio_sm, true);
413 	}
414 
415 	data->spi_ctx.config = spi_cfg;
416 
417 	return 0;
418 }
419 
spi_pico_pio_txrx_4_wire(const struct device * dev)420 static void spi_pico_pio_txrx_4_wire(const struct device *dev)
421 {
422 	struct spi_pico_pio_data *data = dev->data;
423 	const size_t chunk_len = spi_context_max_continuous_chunk(&data->spi_ctx);
424 	const uint8_t *txbuf = data->spi_ctx.tx_buf;
425 	uint8_t *rxbuf = data->spi_ctx.rx_buf;
426 	uint32_t txrx;
427 	size_t fifo_cnt = 0;
428 
429 	data->tx_count = 0;
430 	data->rx_count = 0;
431 
432 	pio_sm_clear_fifos(data->pio, data->pio_sm);
433 
434 	while (data->rx_count < chunk_len || data->tx_count < chunk_len) {
435 		/* Fill up fifo with available TX data */
436 		while ((!pio_sm_is_tx_fifo_full(data->pio, data->pio_sm)) &&
437 		       data->tx_count < chunk_len && fifo_cnt < PIO_FIFO_DEPTH) {
438 			/* Send 0 in the case of read only operation */
439 			txrx = 0;
440 
441 			switch (data->dfs) {
442 			case 4: {
443 				if (txbuf) {
444 					txrx = sys_get_be32(txbuf + (data->tx_count * 4));
445 				}
446 				spi_pico_pio_sm_put32(data->pio, data->pio_sm, txrx);
447 			} break;
448 
449 			case 2: {
450 				if (txbuf) {
451 					txrx = sys_get_be16(txbuf + (data->tx_count * 2));
452 				}
453 				spi_pico_pio_sm_put16(data->pio, data->pio_sm, txrx);
454 			} break;
455 
456 			case 1: {
457 				if (txbuf) {
458 					txrx = ((uint8_t *)txbuf)[data->tx_count];
459 				}
460 				spi_pico_pio_sm_put8(data->pio, data->pio_sm, txrx);
461 			} break;
462 
463 			default:
464 				LOG_ERR("Support fot %d bits not enabled", (data->dfs * 8));
465 				break;
466 			}
467 			data->tx_count++;
468 			fifo_cnt++;
469 		}
470 
471 		while ((!pio_sm_is_rx_fifo_empty(data->pio, data->pio_sm)) &&
472 		       data->rx_count < chunk_len && fifo_cnt > 0) {
473 			switch (data->dfs) {
474 			case 4: {
475 				txrx = spi_pico_pio_sm_get32(data->pio, data->pio_sm);
476 
477 				/* Discard received data if rx buffer not assigned */
478 				if (rxbuf) {
479 					sys_put_be32(txrx, rxbuf + (data->rx_count * 4));
480 				}
481 			} break;
482 
483 			case 2: {
484 				txrx = spi_pico_pio_sm_get16(data->pio, data->pio_sm);
485 
486 				/* Discard received data if rx buffer not assigned */
487 				if (rxbuf) {
488 					sys_put_be16(txrx, rxbuf + (data->rx_count * 2));
489 				}
490 			} break;
491 
492 			case 1: {
493 				txrx = spi_pico_pio_sm_get8(data->pio, data->pio_sm);
494 
495 				/* Discard received data if rx buffer not assigned */
496 				if (rxbuf) {
497 					((uint8_t *)rxbuf)[data->rx_count] = (uint8_t)txrx;
498 				}
499 			} break;
500 
501 			default:
502 				LOG_ERR("Support fot %d bits not enabled", (data->dfs * 8));
503 				break;
504 			}
505 			data->rx_count++;
506 			fifo_cnt--;
507 		}
508 	}
509 }
510 
spi_pico_pio_txrx_3_wire(const struct device * dev)511 static void spi_pico_pio_txrx_3_wire(const struct device *dev)
512 {
513 #if SPI_RPI_PICO_PIO_HALF_DUPLEX_ENABLED
514 	struct spi_pico_pio_data *data = dev->data;
515 	const struct spi_pico_pio_config *dev_cfg = dev->config;
516 	const uint8_t *txbuf = data->spi_ctx.tx_buf;
517 	uint8_t *rxbuf = data->spi_ctx.rx_buf;
518 	uint32_t txrx;
519 	int sio_pin = dev_cfg->sio_gpio.pin;
520 	uint32_t tx_size = data->spi_ctx.tx_len; /* Number of WORDS to send */
521 	uint32_t rx_size = data->spi_ctx.rx_len; /* Number of WORDS to receive */
522 
523 	data->tx_count = 0;
524 	data->rx_count = 0;
525 
526 	if (txbuf) {
527 		pio_sm_set_enabled(data->pio, data->pio_sm, false);
528 		pio_sm_set_wrap(data->pio, data->pio_sm,
529 				data->pio_tx_offset +
530 					RPI_PICO_PIO_GET_WRAP_TARGET(spi_sio_mode_0_0_tx),
531 				data->pio_tx_offset + RPI_PICO_PIO_GET_WRAP(spi_sio_mode_0_0_tx));
532 		pio_sm_clear_fifos(data->pio, data->pio_sm);
533 		pio_sm_set_pindirs_with_mask(data->pio, data->pio_sm, BIT(sio_pin), BIT(sio_pin));
534 		pio_sm_restart(data->pio, data->pio_sm);
535 		pio_sm_clkdiv_restart(data->pio, data->pio_sm);
536 		pio_sm_exec(data->pio, data->pio_sm, pio_encode_jmp(data->pio_tx_offset));
537 		pio_sm_set_enabled(data->pio, data->pio_sm, true);
538 
539 		while (data->tx_count < tx_size) {
540 			/* Fill up fifo with available TX data */
541 			while ((!pio_sm_is_tx_fifo_full(data->pio, data->pio_sm)) &&
542 			       data->tx_count < tx_size) {
543 
544 				switch (data->dfs) {
545 				case 4: {
546 					txrx = sys_get_be32(txbuf + (data->tx_count * 4));
547 					spi_pico_pio_sm_put32(data->pio, data->pio_sm, txrx);
548 				} break;
549 
550 				case 2: {
551 					txrx = sys_get_be16(txbuf + (data->tx_count * 2));
552 					spi_pico_pio_sm_put16(data->pio, data->pio_sm, txrx);
553 				} break;
554 
555 				case 1: {
556 					txrx = ((uint8_t *)txbuf)[data->tx_count];
557 					spi_pico_pio_sm_put8(data->pio, data->pio_sm, txrx);
558 				} break;
559 
560 				default:
561 					LOG_ERR("Support fot %d bits not enabled", (data->dfs * 8));
562 					break;
563 				}
564 				data->tx_count++;
565 			}
566 		}
567 		/* Wait for the state machine to complete the cycle */
568 		/* before resetting the PIO for reading.            */
569 		while ((!pio_sm_is_tx_fifo_empty(data->pio, data->pio_sm)) ||
570 		       (!spi_pico_pio_sm_complete(data)))
571 			;
572 	}
573 
574 	if (rxbuf) {
575 		pio_sm_set_enabled(data->pio, data->pio_sm, false);
576 		pio_sm_set_wrap(data->pio, data->pio_sm, data->pio_rx_wrap_target,
577 				data->pio_rx_wrap);
578 		pio_sm_clear_fifos(data->pio, data->pio_sm);
579 		pio_sm_set_pindirs_with_mask(data->pio, data->pio_sm, 0, BIT(sio_pin));
580 		pio_sm_restart(data->pio, data->pio_sm);
581 		pio_sm_clkdiv_restart(data->pio, data->pio_sm);
582 		pio_sm_put(data->pio, data->pio_sm, (rx_size * data->bits) - 1);
583 		pio_sm_exec(data->pio, data->pio_sm, pio_encode_jmp(data->pio_rx_offset));
584 		pio_sm_set_enabled(data->pio, data->pio_sm, true);
585 
586 		while (data->rx_count < rx_size) {
587 			while ((!pio_sm_is_rx_fifo_empty(data->pio, data->pio_sm)) &&
588 			       data->rx_count < rx_size) {
589 
590 				switch (data->dfs) {
591 				case 4: {
592 					txrx = spi_pico_pio_sm_get32(data->pio, data->pio_sm);
593 					sys_put_be32(txrx, rxbuf + (data->rx_count * 4));
594 				} break;
595 
596 				case 2: {
597 					txrx = spi_pico_pio_sm_get16(data->pio, data->pio_sm);
598 					sys_put_be16(txrx, rxbuf + (data->rx_count * 2));
599 				} break;
600 
601 				case 1: {
602 					txrx = spi_pico_pio_sm_get8(data->pio, data->pio_sm);
603 					rxbuf[data->rx_count] = (uint8_t)txrx;
604 				} break;
605 
606 				default:
607 					LOG_ERR("Support fot %d bits not enabled", (data->dfs * 8));
608 					break;
609 				}
610 				data->rx_count++;
611 			}
612 		}
613 	}
614 #else
615 	LOG_ERR("SIO pin requires half-duplex support");
616 #endif /* SPI_RPI_PICO_PIO_HALF_DUPLEX_ENABLED */
617 }
618 
spi_pico_pio_txrx(const struct device * dev)619 static void spi_pico_pio_txrx(const struct device *dev)
620 {
621 	const struct spi_pico_pio_config *dev_cfg = dev->config;
622 
623 	/* 3-wire or 4-wire mode? */
624 	if (dev_cfg->sio_gpio.port) {
625 		spi_pico_pio_txrx_3_wire(dev);
626 	} else {
627 		spi_pico_pio_txrx_4_wire(dev);
628 	}
629 }
630 
spi_pico_pio_transceive_impl(const struct device * dev,const struct spi_config * spi_cfg,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs,bool asynchronous,spi_callback_t cb,void * userdata)631 static int spi_pico_pio_transceive_impl(const struct device *dev, const struct spi_config *spi_cfg,
632 					const struct spi_buf_set *tx_bufs,
633 					const struct spi_buf_set *rx_bufs, bool asynchronous,
634 					spi_callback_t cb, void *userdata)
635 {
636 	const struct spi_pico_pio_config *dev_cfg = dev->config;
637 	struct spi_pico_pio_data *data = dev->data;
638 	struct spi_context *spi_ctx = &data->spi_ctx;
639 	int rc = 0;
640 
641 	spi_context_lock(spi_ctx, asynchronous, cb, userdata, spi_cfg);
642 
643 	rc = spi_pico_pio_configure(dev_cfg, data, spi_cfg);
644 	if (rc < 0) {
645 		goto error;
646 	}
647 
648 	spi_context_buffers_setup(spi_ctx, tx_bufs, rx_bufs, data->dfs);
649 	spi_context_cs_control(spi_ctx, true);
650 
651 	do {
652 		spi_pico_pio_txrx(dev);
653 		spi_context_update_tx(spi_ctx, 1, data->tx_count);
654 		spi_context_update_rx(spi_ctx, 1, data->rx_count);
655 	} while (spi_pico_pio_transfer_ongoing(data));
656 
657 	spi_context_cs_control(spi_ctx, false);
658 
659 error:
660 	spi_context_release(spi_ctx, rc);
661 
662 	return rc;
663 }
664 
spi_pico_pio_transceive(const struct device * dev,const struct spi_config * spi_cfg,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs)665 static int spi_pico_pio_transceive(const struct device *dev, const struct spi_config *spi_cfg,
666 				   const struct spi_buf_set *tx_bufs,
667 				   const struct spi_buf_set *rx_bufs)
668 {
669 	return spi_pico_pio_transceive_impl(dev, spi_cfg, tx_bufs, rx_bufs, false, NULL, NULL);
670 }
671 
spi_pico_pio_release(const struct device * dev,const struct spi_config * spi_cfg)672 int spi_pico_pio_release(const struct device *dev, const struct spi_config *spi_cfg)
673 {
674 	struct spi_pico_pio_data *data = dev->data;
675 
676 	spi_context_unlock_unconditionally(&data->spi_ctx);
677 
678 	return 0;
679 }
680 
681 static DEVICE_API(spi, spi_pico_pio_api) = {
682 	.transceive = spi_pico_pio_transceive,
683 	.release = spi_pico_pio_release,
684 };
685 
config_gpio(const struct gpio_dt_spec * gpio,const char * tag,int mode)686 static int config_gpio(const struct gpio_dt_spec *gpio, const char *tag, int mode)
687 {
688 	int rc = 0;
689 
690 	if (!device_is_ready(gpio->port)) {
691 		LOG_ERR("GPIO port for %s pin is not ready", tag);
692 		return -ENODEV;
693 	}
694 
695 	rc = gpio_pin_configure_dt(gpio, mode);
696 	if (rc < 0) {
697 		LOG_ERR("Couldn't configure %s pin; (%d)", tag, rc);
698 		return rc;
699 	}
700 
701 	return 0;
702 }
703 
spi_pico_pio_init(const struct device * dev)704 int spi_pico_pio_init(const struct device *dev)
705 {
706 	const struct spi_pico_pio_config *dev_cfg = dev->config;
707 	struct spi_pico_pio_data *data = dev->data;
708 	int rc;
709 
710 	rc = pinctrl_apply_state(dev_cfg->pin_cfg, PINCTRL_STATE_DEFAULT);
711 	if (rc) {
712 		LOG_ERR("Failed to apply pinctrl state");
713 		return rc;
714 	}
715 
716 	rc = config_gpio(&dev_cfg->clk_gpio, "clk", GPIO_OUTPUT_ACTIVE);
717 	if (rc < 0) {
718 		return rc;
719 	}
720 
721 	if (dev_cfg->mosi_gpio.port != NULL) {
722 		rc = config_gpio(&dev_cfg->mosi_gpio, "mosi", GPIO_OUTPUT);
723 		if (rc < 0) {
724 			return rc;
725 		}
726 	}
727 
728 	if (dev_cfg->miso_gpio.port != NULL) {
729 		rc = config_gpio(&dev_cfg->miso_gpio, "miso", GPIO_INPUT);
730 		if (rc < 0) {
731 			return rc;
732 		}
733 	}
734 
735 	rc = spi_context_cs_configure_all(&data->spi_ctx);
736 	if (rc < 0) {
737 		LOG_ERR("Failed to configure CS pins: %d", rc);
738 		return rc;
739 	}
740 
741 	spi_context_unlock_unconditionally(&data->spi_ctx);
742 
743 	return 0;
744 }
745 
746 #define SPI_PICO_PIO_INIT(inst)                                                                    \
747 	PINCTRL_DT_INST_DEFINE(inst);                                                              \
748 	static struct spi_pico_pio_config spi_pico_pio_config_##inst = {                           \
749 		.piodev = DEVICE_DT_GET(DT_INST_PARENT(inst)),                                     \
750 		.pin_cfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst),                                   \
751 		.clk_gpio = GPIO_DT_SPEC_INST_GET(inst, clk_gpios),                                \
752 		.mosi_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mosi_gpios, {0}),                      \
753 		.miso_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, miso_gpios, {0}),                      \
754 		.sio_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, sio_gpios, {0}),                        \
755 		.clk_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(inst)),                               \
756 		.clk_id = (clock_control_subsys_t)DT_INST_PHA_BY_IDX(inst, clocks, 0, clk_id),     \
757 	};                                                                                         \
758 	static struct spi_pico_pio_data spi_pico_pio_data_##inst = {                               \
759 		SPI_CONTEXT_INIT_LOCK(spi_pico_pio_data_##inst, spi_ctx),                          \
760 		SPI_CONTEXT_INIT_SYNC(spi_pico_pio_data_##inst, spi_ctx),                          \
761 		SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(inst), spi_ctx)};                      \
762 	SPI_DEVICE_DT_INST_DEFINE(inst, spi_pico_pio_init, NULL, &spi_pico_pio_data_##inst,        \
763 			      &spi_pico_pio_config_##inst, POST_KERNEL, CONFIG_SPI_INIT_PRIORITY,  \
764 			      &spi_pico_pio_api);                                                  \
765 	BUILD_ASSERT(DT_INST_NODE_HAS_PROP(inst, clk_gpios), "Missing clock GPIO");                \
766 	BUILD_ASSERT(((DT_INST_NODE_HAS_PROP(inst, mosi_gpios) ||                                  \
767 		       DT_INST_NODE_HAS_PROP(inst, miso_gpios)) &&                                 \
768 		      (!DT_INST_NODE_HAS_PROP(inst, sio_gpios))) ||                                \
769 			     (DT_INST_NODE_HAS_PROP(inst, sio_gpios) &&                            \
770 			      !(DT_INST_NODE_HAS_PROP(inst, mosi_gpios) ||                         \
771 				DT_INST_NODE_HAS_PROP(inst, miso_gpios))),                         \
772 		     "Invalid GPIO Configuration");
773 
774 DT_INST_FOREACH_STATUS_OKAY(SPI_PICO_PIO_INIT)
775