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