[U-Boot] [PATCH v1 0/4] enable support for x16 NAND devices

This series includes independent patch-sets aiming to enable x16 NAND support on AM33xx boards (like beaglebone-LT). [PATCH 1/4]: This patch is ported from linux driver/mtd/nand to allow detection device-width of NAND by reading ONFI parameter page. [PATCH 2/4]: enable NAND_BUSWIDTH_AUTO feature in omap_nand.c [PATCH 3/4]: cleaning of GPMC configs for NAND and NOR [PATCH 4/4]: enable x16 and x8 NAND device pin-muxing for beagle-bone LT (white)
However, this patch does not enable NAND boot via x16 device, as SPL boot does not have capability of reading on-chip ONFI parameters so x16 device would not get detected in SPL NAND boot. Thus x16 device would be detected only once second-stage of u-boot is loaded via some other boot-source like SD/MMC.
---
Matthieu CASTET (1): [PATCH 1/4] mtd: nand: add NAND_BUSWIDTH_AUTO to autodetect bus width
Pekon Gupta (3): [PATCH 2/4] mtd: nand: omap: enable autodetection of bus-width of NAND device [PATCH 3/4] am335x: fix GPMC config for NAND and NOR SPL boot [PATCH 4/4] am33xx: add support for beaglebone x16 NAND cape
arch/arm/cpu/armv7/am33xx/mem.c | 48 +++++++++++------------ arch/arm/include/asm/arch-am33xx/mem.h | 5 --- board/ti/am335x/board.c | 12 ------ board/ti/am335x/mux.c | 71 ++++++++++++++++++++++++---------- drivers/mtd/nand/nand_base.c | 20 +++++++--- drivers/mtd/nand/omap_gpmc.c | 5 +-- include/configs/am335x_evm.h | 3 +- include/linux/mtd/nand.h | 7 ++++ 8 files changed, 99 insertions(+), 72 deletions(-)

