usb: dwc3: pci: add support for the Intel Arrow Lake-H
[platform/kernel/linux-rpi.git] / drivers / mtd / chips / cfi_util.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Common Flash Interface support:
4  *   Generic utility functions not dependent on command set
5  *
6  * Copyright (C) 2002 Red Hat
7  * Copyright (C) 2003 STMicroelectronics Limited
8  */
9
10 #include <linux/module.h>
11 #include <linux/types.h>
12 #include <linux/kernel.h>
13 #include <asm/io.h>
14 #include <asm/byteorder.h>
15
16 #include <linux/errno.h>
17 #include <linux/slab.h>
18 #include <linux/delay.h>
19 #include <linux/interrupt.h>
20 #include <linux/mtd/xip.h>
21 #include <linux/mtd/mtd.h>
22 #include <linux/mtd/map.h>
23 #include <linux/mtd/cfi.h>
24
25 void cfi_udelay(int us)
26 {
27         if (us >= 1000) {
28                 msleep(DIV_ROUND_UP(us, 1000));
29         } else {
30                 udelay(us);
31                 cond_resched();
32         }
33 }
34 EXPORT_SYMBOL(cfi_udelay);
35
36 /*
37  * Returns the command address according to the given geometry.
38  */
39 uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs,
40                                 struct map_info *map, struct cfi_private *cfi)
41 {
42         unsigned bankwidth = map_bankwidth(map);
43         unsigned interleave = cfi_interleave(cfi);
44         unsigned type = cfi->device_type;
45         uint32_t addr;
46
47         addr = (cmd_ofs * type) * interleave;
48
49         /* Modify the unlock address if we are in compatibility mode.
50          * For 16bit devices on 8 bit busses
51          * and 32bit devices on 16 bit busses
52          * set the low bit of the alternating bit sequence of the address.
53          */
54         if (((type * interleave) > bankwidth) && ((cmd_ofs & 0xff) == 0xaa))
55                 addr |= (type >> 1)*interleave;
56
57         return  addr;
58 }
59 EXPORT_SYMBOL(cfi_build_cmd_addr);
60
61 /*
62  * Transforms the CFI command for the given geometry (bus width & interleave).
63  * It looks too long to be inline, but in the common case it should almost all
64  * get optimised away.
65  */
66 map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cfi_private *cfi)
67 {
68         map_word val = { {0} };
69         int wordwidth, words_per_bus, chip_mode, chips_per_word;
70         unsigned long onecmd;
71         int i;
72
73         /* We do it this way to give the compiler a fighting chance
74            of optimising away all the crap for 'bankwidth' larger than
75            an unsigned long, in the common case where that support is
76            disabled */
77         if (map_bankwidth_is_large(map)) {
78                 wordwidth = sizeof(unsigned long);
79                 words_per_bus = (map_bankwidth(map)) / wordwidth; // i.e. normally 1
80         } else {
81                 wordwidth = map_bankwidth(map);
82                 words_per_bus = 1;
83         }
84
85         chip_mode = map_bankwidth(map) / cfi_interleave(cfi);
86         chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map);
87
88         /* First, determine what the bit-pattern should be for a single
89            device, according to chip mode and endianness... */
90         switch (chip_mode) {
91         default: BUG();
92         case 1:
93                 onecmd = cmd;
94                 break;
95         case 2:
96                 onecmd = cpu_to_cfi16(map, cmd);
97                 break;
98         case 4:
99                 onecmd = cpu_to_cfi32(map, cmd);
100                 break;
101         }
102
103         /* Now replicate it across the size of an unsigned long, or
104            just to the bus width as appropriate */
105         switch (chips_per_word) {
106         default: BUG();
107 #if BITS_PER_LONG >= 64
108         case 8:
109                 onecmd |= (onecmd << (chip_mode * 32));
110                 fallthrough;
111 #endif
112         case 4:
113                 onecmd |= (onecmd << (chip_mode * 16));
114                 fallthrough;
115         case 2:
116                 onecmd |= (onecmd << (chip_mode * 8));
117                 fallthrough;
118         case 1:
119                 ;
120         }
121
122         /* And finally, for the multi-word case, replicate it
123            in all words in the structure */
124         for (i=0; i < words_per_bus; i++) {
125                 val.x[i] = onecmd;
126         }
127
128         return val;
129 }
130 EXPORT_SYMBOL(cfi_build_cmd);
131
132 unsigned long cfi_merge_status(map_word val, struct map_info *map,
133                                            struct cfi_private *cfi)
134 {
135         int wordwidth, words_per_bus, chip_mode, chips_per_word;
136         unsigned long onestat, res = 0;
137         int i;
138
139         /* We do it this way to give the compiler a fighting chance
140            of optimising away all the crap for 'bankwidth' larger than
141            an unsigned long, in the common case where that support is
142            disabled */
143         if (map_bankwidth_is_large(map)) {
144                 wordwidth = sizeof(unsigned long);
145                 words_per_bus = (map_bankwidth(map)) / wordwidth; // i.e. normally 1
146         } else {
147                 wordwidth = map_bankwidth(map);
148                 words_per_bus = 1;
149         }
150
151         chip_mode = map_bankwidth(map) / cfi_interleave(cfi);
152         chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map);
153
154         onestat = val.x[0];
155         /* Or all status words together */
156         for (i=1; i < words_per_bus; i++) {
157                 onestat |= val.x[i];
158         }
159
160         res = onestat;
161         switch(chips_per_word) {
162         default: BUG();
163 #if BITS_PER_LONG >= 64
164         case 8:
165                 res |= (onestat >> (chip_mode * 32));
166                 fallthrough;
167 #endif
168         case 4:
169                 res |= (onestat >> (chip_mode * 16));
170                 fallthrough;
171         case 2:
172                 res |= (onestat >> (chip_mode * 8));
173                 fallthrough;
174         case 1:
175                 ;
176         }
177
178         /* Last, determine what the bit-pattern should be for a single
179            device, according to chip mode and endianness... */
180         switch (chip_mode) {
181         case 1:
182                 break;
183         case 2:
184                 res = cfi16_to_cpu(map, res);
185                 break;
186         case 4:
187                 res = cfi32_to_cpu(map, res);
188                 break;
189         default: BUG();
190         }
191         return res;
192 }
193 EXPORT_SYMBOL(cfi_merge_status);
194
195 /*
196  * Sends a CFI command to a bank of flash for the given geometry.
197  *
198  * Returns the offset in flash where the command was written.
199  * If prev_val is non-null, it will be set to the value at the command address,
200  * before the command was written.
201  */
202 uint32_t cfi_send_gen_cmd(u_char cmd, uint32_t cmd_addr, uint32_t base,
203                                 struct map_info *map, struct cfi_private *cfi,
204                                 int type, map_word *prev_val)
205 {
206         map_word val;
207         uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, map, cfi);
208         val = cfi_build_cmd(cmd, map, cfi);
209
210         if (prev_val)
211                 *prev_val = map_read(map, addr);
212
213         map_write(map, val, addr);
214
215         return addr - base;
216 }
217 EXPORT_SYMBOL(cfi_send_gen_cmd);
218
219 int __xipram cfi_qry_present(struct map_info *map, __u32 base,
220                              struct cfi_private *cfi)
221 {
222         int osf = cfi->interleave * cfi->device_type;   /* scale factor */
223         map_word val[3];
224         map_word qry[3];
225
226         qry[0] = cfi_build_cmd('Q', map, cfi);
227         qry[1] = cfi_build_cmd('R', map, cfi);
228         qry[2] = cfi_build_cmd('Y', map, cfi);
229
230         val[0] = map_read(map, base + osf*0x10);
231         val[1] = map_read(map, base + osf*0x11);
232         val[2] = map_read(map, base + osf*0x12);
233
234         if (!map_word_equal(map, qry[0], val[0]))
235                 return 0;
236
237         if (!map_word_equal(map, qry[1], val[1]))
238                 return 0;
239
240         if (!map_word_equal(map, qry[2], val[2]))
241                 return 0;
242
243         return 1;       /* "QRY" found */
244 }
245 EXPORT_SYMBOL_GPL(cfi_qry_present);
246
247 int __xipram cfi_qry_mode_on(uint32_t base, struct map_info *map,
248                              struct cfi_private *cfi)
249 {
250         cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
251         cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
252         if (cfi_qry_present(map, base, cfi))
253                 return 1;
254         /* QRY not found probably we deal with some odd CFI chips */
255         /* Some revisions of some old Intel chips? */
256         cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
257         cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
258         cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
259         if (cfi_qry_present(map, base, cfi))
260                 return 1;
261         /* ST M29DW chips */
262         cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
263         cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
264         if (cfi_qry_present(map, base, cfi))
265                 return 1;
266         /* some old SST chips, e.g. 39VF160x/39VF320x */
267         cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
268         cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
269         cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
270         cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
271         if (cfi_qry_present(map, base, cfi))
272                 return 1;
273         /* SST 39VF640xB */
274         cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
275         cfi_send_gen_cmd(0xAA, 0x555, base, map, cfi, cfi->device_type, NULL);
276         cfi_send_gen_cmd(0x55, 0x2AA, base, map, cfi, cfi->device_type, NULL);
277         cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
278         if (cfi_qry_present(map, base, cfi))
279                 return 1;
280         /* QRY not found */
281         return 0;
282 }
283 EXPORT_SYMBOL_GPL(cfi_qry_mode_on);
284
285 void __xipram cfi_qry_mode_off(uint32_t base, struct map_info *map,
286                                struct cfi_private *cfi)
287 {
288         cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
289         cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
290         /* M29W128G flashes require an additional reset command
291            when exit qry mode */
292         if ((cfi->mfr == CFI_MFR_ST) && (cfi->id == 0x227E || cfi->id == 0x7E))
293                 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
294 }
295 EXPORT_SYMBOL_GPL(cfi_qry_mode_off);
296
297 struct cfi_extquery *
298 __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* name)
299 {
300         struct cfi_private *cfi = map->fldrv_priv;
301         __u32 base = 0; // cfi->chips[0].start;
302         int ofs_factor = cfi->interleave * cfi->device_type;
303         int i;
304         struct cfi_extquery *extp = NULL;
305
306         if (!adr)
307                 goto out;
308
309         printk(KERN_INFO "%s Extended Query Table at 0x%4.4X\n", name, adr);
310
311         extp = kmalloc(size, GFP_KERNEL);
312         if (!extp)
313                 goto out;
314
315 #ifdef CONFIG_MTD_XIP
316         local_irq_disable();
317 #endif
318
319         /* Switch it into Query Mode */
320         cfi_qry_mode_on(base, map, cfi);
321         /* Read in the Extended Query Table */
322         for (i=0; i<size; i++) {
323                 ((unsigned char *)extp)[i] =
324                         cfi_read_query(map, base+((adr+i)*ofs_factor));
325         }
326
327         /* Make sure it returns to read mode */
328         cfi_qry_mode_off(base, map, cfi);
329
330 #ifdef CONFIG_MTD_XIP
331         (void) map_read(map, base);
332         xip_iprefetch();
333         local_irq_enable();
334 #endif
335
336  out:   return extp;
337 }
338
339 EXPORT_SYMBOL(cfi_read_pri);
340
341 void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup *fixups)
342 {
343         struct map_info *map = mtd->priv;
344         struct cfi_private *cfi = map->fldrv_priv;
345         struct cfi_fixup *f;
346
347         for (f=fixups; f->fixup; f++) {
348                 if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi->mfr)) &&
349                     ((f->id  == CFI_ID_ANY)  || (f->id  == cfi->id))) {
350                         f->fixup(mtd);
351                 }
352         }
353 }
354
355 EXPORT_SYMBOL(cfi_fixup);
356
357 int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
358                                      loff_t ofs, size_t len, void *thunk)
359 {
360         struct map_info *map = mtd->priv;
361         struct cfi_private *cfi = map->fldrv_priv;
362         unsigned long adr;
363         int chipnum, ret = 0;
364         int i, first;
365         struct mtd_erase_region_info *regions = mtd->eraseregions;
366
367         /* Check that both start and end of the requested erase are
368          * aligned with the erasesize at the appropriate addresses.
369          */
370
371         i = 0;
372
373         /* Skip all erase regions which are ended before the start of
374            the requested erase. Actually, to save on the calculations,
375            we skip to the first erase region which starts after the
376            start of the requested erase, and then go back one.
377         */
378
379         while (i < mtd->numeraseregions && ofs >= regions[i].offset)
380                i++;
381         i--;
382
383         /* OK, now i is pointing at the erase region in which this
384            erase request starts. Check the start of the requested
385            erase range is aligned with the erase size which is in
386            effect here.
387         */
388
389         if (ofs & (regions[i].erasesize-1))
390                 return -EINVAL;
391
392         /* Remember the erase region we start on */
393         first = i;
394
395         /* Next, check that the end of the requested erase is aligned
396          * with the erase region at that address.
397          */
398
399         while (i<mtd->numeraseregions && (ofs + len) >= regions[i].offset)
400                 i++;
401
402         /* As before, drop back one to point at the region in which
403            the address actually falls
404         */
405         i--;
406
407         if ((ofs + len) & (regions[i].erasesize-1))
408                 return -EINVAL;
409
410         chipnum = ofs >> cfi->chipshift;
411         adr = ofs - (chipnum << cfi->chipshift);
412
413         i=first;
414
415         while(len) {
416                 int size = regions[i].erasesize;
417
418                 ret = (*frob)(map, &cfi->chips[chipnum], adr, size, thunk);
419
420                 if (ret)
421                         return ret;
422
423                 adr += size;
424                 ofs += size;
425                 len -= size;
426
427                 if (ofs == regions[i].offset + size * regions[i].numblocks)
428                         i++;
429
430                 if (adr >> cfi->chipshift) {
431                         adr = 0;
432                         chipnum++;
433
434                         if (chipnum >= cfi->numchips)
435                                 break;
436                 }
437         }
438
439         return 0;
440 }
441
442 EXPORT_SYMBOL(cfi_varsize_frob);
443
444 MODULE_LICENSE("GPL");