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