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