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