source: rtems/c/src/lib/libbsp/arm/lpc32xx/include/nand-mlc.h @ cc69334f

4.115
Last change on this file since cc69334f was cc69334f, checked in by Joel Sherrill <joel.sherrill@…>, on Mar 6, 2015 at 4:35:40 PM

Fix a number of minor Doxygen formatting issues

  • Property mode set to 100644
File size: 10.9 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup lpc32xx_nand_mlc
5 *
6 * @brief NAND MLC controller API.
7 */
8
9/*
10 * Copyright (c) 2010-2011 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Obere Lagerstr. 30
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * Copyright (c) 2011 Stephan Hoffmann <sho@reLinux.de>
19 *
20 * The license and distribution terms for this file may be
21 * found in the file LICENSE in this distribution or at
22 * http://www.rtems.org/license/LICENSE.
23 */
24
25#ifndef LIBBSP_ARM_LPC32XX_NAND_MLC_H
26#define LIBBSP_ARM_LPC32XX_NAND_MLC_H
27
28#include <rtems.h>
29
30#include <bsp/utility.h>
31
32#ifdef __cplusplus
33extern "C" {
34#endif /* __cplusplus */
35
36/**
37 * @defgroup lpc32xx_nand_mlc NAND MLC Controller
38 *
39 * @ingroup arm_lpc32xx
40 *
41 * @brief NAND MLC Controller.
42 *
43 * Timing constraints:
44 *
45 * -# (WR_LOW + 1) / HCLK >= tWP
46 * -# (WR_HIGH - WR_LOW) / HCLK >= tWH
47 * -# (WR_LOW + 1) / HCLK + (WR_HIGH - WR_LOW) / HCLK >= tWC
48 * -# (RD_LOW + 1) / HCLK >= tRP
49 * -# (RD_LOW + 1) / HCLK >= tREA + tSU
50 * -# (RD_HIGH - RD_LOW) / HCLK >= tREH
51 * -# (RD_LOW + 1) / HCLK + (RD_HIGH - RD_LOW) / HCLK >= tRC
52 * -# (RD_HIGH - RD_LOW) / HCLK + NAND_TA / HCLK >= tRHZ
53 * -# BUSY_DELAY / HCLK >= max(tWB, tRB)
54 * -# TCEA_DELAY / HCLK >= tCEA - tREA
55 *
56 * Known flash layouts (Format: SP = small pages, LP = large pages / address
57 * cycles / pages per block):
58 *
59 * -# SP/3/32
60 * -# SP/4/32
61 * -# LP/4/64
62 * -# LP/5/64
63 * -# LP/5/128
64 *
65 * @{
66 */
67
68/**
69 * @name MLC NAND Flash Dimensions
70 *
71 * @{
72 */
73
74#define MLC_SMALL_PAGE_SIZE 528
75#define MLC_SMALL_DATA_SIZE 512
76#define MLC_SMALL_SPARE_SIZE 16
77#define MLC_SMALL_USER_SPARE_SIZE 6
78#define MLC_SMALL_ECC_SPARE_SIZE 10
79#define MLC_SMALL_DATA_WORD_COUNT (MLC_SMALL_DATA_SIZE / 4)
80#define MLC_SMALL_SPARE_WORD_COUNT (MLC_SMALL_SPARE_SIZE / 4)
81#define MLC_SMALL_PAGES_PER_LARGE_PAGE 4
82#define MLC_LARGE_PAGE_SIZE \
83  (MLC_SMALL_PAGES_PER_LARGE_PAGE * MLC_SMALL_PAGE_SIZE)
84#define MLC_LARGE_DATA_SIZE \
85  (MLC_SMALL_PAGES_PER_LARGE_PAGE * MLC_SMALL_DATA_SIZE)
86#define MLC_LARGE_SPARE_SIZE \
87  (MLC_SMALL_PAGES_PER_LARGE_PAGE * MLC_SMALL_SPARE_SIZE)
88#define MLC_LARGE_DATA_WORD_COUNT (MLC_LARGE_DATA_SIZE / 4)
89#define MLC_LARGE_SPARE_WORD_COUNT (MLC_LARGE_SPARE_SIZE / 4)
90
91/** @} */
92
93/**
94 * @name NAND Flash Clock Control Register (FLASHCLK_CTRL)
95 *
96 * @{
97 */
98
99#define FLASHCLK_IRQ_MLC BSP_BIT32(5)
100#define FLASHCLK_MLC_DMA_RNB BSP_BIT32(4)
101#define FLASHCLK_MLC_DMA_INT BSP_BIT32(3)
102#define FLASHCLK_SELECT_SLC BSP_BIT32(2)
103#define FLASHCLK_MLC_CLK_ENABLE BSP_BIT32(1)
104#define FLASHCLK_SLC_CLK_ENABLE BSP_BIT32(0)
105
106/** @} */
107
108/**
109 * @name MLC NAND Timing Register (MLC_TIME_REG)
110 *
111 * @{
112 */
113
114#define MLC_TIME_WR_LOW(val) BSP_FLD32(val, 0, 3)
115#define MLC_TIME_WR_HIGH(val) BSP_FLD32(val, 4, 7)
116#define MLC_TIME_RD_LOW(val) BSP_FLD32(val, 8, 11)
117#define MLC_TIME_RD_HIGH(val) BSP_FLD32(val, 12, 15)
118#define MLC_TIME_NAND_TA(val) BSP_FLD32(val, 16, 18)
119#define MLC_TIME_BUSY_DELAY(val) BSP_FLD32(val, 19, 23)
120#define MLC_TIME_TCEA_DELAY(val) BSP_FLD32(val, 24, 25)
121
122/** @} */
123
124/**
125 * @name MLC NAND Lock Protection Register (MLC_LOCK_PR)
126 *
127 * @{
128 */
129
130#define MLC_UNLOCK_PROT 0xa25e
131
132/** @} */
133
134/**
135 * @name MLC NAND Status Register (MLC_ISR)
136 *
137 * @{
138 */
139
140#define MLC_ISR_DECODER_FAILURE BSP_BIT32(6)
141#define MLC_ISR_SYMBOL_ERRORS(reg) BSP_FLD32GET(reg, 4, 5)
142#define MLC_ISR_ERRORS_DETECTED BSP_BIT32(3)
143#define MLC_ISR_ECC_READY BSP_BIT32(2)
144#define MLC_ISR_CONTROLLER_READY BSP_BIT32(1)
145#define MLC_ISR_NAND_READY BSP_BIT32(0)
146
147/** @} */
148
149/**
150 * @name MLC NAND Controller Configuration Register (MLC_ICR)
151 *
152 * @{
153 */
154
155#define MLC_ICR_SOFT_WRITE_PROT BSP_BIT32(3)
156#define MLC_ICR_LARGE_PAGES BSP_BIT32(2)
157#define MLC_ICR_ADDR_WORD_COUNT_4_5 BSP_BIT32(1)
158#define MLC_ICR_IO_BUS_16 BSP_BIT32(0)
159
160/** @} */
161
162/**
163 * @name MLC NAND Auto Encode Register (MLC_ECC_AUTO_ENC)
164 *
165 * @{
166 */
167
168#define MLC_ECC_AUTO_ENC_PROGRAM BSP_BIT32(8)
169
170/** @} */
171
172/**
173 * @name NAND Status Register
174 *
175 * @{
176 */
177
178#define NAND_STATUS_ERROR (1U << 0)
179#define NAND_STATUS_READY (1U << 6)
180#define NAND_STATUS_NOT_PROTECTED (1U << 7)
181
182/** @} */
183
184/**
185 * @brief MLC NAND controller configuration.
186 */
187typedef struct {
188  uint32_t flags;
189
190  uint32_t block_count;
191
192  /**
193   * @brief Value for the MLC NAND Timing Register (MLC_TIME_REG).
194   */
195  uint32_t time;
196} lpc32xx_mlc_config;
197
198/**
199 * @brief Selects small pages (512 Bytes user data and 16 Bytes spare data)
200 * or large pages (2048 Bytes user data and 64 Bytes spare data) if not set.
201 */
202#define MLC_SMALL_PAGES 0x1U
203
204/**
205 * @Brief Selects 4/5 address cycles for small/large pages or 3/4 address
206 * cycles if not set.
207 */
208#define MLC_MANY_ADDRESS_CYCLES 0x2U
209
210/**
211 * @brief Selects 64 pages per block or 128 pages per block if not set.
212 *
213 * This flag is only valid for large pages.
214 */
215#define MLC_NORMAL_BLOCKS 0x4U
216
217/**
218 * @brief Selects 16-bit IO width or 8-bit IO width if not set.
219 */
220#define MLC_IO_WIDTH_16_BIT 0x8U
221
222/**
223 * @brief Initializes the MLC NAND controller according to @a cfg.
224 */
225void lpc32xx_mlc_init(const lpc32xx_mlc_config *cfg);
226
227uint32_t lpc32xx_mlc_page_size(void);
228
229uint32_t lpc32xx_mlc_pages_per_block(void);
230
231uint32_t lpc32xx_mlc_block_count(void);
232
233uint32_t lpc32xx_mlc_io_width(void);
234
235void lpc32xx_mlc_write_protection(
236  uint32_t page_index_low,
237  uint32_t page_index_high
238);
239
240void lpc32xx_mlc_read_id(uint8_t *id, size_t n);
241
242/**
243 * @brief Reads the page with index @a page_index.
244 *
245 * Bytes 6 to 15 of the spare area will contain the ECC.
246 *
247 * If the read is successful, then the @a symbol_error_count will contain the
248 * number of detected symbol errors (0, 1, 2, 3, or 4), else the value will be
249 * 0xffffffff.  The @a symbol_error_count pointer may be @c NULL.
250 *
251 * @retval RTEMS_SUCCESSFUL Successful operation.
252 * @retval RTEMS_INVALID_ID Invalid @a page_index value.
253 * @retval RTEMS_IO_ERROR Uncorrectable bit error.
254 */
255rtems_status_code lpc32xx_mlc_read_page(
256  uint32_t page_index,
257  void *data,
258  void *spare,
259  uint32_t *symbol_error_count
260);
261
262/**
263 * @brief Checks if the block with index @a block_index is valid.
264 *
265 * The initial valid block information of the manufacturer will be used.
266 * Unfortunately there seems to be no standard for this.  A block will be
267 * considered as bad if the first or second page of this block does not contain
268 * 0xff at the 6th byte of the spare area.  This should work for flashes with
269 * small pages and a 8-bit IO width.
270 *
271 * @retval RTEMS_SUCCESSFUL The block is valid.
272 * @retval RTEMS_INVALID_ID Invalid @a block_index value.
273 * @retval RTEMS_IO_ERROR Uncorrectable bit error.
274 * @retval RTEMS_INCORRECT_STATE The block is bad.
275 * @retval RTEMS_NOT_IMPLEMENTED No implementation available for this flash
276 * type.
277 */
278rtems_status_code lpc32xx_mlc_is_valid_block(uint32_t block_index);
279
280/**
281 * @brief Erases the block with index @a block_index.
282 *
283 * @retval RTEMS_SUCCESSFUL Successful operation.
284 * @retval RTEMS_INVALID_ID Invalid @a block_index value.
285 * @retval RTEMS_UNSATISFIED Erase error.
286 */
287rtems_status_code lpc32xx_mlc_erase_block(uint32_t block_index);
288
289/**
290 * @brief Erases the block with index @a block_index.
291 *
292 * In case of an erase error all pages and the spare areas of this block are
293 * programmed with zero values.  This will hopefully mark the block as bad.
294 *
295 * @retval RTEMS_SUCCESSFUL Successful operation.
296 * @retval RTEMS_INCORRECT_STATE The block is bad.
297 * @retval RTEMS_INVALID_ID Invalid @a block_index value.
298 * @retval RTEMS_UNSATISFIED Erase error.
299 * @retval RTEMS_NOT_IMPLEMENTED No implementation available for this flash
300 * type.
301 */
302rtems_status_code lpc32xx_mlc_erase_block_safe(uint32_t block_index);
303
304/**
305 * @brief Erases the block with index @a block_index.
306 *
307 * Variant of lpc32xx_mlc_erase_block_safe() with more parameters for
308 * efficiency reasons.  The @a page_begin must be the index of the first page
309 * of the block.  The @a page_end must be the page index of the last page of
310 * the block plus one.
311 */
312rtems_status_code lpc32xx_mlc_erase_block_safe_3(
313  uint32_t block_index,
314  uint32_t page_begin,
315  uint32_t page_end
316);
317
318/**
319 * @brief Writes zero values to the pages specified by @a page_begin and
320 * @a page_end.
321 *
322 * The data and spare area are cleared to zero.  This marks the pages as bad.
323 */
324void lpc32xx_mlc_zero_pages(uint32_t page_begin, uint32_t page_end);
325
326/**
327 * @brief Writes the page with index @a page_index.
328 *
329 * Only the bytes 0 to 5 of the spare area can be used for user data, the bytes
330 * 6 to 15 will be used for the automatically generated ECC.
331 *
332 * @retval RTEMS_SUCCESSFUL Successful operation.
333 * @retval RTEMS_INVALID_ID Invalid @a page_index value.
334 * @retval RTEMS_IO_ERROR Write error.
335 */
336rtems_status_code lpc32xx_mlc_write_page_with_ecc(
337  uint32_t page_index,
338  const void *data,
339  const void *spare
340);
341
342/**
343 * @brief Writes @a src_size Bytes from @a src to the flash area specified by
344 * @a block_begin and @a block_end.
345 *
346 * The @a page_buffer will be used as an intermediate buffer.
347 *
348 * @retval RTEMS_SUCCESSFUL Successful operation.
349 * @retval RTEMS_INVALID_ID Invalid @a block_begin or @a block_end value.
350 * @retval RTEMS_IO_ERROR Too many bad blocks or source area too big.
351 */
352rtems_status_code lpc32xx_mlc_write_blocks(
353  uint32_t block_begin,
354  uint32_t block_end,
355  const void *src,
356  size_t src_size,
357  uint32_t page_buffer [MLC_LARGE_DATA_WORD_COUNT]
358);
359
360/**
361 * @brief Read blocks process function type.
362 *
363 * @see lpc32xx_mlc_read_blocks().
364 *
365 * @retval false Continue processing.
366 * @retval true Stop processing.
367 */
368typedef bool (*lpc32xx_mlc_read_process)(
369  void *process_arg,
370  uint32_t page_index,
371  uint32_t page_size,
372  uint32_t page_data [MLC_LARGE_DATA_WORD_COUNT],
373  uint32_t page_spare [MLC_LARGE_SPARE_WORD_COUNT]
374);
375
376/**
377 * @brief Reads the pages of block @a block_begin up to and excluding
378 * @a block_end.
379 *
380 * For each page @a process will be called with the @a process_arg parameter,
381 * the page_index, the page data and the page spare.
382 *
383 * The @a page_buffer_0 and @a page_buffer_1 will be used as
384 * intermediate buffers.
385 */
386rtems_status_code lpc32xx_mlc_read_blocks(
387  uint32_t block_begin,
388  uint32_t block_end,
389  lpc32xx_mlc_read_process process,
390  void *process_arg,
391  uint32_t page_buffer_0 [MLC_LARGE_DATA_WORD_COUNT],
392  uint32_t page_buffer_1 [MLC_LARGE_DATA_WORD_COUNT]
393);
394
395/**
396 * @brief Checks if the page spare area indicates to a bad page.
397 *
398 * If the first (byte offset 0) or sixth (byte offset 5) byte of the spare area
399 * has a value other than 0xff, then it returns @a true (the page is bad), else
400 * it returns @a false (the page is not bad).
401 *
402 * Samsung uses the sixth byte to indicate a bad page.  Mircon uses the first
403 * and sixth byte to indicate a bad page.
404 *
405 * This functions works only for small page flashes.
406 */
407static inline bool lpc32xx_mlc_is_bad_page(const uint32_t *spare)
408{
409  uint32_t first_byte_mask = 0x000000ff;
410  uint32_t sixth_byte_mask = 0x0000ff00;
411
412  return (spare [0] & first_byte_mask) != first_byte_mask
413    || (spare [1] & sixth_byte_mask) != sixth_byte_mask;
414}
415
416/** @} */
417
418#ifdef __cplusplus
419}
420#endif /* __cplusplus */
421
422#endif /* LIBBSP_ARM_LPC32XX_NAND_MLC_H */
Note: See TracBrowser for help on using the repository browser.