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 * $Id: nettel.c,v 1.12 2005/11/29 14:30:00 gleixner Exp $ 10 */ 11 12 /****************************************************************************/ 13 14 #include <linux/module.h> 15 #include <linux/init.h> 16 #include <linux/types.h> 17 #include <linux/kernel.h> 18 #include <linux/mtd/mtd.h> 19 #include <linux/mtd/map.h> 20 #include <linux/mtd/partitions.h> 21 #include <linux/mtd/cfi.h> 22 #include <linux/reboot.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 55 static void *nettel_mmcrp = NULL; 56 57 #ifdef CONFIG_MTD_CFI_INTELEXT 58 static struct mtd_info *intel_mtd; 59 #endif 60 static struct mtd_info *amd_mtd; 61 62 /****************************************************************************/ 63 64 /****************************************************************************/ 65 66 #ifdef CONFIG_MTD_CFI_INTELEXT 67 static struct map_info nettel_intel_map = { 68 .name = "SnapGear Intel", 69 .size = 0, 70 .bankwidth = INTEL_BUSWIDTH, 71 }; 72 73 static 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 105 static struct map_info nettel_amd_map = { 106 .name = "SnapGear AMD", 107 .size = AMD_WINDOW_MAXSIZE, 108 .bankwidth = AMD_BUSWIDTH, 109 }; 110 111 static 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 */ 143 static 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 156 static struct notifier_block nettel_notifier_block = { 157 nettel_reboot_notifier, NULL, 0 158 }; 159 160 /* 161 * Erase the configuration file system. 162 * Used to support the software reset button. 163 */ 164 static void nettel_erasecallback(struct erase_info *done) 165 { 166 wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv; 167 wake_up(wait_q); 168 } 169 170 static struct erase_info nettel_erase; 171 172 int nettel_eraseconfig(void) 173 { 174 struct mtd_info *mtd; 175 DECLARE_WAITQUEUE(wait, current); 176 wait_queue_head_t wait_q; 177 int ret; 178 179 init_waitqueue_head(&wait_q); 180 mtd = get_mtd_device(NULL, 2); 181 if (mtd) { 182 nettel_erase.mtd = mtd; 183 nettel_erase.callback = nettel_erasecallback; 184 nettel_erase.callback = NULL; 185 nettel_erase.addr = 0; 186 nettel_erase.len = mtd->size; 187 nettel_erase.priv = (u_long) &wait_q; 188 nettel_erase.priv = 0; 189 190 set_current_state(TASK_INTERRUPTIBLE); 191 add_wait_queue(&wait_q, &wait); 192 193 ret = mtd->erase(mtd, &nettel_erase); 194 if (ret) { 195 set_current_state(TASK_RUNNING); 196 remove_wait_queue(&wait_q, &wait); 197 put_mtd_device(mtd); 198 return(ret); 199 } 200 201 schedule(); /* Wait for erase to finish. */ 202 remove_wait_queue(&wait_q, &wait); 203 204 put_mtd_device(mtd); 205 } 206 207 return(0); 208 } 209 210 #else 211 212 int nettel_eraseconfig(void) 213 { 214 return(0); 215 } 216 217 #endif 218 219 /****************************************************************************/ 220 221 int __init nettel_init(void) 222 { 223 volatile unsigned long *amdpar; 224 unsigned long amdaddr, maxsize; 225 int num_amd_partitions=0; 226 #ifdef CONFIG_MTD_CFI_INTELEXT 227 volatile unsigned long *intel0par, *intel1par; 228 unsigned long orig_bootcspar, orig_romcs1par; 229 unsigned long intel0addr, intel0size; 230 unsigned long intel1addr, intel1size; 231 int intelboot, intel0cs, intel1cs; 232 int num_intel_partitions; 233 #endif 234 int rc = 0; 235 236 nettel_mmcrp = (void *) ioremap_nocache(0xfffef000, 4096); 237 if (nettel_mmcrp == NULL) { 238 printk("SNAPGEAR: failed to disable MMCR cache??\n"); 239 return(-EIO); 240 } 241 242 /* Set CPU clock to be 33.000MHz */ 243 *((unsigned char *) (nettel_mmcrp + 0xc64)) = 0x01; 244 245 amdpar = (volatile unsigned long *) (nettel_mmcrp + 0xc4); 246 247 #ifdef CONFIG_MTD_CFI_INTELEXT 248 intelboot = 0; 249 intel0cs = SC520_PAR_ROMCS1; 250 intel0par = (volatile unsigned long *) (nettel_mmcrp + 0xc0); 251 intel1cs = SC520_PAR_ROMCS2; 252 intel1par = (volatile unsigned long *) (nettel_mmcrp + 0xbc); 253 254 /* 255 * Save the CS settings then ensure ROMCS1 and ROMCS2 are off, 256 * otherwise they might clash with where we try to map BOOTCS. 257 */ 258 orig_bootcspar = *amdpar; 259 orig_romcs1par = *intel0par; 260 *intel0par = 0; 261 *intel1par = 0; 262 #endif 263 264 /* 265 * The first thing to do is determine if we have a separate 266 * boot FLASH device. Typically this is a small (1 to 2MB) 267 * AMD FLASH part. It seems that device size is about the 268 * only way to tell if this is the case... 269 */ 270 amdaddr = 0x20000000; 271 maxsize = AMD_WINDOW_MAXSIZE; 272 273 *amdpar = SC520_PAR(SC520_PAR_BOOTCS, amdaddr, maxsize); 274 __asm__ ("wbinvd"); 275 276 nettel_amd_map.phys = amdaddr; 277 nettel_amd_map.virt = ioremap_nocache(amdaddr, maxsize); 278 if (!nettel_amd_map.virt) { 279 printk("SNAPGEAR: failed to ioremap() BOOTCS\n"); 280 iounmap(nettel_mmcrp); 281 return(-EIO); 282 } 283 simple_map_init(&nettel_amd_map); 284 285 if ((amd_mtd = do_map_probe("jedec_probe", &nettel_amd_map))) { 286 printk(KERN_NOTICE "SNAPGEAR: AMD flash device size = %dK\n", 287 amd_mtd->size>>10); 288 289 amd_mtd->owner = THIS_MODULE; 290 291 /* The high BIOS partition is only present for 2MB units */ 292 num_amd_partitions = NUM_AMD_PARTITIONS; 293 if (amd_mtd->size < AMD_WINDOW_MAXSIZE) 294 num_amd_partitions--; 295 /* Don't add the partition until after the primary INTEL's */ 296 297 #ifdef CONFIG_MTD_CFI_INTELEXT 298 /* 299 * Map the Intel flash into memory after the AMD 300 * It has to start on a multiple of maxsize. 301 */ 302 maxsize = SC520_PAR_TO_SIZE(orig_romcs1par); 303 if (maxsize < (32 * 1024 * 1024)) 304 maxsize = (32 * 1024 * 1024); 305 intel0addr = amdaddr + maxsize; 306 #endif 307 } else { 308 #ifdef CONFIG_MTD_CFI_INTELEXT 309 /* INTEL boot FLASH */ 310 intelboot++; 311 312 if (!orig_romcs1par) { 313 intel0cs = SC520_PAR_BOOTCS; 314 intel0par = (volatile unsigned long *) 315 (nettel_mmcrp + 0xc4); 316 intel1cs = SC520_PAR_ROMCS1; 317 intel1par = (volatile unsigned long *) 318 (nettel_mmcrp + 0xc0); 319 320 intel0addr = SC520_PAR_TO_ADDR(orig_bootcspar); 321 maxsize = SC520_PAR_TO_SIZE(orig_bootcspar); 322 } else { 323 /* Kernel base is on ROMCS1, not BOOTCS */ 324 intel0cs = SC520_PAR_ROMCS1; 325 intel0par = (volatile unsigned long *) 326 (nettel_mmcrp + 0xc0); 327 intel1cs = SC520_PAR_BOOTCS; 328 intel1par = (volatile unsigned long *) 329 (nettel_mmcrp + 0xc4); 330 331 intel0addr = SC520_PAR_TO_ADDR(orig_romcs1par); 332 maxsize = SC520_PAR_TO_SIZE(orig_romcs1par); 333 } 334 335 /* Destroy useless AMD MTD mapping */ 336 amd_mtd = NULL; 337 iounmap(nettel_amd_map.virt); 338 nettel_amd_map.virt = NULL; 339 #else 340 /* Only AMD flash supported */ 341 rc = -ENXIO; 342 goto out_unmap2; 343 #endif 344 } 345 346 #ifdef CONFIG_MTD_CFI_INTELEXT 347 /* 348 * We have determined the INTEL FLASH configuration, so lets 349 * go ahead and probe for them now. 350 */ 351 352 /* Set PAR to the maximum size */ 353 if (maxsize < (32 * 1024 * 1024)) 354 maxsize = (32 * 1024 * 1024); 355 *intel0par = SC520_PAR(intel0cs, intel0addr, maxsize); 356 357 /* Turn other PAR off so the first probe doesn't find it */ 358 *intel1par = 0; 359 360 /* Probe for the the size of the first Intel flash */ 361 nettel_intel_map.size = maxsize; 362 nettel_intel_map.phys = intel0addr; 363 nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize); 364 if (!nettel_intel_map.virt) { 365 printk("SNAPGEAR: failed to ioremap() ROMCS1\n"); 366 rc = -EIO; 367 goto out_unmap2; 368 } 369 simple_map_init(&nettel_intel_map); 370 371 intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map); 372 if (!intel_mtd) { 373 rc = -ENXIO; 374 goto out_unmap1; 375 } 376 377 /* Set PAR to the detected size */ 378 intel0size = intel_mtd->size; 379 *intel0par = SC520_PAR(intel0cs, intel0addr, intel0size); 380 381 /* 382 * Map second Intel FLASH right after first. Set its size to the 383 * same maxsize used for the first Intel FLASH. 384 */ 385 intel1addr = intel0addr + intel0size; 386 *intel1par = SC520_PAR(intel1cs, intel1addr, maxsize); 387 __asm__ ("wbinvd"); 388 389 maxsize += intel0size; 390 391 /* Delete the old map and probe again to do both chips */ 392 map_destroy(intel_mtd); 393 intel_mtd = NULL; 394 iounmap(nettel_intel_map.virt); 395 396 nettel_intel_map.size = maxsize; 397 nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize); 398 if (!nettel_intel_map.virt) { 399 printk("SNAPGEAR: failed to ioremap() ROMCS1/2\n"); 400 rc = -EIO; 401 goto out_unmap2; 402 } 403 404 intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map); 405 if (! intel_mtd) { 406 rc = -ENXIO; 407 goto out_unmap1; 408 } 409 410 intel1size = intel_mtd->size - intel0size; 411 if (intel1size > 0) { 412 *intel1par = SC520_PAR(intel1cs, intel1addr, intel1size); 413 __asm__ ("wbinvd"); 414 } else { 415 *intel1par = 0; 416 } 417 418 printk(KERN_NOTICE "SNAPGEAR: Intel flash device size = %dK\n", 419 (intel_mtd->size >> 10)); 420 421 intel_mtd->owner = THIS_MODULE; 422 423 #ifndef CONFIG_BLK_DEV_INITRD 424 ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 1); 425 #endif 426 427 num_intel_partitions = sizeof(nettel_intel_partitions) / 428 sizeof(nettel_intel_partitions[0]); 429 430 if (intelboot) { 431 /* 432 * Adjust offset and size of last boot partition. 433 * Must allow for BIOS region at end of FLASH. 434 */ 435 nettel_intel_partitions[1].size = (intel0size + intel1size) - 436 (1024*1024 + intel_mtd->erasesize); 437 nettel_intel_partitions[3].size = intel0size + intel1size; 438 nettel_intel_partitions[4].offset = 439 (intel0size + intel1size) - intel_mtd->erasesize; 440 nettel_intel_partitions[4].size = intel_mtd->erasesize; 441 nettel_intel_partitions[5].offset = 442 nettel_intel_partitions[4].offset; 443 nettel_intel_partitions[5].size = 444 nettel_intel_partitions[4].size; 445 } else { 446 /* No BIOS regions when AMD boot */ 447 num_intel_partitions -= 2; 448 } 449 rc = add_mtd_partitions(intel_mtd, nettel_intel_partitions, 450 num_intel_partitions); 451 #endif 452 453 if (amd_mtd) { 454 rc = add_mtd_partitions(amd_mtd, nettel_amd_partitions, 455 num_amd_partitions); 456 } 457 458 #ifdef CONFIG_MTD_CFI_INTELEXT 459 register_reboot_notifier(&nettel_notifier_block); 460 #endif 461 462 return(rc); 463 464 #ifdef CONFIG_MTD_CFI_INTELEXT 465 out_unmap1: 466 iounmap((void *) nettel_intel_map.virt); 467 #endif 468 469 out_unmap2: 470 iounmap(nettel_mmcrp); 471 iounmap(nettel_amd_map.virt); 472 473 return(rc); 474 475 } 476 477 /****************************************************************************/ 478 479 void __exit nettel_cleanup(void) 480 { 481 #ifdef CONFIG_MTD_CFI_INTELEXT 482 unregister_reboot_notifier(&nettel_notifier_block); 483 #endif 484 if (amd_mtd) { 485 del_mtd_partitions(amd_mtd); 486 map_destroy(amd_mtd); 487 } 488 if (nettel_mmcrp) { 489 iounmap(nettel_mmcrp); 490 nettel_mmcrp = NULL; 491 } 492 if (nettel_amd_map.virt) { 493 iounmap(nettel_amd_map.virt); 494 nettel_amd_map.virt = NULL; 495 } 496 #ifdef CONFIG_MTD_CFI_INTELEXT 497 if (intel_mtd) { 498 del_mtd_partitions(intel_mtd); 499 map_destroy(intel_mtd); 500 } 501 if (nettel_intel_map.virt) { 502 iounmap(nettel_intel_map.virt); 503 nettel_intel_map.virt = NULL; 504 } 505 #endif 506 } 507 508 /****************************************************************************/ 509 510 module_init(nettel_init); 511 module_exit(nettel_cleanup); 512 513 MODULE_LICENSE("GPL"); 514 MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>"); 515 MODULE_DESCRIPTION("SnapGear/SecureEdge FLASH support"); 516 517 /****************************************************************************/ 518