linux/arch/cris/arch-v10/drivers/axisflashmap.c
<<
>>
Prefs
   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 * $Log: axisflashmap.c,v $
  14 * Revision 1.11  2004/11/15 10:27:14  starvik
  15 * Corrected typo (Thanks to Milton Miller <miltonm@bga.com>).
  16 *
  17 * Revision 1.10  2004/08/16 12:37:22  starvik
  18 * Merge of Linux 2.6.8
  19 *
  20 * Revision 1.8  2004/05/14 07:58:03  starvik
  21 * Merge of changes from 2.4
  22 *
  23 * Revision 1.6  2003/07/04 08:27:37  starvik
  24 * Merge of Linux 2.5.74
  25 *
  26 * Revision 1.5  2002/12/11 13:13:57  starvik
  27 * Added arch/ to v10 specific includes
  28 * Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
  29 *
  30 * Revision 1.4  2002/11/20 11:56:10  starvik
  31 * Merge of Linux 2.5.48
  32 *
  33 * Revision 1.3  2002/11/13 14:54:13  starvik
  34 * Copied from linux 2.4
  35 *
  36 * Revision 1.28  2002/10/01 08:08:43  jonashg
  37 * The first partition ends at the start of the partition table.
  38 *
  39 * Revision 1.27  2002/08/21 09:23:13  jonashg
  40 * Speling.
  41 *
  42 * Revision 1.26  2002/08/21 08:35:20  jonashg
  43 * Cosmetic change to printouts.
  44 *
  45 * Revision 1.25  2002/08/21 08:15:42  jonashg
  46 * Made it compile even without CONFIG_MTD_CONCAT defined.
  47 *
  48 * Revision 1.24  2002/08/20 13:12:35  jonashg
  49 * * New approach to probing. Probe cse0 and cse1 separately and (mtd)concat
  50 *   the results.
  51 * * Removed compile time tests concerning how the mtdram driver has been
  52 *   configured. The user will know about the misconfiguration at runtime
  53 *   instead. (The old approach made it impossible to use mtdram for anything
  54 *   else than RAM boot).
  55 *
  56 * Revision 1.23  2002/05/13 12:12:28  johana
  57 * Allow compile without CONFIG_MTD_MTDRAM but warn at compiletime and
  58 * be informative at runtime.
  59 *
  60 * Revision 1.22  2002/05/13 10:24:44  johana
  61 * Added #if checks on MTDRAM CONFIG
  62 *
  63 * Revision 1.21  2002/05/06 16:05:20  johana
  64 * Removed debug printout.
  65 *
  66 * Revision 1.20  2002/05/06 16:03:00  johana
  67 * No more cramfs as root hack in generic code.
  68 * It's handled by axisflashmap using mtdram.
  69 *
  70 * Revision 1.19  2002/03/15 17:10:28  bjornw
  71 * Changed comment about cached access since we changed this before
  72 *
  73 * Revision 1.18  2002/03/05 17:06:15  jonashg
  74 * Try amd_flash probe before cfi_probe since amd_flash driver can handle two
  75 * (or more) flash chips of different model and the cfi driver cannot.
  76 *
  77 * Revision 1.17  2001/11/12 19:42:38  pkj
  78 * Fixed compiler warnings.
  79 *
  80 * Revision 1.16  2001/11/08 11:18:58  jonashg
  81 * Always read from uncached address to avoid problems with flushing
  82 * cachelines after write and MTD-erase. No performance loss have been
  83 * seen yet.
  84 *
  85 * Revision 1.15  2001/10/19 12:41:04  jonashg
  86 * Name of probe has changed in MTD.
  87 *
  88 * Revision 1.14  2001/09/21 07:14:10  jonashg
  89 * Made root filesystem (cramfs) use mtdblock driver when booting from flash.
  90 *
  91 * Revision 1.13  2001/08/15 13:57:35  jonashg
  92 * Entire MTD updated to the linux 2.4.7 version.
  93 *
  94 * Revision 1.12  2001/06/11 09:50:30  jonashg
  95 * Oops, 2MB is 0x200000 bytes.
  96 *
  97 * Revision 1.11  2001/06/08 11:39:44  jonashg
  98 * Changed sizes and offsets in axis_default_partitions to use
  99 * CONFIG_ETRAX_PTABLE_SECTOR.
 100 *
 101 * Revision 1.10  2001/05/29 09:42:03  jonashg
 102 * Use macro for end marker length instead of sizeof.
 103 *
 104 * Revision 1.9  2001/05/29 08:52:52  jonashg
 105 * Gave names to the magic fours (size of the ptable end marker).
 106 *
 107 * Revision 1.8  2001/05/28 15:36:20  jonashg
 108 * * Removed old comment about ptable location in flash (it's a CONFIG_ option).
 109 * * Variable ptable was initialized twice to the same value.
 110 *
 111 * Revision 1.7  2001/04/05 13:41:46  markusl
 112 * Updated according to review remarks
 113 *
 114 * Revision 1.6  2001/03/07 09:21:21  bjornw
 115 * No need to waste .data
 116 *
 117 * Revision 1.5  2001/03/06 16:27:01  jonashg
 118 * Probe the entire flash area for flash devices.
 119 *
 120 * Revision 1.4  2001/02/23 12:47:15  bjornw
 121 * Uncached flash in LOW_MAP moved from 0xe to 0x8
 122 *
 123 * Revision 1.3  2001/02/16 12:11:45  jonashg
 124 * MTD driver amd_flash is now included in MTD CVS repository.
 125 * (It's now in drivers/mtd).
 126 *
 127 * Revision 1.2  2001/02/09 11:12:22  jonashg
 128 * Support for AMD compatible non-CFI flash chips.
 129 * Only tested with Toshiba TC58FVT160 so far.
 130 *
 131 * Revision 1.1  2001/01/12 17:01:18  bjornw
 132 * * Added axisflashmap.c, a physical mapping for MTD that reads and understands
 133 *   Axis partition-table format.
 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/* From head.S */
 171extern unsigned long romfs_start, romfs_length, romfs_in_flash;
 172
 173/* The master mtd for the entire flash. */
 174struct mtd_info* axisflash_mtd = NULL;
 175
 176/* Map driver functions. */
 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 * The map for chip select e0.
 198 *
 199 * We run into tricky coherence situations if we mix cached with uncached
 200 * accesses to we only use the uncached version here.
 201 *
 202 * The size field is the total size where the flash chips may be mapped on the
 203 * chip select. MTD probes should find all devices there and it does not matter
 204 * if there are unmapped gaps or aliases (mirrors of flash devices). The MTD
 205 * probes will ignore them.
 206 *
 207 * The start address in map_priv_1 is in virtual memory so we cannot use
 208 * MEM_CSE0_START but must rely on that FLASH_UNCACHED_ADDR is the start
 209 * address of cse0.
 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 * The map for chip select e1.
 223 *
 224 * If there was a gap between cse0 and cse1, map_priv_1 would get the wrong
 225 * address, but there isn't.
 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/* If no partition-table was found, we use this default-set. */
 238#define MAX_PARTITIONS         7  
 239#define NUM_DEFAULT_PARTITIONS 3
 240
 241/*
 242 * Default flash size is 2MB. CONFIG_ETRAX_PTABLE_SECTOR is most likely the
 243 * size of one flash block and "filesystem"-partition needs 5 blocks to be able
 244 * to use JFFS.
 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/* Initialize the ones normally used. */
 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 * Probe a chip select for AMD-compatible (JEDEC) or CFI-compatible flash
 305 * chips in that order (because the amd_flash-driver is faster).
 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 * Probe each chip select individually for flash chips. If there are chips on
 329 * both cse0 and cse1, the mtd_info structs will be concatenated to one struct
 330 * so that MTD partitions can cross chip boundries.
 331 *
 332 * The only known restriction to how you can mount your chips is that each
 333 * chip select must hold similar flash chips. But you need external hardware
 334 * to do that anyway and you can put totally different chips on cse0 and cse1
 335 * so it isn't really much of a restriction.
 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                /* No chip found. */
 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                /* Since the concatenation layer adds a small overhead we
 356                 * could try to figure out if the chips in cse0 and cse1 are
 357                 * identical and reprobe the whole cse0+cse1 window. But since
 358                 * flash chips are slow, the overhead is relatively small.
 359                 * So we use the MTD concatenation layer instead of further
 360                 * complicating the probing procedure.
 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                        /* The best we can do now is to only use what we found
 374                         * at cse0.
 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 * Probe the flash chip(s) and, if it succeeds, read the partition-table
 388 * and register the partitions with MTD.
 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; /* Until proven otherwise. */
 398        const char *pmsg = "  /dev/flash%d at 0x%08x, size 0x%08x\n";
 399
 400        if (!(mymtd = flash_probe())) {
 401                /* There's no reason to use this module if no flash chip can
 402                 * be identified. Make sure that's understood.
 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++;  /* First partition is always set to the default. */
 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                /* Looks like a start, sane length and end of a
 428                 * partition table, lets check csum etc.
 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                /* Lets be PARANOID, and check the checksum. */
 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                /* Read the entries and use/show the info.  */
 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                /* We have found a working bootblock.  Now read the
 459                 * partition table.  Scan the table.  It ends when
 460                 * there is 0xffffffff, that is, empty flash.
 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                /* Add an overlapping device for the root partition (romfs). */
 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                /* Create an RAM device for the root partition (romfs). */
 509
 510#if !defined(CONFIG_MTD_MTDRAM) || (CONFIG_MTDRAM_TOTAL_SIZE != 0) || (CONFIG_MTDRAM_ABS_POS != 0)
 511                /* No use trying to boot this kernel from RAM. Panic! */
 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/* This adds the above to the kernels init-call chain. */
 541module_init(init_axis_flash);
 542
 543EXPORT_SYMBOL(axisflash_mtd);
 544