2 /* Linux driver for Disk-On-Chip devices */
3 /* Probe routines common to all DoC devices */
4 /* (C) 1999 Machine Vision Holdings, Inc. */
5 /* (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> */
7 /* $Id: docprobe.c,v 1.33 2003/01/24 14:02:47 dwmw2 Exp $ */
12 In order to ensure that the BIOS checksum is correct at boot time, and
13 hence that the onboard BIOS extension gets executed, the DiskOnChip
14 goes into reset mode when it is read sequentially: all registers
15 return 0xff until the chip is woken up again by writing to the
18 Unfortunately, this means that the probe for the DiskOnChip is unsafe,
19 because one of the first things it does is write to where it thinks
20 the DOCControl register should be - which may well be shared memory
21 for another device. I've had machines which lock up when this is
22 attempted. Hence the possibility to do a passive probe, which will fail
23 to detect a chip in reset mode, but is at least guaranteed not to lock
26 If you have this problem, uncomment the following line:
27 #define DOC_PASSIVE_PROBE
32 Millennium driver has been merged into DOC2000 driver.
34 The newly-merged driver doesn't appear to work for writing. It's the
35 same with the DiskOnChip 2000 and the Millennium. If you have a
36 Millennium and you want write support to work, remove the definition
37 of DOC_SINGLE_DRIVER below to use the old doc2001-specific driver.
39 Otherwise, it's left on in the hope that it'll annoy someone with
40 a Millennium enough that they go through and work out what the
43 #define DOC_SINGLE_DRIVER
45 #include <linux/config.h>
46 #include <linux/kernel.h>
47 #include <linux/module.h>
48 #include <asm/errno.h>
50 #include <asm/uaccess.h>
51 #include <linux/miscdevice.h>
52 #include <linux/pci.h>
53 #include <linux/delay.h>
54 #include <linux/slab.h>
55 #include <linux/sched.h>
56 #include <linux/init.h>
57 #include <linux/types.h>
59 #include <linux/mtd/mtd.h>
60 #include <linux/mtd/nand.h>
61 #include <linux/mtd/doc2000.h>
63 /* Where to look for the devices? */
64 #ifndef CONFIG_MTD_DOCPROBE_ADDRESS
65 #define CONFIG_MTD_DOCPROBE_ADDRESS 0
69 static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS;
70 MODULE_PARM(doc_config_location, "l");
71 MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip");
73 static unsigned long __initdata doc_locations[] = {
74 #if defined (__alpha__) || defined(__i386__) || defined(__x86_64__)
75 #ifdef CONFIG_MTD_DOCPROBE_HIGH
76 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000,
77 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000,
78 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000,
79 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000,
80 0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000,
81 #else /* CONFIG_MTD_DOCPROBE_HIGH */
82 0xc8000, 0xca000, 0xcc000, 0xce000,
83 0xd0000, 0xd2000, 0xd4000, 0xd6000,
84 0xd8000, 0xda000, 0xdc000, 0xde000,
85 0xe0000, 0xe2000, 0xe4000, 0xe6000,
86 0xe8000, 0xea000, 0xec000, 0xee000,
87 #endif /* CONFIG_MTD_DOCPROBE_HIGH */
88 #elif defined(__PPC__)
90 #elif defined(CONFIG_MOMENCO_OCELOT)
93 #elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
96 #warning Unknown architecture for DiskOnChip. No default probe locations defined
100 /* doccheck: Probe a given memory window to see if there's a DiskOnChip present */
102 static inline int __init doccheck(unsigned long potential, unsigned long physadr)
104 unsigned long window=potential;
105 unsigned char tmp, ChipID;
106 #ifndef DOC_PASSIVE_PROBE
110 /* Routine copied from the Linux DOC driver */
112 #ifdef CONFIG_MTD_DOCPROBE_55AA
113 /* Check for 0x55 0xAA signature at beginning of window,
114 this is no longer true once we remove the IPL (for Millennium */
115 if (ReadDOC(window, Sig1) != 0x55 || ReadDOC(window, Sig2) != 0xaa)
117 #endif /* CONFIG_MTD_DOCPROBE_55AA */
119 #ifndef DOC_PASSIVE_PROBE
120 /* It's not possible to cleanly detect the DiskOnChip - the
121 * bootup procedure will put the device into reset mode, and
122 * it's not possible to talk to it without actually writing
123 * to the DOCControl register. So we store the current contents
124 * of the DOCControl register's location, in case we later decide
125 * that it's not a DiskOnChip, and want to put it back how we
128 tmp2 = ReadDOC(window, DOCControl);
130 /* Reset the DiskOnChip ASIC */
131 WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
133 WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
136 /* Enable the DiskOnChip ASIC */
137 WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
139 WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
141 #endif /* !DOC_PASSIVE_PROBE */
143 ChipID = ReadDOC(window, ChipID);
146 case DOC_ChipID_Doc2k:
147 /* Check the TOGGLE bit in the ECC register */
148 tmp = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT;
149 if ((ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT) != tmp)
153 case DOC_ChipID_DocMil:
154 /* Check the TOGGLE bit in the ECC register */
155 tmp = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
156 if ((ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT) != tmp)
161 #ifndef CONFIG_MTD_DOCPROBE_55AA
162 printk(KERN_WARNING "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n",
165 #ifndef DOC_PASSIVE_PROBE
166 /* Put back the contents of the DOCControl register, in case it's not
167 * actually a DiskOnChip.
169 WriteDOC(tmp2, window, DOCControl);
174 printk(KERN_WARNING "DiskOnChip failed TOGGLE test, dropping.\n");
176 #ifndef DOC_PASSIVE_PROBE
177 /* Put back the contents of the DOCControl register: it's not a DiskOnChip */
178 WriteDOC(tmp2, window, DOCControl);
185 static void __init DoC_Probe(unsigned long physadr)
187 unsigned long docptr;
188 struct DiskOnChip *this;
189 struct mtd_info *mtd;
192 char *name = namebuf;
193 char *im_funcname = NULL;
194 char *im_modname = NULL;
195 void (*initroutine)(struct mtd_info *) = NULL;
197 docptr = (unsigned long)ioremap(physadr, DOC_IOREMAP_LEN);
202 if ((ChipID = doccheck(docptr, physadr))) {
204 mtd = kmalloc(sizeof(struct DiskOnChip) + sizeof(struct mtd_info), GFP_KERNEL);
207 printk(KERN_WARNING "Cannot allocate memory for data structures. Dropping.\n");
208 iounmap((void *)docptr);
212 this = (struct DiskOnChip *)(&mtd[1]);
214 memset((char *)mtd,0, sizeof(struct mtd_info));
215 memset((char *)this, 0, sizeof(struct DiskOnChip));
218 this->virtadr = docptr;
219 this->physadr = physadr;
220 this->ChipID = ChipID;
221 sprintf(namebuf, "with ChipID %2.2X", ChipID);
224 case DOC_ChipID_Doc2k:
226 im_funcname = "DoC2k_init";
227 im_modname = "doc2000";
230 case DOC_ChipID_DocMil:
232 #ifdef DOC_SINGLE_DRIVER
233 im_funcname = "DoC2k_init";
234 im_modname = "doc2000";
236 im_funcname = "DoCMil_init";
237 im_modname = "doc2001";
238 #endif /* DOC_SINGLE_DRIVER */
243 initroutine = inter_module_get_request(im_funcname, im_modname);
247 inter_module_put(im_funcname);
250 printk(KERN_NOTICE "Cannot find driver for DiskOnChip %s at 0x%lX\n", name, physadr);
252 iounmap((void *)docptr);
256 /****************************************************************************
260 ****************************************************************************/
262 int __init init_doc(void)
266 if (doc_config_location) {
267 printk(KERN_INFO "Using configured DiskOnChip probe address 0x%lx\n", doc_config_location);
268 DoC_Probe(doc_config_location);
270 for (i=0; doc_locations[i]; i++) {
271 DoC_Probe(doc_locations[i]);
274 /* No banner message any more. Print a message if no DiskOnChip
275 found, so the user knows we at least tried. */
277 printk(KERN_INFO "No recognised DiskOnChip devices found\n");
278 /* So it looks like we've been used and we get unloaded */
285 module_init(init_doc);
287 MODULE_LICENSE("GPL");
288 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
289 MODULE_DESCRIPTION("Probe code for DiskOnChip 2000 and Millennium devices");