1 /* $Id: sun_uflash.c,v 1.11 2004/11/04 13:24:15 gleixner Exp $
3 * sun_uflash - Driver implementation for user-programmable flash
4 * present on many Sun Microsystems SME boardsets.
6 * This driver does NOT provide access to the OBP-flash for
7 * safety reasons-- use <linux>/drivers/sbus/char/flash.c instead.
9 * Copyright (c) 2001 Eric Brower (ebrower@usa.net)
13 #include <linux/kernel.h>
14 #include <linux/module.h>
16 #include <linux/errno.h>
17 #include <linux/init.h>
18 #include <linux/ioport.h>
20 #include <asm/oplib.h>
21 #include <asm/uaccess.h>
24 #include <linux/mtd/mtd.h>
25 #include <linux/mtd/map.h>
27 #define UFLASH_OBPNAME "flashprom"
28 #define UFLASH_DEVNAME "userflash"
30 #define UFLASH_WINDOW_SIZE 0x200000
31 #define UFLASH_BUSWIDTH 1 /* EBus is 8-bit */
34 ("Eric Brower <ebrower@usa.net>");
36 ("User-programmable flash device on Sun Microsystems boardsets");
37 MODULE_SUPPORTED_DEVICE
42 static LIST_HEAD(device_list
);
44 char * name
; /* device name */
45 struct map_info map
; /* mtd map info */
46 struct mtd_info
* mtd
; /* mtd info */
47 struct list_head list
;
51 struct map_info uflash_map_templ
= {
52 .name
= "SUNW,???-????",
53 .size
= UFLASH_WINDOW_SIZE
,
54 .bankwidth
= UFLASH_BUSWIDTH
,
57 int uflash_devinit(struct linux_ebus_device
* edev
)
60 struct linux_prom_registers regs
[2];
61 struct uflash_dev
*pdev
;
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
);
71 nregs
= iTmp
/ sizeof(regs
[0]);
74 /* Non-CFI userflash device-- once I find one we
75 * can work on supporting it.
77 printk("%s: unsupported device at 0x%lx (%d regs): " \
78 "email ebrower@usa.net\n",
79 UFLASH_DEVNAME
, edev
->resource
[0].start
, nregs
);
83 if(0 == (pdev
= kmalloc(sizeof(struct uflash_dev
), GFP_KERNEL
))) {
84 printk("%s: unable to kmalloc new device\n", UFLASH_DEVNAME
);
88 /* copy defaults and tweak parameters */
89 memcpy(&pdev
->map
, &uflash_map_templ
, sizeof(uflash_map_templ
));
90 pdev
->map
.size
= regs
[0].reg_size
;
92 iTmp
= prom_getproplen(edev
->prom_node
, "model");
93 pdev
->name
= kmalloc(iTmp
, GFP_KERNEL
);
94 prom_getstring(edev
->prom_node
, "model", pdev
->name
, iTmp
);
95 if(0 != pdev
->name
&& 0 < strlen(pdev
->name
)) {
96 pdev
->map
.name
= pdev
->name
;
98 pdev
->map
.phys
= edev
->resource
[0].start
;
99 pdev
->map
.virt
= ioremap_nocache(edev
->resource
[0].start
, pdev
->map
.size
);
100 if(0 == pdev
->map
.virt
) {
101 printk("%s: failed to map device\n", __FUNCTION__
);
107 simple_map_init(&pdev
->map
);
109 /* MTD registration */
110 pdev
->mtd
= do_map_probe("cfi_probe", &pdev
->map
);
112 iounmap(pdev
->map
.virt
);
118 list_add(&pdev
->list
, &device_list
);
120 pdev
->mtd
->owner
= THIS_MODULE
;
122 add_mtd_device(pdev
->mtd
);
126 static int __init
uflash_init(void)
128 struct linux_ebus
*ebus
= NULL
;
129 struct linux_ebus_device
*edev
= NULL
;
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
);
138 uflash_devinit(edev
);
144 if(list_empty(&device_list
)) {
145 printk("%s: unable to locate device\n", UFLASH_DEVNAME
);
151 static void __exit
uflash_cleanup(void)
153 struct list_head
*udevlist
;
154 struct uflash_dev
*udev
;
156 list_for_each(udevlist
, &device_list
) {
157 udev
= list_entry(udevlist
, struct uflash_dev
, list
);
158 DEBUG(2, "%s: removing device %s\n",
159 UFLASH_DEVNAME
, udev
->name
);
162 del_mtd_device(udev
->mtd
);
163 map_destroy(udev
->mtd
);
165 if(0 != udev
->map
.virt
) {
166 iounmap(udev
->map
.virt
);
167 udev
->map
.virt
= NULL
;
169 if(0 != udev
->name
) {
176 module_init(uflash_init
);
177 module_exit(uflash_cleanup
);