00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <linux/module.h>
00019 #include <linux/types.h>
00020 #include <linux/kernel.h>
00021 #include <linux/init.h>
00022 #include <linux/slab.h>
00023
00024 #include <linux/mtd/concat.h>
00025 #include <linux/mtd/map.h>
00026 #include <linux/mtd/mtd.h>
00027 #include <linux/mtd/mtdram.h>
00028 #include <linux/mtd/partitions.h>
00029
00030 #include <linux/cramfs_fs.h>
00031
00032 #include <asm/arch/hwregs/config_defs.h>
00033 #include <asm/axisflashmap.h>
00034 #include <asm/mmu.h>
00035
00036 #define MEM_CSE0_SIZE (0x04000000)
00037 #define MEM_CSE1_SIZE (0x04000000)
00038
00039 #define FLASH_UNCACHED_ADDR KSEG_E
00040 #define FLASH_CACHED_ADDR KSEG_F
00041
00042 #define PAGESIZE (512)
00043
00044 #if CONFIG_ETRAX_FLASH_BUSWIDTH==1
00045 #define flash_data __u8
00046 #elif CONFIG_ETRAX_FLASH_BUSWIDTH==2
00047 #define flash_data __u16
00048 #elif CONFIG_ETRAX_FLASH_BUSWIDTH==4
00049 #define flash_data __u32
00050 #endif
00051
00052 #define NAND_BBT_SPACE 0x00400000
00053
00054 extern unsigned long romfs_in_flash;
00055 extern unsigned long romfs_start, romfs_length;
00056 extern unsigned long nand_boot;
00057
00058 struct partition_name {
00059 char name[6];
00060 };
00061
00062
00063 struct mtd_info* axisflash_mtd = NULL;
00064
00065
00066
00067 static map_word flash_read(struct map_info *map, unsigned long ofs)
00068 {
00069 map_word tmp;
00070 tmp.x[0] = *(flash_data *)(map->map_priv_1 + ofs);
00071 return tmp;
00072 }
00073
00074 static void flash_copy_from(struct map_info *map, void *to,
00075 unsigned long from, ssize_t len)
00076 {
00077 memcpy(to, (void *)(map->map_priv_1 + from), len);
00078 }
00079
00080 static void flash_write(struct map_info *map, map_word d, unsigned long adr)
00081 {
00082 *(flash_data *)(map->map_priv_1 + adr) = (flash_data)d.x[0];
00083 }
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 static struct map_info map_cse0 = {
00101 .name = "cse0",
00102 .size = MEM_CSE0_SIZE,
00103 .bankwidth = CONFIG_ETRAX_FLASH_BUSWIDTH,
00104 .read = flash_read,
00105 .copy_from = flash_copy_from,
00106 .write = flash_write,
00107 .map_priv_1 = FLASH_UNCACHED_ADDR
00108 };
00109
00110
00111
00112
00113
00114
00115
00116 static struct map_info map_cse1 = {
00117 .name = "cse1",
00118 .size = MEM_CSE1_SIZE,
00119 .bankwidth = CONFIG_ETRAX_FLASH_BUSWIDTH,
00120 .read = flash_read,
00121 .copy_from = flash_copy_from,
00122 .write = flash_write,
00123 .map_priv_1 = FLASH_UNCACHED_ADDR + MEM_CSE0_SIZE
00124 };
00125
00126 #define MAX_PARTITIONS 7
00127 #ifdef CONFIG_ETRAX_NANDBOOT
00128 #define NUM_DEFAULT_PARTITIONS 4
00129 #define DEFAULT_ROOTFS_PARTITION_NO 2
00130 #define DEFAULT_MEDIA_SIZE 0x2000000
00131 #else
00132 #define NUM_DEFAULT_PARTITIONS 3
00133 #define DEFAULT_ROOTFS_PARTITION_NO (-1)
00134 #define DEFAULT_MEDIA_SIZE 0x800000
00135 #endif
00136
00137 #if (MAX_PARTITIONS < NUM_DEFAULT_PARTITIONS)
00138 #error MAX_PARTITIONS must be >= than NUM_DEFAULT_PARTITIONS
00139 #endif
00140
00141
00142 static struct mtd_partition axis_partitions[MAX_PARTITIONS] = {
00143 {
00144 .name = "part0",
00145 .size = CONFIG_ETRAX_PTABLE_SECTOR,
00146 .offset = 0
00147 },
00148 {
00149 .name = "part1",
00150 .size = 0,
00151 .offset = 0
00152 },
00153 {
00154 .name = "part2",
00155 .size = 0,
00156 .offset = 0
00157 },
00158 {
00159 .name = "part3",
00160 .size = 0,
00161 .offset = 0
00162 },
00163 {
00164 .name = "part4",
00165 .size = 0,
00166 .offset = 0
00167 },
00168 {
00169 .name = "part5",
00170 .size = 0,
00171 .offset = 0
00172 },
00173 {
00174 .name = "part6",
00175 .size = 0,
00176 .offset = 0
00177 },
00178 };
00179
00180
00181
00182
00183
00184
00185
00186 static struct mtd_partition axis_default_partitions[NUM_DEFAULT_PARTITIONS] = {
00187 {
00188 .name = "boot firmware",
00189 .size = CONFIG_ETRAX_PTABLE_SECTOR,
00190 .offset = 0
00191 },
00192 {
00193 .name = "kernel",
00194 .size = 10 * CONFIG_ETRAX_PTABLE_SECTOR,
00195 .offset = CONFIG_ETRAX_PTABLE_SECTOR
00196 },
00197 #define FILESYSTEM_SECTOR (11 * CONFIG_ETRAX_PTABLE_SECTOR)
00198 #ifdef CONFIG_ETRAX_NANDBOOT
00199 {
00200 .name = "rootfs",
00201 .size = 10 * CONFIG_ETRAX_PTABLE_SECTOR,
00202 .offset = FILESYSTEM_SECTOR
00203 },
00204 #undef FILESYSTEM_SECTOR
00205 #define FILESYSTEM_SECTOR (21 * CONFIG_ETRAX_PTABLE_SECTOR)
00206 #endif
00207 {
00208 .name = "rwfs",
00209 .size = DEFAULT_MEDIA_SIZE - FILESYSTEM_SECTOR,
00210 .offset = FILESYSTEM_SECTOR
00211 }
00212 };
00213
00214 #ifdef CONFIG_ETRAX_AXISFLASHMAP_MTD0WHOLE
00215
00216 static struct mtd_partition main_partition = {
00217 .name = "main",
00218 .size = 0,
00219 .offset = 0
00220 };
00221 #endif
00222
00223
00224 static struct mtd_partition aux_partition = {
00225 .name = "aux",
00226 .size = 0,
00227 .offset = 0
00228 };
00229
00230
00231
00232
00233
00234 static struct mtd_info *probe_cs(struct map_info *map_cs)
00235 {
00236 struct mtd_info *mtd_cs = NULL;
00237
00238 printk(KERN_INFO
00239 "%s: Probing a 0x%08lx bytes large window at 0x%08lx.\n",
00240 map_cs->name, map_cs->size, map_cs->map_priv_1);
00241
00242 #ifdef CONFIG_MTD_CFI
00243 mtd_cs = do_map_probe("cfi_probe", map_cs);
00244 #endif
00245 #ifdef CONFIG_MTD_JEDECPROBE
00246 if (!mtd_cs) {
00247 mtd_cs = do_map_probe("jedec_probe", map_cs);
00248 }
00249 #endif
00250
00251 return mtd_cs;
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 extern struct mtd_info* __init crisv32_nand_flash_probe (void);
00265 static struct mtd_info *flash_probe(void)
00266 {
00267 struct mtd_info *mtd_cse0;
00268 struct mtd_info *mtd_cse1;
00269 struct mtd_info *mtd_total;
00270 struct mtd_info *mtds[2];
00271 int count = 0;
00272
00273 if ((mtd_cse0 = probe_cs(&map_cse0)) != NULL)
00274 mtds[count++] = mtd_cse0;
00275 if ((mtd_cse1 = probe_cs(&map_cse1)) != NULL)
00276 mtds[count++] = mtd_cse1;
00277
00278
00279 if (!mtd_cse0 && !mtd_cse1) {
00280
00281 return NULL;
00282 }
00283
00284 if (count > 1) {
00285 #ifdef CONFIG_MTD_CONCAT
00286
00287
00288
00289
00290
00291
00292
00293 mtd_total = mtd_concat_create(mtds,
00294 count,
00295 "cse0+cse1");
00296 #else
00297 printk(KERN_ERR "%s and %s: Cannot concatenate due to kernel "
00298 "(mis)configuration!\n", map_cse0.name, map_cse1.name);
00299 mtd_toal = NULL;
00300 #endif
00301 if (!mtd_total) {
00302 printk(KERN_ERR "%s and %s: Concatenation failed!\n",
00303 map_cse0.name, map_cse1.name);
00304
00305
00306
00307
00308 mtd_total = mtd_cse0;
00309 map_destroy(mtd_cse1);
00310 }
00311 } else {
00312 mtd_total = mtd_cse0 ? mtd_cse0 : mtd_cse1;
00313
00314 }
00315
00316 return mtd_total;
00317 }
00318
00319
00320
00321
00322
00323 static int __init init_axis_flash(void)
00324 {
00325 struct mtd_info *main_mtd = NULL;
00326 struct mtd_info *aux_mtd = NULL;
00327 int err = 0;
00328 int pidx = 0;
00329 struct partitiontable_head *ptable_head = NULL;
00330 struct partitiontable_entry *ptable;
00331 int ptable_ok = 0;
00332 static char page[PAGESIZE];
00333 size_t len;
00334 int ram_rootfs_partition = -1;
00335 int part;
00336
00337 printk(KERN_EMERG "axisflashmap: ...\n");
00338
00339
00340
00341
00342
00343 #if !defined(CONFIG_MTD_MTDRAM) || (CONFIG_MTDRAM_TOTAL_SIZE != 0) || (CONFIG_MTDRAM_ABS_POS != 0)
00344 if (!romfs_in_flash && !nand_boot) {
00345 printk(KERN_EMERG "axisflashmap: Cannot create an MTD RAM "
00346 "device; configure CONFIG_MTD_MTDRAM with size = 0!\n");
00347 panic("This kernel cannot boot from RAM!\n");
00348 }
00349 #endif
00350
00351 #ifndef CONFIG_ETRAXFS_SIM
00352 #ifndef CONFIG_ETRAX_NANDFLASH
00353 main_mtd = flash_probe();
00354 if (main_mtd)
00355 printk(KERN_INFO "%s: 0x%08x bytes of NOR flash memory.\n",
00356 main_mtd->name, main_mtd->size);
00357 #endif
00358 #ifdef CONFIG_ETRAX_NANDFLASH
00359 aux_mtd = crisv32_nand_flash_probe();
00360 if (aux_mtd)
00361 printk(KERN_INFO "%s: 0x%08x bytes of NAND flash memory.\n",
00362 aux_mtd->name, aux_mtd->size);
00363
00364 #ifdef CONFIG_ETRAX_NANDBOOT
00365 {
00366 struct mtd_info *tmp_mtd;
00367
00368 printk(KERN_INFO "axisflashmap: Set to boot from NAND flash, "
00369 "making NAND flash primary device.\n");
00370 tmp_mtd = main_mtd;
00371 main_mtd = aux_mtd;
00372 aux_mtd = tmp_mtd;
00373 }
00374 #endif
00375 #endif
00376
00377 if (!main_mtd && !aux_mtd) {
00378
00379
00380
00381 printk(KERN_INFO "axisflashmap: Found no flash chip.\n");
00382 }
00383
00384 #if 0
00385 if (main_mtd) {
00386 int sectoraddr, i;
00387 for (sectoraddr = 0; sectoraddr < 2*65536+4096; sectoraddr += PAGESIZE) {
00388 main_mtd->read(main_mtd, sectoraddr, PAGESIZE, &len, page);
00389 printk(KERN_INFO
00390 "Sector at %d (length %d):\n",
00391 sectoraddr, len);
00392 for (i = 0; i < PAGESIZE; i += 16) {
00393 printk(KERN_INFO
00394 "%02x %02x %02x %02x %02x %02x %02x %02x "
00395 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
00396 page[i] & 255, page[i+1] & 255,
00397 page[i+2] & 255, page[i+3] & 255,
00398 page[i+4] & 255, page[i+5] & 255,
00399 page[i+6] & 255, page[i+7] & 255,
00400 page[i+8] & 255, page[i+9] & 255,
00401 page[i+10] & 255, page[i+11] & 255,
00402 page[i+12] & 255, page[i+13] & 255,
00403 page[i+14] & 255, page[i+15] & 255);
00404 }
00405
00406 }
00407 }
00408 #endif
00409
00410 if (main_mtd) {
00411 main_mtd->owner = THIS_MODULE;
00412 axisflash_mtd = main_mtd;
00413
00414 loff_t ptable_sector = CONFIG_ETRAX_PTABLE_SECTOR;
00415
00416 pidx++;
00417 #ifdef CONFIG_ETRAX_NANDBOOT
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 int blockstat;
00432 do {
00433 blockstat = main_mtd->block_isbad(main_mtd, ptable_sector);
00434 if (blockstat < 0)
00435 ptable_sector = 0;
00436 else if (blockstat)
00437 ptable_sector += main_mtd->erasesize;
00438 } while (blockstat && ptable_sector);
00439 #endif
00440 if (ptable_sector) {
00441 main_mtd->read(main_mtd, ptable_sector, PAGESIZE, &len, page);
00442 ptable_head = &((struct partitiontable *) page)->head;
00443 }
00444
00445
00446 printk(KERN_INFO
00447 "axisflashmap: flash read %d bytes at 0x%08x, data: "
00448 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
00449 len, ptable_sector,
00450
00451 page[0] & 255, page[1] & 255,
00452 page[2] & 255, page[3] & 255,
00453 page[4] & 255, page[5] & 255,
00454 page[6] & 255, page[7] & 255);
00455 printk(KERN_INFO
00456 "axisflashmap: partition table offset %d, data: "
00457 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
00458 PARTITION_TABLE_OFFSET,
00459 page[PARTITION_TABLE_OFFSET+0] & 255,
00460 page[PARTITION_TABLE_OFFSET+1] & 255,
00461 page[PARTITION_TABLE_OFFSET+2] & 255,
00462 page[PARTITION_TABLE_OFFSET+3] & 255,
00463 page[PARTITION_TABLE_OFFSET+4] & 255,
00464 page[PARTITION_TABLE_OFFSET+5] & 255,
00465 page[PARTITION_TABLE_OFFSET+6] & 255,
00466 page[PARTITION_TABLE_OFFSET+7] & 255);
00467
00468 }
00469
00470 if (ptable_head && (ptable_head->magic == PARTITION_TABLE_MAGIC)
00471 && (ptable_head->size <
00472 (MAX_PARTITIONS * sizeof(struct partitiontable_entry) +
00473 PARTITIONTABLE_END_MARKER_SIZE))
00474 && (*(unsigned long*)((void*)ptable_head + sizeof(*ptable_head) +
00475 ptable_head->size -
00476 PARTITIONTABLE_END_MARKER_SIZE)
00477 == PARTITIONTABLE_END_MARKER)) {
00478
00479
00480
00481 struct partitiontable_entry *max_addr =
00482 (struct partitiontable_entry *)
00483 ((unsigned long)ptable_head + sizeof(*ptable_head) +
00484 ptable_head->size);
00485 unsigned long offset = CONFIG_ETRAX_PTABLE_SECTOR;
00486 unsigned char *p;
00487 unsigned long csum = 0;
00488
00489 ptable = (struct partitiontable_entry *)
00490 ((unsigned long)ptable_head + sizeof(*ptable_head));
00491
00492
00493 p = (unsigned char*) ptable;
00494
00495 while (p <= (unsigned char*)max_addr) {
00496 csum += *p++;
00497 csum += *p++;
00498 csum += *p++;
00499 csum += *p++;
00500 }
00501 ptable_ok = (csum == ptable_head->checksum);
00502
00503
00504 printk(KERN_INFO "axisflashmap: "
00505 "Found a%s partition table at 0x%p-0x%p.\n",
00506 (ptable_ok ? " valid" : "n invalid"), ptable_head,
00507 max_addr);
00508
00509
00510
00511
00512 while (ptable_ok
00513 && ptable->offset != PARTITIONTABLE_END_MARKER
00514 && ptable < max_addr
00515 && pidx < MAX_PARTITIONS - 1) {
00516
00517 axis_partitions[pidx].offset = offset + ptable->offset;
00518 #ifdef CONFIG_ETRAX_NANDFLASH
00519 if (main_mtd->type == MTD_NANDFLASH) {
00520 axis_partitions[pidx].size = ( ((ptable+1)->offset == PARTITIONTABLE_END_MARKER) ? (main_mtd->size - NAND_BBT_SPACE) : ((ptable+1)->offset + offset)) - (ptable->offset + offset);
00521 } else
00522 #endif
00523 axis_partitions[pidx].size = ptable->size;
00524 #ifdef CONFIG_ETRAX_NANDBOOT
00525
00526
00527
00528 if (!nand_boot &&
00529 ram_rootfs_partition < 0 &&
00530 ptable->type == PARTITION_TYPE_JFFS2 &&
00531 (ptable->flags & PARTITION_FLAGS_READONLY_MASK) ==
00532 PARTITION_FLAGS_READONLY)
00533 ram_rootfs_partition = pidx;
00534 #endif
00535 printk(KERN_INFO "offset == 0x%08X, size == 0x%08X\n" , axis_partitions[pidx].offset, axis_partitions[pidx].size);
00536 pidx++;
00537 ptable++;
00538 }
00539 }
00540
00541
00542
00543
00544 struct mtd_partition *partition = &axis_partitions[0];
00545 if (main_mtd && !ptable_ok) {
00546 memcpy(axis_partitions, axis_default_partitions,
00547 sizeof(axis_default_partitions));
00548 pidx = NUM_DEFAULT_PARTITIONS;
00549 ram_rootfs_partition = DEFAULT_ROOTFS_PARTITION_NO;
00550 }
00551
00552
00553 if (romfs_in_flash) {
00554
00555
00556 printk(KERN_INFO "axisflashmap: Adding partition for "
00557 "overlapping root file system image\n");
00558 axis_partitions[pidx].size = romfs_length;
00559 axis_partitions[pidx].offset = romfs_start - FLASH_CACHED_ADDR;
00560 axis_partitions[pidx].name = "romfs";
00561 axis_partitions[pidx].mask_flags |= MTD_WRITEABLE;
00562 ram_rootfs_partition = -1;
00563 pidx++;
00564 }
00565 else if (romfs_length && !nand_boot) {
00566
00567
00568 if (ram_rootfs_partition < 0) {
00569 ram_rootfs_partition = pidx;
00570 pidx++;
00571 }
00572 printk(KERN_INFO "axisflashmap: Adding partition for "
00573 "root file system image in RAM\n");
00574 axis_partitions[ram_rootfs_partition].size = romfs_length;
00575 axis_partitions[ram_rootfs_partition].offset = romfs_start;
00576 axis_partitions[ram_rootfs_partition].name = "romfs";
00577 axis_partitions[ram_rootfs_partition].mask_flags |=
00578 MTD_WRITEABLE;
00579 }
00580
00581 #ifdef CONFIG_ETRAX_AXISFLASHMAP_MTD0WHOLE
00582 if (main_mtd) {
00583 main_partition.size = main_mtd->size;
00584 err = add_mtd_partitions(main_mtd, &main_partition, 1);
00585 if (err)
00586 panic("axisflashmap: Could not initialize "
00587 "partition for whole main mtd device!\n");
00588 }
00589 #endif
00590
00591
00592
00593
00594
00595 for (part = 0; part < pidx; part++) {
00596 if (part == ram_rootfs_partition) {
00597
00598 struct mtd_info *mtd_ram;
00599
00600 mtd_ram = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
00601 if (!mtd_ram)
00602 panic("axisflashmap: Couldn't allocate memory "
00603 "for mtd_info!\n");
00604 printk(KERN_INFO "axisflashmap: Adding RAM partition "
00605 "for rootfs image.\n");
00606 err = mtdram_init_device(mtd_ram,
00607 (void *)partition[part].offset,
00608 partition[part].size,
00609 partition[part].name);
00610 if (err)
00611 panic("axisflashmap: Could not initialize "
00612 "MTD RAM device!\n");
00613
00614
00615
00616
00617 mtd_ram->erasesize = (main_mtd ? main_mtd->erasesize :
00618 CONFIG_ETRAX_PTABLE_SECTOR);
00619 } else {
00620 err = add_mtd_partitions(main_mtd,
00621 &partition[part], 1);
00622 if (err)
00623 panic("axisflashmap: Could not add mtd "
00624 "partition %d\n", part);
00625 }
00626 }
00627
00628 #endif
00629
00630 #ifdef CONFIG_ETRAXFS_SIM
00631
00632
00633
00634
00635 struct mtd_info *mtd_ram;
00636
00637 mtd_ram = (struct mtd_info *)kmalloc(sizeof(struct mtd_info),
00638 GFP_KERNEL);
00639 if (!mtd_ram) {
00640 panic("axisflashmap: Couldn't allocate memory for "
00641 "mtd_info!\n");
00642 }
00643
00644 printk(KERN_INFO "axisflashmap: Adding RAM partition for romfs, "
00645 "at %u, size %u\n",
00646 (unsigned) romfs_start, (unsigned) romfs_length);
00647
00648 err = mtdram_init_device(mtd_ram, (void*)romfs_start,
00649 romfs_length, "romfs");
00650 if (err) {
00651 panic("axisflashmap: Could not initialize MTD RAM "
00652 "device!\n");
00653 }
00654 #endif
00655
00656 #ifndef CONFIG_ETRAXFS_SIM
00657 if (aux_mtd) {
00658 aux_partition.size = aux_mtd->size;
00659 err = add_mtd_partitions(aux_mtd, &aux_partition, 1);
00660 if (err)
00661 panic("axisflashmap: Could not initialize "
00662 "aux mtd device!\n");
00663
00664 }
00665 #endif
00666
00667 return err;
00668 }
00669
00670
00671 module_init(init_axis_flash);
00672
00673 EXPORT_SYMBOL(axisflash_mtd);