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