From 716ca530e1c4515d8683c9d5be3d56b301758b66 Mon Sep 17 00:00:00 2001 From: James <> Date: Wed, 4 Nov 2015 11:49:21 +0000 Subject: trunk-47381 --- .../oxnas/files/drivers/mtd/nand/oxnas_nand.c | 102 +++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 target/linux/oxnas/files/drivers/mtd/nand/oxnas_nand.c (limited to 'target/linux/oxnas/files/drivers/mtd/nand/oxnas_nand.c') diff --git a/target/linux/oxnas/files/drivers/mtd/nand/oxnas_nand.c b/target/linux/oxnas/files/drivers/mtd/nand/oxnas_nand.c new file mode 100644 index 0000000..55eb009 --- /dev/null +++ b/target/linux/oxnas/files/drivers/mtd/nand/oxnas_nand.c @@ -0,0 +1,102 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* nand commands */ +#define NAND_CMD_ALE BIT(18) +#define NAND_CMD_CLE BIT(19) +#define NAND_CMD_CS 0 +#define NAND_CMD_RESET 0xff +#define NAND_CMD (NAND_CMD_CS | NAND_CMD_CLE) +#define NAND_ADDR (NAND_CMD_CS | NAND_CMD_ALE) +#define NAND_DATA (NAND_CMD_CS) + +static void oxnas_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct nand_chip *this = mtd->priv; + unsigned long nandaddr = (unsigned long) this->IO_ADDR_W; + + if (ctrl & NAND_CTRL_CHANGE) { + nandaddr &= ~(NAND_CMD | NAND_ADDR); + if (ctrl & NAND_CLE) + nandaddr |= NAND_CMD; + else if (ctrl & NAND_ALE) + nandaddr |= NAND_ADDR; + this->IO_ADDR_W = (void __iomem *) nandaddr; + } + + if (cmd != NAND_CMD_NONE) + writeb(cmd, (void __iomem *) nandaddr); +} + +static int oxnas_nand_probe(struct platform_device *pdev) +{ + /* enable clock and release static block reset */ + struct clk *clk = of_clk_get(pdev->dev.of_node, 0); + + if (IS_ERR(clk)) + return PTR_ERR(clk); + + clk_prepare_enable(clk); + device_reset(&pdev->dev); + + return 0; +} + +/* allow users to override the partition in DT using the cmdline */ +static const char * part_probes[] = { "cmdlinepart", "ofpart", NULL }; + +static struct platform_nand_data oxnas_nand_data = { + .chip = { + .nr_chips = 1, + .chip_delay = 30, + .part_probe_types = part_probes, + }, + .ctrl = { + .probe = oxnas_nand_probe, + .cmd_ctrl = oxnas_cmd_ctrl, + } +}; + +/* + * Try to find the node inside the DT. If it is available attach out + * platform_nand_data + */ +static int __init oxnas_register_nand(void) +{ + struct device_node *node; + struct platform_device *pdev; + + node = of_find_compatible_node(NULL, NULL, "plxtech,nand-nas782x"); + if (!node) + return -ENOENT; + pdev = of_find_device_by_node(node); + if (!pdev) + return -EINVAL; + pdev->dev.platform_data = &oxnas_nand_data; + of_node_put(node); + return 0; +} + +subsys_initcall(oxnas_register_nand); + +static const struct of_device_id oxnas_nand_ids[] = { + { .compatible = "plxtech,nand-nas782x"}, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, oxnas_nand_ids); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ma Haijun"); +MODULE_DESCRIPTION("NAND glue for Oxnas platforms"); +MODULE_ALIAS("platform:oxnas_nand"); -- cgit v1.2.3