1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2020-08-07 NU-LL first version
9 */
10 #include <rtthread.h>
11 #include <board.h>
12 #include <drv_qspi.h>
13 #include <rtdevice.h>
14 #include <rthw.h>
15 #include <finsh.h>
16
17 #ifdef BSP_USING_QSPI_FLASH
18
19 #include <fal.h>
20 #include <sfud.h>
21 #include "dfs_fs.h"
22 #include "drv_spi.h"
23 #include "dev_spi_flash.h"
24 #include "dev_spi_flash_sfud.h"
25
26 //#define DRV_DEBUG
27 #define LOG_TAG "drv.qspiflash"
28 #include <drv_log.h>
29
30
31 #define FS_PARTITION_NAME "fs_qspi"
32 #define FAL_USING_NOR_FLASH_2_DEV_NAME "W25Q64_q"
33
34
35 static sfud_flash_t sfud_dev = NULL;
36
37 static int init(void);
38 static int read(long offset, rt_uint8_t *buf, rt_size_t size);
39 static int write(long offset, const rt_uint8_t *buf, rt_size_t size);
40 static int erase(long offset, rt_size_t size);
41
42 struct fal_flash_dev nor_flash1 =
43 {
44 .name = FAL_USING_NOR_FLASH_2_DEV_NAME,
45 .addr = 0,
46 .len = 8 * 1024 * 1024,
47 .blk_size = 4096,
48 .ops = {init, read, write, erase},
49 .write_gran = 4
50 };
51
init(void)52 static int init(void)
53 {
54
55 #ifdef RT_USING_SFUD
56 /* RT-Thread RTOS platform */
57 sfud_dev = rt_sfud_flash_find_by_dev_name(FAL_USING_NOR_FLASH_2_DEV_NAME);
58 #else
59 /* bare metal platform */
60 extern sfud_flash nor_flash1;
61 sfud_dev = &nor_flash1;
62 #endif
63
64 if (NULL == sfud_dev)
65 {
66 return -1;
67 }
68
69 /* update the flash chip information */
70 nor_flash1.blk_size = sfud_dev->chip.erase_gran;
71 nor_flash1.len = sfud_dev->chip.capacity;
72
73 return 0;
74 }
75
read(long offset,rt_uint8_t * buf,rt_size_t size)76 static int read(long offset, rt_uint8_t *buf, rt_size_t size)
77 {
78 RT_ASSERT(sfud_dev);
79 RT_ASSERT(sfud_dev->init_ok);
80 sfud_read(sfud_dev, nor_flash1.addr + offset, size, buf);
81
82 return size;
83 }
84
write(long offset,const rt_uint8_t * buf,rt_size_t size)85 static int write(long offset, const rt_uint8_t *buf, rt_size_t size)
86 {
87 RT_ASSERT(sfud_dev);
88 RT_ASSERT(sfud_dev->init_ok);
89 if (sfud_write(sfud_dev, nor_flash1.addr + offset, size, buf) != SFUD_SUCCESS)
90 {
91 return -1;
92 }
93
94 return size;
95 }
96
erase(long offset,rt_size_t size)97 static int erase(long offset, rt_size_t size)
98 {
99 RT_ASSERT(sfud_dev);
100 RT_ASSERT(sfud_dev->init_ok);
101 if (sfud_erase(sfud_dev, nor_flash1.addr + offset, size) != SFUD_SUCCESS)
102 {
103 return -1;
104 }
105
106 return size;
107 }
108
109
110
111
112
113
114
115
116
w25qxx_read_status_register2(struct rt_qspi_device * device)117 char w25qxx_read_status_register2(struct rt_qspi_device *device)
118 {
119 /* 0x35 read status register2 */
120 char instruction = 0x35, status;
121
122 rt_qspi_send_then_recv(device, &instruction, 1, &status, 1);
123
124 return status;
125 }
126
w25qxx_write_enable(struct rt_qspi_device * device)127 void w25qxx_write_enable(struct rt_qspi_device *device)
128 {
129 /* 0x06 write enable */
130 char instruction = 0x06;
131
132 rt_qspi_send(device, &instruction, 1);
133 }
134
w25qxx_enter_qspi_mode(struct rt_qspi_device * device)135 void w25qxx_enter_qspi_mode(struct rt_qspi_device *device)
136 {
137 char status = 0;
138 /* 0x38 enter qspi mode */
139 char instruction = 0x38;
140 char write_status2_buf[2] = {0};
141
142 /* 0x31 write status register2 */
143 write_status2_buf[0] = 0x31;
144
145 status = w25qxx_read_status_register2(device);
146 if (!(status & 0x02))
147 {
148 status |= 1 << 1;
149 w25qxx_write_enable(device);
150 write_status2_buf[1] = status;
151 rt_qspi_send(device, &write_status2_buf, 2);
152 rt_qspi_send(device, &instruction, 1);
153 rt_kprintf("flash already enter qspi mode\n");
154 rt_thread_mdelay(10);
155 }
156 }
157
rt_qspi_flash_init(void)158 static int rt_qspi_flash_init(void)
159 {
160 extern rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const char *spi_dev_name);
161
162 rt_hw_qspi_device_attach("qspi1", "qspi10", RT_NULL, 4, w25qxx_enter_qspi_mode, RT_NULL);
163 if (RT_NULL == rt_sfud_flash_probe(FAL_USING_NOR_FLASH_2_DEV_NAME, "qspi10"))
164 {
165 LOG_E("Failed to probe flash device "FAL_USING_NOR_FLASH_2_DEV_NAME);
166 return -RT_ERROR;
167 }
168 return RT_EOK;
169 }
170 INIT_DEVICE_EXPORT(rt_qspi_flash_init);
171
172
173 #endif/* BSP_USING_QSPI_FLASH */
174