diff options
author | Wolfgang Denk <wd@denx.de> | 2012-04-09 17:07:50 +0200 |
---|---|---|
committer | Wolfgang Denk <wd@denx.de> | 2012-04-09 17:07:50 +0200 |
commit | 691288e14dc5cccc9ff1219765554981f73a7c14 (patch) | |
tree | ac69f4439cb87dd0234f89ca112789f744604256 | |
parent | 5c877b1ae0a4219ed6bd8d32cf3f7106b81ecb3b (diff) | |
parent | a08a649d7034333a3f47d11fa76f98abac70a256 (diff) |
Merge branch 'master' of git://git.denx.de/u-boot-onenand
* 'master' of git://git.denx.de/u-boot-onenand:
onenand: samsung: Enable OneNAND support at Samsung's Exynos4210
onenand: Replace ONENAND_IS_MLC() with ONENAND_HAS_4KB()
onenand:samsung OneNAND chip probe functions added for GONI and Exynos4210
onenand:samsung Target dependent OneNAND chip probe function
-rw-r--r-- | board/samsung/goni/onenand.c | 1 | ||||
-rw-r--r-- | board/samsung/universal_c210/onenand.c | 2 | ||||
-rw-r--r-- | drivers/mtd/onenand/onenand_base.c | 88 | ||||
-rw-r--r-- | drivers/mtd/onenand/samsung.c | 10 | ||||
-rw-r--r-- | include/configs/s5pc210_universal.h | 1 | ||||
-rw-r--r-- | include/linux/mtd/onenand.h | 5 | ||||
-rw-r--r-- | include/linux/mtd/samsung_onenand.h | 2 |
7 files changed, 86 insertions, 23 deletions
diff --git a/board/samsung/goni/onenand.c b/board/samsung/goni/onenand.c index 8d3769b916..9dd80fa678 100644 --- a/board/samsung/goni/onenand.c +++ b/board/samsung/goni/onenand.c @@ -33,4 +33,5 @@ void onenand_board_init(struct mtd_info *mtd) this->base = (void *)CONFIG_SYS_ONENAND_BASE; this->options |= ONENAND_RUNTIME_BADBLOCK_CHECK; + this->chip_probe = s5pc110_chip_probe; } diff --git a/board/samsung/universal_c210/onenand.c b/board/samsung/universal_c210/onenand.c index 20e1dc54eb..5b92308653 100644 --- a/board/samsung/universal_c210/onenand.c +++ b/board/samsung/universal_c210/onenand.c @@ -24,6 +24,7 @@ #include <common.h> #include <linux/mtd/mtd.h> #include <linux/mtd/onenand.h> +#include <linux/mtd/samsung_onenand.h> void onenand_board_init(struct mtd_info *mtd) { @@ -31,4 +32,5 @@ void onenand_board_init(struct mtd_info *mtd) this->base = (void *)CONFIG_SYS_ONENAND_BASE; this->options |= ONENAND_RUNTIME_BADBLOCK_CHECK; + this->chip_probe = s5pc210_chip_probe; } diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 06f187fdd7..480ae7a207 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -367,7 +367,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); - if (ONENAND_IS_MLC(this)) + if (ONENAND_IS_4KB_PAGE(this)) ONENAND_SET_BUFFERRAM0(this); else /* Switch to the next data buffer */ @@ -395,7 +395,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, case FLEXONENAND_CMD_RECOVER_LSB: case ONENAND_CMD_READ: case ONENAND_CMD_READOOB: - if (ONENAND_IS_MLC(this)) + if (ONENAND_IS_4KB_PAGE(this)) dataram = ONENAND_SET_BUFFERRAM0(this); else dataram = ONENAND_SET_NEXT_BUFFERRAM(this); @@ -893,7 +893,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, while (!ret) { /* If there is more to load then start next load */ from += thislen; - if (!ONENAND_IS_MLC(this) && read + thislen < len) { + if (!ONENAND_IS_4KB_PAGE(this) && read + thislen < len) { this->main_buf = buf + thislen; this->command(mtd, ONENAND_CMD_READ, from, writesize); /* @@ -927,7 +927,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, oobcolumn = 0; } - if (ONENAND_IS_MLC(this) && (read + thislen < len)) { + if (ONENAND_IS_4KB_PAGE(this) && (read + thislen < len)) { this->command(mtd, ONENAND_CMD_READ, from, writesize); ret = this->wait(mtd, FL_READING); if (unlikely(ret)) @@ -944,13 +944,13 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, /* Set up for next read from bufferRAM */ if (unlikely(boundary)) this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2); - if (!ONENAND_IS_MLC(this)) + if (!ONENAND_IS_4KB_PAGE(this)) ONENAND_SET_NEXT_BUFFERRAM(this); buf += thislen; thislen = min_t(int, writesize, len - read); column = 0; - if (!ONENAND_IS_MLC(this)) { + if (!ONENAND_IS_4KB_PAGE(this)) { /* Now wait for load */ ret = this->wait(mtd, FL_READING); onenand_update_bufferram(mtd, from, !ret); @@ -1024,7 +1024,8 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from, stats = mtd->ecc_stats; - readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB; + readcmd = ONENAND_IS_4KB_PAGE(this) ? + ONENAND_CMD_READ : ONENAND_CMD_READOOB; while (read < len) { thislen = oobsize - column; @@ -1202,7 +1203,8 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from, MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_bbt_read_oob: from = 0x%08x, len = %zi\n", (unsigned int) from, len); - readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB; + readcmd = ONENAND_IS_4KB_PAGE(this) ? + ONENAND_CMD_READ : ONENAND_CMD_READOOB; /* Initialize return value */ ops->oobretlen = 0; @@ -1271,7 +1273,8 @@ static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to u_char *oob_buf = this->oob_buf; int status, i, readcmd; - readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB; + readcmd = ONENAND_IS_4KB_PAGE(this) ? + ONENAND_CMD_READ : ONENAND_CMD_READOOB; this->command(mtd, readcmd, to, mtd->oobsize); onenand_update_bufferram(mtd, to, 0); @@ -1560,7 +1563,8 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to, oobbuf = this->oob_buf; - oobcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_PROG : ONENAND_CMD_PROGOOB; + oobcmd = ONENAND_IS_4KB_PAGE(this) ? + ONENAND_CMD_PROG : ONENAND_CMD_PROGOOB; /* Loop until all data write */ while (written < len) { @@ -1577,7 +1581,7 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to, memcpy(oobbuf + column, buf, thislen); this->write_bufferram(mtd, 0, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize); - if (ONENAND_IS_MLC(this)) { + if (ONENAND_IS_4KB_PAGE(this)) { /* Set main area of DataRAM to 0xff*/ memset(this->page_buf, 0xff, mtd->writesize); this->write_bufferram(mtd, 0, ONENAND_DATARAM, @@ -2140,7 +2144,10 @@ static void onenand_check_features(struct mtd_info *mtd) /* Lock scheme */ switch (density) { case ONENAND_DEVICE_DENSITY_4Gb: - this->options |= ONENAND_HAS_2PLANE; + if (ONENAND_IS_DDP(this)) + this->options |= ONENAND_HAS_2PLANE; + else + this->options |= ONENAND_HAS_4KB_PAGE; case ONENAND_DEVICE_DENSITY_2Gb: /* 2Gb DDP don't have 2 plane */ @@ -2162,6 +2169,9 @@ static void onenand_check_features(struct mtd_info *mtd) } if (ONENAND_IS_MLC(this)) + this->options |= ONENAND_HAS_4KB_PAGE; + + if (ONENAND_IS_4KB_PAGE(this)) this->options &= ~ONENAND_HAS_2PLANE; if (FLEXONENAND(this)) { @@ -2175,6 +2185,9 @@ static void onenand_check_features(struct mtd_info *mtd) printk(KERN_DEBUG "Chip support all block unlock\n"); if (this->options & ONENAND_HAS_2PLANE) printk(KERN_DEBUG "Chip has 2 plane\n"); + if (this->options & ONENAND_HAS_4KB_PAGE) + printk(KERN_DEBUG "Chip has 4KiB pagesize\n"); + } /** @@ -2501,23 +2514,24 @@ out: } /** - * onenand_probe - [OneNAND Interface] Probe the OneNAND device + * onenand_chip_probe - [OneNAND Interface] Probe the OneNAND chip * @param mtd MTD device structure * * OneNAND detection method: * Compare the the values from command with ones from register */ -static int onenand_probe(struct mtd_info *mtd) +static int onenand_chip_probe(struct mtd_info *mtd) { struct onenand_chip *this = mtd->priv; - int bram_maf_id, bram_dev_id, maf_id, dev_id, ver_id; - int density; + int bram_maf_id, bram_dev_id, maf_id, dev_id; int syscfg; /* Save system configuration 1 */ syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1); + /* Clear Sync. Burst Read mode to read BootRAM */ - this->write_word((syscfg & ~ONENAND_SYS_CFG1_SYNC_READ), this->base + ONENAND_REG_SYS_CFG1); + this->write_word((syscfg & ~ONENAND_SYS_CFG1_SYNC_READ), + this->base + ONENAND_REG_SYS_CFG1); /* Send the command for reading device ID from BootRAM */ this->write_word(ONENAND_CMD_READID, this->base + ONENAND_BOOTRAM); @@ -2542,18 +2556,46 @@ static int onenand_probe(struct mtd_info *mtd) /* Read manufacturer and device IDs from Register */ maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); - ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID); - this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY); /* Check OneNAND device */ if (maf_id != bram_maf_id || dev_id != bram_dev_id) return -ENXIO; + return 0; +} + +/** + * onenand_probe - [OneNAND Interface] Probe the OneNAND device + * @param mtd MTD device structure + * + * OneNAND detection method: + * Compare the the values from command with ones from register + */ +int onenand_probe(struct mtd_info *mtd) +{ + struct onenand_chip *this = mtd->priv; + int maf_id, dev_id, ver_id; + int density; + int ret; + + ret = this->chip_probe(mtd); + if (ret) + return ret; + + /* Read manufacturer and device IDs from Register */ + maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); + dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); + ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID); + this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY); + /* Flash device information */ mtd->name = onenand_print_device_info(dev_id, ver_id); this->device_id = dev_id; this->version_id = ver_id; + /* Check OneNAND features */ + onenand_check_features(mtd); + density = onenand_get_density(dev_id); if (FLEXONENAND(this)) { this->dies = ONENAND_IS_DDP(this) ? 2 : 1; @@ -2576,7 +2618,7 @@ static int onenand_probe(struct mtd_info *mtd) mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE); /* We use the full BufferRAM */ - if (ONENAND_IS_MLC(this)) + if (ONENAND_IS_4KB_PAGE(this)) mtd->writesize <<= 1; mtd->oobsize = mtd->writesize >> 5; @@ -2607,9 +2649,6 @@ static int onenand_probe(struct mtd_info *mtd) else mtd->size = this->chipsize; - /* Check OneNAND features */ - onenand_check_features(mtd); - mtd->flags = MTD_CAP_NANDFLASH; mtd->erase = onenand_erase; mtd->read = onenand_read; @@ -2655,6 +2694,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) if (!this->write_bufferram) this->write_bufferram = onenand_write_bufferram; + if (!this->chip_probe) + this->chip_probe = onenand_chip_probe; + if (!this->block_markbad) this->block_markbad = onenand_default_block_markbad; if (!this->scan_bbt) diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index ff59064599..c9d33ec825 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c @@ -589,6 +589,16 @@ static void s3c_set_width_regs(struct onenand_chip *this) } #endif +int s5pc110_chip_probe(struct mtd_info *mtd) +{ + return 0; +} + +int s5pc210_chip_probe(struct mtd_info *mtd) +{ + return 0; +} + void s3c_onenand_init(struct mtd_info *mtd) { struct onenand_chip *this = mtd->priv; diff --git a/include/configs/s5pc210_universal.h b/include/configs/s5pc210_universal.h index 8286680f26..13012756ab 100644 --- a/include/configs/s5pc210_universal.h +++ b/include/configs/s5pc210_universal.h @@ -233,6 +233,7 @@ #define CONFIG_SYS_MONITOR_LEN (256 << 10) /* Reserve 2 sectors */ #define CONFIG_USE_ONENAND_BOARD_INIT +#define CONFIG_SAMSUNG_ONENAND #define CONFIG_SYS_ONENAND_BASE 0x0C000000 #define CONFIG_ENV_IS_IN_MMC 1 diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index 5465562639..bb4a4a6b28 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -101,6 +101,7 @@ struct onenand_chip { size_t count); unsigned short (*read_word) (void __iomem *addr); void (*write_word) (unsigned short value, void __iomem *addr); + int (*chip_probe)(struct mtd_info *mtd); void (*mmcontrol) (struct mtd_info *mtd, int sync_read); int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); int (*scan_bbt)(struct mtd_info *mtd); @@ -139,6 +140,9 @@ struct onenand_chip { #define ONENAND_IS_DDP(this) \ (this->device_id & ONENAND_DEVICE_IS_DDP) +#define ONENAND_IS_4KB_PAGE(this) \ + (this->options & ONENAND_HAS_4KB_PAGE) + #define ONENAND_IS_2PLANE(this) (0) /* @@ -147,6 +151,7 @@ struct onenand_chip { #define ONENAND_HAS_CONT_LOCK (0x0001) #define ONENAND_HAS_UNLOCK_ALL (0x0002) #define ONENAND_HAS_2PLANE (0x0004) +#define ONENAND_HAS_4KB_PAGE (0x0008) #define ONENAND_RUNTIME_BADBLOCK_CHECK (0x0200) #define ONENAND_PAGEBUF_ALLOC (0x1000) #define ONENAND_OOBBUF_ALLOC (0x2000) diff --git a/include/linux/mtd/samsung_onenand.h b/include/linux/mtd/samsung_onenand.h index 021fa27f7d..ddb29bbee7 100644 --- a/include/linux/mtd/samsung_onenand.h +++ b/include/linux/mtd/samsung_onenand.h @@ -127,5 +127,7 @@ struct samsung_onenand { /* common initialize function */ extern void s3c_onenand_init(struct mtd_info *); +extern int s5pc110_chip_probe(struct mtd_info *); +extern int s5pc210_chip_probe(struct mtd_info *); #endif |