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