1 diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
2 index cfe288a..c528024 100644
3 --- a/drivers/mtd/nand/Kconfig
4 +++ b/drivers/mtd/nand/Kconfig
5 @@ -55,6 +55,12 @@ config MTD_NAND_TOTO
7 Support for NAND flash on Texas Instruments Toto platform.
10 + tristate "NAND Flash device on RB500 board"
13 + Support for NAND flash on RB500 platform.
18 diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
19 index 4174202..2be57c1 100644
20 --- a/drivers/mtd/nand/Makefile
21 +++ b/drivers/mtd/nand/Makefile
22 @@ -8,6 +8,7 @@ obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.
24 obj-$(CONFIG_MTD_NAND_SPIA) += spia.o
25 obj-$(CONFIG_MTD_NAND_TOTO) += toto.o
26 +obj-$(CONFIG_MTD_NAND_RB500) += rbmipsnand.o
27 obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o
28 obj-$(CONFIG_MTD_NAND_EDB7312) += edb7312.o
29 obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o
30 diff --git a/drivers/mtd/nand/rbmipsnand.c b/drivers/mtd/nand/rbmipsnand.c
32 index 0000000..6f7452a
34 +++ b/drivers/mtd/nand/rbmipsnand.c
36 +#include <linux/init.h>
37 +#include <linux/mtd/nand.h>
38 +#include <linux/mtd/mtd.h>
39 +#include <linux/mtd/partitions.h>
40 +#include <linux/delay.h>
43 +#include <asm/bootinfo.h>
44 +//#include <asm/rb/rb100.h>
46 +#define IDT434_REG_BASE ((volatile void *) KSEG1ADDR(0x18000000))
48 +#define SMEM1(x) (*((volatile unsigned char *) (KSEG1ADDR(SMEM1_BASE) + x)))
50 +#define GPIOF 0x050000
51 +#define GPIOC 0x050004
52 +#define GPIOD 0x050008
54 +#define GPIO_RDY (1 << 0x08)
55 +#define GPIO_WPX (1 << 0x09)
56 +#define GPIO_ALE (1 << 0x0a)
57 +#define GPIO_CLE (1 << 0x0b)
59 +#define NAND_RW_REG 0x0 //data register
60 +#define NAND_SET_CEn 0x1 //CE# low
61 +#define NAND_CLR_CEn 0x2 //CE# high
62 +#define NAND_CLR_CLE 0x3 //CLE low
63 +#define NAND_SET_CLE 0x4 //CLE high
64 +#define NAND_CLR_ALE 0x5 //ALE low
65 +#define NAND_SET_ALE 0x6 //ALE high
66 +#define NAND_SET_SPn 0x7 //SP# low (use spare area)
67 +#define NAND_CLR_SPn 0x8 //SP# high (do not use spare area)
68 +#define NAND_SET_WPn 0x9 //WP# low
69 +#define NAND_CLR_WPn 0xA //WP# high
70 +#define NAND_STS_REG 0xB //Status register
72 +#define DEV2BASE 0x010020
74 +#define LO_WPX (1 << 0)
75 +#define LO_ALE (1 << 1)
76 +#define LO_CLE (1 << 2)
77 +#define LO_CEX (1 << 3)
78 +#define LO_FOFF (1 << 5)
79 +#define LO_SPICS (1 << 6)
80 +#define LO_ULED (1 << 7)
82 +#define MEM32(x) *((volatile unsigned *) (x))
83 +static void __iomem *p_nand;
85 +extern void changeLatchU5(unsigned char orMask, unsigned char nandMask);
87 +static int rb500_dev_ready(struct mtd_info *mtd) {
88 + return MEM32(IDT434_REG_BASE + GPIOD) & GPIO_RDY;
91 +static int rb100_dev_ready(struct mtd_info *mtd) {
92 + return SMEM1(NAND_STS_REG) & 0x80;
95 +static unsigned long iflags = 0;
98 +static void rbmips_hwcontrol400(struct mtd_info *mtd, int cmd) {
100 + case NAND_CTL_SETCLE:
101 + MEM32(IDT434_REG_BASE + GPIOD) |= GPIO_CLE;
103 + case NAND_CTL_CLRCLE:
104 + MEM32(IDT434_REG_BASE + GPIOD) &= ~GPIO_CLE;
106 + case NAND_CTL_SETALE:
107 + MEM32(IDT434_REG_BASE + GPIOD) |= GPIO_ALE;
109 + case NAND_CTL_CLRALE:
110 + MEM32(IDT434_REG_BASE + GPIOD) &= ~GPIO_ALE;
117 +static void rbmips_hwcontrol500(struct mtd_info *mtd, int cmd) {
119 + case NAND_CTL_SETCLE:
120 + changeLatchU5(LO_CLE, 0);
122 + case NAND_CTL_CLRCLE:
123 + changeLatchU5(0, LO_CLE);
125 + case NAND_CTL_SETALE:
126 + changeLatchU5(LO_ALE, 0);
128 + case NAND_CTL_CLRALE:
129 + changeLatchU5(0, LO_ALE);
136 +static void rbmips_hwcontrol100(struct mtd_info *mtd, int cmd){
138 + case NAND_CTL_SETCLE:
139 + SMEM1(NAND_SET_CLE) = 0x01;
141 + case NAND_CTL_CLRCLE:
142 + SMEM1(NAND_CLR_CLE) = 0x01;
144 + case NAND_CTL_SETALE:
145 + SMEM1(NAND_SET_ALE) = 0x01;
147 + case NAND_CTL_CLRALE:
148 + SMEM1(NAND_CLR_ALE) = 0x01;
150 + case NAND_CTL_SETNCE:
151 + SMEM1(NAND_SET_CEn) = 0x01;
153 + case NAND_CTL_CLRNCE:
154 + SMEM1(NAND_CLR_CEn) = 0x01;
159 +static struct mtd_partition partition_info[] = {
161 + name: "RouterBoard NAND Boot",
163 + size: 4 * 1024 * 1024
166 + name: "RouterBoard NAND Main",
167 + offset: MTDPART_OFS_NXTBLK,
168 + size: MTDPART_SIZ_FULL
172 +static struct mtd_info rmtd;
173 +static struct nand_chip rnand;
175 +static unsigned init_ok = 0;
177 +unsigned get_rbnand_block_size(void) {
178 + if (init_ok) return rmtd.oobblock; else return 0;
181 +EXPORT_SYMBOL(get_rbnand_block_size);
183 +int __init rbmips_init(void) {
184 + memset(&rmtd, 0, sizeof(rmtd));
185 + memset(&rnand, 0, sizeof(rnand));
189 + printk("RB400 nand\n");
190 + MEM32(IDT434_REG_BASE + GPIOD) |= GPIO_WPX;
191 + MEM32(IDT434_REG_BASE + GPIOD) &= ~GPIO_CLE;
192 + MEM32(IDT434_REG_BASE + GPIOD) &= ~GPIO_ALE;
193 + rnand.hwcontrol = rbmips_hwcontrol400;
196 + printk("RB500 nand\n");
197 + changeLatchU5(LO_WPX | LO_FOFF | LO_CEX,
198 + LO_ULED | LO_ALE | LO_CLE);
199 + rnand.hwcontrol = rbmips_hwcontrol500;
202 + rnand.dev_ready = rb500_dev_ready;
203 + rnand.IO_ADDR_W = (unsigned char *)
204 + KSEG1ADDR(MEM32(IDT434_REG_BASE + DEV2BASE));
205 + rnand.IO_ADDR_R = rnand.IO_ADDR_W;
206 +/* } else if (is_rb100()) {
207 + printk("RB100 nand\n");
208 + MEM32(0xB2000064) = 0x100;
209 + MEM32(0xB2000008) = 0x1;
210 + SMEM1(NAND_SET_SPn) = 0x01;
211 + SMEM1(NAND_CLR_WPn) = 0x01;
212 + rnand.IO_ADDR_R = (unsigned char *)KSEG1ADDR(SMEM1_BASE);
213 + rnand.IO_ADDR_W = rnand.IO_ADDR_R;
214 + rnand.hwcontrol = rbmips_hwcontrol100;
215 + rnand.dev_ready = rb100_dev_ready;
218 + p_nand = (void __iomem *)ioremap(( void*)0x18a20000, 0x1000);
220 + printk("RBnand Unable ioremap buffer");
223 + rnand.eccmode = NAND_ECC_SOFT;
224 + rnand.chip_delay = 25;
225 + rnand.options |= NAND_NO_AUTOINCR;
226 + rmtd.priv = &rnand;
228 + int *b = ( int *)KSEG1ADDR( 0x18010020);
229 + printk( "dev2base 0x%08x mask 0x%08x c 0x%08x tc 0x%08x\n", b[ 0], b[ 1], b[ 2], b[ 3]);
231 + if (nand_scan(&rmtd, 1) && nand_scan(&rmtd, 1)
232 + && nand_scan(&rmtd, 1) && nand_scan(&rmtd, 1)) {
233 + printk("RBxxx nand device not found");
234 + iounmap ((void *)p_nand);
238 + add_mtd_partitions(&rmtd, partition_info, 2);
243 +module_init(rbmips_init);