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