diff options
Diffstat (limited to 'drivers/mtd/onenand')
-rw-r--r-- | drivers/mtd/onenand/onenand_base.c | 51 |
1 files changed, 36 insertions, 15 deletions
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 7d194cfdb873..45bc1433b28d 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c | |||
@@ -921,17 +921,22 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col | |||
921 | * | 921 | * |
922 | * OneNAND read out-of-band data from the spare area | 922 | * OneNAND read out-of-band data from the spare area |
923 | */ | 923 | */ |
924 | static int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len, | 924 | static int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, |
925 | size_t *retlen, u_char *buf, mtd_oob_mode_t mode) | 925 | struct mtd_oob_ops *ops) |
926 | { | 926 | { |
927 | struct onenand_chip *this = mtd->priv; | 927 | struct onenand_chip *this = mtd->priv; |
928 | int read = 0, thislen, column, oobsize; | 928 | int read = 0, thislen, column, oobsize; |
929 | size_t len = ops->ooblen; | ||
930 | mtd_oob_mode_t mode = ops->mode; | ||
931 | u_char *buf = ops->oobbuf; | ||
929 | int ret = 0; | 932 | int ret = 0; |
930 | 933 | ||
934 | from += ops->ooboffs; | ||
935 | |||
931 | DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); | 936 | DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); |
932 | 937 | ||
933 | /* Initialize return length value */ | 938 | /* Initialize return length value */ |
934 | *retlen = 0; | 939 | ops->oobretlen = 0; |
935 | 940 | ||
936 | if (mode == MTD_OOB_AUTO) | 941 | if (mode == MTD_OOB_AUTO) |
937 | oobsize = this->ecclayout->oobavail; | 942 | oobsize = this->ecclayout->oobavail; |
@@ -997,7 +1002,7 @@ static int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len, | |||
997 | /* Deselect and wake up anyone waiting on the device */ | 1002 | /* Deselect and wake up anyone waiting on the device */ |
998 | onenand_release_device(mtd); | 1003 | onenand_release_device(mtd); |
999 | 1004 | ||
1000 | *retlen = read; | 1005 | ops->oobretlen = read; |
1001 | return ret; | 1006 | return ret; |
1002 | } | 1007 | } |
1003 | 1008 | ||
@@ -1019,8 +1024,7 @@ static int onenand_read_oob(struct mtd_info *mtd, loff_t from, | |||
1019 | default: | 1024 | default: |
1020 | return -EINVAL; | 1025 | return -EINVAL; |
1021 | } | 1026 | } |
1022 | return onenand_do_read_oob(mtd, from + ops->ooboffs, ops->ooblen, | 1027 | return onenand_do_read_oob(mtd, from, ops); |
1023 | &ops->oobretlen, ops->oobbuf, ops->mode); | ||
1024 | } | 1028 | } |
1025 | 1029 | ||
1026 | /** | 1030 | /** |
@@ -1370,18 +1374,23 @@ static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf, | |||
1370 | * | 1374 | * |
1371 | * OneNAND write out-of-band | 1375 | * OneNAND write out-of-band |
1372 | */ | 1376 | */ |
1373 | static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len, | 1377 | static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, |
1374 | size_t *retlen, const u_char *buf, mtd_oob_mode_t mode) | 1378 | struct mtd_oob_ops *ops) |
1375 | { | 1379 | { |
1376 | struct onenand_chip *this = mtd->priv; | 1380 | struct onenand_chip *this = mtd->priv; |
1377 | int column, ret = 0, oobsize; | 1381 | int column, ret = 0, oobsize; |
1378 | int written = 0; | 1382 | int written = 0; |
1379 | u_char *oobbuf; | 1383 | u_char *oobbuf; |
1384 | size_t len = ops->ooblen; | ||
1385 | const u_char *buf = ops->oobbuf; | ||
1386 | mtd_oob_mode_t mode = ops->mode; | ||
1387 | |||
1388 | to += ops->ooboffs; | ||
1380 | 1389 | ||
1381 | DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); | 1390 | DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); |
1382 | 1391 | ||
1383 | /* Initialize retlen, in case of early exit */ | 1392 | /* Initialize retlen, in case of early exit */ |
1384 | *retlen = 0; | 1393 | ops->oobretlen = 0; |
1385 | 1394 | ||
1386 | if (mode == MTD_OOB_AUTO) | 1395 | if (mode == MTD_OOB_AUTO) |
1387 | oobsize = this->ecclayout->oobavail; | 1396 | oobsize = this->ecclayout->oobavail; |
@@ -1464,7 +1473,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len, | |||
1464 | /* Deselect and wake up anyone waiting on the device */ | 1473 | /* Deselect and wake up anyone waiting on the device */ |
1465 | onenand_release_device(mtd); | 1474 | onenand_release_device(mtd); |
1466 | 1475 | ||
1467 | *retlen = written; | 1476 | ops->oobretlen = written; |
1468 | 1477 | ||
1469 | return ret; | 1478 | return ret; |
1470 | } | 1479 | } |
@@ -1487,8 +1496,7 @@ static int onenand_write_oob(struct mtd_info *mtd, loff_t to, | |||
1487 | default: | 1496 | default: |
1488 | return -EINVAL; | 1497 | return -EINVAL; |
1489 | } | 1498 | } |
1490 | return onenand_do_write_oob(mtd, to + ops->ooboffs, ops->ooblen, | 1499 | return onenand_do_write_oob(mtd, to, ops); |
1491 | &ops->oobretlen, ops->oobbuf, ops->mode); | ||
1492 | } | 1500 | } |
1493 | 1501 | ||
1494 | /** | 1502 | /** |
@@ -1646,7 +1654,12 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
1646 | struct onenand_chip *this = mtd->priv; | 1654 | struct onenand_chip *this = mtd->priv; |
1647 | struct bbm_info *bbm = this->bbm; | 1655 | struct bbm_info *bbm = this->bbm; |
1648 | u_char buf[2] = {0, 0}; | 1656 | u_char buf[2] = {0, 0}; |
1649 | size_t retlen; | 1657 | struct mtd_oob_ops ops = { |
1658 | .mode = MTD_OOB_PLACE, | ||
1659 | .ooblen = 2, | ||
1660 | .oobbuf = buf, | ||
1661 | .ooboffs = 0, | ||
1662 | }; | ||
1650 | int block; | 1663 | int block; |
1651 | 1664 | ||
1652 | /* Get block number */ | 1665 | /* Get block number */ |
@@ -1656,7 +1669,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
1656 | 1669 | ||
1657 | /* We write two bytes, so we dont have to mess with 16 bit access */ | 1670 | /* We write two bytes, so we dont have to mess with 16 bit access */ |
1658 | ofs += mtd->oobsize + (bbm->badblockpos & ~0x01); | 1671 | ofs += mtd->oobsize + (bbm->badblockpos & ~0x01); |
1659 | return onenand_do_write_oob(mtd, ofs , 2, &retlen, buf, MTD_OOB_PLACE); | 1672 | return onenand_do_write_oob(mtd, ofs, &ops); |
1660 | } | 1673 | } |
1661 | 1674 | ||
1662 | /** | 1675 | /** |
@@ -1945,13 +1958,21 @@ static int do_otp_lock(struct mtd_info *mtd, loff_t from, size_t len, | |||
1945 | size_t *retlen, u_char *buf) | 1958 | size_t *retlen, u_char *buf) |
1946 | { | 1959 | { |
1947 | struct onenand_chip *this = mtd->priv; | 1960 | struct onenand_chip *this = mtd->priv; |
1961 | struct mtd_oob_ops ops = { | ||
1962 | .mode = MTD_OOB_PLACE, | ||
1963 | .ooblen = len, | ||
1964 | .oobbuf = buf, | ||
1965 | .ooboffs = 0, | ||
1966 | }; | ||
1948 | int ret; | 1967 | int ret; |
1949 | 1968 | ||
1950 | /* Enter OTP access mode */ | 1969 | /* Enter OTP access mode */ |
1951 | this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0); | 1970 | this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0); |
1952 | this->wait(mtd, FL_OTPING); | 1971 | this->wait(mtd, FL_OTPING); |
1953 | 1972 | ||
1954 | ret = onenand_do_write_oob(mtd, from, len, retlen, buf, MTD_OOB_PLACE); | 1973 | ret = onenand_do_write_oob(mtd, from, &ops); |
1974 | |||
1975 | *retlen = ops.oobretlen; | ||
1955 | 1976 | ||
1956 | /* Exit OTP access mode */ | 1977 | /* Exit OTP access mode */ |
1957 | this->command(mtd, ONENAND_CMD_RESET, 0, 0); | 1978 | this->command(mtd, ONENAND_CMD_RESET, 0, 0); |