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 return(-EIO); 281 } 282 simple_map_init(&nettel_amd_map); 283 284 if ((amd_mtd = do_map_probe("jedec_probe", &nettel_amd_map))) { 285 printk(KERN_NOTICE "SNAPGEAR: AMD flash device size = %dK\n", 286 amd_mtd->size>>10); 287 288 amd_mtd->owner = THIS_MODULE; 289 290 /* The high BIOS partition is only present for 2MB units */ 291 num_amd_partitions = NUM_AMD_PARTITIONS; 292 if (amd_mtd->size < AMD_WINDOW_MAXSIZE) 293 num_amd_partitions--; 294 /* Don't add the partition until after the primary INTEL's */ 295 296 #ifdef CONFIG_MTD_CFI_INTELEXT 297 /* 298 * Map the Intel flash into memory after the AMD 299 * It has to start on a multiple of maxsize. 300 */ 301 maxsize = SC520_PAR_TO_SIZE(orig_romcs1par); 302 if (maxsize < (32 * 1024 * 1024)) 303 maxsize = (32 * 1024 * 1024); 304 intel0addr = amdaddr + maxsize; 305 #endif 306 } else { 307 #ifdef CONFIG_MTD_CFI_INTELEXT 308 /* INTEL boot FLASH */ 309 intelboot++; 310 311 if (!orig_romcs1par) { 312 intel0cs = SC520_PAR_BOOTCS; 313 intel0par = (volatile unsigned long *) 314 (nettel_mmcrp + 0xc4); 315 intel1cs = SC520_PAR_ROMCS1; 316 intel1par = (volatile unsigned long *) 317 (nettel_mmcrp + 0xc0); 318 319 intel0addr = SC520_PAR_TO_ADDR(orig_bootcspar); 320 maxsize = SC520_PAR_TO_SIZE(orig_bootcspar); 321 } else { 322 /* Kernel base is on ROMCS1, not BOOTCS */ 323 intel0cs = SC520_PAR_ROMCS1; 324 intel0par = (volatile unsigned long *) 325 (nettel_mmcrp + 0xc0); 326 intel1cs = SC520_PAR_BOOTCS; 327 intel1par = (volatile unsigned long *) 328 (nettel_mmcrp + 0xc4); 329 330 intel0addr = SC520_PAR_TO_ADDR(orig_romcs1par); 331 maxsize = SC520_PAR_TO_SIZE(orig_romcs1par); 332 } 333 334 /* Destroy useless AMD MTD mapping */ 335 amd_mtd = NULL; 336 iounmap(nettel_amd_map.virt); 337 nettel_amd_map.virt = NULL; 338 #else 339 /* Only AMD flash supported */ 340 return(-ENXIO); 341 #endif 342 } 343 344 #ifdef CONFIG_MTD_CFI_INTELEXT 345 /* 346 * We have determined the INTEL FLASH configuration, so lets 347 * go ahead and probe for them now. 348 */ 349 350 /* Set PAR to the maximum size */ 351 if (maxsize < (32 * 1024 * 1024)) 352 maxsize = (32 * 1024 * 1024); 353 *intel0par = SC520_PAR(intel0cs, intel0addr, maxsize); 354 355 /* Turn other PAR off so the first probe doesn't find it */ 356 *intel1par = 0; 357 358 /* Probe for the the size of the first Intel flash */ 359 nettel_intel_map.size = maxsize; 360 nettel_intel_map.phys = intel0addr; 361 nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize); 362 if (!nettel_intel_map.virt) { 363 printk("SNAPGEAR: failed to ioremap() ROMCS1\n"); 364 return(-EIO); 365 } 366 simple_map_init(&nettel_intel_map); 367 368 intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map); 369 if (!intel_mtd) { 370 iounmap(nettel_intel_map.virt); 371 return(-ENXIO); 372 } 373 374 /* Set PAR to the detected size */ 375 intel0size = intel_mtd->size; 376 *intel0par = SC520_PAR(intel0cs, intel0addr, intel0size); 377 378 /* 379 * Map second Intel FLASH right after first. Set its size to the 380 * same maxsize used for the first Intel FLASH. 381 */ 382 intel1addr = intel0addr + intel0size; 383 *intel1par = SC520_PAR(intel1cs, intel1addr, maxsize); 384 __asm__ ("wbinvd"); 385 386 maxsize += intel0size; 387 388 /* Delete the old map and probe again to do both chips */ 389 map_destroy(intel_mtd); 390 intel_mtd = NULL; 391 iounmap(nettel_intel_map.virt); 392 393 nettel_intel_map.size = maxsize; 394 nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize); 395 if (!nettel_intel_map.virt) { 396 printk("SNAPGEAR: failed to ioremap() ROMCS1/2\n"); 397 return(-EIO); 398 } 399 400 intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map); 401 if (! intel_mtd) { 402 iounmap((void *) nettel_intel_map.virt); 403 return(-ENXIO); 404 } 405 406 intel1size = intel_mtd->size - intel0size; 407 if (intel1size > 0) { 408 *intel1par = SC520_PAR(intel1cs, intel1addr, intel1size); 409 __asm__ ("wbinvd"); 410 } else { 411 *intel1par = 0; 412 } 413 414 printk(KERN_NOTICE "SNAPGEAR: Intel flash device size = %dK\n", 415 (intel_mtd->size >> 10)); 416 417 intel_mtd->owner = THIS_MODULE; 418 419 #ifndef CONFIG_BLK_DEV_INITRD 420 ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 1); 421 #endif 422 423 num_intel_partitions = sizeof(nettel_intel_partitions) / 424 sizeof(nettel_intel_partitions[0]); 425 426 if (intelboot) { 427 /* 428 * Adjust offset and size of last boot partition. 429 * Must allow for BIOS region at end of FLASH. 430 */ 431 nettel_intel_partitions[1].size = (intel0size + intel1size) - 432 (1024*1024 + intel_mtd->erasesize); 433 nettel_intel_partitions[3].size = intel0size + intel1size; 434 nettel_intel_partitions[4].offset = 435 (intel0size + intel1size) - intel_mtd->erasesize; 436 nettel_intel_partitions[4].size = intel_mtd->erasesize; 437 nettel_intel_partitions[5].offset = 438 nettel_intel_partitions[4].offset; 439 nettel_intel_partitions[5].size = 440 nettel_intel_partitions[4].size; 441 } else { 442 /* No BIOS regions when AMD boot */ 443 num_intel_partitions -= 2; 444 } 445 rc = add_mtd_partitions(intel_mtd, nettel_intel_partitions, 446 num_intel_partitions); 447 #endif 448 449 if (amd_mtd) { 450 rc = add_mtd_partitions(amd_mtd, nettel_amd_partitions, 451 num_amd_partitions); 452 } 453 454 #ifdef CONFIG_MTD_CFI_INTELEXT 455 register_reboot_notifier(&nettel_notifier_block); 456 #endif 457 458 return(rc); 459 } 460 461 /****************************************************************************/ 462 463 void __exit nettel_cleanup(void) 464 { 465 #ifdef CONFIG_MTD_CFI_INTELEXT 466 unregister_reboot_notifier(&nettel_notifier_block); 467 #endif 468 if (amd_mtd) { 469 del_mtd_partitions(amd_mtd); 470 map_destroy(amd_mtd); 471 } 472 if (nettel_amd_map.virt) { 473 iounmap(nettel_amd_map.virt); 474 nettel_amd_map.virt = NULL; 475 } 476 #ifdef CONFIG_MTD_CFI_INTELEXT 477 if (intel_mtd) { 478 del_mtd_partitions(intel_mtd); 479 map_destroy(intel_mtd); 480 } 481 if (nettel_intel_map.virt) { 482 iounmap(nettel_intel_map.virt); 483 nettel_intel_map.virt = NULL; 484 } 485 #endif 486 } 487 488 /****************************************************************************/ 489 490 module_init(nettel_init); 491 module_exit(nettel_cleanup); 492 493 MODULE_LICENSE("GPL"); 494 MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>"); 495 MODULE_DESCRIPTION("SnapGear/SecureEdge FLASH support"); 496 497 /****************************************************************************/ 498