aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorAtsushi Nemoto <anemo@mba.ocn.ne.jp>2009-09-04 12:20:45 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-09-19 17:20:58 -0400
commitc0cbfd0e81d879a950ba6f0df3f75ea30c5ab16e (patch)
tree96509903683e7a51c726cdad95dea3ba826408fc /drivers/mtd/nand
parent0f777fb9318739baf517c4f4ef66347d8898643d (diff)
mtd: nand: txx9ndfmc: transfer 512 byte at a time if possible
Using __nand_correct_data() helper function, this driver can read 512 byte (with 6 byte ECC) at a time. This results minor performance improvement. Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/txx9ndfmc.c52
1 files changed, 47 insertions, 5 deletions
diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c
index 488088eff2ca..73af8324d0d0 100644
--- a/drivers/mtd/nand/txx9ndfmc.c
+++ b/drivers/mtd/nand/txx9ndfmc.c
@@ -189,18 +189,43 @@ static int txx9ndfmc_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
189 uint8_t *ecc_code) 189 uint8_t *ecc_code)
190{ 190{
191 struct platform_device *dev = mtd_to_platdev(mtd); 191 struct platform_device *dev = mtd_to_platdev(mtd);
192 struct nand_chip *chip = mtd->priv;
193 int eccbytes;
192 u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR); 194 u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR);
193 195
194 mcr &= ~TXX9_NDFMCR_ECC_ALL; 196 mcr &= ~TXX9_NDFMCR_ECC_ALL;
195 txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_OFF, TXX9_NDFMCR); 197 txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_OFF, TXX9_NDFMCR);
196 txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_READ, TXX9_NDFMCR); 198 txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_READ, TXX9_NDFMCR);
197 ecc_code[1] = txx9ndfmc_read(dev, TXX9_NDFDTR); 199 for (eccbytes = chip->ecc.bytes; eccbytes > 0; eccbytes -= 3) {
198 ecc_code[0] = txx9ndfmc_read(dev, TXX9_NDFDTR); 200 ecc_code[1] = txx9ndfmc_read(dev, TXX9_NDFDTR);
199 ecc_code[2] = txx9ndfmc_read(dev, TXX9_NDFDTR); 201 ecc_code[0] = txx9ndfmc_read(dev, TXX9_NDFDTR);
202 ecc_code[2] = txx9ndfmc_read(dev, TXX9_NDFDTR);
203 ecc_code += 3;
204 }
200 txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_OFF, TXX9_NDFMCR); 205 txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_OFF, TXX9_NDFMCR);
201 return 0; 206 return 0;
202} 207}
203 208
209static int txx9ndfmc_correct_data(struct mtd_info *mtd, unsigned char *buf,
210 unsigned char *read_ecc, unsigned char *calc_ecc)
211{
212 struct nand_chip *chip = mtd->priv;
213 int eccsize;
214 int corrected = 0;
215 int stat;
216
217 for (eccsize = chip->ecc.size; eccsize > 0; eccsize -= 256) {
218 stat = __nand_correct_data(buf, read_ecc, calc_ecc, 256);
219 if (stat < 0)
220 return stat;
221 corrected += stat;
222 buf += 256;
223 read_ecc += 3;
224 calc_ecc += 3;
225 }
226 return corrected;
227}
228
204static void txx9ndfmc_enable_hwecc(struct mtd_info *mtd, int mode) 229static void txx9ndfmc_enable_hwecc(struct mtd_info *mtd, int mode)
205{ 230{
206 struct platform_device *dev = mtd_to_platdev(mtd); 231 struct platform_device *dev = mtd_to_platdev(mtd);
@@ -244,6 +269,22 @@ static void txx9ndfmc_initialize(struct platform_device *dev)
244#define TXX9NDFMC_NS_TO_CYC(gbusclk, ns) \ 269#define TXX9NDFMC_NS_TO_CYC(gbusclk, ns) \
245 DIV_ROUND_UP((ns) * DIV_ROUND_UP(gbusclk, 1000), 1000000) 270 DIV_ROUND_UP((ns) * DIV_ROUND_UP(gbusclk, 1000), 1000000)
246 271
272static int txx9ndfmc_nand_scan(struct mtd_info *mtd)
273{
274 struct nand_chip *chip = mtd->priv;
275 int ret;
276
277 ret = nand_scan_ident(mtd, 1);
278 if (!ret) {
279 if (mtd->writesize >= 512) {
280 chip->ecc.size = mtd->writesize;
281 chip->ecc.bytes = 3 * (mtd->writesize / 256);
282 }
283 ret = nand_scan_tail(mtd);
284 }
285 return ret;
286}
287
247static int __init txx9ndfmc_probe(struct platform_device *dev) 288static int __init txx9ndfmc_probe(struct platform_device *dev)
248{ 289{
249 struct txx9ndfmc_platform_data *plat = dev->dev.platform_data; 290 struct txx9ndfmc_platform_data *plat = dev->dev.platform_data;
@@ -321,9 +362,10 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
321 chip->cmd_ctrl = txx9ndfmc_cmd_ctrl; 362 chip->cmd_ctrl = txx9ndfmc_cmd_ctrl;
322 chip->dev_ready = txx9ndfmc_dev_ready; 363 chip->dev_ready = txx9ndfmc_dev_ready;
323 chip->ecc.calculate = txx9ndfmc_calculate_ecc; 364 chip->ecc.calculate = txx9ndfmc_calculate_ecc;
324 chip->ecc.correct = nand_correct_data; 365 chip->ecc.correct = txx9ndfmc_correct_data;
325 chip->ecc.hwctl = txx9ndfmc_enable_hwecc; 366 chip->ecc.hwctl = txx9ndfmc_enable_hwecc;
326 chip->ecc.mode = NAND_ECC_HW; 367 chip->ecc.mode = NAND_ECC_HW;
368 /* txx9ndfmc_nand_scan will overwrite ecc.size and ecc.bytes */
327 chip->ecc.size = 256; 369 chip->ecc.size = 256;
328 chip->ecc.bytes = 3; 370 chip->ecc.bytes = 3;
329 chip->chip_delay = 100; 371 chip->chip_delay = 100;
@@ -349,7 +391,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
349 if (plat->wide_mask & (1 << i)) 391 if (plat->wide_mask & (1 << i))
350 chip->options |= NAND_BUSWIDTH_16; 392 chip->options |= NAND_BUSWIDTH_16;
351 393
352 if (nand_scan(mtd, 1)) { 394 if (txx9ndfmc_nand_scan(mtd)) {
353 kfree(txx9_priv->mtdname); 395 kfree(txx9_priv->mtdname);
354 kfree(txx9_priv); 396 kfree(txx9_priv);
355 continue; 397 continue;