From 1d9654dc43ea0e4dc083487005f00e32e16a42be Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 26 Aug 2017 01:12:31 +0900 Subject: [PATCH] mtd: nand: denali_dt: add a DT driver A patch for NAND uclass support was proposed about half a year ago: https://patchwork.ozlabs.org/patch/722282/ It was not merged and I do not see on-going work for this. Without DM-based probing, we need to set up pinctrl etc. in an ad-hoc way and give lots of crappy CONFIG options for base addresses and properties, which are supposed to be specified by DT. This is painful. This commit just provides a probe hook to retrieve "reg" from DT and allocate private data in a DM manner. This DT driver is not essentially a NAND driver, in fact it is (ab)using UCLASS_MISC. Once UCLASS_NAND is supported, it would be possible to migrate to it. Signed-off-by: Masahiro Yamada --- drivers/mtd/nand/Kconfig | 7 ++++ drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/denali.c | 4 ++- drivers/mtd/nand/denali.h | 2 ++ drivers/mtd/nand/denali_dt.c | 68 ++++++++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 drivers/mtd/nand/denali_dt.c diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 71d678fc66..85b26d6088 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -16,6 +16,13 @@ config NAND_DENALI help Enable support for the Denali NAND controller. +config NAND_DENALI_DT + bool "Support Denali NAND controller as a DT device" + depends on NAND_DENALI && OF_CONTROL && DM + help + Enable the driver for NAND flash on platforms using a Denali NAND + controller as a DT device. + config SYS_NAND_DENALI_64BIT bool "Use 64-bit variant of Denali NAND controller" depends on NAND_DENALI diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index c3d4a996f3..9f7d9d6ff7 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_NAND_ATMEL) += atmel_nand.o obj-$(CONFIG_NAND_ARASAN) += arasan_nfc.o obj-$(CONFIG_NAND_DAVINCI) += davinci_nand.o obj-$(CONFIG_NAND_DENALI) += denali.o +obj-$(CONFIG_NAND_DENALI_DT) += denali_dt.o obj-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o obj-$(CONFIG_NAND_FSL_IFC) += fsl_ifc_nand.o obj-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 18280b0b2f..47cf37d1d9 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -1175,7 +1175,7 @@ static void denali_hw_init(struct denali_nand_info *denali) static struct nand_ecclayout nand_oob; -static int denali_init(struct denali_nand_info *denali) +int denali_init(struct denali_nand_info *denali) { struct mtd_info *mtd = nand_to_mtd(&denali->nand); int ret; @@ -1273,6 +1273,7 @@ fail: return ret; } +#ifndef CONFIG_NAND_DENALI_DT static int __board_nand_init(void) { struct denali_nand_info *denali; @@ -1296,3 +1297,4 @@ void board_nand_init(void) if (__board_nand_init() < 0) pr_warn("Failed to initialize Denali NAND controller.\n"); } +#endif diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index 0e098bddf1..694bce53a9 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -464,4 +464,6 @@ struct denali_nand_info { uint32_t max_banks; }; +int denali_init(struct denali_nand_info *denali); + #endif /* __DENALI_H__ */ diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c new file mode 100644 index 0000000000..0a6155c748 --- /dev/null +++ b/drivers/mtd/nand/denali_dt.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2017 Socionext Inc. + * Author: Masahiro Yamada + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +#include "denali.h" + +static const struct udevice_id denali_nand_dt_ids[] = { + { + .compatible = "altr,socfpga-denali-nand", + }, + { + .compatible = "socionext,uniphier-denali-nand-v5a", + }, + { + .compatible = "socionext,uniphier-denali-nand-v5b", + }, + { /* sentinel */ } +}; + +static int denali_dt_probe(struct udevice *dev) +{ + struct denali_nand_info *denali = dev_get_priv(dev); + struct resource res; + int ret; + + ret = dev_read_resource_byname(dev, "denali_reg", &res); + if (ret) + return ret; + + denali->flash_reg = devm_ioremap(dev, res.start, resource_size(&res)); + + ret = dev_read_resource_byname(dev, "nand_data", &res); + if (ret) + return ret; + + denali->flash_mem = devm_ioremap(dev, res.start, resource_size(&res)); + + return denali_init(denali); +} + +U_BOOT_DRIVER(denali_nand_dt) = { + .name = "denali-nand-dt", + .id = UCLASS_MISC, + .of_match = denali_nand_dt_ids, + .probe = denali_dt_probe, + .priv_auto_alloc_size = sizeof(struct denali_nand_info), +}; + +void board_nand_init(void) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(denali_nand_dt), + &dev); + if (ret && ret != -ENODEV) + printf("Failed to initialize Denali NAND controller. (error %d)\n", + ret); +} -- 2.25.1