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.8 2000/06/26 20:40:53 dwmw2 Exp $ */
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
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
25 If you have this problem, uncomment the following line:
26 #define DOC_PASSIVE_PROBE
30 #include <linux/kernel.h>
31 #include <linux/module.h>
32 #include <linux/kmod.h>
33 #include <asm/errno.h>
35 #include <asm/uaccess.h>
36 #include <linux/miscdevice.h>
37 #include <linux/pci.h>
38 #include <linux/delay.h>
39 #include <linux/malloc.h>
40 #include <linux/sched.h>
41 #include <linux/init.h>
42 #include <linux/types.h>
44 #include <linux/mtd/mtd.h>
45 #include <linux/mtd/nand.h>
46 #include <linux/mtd/doc2000.h>
48 /* Where to look for the devices? */
50 #if defined (__alpha__) || defined(__i386__)
51 static unsigned long __initdata doc_locations
[] = {
52 0xc8000, 0xca000, 0xcc000, 0xce000,
53 0xd0000, 0xd2000, 0xd4000, 0xd6000,
54 0xd8000, 0xda000, 0xdc000, 0xde000,
55 0xe0000, 0xe2000, 0xe4000, 0xe6000,
56 0xe8000, 0xea000, 0xec000, 0xee000, 0 };
57 #elif defined(__ppc__)
58 static unsigned long __initdata doc_locations
[] = {
61 #warning Unknown architecture for DiskOnChip. No default probe locations defined
64 #ifdef CONFIG_MTD_DOC2000
65 extern void DoC2k_init(struct mtd_info
*);
67 #ifdef CONFIG_MTD_DOC2001
68 extern void DoCMil_init(struct mtd_info
*);
71 /* doccheck: Probe a given memory window to see if there's a DiskOnChip present */
73 static inline int __init
doccheck(unsigned long potential
, unsigned long physadr
)
75 unsigned long window
=potential
;
76 unsigned char tmp
, ChipID
;
77 #ifndef DOC_PASSIVE_PROBE
81 /* Routine copied from the Linux DOC driver */
83 /* Check for 0x55 0xAA signature at beginning of window */
84 if (ReadDOC(window
, Sig1
) != 0x55 || ReadDOC(window
, Sig2
) != 0xaa)
87 #ifndef DOC_PASSIVE_PROBE
88 /* It's not possible to cleanly detect the DiskOnChip - the
89 * bootup procedure will put the device into reset mode, and
90 * it's not possible to talk to it without actually writing
91 * to the DOCControl register. So we store the current contents
92 * of the DOCControl register's location, in case we later decide
93 * that it's not a DiskOnChip, and want to put it back how we
96 tmp2
= ReadDOC(window
, DOCControl
);
98 /* Reset the DiskOnChip ASIC */
99 WriteDOC(DOC_MODE_CLR_ERR
| DOC_MODE_MDWREN
| DOC_MODE_RESET
,
101 WriteDOC(DOC_MODE_CLR_ERR
| DOC_MODE_MDWREN
| DOC_MODE_RESET
,
104 /* Enable the DiskOnChip ASIC */
105 WriteDOC(DOC_MODE_CLR_ERR
| DOC_MODE_MDWREN
| DOC_MODE_NORMAL
,
107 WriteDOC(DOC_MODE_CLR_ERR
| DOC_MODE_MDWREN
| DOC_MODE_NORMAL
,
109 #endif /* !DOC_PASSIVE_PROBE */
111 ChipID
= ReadDOC(window
, ChipID
);
114 case DOC_ChipID_Doc2k
:
115 /* Check the TOGGLE bit in the ECC register */
116 tmp
= ReadDOC(window
, 2k_ECCStatus
) & DOC_TOGGLE_BIT
;
117 if ((ReadDOC(window
, 2k_ECCStatus
) & DOC_TOGGLE_BIT
) != tmp
)
121 case DOC_ChipID_DocMil
:
122 /* Check the TOGGLE bit in the ECC register */
123 tmp
= ReadDOC(window
, ECCConf
) & DOC_TOGGLE_BIT
;
124 if ((ReadDOC(window
, ECCConf
) & DOC_TOGGLE_BIT
) != tmp
)
129 printk(KERN_WARNING
"Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n",
132 #ifndef DOC_PASSIVE_PROBE
133 /* Put back the contents of the DOCControl register, in case it's not
134 * actually a DiskOnChip.
136 WriteDOC(tmp2
, window
, DOCControl
);
141 printk(KERN_WARNING
"DiskOnChip failed TOGGLE test, dropping.\n");
143 #ifndef DOC_PASSIVE_PROBE
144 /* Put back the contents of the DOCControl register: it's not a DiskOnChip */
145 WriteDOC(tmp2
, window
, DOCControl
);
151 static void DoC_Probe(unsigned long physadr
)
153 unsigned long docptr
;
154 struct DiskOnChip
*this;
155 struct mtd_info
*mtd
;
158 char *name
= namebuf
;
159 void (*initroutine
)(struct mtd_info
*) = NULL
;
160 int initroutinedynamic
= 0;
162 docptr
= (unsigned long)ioremap(physadr
, 0x2000);
167 if ((ChipID
= doccheck(docptr
, physadr
))) {
169 mtd
= kmalloc(sizeof(struct DiskOnChip
) + sizeof(struct mtd_info
), GFP_KERNEL
);
172 printk("Cannot allocate memory for data structures. Dropping.\n");
173 iounmap((void *)docptr
);
177 this = (struct DiskOnChip
*)(&mtd
[1]);
179 memset((char *)mtd
,0, sizeof(struct mtd_info
));
180 memset((char *)this, 0, sizeof(struct DiskOnChip
));
183 this->virtadr
= docptr
;
184 this->physadr
= physadr
;
185 this->ChipID
= ChipID
;
186 sprintf(namebuf
, "with ChipID %2.2X", ChipID
);
189 case DOC_ChipID_Doc2k
:
191 #ifdef CONFIG_MTD_DOC2000
192 initroutine
= &DoC2k_init
;
194 initroutinedynamic
=1;
195 initroutine
= (void *)get_module_symbol(NULL
, "DoC2k_init");
198 request_module("doc2000");
199 initroutine
= (void *)get_module_symbol("doc2000", "DoC2k_init");
201 #endif /* CONFIG_KMOD */
205 case DOC_ChipID_DocMil
:
207 #ifdef CONFIG_MTD_DOC2001
208 initroutine
= &DocMil_init
;
210 initroutinedynamic
=1;
211 initroutine
= (void *)get_module_symbol(NULL
, "DoCMil_init");
214 request_module("doc2001");
215 initroutine
= (void *)get_module_symbol("doc2001", "DoCMil_init");
217 #endif /* CONFIG_KMOD */
223 #if defined(CONFIG_MODULES) && LINUX_VERSION_CODE >= 0x20400
224 if (initroutinedynamic
)
225 put_module_symbol(initroutine
);
229 printk("Cannot find driver for DiskOnChip %s at 0x%X\n", name
, physadr
);
231 iounmap((void *)docptr
);
235 /****************************************************************************
239 ****************************************************************************/
241 #if LINUX_VERSION_CODE < 0x20300
243 #define init_doc init_module
248 int __init
init_doc(void)
252 printk(KERN_NOTICE
"M-Systems DiskOnChip driver. (C) 1999 Machine Vision Holdings, Inc.\n");
254 printk(KERN_INFO
"$Id: docprobe.c,v 1.8 2000/06/26 20:40:53 dwmw2 Exp $\n");
257 for (i
=0; doc_locations
[i
]; i
++) {
258 DoC_Probe(doc_locations
[i
]);
266 #if LINUX_VERSION_CODE > 0x20300
267 module_init(init_doc
);