1 /*
2  * Copyright (c) 2022 Microchip Technology Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT microchip_mpfs_spi
8 
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/spi.h>
11 #include <zephyr/sys/sys_io.h>
12 #include <zephyr/sys/util.h>
13 #include <zephyr/logging/log.h>
14 #include <zephyr/irq.h>
15 
16 LOG_MODULE_REGISTER(mss_spi, CONFIG_SPI_LOG_LEVEL);
17 
18 #include "spi_context.h"
19 
20 /* MSS SPI Register offsets */
21 #define MSS_SPI_REG_CONTROL     (0x00)
22 #define MSS_SPI_REG_TXRXDF_SIZE (0x04)
23 #define MSS_SPI_REG_STATUS      (0x08)
24 #define MSS_SPI_REG_INT_CLEAR   (0x0c)
25 #define MSS_SPI_REG_RX_DATA     (0x10)
26 #define MSS_SPI_REG_TX_DATA     (0x14)
27 #define MSS_SPI_REG_CLK_GEN     (0x18)
28 #define MSS_SPI_REG_SS          (0x1c)
29 #define MSS_SPI_REG_MIS         (0x20)
30 #define MSS_SPI_REG_RIS         (0x24)
31 #define MSS_SPI_REG_CONTROL2    (0x28)
32 #define MSS_SPI_REG_COMMAND     (0x2c)
33 #define MSS_SPI_REG_PKTSIZE     (0x30)
34 #define MSS_SPI_REG_CMD_SIZE    (0x34)
35 #define MSS_SPI_REG_HWSTATUS    (0x38)
36 #define MSS_SPI_REG_FRAMESUP    (0x50)
37 
38 /* SPICR bit definitions */
39 #define MSS_SPI_CONTROL_ENABLE       BIT(0)
40 #define MSS_SPI_CONTROL_MASTER       BIT(1)
41 #define MSS_SPI_CONTROL_PROTO_MSK    BIT(2)
42 #define MSS_SPI_CONTROL_PROTO_MOTO   (0 << 2)
43 #define MSS_SPI_CONTROL_RX_DATA_INT  BIT(4)
44 #define MSS_SPI_CONTROL_TX_DATA_INT  BIT(5)
45 #define MSS_SPI_CONTROL_RX_OVER_INT  BIT(6)
46 #define MSS_SPI_CONTROL_TX_UNDER_INT BIT(7)
47 #define MSS_SPI_CONTROL_CNT_MSK      (0xffff << 8)
48 #define MSS_SPI_CONTROL_CNT_SHF      (8)
49 #define MSS_SPI_CONTROL_SPO          BIT(24)
50 #define MSS_SPI_CONTROL_SPH          BIT(25)
51 #define MSS_SPI_CONTROL_SPS          BIT(26)
52 #define MSS_SPI_CONTROL_FRAMEURUN    BIT(27)
53 #define MSS_SPI_CONTROL_CLKMODE      BIT(28)
54 #define MSS_SPI_CONTROL_BIGFIFO      BIT(29)
55 #define MSS_SPI_CONTROL_OENOFF       BIT(30)
56 #define MSS_SPI_CONTROL_RESET        BIT(31)
57 
58 /* SPIFRAMESIZE bit definitions */
59 #define MSS_SPI_FRAMESIZE_DEFAULT (8)
60 
61 /* SPISS bit definitions */
62 #define MSS_SPI_SSEL_MASK (0xff)
63 #define MSS_SPI_DIRECT    (0x100)
64 #define MSS_SPI_SSELOUT   (0x200)
65 #define MSS_SPI_MIN_SLAVE (0)
66 #define MSS_SPI_MAX_SLAVE (7)
67 
68 /* SPIST bit definitions */
69 #define MSS_SPI_STATUS_ACTIVE                 BIT(14)
70 #define MSS_SPI_STATUS_SSEL                   BIT(13)
71 #define MSS_SPI_STATUS_FRAMESTART             BIT(12)
72 #define MSS_SPI_STATUS_TXFIFO_EMPTY_NEXT_READ BIT(11)
73 #define MSS_SPI_STATUS_TXFIFO_EMPTY           BIT(10)
74 #define MSS_SPI_STATUS_TXFIFO_FULL_NEXT_WRITE BIT(9)
75 #define MSS_SPI_STATUS_TXFIFO_FULL            BIT(8)
76 #define MSS_SPI_STATUS_RXFIFO_EMPTY_NEXT_READ BIT(7)
77 #define MSS_SPI_STATUS_RXFIFO_EMPTY           BIT(6)
78 #define MSS_SPI_STATUS_RXFIFO_FULL_NEXT_WRITE BIT(5)
79 #define MSS_SPI_STATUS_RXFIFO_FULL            BIT(4)
80 #define MSS_SPI_STATUS_TX_UNDERRUN            BIT(3)
81 #define MSS_SPI_STATUS_RX_OVERFLOW            BIT(2)
82 #define MSS_SPI_STATUS_RXDAT_RCED             BIT(1)
83 #define MSS_SPI_STATUS_TXDAT_SENT             BIT(0)
84 
85 /* SPIINT register defines */
86 #define MSS_SPI_INT_TXDONE       BIT(0)
87 #define MSS_SPI_INT_RXRDY        BIT(1)
88 #define MSS_SPI_INT_RX_CH_OVRFLW BIT(2)
89 #define MSS_SPI_INT_TX_CH_UNDRUN BIT(3)
90 #define MSS_SPI_INT_CMD          BIT(4)
91 #define MSS_SPI_INT_SSEND        BIT(5)
92 
93 /* SPICOMMAND bit definitions */
94 #define MSS_SPI_COMMAND_FIFO_MASK (0xC)
95 
96 /* SPIFRAMESUP bit definitions */
97 #define MSS_SPI_FRAMESUP_UP_BYTES_MSK (0xFFFF << 16)
98 #define MSS_SPI_FRAMESUP_LO_BYTES_MSK (0xFFFF << 0)
99 
100 struct mss_spi_config {
101 	mm_reg_t base;
102 	uint8_t clk_gen;
103 	int clock_freq;
104 };
105 
106 struct mss_spi_transfer {
107 	uint32_t rx_len;
108 	uint32_t control;
109 };
110 
111 struct mss_spi_data {
112 	struct spi_context ctx;
113 	struct mss_spi_transfer xfer;
114 };
115 
mss_spi_read(const struct mss_spi_config * cfg,mm_reg_t offset)116 static inline uint32_t mss_spi_read(const struct mss_spi_config *cfg, mm_reg_t offset)
117 {
118 	return sys_read32(cfg->base + offset);
119 }
120 
mss_spi_write(const struct mss_spi_config * cfg,mm_reg_t offset,uint32_t val)121 static inline void mss_spi_write(const struct mss_spi_config *cfg, mm_reg_t offset, uint32_t val)
122 {
123 	sys_write32(val, cfg->base + offset);
124 }
125 
mss_spi_hw_tfsz_set(const struct mss_spi_config * cfg,int len)126 static inline void mss_spi_hw_tfsz_set(const struct mss_spi_config *cfg, int len)
127 {
128 	uint32_t control;
129 
130 	mss_spi_write(cfg, MSS_SPI_REG_FRAMESUP, (len & MSS_SPI_FRAMESUP_UP_BYTES_MSK));
131 	control = mss_spi_read(cfg, MSS_SPI_REG_CONTROL);
132 	control &= ~MSS_SPI_CONTROL_CNT_MSK;
133 	control |= ((len & MSS_SPI_FRAMESUP_LO_BYTES_MSK) << MSS_SPI_CONTROL_CNT_SHF);
134 	mss_spi_write(cfg, MSS_SPI_REG_CONTROL, control);
135 }
136 
mss_spi_enable_controller(const struct mss_spi_config * cfg)137 static inline void mss_spi_enable_controller(const struct mss_spi_config *cfg)
138 {
139 	uint32_t control;
140 
141 	control = mss_spi_read(cfg, MSS_SPI_REG_CONTROL);
142 	control |= MSS_SPI_CONTROL_ENABLE;
143 	mss_spi_write(cfg, MSS_SPI_REG_CONTROL, control);
144 }
145 
mss_spi_disable_controller(const struct mss_spi_config * cfg)146 static inline void mss_spi_disable_controller(const struct mss_spi_config *cfg)
147 {
148 	uint32_t control;
149 
150 	control = mss_spi_read(cfg, MSS_SPI_REG_CONTROL);
151 	control &= ~MSS_SPI_CONTROL_ENABLE;
152 	mss_spi_write(cfg, MSS_SPI_REG_CONTROL, control);
153 }
154 
mss_spi_enable_ints(const struct mss_spi_config * cfg)155 static void mss_spi_enable_ints(const struct mss_spi_config *cfg)
156 {
157 	uint32_t control;
158 	uint32_t mask = MSS_SPI_CONTROL_RX_DATA_INT | MSS_SPI_CONTROL_TX_DATA_INT |
159 			MSS_SPI_CONTROL_RX_OVER_INT | MSS_SPI_CONTROL_TX_UNDER_INT;
160 
161 	control = mss_spi_read(cfg, MSS_SPI_REG_CONTROL);
162 	control |= mask;
163 	mss_spi_write(cfg, MSS_SPI_REG_CONTROL, control);
164 }
165 
mss_spi_disable_ints(const struct mss_spi_config * cfg)166 static void mss_spi_disable_ints(const struct mss_spi_config *cfg)
167 {
168 	uint32_t control;
169 	uint32_t mask = MSS_SPI_CONTROL_RX_DATA_INT | MSS_SPI_CONTROL_TX_DATA_INT |
170 			MSS_SPI_CONTROL_RX_OVER_INT | MSS_SPI_CONTROL_TX_UNDER_INT;
171 
172 	mask = ~mask;
173 	control = mss_spi_read(cfg, MSS_SPI_REG_CONTROL);
174 	control &= ~mask;
175 	mss_spi_write(cfg, MSS_SPI_REG_CONTROL, control);
176 }
177 
mss_spi_readwr_fifo(const struct device * dev)178 static inline void mss_spi_readwr_fifo(const struct device *dev)
179 {
180 	const struct mss_spi_config *cfg = dev->config;
181 	struct mss_spi_data *data = dev->data;
182 	struct spi_context *ctx = &data->ctx;
183 	struct mss_spi_transfer *xfer = &data->xfer;
184 	uint32_t rx_raw = 0, rd_byte_size, tr_len;
185 	uint32_t data8, transfer_idx = 0;
186 	int count;
187 
188 	tr_len = spi_context_longest_current_buf(ctx);
189 	count = spi_context_total_tx_len(ctx);
190 	if (ctx->rx_buf) {
191 		rd_byte_size = count - tr_len;
192 	} else {
193 		rd_byte_size = 0;
194 	}
195 	mss_spi_hw_tfsz_set(cfg, count);
196 
197 	mss_spi_enable_ints(cfg);
198 	spi_context_update_rx(ctx, 1, xfer->rx_len);
199 	while (transfer_idx < count) {
200 		if (!(mss_spi_read(cfg, MSS_SPI_REG_STATUS) & MSS_SPI_STATUS_RXFIFO_EMPTY)) {
201 			rx_raw = mss_spi_read(cfg, MSS_SPI_REG_RX_DATA);
202 			if (transfer_idx >= tr_len) {
203 				if (spi_context_rx_buf_on(ctx)) {
204 					UNALIGNED_PUT(rx_raw, (uint8_t *)ctx->rx_buf);
205 					spi_context_update_rx(ctx, 1, 1);
206 				}
207 			}
208 			++transfer_idx;
209 		}
210 
211 		if (!(mss_spi_read(cfg, MSS_SPI_REG_STATUS) & MSS_SPI_STATUS_TXFIFO_FULL)) {
212 			if (spi_context_tx_buf_on(ctx)) {
213 				data8 = ctx->tx_buf[0];
214 				mss_spi_write(cfg, MSS_SPI_REG_TX_DATA, data8);
215 				spi_context_update_tx(ctx, 1, 1);
216 			} else {
217 				mss_spi_write(cfg, MSS_SPI_REG_TX_DATA, 0x0);
218 			}
219 		}
220 	}
221 }
222 
mss_spi_select_slave(const struct mss_spi_config * cfg,int cs)223 static inline int mss_spi_select_slave(const struct mss_spi_config *cfg, int cs)
224 {
225 	uint32_t slave;
226 	uint32_t reg = mss_spi_read(cfg, MSS_SPI_REG_SS);
227 
228 	slave = (cs >= MSS_SPI_MIN_SLAVE && cs <= MSS_SPI_MAX_SLAVE) ? (1 << cs) : 0;
229 	reg &= ~MSS_SPI_SSEL_MASK;
230 	reg |= slave;
231 
232 	mss_spi_write(cfg, MSS_SPI_REG_SS, reg);
233 
234 	return 0;
235 }
236 
mss_spi_activate_cs(struct mss_spi_config * cfg)237 static inline void mss_spi_activate_cs(struct mss_spi_config *cfg)
238 {
239 	uint32_t reg = mss_spi_read(cfg, MSS_SPI_REG_SS);
240 
241 	reg |= MSS_SPI_SSELOUT;
242 	mss_spi_write(cfg, MSS_SPI_REG_SS, reg);
243 }
244 
mss_spi_deactivate_cs(const struct mss_spi_config * cfg)245 static inline void mss_spi_deactivate_cs(const struct mss_spi_config *cfg)
246 {
247 	uint32_t reg = mss_spi_read(cfg, MSS_SPI_REG_SS);
248 
249 	reg &= ~MSS_SPI_SSELOUT;
250 	mss_spi_write(cfg, MSS_SPI_REG_SS, reg);
251 }
252 
mss_spi_clk_gen_set(const struct mss_spi_config * cfg,const struct spi_config * spi_cfg)253 static inline int mss_spi_clk_gen_set(const struct mss_spi_config *cfg,
254 				      const struct spi_config *spi_cfg)
255 {
256 	uint32_t idx, clkrate, val = 0, speed;
257 
258 	if (spi_cfg->frequency > cfg->clock_freq) {
259 		speed = cfg->clock_freq / 2;
260 	}
261 
262 	for (idx = 1; idx < 16; idx++) {
263 		clkrate = cfg->clock_freq / (2 * idx);
264 		if (clkrate <= spi_cfg->frequency) {
265 			val = idx;
266 			break;
267 		}
268 	}
269 
270 	mss_spi_write(cfg, MSS_SPI_REG_CLK_GEN, val);
271 
272 	return 0;
273 }
274 
mss_spi_hw_mode_set(const struct mss_spi_config * cfg,unsigned int mode)275 static inline int mss_spi_hw_mode_set(const struct mss_spi_config *cfg, unsigned int mode)
276 {
277 	uint32_t control = mss_spi_read(cfg, MSS_SPI_REG_CONTROL);
278 
279 	/* set the mode */
280 	if (mode & SPI_MODE_CPHA) {
281 		control |= MSS_SPI_CONTROL_SPH;
282 	} else {
283 		control &= ~MSS_SPI_CONTROL_SPH;
284 	}
285 
286 	if (mode & SPI_MODE_CPOL) {
287 		control |= MSS_SPI_CONTROL_SPO;
288 	} else {
289 		control &= ~MSS_SPI_CONTROL_SPO;
290 	}
291 
292 	mss_spi_write(cfg, MSS_SPI_REG_CONTROL, control);
293 
294 	return 0;
295 }
296 
mss_spi_interrupt(const struct device * dev)297 static void mss_spi_interrupt(const struct device *dev)
298 {
299 	const struct mss_spi_config *cfg = dev->config;
300 	struct mss_spi_data *data = dev->data;
301 	struct spi_context *ctx = &data->ctx;
302 	int intfield = mss_spi_read(cfg, MSS_SPI_REG_MIS) & 0xf;
303 
304 	if (intfield == 0) {
305 		return;
306 	}
307 
308 	mss_spi_write(cfg, MSS_SPI_REG_INT_CLEAR, intfield);
309 	spi_context_complete(ctx, dev, 0);
310 }
311 
mss_spi_release(const struct device * dev,const struct spi_config * config)312 static int mss_spi_release(const struct device *dev, const struct spi_config *config)
313 {
314 	const struct mss_spi_config *cfg = dev->config;
315 	struct mss_spi_data *data = dev->data;
316 
317 	mss_spi_disable_ints(cfg);
318 
319 	/* release kernel resources */
320 	spi_context_unlock_unconditionally(&data->ctx);
321 	mss_spi_disable_controller(cfg);
322 
323 	return 0;
324 }
325 
mss_spi_configure(const struct device * dev,const struct spi_config * spi_cfg)326 static int mss_spi_configure(const struct device *dev, const struct spi_config *spi_cfg)
327 {
328 	const struct mss_spi_config *cfg = dev->config;
329 	struct mss_spi_data *data = dev->data;
330 	struct spi_context *ctx = &data->ctx;
331 	struct mss_spi_transfer *xfer = &data->xfer;
332 	uint32_t control;
333 
334 	if (spi_cfg->operation & (SPI_TRANSFER_LSB | SPI_OP_MODE_SLAVE | SPI_MODE_LOOP)) {
335 		LOG_WRN("not supported operation\n\r");
336 		return -ENOTSUP;
337 	}
338 
339 	if (SPI_WORD_SIZE_GET(spi_cfg->operation) != MSS_SPI_FRAMESIZE_DEFAULT) {
340 		return -ENOTSUP;
341 	}
342 
343 	ctx->config = spi_cfg;
344 	mss_spi_select_slave(cfg, spi_cfg->slave);
345 	control = mss_spi_read(cfg, MSS_SPI_REG_CONTROL);
346 
347 	/*
348 	 * Fill up the default values
349 	 * Slave select behaviour set
350 	 * Fifo depth greater than 4 frames
351 	 * Methodology to calculate SPI Clock:
352 	 *	0:	SPICLK = 1 / (2 CLK_GEN + 1) , CLK_GEN is from 0 to 15
353 	 *	1:	SPICLK = 1 / (2 * (CLK_GEN + 1)) , CLK_GEN is from 0 to 255
354 	 */
355 
356 	mss_spi_write(cfg, MSS_SPI_REG_CONTROL, xfer->control);
357 
358 	if (mss_spi_clk_gen_set(cfg, spi_cfg)) {
359 		LOG_ERR("can't set clk divider\n");
360 		return -EINVAL;
361 	}
362 
363 	mss_spi_hw_mode_set(cfg, spi_cfg->operation);
364 	mss_spi_write(cfg, MSS_SPI_REG_TXRXDF_SIZE, MSS_SPI_FRAMESIZE_DEFAULT);
365 	mss_spi_enable_controller(cfg);
366 	mss_spi_write(cfg, MSS_SPI_REG_COMMAND, MSS_SPI_COMMAND_FIFO_MASK);
367 
368 	return 0;
369 }
370 
mss_spi_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,bool async,spi_callback_t cb,void * userdata)371 static int mss_spi_transceive(const struct device *dev, const struct spi_config *spi_cfg,
372 			      const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs,
373 			      bool async, spi_callback_t cb, void *userdata)
374 {
375 
376 	const struct mss_spi_config *config = dev->config;
377 	struct mss_spi_data *data = dev->data;
378 	struct spi_context *ctx = &data->ctx;
379 	struct mss_spi_transfer *xfer = &data->xfer;
380 	int ret = 0;
381 
382 	spi_context_lock(ctx, async, cb, userdata, spi_cfg);
383 
384 	ret = mss_spi_configure(dev, spi_cfg);
385 	if (ret) {
386 		LOG_ERR("Fail to configure\n\r");
387 		goto out;
388 	}
389 
390 	spi_context_buffers_setup(ctx, tx_bufs, rx_bufs, 1);
391 	xfer->rx_len = ctx->rx_len;
392 	mss_spi_readwr_fifo(dev);
393 	ret = spi_context_wait_for_completion(ctx);
394 out:
395 	spi_context_release(ctx, ret);
396 	mss_spi_disable_ints(config);
397 	mss_spi_disable_controller(config);
398 
399 	return ret;
400 }
401 
mss_spi_transceive_blocking(const struct device * dev,const struct spi_config * spi_cfg,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs)402 static int mss_spi_transceive_blocking(const struct device *dev, const struct spi_config *spi_cfg,
403 				       const struct spi_buf_set *tx_bufs,
404 				       const struct spi_buf_set *rx_bufs)
405 {
406 
407 	return mss_spi_transceive(dev, spi_cfg, tx_bufs, rx_bufs, false, NULL, NULL);
408 }
409 
410 #ifdef CONFIG_SPI_ASYNC
mss_spi_transceive_async(const struct device * dev,const struct spi_config * spi_cfg,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs,spi_callback_t cb,void * userdata)411 static int mss_spi_transceive_async(const struct device *dev, const struct spi_config *spi_cfg,
412 				    const struct spi_buf_set *tx_bufs,
413 				    const struct spi_buf_set *rx_bufs, spi_callback_t cb,
414 				    void *userdata)
415 {
416 	return mss_spi_transceive(dev, spi_cfg, tx_bufs, rx_bufs, true, cb, userdata);
417 }
418 #endif /* CONFIG_SPI_ASYNC */
419 
mss_spi_init(const struct device * dev)420 static int mss_spi_init(const struct device *dev)
421 {
422 	const struct mss_spi_config *cfg = dev->config;
423 	struct mss_spi_data *data = dev->data;
424 	struct mss_spi_transfer *xfer = &data->xfer;
425 	int ret = 0;
426 	uint32_t control = 0;
427 
428 	/* Remove SPI from Reset  */
429 	control = mss_spi_read(cfg, MSS_SPI_REG_CONTROL);
430 	control &= ~MSS_SPI_CONTROL_RESET;
431 	mss_spi_write(cfg, MSS_SPI_REG_CONTROL, control);
432 
433 	/* Set master mode */
434 	mss_spi_disable_controller(cfg);
435 	xfer->control = (MSS_SPI_CONTROL_SPS | MSS_SPI_CONTROL_BIGFIFO | MSS_SPI_CONTROL_MASTER |
436 			 MSS_SPI_CONTROL_CLKMODE);
437 
438 	spi_context_unlock_unconditionally(&data->ctx);
439 
440 	return ret;
441 }
442 
443 #define MICROCHIP_SPI_PM_OPS (NULL)
444 
445 static const struct spi_driver_api mss_spi_driver_api = {
446 	.transceive = mss_spi_transceive_blocking,
447 #ifdef CONFIG_SPI_ASYNC
448 	.transceive_async = mss_spi_transceive_async,
449 #endif /* CONFIG_SPI_ASYNC */
450 	.release = mss_spi_release,
451 };
452 
453 #define MSS_SPI_INIT(n)                                                                            \
454 	static int mss_spi_init_##n(const struct device *dev)                                      \
455 	{                                                                                          \
456 		mss_spi_init(dev);                                                                 \
457                                                                                                    \
458 		IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), mss_spi_interrupt,          \
459 			    DEVICE_DT_INST_GET(n), 0);                                             \
460                                                                                                    \
461 		irq_enable(DT_INST_IRQN(n));                                                       \
462                                                                                                    \
463 		return 0;                                                                          \
464 	}                                                                                          \
465                                                                                                    \
466 	static const struct mss_spi_config mss_spi_config_##n = {                                  \
467 		.base = DT_INST_REG_ADDR(n),                                                       \
468 		.clock_freq = DT_INST_PROP(n, clock_frequency),                                    \
469 	};                                                                                         \
470                                                                                                    \
471 	static struct mss_spi_data mss_spi_data_##n = {                                            \
472 		SPI_CONTEXT_INIT_LOCK(mss_spi_data_##n, ctx),                                      \
473 		SPI_CONTEXT_INIT_SYNC(mss_spi_data_##n, ctx),                                      \
474 	};                                                                                         \
475                                                                                                    \
476 	DEVICE_DT_INST_DEFINE(n, mss_spi_init_##n, NULL, &mss_spi_data_##n, &mss_spi_config_##n,   \
477 			      POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,                     \
478 			      &mss_spi_driver_api);
479 
480 DT_INST_FOREACH_STATUS_OKAY(MSS_SPI_INIT)
481