nettel.c revision f4a43cfcecfcaeeaa40a9dbc1d1378298c22446e
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 55static void *nettel_mmcrp = NULL; 56 57#ifdef CONFIG_MTD_CFI_INTELEXT 58static struct mtd_info *intel_mtd; 59#endif 60static struct mtd_info *amd_mtd; 61 62/****************************************************************************/ 63 64/****************************************************************************/ 65 66#ifdef CONFIG_MTD_CFI_INTELEXT 67static struct map_info nettel_intel_map = { 68 .name = "SnapGear Intel", 69 .size = 0, 70 .bankwidth = INTEL_BUSWIDTH, 71}; 72 73static 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 105static struct map_info nettel_amd_map = { 106 .name = "SnapGear AMD", 107 .size = AMD_WINDOW_MAXSIZE, 108 .bankwidth = AMD_BUSWIDTH, 109}; 110 111static 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 */ 143static 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 156static 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 */ 164static 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 170static struct erase_info nettel_erase; 171 172int 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 212int nettel_eraseconfig(void) 213{ 214 return(0); 215} 216 217#endif 218 219/****************************************************************************/ 220 221int __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 463void __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 490module_init(nettel_init); 491module_exit(nettel_cleanup); 492 493MODULE_LICENSE("GPL"); 494MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>"); 495MODULE_DESCRIPTION("SnapGear/SecureEdge FLASH support"); 496 497/****************************************************************************/ 498