linux/drivers/mtd/maps/nettel.c
<<
>>
Prefs
   1/****************************************************************************/
   2
   3/*
   4 *      nettel.c -- mappings for NETtel/SecureEdge/SnapGear (x86) boards.
   5 *
   6 *      (C) Copyright 2000-2001, Greg Ungerer (gerg@snapgear.com)
   7 *      (C) Copyright 2001-2002, SnapGear (www.snapgear.com)
   8 */
   9
  10/****************************************************************************/
  11
  12#include <linux/module.h>
  13#include <linux/init.h>
  14#include <linux/types.h>
  15#include <linux/kernel.h>
  16#include <linux/mtd/mtd.h>
  17#include <linux/mtd/map.h>
  18#include <linux/mtd/partitions.h>
  19#include <linux/mtd/cfi.h>
  20#include <linux/reboot.h>
  21#include <linux/err.h>
  22#include <linux/kdev_t.h>
  23#include <linux/root_dev.h>
  24#include <asm/io.h>
  25
  26/****************************************************************************/
  27
  28#define INTEL_BUSWIDTH          1
  29#define AMD_WINDOW_MAXSIZE      0x00200000
  30#define AMD_BUSWIDTH            1
  31
  32/*
  33 *      PAR masks and shifts, assuming 64K pages.
  34 */
  35#define SC520_PAR_ADDR_MASK     0x00003fff
  36#define SC520_PAR_ADDR_SHIFT    16
  37#define SC520_PAR_TO_ADDR(par) \
  38        (((par)&SC520_PAR_ADDR_MASK) << SC520_PAR_ADDR_SHIFT)
  39
  40#define SC520_PAR_SIZE_MASK     0x01ffc000
  41#define SC520_PAR_SIZE_SHIFT    2
  42#define SC520_PAR_TO_SIZE(par) \
  43        ((((par)&SC520_PAR_SIZE_MASK) << SC520_PAR_SIZE_SHIFT) + (64*1024))
  44
  45#define SC520_PAR(cs, addr, size) \
  46        ((cs) | \
  47        ((((size)-(64*1024)) >> SC520_PAR_SIZE_SHIFT) & SC520_PAR_SIZE_MASK) | \
  48        (((addr) >> SC520_PAR_ADDR_SHIFT) & SC520_PAR_ADDR_MASK))
  49
  50#define SC520_PAR_BOOTCS        0x8a000000
  51#define SC520_PAR_ROMCS1        0xaa000000
  52#define SC520_PAR_ROMCS2        0xca000000      /* Cache disabled, 64K page */
  53
  54static void *nettel_mmcrp = NULL;
  55
  56#ifdef CONFIG_MTD_CFI_INTELEXT
  57static struct mtd_info *intel_mtd;
  58#endif
  59static struct mtd_info *amd_mtd;
  60
  61/****************************************************************************/
  62
  63/****************************************************************************/
  64
  65#ifdef CONFIG_MTD_CFI_INTELEXT
  66static struct map_info nettel_intel_map = {
  67        .name = "SnapGear Intel",
  68        .size = 0,
  69        .bankwidth = INTEL_BUSWIDTH,
  70};
  71
  72static struct mtd_partition nettel_intel_partitions[] = {
  73        {
  74                .name = "SnapGear kernel",
  75                .offset = 0,
  76                .size = 0x000e0000
  77        },
  78        {
  79                .name = "SnapGear filesystem",
  80                .offset = 0x00100000,
  81        },
  82        {
  83                .name = "SnapGear config",
  84                .offset = 0x000e0000,
  85                .size = 0x00020000
  86        },
  87        {
  88                .name = "SnapGear Intel",
  89                .offset = 0
  90        },
  91        {
  92                .name = "SnapGear BIOS Config",
  93                .offset = 0x007e0000,
  94                .size = 0x00020000
  95        },
  96        {
  97                .name = "SnapGear BIOS",
  98                .offset = 0x007e0000,
  99                .size = 0x00020000
 100        },
 101};
 102#endif
 103
 104static struct map_info nettel_amd_map = {
 105        .name = "SnapGear AMD",
 106        .size = AMD_WINDOW_MAXSIZE,
 107        .bankwidth = AMD_BUSWIDTH,
 108};
 109
 110static struct mtd_partition nettel_amd_partitions[] = {
 111        {
 112                .name = "SnapGear BIOS config",
 113                .offset = 0x000e0000,
 114                .size = 0x00010000
 115        },
 116        {
 117                .name = "SnapGear BIOS",
 118                .offset = 0x000f0000,
 119                .size = 0x00010000
 120        },
 121        {
 122                .name = "SnapGear AMD",
 123                .offset = 0
 124        },
 125        {
 126                .name = "SnapGear high BIOS",
 127                .offset = 0x001f0000,
 128                .size = 0x00010000
 129        }
 130};
 131
 132#define NUM_AMD_PARTITIONS ARRAY_SIZE(nettel_amd_partitions)
 133
 134/****************************************************************************/
 135
 136#ifdef CONFIG_MTD_CFI_INTELEXT
 137
 138/*
 139 *      Set the Intel flash back to read mode since some old boot
 140 *      loaders don't.
 141 */
 142static int nettel_reboot_notifier(struct notifier_block *nb, unsigned long val, void *v)
 143{
 144        struct cfi_private *cfi = nettel_intel_map.fldrv_priv;
 145        unsigned long b;
 146
 147        /* Make sure all FLASH chips are put back into read mode */
 148        for (b = 0; (b < nettel_intel_partitions[3].size); b += 0x100000) {
 149                cfi_send_gen_cmd(0xff, 0x55, b, &nettel_intel_map, cfi,
 150                        cfi->device_type, NULL);
 151        }
 152        return(NOTIFY_OK);
 153}
 154
 155static struct notifier_block nettel_notifier_block = {
 156        nettel_reboot_notifier, NULL, 0
 157};
 158
 159#endif
 160
 161/****************************************************************************/
 162
 163static int __init nettel_init(void)
 164{
 165        volatile unsigned long *amdpar;
 166        unsigned long amdaddr, maxsize;
 167        int num_amd_partitions=0;
 168#ifdef CONFIG_MTD_CFI_INTELEXT
 169        volatile unsigned long *intel0par, *intel1par;
 170        unsigned long orig_bootcspar, orig_romcs1par;
 171        unsigned long intel0addr, intel0size;
 172        unsigned long intel1addr, intel1size;
 173        int intelboot, intel0cs, intel1cs;
 174        int num_intel_partitions;
 175#endif
 176        int rc = 0;
 177
 178        nettel_mmcrp = (void *) ioremap_nocache(0xfffef000, 4096);
 179        if (nettel_mmcrp == NULL) {
 180                printk("SNAPGEAR: failed to disable MMCR cache??\n");
 181                return(-EIO);
 182        }
 183
 184        /* Set CPU clock to be 33.000MHz */
 185        *((unsigned char *) (nettel_mmcrp + 0xc64)) = 0x01;
 186
 187        amdpar = (volatile unsigned long *) (nettel_mmcrp + 0xc4);
 188
 189#ifdef CONFIG_MTD_CFI_INTELEXT
 190        intelboot = 0;
 191        intel0cs = SC520_PAR_ROMCS1;
 192        intel0par = (volatile unsigned long *) (nettel_mmcrp + 0xc0);
 193        intel1cs = SC520_PAR_ROMCS2;
 194        intel1par = (volatile unsigned long *) (nettel_mmcrp + 0xbc);
 195
 196        /*
 197         *      Save the CS settings then ensure ROMCS1 and ROMCS2 are off,
 198         *      otherwise they might clash with where we try to map BOOTCS.
 199         */
 200        orig_bootcspar = *amdpar;
 201        orig_romcs1par = *intel0par;
 202        *intel0par = 0;
 203        *intel1par = 0;
 204#endif
 205
 206        /*
 207         *      The first thing to do is determine if we have a separate
 208         *      boot FLASH device. Typically this is a small (1 to 2MB)
 209         *      AMD FLASH part. It seems that device size is about the
 210         *      only way to tell if this is the case...
 211         */
 212        amdaddr = 0x20000000;
 213        maxsize = AMD_WINDOW_MAXSIZE;
 214
 215        *amdpar = SC520_PAR(SC520_PAR_BOOTCS, amdaddr, maxsize);
 216        __asm__ ("wbinvd");
 217
 218        nettel_amd_map.phys = amdaddr;
 219        nettel_amd_map.virt = ioremap_nocache(amdaddr, maxsize);
 220        if (!nettel_amd_map.virt) {
 221                printk("SNAPGEAR: failed to ioremap() BOOTCS\n");
 222                iounmap(nettel_mmcrp);
 223                return(-EIO);
 224        }
 225        simple_map_init(&nettel_amd_map);
 226
 227        if ((amd_mtd = do_map_probe("jedec_probe", &nettel_amd_map))) {
 228                printk(KERN_NOTICE "SNAPGEAR: AMD flash device size = %dK\n",
 229                        (int)(amd_mtd->size>>10));
 230
 231                amd_mtd->owner = THIS_MODULE;
 232
 233                /* The high BIOS partition is only present for 2MB units */
 234                num_amd_partitions = NUM_AMD_PARTITIONS;
 235                if (amd_mtd->size < AMD_WINDOW_MAXSIZE)
 236                        num_amd_partitions--;
 237                /* Don't add the partition until after the primary INTEL's */
 238
 239#ifdef CONFIG_MTD_CFI_INTELEXT
 240                /*
 241                 *      Map the Intel flash into memory after the AMD
 242                 *      It has to start on a multiple of maxsize.
 243                 */
 244                maxsize = SC520_PAR_TO_SIZE(orig_romcs1par);
 245                if (maxsize < (32 * 1024 * 1024))
 246                        maxsize = (32 * 1024 * 1024);
 247                intel0addr = amdaddr + maxsize;
 248#endif
 249        } else {
 250#ifdef CONFIG_MTD_CFI_INTELEXT
 251                /* INTEL boot FLASH */
 252                intelboot++;
 253
 254                if (!orig_romcs1par) {
 255                        intel0cs = SC520_PAR_BOOTCS;
 256                        intel0par = (volatile unsigned long *)
 257                                (nettel_mmcrp + 0xc4);
 258                        intel1cs = SC520_PAR_ROMCS1;
 259                        intel1par = (volatile unsigned long *)
 260                                (nettel_mmcrp + 0xc0);
 261
 262                        intel0addr = SC520_PAR_TO_ADDR(orig_bootcspar);
 263                        maxsize = SC520_PAR_TO_SIZE(orig_bootcspar);
 264                } else {
 265                        /* Kernel base is on ROMCS1, not BOOTCS */
 266                        intel0cs = SC520_PAR_ROMCS1;
 267                        intel0par = (volatile unsigned long *)
 268                                (nettel_mmcrp + 0xc0);
 269                        intel1cs = SC520_PAR_BOOTCS;
 270                        intel1par = (volatile unsigned long *)
 271                                (nettel_mmcrp + 0xc4);
 272
 273                        intel0addr = SC520_PAR_TO_ADDR(orig_romcs1par);
 274                        maxsize = SC520_PAR_TO_SIZE(orig_romcs1par);
 275                }
 276
 277                /* Destroy useless AMD MTD mapping */
 278                amd_mtd = NULL;
 279                iounmap(nettel_amd_map.virt);
 280                nettel_amd_map.virt = NULL;
 281#else
 282                /* Only AMD flash supported */
 283                rc = -ENXIO;
 284                goto out_unmap2;
 285#endif
 286        }
 287
 288#ifdef CONFIG_MTD_CFI_INTELEXT
 289        /*
 290         *      We have determined the INTEL FLASH configuration, so lets
 291         *      go ahead and probe for them now.
 292         */
 293
 294        /* Set PAR to the maximum size */
 295        if (maxsize < (32 * 1024 * 1024))
 296                maxsize = (32 * 1024 * 1024);
 297        *intel0par = SC520_PAR(intel0cs, intel0addr, maxsize);
 298
 299        /* Turn other PAR off so the first probe doesn't find it */
 300        *intel1par = 0;
 301
 302        /* Probe for the size of the first Intel flash */
 303        nettel_intel_map.size = maxsize;
 304        nettel_intel_map.phys = intel0addr;
 305        nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize);
 306        if (!nettel_intel_map.virt) {
 307                printk("SNAPGEAR: failed to ioremap() ROMCS1\n");
 308                rc = -EIO;
 309                goto out_unmap2;
 310        }
 311        simple_map_init(&nettel_intel_map);
 312
 313        intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map);
 314        if (!intel_mtd) {
 315                rc = -ENXIO;
 316                goto out_unmap1;
 317        }
 318
 319        /* Set PAR to the detected size */
 320        intel0size = intel_mtd->size;
 321        *intel0par = SC520_PAR(intel0cs, intel0addr, intel0size);
 322
 323        /*
 324         *      Map second Intel FLASH right after first. Set its size to the
 325         *      same maxsize used for the first Intel FLASH.
 326         */
 327        intel1addr = intel0addr + intel0size;
 328        *intel1par = SC520_PAR(intel1cs, intel1addr, maxsize);
 329        __asm__ ("wbinvd");
 330
 331        maxsize += intel0size;
 332
 333        /* Delete the old map and probe again to do both chips */
 334        map_destroy(intel_mtd);
 335        intel_mtd = NULL;
 336        iounmap(nettel_intel_map.virt);
 337
 338        nettel_intel_map.size = maxsize;
 339        nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize);
 340        if (!nettel_intel_map.virt) {
 341                printk("SNAPGEAR: failed to ioremap() ROMCS1/2\n");
 342                rc = -EIO;
 343                goto out_unmap2;
 344        }
 345
 346        intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map);
 347        if (! intel_mtd) {
 348                rc = -ENXIO;
 349                goto out_unmap1;
 350        }
 351
 352        intel1size = intel_mtd->size - intel0size;
 353        if (intel1size > 0) {
 354                *intel1par = SC520_PAR(intel1cs, intel1addr, intel1size);
 355                __asm__ ("wbinvd");
 356        } else {
 357                *intel1par = 0;
 358        }
 359
 360        printk(KERN_NOTICE "SNAPGEAR: Intel flash device size = %lldKiB\n",
 361               (unsigned long long)(intel_mtd->size >> 10));
 362
 363        intel_mtd->owner = THIS_MODULE;
 364
 365        num_intel_partitions = ARRAY_SIZE(nettel_intel_partitions);
 366
 367        if (intelboot) {
 368                /*
 369                 *      Adjust offset and size of last boot partition.
 370                 *      Must allow for BIOS region at end of FLASH.
 371                 */
 372                nettel_intel_partitions[1].size = (intel0size + intel1size) -
 373                        (1024*1024 + intel_mtd->erasesize);
 374                nettel_intel_partitions[3].size = intel0size + intel1size;
 375                nettel_intel_partitions[4].offset =
 376                        (intel0size + intel1size) - intel_mtd->erasesize;
 377                nettel_intel_partitions[4].size = intel_mtd->erasesize;
 378                nettel_intel_partitions[5].offset =
 379                        nettel_intel_partitions[4].offset;
 380                nettel_intel_partitions[5].size =
 381                        nettel_intel_partitions[4].size;
 382        } else {
 383                /* No BIOS regions when AMD boot */
 384                num_intel_partitions -= 2;
 385        }
 386        rc = mtd_device_register(intel_mtd, nettel_intel_partitions,
 387                                 num_intel_partitions);
 388        if (rc)
 389                goto out_map_destroy;
 390#endif
 391
 392        if (amd_mtd) {
 393                rc = mtd_device_register(amd_mtd, nettel_amd_partitions,
 394                                         num_amd_partitions);
 395                if (rc)
 396                        goto out_mtd_unreg;
 397        }
 398
 399#ifdef CONFIG_MTD_CFI_INTELEXT
 400        register_reboot_notifier(&nettel_notifier_block);
 401#endif
 402
 403        return rc;
 404
 405out_mtd_unreg:
 406#ifdef CONFIG_MTD_CFI_INTELEXT
 407        mtd_device_unregister(intel_mtd);
 408out_map_destroy:
 409        map_destroy(intel_mtd);
 410out_unmap1:
 411        iounmap(nettel_intel_map.virt);
 412#endif
 413
 414out_unmap2:
 415        iounmap(nettel_mmcrp);
 416        iounmap(nettel_amd_map.virt);
 417
 418        return rc;
 419}
 420
 421/****************************************************************************/
 422
 423static void __exit nettel_cleanup(void)
 424{
 425#ifdef CONFIG_MTD_CFI_INTELEXT
 426        unregister_reboot_notifier(&nettel_notifier_block);
 427#endif
 428        if (amd_mtd) {
 429                mtd_device_unregister(amd_mtd);
 430                map_destroy(amd_mtd);
 431        }
 432        if (nettel_mmcrp) {
 433                iounmap(nettel_mmcrp);
 434                nettel_mmcrp = NULL;
 435        }
 436        if (nettel_amd_map.virt) {
 437                iounmap(nettel_amd_map.virt);
 438                nettel_amd_map.virt = NULL;
 439        }
 440#ifdef CONFIG_MTD_CFI_INTELEXT
 441        if (intel_mtd) {
 442                mtd_device_unregister(intel_mtd);
 443                map_destroy(intel_mtd);
 444        }
 445        if (nettel_intel_map.virt) {
 446                iounmap(nettel_intel_map.virt);
 447                nettel_intel_map.virt = NULL;
 448        }
 449#endif
 450}
 451
 452/****************************************************************************/
 453
 454module_init(nettel_init);
 455module_exit(nettel_cleanup);
 456
 457MODULE_LICENSE("GPL");
 458MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>");
 459MODULE_DESCRIPTION("SnapGear/SecureEdge FLASH support");
 460
 461/****************************************************************************/
 462