1 /* 2 * Flash memory access on SA11x0 based devices 3 * 4 * (C) 2000 Nicolas Pitre <nico@cam.org> 5 * 6 * $Id: sa1100-flash.c,v 1.47 2004/11/01 13:44:36 rmk Exp $ 7 */ 8 #include <linux/config.h> 9 #include <linux/module.h> 10 #include <linux/types.h> 11 #include <linux/ioport.h> 12 #include <linux/kernel.h> 13 #include <linux/init.h> 14 #include <linux/errno.h> 15 #include <linux/slab.h> 16 #include <linux/device.h> 17 #include <linux/err.h> 18 19 #include <linux/mtd/mtd.h> 20 #include <linux/mtd/map.h> 21 #include <linux/mtd/partitions.h> 22 #include <linux/mtd/concat.h> 23 24 #include <asm/io.h> 25 #include <asm/sizes.h> 26 #include <asm/mach/flash.h> 27 28 #if 0 29 /* 30 * This is here for documentation purposes only - until these people 31 * submit their machine types. It will be gone January 2005. 32 */ 33 static struct mtd_partition consus_partitions[] = { 34 { 35 .name = "Consus boot firmware", 36 .offset = 0, 37 .size = 0x00040000, 38 .mask_flags = MTD_WRITABLE, /* force read-only */ 39 }, { 40 .name = "Consus kernel", 41 .offset = 0x00040000, 42 .size = 0x00100000, 43 .mask_flags = 0, 44 }, { 45 .name = "Consus disk", 46 .offset = 0x00140000, 47 /* The rest (up to 16M) for jffs. We could put 0 and 48 make it find the size automatically, but right now 49 i have 32 megs. jffs will use all 32 megs if given 50 the chance, and this leads to horrible problems 51 when you try to re-flash the image because blob 52 won't erase the whole partition. */ 53 .size = 0x01000000 - 0x00140000, 54 .mask_flags = 0, 55 }, { 56 /* this disk is a secondary disk, which can be used as 57 needed, for simplicity, make it the size of the other 58 consus partition, although realistically it could be 59 the remainder of the disk (depending on the file 60 system used) */ 61 .name = "Consus disk2", 62 .offset = 0x01000000, 63 .size = 0x01000000 - 0x00140000, 64 .mask_flags = 0, 65 } 66 }; 67 68 /* Frodo has 2 x 16M 28F128J3A flash chips in bank 0: */ 69 static struct mtd_partition frodo_partitions[] = 70 { 71 { 72 .name = "bootloader", 73 .size = 0x00040000, 74 .offset = 0x00000000, 75 .mask_flags = MTD_WRITEABLE 76 }, { 77 .name = "bootloader params", 78 .size = 0x00040000, 79 .offset = MTDPART_OFS_APPEND, 80 .mask_flags = MTD_WRITEABLE 81 }, { 82 .name = "kernel", 83 .size = 0x00100000, 84 .offset = MTDPART_OFS_APPEND, 85 .mask_flags = MTD_WRITEABLE 86 }, { 87 .name = "ramdisk", 88 .size = 0x00400000, 89 .offset = MTDPART_OFS_APPEND, 90 .mask_flags = MTD_WRITEABLE 91 }, { 92 .name = "file system", 93 .size = MTDPART_SIZ_FULL, 94 .offset = MTDPART_OFS_APPEND 95 } 96 }; 97 98 static struct mtd_partition jornada56x_partitions[] = { 99 { 100 .name = "bootldr", 101 .size = 0x00040000, 102 .offset = 0, 103 .mask_flags = MTD_WRITEABLE, 104 }, { 105 .name = "rootfs", 106 .size = MTDPART_SIZ_FULL, 107 .offset = MTDPART_OFS_APPEND, 108 } 109 }; 110 111 static void jornada56x_set_vpp(int vpp) 112 { 113 if (vpp) 114 GPSR = GPIO_GPIO26; 115 else 116 GPCR = GPIO_GPIO26; 117 GPDR |= GPIO_GPIO26; 118 } 119 120 /* 121 * Machine Phys Size set_vpp 122 * Consus : SA1100_CS0_PHYS SZ_32M 123 * Frodo : SA1100_CS0_PHYS SZ_32M 124 * Jornada56x: SA1100_CS0_PHYS SZ_32M jornada56x_set_vpp 125 */ 126 #endif 127 128 struct sa_subdev_info { 129 char name[16]; 130 struct map_info map; 131 struct mtd_info *mtd; 132 struct flash_platform_data *data; 133 }; 134 135 struct sa_info { 136 struct mtd_partition *parts; 137 struct mtd_info *mtd; 138 int num_subdev; 139 struct sa_subdev_info subdev[0]; 140 }; 141 142 static void sa1100_set_vpp(struct map_info *map, int on) 143 { 144 struct sa_subdev_info *subdev = container_of(map, struct sa_subdev_info, map); 145 subdev->data->set_vpp(on); 146 } 147 148 static void sa1100_destroy_subdev(struct sa_subdev_info *subdev) 149 { 150 if (subdev->mtd) 151 map_destroy(subdev->mtd); 152 if (subdev->map.virt) 153 iounmap(subdev->map.virt); 154 release_mem_region(subdev->map.phys, subdev->map.size); 155 } 156 157 static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *res) 158 { 159 unsigned long phys; 160 unsigned int size; 161 int ret; 162 163 phys = res->start; 164 size = res->end - phys + 1; 165 166 /* 167 * Retrieve the bankwidth from the MSC registers. 168 * We currently only implement CS0 and CS1 here. 169 */ 170 switch (phys) { 171 default: 172 printk(KERN_WARNING "SA1100 flash: unknown base address " 173 "0x%08lx, assuming CS0\n", phys); 174 175 case SA1100_CS0_PHYS: 176 subdev->map.bankwidth = (MSC0 & MSC_RBW) ? 2 : 4; 177 break; 178 179 case SA1100_CS1_PHYS: 180 subdev->map.bankwidth = ((MSC0 >> 16) & MSC_RBW) ? 2 : 4; 181 break; 182 } 183 184 if (!request_mem_region(phys, size, subdev->name)) { 185 ret = -EBUSY; 186 goto out; 187 } 188 189 if (subdev->data->set_vpp) 190 subdev->map.set_vpp = sa1100_set_vpp; 191 192 subdev->map.phys = phys; 193 subdev->map.size = size; 194 subdev->map.virt = ioremap(phys, size); 195 if (!subdev->map.virt) { 196 ret = -ENOMEM; 197 goto err; 198 } 199 200 simple_map_init(&subdev->map); 201 202 /* 203 * Now let's probe for the actual flash. Do it here since 204 * specific machine settings might have been set above. 205 */ 206 subdev->mtd = do_map_probe(subdev->data->map_name, &subdev->map); 207 if (subdev->mtd == NULL) { 208 ret = -ENXIO; 209 goto err; 210 } 211 subdev->mtd->owner = THIS_MODULE; 212 213 printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, " 214 "%d-bit\n", phys, subdev->mtd->size >> 20, 215 subdev->map.bankwidth * 8); 216 217 return 0; 218 219 err: 220 sa1100_destroy_subdev(subdev); 221 out: 222 return ret; 223 } 224 225 static void sa1100_destroy(struct sa_info *info) 226 { 227 int i; 228 229 if (info->mtd) { 230 del_mtd_partitions(info->mtd); 231 232 #ifdef CONFIG_MTD_CONCAT 233 if (info->mtd != info->subdev[0].mtd) 234 mtd_concat_destroy(info->mtd); 235 #endif 236 } 237 238 if (info->parts) 239 kfree(info->parts); 240 241 for (i = info->num_subdev - 1; i >= 0; i--) 242 sa1100_destroy_subdev(&info->subdev[i]); 243 kfree(info); 244 } 245 246 static struct sa_info *__init 247 sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash) 248 { 249 struct sa_info *info; 250 int nr, size, i, ret = 0; 251 252 /* 253 * Count number of devices. 254 */ 255 for (nr = 0; ; nr++) 256 if (!platform_get_resource(pdev, IORESOURCE_MEM, nr)) 257 break; 258 259 if (nr == 0) { 260 ret = -ENODEV; 261 goto out; 262 } 263 264 size = sizeof(struct sa_info) + sizeof(struct sa_subdev_info) * nr; 265 266 /* 267 * Allocate the map_info structs in one go. 268 */ 269 info = kmalloc(size, GFP_KERNEL); 270 if (!info) { 271 ret = -ENOMEM; 272 goto out; 273 } 274 275 memset(info, 0, size); 276 277 /* 278 * Claim and then map the memory regions. 279 */ 280 for (i = 0; i < nr; i++) { 281 struct sa_subdev_info *subdev = &info->subdev[i]; 282 struct resource *res; 283 284 res = platform_get_resource(pdev, IORESOURCE_MEM, i); 285 if (!res) 286 break; 287 288 subdev->map.name = subdev->name; 289 sprintf(subdev->name, "sa1100-%d", i); 290 subdev->data = flash; 291 292 ret = sa1100_probe_subdev(subdev, res); 293 if (ret) 294 break; 295 } 296 297 info->num_subdev = i; 298 299 /* 300 * ENXIO is special. It means we didn't find a chip when we probed. 301 */ 302 if (ret != 0 && !(ret == -ENXIO && info->num_subdev > 0)) 303 goto err; 304 305 /* 306 * If we found one device, don't bother with concat support. If 307 * we found multiple devices, use concat if we have it available, 308 * otherwise fail. Either way, it'll be called "sa1100". 309 */ 310 if (info->num_subdev == 1) { 311 strcpy(info->subdev[0].name, "sa1100"); 312 info->mtd = info->subdev[0].mtd; 313 ret = 0; 314 } else if (info->num_subdev > 1) { 315 #ifdef CONFIG_MTD_CONCAT 316 struct mtd_info *cdev[nr]; 317 /* 318 * We detected multiple devices. Concatenate them together. 319 */ 320 for (i = 0; i < info->num_subdev; i++) 321 cdev[i] = info->subdev[i].mtd; 322 323 info->mtd = mtd_concat_create(cdev, info->num_subdev, 324 "sa1100"); 325 if (info->mtd == NULL) 326 ret = -ENXIO; 327 #else 328 printk(KERN_ERR "SA1100 flash: multiple devices " 329 "found but MTD concat support disabled.\n"); 330 ret = -ENXIO; 331 #endif 332 } 333 334 if (ret == 0) 335 return info; 336 337 err: 338 sa1100_destroy(info); 339 out: 340 return ERR_PTR(ret); 341 } 342 343 static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; 344 345 static int __init sa1100_mtd_probe(struct device *dev) 346 { 347 struct platform_device *pdev = to_platform_device(dev); 348 struct flash_platform_data *flash = pdev->dev.platform_data; 349 struct mtd_partition *parts; 350 const char *part_type = NULL; 351 struct sa_info *info; 352 int err, nr_parts = 0; 353 354 if (!flash) 355 return -ENODEV; 356 357 info = sa1100_setup_mtd(pdev, flash); 358 if (IS_ERR(info)) { 359 err = PTR_ERR(info); 360 goto out; 361 } 362 363 /* 364 * Partition selection stuff. 365 */ 366 #ifdef CONFIG_MTD_PARTITIONS 367 nr_parts = parse_mtd_partitions(info->mtd, part_probes, &parts, 0); 368 if (nr_parts > 0) { 369 info->parts = parts; 370 part_type = "dynamic"; 371 } else 372 #endif 373 { 374 parts = flash->parts; 375 nr_parts = flash->nr_parts; 376 part_type = "static"; 377 } 378 379 if (nr_parts == 0) { 380 printk(KERN_NOTICE "SA1100 flash: no partition info " 381 "available, registering whole flash\n"); 382 add_mtd_device(info->mtd); 383 } else { 384 printk(KERN_NOTICE "SA1100 flash: using %s partition " 385 "definition\n", part_type); 386 add_mtd_partitions(info->mtd, parts, nr_parts); 387 } 388 389 dev_set_drvdata(dev, info); 390 err = 0; 391 392 out: 393 return err; 394 } 395 396 static int __exit sa1100_mtd_remove(struct device *dev) 397 { 398 struct sa_info *info = dev_get_drvdata(dev); 399 dev_set_drvdata(dev, NULL); 400 sa1100_destroy(info); 401 return 0; 402 } 403 404 #ifdef CONFIG_PM 405 static int sa1100_mtd_suspend(struct device *dev, pm_message_t state, u32 level) 406 { 407 struct sa_info *info = dev_get_drvdata(dev); 408 int ret = 0; 409 410 if (info && level == SUSPEND_SAVE_STATE) 411 ret = info->mtd->suspend(info->mtd); 412 413 return ret; 414 } 415 416 static int sa1100_mtd_resume(struct device *dev, u32 level) 417 { 418 struct sa_info *info = dev_get_drvdata(dev); 419 if (info && level == RESUME_RESTORE_STATE) 420 info->mtd->resume(info->mtd); 421 return 0; 422 } 423 #else 424 #define sa1100_mtd_suspend NULL 425 #define sa1100_mtd_resume NULL 426 #endif 427 428 static struct device_driver sa1100_mtd_driver = { 429 .name = "flash", 430 .bus = &platform_bus_type, 431 .probe = sa1100_mtd_probe, 432 .remove = __exit_p(sa1100_mtd_remove), 433 .suspend = sa1100_mtd_suspend, 434 .resume = sa1100_mtd_resume, 435 }; 436 437 static int __init sa1100_mtd_init(void) 438 { 439 return driver_register(&sa1100_mtd_driver); 440 } 441 442 static void __exit sa1100_mtd_exit(void) 443 { 444 driver_unregister(&sa1100_mtd_driver); 445 } 446 447 module_init(sa1100_mtd_init); 448 module_exit(sa1100_mtd_exit); 449 450 MODULE_AUTHOR("Nicolas Pitre"); 451 MODULE_DESCRIPTION("SA1100 CFI map driver"); 452 MODULE_LICENSE("GPL"); 453