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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [mtd/] [chips/] [gen_probe.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Routines common to all CFI-type probes.
3
 * (C) 2001, 2001 Red Hat, Inc.
4
 * GPL'd
5
 * $Id: gen_probe.c,v 1.1.1.1 2004-04-15 01:52:06 phoenix Exp $
6
 */
7
 
8
#include <linux/kernel.h>
9
#include <linux/mtd/mtd.h>
10
#include <linux/mtd/map.h>
11
#include <linux/mtd/cfi.h>
12
#include <linux/mtd/gen_probe.h>
13
 
14
static struct mtd_info *check_cmd_set(struct map_info *, int);
15
static struct cfi_private *genprobe_ident_chips(struct map_info *map,
16
                                                struct chip_probe *cp);
17
static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,
18
                             struct cfi_private *cfi);
19
 
20
struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp)
21
{
22
        struct mtd_info *mtd = NULL;
23
        struct cfi_private *cfi;
24
 
25
        /* First probe the map to see if we have CFI stuff there. */
26
        cfi = genprobe_ident_chips(map, cp);
27
 
28
        if (!cfi)
29
                return NULL;
30
 
31
        map->fldrv_priv = cfi;
32
        /* OK we liked it. Now find a driver for the command set it talks */
33
 
34
        mtd = check_cmd_set(map, 1); /* First the primary cmdset */
35
        if (!mtd)
36
                mtd = check_cmd_set(map, 0); /* Then the secondary */
37
 
38
        if (mtd)
39
                return mtd;
40
 
41
        printk(KERN_WARNING"gen_probe: No supported Vendor Command Set found\n");
42
 
43
        kfree(cfi->cfiq);
44
        kfree(cfi);
45
        map->fldrv_priv = NULL;
46
        return NULL;
47
}
48
EXPORT_SYMBOL(mtd_do_chip_probe);
49
 
50
 
51
struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp)
52
{
53
        unsigned long base=0;
54
        struct cfi_private cfi;
55
        struct cfi_private *retcfi;
56
        struct flchip chip[MAX_CFI_CHIPS];
57
        int i;
58
 
59
        memset(&cfi, 0, sizeof(cfi));
60
 
61
        /* Call the probetype-specific code with all permutations of
62
           interleave and device type, etc. */
63
        if (!genprobe_new_chip(map, cp, &cfi)) {
64
                /* The probe didn't like it */
65
                printk(KERN_WARNING "%s: Found no %s device at location zero\n",
66
                       cp->name, map->name);
67
                return NULL;
68
        }
69
 
70
#if 0 /* Let the CFI probe routine do this sanity check. The Intel and AMD
71
         probe routines won't ever return a broken CFI structure anyway,
72
         because they make them up themselves.
73
      */
74
        if (cfi.cfiq->NumEraseRegions == 0) {
75
                printk(KERN_WARNING "Number of erase regions is zero\n");
76
                kfree(cfi.cfiq);
77
                return NULL;
78
        }
79
#endif
80
        chip[0].start = 0;
81
        chip[0].state = FL_READY;
82
        cfi.chipshift = cfi.cfiq->DevSize;
83
 
84
        switch(cfi.interleave) {
85
#ifdef CFIDEV_INTERLEAVE_1
86
        case 1:
87
                break;
88
#endif
89
#ifdef CFIDEV_INTERLEAVE_2
90
        case 2:
91
                cfi.chipshift++;
92
                break;
93
#endif
94
#ifdef CFIDEV_INTERLEAVE_4
95
        case 4:
96
                cfi.chipshift+=2;
97
                break;
98
#endif
99
        default:
100
                BUG();
101
        }
102
 
103
        cfi.numchips = 1;
104
 
105
        /*
106
         * Now probe for other chips, checking sensibly for aliases while
107
         * we're at it. The new_chip probe above should have let the first
108
         * chip in read mode.
109
         *
110
         * NOTE: Here, we're checking if there is room for another chip
111
         *       the same size within the mapping. Therefore,
112
         *       base + chipsize <= map->size is the correct thing to do,
113
         *       because, base + chipsize would be the  _first_ byte of the
114
         *       next chip, not the one we're currently pondering.
115
         */
116
 
117
        for (base = (1<<cfi.chipshift); base + (1<<cfi.chipshift) <= map->size;
118
             base += (1<<cfi.chipshift))
119
                cp->probe_chip(map, base, &chip[0], &cfi);
120
 
121
        /*
122
         * Now allocate the space for the structures we need to return to
123
         * our caller, and copy the appropriate data into them.
124
         */
125
 
126
        retcfi = kmalloc(sizeof(struct cfi_private) + cfi.numchips * sizeof(struct flchip), GFP_KERNEL);
127
 
128
        if (!retcfi) {
129
                printk(KERN_WARNING "%s: kmalloc failed for CFI private structure\n", map->name);
130
                kfree(cfi.cfiq);
131
                return NULL;
132
        }
133
 
134
        memcpy(retcfi, &cfi, sizeof(cfi));
135
        memcpy(&retcfi->chips[0], chip, sizeof(struct flchip) * cfi.numchips);
136
 
137
        /* Fix up the stuff that breaks when you move it */
138
        for (i=0; i< retcfi->numchips; i++) {
139
                init_waitqueue_head(&retcfi->chips[i].wq);
140
                spin_lock_init(&retcfi->chips[i]._spinlock);
141
                retcfi->chips[i].mutex = &retcfi->chips[i]._spinlock;
142
        }
143
 
144
        return retcfi;
145
}
146
 
