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