xref: /nrf52832-nimble/rt-thread/components/dfs/filesystems/uffs/src/inc/uffs/uffs_flash.h (revision 104654410c56c573564690304ae786df310c91fc)
1 /*
2   This file is part of UFFS, the Ultra-low-cost Flash File System.
3 
4   Copyright (C) 2005-2009 Ricky Zheng <[email protected]>
5 
6   UFFS is free software; you can redistribute it and/or modify it under
7   the GNU Library General Public License as published by the Free Software
8   Foundation; either version 2 of the License, or (at your option) any
9   later version.
10 
11   UFFS is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   or GNU Library General Public License, as applicable, for more details.
15 
16   You should have received a copy of the GNU General Public License
17   and GNU Library General Public License along with UFFS; if not, write
18   to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19   Boston, MA  02110-1301, USA.
20 
21   As a special exception, if other files instantiate templates or use
22   macros or inline functions from this file, or you compile this file
23   and link it with other works to produce a work based on this file,
24   this file does not by itself cause the resulting work to be covered
25   by the GNU General Public License. However the source code for this
26   file must still be made available in accordance with section (3) of
27   the GNU General Public License v2.
28 
29   This exception does not invalidate any other reasons why a work based
30   on this file might be covered by the GNU General Public License.
31 */
32 
33 /**
34  * \file uffs_public.h
35  * \brief flash interface for UFFS
36  * \author Ricky Zheng
37  */
38 
39 #ifndef _UFFS_FLASH_H_
40 #define _UFFS_FLASH_H_
41 
42 #include "uffs/uffs_types.h"
43 #include "uffs/uffs_core.h"
44 #include "uffs/uffs_device.h"
45 #include "uffs/uffs_fs.h"
46 
47 #ifdef __cplusplus
48 extern "C"{
49 #endif
50 
51 
52 /** ECC options (uffs_StorageAttrSt.ecc_opt) */
53 #define UFFS_ECC_NONE		0	//!< do not use ECC
54 #define UFFS_ECC_SOFT		1	//!< UFFS calculate the ECC
55 #define UFFS_ECC_HW			2	//!< Flash driver(or by hardware) calculate the ECC
56 #define UFFS_ECC_HW_AUTO	3	//!< Hardware calculate the ECC and automatically write to spare.
57 
58 #define UFFS_ECC_OPTION_STRING \
59 	{ "none", "soft", "hw", "auto" }	// index is the ecc option value.
60 
61 /** spare layout options (uffs_StorageAttrSt.layout_opt) */
62 #define UFFS_LAYOUT_UFFS	0	//!< do layout by dev->attr information
63 #define UFFS_LAYOUT_FLASH	1	//!< flash driver do the layout
64 
65 #define UFFS_SPARE_LAYOUT_SIZE	6	//!< maximum spare layout array size, 2 segments
66 
67 /** flash operation return code */
68 #define UFFS_FLASH_NO_ERR		0		//!< no error
69 #define UFFS_FLASH_ECC_OK		1		//!< bit-flip found, but corrected by ECC
70 #define UFFS_FLASH_NOT_SEALED	2		//!< page spare area is not sealed properly (only for ReadPageWithLayout())
71 #define UFFS_FLASH_IO_ERR		-1		//!< I/O error
72 #define UFFS_FLASH_ECC_FAIL		-2		//!< ECC failed
73 #define UFFS_FLASH_BAD_BLK		-3		//!< bad block
74 #define UFFS_FLASH_CRC_ERR		-4		//!< CRC failed
75 #define UFFS_FLASH_UNKNOWN_ERR	-100	//!< unkown error?
76 
77 #define UFFS_FLASH_HAVE_ERR(e)		((e) < 0)
78 
79 #if defined(CONFIG_BAD_BLOCK_POLICY_STRICT)
80 # define UFFS_FLASH_IS_BAD_BLOCK(e)	\
81 	((e) == UFFS_FLASH_ECC_FAIL || (e) == UFFS_FLASH_ECC_OK || (e) == UFFS_FLASH_BAD_BLK || (e) == UFFS_FLASH_CRC_ERR)
82 #else
83 # define UFFS_FLASH_IS_BAD_BLOCK(e)	\
84 	((e) == UFFS_FLASH_ECC_FAIL || (e) == UFFS_FLASH_BAD_BLK || (e) == UFFS_FLASH_CRC_ERR)
85 #endif
86 
87 
88 /** defines for page info (data length and data sum) */
89 #define UFFS_PAGE_INFO_CLEAN	0xFFFFFFFF
90 #define UFFS_PAGE_INFO_IOERR	0xDEADFFFF
91 #define UFFS_PAGE_GET_LEN(info)	(info & 0xFFFF)
92 #define UFFS_PAGE_GET_DSUM(info) (info >> 16)
93 #define UFFS_PAGE_MAKE_INFO(d_len, d_sum) ((d_sum << 16) | d_len)
94 
95 /**
96  * \struct uffs_StorageAttrSt
97  * \brief uffs device storage attribute, provide by nand specific file
98  */
99 struct uffs_StorageAttrSt {
100 	u32 total_blocks;		//!< total blocks in this chip
101 	u16 page_data_size;		//!< page data size (physical page data size, e.g. 512)
102 	u16 pages_per_block;	//!< pages per block
103 	u8 spare_size;			//!< page spare size (physical page spare size, e.g. 16)
104 	u8 block_status_offs;	//!< block status byte offset in spare
105 	int ecc_opt;			//!< ecc option ( #UFFS_ECC_[NONE|SOFT|HW|HW_AUTO] )
106 	int layout_opt;			//!< layout option (#UFFS_LAYOUT_UFFS or #UFFS_LAYOUT_FLASH)
107 	int ecc_size;			//!< ecc size in bytes
108 	const u8 *ecc_layout;	//!< page data ECC layout: [ofs1, size1, ofs2, size2, ..., 0xFF, 0]
109 	const u8 *data_layout;	//!< spare data layout: [ofs1, size1, ofs2, size2, ..., 0xFF, 0]
110 	u8 _uffs_ecc_layout[UFFS_SPARE_LAYOUT_SIZE];	//!< uffs spare ecc layout
111 	u8 _uffs_data_layout[UFFS_SPARE_LAYOUT_SIZE];	//!< uffs spare data layout
112 	void *_private;			//!< private data for storage attribute
113 };
114 
115 
116 /**
117  * \struct uffs_FlashOpsSt
118  * \brief low level flash operations, should be implement in flash driver
119  */
120 struct uffs_FlashOpsSt {
121 	/**
122 	 * Initilize flash driver, called once when UFFS initilize partition
123 	 *
124 	 * \return 0 if no error, return -1 when failed.
125 	 *
126 	 * \note This function is optional.
127 	 */
128 	int (*InitFlash)(uffs_Device *dev);
129 
130 	/**
131 	 * Release flash driver, called once when UFFS unmount partition
132 	 *
133 	 * \return 0 if no error, return -1 when failed.
134 	 *
135 	 * \note This function is optional.
136 	 */
137 	int (*ReleaseFlash)(uffs_Device *dev);
138 
139 	/**
140 	 * Read a full nand page, UFFS do the layout.
141 	 *
142 	 * \param[out] ecc ecc of page data
143 	 *   if ecc_opt is UFFS_ECC_HW, flash driver must calculate and return ecc of data(if ecc != NULL).
144 	 *   if ecc_opt is UFFS_ECC_HW_AUTO, flash driver do ecc correction before return data and flash driver do not need to return ecc.
145 	 *   if ecc_opt is UFFS_ECC_NONE or UFFS_ECC_SOFT, flash driver do not need to calculate data ecc and return ecc.
146 	 *
147 	 * \return	#UFFS_FLASH_NO_ERR: success and/or has no flip bits.
148 	 *			#UFFS_FLASH_IO_ERR: I/O error, expect retry ?
149 	 *			#UFFS_FLASH_ECC_FAIL: page data has flip bits and ecc correct failed (when ecc_opt == UFFS_ECC_HW_AUTO)
150 	 *			#UFFS_FLASH_ECC_OK: page data has flip bits and corrected by ecc (when ecc_opt == UFFS_ECC_HW_AUTO)
151 	 *          #UFFS_FLASH_BAD_BLK: if the block is a bad block (e.g., the bad block mark byte is not 0xFF).
152 	 *
153 	 * \note if data is NULL, do not return data; if spare is NULL, do not return spare; if both data and spare are all NULL,
154 	 *       then read bad block mark and return UFFS_FLASH_BAD_BLK if bad block mark is not 0xFF.
155 	 *
156 	 * \note pad 0xFF for calculating ECC if len < page_data_size
157 	 */
158 	int (*ReadPage)(uffs_Device *dev, u32 block, u32 page, u8 *data, int data_len, u8 *ecc,
159 						u8 *spare, int spare_len);
160 
161 	/**
162 	 * Read a full nand page, driver do the layout.
163 	 *
164 	 * \param[out] ecc ecc of page data
165 	 *   if ecc_opt is UFFS_ECC_HW, flash driver must calculate and return ecc of data(if ecc != NULL).
166 	 *   if ecc_opt is UFFS_ECC_HW_AUTO, flash driver do ecc correction before return data and flash driver do not need to return ecc.
167 	 *   if ecc_opt is UFFS_ECC_NONE or UFFS_ECC_SOFT, flash driver do not need calculate data ecc and return ecc.
168 	 *
169 	 * \param[out] ecc_store ecc store on spare area
170 	 *   if ecc_opt is UFFS_ECC_NONE or UFFS_ECC_HW_AUTO, do not need to return ecc_store.
171 	 *
172 	 * \note flash driver must provide this function if layout_opt is UFFS_LAYOUT_FLASH.
173 	 *       UFFS will use this function (if exist) prio to 'ReadPageSpare()'
174 	 *
175 	 * \return	#UFFS_FLASH_NO_ERR: success
176 	 *			#UFFS_FLASH_IO_ERR: I/O error, expect retry ?
177 	 *			#UFFS_FLASH_ECC_FAIL: page data has flip bits and ecc correct failed (when ecc_opt == UFFS_ECC_HW_AUTO)
178 	 *			#UFFS_FLASH_ECC_OK: page data has flip bits and corrected by ecc (when ecc_opt == UFFS_ECC_HW_AUTO)
179 	 *          #UFFS_FLASH_BAD_BLK: if the block is a bad block (e.g., the bad block mark byte is not 0xFF)
180 	 *			#UFFS_FLASH_NOT_SEALED: if the page spare is not sealed properly
181 	 *
182 	 * \note if data is NULL, do not return data; if ts is NULL, do not read tag; if both data and ts are NULL,
183 	 *       then read bad block mark and return UFFS_FLASH_BAD_BLK if bad block mark is not 0xFF.
184 	 *
185 	 * \note flash driver DO NOT need to do ecc correction for tag,
186 	 *		UFFS will take care of tag ecc.
187 	 */
188 	int (*ReadPageWithLayout)(uffs_Device *dev, u32 block, u32 page, u8* data, int data_len, u8 *ecc,
189 									uffs_TagStore *ts, u8 *ecc_store);
190 
191 	/**
192 	 * Write a full page, UFFS do the layout for spare area.
193 	 *
194 	 * \note If you have ecc_opt UFFS_ECC_HW or UFFS_ECC_HW_AUTO, you MUST implement WritePageWithLayout().
195 	 *       Implement WritePage() function if you have ecc_opt UFFS_ECC_NONE or UFFS_ECC_SOFT and
196 	 *       WritePageWithLayout() is not implemented.
197 	 *
198 	 * \note If data == NULL && spare == NULL, driver should mark this block as a 'bad block'.
199 	 *
200 	 * \return	#UFFS_FLASH_NO_ERR: success
201 	 *			#UFFS_FLASH_IO_ERR: I/O error, expect retry ?
202 	 *			#UFFS_FLASH_BAD_BLK: a bad block detected.
203 	 */
204 	int (*WritePage)(uffs_Device *dev, u32 block, u32 page,
205 							const u8 *data, int data_len, const u8 *spare, int spare_len);
206 
207 	/**
208 	 * Write full page, flash driver do the layout for spare area.
209 	 *
210 	 * \note if layout_opt is UFFS_LAYOUT_FLASH or ecc_opt is UFFS_ECC_HW/UFFS_ECC_HW_AUTO, flash driver MUST implement
211 	 *       this function. UFFS will use this function (if provided) prio to 'WritePage()'
212 	 *
213 	 * \param[in] ecc ecc of data. if ecc_opt is UFFS_ECC_SOFT and this function is implemented,
214 	 *                UFFS will calculate page data ecc and pass it to WritePageWithLayout().
215 	 *            if ecc_opt is UFFS_ECC_NONE/UFFS_ECC_HW/UFFS_ECC_HW_AUTO, UFFS pass ecc = NULL.
216 	 *
217 	 * \note If data == NULL && ts == NULL, driver should mark this block as a 'bad block'.
218 	 *
219 	 * \return	#UFFS_FLASH_NO_ERR: success
220 	 *			#UFFS_FLASH_IO_ERR: I/O error, expect retry ?
221 	 *			#UFFS_FLASH_BAD_BLK: a bad block detected.
222 	 */
223 	int (*WritePageWithLayout)(uffs_Device *dev, u32 block, u32 page,
224 							const u8 *data, int data_len, const u8 *ecc, const uffs_TagStore *ts);
225 
226 	/**
227 	 * Check block status.
228 	 *
229 	 * \note flash driver may maintain a bad block table to speed up bad block checking or
230 	 *		it will require one or two read spare I/O to check block status.
231 	 *
232 	 * \note if this function is not implented by driver, UFFS check the block_status byte in spare.
233 	 *
234 	 * \return 1 if it's a bad block, 0 if it's not.
235 	 */
236 	int (*IsBadBlock)(uffs_Device *dev, u32 block);
237 
238 	/**
239 	 * Mark a new bad block.
240 	 *
241 	 * \note if this function is not implemented, UFFS mark bad block by call 'WritePage()/WritePageWithLayout()'
242 	 *       with: data == NULL && spare == NULL && ts == NULL.
243 	 *
244 	 * \return 0 if success, otherwise return -1.
245 	 */
246 	int (*MarkBadBlock)(uffs_Device *dev, u32 block);
247 
248 	/**
249 	 * Erase a block, driver MUST implement this function.
250 	 *
251 	 * \return	#UFFS_FLASH_NO_ERR: success
252 	 *			#UFFS_FLASH_IO_ERR: I/O error, expect retry ?
253 	 *			#UFFS_FLASH_BAD_BLK: a bad block detected.
254 	 */
255 	int (*EraseBlock)(uffs_Device *dev, u32 block);
256 };
257 
258 /** make spare from tag store and ecc */
259 void uffs_FlashMakeSpare(uffs_Device *dev, const uffs_TagStore *ts, const u8 *ecc, u8* spare);
260 
261 /** unload tag and ecc from spare */
262 void uffs_FlashUnloadSpare(uffs_Device *dev, const u8 *spare, struct uffs_TagStoreSt *ts, u8 *ecc);
263 
264 /** read page spare and fill to tag */
265 int uffs_FlashReadPageTag(uffs_Device *dev, int block, int page, uffs_Tags *tag);
266 
267 /** read page data to page buf and do ECC correct */
268 int uffs_FlashReadPage(uffs_Device *dev, int block, int page, uffs_Buf *buf, UBOOL skip_ecc);
269 
270 /** write page data and spare */
271 int uffs_FlashWritePageCombine(uffs_Device *dev, int block, int page, uffs_Buf *buf, uffs_Tags *tag);
272 
273 /** Mark this block as bad block */
274 int uffs_FlashMarkBadBlock(uffs_Device *dev, int block);
275 
276 /** Is this block a bad block ? */
277 UBOOL uffs_FlashIsBadBlock(uffs_Device *dev, int block);
278 
279 /** Erase flash block */
280 int uffs_FlashEraseBlock(uffs_Device *dev, int block);
281 
282 /* mark a clean page as 'dirty' (and 'invalid') */
283 int uffs_FlashMarkDirtyPage(uffs_Device *dev, uffs_BlockInfo *bc, int page);
284 
285 /* check if the block pages are all clean */
286 URET uffs_FlashCheckErasedBlock(uffs_Device *dev, int block);
287 
288 /**
289  * get page head info
290  *
291  * \return #UFFS_PAGE_INFO_IOERR if I/O error, otherwise return page info
292  */
293 u32 uffs_FlashGetPageInfo(uffs_Device *dev, int block, int page);
294 
295 /** load uffs_FileInfo from flash storage */
296 URET uffs_FlashReadFileinfoPhy(uffs_Device *dev, int block, int page, uffs_FileInfo *info);
297 
298 /**
299  * Initialize UFFS flash interface
300  */
301 URET uffs_FlashInterfaceInit(uffs_Device *dev);
302 
303 /**
304  * Release UFFS flash interface
305  */
306 URET uffs_FlashInterfaceRelease(uffs_Device *dev);
307 
308 #ifdef __cplusplus
309 }
310 #endif
311 #endif
312