1
2 /* Linux driver for Disk-On-Chip devices */
3 /* Probe routines common to all DoC devices */
4 /* (c) 1999 Machine Vision Holdings, Inc. */
5 /* Author: David Woodhouse <dwmw2@mvhi.com> */
6 /* $Id: docprobe.c,v 1.21 2000/12/03 19:32:34 dwmw2 Exp $ */
7
8
9
10 /* DOC_PASSIVE_PROBE:
11 In order to ensure that the BIOS checksum is correct at boot time, and
12 hence that the onboard BIOS extension gets executed, the DiskOnChip
13 goes into reset mode when it is read sequentially: all registers
14 return 0xff until the chip is woken up again by writing to the
15 DOCControl register.
16
17 Unfortunately, this means that the probe for the DiskOnChip is unsafe,
18 because one of the first things it does is write to where it thinks
19 the DOCControl register should be - which may well be shared memory
20 for another device. I've had machines which lock up when this is
21 attempted. Hence the possibility to do a passive probe, which will fail
22 to detect a chip in reset mode, but is at least guaranteed not to lock
23 the machine.
24
25 If you have this problem, uncomment the following line:
26 #define DOC_PASSIVE_PROBE
27 */
28
29
30 /* DOC_SINGLE_DRIVER:
31 Millennium driver has been merged into DOC2000 driver.
32
33 The newly-merged driver doesn't appear to work for writing. It's the
34 same with the DiskOnChip 2000 and the Millennium. If you have a
35 Millennium and you want write support to work, remove the definition
36 of DOC_SINGLE_DRIVER below to use the old doc2001-specific driver.
37
38 Otherwise, it's left on in the hope that it'll annoy someone with
39 a Millennium enough that they go through and work out what the
40 difference is :)
41 */
42 #define DOC_SINGLE_DRIVER
43
44 #include <linux/config.h>
45 #include <linux/kernel.h>
46 #include <linux/module.h>
47 #include <asm/errno.h>
48 #include <asm/io.h>
49 #include <asm/uaccess.h>
50 #include <linux/miscdevice.h>
51 #include <linux/pci.h>
52 #include <linux/delay.h>
53 #include <linux/malloc.h>
54 #include <linux/sched.h>
55 #include <linux/init.h>
56 #include <linux/types.h>
57
58 #include <linux/mtd/mtd.h>
59 #include <linux/mtd/nand.h>
60 #include <linux/mtd/doc2000.h>
61
62 /* Where to look for the devices? */
63 #ifndef CONFIG_MTD_DOCPROBE_ADDRESS
64 #define CONFIG_MTD_DOCPROBE_ADDRESS 0
65 #endif
66
67
68 static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS;
69 MODULE_PARM(doc_config_location, "l");
70
71
72 static unsigned long __initdata doc_locations[] = {
73 #if defined (__alpha__) || defined(__i386__)
74 #ifdef CONFIG_MTD_DOCPROBE_HIGH
75 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000,
76 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000,
77 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000,
78 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000,
79 0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000,
80 #else /* CONFIG_MTD_DOCPROBE_HIGH */
81 0xc8000, 0xca000, 0xcc000, 0xce000,
82 0xd0000, 0xd2000, 0xd4000, 0xd6000,
83 0xd8000, 0xda000, 0xdc000, 0xde000,
84 0xe0000, 0xe2000, 0xe4000, 0xe6000,
85 0xe8000, 0xea000, 0xec000, 0xee000,
86 #endif /* CONFIG_MTD_DOCPROBE_HIGH */
87 #elif defined(__ppc__)
88 0xe4000000,
89 #else
90 #warning Unknown architecture for DiskOnChip. No default probe locations defined
91 #endif
92 0 };
93
94 /* doccheck: Probe a given memory window to see if there's a DiskOnChip present */
95
96 static inline int __init doccheck(unsigned long potential, unsigned long physadr)
97 {
98 unsigned long window=potential;
99 unsigned char tmp, ChipID;
100 #ifndef DOC_PASSIVE_PROBE
101 unsigned char tmp2;
102 #endif
103
104 /* Routine copied from the Linux DOC driver */
105
106 #ifdef CONFIG_MTD_DOCPROBE_55AA
107 /* Check for 0x55 0xAA signature at beginning of window,
108 this is no longer true once we remove the IPL (for Millennium */
109 if (ReadDOC(window, Sig1) != 0x55 || ReadDOC(window, Sig2) != 0xaa)
110 return 0;
111 #endif /* CONFIG_MTD_DOCPROBE_55AA */
112
113 #ifndef DOC_PASSIVE_PROBE
114 /* It's not possible to cleanly detect the DiskOnChip - the
115 * bootup procedure will put the device into reset mode, and
116 * it's not possible to talk to it without actually writing
117 * to the DOCControl register. So we store the current contents
118 * of the DOCControl register's location, in case we later decide
119 * that it's not a DiskOnChip, and want to put it back how we
120 * found it.
121 */
122 tmp2 = ReadDOC(window, DOCControl);
123
124 /* Reset the DiskOnChip ASIC */
125 WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
126 window, DOCControl);
127 WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
128 window, DOCControl);
129
130 /* Enable the DiskOnChip ASIC */
131 WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
132 window, DOCControl);
133 WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
134 window, DOCControl);
135 #endif /* !DOC_PASSIVE_PROBE */
136
137 ChipID = ReadDOC(window, ChipID);
138
139 switch (ChipID) {
140 case DOC_ChipID_Doc2k:
141 /* Check the TOGGLE bit in the ECC register */
142 tmp = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT;
143 if ((ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT) != tmp)
144 return ChipID;
145 break;
146
147 case DOC_ChipID_DocMil:
148 /* Check the TOGGLE bit in the ECC register */
149 tmp = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
150 if ((ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT) != tmp)
151 return ChipID;
152 break;
153
154 default:
155 #ifndef CONFIG_MTD_DOCPROBE_55AA
156 printk(KERN_WARNING "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n",
157 ChipID, physadr);
158 #endif
159 #ifndef DOC_PASSIVE_PROBE
160 /* Put back the contents of the DOCControl register, in case it's not
161 * actually a DiskOnChip.
162 */
163 WriteDOC(tmp2, window, DOCControl);
164 #endif
165 return 0;
166 }
167
168 printk(KERN_WARNING "DiskOnChip failed TOGGLE test, dropping.\n");
169
170 #ifndef DOC_PASSIVE_PROBE
171 /* Put back the contents of the DOCControl register: it's not a DiskOnChip */
172 WriteDOC(tmp2, window, DOCControl);
173 #endif
174 return 0;
175 }
176
177
178 static void DoC_Probe(unsigned long physadr)
179 {
180 unsigned long docptr;
181 struct DiskOnChip *this;
182 struct mtd_info *mtd;
183 int ChipID;
184 char namebuf[15];
185 char *name = namebuf;
186 char *im_funcname = NULL;
187 char *im_modname = NULL;
188 void (*initroutine)(struct mtd_info *) = NULL;
189
190 docptr = (unsigned long)ioremap(physadr, 0x2000);
191
192 if (!docptr)
193 return;
194
195 if ((ChipID = doccheck(docptr, physadr))) {
196
197 mtd = kmalloc(sizeof(struct DiskOnChip) + sizeof(struct mtd_info), GFP_KERNEL);
198
199 if (!mtd) {
200 printk("Cannot allocate memory for data structures. Dropping.\n");
201 iounmap((void *)docptr);
202 return;
203 }
204
205 this = (struct DiskOnChip *)(&mtd[1]);
206
207 memset((char *)mtd,0, sizeof(struct mtd_info));
208 memset((char *)this, 0, sizeof(struct DiskOnChip));
209
210 mtd->priv = this;
211 this->virtadr = docptr;
212 this->physadr = physadr;
213 this->ChipID = ChipID;
214 sprintf(namebuf, "with ChipID %2.2X", ChipID);
215
216 switch(ChipID) {
217 case DOC_ChipID_Doc2k:
218 name="2000";
219 im_funcname = "DoC2k_init";
220 im_modname = "doc2000";
221 break;
222
223 case DOC_ChipID_DocMil:
224 name="Millennium";
225 #ifdef DOC_SINGLE_DRIVER
226 im_funcname = "DoC2k_init";
227 im_modname = "doc2000";
228 #else
229 im_funcname = "DoCMil_init";
230 im_modname = "doc2001";
231 #endif /* DOC_SINGLE_DRIVER */
232 break;
233 }
234
235 if (im_funcname)
236 initroutine = inter_module_get_request(im_funcname, im_modname);
237
238 if (initroutine) {
239 (*initroutine)(mtd);
240 inter_module_put(im_funcname);
241 return;
242 }
243 printk("Cannot find driver for DiskOnChip %s at 0x%lX\n", name, physadr);
244 }
245 iounmap((void *)docptr);
246 }
247
248
249 /****************************************************************************
250 *
251 * Module stuff
252 *
253 ****************************************************************************/
254
255 #if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
256 #define init_doc init_module
257 #endif
258
259 int __init init_doc(void)
260 {
261 int i;
262
263 printk(KERN_NOTICE "M-Systems DiskOnChip driver. (C) 1999 Machine Vision Holdings, Inc.\n");
264 #ifdef PRERELEASE
265 printk(KERN_INFO "$Id: docprobe.c,v 1.21 2000/12/03 19:32:34 dwmw2 Exp $\n");
266 #endif
267 if (doc_config_location) {
268 printk("Using configured probe address 0x%lx\n", doc_config_location);
269 DoC_Probe(doc_config_location);
270 } else {
271 for (i=0; doc_locations[i]; i++) {
272 DoC_Probe(doc_locations[i]);
273 }
274 }
275 /* So it looks like we've been used and we get unloaded */
276 MOD_INC_USE_COUNT;
277 MOD_DEC_USE_COUNT;
278 return 0;
279
280 }
281
282 module_init(init_doc);
283
284
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.