xref: /nrf52832-nimble/rt-thread/components/drivers/spi/spi_flash_sst25vfxx.c (revision 104654410c56c573564690304ae786df310c91fc)
1 /*
2  * Copyright (c) 2006-2018, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2011-12-16     aozima       the first version
9  */
10 
11 #include <stdint.h>
12 #include "spi_flash_sst25vfxx.h"
13 
14 #define FLASH_DEBUG
15 
16 #ifdef FLASH_DEBUG
17 #define FLASH_TRACE         rt_kprintf
18 #else
19 #define FLASH_TRACE(...)
20 #endif /* #ifdef FLASH_DEBUG */
21 
22 /* JEDEC Manufacturer’s ID */
23 #define MF_ID                       (0xBF)
24 /* JEDEC Device ID : Memory Type */
25 #define MT_ID                       (0x25)
26 /* JEDEC Device ID: Memory Capacity */
27 #define MC_ID_SST25VF020B            (0x8C) /* 2Mbit  */
28 #define MC_ID_SST25VF040B            (0x8D) /* 4Mbit  */
29 #define MC_ID_SST25VF080B            (0x8E) /* 8Mbit  */
30 #define MC_ID_SST25VF016B            (0x41) /* 16Mbit */
31 #define MC_ID_SST25VF032B            (0x4A) /* 32Mbit */
32 #define MC_ID_SST25VF064C            (0x4B) /* 64Mbit */
33 
34 /* command list */
35 #define CMD_RDSR                    (0x05)
36 #define CMD_WRSR                    (0x01)
37 #define CMD_EWSR                    (0x50)
38 #define CMD_WRDI                    (0x04)
39 #define CMD_WREN                    (0x06)
40 #define CMD_READ                    (0x03)
41 #define CMD_FAST_READ               (0x0B)
42 #define CMD_BP                      (0x02)
43 #define CMD_AAIP                    (0xAD)
44 #define CMD_ERASE_4K                (0x20)
45 #define CMD_ERASE_32K               (0x52)
46 #define CMD_ERASE_64K               (0xD8)
47 #define CMD_ERASE_full              (0xC7)
48 #define CMD_JEDEC_ID                (0x9F)
49 #define CMD_EBSY                    (0x70)
50 #define CMD_DBSY                    (0x80)
51 
52 #define DUMMY                       (0xFF)
53 
54 static struct spi_flash_sst25vfxx  spi_flash_sst25vfxx;
55 
sst25vfxx_read_status(struct spi_flash_sst25vfxx * spi_flash)56 static uint8_t sst25vfxx_read_status(struct spi_flash_sst25vfxx * spi_flash)
57 {
58     return rt_spi_sendrecv8(spi_flash->rt_spi_device, CMD_RDSR);
59 }
60 
sst25vfxx_wait_busy(struct spi_flash_sst25vfxx * spi_flash)61 static void sst25vfxx_wait_busy(struct spi_flash_sst25vfxx * spi_flash)
62 {
63     while( sst25vfxx_read_status(spi_flash) & (0x01));
64 }
65 
66 /** \brief write N page on [page]
67  *
68  * \param page uint32_t unit : byte (4096 * N,1 page = 4096byte)
69  * \param buffer const uint8_t*
70  * \param size uint32_t unit : byte ( 4096*N )
71  * \return uint32_t
72  *
73  */
sst25vfxx_page_write(struct spi_flash_sst25vfxx * spi_flash,uint32_t page,const uint8_t * buffer,uint32_t size)74 static uint32_t sst25vfxx_page_write(struct spi_flash_sst25vfxx * spi_flash, uint32_t page, const uint8_t * buffer, uint32_t size)
75 {
76     uint32_t index;
77     uint32_t need_wirte = size;
78     uint8_t send_buffer[6];
79 
80     page &= ~0xFFF; // page size = 4096byte
81 
82     send_buffer[0] = CMD_WREN;
83     rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1);
84 
85     send_buffer[0] = CMD_ERASE_4K;
86     send_buffer[1] = (page >> 16);
87     send_buffer[2] = (page >> 8);
88     send_buffer[3] = (page);
89     rt_spi_send(spi_flash->rt_spi_device, send_buffer, 4);
90 
91     sst25vfxx_wait_busy(spi_flash); // wait erase done.
92 
93     send_buffer[0] = CMD_WREN;
94     rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1);
95 
96     send_buffer[0] = CMD_AAIP;
97     send_buffer[1] = (uint8_t)(page >> 16);
98     send_buffer[2] = (uint8_t)(page >> 8);
99     send_buffer[3] = (uint8_t)(page);
100     send_buffer[4] = *buffer++;
101     send_buffer[5] = *buffer++;
102     need_wirte -= 2;
103     rt_spi_send(spi_flash->rt_spi_device, send_buffer, 6);
104 
105     sst25vfxx_wait_busy(spi_flash);
106 
107     for(index=0; index < need_wirte/2; index++)
108     {
109         send_buffer[0] = CMD_AAIP;
110         send_buffer[1] = *buffer++;
111         send_buffer[2] = *buffer++;
112         rt_spi_send(spi_flash->rt_spi_device, send_buffer, 3);
113         sst25vfxx_wait_busy(spi_flash);
114     }
115 
116     send_buffer[0] = CMD_WRDI;
117     rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1);
118 
119     return size;
120 }
121 
122 /* RT-Thread device interface */
sst25vfxx_flash_init(rt_device_t dev)123 static rt_err_t sst25vfxx_flash_init(rt_device_t dev)
124 {
125     return RT_EOK;
126 }
127 
sst25vfxx_flash_open(rt_device_t dev,rt_uint16_t oflag)128 static rt_err_t sst25vfxx_flash_open(rt_device_t dev, rt_uint16_t oflag)
129 {
130     rt_err_t result;
131     uint8_t send_buffer[2];
132     struct spi_flash_sst25vfxx * spi_flash = (struct spi_flash_sst25vfxx *)dev;
133 
134     /* lock spi flash */
135     result = rt_mutex_take(&(spi_flash->lock), RT_WAITING_FOREVER);
136     if(result != RT_EOK)
137     {
138         return result;
139     }
140 
141     send_buffer[0] = CMD_DBSY;
142     rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1);
143 
144     send_buffer[0] = CMD_EWSR;
145     rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1);
146 
147     send_buffer[0] = CMD_WRSR;
148     send_buffer[1] = 0;
149     rt_spi_send(spi_flash->rt_spi_device, send_buffer, 2);
150 
151     /* release lock */
152     rt_mutex_release(&(spi_flash->lock));
153 
154     return RT_EOK;
155 }
156 
sst25vfxx_flash_close(rt_device_t dev)157 static rt_err_t sst25vfxx_flash_close(rt_device_t dev)
158 {
159     return RT_EOK;
160 }
161 
sst25vfxx_flash_control(rt_device_t dev,int cmd,void * args)162 static rt_err_t sst25vfxx_flash_control(rt_device_t dev, int cmd, void *args)
163 {
164     struct spi_flash_sst25vfxx * spi_flash;
165 
166     spi_flash = (struct spi_flash_sst25vfxx *)dev;
167 
168     RT_ASSERT(dev != RT_NULL);
169 
170     if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
171     {
172         struct rt_device_blk_geometry *geometry;
173 
174         geometry = (struct rt_device_blk_geometry *)args;
175         if (geometry == RT_NULL) return -RT_ERROR;
176 
177         geometry->bytes_per_sector = spi_flash->geometry.bytes_per_sector;
178         geometry->sector_count = spi_flash->geometry.sector_count;
179         geometry->block_size = spi_flash->geometry.block_size;
180     }
181 
182     return RT_EOK;
183 }
184 
sst25vfxx_flash_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)185 static rt_size_t sst25vfxx_flash_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
186 {
187     rt_err_t result;
188     uint8_t send_buffer[4];
189     struct spi_flash_sst25vfxx * spi_flash = (struct spi_flash_sst25vfxx *)dev;
190     uint32_t offset = pos * spi_flash->geometry.bytes_per_sector;
191 
192     /* lock spi flash */
193     result = rt_mutex_take(&(spi_flash->lock), RT_WAITING_FOREVER);
194     if(result != RT_EOK)
195     {
196         return 0;
197     }
198 
199     send_buffer[0] = CMD_WRDI;
200     rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1);
201 
202     send_buffer[0] = CMD_READ;
203     send_buffer[1] = (uint8_t)(offset>>16);
204     send_buffer[2] = (uint8_t)(offset>>8);
205     send_buffer[3] = (uint8_t)(offset);
206     rt_spi_send_then_recv(spi_flash->rt_spi_device, send_buffer, 4, buffer, size * spi_flash->geometry.bytes_per_sector);
207 
208     /* release lock */
209     rt_mutex_release(&(spi_flash->lock));
210 
211     return size;
212 }
213 
sst25vfxx_flash_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)214 static rt_size_t sst25vfxx_flash_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
215 {
216     uint32_t i;
217     rt_err_t result;
218     const uint8_t * write_buffer = buffer;
219     struct spi_flash_sst25vfxx * spi_flash = (struct spi_flash_sst25vfxx *)dev;
220 
221     /* lock spi flash */
222     result = rt_mutex_take(&(spi_flash->lock), RT_WAITING_FOREVER);
223     if(result != RT_EOK)
224     {
225         return 0;
226     }
227 
228     for(i=0; i<size; i++)
229     {
230         sst25vfxx_page_write(spi_flash,
231                              (pos + i) * spi_flash->geometry.bytes_per_sector,
232                              write_buffer,
233                              spi_flash->geometry.bytes_per_sector);
234         write_buffer += spi_flash->geometry.bytes_per_sector;
235     }
236 
237     /* release lock */
238     rt_mutex_release(&(spi_flash->lock));
239 
240     return size;
241 }
242 
243 #ifdef RT_USING_DEVICE_OPS
244 const static struct rt_device_ops sst25vfxx_device_ops =
245 {
246     sst25vfxx_flash_init,
247     sst25vfxx_flash_open,
248     sst25vfxx_flash_close,
249     sst25vfxx_flash_read,
250     sst25vfxx_flash_write,
251     sst25vfxx_flash_control
252 };
253 #endif
254 
sst25vfxx_init(const char * flash_device_name,const char * spi_device_name)255 rt_err_t sst25vfxx_init(const char * flash_device_name, const char * spi_device_name)
256 {
257     struct rt_spi_device * rt_spi_device;
258     struct spi_flash_sst25vfxx * spi_flash = &spi_flash_sst25vfxx;
259 
260     rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name);
261     if(rt_spi_device == RT_NULL)
262     {
263         FLASH_TRACE("spi device %s not found!\r\n", spi_device_name);
264         return -RT_ENOSYS;
265     }
266     spi_flash->rt_spi_device = rt_spi_device;
267 
268     /* config spi */
269     {
270         struct rt_spi_configuration cfg;
271         cfg.data_width = 8;
272         cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */
273         cfg.max_hz = 50000000; /* 50M */
274         rt_spi_configure(spi_flash->rt_spi_device, &cfg);
275     }
276 
277     /* init flash */
278     {
279         rt_uint8_t cmd;
280         rt_uint8_t id_recv[3];
281 
282         cmd = CMD_WRDI;
283         rt_spi_send(spi_flash->rt_spi_device, &cmd, 1);
284 
285         /* read flash id */
286         cmd = CMD_JEDEC_ID;
287         rt_spi_send_then_recv(spi_flash->rt_spi_device, &cmd, 1, id_recv, 3);
288 
289         if(id_recv[0] != MF_ID || id_recv[1] != MT_ID)
290         {
291             FLASH_TRACE("Manufacturer’s ID or Memory Type error!\r\n");
292             FLASH_TRACE("JEDEC Read-ID Data : %02X %02X %02X\r\n", id_recv[0], id_recv[1], id_recv[2]);
293             return -RT_ENOSYS;
294         }
295 
296         spi_flash->geometry.bytes_per_sector = 4096;
297         spi_flash->geometry.block_size = 4096; /* block erase: 4k */
298 
299         if(id_recv[2] == MC_ID_SST25VF020B)
300         {
301             FLASH_TRACE("SST25VF020B detection\r\n");
302             spi_flash->geometry.sector_count = 64;
303         }
304         else if(id_recv[2] == MC_ID_SST25VF040B)
305         {
306             FLASH_TRACE("SST25VF040B detection\r\n");
307             spi_flash->geometry.sector_count = 128;
308         }
309         else if(id_recv[2] == MC_ID_SST25VF080B)
310         {
311             FLASH_TRACE("SST25VF080B detection\r\n");
312             spi_flash->geometry.sector_count = 256;
313         }
314         else if(id_recv[2] == MC_ID_SST25VF016B)
315         {
316             FLASH_TRACE("SST25VF016B detection\r\n");
317             spi_flash->geometry.sector_count = 512;
318         }
319         else if(id_recv[2] == MC_ID_SST25VF032B)
320         {
321             FLASH_TRACE("SST25VF032B detection\r\n");
322             spi_flash->geometry.sector_count = 1024;
323         }
324         else if(id_recv[2] == MC_ID_SST25VF064C)
325         {
326             FLASH_TRACE("SST25VF064C detection\r\n");
327             spi_flash->geometry.sector_count = 2048;
328         }
329         else
330         {
331             FLASH_TRACE("Memory Capacity error!\r\n");
332             return -RT_ENOSYS;
333         }
334     }
335 
336     /* initialize mutex lock */
337     rt_mutex_init(&spi_flash->lock, flash_device_name, RT_IPC_FLAG_PRIO);
338 
339     /* register device */
340     spi_flash->flash_device.type    = RT_Device_Class_Block;
341 #ifdef RT_USING_DEVICE_OPS
342     spi_flash->flash_device.ops     = &sst25vfxx_device_ops;
343 #else
344     spi_flash->flash_device.init    = sst25vfxx_flash_init;
345     spi_flash->flash_device.open    = sst25vfxx_flash_open;
346     spi_flash->flash_device.close   = sst25vfxx_flash_close;
347     spi_flash->flash_device.read    = sst25vfxx_flash_read;
348     spi_flash->flash_device.write   = sst25vfxx_flash_write;
349     spi_flash->flash_device.control = sst25vfxx_flash_control;
350 #endif
351     /* no private */
352     spi_flash->flash_device.user_data = RT_NULL;
353 
354     rt_device_register(&spi_flash->flash_device, flash_device_name,
355                        RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
356 
357     return RT_EOK;
358 }
359