[U-Boot] [PATCH v2 0/3] tegra nand mtd, ubi, driver model and live tree enablement

This series addresses recent Tegra NAND driver breakage caused by ongoing driver model resp. live tree migration work and enables it on Harmony as well.
This series is available at http://git.toradex.com/cgit/u-boot-toradex.git/log/?h=for-next
Changes in v2: - Use UCLASS_MTD rather than MISC as suggested by Stefan. - Enable CONFIG_MTD as well to make sure UCLASS_MTD is available. - New commit required due to using UCLASS_MTD.
Marcel Ziswiler (3): mtd: nand: tegra: convert to driver model and live tree configs: harmony: enable live tree, mtd and ubi configs: colibri_t20: enable mtd
configs/colibri_t20_defconfig | 1 + configs/harmony_defconfig | 6 +++ drivers/mtd/nand/tegra_nand.c | 98 ++++++++++++++++++++++++------------------- include/configs/harmony.h | 4 ++ 4 files changed, 66 insertions(+), 43 deletions(-)

From: Marcel Ziswiler marcel.ziswiler@toradex.com
The Tegra NAND driver recently got broken by ongoing driver model resp. live tree migration work:
NAND: Could not decode nand-flash in device tree Tegra NAND init failed 0 MiB
A patch for NAND uclass support was proposed about a year ago: https://patchwork.ozlabs.org/patch/722282/
It was not merged and I do not see on-going work for this.
This commit just provides a driver model probe hook to retrieve further configuration from the live device tree. As there is no NAND ulass as of yet (ab)using UCLASS_MTD. Once UCLASS_NAND is supported, it would be possible to migrate to it.
Signed-off-by: Marcel Ziswiler marcel.ziswiler@toradex.com Reviewed-by: Simon Glass sjg@chromium.org
---
Changes in v2: - Use UCLASS_MTD rather than MISC as suggested by Stefan.
drivers/mtd/nand/tegra_nand.c | 98 ++++++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 43 deletions(-)
diff --git a/drivers/mtd/nand/tegra_nand.c b/drivers/mtd/nand/tegra_nand.c index c03c9cb178..3802cc9e89 100644 --- a/drivers/mtd/nand/tegra_nand.c +++ b/drivers/mtd/nand/tegra_nand.c @@ -18,6 +18,7 @@ #include <asm/gpio.h> #include <fdtdec.h> #include <bouncebuf.h> +#include <dm.h> #include "tegra_nand.h"
DECLARE_GLOBAL_DATA_PTR; @@ -29,6 +30,13 @@ DECLARE_GLOBAL_DATA_PTR; /* ECC bytes to be generated for tag data */ #define TAG_ECC_BYTES 4
+static const struct udevice_id tegra_nand_dt_ids[] = { + { + .compatible = "nvidia,tegra20-nand", + }, + { /* sentinel */ } +}; + /* 64 byte oob block info for large page (== 2KB) device * * OOB flash layout for Tegra with Reed-Solomon 4 symbol correct ECC: @@ -91,9 +99,11 @@ struct nand_drv { struct fdt_nand config; };
-static struct nand_drv nand_ctrl; -static struct mtd_info *our_mtd; -static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE]; +struct tegra_nand_info { + struct udevice *dev; + struct nand_drv nand_ctrl; + struct nand_chip nand_chip; +};
/** * Wait for command completion @@ -453,8 +463,8 @@ static void stop_command(struct nand_ctlr *reg) * @param *reg_val address of reg_val * @return 0 if ok, -1 on error */ -static int set_bus_width_page_size(struct fdt_nand *config, - u32 *reg_val) +static int set_bus_width_page_size(struct mtd_info *our_mtd, + struct fdt_nand *config, u32 *reg_val) { if (config->width == 8) *reg_val = CFG_BUS_WIDTH_8BIT; @@ -514,7 +524,7 @@ static int nand_rw_page(struct mtd_info *mtd, struct nand_chip *chip,
info = (struct nand_drv *)nand_get_controller_data(chip); config = &info->config; - if (set_bus_width_page_size(config, ®_val)) + if (set_bus_width_page_size(mtd, config, ®_val)) return -EINVAL;
/* Need to be 4-byte aligned */ @@ -722,7 +732,7 @@ static int nand_rw_oob(struct mtd_info *mtd, struct nand_chip *chip, if (((int)chip->oob_poi) & 0x03) return -EINVAL; info = (struct nand_drv *)nand_get_controller_data(chip); - if (set_bus_width_page_size(&info->config, ®_val)) + if (set_bus_width_page_size(mtd, &info->config, ®_val)) return -EINVAL;
stop_command(info->reg); @@ -883,51 +893,39 @@ static void setup_timing(unsigned timing[FDT_NAND_TIMING_COUNT], /** * Decode NAND parameters from the device tree * - * @param blob Device tree blob - * @param node Node containing "nand-flash" compatible node + * @param dev Driver model device + * @param config Device tree NAND configuration * @return 0 if ok, -ve on error (FDT_ERR_...) */ -static int fdt_decode_nand(const void *blob, int node, struct fdt_nand *config) +static int fdt_decode_nand(struct udevice *dev, struct fdt_nand *config) { int err;
- config->reg = (struct nand_ctlr *)fdtdec_get_addr(blob, node, "reg"); - config->enabled = fdtdec_get_is_enabled(blob, node); - config->width = fdtdec_get_int(blob, node, "nvidia,nand-width", 8); - err = gpio_request_by_name_nodev(offset_to_ofnode(node), - "nvidia,wp-gpios", 0, &config->wp_gpio, GPIOD_IS_OUT); + config->reg = (struct nand_ctlr *)dev_read_addr(dev); + config->enabled = dev_read_enabled(dev); + config->width = dev_read_u32_default(dev, "nvidia,nand-width", 8); + err = gpio_request_by_name(dev, "nvidia,wp-gpios", 0, &config->wp_gpio, + GPIOD_IS_OUT); if (err) return err; - err = fdtdec_get_int_array(blob, node, "nvidia,timing", - config->timing, FDT_NAND_TIMING_COUNT); + err = dev_read_u32_array(dev, "nvidia,timing", config->timing, + FDT_NAND_TIMING_COUNT); if (err < 0) return err;
- /* Now look up the controller and decode that */ - node = fdt_next_node(blob, node, NULL); - if (node < 0) - return node; - return 0; }
-/** - * Board-specific NAND initialization - * - * @param nand nand chip info structure - * @return 0, after initialized, -1 on error - */ -int tegra_nand_init(struct nand_chip *nand, int devnum) +static int tegra_probe(struct udevice *dev) { - struct nand_drv *info = &nand_ctrl; + struct tegra_nand_info *tegra = dev_get_priv(dev); + struct nand_chip *nand = &tegra->nand_chip; + struct nand_drv *info = &tegra->nand_ctrl; struct fdt_nand *config = &info->config; - int node, ret; + struct mtd_info *our_mtd; + int ret;
- node = fdtdec_next_compatible(gd->fdt_blob, 0, - COMPAT_NVIDIA_TEGRA20_NAND); - if (node < 0) - return -1; - if (fdt_decode_nand(gd->fdt_blob, node, config)) { + if (fdt_decode_nand(dev, config)) { printf("Could not decode nand-flash in device tree\n"); return -1; } @@ -950,7 +948,7 @@ int tegra_nand_init(struct nand_chip *nand, int devnum) nand->ecc.strength = 1; nand->select_chip = nand_select_chip; nand->dev_ready = nand_dev_ready; - nand_set_controller_data(nand, &nand_ctrl); + nand_set_controller_data(nand, &tegra->nand_ctrl);
/* Disable subpage writes as we do not provide ecc->hwctl */ nand->options |= NAND_NO_SUBPAGE_WRITE; @@ -975,17 +973,31 @@ int tegra_nand_init(struct nand_chip *nand, int devnum) if (ret) return ret;
- ret = nand_register(devnum, our_mtd); - if (ret) + ret = nand_register(0, our_mtd); + if (ret) { + dev_err(dev, "Failed to register MTD: %d\n", ret); return ret; + }
return 0; }
+U_BOOT_DRIVER(tegra_nand) = { + .name = "tegra-nand", + .id = UCLASS_MTD, + .of_match = tegra_nand_dt_ids, + .probe = tegra_probe, + .priv_auto_alloc_size = sizeof(struct tegra_nand_info), +}; + void board_nand_init(void) { - struct nand_chip *nand = &nand_chip[0]; - - if (tegra_nand_init(nand, 0)) - puts("Tegra NAND init failed\n"); + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_MTD, + DM_GET_DRIVER(tegra_nand), &dev); + if (ret && ret != -ENODEV) + pr_err("Failed to initialize %s. (error %d)\n", dev->name, + ret); }

From: Marcel Ziswiler marcel.ziswiler@toradex.com
U-Boot on Harmony recently got broken by ongoing driver model resp. live tree migration work:
U-Boot 2018.03-rc3 (Feb 21 2018 - 15:43:08 +0100)
TEGRA20 Model: NVIDIA Tegra20 Harmony evaluation board Board: NVIDIA Harmony DRAM: 1 GiB Video device 'dc@54200000' cannot allocate frame buffer memory -ensure the device is set up before relocation Error binding driver 'tegra_lcd': -28 Some drivers failed to bind Error binding driver 'generic_simple_bus': -28 Some drivers failed to bind initcall sequence 3ffa86d0 failed at call 00121dc0 (err=-28)
This commit fixes this by enabling live tree, MTD and UBI for Harmony as well.
Signed-off-by: Marcel Ziswiler marcel.ziswiler@toradex.com
---
Changes in v2: - Enable CONFIG_MTD as well to make sure UCLASS_MTD is available.
configs/harmony_defconfig | 6 ++++++ include/configs/harmony.h | 4 ++++ 2 files changed, 10 insertions(+)
diff --git a/configs/harmony_defconfig b/configs/harmony_defconfig index d716fc3546..9d4235b3a7 100644 --- a/configs/harmony_defconfig +++ b/configs/harmony_defconfig @@ -18,13 +18,19 @@ CONFIG_CMD_USB=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_EXT4_WRITE=y +CONFIG_MTDIDS_DEFAULT="nand0=tegra_nand" +CONFIG_MTDPARTS_DEFAULT="mtdparts=tegra_nand:2m(u-boot)ro,1m(u-boot-env),1m(cfgblock)ro,-(ubi)" +CONFIG_CMD_UBI=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set +CONFIG_OF_LIVE=y CONFIG_ENV_IS_IN_NAND=y CONFIG_SPL_DM=y CONFIG_PCI=y CONFIG_DM_PCI=y CONFIG_DM_PCI_COMPAT=y +CONFIG_MTD=y +CONFIG_MTD_UBI_FASTMAP=y CONFIG_DM_PMIC=y CONFIG_DM_REGULATOR=y CONFIG_DM_REGULATOR_FIXED=y diff --git a/include/configs/harmony.h b/include/configs/harmony.h index 9a0b1aff24..59fd6c4eb5 100644 --- a/include/configs/harmony.h +++ b/include/configs/harmony.h @@ -30,6 +30,10 @@ #define CONFIG_TEGRA_NAND #define CONFIG_SYS_MAX_NAND_DEVICE 1
+/* Dynamic MTD partition support */ +#define CONFIG_MTD_PARTITIONS +#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */ + /* Environment in NAND (which is 512M), aligned to start of last sector */ #define CONFIG_ENV_OFFSET (SZ_512M - SZ_128K) /* 128K sector size */

From: Marcel Ziswiler marcel.ziswiler@toradex.com
Enable CONFIG_MTD as well to make sure UCLASS_MTD is available
Signed-off-by: Marcel Ziswiler marcel.ziswiler@toradex.com
---
Changes in v2: - New commit required due to using UCLASS_MTD.
configs/colibri_t20_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/colibri_t20_defconfig b/configs/colibri_t20_defconfig index 90777e0201..e5d33ecfef 100644 --- a/configs/colibri_t20_defconfig +++ b/configs/colibri_t20_defconfig @@ -35,6 +35,7 @@ CONFIG_ENV_IS_IN_NAND=y CONFIG_SPL_DM=y CONFIG_DFU_MMC=y CONFIG_DFU_RAM=y +CONFIG_MTD=y CONFIG_MTD_UBI_FASTMAP=y CONFIG_DM_PMIC=y CONFIG_DM_REGULATOR=y
participants (1)
-
Marcel Ziswiler