diff options
| author | David Woodhouse <dwmw2@infradead.org> | 2008-02-03 02:31:04 -0500 |
|---|---|---|
| committer | David Woodhouse <dwmw2@infradead.org> | 2008-02-03 02:31:04 -0500 |
| commit | b7e23d913aafc93fc5f119e1be17620073cc3811 (patch) | |
| tree | 0f76a32d5b22cf12f6f822cf0c04481f3bb227fb | |
| parent | c1f3ee120bb61045b1c0a3ead620d1d65af47130 (diff) | |
| parent | 69d79186dc48ca22a0ce69511bef8ef6c2465ada (diff) | |
Merge git://git.infradead.org/~kmpark/onenand-mtd-2.6
| -rw-r--r-- | drivers/mtd/onenand/onenand_base.c | 59 | ||||
| -rw-r--r-- | include/linux/mtd/onenand_regs.h | 1 |
2 files changed, 29 insertions, 31 deletions
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index ed9f9c061ac5..b281b116aaeb 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c | |||
| @@ -170,6 +170,18 @@ static int onenand_buffer_address(int dataram1, int sectors, int count) | |||
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | /** | 172 | /** |
| 173 | * onenand_get_density - [DEFAULT] Get OneNAND density | ||
| 174 | * @param dev_id OneNAND device ID | ||
| 175 | * | ||
| 176 | * Get OneNAND density from device ID | ||
| 177 | */ | ||
| 178 | static inline int onenand_get_density(int dev_id) | ||
| 179 | { | ||
| 180 | int density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT; | ||
| 181 | return (density & ONENAND_DEVICE_DENSITY_MASK); | ||
| 182 | } | ||
| 183 | |||
| 184 | /** | ||
| 173 | * onenand_command - [DEFAULT] Send command to OneNAND device | 185 | * onenand_command - [DEFAULT] Send command to OneNAND device |
| 174 | * @param mtd MTD device structure | 186 | * @param mtd MTD device structure |
| 175 | * @param cmd the command to be sent | 187 | * @param cmd the command to be sent |
| @@ -182,8 +194,7 @@ static int onenand_buffer_address(int dataram1, int sectors, int count) | |||
| 182 | static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t len) | 194 | static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t len) |
| 183 | { | 195 | { |
| 184 | struct onenand_chip *this = mtd->priv; | 196 | struct onenand_chip *this = mtd->priv; |
| 185 | int value, readcmd = 0, block_cmd = 0; | 197 | int value, block, page; |
| 186 | int block, page; | ||
| 187 | 198 | ||
| 188 | /* Address translation */ | 199 | /* Address translation */ |
| 189 | switch (cmd) { | 200 | switch (cmd) { |
| @@ -198,7 +209,6 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le | |||
| 198 | case ONENAND_CMD_ERASE: | 209 | case ONENAND_CMD_ERASE: |
| 199 | case ONENAND_CMD_BUFFERRAM: | 210 | case ONENAND_CMD_BUFFERRAM: |
| 200 | case ONENAND_CMD_OTP_ACCESS: | 211 | case ONENAND_CMD_OTP_ACCESS: |
| 201 | block_cmd = 1; | ||
| 202 | block = (int) (addr >> this->erase_shift); | 212 | block = (int) (addr >> this->erase_shift); |
| 203 | page = -1; | 213 | page = -1; |
| 204 | break; | 214 | break; |
| @@ -240,11 +250,9 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le | |||
| 240 | value = onenand_block_address(this, block); | 250 | value = onenand_block_address(this, block); |
| 241 | this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); | 251 | this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); |
| 242 | 252 | ||
| 243 | if (block_cmd) { | 253 | /* Select DataRAM for DDP */ |
| 244 | /* Select DataRAM for DDP */ | 254 | value = onenand_bufferram_address(this, block); |
| 245 | value = onenand_bufferram_address(this, block); | 255 | this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); |
| 246 | this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); | ||
| 247 | } | ||
| 248 | } | 256 | } |
| 249 | 257 | ||
| 250 | if (page != -1) { | 258 | if (page != -1) { |
| @@ -256,7 +264,6 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le | |||
| 256 | case ONENAND_CMD_READ: | 264 | case ONENAND_CMD_READ: |
| 257 | case ONENAND_CMD_READOOB: | 265 | case ONENAND_CMD_READOOB: |
| 258 | dataram = ONENAND_SET_NEXT_BUFFERRAM(this); | 266 | dataram = ONENAND_SET_NEXT_BUFFERRAM(this); |
| 259 | readcmd = 1; | ||
| 260 | break; | 267 | break; |
| 261 | 268 | ||
| 262 | default: | 269 | default: |
| @@ -273,12 +280,6 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le | |||
| 273 | /* Write 'BSA, BSC' of DataRAM */ | 280 | /* Write 'BSA, BSC' of DataRAM */ |
| 274 | value = onenand_buffer_address(dataram, sectors, count); | 281 | value = onenand_buffer_address(dataram, sectors, count); |
| 275 | this->write_word(value, this->base + ONENAND_REG_START_BUFFER); | 282 | this->write_word(value, this->base + ONENAND_REG_START_BUFFER); |
| 276 | |||
| 277 | if (readcmd) { | ||
| 278 | /* Select DataRAM for DDP */ | ||
| 279 | value = onenand_bufferram_address(this, block); | ||
| 280 | this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); | ||
| 281 | } | ||
| 282 | } | 283 | } |
| 283 | 284 | ||
| 284 | /* Interrupt clear */ | 285 | /* Interrupt clear */ |
| @@ -1118,12 +1119,10 @@ static int onenand_bbt_wait(struct mtd_info *mtd, int state) | |||
| 1118 | interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); | 1119 | interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); |
| 1119 | ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); | 1120 | ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); |
| 1120 | 1121 | ||
| 1122 | /* Initial bad block case: 0x2400 or 0x0400 */ | ||
| 1121 | if (ctrl & ONENAND_CTRL_ERROR) { | 1123 | if (ctrl & ONENAND_CTRL_ERROR) { |
| 1122 | printk(KERN_DEBUG "onenand_bbt_wait: controller error = 0x%04x\n", ctrl); | 1124 | printk(KERN_DEBUG "onenand_bbt_wait: controller error = 0x%04x\n", ctrl); |
| 1123 | /* Initial bad block case */ | 1125 | return ONENAND_BBT_READ_ERROR; |
| 1124 | if (ctrl & ONENAND_CTRL_LOAD) | ||
| 1125 | return ONENAND_BBT_READ_ERROR; | ||
| 1126 | return ONENAND_BBT_READ_FATAL_ERROR; | ||
| 1127 | } | 1126 | } |
| 1128 | 1127 | ||
| 1129 | if (interrupt & ONENAND_INT_READ) { | 1128 | if (interrupt & ONENAND_INT_READ) { |
| @@ -1218,7 +1217,7 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from, | |||
| 1218 | static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to) | 1217 | static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to) |
| 1219 | { | 1218 | { |
| 1220 | struct onenand_chip *this = mtd->priv; | 1219 | struct onenand_chip *this = mtd->priv; |
| 1221 | char oobbuf[64]; | 1220 | u_char *oob_buf = this->oob_buf; |
| 1222 | int status, i; | 1221 | int status, i; |
| 1223 | 1222 | ||
| 1224 | this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize); | 1223 | this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize); |
| @@ -1227,9 +1226,9 @@ static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to | |||
| 1227 | if (status) | 1226 | if (status) |
| 1228 | return status; | 1227 | return status; |
| 1229 | 1228 | ||
| 1230 | this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize); | 1229 | this->read_bufferram(mtd, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize); |
| 1231 | for (i = 0; i < mtd->oobsize; i++) | 1230 | for (i = 0; i < mtd->oobsize; i++) |
| 1232 | if (buf[i] != 0xFF && buf[i] != oobbuf[i]) | 1231 | if (buf[i] != 0xFF && buf[i] != oob_buf[i]) |
| 1233 | return -EBADMSG; | 1232 | return -EBADMSG; |
| 1234 | 1233 | ||
| 1235 | return 0; | 1234 | return 0; |
| @@ -1431,7 +1430,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, | |||
| 1431 | } | 1430 | } |
| 1432 | 1431 | ||
| 1433 | /* Only check verify write turn on */ | 1432 | /* Only check verify write turn on */ |
| 1434 | ret = onenand_verify(mtd, (u_char *) wbuf, to, thislen); | 1433 | ret = onenand_verify(mtd, buf, to, thislen); |
| 1435 | if (ret) { | 1434 | if (ret) { |
| 1436 | printk(KERN_ERR "onenand_write_ops_nolock: verify failed %d\n", ret); | 1435 | printk(KERN_ERR "onenand_write_ops_nolock: verify failed %d\n", ret); |
| 1437 | break; | 1436 | break; |
| @@ -1447,9 +1446,6 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, | |||
| 1447 | buf += thislen; | 1446 | buf += thislen; |
| 1448 | } | 1447 | } |
| 1449 | 1448 | ||
| 1450 | /* Deselect and wake up anyone waiting on the device */ | ||
| 1451 | onenand_release_device(mtd); | ||
| 1452 | |||
| 1453 | ops->retlen = written; | 1449 | ops->retlen = written; |
| 1454 | 1450 | ||
| 1455 | return ret; | 1451 | return ret; |
| @@ -2160,7 +2156,7 @@ static int onenand_otp_walk(struct mtd_info *mtd, loff_t from, size_t len, | |||
| 2160 | 2156 | ||
| 2161 | *retlen = 0; | 2157 | *retlen = 0; |
| 2162 | 2158 | ||
| 2163 | density = this->device_id >> ONENAND_DEVICE_DENSITY_SHIFT; | 2159 | density = onenand_get_density(this->device_id); |
| 2164 | if (density < ONENAND_DEVICE_DENSITY_512Mb) | 2160 | if (density < ONENAND_DEVICE_DENSITY_512Mb) |
| 2165 | otp_pages = 20; | 2161 | otp_pages = 20; |
| 2166 | else | 2162 | else |
| @@ -2311,7 +2307,8 @@ static int onenand_write_user_prot_reg(struct mtd_info *mtd, loff_t from, | |||
| 2311 | static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, | 2307 | static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, |
| 2312 | size_t len) | 2308 | size_t len) |
| 2313 | { | 2309 | { |
| 2314 | unsigned char oob_buf[64]; | 2310 | struct onenand_chip *this = mtd->priv; |
| 2311 | u_char *oob_buf = this->oob_buf; | ||
| 2315 | size_t retlen; | 2312 | size_t retlen; |
| 2316 | int ret; | 2313 | int ret; |
| 2317 | 2314 | ||
| @@ -2351,7 +2348,7 @@ static void onenand_check_features(struct mtd_info *mtd) | |||
| 2351 | unsigned int density, process; | 2348 | unsigned int density, process; |
| 2352 | 2349 | ||
| 2353 | /* Lock scheme depends on density and process */ | 2350 | /* Lock scheme depends on density and process */ |
| 2354 | density = this->device_id >> ONENAND_DEVICE_DENSITY_SHIFT; | 2351 | density = onenand_get_density(this->device_id); |
| 2355 | process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT; | 2352 | process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT; |
| 2356 | 2353 | ||
| 2357 | /* Lock scheme */ | 2354 | /* Lock scheme */ |
| @@ -2400,7 +2397,7 @@ static void onenand_print_device_info(int device, int version) | |||
| 2400 | vcc = device & ONENAND_DEVICE_VCC_MASK; | 2397 | vcc = device & ONENAND_DEVICE_VCC_MASK; |
| 2401 | demuxed = device & ONENAND_DEVICE_IS_DEMUX; | 2398 | demuxed = device & ONENAND_DEVICE_IS_DEMUX; |
| 2402 | ddp = device & ONENAND_DEVICE_IS_DDP; | 2399 | ddp = device & ONENAND_DEVICE_IS_DDP; |
| 2403 | density = device >> ONENAND_DEVICE_DENSITY_SHIFT; | 2400 | density = onenand_get_density(device); |
| 2404 | printk(KERN_INFO "%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n", | 2401 | printk(KERN_INFO "%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n", |
| 2405 | demuxed ? "" : "Muxed ", | 2402 | demuxed ? "" : "Muxed ", |
| 2406 | ddp ? "(DDP)" : "", | 2403 | ddp ? "(DDP)" : "", |
| @@ -2492,7 +2489,7 @@ static int onenand_probe(struct mtd_info *mtd) | |||
| 2492 | this->device_id = dev_id; | 2489 | this->device_id = dev_id; |
| 2493 | this->version_id = ver_id; | 2490 | this->version_id = ver_id; |
| 2494 | 2491 | ||
| 2495 | density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT; | 2492 | density = onenand_get_density(dev_id); |
| 2496 | this->chipsize = (16 << density) << 20; | 2493 | this->chipsize = (16 << density) << 20; |
| 2497 | /* Set density mask. it is used for DDP */ | 2494 | /* Set density mask. it is used for DDP */ |
| 2498 | if (ONENAND_IS_DDP(this)) | 2495 | if (ONENAND_IS_DDP(this)) |
diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h index c46161f4eee3..d1b310c92eb4 100644 --- a/include/linux/mtd/onenand_regs.h +++ b/include/linux/mtd/onenand_regs.h | |||
| @@ -67,6 +67,7 @@ | |||
| 67 | /* | 67 | /* |
| 68 | * Device ID Register F001h (R) | 68 | * Device ID Register F001h (R) |
| 69 | */ | 69 | */ |
| 70 | #define ONENAND_DEVICE_DENSITY_MASK (0xf) | ||
| 70 | #define ONENAND_DEVICE_DENSITY_SHIFT (4) | 71 | #define ONENAND_DEVICE_DENSITY_SHIFT (4) |
| 71 | #define ONENAND_DEVICE_IS_DDP (1 << 3) | 72 | #define ONENAND_DEVICE_IS_DDP (1 << 3) |
| 72 | #define ONENAND_DEVICE_IS_DEMUX (1 << 2) | 73 | #define ONENAND_DEVICE_IS_DEMUX (1 << 2) |
