1 /* $Id: sun_uflash.c,v 1.13 2005/11/07 11:14:28 gleixner Exp $ 2 * 3 * sun_uflash - Driver implementation for user-programmable flash 4 * present on many Sun Microsystems SME boardsets. 5 * 6 * This driver does NOT provide access to the OBP-flash for 7 * safety reasons-- use <linux>/drivers/sbus/char/flash.c instead. 8 * 9 * Copyright (c) 2001 Eric Brower (ebrower@usa.net) 10 * 11 */ 12 13 #include <linux/kernel.h> 14 #include <linux/module.h> 15 #include <linux/fs.h> 16 #include <linux/errno.h> 17 #include <linux/init.h> 18 #include <linux/ioport.h> 19 #include <asm/ebus.h> 20 #include <asm/oplib.h> 21 #include <asm/prom.h> 22 #include <asm/uaccess.h> 23 #include <asm/io.h> 24 25 #include <linux/mtd/mtd.h> 26 #include <linux/mtd/map.h> 27 28 #define UFLASH_OBPNAME "flashprom" 29 #define UFLASH_DEVNAME "userflash" 30 31 #define UFLASH_WINDOW_SIZE 0x200000 32 #define UFLASH_BUSWIDTH 1 /* EBus is 8-bit */ 33 34 MODULE_AUTHOR("Eric Brower <ebrower@usa.net>"); 35 MODULE_DESCRIPTION("User-programmable flash device on Sun Microsystems boardsets"); 36 MODULE_SUPPORTED_DEVICE("userflash"); 37 MODULE_LICENSE("GPL"); 38 MODULE_VERSION("2.0"); 39 40 static LIST_HEAD(device_list); 41 struct uflash_dev { 42 const char *name; /* device name */ 43 struct map_info map; /* mtd map info */ 44 struct mtd_info *mtd; /* mtd info */ 45 }; 46 47 48 struct map_info uflash_map_templ = { 49 .name = "SUNW,???-????", 50 .size = UFLASH_WINDOW_SIZE, 51 .bankwidth = UFLASH_BUSWIDTH, 52 }; 53 54 int uflash_devinit(struct linux_ebus_device *edev, struct device_node *dp) 55 { 56 struct uflash_dev *up; 57 struct resource *res; 58 59 res = &edev->resource[0]; 60 61 if (edev->num_addrs != 1) { 62 /* Non-CFI userflash device-- once I find one we 63 * can work on supporting it. 64 */ 65 printk("%s: unsupported device at 0x%llx (%d regs): " \ 66 "email ebrower@usa.net\n", 67 dp->full_name, (unsigned long long)res->start, 68 edev->num_addrs); 69 70 return -ENODEV; 71 } 72 73 up = kzalloc(sizeof(struct uflash_dev), GFP_KERNEL); 74 if (!up) 75 return -ENOMEM; 76 77 /* copy defaults and tweak parameters */ 78 memcpy(&up->map, &uflash_map_templ, sizeof(uflash_map_templ)); 79 up->map.size = (res->end - res->start) + 1UL; 80 81 up->name = of_get_property(dp, "model", NULL); 82 if (up->name && 0 < strlen(up->name)) 83 up->map.name = (char *)up->name; 84 85 up->map.phys = res->start; 86 87 up->map.virt = ioremap_nocache(res->start, up->map.size); 88 if (!up->map.virt) { 89 printk("%s: Failed to map device.\n", dp->full_name); 90 kfree(up); 91 92 return -EINVAL; 93 } 94 95 simple_map_init(&up->map); 96 97 /* MTD registration */ 98 up->mtd = do_map_probe("cfi_probe", &up->map); 99 if (!up->mtd) { 100 iounmap(up->map.virt); 101 kfree(up); 102 103 return -ENXIO; 104 } 105 106 up->mtd->owner = THIS_MODULE; 107 108 add_mtd_device(up->mtd); 109 110 dev_set_drvdata(&edev->ofdev.dev, up); 111 112 return 0; 113 } 114 115 static int __devinit uflash_probe(struct of_device *dev, const struct of_device_id *match) 116 { 117 struct linux_ebus_device *edev = to_ebus_device(&dev->dev); 118 struct device_node *dp = dev->node; 119 120 if (of_find_property(dp, "user", NULL)) 121 return -ENODEV; 122 123 return uflash_devinit(edev, dp); 124 } 125 126 static int __devexit uflash_remove(struct of_device *dev) 127 { 128 struct uflash_dev *up = dev_get_drvdata(&dev->dev); 129 130 if (up->mtd) { 131 del_mtd_device(up->mtd); 132 map_destroy(up->mtd); 133 } 134 if (up->map.virt) { 135 iounmap(up->map.virt); 136 up->map.virt = NULL; 137 } 138 139 kfree(up); 140 141 return 0; 142 } 143 144 static struct of_device_id uflash_match[] = { 145 { 146 .name = UFLASH_OBPNAME, 147 }, 148 {}, 149 }; 150 151 MODULE_DEVICE_TABLE(of, uflash_match); 152 153 static struct of_platform_driver uflash_driver = { 154 .name = UFLASH_DEVNAME, 155 .match_table = uflash_match, 156 .probe = uflash_probe, 157 .remove = __devexit_p(uflash_remove), 158 }; 159 160 static int __init uflash_init(void) 161 { 162 return of_register_driver(&uflash_driver, &ebus_bus_type); 163 } 164 165 static void __exit uflash_exit(void) 166 { 167 of_unregister_driver(&uflash_driver); 168 } 169 170 module_init(uflash_init); 171 module_exit(uflash_exit); 172