463 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/****************************************************************************/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 130#define AMD_WINDOW_MAXSIZE 0x0020000031#define AMD_BUSWIDTH 132 33/*34 * PAR masks and shifts, assuming 64K pages.35 */36#define SC520_PAR_ADDR_MASK 0x00003fff37#define SC520_PAR_ADDR_SHIFT 1638#define SC520_PAR_TO_ADDR(par) \39 (((par)&SC520_PAR_ADDR_MASK) << SC520_PAR_ADDR_SHIFT)40 41#define SC520_PAR_SIZE_MASK 0x01ffc00042#define SC520_PAR_SIZE_SHIFT 243#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 0x8a00000052#define SC520_PAR_ROMCS1 0xaa00000053#define SC520_PAR_ROMCS2 0xca000000 /* Cache disabled, 64K page */54 55static void *nettel_mmcrp = NULL;56 57#ifdef CONFIG_MTD_CFI_INTELEXT58static struct mtd_info *intel_mtd;59#endif60static struct mtd_info *amd_mtd;61 62/****************************************************************************/63 64/****************************************************************************/65 66#ifdef CONFIG_MTD_CFI_INTELEXT67static 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 = 0x000e000078 },79 {80 .name = "SnapGear filesystem",81 .offset = 0x00100000,82 },83 {84 .name = "SnapGear config",85 .offset = 0x000e0000,86 .size = 0x0002000087 },88 {89 .name = "SnapGear Intel",90 .offset = 091 },92 {93 .name = "SnapGear BIOS Config",94 .offset = 0x007e0000,95 .size = 0x0002000096 },97 {98 .name = "SnapGear BIOS",99 .offset = 0x007e0000,100 .size = 0x00020000101 },102};103#endif104 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 = 0x00010000116 },117 {118 .name = "SnapGear BIOS",119 .offset = 0x000f0000,120 .size = 0x00010000121 },122 {123 .name = "SnapGear AMD",124 .offset = 0125 },126 {127 .name = "SnapGear high BIOS",128 .offset = 0x001f0000,129 .size = 0x00010000130 }131};132 133#define NUM_AMD_PARTITIONS ARRAY_SIZE(nettel_amd_partitions)134 135/****************************************************************************/136 137#ifdef CONFIG_MTD_CFI_INTELEXT138 139/*140 * Set the Intel flash back to read mode since some old boot141 * 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, 0158};159 160#endif161 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_INTELEXT170 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#endif177 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_INTELEXT191 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#endif206 207 /*208 * The first thing to do is determine if we have a separate209 * boot FLASH device. Typically this is a small (1 to 2MB)210 * AMD FLASH part. It seems that device size is about the211 * 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_INTELEXT241 /*242 * Map the Intel flash into memory after the AMD243 * 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#endif250 } else {251#ifdef CONFIG_MTD_CFI_INTELEXT252 /* 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#else283 /* Only AMD flash supported */284 rc = -ENXIO;285 goto out_unmap2;286#endif287 }288 289#ifdef CONFIG_MTD_CFI_INTELEXT290 /*291 * We have determined the INTEL FLASH configuration, so lets292 * 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 the326 * 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#endif392 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_INTELEXT401 register_reboot_notifier(&nettel_notifier_block);402#endif403 404 return rc;405 406out_mtd_unreg:407#ifdef CONFIG_MTD_CFI_INTELEXT408 mtd_device_unregister(intel_mtd);409out_map_destroy:410 map_destroy(intel_mtd);411out_unmap1:412 iounmap(nettel_intel_map.virt);413#endif414 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_INTELEXT427 unregister_reboot_notifier(&nettel_notifier_block);428#endif429 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_INTELEXT442 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#endif451}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