diff options
Diffstat (limited to 'bsps/arm/lpc32xx/nand')
-rw-r--r-- | bsps/arm/lpc32xx/nand/nand-mlc-erase-block-safe.c | 122 | ||||
-rw-r--r-- | bsps/arm/lpc32xx/nand/nand-mlc-read-blocks.c | 134 | ||||
-rw-r--r-- | bsps/arm/lpc32xx/nand/nand-mlc-write-blocks.c | 111 | ||||
-rw-r--r-- | bsps/arm/lpc32xx/nand/nand-mlc.c | 397 | ||||
-rw-r--r-- | bsps/arm/lpc32xx/nand/nand-select.c | 44 |
5 files changed, 808 insertions, 0 deletions
diff --git a/bsps/arm/lpc32xx/nand/nand-mlc-erase-block-safe.c b/bsps/arm/lpc32xx/nand/nand-mlc-erase-block-safe.c new file mode 100644 index 0000000000..b7e570e46d --- /dev/null +++ b/bsps/arm/lpc32xx/nand/nand-mlc-erase-block-safe.c @@ -0,0 +1,122 @@ +/** + * @file + * + * @ingroup lpc32xx_nand_mlc + * + * @brief lpc32xx_mlc_erase_block_safe(), lpc32xx_mlc_erase_block_safe_3(), and + * lpc32xx_mlc_zero_block() implementation. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/nand-mlc.h> + +#include <string.h> + +#include <bsp.h> + +void lpc32xx_mlc_zero_pages(uint32_t page_begin, uint32_t page_end) +{ + uint32_t page = 0; + + for (page = page_begin; page < page_end; ++page) { + lpc32xx_mlc_write_page_with_ecc( + page, + lpc32xx_magic_zero_begin, + lpc32xx_magic_zero_begin + ); + } +} + +static rtems_status_code is_valid_page( + uint32_t page_begin, + uint32_t page_offset +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + uint32_t spare [MLC_LARGE_SPARE_WORD_COUNT]; + + memset(spare, 0, MLC_LARGE_SPARE_SIZE); + + sc = lpc32xx_mlc_read_page( + page_begin + page_offset, + lpc32xx_magic_zero_begin, + spare, + NULL + ); + if (sc == RTEMS_SUCCESSFUL) { + if (lpc32xx_mlc_is_bad_page(spare)) { + sc = RTEMS_INCORRECT_STATE; + } + } + + return sc; +} + +static rtems_status_code is_valid_block(uint32_t page_begin) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (lpc32xx_mlc_page_size() == 512 && lpc32xx_mlc_io_width() == 8) { + sc = is_valid_page(page_begin, 0); + if (sc == RTEMS_SUCCESSFUL) { + sc = is_valid_page(page_begin, 1); + } + } else { + sc = RTEMS_NOT_IMPLEMENTED; + } + + return sc; +} + +rtems_status_code lpc32xx_mlc_is_valid_block(uint32_t block_index) +{ + uint32_t pages_per_block = lpc32xx_mlc_pages_per_block(); + uint32_t page_begin = block_index * pages_per_block; + + return is_valid_block(page_begin); +} + +rtems_status_code lpc32xx_mlc_erase_block_safe_3( + uint32_t block_index, + uint32_t page_begin, + uint32_t page_end +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + sc = is_valid_block(page_begin); + if (sc == RTEMS_SUCCESSFUL) { + sc = lpc32xx_mlc_erase_block(block_index); + if (sc == RTEMS_UNSATISFIED) { + lpc32xx_mlc_zero_pages(page_begin, page_end); + } + } + + return sc; +} + +rtems_status_code lpc32xx_mlc_erase_block_safe(uint32_t block_index) +{ + uint32_t pages_per_block = lpc32xx_mlc_pages_per_block(); + uint32_t page_begin = block_index * pages_per_block; + uint32_t page_end = page_begin + pages_per_block; + + return lpc32xx_mlc_erase_block_safe_3( + block_index, + page_begin, + page_end + ); +} diff --git a/bsps/arm/lpc32xx/nand/nand-mlc-read-blocks.c b/bsps/arm/lpc32xx/nand/nand-mlc-read-blocks.c new file mode 100644 index 0000000000..bc01a984ea --- /dev/null +++ b/bsps/arm/lpc32xx/nand/nand-mlc-read-blocks.c @@ -0,0 +1,134 @@ +/** + * @file + * + * @ingroup lpc32xx_nand_mlc + * + * @brief lpc32xx_mlc_read_blocks() implementation. + */ + +/* + * Copyright (c) 2010 + * embedded brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/nand-mlc.h> + +#include <string.h> + +static rtems_status_code read_page( + uint32_t first_page_of_block, + uint32_t page, + uint32_t page_data [MLC_LARGE_DATA_WORD_COUNT], + uint32_t page_spare [MLC_LARGE_SPARE_WORD_COUNT] +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + uint32_t page_index = first_page_of_block + page; + bool possible_bad_page = page == 0 || page == 1; + + if (possible_bad_page) { + memset(page_spare, 0, MLC_LARGE_SPARE_SIZE); + } + + sc = lpc32xx_mlc_read_page(page_index, page_data, page_spare, NULL); + if (possible_bad_page && lpc32xx_mlc_is_bad_page(page_spare)) { + return RTEMS_UNSATISFIED; + } else if (sc == RTEMS_SUCCESSFUL) { + return RTEMS_SUCCESSFUL; + } else { + return sc; + } +} + +rtems_status_code lpc32xx_mlc_read_blocks( + uint32_t block_begin, + uint32_t block_end, + lpc32xx_mlc_read_process process, + void *process_arg, + uint32_t page_buffer_0 [MLC_LARGE_DATA_WORD_COUNT], + uint32_t page_buffer_1 [MLC_LARGE_DATA_WORD_COUNT] +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + uint32_t page_spare_0 [MLC_LARGE_SPARE_WORD_COUNT]; + uint32_t page_spare_1 [MLC_LARGE_SPARE_WORD_COUNT]; + uint32_t pages_per_block = lpc32xx_mlc_pages_per_block(); + uint32_t page_size = lpc32xx_mlc_page_size(); + uint32_t block = 0; + uint32_t first_page_of_block = block_begin * pages_per_block; + + for ( + block = block_begin; + block != block_end; + ++block, first_page_of_block += pages_per_block + ) { + uint32_t page = 0; + bool done = false; + + sc = read_page(first_page_of_block, 0, page_buffer_0, page_spare_0); + if (sc == RTEMS_UNSATISFIED) { + continue; + } else if (sc != RTEMS_SUCCESSFUL) { + goto done; + } + + sc = read_page(first_page_of_block, 1, page_buffer_1, page_spare_1); + if (sc == RTEMS_UNSATISFIED) { + continue; + } else if (sc != RTEMS_SUCCESSFUL) { + goto done; + } + + done = (*process)( + process_arg, + first_page_of_block + 0, + page_size, + page_buffer_0, + page_spare_0 + ); + if (done) { + goto done; + } + + done = (*process)( + process_arg, + first_page_of_block + 1, + page_size, + page_buffer_1, + page_spare_1 + ); + if (done) { + goto done; + } + + for (page = 2; page < pages_per_block; ++page) { + sc = read_page(first_page_of_block, page, page_buffer_1, page_spare_1); + if (sc != RTEMS_SUCCESSFUL) { + goto done; + } + + done = (*process)( + process_arg, + first_page_of_block + page, + page_size, + page_buffer_1, + page_spare_1 + ); + if (done) { + goto done; + } + } + } + +done: + + return sc; +} diff --git a/bsps/arm/lpc32xx/nand/nand-mlc-write-blocks.c b/bsps/arm/lpc32xx/nand/nand-mlc-write-blocks.c new file mode 100644 index 0000000000..cfcb9cd27e --- /dev/null +++ b/bsps/arm/lpc32xx/nand/nand-mlc-write-blocks.c @@ -0,0 +1,111 @@ +/** + * @file + * + * @ingroup lpc32xx_nand_mlc + * + * @brief lpc32xx_mlc_write_blocks() implementation. + */ + +/* + * Copyright (c) 2010-2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/nand-mlc.h> + +#include <string.h> + +static const uint32_t ones_spare [MLC_LARGE_SPARE_WORD_COUNT] = { + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xffffffff +}; + +rtems_status_code lpc32xx_mlc_write_blocks( + uint32_t block_begin, + uint32_t block_end, + const void *src, + size_t src_size, + uint32_t *page_data_buffer +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + uint32_t pages_per_block = lpc32xx_mlc_pages_per_block(); + uint32_t block_count = lpc32xx_mlc_block_count(); + uint32_t page_size = lpc32xx_mlc_page_size(); + uint32_t block = 0; + const uint8_t *current = src; + const uint8_t *last = current; + const uint8_t *end = current + src_size; + + if (block_begin > block_end || block_end > block_count) { + return RTEMS_INVALID_ID; + } + + for (block = block_begin; block != block_end; ++block) { + uint32_t page_begin = block * pages_per_block; + uint32_t page_end = page_begin + pages_per_block; + uint32_t page = 0; + + sc = lpc32xx_mlc_erase_block_safe_3(block, page_begin, page_end); + if (sc != RTEMS_SUCCESSFUL) { + continue; + } + + for (page = page_begin; page < page_end; ++page) { + uintptr_t remainder = (uintptr_t) end - (uintptr_t) current; + size_t delta = remainder < page_size ? remainder : page_size; + + if (remainder > 0) { + memcpy(page_data_buffer, current, delta); + sc = lpc32xx_mlc_write_page_with_ecc( + page, + page_data_buffer, + ones_spare + ); + if (sc != RTEMS_SUCCESSFUL) { + lpc32xx_mlc_erase_block(block); + lpc32xx_mlc_zero_pages(page_begin, page_end); + current = last; + continue; + } + + current += delta; + } else { + goto done; + } + } + + last = current; + } + +done: + + if (current != end) { + return RTEMS_IO_ERROR; + } + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/lpc32xx/nand/nand-mlc.c b/bsps/arm/lpc32xx/nand/nand-mlc.c new file mode 100644 index 0000000000..f87c59b133 --- /dev/null +++ b/bsps/arm/lpc32xx/nand/nand-mlc.c @@ -0,0 +1,397 @@ +/** + * @file + * + * @ingroup lpc32xx_nand_mlc + * + * @brief NAND MLC controller implementation. + */ + +/* + * Copyright (c) 2010-2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/lpc32xx.h> +#include <bsp/nand-mlc.h> + +static volatile lpc32xx_nand_mlc *const mlc = &lpc32xx.nand_mlc; + +static uint32_t mlc_flags; + +static uint32_t mlc_block_count; + +static uint32_t mlc_page_count; + +static bool mlc_small_pages(void) +{ + return (mlc_flags & MLC_SMALL_PAGES) != 0; +} + +static bool mlc_many_address_cycles(void) +{ + return (mlc_flags & MLC_MANY_ADDRESS_CYCLES) != 0; +} + +static bool mlc_normal_blocks(void) +{ + return (mlc_flags & MLC_NORMAL_BLOCKS) != 0; +} + +uint32_t lpc32xx_mlc_page_size(void) +{ + if (mlc_small_pages()) { + return 512; + } else { + return 2048; + } +} + +uint32_t lpc32xx_mlc_pages_per_block(void) +{ + if (mlc_small_pages()) { + return 32; + } else { + if (mlc_normal_blocks()) { + return 64; + } else { + return 128; + } + } +} + +uint32_t lpc32xx_mlc_block_count(void) +{ + return mlc_block_count; +} + +uint32_t lpc32xx_mlc_io_width(void) +{ + if ((mlc_flags & MLC_IO_WIDTH_16_BIT) == 0) { + return 8; + } else { + return 16; + } +} + +static void mlc_unlock(void) +{ + mlc->lock_pr = MLC_UNLOCK_PROT; +} + +static void mlc_wait(uint32_t flags) +{ + while ((mlc->isr & flags) != flags) { + /* Wait */ + } +} + +static void mlc_wait_until_ready(void) +{ + mlc_wait(MLC_ISR_CONTROLLER_READY | MLC_ISR_NAND_READY); +} + +static void mlc_reset(void) +{ + mlc->cmd = 0xff; +} + +static uint32_t mlc_status(void) +{ + mlc_wait_until_ready(); + mlc->cmd = 0x70; + + return mlc->data.w8; +} + +static bool mlc_was_operation_successful(void) +{ + return (mlc_status() & (NAND_STATUS_READY | NAND_STATUS_ERROR)) + == NAND_STATUS_READY; +} + +static void mlc_set_block_address(uint32_t block_index) +{ + if (mlc_small_pages()) { + mlc->addr = (uint8_t) (block_index << 5); + mlc->addr = (uint8_t) (block_index >> 3); + if (mlc_many_address_cycles()) { + mlc->addr = (uint8_t) (block_index >> 11); + } + } else { + if (mlc_normal_blocks()) { + mlc->addr = (uint8_t) (block_index << 6); + mlc->addr = (uint8_t) (block_index >> 2); + if (mlc_many_address_cycles()) { + mlc->addr = (uint8_t) (block_index >> 10); + } + } else { + mlc->addr = (uint8_t) (block_index << 7); + mlc->addr = (uint8_t) (block_index >> 1); + if (mlc_many_address_cycles()) { + mlc->addr = (uint8_t) (block_index >> 9); + } + } + } +} + +static void mlc_set_page_address(uint32_t page_index) +{ + mlc->addr = 0; + if (mlc_small_pages()) { + mlc->addr = (uint8_t) page_index; + mlc->addr = (uint8_t) (page_index >> 8); + if (mlc_many_address_cycles()) { + mlc->addr = (uint8_t) (page_index >> 16); + } + } else { + mlc->addr = 0; + mlc->addr = (uint8_t) page_index; + mlc->addr = (uint8_t) (page_index >> 8); + if (mlc_many_address_cycles()) { + mlc->addr = (uint8_t) (page_index >> 16); + } + } +} + +void lpc32xx_mlc_init(const lpc32xx_mlc_config *cfg) +{ + uint32_t icr = 0; + + mlc_flags = cfg->flags; + mlc_block_count = cfg->block_count; + mlc_page_count = cfg->block_count * lpc32xx_mlc_pages_per_block(); + + /* Clock */ + LPC32XX_FLASHCLK_CTRL = FLASHCLK_IRQ_MLC | FLASHCLK_MLC_CLK_ENABLE; + + /* Timing settings */ + mlc_unlock(); + mlc->time = cfg->time; + + /* Configuration */ + if (!mlc_small_pages()) { + icr |= MLC_ICR_LARGE_PAGES; + } + if (mlc_many_address_cycles()) { + icr |= MLC_ICR_ADDR_WORD_COUNT_4_5; + } + mlc_unlock(); + mlc->icr = icr; + + mlc_reset(); +} + +void lpc32xx_mlc_write_protection( + uint32_t page_index_low, + uint32_t page_index_high +) +{ + mlc_unlock(); + mlc->sw_wp_add_low = page_index_low; + mlc_unlock(); + mlc->sw_wp_add_hig = page_index_high; + mlc_unlock(); + mlc->icr |= MLC_ICR_SOFT_WRITE_PROT; +} + +static bool is_word_aligned(const void *data, const void *spare) +{ + return (((uintptr_t) data) | ((uintptr_t) spare)) % 4 == 0; +} + +rtems_status_code lpc32xx_mlc_read_page( + uint32_t page_index, + void *data, + void *spare, + uint32_t *symbol_error_count_ptr +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + size_t small_pages_count = mlc_small_pages() ? 1 : MLC_SMALL_PAGES_PER_LARGE_PAGE; + size_t sp = 0; + size_t i = 0; + uint32_t isr = 0; + uint32_t symbol_error_count = 0xffffffff; + bool aligned = is_word_aligned(data, spare); + uint8_t *current_data = data; + uint8_t *current_spare = spare; + + if (page_index >= mlc_page_count) { + return RTEMS_INVALID_ID; + } + + mlc_wait_until_ready(); + mlc->cmd = 0x00; + if (!mlc_small_pages()) { + mlc->cmd = 0x30; + } + mlc_set_page_address(page_index); + mlc_wait(MLC_ISR_NAND_READY); + + for (sp = 0; sc == RTEMS_SUCCESSFUL && sp < small_pages_count; ++sp) { + uint32_t *aligned_data = (uint32_t *) current_data; + uint32_t *aligned_spare = (uint32_t *) current_spare; + + mlc->ecc_dec = 0; + + if (aligned) { + for (i = 0; i < MLC_SMALL_DATA_WORD_COUNT; ++i) { + aligned_data [i] = mlc->data.w32; + } + for (i = 0; i < MLC_SMALL_SPARE_WORD_COUNT; ++i) { + aligned_spare [i] = mlc->data.w32; + } + } else { + for (i = 0; i < MLC_SMALL_DATA_SIZE; ++i) { + current_data [i] = mlc->data.w8; + } + for (i = 0; i < MLC_SMALL_SPARE_SIZE; ++i) { + current_spare [i] = mlc->data.w8; + } + } + + mlc_wait(MLC_ISR_ECC_READY); + + isr = mlc->isr; + if ((isr & MLC_ISR_ERRORS_DETECTED) == 0) { + symbol_error_count = 0; + } else { + if ((isr & MLC_ISR_DECODER_FAILURE) == 0) { + symbol_error_count = MLC_ISR_SYMBOL_ERRORS(isr); + if (aligned) { + mlc->rubp = 0; + for (i = 0; i < MLC_SMALL_DATA_WORD_COUNT; ++i) { + aligned_data [i] = mlc->buff.w32; + } + mlc->robp = 0; + for (i = 0; i < MLC_SMALL_SPARE_WORD_COUNT; ++i) { + aligned_spare [i] = mlc->buff.w32; + } + } else { + mlc->rubp = 0; + for (i = 0; i < MLC_SMALL_DATA_SIZE; ++i) { + current_data [i] = mlc->buff.w8; + } + mlc->robp = 0; + for (i = 0; i < MLC_SMALL_SPARE_SIZE; ++i) { + current_spare [i] = mlc->buff.w8; + } + } + } else { + sc = RTEMS_IO_ERROR; + } + } + + current_data += MLC_SMALL_DATA_SIZE; + current_spare += MLC_SMALL_SPARE_SIZE; + } + + if (symbol_error_count_ptr != NULL) { + *symbol_error_count_ptr = symbol_error_count; + } + + return sc; +} + +void lpc32xx_mlc_read_id(uint8_t *id, size_t n) +{ + size_t i = 0; + + mlc_wait_until_ready(); + mlc->cmd = 0x90; + mlc->addr = 0; + mlc_wait(MLC_ISR_NAND_READY); + + for (i = 0; i < n; ++i) { + id [i] = mlc->data.w8; + } +} + +rtems_status_code lpc32xx_mlc_erase_block(uint32_t block_index) +{ + rtems_status_code sc = RTEMS_UNSATISFIED; + + if (block_index >= mlc_block_count) { + return RTEMS_INVALID_ID; + } + + mlc_wait_until_ready(); + mlc->cmd = 0x60; + mlc_set_block_address(block_index); + mlc->cmd = 0xd0; + + if (mlc_was_operation_successful()) { + sc = RTEMS_SUCCESSFUL; + } + + return sc; +} + +rtems_status_code lpc32xx_mlc_write_page_with_ecc( + uint32_t page_index, + const void *data, + const void *spare +) +{ + rtems_status_code sc = RTEMS_IO_ERROR; + size_t small_pages_count = mlc_small_pages() ? + 1 : MLC_SMALL_PAGES_PER_LARGE_PAGE; + size_t sp = 0; + size_t i = 0; + bool aligned = is_word_aligned(data, spare); + const uint8_t *current_data = data; + const uint8_t *current_spare = spare; + + if (page_index >= mlc_page_count) { + return RTEMS_INVALID_ID; + } + + mlc_wait_until_ready(); + mlc->cmd = 0x80; + mlc_set_page_address(page_index); + + for (sp = 0; sp < small_pages_count; ++sp) { + mlc->ecc_enc = 0; + + if (aligned) { + const uint32_t *aligned_data = (const uint32_t *) current_data; + const uint32_t *aligned_spare = (const uint32_t *) current_spare; + + for (i = 0; i < MLC_SMALL_DATA_WORD_COUNT; ++i) { + mlc->data.w32 = aligned_data [i]; + } + mlc->data.w32 = aligned_spare [0]; + mlc->data.w16 = (uint16_t) aligned_spare [1]; + } else { + for (i = 0; i < MLC_SMALL_DATA_SIZE; ++i) { + mlc->data.w8 = current_data [i]; + } + for (i = 0; i < MLC_SMALL_USER_SPARE_SIZE; ++i) { + mlc->data.w8 = current_spare [i]; + } + } + mlc->wpr = 0; + + mlc_wait(MLC_ISR_CONTROLLER_READY); + + current_data += MLC_SMALL_DATA_SIZE; + current_spare += MLC_SMALL_SPARE_SIZE; + } + + mlc->cmd = 0x10; + + if (mlc_was_operation_successful()) { + sc = RTEMS_SUCCESSFUL; + } + + return sc; +} diff --git a/bsps/arm/lpc32xx/nand/nand-select.c b/bsps/arm/lpc32xx/nand/nand-select.c new file mode 100644 index 0000000000..9c03b12b85 --- /dev/null +++ b/bsps/arm/lpc32xx/nand/nand-select.c @@ -0,0 +1,44 @@ +/** + * @file + * + * @ingroup arm_lpc32xx + * + * @brief NAND controller selection. + */ + +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/lpc32xx.h> +#include <bsp/nand-mlc.h> + +void lpc32xx_select_nand_controller(lpc32xx_nand_controller nand_controller) +{ + uint32_t flashclk_ctrl = LPC32XX_FLASHCLK_CTRL & ~(FLASHCLK_IRQ_MLC + | FLASHCLK_SELECT_SLC | FLASHCLK_MLC_CLK_ENABLE | FLASHCLK_SLC_CLK_ENABLE); + + switch (nand_controller) { + case LPC32XX_NAND_CONTROLLER_MLC: + flashclk_ctrl |= FLASHCLK_IRQ_MLC | FLASHCLK_MLC_CLK_ENABLE; + break; + case LPC32XX_NAND_CONTROLLER_SLC: + flashclk_ctrl |= FLASHCLK_SELECT_SLC | FLASHCLK_SLC_CLK_ENABLE; + break; + default: + break; + } + + LPC32XX_FLASHCLK_CTRL = flashclk_ctrl; +} |