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