147
 
148
static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,
149
                             struct cfi_private *cfi)
150
{
151
        switch (map->buswidth) {
152
#ifdef CFIDEV_BUSWIDTH_1                
153
        case CFIDEV_BUSWIDTH_1:
154
                cfi->interleave = CFIDEV_INTERLEAVE_1;
155
 
156
                cfi->device_type = CFI_DEVICETYPE_X8;
157
                if (cp->probe_chip(map, 0, NULL, cfi))
158
                        return 1;
159
 
160
                cfi->device_type = CFI_DEVICETYPE_X16;
161
                if (cp->probe_chip(map, 0, NULL, cfi))
162
                        return 1;
163
                break;
164
#endif /* CFIDEV_BUSWITDH_1 */
165
 
166
#ifdef CFIDEV_BUSWIDTH_2                
167
        case CFIDEV_BUSWIDTH_2:
168
#ifdef CFIDEV_INTERLEAVE_1
169
                cfi->interleave = CFIDEV_INTERLEAVE_1;
170
 
171
                cfi->device_type = CFI_DEVICETYPE_X16;
172
                if (cp->probe_chip(map, 0, NULL, cfi))
173
                        return 1;
174
#endif /* CFIDEV_INTERLEAVE_1 */
175
#ifdef CFIDEV_INTERLEAVE_2
176
                cfi->interleave = CFIDEV_INTERLEAVE_2;
177
 
178
                cfi->device_type = CFI_DEVICETYPE_X8;
179
                if (cp->probe_chip(map, 0, NULL, cfi))
180
                        return 1;
181
 
182
                cfi->device_type = CFI_DEVICETYPE_X16;
183
                if (cp->probe_chip(map, 0, NULL, cfi))
184
                        return 1;
185
#endif /* CFIDEV_INTERLEAVE_2 */
186
                break;
187
#endif /* CFIDEV_BUSWIDTH_2 */
188
 
189
#ifdef CFIDEV_BUSWIDTH_4
190
        case CFIDEV_BUSWIDTH_4:
191
#if defined(CFIDEV_INTERLEAVE_1) && defined(SOMEONE_ACTUALLY_MAKES_THESE)
192
                cfi->interleave = CFIDEV_INTERLEAVE_1;
193
 
194
                cfi->device_type = CFI_DEVICETYPE_X32;
195
                if (cp->probe_chip(map, 0, NULL, cfi))
196
                        return 1;
197
#endif /* CFIDEV_INTERLEAVE_1 */
198
#ifdef CFIDEV_INTERLEAVE_2
199
                cfi->interleave = CFIDEV_INTERLEAVE_2;
200
 
201
#ifdef SOMEONE_ACTUALLY_MAKES_THESE
202
                cfi->device_type = CFI_DEVICETYPE_X32;
203
                if (cp->probe_chip(map, 0, NULL, cfi))
204
                        return 1;
205
#endif
206
                cfi->device_type = CFI_DEVICETYPE_X16;
207
                if (cp->probe_chip(map, 0, NULL, cfi))
208
                        return 1;
209
 
210
                cfi->device_type = CFI_DEVICETYPE_X8;
211
                if (cp->probe_chip(map, 0, NULL, cfi))
212
                        return 1;
213
#endif /* CFIDEV_INTERLEAVE_2 */
214
#ifdef CFIDEV_INTERLEAVE_4
215
                cfi->interleave = CFIDEV_INTERLEAVE_4;
216
 
217
#ifdef SOMEONE_ACTUALLY_MAKES_THESE
218
                cfi->device_type = CFI_DEVICETYPE_X32;
219
                if (cp->probe_chip(map, 0, NULL, cfi))
220
                        return 1;
221
#endif
222
                cfi->device_type = CFI_DEVICETYPE_X16;
223
                if (cp->probe_chip(map, 0, NULL, cfi))
224
                        return 1;
225
 
226
                cfi->device_type = CFI_DEVICETYPE_X8;
227
                if (cp->probe_chip(map, 0, NULL, cfi))
228
                        return 1;
229
#endif /* CFIDEV_INTERLEAVE_4 */
230
                break;
231
#endif /* CFIDEV_BUSWIDTH_4 */
232
 
233
#ifdef CFIDEV_BUSWIDTH_8
234
        case CFIDEV_BUSWIDTH_8:
235
#if defined(CFIDEV_INTERLEAVE_2) && defined(SOMEONE_ACTUALLY_MAKES_THESE)
236
                cfi->interleave = CFIDEV_INTERLEAVE_2;
237
 
238
                cfi->device_type = CFI_DEVICETYPE_X32;
239
                if (cp->probe_chip(map, 0, NULL, cfi))
240
                        return 1;
241
#endif /* CFIDEV_INTERLEAVE_2 */
242
#ifdef CFIDEV_INTERLEAVE_4
243
                cfi->interleave = CFIDEV_INTERLEAVE_4;
244
 
245
#ifdef SOMEONE_ACTUALLY_MAKES_THESE
246
                cfi->device_type = CFI_DEVICETYPE_X32;
247
                if (cp->probe_chip(map, 0, NULL, cfi))
248
                        return 1;
249
#endif
250
                cfi->device_type = CFI_DEVICETYPE_X16;
251
                if (cp->probe_chip(map, 0, NULL, cfi))
252
                        return 1;
253
#endif /* CFIDEV_INTERLEAVE_4 */
254
#ifdef CFIDEV_INTERLEAVE_8
255
                cfi->interleave = CFIDEV_INTERLEAVE_8;
256
 
257
                cfi->device_type = CFI_DEVICETYPE_X16;
258
                if (cp->probe_chip(map, 0, NULL, cfi))
259
                        return 1;
260
 
261
                cfi->device_type = CFI_DEVICETYPE_X8;
262
                if (cp->probe_chip(map, 0, NULL, cfi))
263
                        return 1;
264
#endif /* CFIDEV_INTERLEAVE_8 */
265
                break;
266
#endif /* CFIDEV_BUSWIDTH_8 */
267
 
268
        default:
269
                printk(KERN_WARNING "genprobe_new_chip called with unsupported buswidth %d\n", map->buswidth);
270
                return 0;
271
        }
272
        return 0;
273
}
274
 
