OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [mtd/] [devices/] [docprobe.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
 
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>          */
6
 
7
/* $Id: docprobe.c,v 1.1.1.1 2004-04-15 01:52:04 phoenix Exp $  */
8
 
9
 
10
 
11
/* DOC_PASSIVE_PROBE:
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
16
   DOCControl register.
17
 
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
24
   the machine.
25
 
26
   If you have this problem, uncomment the following line:
27
#define DOC_PASSIVE_PROBE
28
*/
29
 
30
 
31
/* DOC_SINGLE_DRIVER:
32
   Millennium driver has been merged into DOC2000 driver.
33
 
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.
38
 
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
41
   difference is :)
42
*/
43
#define DOC_SINGLE_DRIVER
44
 
45
#include <linux/config.h>
46
#include <linux/kernel.h>
47
#include <linux/module.h>
48
#include <asm/errno.h>
49
#include <asm/io.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>
58
 
59
#include <linux/mtd/mtd.h>
60
#include <linux/mtd/nand.h>
61
#include <linux/mtd/doc2000.h>
62
 
63
/* Where to look for the devices? */
64
#ifndef CONFIG_MTD_DOCPROBE_ADDRESS
65
#define CONFIG_MTD_DOCPROBE_ADDRESS 0
66
#endif
67
 
68
 
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");
72
 
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__)
89
        0xe4000000,
90
#elif defined(CONFIG_MOMENCO_OCELOT)
91
        0x2f000000,
92
        0xff000000,
93
#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
94
        0xff000000,
95
##else
96
#warning Unknown architecture for DiskOnChip. No default probe locations defined
97
#endif
98
 
99
 
100
/* doccheck: Probe a given memory window to see if there's a DiskOnChip present */
101
 
102
static inline int __init doccheck(unsigned long potential, unsigned long physadr)
103
{
104
        unsigned long window=potential;
105
        unsigned char tmp, ChipID;
106
#ifndef DOC_PASSIVE_PROBE
107
        unsigned char tmp2;
108
#endif
109
 
110
        /* Routine copied from the Linux DOC driver */
111
 
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)
116
                return 0;
117
#endif /* CONFIG_MTD_DOCPROBE_55AA */
118
 
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
126
         * found it.
127
         */
128
        tmp2 = ReadDOC(window, DOCControl);
129
 
130
        /* Reset the DiskOnChip ASIC */
131
        WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
132
                 window, DOCControl);
133
        WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
134
                 window, DOCControl);
135
 
136
        /* Enable the DiskOnChip ASIC */
137
        WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
138
                 window, DOCControl);
139
        WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
140
                 window, DOCControl);
141
#endif /* !DOC_PASSIVE_PROBE */ 
142
 
143
        ChipID = ReadDOC(window, ChipID);
144
 
145
        switch (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)
150
                                return ChipID;
151
                break;
152
 
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)
157
                                return ChipID;
158
                break;
159
 
160
        default:
161
#ifndef CONFIG_MTD_DOCPROBE_55AA
162
                printk(KERN_WARNING "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n",
163
                       ChipID, physadr);
164
#endif
165
#ifndef DOC_PASSIVE_PROBE
166
                /* Put back the contents of the DOCControl register, in case it's not
167
                 * actually a DiskOnChip.
168
                 */
169
                WriteDOC(tmp2, window, DOCControl);
170
#endif
171
                return 0;
172
        }
173
 
174
        printk(KERN_WARNING "DiskOnChip failed TOGGLE test, dropping.\n");
175
 
176
#ifndef DOC_PASSIVE_PROBE
177
        /* Put back the contents of the DOCControl register: it's not a DiskOnChip */
178
        WriteDOC(tmp2, window, DOCControl);
179
#endif
180
        return 0;
181
}
182
 
183
static int docfound;
184
 
185
static void __init DoC_Probe(unsigned long physadr)
186
{
187
        unsigned long docptr;
188
        struct DiskOnChip *this;
189
        struct mtd_info *mtd;
190
        int ChipID;
191
        char namebuf[15];
192
        char *name = namebuf;
193
        char *im_funcname = NULL;
194
        char *im_modname = NULL;
195
        void (*initroutine)(struct mtd_info *) = NULL;
196
 
197
        docptr = (unsigned long)ioremap(physadr, DOC_IOREMAP_LEN);
198
 
199
        if (!docptr)
200
                return;
201
 
202
        if ((ChipID = doccheck(docptr, physadr))) {
203
                docfound = 1;
204
                mtd = kmalloc(sizeof(struct DiskOnChip) + sizeof(struct mtd_info), GFP_KERNEL);
205
 
206
                if (!mtd) {
207
                        printk(KERN_WARNING "Cannot allocate memory for data structures. Dropping.\n");
208
                        iounmap((void *)docptr);
209
                        return;
210
                }
211
 
212
                this = (struct DiskOnChip *)(&mtd[1]);
213
 
214
                memset((char *)mtd,0, sizeof(struct mtd_info));
215
                memset((char *)this, 0, sizeof(struct DiskOnChip));
216
 
217
                mtd->priv = this;
218
                this->virtadr = docptr;
219
                this->physadr = physadr;
220
                this->ChipID = ChipID;
221
                sprintf(namebuf, "with ChipID %2.2X", ChipID);
222
 
223
                switch(ChipID) {
224
                case DOC_ChipID_Doc2k:
225
                        name="2000";
226
                        im_funcname = "DoC2k_init";
227
                        im_modname = "doc2000";
228
                        break;
229
 
230
                case DOC_ChipID_DocMil:
231
                        name="Millennium";
232
#ifdef DOC_SINGLE_DRIVER
233
                        im_funcname = "DoC2k_init";
234
                        im_modname = "doc2000";
235
#else
236
                        im_funcname = "DoCMil_init";
237
                        im_modname = "doc2001";
238
#endif /* DOC_SINGLE_DRIVER */
239
                        break;
240
                }
241
 
242
                if (im_funcname)
243
                        initroutine = inter_module_get_request(im_funcname, im_modname);
244
 
245
                if (initroutine) {
246
                        (*initroutine)(mtd);
247
                        inter_module_put(im_funcname);
248
                        return;
249
                }
250
                printk(KERN_NOTICE "Cannot find driver for DiskOnChip %s at 0x%lX\n", name, physadr);
251
        }
252
        iounmap((void *)docptr);
253
}
254
 
255
 
256
/****************************************************************************
257
 *
258
 * Module stuff
259
 *
260
 ****************************************************************************/
261
 
262
int __init init_doc(void)
263
{
264
        int i;
265
 
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);
269
        } else {
270
                for (i=0; doc_locations[i]; i++) {
271
                        DoC_Probe(doc_locations[i]);
272
                }
273
        }
274
        /* No banner message any more. Print a message if no DiskOnChip
275
           found, so the user knows we at least tried. */
276
        if (!docfound)
277
                printk(KERN_INFO "No recognised DiskOnChip devices found\n");
278
        /* So it looks like we've been used and we get unloaded */
279
        MOD_INC_USE_COUNT;
280
        MOD_DEC_USE_COUNT;
281
        return 0;
282
 
283
}
284
 
285
module_init(init_doc);
286
 
287
MODULE_LICENSE("GPL");
288
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
289
MODULE_DESCRIPTION("Probe code for DiskOnChip 2000 and Millennium devices");
290
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.