File: /usr/src/linux/arch/cris/drivers/axisflashmap.c
1 /*
2 * Physical mapping layer for MTD using the Axis partitiontable format
3 *
4 * Copyright (c) 2001 Axis Communications AB
5 *
6 * This file is under the GPL.
7 *
8 * First partition is always sector 0 regardless of if we find a partitiontable
9 * or not. In the start of the next sector, there can be a partitiontable that
10 * tells us what other partitions to define. If there isn't, we use a default
11 * partition split defined below.
12 *
13 * $Log: axisflashmap.c,v $
14 * Revision 1.12 2001/06/11 09:50:30 jonashg
15 * Oops, 2MB is 0x200000 bytes.
16 *
17 * Revision 1.11 2001/06/08 11:39:44 jonashg
18 * Changed sizes and offsets in axis_default_partitions to use
19 * CONFIG_ETRAX_PTABLE_SECTOR.
20 *
21 * Revision 1.10 2001/05/29 09:42:03 jonashg
22 * Use macro for end marker length instead of sizeof.
23 *
24 * Revision 1.9 2001/05/29 08:52:52 jonashg
25 * Gave names to the magic fours (size of the ptable end marker).
26 *
27 * Revision 1.8 2001/05/28 15:36:20 jonashg
28 * * Removed old comment about ptable location in flash (it's a CONFIG_ option).
29 * * Variable ptable was initialized twice to the same value.
30 *
31 * Revision 1.7 2001/04/05 13:41:46 markusl
32 * Updated according to review remarks
33 *
34 * Revision 1.6 2001/03/07 09:21:21 bjornw
35 * No need to waste .data
36 *
37 * Revision 1.5 2001/03/06 16:27:01 jonashg
38 * Probe the entire flash area for flash devices.
39 *
40 * Revision 1.4 2001/02/23 12:47:15 bjornw
41 * Uncached flash in LOW_MAP moved from 0xe to 0x8
42 *
43 * Revision 1.3 2001/02/16 12:11:45 jonashg
44 * MTD driver amd_flash is now included in MTD CVS repository.
45 * (It's now in drivers/mtd).
46 *
47 * Revision 1.2 2001/02/09 11:12:22 jonashg
48 * Support for AMD compatible non-CFI flash chips.
49 * Only tested with Toshiba TC58FVT160 so far.
50 *
51 * Revision 1.1 2001/01/12 17:01:18 bjornw
52 * * Added axisflashmap.c, a physical mapping for MTD that reads and understands
53 * Axis partition-table format.
54 *
55 *
56 */
57
58 #include <linux/module.h>
59 #include <linux/types.h>
60 #include <linux/kernel.h>
61 #include <linux/config.h>
62
63 #include <linux/mtd/mtd.h>
64 #include <linux/mtd/map.h>
65 #include <linux/mtd/partitions.h>
66
67 #include <asm/axisflashmap.h>
68 #include <asm/mmu.h>
69
70 #ifdef CONFIG_CRIS_LOW_MAP
71 #define FLASH_UNCACHED_ADDR KSEG_8
72 #define FLASH_CACHED_ADDR KSEG_5
73 #else
74 #define FLASH_UNCACHED_ADDR KSEG_E
75 #define FLASH_CACHED_ADDR KSEG_F
76 #endif
77
78 /*
79 * WINDOW_SIZE is the total size where the flash chips may be mapped.
80 * MTD probes should find all devices there and it does not matter
81 * if there are unmapped gaps or aliases (mirrors of flash devices).
82 * The MTD probes will ignore them.
83 */
84
85 #define WINDOW_SIZE (128 * 1024 * 1024)
86
87 /*
88 * Map driver
89 *
90 * Ok this is the scoop - we need to access the flash both with and without
91 * the cache - without when doing all the fancy flash interfacing, and with
92 * when we do actual copying because otherwise it will be slow like molasses.
93 */
94
95 static __u8 flash_read8(struct map_info *map, unsigned long ofs)
96 {
97 return *(__u8 *)(FLASH_UNCACHED_ADDR + ofs);
98 }
99
100 static __u16 flash_read16(struct map_info *map, unsigned long ofs)
101 {
102 return *(__u16 *)(FLASH_UNCACHED_ADDR + ofs);
103 }
104
105 static __u32 flash_read32(struct map_info *map, unsigned long ofs)
106 {
107 return *(volatile unsigned int *)(FLASH_UNCACHED_ADDR + ofs);
108 }
109
110 static void flash_copy_from(struct map_info *map, void *to,
111 unsigned long from, ssize_t len)
112 {
113 memcpy(to, (void *)(FLASH_CACHED_ADDR + from), len);
114 }
115
116 static void flash_write8(struct map_info *map, __u8 d, unsigned long adr)
117 {
118 *(__u8 *)(FLASH_UNCACHED_ADDR + adr) = d;
119 }
120
121 static void flash_write16(struct map_info *map, __u16 d, unsigned long adr)
122 {
123 *(__u16 *)(FLASH_UNCACHED_ADDR + adr) = d;
124 }
125
126 static void flash_write32(struct map_info *map, __u32 d, unsigned long adr)
127 {
128 *(__u32 *)(FLASH_UNCACHED_ADDR + adr) = d;
129 }
130
131 static struct map_info axis_map = {
132 name: "Axis flash",
133 size: WINDOW_SIZE,
134 buswidth: CONFIG_ETRAX_FLASH_BUSWIDTH,
135 read8: flash_read8,
136 read16: flash_read16,
137 read32: flash_read32,
138 copy_from: flash_copy_from,
139 write8: flash_write8,
140 write16: flash_write16,
141 write32: flash_write32,
142 };
143
144 /* If no partition-table was found, we use this default-set.
145 */
146
147 #define MAX_PARTITIONS 7
148 #define NUM_DEFAULT_PARTITIONS 3
149
150 /* Default flash size is 2MB. CONFIG_ETRAX_PTABLE_SECTOR is most likely the
151 * size of one flash block and "filesystem"-partition needs 5 blocks to be able
152 * to use JFFS.
153 */
154 static struct mtd_partition axis_default_partitions[NUM_DEFAULT_PARTITIONS] = {
155 {
156 name: "boot firmware",
157 size: CONFIG_ETRAX_PTABLE_SECTOR,
158 offset: 0
159 },
160 {
161 name: "kernel",
162 size: 0x200000 - (6 * CONFIG_ETRAX_PTABLE_SECTOR),
163 offset: CONFIG_ETRAX_PTABLE_SECTOR
164 },
165 {
166 name: "filesystem",
167 size: 5 * CONFIG_ETRAX_PTABLE_SECTOR,
168 offset: 0x200000 - (5 * CONFIG_ETRAX_PTABLE_SECTOR)
169 }
170 };
171
172 static struct mtd_partition axis_partitions[MAX_PARTITIONS] = {
173 {
174 name: "part0",
175 size: 0,
176 offset: 0
177 },
178 {
179 name: "part1",
180 size: 0,
181 offset: 0
182 },
183 {
184 name: "part2",
185 size: 0,
186 offset: 0
187 },
188 {
189 name: "part3",
190 size: 0,
191 offset: 0
192 },
193 {
194 name: "part4",
195 size: 0,
196 offset: 0
197 },
198 {
199 name: "part5",
200 size: 0,
201 offset: 0
202 },
203 {
204 name: "part6",
205 size: 0,
206 offset: 0
207 },
208 };
209
210 /*
211 * This is the master MTD device for which all the others are just
212 * auto-relocating aliases.
213 */
214 static struct mtd_info *mymtd;
215
216 /* CFI-scan the flash, and if there was a chip, read the partition-table
217 * and register the partitions with MTD.
218 */
219
220 static int __init
221 init_axis_flash(void)
222 {
223 int pidx = 0;
224 struct partitiontable_head *ptable_head;
225 struct partitiontable_entry *ptable;
226 int use_default_ptable = 1; /* Until proven otherwise */
227 const char *pmsg = " /dev/flash%d at 0x%x, size 0x%x\n";
228
229 printk(KERN_NOTICE "Axis flash mapping: %x at %x\n",
230 WINDOW_SIZE, FLASH_CACHED_ADDR);
231
232 mymtd = (struct mtd_info *)do_cfi_probe(&axis_map);
233
234 #ifdef CONFIG_MTD_AMDSTD
235 if (!mymtd) {
236 mymtd = (struct mtd_info *)do_amd_flash_probe(&axis_map);
237 }
238 #endif
239
240 if(!mymtd) {
241 printk("%s: No flash chip found!\n", axis_map.name);
242 return -ENXIO;
243 }
244
245 mymtd->module = THIS_MODULE;
246
247 ptable_head = (struct partitiontable_head *)(FLASH_CACHED_ADDR +
248 CONFIG_ETRAX_PTABLE_SECTOR + PARTITION_TABLE_OFFSET);
249 pidx++; /* first partition is always set to the default */
250
251 if ((ptable_head->magic == PARTITION_TABLE_MAGIC)
252 && (ptable_head->size <
253 (MAX_PARTITIONS * sizeof(struct partitiontable_entry) +
254 PARTITIONTABLE_END_MARKER_SIZE))
255 && (*(unsigned long*)((void*)ptable_head + sizeof(*ptable_head) +
256 ptable_head->size -
257 PARTITIONTABLE_END_MARKER_SIZE)
258 == PARTITIONTABLE_END_MARKER)) {
259 /* Looks like a start, sane length and end of a
260 * partition table, lets check csum etc.
261 */
262 int ptable_ok = 0;
263 struct partitiontable_entry *max_addr =
264 (struct partitiontable_entry *)
265 ((unsigned long)ptable_head + sizeof(*ptable_head) +
266 ptable_head->size);
267 unsigned long offset = CONFIG_ETRAX_PTABLE_SECTOR;
268 unsigned char *p;
269 unsigned long csum = 0;
270
271 ptable = (struct partitiontable_entry *)
272 ((unsigned long)ptable_head + sizeof(*ptable_head));
273
274 /* Lets be PARANOID, and check the checksum. */
275 p = (unsigned char*) ptable;
276
277 while (p <= (unsigned char*)max_addr) {
278 csum += *p++;
279 csum += *p++;
280 csum += *p++;
281 csum += *p++;
282 }
283 /* printk(" total csum: 0x%08X 0x%08X\n",
284 csum, ptable_head->checksum); */
285 ptable_ok = (csum == ptable_head->checksum);
286
287 /* Read the entries and use/show the info. */
288 printk(" Found %s partition table at 0x%08lX-0x%08lX.\n",
289 (ptable_ok ? "valid" : "invalid"),
290 (unsigned long)ptable_head,
291 (unsigned long)max_addr);
292
293 /* We have found a working bootblock. Now read the
294 partition table. Scan the table. It ends when
295 there is 0xffffffff, that is, empty flash. */
296
297 while (ptable_ok
298 && ptable->offset != 0xffffffff
299 && ptable < max_addr
300 && pidx < MAX_PARTITIONS) {
301
302 axis_partitions[pidx].offset = offset + ptable->offset;
303 axis_partitions[pidx].size = ptable->size;
304
305 printk(pmsg, pidx, axis_partitions[pidx].offset,
306 axis_partitions[pidx].size);
307 pidx++;
308 ptable++;
309 }
310 use_default_ptable = !ptable_ok;
311 }
312
313 if(use_default_ptable) {
314 printk(" Using default partition table\n");
315 return add_mtd_partitions(mymtd, axis_default_partitions,
316 NUM_DEFAULT_PARTITIONS);
317 } else {
318 return add_mtd_partitions(mymtd, axis_partitions, pidx);
319 }
320 }
321
322 /* This adds the above to the kernels init-call chain */
323
324 module_init(init_axis_flash);
325
326