diff options
Diffstat (limited to 'drivers/sbus/char/flash.c')
-rw-r--r-- | drivers/sbus/char/flash.c | 130 |
1 files changed, 50 insertions, 80 deletions
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 7d95e151513a..715996f5c538 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* $Id: flash.c,v 1.25 2001/12/21 04:56:16 davem Exp $ | 1 | /* flash.c: Allow mmap access to the OBP Flash, for OBP updates. |
2 | * flash.c: Allow mmap access to the OBP Flash, for OBP updates. | ||
3 | * | 2 | * |
4 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) | 3 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) |
5 | */ | 4 | */ |
@@ -15,13 +14,13 @@ | |||
15 | #include <linux/smp_lock.h> | 14 | #include <linux/smp_lock.h> |
16 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
17 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
17 | #include <linux/of.h> | ||
18 | #include <linux/of_device.h> | ||
18 | 19 | ||
19 | #include <asm/system.h> | 20 | #include <asm/system.h> |
20 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
21 | #include <asm/pgtable.h> | 22 | #include <asm/pgtable.h> |
22 | #include <asm/io.h> | 23 | #include <asm/io.h> |
23 | #include <asm/sbus.h> | ||
24 | #include <asm/ebus.h> | ||
25 | #include <asm/upa.h> | 24 | #include <asm/upa.h> |
26 | 25 | ||
27 | static DEFINE_SPINLOCK(flash_lock); | 26 | static DEFINE_SPINLOCK(flash_lock); |
@@ -161,97 +160,68 @@ static const struct file_operations flash_fops = { | |||
161 | 160 | ||
162 | static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops }; | 161 | static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops }; |
163 | 162 | ||
164 | static int __init flash_init(void) | 163 | static int __devinit flash_probe(struct of_device *op, |
164 | const struct of_device_id *match) | ||
165 | { | 165 | { |
166 | struct sbus_bus *sbus; | 166 | struct device_node *dp = op->node; |
167 | struct sbus_dev *sdev = NULL; | 167 | struct device_node *parent; |
168 | #ifdef CONFIG_PCI | ||
169 | struct linux_ebus *ebus; | ||
170 | struct linux_ebus_device *edev = NULL; | ||
171 | struct linux_prom_registers regs[2]; | ||
172 | int len, nregs; | ||
173 | #endif | ||
174 | int err; | ||
175 | |||
176 | for_all_sbusdev(sdev, sbus) { | ||
177 | if (!strcmp(sdev->prom_name, "flashprom")) { | ||
178 | if (sdev->reg_addrs[0].phys_addr == sdev->reg_addrs[1].phys_addr) { | ||
179 | flash.read_base = ((unsigned long)sdev->reg_addrs[0].phys_addr) | | ||
180 | (((unsigned long)sdev->reg_addrs[0].which_io)<<32UL); | ||
181 | flash.read_size = sdev->reg_addrs[0].reg_size; | ||
182 | flash.write_base = flash.read_base; | ||
183 | flash.write_size = flash.read_size; | ||
184 | } else { | ||
185 | flash.read_base = ((unsigned long)sdev->reg_addrs[0].phys_addr) | | ||
186 | (((unsigned long)sdev->reg_addrs[0].which_io)<<32UL); | ||
187 | flash.read_size = sdev->reg_addrs[0].reg_size; | ||
188 | flash.write_base = ((unsigned long)sdev->reg_addrs[1].phys_addr) | | ||
189 | (((unsigned long)sdev->reg_addrs[1].which_io)<<32UL); | ||
190 | flash.write_size = sdev->reg_addrs[1].reg_size; | ||
191 | } | ||
192 | flash.busy = 0; | ||
193 | break; | ||
194 | } | ||
195 | } | ||
196 | if (!sdev) { | ||
197 | #ifdef CONFIG_PCI | ||
198 | const struct linux_prom_registers *ebus_regs; | ||
199 | |||
200 | for_each_ebus(ebus) { | ||
201 | for_each_ebusdev(edev, ebus) { | ||
202 | if (!strcmp(edev->prom_node->name, "flashprom")) | ||
203 | goto ebus_done; | ||
204 | } | ||
205 | } | ||
206 | ebus_done: | ||
207 | if (!edev) | ||
208 | return -ENODEV; | ||
209 | |||
210 | ebus_regs = of_get_property(edev->prom_node, "reg", &len); | ||
211 | if (!ebus_regs || (len % sizeof(regs[0])) != 0) { | ||
212 | printk("flash: Strange reg property size %d\n", len); | ||
213 | return -ENODEV; | ||
214 | } | ||
215 | |||
216 | nregs = len / sizeof(ebus_regs[0]); | ||
217 | 168 | ||
218 | flash.read_base = edev->resource[0].start; | 169 | parent = dp->parent; |
219 | flash.read_size = ebus_regs[0].reg_size; | ||
220 | 170 | ||
221 | if (nregs == 1) { | 171 | if (strcmp(parent->name, "sbus") && |
222 | flash.write_base = edev->resource[0].start; | 172 | strcmp(parent->name, "sbi") && |
223 | flash.write_size = ebus_regs[0].reg_size; | 173 | strcmp(parent->name, "ebus")) |
224 | } else if (nregs == 2) { | ||
225 | flash.write_base = edev->resource[1].start; | ||
226 | flash.write_size = ebus_regs[1].reg_size; | ||
227 | } else { | ||
228 | printk("flash: Strange number of regs %d\n", nregs); | ||
229 | return -ENODEV; | ||
230 | } | ||
231 | |||
232 | flash.busy = 0; | ||
233 | |||
234 | #else | ||
235 | return -ENODEV; | 174 | return -ENODEV; |
236 | #endif | 175 | |
176 | flash.read_base = op->resource[0].start; | ||
177 | flash.read_size = resource_size(&op->resource[0]); | ||
178 | if (op->resource[1].flags) { | ||
179 | flash.write_base = op->resource[1].start; | ||
180 | flash.write_size = resource_size(&op->resource[1]); | ||
181 | } else { | ||
182 | flash.write_base = op->resource[0].start; | ||
183 | flash.write_size = resource_size(&op->resource[0]); | ||
237 | } | 184 | } |
185 | flash.busy = 0; | ||
238 | 186 | ||
239 | printk("OBP Flash: RD %lx[%lx] WR %lx[%lx]\n", | 187 | printk(KERN_INFO "%s: OBP Flash, RD %lx[%lx] WR %lx[%lx]\n", |
188 | op->node->full_name, | ||
240 | flash.read_base, flash.read_size, | 189 | flash.read_base, flash.read_size, |
241 | flash.write_base, flash.write_size); | 190 | flash.write_base, flash.write_size); |
242 | 191 | ||
243 | err = misc_register(&flash_dev); | 192 | return misc_register(&flash_dev); |
244 | if (err) { | 193 | } |
245 | printk(KERN_ERR "flash: unable to get misc minor\n"); | 194 | |
246 | return err; | 195 | static int __devexit flash_remove(struct of_device *op) |
247 | } | 196 | { |
197 | misc_deregister(&flash_dev); | ||
248 | 198 | ||
249 | return 0; | 199 | return 0; |
250 | } | 200 | } |
251 | 201 | ||
202 | static struct of_device_id flash_match[] = { | ||
203 | { | ||
204 | .name = "flashprom", | ||
205 | }, | ||
206 | {}, | ||
207 | }; | ||
208 | MODULE_DEVICE_TABLE(of, flash_match); | ||
209 | |||
210 | static struct of_platform_driver flash_driver = { | ||
211 | .name = "flash", | ||
212 | .match_table = flash_match, | ||
213 | .probe = flash_probe, | ||
214 | .remove = __devexit_p(flash_remove), | ||
215 | }; | ||
216 | |||
217 | static int __init flash_init(void) | ||
218 | { | ||
219 | return of_register_driver(&flash_driver, &of_bus_type); | ||
220 | } | ||
221 | |||
252 | static void __exit flash_cleanup(void) | 222 | static void __exit flash_cleanup(void) |
253 | { | 223 | { |
254 | misc_deregister(&flash_dev); | 224 | of_unregister_driver(&flash_driver); |
255 | } | 225 | } |
256 | 226 | ||
257 | module_init(flash_init); | 227 | module_init(flash_init); |