1 /*
2 * Copyright (c) 2022 Winner Microelectronics Co., Ltd. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 /**
17 * @file wm_fls_gd25qxx.c
18 *
19 * @brief gd25qxx flash Driver Module
20 *
21 * @author dave
22 *
23 * Copyright (c) 2015 Winner Microelectronics Co., Ltd.
24 */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include "wm_type_def.h"
29 #include "wm_flash.h"
30 #include "wm_hostspi.h"
31 #include "wm_debug.h"
32 #include "wm_gpio.h"
33 #include "wm_fls_gd25qxx.h"
34
35 static int tls_spifls_drv_read(u32 addr, u8 *buf, u32 len);
36 static int tls_spifls_drv_fast_read(u32 addr, u8 *buf, u32 len);
37 static int tls_spifls_drv_page_write(u32 page, u8 *buf);
38 static int tls_spifls_drv_erase(u32 sector);
39 static int tls_spifls_drv_chip_erase(void);
40 static int tls_spifls_drv_probe(u32 id);
41 static void tls_spifls_drv_remove(void);
42
43 static struct tls_fls_drv exspi_fls = {
44 .drv_list = {NULL, NULL},
45 .clock = SPI_SCLK,
46 .mode = TLS_SPI_MODE_0,
47 .cs_active = TLS_SPI_CS_LOW,
48 .flags = 0,
49 .read = tls_spifls_drv_read,
50 .fast_read = tls_spifls_drv_fast_read,
51 .page_write = tls_spifls_drv_page_write,
52 .erase = tls_spifls_drv_erase,
53 .chip_erase = tls_spifls_drv_chip_erase,
54 .probe = tls_spifls_drv_probe,
55 .remove = tls_spifls_drv_remove
56 };
57
58 static struct tls_fls_drv *exspifls_drv = NULL;
59
swap32(unsigned int v)60 static unsigned int swap32(unsigned int v)
61 {
62 return ((v & 0xff) << 24) | ((v & 0xff00) << 8) |
63 ((v & 0xff0000) >> 8) | (v >> 24);
64 }
65
tls_spifls_drv_write_enable(void)66 static int tls_spifls_drv_write_enable(void)
67 {
68 u8 cmd;
69 int err;
70
71 cmd = EXSPIFLASH_WRITE_ENABLE;
72
73 err = tls_spi_write((const u8 *) &cmd, 1);
74 if (err != TLS_SPI_STATUS_OK) {
75 return TLS_FLS_STATUS_EIO;
76 }
77
78 return TLS_FLS_STATUS_OK;
79 }
80
tls_spifls_drv_wait_write_enable(void)81 static int tls_spifls_drv_wait_write_enable(void)
82 {
83 u8 cmd;
84 u8 sr;
85
86 cmd = EXSPIFLASH_READ_SR1;
87 sr = 0;
88 do {
89 int err = tls_spi_read_with_cmd((const u8 *) &cmd, 1, &sr, 1);
90 if (err != TLS_SPI_STATUS_OK) {
91 return TLS_FLS_STATUS_EIO;
92 }
93
94 if (sr & FLASH_STATUS_WEL) {
95 break;
96 }
97 }while (1);
98
99 return TLS_FLS_STATUS_OK;
100 }
101
tls_spifls_drv_wait_flash_ready(void)102 static int tls_spifls_drv_wait_flash_ready(void)
103 {
104 u8 cmd;
105 u8 sr;
106
107 cmd = EXSPIFLASH_READ_SR1;
108 sr = 0;
109 do {
110 int err = tls_spi_read_with_cmd((const u8 *) &cmd, 1, &sr, 1);
111 if (err != TLS_SPI_STATUS_OK) {
112 return TLS_FLS_STATUS_EIO;
113 }
114
115 if ((sr & FLASH_STATUS_BUSY) == 0x00) {
116 break;
117 }
118 }while (1);
119
120 return TLS_FLS_STATUS_OK;
121 }
122
tls_spifls_drv_read(u32 addr,u8 * buf,u32 len)123 static int tls_spifls_drv_read(u32 addr, u8 * buf, u32 len)
124 {
125 u32 cmd;
126 int err;
127
128 cmd = 0;
129 cmd |= EXSPIFLASH_DATA_READ;
130 cmd |= swap32(addr) & 0xffffff00;
131 err = tls_spi_read_with_cmd((const u8 *) &cmd, 4, buf, len);
132 if (err != TLS_SPI_STATUS_OK) {
133 return TLS_FLS_STATUS_EIO;
134 }
135
136 return TLS_FLS_STATUS_OK;
137 }
138
tls_spifls_drv_fast_read(u32 addr,u8 * buf,u32 len)139 static int tls_spifls_drv_fast_read(u32 addr, u8 * buf, u32 len)
140 {
141 return TLS_FLS_STATUS_ENOSUPPORT;
142 }
143
tls_spifls_drv_page_write(u32 page,u8 * buf)144 static int tls_spifls_drv_page_write(u32 page, u8 * buf)
145 {
146 u32 cmd;
147 int err;
148
149 err = tls_spifls_drv_write_enable();
150 if (err != TLS_SPI_STATUS_OK) {
151 return TLS_FLS_STATUS_EIO;
152 }
153
154 err = tls_spifls_drv_wait_write_enable();
155 if (err != TLS_SPI_STATUS_OK) {
156 return TLS_FLS_STATUS_EIO;
157 }
158
159 cmd = 0;
160 cmd |= EXSPIFLASH_PAGE_PROGRAM;
161 cmd |= swap32(page * exspifls_drv->page_size) & 0xffffff00;
162 err = tls_spi_write_with_cmd((const u8 *) &cmd, 4, (const u8 *) buf,
163 exspifls_drv->page_size);
164 if (err != TLS_SPI_STATUS_OK) {
165 return TLS_FLS_STATUS_EIO;
166 }
167
168 err = tls_spifls_drv_wait_flash_ready();
169 if (err != TLS_SPI_STATUS_OK) {
170 return TLS_FLS_STATUS_EIO;
171 }
172
173 return TLS_FLS_STATUS_OK;
174 }
175
tls_spifls_drv_erase(u32 sector)176 static int tls_spifls_drv_erase(u32 sector)
177 {
178 u32 cmd;
179 int err;
180
181 err = tls_spifls_drv_write_enable();
182 if (err != TLS_SPI_STATUS_OK) {
183 return TLS_FLS_STATUS_EIO;
184 }
185 err = tls_spifls_drv_wait_write_enable();
186 if (err != TLS_SPI_STATUS_OK) {
187 return TLS_FLS_STATUS_EIO;
188 }
189 cmd = 0;
190 cmd |= EXSPIFLASH_SECTOR_ERASE;
191 cmd |= swap32(sector * exspifls_drv->sector_size) & 0xffffff00;
192 err = tls_spi_write((const u8 *) &cmd, 4);
193 if (err != TLS_SPI_STATUS_OK) {
194 return TLS_FLS_STATUS_EIO;
195 }
196 tls_os_time_delay(6);
197 err = tls_spifls_drv_wait_flash_ready();
198 if (err != TLS_SPI_STATUS_OK) {
199 return TLS_FLS_STATUS_EIO;
200 }
201 return TLS_FLS_STATUS_OK;
202 }
203
tls_spifls_drv_chip_erase(void)204 static int tls_spifls_drv_chip_erase(void)
205 {
206 u8 cmd;
207 int err;
208
209 err = tls_spifls_drv_write_enable();
210 if (err != TLS_SPI_STATUS_OK) {
211 return TLS_FLS_STATUS_EIO;
212 }
213
214 err = tls_spifls_drv_wait_write_enable();
215 if (err != TLS_SPI_STATUS_OK) {
216 return TLS_FLS_STATUS_EIO;
217 }
218
219 cmd = EXSPIFLASH_CHIP_ERASE;
220 err = tls_spi_write((const u8 *) &cmd, 1);
221 if (err != TLS_SPI_STATUS_OK) {
222 return TLS_FLS_STATUS_EIO;
223 }
224
225 err = tls_spifls_drv_wait_flash_ready();
226 if (err != TLS_SPI_STATUS_OK) {
227 return TLS_FLS_STATUS_EIO;
228 }
229
230 return TLS_FLS_STATUS_OK;
231 }
232
tls_spifls_drv_probe(u32 id)233 static int tls_spifls_drv_probe(u32 id)
234 {
235 if (!id) {
236 return TLS_FLS_STATUS_EINVAL;
237 }
238
239 exspi_fls.id = id;
240 if ((id>>16)&0xFF) {
241 exspi_fls.total_size = 1 << (id>>16);
242 } else {
243 exspi_fls.total_size = FLASH_TOTAL_SIZE; /* 1MByte */
244 }
245
246 exspi_fls.page_size = PAGE_SIZE;
247 exspi_fls.program_size = PROGRAM_SIZE;
248 exspi_fls.sector_size = SECTOR_SIZE;
249 exspifls_drv = &exspi_fls;
250 return TLS_FLS_STATUS_OK;
251 }
252
tls_spifls_drv_remove(void)253 static void tls_spifls_drv_remove(void)
254 {
255 exspifls_drv = NULL;
256 }
257
258 /**
259 * @brief This function is used to install gd25qxx driver.
260 *
261 * @param[in] None
262 *
263 * @retval TLS_FLS_STATUS_OK if write flash success
264 * @retval TLS_FLS_STATUS_EPERM if flash struct point is null
265 * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed
266 * @retval TLS_FLS_STATUS_EINVAL if argument is invalid
267 * @retval TLS_FLS_STATUS_EIO if io error
268 * @retval TLS_FLS_STATUS_EEXIST if driver is already existed
269 *
270 * @note None
271 */
tls_spifls_drv_install(void)272 int tls_spifls_drv_install(void)
273 {
274 int err;
275 extern int tls_spifls_probe(void);
276 extern int tls_spifls_drv_register(struct tls_fls_drv *fls_drv);
277
278 err = tls_spifls_drv_register((struct tls_fls_drv *) &exspi_fls);
279 if (err == TLS_FLS_STATUS_EEXIST) {
280 return err;
281 }
282 TLS_DBGPRT_INFO("register the spi flash driver - %d.\n", err);
283
284 err = tls_spifls_probe();
285 TLS_DBGPRT_INFO("probe spi flash - %d.\n", err);
286
287 return err;
288 }