![]() |
|
|||
File indexing completed on 2025-05-11 08:23:04
0001 /** 0002 * @file 0003 * 0004 * @ingroup lpc32xx_nand_mlc 0005 * 0006 * @brief NAND MLC controller API. 0007 */ 0008 0009 /* 0010 * Copyright (C) 2010, 2011 embedded brains GmbH & Co. KG 0011 * 0012 * Copyright (c) 2011 Stephan Hoffmann <sho@reLinux.de> 0013 * 0014 * The license and distribution terms for this file may be 0015 * found in the file LICENSE in this distribution or at 0016 * http://www.rtems.org/license/LICENSE. 0017 */ 0018 0019 #ifndef LIBBSP_ARM_LPC32XX_NAND_MLC_H 0020 #define LIBBSP_ARM_LPC32XX_NAND_MLC_H 0021 0022 #include <rtems.h> 0023 0024 #include <bsp/utility.h> 0025 0026 #ifdef __cplusplus 0027 extern "C" { 0028 #endif /* __cplusplus */ 0029 0030 /** 0031 * @defgroup lpc32xx_nand_mlc NAND MLC Controller 0032 * 0033 * @ingroup RTEMSBSPsARMLPC32XX 0034 * 0035 * @brief NAND MLC Controller. 0036 * 0037 * Timing constraints: 0038 * 0039 * -# (WR_LOW + 1) / HCLK >= tWP 0040 * -# (WR_HIGH - WR_LOW) / HCLK >= tWH 0041 * -# (WR_LOW + 1) / HCLK + (WR_HIGH - WR_LOW) / HCLK >= tWC 0042 * -# (RD_LOW + 1) / HCLK >= tRP 0043 * -# (RD_LOW + 1) / HCLK >= tREA + tSU 0044 * -# (RD_HIGH - RD_LOW) / HCLK >= tREH 0045 * -# (RD_LOW + 1) / HCLK + (RD_HIGH - RD_LOW) / HCLK >= tRC 0046 * -# (RD_HIGH - RD_LOW) / HCLK + NAND_TA / HCLK >= tRHZ 0047 * -# BUSY_DELAY / HCLK >= max(tWB, tRB) 0048 * -# TCEA_DELAY / HCLK >= tCEA - tREA 0049 * 0050 * Known flash layouts (Format: SP = small pages, LP = large pages / address 0051 * cycles / pages per block): 0052 * 0053 * -# SP/3/32 0054 * -# SP/4/32 0055 * -# LP/4/64 0056 * -# LP/5/64 0057 * -# LP/5/128 0058 * 0059 * @{ 0060 */ 0061 0062 /** 0063 * @name MLC NAND Flash Dimensions 0064 * 0065 * @{ 0066 */ 0067 0068 #define MLC_SMALL_PAGE_SIZE 528 0069 #define MLC_SMALL_DATA_SIZE 512 0070 #define MLC_SMALL_SPARE_SIZE 16 0071 #define MLC_SMALL_USER_SPARE_SIZE 6 0072 #define MLC_SMALL_ECC_SPARE_SIZE 10 0073 #define MLC_SMALL_DATA_WORD_COUNT (MLC_SMALL_DATA_SIZE / 4) 0074 #define MLC_SMALL_SPARE_WORD_COUNT (MLC_SMALL_SPARE_SIZE / 4) 0075 #define MLC_SMALL_PAGES_PER_LARGE_PAGE 4 0076 #define MLC_LARGE_PAGE_SIZE \ 0077 (MLC_SMALL_PAGES_PER_LARGE_PAGE * MLC_SMALL_PAGE_SIZE) 0078 #define MLC_LARGE_DATA_SIZE \ 0079 (MLC_SMALL_PAGES_PER_LARGE_PAGE * MLC_SMALL_DATA_SIZE) 0080 #define MLC_LARGE_SPARE_SIZE \ 0081 (MLC_SMALL_PAGES_PER_LARGE_PAGE * MLC_SMALL_SPARE_SIZE) 0082 #define MLC_LARGE_DATA_WORD_COUNT (MLC_LARGE_DATA_SIZE / 4) 0083 #define MLC_LARGE_SPARE_WORD_COUNT (MLC_LARGE_SPARE_SIZE / 4) 0084 0085 /** @} */ 0086 0087 /** 0088 * @name NAND Flash Clock Control Register (FLASHCLK_CTRL) 0089 * 0090 * @{ 0091 */ 0092 0093 #define FLASHCLK_IRQ_MLC BSP_BIT32(5) 0094 #define FLASHCLK_MLC_DMA_RNB BSP_BIT32(4) 0095 #define FLASHCLK_MLC_DMA_INT BSP_BIT32(3) 0096 #define FLASHCLK_SELECT_SLC BSP_BIT32(2) 0097 #define FLASHCLK_MLC_CLK_ENABLE BSP_BIT32(1) 0098 #define FLASHCLK_SLC_CLK_ENABLE BSP_BIT32(0) 0099 0100 /** @} */ 0101 0102 /** 0103 * @name MLC NAND Timing Register (MLC_TIME_REG) 0104 * 0105 * @{ 0106 */ 0107 0108 #define MLC_TIME_WR_LOW(val) BSP_FLD32(val, 0, 3) 0109 #define MLC_TIME_WR_HIGH(val) BSP_FLD32(val, 4, 7) 0110 #define MLC_TIME_RD_LOW(val) BSP_FLD32(val, 8, 11) 0111 #define MLC_TIME_RD_HIGH(val) BSP_FLD32(val, 12, 15) 0112 #define MLC_TIME_NAND_TA(val) BSP_FLD32(val, 16, 18) 0113 #define MLC_TIME_BUSY_DELAY(val) BSP_FLD32(val, 19, 23) 0114 #define MLC_TIME_TCEA_DELAY(val) BSP_FLD32(val, 24, 25) 0115 0116 /** @} */ 0117 0118 /** 0119 * @name MLC NAND Lock Protection Register (MLC_LOCK_PR) 0120 * 0121 * @{ 0122 */ 0123 0124 #define MLC_UNLOCK_PROT 0xa25e 0125 0126 /** @} */ 0127 0128 /** 0129 * @name MLC NAND Status Register (MLC_ISR) 0130 * 0131 * @{ 0132 */ 0133 0134 #define MLC_ISR_DECODER_FAILURE BSP_BIT32(6) 0135 #define MLC_ISR_SYMBOL_ERRORS(reg) BSP_FLD32GET(reg, 4, 5) 0136 #define MLC_ISR_ERRORS_DETECTED BSP_BIT32(3) 0137 #define MLC_ISR_ECC_READY BSP_BIT32(2) 0138 #define MLC_ISR_CONTROLLER_READY BSP_BIT32(1) 0139 #define MLC_ISR_NAND_READY BSP_BIT32(0) 0140 0141 /** @} */ 0142 0143 /** 0144 * @name MLC NAND Controller Configuration Register (MLC_ICR) 0145 * 0146 * @{ 0147 */ 0148 0149 #define MLC_ICR_SOFT_WRITE_PROT BSP_BIT32(3) 0150 #define MLC_ICR_LARGE_PAGES BSP_BIT32(2) 0151 #define MLC_ICR_ADDR_WORD_COUNT_4_5 BSP_BIT32(1) 0152 #define MLC_ICR_IO_BUS_16 BSP_BIT32(0) 0153 0154 /** @} */ 0155 0156 /** 0157 * @name MLC NAND Auto Encode Register (MLC_ECC_AUTO_ENC) 0158 * 0159 * @{ 0160 */ 0161 0162 #define MLC_ECC_AUTO_ENC_PROGRAM BSP_BIT32(8) 0163 0164 /** @} */ 0165 0166 /** 0167 * @name NAND Status Register 0168 * 0169 * @{ 0170 */ 0171 0172 #define NAND_STATUS_ERROR (1U << 0) 0173 #define NAND_STATUS_READY (1U << 6) 0174 #define NAND_STATUS_NOT_PROTECTED (1U << 7) 0175 0176 /** @} */ 0177 0178 /** 0179 * @brief MLC NAND controller configuration. 0180 */ 0181 typedef struct { 0182 uint32_t flags; 0183 0184 uint32_t block_count; 0185 0186 /** 0187 * @brief Value for the MLC NAND Timing Register (MLC_TIME_REG). 0188 */ 0189 uint32_t time; 0190 } lpc32xx_mlc_config; 0191 0192 /** 0193 * @brief Selects small pages (512 Bytes user data and 16 Bytes spare data) 0194 * or large pages (2048 Bytes user data and 64 Bytes spare data) if not set. 0195 */ 0196 #define MLC_SMALL_PAGES 0x1U 0197 0198 /** 0199 * @Brief Selects 4/5 address cycles for small/large pages or 3/4 address 0200 * cycles if not set. 0201 */ 0202 #define MLC_MANY_ADDRESS_CYCLES 0x2U 0203 0204 /** 0205 * @brief Selects 64 pages per block or 128 pages per block if not set. 0206 * 0207 * This flag is only valid for large pages. 0208 */ 0209 #define MLC_NORMAL_BLOCKS 0x4U 0210 0211 /** 0212 * @brief Selects 16-bit IO width or 8-bit IO width if not set. 0213 */ 0214 #define MLC_IO_WIDTH_16_BIT 0x8U 0215 0216 /** 0217 * @brief Initializes the MLC NAND controller according to @a cfg. 0218 */ 0219 void lpc32xx_mlc_init(const lpc32xx_mlc_config *cfg); 0220 0221 uint32_t lpc32xx_mlc_page_size(void); 0222 0223 uint32_t lpc32xx_mlc_pages_per_block(void); 0224 0225 uint32_t lpc32xx_mlc_block_count(void); 0226 0227 uint32_t lpc32xx_mlc_io_width(void); 0228 0229 void lpc32xx_mlc_write_protection( 0230 uint32_t page_index_low, 0231 uint32_t page_index_high 0232 ); 0233 0234 void lpc32xx_mlc_read_id(uint8_t *id, size_t n); 0235 0236 /** 0237 * @brief Reads the page with index @a page_index. 0238 * 0239 * Bytes 6 to 15 of the spare area will contain the ECC. 0240 * 0241 * If the read is successful, then the @a symbol_error_count will contain the 0242 * number of detected symbol errors (0, 1, 2, 3, or 4), else the value will be 0243 * 0xffffffff. The @a symbol_error_count pointer may be @c NULL. 0244 * 0245 * @retval RTEMS_SUCCESSFUL Successful operation. 0246 * @retval RTEMS_INVALID_ID Invalid @a page_index value. 0247 * @retval RTEMS_IO_ERROR Uncorrectable bit error. 0248 */ 0249 rtems_status_code lpc32xx_mlc_read_page( 0250 uint32_t page_index, 0251 void *data, 0252 void *spare, 0253 uint32_t *symbol_error_count 0254 ); 0255 0256 /** 0257 * @brief Checks if the block with index @a block_index is valid. 0258 * 0259 * The initial valid block information of the manufacturer will be used. 0260 * Unfortunately there seems to be no standard for this. A block will be 0261 * considered as bad if the first or second page of this block does not contain 0262 * 0xff at the 6th byte of the spare area. This should work for flashes with 0263 * small pages and a 8-bit IO width. 0264 * 0265 * @retval RTEMS_SUCCESSFUL The block is valid. 0266 * @retval RTEMS_INVALID_ID Invalid @a block_index value. 0267 * @retval RTEMS_IO_ERROR Uncorrectable bit error. 0268 * @retval RTEMS_INCORRECT_STATE The block is bad. 0269 * @retval RTEMS_NOT_IMPLEMENTED No implementation available for this flash 0270 * type. 0271 */ 0272 rtems_status_code lpc32xx_mlc_is_valid_block(uint32_t block_index); 0273 0274 /** 0275 * @brief Erases the block with index @a block_index. 0276 * 0277 * @retval RTEMS_SUCCESSFUL Successful operation. 0278 * @retval RTEMS_INVALID_ID Invalid @a block_index value. 0279 * @retval RTEMS_UNSATISFIED Erase error. 0280 */ 0281 rtems_status_code lpc32xx_mlc_erase_block(uint32_t block_index); 0282 0283 /** 0284 * @brief Erases the block with index @a block_index. 0285 * 0286 * In case of an erase error all pages and the spare areas of this block are 0287 * programmed with zero values. This will hopefully mark the block as bad. 0288 * 0289 * @retval RTEMS_SUCCESSFUL Successful operation. 0290 * @retval RTEMS_INCORRECT_STATE The block is bad. 0291 * @retval RTEMS_INVALID_ID Invalid @a block_index value. 0292 * @retval RTEMS_UNSATISFIED Erase error. 0293 * @retval RTEMS_NOT_IMPLEMENTED No implementation available for this flash 0294 * type. 0295 */ 0296 rtems_status_code lpc32xx_mlc_erase_block_safe(uint32_t block_index); 0297 0298 /** 0299 * @brief Erases the block with index @a block_index. 0300 * 0301 * Variant of lpc32xx_mlc_erase_block_safe() with more parameters for 0302 * efficiency reasons. The @a page_begin must be the index of the first page 0303 * of the block. The @a page_end must be the page index of the last page of 0304 * the block plus one. 0305 */ 0306 rtems_status_code lpc32xx_mlc_erase_block_safe_3( 0307 uint32_t block_index, 0308 uint32_t page_begin, 0309 uint32_t page_end 0310 ); 0311 0312 /** 0313 * @brief Writes zero values to the pages specified by @a page_begin and 0314 * @a page_end. 0315 * 0316 * The data and spare area are cleared to zero. This marks the pages as bad. 0317 */ 0318 void lpc32xx_mlc_zero_pages(uint32_t page_begin, uint32_t page_end); 0319 0320 /** 0321 * @brief Writes the page with index @a page_index. 0322 * 0323 * Only the bytes 0 to 5 of the spare area can be used for user data, the bytes 0324 * 6 to 15 will be used for the automatically generated ECC. 0325 * 0326 * @retval RTEMS_SUCCESSFUL Successful operation. 0327 * @retval RTEMS_INVALID_ID Invalid @a page_index value. 0328 * @retval RTEMS_IO_ERROR Write error. 0329 */ 0330 rtems_status_code lpc32xx_mlc_write_page_with_ecc( 0331 uint32_t page_index, 0332 const void *data, 0333 const void *spare 0334 ); 0335 0336 /** 0337 * @brief Writes @a src_size Bytes from @a src to the flash area specified by 0338 * @a block_begin and @a block_end. 0339 * 0340 * The @a page_buffer will be used as an intermediate buffer. 0341 * 0342 * @retval RTEMS_SUCCESSFUL Successful operation. 0343 * @retval RTEMS_INVALID_ID Invalid @a block_begin or @a block_end value. 0344 * @retval RTEMS_IO_ERROR Too many bad blocks or source area too big. 0345 */ 0346 rtems_status_code lpc32xx_mlc_write_blocks( 0347 uint32_t block_begin, 0348 uint32_t block_end, 0349 const void *src, 0350 size_t src_size, 0351 uint32_t page_buffer [MLC_LARGE_DATA_WORD_COUNT] 0352 ); 0353 0354 /** 0355 * @brief Read blocks process function type. 0356 * 0357 * @see lpc32xx_mlc_read_blocks(). 0358 * 0359 * @retval false Continue processing. 0360 * @retval true Stop processing. 0361 */ 0362 typedef bool (*lpc32xx_mlc_read_process)( 0363 void *process_arg, 0364 uint32_t page_index, 0365 uint32_t page_size, 0366 uint32_t page_data [MLC_LARGE_DATA_WORD_COUNT], 0367 uint32_t page_spare [MLC_LARGE_SPARE_WORD_COUNT] 0368 ); 0369 0370 /** 0371 * @brief Reads the pages of block @a block_begin up to and excluding 0372 * @a block_end. 0373 * 0374 * For each page @a process will be called with the @a process_arg parameter, 0375 * the page_index, the page data and the page spare. 0376 * 0377 * The @a page_buffer_0 and @a page_buffer_1 will be used as 0378 * intermediate buffers. 0379 */ 0380 rtems_status_code lpc32xx_mlc_read_blocks( 0381 uint32_t block_begin, 0382 uint32_t block_end, 0383 lpc32xx_mlc_read_process process, 0384 void *process_arg, 0385 uint32_t page_buffer_0 [MLC_LARGE_DATA_WORD_COUNT], 0386 uint32_t page_buffer_1 [MLC_LARGE_DATA_WORD_COUNT] 0387 ); 0388 0389 /** 0390 * @brief Checks if the page spare area indicates to a bad page. 0391 * 0392 * If the first (byte offset 0) or sixth (byte offset 5) byte of the spare area 0393 * has a value other than 0xff, then it returns @a true (the page is bad), else 0394 * it returns @a false (the page is not bad). 0395 * 0396 * Samsung uses the sixth byte to indicate a bad page. Mircon uses the first 0397 * and sixth byte to indicate a bad page. 0398 * 0399 * This functions works only for small page flashes. 0400 */ 0401 static inline bool lpc32xx_mlc_is_bad_page(const uint32_t *spare) 0402 { 0403 uint32_t first_byte_mask = 0x000000ff; 0404 uint32_t sixth_byte_mask = 0x0000ff00; 0405 0406 return (spare [0] & first_byte_mask) != first_byte_mask 0407 || (spare [1] & sixth_byte_mask) != sixth_byte_mask; 0408 } 0409 0410 /** @} */ 0411 0412 #ifdef __cplusplus 0413 } 0414 #endif /* __cplusplus */ 0415 0416 #endif /* LIBBSP_ARM_LPC32XX_NAND_MLC_H */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |