1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2021-04-11     Carl      the first version
9  */
10 
11 #include "drv_qspi.h"
12 #include <rtthread.h>
13 #include "rtdevice.h"
14 #include "ft_qspi.h"
15 #include "ft_parameters.h"
16 
17 #ifdef BSP_USE_QSPI
18 
19 #define DRV_DEBUG
20 #define LOG_TAG "drv.qspi"
21 #include <drv_log.h>
22 
23 struct ft2004_qspi_bus
24 {
25     FQSpi_t fqspi;
26     char *name;
27     rt_uint32_t init; /* 1 is init already   */
28 };
29 
30 static struct rt_spi_bus _qspi_bus;
31 static struct ft2004_qspi_bus _ft2004_qspi_bus;
32 
ft2004_qspi_init(struct rt_qspi_device * device,struct rt_qspi_configuration * qspi_cfg)33 static int ft2004_qspi_init(struct rt_qspi_device *device, struct rt_qspi_configuration *qspi_cfg)
34 {
35 
36     RT_ASSERT(device != RT_NULL);
37     RT_ASSERT(qspi_cfg != RT_NULL);
38 
39     // struct rt_spi_configuration *cfg = &qspi_cfg->parent;
40     struct ft2004_qspi_bus *qspi_bus_p = device->parent.bus->parent.user_data;
41 
42     if (qspi_bus_p->init == 0)
43     {
44         qspi_bus_p->init = 1;
45         FQSpi_CfgInitialize(&qspi_bus_p->fqspi, FQSpi_LookupConfig(0));
46     }
47 
48     return RT_EOK;
49 }
50 
ft2004_cmdOperation(struct ft2004_qspi_bus * qspi_bus_p,struct rt_spi_message * message)51 static rt_err_t ft2004_cmdOperation(struct ft2004_qspi_bus *qspi_bus_p, struct rt_spi_message *message)
52 {
53     struct rt_qspi_message *qspi_message = (struct rt_qspi_message *)message;
54     const rt_uint8_t *sndb = message->send_buf;
55     rt_uint8_t *rcvb = message->recv_buf;
56     ft_error_t ret;
57     RT_ASSERT(qspi_bus_p != RT_NULL);
58     RT_ASSERT(message != RT_NULL);
59 
60     struct FQSpi_CmdPack cmd_pack = {0};
61 
62     if (qspi_message->instruction.qspi_lines == 0)
63     {
64         LOG_E("instruction is not valid");
65         return -RT_ERROR;
66     }
67 
68     cmd_pack.cmd = qspi_message->instruction.content;
69 
70     if (qspi_message->address.qspi_lines != 0)
71     {
72         cmd_pack.flags |= FQSPI_CMD_NEED_ADDR_MASK;
73         cmd_pack.addr = qspi_message->address.content;
74     }
75 
76     if (qspi_message->address.size == 24)
77     {
78         cmd_pack.flags |= FQSPI_CMD_ADDRESS_3BYTE_MASK;
79     }
80     else if (qspi_message->address.size == 32)
81     {
82         cmd_pack.flags |= FQSPI_CMD_ADDRESS_4BYTE_MASK;
83     }
84 
85     if (qspi_message->qspi_data_lines != 0)
86     {
87         if (sndb && (message->length > 0))
88         {
89             cmd_pack.flags |= FQSPI_CMD_NEED_SET_MASK;
90             cmd_pack.txBuf = sndb;
91             cmd_pack.length = message->length;
92         }
93         else if (rcvb && (message->length > 0))
94         {
95             cmd_pack.flags |= FQSPI_CMD_NEED_GET_MASK;
96             cmd_pack.rxBuf = rcvb;
97             cmd_pack.length = message->length;
98         }
99         else
100         {
101             cmd_pack.flags &= ~(FQSPI_CMD_NEED_GET_MASK | FQSPI_CMD_NEED_SET_MASK);
102         }
103     }
104 
105     if (qspi_message->dummy_cycles)
106     {
107         cmd_pack.flags |= FQSPI_CMD_NEED_DUMMY_MASK;
108         cmd_pack.dummyCycle = qspi_message->dummy_cycles;
109     }
110 
111     if (cmd_pack.cmd == 0x20)
112     {
113         if (qspi_message->address.size == 32)
114         {
115             cmd_pack.cmd = 0xdc;
116         }
117     }
118 
119 #ifdef BSP_QSPI_DEBUG
120     LOG_I("flags %x", cmd_pack.flags);
121 #endif
122 
123     ret = FQSpi_CmdOperation(&qspi_bus_p->fqspi, &cmd_pack);
124 
125 #ifdef BSP_QSPI_DEBUG
126     if (ret == FQSPI_SUCCESS)
127         if (cmd_pack.cmd == 5)
128         {
129             LOG_I("cmd05 0x%x", cmd_pack.rxBuf[0]);
130         }
131 #endif
132 
133     return (ret == FQSPI_SUCCESS) ? RT_EOK : -RT_ERROR;
134 }
135 
ft2004_qspi_xfer(struct ft2004_qspi_bus * qspi_bus_p,struct rt_spi_message * message)136 static rt_ssize_t ft2004_qspi_xfer(struct ft2004_qspi_bus *qspi_bus_p, struct rt_spi_message *message)
137 {
138     struct rt_qspi_message *qspi_message = (struct rt_qspi_message *)message;
139     rt_ssize_t ret_length = 0;
140     const rt_uint8_t *sndb = message->send_buf;
141     rt_uint8_t *rcvb = message->recv_buf;
142     rt_int32_t length = message->length;
143     rt_uint32_t cmd;
144     rt_uint32_t addr;
145     FQSpi_t *qspi_p;
146     FQSpi_Config_t *qspi_config_p;
147     struct FQSpi_DataPack data_pack = {0};
148     qspi_p = &qspi_bus_p->fqspi;
149     qspi_config_p = &qspi_bus_p->fqspi.config;
150 
151     cmd = qspi_message->instruction.content;
152     addr = qspi_message->address.content;
153 
154 #ifdef BSP_QSPI_DEBUG
155     LOG_I("cmd is %x ", cmd);
156     LOG_I("length %d , rcvb %x sndb %x addr %x dummy_cycles %x ", length, rcvb, sndb, addr, qspi_message->dummy_cycles);
157 #endif
158 
159     if (qspi_config_p->channel >= FT_QSPI_MAX_CS_NUM)
160     {
161         LOG_E("invalid channel[%x] ", qspi_config_p->channel);
162         return -RT_ERROR;
163     }
164     switch (cmd)
165     {
166     case FQSPI_FLASH_CMD_PP:
167     {
168         if (RT_NULL != sndb)
169         {
170             data_pack.cmd = cmd;
171             data_pack.addr = addr;
172             if (qspi_message->address.size == 24)
173             {
174                 data_pack.flags |= FQSPI_DATA_ADDRESS_3BYTE_MASK;
175             }
176             else
177             {
178                 data_pack.flags |= FQSPI_DATA_ADDRESS_4BYTE_MASK;
179             }
180 
181             LOG_E("write flags %x ", data_pack.flags);
182             data_pack.txBuf = sndb;
183             data_pack.length = length;
184             ret_length = ((FQSpi_Write(qspi_p, &data_pack) == FQSPI_SUCCESS) ? length : 0);
185         }
186         else
187         {
188             LOG_E("pp cmd %x sndb is null", cmd);
189             ret_length = 0;
190         }
191     }
192     break;
193     case FQSPI_FLASH_CMD_WRDI: /* for sufd qspi fast read */
194         FQSpi_FlashRegSet(qspi_p, cmd, RT_NULL, 0);
195     case FQSPI_FLASH_CMD_READ:
196     {
197         if (RT_NULL != rcvb)
198         {
199             data_pack.cmd = FQSPI_FLASH_CMD_READ;
200             data_pack.addr = addr;
201             if (qspi_message->address.size == 24)
202             {
203                 data_pack.flags |= FQSPI_DATA_ADDRESS_3BYTE_MASK;
204             }
205             else
206             {
207                 data_pack.flags |= FQSPI_DATA_ADDRESS_4BYTE_MASK;
208             }
209 
210             if (qspi_message->dummy_cycles)
211             {
212                 data_pack.flags |= FQSPI_DATA_NEED_DUMMY_MASK;
213                 data_pack.dummyCycle = qspi_message->dummy_cycles;
214             }
215             data_pack.rxBuf = rcvb;
216             data_pack.length = length;
217 
218             ret_length = ((FQSpi_Read(qspi_p, &data_pack) == FQSPI_SUCCESS) ? length : 0);
219         }
220         else
221         {
222             // LOG_E("read cmd %x rcvb is null", cmd);
223             ret_length = 0;
224         }
225     }
226     break;
227 
228     default:
229     {
230         if (ft2004_cmdOperation(qspi_bus_p, message) == RT_EOK)
231         {
232             ret_length = 1;
233         }
234         else
235         {
236             LOG_E("ft2004_cmdOperation error");
237             ret_length = 0;
238         }
239     }
240     }
241 
242     return ret_length;
243 }
244 
qspixfer(struct rt_spi_device * device,struct rt_spi_message * message)245 static rt_uint32_t qspixfer(struct rt_spi_device *device, struct rt_spi_message *message)
246 {
247     RT_ASSERT(device != RT_NULL);
248     RT_ASSERT(device->bus != RT_NULL);
249     struct ft2004_qspi_bus *qspi_bus_p = device->bus->parent.user_data;
250 
251     return ft2004_qspi_xfer(qspi_bus_p, message);
252 }
253 
qspi_configure(struct rt_spi_device * device,struct rt_spi_configuration * configuration)254 static rt_err_t qspi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration)
255 {
256     RT_ASSERT(device != RT_NULL);
257     RT_ASSERT(configuration != RT_NULL);
258 
259     struct rt_qspi_device *qspi_device = (struct rt_qspi_device *)device;
260     return ft2004_qspi_init(qspi_device, &qspi_device->config);
261 }
262 
263 static const struct rt_spi_ops ft2004_qspi_ops =
264     {
265         .configure = qspi_configure,
266         .xfer = qspixfer,
267 };
268 
ft2004_qspi_register_bus(struct ft2004_qspi_bus * qspi_bus,const char * name)269 static int ft2004_qspi_register_bus(struct ft2004_qspi_bus *qspi_bus, const char *name)
270 {
271     RT_ASSERT(qspi_bus != RT_NULL);
272     RT_ASSERT(name != RT_NULL);
273 
274     _qspi_bus.parent.user_data = qspi_bus;
275     return rt_qspi_bus_register(&_qspi_bus, name, &ft2004_qspi_ops);
276 }
277 
ft2004_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)())278 rt_err_t ft2004_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)())
279 {
280     struct rt_qspi_device *qspi_device = RT_NULL;
281     rt_err_t result = RT_EOK;
282 
283     RT_ASSERT(bus_name != RT_NULL);
284     RT_ASSERT(device_name != RT_NULL);
285     RT_ASSERT(data_line_width == 1 || data_line_width == 2 || data_line_width == 4);
286 
287     qspi_device = (struct rt_qspi_device *)rt_malloc(sizeof(struct rt_qspi_device));
288     if (qspi_device == RT_NULL)
289     {
290         LOG_E("no memory, qspi bus attach device failed!");
291         result = -RT_ENOMEM;
292         goto __exit;
293     }
294 
295     qspi_device->enter_qspi_mode = enter_qspi_mode;
296     qspi_device->exit_qspi_mode = exit_qspi_mode;
297     qspi_device->config.qspi_dl_width = data_line_width;
298 
299     result = rt_spi_bus_attach_device(&qspi_device->parent, device_name, bus_name, RT_NULL);
300 
301 __exit:
302     if (result != RT_EOK)
303     {
304         if (qspi_device)
305         {
306             rt_free(qspi_device);
307         }
308     }
309 
310     return result;
311 }
312 
rt_hw_qspi_bus_init(void)313 static int rt_hw_qspi_bus_init(void)
314 {
315     return ft2004_qspi_register_bus(&_ft2004_qspi_bus, FT2004_QSPI_NAME);
316 }
317 INIT_BOARD_EXPORT(rt_hw_qspi_bus_init);
318 #ifdef BSP_QSPI_DEBUG
cmd05_check(void)319 static void cmd05_check(void)
320 {
321     struct FQSpi_CmdPack cmd_pack = {0};
322     u8 rx_buffer[1];
323 
324     cmd_pack.cmd = 0x6;
325     FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
326 
327     rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
328     cmd_pack.cmd = 0x5;
329     cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
330     cmd_pack.rxBuf = rx_buffer;
331     cmd_pack.length = sizeof(rx_buffer);
332 
333     FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
334 
335     for (u32 i = 0; i < cmd_pack.length; i++)
336     {
337         LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
338     }
339 
340     rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
341     cmd_pack.cmd = 0x4;
342     FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
343 
344     rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
345     cmd_pack.cmd = 0x5;
346     cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
347     cmd_pack.rxBuf = rx_buffer;
348     cmd_pack.length = sizeof(rx_buffer);
349 
350     FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
351 
352     for (u32 i = 0; i < cmd_pack.length; i++)
353     {
354         LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
355     }
356 }
357 MSH_CMD_EXPORT_ALIAS(cmd05_check, cmd05_check, cmd05_check);
358 #endif
359 
360 #ifdef BSP_QSPI_DEBUG
cmd35_check(void)361 static void cmd35_check(void)
362 {
363     struct FQSpi_CmdPack cmd_pack = {0};
364     u8 rx_buffer[1];
365 
366     cmd_pack.cmd = 0x6;
367     FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
368 
369     rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
370     cmd_pack.cmd = 0x5;
371     cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
372     cmd_pack.rxBuf = rx_buffer;
373     cmd_pack.length = sizeof(rx_buffer);
374 
375     FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
376 
377     for (u32 i = 0; i < cmd_pack.length; i++)
378     {
379         LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
380     }
381 
382     cmd_pack.cmd = 0xB7;
383     FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
384 
385     rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
386     cmd_pack.cmd = 0x35;
387     cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
388     cmd_pack.rxBuf = rx_buffer;
389     cmd_pack.length = sizeof(rx_buffer);
390 
391     FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
392 
393     for (u32 i = 0; i < cmd_pack.length; i++)
394     {
395         LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
396     }
397 }
398 MSH_CMD_EXPORT_ALIAS(cmd35_check, cmd35_check, cmd35_check);
399 #endif
400 #ifdef BSP_QSPI_DEBUG
cmd15_check(void)401 static void cmd15_check(void)
402 {
403     struct FQSpi_CmdPack cmd_pack = {0};
404     u8 rx_buffer[1];
405 
406     // cmd_pack.cmd = 0xB7;
407     // FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
408 
409     rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
410     cmd_pack.cmd = 0x15;
411     cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
412     cmd_pack.rxBuf = rx_buffer;
413     cmd_pack.length = sizeof(rx_buffer);
414 
415     FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
416 
417     for (u32 i = 0; i < cmd_pack.length; i++)
418     {
419         LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
420     }
421 }
422 MSH_CMD_EXPORT_ALIAS(cmd15_check, cmd15_check, cmd15_check);
423 #endif
424 #endif
425