275
 
276
typedef struct mtd_info *cfi_cmdset_fn_t(struct map_info *, int);
277
 
278
extern cfi_cmdset_fn_t cfi_cmdset_0001;
279
extern cfi_cmdset_fn_t cfi_cmdset_0002;
280
extern cfi_cmdset_fn_t cfi_cmdset_0020;
281
 
282
static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map,
283
                                                  int primary)
284
{
285
        struct cfi_private *cfi = map->fldrv_priv;
286
        __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID;
287
#if defined(CONFIG_MODULES) && defined(HAVE_INTER_MODULE)
288
        char probename[32];
289
        cfi_cmdset_fn_t *probe_function;
290
 
291
        sprintf(probename, "cfi_cmdset_%4.4X", type);
292
 
293
        probe_function = inter_module_get_request(probename, probename);
294
 
295
        if (probe_function) {
296
                struct mtd_info *mtd;
297
 
298
                mtd = (*probe_function)(map, primary);
299
                /* If it was happy, it'll have increased its own use count */
300
                inter_module_put(probename);
301
                return mtd;
302
        }
303
#endif
304
        printk(KERN_NOTICE "Support for command set %04X not present\n",
305
               type);
306
 
307
        return NULL;
308
}
309
 
310
static struct mtd_info *check_cmd_set(struct map_info *map, int primary)
311
{
312
        struct cfi_private *cfi = map->fldrv_priv;
313
        __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID;
314
 
315
        if (type == P_ID_NONE || type == P_ID_RESERVED)
316
                return NULL;
317
 
318
        switch(type){
319
                /* Urgh. Ifdefs. The version with weak symbols was
320
                 * _much_ nicer. Shame it didn't seem to work on
321
                 * anything but x86, really.
322
                 * But we can't rely in inter_module_get() because
323
                 * that'd mean we depend on link order.
324
                 */
325
#ifdef CONFIG_MTD_CFI_INTELEXT
326
        case 0x0001:
327
        case 0x0003:
328
                return cfi_cmdset_0001(map, primary);
329
#endif
330
#ifdef CONFIG_MTD_CFI_AMDSTD
331
        case 0x0002:
332
                return cfi_cmdset_0002(map, primary);
333
#endif
334
#ifdef CONFIG_MTD_CFI_STAA
335
        case 0x0020:
336
                return cfi_cmdset_0020(map, primary);
337
#endif
338
        }
339
 
340
        return cfi_cmdset_unknown(map, primary);
341
}
342
 
343
MODULE_LICENSE("GPL");
344
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
345
MODULE_DESCRIPTION("Helper routines for flash chip probe code");

powered by: WebSVN 2.1.0

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