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