1 /**************************************************************************//**
2 *
3 * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Change Logs:
8 * Date            Author           Notes
9 * 2020-5-19       YHKuo            First version
10 *
11 ******************************************************************************/
12 #include <rtconfig.h>
13 
14 #if defined(BSP_USING_QSPI)
15 
16 #define LOG_TAG                 "drv.qspi"
17 #define DBG_ENABLE
18 #define DBG_SECTION_NAME        LOG_TAG
19 #define DBG_LEVEL               DBG_INFO
20 #define DBG_COLOR
21 #include <rtdbg.h>
22 
23 #include <rthw.h>
24 #include <rtdef.h>
25 
26 #include <drv_spi.h>
27 
28 /* Private define ---------------------------------------------------------------*/
29 enum
30 {
31     QSPI_START = -1,
32 #if defined(BSP_USING_QSPI0)
33     QSPI0_IDX,
34 #endif
35 #if defined(BSP_USING_QSPI1)
36     QSPI1_IDX,
37 #endif
38     QSPI_CNT
39 };
40 
41 /* Private typedef --------------------------------------------------------------*/
42 
43 /* Private functions ------------------------------------------------------------*/
44 static rt_err_t nu_qspi_bus_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration);
45 static rt_ssize_t nu_qspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message);
46 static int nu_qspi_register_bus(struct nu_spi *qspi_bus, const char *name);
47 
48 /* Public functions -------------------------------------------------------------*/
49 
50 /* Private variables ------------------------------------------------------------*/
51 static struct rt_spi_ops nu_qspi_poll_ops =
52 {
53     .configure = nu_qspi_bus_configure,
54     .xfer      = nu_qspi_bus_xfer,
55 };
56 
57 static struct nu_spi nu_qspi_arr [] =
58 {
59 #if defined(BSP_USING_QSPI0)
60     {
61         .name = "qspi0",
62         .spi_base = (SPI_T *)QSPI0,
63         .rstidx = QSPI0_RST,
64 #if defined(BSP_USING_SPI_PDMA)
65 #if defined(BSP_USING_QSPI0_PDMA)
66         .pdma_perp_tx = PDMA_QSPI0_TX,
67         .pdma_perp_rx = PDMA_QSPI0_RX,
68 #else
69         .pdma_perp_tx = NU_PDMA_UNUSED,
70         .pdma_perp_rx = NU_PDMA_UNUSED,
71 #endif
72 #endif
73     },
74 #endif
75 #if defined(BSP_USING_QSPI1)
76     {
77         .name = "qspi1",
78         .spi_base = (SPI_T *)QSPI1,
79         .rstidx = QSPI1_RST,
80 #if defined(BSP_USING_SPI_PDMA)
81 #if defined(BSP_USING_QSPI1_PDMA)
82         .pdma_perp_tx = PDMA_QSPI1_TX,
83         .pdma_perp_rx = PDMA_QSPI1_RX,
84 #else
85         .pdma_perp_tx = NU_PDMA_UNUSED,
86         .pdma_perp_rx = NU_PDMA_UNUSED,
87 #endif
88 #endif
89     },
90 #endif
91 }; /* qspi nu_qspi */
92 
nu_qspi_bus_configure(struct rt_spi_device * device,struct rt_spi_configuration * configuration)93 static rt_err_t nu_qspi_bus_configure(struct rt_spi_device *device,
94                                       struct rt_spi_configuration *configuration)
95 {
96     struct nu_spi *spi_bus;
97     rt_uint32_t u32SPIMode;
98     rt_uint32_t u32BusClock;
99     rt_err_t ret = RT_EOK;
100 
101     RT_ASSERT(device != RT_NULL);
102     RT_ASSERT(configuration != RT_NULL);
103 
104     spi_bus = (struct nu_spi *) device->bus;
105 
106     /* Check mode */
107     switch (configuration->mode & RT_SPI_MODE_3)
108     {
109     case RT_SPI_MODE_0:
110         u32SPIMode = SPI_MODE_0;
111         break;
112     case RT_SPI_MODE_1:
113         u32SPIMode = SPI_MODE_1;
114         break;
115     case RT_SPI_MODE_2:
116         u32SPIMode = SPI_MODE_2;
117         break;
118     case RT_SPI_MODE_3:
119         u32SPIMode = SPI_MODE_3;
120         break;
121     default:
122         ret = -RT_EIO;
123         goto exit_nu_qspi_bus_configure;
124     }
125 
126     /* Check data width */
127     if (!(configuration->data_width == 8  ||
128             configuration->data_width == 16 ||
129             configuration->data_width == 24 ||
130             configuration->data_width == 32))
131     {
132         ret = -RT_EINVAL;
133         goto exit_nu_qspi_bus_configure;
134     }
135 
136     /* Try to set clock and get actual spi bus clock */
137     u32BusClock = QSPI_SetBusClock((QSPI_T *)spi_bus->spi_base, configuration->max_hz);
138     if (configuration->max_hz > u32BusClock)
139     {
140         LOG_W("%s clock max frequency is %dHz (!= %dHz)\n", spi_bus->name, u32BusClock, configuration->max_hz);
141         configuration->max_hz = u32BusClock;
142     }
143 
144     /* Need to initialize new configuration? */
145     if (rt_memcmp(configuration, &spi_bus->configuration, sizeof(struct rt_spi_configuration)) != 0)
146     {
147         rt_memcpy(&spi_bus->configuration, configuration, sizeof(struct rt_spi_configuration));
148 
149         QSPI_Open((QSPI_T *)spi_bus->spi_base, SPI_MASTER, u32SPIMode, configuration->data_width, u32BusClock);
150 
151         if (configuration->mode & RT_SPI_CS_HIGH)
152         {
153             /* Set CS pin to LOW */
154             SPI_SET_SS_LOW(spi_bus->spi_base);
155         }
156         else
157         {
158             /* Set CS pin to HIGH */
159             SPI_SET_SS_HIGH(spi_bus->spi_base);
160         }
161 
162         if (configuration->mode & RT_SPI_MSB)
163         {
164             /* Set sequence to MSB first */
165             SPI_SET_MSB_FIRST(spi_bus->spi_base);
166         }
167         else
168         {
169             /* Set sequence to LSB first */
170             SPI_SET_LSB_FIRST(spi_bus->spi_base);
171         }
172     }
173 
174     /* Clear SPI RX FIFO */
175     nu_spi_drain_rxfifo(spi_bus->spi_base);
176 
177 exit_nu_qspi_bus_configure:
178 
179     return -(ret);
180 }
181 
nu_qspi_mode_config(struct nu_spi * qspi_bus,rt_uint8_t * tx,rt_uint8_t * rx,int qspi_lines)182 static int nu_qspi_mode_config(struct nu_spi *qspi_bus, rt_uint8_t *tx, rt_uint8_t *rx, int qspi_lines)
183 {
184     QSPI_T *qspi_base = (QSPI_T *)qspi_bus->spi_base;
185 #if defined(RT_SFUD_USING_QSPI)
186     if (qspi_lines > 1)
187     {
188         if (tx)
189         {
190             switch (qspi_lines)
191             {
192             case 2:
193                 QSPI_ENABLE_DUAL_OUTPUT_MODE(qspi_base);
194                 break;
195             case 4:
196                 QSPI_ENABLE_QUAD_OUTPUT_MODE(qspi_base);
197                 break;
198             default:
199                 LOG_E("Data line is not supported.\n");
200                 break;
201             }
202         }
203         else
204         {
205             switch (qspi_lines)
206             {
207             case 2:
208                 QSPI_ENABLE_DUAL_INPUT_MODE(qspi_base);
209                 break;
210             case 4:
211                 QSPI_ENABLE_QUAD_INPUT_MODE(qspi_base);
212                 break;
213             default:
214                 LOG_E("Data line is not supported.\n");
215                 break;
216             }
217         }
218     }
219     else
220 #endif
221     {
222         QSPI_DISABLE_DUAL_MODE(qspi_base);
223         QSPI_DISABLE_QUAD_MODE(qspi_base);
224     }
225     return qspi_lines;
226 }
227 
nu_qspi_bus_xfer(struct rt_spi_device * device,struct rt_spi_message * message)228 static rt_ssize_t nu_qspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
229 {
230     struct nu_spi *qspi_bus;
231     struct rt_qspi_configuration *qspi_configuration;
232     struct rt_qspi_message *qspi_message;
233     rt_uint8_t u8last = 1;
234     rt_uint8_t bytes_per_word;
235     QSPI_T *qspi_base;
236     rt_ssize_t u32len = 0;
237 
238     RT_ASSERT(device != RT_NULL);
239     RT_ASSERT(message != RT_NULL);
240 
241     qspi_bus = (struct nu_spi *) device->bus;
242     qspi_base = (QSPI_T *)qspi_bus->spi_base;
243     qspi_configuration = &qspi_bus->configuration;
244 
245     bytes_per_word = qspi_configuration->parent.data_width / 8;
246 
247     if (message->cs_take && !(qspi_configuration->parent.mode & RT_SPI_NO_CS))
248     {
249         if (qspi_configuration->parent.mode & RT_SPI_CS_HIGH)
250         {
251             QSPI_SET_SS_HIGH(qspi_base);
252         }
253         else
254         {
255             QSPI_SET_SS_LOW(qspi_base);
256         }
257     }
258 
259     qspi_message = (struct rt_qspi_message *)message;
260 
261     /* Command + Address + Dummy + Data */
262     /* Command stage */
263     if (qspi_message->instruction.content != 0)
264     {
265         u8last = nu_qspi_mode_config(qspi_bus, (rt_uint8_t *) &qspi_message->instruction.content, RT_NULL, qspi_message->instruction.qspi_lines);
266         nu_spi_transfer((struct nu_spi *)qspi_bus,
267                         (rt_uint8_t *) &qspi_message->instruction.content,
268                         RT_NULL,
269                         1,
270                         1);
271     }
272 
273     /* Address stage */
274     if (qspi_message->address.size > 0)
275     {
276         rt_uint32_t u32ReversedAddr = 0;
277         rt_uint32_t u32AddrNumOfByte = qspi_message->address.size / 8;
278         switch (u32AddrNumOfByte)
279         {
280         case 1:
281             u32ReversedAddr = (qspi_message->address.content & 0xff);
282             break;
283         case 2:
284             nu_set16_be((rt_uint8_t *)&u32ReversedAddr, qspi_message->address.content);
285             break;
286         case 3:
287             nu_set24_be((rt_uint8_t *)&u32ReversedAddr, qspi_message->address.content);
288             break;
289         case 4:
290             nu_set32_be((rt_uint8_t *)&u32ReversedAddr, qspi_message->address.content);
291             break;
292         default:
293             RT_ASSERT(0);
294             break;
295         }
296         u8last = nu_qspi_mode_config(qspi_bus, (rt_uint8_t *)&u32ReversedAddr, RT_NULL, qspi_message->address.qspi_lines);
297         nu_spi_transfer((struct nu_spi *)qspi_bus,
298                         (rt_uint8_t *) &u32ReversedAddr,
299                         RT_NULL,
300                         u32AddrNumOfByte,
301                         1);
302     }
303 
304     /* alternate_bytes stage */
305     if ((qspi_message->alternate_bytes.size > 0) && (qspi_message->alternate_bytes.size <= 4))
306     {
307         rt_uint32_t u32AlternateByte = 0;
308         rt_uint32_t u32NumOfByte = qspi_message->alternate_bytes.size / 8;
309         switch (u32NumOfByte)
310         {
311         case 1:
312             u32AlternateByte = (qspi_message->alternate_bytes.content & 0xff);
313             break;
314         case 2:
315             nu_set16_be((rt_uint8_t *)&u32AlternateByte, qspi_message->alternate_bytes.content);
316             break;
317         case 3:
318             nu_set24_be((rt_uint8_t *)&u32AlternateByte, qspi_message->alternate_bytes.content);
319             break;
320         case 4:
321             nu_set32_be((rt_uint8_t *)&u32AlternateByte, qspi_message->alternate_bytes.content);
322             break;
323         default:
324             RT_ASSERT(0);
325             break;
326         }
327         u8last = nu_qspi_mode_config(qspi_bus, (rt_uint8_t *)&u32AlternateByte, RT_NULL, qspi_message->alternate_bytes.qspi_lines);
328         nu_spi_transfer((struct nu_spi *)qspi_bus,
329                         (rt_uint8_t *) &u32AlternateByte,
330                         RT_NULL,
331                         u32NumOfByte,
332                         1);
333     }
334 
335     /* Dummy_cycles stage */
336     if (qspi_message->dummy_cycles > 0)
337     {
338         qspi_bus->dummy = 0x00;
339 
340         u8last = nu_qspi_mode_config(qspi_bus, (rt_uint8_t *) &qspi_bus->dummy, RT_NULL, u8last);
341         nu_spi_transfer((struct nu_spi *)qspi_bus,
342                         (rt_uint8_t *) &qspi_bus->dummy,
343                         RT_NULL,
344                         qspi_message->dummy_cycles / (8 / u8last),
345                         1);
346     }
347 
348     if (message->length > 0)
349     {
350         /* Data stage */
351         nu_qspi_mode_config(qspi_bus, (rt_uint8_t *) message->send_buf, (rt_uint8_t *) message->recv_buf, qspi_message->qspi_data_lines);
352         nu_spi_transfer((struct nu_spi *)qspi_bus,
353                         (rt_uint8_t *) message->send_buf,
354                         (rt_uint8_t *) message->recv_buf,
355                         message->length,
356                         bytes_per_word);
357         u32len = message->length;
358     }
359     else
360     {
361         u32len = 1;
362     }
363 
364     if (message->cs_release && !(qspi_configuration->parent.mode & RT_SPI_NO_CS))
365     {
366         if (qspi_configuration->parent.mode & RT_SPI_CS_HIGH)
367         {
368             QSPI_SET_SS_LOW(qspi_base);
369         }
370         else
371         {
372             QSPI_SET_SS_HIGH(qspi_base);
373         }
374     }
375 
376     return u32len;
377 }
378 
nu_qspi_register_bus(struct nu_spi * qspi_bus,const char * name)379 static int nu_qspi_register_bus(struct nu_spi *qspi_bus, const char *name)
380 {
381     return rt_qspi_bus_register(&qspi_bus->dev, name, &nu_qspi_poll_ops);
382 }
383 
384 /**
385  * Hardware SPI Initial
386  */
rt_hw_qspi_init(void)387 static int rt_hw_qspi_init(void)
388 {
389     rt_uint8_t i;
390 
391     for (i = (QSPI_START + 1); i < QSPI_CNT; i++)
392     {
393         SYS_ResetModule(nu_qspi_arr[i].rstidx);
394 
395         nu_qspi_register_bus(&nu_qspi_arr[i], nu_qspi_arr[i].name);
396 #if defined(BSP_USING_SPI_PDMA)
397         nu_qspi_arr[i].pdma_chanid_tx = -1;
398         nu_qspi_arr[i].pdma_chanid_rx = -1;
399 #endif
400 #if defined(BSP_USING_QSPI_PDMA)
401         if ((nu_qspi_arr[i].pdma_perp_tx != NU_PDMA_UNUSED) && (nu_qspi_arr[i].pdma_perp_rx != NU_PDMA_UNUSED))
402         {
403             if (nu_hw_spi_pdma_allocate(&nu_qspi_arr[i]) != RT_EOK)
404             {
405                 LOG_E("Failed to allocate DMA channels for %s. We will use poll-mode for this bus.\n", nu_qspi_arr[i].name);
406             }
407         }
408 #endif
409     }
410 
411     return 0;
412 }
413 INIT_DEVICE_EXPORT(rt_hw_qspi_init);
414 
nu_qspi_bus_attach_device(const char * bus_name,const char * device_name,rt_uint8_t data_line_width,void (* enter_qspi_mode)(),void (* exit_qspi_mode)())415 rt_err_t nu_qspi_bus_attach_device(const char *bus_name, const char *device_name, rt_uint8_t data_line_width, void (*enter_qspi_mode)(), void (*exit_qspi_mode)())
416 {
417     struct rt_qspi_device *qspi_device = RT_NULL;
418     rt_err_t result = RT_EOK;
419 
420     RT_ASSERT(bus_name != RT_NULL);
421     RT_ASSERT(device_name != RT_NULL);
422     RT_ASSERT(data_line_width == 1 || data_line_width == 2 || data_line_width == 4);
423 
424     qspi_device = (struct rt_qspi_device *)rt_malloc(sizeof(struct rt_qspi_device));
425     if (qspi_device == RT_NULL)
426     {
427         LOG_E("no memory, qspi bus attach device failed!\n");
428         result = -RT_ENOMEM;
429         goto __exit;
430     }
431 
432     qspi_device->enter_qspi_mode = enter_qspi_mode;
433     qspi_device->exit_qspi_mode = exit_qspi_mode;
434     qspi_device->config.qspi_dl_width = data_line_width;
435 
436     result = rt_spi_bus_attach_device(&qspi_device->parent, device_name, bus_name, RT_NULL);
437 
438 __exit:
439     if (result != RT_EOK)
440     {
441         if (qspi_device)
442         {
443             rt_free(qspi_device);
444         }
445     }
446 
447     return  result;
448 }
449 
450 #endif //#if defined(BSP_USING_QSPI)
451