aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/lantiq/patches-3.9/0013-MTD-lantiq-Add-NAND-support-on-Lantiq-Falcon-SoC.patch
blob: ea6ce5b6a1e6798a8cb7251b8741e40ec148adcf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
From 6bfb122580ccf67b82abf6c5fe2ae1e770812f0d Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 30 Jan 2013 21:12:47 +0100
Subject: [PATCH 13/22] MTD: lantiq: Add NAND support on Lantiq Falcon SoC.

The driver uses plat_nand. As the platform_device is loaded from DT, we need
to lookup the node and attach our falcon specific "struct platform_nand_data"
to it.

Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
Signed-off-by: John Crispin <blogic@openwrt.org>
---
 drivers/mtd/nand/Kconfig       |    8 ++++
 drivers/mtd/nand/Makefile      |    1 +
 drivers/mtd/nand/falcon_nand.c |   83 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 92 insertions(+)
 create mode 100644 drivers/mtd/nand/falcon_nand.c

--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -574,4 +574,12 @@ config MTD_NAND_XWAY
 	  Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached
 	  to the External Bus Unit (EBU).
 
+config MTD_NAND_FALCON
+	tristate "Support for NAND on Lantiq FALC-ON SoC"
+	depends on LANTIQ && SOC_FALCON
+	select MTD_NAND_PLATFORM
+	help
+	  Enables support for NAND Flash chips on Lantiq FALC-ON SoCs. NAND is
+	  attached to the External Bus Unit (EBU).
+
 endif # MTD_NAND
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -53,5 +53,6 @@ obj-$(CONFIG_MTD_NAND_JZ4740)		+= jz4740
 obj-$(CONFIG_MTD_NAND_GPMI_NAND)	+= gpmi-nand/
 obj-$(CONFIG_MTD_NAND_XWAY)		+= xway_nand.o
 obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH)	+= bcm47xxnflash/
+obj-$(CONFIG_MTD_NAND_FALCON)		+= falcon_nand.o
 
 nand-objs := nand_base.o nand_bbt.o
--- /dev/null
+++ b/drivers/mtd/nand/falcon_nand.c
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com>
+ * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/mtd/nand.h>
+#include <linux/of_platform.h>
+
+#include <lantiq_soc.h>
+
+/* address lines used for NAND control signals */
+#define NAND_ADDR_ALE		0x10000
+#define NAND_ADDR_CLE		0x20000
+
+/* Ready/Busy Status */
+#define MODCON_STS		0x0002
+
+/* Ready/Busy Status Edge */
+#define MODCON_STSEDGE		0x0004
+#define LTQ_EBU_MODCON		0x000C
+
+static const char const *part_probes[] = { "cmdlinepart", "ofpart", NULL };
+
+static int falcon_nand_ready(struct mtd_info *mtd)
+{
+	u32 modcon = ltq_ebu_r32(LTQ_EBU_MODCON);
+
+	return (((modcon & (MODCON_STS | MODCON_STSEDGE)) ==
+						(MODCON_STS | MODCON_STSEDGE)));
+}
+
+static void falcon_hwcontrol(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_ADDR_ALE | NAND_ADDR_CLE);
+
+		if (ctrl & NAND_CLE)
+			nandaddr |= NAND_ADDR_CLE;
+		if (ctrl & NAND_ALE)
+			nandaddr |= NAND_ADDR_ALE;
+
+		this->IO_ADDR_W = (void __iomem *) nandaddr;
+	}
+
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, this->IO_ADDR_W);
+}
+
+static struct platform_nand_data falcon_nand_data = {
+	.chip = {
+		.nr_chips		= 1,
+		.chip_delay		= 25,
+		.part_probe_types	= part_probes,
+	},
+	.ctrl = {
+		.cmd_ctrl		= falcon_hwcontrol,
+		.dev_ready		= falcon_nand_ready,
+	}
+};
+
+int __init falcon_register_nand(void)
+{
+	struct device_node *node;
+	struct platform_device *pdev;
+
+	node = of_find_compatible_node(NULL, NULL, "lantiq,nand-falcon");
+	if (!node)
+		return -1;
+	pdev = of_find_device_by_node(node);
+	if (pdev)
+		pdev->dev.platform_data = &falcon_nand_data;
+	of_node_put(node);
+	return 0;
+}
+
+arch_initcall(falcon_register_nand);