diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-06-25 02:27:00 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-26 02:14:51 -0400 |
commit | 29f7ac7ecc853037cd7273f1fa35b1d996f8234a (patch) | |
tree | bc4fe3260845ae6e675ab8cff62b725d8b64a49c /drivers | |
parent | fcc18e83e1f6fd9fa6b333735bf0fcd530655511 (diff) |
[MTD] sun_uflash: Port to new EBUS device layer.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mtd/maps/sun_uflash.c | 195 |
1 files changed, 95 insertions, 100 deletions
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c index 0758cb1d0105..24a03152d196 100644 --- a/drivers/mtd/maps/sun_uflash.c +++ b/drivers/mtd/maps/sun_uflash.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/ioport.h> | 18 | #include <linux/ioport.h> |
19 | #include <asm/ebus.h> | 19 | #include <asm/ebus.h> |
20 | #include <asm/oplib.h> | 20 | #include <asm/oplib.h> |
21 | #include <asm/prom.h> | ||
21 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
22 | #include <asm/io.h> | 23 | #include <asm/io.h> |
23 | 24 | ||
@@ -30,146 +31,140 @@ | |||
30 | #define UFLASH_WINDOW_SIZE 0x200000 | 31 | #define UFLASH_WINDOW_SIZE 0x200000 |
31 | #define UFLASH_BUSWIDTH 1 /* EBus is 8-bit */ | 32 | #define UFLASH_BUSWIDTH 1 /* EBus is 8-bit */ |
32 | 33 | ||
33 | MODULE_AUTHOR | 34 | MODULE_AUTHOR("Eric Brower <ebrower@usa.net>"); |
34 | ("Eric Brower <ebrower@usa.net>"); | 35 | MODULE_DESCRIPTION("User-programmable flash device on Sun Microsystems boardsets"); |
35 | MODULE_DESCRIPTION | 36 | MODULE_SUPPORTED_DEVICE("userflash"); |
36 | ("User-programmable flash device on Sun Microsystems boardsets"); | 37 | MODULE_LICENSE("GPL"); |
37 | MODULE_SUPPORTED_DEVICE | 38 | MODULE_VERSION("2.0"); |
38 | ("userflash"); | ||
39 | MODULE_LICENSE | ||
40 | ("GPL"); | ||
41 | 39 | ||
42 | static LIST_HEAD(device_list); | 40 | static LIST_HEAD(device_list); |
43 | struct uflash_dev { | 41 | struct uflash_dev { |
44 | char * name; /* device name */ | 42 | char *name; /* device name */ |
45 | struct map_info map; /* mtd map info */ | 43 | struct map_info map; /* mtd map info */ |
46 | struct mtd_info * mtd; /* mtd info */ | 44 | struct mtd_info *mtd; /* mtd info */ |
47 | struct list_head list; | ||
48 | }; | 45 | }; |
49 | 46 | ||
50 | 47 | ||
51 | struct map_info uflash_map_templ = { | 48 | struct map_info uflash_map_templ = { |
52 | .name = "SUNW,???-????", | 49 | .name = "SUNW,???-????", |
53 | .size = UFLASH_WINDOW_SIZE, | 50 | .size = UFLASH_WINDOW_SIZE, |
54 | .bankwidth = UFLASH_BUSWIDTH, | 51 | .bankwidth = UFLASH_BUSWIDTH, |
55 | }; | 52 | }; |
56 | 53 | ||
57 | int uflash_devinit(struct linux_ebus_device* edev) | 54 | int uflash_devinit(struct linux_ebus_device *edev, struct device_node *dp) |
58 | { | 55 | { |
59 | int iTmp, nregs; | 56 | struct uflash_dev *up; |
60 | struct linux_prom_registers regs[2]; | 57 | struct resource *res; |
61 | struct uflash_dev *pdev; | ||
62 | |||
63 | iTmp = prom_getproperty( | ||
64 | edev->prom_node, "reg", (void *)regs, sizeof(regs)); | ||
65 | if ((iTmp % sizeof(regs[0])) != 0) { | ||
66 | printk("%s: Strange reg property size %d\n", | ||
67 | UFLASH_DEVNAME, iTmp); | ||
68 | return -ENODEV; | ||
69 | } | ||
70 | 58 | ||
71 | nregs = iTmp / sizeof(regs[0]); | 59 | res = &edev->resource[0]; |
72 | 60 | ||
73 | if (nregs != 1) { | 61 | if (edev->num_addrs != 1) { |
74 | /* Non-CFI userflash device-- once I find one we | 62 | /* Non-CFI userflash device-- once I find one we |
75 | * can work on supporting it. | 63 | * can work on supporting it. |
76 | */ | 64 | */ |
77 | printk("%s: unsupported device at 0x%lx (%d regs): " \ | 65 | printk("%s: unsupported device at 0x%lx (%d regs): " \ |
78 | "email ebrower@usa.net\n", | 66 | "email ebrower@usa.net\n", |
79 | UFLASH_DEVNAME, edev->resource[0].start, nregs); | 67 | dp->full_name, res->start, edev->num_addrs); |
68 | |||
80 | return -ENODEV; | 69 | return -ENODEV; |
81 | } | 70 | } |
82 | 71 | ||
83 | if(0 == (pdev = kmalloc(sizeof(struct uflash_dev), GFP_KERNEL))) { | 72 | up = kzalloc(sizeof(struct uflash_dev), GFP_KERNEL); |
84 | printk("%s: unable to kmalloc new device\n", UFLASH_DEVNAME); | 73 | if (!up) |
85 | return(-ENOMEM); | 74 | return -ENOMEM; |
86 | } | ||
87 | 75 | ||
88 | /* copy defaults and tweak parameters */ | 76 | /* copy defaults and tweak parameters */ |
89 | memcpy(&pdev->map, &uflash_map_templ, sizeof(uflash_map_templ)); | 77 | memcpy(&up->map, &uflash_map_templ, sizeof(uflash_map_templ)); |
90 | pdev->map.size = regs[0].reg_size; | 78 | up->map.size = (res->end - res->start) + 1UL; |
91 | 79 | ||
92 | iTmp = prom_getproplen(edev->prom_node, "model"); | 80 | up->name = of_get_property(dp, "model", NULL); |
93 | pdev->name = kmalloc(iTmp, GFP_KERNEL); | 81 | if (up->name && 0 < strlen(up->name)) |
94 | prom_getstring(edev->prom_node, "model", pdev->name, iTmp); | 82 | up->map.name = up->name; |
95 | if(0 != pdev->name && 0 < strlen(pdev->name)) { | 83 | |
96 | pdev->map.name = pdev->name; | 84 | up->map.phys = res->start; |
97 | } | 85 | |
98 | pdev->map.phys = edev->resource[0].start; | 86 | up->map.virt = ioremap_nocache(res->start, up->map.size); |
99 | pdev->map.virt = ioremap_nocache(edev->resource[0].start, pdev->map.size); | 87 | if (!up->map.virt) { |
100 | if(0 == pdev->map.virt) { | 88 | printk("%s: Failed to map device.\n", dp->full_name); |
101 | printk("%s: failed to map device\n", __FUNCTION__); | 89 | kfree(up); |
102 | kfree(pdev->name); | 90 | |
103 | kfree(pdev); | 91 | return -EINVAL; |
104 | return(-1); | ||
105 | } | 92 | } |
106 | 93 | ||
107 | simple_map_init(&pdev->map); | 94 | simple_map_init(&up->map); |
108 | 95 | ||
109 | /* MTD registration */ | 96 | /* MTD registration */ |
110 | pdev->mtd = do_map_probe("cfi_probe", &pdev->map); | 97 | up->mtd = do_map_probe("cfi_probe", &up->map); |
111 | if(0 == pdev->mtd) { | 98 | if (!up->mtd) { |
112 | iounmap(pdev->map.virt); | 99 | iounmap(up->map.virt); |
113 | kfree(pdev->name); | 100 | kfree(up); |
114 | kfree(pdev); | 101 | |
115 | return(-ENXIO); | 102 | return -ENXIO; |
116 | } | 103 | } |
117 | 104 | ||
118 | list_add(&pdev->list, &device_list); | 105 | up->mtd->owner = THIS_MODULE; |
119 | 106 | ||
120 | pdev->mtd->owner = THIS_MODULE; | 107 | add_mtd_device(up->mtd); |
121 | 108 | ||
122 | add_mtd_device(pdev->mtd); | 109 | dev_set_drvdata(&edev->ofdev.dev, up); |
123 | return(0); | 110 | |
111 | return 0; | ||
124 | } | 112 | } |
125 | 113 | ||
126 | static int __init uflash_init(void) | 114 | static int __devinit uflash_probe(struct of_device *dev, const struct of_device_id *match) |
127 | { | 115 | { |
128 | struct linux_ebus *ebus = NULL; | 116 | struct linux_ebus_device *edev = to_ebus_device(&dev->dev); |
129 | struct linux_ebus_device *edev = NULL; | 117 | struct device_node *dp = dev->node; |
130 | |||
131 | for_each_ebus(ebus) { | ||
132 | for_each_ebusdev(edev, ebus) { | ||
133 | if (!strcmp(edev->prom_name, UFLASH_OBPNAME)) { | ||
134 | if(0 > prom_getproplen(edev->prom_node, "user")) { | ||
135 | DEBUG(2, "%s: ignoring device at 0x%lx\n", | ||
136 | UFLASH_DEVNAME, edev->resource[0].start); | ||
137 | } else { | ||
138 | uflash_devinit(edev); | ||
139 | } | ||
140 | } | ||
141 | } | ||
142 | } | ||
143 | 118 | ||
144 | if(list_empty(&device_list)) { | 119 | if (of_find_property(dp, "user", NULL)) |
145 | printk("%s: unable to locate device\n", UFLASH_DEVNAME); | ||
146 | return -ENODEV; | 120 | return -ENODEV; |
147 | } | 121 | |
148 | return(0); | 122 | return uflash_devinit(edev, dp); |
149 | } | 123 | } |
150 | 124 | ||
151 | static void __exit uflash_cleanup(void) | 125 | static int __devexit uflash_remove(struct of_device *dev) |
152 | { | 126 | { |
153 | struct list_head *udevlist; | 127 | struct uflash_dev *up = dev_get_drvdata(&dev->dev); |
154 | struct uflash_dev *udev; | 128 | |
155 | 129 | if (up->mtd) { | |
156 | list_for_each(udevlist, &device_list) { | 130 | del_mtd_device(up->mtd); |
157 | udev = list_entry(udevlist, struct uflash_dev, list); | 131 | map_destroy(up->mtd); |
158 | DEBUG(2, "%s: removing device %s\n", | ||
159 | UFLASH_DEVNAME, udev->name); | ||
160 | |||
161 | if(0 != udev->mtd) { | ||
162 | del_mtd_device(udev->mtd); | ||
163 | map_destroy(udev->mtd); | ||
164 | } | ||
165 | if(0 != udev->map.virt) { | ||
166 | iounmap(udev->map.virt); | ||
167 | udev->map.virt = NULL; | ||
168 | } | ||
169 | kfree(udev->name); | ||
170 | kfree(udev); | ||
171 | } | 132 | } |
133 | if (up->map.virt) { | ||
134 | iounmap(up->map.virt); | ||
135 | up->map.virt = NULL; | ||
136 | } | ||
137 | |||
138 | kfree(up); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static struct of_device_id uflash_match[] = { | ||
144 | { | ||
145 | .name = UFLASH_OBPNAME, | ||
146 | }, | ||
147 | {}, | ||
148 | }; | ||
149 | |||
150 | MODULE_DEVICE_TABLE(of, uflash_match); | ||
151 | |||
152 | static struct of_platform_driver uflash_driver = { | ||
153 | .name = UFLASH_DEVNAME, | ||
154 | .match_table = uflash_match, | ||
155 | .probe = uflash_probe, | ||
156 | .remove = __devexit_p(uflash_remove), | ||
157 | }; | ||
158 | |||
159 | static int __init uflash_init(void) | ||
160 | { | ||
161 | return of_register_driver(&uflash_driver, &ebus_bus_type); | ||
162 | } | ||
163 | |||
164 | static void __exit uflash_exit(void) | ||
165 | { | ||
166 | of_unregister_driver(&uflash_driver); | ||
172 | } | 167 | } |
173 | 168 | ||
174 | module_init(uflash_init); | 169 | module_init(uflash_init); |
175 | module_exit(uflash_cleanup); | 170 | module_exit(uflash_exit); |