1 /*
2  * Copyright (C) 2017-2020 Alibaba Group Holding Limited
3  */
4 
5 /******************************************************************************
6  * @file     drv/spiflash.h
7  * @brief    Header File for SPIFLASH Driver
8  * @version  V1.0
9  * @date     02. June 2020
10  * @model    spiflash
11  ******************************************************************************/
12 #ifndef _DRV_SPIFLASH_H_
13 #define _DRV_SPIFLASH_H_
14 
15 #include <stdint.h>
16 #include <drv/gpio.h>
17 #include <drv/spi.h>
18 #include <drv/qspi.h>
19 #include <drv/common.h>
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 /**
26 * \brief  Build a flash ID
27 * \param [in] vendor_id    Vendor id(8bit)
28 * \param [in] device_id    Flash device id (ID15~ID0) 16bit
29 * \return    24bit flash id
30 */
31 #define FLASH_ID_BUILD(VENDOR_ID,DEVICE_ID)
32 
33 /**
34 * \struct csi_spiflash_lock_info_t
35 * \ flash use status register 1 to protect data in memory array
36 * \ different flash vendor support different  protect region (top/bottom/none)
37 *   also support different protect number
38 *   status1 register bif field show as follow
39 *   7          |6           |5            |4     |3     |2     |1     |0
40 *   ---------------------------------------------------------------------
41 *   vensor def | vendor def | vendor def  | BP2  | BP1  |  BP0 | WEL  | BUSY
42 * \ Protect type
43 * \ Protect block size : Vendor define ,user should check flash datasheet of vendor
44 *                      : Use w25q64fw as example , min protect block size is 128 KB
45 * \ TOP      : Protect address from flash top address
46 * \ BOTTOM   : Protect address from flash bottom address
47 * \ SEC      : Protect addres base on sector unit and protect region only must not exceed one block
48 * \ BPx      : Protect start addres base on TOP/BOTTOM feature,and BPx value denote protect number
49 * \            BP[x..0]'s value : 2^(n-1) protect block unit, ex, BP[x..0] = 5, protect block number = 2^(5-1) = 16
50 * \            If BP[x..0] = 0  denote protect none
51 * \            If BP[x..0]'s all bis is 1 ,denote protect all flash
52 * \
53 * \ NOTE:
54 * \        only  support SEC = 0
55 * \        only  support CMP = 0
56 * \
57 *
58 * Sample table portion for 8MB flash (Winbond w25q64fw):
59 *
60 *   SEC  |  TB   |  BP2  |  BP1  |  BP0  |  Prot Length  | Protected Portion
61 *  --------------------------------------------------------------------------
62 *    X   |   X   |   0   |   0   |   0   |  NONE         | NONE
63 *    0   |   0   |   0   |   0   |   1   |  128 KB       | Upper 1/64
64 *    0   |   0   |   0   |   1   |   0   |  256 KB       | Upper 1/32
65 *    0   |   0   |   0   |   1   |   1   |  512 KB       | Upper 1/16
66 *    0   |   0   |   1   |   0   |   0   |  1 MB         | Upper 1/8
67 *    0   |   0   |   1   |   0   |   1   |  2 MB         | Upper 1/4
68 *    0   |   0   |   1   |   1   |   0   |  4 MB         | Upper 1/2
69 *    X   |   X   |   1   |   1   |   1   |  8 MB         | ALL
70 *  ------|-------|-------|-------|-------|---------------|-------------------
71 *    0   |   1   |   0   |   0   |   1   |  128 KB       | Lower 1/64
72 *    0   |   1   |   0   |   1   |   0   |  256 KB       | Lower 1/32
73 *    0   |   1   |   0   |   1   |   1   |  512 KB       | Lower 1/16
74 *    0   |   1   |   1   |   0   |   0   |  1 MB         | Lower 1/8
75 *    0   |   1   |   1   |   0   |   1   |  2 MB         | Lower 1/4
76 *    0   |   1   |   1   |   1   |   0   |  4 MB         | Lower 1/2
77 *
78 */
79 typedef enum {
80     LOCK_TP_NONE,
81     LOCK_TP_TOP,
82     LOCK_TP_BOTTOM,
83     LOCK_TP_DUAL
84 } csi_spiflash_lock_region_t;
85 typedef enum {
86     SPIFLASH_DATA_1_LINE  = 1,
87     SPIFLASH_DATA_2_LINES = 2,
88     SPIFLASH_DATA_4_LINES = 4
89 } csi_spiflash_data_line_t;
90 typedef union {
91     csi_spi_t   spi;
92     csi_qspi_t  qspi;
93 } csi_spi_qspi_t;
94 
95 /**
96 \brief Flash information
97 */
98 typedef struct {
99     char    *flash_name;                  ///< Name string of spiflash
100     uint32_t flash_id;                    ///< JEDEC ID  = manufature ID <<16 | device ID (ID15~ID0)
101     uint32_t flash_size;                  ///< Flash chip size
102     uint32_t xip_addr;                    ///< If use qspi controler to access flash ,code can be ececuted on flash ,the addr is xip addr
103     uint32_t sector_size;                 ///< Sector size
104     uint32_t page_size;                   ///< Page size for read or program
105 } csi_spiflash_info_t;
106 
107 typedef struct{
108     struct{
109         uint8_t buswidth;                  ///< cmd buswidth
110     }cmd;
111     struct {
112         uint8_t buswidth;                  ///< addr buswidth
113     }addr;
114     struct {
115         uint8_t nbytes;                    ///< dummy bytes
116     }dummy;
117     struct {
118         uint8_t buswidth;                  ///<  data buswidth
119     }data;
120 } csi_spiflash_cmd_t;
121 
122 /**
123 \brief Flash control block
124 */
125 typedef struct {
126     csi_spi_qspi_t spi_qspi;               ///< Spi/qspi handle
127     void (*spi_cs_callback)(csi_gpio_pin_state_t value);
128     void           *flash_prv_info;        ///< Point to vendor private feature struct
129     int32_t (*spi_send)(void *spi, uint8_t cmd, uint32_t addr, uint32_t addr_size, const void *data, uint32_t size);
130     int32_t (*spi_receive)(void *spi, uint8_t cmd, uint32_t addr, uint32_t addr_size, void *data, uint32_t size);
131     csi_error_t (*set_cmd)(void *spi, csi_spiflash_cmd_t *cmd);
132     void           *priv;                  ///< User private param
133 } csi_spiflash_t;
134 
135 /**
136   \brief       Initialize SPIFLASH with spi controler  and probe flash device
137   \param[in]   spiflash   SPIFLASH handle
138   \param[in]   spi_idx    SPI controler index
139   \param[in]   spi_cs     GPIO info for chip select,if NULL, not use gpio cs
140   \return      Error code
141 */
142 csi_error_t csi_spiflash_spi_init(csi_spiflash_t *spiflash, uint32_t spi_idx, void *spi_cs_callback);
143 
144 /**
145   \brief       Initialize SPIFLASH with qspi controler  and probe flash device
146   \param[in]   spiflash    SPIFLASH handle
147   \param[in]   qspi_idx    QSPI controler index
148   \return      Error code
149 */
150 csi_error_t csi_spiflash_qspi_init(csi_spiflash_t *spiflash, uint32_t qspi_idx, void *qspi_cs_callback);
151 
152 /**
153   \brief       De-initialize SPIFLASH Interface based on spi controler. stops operation and releases the software resources used by the interface
154   \param[in]   spiflash    SPIFLASH handle to operate
155   \return      Error code
156 */
157 void csi_spiflash_spi_uninit(csi_spiflash_t *spiflash);
158 
159 /**
160   \brief       De-initialize SPIFLASH Interface based on qspi controler. stops operation and releases the software resources used by the interface
161   \param[in]   spiflash    SPIFLASH handle to operate
162   \return      Error code
163 */
164 void csi_spiflash_qspi_uninit(csi_spiflash_t *spiflash);
165 
166 
167 /**
168   \brief       Get flash device infomation
169   \param[in]   spiflash      SPIFLASH handle to operate
170   \param[in]   flash_info    User storage to get flash vendor info after flash init
171   \return      spiflash_info_t
172 */
173 csi_error_t csi_spiflash_get_flash_info(csi_spiflash_t *spiflash, csi_spiflash_info_t *flash_info);
174 
175 
176 /**
177   \brief       Read data from Flash
178   \param[in]   spiflash   SPIFLASH handle to operate
179   \param[in]   offset     Data address, offset address relative to zero
180   \param[out]  data       Pointer to a buffer storing the data read from Flash
181   \param[in]   size       Number of data items to read
182   \return      If receive successful, this function shall return the num of data witch is received successful
183                otherwise, the function shall return Error code
184 */
185 int32_t csi_spiflash_read(csi_spiflash_t *spiflash, uint32_t offset, void *data, uint32_t size);
186 
187 /**
188   \brief       Program data to Flash
189   \param[in]   spiflash  SPIFLASH handle to operate
190   \param[in]   offset    Data address, offset address relative to zero
191   \param[in]   data      Pointer to a buffer containing the data to be programmed to Flash.
192   \param[in]   size      Number of data items to program
193   \return      If program successful, this function shall return the num of data witch is program successful,
194                otherwise, the function shall return Error code
195 */
196 int32_t csi_spiflash_program(csi_spiflash_t *spiflash, uint32_t offset, const void *data, uint32_t size);
197 
198 /**
199   \brief       Erase Flash Sector
200   \param[in]   spiflash    SPIFLASH handle to operate
201   \param[in]   offset    Data address, offset address relative to zero
202   \param[in]   size      Length to be erased
203   \return      Error code
204 */
205 csi_error_t csi_spiflash_erase(csi_spiflash_t *spiflash, uint32_t offset, uint32_t size);
206 
207 /**
208   \brief       Read flash status register
209   \param[in]   spiflash  SPIFLASH handle to operate
210   \param[in]   cmd_code  Cmd code
211   \param[out]  data      Data buf to save flash status register
212   \param[in]   size      Register length in byte
213   \return      Error code
214 */
215 csi_error_t csi_spiflash_read_reg(csi_spiflash_t *spiflash, uint8_t cmd_code, uint8_t *data, uint32_t size);
216 
217 /**
218   \brief       Write status register
219   \param[in]   spiflash  SPIFLASH handle to operate
220   \param[in]   cmd       Cmd code
221   \param[out]  data      Data buf to save flash status register
222   \param[in]   size      Register length in byte
223   \return      Error code
224 */
225 csi_error_t csi_spiflash_write_reg(csi_spiflash_t *spiflash, uint8_t cmd_code, uint8_t *data, uint32_t size);
226 
227 
228 /**
229   \brief       Enable spiflash write protection
230   \param[in]   spiflash    SPIFLASH handle to operate
231   \param[in]   offset      Protect flash offset,offset need protect block size aligned
232   \param[in]   size        Lock size(byte)
233   \return      Error code
234 */
235 csi_error_t csi_spiflash_lock(csi_spiflash_t *spiflash, uint32_t offset, uint32_t size);
236 
237 /**
238   \brief       Enable spiflash write protection
239   \param[in]   spiflash    SPIFLASH handle to operate
240   \param[in]   offset      Protect flash offset,offset need protect block size aligned
241   \param[in]   size        Unlock size(byte)
242   \return      Error code
243 */
244 csi_error_t csi_spiflash_unlock(csi_spiflash_t *spiflash, uint32_t offset, uint32_t size);
245 
246 /**
247   \brief       check flash is locked(write protect)
248   \param[in]   spiflash    SPIFLASH handle to operate
249   \param[in]   offset      Protect flash offset,offset need protect block size aligned
250   \param[in]   size        Locked size(byte)
251   \return      0:unlocked if query region overlay with locked region 1: locked if query reigon is fully in locked region
252 */
253 int csi_spiflash_is_locked(csi_spiflash_t *spiflash, uint32_t offset, uint32_t size);
254 
255 /**
256   \brief       Set QSPI data line
257   \param[in]   spiflash    SPIFLASH handle to operate
258   \param[in]   line        SPIFLASH data line mode
259   \return      Error code
260 */
261 csi_error_t csi_spiflash_config_data_line(csi_spiflash_t *spiflash, csi_spiflash_data_line_t line);
262 
263 /**
264   \brief       Set QSPI frequence
265   \param[in]   spiflash SPIFLASH handle to operate
266   \param[in]   hz       SPIFLASH frequence
267   \return      The actual config frequency
268 */
269 uint32_t csi_spiflash_frequence(csi_spiflash_t *spiflash, uint32_t hz);
270 
271 /**
272   \brief       Flash power down.
273   \param[in]   spiflash SPIFLASH handle to operate.
274   \return      error code
275 */
276 csi_error_t csi_spiflash_release_power_down(csi_spiflash_t *spiflash);
277 
278 /**
279   \brief       Flash power release.
280   \param[in]   spiflash SPIFLASH handle to operate.
281   \return      none
282 */
283 void csi_spiflash_power_down(csi_spiflash_t *spiflash);
284 
285 #ifdef __cplusplus
286 }
287 #endif
288 
289 #endif /* _DRV_SPIFLASH_H_ */
290