summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/arm/lpc32xx/include
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2010-06-23 08:27:57 +0000
committerSebastian Huber <sebastian.huber@embedded-brains.de>2010-06-23 08:27:57 +0000
commit3103d4cbad582cc9e62aaf15fd5af308949a83f0 (patch)
treeb1ff4f68908b3177c614349a2f0252e4b64e9b18 /c/src/lib/libbsp/arm/lpc32xx/include
parent2010-06-23 Sebastian Huber <sebastian.huber@embedded-brains.de> (diff)
downloadrtems-3103d4cbad582cc9e62aaf15fd5af308949a83f0.tar.bz2
2010-06-23 Sebastian Huber <sebastian.huber@embedded-brains.de>
* make/custom/lpc32xx_mzx_boot_int.cfg, startup/linkcmds.lpc32xx_mzx_boot_int: Removed files. * include/boot.h, include/emc.h, include/i2c.h, include/nand-mlc.h, make/custom/lpc32xx_mzx.cfg, make/custom/lpc32xx_mzx_stage_1.cfg, make/custom/lpc32xx_mzx_stage_2.cfg, misc/boot.c, misc/emc.c, misc/i2c.c, misc/nand-mlc.c, misc/nand-mlc-read-blocks.c, misc/nand-mlc-write-blocks.c, misc/restart.c, startup/linkcmds.lpc32xx, startup/linkcmds.lpc32xx_mzx, startup/linkcmds.lpc32xx_mzx_stage_1, startup/linkcmds.lpc32xx_mzx_stage_2: New files. * configure.ac, Makefile.am, preinstall.am: Reflect changes above. * include/bsp.h, include/lpc32xx.h, irq/irq.c, rtc/rtc-config.c, startup/bspstart.c, startup/bspstarthooks.c, startup/linkcmds.lpc32xx_phycore: Changes throughout.
Diffstat (limited to '')
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/include/boot.h111
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/include/bsp.h41
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/include/emc.h231
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/include/i2c.h269
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/include/lpc32xx.h356
-rw-r--r--c/src/lib/libbsp/arm/lpc32xx/include/nand-mlc.h335
6 files changed, 1303 insertions, 40 deletions
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/boot.h b/c/src/lib/libbsp/arm/lpc32xx/include/boot.h
new file mode 100644
index 0000000000..cb8ab5c392
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/boot.h
@@ -0,0 +1,111 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_boot
+ *
+ * @brief Boot support API.
+ */
+
+/*
+ * 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.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_LPC32XX_BOOT_H
+#define LIBBSP_ARM_LPC32XX_BOOT_H
+
+#include <stdint.h>
+
+#include <bsp/nand-mlc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup lpc32xx_boot Boot Support
+ *
+ * @ingroup lpc32xx
+ *
+ * @brief Boot support.
+ *
+ * The NXP internal boot program shall be the "stage-0 program".
+ *
+ * The boot program within the first page of the first or second block shall be
+ * "stage-1 program". It will be invoked by the stage-0 program from NXP.
+ *
+ * The program loaded by the stage-1 program will be the "stage-2 program" or the
+ * "boot loader".
+ *
+ * The program loaded by the stage-2 program will be the "stage-3 program" or the
+ * "application".
+ *
+ * The stage-1 program image must have a format specified by NXP.
+ *
+ * The stage-2 and stage-3 program images may have any format.
+ *
+ * @{
+ */
+
+#define LPC32XX_BOOT_STAGE_1_BLOCK_0 0
+#define LPC32XX_BOOT_STAGE_1_BLOCK_1 1
+#define LPC32XX_BOOT_STAGE_2_BLOCK_0 2
+
+#define LPC32XX_BOOT_ICR_SP_3AC_8IF 0xf0
+#define LPC32XX_BOOT_ICR_SP_4AC_8IF 0xd2
+#define LPC32XX_BOOT_ICR_LP_4AC_8IF 0xb4
+#define LPC32XX_BOOT_ICR_LP_5AC_8IF 0x96
+
+typedef union {
+ struct {
+ uint8_t d0;
+ uint8_t reserved_0 [3];
+ uint8_t d1;
+ uint8_t reserved_1 [3];
+ uint8_t d2;
+ uint8_t reserved_2 [3];
+ uint8_t d3;
+ uint8_t reserved_3 [3];
+ uint8_t d4;
+ uint8_t reserved_4 [3];
+ uint8_t d5;
+ uint8_t reserved_5 [3];
+ uint8_t d6;
+ uint8_t reserved_6 [3];
+ uint8_t d7;
+ uint8_t reserved_7 [3];
+ uint8_t d8;
+ uint8_t reserved_8 [3];
+ uint8_t d9;
+ uint8_t reserved_9 [3];
+ uint8_t d10;
+ uint8_t reserved_10 [3];
+ uint8_t d11;
+ uint8_t reserved_11 [3];
+ uint8_t d12;
+ uint8_t reserved_12 [463];
+ } field;
+ uint32_t data [MLC_SMALL_DATA_WORD_COUNT];
+} lpc32xx_boot_block;
+
+void lpc32xx_setup_boot_block(
+ lpc32xx_boot_block *boot_block,
+ uint8_t icr,
+ uint8_t page_count
+);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_LPC32XX_BOOT_H */
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/bsp.h b/c/src/lib/libbsp/arm/lpc32xx/include/bsp.h
index bef90e1333..b4c0c1143a 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/include/bsp.h
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/bsp.h
@@ -7,7 +7,7 @@
*/
/*
- * Copyright (c) 2009
+ * Copyright (c) 2009, 2010
* embedded brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
@@ -29,7 +29,6 @@
#include <rtems/clockdrv.h>
#include <bsp/lpc32xx.h>
-#include <bsp/lpc-timer.h>
#ifdef __cplusplus
extern "C" {
@@ -91,7 +90,7 @@ int lpc_eth_attach_detach(
*/
void *lpc32xx_idle(uintptr_t ignored);
-#define LPC32XX_STANDARD_TIMER ((volatile lpc_timer *) LPC32XX_BASE_TIMER_1)
+#define LPC32XX_STANDARD_TIMER (&lpc32xx.timer_1)
static inline unsigned lpc32xx_timer(void)
{
@@ -100,7 +99,41 @@ static inline unsigned lpc32xx_timer(void)
return timer->tc;
}
-#define BSP_CONSOLE_UART_BASE 0x40090000
+static inline void lpc32xx_micro_seconds_delay(unsigned us)
+{
+ unsigned start = lpc32xx_timer();
+ unsigned end = start + us * (LPC32XX_PERIPH_CLK / 1000000);
+ unsigned now = 0;
+
+ do {
+ now = lpc32xx_timer();
+ } while (now < end);
+}
+
+void lpc32xx_restart(void *addr);
+
+#define BSP_CONSOLE_UART_BASE LPC32XX_BASE_UART_5
+
+/**
+ * @brief Begin of magic zero area.
+ *
+ * A read from this area returns zero. Writes have no effect.
+ */
+extern uint32_t lpc32xx_magic_zero_begin [];
+
+/**
+ * @brief End of magic zero area.
+ *
+ * A read from this area returns zero. Writes have no effect.
+ */
+extern uint32_t lpc32xx_magic_zero_end [];
+
+/**
+ * @brief Size of magic zero area.
+ *
+ * A read from this area returns zero. Writes have no effect.
+ */
+extern uint32_t lpc32xx_magic_zero_size [];
/** @} */
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/emc.h b/c/src/lib/libbsp/arm/lpc32xx/include/emc.h
new file mode 100644
index 0000000000..2eb5a3bda3
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/emc.h
@@ -0,0 +1,231 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_emc
+ *
+ * @brief EMC support API.
+ */
+
+/*
+ * 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.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_LPC32XX_EMC_H
+#define LIBBSP_ARM_LPC32XX_EMC_H
+
+#include <rtems.h>
+
+#include <bsp/lpc32xx.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup lpc32xx_emc EMC Support
+ *
+ * @ingroup lpc32xx
+ *
+ * @brief EMC Support
+ *
+ * @{
+ */
+
+
+/**
+ * @name SDRAM Clock Control Register (SDRAMCLK_CTRL)
+ *
+ * @{
+ */
+
+#define SDRAMCLK_CLOCKS_DIS BIT32(0)
+#define SDRAMCLK_DDR_MODE BIT32(1)
+#define SDRAMCLK_DDR_DQSIN_DELAY(val) FIELD32(val, 2, 6)
+#define SDRAMCLK_RTC_TICK_EN BIT32(7)
+#define SDRAMCLK_SW_DDR_CAL BIT32(8)
+#define SDRAMCLK_CAL_DELAY BIT32(9)
+#define SDRAMCLK_SENSITIVITY_FACTOR(val) FIELD32(val, 10, 12)
+#define SDRAMCLK_DCA_STATUS BIT32(13)
+#define SDRAMCLK_COMMAND_DELAY(val) FIELD32(val, 14, 18)
+#define SDRAMCLK_SW_DDR_RESET BIT32(19)
+#define SDRAMCLK_PIN_1_FAST BIT32(20)
+#define SDRAMCLK_PIN_2_FAST BIT32(21)
+#define SDRAMCLK_PIN_3_FAST BIT32(22)
+
+/** @} */
+
+/**
+ * @name EMC Control Register (EMCControl)
+ *
+ * @{
+ */
+
+#define EMC_CTRL_EN BIT32(0)
+#define EMC_CTRL_LOW_POWER BIT32(2)
+
+/** @} */
+
+/**
+ * @name EMC Dynamic Memory Control Register (EMCDynamicControl)
+ *
+ * @{
+ */
+
+#define EMC_DYN_CTRL_CE BIT32(0)
+#define EMC_DYN_CTRL_CS BIT32(1)
+#define EMC_DYN_CTRL_SR BIT32(2)
+#define EMC_DYN_CTRL_SRMCC BIT32(3)
+#define EMC_DYN_CTRL_IMCC BIT32(4)
+#define EMC_DYN_CTRL_MCC BIT32(5)
+#define EMC_DYN_CTRL_I_MASK MASK32(7, 8)
+#define EMC_DYN_CTRL_I_NORMAL FIELD32(0x0, 7, 8)
+#define EMC_DYN_CTRL_I_MODE FIELD32(0x1, 7, 8)
+#define EMC_DYN_CTRL_I_PALL FIELD32(0x2, 7, 8)
+#define EMC_DYN_CTRL_I_NOP FIELD32(0x3, 7, 8)
+#define EMC_DYN_CTRL_DP BIT32(9)
+
+/** @} */
+
+/**
+ * @name EMC Dynamic Memory Read Configuration Register (EMCDynamicReadConfig)
+ *
+ * @{
+ */
+
+#define EMC_DYN_READ_CONFIG_SDR_STRAT(val) FIELD32(val, 0, 1)
+#define EMC_DYN_READ_CONFIG_SDR_POL_POS BIT32(4)
+#define EMC_DYN_READ_CONFIG_DDR_STRAT(val) FIELD32(val, 8, 9)
+#define EMC_DYN_READ_CONFIG_DDR_POL_POS BIT32(12)
+
+/** @} */
+
+/**
+ * @name EMC Dynamic Memory Configuration N Register (EMCDynamicConfigN)
+ *
+ * @{
+ */
+
+#define EMC_DYN_CFG_MD(val) FIELD32(val, 0, 2)
+#define EMC_DYN_CFG_AM(val) FIELD32(val, 7, 14)
+#define EMC_DYN_CFG_P(val) BIT32(20)
+
+/** @} */
+
+/**
+ * @name EMC Dynamic Memory RAS and CAS Delay N Register (EMCDynamicRasCasN)
+ *
+ * @{
+ */
+
+#define EMC_DYN_RAS(val) FIELD32(val, 0, 3)
+#define EMC_DYN_CAS(val) FIELD32(val, 7, 10)
+
+/** @} */
+
+/**
+ * @name EMC AHB Control Register (EMCAHBControl)
+ *
+ * @{
+ */
+
+#define EMC_AHB_PORT_BUFF_EN BIT32(0)
+
+/** @} */
+
+/**
+ * @name EMC AHB Timeout Register (EMCAHBTimeOut)
+ *
+ * @{
+ */
+
+#define EMC_AHB_TIMEOUT(val) FIELD32(val, 0, 9)
+
+/** @} */
+
+/**
+ * @name SDRAM Mode and Extended Mode Registers
+ *
+ * @{
+ */
+
+#define SDRAM_ADDR_ROW_16MB(val) ((uint32_t) (val) << 10)
+#define SDRAM_ADDR_ROW_32MB(val) ((uint32_t) (val) << 11)
+#define SDRAM_ADDR_ROW_64MB(val) ((uint32_t) (val) << 11)
+
+#define SDRAM_ADDR_BANK_16MB(ba1, ba0) \
+ (((uint32_t) (ba1) << 23) | ((uint32_t) (ba0) << 22))
+#define SDRAM_ADDR_BANK_32MB(ba1, ba0) \
+ (((uint32_t) (ba1) << 23) | ((uint32_t) (ba0) << 24))
+#define SDRAM_ADDR_BANK_64MB(ba1, ba0) \
+ (((uint32_t) (ba1) << 25) | ((uint32_t) (ba0) << 24))
+
+#define SDRAM_MODE_16MB(mode) \
+ (SDRAM_ADDR_BANK_16MB(0, 0) | SDRAM_ADDR_ROW_16MB(mode))
+#define SDRAM_MODE_32MB(mode) \
+ (SDRAM_ADDR_BANK_32MB(0, 0) | SDRAM_ADDR_ROW_32MB(mode))
+#define SDRAM_MODE_64MB(mode) \
+ (SDRAM_ADDR_BANK_64MB(0, 0) | SDRAM_ADDR_ROW_64MB(mode))
+
+#define SDRAM_EXTMODE_16MB(mode) \
+ (SDRAM_ADDR_BANK_16MB(1, 0) | SDRAM_ADDR_ROW_16MB(mode))
+#define SDRAM_EXTMODE_32MB(mode) \
+ (SDRAM_ADDR_BANK_32MB(1, 0) | SDRAM_ADDR_ROW_32MB(mode))
+#define SDRAM_EXTMODE_64MB(mode) \
+ (SDRAM_ADDR_BANK_64MB(1, 0) | SDRAM_ADDR_ROW_64MB(mode))
+
+#define SDRAM_MODE_BURST_LENGTH(val) FIELD32(val, 0, 2)
+#define SDRAM_MODE_BURST_INTERLEAVE BIT32(3)
+#define SDRAM_MODE_CAS(val) FIELD32(val, 4, 6)
+#define SDRAM_MODE_TEST_MODE(val) FIELD32(val, 7, 8)
+#define SDRAM_MODE_WRITE_BURST_SINGLE_BIT BIT32(9)
+
+#define SDRAM_EXTMODE_PASR(val) FIELD32(val, 0, 2)
+#define SDRAM_EXTMODE_DRIVER_STRENGTH(val) FIELD32(val, 5, 6)
+
+/** @} */
+
+typedef struct {
+ uint32_t size;
+ uint32_t config;
+ uint32_t rascas;
+ uint32_t mode;
+ uint32_t extmode;
+} lpc32xx_emc_dynamic_chip_config;
+
+typedef struct {
+ uint32_t sdramclk_ctrl;
+ uint32_t nop_time_in_us;
+ uint32_t control;
+ uint32_t refresh;
+ uint32_t readconfig;
+ uint32_t trp;
+ uint32_t tras;
+ uint32_t tsrex;
+ uint32_t twr;
+ uint32_t trc;
+ uint32_t trfc;
+ uint32_t txsr;
+ uint32_t trrd;
+ uint32_t tmrd;
+ uint32_t tcdlr;
+ lpc32xx_emc_dynamic_chip_config chip [EMC_DYN_CHIP_COUNT];
+} lpc32xx_emc_dynamic_config;
+
+void lpc32xx_emc_init(const lpc32xx_emc_dynamic_config *dyn_cfg);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_LPC32XX_EMC_H */
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/i2c.h b/c/src/lib/libbsp/arm/lpc32xx/include/i2c.h
new file mode 100644
index 0000000000..b25ea28c0a
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/i2c.h
@@ -0,0 +1,269 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_i2c
+ *
+ * @brief I2C support API.
+ */
+
+/*
+ * 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.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_LPC32XX_I2C_H
+#define LIBBSP_ARM_LPC32XX_I2C_H
+
+#include <rtems.h>
+
+#include <bsp/lpc32xx.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup lpc32xx_i2c I2C Support
+ *
+ * @ingroup lpc32xx
+ *
+ * @brief I2C Support
+ *
+ * All writes and reads will be performed in master mode. Exclusive bus access
+ * will be assumed.
+ *
+ * @{
+ */
+
+/**
+ * @name I2C Clock Control Register (I2CCLK_CTRL)
+ *
+ * @{
+ */
+
+#define I2CCLK_1_EN BIT32(0)
+#define I2CCLK_2_EN BIT32(1)
+#define I2CCLK_1_HIGH_DRIVE BIT32(2)
+#define I2CCLK_2_HIGH_DRIVE BIT32(3)
+#define I2CCLK_USB_HIGH_DRIVE BIT32(4)
+
+/** @} */
+
+/**
+ * @name I2C TX Data FIFO Register (I2Cn_TX)
+ *
+ * @{
+ */
+
+#define I2C_TX_READ BIT32(0)
+#define I2C_TX_ADDR(val) FIELD32(val, 1, 7)
+#define I2C_TX_START BIT32(8)
+#define I2C_TX_STOP BIT32(9)
+
+/** @} */
+
+/**
+ * @name I2C Status Register (I2Cn_STAT)
+ *
+ * @{
+ */
+
+#define I2C_STAT_TDI BIT32(0)
+#define I2C_STAT_AFI BIT32(1)
+#define I2C_STAT_NAI BIT32(2)
+#define I2C_STAT_DRMI BIT32(3)
+#define I2C_STAT_DRSI BIT32(4)
+#define I2C_STAT_ACTIVE BIT32(5)
+#define I2C_STAT_SCL BIT32(6)
+#define I2C_STAT_SDA BIT32(7)
+#define I2C_STAT_RFF BIT32(8)
+#define I2C_STAT_RFE BIT32(9)
+#define I2C_STAT_TFF BIT32(10)
+#define I2C_STAT_TFE BIT32(11)
+#define I2C_STAT_TFFS BIT32(12)
+#define I2C_STAT_TFES BIT32(13)
+
+/** @} */
+
+/**
+ * @name I2C Control Register (I2Cn_CTRL)
+ *
+ * @{
+ */
+
+#define I2C_CTRL_TDIE BIT32(0)
+#define I2C_CTRL_AFIE BIT32(1)
+#define I2C_CTRL_NAIE BIT32(2)
+#define I2C_CTRL_DRMIE BIT32(3)
+#define I2C_CTRL_DRSIE BIT32(4)
+#define I2C_CTRL_RFFIE BIT32(5)
+#define I2C_CTRL_RFDAIE BIT32(6)
+#define I2C_CTRL_TFFIO BIT32(7)
+#define I2C_CTRL_RESET BIT32(8)
+#define I2C_CTRL_SEVEN BIT32(9)
+#define I2C_CTRL_TFFSIE BIT32(10)
+
+/** @} */
+
+/**
+ * @brief Initializes the I2C module @a i2c.
+ *
+ * Valid @a clock_in_hz values are 100000 and 400000.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_INVALID_ID Invalid @a i2c value.
+ * @retval RTEMS_INVALID_CLOCK Invalid @a clock_in_hz value.
+ */
+rtems_status_code lpc32xx_i2c_init(
+ volatile lpc32xx_i2c *i2c,
+ unsigned clock_in_hz
+);
+
+/**
+ * @brief Resets the I2C module @a i2c.
+ */
+void lpc32xx_i2c_reset(volatile lpc32xx_i2c *i2c);
+
+/**
+ * @brief Sets the I2C module @a i2c clock.
+ *
+ * Valid @a clock_in_hz values are 100000 and 400000.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_INVALID_CLOCK Invalid @a clock_in_hz value.
+ */
+rtems_status_code lpc32xx_i2c_clock(
+ volatile lpc32xx_i2c *i2c,
+ unsigned clock_in_hz
+);
+
+/**
+ * @brief Starts a write transaction on the I2C module @a i2c.
+ *
+ * The address parameter @a addr must not contain the read/write bit.
+ *
+ * The error status may be delayed to the next
+ * lpc32xx_i2c_write_with_optional_stop() due to controller flaws.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_IO_ERROR Received a NACK from the slave.
+ */
+rtems_status_code lpc32xx_i2c_write_start(
+ volatile lpc32xx_i2c *i2c,
+ unsigned addr
+);
+
+/**
+ * @brief Writes data via the I2C module @a i2c with optional stop.
+ *
+ * The error status may be delayed to the next
+ * lpc32xx_i2c_write_with_optional_stop() due to controller flaws.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_IO_ERROR Received a NACK from the slave.
+ */
+rtems_status_code lpc32xx_i2c_write_with_optional_stop(
+ volatile lpc32xx_i2c *i2c,
+ const uint8_t *out,
+ size_t n,
+ bool stop
+);
+
+/**
+ * @brief Starts a read transaction on the I2C module @a i2c.
+ *
+ * The address parameter @a addr must not contain the read/write bit.
+ *
+ * The error status may be delayed to the next
+ * lpc32xx_i2c_read_with_optional_stop() due to controller flaws.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_IO_ERROR Received a NACK from the slave.
+ */
+rtems_status_code lpc32xx_i2c_read_start(
+ volatile lpc32xx_i2c *i2c,
+ unsigned addr
+);
+
+/**
+ * @brief Reads data via the I2C module @a i2c with optional stop.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_IO_ERROR Received a NACK from the slave.
+ * @retval RTEMS_NOT_IMPLEMENTED Stop is @a false.
+ */
+rtems_status_code lpc32xx_i2c_read_with_optional_stop(
+ volatile lpc32xx_i2c *i2c,
+ uint8_t *in,
+ size_t n,
+ bool stop
+);
+
+/**
+ * @brief Writes and reads data via the I2C module @a i2c.
+ *
+ * This will be one bus transaction.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_IO_ERROR Received a NACK from the slave.
+ */
+rtems_status_code lpc32xx_i2c_write_and_read(
+ volatile lpc32xx_i2c *i2c,
+ unsigned addr,
+ const uint8_t *out,
+ size_t out_size,
+ uint8_t *in,
+ size_t in_size
+);
+
+/**
+ * @brief Writes data via the I2C module @a i2c.
+ *
+ * This will be one bus transaction.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_IO_ERROR Received a NACK from the slave.
+ */
+static inline rtems_status_code lpc32xx_i2c_write(
+ volatile lpc32xx_i2c *i2c,
+ unsigned addr,
+ const uint8_t *out,
+ size_t out_size
+)
+{
+ return lpc32xx_i2c_write_and_read(i2c, addr, out, out_size, NULL, 0);
+}
+
+/**
+ * @brief Reads data via the I2C module @a i2c.
+ *
+ * This will be one bus transaction.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_IO_ERROR Received a NACK from the slave.
+ */
+static inline rtems_status_code lpc32xx_i2c_read(
+ volatile lpc32xx_i2c *i2c,
+ unsigned addr,
+ uint8_t *in,
+ size_t in_size
+)
+{
+ return lpc32xx_i2c_write_and_read(i2c, addr, NULL, 0, in, in_size);
+}
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_LPC32XX_I2C_H */
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/lpc32xx.h b/c/src/lib/libbsp/arm/lpc32xx/include/lpc32xx.h
index 540438874b..0f00981ca3 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/include/lpc32xx.h
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/lpc32xx.h
@@ -7,7 +7,7 @@
*/
/*
- * Copyright (c) 2009
+ * Copyright (c) 2009, 2010
* embedded brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
@@ -25,6 +25,7 @@
#include <stdint.h>
#include <bsp/utility.h>
+#include <bsp/lpc-timer.h>
/**
* @defgroup lpc32xx_reg Register Definitions
@@ -164,41 +165,9 @@
#define LPC32XX_KEYCLK_CTRL (*(volatile uint32_t *) 0x400040b0)
#define LPC32XX_PWMCLK_CTRL (*(volatile uint32_t *) 0x400040b8)
#define LPC32XX_UARTCLK_CTRL (*(volatile uint32_t *) 0x400040e4)
-#define LPC32XX_POS0_IRAM_CTRl (*(volatile uint32_t *) 0x40004110)
-#define LPC32XX_POS1_IRAM_CTRl (*(volatile uint32_t *) 0x40004114)
-
-/** @} */
-
-/**
- * @name GPIO Registers
- *
- * @{
- */
-
-#define LPC32XX_P0_INP_STATE (*(volatile uint32_t *) 0x40028040)
-#define LPC32XX_P0_OUTP_SET (*(volatile uint32_t *) 0x40028044)
-#define LPC32XX_P0_OUTP_CLR (*(volatile uint32_t *) 0x40028048)
-#define LPC32XX_P0_DIR_SET (*(volatile uint32_t *) 0x40028050)
-#define LPC32XX_P0_DIR_CLR (*(volatile uint32_t *) 0x40028054)
-#define LPC32XX_P0_DIR_STATE (*(volatile uint32_t *) 0x40028058)
-#define LPC32XX_P0_OUTP_STATE (*(volatile uint32_t *) 0x4002804c)
-#define LPC32XX_P1_INP_STATE (*(volatile uint32_t *) 0x40028060)
-#define LPC32XX_P1_OUTP_SET (*(volatile uint32_t *) 0x40028064)
-#define LPC32XX_P1_OUTP_CLR (*(volatile uint32_t *) 0x40028068)
-#define LPC32XX_P1_DIR_SET (*(volatile uint32_t *) 0x40028070)
-#define LPC32XX_P1_DIR_CLR (*(volatile uint32_t *) 0x40028074)
-#define LPC32XX_P1_DIR_STATE (*(volatile uint32_t *) 0x40028078)
-#define LPC32XX_P1_OUTP_STATE (*(volatile uint32_t *) 0x4002806c)
-#define LPC32XX_P2_INP_STATE (*(volatile uint32_t *) 0x4002801c)
-#define LPC32XX_P2_OUTP_SET (*(volatile uint32_t *) 0x40028020)
-#define LPC32XX_P2_OUTP_CLR (*(volatile uint32_t *) 0x40028024)
-#define LPC32XX_P2_DIR_SET (*(volatile uint32_t *) 0x40028010)
-#define LPC32XX_P2_DIR_CLR (*(volatile uint32_t *) 0x40028014)
-#define LPC32XX_P2_DIR_STATE (*(volatile uint32_t *) 0x40028018)
-#define LPC32XX_P3_INP_STATE (*(volatile uint32_t *) 0x40028000)
-#define LPC32XX_P3_OUTP_SET (*(volatile uint32_t *) 0x40028004)
-#define LPC32XX_P3_OUTP_CLR (*(volatile uint32_t *) 0x40028008)
-#define LPC32XX_P3_OUTP_STATE (*(volatile uint32_t *) 0x4002800c)
+#define LPC32XX_POS0_IRAM_CTRL (*(volatile uint32_t *) 0x40004110)
+#define LPC32XX_POS1_IRAM_CTRL (*(volatile uint32_t *) 0x40004114)
+#define LPC32XX_SDRAMCLK_CTRL (*(volatile uint32_t *) 0x40004068)
/** @} */
@@ -250,6 +219,321 @@
/** @} */
+#define LPC32XX_RESERVED(a, b, s) (((b) - (a) - sizeof(s)) / 4)
+
+typedef struct {
+} lpc32xx_nand_slc;
+
+typedef struct {
+} lpc32xx_ssp;
+
+typedef struct {
+} lpc32xx_spi;
+
+typedef struct {
+} lpc32xx_i2s;
+
+typedef struct {
+} lpc32xx_sd_card;
+
+typedef struct {
+} lpc32xx_dma;
+
+typedef struct {
+} lpc32xx_usb;
+
+typedef struct {
+} lpc32xx_lcd;
+
+typedef struct {
+} lpc32xx_etb;
+
+typedef struct {
+} lpc32xx_syscon;
+
+typedef struct {
+} lpc32xx_uart_ctrl;
+
+typedef struct {
+} lpc32xx_uart;
+
+typedef struct {
+} lpc32xx_ms_timer;
+
+typedef struct {
+} lpc32xx_hs_timer;
+
+typedef struct {
+} lpc32xx_wdg_timer;
+
+typedef struct {
+} lpc32xx_debug;
+
+typedef struct {
+} lpc32xx_adc;
+
+typedef struct {
+} lpc32xx_keyscan;
+
+typedef struct {
+} lpc32xx_pwm;
+
+typedef struct {
+} lpc32xx_mcpwm;
+
+typedef struct {
+} lpc32xx_eth;
+
+typedef struct {
+ uint32_t er;
+ uint32_t rsr;
+ uint32_t sr;
+ uint32_t apr;
+ uint32_t atr;
+ uint32_t itr;
+} lpc32xx_irq;
+
+typedef struct {
+ uint32_t p3_inp_state;
+ uint32_t p3_outp_set;
+ uint32_t p3_outp_clr;
+ uint32_t p3_outp_state;
+ uint32_t p2_dir_set;
+ uint32_t p2_dir_clr;
+ uint32_t p2_dir_state;
+ uint32_t p2_inp_state;
+ uint32_t p2_outp_set;
+ uint32_t p2_outp_clr;
+ uint32_t reserved_0 [6];
+ uint32_t p0_inp_state;
+ uint32_t p0_outp_set;
+ uint32_t p0_outp_clr;
+ uint32_t p0_outp_state;
+ uint32_t p0_dir_set;
+ uint32_t p0_dir_clr;
+ uint32_t p0_dir_state;
+ uint32_t reserved_1 [1];
+ uint32_t p1_inp_state;
+ uint32_t p1_outp_set;
+ uint32_t p1_outp_clr;
+ uint32_t p1_outp_state;
+ uint32_t p1_dir_set;
+ uint32_t p1_dir_clr;
+ uint32_t p1_dir_state;
+} lpc32xx_gpio;
+
+typedef struct {
+ uint32_t rx_or_tx;
+ uint32_t stat;
+ uint32_t ctrl;
+ uint32_t clk_hi;
+ uint32_t clk_lo;
+ uint32_t adr;
+ uint32_t rxfl;
+ uint32_t txfl;
+ uint32_t rxb;
+ uint32_t txb;
+ uint32_t s_tx;
+ uint32_t s_txfl;
+} lpc32xx_i2c;
+
+typedef struct {
+ uint32_t ucount;
+ uint32_t dcount;
+ uint32_t match0;
+ uint32_t match1;
+ uint32_t ctrl;
+ uint32_t intstat;
+ uint32_t key;
+ uint32_t sram [32];
+} lpc32xx_rtc;
+
+#define EMC_DYN_CHIP_COUNT 2
+
+#define EMC_STATIC_CHIP_COUNT 4
+
+typedef struct {
+ uint32_t config;
+ uint32_t rascas;
+ uint32_t reserved_0 [6];
+} lpc32xx_emc_dynamic;
+
+typedef struct {
+ uint32_t config;
+ uint32_t waitwen;
+ uint32_t waitoen;
+ uint32_t waitrd;
+ uint32_t waitpage;
+ uint32_t waitwr;
+ uint32_t waitturn;
+ uint32_t reserved_0 [1];
+} lpc32xx_emc_static;
+
+typedef struct {
+ uint32_t control;
+ uint32_t status;
+ uint32_t timeout;
+ uint32_t reserved_0 [5];
+} lpc32xx_emc_ahb;
+
+typedef struct {
+ uint32_t control;
+ uint32_t status;
+ uint32_t config;
+ uint32_t reserved_0 [5];
+ uint32_t dynamiccontrol;
+ uint32_t dynamicrefresh;
+ uint32_t dynamicreadconfig;
+ uint32_t reserved_1;
+ uint32_t dynamictrp;
+ uint32_t dynamictras;
+ uint32_t dynamictsrex;
+ uint32_t reserved_2 [2];
+ uint32_t dynamictwr;
+ uint32_t dynamictrc;
+ uint32_t dynamictrfc;
+ uint32_t dynamictxsr;
+ uint32_t dynamictrrd;
+ uint32_t dynamictmrd;
+ uint32_t dynamictcdlr;
+ uint32_t reserved_3 [8];
+ uint32_t staticextendedwait;
+ uint32_t reserved_4 [31];
+ lpc32xx_emc_dynamic dynamic [EMC_DYN_CHIP_COUNT];
+ uint32_t reserved_5 [48];
+ lpc32xx_emc_static emcstatic [EMC_STATIC_CHIP_COUNT];
+ uint32_t reserved_6 [96];
+ lpc32xx_emc_ahb ahb [5];
+} lpc32xx_emc;
+
+typedef struct {
+ union {
+ uint32_t w32;
+ uint16_t w16;
+ uint8_t w8;
+ } buff;
+ uint32_t reserved_0 [8191];
+ union {
+ uint32_t w32;
+ uint16_t w16;
+ uint8_t w8;
+ } data;
+ uint32_t reserved_1 [8191];
+ uint32_t cmd;
+ uint32_t addr;
+ uint32_t ecc_enc;
+ uint32_t ecc_dec;
+ uint32_t ecc_auto_enc;
+ uint32_t ecc_auto_dec;
+ uint32_t rpr;
+ uint32_t wpr;
+ uint32_t rubp;
+ uint32_t robp;
+ uint32_t sw_wp_add_low;
+ uint32_t sw_wp_add_hig;
+ uint32_t icr;
+ uint32_t time;
+ uint32_t irq_mr;
+ uint32_t irq_sr;
+ uint32_t lock_pr;
+ uint32_t isr;
+ uint32_t ceh;
+} lpc32xx_nand_mlc;
+
+typedef struct {
+ lpc32xx_nand_slc nand_slc;
+ uint32_t reserved_0 [LPC32XX_RESERVED(0x20020000, 0x20084000, lpc32xx_nand_slc)];
+ lpc32xx_ssp ssp_0;
+ uint32_t reserved_1 [LPC32XX_RESERVED(0x20084000, 0x20088000, lpc32xx_ssp)];
+ lpc32xx_spi spi_1;
+ uint32_t reserved_2 [LPC32XX_RESERVED(0x20088000, 0x2008c000, lpc32xx_spi)];
+ lpc32xx_ssp ssp_1;
+ uint32_t reserved_3 [LPC32XX_RESERVED(0x2008c000, 0x20090000, lpc32xx_ssp)];
+ lpc32xx_spi spi_2;
+ uint32_t reserved_4 [LPC32XX_RESERVED(0x20090000, 0x20094000, lpc32xx_spi)];
+ lpc32xx_i2s i2s_0;
+ uint32_t reserved_5 [LPC32XX_RESERVED(0x20094000, 0x20098000, lpc32xx_i2s)];
+ lpc32xx_sd_card sd_card;
+ uint32_t reserved_6 [LPC32XX_RESERVED(0x20098000, 0x2009c000, lpc32xx_sd_card)];
+ lpc32xx_i2s i2s_1;
+ uint32_t reserved_7 [LPC32XX_RESERVED(0x2009c000, 0x200a8000, lpc32xx_i2s)];
+ lpc32xx_nand_mlc nand_mlc;
+ uint32_t reserved_8 [LPC32XX_RESERVED(0x200a8000, 0x31000000, lpc32xx_nand_mlc)];
+ lpc32xx_dma dma;
+ uint32_t reserved_9 [LPC32XX_RESERVED(0x31000000, 0x31020000, lpc32xx_dma)];
+ lpc32xx_usb usb;
+ uint32_t reserved_10 [LPC32XX_RESERVED(0x31020000, 0x31040000, lpc32xx_usb)];
+ lpc32xx_lcd lcd;
+ uint32_t reserved_11 [LPC32XX_RESERVED(0x31040000, 0x31060000, lpc32xx_lcd)];
+ lpc32xx_eth eth;
+ uint32_t reserved_12 [LPC32XX_RESERVED(0x31060000, 0x31080000, lpc32xx_eth)];
+ lpc32xx_emc emc;
+ uint32_t reserved_13 [LPC32XX_RESERVED(0x31080000, 0x310c0000, lpc32xx_emc)];
+ lpc32xx_etb etb;
+ uint32_t reserved_14 [LPC32XX_RESERVED(0x310c0000, 0x40004000, lpc32xx_etb)];
+ lpc32xx_syscon syscon;
+ uint32_t reserved_15 [LPC32XX_RESERVED(0x40004000, 0x40008000, lpc32xx_syscon)];
+ lpc32xx_irq mic;
+ uint32_t reserved_16 [LPC32XX_RESERVED(0x40008000, 0x4000c000, lpc32xx_irq)];
+ lpc32xx_irq sic_1;
+ uint32_t reserved_17 [LPC32XX_RESERVED(0x4000c000, 0x40010000, lpc32xx_irq)];
+ lpc32xx_irq sic_2;
+ uint32_t reserved_18 [LPC32XX_RESERVED(0x40010000, 0x40014000, lpc32xx_irq)];
+ lpc32xx_uart uart_1;
+ uint32_t reserved_19 [LPC32XX_RESERVED(0x40014000, 0x40018000, lpc32xx_uart)];
+ lpc32xx_uart uart_2;
+ uint32_t reserved_20 [LPC32XX_RESERVED(0x40018000, 0x4001c000, lpc32xx_uart)];
+ lpc32xx_uart uart_7;
+ uint32_t reserved_21 [LPC32XX_RESERVED(0x4001c000, 0x40024000, lpc32xx_uart)];
+ lpc32xx_rtc rtc;
+ uint32_t reserved_22 [LPC32XX_RESERVED(0x40024000, 0x40028000, lpc32xx_rtc)];
+ lpc32xx_gpio gpio;
+ uint32_t reserved_23 [LPC32XX_RESERVED(0x40028000, 0x4002c000, lpc32xx_gpio)];
+ lpc_timer timer_4;
+ uint32_t reserved_24 [LPC32XX_RESERVED(0x4002c000, 0x40030000, lpc_timer)];
+ lpc_timer timer_5;
+ uint32_t reserved_25 [LPC32XX_RESERVED(0x40030000, 0x40034000, lpc_timer)];
+ lpc32xx_ms_timer ms_timer;
+ uint32_t reserved_26 [LPC32XX_RESERVED(0x40034000, 0x40038000, lpc32xx_ms_timer)];
+ lpc32xx_hs_timer hs_timer;
+ uint32_t reserved_27 [LPC32XX_RESERVED(0x40038000, 0x4003c000, lpc32xx_hs_timer)];
+ lpc32xx_wdg_timer wdg_timer;
+ uint32_t reserved_28 [LPC32XX_RESERVED(0x4003c000, 0x40040000, lpc32xx_wdg_timer)];
+ lpc32xx_debug debug;
+ uint32_t reserved_29 [LPC32XX_RESERVED(0x40040000, 0x40044000, lpc32xx_debug)];
+ lpc_timer timer_0;
+ uint32_t reserved_30 [LPC32XX_RESERVED(0x40044000, 0x40048000, lpc_timer)];
+ lpc32xx_adc adc;
+ uint32_t reserved_31 [LPC32XX_RESERVED(0x40048000, 0x4004c000, lpc32xx_adc)];
+ lpc_timer timer_1;
+ uint32_t reserved_32 [LPC32XX_RESERVED(0x4004c000, 0x40050000, lpc_timer)];
+ lpc32xx_keyscan keyscan;
+ uint32_t reserved_33 [LPC32XX_RESERVED(0x40050000, 0x40054000, lpc32xx_keyscan)];
+ lpc32xx_uart_ctrl uart_ctrl;
+ uint32_t reserved_34 [LPC32XX_RESERVED(0x40054000, 0x40058000, lpc32xx_uart_ctrl)];
+ lpc_timer timer_2;
+ uint32_t reserved_35 [LPC32XX_RESERVED(0x40058000, 0x4005c000, lpc_timer)];
+ lpc32xx_pwm pwm_1_and_pwm_2;
+ uint32_t reserved_36 [LPC32XX_RESERVED(0x4005c000, 0x40060000, lpc32xx_pwm)];
+ lpc_timer timer3;
+ uint32_t reserved_37 [LPC32XX_RESERVED(0x40060000, 0x40080000, lpc_timer)];
+ lpc32xx_uart uart_3;
+ uint32_t reserved_38 [LPC32XX_RESERVED(0x40080000, 0x40088000, lpc32xx_uart)];
+ lpc32xx_uart uart_4;
+ uint32_t reserved_39 [LPC32XX_RESERVED(0x40088000, 0x40090000, lpc32xx_uart)];
+ lpc32xx_uart uart_5;
+ uint32_t reserved_40 [LPC32XX_RESERVED(0x40090000, 0x40098000, lpc32xx_uart)];
+ lpc32xx_uart uart_6;
+ uint32_t reserved_41 [LPC32XX_RESERVED(0x40098000, 0x400a0000, lpc32xx_uart)];
+ lpc32xx_i2c i2c_1;
+ uint32_t reserved_42 [LPC32XX_RESERVED(0x400a0000, 0x400a8000, lpc32xx_i2c)];
+ lpc32xx_i2c i2c_2;
+ uint32_t reserved_43 [LPC32XX_RESERVED(0x400a8000, 0x400e8000, lpc32xx_i2c)];
+ lpc32xx_mcpwm mcpwm;
+} lpc32xx_registers;
+
+extern volatile lpc32xx_registers lpc32xx;
+
/** @} */
#endif /* LIBBSP_ARM_LPC32XX_LPC32XX_H */
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/nand-mlc.h b/c/src/lib/libbsp/arm/lpc32xx/include/nand-mlc.h
new file mode 100644
index 0000000000..c5849103d0
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/nand-mlc.h
@@ -0,0 +1,335 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_nand_mlc
+ *
+ * @brief NAND MLC controller API.
+ */
+
+/*
+ * 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.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_LPC32XX_NAND_MLC_H
+#define LIBBSP_ARM_LPC32XX_NAND_MLC_H
+
+#include <rtems.h>
+
+#include <bsp/utility.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup lpc32xx_nand_mlc NAND MLC Controller
+ *
+ * @ingroup lpc32xx
+ *
+ * @brief NAND MLC Controller.
+ *
+ * Timing constraints:
+ *
+ * -# (WR_LOW + 1) / HCLK >= tWP
+ * -# (WR_HIGH - WR_LOW) / HCLK >= tWH
+ * -# (WR_LOW + 1) / HCLK + (WR_HIGH - WR_LOW) / HCLK >= tWC
+ * -# (RD_LOW + 1) / HCLK >= tRP
+ * -# (RD_LOW + 1) / HCLK >= tREA + tSU
+ * -# (RD_HIGH - RD_LOW) / HCLK >= tREH
+ * -# (RD_LOW + 1) / HCLK + (RD_HIGH - RD_LOW) / HCLK >= tRC
+ * -# (RD_HIGH - RD_LOW) / HCLK + NAND_TA / HCLK >= tRHZ
+ * -# BUSY_DELAY / HCLK >= max(tWB, tRB)
+ * -# TCEA_DELAY / HCLK >= tCEA - tREA
+ *
+ * Known flash layouts (Format: SP = small pages, LP = large pages / address
+ * cycles / pages per block):
+ *
+ * -# SP/3/32
+ * -# SP/4/32
+ * -# LP/4/64
+ * -# LP/5/64
+ * -# LP/5/128
+ *
+ * @{
+ */
+
+/**
+ * @name MLC NAND Flash Dimensions
+ *
+ * @{
+ */
+
+#define MLC_SMALL_PAGE_SIZE 528
+#define MLC_SMALL_DATA_SIZE 512
+#define MLC_SMALL_SPARE_SIZE 16
+#define MLC_SMALL_DATA_WORD_COUNT (MLC_SMALL_DATA_SIZE / 4)
+#define MLC_SMALL_SPARE_WORD_COUNT (MLC_SMALL_SPARE_SIZE / 4)
+#define MLC_SMALL_PAGES_PER_LARGE_PAGE 4
+#define MLC_LARGE_PAGE_SIZE \
+ (MLC_SMALL_PAGES_PER_LARGE_PAGE * MLC_SMALL_PAGE_SIZE)
+#define MLC_LARGE_DATA_SIZE \
+ (MLC_SMALL_PAGES_PER_LARGE_PAGE * MLC_SMALL_DATA_SIZE)
+#define MLC_LARGE_SPARE_SIZE \
+ (MLC_SMALL_PAGES_PER_LARGE_PAGE * MLC_SMALL_SPARE_SIZE)
+#define MLC_LARGE_DATA_WORD_COUNT (MLC_LARGE_DATA_SIZE / 4)
+#define MLC_LARGE_SPARE_WORD_COUNT (MLC_LARGE_SPARE_SIZE / 4)
+
+/** @} */
+
+/**
+ * @name NAND Flash Clock Control Register (FLASHCLK_CTRL)
+ *
+ * @{
+ */
+
+#define FLASHCLK_IRQ_MLC BIT32(5)
+#define FLASHCLK_MLC_DMA_RNB BIT32(4)
+#define FLASHCLK_MLC_DMA_INT BIT32(3)
+#define FLASHCLK_SELECT_SLC BIT32(2)
+#define FLASHCLK_MLC_CLK_ENABLE BIT32(1)
+#define FLASHCLK_SLC_CLK_ENABLE BIT32(0)
+
+/** @} */
+
+/**
+ * @name MLC NAND Timing Register (MLC_TIME_REG)
+ *
+ * @{
+ */
+
+#define MLC_TIME_WR_LOW(val) FIELD32(val, 0, 3)
+#define MLC_TIME_WR_HIGH(val) FIELD32(val, 4, 7)
+#define MLC_TIME_RD_LOW(val) FIELD32(val, 8, 11)
+#define MLC_TIME_RD_HIGH(val) FIELD32(val, 12, 15)
+#define MLC_TIME_NAND_TA(val) FIELD32(val, 16, 18)
+#define MLC_TIME_BUSY_DELAY(val) FIELD32(val, 19, 23)
+#define MLC_TIME_TCEA_DELAY(val) FIELD32(val, 24, 25)
+
+/** @} */
+
+/**
+ * @name MLC NAND Lock Protection Register (MLC_LOCK_PR)
+ *
+ * @{
+ */
+
+#define MLC_UNLOCK_PROT 0xa25e
+
+/** @} */
+
+/**
+ * @name MLC NAND Status Register (MLC_ISR)
+ *
+ * @{
+ */
+
+#define MLC_ISR_DECODER_FAILURE BIT32(6)
+#define MLC_ISR_ERRORS_DETECTED BIT32(3)
+#define MLC_ISR_ECC_READY BIT32(2)
+#define MLC_ISR_CONTROLLER_READY BIT32(1)
+#define MLC_ISR_NAND_READY BIT32(0)
+
+/** @} */
+
+/**
+ * @name MLC NAND Controller Configuration Register (MLC_ICR)
+ *
+ * @{
+ */
+
+#define MLC_ICR_SOFT_WRITE_PROT BIT32(3)
+#define MLC_ICR_LARGE_PAGES BIT32(2)
+#define MLC_ICR_ADDR_WORD_COUNT_4_5 BIT32(1)
+#define MLC_ICR_IO_BUS_16 BIT32(0)
+
+/** @} */
+
+/**
+ * @name MLC NAND Auto Encode Register (MLC_ECC_AUTO_ENC)
+ *
+ * @{
+ */
+
+#define MLC_ECC_AUTO_ENC_PROGRAM BIT32(8)
+
+/** @} */
+
+#define MLC_BAD_BLOCK_MASK ((uint32_t) 0xff00)
+
+/**
+ * @name NAND Status Register
+ *
+ * @{
+ */
+
+#define NAND_STATUS_ERROR (1U << 0)
+#define NAND_STATUS_READY (1U << 6)
+#define NAND_STATUS_NOT_PROTECTED (1U << 7)
+
+/** @} */
+
+/**
+ * @brief MLC NAND controller configuration.
+ */
+typedef struct {
+ /**
+ * @brief Selects small pages (512 Bytes user data and 16 Bytes spare data)
+ * or large pages (2048 Bytes user data and 64 Bytes spare data).
+ */
+ bool small_pages;
+
+ /**
+ * @brief Selects 3/4 address cycles for small pages/large pages or 4/5
+ * address cycles.
+ */
+ bool many_address_cycles;
+
+ /**
+ * @brief Selects 64 or 128 pages per block in case of large pages.
+ */
+ bool normal_blocks;
+
+ uint32_t block_count;
+
+ /**
+ * @brief Value for the MLC NAND Timing Register (MLC_TIME_REG).
+ */
+ uint32_t time;
+} lpc32xx_mlc_config;
+
+/**
+ * @brief Initializes the MLC NAND controller according to @a cfg.
+ */
+void lpc32xx_mlc_init(const lpc32xx_mlc_config *cfg);
+
+uint32_t lpc32xx_mlc_page_size(void);
+
+uint32_t lpc32xx_mlc_pages_per_block(void);
+
+uint32_t lpc32xx_mlc_block_count(void);
+
+void lpc32xx_mlc_write_protection(
+ uint32_t page_index_low,
+ uint32_t page_index_high
+);
+
+void lpc32xx_mlc_read_id(uint8_t *id, size_t n);
+
+/**
+ * @brief Reads the page with index @a page_index.
+ *
+ * 32-bit reads will be performed.
+ *
+ * Bytes 7 to 15 of the spare area will contain the ECC.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_INVALID_ID Invalid @a page_index value.
+ * @retval RTEMS_IO_ERROR Uncorrectable bit error.
+ */
+rtems_status_code lpc32xx_mlc_read_page(
+ uint32_t page_index,
+ uint32_t *data,
+ uint32_t *spare
+);
+
+/**
+ * @brief Erases the block with index @a block_index.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_INVALID_ID Invalid @a block_index value.
+ * @retval RTEMS_IO_ERROR Erase error.
+ */
+rtems_status_code lpc32xx_mlc_erase_block(uint32_t block_index);
+
+/**
+ * @brief Writes the page with index @a page_index.
+ *
+ * 32-bit writes will be performed.
+ *
+ * Bytes 7 to 15 of the spare area will be used for the automatically generated
+ * ECC.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_INVALID_ID Invalid @a page_index value.
+ * @retval RTEMS_IO_ERROR Write error.
+ */
+rtems_status_code lpc32xx_mlc_write_page_with_ecc(
+ uint32_t page_index,
+ const uint32_t *data,
+ const uint32_t *spare
+);
+
+/**
+ * @brief Writes @a src_size Bytes from @a src to the flash area specified by
+ * @a block_begin and @a block_end.
+ *
+ * The @a page_buffer will be used as an intermediate buffer.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_INVALID_ID Invalid @a block_begin or @a block_end value.
+ * @retval RTEMS_IO_ERROR To many bad blocks or source area to big.
+ */
+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_buffer [MLC_LARGE_DATA_WORD_COUNT]
+);
+
+/**
+ * @brief Read blocks process function type.
+ *
+ * @see lpc32xx_mlc_read_blocks().
+ *
+ * @retval false Continue processing.
+ * @retval true Stop processing.
+ */
+typedef bool (*lpc32xx_mlc_read_process)(
+ void *process_arg,
+ uint32_t page_index,
+ uint32_t page_size,
+ uint32_t page_data [MLC_LARGE_DATA_WORD_COUNT],
+ uint32_t page_spare [MLC_LARGE_SPARE_WORD_COUNT]
+);
+
+/**
+ * @brief Reads the pages of block @a block_begin up to and excluding
+ * @a block_end.
+ *
+ * For each page @a process will be called with the @a process_arg parameter,
+ * the page_index, the page data and the page spare.
+ *
+ * The @a page_buffer_0 and @a page_buffer_1 will be used as
+ * intermediate buffers.
+ */
+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]
+);
+
+static inline bool lpc32xx_mlc_is_bad_page(const uint32_t *spare)
+{
+ return (spare [1] & MLC_BAD_BLOCK_MASK) != MLC_BAD_BLOCK_MASK;
+}
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_LPC32XX_NAND_MLC_H */