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