xref: /openbmc/u-boot/drivers/mtd/onenand/samsung.c (revision 9458f6d8)
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 }
594