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