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