• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/mtd/onenand/
1/*
2 * Samsung S3C64XX/S5PC1XX OneNAND driver
3 *
4 *  Copyright �� 2008-2010 Samsung Electronics
5 *  Kyungmin Park <kyungmin.park@samsung.com>
6 *  Marek Szyprowski <m.szyprowski@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * Implementation:
13 *	S3C64XX and S5PC100: emulate the pseudo BufferRAM
14 *	S5PC110: use DMA
15 */
16
17#include <linux/module.h>
18#include <linux/platform_device.h>
19#include <linux/sched.h>
20#include <linux/slab.h>
21#include <linux/mtd/mtd.h>
22#include <linux/mtd/onenand.h>
23#include <linux/mtd/partitions.h>
24#include <linux/dma-mapping.h>
25
26#include <asm/mach/flash.h>
27#include <plat/regs-onenand.h>
28
29#include <linux/io.h>
30
31enum soc_type {
32	TYPE_S3C6400,
33	TYPE_S3C6410,
34	TYPE_S5PC100,
35	TYPE_S5PC110,
36};
37
38#define ONENAND_ERASE_STATUS		0x00
39#define ONENAND_MULTI_ERASE_SET		0x01
40#define ONENAND_ERASE_START		0x03
41#define ONENAND_UNLOCK_START		0x08
42#define ONENAND_UNLOCK_END		0x09
43#define ONENAND_LOCK_START		0x0A
44#define ONENAND_LOCK_END		0x0B
45#define ONENAND_LOCK_TIGHT_START	0x0C
46#define ONENAND_LOCK_TIGHT_END		0x0D
47#define ONENAND_UNLOCK_ALL		0x0E
48#define ONENAND_OTP_ACCESS		0x12
49#define ONENAND_SPARE_ACCESS_ONLY	0x13
50#define ONENAND_MAIN_ACCESS_ONLY	0x14
51#define ONENAND_ERASE_VERIFY		0x15
52#define ONENAND_MAIN_SPARE_ACCESS	0x16
53#define ONENAND_PIPELINE_READ		0x4000
54
55#define MAP_00				(0x0)
56#define MAP_01				(0x1)
57#define MAP_10				(0x2)
58#define MAP_11				(0x3)
59
60#define S3C64XX_CMD_MAP_SHIFT		24
61#define S5PC1XX_CMD_MAP_SHIFT		26
62
63#define S3C6400_FBA_SHIFT		10
64#define S3C6400_FPA_SHIFT		4
65#define S3C6400_FSA_SHIFT		2
66
67#define S3C6410_FBA_SHIFT		12
68#define S3C6410_FPA_SHIFT		6
69#define S3C6410_FSA_SHIFT		4
70
71#define S5PC100_FBA_SHIFT		13
72#define S5PC100_FPA_SHIFT		7
73#define S5PC100_FSA_SHIFT		5
74
75/* S5PC110 specific definitions */
76#define S5PC110_DMA_SRC_ADDR		0x400
77#define S5PC110_DMA_SRC_CFG		0x404
78#define S5PC110_DMA_DST_ADDR		0x408
79#define S5PC110_DMA_DST_CFG		0x40C
80#define S5PC110_DMA_TRANS_SIZE		0x414
81#define S5PC110_DMA_TRANS_CMD		0x418
82#define S5PC110_DMA_TRANS_STATUS	0x41C
83#define S5PC110_DMA_TRANS_DIR		0x420
84
85#define S5PC110_DMA_CFG_SINGLE		(0x0 << 16)
86#define S5PC110_DMA_CFG_4BURST		(0x2 << 16)
87#define S5PC110_DMA_CFG_8BURST		(0x3 << 16)
88#define S5PC110_DMA_CFG_16BURST		(0x4 << 16)
89
90#define S5PC110_DMA_CFG_INC		(0x0 << 8)
91#define S5PC110_DMA_CFG_CNT		(0x1 << 8)
92
93#define S5PC110_DMA_CFG_8BIT		(0x0 << 0)
94#define S5PC110_DMA_CFG_16BIT		(0x1 << 0)
95#define S5PC110_DMA_CFG_32BIT		(0x2 << 0)
96
97#define S5PC110_DMA_SRC_CFG_READ	(S5PC110_DMA_CFG_16BURST | \
98					S5PC110_DMA_CFG_INC | \
99					S5PC110_DMA_CFG_16BIT)
100#define S5PC110_DMA_DST_CFG_READ	(S5PC110_DMA_CFG_16BURST | \
101					S5PC110_DMA_CFG_INC | \
102					S5PC110_DMA_CFG_32BIT)
103#define S5PC110_DMA_SRC_CFG_WRITE	(S5PC110_DMA_CFG_16BURST | \
104					S5PC110_DMA_CFG_INC | \
105					S5PC110_DMA_CFG_32BIT)
106#define S5PC110_DMA_DST_CFG_WRITE	(S5PC110_DMA_CFG_16BURST | \
107					S5PC110_DMA_CFG_INC | \
108					S5PC110_DMA_CFG_16BIT)
109
110#define S5PC110_DMA_TRANS_CMD_TDC	(0x1 << 18)
111#define S5PC110_DMA_TRANS_CMD_TEC	(0x1 << 16)
112#define S5PC110_DMA_TRANS_CMD_TR	(0x1 << 0)
113
114#define S5PC110_DMA_TRANS_STATUS_TD	(0x1 << 18)
115#define S5PC110_DMA_TRANS_STATUS_TB	(0x1 << 17)
116#define S5PC110_DMA_TRANS_STATUS_TE	(0x1 << 16)
117
118#define S5PC110_DMA_DIR_READ		0x0
119#define S5PC110_DMA_DIR_WRITE		0x1
120
121struct s3c_onenand {
122	struct mtd_info	*mtd;
123	struct platform_device	*pdev;
124	enum soc_type	type;
125	void __iomem	*base;
126	struct resource *base_res;
127	void __iomem	*ahb_addr;
128	struct resource *ahb_res;
129	int		bootram_command;
130	void __iomem	*page_buf;
131	void __iomem	*oob_buf;
132	unsigned int	(*mem_addr)(int fba, int fpa, int fsa);
133	unsigned int	(*cmd_map)(unsigned int type, unsigned int val);
134	void __iomem	*dma_addr;
135	struct resource *dma_res;
136	unsigned long	phys_base;
137#ifdef CONFIG_MTD_PARTITIONS
138	struct mtd_partition *parts;
139#endif
140};
141
142#define CMD_MAP_00(dev, addr)		(dev->cmd_map(MAP_00, ((addr) << 1)))
143#define CMD_MAP_01(dev, mem_addr)	(dev->cmd_map(MAP_01, (mem_addr)))
144#define CMD_MAP_10(dev, mem_addr)	(dev->cmd_map(MAP_10, (mem_addr)))
145#define CMD_MAP_11(dev, addr)		(dev->cmd_map(MAP_11, ((addr) << 2)))
146
147static struct s3c_onenand *onenand;
148
149#ifdef CONFIG_MTD_PARTITIONS
150static const char *part_probes[] = { "cmdlinepart", NULL, };
151#endif
152
153static inline int s3c_read_reg(int offset)
154{
155	return readl(onenand->base + offset);
156}
157
158static inline void s3c_write_reg(int value, int offset)
159{
160	writel(value, onenand->base + offset);
161}
162
163static inline int s3c_read_cmd(unsigned int cmd)
164{
165	return readl(onenand->ahb_addr + cmd);
166}
167
168static inline void s3c_write_cmd(int value, unsigned int cmd)
169{
170	writel(value, onenand->ahb_addr + cmd);
171}
172
173#ifdef SAMSUNG_DEBUG
174static void s3c_dump_reg(void)
175{
176	int i;
177
178	for (i = 0; i < 0x400; i += 0x40) {
179		printk(KERN_INFO "0x%08X: 0x%08x 0x%08x 0x%08x 0x%08x\n",
180			(unsigned int) onenand->base + i,
181			s3c_read_reg(i), s3c_read_reg(i + 0x10),
182			s3c_read_reg(i + 0x20), s3c_read_reg(i + 0x30));
183	}
184}
185#endif
186
187static unsigned int s3c64xx_cmd_map(unsigned type, unsigned val)
188{
189	return (type << S3C64XX_CMD_MAP_SHIFT) | val;
190}
191
192static unsigned int s5pc1xx_cmd_map(unsigned type, unsigned val)
193{
194	return (type << S5PC1XX_CMD_MAP_SHIFT) | val;
195}
196
197static unsigned int s3c6400_mem_addr(int fba, int fpa, int fsa)
198{
199	return (fba << S3C6400_FBA_SHIFT) | (fpa << S3C6400_FPA_SHIFT) |
200		(fsa << S3C6400_FSA_SHIFT);
201}
202
203static unsigned int s3c6410_mem_addr(int fba, int fpa, int fsa)
204{
205	return (fba << S3C6410_FBA_SHIFT) | (fpa << S3C6410_FPA_SHIFT) |
206		(fsa << S3C6410_FSA_SHIFT);
207}
208
209static unsigned int s5pc100_mem_addr(int fba, int fpa, int fsa)
210{
211	return (fba << S5PC100_FBA_SHIFT) | (fpa << S5PC100_FPA_SHIFT) |
212		(fsa << S5PC100_FSA_SHIFT);
213}
214
215static void s3c_onenand_reset(void)
216{
217	unsigned long timeout = 0x10000;
218	int stat;
219
220	s3c_write_reg(ONENAND_MEM_RESET_COLD, MEM_RESET_OFFSET);
221	while (1 && timeout--) {
222		stat = s3c_read_reg(INT_ERR_STAT_OFFSET);
223		if (stat & RST_CMP)
224			break;
225	}
226	stat = s3c_read_reg(INT_ERR_STAT_OFFSET);
227	s3c_write_reg(stat, INT_ERR_ACK_OFFSET);
228
229	/* Clear interrupt */
230	s3c_write_reg(0x0, INT_ERR_ACK_OFFSET);
231	/* Clear the ECC status */
232	s3c_write_reg(0x0, ECC_ERR_STAT_OFFSET);
233}
234
235static unsigned short s3c_onenand_readw(void __iomem *addr)
236{
237	struct onenand_chip *this = onenand->mtd->priv;
238	struct device *dev = &onenand->pdev->dev;
239	int reg = addr - this->base;
240	int word_addr = reg >> 1;
241	int value;
242
243	/* It's used for probing time */
244	switch (reg) {
245	case ONENAND_REG_MANUFACTURER_ID:
246		return s3c_read_reg(MANUFACT_ID_OFFSET);
247	case ONENAND_REG_DEVICE_ID:
248		return s3c_read_reg(DEVICE_ID_OFFSET);
249	case ONENAND_REG_VERSION_ID:
250		return s3c_read_reg(FLASH_VER_ID_OFFSET);
251	case ONENAND_REG_DATA_BUFFER_SIZE:
252		return s3c_read_reg(DATA_BUF_SIZE_OFFSET);
253	case ONENAND_REG_TECHNOLOGY:
254		return s3c_read_reg(TECH_OFFSET);
255	case ONENAND_REG_SYS_CFG1:
256		return s3c_read_reg(MEM_CFG_OFFSET);
257
258	/* Used at unlock all status */
259	case ONENAND_REG_CTRL_STATUS:
260		return 0;
261
262	case ONENAND_REG_WP_STATUS:
263		return ONENAND_WP_US;
264
265	default:
266		break;
267	}
268
269	/* BootRAM access control */
270	if ((unsigned int) addr < ONENAND_DATARAM && onenand->bootram_command) {
271		if (word_addr == 0)
272			return s3c_read_reg(MANUFACT_ID_OFFSET);
273		if (word_addr == 1)
274			return s3c_read_reg(DEVICE_ID_OFFSET);
275		if (word_addr == 2)
276			return s3c_read_reg(FLASH_VER_ID_OFFSET);
277	}
278
279	value = s3c_read_cmd(CMD_MAP_11(onenand, word_addr)) & 0xffff;
280	dev_info(dev, "%s: Illegal access at reg 0x%x, value 0x%x\n", __func__,
281		 word_addr, value);
282	return value;
283}
284
285static void s3c_onenand_writew(unsigned short value, void __iomem *addr)
286{
287	struct onenand_chip *this = onenand->mtd->priv;
288	struct device *dev = &onenand->pdev->dev;
289	unsigned int reg = addr - this->base;
290	unsigned int word_addr = reg >> 1;
291
292	/* It's used for probing time */
293	switch (reg) {
294	case ONENAND_REG_SYS_CFG1:
295		s3c_write_reg(value, MEM_CFG_OFFSET);
296		return;
297
298	case ONENAND_REG_START_ADDRESS1:
299	case ONENAND_REG_START_ADDRESS2:
300		return;
301
302	/* Lock/lock-tight/unlock/unlock_all */
303	case ONENAND_REG_START_BLOCK_ADDRESS:
304		return;
305
306	default:
307		break;
308	}
309
310	/* BootRAM access control */
311	if ((unsigned int)addr < ONENAND_DATARAM) {
312		if (value == ONENAND_CMD_READID) {
313			onenand->bootram_command = 1;
314			return;
315		}
316		if (value == ONENAND_CMD_RESET) {
317			s3c_write_reg(ONENAND_MEM_RESET_COLD, MEM_RESET_OFFSET);
318			onenand->bootram_command = 0;
319			return;
320		}
321	}
322
323	dev_info(dev, "%s: Illegal access at reg 0x%x, value 0x%x\n", __func__,
324		 word_addr, value);
325
326	s3c_write_cmd(value, CMD_MAP_11(onenand, word_addr));
327}
328
329static int s3c_onenand_wait(struct mtd_info *mtd, int state)
330{
331	struct device *dev = &onenand->pdev->dev;
332	unsigned int flags = INT_ACT;
333	unsigned int stat, ecc;
334	unsigned long timeout;
335
336	switch (state) {
337	case FL_READING:
338		flags |= BLK_RW_CMP | LOAD_CMP;
339		break;
340	case FL_WRITING:
341		flags |= BLK_RW_CMP | PGM_CMP;
342		break;
343	case FL_ERASING:
344		flags |= BLK_RW_CMP | ERS_CMP;
345		break;
346	case FL_LOCKING:
347		flags |= BLK_RW_CMP;
348		break;
349	default:
350		break;
351	}
352
353	/* The 20 msec is enough */
354	timeout = jiffies + msecs_to_jiffies(20);
355	while (time_before(jiffies, timeout)) {
356		stat = s3c_read_reg(INT_ERR_STAT_OFFSET);
357		if (stat & flags)
358			break;
359
360		if (state != FL_READING)
361			cond_resched();
362	}
363	/* To get correct interrupt status in timeout case */
364	stat = s3c_read_reg(INT_ERR_STAT_OFFSET);
365	s3c_write_reg(stat, INT_ERR_ACK_OFFSET);
366
367	/*
368	 * In the Spec. it checks the controller status first
369	 * However if you get the correct information in case of
370	 * power off recovery (POR) test, it should read ECC status first
371	 */
372	if (stat & LOAD_CMP) {
373		ecc = s3c_read_reg(ECC_ERR_STAT_OFFSET);
374		if (ecc & ONENAND_ECC_4BIT_UNCORRECTABLE) {
375			dev_info(dev, "%s: ECC error = 0x%04x\n", __func__,
376				 ecc);
377			mtd->ecc_stats.failed++;
378			return -EBADMSG;
379		}
380	}
381
382	if (stat & (LOCKED_BLK | ERS_FAIL | PGM_FAIL | LD_FAIL_ECC_ERR)) {
383		dev_info(dev, "%s: controller error = 0x%04x\n", __func__,
384			 stat);
385		if (stat & LOCKED_BLK)
386			dev_info(dev, "%s: it's locked error = 0x%04x\n",
387				 __func__, stat);
388
389		return -EIO;
390	}
391
392	return 0;
393}
394
395static int s3c_onenand_command(struct mtd_info *mtd, int cmd, loff_t addr,
396			       size_t len)
397{
398	struct onenand_chip *this = mtd->priv;
399	unsigned int *m, *s;
400	int fba, fpa, fsa = 0;
401	unsigned int mem_addr, cmd_map_01, cmd_map_10;
402	int i, mcount, scount;
403	int index;
404
405	fba = (int) (addr >> this->erase_shift);
406	fpa = (int) (addr >> this->page_shift);
407	fpa &= this->page_mask;
408
409	mem_addr = onenand->mem_addr(fba, fpa, fsa);
410	cmd_map_01 = CMD_MAP_01(onenand, mem_addr);
411	cmd_map_10 = CMD_MAP_10(onenand, mem_addr);
412
413	switch (cmd) {
414	case ONENAND_CMD_READ:
415	case ONENAND_CMD_READOOB:
416	case ONENAND_CMD_BUFFERRAM:
417		ONENAND_SET_NEXT_BUFFERRAM(this);
418	default:
419		break;
420	}
421
422	index = ONENAND_CURRENT_BUFFERRAM(this);
423
424	/*
425	 * Emulate Two BufferRAMs and access with 4 bytes pointer
426	 */
427	m = (unsigned int *) onenand->page_buf;
428	s = (unsigned int *) onenand->oob_buf;
429
430	if (index) {
431		m += (this->writesize >> 2);
432		s += (mtd->oobsize >> 2);
433	}
434
435	mcount = mtd->writesize >> 2;
436	scount = mtd->oobsize >> 2;
437
438	switch (cmd) {
439	case ONENAND_CMD_READ:
440		/* Main */
441		for (i = 0; i < mcount; i++)
442			*m++ = s3c_read_cmd(cmd_map_01);
443		return 0;
444
445	case ONENAND_CMD_READOOB:
446		s3c_write_reg(TSRF, TRANS_SPARE_OFFSET);
447		/* Main */
448		for (i = 0; i < mcount; i++)
449			*m++ = s3c_read_cmd(cmd_map_01);
450
451		/* Spare */
452		for (i = 0; i < scount; i++)
453			*s++ = s3c_read_cmd(cmd_map_01);
454
455		s3c_write_reg(0, TRANS_SPARE_OFFSET);
456		return 0;
457
458	case ONENAND_CMD_PROG:
459		/* Main */
460		for (i = 0; i < mcount; i++)
461			s3c_write_cmd(*m++, cmd_map_01);
462		return 0;
463
464	case ONENAND_CMD_PROGOOB:
465		s3c_write_reg(TSRF, TRANS_SPARE_OFFSET);
466
467		/* Main - dummy write */
468		for (i = 0; i < mcount; i++)
469			s3c_write_cmd(0xffffffff, cmd_map_01);
470
471		/* Spare */
472		for (i = 0; i < scount; i++)
473			s3c_write_cmd(*s++, cmd_map_01);
474
475		s3c_write_reg(0, TRANS_SPARE_OFFSET);
476		return 0;
477
478	case ONENAND_CMD_UNLOCK_ALL:
479		s3c_write_cmd(ONENAND_UNLOCK_ALL, cmd_map_10);
480		return 0;
481
482	case ONENAND_CMD_ERASE:
483		s3c_write_cmd(ONENAND_ERASE_START, cmd_map_10);
484		return 0;
485
486	default:
487		break;
488	}
489
490	return 0;
491}
492
493static unsigned char *s3c_get_bufferram(struct mtd_info *mtd, int area)
494{
495	struct onenand_chip *this = mtd->priv;
496	int index = ONENAND_CURRENT_BUFFERRAM(this);
497	unsigned char *p;
498
499	if (area == ONENAND_DATARAM) {
500		p = (unsigned char *) onenand->page_buf;
501		if (index == 1)
502			p += this->writesize;
503	} else {
504		p = (unsigned char *) onenand->oob_buf;
505		if (index == 1)
506			p += mtd->oobsize;
507	}
508
509	return p;
510}
511
512static int onenand_read_bufferram(struct mtd_info *mtd, int area,
513				  unsigned char *buffer, int offset,
514				  size_t count)
515{
516	unsigned char *p;
517
518	p = s3c_get_bufferram(mtd, area);
519	memcpy(buffer, p + offset, count);
520	return 0;
521}
522
523static int onenand_write_bufferram(struct mtd_info *mtd, int area,
524				   const unsigned char *buffer, int offset,
525				   size_t count)
526{
527	unsigned char *p;
528
529	p = s3c_get_bufferram(mtd, area);
530	memcpy(p + offset, buffer, count);
531	return 0;
532}
533
534static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction)
535{
536	void __iomem *base = onenand->dma_addr;
537	int status;
538
539	writel(src, base + S5PC110_DMA_SRC_ADDR);
540	writel(dst, base + S5PC110_DMA_DST_ADDR);
541
542	if (direction == S5PC110_DMA_DIR_READ) {
543		writel(S5PC110_DMA_SRC_CFG_READ, base + S5PC110_DMA_SRC_CFG);
544		writel(S5PC110_DMA_DST_CFG_READ, base + S5PC110_DMA_DST_CFG);
545	} else {
546		writel(S5PC110_DMA_SRC_CFG_WRITE, base + S5PC110_DMA_SRC_CFG);
547		writel(S5PC110_DMA_DST_CFG_WRITE, base + S5PC110_DMA_DST_CFG);
548	}
549
550	writel(count, base + S5PC110_DMA_TRANS_SIZE);
551	writel(direction, base + S5PC110_DMA_TRANS_DIR);
552
553	writel(S5PC110_DMA_TRANS_CMD_TR, base + S5PC110_DMA_TRANS_CMD);
554
555	do {
556		status = readl(base + S5PC110_DMA_TRANS_STATUS);
557		if (status & S5PC110_DMA_TRANS_STATUS_TE) {
558			writel(S5PC110_DMA_TRANS_CMD_TEC,
559					base + S5PC110_DMA_TRANS_CMD);
560			return -EIO;
561		}
562	} while (!(status & S5PC110_DMA_TRANS_STATUS_TD));
563
564	writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD);
565
566	return 0;
567}
568
569static int s5pc110_read_bufferram(struct mtd_info *mtd, int area,
570		unsigned char *buffer, int offset, size_t count)
571{
572	struct onenand_chip *this = mtd->priv;
573	void __iomem *p;
574	void *buf = (void *) buffer;
575	dma_addr_t dma_src, dma_dst;
576	int err;
577
578	p = this->base + area;
579	if (ONENAND_CURRENT_BUFFERRAM(this)) {
580		if (area == ONENAND_DATARAM)
581			p += this->writesize;
582		else
583			p += mtd->oobsize;
584	}
585
586	if (offset & 3 || (size_t) buf & 3 ||
587		!onenand->dma_addr || count != mtd->writesize)
588		goto normal;
589
590	/* Handle vmalloc address */
591	if (buf >= high_memory) {
592		struct page *page;
593
594		if (((size_t) buf & PAGE_MASK) !=
595		    ((size_t) (buf + count - 1) & PAGE_MASK))
596			goto normal;
597		page = vmalloc_to_page(buf);
598		if (!page)
599			goto normal;
600		buf = page_address(page) + ((size_t) buf & ~PAGE_MASK);
601	}
602
603	/* DMA routine */
604	dma_src = onenand->phys_base + (p - this->base);
605	dma_dst = dma_map_single(&onenand->pdev->dev,
606			buf, count, DMA_FROM_DEVICE);
607	if (dma_mapping_error(&onenand->pdev->dev, dma_dst)) {
608		dev_err(&onenand->pdev->dev,
609			"Couldn't map a %d byte buffer for DMA\n", count);
610		goto normal;
611	}
612	err = s5pc110_dma_ops((void *) dma_dst, (void *) dma_src,
613			count, S5PC110_DMA_DIR_READ);
614	dma_unmap_single(&onenand->pdev->dev, dma_dst, count, DMA_FROM_DEVICE);
615
616	if (!err)
617		return 0;
618
619normal:
620	if (count != mtd->writesize) {
621		/* Copy the bufferram to memory to prevent unaligned access */
622		memcpy(this->page_buf, p, mtd->writesize);
623		p = this->page_buf + offset;
624	}
625
626	memcpy(buffer, p, count);
627
628	return 0;
629}
630
631static int s5pc110_chip_probe(struct mtd_info *mtd)
632{
633	/* Now just return 0 */
634	return 0;
635}
636
637static int s3c_onenand_bbt_wait(struct mtd_info *mtd, int state)
638{
639	unsigned int flags = INT_ACT | LOAD_CMP;
640	unsigned int stat;
641	unsigned long timeout;
642
643	/* The 20 msec is enough */
644	timeout = jiffies + msecs_to_jiffies(20);
645	while (time_before(jiffies, timeout)) {
646		stat = s3c_read_reg(INT_ERR_STAT_OFFSET);
647		if (stat & flags)
648			break;
649	}
650	/* To get correct interrupt status in timeout case */
651	stat = s3c_read_reg(INT_ERR_STAT_OFFSET);
652	s3c_write_reg(stat, INT_ERR_ACK_OFFSET);
653
654	if (stat & LD_FAIL_ECC_ERR) {
655		s3c_onenand_reset();
656		return ONENAND_BBT_READ_ERROR;
657	}
658
659	if (stat & LOAD_CMP) {
660		int ecc = s3c_read_reg(ECC_ERR_STAT_OFFSET);
661		if (ecc & ONENAND_ECC_4BIT_UNCORRECTABLE) {
662			s3c_onenand_reset();
663			return ONENAND_BBT_READ_ERROR;
664		}
665	}
666
667	return 0;
668}
669
670static void s3c_onenand_check_lock_status(struct mtd_info *mtd)
671{
672	struct onenand_chip *this = mtd->priv;
673	struct device *dev = &onenand->pdev->dev;
674	unsigned int block, end;
675	int tmp;
676
677	end = this->chipsize >> this->erase_shift;
678
679	for (block = 0; block < end; block++) {
680		unsigned int mem_addr = onenand->mem_addr(block, 0, 0);
681		tmp = s3c_read_cmd(CMD_MAP_01(onenand, mem_addr));
682
683		if (s3c_read_reg(INT_ERR_STAT_OFFSET) & LOCKED_BLK) {
684			dev_err(dev, "block %d is write-protected!\n", block);
685			s3c_write_reg(LOCKED_BLK, INT_ERR_ACK_OFFSET);
686		}
687	}
688}
689
690static void s3c_onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs,
691				    size_t len, int cmd)
692{
693	struct onenand_chip *this = mtd->priv;
694	int start, end, start_mem_addr, end_mem_addr;
695
696	start = ofs >> this->erase_shift;
697	start_mem_addr = onenand->mem_addr(start, 0, 0);
698	end = start + (len >> this->erase_shift) - 1;
699	end_mem_addr = onenand->mem_addr(end, 0, 0);
700
701	if (cmd == ONENAND_CMD_LOCK) {
702		s3c_write_cmd(ONENAND_LOCK_START, CMD_MAP_10(onenand,
703							     start_mem_addr));
704		s3c_write_cmd(ONENAND_LOCK_END, CMD_MAP_10(onenand,
705							   end_mem_addr));
706	} else {
707		s3c_write_cmd(ONENAND_UNLOCK_START, CMD_MAP_10(onenand,
708							       start_mem_addr));
709		s3c_write_cmd(ONENAND_UNLOCK_END, CMD_MAP_10(onenand,
710							     end_mem_addr));
711	}
712
713	this->wait(mtd, FL_LOCKING);
714}
715
716static void s3c_unlock_all(struct mtd_info *mtd)
717{
718	struct onenand_chip *this = mtd->priv;
719	loff_t ofs = 0;
720	size_t len = this->chipsize;
721
722	if (this->options & ONENAND_HAS_UNLOCK_ALL) {
723		/* Write unlock command */
724		this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0);
725
726		/* No need to check return value */
727		this->wait(mtd, FL_LOCKING);
728
729		if (!ONENAND_IS_DDP(this)) {
730			s3c_onenand_check_lock_status(mtd);
731			return;
732		}
733
734		/* All blocks on another chip */
735		ofs = this->chipsize >> 1;
736		len = this->chipsize >> 1;
737	}
738
739	s3c_onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
740
741	s3c_onenand_check_lock_status(mtd);
742}
743
744static void s3c_onenand_setup(struct mtd_info *mtd)
745{
746	struct onenand_chip *this = mtd->priv;
747
748	onenand->mtd = mtd;
749
750	if (onenand->type == TYPE_S3C6400) {
751		onenand->mem_addr = s3c6400_mem_addr;
752		onenand->cmd_map = s3c64xx_cmd_map;
753	} else if (onenand->type == TYPE_S3C6410) {
754		onenand->mem_addr = s3c6410_mem_addr;
755		onenand->cmd_map = s3c64xx_cmd_map;
756	} else if (onenand->type == TYPE_S5PC100) {
757		onenand->mem_addr = s5pc100_mem_addr;
758		onenand->cmd_map = s5pc1xx_cmd_map;
759	} else if (onenand->type == TYPE_S5PC110) {
760		/* Use generic onenand functions */
761		onenand->cmd_map = s5pc1xx_cmd_map;
762		this->read_bufferram = s5pc110_read_bufferram;
763		this->chip_probe = s5pc110_chip_probe;
764		return;
765	} else {
766		BUG();
767	}
768
769	this->read_word = s3c_onenand_readw;
770	this->write_word = s3c_onenand_writew;
771
772	this->wait = s3c_onenand_wait;
773	this->bbt_wait = s3c_onenand_bbt_wait;
774	this->unlock_all = s3c_unlock_all;
775	this->command = s3c_onenand_command;
776
777	this->read_bufferram = onenand_read_bufferram;
778	this->write_bufferram = onenand_write_bufferram;
779}
780
781static int s3c_onenand_probe(struct platform_device *pdev)
782{
783	struct onenand_platform_data *pdata;
784	struct onenand_chip *this;
785	struct mtd_info *mtd;
786	struct resource *r;
787	int size, err;
788
789	pdata = pdev->dev.platform_data;
790	/* No need to check pdata. the platform data is optional */
791
792	size = sizeof(struct mtd_info) + sizeof(struct onenand_chip);
793	mtd = kzalloc(size, GFP_KERNEL);
794	if (!mtd) {
795		dev_err(&pdev->dev, "failed to allocate memory\n");
796		return -ENOMEM;
797	}
798
799	onenand = kzalloc(sizeof(struct s3c_onenand), GFP_KERNEL);
800	if (!onenand) {
801		err = -ENOMEM;
802		goto onenand_fail;
803	}
804
805	this = (struct onenand_chip *) &mtd[1];
806	mtd->priv = this;
807	mtd->dev.parent = &pdev->dev;
808	mtd->owner = THIS_MODULE;
809	onenand->pdev = pdev;
810	onenand->type = platform_get_device_id(pdev)->driver_data;
811
812	s3c_onenand_setup(mtd);
813
814	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
815	if (!r) {
816		dev_err(&pdev->dev, "no memory resource defined\n");
817		return -ENOENT;
818		goto ahb_resource_failed;
819	}
820
821	onenand->base_res = request_mem_region(r->start, resource_size(r),
822					       pdev->name);
823	if (!onenand->base_res) {
824		dev_err(&pdev->dev, "failed to request memory resource\n");
825		err = -EBUSY;
826		goto resource_failed;
827	}
828
829	onenand->base = ioremap(r->start, resource_size(r));
830	if (!onenand->base) {
831		dev_err(&pdev->dev, "failed to map memory resource\n");
832		err = -EFAULT;
833		goto ioremap_failed;
834	}
835	/* Set onenand_chip also */
836	this->base = onenand->base;
837
838	/* Use runtime badblock check */
839	this->options |= ONENAND_SKIP_UNLOCK_CHECK;
840
841	if (onenand->type != TYPE_S5PC110) {
842		r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
843		if (!r) {
844			dev_err(&pdev->dev, "no buffer memory resource defined\n");
845			return -ENOENT;
846			goto ahb_resource_failed;
847		}
848
849		onenand->ahb_res = request_mem_region(r->start, resource_size(r),
850						      pdev->name);
851		if (!onenand->ahb_res) {
852			dev_err(&pdev->dev, "failed to request buffer memory resource\n");
853			err = -EBUSY;
854			goto ahb_resource_failed;
855		}
856
857		onenand->ahb_addr = ioremap(r->start, resource_size(r));
858		if (!onenand->ahb_addr) {
859			dev_err(&pdev->dev, "failed to map buffer memory resource\n");
860			err = -EINVAL;
861			goto ahb_ioremap_failed;
862		}
863
864		/* Allocate 4KiB BufferRAM */
865		onenand->page_buf = kzalloc(SZ_4K, GFP_KERNEL);
866		if (!onenand->page_buf) {
867			err = -ENOMEM;
868			goto page_buf_fail;
869		}
870
871		/* Allocate 128 SpareRAM */
872		onenand->oob_buf = kzalloc(128, GFP_KERNEL);
873		if (!onenand->oob_buf) {
874			err = -ENOMEM;
875			goto oob_buf_fail;
876		}
877
878		/* S3C doesn't handle subpage write */
879		mtd->subpage_sft = 0;
880		this->subpagesize = mtd->writesize;
881
882	} else { /* S5PC110 */
883		r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
884		if (!r) {
885			dev_err(&pdev->dev, "no dma memory resource defined\n");
886			return -ENOENT;
887			goto dma_resource_failed;
888		}
889
890		onenand->dma_res = request_mem_region(r->start, resource_size(r),
891						      pdev->name);
892		if (!onenand->dma_res) {
893			dev_err(&pdev->dev, "failed to request dma memory resource\n");
894			err = -EBUSY;
895			goto dma_resource_failed;
896		}
897
898		onenand->dma_addr = ioremap(r->start, resource_size(r));
899		if (!onenand->dma_addr) {
900			dev_err(&pdev->dev, "failed to map dma memory resource\n");
901			err = -EINVAL;
902			goto dma_ioremap_failed;
903		}
904
905		onenand->phys_base = onenand->base_res->start;
906	}
907
908	if (onenand_scan(mtd, 1)) {
909		err = -EFAULT;
910		goto scan_failed;
911	}
912
913	if (onenand->type != TYPE_S5PC110) {
914		/* S3C doesn't handle subpage write */
915		mtd->subpage_sft = 0;
916		this->subpagesize = mtd->writesize;
917	}
918
919	if (s3c_read_reg(MEM_CFG_OFFSET) & ONENAND_SYS_CFG1_SYNC_READ)
920		dev_info(&onenand->pdev->dev, "OneNAND Sync. Burst Read enabled\n");
921
922#ifdef CONFIG_MTD_PARTITIONS
923	err = parse_mtd_partitions(mtd, part_probes, &onenand->parts, 0);
924	if (err > 0)
925		add_mtd_partitions(mtd, onenand->parts, err);
926	else if (err <= 0 && pdata && pdata->parts)
927		add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
928	else
929#endif
930		err = add_mtd_device(mtd);
931
932	platform_set_drvdata(pdev, mtd);
933
934	return 0;
935
936scan_failed:
937	if (onenand->dma_addr)
938		iounmap(onenand->dma_addr);
939dma_ioremap_failed:
940	if (onenand->dma_res)
941		release_mem_region(onenand->dma_res->start,
942				   resource_size(onenand->dma_res));
943	kfree(onenand->oob_buf);
944oob_buf_fail:
945	kfree(onenand->page_buf);
946page_buf_fail:
947	if (onenand->ahb_addr)
948		iounmap(onenand->ahb_addr);
949ahb_ioremap_failed:
950	if (onenand->ahb_res)
951		release_mem_region(onenand->ahb_res->start,
952				   resource_size(onenand->ahb_res));
953dma_resource_failed:
954ahb_resource_failed:
955	iounmap(onenand->base);
956ioremap_failed:
957	if (onenand->base_res)
958		release_mem_region(onenand->base_res->start,
959				   resource_size(onenand->base_res));
960resource_failed:
961	kfree(onenand);
962onenand_fail:
963	kfree(mtd);
964	return err;
965}
966
967static int __devexit s3c_onenand_remove(struct platform_device *pdev)
968{
969	struct mtd_info *mtd = platform_get_drvdata(pdev);
970
971	onenand_release(mtd);
972	if (onenand->ahb_addr)
973		iounmap(onenand->ahb_addr);
974	if (onenand->ahb_res)
975		release_mem_region(onenand->ahb_res->start,
976				   resource_size(onenand->ahb_res));
977	if (onenand->dma_addr)
978		iounmap(onenand->dma_addr);
979	if (onenand->dma_res)
980		release_mem_region(onenand->dma_res->start,
981				   resource_size(onenand->dma_res));
982
983	iounmap(onenand->base);
984	release_mem_region(onenand->base_res->start,
985			   resource_size(onenand->base_res));
986
987	platform_set_drvdata(pdev, NULL);
988	kfree(onenand->oob_buf);
989	kfree(onenand->page_buf);
990	kfree(onenand);
991	kfree(mtd);
992	return 0;
993}
994
995static int s3c_pm_ops_suspend(struct device *dev)
996{
997	struct platform_device *pdev = to_platform_device(dev);
998	struct mtd_info *mtd = platform_get_drvdata(pdev);
999	struct onenand_chip *this = mtd->priv;
1000
1001	this->wait(mtd, FL_PM_SUSPENDED);
1002	return mtd->suspend(mtd);
1003}
1004
1005static  int s3c_pm_ops_resume(struct device *dev)
1006{
1007	struct platform_device *pdev = to_platform_device(dev);
1008	struct mtd_info *mtd = platform_get_drvdata(pdev);
1009	struct onenand_chip *this = mtd->priv;
1010
1011	mtd->resume(mtd);
1012	this->unlock_all(mtd);
1013	return 0;
1014}
1015
1016static const struct dev_pm_ops s3c_pm_ops = {
1017	.suspend	= s3c_pm_ops_suspend,
1018	.resume		= s3c_pm_ops_resume,
1019};
1020
1021static struct platform_device_id s3c_onenand_driver_ids[] = {
1022	{
1023		.name		= "s3c6400-onenand",
1024		.driver_data	= TYPE_S3C6400,
1025	}, {
1026		.name		= "s3c6410-onenand",
1027		.driver_data	= TYPE_S3C6410,
1028	}, {
1029		.name		= "s5pc100-onenand",
1030		.driver_data	= TYPE_S5PC100,
1031	}, {
1032		.name		= "s5pc110-onenand",
1033		.driver_data	= TYPE_S5PC110,
1034	}, { },
1035};
1036MODULE_DEVICE_TABLE(platform, s3c_onenand_driver_ids);
1037
1038static struct platform_driver s3c_onenand_driver = {
1039	.driver         = {
1040		.name	= "samsung-onenand",
1041		.pm	= &s3c_pm_ops,
1042	},
1043	.id_table	= s3c_onenand_driver_ids,
1044	.probe          = s3c_onenand_probe,
1045	.remove         = __devexit_p(s3c_onenand_remove),
1046};
1047
1048static int __init s3c_onenand_init(void)
1049{
1050	return platform_driver_register(&s3c_onenand_driver);
1051}
1052
1053static void __exit s3c_onenand_exit(void)
1054{
1055	platform_driver_unregister(&s3c_onenand_driver);
1056}
1057
1058module_init(s3c_onenand_init);
1059module_exit(s3c_onenand_exit);
1060
1061MODULE_LICENSE("GPL");
1062MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>");
1063MODULE_DESCRIPTION("Samsung OneNAND controller support");
1064