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 #endif 162 163 /****************************************************************************/ 164 165 static int __init nettel_init(void) 166 { 167 volatile unsigned long *amdpar; 168 unsigned long amdaddr, maxsize; 169 int num_amd_partitions=0; 170 #ifdef CONFIG_MTD_CFI_INTELEXT 171 volatile unsigned long *intel0par, *intel1par; 172 unsigned long orig_bootcspar, orig_romcs1par; 173 unsigned long intel0addr, intel0size; 174 unsigned long intel1addr, intel1size; 175 int intelboot, intel0cs, intel1cs; 176 int num_intel_partitions; 177 #endif 178 int rc = 0; 179 180 nettel_mmcrp = (void *) ioremap_nocache(0xfffef000, 4096); 181 if (nettel_mmcrp == NULL) { 182 printk("SNAPGEAR: failed to disable MMCR cache??\n"); 183 return(-EIO); 184 } 185 186 /* Set CPU clock to be 33.000MHz */ 187 *((unsigned char *) (nettel_mmcrp + 0xc64)) = 0x01; 188 189 amdpar = (volatile unsigned long *) (nettel_mmcrp + 0xc4); 190 191 #ifdef CONFIG_MTD_CFI_INTELEXT 192 intelboot = 0; 193 intel0cs = SC520_PAR_ROMCS1; 194 intel0par = (volatile unsigned long *) (nettel_mmcrp + 0xc0); 195 intel1cs = SC520_PAR_ROMCS2; 196 intel1par = (volatile unsigned long *) (nettel_mmcrp + 0xbc); 197 198 /* 199 * Save the CS settings then ensure ROMCS1 and ROMCS2 are off, 200 * otherwise they might clash with where we try to map BOOTCS. 201 */ 202 orig_bootcspar = *amdpar; 203 orig_romcs1par = *intel0par; 204 *intel0par = 0; 205 *intel1par = 0; 206 #endif 207 208 /* 209 * The first thing to do is determine if we have a separate 210 * boot FLASH device. Typically this is a small (1 to 2MB) 211 * AMD FLASH part. It seems that device size is about the 212 * only way to tell if this is the case... 213 */ 214 amdaddr = 0x20000000; 215 maxsize = AMD_WINDOW_MAXSIZE; 216 217 *amdpar = SC520_PAR(SC520_PAR_BOOTCS, amdaddr, maxsize); 218 __asm__ ("wbinvd"); 219 220 nettel_amd_map.phys = amdaddr; 221 nettel_amd_map.virt = ioremap_nocache(amdaddr, maxsize); 222 if (!nettel_amd_map.virt) { 223 printk("SNAPGEAR: failed to ioremap() BOOTCS\n"); 224 iounmap(nettel_mmcrp); 225 return(-EIO); 226 } 227 simple_map_init(&nettel_amd_map); 228 229 if ((amd_mtd = do_map_probe("jedec_probe", &nettel_amd_map))) { 230 printk(KERN_NOTICE "SNAPGEAR: AMD flash device size = %dK\n", 231 amd_mtd->size>>10); 232 233 amd_mtd->owner = THIS_MODULE; 234 235 /* The high BIOS partition is only present for 2MB units */ 236 num_amd_partitions = NUM_AMD_PARTITIONS; 237 if (amd_mtd->size < AMD_WINDOW_MAXSIZE) 238 num_amd_partitions--; 239 /* Don't add the partition until after the primary INTEL's */ 240 241 #ifdef CONFIG_MTD_CFI_INTELEXT 242 /* 243 * Map the Intel flash into memory after the AMD 244 * It has to start on a multiple of maxsize. 245 */ 246 maxsize = SC520_PAR_TO_SIZE(orig_romcs1par); 247 if (maxsize < (32 * 1024 * 1024)) 248 maxsize = (32 * 1024 * 1024); 249 intel0addr = amdaddr + maxsize; 250 #endif 251 } else { 252 #ifdef CONFIG_MTD_CFI_INTELEXT 253 /* INTEL boot FLASH */ 254 intelboot++; 255 256 if (!orig_romcs1par) { 257 intel0cs = SC520_PAR_BOOTCS; 258 intel0par = (volatile unsigned long *) 259 (nettel_mmcrp + 0xc4); 260 intel1cs = SC520_PAR_ROMCS1; 261 intel1par = (volatile unsigned long *) 262 (nettel_mmcrp + 0xc0); 263 264 intel0addr = SC520_PAR_TO_ADDR(orig_bootcspar); 265 maxsize = SC520_PAR_TO_SIZE(orig_bootcspar); 266 } else { 267 /* Kernel base is on ROMCS1, not BOOTCS */ 268 intel0cs = SC520_PAR_ROMCS1; 269 intel0par = (volatile unsigned long *) 270 (nettel_mmcrp + 0xc0); 271 intel1cs = SC520_PAR_BOOTCS; 272 intel1par = (volatile unsigned long *) 273 (nettel_mmcrp + 0xc4); 274 275 intel0addr = SC520_PAR_TO_ADDR(orig_romcs1par); 276 maxsize = SC520_PAR_TO_SIZE(orig_romcs1par); 277 } 278 279 /* Destroy useless AMD MTD mapping */ 280 amd_mtd = NULL; 281 iounmap(nettel_amd_map.virt); 282 nettel_amd_map.virt = NULL; 283 #else 284 /* Only AMD flash supported */ 285 rc = -ENXIO; 286 goto out_unmap2; 287 #endif 288 } 289 290 #ifdef CONFIG_MTD_CFI_INTELEXT 291 /* 292 * We have determined the INTEL FLASH configuration, so lets 293 * go ahead and probe for them now. 294 */ 295 296 /* Set PAR to the maximum size */ 297 if (maxsize < (32 * 1024 * 1024)) 298 maxsize = (32 * 1024 * 1024); 299 *intel0par = SC520_PAR(intel0cs, intel0addr, maxsize); 300 301 /* Turn other PAR off so the first probe doesn't find it */ 302 *intel1par = 0; 303 304 /* Probe for the size of the first Intel flash */ 305 nettel_intel_map.size = maxsize; 306 nettel_intel_map.phys = intel0addr; 307 nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize); 308 if (!nettel_intel_map.virt) { 309 printk("SNAPGEAR: failed to ioremap() ROMCS1\n"); 310 rc = -EIO; 311 goto out_unmap2; 312 } 313 simple_map_init(&nettel_intel_map); 314 315 intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map); 316 if (!intel_mtd) { 317 rc = -ENXIO; 318 goto out_unmap1; 319 } 320 321 /* Set PAR to the detected size */ 322 intel0size = intel_mtd->size; 323 *intel0par = SC520_PAR(intel0cs, intel0addr, intel0size); 324 325 /* 326 * Map second Intel FLASH right after first. Set its size to the 327 * same maxsize used for the first Intel FLASH. 328 */ 329 intel1addr = intel0addr + intel0size; 330 *intel1par = SC520_PAR(intel1cs, intel1addr, maxsize); 331 __asm__ ("wbinvd"); 332 333 maxsize += intel0size; 334 335 /* Delete the old map and probe again to do both chips */ 336 map_destroy(intel_mtd); 337 intel_mtd = NULL; 338 iounmap(nettel_intel_map.virt); 339 340 nettel_intel_map.size = maxsize; 341 nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize); 342 if (!nettel_intel_map.virt) { 343 printk("SNAPGEAR: failed to ioremap() ROMCS1/2\n"); 344 rc = -EIO; 345 goto out_unmap2; 346 } 347 348 intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map); 349 if (! intel_mtd) { 350 rc = -ENXIO; 351 goto out_unmap1; 352 } 353 354 intel1size = intel_mtd->size - intel0size; 355 if (intel1size > 0) { 356 *intel1par = SC520_PAR(intel1cs, intel1addr, intel1size); 357 __asm__ ("wbinvd"); 358 } else { 359 *intel1par = 0; 360 } 361 362 printk(KERN_NOTICE "SNAPGEAR: Intel flash device size = %dK\n", 363 (intel_mtd->size >> 10)); 364 365 intel_mtd->owner = THIS_MODULE; 366 367 num_intel_partitions = sizeof(nettel_intel_partitions) / 368 sizeof(nettel_intel_partitions[0]); 369 370 if (intelboot) { 371 /* 372 * Adjust offset and size of last boot partition. 373 * Must allow for BIOS region at end of FLASH. 374 */ 375 nettel_intel_partitions[1].size = (intel0size + intel1size) - 376 (1024*1024 + intel_mtd->erasesize); 377 nettel_intel_partitions[3].size = intel0size + intel1size; 378 nettel_intel_partitions[4].offset = 379 (intel0size + intel1size) - intel_mtd->erasesize; 380 nettel_intel_partitions[4].size = intel_mtd->erasesize; 381 nettel_intel_partitions[5].offset = 382 nettel_intel_partitions[4].offset; 383 nettel_intel_partitions[5].size = 384 nettel_intel_partitions[4].size; 385 } else { 386 /* No BIOS regions when AMD boot */ 387 num_intel_partitions -= 2; 388 } 389 rc = add_mtd_partitions(intel_mtd, nettel_intel_partitions, 390 num_intel_partitions); 391 #endif 392 393 if (amd_mtd) { 394 rc = add_mtd_partitions(amd_mtd, nettel_amd_partitions, 395 num_amd_partitions); 396 } 397 398 #ifdef CONFIG_MTD_CFI_INTELEXT 399 register_reboot_notifier(&nettel_notifier_block); 400 #endif 401 402 return(rc); 403 404 #ifdef CONFIG_MTD_CFI_INTELEXT 405 out_unmap1: 406 iounmap(nettel_intel_map.virt); 407 #endif 408 409 out_unmap2: 410 iounmap(nettel_mmcrp); 411 iounmap(nettel_amd_map.virt); 412 413 return(rc); 414 415 } 416 417 /****************************************************************************/ 418 419 static void __exit nettel_cleanup(void) 420 { 421 #ifdef CONFIG_MTD_CFI_INTELEXT 422 unregister_reboot_notifier(&nettel_notifier_block); 423 #endif 424 if (amd_mtd) { 425 del_mtd_partitions(amd_mtd); 426 map_destroy(amd_mtd); 427 } 428 if (nettel_mmcrp) { 429 iounmap(nettel_mmcrp); 430 nettel_mmcrp = NULL; 431 } 432 if (nettel_amd_map.virt) { 433 iounmap(nettel_amd_map.virt); 434 nettel_amd_map.virt = NULL; 435 } 436 #ifdef CONFIG_MTD_CFI_INTELEXT 437 if (intel_mtd) { 438 del_mtd_partitions(intel_mtd); 439 map_destroy(intel_mtd); 440 } 441 if (nettel_intel_map.virt) { 442 iounmap(nettel_intel_map.virt); 443 nettel_intel_map.virt = NULL; 444 } 445 #endif 446 } 447 448 /****************************************************************************/ 449 450 module_init(nettel_init); 451 module_exit(nettel_cleanup); 452 453 MODULE_LICENSE("GPL"); 454 MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>"); 455 MODULE_DESCRIPTION("SnapGear/SecureEdge FLASH support"); 456 457 /****************************************************************************/ 458