More Makefile cleanups, otherwise mainly noticeable are the netfilter fix
[davej-history.git] / drivers / mtd / octagon-5066.c
blob70e78d7e9c0318a6c55a449ef2177edc74a7d61e
1 // $Id: octagon-5066.c,v 1.12 2000/11/27 08:50:22 dwmw2 Exp $
2 /* ######################################################################
4 Octagon 5066 MTD Driver.
6 The Octagon 5066 is a SBC based on AMD's 586-WB running at 133 MHZ. It
7 comes with a builtin AMD 29F016 flash chip and a socketed EEPROM that
8 is replacable by flash. Both units are mapped through a multiplexer
9 into a 32k memory window at 0xe8000. The control register for the
10 multiplexing unit is located at IO 0x208 with a bit map of
11 0-5 Page Selection in 32k increments
12 6-7 Device selection:
13 00 SSD off
14 01 SSD 0 (Socket)
15 10 SSD 1 (Flash chip)
16 11 undefined
18 On each SSD, the first 128k is reserved for use by the bios
19 (actually it IS the bios..) This only matters if you are booting off the
20 flash, you must not put a file system starting there.
22 The driver tries to do a detection algorithm to guess what sort of devices
23 are plugged into the sockets.
25 ##################################################################### */
27 #include <linux/module.h>
28 #include <linux/malloc.h>
29 #include <linux/ioport.h>
30 #include <linux/init.h>
31 #include <asm/io.h>
33 #include <linux/mtd/map.h>
35 #define WINDOW_START 0xe8000
36 #define WINDOW_LENGTH 0x8000
37 #define WINDOW_SHIFT 27
38 #define WINDOW_MASK 0x7FFF
39 #define PAGE_IO 0x208
41 static volatile char page_n_dev = 0;
42 static unsigned long iomapadr;
43 static spinlock_t oct5066_spin = SPIN_LOCK_UNLOCKED;
46 * We use map_priv_1 to identify which device we are.
49 static void __oct5066_page(struct map_info *map, __u8 byte)
51 outb(byte,PAGE_IO);
52 page_n_dev = byte;
55 static inline void oct5066_page(struct map_info *map, unsigned long ofs)
57 __u8 byte = map->map_priv_1 | (ofs >> WINDOW_SHIFT);
59 if (page_n_dev != byte)
60 __oct5066_page(map, byte);
64 static __u8 oct5066_read8(struct map_info *map, unsigned long ofs)
66 __u8 ret;
67 spin_lock(&oct5066_spin);
68 oct5066_page(map, ofs);
69 ret = readb(iomapadr + (ofs & WINDOW_MASK));
70 spin_unlock(&oct5066_spin);
71 return ret;
74 static __u16 oct5066_read16(struct map_info *map, unsigned long ofs)
76 __u16 ret;
77 spin_lock(&oct5066_spin);
78 oct5066_page(map, ofs);
79 ret = readw(iomapadr + (ofs & WINDOW_MASK));
80 spin_unlock(&oct5066_spin);
81 return ret;
84 static __u32 oct5066_read32(struct map_info *map, unsigned long ofs)
86 __u32 ret;
87 spin_lock(&oct5066_spin);
88 oct5066_page(map, ofs);
89 ret = readl(iomapadr + (ofs & WINDOW_MASK));
90 spin_unlock(&oct5066_spin);
91 return ret;
94 static void oct5066_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
96 while(len) {
97 unsigned long thislen = len;
98 if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))
99 thislen = WINDOW_LENGTH-(from & WINDOW_MASK);
101 spin_lock(&oct5066_spin);
102 oct5066_page(map, from);
103 memcpy_fromio(to, iomapadr + from, thislen);
104 spin_unlock(&oct5066_spin);
105 to += thislen;
106 from += thislen;
107 len -= thislen;
111 static void oct5066_write8(struct map_info *map, __u8 d, unsigned long adr)
113 spin_lock(&oct5066_spin);
114 oct5066_page(map, adr);
115 writeb(d, iomapadr + (adr & WINDOW_MASK));
116 spin_unlock(&oct5066_spin);
119 static void oct5066_write16(struct map_info *map, __u16 d, unsigned long adr)
121 spin_lock(&oct5066_spin);
122 oct5066_page(map, adr);
123 writew(d, iomapadr + (adr & WINDOW_MASK));
124 spin_unlock(&oct5066_spin);
127 static void oct5066_write32(struct map_info *map, __u32 d, unsigned long adr)
129 spin_lock(&oct5066_spin);
130 oct5066_page(map, adr);
131 writel(d, iomapadr + (adr & WINDOW_MASK));
132 spin_unlock(&oct5066_spin);
135 static void oct5066_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
137 while(len) {
138 unsigned long thislen = len;
139 if (len > (WINDOW_LENGTH - (to & WINDOW_MASK)))
140 thislen = WINDOW_LENGTH-(to & WINDOW_MASK);
142 spin_lock(&oct5066_spin);
143 oct5066_page(map, to);
144 memcpy_toio(iomapadr + to, from, thislen);
145 spin_unlock(&oct5066_spin);
146 to += thislen;
147 from += thislen;
148 len -= thislen;
152 static struct map_info oct5066_map[2] = {
154 name: "Octagon 5066 Socket",
155 size: 512 * 1024,
156 buswidth: 1,
157 read8: oct5066_read8,
158 read16: oct5066_read16,
159 read32: oct5066_read32,
160 copy_from: oct5066_copy_from,
161 write8: oct5066_write8,
162 write16: oct5066_write16,
163 write32: oct5066_write32,
164 copy_to: oct5066_copy_to,
165 map_priv_1: 1<<6
168 name: "Octagon 5066 Internal Flash",
169 size: 2 * 1024 * 1024,
170 buswidth: 1,
171 read8: oct5066_read8,
172 read16: oct5066_read16,
173 read32: oct5066_read32,
174 copy_from: oct5066_copy_from,
175 write8: oct5066_write8,
176 write16: oct5066_write16,
177 write32: oct5066_write32,
178 copy_to: oct5066_copy_to,
179 map_priv_1: 2<<6
183 static struct mtd_info *oct5066_mtd[2] = {NULL, NULL};
185 // OctProbe - Sense if this is an octagon card
186 // ---------------------------------------------------------------------
187 /* Perform a simple validity test, we map the window select SSD0 and
188 change pages while monitoring the window. A change in the window,
189 controlled by the PAGE_IO port is a functioning 5066 board. This will
190 fail if the thing in the socket is set to a uniform value. */
191 static int __init OctProbe()
193 unsigned int Base = (1 << 6);
194 unsigned long I;
195 unsigned long Values[10];
196 for (I = 0; I != 20; I++)
198 outb(Base + (I%10),PAGE_IO);
199 if (I < 10)
201 // Record the value and check for uniqueness
202 Values[I%10] = readl(iomapadr);
203 if (I > 0 && Values[I%10] == Values[0])
204 return -EAGAIN;
206 else
208 // Make sure we get the same values on the second pass
209 if (Values[I%10] != readl(iomapadr))
210 return -EAGAIN;
213 return 0;
216 #if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
217 #define init_oct5066 init_module
218 #define cleanup_oct5066 cleanup_module
219 #endif
221 void cleanup_oct5066(void)
223 int i;
224 for (i=0; i<2; i++) {
225 if (oct5066_mtd[i]) {
226 del_mtd_device(oct5066_mtd[i]);
227 map_destroy(oct5066_mtd[i]);
230 iounmap((void *)iomapadr);
231 release_region(PAGE_IO,1);
234 int __init init_oct5066(void)
236 int i;
238 // Do an autoprobe sequence
239 if (check_region(PAGE_IO,1) != 0)
241 printk("5066: Page Register in Use\n");
242 return -EAGAIN;
244 iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH);
245 if (!iomapadr) {
246 printk("Failed to ioremap memory region\n");
247 return -EIO;
249 if (OctProbe() != 0)
251 printk("5066: Octagon Probe Failed, is this an Octagon 5066 SBC?\n");
252 iounmap((void *)iomapadr);
253 return -EAGAIN;
256 request_region(PAGE_IO,1,"Octagon SSD");
258 // Print out our little header..
259 printk("Octagon 5066 SSD IO:0x%x MEM:0x%x-0x%x\n",PAGE_IO,WINDOW_START,
260 WINDOW_START+WINDOW_LENGTH);
262 for (i=0; i<2; i++) {
263 oct5066_mtd[i] = do_cfi_probe(&oct5066_map[i]);
264 if (!oct5066_mtd[i])
265 oct5066_mtd[i] = do_jedec_probe(&oct5066_map[i]);
266 if (!oct5066_mtd[i])
267 oct5066_mtd[i] = do_ram_probe(&oct5066_map[i]);
268 if (!oct5066_mtd[i])
269 oct5066_mtd[i] = do_rom_probe(&oct5066_map[i]);
270 if (oct5066_mtd[i]) {
271 oct5066_mtd[i]->module = THIS_MODULE;
272 add_mtd_device(oct5066_mtd[i]);
276 if (!oct5066_mtd[1] && !oct5066_mtd[2]) {
277 cleanup_oct5066();
278 return -ENXIO;
281 return 0;
284 module_init(init_oct5066);
285 module_exit(cleanup_oct5066);