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