This source file includes following definitions.
- read8
- read32
- write32
- flash_probe
- erase_block
- flash_erase
- flash_read
- write_dword
- flash_write
- lart_flash_init
- lart_flash_exit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 #include <linux/kernel.h>
35 #include <linux/module.h>
36 #include <linux/types.h>
37 #include <linux/init.h>
38 #include <linux/errno.h>
39 #include <linux/string.h>
40 #include <linux/mtd/mtd.h>
41 #include <linux/mtd/partitions.h>
42
43 #ifndef CONFIG_SA1100_LART
44 #error This is for LART architecture only
45 #endif
46
47 static char module_name[] = "lart";
48
49
50
51
52
53 #define FLASH_BLOCKSIZE_PARAM (4096 * BUSWIDTH)
54 #define FLASH_NUMBLOCKS_16m_PARAM 8
55 #define FLASH_NUMBLOCKS_8m_PARAM 8
56
57
58
59
60
61 #define FLASH_BLOCKSIZE_MAIN (32768 * BUSWIDTH)
62 #define FLASH_NUMBLOCKS_16m_MAIN 31
63 #define FLASH_NUMBLOCKS_8m_MAIN 15
64
65
66
67
68
69
70 #define BUSWIDTH 4
71 #define FLASH_OFFSET 0xe8000000
72
73
74 #define NUM_BLOB_BLOCKS FLASH_NUMBLOCKS_16m_PARAM
75 #define PART_BLOB_START 0x00000000
76 #define PART_BLOB_LEN (NUM_BLOB_BLOCKS * FLASH_BLOCKSIZE_PARAM)
77
78
79 #define NUM_KERNEL_BLOCKS 7
80 #define PART_KERNEL_START (PART_BLOB_START + PART_BLOB_LEN)
81 #define PART_KERNEL_LEN (NUM_KERNEL_BLOCKS * FLASH_BLOCKSIZE_MAIN)
82
83
84 #define NUM_INITRD_BLOCKS 24
85 #define PART_INITRD_START (PART_KERNEL_START + PART_KERNEL_LEN)
86 #define PART_INITRD_LEN (NUM_INITRD_BLOCKS * FLASH_BLOCKSIZE_MAIN)
87
88
89
90
91 #define READ_ARRAY 0x00FF00FF
92 #define READ_ID_CODES 0x00900090
93 #define ERASE_SETUP 0x00200020
94 #define ERASE_CONFIRM 0x00D000D0
95 #define PGM_SETUP 0x00400040
96 #define STATUS_READ 0x00700070
97 #define STATUS_CLEAR 0x00500050
98 #define STATUS_BUSY 0x00800080
99 #define STATUS_ERASE_ERR 0x00200020
100 #define STATUS_PGM_ERR 0x00100010
101
102
103
104
105 #define FLASH_MANUFACTURER 0x00890089
106 #define FLASH_DEVICE_8mbit_TOP 0x88f188f1
107 #define FLASH_DEVICE_8mbit_BOTTOM 0x88f288f2
108 #define FLASH_DEVICE_16mbit_TOP 0x88f388f3
109 #define FLASH_DEVICE_16mbit_BOTTOM 0x88f488f4
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137 #define DATA_TO_FLASH(x) \
138 ( \
139 (((x) & 0x08009000) >> 11) + \
140 (((x) & 0x00002000) >> 10) + \
141 (((x) & 0x04004000) >> 8) + \
142 (((x) & 0x00000010) >> 4) + \
143 (((x) & 0x91000820) >> 3) + \
144 (((x) & 0x22080080) >> 2) + \
145 ((x) & 0x40000400) + \
146 (((x) & 0x00040040) << 1) + \
147 (((x) & 0x00110000) << 4) + \
148 (((x) & 0x00220100) << 5) + \
149 (((x) & 0x00800208) << 6) + \
150 (((x) & 0x00400004) << 9) + \
151 (((x) & 0x00000001) << 12) + \
152 (((x) & 0x00000002) << 13) \
153 )
154
155
156 #define FLASH_TO_DATA(x) \
157 ( \
158 (((x) & 0x00010012) << 11) + \
159 (((x) & 0x00000008) << 10) + \
160 (((x) & 0x00040040) << 8) + \
161 (((x) & 0x00000001) << 4) + \
162 (((x) & 0x12200104) << 3) + \
163 (((x) & 0x08820020) << 2) + \
164 ((x) & 0x40000400) + \
165 (((x) & 0x00080080) >> 1) + \
166 (((x) & 0x01100000) >> 4) + \
167 (((x) & 0x04402000) >> 5) + \
168 (((x) & 0x20008200) >> 6) + \
169 (((x) & 0x80000800) >> 9) + \
170 (((x) & 0x00001000) >> 12) + \
171 (((x) & 0x00004000) >> 13) \
172 )
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213 #define ADDR_TO_FLASH_U2(x) \
214 ( \
215 (((x) & 0x00000f00) >> 4) + \
216 (((x) & 0x00042000) << 1) + \
217 (((x) & 0x0009c003) << 2) + \
218 (((x) & 0x00021080) << 3) + \
219 (((x) & 0x00000010) << 4) + \
220 (((x) & 0x00000040) << 5) + \
221 (((x) & 0x00000024) << 7) + \
222 (((x) & 0x00000008) << 10) \
223 )
224
225
226 #define FLASH_U2_TO_ADDR(x) \
227 ( \
228 (((x) << 4) & 0x00000f00) + \
229 (((x) >> 1) & 0x00042000) + \
230 (((x) >> 2) & 0x0009c003) + \
231 (((x) >> 3) & 0x00021080) + \
232 (((x) >> 4) & 0x00000010) + \
233 (((x) >> 5) & 0x00000040) + \
234 (((x) >> 7) & 0x00000024) + \
235 (((x) >> 10) & 0x00000008) \
236 )
237
238
239 #define ADDR_TO_FLASH_U3(x) \
240 ( \
241 (((x) & 0x00000080) >> 3) + \
242 (((x) & 0x00000040) >> 1) + \
243 (((x) & 0x00052020) << 1) + \
244 (((x) & 0x00084f03) << 2) + \
245 (((x) & 0x00029010) << 3) + \
246 (((x) & 0x00000008) << 5) + \
247 (((x) & 0x00000004) << 7) \
248 )
249
250
251 #define FLASH_U3_TO_ADDR(x) \
252 ( \
253 (((x) << 3) & 0x00000080) + \
254 (((x) << 1) & 0x00000040) + \
255 (((x) >> 1) & 0x00052020) + \
256 (((x) >> 2) & 0x00084f03) + \
257 (((x) >> 3) & 0x00029010) + \
258 (((x) >> 5) & 0x00000008) + \
259 (((x) >> 7) & 0x00000004) \
260 )
261
262
263
264 static __u8 read8 (__u32 offset)
265 {
266 volatile __u8 *data = (__u8 *) (FLASH_OFFSET + offset);
267 #ifdef LART_DEBUG
268 printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.2x\n", __func__, offset, *data);
269 #endif
270 return (*data);
271 }
272
273 static __u32 read32 (__u32 offset)
274 {
275 volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset);
276 #ifdef LART_DEBUG
277 printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.8x\n", __func__, offset, *data);
278 #endif
279 return (*data);
280 }
281
282 static void write32 (__u32 x,__u32 offset)
283 {
284 volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset);
285 *data = x;
286 #ifdef LART_DEBUG
287 printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n", __func__, offset, *data);
288 #endif
289 }
290
291
292
293
294
295
296
297
298
299
300
301 static int flash_probe (void)
302 {
303 __u32 manufacturer,devtype;
304
305
306 write32 (DATA_TO_FLASH (READ_ID_CODES),0x00000000);
307
308
309
310 manufacturer = FLASH_TO_DATA (read32 (ADDR_TO_FLASH_U2 (0x00000000)));
311 devtype = FLASH_TO_DATA (read32 (ADDR_TO_FLASH_U2 (0x00000001)));
312
313
314 write32 (DATA_TO_FLASH (READ_ARRAY),0x00000000);
315
316 return (manufacturer == FLASH_MANUFACTURER && (devtype == FLASH_DEVICE_16mbit_TOP || devtype == FLASH_DEVICE_16mbit_BOTTOM));
317 }
318
319
320
321
322
323
324
325 static inline int erase_block (__u32 offset)
326 {
327 __u32 status;
328
329 #ifdef LART_DEBUG
330 printk (KERN_DEBUG "%s(): 0x%.8x\n", __func__, offset);
331 #endif
332
333
334 write32 (DATA_TO_FLASH (ERASE_SETUP),offset);
335 write32 (DATA_TO_FLASH (ERASE_CONFIRM),offset);
336
337
338 do
339 {
340 write32 (DATA_TO_FLASH (STATUS_READ),offset);
341 status = FLASH_TO_DATA (read32 (offset));
342 }
343 while ((~status & STATUS_BUSY) != 0);
344
345
346 write32 (DATA_TO_FLASH (READ_ARRAY),offset);
347
348
349 if ((status & STATUS_ERASE_ERR))
350 {
351 printk (KERN_WARNING "%s: erase error at address 0x%.8x.\n",module_name,offset);
352 return (0);
353 }
354
355 return (1);
356 }
357
358 static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
359 {
360 __u32 addr,len;
361 int i,first;
362
363 #ifdef LART_DEBUG
364 printk (KERN_DEBUG "%s(addr = 0x%.8x, len = %d)\n", __func__, instr->addr, instr->len);
365 #endif
366
367
368
369
370
371
372
373
374
375
376 for (i = 0; i < mtd->numeraseregions && instr->addr >= mtd->eraseregions[i].offset; i++) ;
377 i--;
378
379
380
381
382
383
384
385 if (i < 0 || (instr->addr & (mtd->eraseregions[i].erasesize - 1)))
386 return -EINVAL;
387
388
389 first = i;
390
391
392
393
394
395
396
397
398 for (; i < mtd->numeraseregions && instr->addr + instr->len >= mtd->eraseregions[i].offset; i++) ;
399 i--;
400
401
402 if (i < 0 || ((instr->addr + instr->len) & (mtd->eraseregions[i].erasesize - 1)))
403 return -EINVAL;
404
405 addr = instr->addr;
406 len = instr->len;
407
408 i = first;
409
410
411 while (len)
412 {
413 if (!erase_block (addr))
414 return (-EIO);
415
416 addr += mtd->eraseregions[i].erasesize;
417 len -= mtd->eraseregions[i].erasesize;
418
419 if (addr == mtd->eraseregions[i].offset + (mtd->eraseregions[i].erasesize * mtd->eraseregions[i].numblocks)) i++;
420 }
421
422 return (0);
423 }
424
425 static int flash_read (struct mtd_info *mtd,loff_t from,size_t len,size_t *retlen,u_char *buf)
426 {
427 #ifdef LART_DEBUG
428 printk (KERN_DEBUG "%s(from = 0x%.8x, len = %d)\n", __func__, (__u32)from, len);
429 #endif
430
431
432 *retlen = len;
433
434
435 if (from & (BUSWIDTH - 1))
436 {
437 int gap = BUSWIDTH - (from & (BUSWIDTH - 1));
438
439 while (len && gap--) *buf++ = read8 (from++), len--;
440 }
441
442
443 while (len >= BUSWIDTH)
444 {
445 *((__u32 *) buf) = read32 (from);
446
447 buf += BUSWIDTH;
448 from += BUSWIDTH;
449 len -= BUSWIDTH;
450 }
451
452
453 if (len & (BUSWIDTH - 1))
454 while (len--) *buf++ = read8 (from++);
455
456 return (0);
457 }
458
459
460
461
462
463
464
465 static inline int write_dword (__u32 offset,__u32 x)
466 {
467 __u32 status;
468
469 #ifdef LART_DEBUG
470 printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n", __func__, offset, x);
471 #endif
472
473
474 write32 (DATA_TO_FLASH (PGM_SETUP),offset);
475
476
477 write32 (x,offset);
478
479
480 do
481 {
482 write32 (DATA_TO_FLASH (STATUS_READ),offset);
483 status = FLASH_TO_DATA (read32 (offset));
484 }
485 while ((~status & STATUS_BUSY) != 0);
486
487
488 write32 (DATA_TO_FLASH (READ_ARRAY),offset);
489
490
491 if ((status & STATUS_PGM_ERR) || read32 (offset) != x)
492 {
493 printk (KERN_WARNING "%s: write error at address 0x%.8x.\n",module_name,offset);
494 return (0);
495 }
496
497 return (1);
498 }
499
500 static int flash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf)
501 {
502 __u8 tmp[4];
503 int i,n;
504
505 #ifdef LART_DEBUG
506 printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n", __func__, (__u32)to, len);
507 #endif
508
509
510 if (!len) return (0);
511
512
513 if (to & (BUSWIDTH - 1))
514 {
515 __u32 aligned = to & ~(BUSWIDTH - 1);
516 int gap = to - aligned;
517
518 i = n = 0;
519
520 while (gap--) tmp[i++] = 0xFF;
521 while (len && i < BUSWIDTH) tmp[i++] = buf[n++], len--;
522 while (i < BUSWIDTH) tmp[i++] = 0xFF;
523
524 if (!write_dword (aligned,*((__u32 *) tmp))) return (-EIO);
525
526 to += n;
527 buf += n;
528 *retlen += n;
529 }
530
531
532 while (len >= BUSWIDTH)
533 {
534 if (!write_dword (to,*((__u32 *) buf))) return (-EIO);
535
536 to += BUSWIDTH;
537 buf += BUSWIDTH;
538 *retlen += BUSWIDTH;
539 len -= BUSWIDTH;
540 }
541
542
543 if (len & (BUSWIDTH - 1))
544 {
545 i = n = 0;
546
547 while (len--) tmp[i++] = buf[n++];
548 while (i < BUSWIDTH) tmp[i++] = 0xFF;
549
550 if (!write_dword (to,*((__u32 *) tmp))) return (-EIO);
551
552 *retlen += n;
553 }
554
555 return (0);
556 }
557
558
559
560 static struct mtd_info mtd;
561
562 static struct mtd_erase_region_info erase_regions[] = {
563
564 {
565 .offset = 0x00000000,
566 .erasesize = FLASH_BLOCKSIZE_PARAM,
567 .numblocks = FLASH_NUMBLOCKS_16m_PARAM,
568 },
569
570 {
571 .offset = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM,
572 .erasesize = FLASH_BLOCKSIZE_MAIN,
573 .numblocks = FLASH_NUMBLOCKS_16m_MAIN,
574 }
575 };
576
577 static const struct mtd_partition lart_partitions[] = {
578
579 {
580 .name = "blob",
581 .offset = PART_BLOB_START,
582 .size = PART_BLOB_LEN,
583 },
584
585 {
586 .name = "kernel",
587 .offset = PART_KERNEL_START,
588 .size = PART_KERNEL_LEN,
589 },
590
591 {
592 .name = "file system",
593 .offset = PART_INITRD_START,
594 .size = PART_INITRD_LEN,
595 }
596 };
597 #define NUM_PARTITIONS ARRAY_SIZE(lart_partitions)
598
599 static int __init lart_flash_init (void)
600 {
601 int result;
602 memset (&mtd,0,sizeof (mtd));
603 printk ("MTD driver for LART. Written by Abraham vd Merwe <abraham@2d3d.co.za>\n");
604 printk ("%s: Probing for 28F160x3 flash on LART...\n",module_name);
605 if (!flash_probe ())
606 {
607 printk (KERN_WARNING "%s: Found no LART compatible flash device\n",module_name);
608 return (-ENXIO);
609 }
610 printk ("%s: This looks like a LART board to me.\n",module_name);
611 mtd.name = module_name;
612 mtd.type = MTD_NORFLASH;
613 mtd.writesize = 1;
614 mtd.writebufsize = 4;
615 mtd.flags = MTD_CAP_NORFLASH;
616 mtd.size = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM + FLASH_BLOCKSIZE_MAIN * FLASH_NUMBLOCKS_16m_MAIN;
617 mtd.erasesize = FLASH_BLOCKSIZE_MAIN;
618 mtd.numeraseregions = ARRAY_SIZE(erase_regions);
619 mtd.eraseregions = erase_regions;
620 mtd._erase = flash_erase;
621 mtd._read = flash_read;
622 mtd._write = flash_write;
623 mtd.owner = THIS_MODULE;
624
625 #ifdef LART_DEBUG
626 printk (KERN_DEBUG
627 "mtd.name = %s\n"
628 "mtd.size = 0x%.8x (%uM)\n"
629 "mtd.erasesize = 0x%.8x (%uK)\n"
630 "mtd.numeraseregions = %d\n",
631 mtd.name,
632 mtd.size,mtd.size / (1024*1024),
633 mtd.erasesize,mtd.erasesize / 1024,
634 mtd.numeraseregions);
635
636 if (mtd.numeraseregions)
637 for (result = 0; result < mtd.numeraseregions; result++)
638 printk (KERN_DEBUG
639 "\n\n"
640 "mtd.eraseregions[%d].offset = 0x%.8x\n"
641 "mtd.eraseregions[%d].erasesize = 0x%.8x (%uK)\n"
642 "mtd.eraseregions[%d].numblocks = %d\n",
643 result,mtd.eraseregions[result].offset,
644 result,mtd.eraseregions[result].erasesize,mtd.eraseregions[result].erasesize / 1024,
645 result,mtd.eraseregions[result].numblocks);
646
647 printk ("\npartitions = %d\n", ARRAY_SIZE(lart_partitions));
648
649 for (result = 0; result < ARRAY_SIZE(lart_partitions); result++)
650 printk (KERN_DEBUG
651 "\n\n"
652 "lart_partitions[%d].name = %s\n"
653 "lart_partitions[%d].offset = 0x%.8x\n"
654 "lart_partitions[%d].size = 0x%.8x (%uK)\n",
655 result,lart_partitions[result].name,
656 result,lart_partitions[result].offset,
657 result,lart_partitions[result].size,lart_partitions[result].size / 1024);
658 #endif
659
660 result = mtd_device_register(&mtd, lart_partitions,
661 ARRAY_SIZE(lart_partitions));
662
663 return (result);
664 }
665
666 static void __exit lart_flash_exit (void)
667 {
668 mtd_device_unregister(&mtd);
669 }
670
671 module_init (lart_flash_init);
672 module_exit (lart_flash_exit);
673
674 MODULE_LICENSE("GPL");
675 MODULE_AUTHOR("Abraham vd Merwe <abraham@2d3d.co.za>");
676 MODULE_DESCRIPTION("MTD driver for Intel 28F160F3 on LART board");