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> */
9 In order to ensure that the BIOS checksum is correct at boot time, and
10 hence that the onboard BIOS extension gets executed, the DiskOnChip
11 goes into reset mode when it is read sequentially: all registers
12 return 0xff until the chip is woken up again by writing to the
15 Unfortunately, this means that the probe for the DiskOnChip is unsafe,
16 because one of the first things it does is write to where it thinks
17 the DOCControl register should be - which may well be shared memory
18 for another device. I've had machines which lock up when this is
19 attempted. Hence the possibility to do a passive probe, which will fail
20 to detect a chip in reset mode, but is at least guaranteed not to lock
23 If you have this problem, uncomment the following line:
24 #define DOC_PASSIVE_PROBE
29 Millennium driver has been merged into DOC2000 driver.
31 The old Millennium-only driver has been retained just in case there
32 are problems with the new code. If the combined driver doesn't work
33 for you, you can try the old one by undefining DOC_SINGLE_DRIVER
34 below and also enabling it in your configuration. If this fixes the
35 problems, please send a report to the MTD mailing list at
36 <linux-mtd@lists.infradead.org>.
38 #define DOC_SINGLE_DRIVER
40 #include <linux/kernel.h>
41 #include <linux/module.h>
42 #include <asm/errno.h>
44 #include <linux/delay.h>
45 #include <linux/slab.h>
46 #include <linux/init.h>
47 #include <linux/types.h>
49 #include <linux/mtd/mtd.h>
50 #include <linux/mtd/nand.h>
51 #include <linux/mtd/doc2000.h>
53 /* Where to look for the devices? */
54 #ifndef CONFIG_MTD_DOCPROBE_ADDRESS
55 #define CONFIG_MTD_DOCPROBE_ADDRESS 0
59 static unsigned long doc_config_location
= CONFIG_MTD_DOCPROBE_ADDRESS
;
60 module_param(doc_config_location
, ulong
, 0);
61 MODULE_PARM_DESC(doc_config_location
, "Physical memory address at which to probe for DiskOnChip");
63 static unsigned long __initdata doc_locations
[] = {
64 #if defined (__alpha__) || defined(__i386__) || defined(__x86_64__)
65 #ifdef CONFIG_MTD_DOCPROBE_HIGH
66 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000,
67 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000,
68 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000,
69 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000,
70 0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000,
71 #else /* CONFIG_MTD_DOCPROBE_HIGH */
72 0xc8000, 0xca000, 0xcc000, 0xce000,
73 0xd0000, 0xd2000, 0xd4000, 0xd6000,
74 0xd8000, 0xda000, 0xdc000, 0xde000,
75 0xe0000, 0xe2000, 0xe4000, 0xe6000,
76 0xe8000, 0xea000, 0xec000, 0xee000,
77 #endif /* CONFIG_MTD_DOCPROBE_HIGH */
79 #warning Unknown architecture for DiskOnChip. No default probe locations defined
83 /* doccheck: Probe a given memory window to see if there's a DiskOnChip present */
85 static inline int __init
doccheck(void __iomem
*potential
, unsigned long physadr
)
87 void __iomem
*window
=potential
;
88 unsigned char tmp
, tmpb
, tmpc
, ChipID
;
89 #ifndef DOC_PASSIVE_PROBE
93 /* Routine copied from the Linux DOC driver */
95 #ifdef CONFIG_MTD_DOCPROBE_55AA
96 /* Check for 0x55 0xAA signature at beginning of window,
97 this is no longer true once we remove the IPL (for Millennium */
98 if (ReadDOC(window
, Sig1
) != 0x55 || ReadDOC(window
, Sig2
) != 0xaa)
100 #endif /* CONFIG_MTD_DOCPROBE_55AA */
102 #ifndef DOC_PASSIVE_PROBE
103 /* It's not possible to cleanly detect the DiskOnChip - the
104 * bootup procedure will put the device into reset mode, and
105 * it's not possible to talk to it without actually writing
106 * to the DOCControl register. So we store the current contents
107 * of the DOCControl register's location, in case we later decide
108 * that it's not a DiskOnChip, and want to put it back how we
111 tmp2
= ReadDOC(window
, DOCControl
);
113 /* Reset the DiskOnChip ASIC */
114 WriteDOC(DOC_MODE_CLR_ERR
| DOC_MODE_MDWREN
| DOC_MODE_RESET
,
116 WriteDOC(DOC_MODE_CLR_ERR
| DOC_MODE_MDWREN
| DOC_MODE_RESET
,
119 /* Enable the DiskOnChip ASIC */
120 WriteDOC(DOC_MODE_CLR_ERR
| DOC_MODE_MDWREN
| DOC_MODE_NORMAL
,
122 WriteDOC(DOC_MODE_CLR_ERR
| DOC_MODE_MDWREN
| DOC_MODE_NORMAL
,
124 #endif /* !DOC_PASSIVE_PROBE */
126 /* We need to read the ChipID register four times. For some
127 newer DiskOnChip 2000 units, the first three reads will
128 return the DiskOnChip Millennium ident. Don't ask. */
129 ChipID
= ReadDOC(window
, ChipID
);
132 case DOC_ChipID_Doc2k
:
133 /* Check the TOGGLE bit in the ECC register */
134 tmp
= ReadDOC(window
, 2k_ECCStatus
) & DOC_TOGGLE_BIT
;
135 tmpb
= ReadDOC(window
, 2k_ECCStatus
) & DOC_TOGGLE_BIT
;
136 tmpc
= ReadDOC(window
, 2k_ECCStatus
) & DOC_TOGGLE_BIT
;
137 if (tmp
!= tmpb
&& tmp
== tmpc
)
141 case DOC_ChipID_DocMil
:
142 /* Check for the new 2000 with Millennium ASIC */
143 ReadDOC(window
, ChipID
);
144 ReadDOC(window
, ChipID
);
145 if (ReadDOC(window
, ChipID
) != DOC_ChipID_DocMil
)
146 ChipID
= DOC_ChipID_Doc2kTSOP
;
148 /* Check the TOGGLE bit in the ECC register */
149 tmp
= ReadDOC(window
, ECCConf
) & DOC_TOGGLE_BIT
;
150 tmpb
= ReadDOC(window
, ECCConf
) & DOC_TOGGLE_BIT
;
151 tmpc
= ReadDOC(window
, ECCConf
) & DOC_TOGGLE_BIT
;
152 if (tmp
!= tmpb
&& tmp
== tmpc
)
156 case DOC_ChipID_DocMilPlus16
:
157 case DOC_ChipID_DocMilPlus32
:
159 /* Possible Millennium+, need to do more checks */
160 #ifndef DOC_PASSIVE_PROBE
161 /* Possibly release from power down mode */
162 for (tmp
= 0; (tmp
< 4); tmp
++)
163 ReadDOC(window
, Mplus_Power
);
165 /* Reset the DiskOnChip ASIC */
166 tmp
= DOC_MODE_RESET
| DOC_MODE_MDWREN
| DOC_MODE_RST_LAT
|
168 WriteDOC(tmp
, window
, Mplus_DOCControl
);
169 WriteDOC(~tmp
, window
, Mplus_CtrlConfirm
);
172 /* Enable the DiskOnChip ASIC */
173 tmp
= DOC_MODE_NORMAL
| DOC_MODE_MDWREN
| DOC_MODE_RST_LAT
|
175 WriteDOC(tmp
, window
, Mplus_DOCControl
);
176 WriteDOC(~tmp
, window
, Mplus_CtrlConfirm
);
178 #endif /* !DOC_PASSIVE_PROBE */
180 ChipID
= ReadDOC(window
, ChipID
);
183 case DOC_ChipID_DocMilPlus16
:
184 case DOC_ChipID_DocMilPlus32
:
185 /* Check the TOGGLE bit in the toggle register */
186 tmp
= ReadDOC(window
, Mplus_Toggle
) & DOC_TOGGLE_BIT
;
187 tmpb
= ReadDOC(window
, Mplus_Toggle
) & DOC_TOGGLE_BIT
;
188 tmpc
= ReadDOC(window
, Mplus_Toggle
) & DOC_TOGGLE_BIT
;
189 if (tmp
!= tmpb
&& tmp
== tmpc
)
198 #ifdef CONFIG_MTD_DOCPROBE_55AA
199 printk(KERN_DEBUG
"Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n",
202 #ifndef DOC_PASSIVE_PROBE
203 /* Put back the contents of the DOCControl register, in case it's not
204 * actually a DiskOnChip.
206 WriteDOC(tmp2
, window
, DOCControl
);
211 printk(KERN_WARNING
"DiskOnChip failed TOGGLE test, dropping.\n");
213 #ifndef DOC_PASSIVE_PROBE
214 /* Put back the contents of the DOCControl register: it's not a DiskOnChip */
215 WriteDOC(tmp2
, window
, DOCControl
);
222 extern void DoC2k_init(struct mtd_info
*);
223 extern void DoCMil_init(struct mtd_info
*);
224 extern void DoCMilPlus_init(struct mtd_info
*);
226 static void __init
DoC_Probe(unsigned long physadr
)
228 void __iomem
*docptr
;
229 struct DiskOnChip
*this;
230 struct mtd_info
*mtd
;
233 char *name
= namebuf
;
234 void (*initroutine
)(struct mtd_info
*) = NULL
;
236 docptr
= ioremap(physadr
, DOC_IOREMAP_LEN
);
241 if ((ChipID
= doccheck(docptr
, physadr
))) {
242 if (ChipID
== DOC_ChipID_Doc2kTSOP
) {
243 /* Remove this at your own peril. The hardware driver works but nothing prevents you from erasing bad blocks */
244 printk(KERN_NOTICE
"Refusing to drive DiskOnChip 2000 TSOP until Bad Block Table is correctly supported by INFTL\n");
249 mtd
= kmalloc(sizeof(struct DiskOnChip
) + sizeof(struct mtd_info
), GFP_KERNEL
);
252 printk(KERN_WARNING
"Cannot allocate memory for data structures. Dropping.\n");
257 this = (struct DiskOnChip
*)(&mtd
[1]);
259 memset((char *)mtd
,0, sizeof(struct mtd_info
));
260 memset((char *)this, 0, sizeof(struct DiskOnChip
));
263 this->virtadr
= docptr
;
264 this->physadr
= physadr
;
265 this->ChipID
= ChipID
;
266 sprintf(namebuf
, "with ChipID %2.2X", ChipID
);
269 case DOC_ChipID_Doc2kTSOP
:
271 initroutine
= symbol_request(DoC2k_init
);
274 case DOC_ChipID_Doc2k
:
276 initroutine
= symbol_request(DoC2k_init
);
279 case DOC_ChipID_DocMil
:
281 #ifdef DOC_SINGLE_DRIVER
282 initroutine
= symbol_request(DoC2k_init
);
284 initroutine
= symbol_request(DoCMil_init
);
285 #endif /* DOC_SINGLE_DRIVER */
288 case DOC_ChipID_DocMilPlus16
:
289 case DOC_ChipID_DocMilPlus32
:
290 name
="MillenniumPlus";
291 initroutine
= symbol_request(DoCMilPlus_init
);
297 symbol_put_addr(initroutine
);
300 printk(KERN_NOTICE
"Cannot find driver for DiskOnChip %s at 0x%lX\n", name
, physadr
);
307 /****************************************************************************
311 ****************************************************************************/
313 static int __init
init_doc(void)
317 if (doc_config_location
) {
318 printk(KERN_INFO
"Using configured DiskOnChip probe address 0x%lx\n", doc_config_location
);
319 DoC_Probe(doc_config_location
);
321 for (i
=0; (doc_locations
[i
] != 0xffffffff); i
++) {
322 DoC_Probe(doc_locations
[i
]);
325 /* No banner message any more. Print a message if no DiskOnChip
326 found, so the user knows we at least tried. */
328 printk(KERN_INFO
"No recognised DiskOnChip devices found\n");
332 module_init(init_doc
);
334 MODULE_LICENSE("GPL");
335 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
336 MODULE_DESCRIPTION("Probe code for DiskOnChip 2000 and Millennium devices");