special usb hub handling, IDE disks, and retries all over the place
[linux-2.4.git] / drivers / mtd / maps / integrator-flash.c
1 /*======================================================================
2
3     drivers/mtd/maps/armflash.c: ARM Flash Layout/Partitioning
4   
5     Copyright (C) 2000 ARM Limited
6   
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11   
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16   
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20   
21    This is access code for flashes using ARM's flash partitioning 
22    standards.
23
24    $Id: integrator-flash.c,v 1.7 2001/11/01 20:55:47 rmk Exp $
25
26 ======================================================================*/
27
28 #include <linux/config.h>
29 #include <linux/module.h>
30 #include <linux/types.h>
31 #include <linux/kernel.h>
32 #include <linux/slab.h>
33 #include <linux/ioport.h>
34 #include <linux/init.h>
35
36 #include <linux/mtd/mtd.h>
37 #include <linux/mtd/map.h>
38 #include <linux/mtd/partitions.h>
39
40 #include <asm/hardware.h>
41 #include <asm/io.h>
42 #include <asm/system.h>
43
44 extern int parse_afs_partitions(struct mtd_info *, struct mtd_partition **);
45
46 // board specific stuff - sorry, it should be in arch/arm/mach-*.
47 #ifdef CONFIG_ARCH_INTEGRATOR
48
49 #define FLASH_BASE      INTEGRATOR_FLASH_BASE
50 #define FLASH_SIZE      INTEGRATOR_FLASH_SIZE
51
52 #define FLASH_PART_SIZE 0x400000
53
54 #define SC_CTRLC        (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET)
55 #define SC_CTRLS        (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET)
56 #define EBI_CSR1        (IO_ADDRESS(INTEGRATOR_EBI_BASE) + INTEGRATOR_EBI_CSR1_OFFSET)
57 #define EBI_LOCK        (IO_ADDRESS(INTEGRATOR_EBI_BASE) + INTEGRATOR_EBI_LOCK_OFFSET)
58
59 /*
60  * Initialise the flash access systems:
61  *  - Disable VPP
62  *  - Assert WP
63  *  - Set write enable bit in EBI reg
64  */
65 static void armflash_flash_init(void)
66 {
67         unsigned int tmp;
68
69         __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
70
71         tmp = __raw_readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE;
72         __raw_writel(tmp, EBI_CSR1);
73
74         if (!(__raw_readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE)) {
75                 __raw_writel(0xa05f, EBI_LOCK);
76                 __raw_writel(tmp, EBI_CSR1);
77                 __raw_writel(0, EBI_LOCK);
78         }
79 }
80
81 /*
82  * Shutdown the flash access systems:
83  *  - Disable VPP
84  *  - Assert WP
85  *  - Clear write enable bit in EBI reg
86  */
87 static void armflash_flash_exit(void)
88 {
89         unsigned int tmp;
90
91         __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
92
93         /*
94          * Clear the write enable bit in system controller EBI register.
95          */
96         tmp = __raw_readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE;
97         __raw_writel(tmp, EBI_CSR1);
98
99         if (__raw_readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE) {
100                 __raw_writel(0xa05f, EBI_LOCK);
101                 __raw_writel(tmp, EBI_CSR1);
102                 __raw_writel(0, EBI_LOCK);
103         }
104 }
105
106 static void armflash_flash_wp(int on)
107 {
108         unsigned int reg;
109
110         if (on)
111                 reg = SC_CTRLC;
112         else
113                 reg = SC_CTRLS;
114
115         __raw_writel(INTEGRATOR_SC_CTRL_nFLWP, reg);
116 }
117
118 static void armflash_set_vpp(struct map_info *map, int on)
119 {
120         unsigned int reg;
121
122         if (on)
123                 reg = SC_CTRLS;
124         else
125                 reg = SC_CTRLC;
126
127         __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg);
128 }
129 #endif
130
131 #ifdef CONFIG_ARCH_P720T
132
133 #define FLASH_BASE              (0x04000000)
134 #define FLASH_SIZE              (64*1024*1024)
135
136 #define FLASH_PART_SIZE         (4*1024*1024)
137 #define FLASH_BLOCK_SIZE        (128*1024)
138
139 static void armflash_flash_init(void)
140 {
141 }
142
143 static void armflash_flash_exit(void)
144 {
145 }
146
147 static void armflash_flash_wp(int on)
148 {
149 }
150
151 static void armflash_set_vpp(struct map_info *map, int on)
152 {
153 }
154 #endif
155
156 static __u8 armflash_read8(struct map_info *map, unsigned long ofs)
157 {
158         return readb(ofs + map->map_priv_2);
159 }
160
161 static __u16 armflash_read16(struct map_info *map, unsigned long ofs)
162 {
163         return readw(ofs + map->map_priv_2);
164 }
165
166 static __u32 armflash_read32(struct map_info *map, unsigned long ofs)
167 {
168         return readl(ofs + map->map_priv_2);
169 }
170
171 static void armflash_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
172 {
173         memcpy(to, (void *) (from + map->map_priv_2), len);
174 }
175
176 static void armflash_write8(struct map_info *map, __u8 d, unsigned long adr)
177 {
178         writeb(d, adr + map->map_priv_2);
179 }
180
181 static void armflash_write16(struct map_info *map, __u16 d, unsigned long adr)
182 {
183         writew(d, adr + map->map_priv_2);
184 }
185
186 static void armflash_write32(struct map_info *map, __u32 d, unsigned long adr)
187 {
188         writel(d, adr + map->map_priv_2);
189 }
190
191 static void armflash_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
192 {
193         memcpy((void *) (to + map->map_priv_2), from, len);
194 }
195
196 static struct map_info armflash_map =
197 {
198         name:           "AFS",
199         read8:          armflash_read8,
200         read16:         armflash_read16,
201         read32:         armflash_read32,
202         copy_from:      armflash_copy_from,
203         write8:         armflash_write8,
204         write16:        armflash_write16,
205         write32:        armflash_write32,
206         copy_to:        armflash_copy_to,
207         set_vpp:        armflash_set_vpp,
208 };
209
210 static struct mtd_info *mtd;
211 static struct mtd_partition *parts;
212
213 static int __init armflash_cfi_init(void *base, u_int size)
214 {
215         int ret;
216
217         armflash_flash_init();
218         armflash_flash_wp(1);
219
220         /*
221          * look for CFI based flash parts fitted to this board
222          */
223         armflash_map.size       = size;
224         armflash_map.buswidth   = 4;
225         armflash_map.map_priv_2 = (unsigned long) base;
226
227         /*
228          * Also, the CFI layer automatically works out what size
229          * of chips we have, and does the necessary identification
230          * for us automatically.
231          */
232         mtd = do_map_probe("cfi_probe", &armflash_map);
233         if (!mtd)
234                 return -ENXIO;
235
236         mtd->module = THIS_MODULE;
237
238         ret = parse_afs_partitions(mtd, &parts);
239         if (ret > 0) {
240                 ret = add_mtd_partitions(mtd, parts, ret);
241                 if (ret)
242                         printk(KERN_ERR "mtd partition registration "
243                                 "failed: %d\n", ret);
244         }
245
246         /*
247          * If we got an error, free all resources.
248          */
249         if (ret < 0) {
250                 del_mtd_partitions(mtd);
251                 map_destroy(mtd);
252         }
253
254         return ret;
255 }
256
257 static void armflash_cfi_exit(void)
258 {
259         if (mtd) {
260                 del_mtd_partitions(mtd);
261                 map_destroy(mtd);
262         }
263         if (parts)
264                 kfree(parts);
265 }
266
267 static int __init armflash_init(void)
268 {
269         int err = -EBUSY;
270         void *base;
271
272         if (request_mem_region(FLASH_BASE, FLASH_SIZE, "flash") == NULL)
273                 goto out;
274
275         base = ioremap(FLASH_BASE, FLASH_SIZE);
276         err = -ENOMEM;
277         if (base == NULL)
278                 goto release;
279
280         err = armflash_cfi_init(base, FLASH_SIZE);
281         if (err) {
282                 iounmap(base);
283 release:
284                 release_mem_region(FLASH_BASE, FLASH_SIZE);
285         }
286 out:
287         return err;
288 }
289
290 static void __exit armflash_exit(void)
291 {
292         armflash_cfi_exit();
293         iounmap((void *)armflash_map.map_priv_2);
294         release_mem_region(FLASH_BASE, FLASH_SIZE);
295         armflash_flash_exit();
296 }
297
298 module_init(armflash_init);
299 module_exit(armflash_exit);
300
301 MODULE_AUTHOR("ARM Ltd");
302 MODULE_DESCRIPTION("ARM Integrator CFI map driver");
303 MODULE_LICENSE("GPL");