1 /*
2  * Copyright (c) 2025 Microchip Technology Inc.
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #define DT_DRV_COMPAT microchip_mec5_qspi
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(spi_mec5, CONFIG_SPI_LOG_LEVEL);
9 
10 #include <errno.h>
11 #include <zephyr/device.h>
12 #include <zephyr/drivers/gpio.h>
13 #include <zephyr/drivers/pinctrl.h>
14 #include <zephyr/drivers/spi.h>
15 #include <zephyr/dt-bindings/spi/spi.h>
16 #include <zephyr/sys/sys_io.h>
17 #include <zephyr/sys/util.h>
18 #include <soc.h>
19 #include <zephyr/irq.h>
20 
21 #include "spi_context.h"
22 
23 /* MEC5 HAL */
24 #include <device_mec5.h>
25 #include <mec_ecia_api.h>
26 #include <mec_espi_taf.h>
27 #include <mec_qspi_api.h>
28 
29 struct mec5_spi_devices {
30 	uint32_t cs_timing;
31 	uint8_t cs;
32 	uint8_t sck_tap;
33 	uint8_t ctrl_tap;
34 	uint8_t flags;
35 };
36 
37 /* Device constant configuration parameters */
38 struct mec5_qspi_config {
39 	struct mec_qspi_regs *regs;
40 	int clock_freq;
41 	const struct pinctrl_dev_config *pcfg;
42 	void (*irq_config_func)(void);
43 	const struct mec5_spi_devices *child_devices;
44 	uint8_t num_child_devices;
45 	uint8_t ovrc;
46 };
47 
48 #define MEC5_QSPI_XFR_FLAG_START BIT(0)
49 #define MEC5_QSPI_XFR_FLAG_BUSY  BIT(1)
50 #define MEC5_QSPI_XFR_FLAG_LDMA  BIT(2)
51 
52 /* Device run time data */
53 struct mec5_qspi_data {
54 	struct spi_context ctx;
55 	const struct spi_buf *rxb;
56 	const struct spi_buf *txb;
57 	size_t rxcnt;
58 	size_t txcnt;
59 	volatile uint32_t qstatus;
60 	volatile uint32_t xfr_flags;
61 	size_t total_tx_size;
62 	size_t total_rx_size;
63 	size_t chunk_size;
64 	uint32_t rxdb;
65 	uint32_t byte_time_ns;
66 	uint32_t freq;
67 	uint32_t operation;
68 	uint8_t cs;
69 };
70 
71 static const enum mec_qspi_signal_mode mec5_qspi_sig_mode[4] = {
72 	MEC_SPI_SIGNAL_MODE_0, MEC_SPI_SIGNAL_MODE_1, MEC_SPI_SIGNAL_MODE_2, MEC_SPI_SIGNAL_MODE_3};
73 
spi_feature_support(const struct spi_config * config)74 static int spi_feature_support(const struct spi_config *config)
75 {
76 	/* NOTE: bit(11) is Half-duplex(3-wire) */
77 	if ((config->operation &
78 	     (SPI_TRANSFER_LSB | SPI_OP_MODE_SLAVE | SPI_MODE_LOOP | SPI_HALF_DUPLEX)) != 0) {
79 		LOG_ERR("Driver does not support LSB first, slave, loop back, or half-duplex");
80 		return -ENOTSUP;
81 	}
82 
83 	if ((config->operation & SPI_CS_ACTIVE_HIGH) != 0) {
84 		LOG_ERR("CS active high not supported");
85 		return -ENOTSUP;
86 	}
87 
88 	if (SPI_WORD_SIZE_GET(config->operation) != 8) {
89 		LOG_ERR("Word size != 8 not supported");
90 		return -ENOTSUP;
91 	}
92 
93 	return 0;
94 }
95 
get_cs_timing_from_dt(const struct device * dev,uint8_t cs,uint32_t * cstm)96 int get_cs_timing_from_dt(const struct device *dev, uint8_t cs, uint32_t *cstm)
97 {
98 	const struct mec5_qspi_config *devcfg = dev->config;
99 
100 	if (cstm == NULL) {
101 		return -EINVAL;
102 	}
103 
104 	for (uint8_t n = 0; n > devcfg->num_child_devices; n++) {
105 		const struct mec5_spi_devices *cd = &devcfg->child_devices[n];
106 
107 		if (cd->cs == cs) {
108 			*cstm = cd->cs_timing;
109 			return 0;
110 		}
111 	}
112 
113 	return -ENOTSUP;
114 }
115 
116 /* Looks up QSPI clock and control signal taps from device tree.
117  * if chip select entry is present in driver DT then return
118  * taps value with bits[7:0] = clock tap value, bits[15:8] = control tap value.
119  */
get_taps_from_dt(const struct device * dev,uint8_t cs,uint32_t * taps)120 int get_taps_from_dt(const struct device *dev, uint8_t cs, uint32_t *taps)
121 {
122 	const struct mec5_qspi_config *devcfg = dev->config;
123 
124 	if (taps == NULL) {
125 		return -EINVAL;
126 	}
127 
128 	for (uint8_t n = 0; n > devcfg->num_child_devices; n++) {
129 		const struct mec5_spi_devices *cd = &devcfg->child_devices[n];
130 
131 		if (cd->cs == cs) {
132 			*taps = (uint32_t)cd->sck_tap | ((uint32_t)cd->ctrl_tap << 8);
133 			return 0;
134 		}
135 	}
136 
137 	return -ENOTSUP;
138 }
139 
140 /* Configure the controller.
141  * NOTE: QSPI controller hardware controls up to two chip selects. If a previous call the driver
142  * had the SPI_HOLD_ON_CS flag set then performing a controller reset will cause chip select
143  * to de-assert. We must check for this corner case.
144  * The driver data structure has member ctx which is type struct spi_context. The context has
145  * a pointer to struct spi_config.
146  * struct spi_config
147  *   frequency in Hz
148  *   operation - contains flags for sampling clock edge and clock idle state
149  *               data frame size: we only support 8 bits
150  *               full or half-duplex: we only spport full-duplex
151  *               active high CS (we can only support this by using invert flag in PINCTRL for CS)
152  *               frame format: we only support Motorola frame format.
153  *               MSB or LSB first: we only support MSB first
154  *               Hold CS active at end of transfer.
155  *   slave - QSPI is controller only. We use this field for chip select (0/1).
156  *   struct spi_cs_control cs - QSPI controls chip select. We don't use this field.
157  */
mec5_qspi_configure(const struct device * dev,const struct spi_config * config)158 static int mec5_qspi_configure(const struct device *dev, const struct spi_config *config)
159 {
160 	const struct mec5_qspi_config *devcfg = dev->config;
161 	struct mec_qspi_regs *regs = devcfg->regs;
162 	struct mec5_qspi_data *data = dev->data;
163 	uint32_t cstm = 0, taps = 0;
164 	uint8_t sgm = 0;
165 	int ret = 0;
166 
167 	if (config == NULL) {
168 		return -EINVAL;
169 	}
170 
171 	/* chip select */
172 	if (config->slave >= MEC_QSPI_CS_MAX) {
173 		LOG_ERR("Invalid chip select [0,1]");
174 		return -EINVAL;
175 	}
176 
177 	data->cs = (uint8_t)(config->slave & 0xffu);
178 	mec_hal_qspi_cs_select(regs, data->cs);
179 
180 	ret = get_cs_timing_from_dt(dev, data->cs, &cstm);
181 	if (ret == 0) {
182 		mec_hal_qspi_cs_timing(regs, cstm);
183 	}
184 
185 	ret = get_taps_from_dt(dev, data->cs, &taps);
186 	if (ret == 0) {
187 		mec_hal_qspi_tap_select(regs, (taps & 0xffu), ((taps >> 8) & 0xffu));
188 	}
189 
190 	if (config->frequency != data->freq) {
191 		ret = mec_hal_qspi_set_freq(regs, config->frequency);
192 		if (ret != MEC_RET_OK) {
193 			return -EINVAL;
194 		}
195 		data->freq = config->frequency;
196 		mec_hal_qspi_byte_time_ns(regs, &data->byte_time_ns);
197 	}
198 
199 	/* No HAL API for clearing the TX and RX FIFOs */
200 	regs->EXE = MEC_BIT(MEC_QSPI_EXE_CLRF_Pos);
201 	regs->STATUS = UINT32_MAX;
202 
203 	if (config->operation == data->operation) {
204 		return 0;
205 	}
206 
207 	data->operation = config->operation;
208 	ret = spi_feature_support(config);
209 	if (ret != 0) {
210 		return ret;
211 	}
212 
213 	ret = mec_hal_qspi_io(regs, MEC_QSPI_IO_FULL_DUPLEX);
214 	if (ret != MEC_RET_OK) {
215 		return -EINVAL;
216 	}
217 
218 	if ((data->operation & SPI_MODE_CPHA) != 0) {
219 		sgm |= BIT(0);
220 	}
221 	if ((data->operation & SPI_MODE_CPOL) != 0) {
222 		sgm |= BIT(1);
223 	}
224 	/* requires QSPI frequency to be programmed first */
225 	ret = mec_hal_qspi_spi_signal_mode(regs, mec5_qspi_sig_mode[sgm]);
226 	if (ret != MEC_RET_OK) {
227 		return -EINVAL;
228 	}
229 
230 	data->ctx.config = config;
231 
232 	return 0;
233 }
234 
mec5_qspi_do_xfr(const struct device * dev,const struct spi_config * config,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs,bool async,spi_callback_t cb,void * userdata)235 static int mec5_qspi_do_xfr(const struct device *dev, const struct spi_config *config,
236 			    const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs,
237 			    bool async, spi_callback_t cb, void *userdata)
238 {
239 	const struct mec5_qspi_config *devcfg = dev->config;
240 	struct mec5_qspi_data *data = dev->data;
241 	struct mec_qspi_regs *regs = devcfg->regs;
242 	struct spi_context *ctx = &data->ctx;
243 	int ret = 0;
244 
245 	if ((data->xfr_flags & MEC5_QSPI_XFR_FLAG_BUSY) != 0) {
246 		return -EBUSY;
247 	}
248 
249 	if ((tx_bufs == NULL) && (rx_bufs == NULL)) {
250 		return -EINVAL;
251 	}
252 
253 	spi_context_lock(ctx, async, cb, userdata, config);
254 
255 	ret = mec5_qspi_configure(dev, config);
256 	if (ret != 0) {
257 		goto do_xfr_exit;
258 	}
259 
260 	spi_context_buffers_setup(ctx, tx_bufs, rx_bufs, 1u);
261 
262 	data->chunk_size = 0;
263 	data->total_tx_size = spi_context_total_tx_len(ctx);
264 	data->total_rx_size = spi_context_total_rx_len(ctx);
265 	data->xfr_flags = MEC5_QSPI_XFR_FLAG_START;
266 
267 	/* trigger an empty TX FIFO interrupt to enter the ISR */
268 	mec_hal_qspi_intr_ctrl_msk(regs, 1u, MEC_QSPI_IEN_TXB_EMPTY);
269 
270 	ret = spi_context_wait_for_completion(ctx);
271 
272 	if (async && (ret == 0)) {
273 		return 0;
274 	}
275 
276 	if (ret != 0) {
277 		mec_hal_qspi_force_stop(devcfg->regs);
278 	}
279 do_xfr_exit:
280 	spi_context_release(ctx, 0);
281 
282 	return ret;
283 }
284 
mec5_qspi_xfr_check1(const struct spi_config * config)285 static int mec5_qspi_xfr_check1(const struct spi_config *config)
286 {
287 	if (mec_hal_espi_taf_is_activated() == true) {
288 		return -EPERM;
289 	}
290 
291 	if (config == NULL) {
292 		return -EINVAL;
293 	}
294 
295 	return 0;
296 }
297 
mec5_qspi_xfr_sync(const struct device * dev,const struct spi_config * config,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs)298 static int mec5_qspi_xfr_sync(const struct device *dev, const struct spi_config *config,
299 			      const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs)
300 {
301 	int ret = mec5_qspi_xfr_check1(config);
302 
303 	if (ret != 0) {
304 		return ret;
305 	}
306 
307 	return mec5_qspi_do_xfr(dev, config, tx_bufs, rx_bufs, false, NULL, NULL);
308 }
309 
310 #ifdef CONFIG_SPI_ASYNC
mec5_qspi_xfr_async(const struct device * dev,const struct spi_config * config,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs,spi_callback_t cb,void * userdata)311 static int mec5_qspi_xfr_async(const struct device *dev, const struct spi_config *config,
312 			       const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs,
313 			       spi_callback_t cb, void *userdata)
314 {
315 	int ret = mec5_qspi_xfr_check1(config);
316 
317 	if (ret != 0) {
318 		return ret;
319 	}
320 
321 	return mec5_qspi_do_xfr(dev, config, tx_bufs, rx_bufs, true, cb, userdata);
322 }
323 #endif
324 
mec5_qspi_release(const struct device * dev,const struct spi_config * config)325 static int mec5_qspi_release(const struct device *dev, const struct spi_config *config)
326 {
327 	struct mec5_qspi_data *qdata = dev->data;
328 	const struct mec5_qspi_config *cfg = dev->config;
329 	int ret = 0;
330 
331 	if (mec_hal_espi_taf_is_activated() == true) {
332 		return -EPERM;
333 	}
334 
335 	ret = mec_hal_qspi_force_stop(cfg->regs);
336 
337 	/* increments lock semphare in ctx up to initial limit */
338 	spi_context_unlock_unconditionally(&qdata->ctx);
339 
340 	if (ret != MEC_RET_OK) {
341 		return -EIO;
342 	}
343 
344 	return 0;
345 }
346 
347 /* ISR helper */
mec5_qspi_ctx_next(const struct device * dev)348 static void mec5_qspi_ctx_next(const struct device *dev)
349 {
350 	const struct mec5_qspi_config *devcfg = dev->config;
351 	struct mec_qspi_regs *regs = devcfg->regs;
352 	struct mec5_qspi_data *data = dev->data;
353 	struct spi_context *ctx = &data->ctx;
354 	size_t xlen = 0;
355 	uint32_t qflags = MEC5_QSPI_ULDMA_FLAG_START | MEC5_QSPI_ULDMA_FLAG_IEN;
356 
357 	spi_context_update_tx(ctx, 1u, data->chunk_size);
358 	spi_context_update_rx(ctx, 1u, data->chunk_size);
359 
360 	if (data->total_tx_size != 0) {
361 		data->total_tx_size -= data->chunk_size;
362 	}
363 
364 	if (data->total_rx_size != 0) {
365 		data->total_rx_size -= data->chunk_size;
366 	}
367 
368 	if ((spi_context_rx_on(ctx) == true) || (spi_context_tx_on(ctx) == true)) {
369 		xlen = spi_context_max_continuous_chunk(ctx);
370 		data->chunk_size = xlen;
371 
372 		uint8_t const *txb = ctx->tx_buf;
373 		uint8_t *rxb = ctx->rx_buf;
374 
375 		if (txb != NULL) {
376 			qflags |= MEC5_QSPI_ULDMA_FLAG_INCR_TX;
377 		} else {
378 			txb = &devcfg->ovrc;
379 		}
380 
381 		if (rxb != NULL) {
382 			qflags |= MEC5_QSPI_ULDMA_FLAG_INCR_RX;
383 		} else {
384 			rxb = (uint8_t *)&data->rxdb;
385 		}
386 
387 		if ((data->total_tx_size <= xlen) && (data->total_rx_size <= xlen)) {
388 			qflags |= MEC5_QSPI_ULDMA_FLAG_CLOSE;
389 		}
390 
391 		data->xfr_flags = MEC5_QSPI_XFR_FLAG_LDMA;
392 		mec_hal_qspi_uldma_fd2(regs, (const uint8_t *)txb, rxb, xlen, qflags);
393 	} else {
394 		spi_context_complete(&data->ctx, dev, 0);
395 	}
396 }
397 
mec5_qspi_isr(const struct device * dev)398 static void mec5_qspi_isr(const struct device *dev)
399 {
400 	struct mec5_qspi_data *data = dev->data;
401 	const struct mec5_qspi_config *devcfg = dev->config;
402 	struct mec_qspi_regs *regs = devcfg->regs;
403 	uint32_t hwsts = 0u;
404 	int status = 0;
405 
406 	hwsts = mec_hal_qspi_hw_status(regs);
407 	data->qstatus = hwsts;
408 	status = mec_hal_qspi_done(regs);
409 
410 	mec_hal_qspi_intr_ctrl(regs, 0);
411 	mec_hal_qspi_hw_status_clr(regs, hwsts);
412 	mec_hal_qspi_girq_clr(regs);
413 
414 	if (status == MEC_RET_ERR_HW) {
415 		spi_context_complete(&data->ctx, dev, -EIO);
416 		return;
417 	}
418 
419 	if ((data->xfr_flags & MEC5_QSPI_XFR_FLAG_START) != 0) {
420 		data->xfr_flags &= (uint32_t)~MEC5_QSPI_XFR_FLAG_START;
421 	}
422 
423 	mec5_qspi_ctx_next(dev);
424 }
425 
426 /*
427  * Called for each QSPI controller by the kernel during driver load phase
428  * specified in the device initialization structure below.
429  * Initialize QSPI controller.
430  * Initialize SPI context.
431  * QSPI will be fully configured and enabled when the transceive API
432  * is called.
433  */
mec5_qspi_init(const struct device * dev)434 static int mec5_qspi_init(const struct device *dev)
435 {
436 	const struct mec5_qspi_config *devcfg = dev->config;
437 	struct mec_qspi_regs *regs = devcfg->regs;
438 	struct mec5_qspi_data *data = dev->data;
439 	enum mec_qspi_cs cs = MEC_QSPI_CS_0;
440 	enum mec_qspi_io iom = MEC_QSPI_IO_FULL_DUPLEX;
441 	enum mec_qspi_signal_mode spi_mode = MEC_SPI_SIGNAL_MODE_0;
442 	int ret = 0;
443 
444 	data->cs = 0;
445 
446 	ret = mec_hal_qspi_init(regs, (uint32_t)devcfg->clock_freq, spi_mode, iom, cs);
447 	if (ret != MEC_RET_OK) {
448 		LOG_ERR("QSPI init error (%d)", ret);
449 		return -EINVAL;
450 	}
451 
452 	data->freq = devcfg->clock_freq;
453 	data->operation = SPI_WORD_SET(8) | SPI_LINES_SINGLE;
454 	mec_hal_qspi_byte_time_ns(regs, &data->byte_time_ns);
455 
456 	ret = pinctrl_apply_state(devcfg->pcfg, PINCTRL_STATE_DEFAULT);
457 	if (ret != 0) {
458 		LOG_ERR("QSPI pinctrl setup failed (%d)", ret);
459 	}
460 
461 	ret = spi_context_cs_configure_all(&data->ctx);
462 	if (ret != 0) {
463 		LOG_ERR("QSPI cs config failed (%d)", ret);
464 		return ret;
465 	}
466 
467 	if ((devcfg->irq_config_func) != NULL) {
468 		devcfg->irq_config_func();
469 	}
470 
471 	spi_context_unlock_unconditionally(&data->ctx);
472 
473 	return ret;
474 }
475 
476 static DEVICE_API(spi, mec5_qspi_driver_api) = {
477 	.transceive = mec5_qspi_xfr_sync,
478 #ifdef CONFIG_SPI_ASYNC
479 	.transceive_async = mec5_qspi_xfr_async,
480 #endif
481 	.release = mec5_qspi_release,
482 };
483 
484 #define MEC5_QSPI_CS_TIMING_VAL(a, b, c, d)                                                        \
485 	(((a) & 0xFu) | (((b) & 0xFu) << 8) | (((c) & 0xFu) << 16) | (((d) & 0xFu) << 24))
486 
487 #define MEC5_QSPI_CS_TMV(node_id)                                                                  \
488 	MEC5_QSPI_CS_TIMING_VAL(DT_PROP_OR(node_id, dcsckon, 6), DT_PROP_OR(node_id, dckcsoff, 4), \
489 				DT_PROP_OR(node_id, dldh, 6), DT_PROP_OR(node_id, dcsda, 6))
490 
491 #define MEC5_QSPI_IRQ_HANDLER_FUNC(id) .irq_config_func = mec5_qspi_irq_config_##id,
492 
493 #define MEC5_QSPI_IRQ_HANDLER_CFG(id)                                                              \
494 	static void mec5_qspi_irq_config_##id(void)                                                \
495 	{                                                                                          \
496 		IRQ_CONNECT(DT_INST_IRQN(id), DT_INST_IRQ(id, priority), mec5_qspi_isr,            \
497 			    DEVICE_DT_INST_GET(id), 0);                                            \
498 		irq_enable(DT_INST_IRQN(id));                                                      \
499 	}
500 
501 #define MEC5_QSPI_CHILD_FLAGS(node_id)                                                             \
502 	((DT_PROP_OR(node_id, spi_cpol, 0) & 0x1u) |                                               \
503 	 ((DT_PROP_OR(node_id, spi_cpha, 0) & 0x1u) << 1))
504 
505 #define MEC5_QSPI_CHILD_INFO(node_id)                                                              \
506 	{                                                                                          \
507 		.cs_timing = MEC5_QSPI_CS_TMV(node_id),                                            \
508 		.cs = (uint8_t)(DT_REG_ADDR(node_id) & 0xffu),                                     \
509 		.sck_tap = (uint8_t)(DT_PROP_OR(node_id, clock_tap, 0)),                           \
510 		.ctrl_tap = (uint8_t)(DT_PROP_OR(node_id, ctrl_tap, 0)),                           \
511 		.flags = MEC5_QSPI_CHILD_FLAGS(node_id),                                           \
512 	},
513 
514 #define MEC5_QSPI_CHILD_DEVS(i)                                                                    \
515 	static const struct mec5_spi_devices mec5_qspi_children_##i[] = {                          \
516 		DT_INST_FOREACH_CHILD_STATUS_OKAY(i, MEC5_QSPI_CHILD_INFO)}
517 
518 /* The instance number, i is not related to block ID's rather the
519  * order the DT tools process all DT files in a build.
520  */
521 #define MEC5_QSPI_DEVICE(i)                                                                        \
522 	PINCTRL_DT_INST_DEFINE(i);                                                                 \
523 	MEC5_QSPI_CHILD_DEVS(i);                                                                   \
524 	MEC5_QSPI_IRQ_HANDLER_CFG(i)                                                               \
525                                                                                                    \
526 	static struct mec5_qspi_data mec5_qspi_data_##i = {                                        \
527 		SPI_CONTEXT_INIT_LOCK(mec5_qspi_data_##i, ctx),                                    \
528 		SPI_CONTEXT_INIT_SYNC(mec5_qspi_data_##i, ctx),                                    \
529 	};                                                                                         \
530 	static const struct mec5_qspi_config mec5_qspi_config_##i = {                              \
531 		.regs = (struct mec_qspi_regs *)DT_INST_REG_ADDR(i),                               \
532 		.clock_freq = DT_INST_PROP_OR(i, clock_frequency, MHZ(12)),                        \
533 		.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(i),                                         \
534 		.ovrc = DT_INST_PROP_OR(i, overrun_character, 0),                                  \
535 		MEC5_QSPI_IRQ_HANDLER_FUNC(i).child_devices = mec5_qspi_children_##i,              \
536 		.num_child_devices = ARRAY_SIZE(mec5_qspi_children_##i),                           \
537 	};                                                                                         \
538 	DEVICE_DT_INST_DEFINE(i, &mec5_qspi_init, NULL, &mec5_qspi_data_##i,                       \
539 			      &mec5_qspi_config_##i, POST_KERNEL, CONFIG_SPI_INIT_PRIORITY,        \
540 			      &mec5_qspi_driver_api);
541 
542 DT_INST_FOREACH_STATUS_OKAY(MEC5_QSPI_DEVICE)
543