Merge with http://kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
[sfrench/cifs-2.6.git] / drivers / mtd / chips / gen_probe.c
1 /*
2  * Routines common to all CFI-type probes.
3  * (C) 2001-2003 Red Hat, Inc.
4  * GPL'd
5  * $Id: gen_probe.c,v 1.24 2005/11/07 11:14:23 gleixner Exp $
6  */
7
8 #include <linux/kernel.h>
9 #include <linux/slab.h>
10 #include <linux/module.h>
11 #include <linux/mtd/mtd.h>
12 #include <linux/mtd/map.h>
13 #include <linux/mtd/cfi.h>
14 #include <linux/mtd/gen_probe.h>
15
16 static struct mtd_info *check_cmd_set(struct map_info *, int);
17 static struct cfi_private *genprobe_ident_chips(struct map_info *map,
18                                                 struct chip_probe *cp);
19 static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,
20                              struct cfi_private *cfi);
21
22 struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp)
23 {
24         struct mtd_info *mtd = NULL;
25         struct cfi_private *cfi;
26
27         /* First probe the map to see if we have CFI stuff there. */
28         cfi = genprobe_ident_chips(map, cp);
29
30         if (!cfi)
31                 return NULL;
32
33         map->fldrv_priv = cfi;
34         /* OK we liked it. Now find a driver for the command set it talks */
35
36         mtd = check_cmd_set(map, 1); /* First the primary cmdset */
37         if (!mtd)
38                 mtd = check_cmd_set(map, 0); /* Then the secondary */
39
40         if (mtd)
41                 return mtd;
42
43         printk(KERN_WARNING"gen_probe: No supported Vendor Command Set found\n");
44
45         kfree(cfi->cfiq);
46         kfree(cfi);
47         map->fldrv_priv = NULL;
48         return NULL;
49 }
50 EXPORT_SYMBOL(mtd_do_chip_probe);
51
52
53 static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp)
54 {
55         struct cfi_private cfi;
56         struct cfi_private *retcfi;
57         unsigned long *chip_map;
58         int i, j, mapsize;
59         int max_chips;
60
61         memset(&cfi, 0, sizeof(cfi));
62
63         /* Call the probetype-specific code with all permutations of
64            interleave and device type, etc. */
65         if (!genprobe_new_chip(map, cp, &cfi)) {
66                 /* The probe didn't like it */
67                 printk(KERN_DEBUG "%s: Found no %s device at location zero\n",
68                        cp->name, map->name);
69                 return NULL;
70         }
71
72 #if 0 /* Let the CFI probe routine do this sanity check. The Intel and AMD
73          probe routines won't ever return a broken CFI structure anyway,
74          because they make them up themselves.
75       */
76         if (cfi.cfiq->NumEraseRegions == 0) {
77                 printk(KERN_WARNING "Number of erase regions is zero\n");
78                 kfree(cfi.cfiq);
79                 return NULL;
80         }
81 #endif
82         cfi.chipshift = cfi.cfiq->DevSize;
83
84         if (cfi_interleave_is_1(&cfi)) {
85                 ;
86         } else if (cfi_interleave_is_2(&cfi)) {
87                 cfi.chipshift++;
88         } else if (cfi_interleave_is_4((&cfi))) {
89                 cfi.chipshift += 2;
90         } else if (cfi_interleave_is_8(&cfi)) {
91                 cfi.chipshift += 3;
92         } else {
93                 BUG();
94         }
95
96         cfi.numchips = 1;
97
98         /*
99          * Allocate memory for bitmap of valid chips.
100          * Align bitmap storage size to full byte.
101          */
102         max_chips = map->size >> cfi.chipshift;
103         mapsize = (max_chips / 8) + ((max_chips % 8) ? 1 : 0);
104         chip_map = kmalloc(mapsize, GFP_KERNEL);
105         if (!chip_map) {
106                 printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name);
107                 kfree(cfi.cfiq);
108                 return NULL;
109         }
110         memset (chip_map, 0, mapsize);
111
112         set_bit(0, chip_map); /* Mark first chip valid */
113
114         /*
115          * Now probe for other chips, checking sensibly for aliases while
116          * we're at it. The new_chip probe above should have let the first
117          * chip in read mode.
118          */
119
120         for (i = 1; i < max_chips; i++) {
121                 cp->probe_chip(map, i << cfi.chipshift, chip_map, &cfi);
122         }
123
124         /*
125          * Now allocate the space for the structures we need to return to
126          * our caller, and copy the appropriate data into them.
127          */
128
129         retcfi = kmalloc(sizeof(struct cfi_private) + cfi.numchips * sizeof(struct flchip), GFP_KERNEL);
130
131         if (!retcfi) {
132                 printk(KERN_WARNING "%s: kmalloc failed for CFI private structure\n", map->name);
133                 kfree(cfi.cfiq);
134                 kfree(chip_map);
135                 return NULL;
136         }
137
138         memcpy(retcfi, &cfi, sizeof(cfi));
139         memset(&retcfi->chips[0], 0, sizeof(struct flchip) * cfi.numchips);
140
141         for (i = 0, j = 0; (j < cfi.numchips) && (i < max_chips); i++) {
142                 if(test_bit(i, chip_map)) {
143                         struct flchip *pchip = &retcfi->chips[j++];
144
145                         pchip->start = (i << cfi.chipshift);
146                         pchip->state = FL_READY;
147                         init_waitqueue_head(&pchip->wq);
148                         spin_lock_init(&pchip->_spinlock);
149                         pchip->mutex = &pchip->_spinlock;
150                 }
151         }
152
153         kfree(chip_map);
154         return retcfi;
155 }
156
157
158 static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,
159                              struct cfi_private *cfi)
160 {
161         int min_chips = (map_bankwidth(map)/4?:1); /* At most 4-bytes wide. */
162         int max_chips = map_bankwidth(map); /* And minimum 1 */
163         int nr_chips, type;
164
165         for (nr_chips = max_chips; nr_chips >= min_chips; nr_chips >>= 1) {
166
167                 if (!cfi_interleave_supported(nr_chips))
168                     continue;
169
170                 cfi->interleave = nr_chips;
171
172                 /* Minimum device size. Don't look for one 8-bit device
173                    in a 16-bit bus, etc. */
174                 type = map_bankwidth(map) / nr_chips;
175
176                 for (; type <= CFI_DEVICETYPE_X32; type<<=1) {
177                         cfi->device_type = type;
178
179                         if (cp->probe_chip(map, 0, NULL, cfi))
180                                 return 1;
181                 }
182         }
183         return 0;
184 }
185
186 typedef struct mtd_info *cfi_cmdset_fn_t(struct map_info *, int);
187
188 extern cfi_cmdset_fn_t cfi_cmdset_0001;
189 extern cfi_cmdset_fn_t cfi_cmdset_0002;
190 extern cfi_cmdset_fn_t cfi_cmdset_0020;
191
192 static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map,
193                                                   int primary)
194 {
195         struct cfi_private *cfi = map->fldrv_priv;
196         __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID;
197 #if defined(CONFIG_MODULES) && defined(HAVE_INTER_MODULE)
198         char probename[32];
199         cfi_cmdset_fn_t *probe_function;
200
201         sprintf(probename, "cfi_cmdset_%4.4X", type);
202
203         probe_function = inter_module_get_request(probename, probename);
204
205         if (probe_function) {
206                 struct mtd_info *mtd;
207
208                 mtd = (*probe_function)(map, primary);
209                 /* If it was happy, it'll have increased its own use count */
210                 inter_module_put(probename);
211                 return mtd;
212         }
213 #endif
214         printk(KERN_NOTICE "Support for command set %04X not present\n",
215                type);
216
217         return NULL;
218 }
219
220 static struct mtd_info *check_cmd_set(struct map_info *map, int primary)
221 {
222         struct cfi_private *cfi = map->fldrv_priv;
223         __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID;
224
225         if (type == P_ID_NONE || type == P_ID_RESERVED)
226                 return NULL;
227
228         switch(type){
229                 /* Urgh. Ifdefs. The version with weak symbols was
230                  * _much_ nicer. Shame it didn't seem to work on
231                  * anything but x86, really.
232                  * But we can't rely in inter_module_get() because
233                  * that'd mean we depend on link order.
234                  */
235 #ifdef CONFIG_MTD_CFI_INTELEXT
236         case 0x0001:
237         case 0x0003:
238         case 0x0200:
239                 return cfi_cmdset_0001(map, primary);
240 #endif
241 #ifdef CONFIG_MTD_CFI_AMDSTD
242         case 0x0002:
243                 return cfi_cmdset_0002(map, primary);
244 #endif
245 #ifdef CONFIG_MTD_CFI_STAA
246         case 0x0020:
247                 return cfi_cmdset_0020(map, primary);
248 #endif
249         }
250
251         return cfi_cmdset_unknown(map, primary);
252 }
253
254 MODULE_LICENSE("GPL");
255 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
256 MODULE_DESCRIPTION("Helper routines for flash chip probe code");