From: Matthieu CASTET matthieu.castet@parrot.com
This patch is slightly modified from following linux patch http://lists.infradead.org/pipermail/linux-mtd/2012-November/044803.html So retaining the authorship to Matthieu CASTET matthieu.castet@parrot.com *Modifications from original patch* reset chip->read_byte, chip->read_buf, chip->write_buf before setting defaults.
*Original patch message* The driver call nand_scan_ident in 8 bit mode, then readid or onfi detection are done (and detect bus width). The driver should update its bus width before calling nand_scan_tail.
This work because readid and onfi are read work 8 byte mode.
Note that nand_scan_ident send command (NAND_CMD_RESET, NAND_CMD_READID, NAND_CMD_PARAM), address and read data The ONFI specificication is not very clear for x16 device if high byte of address should be driven to 0, but according to [1] it should be ok to not drive it during autodetection.
[1] 3.3.2. Target Initialization
[...] The Read ID and Read Parameter Page commands only use the lower 8-bits of the data bus. The host shall not issue commands that use a word data width on x16 devices until the host determines the device supports a 16-bit data bus width in the parameter page.
Signed-off-by: Pekon Gupta pekon@ti.com --- drivers/mtd/nand/nand_base.c | 20 +++++++++++++++----- include/linux/mtd/nand.h | 7 +++++++ 2 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 9e05cef..52e799b 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2977,11 +2977,21 @@ ident_done: break; }
- /* - * Check, if buswidth is correct. Hardware drivers should set - * chip correct! - */ - if (busw != (chip->options & NAND_BUSWIDTH_16)) { + if (chip->options & NAND_BUSWIDTH_AUTO) { + WARN_ON(chip->options & NAND_BUSWIDTH_16); + chip->options |= busw; + if (chip->read_byte == nand_read_byte) + chip->read_byte = NULL; + if (chip->read_buf == nand_read_buf) + chip->read_buf = NULL; + if (chip->write_buf == nand_write_buf) + chip->write_buf = NULL; + nand_set_defaults(chip, busw); + } else if (busw != (chip->options & NAND_BUSWIDTH_16)) { + /* + * Check, if buswidth is correct. Hardware drivers should set + * chip correct! + */ pr_info("NAND device: Manufacturer ID:" " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id, nand_manuf_ids[maf_idx].name, mtd->name); diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 2055584..bd6bc25 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -211,6 +211,13 @@ typedef enum { #define NAND_OWN_BUFFERS 0x00020000 /* Chip may not exist, so silence any errors in scan */ #define NAND_SCAN_SILENT_NODEV 0x00040000 +/* + * Autodetect nand buswidth with readid/onfi. + * This suppose the driver will configure the hardware in 8 bits mode + * when calling nand_scan_ident, and update its configuration + * before calling nand_scan_tail. + */ +#define NAND_BUSWIDTH_AUTO 0x00080000
/* Options set by nand scan */ /* bbt has already been read */

On Tue, Sep 10, 2013 at 06:57:05PM +0530, pekon gupta wrote:
From: Matthieu CASTET matthieu.castet@parrot.com
This patch is slightly modified from following linux patch http://lists.infradead.org/pipermail/linux-mtd/2012-November/044803.html
Which is now commit 64b37b2a63eb2f80b65c7185f0013f8ffc637ae3
So retaining the authorship to Matthieu CASTET matthieu.castet@parrot.com *Modifications from original patch* reset chip->read_byte, chip->read_buf, chip->write_buf before setting defaults.
Why does U-Boot need this if Linux doesn't?
-Scott

This patch: - Enables autodetection of NAND bus-width by reading ONFI parameter page, during device-scan (nand_scan_ident), removed dependency on static configuration in GPMC_CONFIG1_X register. - adds reconfiguration of device-width in GPMC_CONFIG1_x
Signed-off-by: Pekon Gupta pekon@ti.com --- drivers/mtd/nand/omap_gpmc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c index b044f00..944f0ea 100644 --- a/drivers/mtd/nand/omap_gpmc.c +++ b/drivers/mtd/nand/omap_gpmc.c @@ -834,10 +834,7 @@ int board_nand_init(struct nand_chip *nand) nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd; nand->priv = &bch_priv; nand->cmd_ctrl = omap_nand_hwcontrol; - nand->options = NAND_NO_PADDING | NAND_CACHEPRG; - /* If we are 16 bit dev, our gpmc config tells us that */ - if ((readl(&gpmc_cfg->cs[cs].config1) & 0x3000) == 0x1000) - nand->options |= NAND_BUSWIDTH_16; + nand->options = NAND_NO_PADDING | NAND_CACHEPRG | NAND_BUSWIDTH_AUTO;
nand->chip_delay = 100; nand->ecc.layout = &omap_ecclayout;

GPMC controller is common IP to interface with both NAND and NOR flash devices. Also, it supports max 8 chip-selects, which can be independently connected to any of the devices. But ROM code expects the boot-device to be connected to only chip-select[0]. Thus to resolve conflict between NOR and NAND boot. This patch: - combines NOR and NAND configs spread in board files to common gpmc_init() - configures GPMC based on boot-mode selected for SPL boot.
Signed-off-by: Pekon Gupta pekon@ti.com --- arch/arm/cpu/armv7/am33xx/mem.c | 48 +++++++++++++++++----------------- arch/arm/include/asm/arch-am33xx/mem.h | 5 ---- board/ti/am335x/board.c | 12 --------- include/configs/am335x_evm.h | 3 +-- 4 files changed, 25 insertions(+), 43 deletions(-)
diff --git a/arch/arm/cpu/armv7/am33xx/mem.c b/arch/arm/cpu/armv7/am33xx/mem.c index b6eb466..22ab25b 100644 --- a/arch/arm/cpu/armv7/am33xx/mem.c +++ b/arch/arm/cpu/armv7/am33xx/mem.c @@ -22,17 +22,6 @@
struct gpmc *gpmc_cfg;
-#if defined(CONFIG_CMD_NAND) -static const u32 gpmc_m_nand[GPMC_MAX_REG] = { - M_NAND_GPMC_CONFIG1, - M_NAND_GPMC_CONFIG2, - M_NAND_GPMC_CONFIG3, - M_NAND_GPMC_CONFIG4, - M_NAND_GPMC_CONFIG5, - M_NAND_GPMC_CONFIG6, 0 -}; -#endif -
void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base, u32 size) @@ -61,11 +50,28 @@ void gpmc_init(void) { /* putting a blanket check on GPMC based on ZeBu for now */ gpmc_cfg = (struct gpmc *)GPMC_BASE; - -#ifdef CONFIG_CMD_NAND - const u32 *gpmc_config = NULL; - u32 base = 0; - u32 size = 0; +#if defined(CONFIG_NOR) + const u32 gpmc_regs[GPMC_MAX_REG] = { STNOR_GPMC_CONFIG1, + STNOR_GPMC_CONFIG2, + STNOR_GPMC_CONFIG3, + STNOR_GPMC_CONFIG4, + STNOR_GPMC_CONFIG5, + STNOR_GPMC_CONFIG6, + STNOR_GPMC_CONFIG7 + }; + u32 size = GPMC_SIZE_16M; + u32 base = CONFIG_SYS_FLASH_BASE; +#elif defined(CONFIG_NAND) +static const u32 gpmc_regs[GPMC_MAX_REG] = { M_NAND_GPMC_CONFIG1, + M_NAND_GPMC_CONFIG2, + M_NAND_GPMC_CONFIG3, + M_NAND_GPMC_CONFIG4, + M_NAND_GPMC_CONFIG5, + M_NAND_GPMC_CONFIG6, + 0 + }; + u32 size = GPMC_SIZE_256M; + u32 base = CONFIG_SYS_NAND_BASE; #endif /* global settings */ writel(0x00000008, &gpmc_cfg->sysconfig); @@ -81,12 +87,6 @@ void gpmc_init(void) */ writel(0, &gpmc_cfg->cs[0].config7); sdelay(1000); - -#ifdef CONFIG_CMD_NAND - gpmc_config = gpmc_m_nand; - - base = PISMO1_NAND_BASE; - size = PISMO1_NAND_SIZE; - enable_gpmc_cs_config(gpmc_config, &gpmc_cfg->cs[0], base, size); -#endif + /* enable chip-select specific configurations */ + enable_gpmc_cs_config(gpmc_regs, &gpmc_cfg->cs[0], base, size); } diff --git a/arch/arm/include/asm/arch-am33xx/mem.h b/arch/arm/include/asm/arch-am33xx/mem.h index 983ea28..e7e8c58 100644 --- a/arch/arm/include/asm/arch-am33xx/mem.h +++ b/arch/arm/include/asm/arch-am33xx/mem.h @@ -68,9 +68,4 @@ #define PISMO2_NAND_CS0 7 #define PISMO2_NAND_CS1 8
-/* make it readable for the gpmc_init */ -#define PISMO1_NOR_BASE FLASH_BASE -#define PISMO1_NAND_BASE CONFIG_SYS_NAND_BASE -#define PISMO1_NAND_SIZE GPMC_SIZE_256M - #endif /* endif _MEM_H_ */ diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c index 04c37e2..328e6bd 100644 --- a/board/ti/am335x/board.c +++ b/board/ti/am335x/board.c @@ -337,22 +337,10 @@ void sdram_init(void) */ int board_init(void) { -#ifdef CONFIG_NOR - const u32 gpmc_nor[GPMC_MAX_REG] = { STNOR_GPMC_CONFIG1, - STNOR_GPMC_CONFIG2, STNOR_GPMC_CONFIG3, STNOR_GPMC_CONFIG4, - STNOR_GPMC_CONFIG5, STNOR_GPMC_CONFIG6, STNOR_GPMC_CONFIG7 }; -#endif - gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
gpmc_init();
-#ifdef CONFIG_NOR - /* Reconfigure CS0 for NOR instead of NAND. */ - enable_gpmc_cs_config(gpmc_nor, &gpmc_cfg->cs[0], - CONFIG_SYS_FLASH_BASE, GPMC_SIZE_16M); -#endif - return 0; }
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h index c2d25a4..7c59db9 100644 --- a/include/configs/am335x_evm.h +++ b/include/configs/am335x_evm.h @@ -15,7 +15,6 @@
#ifndef __CONFIG_AM335X_EVM_H #define __CONFIG_AM335X_EVM_H - #include <configs/ti_am335x_common.h>
#define MACH_TYPE_TIAM335EVM 3589 /* Until the next sync */ @@ -240,6 +239,7 @@ #define CONFIG_SYS_SPI_U_BOOT_OFFS 0x20000 #define CONFIG_SPL_MUSB_NEW_SUPPORT #define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/am33xx/u-boot-spl.lds" +#endif
#ifdef CONFIG_NAND #define CONFIG_SYS_NAND_5_ADDR_CYCLE @@ -265,7 +265,6 @@ #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000 #endif -#endif
/* * For NOR boot, we must set this to the start of where NOR is mapped

beaglebone board can be connected to expansion boards to add devices to them. These expansion boards are called 'capes'. This patch updates pin-mux for 'NAND' cape which can be used with beaglebone LT (white). Further information and datasheets of this NAND cape can be found at: - http://beagleboardtoys.info/index.php?title=BeagleBone_Memory_Expansion - http://beagleboardtoys.info/index.php?title=BeagleBone_4Gb_16-Bit_NAND_Modul...
Signed-off-by: Pekon Gupta pekon@ti.com --- board/ti/am335x/mux.c | 71 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 20 deletions(-)
diff --git a/board/ti/am335x/mux.c b/board/ti/am335x/mux.c index b2bfda5..341513a 100644 --- a/board/ti/am335x/mux.c +++ b/board/ti/am335x/mux.c @@ -171,25 +171,53 @@ static struct module_pin_mux mii1_pin_mux[] = { {-1}, };
-static struct module_pin_mux nand_pin_mux[] = { - {OFFSET(gpmc_ad0), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* NAND AD0 */ - {OFFSET(gpmc_ad1), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* NAND AD1 */ - {OFFSET(gpmc_ad2), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* NAND AD2 */ - {OFFSET(gpmc_ad3), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* NAND AD3 */ - {OFFSET(gpmc_ad4), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* NAND AD4 */ - {OFFSET(gpmc_ad5), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* NAND AD5 */ - {OFFSET(gpmc_ad6), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* NAND AD6 */ - {OFFSET(gpmc_ad7), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* NAND AD7 */ - {OFFSET(gpmc_wait0), (MODE(0) | RXACTIVE | PULLUP_EN)}, /* NAND WAIT */ - {OFFSET(gpmc_wpn), (MODE(7) | PULLUP_EN | RXACTIVE)}, /* NAND_WPN */ - {OFFSET(gpmc_csn0), (MODE(0) | PULLUDEN)}, /* NAND_CS0 */ - {OFFSET(gpmc_advn_ale), (MODE(0) | PULLUDEN)}, /* NAND_ADV_ALE */ - {OFFSET(gpmc_oen_ren), (MODE(0) | PULLUDEN)}, /* NAND_OE */ - {OFFSET(gpmc_wen), (MODE(0) | PULLUDEN)}, /* NAND_WEN */ - {OFFSET(gpmc_be0n_cle), (MODE(0) | PULLUDEN)}, /* NAND_BE_CLE */ +#ifdef CONFIG_NAND +static struct module_pin_mux nand_x16_pin_mux[] = { + {OFFSET(gpmc_ad0), (MODE(0) | RXACTIVE)}, /* NAND AD0 */ + {OFFSET(gpmc_ad1), (MODE(0) | RXACTIVE)}, /* NAND AD1 */ + {OFFSET(gpmc_ad2), (MODE(0) | RXACTIVE)}, /* NAND AD2 */ + {OFFSET(gpmc_ad3), (MODE(0) | RXACTIVE)}, /* NAND AD3 */ + {OFFSET(gpmc_ad4), (MODE(0) | RXACTIVE)}, /* NAND AD4 */ + {OFFSET(gpmc_ad5), (MODE(0) | RXACTIVE)}, /* NAND AD5 */ + {OFFSET(gpmc_ad6), (MODE(0) | RXACTIVE)}, /* NAND AD6 */ + {OFFSET(gpmc_ad7), (MODE(0) | RXACTIVE)}, /* NAND AD7 */ + {OFFSET(gpmc_ad8), (MODE(0) | RXACTIVE)}, /* NAND AD8 */ + {OFFSET(gpmc_ad9), (MODE(0) | RXACTIVE)}, /* NAND AD9 */ + {OFFSET(gpmc_ad10), (MODE(0) | RXACTIVE)}, /* NAND AD10 */ + {OFFSET(gpmc_ad11), (MODE(0) | RXACTIVE)}, /* NAND AD11 */ + {OFFSET(gpmc_ad12), (MODE(0) | RXACTIVE)}, /* NAND AD12 */ + {OFFSET(gpmc_ad13), (MODE(0) | RXACTIVE)}, /* NAND AD13 */ + {OFFSET(gpmc_ad14), (MODE(0) | RXACTIVE)}, /* NAND AD14 */ + {OFFSET(gpmc_ad15), (MODE(0) | RXACTIVE)}, /* NAND AD15 */ + {OFFSET(gpmc_wait0), (MODE(0) | RXACTIVE)}, /* NAND WAIT */ + {OFFSET(gpmc_wpn), (MODE(7) | PULLUP_EN)}, /* NAND_WPN */ + {OFFSET(gpmc_csn0), (MODE(0) | PULLUP_EN)}, /* NAND_CS0 */ + {OFFSET(gpmc_wen), (MODE(0) | PULLUP_EN)}, /* NAND_WEN */ + {OFFSET(gpmc_oen_ren), (MODE(0) | PULLUP_EN)}, /* NAND_OE */ + {OFFSET(gpmc_advn_ale), (MODE(0) | PULLDOWN_EN)}, /* NAND_ADV_ALE */ + {OFFSET(gpmc_be0n_cle), (MODE(0) | PULLDOWN_EN)}, /* NAND_BE_CLE */ {-1}, };
+static struct module_pin_mux nand_x8_pin_mux[] = { + {OFFSET(gpmc_ad0), (MODE(0) | RXACTIVE)}, /* NAND AD0 */ + {OFFSET(gpmc_ad1), (MODE(0) | RXACTIVE)}, /* NAND AD1 */ + {OFFSET(gpmc_ad2), (MODE(0) | RXACTIVE)}, /* NAND AD2 */ + {OFFSET(gpmc_ad3), (MODE(0) | RXACTIVE)}, /* NAND AD3 */ + {OFFSET(gpmc_ad4), (MODE(0) | RXACTIVE)}, /* NAND AD4 */ + {OFFSET(gpmc_ad5), (MODE(0) | RXACTIVE)}, /* NAND AD5 */ + {OFFSET(gpmc_ad6), (MODE(0) | RXACTIVE)}, /* NAND AD6 */ + {OFFSET(gpmc_ad7), (MODE(0) | RXACTIVE)}, /* NAND AD7 */ + {OFFSET(gpmc_wait0), (MODE(0) | RXACTIVE)}, /* NAND WAIT */ + {OFFSET(gpmc_wpn), (MODE(7) | PULLUP_EN)}, /* NAND_WPN */ + {OFFSET(gpmc_csn0), (MODE(0) | PULLUP_EN)}, /* NAND_CS0 */ + {OFFSET(gpmc_wen), (MODE(0) | PULLUP_EN)}, /* NAND_WEN */ + {OFFSET(gpmc_oen_ren), (MODE(0) | PULLUP_EN)}, /* NAND_OE */ + {OFFSET(gpmc_advn_ale), (MODE(0) | PULLDOWN_EN)}, /* NAND_ADV_ALE */ + {OFFSET(gpmc_be0n_cle), (MODE(0) | PULLDOWN_EN)}, /* NAND_BE_CLE */ + {-1}, +}; +#endif #if defined(CONFIG_NOR) && !defined(CONFIG_NOR_BOOT) static struct module_pin_mux bone_norcape_pin_mux[] = { {OFFSET(lcd_data0), MODE(1) | PULLUDEN | RXACTIVE}, /* NOR_A0 */ @@ -336,11 +364,12 @@ void enable_board_pin_mux(struct am335x_baseboard_id *header) configure_module_pin_mux(i2c1_pin_mux); configure_module_pin_mux(mii1_pin_mux); configure_module_pin_mux(mmc0_pin_mux); -#ifndef CONFIG_NOR - configure_module_pin_mux(mmc1_pin_mux); -#endif #if defined(CONFIG_NOR) && !defined(CONFIG_NOR_BOOT) configure_module_pin_mux(bone_norcape_pin_mux); +#elif defined(CONFIG_NAND) + configure_module_pin_mux(nand_x16_pin_mux); +#else + configure_module_pin_mux(mmc1_pin_mux); #endif } else if (board_is_gp_evm(header)) { /* General Purpose EVM */ @@ -351,8 +380,10 @@ void enable_board_pin_mux(struct am335x_baseboard_id *header) if (profile & ~PROFILE_2) configure_module_pin_mux(i2c1_pin_mux); /* Profiles 2 & 3 don't have NAND */ +#ifdef CONFIG_NAND if (profile & ~(PROFILE_2 | PROFILE_3)) - configure_module_pin_mux(nand_pin_mux); + configure_module_pin_mux(nand_x8_pin_mux); +#endif else if (profile == PROFILE_2) { configure_module_pin_mux(mmc1_pin_mux); configure_module_pin_mux(spi0_pin_mux);
participants (2)
-
Pekon Gupta
-
Scott Wood