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