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