Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Samsung S3C64XX/S5PC1XX OneNAND driver
0004  *
0005  *  Copyright © 2008-2010 Samsung Electronics
0006  *  Kyungmin Park <kyungmin.park@samsung.com>
0007  *  Marek Szyprowski <m.szyprowski@samsung.com>
0008  *
0009  * Implementation:
0010  *  S3C64XX: emulate the pseudo BufferRAM
0011  *  S5PC110: use DMA
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 /* S5PC110 specific definitions */
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     /* Clear interrupt */
0211     s3c_write_reg(0x0, INT_ERR_ACK_OFFSET);
0212     /* Clear the ECC status */
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     /* It's used for probing time */
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     /* Used at unlock all status */
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     /* BootRAM access control */
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     /* It's used for probing time */
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     /* Lock/lock-tight/unlock/unlock_all */
0284     case ONENAND_REG_START_BLOCK_ADDRESS:
0285         return;
0286 
0287     default:
0288         break;
0289     }
0290 
0291     /* BootRAM access control */
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     /* The 20 msec is enough */
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     /* To get correct interrupt status in timeout case */
0345     stat = s3c_read_reg(INT_ERR_STAT_OFFSET);
0346     s3c_write_reg(stat, INT_ERR_ACK_OFFSET);
0347 
0348     /*
0349      * In the Spec. it checks the controller status first
0350      * However if you get the correct information in case of
0351      * power off recovery (POR) test, it should read ECC status first
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      * Emulate Two BufferRAMs and access with 4 bytes pointer
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         /* Main */
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         /* Main */
0430         for (i = 0; i < mcount; i++)
0431             *m++ = s3c_read_cmd(cmd_map_01);
0432 
0433         /* Spare */
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         /* Main */
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         /* Main - dummy write */
0450         for (i = 0; i < mcount; i++)
0451             s3c_write_cmd(0xffffffff, cmd_map_01);
0452 
0453         /* Spare */
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      * There's no exact timeout values at Spec.
0542      * In real case it takes under 1 msec.
0543      * So 20 msecs are enough.
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     /* Handle vmalloc address */
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         /* Page offset */
0650         ofs = ((size_t) buf & ~PAGE_MASK);
0651         page_dma = 1;
0652 
0653         /* DMA routine */
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         /* DMA routine */
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         /* Copy the bufferram to memory to prevent unaligned access */
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     /* Now just return 0 */
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     /* The 20 msec is enough */
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     /* To get correct interrupt status in timeout case */
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         /* Write unlock command */
0780         this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0);
0781 
0782         /* No need to check return value */
0783         this->wait(mtd, FL_LOCKING);
0784 
0785         /* Workaround for all block unlock in DDP */
0786         if (!ONENAND_IS_DDP(this)) {
0787             s3c_onenand_check_lock_status(mtd);
0788             return;
0789         }
0790 
0791         /* All blocks on another chip */
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         /* Use generic onenand functions */
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     /* No need to check pdata. the platform data is optional */
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     /* Set onenand_chip also */
0871     this->base = onenand->base;
0872 
0873     /* Use runtime badblock check */
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         /* Allocate 4KiB BufferRAM */
0883         onenand->page_buf = devm_kzalloc(&pdev->dev, SZ_4K,
0884                          GFP_KERNEL);
0885         if (!onenand->page_buf)
0886             return -ENOMEM;
0887 
0888         /* Allocate 128 SpareRAM */
0889         onenand->oob_buf = devm_kzalloc(&pdev->dev, 128, GFP_KERNEL);
0890         if (!onenand->oob_buf)
0891             return -ENOMEM;
0892 
0893         /* S3C doesn't handle subpage write */
0894         mtd->subpage_sft = 0;
0895         this->subpagesize = mtd->writesize;
0896 
0897     } else { /* S5PC110 */
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         /* Interrupt support */
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         /* S3C doesn't handle subpage write */
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");