0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/module.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/sched.h>
0017 #include <linux/slab.h>
0018 #include <linux/mtd/mtd.h>
0019 #include <linux/mtd/onenand.h>
0020 #include <linux/mtd/partitions.h>
0021 #include <linux/dma-mapping.h>
0022 #include <linux/interrupt.h>
0023 #include <linux/io.h>
0024
0025 #include "samsung.h"
0026
0027 enum soc_type {
0028 TYPE_S3C6400,
0029 TYPE_S3C6410,
0030 TYPE_S5PC110,
0031 };
0032
0033 #define ONENAND_ERASE_STATUS 0x00
0034 #define ONENAND_MULTI_ERASE_SET 0x01
0035 #define ONENAND_ERASE_START 0x03
0036 #define ONENAND_UNLOCK_START 0x08
0037 #define ONENAND_UNLOCK_END 0x09
0038 #define ONENAND_LOCK_START 0x0A
0039 #define ONENAND_LOCK_END 0x0B
0040 #define ONENAND_LOCK_TIGHT_START 0x0C
0041 #define ONENAND_LOCK_TIGHT_END 0x0D
0042 #define ONENAND_UNLOCK_ALL 0x0E
0043 #define ONENAND_OTP_ACCESS 0x12
0044 #define ONENAND_SPARE_ACCESS_ONLY 0x13
0045 #define ONENAND_MAIN_ACCESS_ONLY 0x14
0046 #define ONENAND_ERASE_VERIFY 0x15
0047 #define ONENAND_MAIN_SPARE_ACCESS 0x16
0048 #define ONENAND_PIPELINE_READ 0x4000
0049
0050 #define MAP_00 (0x0)
0051 #define MAP_01 (0x1)
0052 #define MAP_10 (0x2)
0053 #define MAP_11 (0x3)
0054
0055 #define S3C64XX_CMD_MAP_SHIFT 24
0056
0057 #define S3C6400_FBA_SHIFT 10
0058 #define S3C6400_FPA_SHIFT 4
0059 #define S3C6400_FSA_SHIFT 2
0060
0061 #define S3C6410_FBA_SHIFT 12
0062 #define S3C6410_FPA_SHIFT 6
0063 #define S3C6410_FSA_SHIFT 4
0064
0065
0066 #define S5PC110_DMA_SRC_ADDR 0x400
0067 #define S5PC110_DMA_SRC_CFG 0x404
0068 #define S5PC110_DMA_DST_ADDR 0x408
0069 #define S5PC110_DMA_DST_CFG 0x40C
0070 #define S5PC110_DMA_TRANS_SIZE 0x414
0071 #define S5PC110_DMA_TRANS_CMD 0x418
0072 #define S5PC110_DMA_TRANS_STATUS 0x41C
0073 #define S5PC110_DMA_TRANS_DIR 0x420
0074 #define S5PC110_INTC_DMA_CLR 0x1004
0075 #define S5PC110_INTC_ONENAND_CLR 0x1008
0076 #define S5PC110_INTC_DMA_MASK 0x1024
0077 #define S5PC110_INTC_ONENAND_MASK 0x1028
0078 #define S5PC110_INTC_DMA_PEND 0x1044
0079 #define S5PC110_INTC_ONENAND_PEND 0x1048
0080 #define S5PC110_INTC_DMA_STATUS 0x1064
0081 #define S5PC110_INTC_ONENAND_STATUS 0x1068
0082
0083 #define S5PC110_INTC_DMA_TD (1 << 24)
0084 #define S5PC110_INTC_DMA_TE (1 << 16)
0085
0086 #define S5PC110_DMA_CFG_SINGLE (0x0 << 16)
0087 #define S5PC110_DMA_CFG_4BURST (0x2 << 16)
0088 #define S5PC110_DMA_CFG_8BURST (0x3 << 16)
0089 #define S5PC110_DMA_CFG_16BURST (0x4 << 16)
0090
0091 #define S5PC110_DMA_CFG_INC (0x0 << 8)
0092 #define S5PC110_DMA_CFG_CNT (0x1 << 8)
0093
0094 #define S5PC110_DMA_CFG_8BIT (0x0 << 0)
0095 #define S5PC110_DMA_CFG_16BIT (0x1 << 0)
0096 #define S5PC110_DMA_CFG_32BIT (0x2 << 0)
0097
0098 #define S5PC110_DMA_SRC_CFG_READ (S5PC110_DMA_CFG_16BURST | \
0099 S5PC110_DMA_CFG_INC | \
0100 S5PC110_DMA_CFG_16BIT)
0101 #define S5PC110_DMA_DST_CFG_READ (S5PC110_DMA_CFG_16BURST | \
0102 S5PC110_DMA_CFG_INC | \
0103 S5PC110_DMA_CFG_32BIT)
0104 #define S5PC110_DMA_SRC_CFG_WRITE (S5PC110_DMA_CFG_16BURST | \
0105 S5PC110_DMA_CFG_INC | \
0106 S5PC110_DMA_CFG_32BIT)
0107 #define S5PC110_DMA_DST_CFG_WRITE (S5PC110_DMA_CFG_16BURST | \
0108 S5PC110_DMA_CFG_INC | \
0109 S5PC110_DMA_CFG_16BIT)
0110
0111 #define S5PC110_DMA_TRANS_CMD_TDC (0x1 << 18)
0112 #define S5PC110_DMA_TRANS_CMD_TEC (0x1 << 16)
0113 #define S5PC110_DMA_TRANS_CMD_TR (0x1 << 0)
0114
0115 #define S5PC110_DMA_TRANS_STATUS_TD (0x1 << 18)
0116 #define S5PC110_DMA_TRANS_STATUS_TB (0x1 << 17)
0117 #define S5PC110_DMA_TRANS_STATUS_TE (0x1 << 16)
0118
0119 #define S5PC110_DMA_DIR_READ 0x0
0120 #define S5PC110_DMA_DIR_WRITE 0x1
0121
0122 struct s3c_onenand {
0123 struct mtd_info *mtd;
0124 struct platform_device *pdev;
0125 enum soc_type type;
0126 void __iomem *base;
0127 void __iomem *ahb_addr;
0128 int bootram_command;
0129 void *page_buf;
0130 void *oob_buf;
0131 unsigned int (*mem_addr)(int fba, int fpa, int fsa);
0132 unsigned int (*cmd_map)(unsigned int type, unsigned int val);
0133 void __iomem *dma_addr;
0134 unsigned long phys_base;
0135 struct completion complete;
0136 };
0137
0138 #define CMD_MAP_00(dev, addr) (dev->cmd_map(MAP_00, ((addr) << 1)))
0139 #define CMD_MAP_01(dev, mem_addr) (dev->cmd_map(MAP_01, (mem_addr)))
0140 #define CMD_MAP_10(dev, mem_addr) (dev->cmd_map(MAP_10, (mem_addr)))
0141 #define CMD_MAP_11(dev, addr) (dev->cmd_map(MAP_11, ((addr) << 2)))
0142
0143 static struct s3c_onenand *onenand;
0144
0145 static inline int s3c_read_reg(int offset)
0146 {
0147 return readl(onenand->base + offset);
0148 }
0149
0150 static inline void s3c_write_reg(int value, int offset)
0151 {
0152 writel(value, onenand->base + offset);
0153 }
0154
0155 static inline int s3c_read_cmd(unsigned int cmd)
0156 {
0157 return readl(onenand->ahb_addr + cmd);
0158 }
0159
0160 static inline void s3c_write_cmd(int value, unsigned int cmd)
0161 {
0162 writel(value, onenand->ahb_addr + cmd);
0163 }
0164
0165 #ifdef SAMSUNG_DEBUG
0166 static void s3c_dump_reg(void)
0167 {
0168 int i;
0169
0170 for (i = 0; i < 0x400; i += 0x40) {
0171 printk(KERN_INFO "0x%08X: 0x%08x 0x%08x 0x%08x 0x%08x\n",
0172 (unsigned int) onenand->base + i,
0173 s3c_read_reg(i), s3c_read_reg(i + 0x10),
0174 s3c_read_reg(i + 0x20), s3c_read_reg(i + 0x30));
0175 }
0176 }
0177 #endif
0178
0179 static unsigned int s3c64xx_cmd_map(unsigned type, unsigned val)
0180 {
0181 return (type << S3C64XX_CMD_MAP_SHIFT) | val;
0182 }
0183
0184 static unsigned int s3c6400_mem_addr(int fba, int fpa, int fsa)
0185 {
0186 return (fba << S3C6400_FBA_SHIFT) | (fpa << S3C6400_FPA_SHIFT) |
0187 (fsa << S3C6400_FSA_SHIFT);
0188 }
0189
0190 static unsigned int s3c6410_mem_addr(int fba, int fpa, int fsa)
0191 {
0192 return (fba << S3C6410_FBA_SHIFT) | (fpa << S3C6410_FPA_SHIFT) |
0193 (fsa << S3C6410_FSA_SHIFT);
0194 }
0195
0196 static void s3c_onenand_reset(void)
0197 {
0198 unsigned long timeout = 0x10000;
0199 int stat;
0200
0201 s3c_write_reg(ONENAND_MEM_RESET_COLD, MEM_RESET_OFFSET);
0202 while (1 && timeout--) {
0203 stat = s3c_read_reg(INT_ERR_STAT_OFFSET);
0204 if (stat & RST_CMP)
0205 break;
0206 }
0207 stat = s3c_read_reg(INT_ERR_STAT_OFFSET);
0208 s3c_write_reg(stat, INT_ERR_ACK_OFFSET);
0209
0210
0211 s3c_write_reg(0x0, INT_ERR_ACK_OFFSET);
0212
0213 s3c_write_reg(0x0, ECC_ERR_STAT_OFFSET);
0214 }
0215
0216 static unsigned short s3c_onenand_readw(void __iomem *addr)
0217 {
0218 struct onenand_chip *this = onenand->mtd->priv;
0219 struct device *dev = &onenand->pdev->dev;
0220 int reg = addr - this->base;
0221 int word_addr = reg >> 1;
0222 int value;
0223
0224
0225 switch (reg) {
0226 case ONENAND_REG_MANUFACTURER_ID:
0227 return s3c_read_reg(MANUFACT_ID_OFFSET);
0228 case ONENAND_REG_DEVICE_ID:
0229 return s3c_read_reg(DEVICE_ID_OFFSET);
0230 case ONENAND_REG_VERSION_ID:
0231 return s3c_read_reg(FLASH_VER_ID_OFFSET);
0232 case ONENAND_REG_DATA_BUFFER_SIZE:
0233 return s3c_read_reg(DATA_BUF_SIZE_OFFSET);
0234 case ONENAND_REG_TECHNOLOGY:
0235 return s3c_read_reg(TECH_OFFSET);
0236 case ONENAND_REG_SYS_CFG1:
0237 return s3c_read_reg(MEM_CFG_OFFSET);
0238
0239
0240 case ONENAND_REG_CTRL_STATUS:
0241 return 0;
0242
0243 case ONENAND_REG_WP_STATUS:
0244 return ONENAND_WP_US;
0245
0246 default:
0247 break;
0248 }
0249
0250
0251 if ((unsigned long)addr < ONENAND_DATARAM && onenand->bootram_command) {
0252 if (word_addr == 0)
0253 return s3c_read_reg(MANUFACT_ID_OFFSET);
0254 if (word_addr == 1)
0255 return s3c_read_reg(DEVICE_ID_OFFSET);
0256 if (word_addr == 2)
0257 return s3c_read_reg(FLASH_VER_ID_OFFSET);
0258 }
0259
0260 value = s3c_read_cmd(CMD_MAP_11(onenand, word_addr)) & 0xffff;
0261 dev_info(dev, "%s: Illegal access at reg 0x%x, value 0x%x\n", __func__,
0262 word_addr, value);
0263 return value;
0264 }
0265
0266 static void s3c_onenand_writew(unsigned short value, void __iomem *addr)
0267 {
0268 struct onenand_chip *this = onenand->mtd->priv;
0269 struct device *dev = &onenand->pdev->dev;
0270 unsigned int reg = addr - this->base;
0271 unsigned int word_addr = reg >> 1;
0272
0273
0274 switch (reg) {
0275 case ONENAND_REG_SYS_CFG1:
0276 s3c_write_reg(value, MEM_CFG_OFFSET);
0277 return;
0278
0279 case ONENAND_REG_START_ADDRESS1:
0280 case ONENAND_REG_START_ADDRESS2:
0281 return;
0282
0283
0284 case ONENAND_REG_START_BLOCK_ADDRESS:
0285 return;
0286
0287 default:
0288 break;
0289 }
0290
0291
0292 if ((unsigned long)addr < ONENAND_DATARAM) {
0293 if (value == ONENAND_CMD_READID) {
0294 onenand->bootram_command = 1;
0295 return;
0296 }
0297 if (value == ONENAND_CMD_RESET) {
0298 s3c_write_reg(ONENAND_MEM_RESET_COLD, MEM_RESET_OFFSET);
0299 onenand->bootram_command = 0;
0300 return;
0301 }
0302 }
0303
0304 dev_info(dev, "%s: Illegal access at reg 0x%x, value 0x%x\n", __func__,
0305 word_addr, value);
0306
0307 s3c_write_cmd(value, CMD_MAP_11(onenand, word_addr));
0308 }
0309
0310 static int s3c_onenand_wait(struct mtd_info *mtd, int state)
0311 {
0312 struct device *dev = &onenand->pdev->dev;
0313 unsigned int flags = INT_ACT;
0314 unsigned int stat, ecc;
0315 unsigned long timeout;
0316
0317 switch (state) {
0318 case FL_READING:
0319 flags |= BLK_RW_CMP | LOAD_CMP;
0320 break;
0321 case FL_WRITING:
0322 flags |= BLK_RW_CMP | PGM_CMP;
0323 break;
0324 case FL_ERASING:
0325 flags |= BLK_RW_CMP | ERS_CMP;
0326 break;
0327 case FL_LOCKING:
0328 flags |= BLK_RW_CMP;
0329 break;
0330 default:
0331 break;
0332 }
0333
0334
0335 timeout = jiffies + msecs_to_jiffies(20);
0336 while (time_before(jiffies, timeout)) {
0337 stat = s3c_read_reg(INT_ERR_STAT_OFFSET);
0338 if (stat & flags)
0339 break;
0340
0341 if (state != FL_READING)
0342 cond_resched();
0343 }
0344
0345 stat = s3c_read_reg(INT_ERR_STAT_OFFSET);
0346 s3c_write_reg(stat, INT_ERR_ACK_OFFSET);
0347
0348
0349
0350
0351
0352
0353 if (stat & LOAD_CMP) {
0354 ecc = s3c_read_reg(ECC_ERR_STAT_OFFSET);
0355 if (ecc & ONENAND_ECC_4BIT_UNCORRECTABLE) {
0356 dev_info(dev, "%s: ECC error = 0x%04x\n", __func__,
0357 ecc);
0358 mtd->ecc_stats.failed++;
0359 return -EBADMSG;
0360 }
0361 }
0362
0363 if (stat & (LOCKED_BLK | ERS_FAIL | PGM_FAIL | LD_FAIL_ECC_ERR)) {
0364 dev_info(dev, "%s: controller error = 0x%04x\n", __func__,
0365 stat);
0366 if (stat & LOCKED_BLK)
0367 dev_info(dev, "%s: it's locked error = 0x%04x\n",
0368 __func__, stat);
0369
0370 return -EIO;
0371 }
0372
0373 return 0;
0374 }
0375
0376 static int s3c_onenand_command(struct mtd_info *mtd, int cmd, loff_t addr,
0377 size_t len)
0378 {
0379 struct onenand_chip *this = mtd->priv;
0380 unsigned int *m, *s;
0381 int fba, fpa, fsa = 0;
0382 unsigned int mem_addr, cmd_map_01, cmd_map_10;
0383 int i, mcount, scount;
0384 int index;
0385
0386 fba = (int) (addr >> this->erase_shift);
0387 fpa = (int) (addr >> this->page_shift);
0388 fpa &= this->page_mask;
0389
0390 mem_addr = onenand->mem_addr(fba, fpa, fsa);
0391 cmd_map_01 = CMD_MAP_01(onenand, mem_addr);
0392 cmd_map_10 = CMD_MAP_10(onenand, mem_addr);
0393
0394 switch (cmd) {
0395 case ONENAND_CMD_READ:
0396 case ONENAND_CMD_READOOB:
0397 case ONENAND_CMD_BUFFERRAM:
0398 ONENAND_SET_NEXT_BUFFERRAM(this);
0399 break;
0400 default:
0401 break;
0402 }
0403
0404 index = ONENAND_CURRENT_BUFFERRAM(this);
0405
0406
0407
0408
0409 m = onenand->page_buf;
0410 s = onenand->oob_buf;
0411
0412 if (index) {
0413 m += (this->writesize >> 2);
0414 s += (mtd->oobsize >> 2);
0415 }
0416
0417 mcount = mtd->writesize >> 2;
0418 scount = mtd->oobsize >> 2;
0419
0420 switch (cmd) {
0421 case ONENAND_CMD_READ:
0422
0423 for (i = 0; i < mcount; i++)
0424 *m++ = s3c_read_cmd(cmd_map_01);
0425 return 0;
0426
0427 case ONENAND_CMD_READOOB:
0428 s3c_write_reg(TSRF, TRANS_SPARE_OFFSET);
0429
0430 for (i = 0; i < mcount; i++)
0431 *m++ = s3c_read_cmd(cmd_map_01);
0432
0433
0434 for (i = 0; i < scount; i++)
0435 *s++ = s3c_read_cmd(cmd_map_01);
0436
0437 s3c_write_reg(0, TRANS_SPARE_OFFSET);
0438 return 0;
0439
0440 case ONENAND_CMD_PROG:
0441
0442 for (i = 0; i < mcount; i++)
0443 s3c_write_cmd(*m++, cmd_map_01);
0444 return 0;
0445
0446 case ONENAND_CMD_PROGOOB:
0447 s3c_write_reg(TSRF, TRANS_SPARE_OFFSET);
0448
0449
0450 for (i = 0; i < mcount; i++)
0451 s3c_write_cmd(0xffffffff, cmd_map_01);
0452
0453
0454 for (i = 0; i < scount; i++)
0455 s3c_write_cmd(*s++, cmd_map_01);
0456
0457 s3c_write_reg(0, TRANS_SPARE_OFFSET);
0458 return 0;
0459
0460 case ONENAND_CMD_UNLOCK_ALL:
0461 s3c_write_cmd(ONENAND_UNLOCK_ALL, cmd_map_10);
0462 return 0;
0463
0464 case ONENAND_CMD_ERASE:
0465 s3c_write_cmd(ONENAND_ERASE_START, cmd_map_10);
0466 return 0;
0467
0468 default:
0469 break;
0470 }
0471
0472 return 0;
0473 }
0474
0475 static unsigned char *s3c_get_bufferram(struct mtd_info *mtd, int area)
0476 {
0477 struct onenand_chip *this = mtd->priv;
0478 int index = ONENAND_CURRENT_BUFFERRAM(this);
0479 unsigned char *p;
0480
0481 if (area == ONENAND_DATARAM) {
0482 p = onenand->page_buf;
0483 if (index == 1)
0484 p += this->writesize;
0485 } else {
0486 p = onenand->oob_buf;
0487 if (index == 1)
0488 p += mtd->oobsize;
0489 }
0490
0491 return p;
0492 }
0493
0494 static int onenand_read_bufferram(struct mtd_info *mtd, int area,
0495 unsigned char *buffer, int offset,
0496 size_t count)
0497 {
0498 unsigned char *p;
0499
0500 p = s3c_get_bufferram(mtd, area);
0501 memcpy(buffer, p + offset, count);
0502 return 0;
0503 }
0504
0505 static int onenand_write_bufferram(struct mtd_info *mtd, int area,
0506 const unsigned char *buffer, int offset,
0507 size_t count)
0508 {
0509 unsigned char *p;
0510
0511 p = s3c_get_bufferram(mtd, area);
0512 memcpy(p + offset, buffer, count);
0513 return 0;
0514 }
0515
0516 static int (*s5pc110_dma_ops)(dma_addr_t dst, dma_addr_t src, size_t count, int direction);
0517
0518 static int s5pc110_dma_poll(dma_addr_t dst, dma_addr_t src, size_t count, int direction)
0519 {
0520 void __iomem *base = onenand->dma_addr;
0521 int status;
0522 unsigned long timeout;
0523
0524 writel(src, base + S5PC110_DMA_SRC_ADDR);
0525 writel(dst, base + S5PC110_DMA_DST_ADDR);
0526
0527 if (direction == S5PC110_DMA_DIR_READ) {
0528 writel(S5PC110_DMA_SRC_CFG_READ, base + S5PC110_DMA_SRC_CFG);
0529 writel(S5PC110_DMA_DST_CFG_READ, base + S5PC110_DMA_DST_CFG);
0530 } else {
0531 writel(S5PC110_DMA_SRC_CFG_WRITE, base + S5PC110_DMA_SRC_CFG);
0532 writel(S5PC110_DMA_DST_CFG_WRITE, base + S5PC110_DMA_DST_CFG);
0533 }
0534
0535 writel(count, base + S5PC110_DMA_TRANS_SIZE);
0536 writel(direction, base + S5PC110_DMA_TRANS_DIR);
0537
0538 writel(S5PC110_DMA_TRANS_CMD_TR, base + S5PC110_DMA_TRANS_CMD);
0539
0540
0541
0542
0543
0544
0545 timeout = jiffies + msecs_to_jiffies(20);
0546
0547 do {
0548 status = readl(base + S5PC110_DMA_TRANS_STATUS);
0549 if (status & S5PC110_DMA_TRANS_STATUS_TE) {
0550 writel(S5PC110_DMA_TRANS_CMD_TEC,
0551 base + S5PC110_DMA_TRANS_CMD);
0552 return -EIO;
0553 }
0554 } while (!(status & S5PC110_DMA_TRANS_STATUS_TD) &&
0555 time_before(jiffies, timeout));
0556
0557 writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD);
0558
0559 return 0;
0560 }
0561
0562 static irqreturn_t s5pc110_onenand_irq(int irq, void *data)
0563 {
0564 void __iomem *base = onenand->dma_addr;
0565 int status, cmd = 0;
0566
0567 status = readl(base + S5PC110_INTC_DMA_STATUS);
0568
0569 if (likely(status & S5PC110_INTC_DMA_TD))
0570 cmd = S5PC110_DMA_TRANS_CMD_TDC;
0571
0572 if (unlikely(status & S5PC110_INTC_DMA_TE))
0573 cmd = S5PC110_DMA_TRANS_CMD_TEC;
0574
0575 writel(cmd, base + S5PC110_DMA_TRANS_CMD);
0576 writel(status, base + S5PC110_INTC_DMA_CLR);
0577
0578 if (!onenand->complete.done)
0579 complete(&onenand->complete);
0580
0581 return IRQ_HANDLED;
0582 }
0583
0584 static int s5pc110_dma_irq(dma_addr_t dst, dma_addr_t src, size_t count, int direction)
0585 {
0586 void __iomem *base = onenand->dma_addr;
0587 int status;
0588
0589 status = readl(base + S5PC110_INTC_DMA_MASK);
0590 if (status) {
0591 status &= ~(S5PC110_INTC_DMA_TD | S5PC110_INTC_DMA_TE);
0592 writel(status, base + S5PC110_INTC_DMA_MASK);
0593 }
0594
0595 writel(src, base + S5PC110_DMA_SRC_ADDR);
0596 writel(dst, base + S5PC110_DMA_DST_ADDR);
0597
0598 if (direction == S5PC110_DMA_DIR_READ) {
0599 writel(S5PC110_DMA_SRC_CFG_READ, base + S5PC110_DMA_SRC_CFG);
0600 writel(S5PC110_DMA_DST_CFG_READ, base + S5PC110_DMA_DST_CFG);
0601 } else {
0602 writel(S5PC110_DMA_SRC_CFG_WRITE, base + S5PC110_DMA_SRC_CFG);
0603 writel(S5PC110_DMA_DST_CFG_WRITE, base + S5PC110_DMA_DST_CFG);
0604 }
0605
0606 writel(count, base + S5PC110_DMA_TRANS_SIZE);
0607 writel(direction, base + S5PC110_DMA_TRANS_DIR);
0608
0609 writel(S5PC110_DMA_TRANS_CMD_TR, base + S5PC110_DMA_TRANS_CMD);
0610
0611 wait_for_completion_timeout(&onenand->complete, msecs_to_jiffies(20));
0612
0613 return 0;
0614 }
0615
0616 static int s5pc110_read_bufferram(struct mtd_info *mtd, int area,
0617 unsigned char *buffer, int offset, size_t count)
0618 {
0619 struct onenand_chip *this = mtd->priv;
0620 void __iomem *p;
0621 void *buf = (void *) buffer;
0622 dma_addr_t dma_src, dma_dst;
0623 int err, ofs, page_dma = 0;
0624 struct device *dev = &onenand->pdev->dev;
0625
0626 p = this->base + area;
0627 if (ONENAND_CURRENT_BUFFERRAM(this)) {
0628 if (area == ONENAND_DATARAM)
0629 p += this->writesize;
0630 else
0631 p += mtd->oobsize;
0632 }
0633
0634 if (offset & 3 || (size_t) buf & 3 ||
0635 !onenand->dma_addr || count != mtd->writesize)
0636 goto normal;
0637
0638
0639 if (buf >= high_memory) {
0640 struct page *page;
0641
0642 if (((size_t) buf & PAGE_MASK) !=
0643 ((size_t) (buf + count - 1) & PAGE_MASK))
0644 goto normal;
0645 page = vmalloc_to_page(buf);
0646 if (!page)
0647 goto normal;
0648
0649
0650 ofs = ((size_t) buf & ~PAGE_MASK);
0651 page_dma = 1;
0652
0653
0654 dma_src = onenand->phys_base + (p - this->base);
0655 dma_dst = dma_map_page(dev, page, ofs, count, DMA_FROM_DEVICE);
0656 } else {
0657
0658 dma_src = onenand->phys_base + (p - this->base);
0659 dma_dst = dma_map_single(dev, buf, count, DMA_FROM_DEVICE);
0660 }
0661 if (dma_mapping_error(dev, dma_dst)) {
0662 dev_err(dev, "Couldn't map a %zu byte buffer for DMA\n", count);
0663 goto normal;
0664 }
0665 err = s5pc110_dma_ops(dma_dst, dma_src,
0666 count, S5PC110_DMA_DIR_READ);
0667
0668 if (page_dma)
0669 dma_unmap_page(dev, dma_dst, count, DMA_FROM_DEVICE);
0670 else
0671 dma_unmap_single(dev, dma_dst, count, DMA_FROM_DEVICE);
0672
0673 if (!err)
0674 return 0;
0675
0676 normal:
0677 if (count != mtd->writesize) {
0678
0679 memcpy_fromio(this->page_buf, p, mtd->writesize);
0680 memcpy(buffer, this->page_buf + offset, count);
0681 } else {
0682 memcpy_fromio(buffer, p, count);
0683 }
0684
0685 return 0;
0686 }
0687
0688 static int s5pc110_chip_probe(struct mtd_info *mtd)
0689 {
0690
0691 return 0;
0692 }
0693
0694 static int s3c_onenand_bbt_wait(struct mtd_info *mtd, int state)
0695 {
0696 unsigned int flags = INT_ACT | LOAD_CMP;
0697 unsigned int stat;
0698 unsigned long timeout;
0699
0700
0701 timeout = jiffies + msecs_to_jiffies(20);
0702 while (time_before(jiffies, timeout)) {
0703 stat = s3c_read_reg(INT_ERR_STAT_OFFSET);
0704 if (stat & flags)
0705 break;
0706 }
0707
0708 stat = s3c_read_reg(INT_ERR_STAT_OFFSET);
0709 s3c_write_reg(stat, INT_ERR_ACK_OFFSET);
0710
0711 if (stat & LD_FAIL_ECC_ERR) {
0712 s3c_onenand_reset();
0713 return ONENAND_BBT_READ_ERROR;
0714 }
0715
0716 if (stat & LOAD_CMP) {
0717 int ecc = s3c_read_reg(ECC_ERR_STAT_OFFSET);
0718 if (ecc & ONENAND_ECC_4BIT_UNCORRECTABLE) {
0719 s3c_onenand_reset();
0720 return ONENAND_BBT_READ_ERROR;
0721 }
0722 }
0723
0724 return 0;
0725 }
0726
0727 static void s3c_onenand_check_lock_status(struct mtd_info *mtd)
0728 {
0729 struct onenand_chip *this = mtd->priv;
0730 struct device *dev = &onenand->pdev->dev;
0731 unsigned int block, end;
0732
0733 end = this->chipsize >> this->erase_shift;
0734
0735 for (block = 0; block < end; block++) {
0736 unsigned int mem_addr = onenand->mem_addr(block, 0, 0);
0737 s3c_read_cmd(CMD_MAP_01(onenand, mem_addr));
0738
0739 if (s3c_read_reg(INT_ERR_STAT_OFFSET) & LOCKED_BLK) {
0740 dev_err(dev, "block %d is write-protected!\n", block);
0741 s3c_write_reg(LOCKED_BLK, INT_ERR_ACK_OFFSET);
0742 }
0743 }
0744 }
0745
0746 static void s3c_onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs,
0747 size_t len, int cmd)
0748 {
0749 struct onenand_chip *this = mtd->priv;
0750 int start, end, start_mem_addr, end_mem_addr;
0751
0752 start = ofs >> this->erase_shift;
0753 start_mem_addr = onenand->mem_addr(start, 0, 0);
0754 end = start + (len >> this->erase_shift) - 1;
0755 end_mem_addr = onenand->mem_addr(end, 0, 0);
0756
0757 if (cmd == ONENAND_CMD_LOCK) {
0758 s3c_write_cmd(ONENAND_LOCK_START, CMD_MAP_10(onenand,
0759 start_mem_addr));
0760 s3c_write_cmd(ONENAND_LOCK_END, CMD_MAP_10(onenand,
0761 end_mem_addr));
0762 } else {
0763 s3c_write_cmd(ONENAND_UNLOCK_START, CMD_MAP_10(onenand,
0764 start_mem_addr));
0765 s3c_write_cmd(ONENAND_UNLOCK_END, CMD_MAP_10(onenand,
0766 end_mem_addr));
0767 }
0768
0769 this->wait(mtd, FL_LOCKING);
0770 }
0771
0772 static void s3c_unlock_all(struct mtd_info *mtd)
0773 {
0774 struct onenand_chip *this = mtd->priv;
0775 loff_t ofs = 0;
0776 size_t len = this->chipsize;
0777
0778 if (this->options & ONENAND_HAS_UNLOCK_ALL) {
0779
0780 this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0);
0781
0782
0783 this->wait(mtd, FL_LOCKING);
0784
0785
0786 if (!ONENAND_IS_DDP(this)) {
0787 s3c_onenand_check_lock_status(mtd);
0788 return;
0789 }
0790
0791
0792 ofs = this->chipsize >> 1;
0793 len = this->chipsize >> 1;
0794 }
0795
0796 s3c_onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
0797
0798 s3c_onenand_check_lock_status(mtd);
0799 }
0800
0801 static void s3c_onenand_setup(struct mtd_info *mtd)
0802 {
0803 struct onenand_chip *this = mtd->priv;
0804
0805 onenand->mtd = mtd;
0806
0807 if (onenand->type == TYPE_S3C6400) {
0808 onenand->mem_addr = s3c6400_mem_addr;
0809 onenand->cmd_map = s3c64xx_cmd_map;
0810 } else if (onenand->type == TYPE_S3C6410) {
0811 onenand->mem_addr = s3c6410_mem_addr;
0812 onenand->cmd_map = s3c64xx_cmd_map;
0813 } else if (onenand->type == TYPE_S5PC110) {
0814
0815 this->read_bufferram = s5pc110_read_bufferram;
0816 this->chip_probe = s5pc110_chip_probe;
0817 return;
0818 } else {
0819 BUG();
0820 }
0821
0822 this->read_word = s3c_onenand_readw;
0823 this->write_word = s3c_onenand_writew;
0824
0825 this->wait = s3c_onenand_wait;
0826 this->bbt_wait = s3c_onenand_bbt_wait;
0827 this->unlock_all = s3c_unlock_all;
0828 this->command = s3c_onenand_command;
0829
0830 this->read_bufferram = onenand_read_bufferram;
0831 this->write_bufferram = onenand_write_bufferram;
0832 }
0833
0834 static int s3c_onenand_probe(struct platform_device *pdev)
0835 {
0836 struct onenand_platform_data *pdata;
0837 struct onenand_chip *this;
0838 struct mtd_info *mtd;
0839 struct resource *r;
0840 int size, err;
0841
0842 pdata = dev_get_platdata(&pdev->dev);
0843
0844
0845 size = sizeof(struct mtd_info) + sizeof(struct onenand_chip);
0846 mtd = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
0847 if (!mtd)
0848 return -ENOMEM;
0849
0850 onenand = devm_kzalloc(&pdev->dev, sizeof(struct s3c_onenand),
0851 GFP_KERNEL);
0852 if (!onenand)
0853 return -ENOMEM;
0854
0855 this = (struct onenand_chip *) &mtd[1];
0856 mtd->priv = this;
0857 mtd->dev.parent = &pdev->dev;
0858 onenand->pdev = pdev;
0859 onenand->type = platform_get_device_id(pdev)->driver_data;
0860
0861 s3c_onenand_setup(mtd);
0862
0863 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0864 onenand->base = devm_ioremap_resource(&pdev->dev, r);
0865 if (IS_ERR(onenand->base))
0866 return PTR_ERR(onenand->base);
0867
0868 onenand->phys_base = r->start;
0869
0870
0871 this->base = onenand->base;
0872
0873
0874 this->options |= ONENAND_SKIP_UNLOCK_CHECK;
0875
0876 if (onenand->type != TYPE_S5PC110) {
0877 r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
0878 onenand->ahb_addr = devm_ioremap_resource(&pdev->dev, r);
0879 if (IS_ERR(onenand->ahb_addr))
0880 return PTR_ERR(onenand->ahb_addr);
0881
0882
0883 onenand->page_buf = devm_kzalloc(&pdev->dev, SZ_4K,
0884 GFP_KERNEL);
0885 if (!onenand->page_buf)
0886 return -ENOMEM;
0887
0888
0889 onenand->oob_buf = devm_kzalloc(&pdev->dev, 128, GFP_KERNEL);
0890 if (!onenand->oob_buf)
0891 return -ENOMEM;
0892
0893
0894 mtd->subpage_sft = 0;
0895 this->subpagesize = mtd->writesize;
0896
0897 } else {
0898 r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
0899 onenand->dma_addr = devm_ioremap_resource(&pdev->dev, r);
0900 if (IS_ERR(onenand->dma_addr))
0901 return PTR_ERR(onenand->dma_addr);
0902
0903 s5pc110_dma_ops = s5pc110_dma_poll;
0904
0905 r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
0906 if (r) {
0907 init_completion(&onenand->complete);
0908 s5pc110_dma_ops = s5pc110_dma_irq;
0909 err = devm_request_irq(&pdev->dev, r->start,
0910 s5pc110_onenand_irq,
0911 IRQF_SHARED, "onenand",
0912 &onenand);
0913 if (err) {
0914 dev_err(&pdev->dev, "failed to get irq\n");
0915 return err;
0916 }
0917 }
0918 }
0919
0920 err = onenand_scan(mtd, 1);
0921 if (err)
0922 return err;
0923
0924 if (onenand->type != TYPE_S5PC110) {
0925
0926 mtd->subpage_sft = 0;
0927 this->subpagesize = mtd->writesize;
0928 }
0929
0930 if (s3c_read_reg(MEM_CFG_OFFSET) & ONENAND_SYS_CFG1_SYNC_READ)
0931 dev_info(&onenand->pdev->dev, "OneNAND Sync. Burst Read enabled\n");
0932
0933 err = mtd_device_register(mtd, pdata ? pdata->parts : NULL,
0934 pdata ? pdata->nr_parts : 0);
0935 if (err) {
0936 dev_err(&pdev->dev, "failed to parse partitions and register the MTD device\n");
0937 onenand_release(mtd);
0938 return err;
0939 }
0940
0941 platform_set_drvdata(pdev, mtd);
0942
0943 return 0;
0944 }
0945
0946 static int s3c_onenand_remove(struct platform_device *pdev)
0947 {
0948 struct mtd_info *mtd = platform_get_drvdata(pdev);
0949
0950 onenand_release(mtd);
0951
0952 return 0;
0953 }
0954
0955 static int s3c_pm_ops_suspend(struct device *dev)
0956 {
0957 struct mtd_info *mtd = dev_get_drvdata(dev);
0958 struct onenand_chip *this = mtd->priv;
0959
0960 this->wait(mtd, FL_PM_SUSPENDED);
0961 return 0;
0962 }
0963
0964 static int s3c_pm_ops_resume(struct device *dev)
0965 {
0966 struct mtd_info *mtd = dev_get_drvdata(dev);
0967 struct onenand_chip *this = mtd->priv;
0968
0969 this->unlock_all(mtd);
0970 return 0;
0971 }
0972
0973 static const struct dev_pm_ops s3c_pm_ops = {
0974 .suspend = s3c_pm_ops_suspend,
0975 .resume = s3c_pm_ops_resume,
0976 };
0977
0978 static const struct platform_device_id s3c_onenand_driver_ids[] = {
0979 {
0980 .name = "s3c6400-onenand",
0981 .driver_data = TYPE_S3C6400,
0982 }, {
0983 .name = "s3c6410-onenand",
0984 .driver_data = TYPE_S3C6410,
0985 }, {
0986 .name = "s5pc110-onenand",
0987 .driver_data = TYPE_S5PC110,
0988 }, { },
0989 };
0990 MODULE_DEVICE_TABLE(platform, s3c_onenand_driver_ids);
0991
0992 static struct platform_driver s3c_onenand_driver = {
0993 .driver = {
0994 .name = "samsung-onenand",
0995 .pm = &s3c_pm_ops,
0996 },
0997 .id_table = s3c_onenand_driver_ids,
0998 .probe = s3c_onenand_probe,
0999 .remove = s3c_onenand_remove,
1000 };
1001
1002 module_platform_driver(s3c_onenand_driver);
1003
1004 MODULE_LICENSE("GPL");
1005 MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>");
1006 MODULE_DESCRIPTION("Samsung OneNAND controller support");