]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/mtd/onenand/samsung.c
Merge branch 'master' of git://www.denx.de/git/u-boot-cfi-flash
[karo-tx-uboot.git] / drivers / mtd / onenand / samsung.c
1 /*
2  * S5PC100 OneNAND driver at U-Boot
3  *
4  * Copyright (C) 2008-2009 Samsung Electronics
5  * Kyungmin Park <kyungmin.park@samsung.com>
6  *
7  * Implementation:
8  *      Emulate the pseudo BufferRAM
9  *
10  * SPDX-License-Identifier:     GPL-2.0+
11  */
12
13 #include <common.h>
14 #include <malloc.h>
15 #include <linux/compat.h>
16 #include <linux/mtd/mtd.h>
17 #include <linux/mtd/onenand.h>
18 #include <linux/mtd/samsung_onenand.h>
19
20 #include <asm/io.h>
21 #include <asm/errno.h>
22
23 #ifdef ONENAND_DEBUG
24 #define DPRINTK(format, args...)                                        \
25 do {                                                                    \
26         printf("%s[%d]: " format "\n", __func__, __LINE__, ##args);     \
27 } while (0)
28 #else
29 #define DPRINTK(...)                    do { } while (0)
30 #endif
31
32 #define ONENAND_ERASE_STATUS            0x00
33 #define ONENAND_MULTI_ERASE_SET         0x01
34 #define ONENAND_ERASE_START             0x03
35 #define ONENAND_UNLOCK_START            0x08
36 #define ONENAND_UNLOCK_END              0x09
37 #define ONENAND_LOCK_START              0x0A
38 #define ONENAND_LOCK_END                0x0B
39 #define ONENAND_LOCK_TIGHT_START        0x0C
40 #define ONENAND_LOCK_TIGHT_END          0x0D
41 #define ONENAND_UNLOCK_ALL              0x0E
42 #define ONENAND_OTP_ACCESS              0x12
43 #define ONENAND_SPARE_ACCESS_ONLY       0x13
44 #define ONENAND_MAIN_ACCESS_ONLY        0x14
45 #define ONENAND_ERASE_VERIFY            0x15
46 #define ONENAND_MAIN_SPARE_ACCESS       0x16
47 #define ONENAND_PIPELINE_READ           0x4000
48
49 #if defined(CONFIG_S5P)
50 #define MAP_00                          (0x0 << 26)
51 #define MAP_01                          (0x1 << 26)
52 #define MAP_10                          (0x2 << 26)
53 #define MAP_11                          (0x3 << 26)
54 #endif
55
56 /* read/write of XIP buffer */
57 #define CMD_MAP_00(mem_addr)            (MAP_00 | ((mem_addr) << 1))
58 /* read/write to the memory device */
59 #define CMD_MAP_01(mem_addr)            (MAP_01 | (mem_addr))
60 /* control special functions of the memory device */
61 #define CMD_MAP_10(mem_addr)            (MAP_10 | (mem_addr))
62 /* direct interface(direct access) with the memory device */
63 #define CMD_MAP_11(mem_addr)            (MAP_11 | ((mem_addr) << 2))
64
65 struct s3c_onenand {
66         struct mtd_info *mtd;
67         void __iomem    *base;
68         void __iomem    *ahb_addr;
69         int             bootram_command;
70         void __iomem    *page_buf;
71         void __iomem    *oob_buf;
72         unsigned int    (*mem_addr)(int fba, int fpa, int fsa);
73         struct samsung_onenand *reg;
74 };
75
76 static struct s3c_onenand *onenand;
77
78 static int s3c_read_cmd(unsigned int cmd)
79 {
80         return readl(onenand->ahb_addr + cmd);
81 }
82
83 static void s3c_write_cmd(int value, unsigned int cmd)
84 {
85         writel(value, onenand->ahb_addr + cmd);
86 }
87
88 /*
89  * MEM_ADDR
90  *
91  * fba: flash block address
92  * fpa: flash page address
93  * fsa: flash sector address
94  *
95  * return the buffer address on the memory device
96  * It will be combined with CMD_MAP_XX
97  */
98 #if defined(CONFIG_S5P)
99 static unsigned int s3c_mem_addr(int fba, int fpa, int fsa)
100 {
101         return (fba << 13) | (fpa << 7) | (fsa << 5);
102 }
103 #endif
104
105 static void s3c_onenand_reset(void)
106 {
107         unsigned long timeout = 0x10000;
108         int stat;
109
110         writel(ONENAND_MEM_RESET_COLD, &onenand->reg->mem_reset);
111         while (timeout--) {
112                 stat = readl(&onenand->reg->int_err_stat);
113                 if (stat & RST_CMP)
114                         break;
115         }
116         stat = readl(&onenand->reg->int_err_stat);
117         writel(stat, &onenand->reg->int_err_ack);
118
119         /* Clear interrupt */
120         writel(0x0, &onenand->reg->int_err_ack);
121         /* Clear the ECC status */
122         writel(0x0, &onenand->reg->ecc_err_stat);
123 }
124
125 static unsigned short s3c_onenand_readw(void __iomem *addr)
126 {
127         struct onenand_chip *this = onenand->mtd->priv;
128         int reg = addr - this->base;
129         int word_addr = reg >> 1;
130         int value;
131
132         /* It's used for probing time */
133         switch (reg) {
134         case ONENAND_REG_MANUFACTURER_ID:
135                 return readl(&onenand->reg->manufact_id);
136         case ONENAND_REG_DEVICE_ID:
137                 return readl(&onenand->reg->device_id);
138         case ONENAND_REG_VERSION_ID:
139                 return readl(&onenand->reg->flash_ver_id);
140         case ONENAND_REG_DATA_BUFFER_SIZE:
141                 return readl(&onenand->reg->data_buf_size);
142         case ONENAND_REG_TECHNOLOGY:
143                 return readl(&onenand->reg->tech);
144         case ONENAND_REG_SYS_CFG1:
145                 return readl(&onenand->reg->mem_cfg);
146
147         /* Used at unlock all status */
148         case ONENAND_REG_CTRL_STATUS:
149                 return 0;
150
151         case ONENAND_REG_WP_STATUS:
152                 return ONENAND_WP_US;
153
154         default:
155                 break;
156         }
157
158         /* BootRAM access control */
159         if (reg < ONENAND_DATARAM && onenand->bootram_command) {
160                 if (word_addr == 0)
161                         return readl(&onenand->reg->manufact_id);
162                 if (word_addr == 1)
163                         return readl(&onenand->reg->device_id);
164                 if (word_addr == 2)
165                         return readl(&onenand->reg->flash_ver_id);
166         }
167
168         value = s3c_read_cmd(CMD_MAP_11(word_addr)) & 0xffff;
169         printk(KERN_INFO "s3c_onenand_readw:  Illegal access"
170                 " at reg 0x%x, value 0x%x\n", word_addr, value);
171         return value;
172 }
173
174 static void s3c_onenand_writew(unsigned short value, void __iomem *addr)
175 {
176         struct onenand_chip *this = onenand->mtd->priv;
177         int reg = addr - this->base;
178         int word_addr = reg >> 1;
179
180         /* It's used for probing time */
181         switch (reg) {
182         case ONENAND_REG_SYS_CFG1:
183                 writel(value, &onenand->reg->mem_cfg);
184                 return;
185
186         case ONENAND_REG_START_ADDRESS1:
187         case ONENAND_REG_START_ADDRESS2:
188                 return;
189
190         /* Lock/lock-tight/unlock/unlock_all */
191         case ONENAND_REG_START_BLOCK_ADDRESS:
192                 return;
193
194         default:
195                 break;
196         }
197
198         /* BootRAM access control */
199         if (reg < ONENAND_DATARAM) {
200                 if (value == ONENAND_CMD_READID) {
201                         onenand->bootram_command = 1;
202                         return;
203                 }
204                 if (value == ONENAND_CMD_RESET) {
205                         writel(ONENAND_MEM_RESET_COLD,
206                                         &onenand->reg->mem_reset);
207                         onenand->bootram_command = 0;
208                         return;
209                 }
210         }
211
212         printk(KERN_INFO "s3c_onenand_writew: Illegal access"
213                 " at reg 0x%x, value 0x%x\n", word_addr, value);
214
215         s3c_write_cmd(value, CMD_MAP_11(word_addr));
216 }
217
218 static int s3c_onenand_wait(struct mtd_info *mtd, int state)
219 {
220         unsigned int flags = INT_ACT;
221         unsigned int stat, ecc;
222         unsigned long timeout = 0x100000;
223
224         switch (state) {
225         case FL_READING:
226                 flags |= BLK_RW_CMP | LOAD_CMP;
227                 break;
228         case FL_WRITING:
229                 flags |= BLK_RW_CMP | PGM_CMP;
230                 break;
231         case FL_ERASING:
232                 flags |= BLK_RW_CMP | ERS_CMP;
233                 break;
234         case FL_LOCKING:
235                 flags |= BLK_RW_CMP;
236                 break;
237         default:
238                 break;
239         }
240
241         while (timeout--) {
242                 stat = readl(&onenand->reg->int_err_stat);
243                 if (stat & flags)
244                         break;
245         }
246
247         /* To get correct interrupt status in timeout case */
248         stat = readl(&onenand->reg->int_err_stat);
249         writel(stat, &onenand->reg->int_err_ack);
250
251         /*
252          * In the Spec. it checks the controller status first
253          * However if you get the correct information in case of
254          * power off recovery (POR) test, it should read ECC status first
255          */
256         if (stat & LOAD_CMP) {
257                 ecc = readl(&onenand->reg->ecc_err_stat);
258                 if (ecc & ONENAND_ECC_4BIT_UNCORRECTABLE) {
259                         printk(KERN_INFO "%s: ECC error = 0x%04x\n",
260                                         __func__, ecc);
261                         mtd->ecc_stats.failed++;
262                         return -EBADMSG;
263                 }
264         }
265
266         if (stat & (LOCKED_BLK | ERS_FAIL | PGM_FAIL | LD_FAIL_ECC_ERR)) {
267                 printk(KERN_INFO "%s: controller error = 0x%04x\n",
268                                 __func__, stat);
269                 if (stat & LOCKED_BLK)
270                         printk(KERN_INFO "%s: it's locked error = 0x%04x\n",
271                                         __func__, stat);
272
273                 return -EIO;
274         }
275
276         return 0;
277 }
278
279 static int s3c_onenand_command(struct mtd_info *mtd, int cmd,
280                 loff_t addr, size_t len)
281 {
282         struct onenand_chip *this = mtd->priv;
283         unsigned int *m, *s;
284         int fba, fpa, fsa = 0;
285         unsigned int mem_addr;
286         int i, mcount, scount;
287         int index;
288
289         fba = (int) (addr >> this->erase_shift);
290         fpa = (int) (addr >> this->page_shift);
291         fpa &= this->page_mask;
292
293         mem_addr = onenand->mem_addr(fba, fpa, fsa);
294
295         switch (cmd) {
296         case ONENAND_CMD_READ:
297         case ONENAND_CMD_READOOB:
298         case ONENAND_CMD_BUFFERRAM:
299                 ONENAND_SET_NEXT_BUFFERRAM(this);
300         default:
301                 break;
302         }
303
304         index = ONENAND_CURRENT_BUFFERRAM(this);
305
306         /*
307          * Emulate Two BufferRAMs and access with 4 bytes pointer
308          */
309         m = (unsigned int *) onenand->page_buf;
310         s = (unsigned int *) onenand->oob_buf;
311
312         if (index) {
313                 m += (this->writesize >> 2);
314                 s += (mtd->oobsize >> 2);
315         }
316
317         mcount = mtd->writesize >> 2;
318         scount = mtd->oobsize >> 2;
319
320         switch (cmd) {
321         case ONENAND_CMD_READ:
322                 /* Main */
323                 for (i = 0; i < mcount; i++)
324                         *m++ = s3c_read_cmd(CMD_MAP_01(mem_addr));
325                 return 0;
326
327         case ONENAND_CMD_READOOB:
328                 writel(TSRF, &onenand->reg->trans_spare);
329                 /* Main */
330                 for (i = 0; i < mcount; i++)
331                         *m++ = s3c_read_cmd(CMD_MAP_01(mem_addr));
332
333                 /* Spare */
334                 for (i = 0; i < scount; i++)
335                         *s++ = s3c_read_cmd(CMD_MAP_01(mem_addr));
336
337                 writel(0, &onenand->reg->trans_spare);
338                 return 0;
339
340         case ONENAND_CMD_PROG:
341                 /* Main */
342                 for (i = 0; i < mcount; i++)
343                         s3c_write_cmd(*m++, CMD_MAP_01(mem_addr));
344                 return 0;
345
346         case ONENAND_CMD_PROGOOB:
347                 writel(TSRF, &onenand->reg->trans_spare);
348
349                 /* Main - dummy write */
350                 for (i = 0; i < mcount; i++)
351                         s3c_write_cmd(0xffffffff, CMD_MAP_01(mem_addr));
352
353                 /* Spare */
354                 for (i = 0; i < scount; i++)
355                         s3c_write_cmd(*s++, CMD_MAP_01(mem_addr));
356
357                 writel(0, &onenand->reg->trans_spare);
358                 return 0;
359
360         case ONENAND_CMD_UNLOCK_ALL:
361                 s3c_write_cmd(ONENAND_UNLOCK_ALL, CMD_MAP_10(mem_addr));
362                 return 0;
363
364         case ONENAND_CMD_ERASE:
365                 s3c_write_cmd(ONENAND_ERASE_START, CMD_MAP_10(mem_addr));
366                 return 0;
367
368         case ONENAND_CMD_MULTIBLOCK_ERASE:
369                 s3c_write_cmd(ONENAND_MULTI_ERASE_SET, CMD_MAP_10(mem_addr));
370                 return 0;
371
372         case ONENAND_CMD_ERASE_VERIFY:
373                 s3c_write_cmd(ONENAND_ERASE_VERIFY, CMD_MAP_10(mem_addr));
374                 return 0;
375
376         default:
377                 break;
378         }
379
380         return 0;
381 }
382
383 static unsigned char *s3c_get_bufferram(struct mtd_info *mtd, int area)
384 {
385         struct onenand_chip *this = mtd->priv;
386         int index = ONENAND_CURRENT_BUFFERRAM(this);
387         unsigned char *p;
388
389         if (area == ONENAND_DATARAM) {
390                 p = (unsigned char *) onenand->page_buf;
391                 if (index == 1)
392                         p += this->writesize;
393         } else {
394                 p = (unsigned char *) onenand->oob_buf;
395                 if (index == 1)
396                         p += mtd->oobsize;
397         }
398
399         return p;
400 }
401
402 static int onenand_read_bufferram(struct mtd_info *mtd, loff_t addr, int area,
403                                   unsigned char *buffer, int offset,
404                                   size_t count)
405 {
406         unsigned char *p;
407
408         p = s3c_get_bufferram(mtd, area);
409         memcpy(buffer, p + offset, count);
410         return 0;
411 }
412
413 static int onenand_write_bufferram(struct mtd_info *mtd, loff_t addr, int area,
414                                    const unsigned char *buffer, int offset,
415                                    size_t count)
416 {
417         unsigned char *p;
418
419         p = s3c_get_bufferram(mtd, area);
420         memcpy(p + offset, buffer, count);
421         return 0;
422 }
423
424 static int s3c_onenand_bbt_wait(struct mtd_info *mtd, int state)
425 {
426         struct samsung_onenand *reg = (struct samsung_onenand *)onenand->base;
427         unsigned int flags = INT_ACT | LOAD_CMP;
428         unsigned int stat;
429         unsigned long timeout = 0x10000;
430
431         while (timeout--) {
432                 stat = readl(&reg->int_err_stat);
433                 if (stat & flags)
434                         break;
435         }
436         /* To get correct interrupt status in timeout case */
437         stat = readl(&onenand->reg->int_err_stat);
438         writel(stat, &onenand->reg->int_err_ack);
439
440         if (stat & LD_FAIL_ECC_ERR) {
441                 s3c_onenand_reset();
442                 return ONENAND_BBT_READ_ERROR;
443         }
444
445         if (stat & LOAD_CMP) {
446                 int ecc = readl(&onenand->reg->ecc_err_stat);
447                 if (ecc & ONENAND_ECC_4BIT_UNCORRECTABLE) {
448                         s3c_onenand_reset();
449                         return ONENAND_BBT_READ_ERROR;
450                 }
451         }
452
453         return 0;
454 }
455
456 static void s3c_onenand_check_lock_status(struct mtd_info *mtd)
457 {
458         struct onenand_chip *this = mtd->priv;
459         unsigned int block, end;
460
461         end = this->chipsize >> this->erase_shift;
462
463         for (block = 0; block < end; block++) {
464                 s3c_read_cmd(CMD_MAP_01(onenand->mem_addr(block, 0, 0)));
465
466                 if (readl(&onenand->reg->int_err_stat) & LOCKED_BLK) {
467                         printf("block %d is write-protected!\n", block);
468                         writel(LOCKED_BLK, &onenand->reg->int_err_ack);
469                 }
470         }
471 }
472
473 static void s3c_onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs,
474                 size_t len, int cmd)
475 {
476         struct onenand_chip *this = mtd->priv;
477         int start, end, start_mem_addr, end_mem_addr;
478
479         start = ofs >> this->erase_shift;
480         start_mem_addr = onenand->mem_addr(start, 0, 0);
481         end = start + (len >> this->erase_shift) - 1;
482         end_mem_addr = onenand->mem_addr(end, 0, 0);
483
484         if (cmd == ONENAND_CMD_LOCK) {
485                 s3c_write_cmd(ONENAND_LOCK_START, CMD_MAP_10(start_mem_addr));
486                 s3c_write_cmd(ONENAND_LOCK_END, CMD_MAP_10(end_mem_addr));
487         } else {
488                 s3c_write_cmd(ONENAND_UNLOCK_START, CMD_MAP_10(start_mem_addr));
489                 s3c_write_cmd(ONENAND_UNLOCK_END, CMD_MAP_10(end_mem_addr));
490         }
491
492         this->wait(mtd, FL_LOCKING);
493 }
494
495 static void s3c_onenand_unlock_all(struct mtd_info *mtd)
496 {
497         struct onenand_chip *this = mtd->priv;
498         loff_t ofs = 0;
499         size_t len = this->chipsize;
500
501         /* FIXME workaround */
502         this->subpagesize = mtd->writesize;
503         mtd->subpage_sft = 0;
504
505         if (this->options & ONENAND_HAS_UNLOCK_ALL) {
506                 /* Write unlock command */
507                 this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0);
508
509                 /* No need to check return value */
510                 this->wait(mtd, FL_LOCKING);
511
512                 /* Workaround for all block unlock in DDP */
513                 if (!ONENAND_IS_DDP(this)) {
514                         s3c_onenand_check_lock_status(mtd);
515                         return;
516                 }
517
518                 /* All blocks on another chip */
519                 ofs = this->chipsize >> 1;
520                 len = this->chipsize >> 1;
521         }
522
523         s3c_onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
524         s3c_onenand_check_lock_status(mtd);
525 }
526
527 int s5pc110_chip_probe(struct mtd_info *mtd)
528 {
529         return 0;
530 }
531
532 int s5pc210_chip_probe(struct mtd_info *mtd)
533 {
534         return 0;
535 }
536
537 void s3c_onenand_init(struct mtd_info *mtd)
538 {
539         struct onenand_chip *this = mtd->priv;
540         u32 size = (4 << 10);   /* 4 KiB */
541
542         onenand = malloc(sizeof(struct s3c_onenand));
543         if (!onenand)
544                 return;
545
546         onenand->page_buf = malloc(size * sizeof(char));
547         if (!onenand->page_buf)
548                 return;
549         memset(onenand->page_buf, 0xff, size);
550
551         onenand->oob_buf = malloc(128 * sizeof(char));
552         if (!onenand->oob_buf)
553                 return;
554         memset(onenand->oob_buf, 0xff, 128);
555
556         onenand->mtd = mtd;
557
558 #if defined(CONFIG_S5P)
559         onenand->base = (void *)0xE7100000;
560         onenand->ahb_addr = (void *)0xB0000000;
561 #endif
562         onenand->mem_addr = s3c_mem_addr;
563         onenand->reg = (struct samsung_onenand *)onenand->base;
564
565         this->read_word = s3c_onenand_readw;
566         this->write_word = s3c_onenand_writew;
567
568         this->wait = s3c_onenand_wait;
569         this->bbt_wait = s3c_onenand_bbt_wait;
570         this->unlock_all = s3c_onenand_unlock_all;
571         this->command = s3c_onenand_command;
572
573         this->read_bufferram = onenand_read_bufferram;
574         this->write_bufferram = onenand_write_bufferram;
575
576         this->options |= ONENAND_RUNTIME_BADBLOCK_CHECK;
577 }