1/* 2 * Physical mapping layer for MTD using the Axis partitiontable format 3 * 4 * Copyright (c) 2001, 2002 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 */ 14 15#include <linux/module.h> 16#include <linux/types.h> 17#include <linux/kernel.h> 18#include <linux/init.h> 19#include <linux/slab.h> 20 21#include <linux/mtd/concat.h> 22#include <linux/mtd/map.h> 23#include <linux/mtd/mtd.h> 24#include <linux/mtd/mtdram.h> 25#include <linux/mtd/partitions.h> 26 27#include <asm/axisflashmap.h> 28#include <asm/mmu.h> 29#include <arch/sv_addr_ag.h> 30 31#ifdef CONFIG_CRIS_LOW_MAP 32#define FLASH_UNCACHED_ADDR KSEG_8 33#define FLASH_CACHED_ADDR KSEG_5 34#else 35#define FLASH_UNCACHED_ADDR KSEG_E 36#define FLASH_CACHED_ADDR KSEG_F 37#endif 38 39#if CONFIG_ETRAX_FLASH_BUSWIDTH==1 40#define flash_data __u8 41#elif CONFIG_ETRAX_FLASH_BUSWIDTH==2 42#define flash_data __u16 43#elif CONFIG_ETRAX_FLASH_BUSWIDTH==4 44#define flash_data __u32 45#endif 46 47/* From head.S */ 48extern unsigned long romfs_start, romfs_length, romfs_in_flash; 49 50/* The master mtd for the entire flash. */ 51struct mtd_info* axisflash_mtd = NULL; 52 53/* Map driver functions. */ 54 55static map_word flash_read(struct map_info *map, unsigned long ofs) 56{ 57 map_word tmp; 58 tmp.x[0] = *(flash_data *)(map->map_priv_1 + ofs); 59 return tmp; 60} 61 62static void flash_copy_from(struct map_info *map, void *to, 63 unsigned long from, ssize_t len) 64{ 65 memcpy(to, (void *)(map->map_priv_1 + from), len); 66} 67 68static void flash_write(struct map_info *map, map_word d, unsigned long adr) 69{ 70 *(flash_data *)(map->map_priv_1 + adr) = (flash_data)d.x[0]; 71} 72 73/* 74 * The map for chip select e0. 75 * 76 * We run into tricky coherence situations if we mix cached with uncached 77 * accesses to we only use the uncached version here. 78 * 79 * The size field is the total size where the flash chips may be mapped on the 80 * chip select. MTD probes should find all devices there and it does not matter 81 * if there are unmapped gaps or aliases (mirrors of flash devices). The MTD 82 * probes will ignore them. 83 * 84 * The start address in map_priv_1 is in virtual memory so we cannot use 85 * MEM_CSE0_START but must rely on that FLASH_UNCACHED_ADDR is the start 86 * address of cse0. 87 */ 88static struct map_info map_cse0 = { 89 .name = "cse0", 90 .size = MEM_CSE0_SIZE, 91 .bankwidth = CONFIG_ETRAX_FLASH_BUSWIDTH, 92 .read = flash_read, 93 .copy_from = flash_copy_from, 94 .write = flash_write, 95 .map_priv_1 = FLASH_UNCACHED_ADDR 96}; 97 98/* 99 * The map for chip select e1. 100 * 101 * If there was a gap between cse0 and cse1, map_priv_1 would get the wrong 102 * address, but there isn't. 103 */ 104static struct map_info map_cse1 = { 105 .name = "cse1", 106 .size = MEM_CSE1_SIZE, 107 .bankwidth = CONFIG_ETRAX_FLASH_BUSWIDTH, 108 .read = flash_read, 109 .copy_from = flash_copy_from, 110 .write = flash_write, 111 .map_priv_1 = FLASH_UNCACHED_ADDR + MEM_CSE0_SIZE 112}; 113 114/* If no partition-table was found, we use this default-set. */ 115#define MAX_PARTITIONS 7 116#define NUM_DEFAULT_PARTITIONS 3 117 118/* 119 * Default flash size is 2MB. CONFIG_ETRAX_PTABLE_SECTOR is most likely the 120 * size of one flash block and "filesystem"-partition needs 5 blocks to be able 121 * to use JFFS. 122 */ 123static struct mtd_partition axis_default_partitions[NUM_DEFAULT_PARTITIONS] = { 124 { 125 .name = "boot firmware", 126 .size = CONFIG_ETRAX_PTABLE_SECTOR, 127 .offset = 0 128 }, 129 { 130 .name = "kernel", 131 .size = 0x200000 - (6 * CONFIG_ETRAX_PTABLE_SECTOR), 132 .offset = CONFIG_ETRAX_PTABLE_SECTOR 133 }, 134 { 135 .name = "filesystem", 136 .size = 5 * CONFIG_ETRAX_PTABLE_SECTOR, 137 .offset = 0x200000 - (5 * CONFIG_ETRAX_PTABLE_SECTOR) 138 } 139}; 140 141/* Initialize the ones normally used. */ 142static struct mtd_partition axis_partitions[MAX_PARTITIONS] = { 143 { 144 .name = "part0", 145 .size = CONFIG_ETRAX_PTABLE_SECTOR, 146 .offset = 0 147 }, 148 { 149 .name = "part1", 150 .size = 0, 151 .offset = 0 152 }, 153 { 154 .name = "part2", 155 .size = 0, 156 .offset = 0 157 }, 158 { 159 .name = "part3", 160 .size = 0, 161 .offset = 0 162 }, 163 { 164 .name = "part4", 165 .size = 0, 166 .offset = 0 167 }, 168 { 169 .name = "part5", 170 .size = 0, 171 .offset = 0 172 }, 173 { 174 .name = "part6", 175 .size = 0, 176 .offset = 0 177 }, 178}; 179 180#ifdef CONFIG_ETRAX_AXISFLASHMAP_MTD0WHOLE 181/* Main flash device */ 182static struct mtd_partition main_partition = { 183 .name = "main", 184 .size = 0, 185 .offset = 0 186}; 187#endif 188 189/* 190 * Probe a chip select for AMD-compatible (JEDEC) or CFI-compatible flash 191 * chips in that order (because the amd_flash-driver is faster). 192 */ 193static struct mtd_info *probe_cs(struct map_info *map_cs) 194{ 195 struct mtd_info *mtd_cs = NULL; 196 197 printk(KERN_INFO 198 "%s: Probing a 0x%08lx bytes large window at 0x%08lx.\n", 199 map_cs->name, map_cs->size, map_cs->map_priv_1); 200 201#ifdef CONFIG_MTD_CFI 202 mtd_cs = do_map_probe("cfi_probe", map_cs); 203#endif 204#ifdef CONFIG_MTD_JEDECPROBE 205 if (!mtd_cs) 206 mtd_cs = do_map_probe("jedec_probe", map_cs); 207#endif 208 209 return mtd_cs; 210} 211 212/* 213 * Probe each chip select individually for flash chips. If there are chips on 214 * both cse0 and cse1, the mtd_info structs will be concatenated to one struct 215 * so that MTD partitions can cross chip boundries. 216 * 217 * The only known restriction to how you can mount your chips is that each 218 * chip select must hold similar flash chips. But you need external hardware 219 * to do that anyway and you can put totally different chips on cse0 and cse1 220 * so it isn't really much of a restriction. 221 */ 222static struct mtd_info *flash_probe(void) 223{ 224 struct mtd_info *mtd_cse0; 225 struct mtd_info *mtd_cse1; 226 struct mtd_info *mtd_cse; 227 228 mtd_cse0 = probe_cs(&map_cse0); 229 mtd_cse1 = probe_cs(&map_cse1); 230 231 if (!mtd_cse0 && !mtd_cse1) { 232 /* No chip found. */ 233 return NULL; 234 } 235 236 if (mtd_cse0 && mtd_cse1) { 237#ifdef CONFIG_MTD_CONCAT 238 struct mtd_info *mtds[] = { mtd_cse0, mtd_cse1 }; 239 240 /* Since the concatenation layer adds a small overhead we 241 * could try to figure out if the chips in cse0 and cse1 are 242 * identical and reprobe the whole cse0+cse1 window. But since 243 * flash chips are slow, the overhead is relatively small. 244 * So we use the MTD concatenation layer instead of further 245 * complicating the probing procedure. 246 */ 247 mtd_cse = mtd_concat_create(mtds, ARRAY_SIZE(mtds), 248 "cse0+cse1"); 249#else 250 printk(KERN_ERR "%s and %s: Cannot concatenate due to kernel " 251 "(mis)configuration!\n", map_cse0.name, map_cse1.name); 252 mtd_cse = NULL; 253#endif 254 if (!mtd_cse) { 255 printk(KERN_ERR "%s and %s: Concatenation failed!\n", 256 map_cse0.name, map_cse1.name); 257 258 /* The best we can do now is to only use what we found 259 * at cse0. 260 */ 261 mtd_cse = mtd_cse0; 262 map_destroy(mtd_cse1); 263 } 264 } else { 265 mtd_cse = mtd_cse0? mtd_cse0 : mtd_cse1; 266 } 267 268 return mtd_cse; 269} 270 271/* 272 * Probe the flash chip(s) and, if it succeeds, read the partition-table 273 * and register the partitions with MTD. 274 */ 275static int __init init_axis_flash(void) 276{ 277 struct mtd_info *mymtd; 278 int err = 0; 279 int pidx = 0; 280 struct partitiontable_head *ptable_head = NULL; 281 struct partitiontable_entry *ptable; 282 int use_default_ptable = 1; /* Until proven otherwise. */ 283 const char pmsg[] = " /dev/flash%d at 0x%08x, size 0x%08x\n"; 284 285 if (!(mymtd = flash_probe())) { 286 /* There's no reason to use this module if no flash chip can 287 * be identified. Make sure that's understood. 288 */ 289 printk(KERN_INFO "axisflashmap: Found no flash chip.\n"); 290 } else { 291 printk(KERN_INFO "%s: 0x%08x bytes of flash memory.\n", 292 mymtd->name, mymtd->size); 293 axisflash_mtd = mymtd; 294 } 295 296 if (mymtd) { 297 mymtd->owner = THIS_MODULE; 298 ptable_head = (struct partitiontable_head *)(FLASH_CACHED_ADDR + 299 CONFIG_ETRAX_PTABLE_SECTOR + 300 PARTITION_TABLE_OFFSET); 301 } 302 pidx++; /* First partition is always set to the default. */ 303 304 if (ptable_head && (ptable_head->magic == PARTITION_TABLE_MAGIC) 305 && (ptable_head->size < 306 (MAX_PARTITIONS * sizeof(struct partitiontable_entry) + 307 PARTITIONTABLE_END_MARKER_SIZE)) 308 && (*(unsigned long*)((void*)ptable_head + sizeof(*ptable_head) + 309 ptable_head->size - 310 PARTITIONTABLE_END_MARKER_SIZE) 311 == PARTITIONTABLE_END_MARKER)) { 312 /* Looks like a start, sane length and end of a 313 * partition table, lets check csum etc. 314 */ 315 int ptable_ok = 0; 316 struct partitiontable_entry *max_addr = 317 (struct partitiontable_entry *) 318 ((unsigned long)ptable_head + sizeof(*ptable_head) + 319 ptable_head->size); 320 unsigned long offset = CONFIG_ETRAX_PTABLE_SECTOR; 321 unsigned char *p; 322 unsigned long csum = 0; 323 324 ptable = (struct partitiontable_entry *) 325 ((unsigned long)ptable_head + sizeof(*ptable_head)); 326 327 /* Lets be PARANOID, and check the checksum. */ 328 p = (unsigned char*) ptable; 329 330 while (p <= (unsigned char*)max_addr) { 331 csum += *p++; 332 csum += *p++; 333 csum += *p++; 334 csum += *p++; 335 } 336 ptable_ok = (csum == ptable_head->checksum); 337 338 /* Read the entries and use/show the info. */ 339 printk(KERN_INFO " Found a%s partition table at 0x%p-0x%p.\n", 340 (ptable_ok ? " valid" : "n invalid"), ptable_head, 341 max_addr); 342 343 /* We have found a working bootblock. Now read the 344 * partition table. Scan the table. It ends when 345 * there is 0xffffffff, that is, empty flash. 346 */ 347 while (ptable_ok 348 && ptable->offset != 0xffffffff 349 && ptable < max_addr 350 && pidx < MAX_PARTITIONS) { 351 352 axis_partitions[pidx].offset = offset + ptable->offset; 353 axis_partitions[pidx].size = ptable->size; 354 355 printk(pmsg, pidx, axis_partitions[pidx].offset, 356 axis_partitions[pidx].size); 357 pidx++; 358 ptable++; 359 } 360 use_default_ptable = !ptable_ok; 361 } 362 363 if (romfs_in_flash) { 364 /* Add an overlapping device for the root partition (romfs). */ 365 366 axis_partitions[pidx].name = "romfs"; 367 axis_partitions[pidx].size = romfs_length; 368 axis_partitions[pidx].offset = romfs_start - FLASH_CACHED_ADDR; 369 axis_partitions[pidx].mask_flags |= MTD_WRITEABLE; 370 371 printk(KERN_INFO 372 " Adding readonly flash partition for romfs image:\n"); 373 printk(pmsg, pidx, axis_partitions[pidx].offset, 374 axis_partitions[pidx].size); 375 pidx++; 376 } 377 378#ifdef CONFIG_ETRAX_AXISFLASHMAP_MTD0WHOLE 379 if (mymtd) { 380 main_partition.size = mymtd->size; 381 err = add_mtd_partitions(mymtd, &main_partition, 1); 382 if (err) 383 panic("axisflashmap: Could not initialize " 384 "partition for whole main mtd device!\n"); 385 } 386#endif 387 388 if (mymtd) { 389 if (use_default_ptable) { 390 printk(KERN_INFO " Using default partition table.\n"); 391 err = add_mtd_partitions(mymtd, axis_default_partitions, 392 NUM_DEFAULT_PARTITIONS); 393 } else { 394 err = add_mtd_partitions(mymtd, axis_partitions, pidx); 395 } 396 397 if (err) 398 panic("axisflashmap could not add MTD partitions!\n"); 399 } 400 401 if (!romfs_in_flash) { 402 /* Create an RAM device for the root partition (romfs). */ 403 404#if !defined(CONFIG_MTD_MTDRAM) || (CONFIG_MTDRAM_TOTAL_SIZE != 0) || \ 405 (CONFIG_MTDRAM_ABS_POS != 0) 406 /* No use trying to boot this kernel from RAM. Panic! */ 407 printk(KERN_EMERG "axisflashmap: Cannot create an MTD RAM " 408 "device due to kernel (mis)configuration!\n"); 409 panic("This kernel cannot boot from RAM!\n"); 410#else 411 struct mtd_info *mtd_ram; 412 413 mtd_ram = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); 414 if (!mtd_ram) 415 panic("axisflashmap couldn't allocate memory for " 416 "mtd_info!\n"); 417 418 printk(KERN_INFO " Adding RAM partition for romfs image:\n"); 419 printk(pmsg, pidx, (unsigned)romfs_start, 420 (unsigned)romfs_length); 421 422 err = mtdram_init_device(mtd_ram, 423 (void *)romfs_start, 424 romfs_length, 425 "romfs"); 426 if (err) 427 panic("axisflashmap could not initialize MTD RAM " 428 "device!\n"); 429#endif 430 } 431 return err; 432} 433 434/* This adds the above to the kernels init-call chain. */ 435module_init(init_axis_flash); 436 437EXPORT_SYMBOL(axisflash_mtd); 438