No need to have a dedicated driver for this controller, all we need to do is adjust the memory range offset to account for the fact that the chip is connected to D[16:23] and not D[0:7]. Signed-off-by: Boris Brezillon <boris.brezillon@xxxxxxxxxxxxx> --- arch/arm/mach-pxa/cm-x270.c | 131 ++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c index 9baad11314f2..63bd3be60322 100644 --- a/arch/arm/mach-pxa/cm-x270.c +++ b/arch/arm/mach-pxa/cm-x270.c @@ -23,6 +23,8 @@ #include <linux/platform_data/usb-ohci-pxa27x.h> #include <linux/platform_data/mmc-pxamci.h> +#include <linux/mtd/platnand.h> + #include "generic.h" /* physical address if local-bus attached devices */ @@ -36,6 +38,10 @@ /* MMC power enable */ #define GPIO105_MMC_POWER (105) +/* NAND GPIOs */ +#define GPIO11_NAND_CS (11) +#define GPIO89_NAND_RB (89) + /* WLAN GPIOS */ #define GPIO19_WLAN_STRAP (19) #define GPIO102_WLAN_RST (102) @@ -309,6 +315,130 @@ static void __init cmx270_init_mmc(void) static inline void cmx270_init_mmc(void) {} #endif +/* NAND flash */ +#if IS_ENABLED(CONFIG_MTD_NAND_PLATFORM) +static inline void nand_cs_on(void) +{ + gpio_set_value(GPIO11_NAND_CS, 0); +} + +static void nand_cs_off(void) +{ + dsb(); + + gpio_set_value(GPIO11_NAND_CS, 1); +} + +/* hardware specific access to control-lines */ +static void cmx270_nand_cmd_ctl(struct nand_chip *this, int dat, + unsigned int ctrl) +{ + unsigned long nandaddr = (unsigned long)this->legacy.IO_ADDR_W; + + dsb(); + + if (ctrl & NAND_CTRL_CHANGE) { + if (ctrl & NAND_ALE) + nandaddr |= (1 << 3); + else + nandaddr &= ~(1 << 3); + if (ctrl & NAND_CLE) + nandaddr |= (1 << 2); + else + nandaddr &= ~(1 << 2); + if (ctrl & NAND_NCE) + nand_cs_on(); + else + nand_cs_off(); + } + + dsb(); + this->legacy.IO_ADDR_W = (void __iomem *)nandaddr; + if (dat != NAND_CMD_NONE) + writeb(dat, this->legacy.IO_ADDR_W); + + dsb(); +} + +/* read device ready pin */ +static int cmx270_nand_device_ready(struct nand_chip *this) +{ + dsb(); + + return gpio_get_value(GPIO89_NAND_RB); +} + +static struct mtd_partition cmx270_partition_info[] = { + [0] = { + .name = "cmx270-0", + .offset = 0, + .size = MTDPART_SIZ_FULL + }, +}; + +struct platform_nand_data cmx270_nand_platdata = { + .chip = { + .nr_chips = 1, + .chip_offset = 0, + .nr_partitions = ARRAY_SIZE(cmx270_partition_info), + .partitions = cmx270_partition_info, + .chip_delay = 20, + }, + .ctrl = { + .dev_ready = cmx270_nand_device_ready, + .cmd_ctrl = cmx270_nand_cmd_ctl, + }, +}; + +static struct resource cmx270_nand_resource[] = { + [0] = { + /* + * The NAND is connected to D[16:23], hence the 2 byte offset + * here. + */ + .start = PXA_CS1_PHYS + 2, + .end = PXA_CS1_PHYS + 2 + 12, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device cmx270_nand = { + .name = "gen_nand", + .num_resources = ARRAY_SIZE(cmx270_nand_resource), + .resource = cmx270_nand_resource, + .id = -1, + .dev = { + .platform_data = &cmx270_nand_platdata, + } +}; + +static void __init cmx270_init_nand(void) +{ + int err; + + err = gpio_request(GPIO11_NAND_CS, "NAND CS"); + if (err) { + pr_warn("CMX270: failed to request NAND CS gpio\n"); + return; + } + + gpio_direction_output(GPIO11_NAND_CS, 1); + + err = gpio_request(GPIO89_NAND_RB, "NAND R/B"); + if (err) { + pr_warn("CMX270: failed to request NAND R/B gpio\n"); + gpio_free(GPIO11_NAND_CS); + return; + } + + gpio_direction_input(GPIO89_NAND_RB); + + platform_device_register(&cmx270_nand); +} +#else +static inline void cmx270_init_nand(void) {} +#endif + #if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MODULE) static struct pxa2xx_spi_controller cm_x270_spi_info = { .num_chipselect = 1, @@ -413,6 +543,7 @@ void __init cmx270_init(void) cmx270_init_rtc(); cmx270_init_mmc(); + cmx270_init_nand(); cmx270_init_ohci(); cmx270_init_2700G(); cmx270_init_spi(); -- 2.25.3 ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/