Loading drivers/mtd/nand/Kconfig +0 −1 Original line number Original line Diff line number Diff line Loading @@ -539,7 +539,6 @@ config MTD_NAND_FSMC config MTD_NAND_XWAY config MTD_NAND_XWAY tristate "Support for NAND on Lantiq XWAY SoC" tristate "Support for NAND on Lantiq XWAY SoC" depends on LANTIQ && SOC_TYPE_XWAY depends on LANTIQ && SOC_TYPE_XWAY select MTD_NAND_PLATFORM help help Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached to the External Bus Unit (EBU). to the External Bus Unit (EBU). Loading drivers/mtd/nand/xway_nand.c +80 −36 Original line number Original line Diff line number Diff line Loading @@ -4,6 +4,7 @@ * by the Free Software Foundation. * by the Free Software Foundation. * * * Copyright © 2012 John Crispin <blogic@openwrt.org> * Copyright © 2012 John Crispin <blogic@openwrt.org> * Copyright © 2016 Hauke Mehrtens <hauke@hauke-m.de> */ */ #include <linux/mtd/nand.h> #include <linux/mtd/nand.h> Loading Loading @@ -63,6 +64,10 @@ #define NAND_CON_CSMUX (1 << 1) #define NAND_CON_CSMUX (1 << 1) #define NAND_CON_NANDM 1 #define NAND_CON_NANDM 1 struct xway_nand_data { struct nand_chip chip; }; static void xway_reset_chip(struct nand_chip *chip) static void xway_reset_chip(struct nand_chip *chip) { { unsigned long nandaddr = (unsigned long) chip->IO_ADDR_W; unsigned long nandaddr = (unsigned long) chip->IO_ADDR_W; Loading Loading @@ -139,16 +144,51 @@ static unsigned char xway_read_byte(struct mtd_info *mtd) return ret; return ret; } } /* * Probe for the NAND device. */ static int xway_nand_probe(struct platform_device *pdev) static int xway_nand_probe(struct platform_device *pdev) { { struct nand_chip *this = platform_get_drvdata(pdev); struct xway_nand_data *data; unsigned long nandaddr = (unsigned long) this->IO_ADDR_W; struct mtd_info *mtd; const __be32 *cs = of_get_property(pdev->dev.of_node, struct resource *res; "lantiq,cs", NULL); int err; void __iomem *nandaddr; u32 cs; u32 cs_flag = 0; u32 cs_flag = 0; /* Allocate memory for the device structure (and zero it) */ data = devm_kzalloc(&pdev->dev, sizeof(struct xway_nand_data), GFP_KERNEL); if (!data) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); nandaddr = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(nandaddr)) return PTR_ERR(nandaddr); nand_set_flash_node(&data->chip, pdev->dev.of_node); mtd = nand_to_mtd(&data->chip); mtd->dev.parent = &pdev->dev; data->chip.IO_ADDR_R = nandaddr; data->chip.IO_ADDR_W = nandaddr; data->chip.cmd_ctrl = xway_cmd_ctrl; data->chip.dev_ready = xway_dev_ready; data->chip.select_chip = xway_select_chip; data->chip.read_byte = xway_read_byte; data->chip.chip_delay = 30; data->chip.ecc.mode = NAND_ECC_SOFT; data->chip.ecc.algo = NAND_ECC_HAMMING; platform_set_drvdata(pdev, data); nand_set_controller_data(&data->chip, data); /* load our CS from the DT. Either we find a valid 1 or default to 0 */ /* load our CS from the DT. Either we find a valid 1 or default to 0 */ if (cs && (*cs == 1)) err = of_property_read_u32(pdev->dev.of_node, "lantiq,cs", &cs); if (!err && cs == 1) cs_flag = NAND_CON_IN_CS1 | NAND_CON_OUT_CS1; cs_flag = NAND_CON_IN_CS1 | NAND_CON_OUT_CS1; /* setup the EBU to run in NAND mode on our base addr */ /* setup the EBU to run in NAND mode on our base addr */ Loading @@ -164,43 +204,47 @@ static int xway_nand_probe(struct platform_device *pdev) | cs_flag, EBU_NAND_CON); | cs_flag, EBU_NAND_CON); /* finish with a reset */ /* finish with a reset */ xway_reset_chip(this); xway_reset_chip(&data->chip); return 0; /* Scan to find existence of the device */ } err = nand_scan(mtd, 1); if (err) return err; static struct platform_nand_data xway_nand_data = { err = mtd_device_register(mtd, NULL, 0); .chip = { if (err) .nr_chips = 1, nand_release(mtd); .chip_delay = 30, }, return err; .ctrl = { .probe = xway_nand_probe, .cmd_ctrl = xway_cmd_ctrl, .dev_ready = xway_dev_ready, .select_chip = xway_select_chip, .read_byte = xway_read_byte, } } }; /* /* * Try to find the node inside the DT. If it is available attach out * Remove a NAND device. * platform_nand_data */ */ static int __init xway_register_nand(void) static int xway_nand_remove(struct platform_device *pdev) { { struct device_node *node; struct xway_nand_data *data = platform_get_drvdata(pdev); struct platform_device *pdev; nand_release(nand_to_mtd(&data->chip)); node = of_find_compatible_node(NULL, NULL, "lantiq,nand-xway"); if (!node) return -ENOENT; pdev = of_find_device_by_node(node); if (!pdev) return -EINVAL; pdev->dev.platform_data = &xway_nand_data; of_node_put(node); return 0; return 0; } } subsys_initcall(xway_register_nand); static const struct of_device_id xway_nand_match[] = { { .compatible = "lantiq,nand-xway" }, {}, }; MODULE_DEVICE_TABLE(of, xway_nand_match); static struct platform_driver xway_nand_driver = { .probe = xway_nand_probe, .remove = xway_nand_remove, .driver = { .name = "lantiq,nand-xway", .of_match_table = xway_nand_match, }, }; module_platform_driver(xway_nand_driver); MODULE_LICENSE("GPL"); Loading
drivers/mtd/nand/Kconfig +0 −1 Original line number Original line Diff line number Diff line Loading @@ -539,7 +539,6 @@ config MTD_NAND_FSMC config MTD_NAND_XWAY config MTD_NAND_XWAY tristate "Support for NAND on Lantiq XWAY SoC" tristate "Support for NAND on Lantiq XWAY SoC" depends on LANTIQ && SOC_TYPE_XWAY depends on LANTIQ && SOC_TYPE_XWAY select MTD_NAND_PLATFORM help help Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached to the External Bus Unit (EBU). to the External Bus Unit (EBU). Loading
drivers/mtd/nand/xway_nand.c +80 −36 Original line number Original line Diff line number Diff line Loading @@ -4,6 +4,7 @@ * by the Free Software Foundation. * by the Free Software Foundation. * * * Copyright © 2012 John Crispin <blogic@openwrt.org> * Copyright © 2012 John Crispin <blogic@openwrt.org> * Copyright © 2016 Hauke Mehrtens <hauke@hauke-m.de> */ */ #include <linux/mtd/nand.h> #include <linux/mtd/nand.h> Loading Loading @@ -63,6 +64,10 @@ #define NAND_CON_CSMUX (1 << 1) #define NAND_CON_CSMUX (1 << 1) #define NAND_CON_NANDM 1 #define NAND_CON_NANDM 1 struct xway_nand_data { struct nand_chip chip; }; static void xway_reset_chip(struct nand_chip *chip) static void xway_reset_chip(struct nand_chip *chip) { { unsigned long nandaddr = (unsigned long) chip->IO_ADDR_W; unsigned long nandaddr = (unsigned long) chip->IO_ADDR_W; Loading Loading @@ -139,16 +144,51 @@ static unsigned char xway_read_byte(struct mtd_info *mtd) return ret; return ret; } } /* * Probe for the NAND device. */ static int xway_nand_probe(struct platform_device *pdev) static int xway_nand_probe(struct platform_device *pdev) { { struct nand_chip *this = platform_get_drvdata(pdev); struct xway_nand_data *data; unsigned long nandaddr = (unsigned long) this->IO_ADDR_W; struct mtd_info *mtd; const __be32 *cs = of_get_property(pdev->dev.of_node, struct resource *res; "lantiq,cs", NULL); int err; void __iomem *nandaddr; u32 cs; u32 cs_flag = 0; u32 cs_flag = 0; /* Allocate memory for the device structure (and zero it) */ data = devm_kzalloc(&pdev->dev, sizeof(struct xway_nand_data), GFP_KERNEL); if (!data) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); nandaddr = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(nandaddr)) return PTR_ERR(nandaddr); nand_set_flash_node(&data->chip, pdev->dev.of_node); mtd = nand_to_mtd(&data->chip); mtd->dev.parent = &pdev->dev; data->chip.IO_ADDR_R = nandaddr; data->chip.IO_ADDR_W = nandaddr; data->chip.cmd_ctrl = xway_cmd_ctrl; data->chip.dev_ready = xway_dev_ready; data->chip.select_chip = xway_select_chip; data->chip.read_byte = xway_read_byte; data->chip.chip_delay = 30; data->chip.ecc.mode = NAND_ECC_SOFT; data->chip.ecc.algo = NAND_ECC_HAMMING; platform_set_drvdata(pdev, data); nand_set_controller_data(&data->chip, data); /* load our CS from the DT. Either we find a valid 1 or default to 0 */ /* load our CS from the DT. Either we find a valid 1 or default to 0 */ if (cs && (*cs == 1)) err = of_property_read_u32(pdev->dev.of_node, "lantiq,cs", &cs); if (!err && cs == 1) cs_flag = NAND_CON_IN_CS1 | NAND_CON_OUT_CS1; cs_flag = NAND_CON_IN_CS1 | NAND_CON_OUT_CS1; /* setup the EBU to run in NAND mode on our base addr */ /* setup the EBU to run in NAND mode on our base addr */ Loading @@ -164,43 +204,47 @@ static int xway_nand_probe(struct platform_device *pdev) | cs_flag, EBU_NAND_CON); | cs_flag, EBU_NAND_CON); /* finish with a reset */ /* finish with a reset */ xway_reset_chip(this); xway_reset_chip(&data->chip); return 0; /* Scan to find existence of the device */ } err = nand_scan(mtd, 1); if (err) return err; static struct platform_nand_data xway_nand_data = { err = mtd_device_register(mtd, NULL, 0); .chip = { if (err) .nr_chips = 1, nand_release(mtd); .chip_delay = 30, }, return err; .ctrl = { .probe = xway_nand_probe, .cmd_ctrl = xway_cmd_ctrl, .dev_ready = xway_dev_ready, .select_chip = xway_select_chip, .read_byte = xway_read_byte, } } }; /* /* * Try to find the node inside the DT. If it is available attach out * Remove a NAND device. * platform_nand_data */ */ static int __init xway_register_nand(void) static int xway_nand_remove(struct platform_device *pdev) { { struct device_node *node; struct xway_nand_data *data = platform_get_drvdata(pdev); struct platform_device *pdev; nand_release(nand_to_mtd(&data->chip)); node = of_find_compatible_node(NULL, NULL, "lantiq,nand-xway"); if (!node) return -ENOENT; pdev = of_find_device_by_node(node); if (!pdev) return -EINVAL; pdev->dev.platform_data = &xway_nand_data; of_node_put(node); return 0; return 0; } } subsys_initcall(xway_register_nand); static const struct of_device_id xway_nand_match[] = { { .compatible = "lantiq,nand-xway" }, {}, }; MODULE_DEVICE_TABLE(of, xway_nand_match); static struct platform_driver xway_nand_driver = { .probe = xway_nand_probe, .remove = xway_nand_remove, .driver = { .name = "lantiq,nand-xway", .of_match_table = xway_nand_match, }, }; module_platform_driver(xway_nand_driver); MODULE_LICENSE("GPL");