aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2008-02-03 02:31:04 -0500
committerDavid Woodhouse <dwmw2@infradead.org>2008-02-03 02:31:04 -0500
commitb7e23d913aafc93fc5f119e1be17620073cc3811 (patch)
tree0f76a32d5b22cf12f6f822cf0c04481f3bb227fb /drivers
parentc1f3ee120bb61045b1c0a3ead620d1d65af47130 (diff)
parent69d79186dc48ca22a0ce69511bef8ef6c2465ada (diff)
Merge git://git.infradead.org/~kmpark/onenand-mtd-2.6
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/onenand/onenand_base.c59
1 files changed, 28 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 */
178static 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)
182static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t len) 194static 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,
1218static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to) 1217static 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,
2311static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, 2307static 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))