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
129
130
131
132
133
134
135
136
137
138#include <linux/module.h>
139#include <linux/types.h>
140#include <linux/kernel.h>
141#include <linux/init.h>
142#include <linux/slab.h>
143
144#include <linux/mtd/concat.h>
145#include <linux/mtd/map.h>
146#include <linux/mtd/mtd.h>
147#include <linux/mtd/mtdram.h>
148#include <linux/mtd/partitions.h>
149
150#include <asm/axisflashmap.h>
151#include <asm/mmu.h>
152#include <asm/arch/sv_addr_ag.h>
153
154#ifdef CONFIG_CRIS_LOW_MAP
155#define FLASH_UNCACHED_ADDR KSEG_8
156#define FLASH_CACHED_ADDR KSEG_5
157#else
158#define FLASH_UNCACHED_ADDR KSEG_E
159#define FLASH_CACHED_ADDR KSEG_F
160#endif
161
162#if CONFIG_ETRAX_FLASH_BUSWIDTH==1
163#define flash_data __u8
164#elif CONFIG_ETRAX_FLASH_BUSWIDTH==2
165#define flash_data __u16
166#elif CONFIG_ETRAX_FLASH_BUSWIDTH==4
167#define flash_data __u32
168#endif
169
170
171extern unsigned long romfs_start, romfs_length, romfs_in_flash;
172
173
174struct mtd_info* axisflash_mtd = NULL;
175
176
177
178static map_word flash_read(struct map_info *map, unsigned long ofs)
179{
180 map_word tmp;
181 tmp.x[0] = *(flash_data *)(map->map_priv_1 + ofs);
182 return tmp;
183}
184
185static void flash_copy_from(struct map_info *map, void *to,
186 unsigned long from, ssize_t len)
187{
188 memcpy(to, (void *)(map->map_priv_1 + from), len);
189}
190
191static void flash_write(struct map_info *map, map_word d, unsigned long adr)
192{
193 *(flash_data *)(map->map_priv_1 + adr) = (flash_data)d.x[0];
194}
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211static struct map_info map_cse0 = {
212 .name = "cse0",
213 .size = MEM_CSE0_SIZE,
214 .bankwidth = CONFIG_ETRAX_FLASH_BUSWIDTH,
215 .read = flash_read,
216 .copy_from = flash_copy_from,
217 .write = flash_write,
218 .map_priv_1 = FLASH_UNCACHED_ADDR
219};
220
221
222
223
224
225
226
227static struct map_info map_cse1 = {
228 .name = "cse1",
229 .size = MEM_CSE1_SIZE,
230 .bankwidth = CONFIG_ETRAX_FLASH_BUSWIDTH,
231 .read = flash_read,
232 .copy_from = flash_copy_from,
233 .write = flash_write,
234 .map_priv_1 = FLASH_UNCACHED_ADDR + MEM_CSE0_SIZE
235};
236
237
238#define MAX_PARTITIONS 7
239#define NUM_DEFAULT_PARTITIONS 3
240
241
242
243
244
245
246static struct mtd_partition axis_default_partitions[NUM_DEFAULT_PARTITIONS] = {
247 {
248 .name = "boot firmware",
249 .size = CONFIG_ETRAX_PTABLE_SECTOR,
250 .offset = 0
251 },
252 {
253 .name = "kernel",
254 .size = 0x200000 - (6 * CONFIG_ETRAX_PTABLE_SECTOR),
255 .offset = CONFIG_ETRAX_PTABLE_SECTOR
256 },
257 {
258 .name = "filesystem",
259 .size = 5 * CONFIG_ETRAX_PTABLE_SECTOR,
260 .offset = 0x200000 - (5 * CONFIG_ETRAX_PTABLE_SECTOR)
261 }
262};
263
264
265static struct mtd_partition axis_partitions[MAX_PARTITIONS] = {
266 {
267 .name = "part0",
268 .size = CONFIG_ETRAX_PTABLE_SECTOR,
269 .offset = 0
270 },
271 {
272 .name = "part1",
273 .size = 0,
274 .offset = 0
275 },
276 {
277 .name = "part2",
278 .size = 0,
279 .offset = 0
280 },
281 {
282 .name = "part3",
283 .size = 0,
284 .offset = 0
285 },
286 {
287 .name = "part4",
288 .size = 0,
289 .offset = 0
290 },
291 {
292 .name = "part5",
293 .size = 0,
294 .offset = 0
295 },
296 {
297 .name = "part6",
298 .size = 0,
299 .offset = 0
300 },
301};
302
303
304
305
306
307static struct mtd_info *probe_cs(struct map_info *map_cs)
308{
309 struct mtd_info *mtd_cs = NULL;
310
311 printk(KERN_INFO
312 "%s: Probing a 0x%08lx bytes large window at 0x%08lx.\n",
313 map_cs->name, map_cs->size, map_cs->map_priv_1);
314
315#ifdef CONFIG_MTD_CFI
316 mtd_cs = do_map_probe("cfi_probe", map_cs);
317#endif
318#ifdef CONFIG_MTD_JEDECPROBE
319 if (!mtd_cs) {
320 mtd_cs = do_map_probe("jedec_probe", map_cs);
321 }
322#endif
323
324 return mtd_cs;
325}
326
327
328
329
330
331
332
333
334
335
336
337static struct mtd_info *flash_probe(void)
338{
339 struct mtd_info *mtd_cse0;
340 struct mtd_info *mtd_cse1;
341 struct mtd_info *mtd_cse;
342
343 mtd_cse0 = probe_cs(&map_cse0);
344 mtd_cse1 = probe_cs(&map_cse1);
345
346 if (!mtd_cse0 && !mtd_cse1) {
347
348 return NULL;
349 }
350
351 if (mtd_cse0 && mtd_cse1) {
352#ifdef CONFIG_MTD_CONCAT
353 struct mtd_info *mtds[] = { mtd_cse0, mtd_cse1 };
354
355
356
357
358
359
360
361
362 mtd_cse = mtd_concat_create(mtds, ARRAY_SIZE(mtds),
363 "cse0+cse1");
364#else
365 printk(KERN_ERR "%s and %s: Cannot concatenate due to kernel "
366 "(mis)configuration!\n", map_cse0.name, map_cse1.name);
367 mtd_cse = NULL;
368#endif
369 if (!mtd_cse) {
370 printk(KERN_ERR "%s and %s: Concatenation failed!\n",
371 map_cse0.name, map_cse1.name);
372
373
374
375
376 mtd_cse = mtd_cse0;
377 map_destroy(mtd_cse1);
378 }
379 } else {
380 mtd_cse = mtd_cse0? mtd_cse0 : mtd_cse1;
381 }
382
383 return mtd_cse;
384}
385
386
387
388
389
390static int __init init_axis_flash(void)
391{
392 struct mtd_info *mymtd;
393 int err = 0;
394 int pidx = 0;
395 struct partitiontable_head *ptable_head = NULL;
396 struct partitiontable_entry *ptable;
397 int use_default_ptable = 1;
398 const char *pmsg = " /dev/flash%d at 0x%08x, size 0x%08x\n";
399
400 if (!(mymtd = flash_probe())) {
401
402
403
404 printk(KERN_INFO "axisflashmap: Found no flash chip.\n");
405 } else {
406 printk(KERN_INFO "%s: 0x%08x bytes of flash memory.\n",
407 mymtd->name, mymtd->size);
408 axisflash_mtd = mymtd;
409 }
410
411 if (mymtd) {
412 mymtd->owner = THIS_MODULE;
413 ptable_head = (struct partitiontable_head *)(FLASH_CACHED_ADDR +
414 CONFIG_ETRAX_PTABLE_SECTOR +
415 PARTITION_TABLE_OFFSET);
416 }
417 pidx++;
418
419 if (ptable_head && (ptable_head->magic == PARTITION_TABLE_MAGIC)
420 && (ptable_head->size <
421 (MAX_PARTITIONS * sizeof(struct partitiontable_entry) +
422 PARTITIONTABLE_END_MARKER_SIZE))
423 && (*(unsigned long*)((void*)ptable_head + sizeof(*ptable_head) +
424 ptable_head->size -
425 PARTITIONTABLE_END_MARKER_SIZE)
426 == PARTITIONTABLE_END_MARKER)) {
427
428
429
430 int ptable_ok = 0;
431 struct partitiontable_entry *max_addr =
432 (struct partitiontable_entry *)
433 ((unsigned long)ptable_head + sizeof(*ptable_head) +
434 ptable_head->size);
435 unsigned long offset = CONFIG_ETRAX_PTABLE_SECTOR;
436 unsigned char *p;
437 unsigned long csum = 0;
438
439 ptable = (struct partitiontable_entry *)
440 ((unsigned long)ptable_head + sizeof(*ptable_head));
441
442
443 p = (unsigned char*) ptable;
444
445 while (p <= (unsigned char*)max_addr) {
446 csum += *p++;
447 csum += *p++;
448 csum += *p++;
449 csum += *p++;
450 }
451 ptable_ok = (csum == ptable_head->checksum);
452
453
454 printk(KERN_INFO " Found a%s partition table at 0x%p-0x%p.\n",
455 (ptable_ok ? " valid" : "n invalid"), ptable_head,
456 max_addr);
457
458
459
460
461
462 while (ptable_ok
463 && ptable->offset != 0xffffffff
464 && ptable < max_addr
465 && pidx < MAX_PARTITIONS) {
466
467 axis_partitions[pidx].offset = offset + ptable->offset;
468 axis_partitions[pidx].size = ptable->size;
469
470 printk(pmsg, pidx, axis_partitions[pidx].offset,
471 axis_partitions[pidx].size);
472 pidx++;
473 ptable++;
474 }
475 use_default_ptable = !ptable_ok;
476 }
477
478 if (romfs_in_flash) {
479
480
481 axis_partitions[pidx].name = "romfs";
482 axis_partitions[pidx].size = romfs_length;
483 axis_partitions[pidx].offset = romfs_start - FLASH_CACHED_ADDR;
484 axis_partitions[pidx].mask_flags |= MTD_WRITEABLE;
485
486 printk(KERN_INFO
487 " Adding readonly flash partition for romfs image:\n");
488 printk(pmsg, pidx, axis_partitions[pidx].offset,
489 axis_partitions[pidx].size);
490 pidx++;
491 }
492
493 if (mymtd) {
494 if (use_default_ptable) {
495 printk(KERN_INFO " Using default partition table.\n");
496 err = add_mtd_partitions(mymtd, axis_default_partitions,
497 NUM_DEFAULT_PARTITIONS);
498 } else {
499 err = add_mtd_partitions(mymtd, axis_partitions, pidx);
500 }
501
502 if (err) {
503 panic("axisflashmap could not add MTD partitions!\n");
504 }
505 }
506
507 if (!romfs_in_flash) {
508
509
510#if !defined(CONFIG_MTD_MTDRAM) || (CONFIG_MTDRAM_TOTAL_SIZE != 0) || (CONFIG_MTDRAM_ABS_POS != 0)
511
512 printk(KERN_EMERG "axisflashmap: Cannot create an MTD RAM "
513 "device due to kernel (mis)configuration!\n");
514 panic("This kernel cannot boot from RAM!\n");
515#else
516 struct mtd_info *mtd_ram;
517
518 mtd_ram = kmalloc(sizeof(struct mtd_info),
519 GFP_KERNEL);
520 if (!mtd_ram) {
521 panic("axisflashmap couldn't allocate memory for "
522 "mtd_info!\n");
523 }
524
525 printk(KERN_INFO " Adding RAM partition for romfs image:\n");
526 printk(pmsg, pidx, romfs_start, romfs_length);
527
528 err = mtdram_init_device(mtd_ram, (void*)romfs_start,
529 romfs_length, "romfs");
530 if (err) {
531 panic("axisflashmap could not initialize MTD RAM "
532 "device!\n");
533 }
534#endif
535 }
536
537 return err;
538}
539
540
541module_init(init_axis_flash);
542
543EXPORT_SYMBOL(axisflash_mtd);
544