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/config.h>
31 #include <linux/kernel.h>
32 #include <linux/module.h>
33 #include <linux/kmod.h>
34 #include <asm/errno.h>
36 #include <asm/uaccess.h>
37 #include <linux/miscdevice.h>
38 #include <linux/pci.h>
39 #include <linux/delay.h>
40 #include <linux/malloc.h>
41 #include <linux/sched.h>
42 #include <linux/init.h>
43 #include <linux/types.h>
45 #include <linux/mtd/mtd.h>
46 #include <linux/mtd/nand.h>
47 #include <linux/mtd/doc2000.h>
49 /* Where to look for the devices? */
51 #if defined (__alpha__) || defined(__i386__)
52 static unsigned long __initdata doc_locations
[] = {
53 0xc8000, 0xca000, 0xcc000, 0xce000,
54 0xd0000, 0xd2000, 0xd4000, 0xd6000,
55 0xd8000, 0xda000, 0xdc000, 0xde000,
56 0xe0000, 0xe2000, 0xe4000, 0xe6000,
57 0xe8000, 0xea000, 0xec000, 0xee000, 0 };
58 #elif defined(__ppc__)
59 static unsigned long __initdata doc_locations
[] = {
62 #warning Unknown architecture for DiskOnChip. No default probe locations defined
65 #ifdef CONFIG_MTD_DOC2000
66 extern void DoC2k_init(struct mtd_info
*);
68 #ifdef CONFIG_MTD_DOC2001
69 extern void DoCMil_init(struct mtd_info
*);
72 /* doccheck: Probe a given memory window to see if there's a DiskOnChip present */
74 static inline int __init
doccheck(unsigned long potential
, unsigned long physadr
)
76 unsigned long window
=potential
;
77 unsigned char tmp
, ChipID
;
78 #ifndef DOC_PASSIVE_PROBE
82 /* Routine copied from the Linux DOC driver */
84 /* Check for 0x55 0xAA signature at beginning of window */
85 if (ReadDOC(window
, Sig1
) != 0x55 || ReadDOC(window
, Sig2
) != 0xaa)
88 #ifndef DOC_PASSIVE_PROBE
89 /* It's not possible to cleanly detect the DiskOnChip - the
90 * bootup procedure will put the device into reset mode, and
91 * it's not possible to talk to it without actually writing
92 * to the DOCControl register. So we store the current contents
93 * of the DOCControl register's location, in case we later decide
94 * that it's not a DiskOnChip, and want to put it back how we
97 tmp2
= ReadDOC(window
, DOCControl
);
99 /* Reset the DiskOnChip ASIC */
100 WriteDOC(DOC_MODE_CLR_ERR
| DOC_MODE_MDWREN
| DOC_MODE_RESET
,
102 WriteDOC(DOC_MODE_CLR_ERR
| DOC_MODE_MDWREN
| DOC_MODE_RESET
,
105 /* Enable the DiskOnChip ASIC */
106 WriteDOC(DOC_MODE_CLR_ERR
| DOC_MODE_MDWREN
| DOC_MODE_NORMAL
,
108 WriteDOC(DOC_MODE_CLR_ERR
| DOC_MODE_MDWREN
| DOC_MODE_NORMAL
,
110 #endif /* !DOC_PASSIVE_PROBE */
112 ChipID
= ReadDOC(window
, ChipID
);
115 case DOC_ChipID_Doc2k
:
116 /* Check the TOGGLE bit in the ECC register */
117 tmp
= ReadDOC(window
, 2k_ECCStatus
) & DOC_TOGGLE_BIT
;
118 if ((ReadDOC(window
, 2k_ECCStatus
) & DOC_TOGGLE_BIT
) != tmp
)
122 case DOC_ChipID_DocMil
:
123 /* Check the TOGGLE bit in the ECC register */
124 tmp
= ReadDOC(window
, ECCConf
) & DOC_TOGGLE_BIT
;
125 if ((ReadDOC(window
, ECCConf
) & DOC_TOGGLE_BIT
) != tmp
)
130 printk(KERN_WARNING
"Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n",
133 #ifndef DOC_PASSIVE_PROBE
134 /* Put back the contents of the DOCControl register, in case it's not
135 * actually a DiskOnChip.
137 WriteDOC(tmp2
, window
, DOCControl
);
142 printk(KERN_WARNING
"DiskOnChip failed TOGGLE test, dropping.\n");
144 #ifndef DOC_PASSIVE_PROBE
145 /* Put back the contents of the DOCControl register: it's not a DiskOnChip */
146 WriteDOC(tmp2
, window
, DOCControl
);
152 static void DoC_Probe(unsigned long physadr
)
154 unsigned long docptr
;
155 struct DiskOnChip
*this;
156 struct mtd_info
*mtd
;
159 char *name
= namebuf
;
160 void (*initroutine
)(struct mtd_info
*) = NULL
;
161 int initroutinedynamic
= 0;
163 docptr
= (unsigned long)ioremap(physadr
, 0x2000);
168 if ((ChipID
= doccheck(docptr
, physadr
))) {
170 mtd
= kmalloc(sizeof(struct DiskOnChip
) + sizeof(struct mtd_info
), GFP_KERNEL
);
173 printk("Cannot allocate memory for data structures. Dropping.\n");
174 iounmap((void *)docptr
);
178 this = (struct DiskOnChip
*)(&mtd
[1]);
180 memset((char *)mtd
,0, sizeof(struct mtd_info
));
181 memset((char *)this, 0, sizeof(struct DiskOnChip
));
184 this->virtadr
= docptr
;
185 this->physadr
= physadr
;
186 this->ChipID
= ChipID
;
187 sprintf(namebuf
, "with ChipID %2.2X", ChipID
);
190 case DOC_ChipID_Doc2k
:
192 #ifdef CONFIG_MTD_DOC2000
193 initroutine
= &DoC2k_init
;
195 initroutinedynamic
=1;
196 initroutine
= (void *)get_module_symbol(NULL
, "DoC2k_init");
199 request_module("doc2000");
200 initroutine
= (void *)get_module_symbol("doc2000", "DoC2k_init");
202 #endif /* CONFIG_KMOD */
206 case DOC_ChipID_DocMil
:
208 #ifdef CONFIG_MTD_DOC2001
209 initroutine
= &DocMil_init
;
211 initroutinedynamic
=1;
212 initroutine
= (void *)get_module_symbol(NULL
, "DoCMil_init");
215 request_module("doc2001");
216 initroutine
= (void *)get_module_symbol("doc2001", "DoCMil_init");
218 #endif /* CONFIG_KMOD */
224 #if defined(CONFIG_MODULES) && LINUX_VERSION_CODE >= 0x20400
225 if (initroutinedynamic
)
226 put_module_symbol(initroutine
);
230 printk("Cannot find driver for DiskOnChip %s at 0x%X\n", name
, physadr
);
232 iounmap((void *)docptr
);
236 /****************************************************************************
240 ****************************************************************************/
242 #if LINUX_VERSION_CODE < 0x20300
244 #define init_doc init_module
249 int __init
init_doc(void)
253 printk(KERN_NOTICE
"M-Systems DiskOnChip driver. (C) 1999 Machine Vision Holdings, Inc.\n");
255 printk(KERN_INFO
"$Id: docprobe.c,v 1.8 2000/06/26 20:40:53 dwmw2 Exp $\n");
258 for (i
=0; doc_locations
[i
]; i
++) {
259 DoC_Probe(doc_locations
[i
]);
267 #if LINUX_VERSION_CODE > 0x20300
268 module_init(init_doc
);