Add NAND flash/YAFFS2 patches for RB532 by David Goodenough
[openwrt.git] / target / linux / rb532-2.6 / patches / 500-Nand.patch
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
6         help
7           Support for NAND flash on Texas Instruments Toto platform.
8  
9 +config MTD_NAND_RB500
10 +       tristate "NAND Flash device on RB500 board"
11 +       depends on MTD_NAND
12 +       help
13 +         Support for NAND flash on RB500 platform.
14 +
15  config MTD_NAND_IDS
16         tristate
17  
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.
23  
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
31 new file mode 100644
32 index 0000000..6f7452a
33 --- /dev/null
34 +++ b/drivers/mtd/nand/rbmipsnand.c
35 @@ -0,0 +1,211 @@
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>
41 +#include <asm/io.h>
42 +#include <asm/irq.h>
43 +#include <asm/bootinfo.h>
44 +//#include <asm/rb/rb100.h>
45 +
46 +#define IDT434_REG_BASE ((volatile void *) KSEG1ADDR(0x18000000))
47 +
48 +#define SMEM1(x) (*((volatile unsigned char *) (KSEG1ADDR(SMEM1_BASE) + x)))
49 +
50 +#define GPIOF 0x050000
51 +#define GPIOC 0x050004
52 +#define GPIOD 0x050008
53 +
54 +#define GPIO_RDY (1 << 0x08)
55 +#define GPIO_WPX (1 << 0x09)
56 +#define GPIO_ALE (1 << 0x0a)
57 +#define GPIO_CLE (1 << 0x0b)
58 +
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
71 +
72 +#define DEV2BASE 0x010020
73 +
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)
81 +
82 +#define MEM32(x) *((volatile unsigned *) (x))
83 +static void __iomem *p_nand;
84 +
85 +extern void changeLatchU5(unsigned char orMask, unsigned char nandMask);
86 +
87 +static int rb500_dev_ready(struct mtd_info *mtd) {
88 +    return MEM32(IDT434_REG_BASE + GPIOD) & GPIO_RDY;
89 +}
90 +/*
91 +static int rb100_dev_ready(struct mtd_info *mtd) {
92 +    return SMEM1(NAND_STS_REG) & 0x80;
93 +}
94 +*/
95 +static unsigned long iflags = 0;
96 +static int ioff = 0;
97 +/*
98 +static void rbmips_hwcontrol400(struct mtd_info *mtd, int cmd) {
99 +    switch (cmd) {
100 +    case NAND_CTL_SETCLE:
101 +       MEM32(IDT434_REG_BASE + GPIOD) |= GPIO_CLE;
102 +        break;
103 +    case NAND_CTL_CLRCLE:
104 +       MEM32(IDT434_REG_BASE + GPIOD) &= ~GPIO_CLE;
105 +        break;
106 +    case NAND_CTL_SETALE:
107 +       MEM32(IDT434_REG_BASE + GPIOD) |= GPIO_ALE;
108 +        break;
109 +    case NAND_CTL_CLRALE:
110 +       MEM32(IDT434_REG_BASE + GPIOD) &= ~GPIO_ALE;
111 +        break;
112 +    default:
113 +       break;
114 +    }
115 +}
116 +*/
117 +static void rbmips_hwcontrol500(struct mtd_info *mtd, int cmd) {
118 +    switch (cmd) {
119 +    case NAND_CTL_SETCLE:
120 +       changeLatchU5(LO_CLE, 0);
121 +        break;
122 +    case NAND_CTL_CLRCLE:
123 +       changeLatchU5(0, LO_CLE);
124 +        break;
125 +    case NAND_CTL_SETALE:
126 +       changeLatchU5(LO_ALE, 0);
127 +        break;
128 +    case NAND_CTL_CLRALE:
129 +       changeLatchU5(0, LO_ALE);
130 +        break;
131 +    default:
132 +        break;
133 +    }
134 +}
135 +/*
136 +static void rbmips_hwcontrol100(struct mtd_info *mtd, int cmd){
137 +    switch(cmd){
138 +    case NAND_CTL_SETCLE: 
139 +       SMEM1(NAND_SET_CLE) = 0x01; 
140 +       break;
141 +    case NAND_CTL_CLRCLE: 
142 +       SMEM1(NAND_CLR_CLE) = 0x01; 
143 +       break;
144 +    case NAND_CTL_SETALE: 
145 +       SMEM1(NAND_SET_ALE) = 0x01; 
146 +       break;
147 +    case NAND_CTL_CLRALE: 
148 +       SMEM1(NAND_CLR_ALE) = 0x01; 
149 +       break;
150 +    case NAND_CTL_SETNCE: 
151 +       SMEM1(NAND_SET_CEn) = 0x01; 
152 +       break;
153 +    case NAND_CTL_CLRNCE: 
154 +       SMEM1(NAND_CLR_CEn) = 0x01; 
155 +       break;
156 +    }
157 +}
158 +*/
159 +static struct mtd_partition partition_info[] = {
160 +    {
161 +        name: "RouterBoard NAND Boot",
162 +        offset: 0,
163 +       size: 4 * 1024 * 1024
164 +    },
165 +    {
166 +        name: "RouterBoard NAND Main",
167 +       offset: MTDPART_OFS_NXTBLK,
168 +       size: MTDPART_SIZ_FULL
169 +    }
170 +};
171 +
172 +static struct mtd_info rmtd;
173 +static struct nand_chip rnand;
174 +
175 +static unsigned init_ok = 0;
176 +
177 +unsigned get_rbnand_block_size(void) {
178 +       if (init_ok) return rmtd.oobblock; else return 0;
179 +}
180 +
181 +EXPORT_SYMBOL(get_rbnand_block_size);
182 +
183 +int __init rbmips_init(void) {
184 +       memset(&rmtd, 0, sizeof(rmtd));
185 +       memset(&rnand, 0, sizeof(rnand));
186 +/*
187 +       if (is_rb500()) {
188 +               if (is_rb400()) {
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;
194 +               } else {
195 +*/             
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;
200 +//             }
201 +    
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;
216 +       }
217 +*/
218 +       p_nand = (void __iomem *)ioremap(( void*)0x18a20000, 0x1000);
219 +       if (!p_nand) {
220 +               printk("RBnand Unable ioremap buffer");
221 +               return -ENXIO;
222 +       }
223 +       rnand.eccmode = NAND_ECC_SOFT;
224 +       rnand.chip_delay = 25;
225 +       rnand.options |= NAND_NO_AUTOINCR;
226 +       rmtd.priv = &rnand;
227 +
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]);
230 +
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);
235 +               return -ENXIO;
236 +       }
237 +
238 +       add_mtd_partitions(&rmtd, partition_info, 2);
239 +       init_ok = 1;
240 +       return 0;
241 +}
242 +
243 +module_init(rbmips_init);
244 +
245 +
246 +
247 +
248 +