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