• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Talkweb Co., Ltd.
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 #include "w25qxx.h"
17 
18 #define W25x_PageSize              256
19 #define W25x_PerWritePageSize      256
20 #define W25X_WriteEnable           0x06
21 #define W25X_WriteDisable          0x04
22 #define W25X_ReadStatusReg         0x05
23 #define W25X_WriteStatusReg        0x01
24 #define W25X_ReadData              0x03
25 #define W25X_FastReadData          0x0B
26 #define W25X_FastReadDual          0x3B
27 #define W25X_PageProgram           0x02
28 #define W25X_BlockErase            0xD8
29 #define W25X_SectorErase           0x20
30 #define W25X_ChipErase             0xC7
31 #define W25X_PowerDown             0xB9
32 #define W25X_ReleasePowerDown      0xAB
33 #define W25X_DeviceID              0xAB
34 #define W25X_ManufactDeviceID      0x90
35 #define W25X_JedecDeviceID         0x9F
36 
37 #define WIP_Flag                   0x01
38 
39 #define Dummy_Byte                 0xFF
40 
41 #ifdef LOSCFG_DRIVERS_HDF_PLATFORM_SPI
42 DevHandle spiHandle = NULL;
W25x_InitSpiFlash(uint32_t busNum,uint32_t csNum)43 uint8_t W25x_InitSpiFlash(uint32_t busNum, uint32_t csNum)
44 {
45     struct SpiDevInfo spiDevinfo;
46     spiDevinfo.busNum = busNum;
47     spiDevinfo.csNum = csNum;
48     spiHandle = SpiOpen(&spiDevinfo);
49     if (spiHandle == NULL) {
50         HDF_LOGE("SpiOpen: failed\n");
51         return HDF_FAILURE;
52     }
53 
54     return HDF_SUCCESS;
55 }
56 
W25x_DeInitSpiFlash(void)57 uint8_t W25x_DeInitSpiFlash(void)
58 {
59     if (spiHandle != NULL) {
60         SpiClose(spiHandle);
61     }
62 
63     return HDF_SUCCESS;
64 }
65 
W25x_GetSpiHandle(void)66 DevHandle W25x_GetSpiHandle(void)
67 {
68     return spiHandle;
69 }
70 
W25x_SectorErase(uint32_t SectorAddr)71 void W25x_SectorErase(uint32_t SectorAddr)
72 {
73     if (spiHandle == NULL) {
74         HDF_LOGE("spi flash haven't been inited\n");
75         return;
76     }
77     W25x_WriteEnable();
78     W25x_WaitForWriteEnd();
79     uint8_t wbuf[4] = {0x20, (SectorAddr & 0xff0000) >> 16, (SectorAddr & 0xff00) >> 8, (SectorAddr & 0xff)};
80     uint8_t rbuf[4] = {0};
81     struct SpiMsg msg = {0};
82     msg.wbuf = wbuf;
83     msg.rbuf = rbuf;
84     msg.len = sizeof(wbuf);
85     msg.keepCs = 0;
86     msg.delayUs = 0;
87     int32_t ret = SpiTransfer(spiHandle, &msg, 1);
88     if (ret != 0) {
89         HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
90         return;
91     }
92     W25x_WaitForWriteEnd();
93 }
94 
W25x_BulkErase(void)95 void W25x_BulkErase(void)
96 {
97     if (spiHandle == NULL) {
98         HDF_LOGE("spi flash haven't been inited\n");
99         return;
100     }
101     W25x_WriteEnable();
102     uint8_t wbuf[1] = {W25X_ChipErase};
103     uint8_t rbuf[1] = {0};
104     struct SpiMsg msg = {0};
105     msg.wbuf = wbuf;
106     msg.rbuf = rbuf;
107     msg.len = sizeof(wbuf);
108     msg.keepCs = 0;
109     msg.delayUs = 0;
110     int32_t ret = SpiTransfer(spiHandle, &msg, 1);
111     if (ret != 0) {
112         HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
113         return;
114     }
115     W25x_WaitForWriteEnd();
116     return;
117 }
118 
W25x_PageWrite(uint8_t * pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)119 void W25x_PageWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
120 {
121     if (spiHandle == NULL) {
122         HDF_LOGE("spi flash haven't been inited\n");
123         return;
124     }
125     W25x_WriteEnable();
126     uint8_t wbuf[4] = {W25X_PageProgram, (WriteAddr & 0xff0000) >> 16, (WriteAddr & 0xff00) >> 8, (WriteAddr & 0xff)};
127     uint8_t rbuf[4] = {0};
128     uint8_t *rbuf1 = NULL;
129     int32_t ret = 0;
130 
131     struct SpiMsg msg = {0};
132     msg.wbuf = wbuf;
133     msg.rbuf = rbuf;
134     msg.len = sizeof(wbuf);
135     msg.keepCs = 1;
136     msg.delayUs = 0;
137     ret = SpiTransfer(spiHandle, &msg, 1);
138     if (ret != 0) {
139         HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
140     }
141 
142     if (NumByteToWrite > W25x_PerWritePageSize) {
143             NumByteToWrite = W25x_PerWritePageSize;
144             HDF_LOGE("Err: W25x_PageWrite too large!\n");
145     }
146 
147     rbuf1 = (uint8_t*)OsalMemAlloc(NumByteToWrite);
148     if (rbuf1 == NULL) {
149         HDF_LOGE("malloc failed\n");
150         return;
151     }
152     memset_s(rbuf1, NumByteToWrite, 0, NumByteToWrite);
153     msg.wbuf = pBuffer;
154     msg.rbuf = rbuf1;
155     msg.len = NumByteToWrite;
156     msg.keepCs = 0;
157     msg.delayUs = 0;
158     ret = SpiTransfer(spiHandle, &msg, 1);
159     if (ret != 0) {
160         HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
161     }
162     W25x_WaitForWriteEnd();
163     OsalMemFree(rbuf1);
164     return;
165 }
166 
W25x_BufferWrite(uint8_t * pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)167 void W25x_BufferWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
168 {
169     uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;
170 
171     Addr = WriteAddr % W25x_PageSize;
172     count = W25x_PageSize - Addr;
173     NumOfPage =  NumByteToWrite / W25x_PageSize;
174     NumOfSingle = NumByteToWrite % W25x_PageSize;
175 
176     if (Addr == 0) {
177         if (NumOfPage == 0) {
178             W25x_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
179         } else {
180             while (NumOfPage--) {
181                 W25x_PageWrite(pBuffer, WriteAddr, W25x_PageSize);
182                 WriteAddr +=  W25x_PageSize;
183                 pBuffer += W25x_PageSize;
184             }
185             W25x_PageWrite(pBuffer, WriteAddr, NumOfSingle);
186         }
187     } else {
188         if (NumOfPage == 0) {
189             if (NumOfSingle > count) {
190                 temp = NumOfSingle - count;
191 
192                 W25x_PageWrite(pBuffer, WriteAddr, count);
193                 WriteAddr +=  count;
194                 pBuffer += count;
195 
196                 W25x_PageWrite(pBuffer, WriteAddr, temp);
197             } else {
198                 W25x_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
199             }
200         } else {
201             NumByteToWrite -= count;
202             NumOfPage =  NumByteToWrite / W25x_PageSize;
203             NumOfSingle = NumByteToWrite % W25x_PageSize;
204 
205             W25x_PageWrite(pBuffer, WriteAddr, count);
206             WriteAddr +=  count;
207             pBuffer += count;
208 
209             while (NumOfPage--) {
210                 W25x_PageWrite(pBuffer, WriteAddr, W25x_PageSize);
211                 WriteAddr +=  W25x_PageSize;
212                 pBuffer += W25x_PageSize;
213             }
214 
215             if (NumOfSingle != 0) {
216                 W25x_PageWrite(pBuffer, WriteAddr, NumOfSingle);
217             }
218         }
219     }
220 }
221 
W25x_BufferRead(uint8_t * pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead)222 void W25x_BufferRead(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
223 {
224     if (spiHandle == NULL) {
225         HDF_LOGE("spi flash haven't been inited\n");
226         return;
227     }
228 
229     int32_t ret = 0;
230 
231     uint8_t wbuf[4] = {W25X_ReadData, (ReadAddr & 0xFF0000) >> 16, (ReadAddr& 0xFF00) >> 8, ReadAddr & 0xFF};
232     uint8_t rbuf[4] = {0};
233     struct SpiMsg msg = {0};
234     msg.wbuf = wbuf;
235     msg.rbuf = rbuf;
236     msg.len = sizeof(wbuf);
237     msg.keepCs = 1;
238     msg.delayUs = 0;
239     ret = SpiTransfer(spiHandle, &msg, 1);
240     if (ret != 0) {
241         HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
242         return;
243     }
244     uint8_t *wbuf1 = (uint8_t*)OsalMemAlloc(NumByteToRead);
245     if (wbuf1 == NULL) {
246         HDF_LOGE("malloc failed\n");
247         return;
248     }
249     memset_s(wbuf1, NumByteToRead, 0xff, NumByteToRead);
250     msg.wbuf = wbuf1;
251     msg.rbuf = pBuffer;
252     msg.len = NumByteToRead;
253     msg.keepCs = 0;
254     msg.delayUs = 0;
255     ret = SpiTransfer(spiHandle, &msg, 1);
256     if (ret != 0) {
257         HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
258         return;
259     }
260 
261     OsalMemFree(wbuf1);
262 
263     return;
264 }
265 
W25x_ReadID(void)266 uint32_t W25x_ReadID(void)
267 {
268     int32_t ret = 0;
269     uint16_t flashId = 0;
270     uint8_t rbuff1[4] = { 0 };
271     uint8_t wbuff1[4] = { W25X_JedecDeviceID, Dummy_Byte, Dummy_Byte, Dummy_Byte };
272     struct SpiMsg msg1 = {0};
273     msg1.wbuf = wbuff1;
274     msg1.rbuf = rbuff1;
275     msg1.len = sizeof(wbuff1);
276     msg1.keepCs = 0;
277     msg1.delayUs = 0;
278     ret = SpiTransfer(spiHandle, &msg1, 1);
279     if (ret != 0) {
280         HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
281     } else {
282         flashId = msg1.rbuf[2]<<8 | msg1.rbuf[3];
283     }
284 
285     return flashId;
286 }
287 
W25x_ReadDeviceID(void)288 uint32_t W25x_ReadDeviceID(void)
289 {
290     if (spiHandle == NULL) {
291         HDF_LOGE("spi flash haven't been inited\n");
292         return 0;
293     }
294     struct SpiMsg msg;
295     uint16_t deviceId = 0;
296     uint8_t rbuff[5] = { 0 };
297     uint8_t wbuff[5] = { W25X_DeviceID, Dummy_Byte, Dummy_Byte, Dummy_Byte, Dummy_Byte };
298     int32_t ret = 0;
299     msg.wbuf = wbuff;
300     msg.rbuf = rbuff;
301     msg.len = sizeof(wbuff);
302     msg.keepCs = 0;
303     msg.delayUs = 0;
304     ret = SpiTransfer(spiHandle, &msg, 1);
305     if (ret != 0) {
306         HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
307     } else {
308         deviceId = rbuff[4];
309     }
310 
311     return deviceId;
312 }
313 
W25x_StartReadSequence(uint32_t ReadAddr)314 void W25x_StartReadSequence(uint32_t ReadAddr)
315 {
316     if (spiHandle == NULL) {
317         HDF_LOGE("spi flash haven't been inited\n");
318         return;
319     }
320     struct SpiMsg msg;
321     uint8_t rbuff[4] = { 0 };
322     uint8_t wbuff[4] = { W25X_ReadData, (ReadAddr & 0xff0000) >> 16, (ReadAddr & 0xff00) >> 8, ReadAddr & 0xff };
323     int32_t ret = 0;
324     msg.wbuf = wbuff;
325     msg.rbuf = rbuff;
326     msg.len = sizeof(wbuff);
327     msg.keepCs = 0;
328     msg.delayUs = 0;
329     ret = SpiTransfer(spiHandle, &msg, 1);
330     if (ret != 0) {
331         HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
332     }
333 }
334 
W25x_WriteEnable(void)335 void W25x_WriteEnable(void)
336 {
337     if (spiHandle == NULL) {
338         HDF_LOGE("spi flash haven't been inited\n");
339         return;
340     }
341 
342     uint8_t wbuf[1] = {W25X_WriteEnable};
343     uint8_t rbuf[1] = {0};
344     struct SpiMsg msg = {0};
345     msg.wbuf = wbuf;
346     msg.rbuf = rbuf;
347     msg.len = sizeof(wbuf);
348     msg.keepCs = 0;
349     msg.delayUs = 0;
350     int32_t ret = SpiTransfer(spiHandle, &msg, 1);
351     if (ret != 0) {
352         HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
353     }
354 
355     return;
356 }
357 
W25x_WaitForWriteEnd(void)358 void W25x_WaitForWriteEnd(void)
359 {
360     if (spiHandle == NULL) {
361         HDF_LOGE("spi flash haven't been inited\n");
362         return;
363     }
364 
365     uint8_t FLASH_Status = 0;
366 
367     /* Send "Read Status Register" instruction */
368     uint8_t wbuf[1] = {W25X_ReadStatusReg};
369     uint8_t wbuf1[1] = {0xff};
370     uint8_t rbuf[1] = {0};
371     struct SpiMsg msg = {0};
372     msg.wbuf = wbuf;
373     msg.rbuf = rbuf;
374     msg.len = sizeof(wbuf);
375     msg.keepCs = 1;
376     msg.delayUs = 0;
377     int32_t ret = SpiTransfer(spiHandle, &msg, 1);
378     if (ret != 0) {
379         HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
380     }
381 
382     /* Loop as long as the memory is busy with a write cycle */
383     do {
384         msg.wbuf = wbuf1;
385         msg.rbuf = rbuf;
386         msg.len = sizeof(wbuf1);
387         msg.keepCs = 1;
388         msg.delayUs = 0;
389 
390         ret = SpiTransfer(spiHandle, &msg, 1);
391         if (ret != 0) {
392             HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
393         }
394         FLASH_Status = rbuf[0];
395     }
396     while ((FLASH_Status & WIP_Flag) == 1); /* Write in progress */
397 
398     msg.wbuf = wbuf1;
399     msg.rbuf = rbuf;
400     msg.len = sizeof(wbuf1);
401     msg.keepCs = 0;
402     msg.delayUs = 0;
403 
404     ret = SpiTransfer(spiHandle, &msg, 1);
405     if (ret != 0) {
406         HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
407     }
408 
409     return;
410 }
411 
412 
W25x_PowerDown(void)413 void W25x_PowerDown(void)
414 {
415     if (spiHandle == NULL) {
416         HDF_LOGE("spi flash haven't been inited\n");
417         return;
418     }
419 
420     uint8_t wbuf[1] = {W25X_PowerDown};
421     uint8_t rbuf[1] = {0};
422     struct SpiMsg msg = {0};
423     msg.wbuf = wbuf;
424     msg.rbuf = rbuf;
425     msg.len = sizeof(wbuf);
426     msg.keepCs = 0;
427     msg.delayUs = 0;
428     int32_t ret = SpiTransfer(spiHandle, &msg, 1);
429     if (ret != 0) {
430         HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
431     }
432 
433     return;
434 }
435 
W25x_WAKEUP(void)436 void W25x_WAKEUP(void)
437 {
438     if (spiHandle == NULL) {
439         HDF_LOGE("spi flash haven't been inited\n");
440         return;
441     }
442 
443     uint8_t wbuf[1] = {W25X_ReleasePowerDown};
444     uint8_t rbuf[1] = {0};
445     struct SpiMsg msg = {0};
446     msg.wbuf = wbuf;
447     msg.rbuf = rbuf;
448     msg.len = sizeof(wbuf);
449     msg.keepCs = 0;
450     msg.delayUs = 0;
451     int32_t ret = SpiTransfer(spiHandle, &msg, 1);
452     if (ret != 0) {
453         HDF_LOGE("SpiTransfer: failed, ret %d\n", ret);
454     }
455 
456     return;
457 }
458 #endif
459