| 1 | From 72112b91624dca6c636bd3a592471642d3988b27 Mon Sep 17 00:00:00 2001 |
| 2 | From: John Crispin <blogic@openwrt.org> |
| 3 | Date: Fri, 20 Jul 2012 19:09:01 +0200 |
| 4 | Subject: [PATCH 111/123] MTD: MIPS: lantiq: Add NAND support on Lantiq FALCON |
| 5 | SoC. |
| 6 | |
| 7 | The driver uses plat_nand. As the platform_device is loaded from DT, we need |
| 8 | to lookup the node and attach our falocn specific "struct platform_nand_data" |
| 9 | to it. |
| 10 | |
| 11 | Signed-off-by: John Crispin <blogic@openwrt.org> |
| 12 | Cc: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> |
| 13 | Cc: linux-mtd@lists.infradead.org |
| 14 | --- |
| 15 | drivers/mtd/nand/Kconfig | 8 ++++ |
| 16 | drivers/mtd/nand/Makefile | 1 + |
| 17 | drivers/mtd/nand/falcon_nand.c | 82 ++++++++++++++++++++++++++++++++++++++++ |
| 18 | 3 files changed, 91 insertions(+) |
| 19 | create mode 100644 drivers/mtd/nand/falcon_nand.c |
| 20 | |
| 21 | diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig |
| 22 | index 4883139..a3b05be 100644 |
| 23 | --- a/drivers/mtd/nand/Kconfig |
| 24 | +++ b/drivers/mtd/nand/Kconfig |
| 25 | @@ -572,4 +572,12 @@ config MTD_NAND_XWAY |
| 26 | Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached |
| 27 | to the External Bus Unit (EBU). |
| 28 | |
| 29 | +config MTD_NAND_FALCON |
| 30 | + tristate "Support for NAND on Lantiq FALC-ON SoC" |
| 31 | + depends on LANTIQ && SOC_FALCON |
| 32 | + select MTD_NAND_PLATFORM |
| 33 | + help |
| 34 | + Enables support for NAND Flash chips on Lantiq FALC-ON SoCs. NAND is |
| 35 | + attached to the External Bus Unit (EBU). |
| 36 | + |
| 37 | endif # MTD_NAND |
| 38 | diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile |
| 39 | index 2cbd091..a97e1b5 100644 |
| 40 | --- a/drivers/mtd/nand/Makefile |
| 41 | +++ b/drivers/mtd/nand/Makefile |
| 42 | @@ -53,5 +53,6 @@ obj-$(CONFIG_MTD_NAND_RICOH) += r852.o |
| 43 | obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o |
| 44 | obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/ |
| 45 | obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o |
| 46 | +obj-$(CONFIG_MTD_NAND_FALCON) += falcon_nand.o |
| 47 | |
| 48 | nand-objs := nand_base.o nand_bbt.o |
| 49 | diff --git a/drivers/mtd/nand/falcon_nand.c b/drivers/mtd/nand/falcon_nand.c |
| 50 | new file mode 100644 |
| 51 | index 0000000..b3b850c |
| 52 | --- /dev/null |
| 53 | +++ b/drivers/mtd/nand/falcon_nand.c |
| 54 | @@ -0,0 +1,82 @@ |
| 55 | +/* |
| 56 | + * This program is free software; you can redistribute it and/or modify it |
| 57 | + * under the terms of the GNU General Public License version 2 as published |
| 58 | + * by the Free Software Foundation. |
| 59 | + * |
| 60 | + * Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com> |
| 61 | + * Copyright (C) 2011 John Crispin <blogic@openwrt.org> |
| 62 | + */ |
| 63 | + |
| 64 | +#include <linux/mtd/nand.h> |
| 65 | +#include <linux/of_platform.h> |
| 66 | + |
| 67 | +#include <lantiq_soc.h> |
| 68 | + |
| 69 | +/* nand flash */ |
| 70 | +/* address lines used for NAND control signals */ |
| 71 | +#define NAND_ADDR_ALE 0x10000 |
| 72 | +#define NAND_ADDR_CLE 0x20000 |
| 73 | +/* Ready/Busy Status */ |
| 74 | +#define MODCON_STS 0x0002 |
| 75 | +/* Ready/Busy Status Edge */ |
| 76 | +#define MODCON_STSEDGE 0x0004 |
| 77 | +#define LTQ_EBU_MODCON 0x000C |
| 78 | + |
| 79 | +static const char *part_probes[] = { "cmdlinepart", "ofpart", NULL }; |
| 80 | + |
| 81 | +static int falcon_nand_ready(struct mtd_info *mtd) |
| 82 | +{ |
| 83 | + u32 modcon = ltq_ebu_r32(LTQ_EBU_MODCON); |
| 84 | + |
| 85 | + return (((modcon & (MODCON_STS | MODCON_STSEDGE)) == |
| 86 | + (MODCON_STS | MODCON_STSEDGE))); |
| 87 | +} |
| 88 | + |
| 89 | +static void falcon_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) |
| 90 | +{ |
| 91 | + struct nand_chip *this = mtd->priv; |
| 92 | + unsigned long nandaddr = (unsigned long) this->IO_ADDR_W; |
| 93 | + |
| 94 | + if (ctrl & NAND_CTRL_CHANGE) { |
| 95 | + nandaddr &= ~(NAND_ADDR_ALE | NAND_ADDR_CLE); |
| 96 | + |
| 97 | + if (ctrl & NAND_CLE) |
| 98 | + nandaddr |= NAND_ADDR_CLE; |
| 99 | + if (ctrl & NAND_ALE) |
| 100 | + nandaddr |= NAND_ADDR_ALE; |
| 101 | + |
| 102 | + this->IO_ADDR_W = (void __iomem *) nandaddr; |
| 103 | + } |
| 104 | + |
| 105 | + if (cmd != NAND_CMD_NONE) |
| 106 | + writeb(cmd, this->IO_ADDR_W); |
| 107 | +} |
| 108 | + |
| 109 | +static struct platform_nand_data falcon_nand_data = { |
| 110 | + .chip = { |
| 111 | + .nr_chips = 1, |
| 112 | + .chip_delay = 25, |
| 113 | + .part_probe_types = part_probes, |
| 114 | + }, |
| 115 | + .ctrl = { |
| 116 | + .cmd_ctrl = falcon_hwcontrol, |
| 117 | + .dev_ready = falcon_nand_ready, |
| 118 | + } |
| 119 | +}; |
| 120 | + |
| 121 | +static int __init falcon_register_nand(void) |
| 122 | +{ |
| 123 | + struct device_node *node; |
| 124 | + struct platform_device *pdev; |
| 125 | + |
| 126 | + node = of_find_compatible_node(NULL, NULL, "lantiq,nand-falcon"); |
| 127 | + if (!node) |
| 128 | + return -1; |
| 129 | + pdev = of_find_device_by_node(node); |
| 130 | + if (pdev) |
| 131 | + pdev->dev.platform_data = &falcon_nand_data; |
| 132 | + of_node_put(node); |
| 133 | + return 0; |
| 134 | +} |
| 135 | + |
| 136 | +arch_initcall(falcon_register_nand); |
| 137 | -- |
| 138 | 1.7.10.4 |
| 139 | |
| 140 | |