nettel.c (11842B)
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/****************************************************************************/