diff options
author | Jiri Kosina <jkosina@suse.cz> | 2012-04-08 15:48:52 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2012-04-08 15:48:52 -0400 |
commit | e75d660672ddd11704b7f0fdb8ff21968587b266 (patch) | |
tree | ccb9c107744c10b553c0373e450bee3971d16c00 /drivers/mtd/devices/docg3.c | |
parent | 61282f37927143e45b03153f3e7b48d6b702147a (diff) | |
parent | 0034102808e0dbbf3a2394b82b1bb40b5778de9e (diff) |
Merge branch 'master' into for-next
Merge with latest Linus' tree, as I have incoming patches
that fix code that is newer than current HEAD of for-next.
Conflicts:
drivers/net/ethernet/realtek/r8169.c
Diffstat (limited to 'drivers/mtd/devices/docg3.c')
-rw-r--r-- | drivers/mtd/devices/docg3.c | 201 |
1 files changed, 115 insertions, 86 deletions
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index 9afda6950df7..50aa90aa7a7f 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c | |||
@@ -80,14 +80,9 @@ static struct nand_ecclayout docg3_oobinfo = { | |||
80 | .oobavail = 8, | 80 | .oobavail = 8, |
81 | }; | 81 | }; |
82 | 82 | ||
83 | /** | ||
84 | * struct docg3_bch - BCH engine | ||
85 | */ | ||
86 | static struct bch_control *docg3_bch; | ||
87 | |||
88 | static inline u8 doc_readb(struct docg3 *docg3, u16 reg) | 83 | static inline u8 doc_readb(struct docg3 *docg3, u16 reg) |
89 | { | 84 | { |
90 | u8 val = readb(docg3->base + reg); | 85 | u8 val = readb(docg3->cascade->base + reg); |
91 | 86 | ||
92 | trace_docg3_io(0, 8, reg, (int)val); | 87 | trace_docg3_io(0, 8, reg, (int)val); |
93 | return val; | 88 | return val; |
@@ -95,7 +90,7 @@ static inline u8 doc_readb(struct docg3 *docg3, u16 reg) | |||
95 | 90 | ||
96 | static inline u16 doc_readw(struct docg3 *docg3, u16 reg) | 91 | static inline u16 doc_readw(struct docg3 *docg3, u16 reg) |
97 | { | 92 | { |
98 | u16 val = readw(docg3->base + reg); | 93 | u16 val = readw(docg3->cascade->base + reg); |
99 | 94 | ||
100 | trace_docg3_io(0, 16, reg, (int)val); | 95 | trace_docg3_io(0, 16, reg, (int)val); |
101 | return val; | 96 | return val; |
@@ -103,13 +98,13 @@ static inline u16 doc_readw(struct docg3 *docg3, u16 reg) | |||
103 | 98 | ||
104 | static inline void doc_writeb(struct docg3 *docg3, u8 val, u16 reg) | 99 | static inline void doc_writeb(struct docg3 *docg3, u8 val, u16 reg) |
105 | { | 100 | { |
106 | writeb(val, docg3->base + reg); | 101 | writeb(val, docg3->cascade->base + reg); |
107 | trace_docg3_io(1, 8, reg, val); | 102 | trace_docg3_io(1, 8, reg, val); |
108 | } | 103 | } |
109 | 104 | ||
110 | static inline void doc_writew(struct docg3 *docg3, u16 val, u16 reg) | 105 | static inline void doc_writew(struct docg3 *docg3, u16 val, u16 reg) |
111 | { | 106 | { |
112 | writew(val, docg3->base + reg); | 107 | writew(val, docg3->cascade->base + reg); |
113 | trace_docg3_io(1, 16, reg, val); | 108 | trace_docg3_io(1, 16, reg, val); |
114 | } | 109 | } |
115 | 110 | ||
@@ -643,7 +638,8 @@ static int doc_ecc_bch_fix_data(struct docg3 *docg3, void *buf, u8 *hwecc) | |||
643 | 638 | ||
644 | for (i = 0; i < DOC_ECC_BCH_SIZE; i++) | 639 | for (i = 0; i < DOC_ECC_BCH_SIZE; i++) |
645 | ecc[i] = bitrev8(hwecc[i]); | 640 | ecc[i] = bitrev8(hwecc[i]); |
646 | numerrs = decode_bch(docg3_bch, NULL, DOC_ECC_BCH_COVERED_BYTES, | 641 | numerrs = decode_bch(docg3->cascade->bch, NULL, |
642 | DOC_ECC_BCH_COVERED_BYTES, | ||
647 | NULL, ecc, NULL, errorpos); | 643 | NULL, ecc, NULL, errorpos); |
648 | BUG_ON(numerrs == -EINVAL); | 644 | BUG_ON(numerrs == -EINVAL); |
649 | if (numerrs < 0) | 645 | if (numerrs < 0) |
@@ -734,7 +730,7 @@ err: | |||
734 | * doc_read_page_getbytes - Reads bytes from a prepared page | 730 | * doc_read_page_getbytes - Reads bytes from a prepared page |
735 | * @docg3: the device | 731 | * @docg3: the device |
736 | * @len: the number of bytes to be read (must be a multiple of 4) | 732 | * @len: the number of bytes to be read (must be a multiple of 4) |
737 | * @buf: the buffer to be filled in | 733 | * @buf: the buffer to be filled in (or NULL is forget bytes) |
738 | * @first: 1 if first time read, DOC_READADDRESS should be set | 734 | * @first: 1 if first time read, DOC_READADDRESS should be set |
739 | * | 735 | * |
740 | */ | 736 | */ |
@@ -849,7 +845,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from, | |||
849 | struct mtd_oob_ops *ops) | 845 | struct mtd_oob_ops *ops) |
850 | { | 846 | { |
851 | struct docg3 *docg3 = mtd->priv; | 847 | struct docg3 *docg3 = mtd->priv; |
852 | int block0, block1, page, ret, ofs = 0; | 848 | int block0, block1, page, ret, skip, ofs = 0; |
853 | u8 *oobbuf = ops->oobbuf; | 849 | u8 *oobbuf = ops->oobbuf; |
854 | u8 *buf = ops->datbuf; | 850 | u8 *buf = ops->datbuf; |
855 | size_t len, ooblen, nbdata, nboob; | 851 | size_t len, ooblen, nbdata, nboob; |
@@ -869,34 +865,36 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from, | |||
869 | 865 | ||
870 | doc_dbg("doc_read_oob(from=%lld, mode=%d, data=(%p:%zu), oob=(%p:%zu))\n", | 866 | doc_dbg("doc_read_oob(from=%lld, mode=%d, data=(%p:%zu), oob=(%p:%zu))\n", |
871 | from, ops->mode, buf, len, oobbuf, ooblen); | 867 | from, ops->mode, buf, len, oobbuf, ooblen); |
872 | if ((len % DOC_LAYOUT_PAGE_SIZE) || (ooblen % DOC_LAYOUT_OOB_SIZE) || | 868 | if (ooblen % DOC_LAYOUT_OOB_SIZE) |
873 | (from % DOC_LAYOUT_PAGE_SIZE)) | ||
874 | return -EINVAL; | 869 | return -EINVAL; |
875 | 870 | ||
876 | ret = -EINVAL; | 871 | if (from + len > mtd->size) |
877 | calc_block_sector(from + len, &block0, &block1, &page, &ofs, | 872 | return -EINVAL; |
878 | docg3->reliable); | ||
879 | if (block1 > docg3->max_block) | ||
880 | goto err; | ||
881 | 873 | ||
882 | ops->oobretlen = 0; | 874 | ops->oobretlen = 0; |
883 | ops->retlen = 0; | 875 | ops->retlen = 0; |
884 | ret = 0; | 876 | ret = 0; |
877 | skip = from % DOC_LAYOUT_PAGE_SIZE; | ||
878 | mutex_lock(&docg3->cascade->lock); | ||
885 | while (!ret && (len > 0 || ooblen > 0)) { | 879 | while (!ret && (len > 0 || ooblen > 0)) { |
886 | calc_block_sector(from, &block0, &block1, &page, &ofs, | 880 | calc_block_sector(from - skip, &block0, &block1, &page, &ofs, |
887 | docg3->reliable); | 881 | docg3->reliable); |
888 | nbdata = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE); | 882 | nbdata = min_t(size_t, len, DOC_LAYOUT_PAGE_SIZE - skip); |
889 | nboob = min_t(size_t, ooblen, (size_t)DOC_LAYOUT_OOB_SIZE); | 883 | nboob = min_t(size_t, ooblen, (size_t)DOC_LAYOUT_OOB_SIZE); |
890 | ret = doc_read_page_prepare(docg3, block0, block1, page, ofs); | 884 | ret = doc_read_page_prepare(docg3, block0, block1, page, ofs); |
891 | if (ret < 0) | 885 | if (ret < 0) |
892 | goto err; | 886 | goto out; |
893 | ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_TOTAL_BYTES); | 887 | ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_TOTAL_BYTES); |
894 | if (ret < 0) | 888 | if (ret < 0) |
895 | goto err_in_read; | 889 | goto err_in_read; |
896 | ret = doc_read_page_getbytes(docg3, nbdata, buf, 1); | 890 | ret = doc_read_page_getbytes(docg3, skip, NULL, 1); |
891 | if (ret < skip) | ||
892 | goto err_in_read; | ||
893 | ret = doc_read_page_getbytes(docg3, nbdata, buf, 0); | ||
897 | if (ret < nbdata) | 894 | if (ret < nbdata) |
898 | goto err_in_read; | 895 | goto err_in_read; |
899 | doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE - nbdata, | 896 | doc_read_page_getbytes(docg3, |
897 | DOC_LAYOUT_PAGE_SIZE - nbdata - skip, | ||
900 | NULL, 0); | 898 | NULL, 0); |
901 | ret = doc_read_page_getbytes(docg3, nboob, oobbuf, 0); | 899 | ret = doc_read_page_getbytes(docg3, nboob, oobbuf, 0); |
902 | if (ret < nboob) | 900 | if (ret < nboob) |
@@ -950,13 +948,15 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from, | |||
950 | len -= nbdata; | 948 | len -= nbdata; |
951 | ooblen -= nboob; | 949 | ooblen -= nboob; |
952 | from += DOC_LAYOUT_PAGE_SIZE; | 950 | from += DOC_LAYOUT_PAGE_SIZE; |
951 | skip = 0; | ||
953 | } | 952 | } |
954 | 953 | ||
954 | out: | ||
955 | mutex_unlock(&docg3->cascade->lock); | ||
955 | return ret; | 956 | return ret; |
956 | err_in_read: | 957 | err_in_read: |
957 | doc_read_page_finish(docg3); | 958 | doc_read_page_finish(docg3); |
958 | err: | 959 | goto out; |
959 | return ret; | ||
960 | } | 960 | } |
961 | 961 | ||
962 | /** | 962 | /** |
@@ -1114,10 +1114,10 @@ static int doc_get_op_status(struct docg3 *docg3) | |||
1114 | */ | 1114 | */ |
1115 | static int doc_write_erase_wait_status(struct docg3 *docg3) | 1115 | static int doc_write_erase_wait_status(struct docg3 *docg3) |
1116 | { | 1116 | { |
1117 | int status, ret = 0; | 1117 | int i, status, ret = 0; |
1118 | 1118 | ||
1119 | if (!doc_is_ready(docg3)) | 1119 | for (i = 0; !doc_is_ready(docg3) && i < 5; i++) |
1120 | usleep_range(3000, 3000); | 1120 | msleep(20); |
1121 | if (!doc_is_ready(docg3)) { | 1121 | if (!doc_is_ready(docg3)) { |
1122 | doc_dbg("Timeout reached and the chip is still not ready\n"); | 1122 | doc_dbg("Timeout reached and the chip is still not ready\n"); |
1123 | ret = -EAGAIN; | 1123 | ret = -EAGAIN; |
@@ -1196,18 +1196,19 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *info) | |||
1196 | int block0, block1, page, ret, ofs = 0; | 1196 | int block0, block1, page, ret, ofs = 0; |
1197 | 1197 | ||
1198 | doc_dbg("doc_erase(from=%lld, len=%lld\n", info->addr, info->len); | 1198 | doc_dbg("doc_erase(from=%lld, len=%lld\n", info->addr, info->len); |
1199 | doc_set_device_id(docg3, docg3->device_id); | ||
1200 | 1199 | ||
1201 | info->state = MTD_ERASE_PENDING; | 1200 | info->state = MTD_ERASE_PENDING; |
1202 | calc_block_sector(info->addr + info->len, &block0, &block1, &page, | 1201 | calc_block_sector(info->addr + info->len, &block0, &block1, &page, |
1203 | &ofs, docg3->reliable); | 1202 | &ofs, docg3->reliable); |
1204 | ret = -EINVAL; | 1203 | ret = -EINVAL; |
1205 | if (block1 > docg3->max_block || page || ofs) | 1204 | if (info->addr + info->len > mtd->size || page || ofs) |
1206 | goto reset_err; | 1205 | goto reset_err; |
1207 | 1206 | ||
1208 | ret = 0; | 1207 | ret = 0; |
1209 | calc_block_sector(info->addr, &block0, &block1, &page, &ofs, | 1208 | calc_block_sector(info->addr, &block0, &block1, &page, &ofs, |
1210 | docg3->reliable); | 1209 | docg3->reliable); |
1210 | mutex_lock(&docg3->cascade->lock); | ||
1211 | doc_set_device_id(docg3, docg3->device_id); | ||
1211 | doc_set_reliable_mode(docg3); | 1212 | doc_set_reliable_mode(docg3); |
1212 | for (len = info->len; !ret && len > 0; len -= mtd->erasesize) { | 1213 | for (len = info->len; !ret && len > 0; len -= mtd->erasesize) { |
1213 | info->state = MTD_ERASING; | 1214 | info->state = MTD_ERASING; |
@@ -1215,6 +1216,7 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *info) | |||
1215 | block0 += 2; | 1216 | block0 += 2; |
1216 | block1 += 2; | 1217 | block1 += 2; |
1217 | } | 1218 | } |
1219 | mutex_unlock(&docg3->cascade->lock); | ||
1218 | 1220 | ||
1219 | if (ret) | 1221 | if (ret) |
1220 | goto reset_err; | 1222 | goto reset_err; |
@@ -1401,7 +1403,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, | |||
1401 | struct mtd_oob_ops *ops) | 1403 | struct mtd_oob_ops *ops) |
1402 | { | 1404 | { |
1403 | struct docg3 *docg3 = mtd->priv; | 1405 | struct docg3 *docg3 = mtd->priv; |
1404 | int block0, block1, page, ret, pofs = 0, autoecc, oobdelta; | 1406 | int ret, autoecc, oobdelta; |
1405 | u8 *oobbuf = ops->oobbuf; | 1407 | u8 *oobbuf = ops->oobbuf; |
1406 | u8 *buf = ops->datbuf; | 1408 | u8 *buf = ops->datbuf; |
1407 | size_t len, ooblen; | 1409 | size_t len, ooblen; |
@@ -1438,12 +1440,8 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, | |||
1438 | if (len && ooblen && | 1440 | if (len && ooblen && |
1439 | (len / DOC_LAYOUT_PAGE_SIZE) != (ooblen / oobdelta)) | 1441 | (len / DOC_LAYOUT_PAGE_SIZE) != (ooblen / oobdelta)) |
1440 | return -EINVAL; | 1442 | return -EINVAL; |
1441 | 1443 | if (ofs + len > mtd->size) | |
1442 | ret = -EINVAL; | 1444 | return -EINVAL; |
1443 | calc_block_sector(ofs + len, &block0, &block1, &page, &pofs, | ||
1444 | docg3->reliable); | ||
1445 | if (block1 > docg3->max_block) | ||
1446 | goto err; | ||
1447 | 1445 | ||
1448 | ops->oobretlen = 0; | 1446 | ops->oobretlen = 0; |
1449 | ops->retlen = 0; | 1447 | ops->retlen = 0; |
@@ -1457,6 +1455,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, | |||
1457 | if (autoecc < 0) | 1455 | if (autoecc < 0) |
1458 | return autoecc; | 1456 | return autoecc; |
1459 | 1457 | ||
1458 | mutex_lock(&docg3->cascade->lock); | ||
1460 | while (!ret && len > 0) { | 1459 | while (!ret && len > 0) { |
1461 | memset(oob, 0, sizeof(oob)); | 1460 | memset(oob, 0, sizeof(oob)); |
1462 | if (ofs == docg3->oob_write_ofs) | 1461 | if (ofs == docg3->oob_write_ofs) |
@@ -1477,8 +1476,9 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, | |||
1477 | } | 1476 | } |
1478 | ops->retlen += DOC_LAYOUT_PAGE_SIZE; | 1477 | ops->retlen += DOC_LAYOUT_PAGE_SIZE; |
1479 | } | 1478 | } |
1480 | err: | 1479 | |
1481 | doc_set_device_id(docg3, 0); | 1480 | doc_set_device_id(docg3, 0); |
1481 | mutex_unlock(&docg3->cascade->lock); | ||
1482 | return ret; | 1482 | return ret; |
1483 | } | 1483 | } |
1484 | 1484 | ||
@@ -1535,9 +1535,11 @@ static ssize_t dps0_is_key_locked(struct device *dev, | |||
1535 | struct docg3 *docg3 = sysfs_dev2docg3(dev, attr); | 1535 | struct docg3 *docg3 = sysfs_dev2docg3(dev, attr); |
1536 | int dps0; | 1536 | int dps0; |
1537 | 1537 | ||
1538 | mutex_lock(&docg3->cascade->lock); | ||
1538 | doc_set_device_id(docg3, docg3->device_id); | 1539 | doc_set_device_id(docg3, docg3->device_id); |
1539 | dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS); | 1540 | dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS); |
1540 | doc_set_device_id(docg3, 0); | 1541 | doc_set_device_id(docg3, 0); |
1542 | mutex_unlock(&docg3->cascade->lock); | ||
1541 | 1543 | ||
1542 | return sprintf(buf, "%d\n", !(dps0 & DOC_DPS_KEY_OK)); | 1544 | return sprintf(buf, "%d\n", !(dps0 & DOC_DPS_KEY_OK)); |
1543 | } | 1545 | } |
@@ -1548,9 +1550,11 @@ static ssize_t dps1_is_key_locked(struct device *dev, | |||
1548 | struct docg3 *docg3 = sysfs_dev2docg3(dev, attr); | 1550 | struct docg3 *docg3 = sysfs_dev2docg3(dev, attr); |
1549 | int dps1; | 1551 | int dps1; |
1550 | 1552 | ||
1553 | mutex_lock(&docg3->cascade->lock); | ||
1551 | doc_set_device_id(docg3, docg3->device_id); | 1554 | doc_set_device_id(docg3, docg3->device_id); |
1552 | dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS); | 1555 | dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS); |
1553 | doc_set_device_id(docg3, 0); | 1556 | doc_set_device_id(docg3, 0); |
1557 | mutex_unlock(&docg3->cascade->lock); | ||
1554 | 1558 | ||
1555 | return sprintf(buf, "%d\n", !(dps1 & DOC_DPS_KEY_OK)); | 1559 | return sprintf(buf, "%d\n", !(dps1 & DOC_DPS_KEY_OK)); |
1556 | } | 1560 | } |
@@ -1565,10 +1569,12 @@ static ssize_t dps0_insert_key(struct device *dev, | |||
1565 | if (count != DOC_LAYOUT_DPS_KEY_LENGTH) | 1569 | if (count != DOC_LAYOUT_DPS_KEY_LENGTH) |
1566 | return -EINVAL; | 1570 | return -EINVAL; |
1567 | 1571 | ||
1572 | mutex_lock(&docg3->cascade->lock); | ||
1568 | doc_set_device_id(docg3, docg3->device_id); | 1573 | doc_set_device_id(docg3, docg3->device_id); |
1569 | for (i = 0; i < DOC_LAYOUT_DPS_KEY_LENGTH; i++) | 1574 | for (i = 0; i < DOC_LAYOUT_DPS_KEY_LENGTH; i++) |
1570 | doc_writeb(docg3, buf[i], DOC_DPS0_KEY); | 1575 | doc_writeb(docg3, buf[i], DOC_DPS0_KEY); |
1571 | doc_set_device_id(docg3, 0); | 1576 | doc_set_device_id(docg3, 0); |
1577 | mutex_unlock(&docg3->cascade->lock); | ||
1572 | return count; | 1578 | return count; |
1573 | } | 1579 | } |
1574 | 1580 | ||
@@ -1582,10 +1588,12 @@ static ssize_t dps1_insert_key(struct device *dev, | |||
1582 | if (count != DOC_LAYOUT_DPS_KEY_LENGTH) | 1588 | if (count != DOC_LAYOUT_DPS_KEY_LENGTH) |
1583 | return -EINVAL; | 1589 | return -EINVAL; |
1584 | 1590 | ||
1591 | mutex_lock(&docg3->cascade->lock); | ||
1585 | doc_set_device_id(docg3, docg3->device_id); | 1592 | doc_set_device_id(docg3, docg3->device_id); |
1586 | for (i = 0; i < DOC_LAYOUT_DPS_KEY_LENGTH; i++) | 1593 | for (i = 0; i < DOC_LAYOUT_DPS_KEY_LENGTH; i++) |
1587 | doc_writeb(docg3, buf[i], DOC_DPS1_KEY); | 1594 | doc_writeb(docg3, buf[i], DOC_DPS1_KEY); |
1588 | doc_set_device_id(docg3, 0); | 1595 | doc_set_device_id(docg3, 0); |
1596 | mutex_unlock(&docg3->cascade->lock); | ||
1589 | return count; | 1597 | return count; |
1590 | } | 1598 | } |
1591 | 1599 | ||
@@ -1601,13 +1609,13 @@ static struct device_attribute doc_sys_attrs[DOC_MAX_NBFLOORS][4] = { | |||
1601 | }; | 1609 | }; |
1602 | 1610 | ||
1603 | static int doc_register_sysfs(struct platform_device *pdev, | 1611 | static int doc_register_sysfs(struct platform_device *pdev, |
1604 | struct mtd_info **floors) | 1612 | struct docg3_cascade *cascade) |
1605 | { | 1613 | { |
1606 | int ret = 0, floor, i = 0; | 1614 | int ret = 0, floor, i = 0; |
1607 | struct device *dev = &pdev->dev; | 1615 | struct device *dev = &pdev->dev; |
1608 | 1616 | ||
1609 | for (floor = 0; !ret && floor < DOC_MAX_NBFLOORS && floors[floor]; | 1617 | for (floor = 0; !ret && floor < DOC_MAX_NBFLOORS && |
1610 | floor++) | 1618 | cascade->floors[floor]; floor++) |
1611 | for (i = 0; !ret && i < 4; i++) | 1619 | for (i = 0; !ret && i < 4; i++) |
1612 | ret = device_create_file(dev, &doc_sys_attrs[floor][i]); | 1620 | ret = device_create_file(dev, &doc_sys_attrs[floor][i]); |
1613 | if (!ret) | 1621 | if (!ret) |
@@ -1621,12 +1629,12 @@ static int doc_register_sysfs(struct platform_device *pdev, | |||
1621 | } | 1629 | } |
1622 | 1630 | ||
1623 | static void doc_unregister_sysfs(struct platform_device *pdev, | 1631 | static void doc_unregister_sysfs(struct platform_device *pdev, |
1624 | struct mtd_info **floors) | 1632 | struct docg3_cascade *cascade) |
1625 | { | 1633 | { |
1626 | struct device *dev = &pdev->dev; | 1634 | struct device *dev = &pdev->dev; |
1627 | int floor, i; | 1635 | int floor, i; |
1628 | 1636 | ||
1629 | for (floor = 0; floor < DOC_MAX_NBFLOORS && floors[floor]; | 1637 | for (floor = 0; floor < DOC_MAX_NBFLOORS && cascade->floors[floor]; |
1630 | floor++) | 1638 | floor++) |
1631 | for (i = 0; i < 4; i++) | 1639 | for (i = 0; i < 4; i++) |
1632 | device_remove_file(dev, &doc_sys_attrs[floor][i]); | 1640 | device_remove_file(dev, &doc_sys_attrs[floor][i]); |
@@ -1640,7 +1648,11 @@ static int dbg_flashctrl_show(struct seq_file *s, void *p) | |||
1640 | struct docg3 *docg3 = (struct docg3 *)s->private; | 1648 | struct docg3 *docg3 = (struct docg3 *)s->private; |
1641 | 1649 | ||
1642 | int pos = 0; | 1650 | int pos = 0; |
1643 | u8 fctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | 1651 | u8 fctrl; |
1652 | |||
1653 | mutex_lock(&docg3->cascade->lock); | ||
1654 | fctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
1655 | mutex_unlock(&docg3->cascade->lock); | ||
1644 | 1656 | ||
1645 | pos += seq_printf(s, | 1657 | pos += seq_printf(s, |
1646 | "FlashControl : 0x%02x (%s,CE# %s,%s,%s,flash %s)\n", | 1658 | "FlashControl : 0x%02x (%s,CE# %s,%s,%s,flash %s)\n", |
@@ -1658,9 +1670,12 @@ static int dbg_asicmode_show(struct seq_file *s, void *p) | |||
1658 | { | 1670 | { |
1659 | struct docg3 *docg3 = (struct docg3 *)s->private; | 1671 | struct docg3 *docg3 = (struct docg3 *)s->private; |
1660 | 1672 | ||
1661 | int pos = 0; | 1673 | int pos = 0, pctrl, mode; |
1662 | int pctrl = doc_register_readb(docg3, DOC_ASICMODE); | 1674 | |
1663 | int mode = pctrl & 0x03; | 1675 | mutex_lock(&docg3->cascade->lock); |
1676 | pctrl = doc_register_readb(docg3, DOC_ASICMODE); | ||
1677 | mode = pctrl & 0x03; | ||
1678 | mutex_unlock(&docg3->cascade->lock); | ||
1664 | 1679 | ||
1665 | pos += seq_printf(s, | 1680 | pos += seq_printf(s, |
1666 | "%04x : RAM_WE=%d,RSTIN_RESET=%d,BDETCT_RESET=%d,WRITE_ENABLE=%d,POWERDOWN=%d,MODE=%d%d (", | 1681 | "%04x : RAM_WE=%d,RSTIN_RESET=%d,BDETCT_RESET=%d,WRITE_ENABLE=%d,POWERDOWN=%d,MODE=%d%d (", |
@@ -1692,7 +1707,11 @@ static int dbg_device_id_show(struct seq_file *s, void *p) | |||
1692 | { | 1707 | { |
1693 | struct docg3 *docg3 = (struct docg3 *)s->private; | 1708 | struct docg3 *docg3 = (struct docg3 *)s->private; |
1694 | int pos = 0; | 1709 | int pos = 0; |
1695 | int id = doc_register_readb(docg3, DOC_DEVICESELECT); | 1710 | int id; |
1711 | |||
1712 | mutex_lock(&docg3->cascade->lock); | ||
1713 | id = doc_register_readb(docg3, DOC_DEVICESELECT); | ||
1714 | mutex_unlock(&docg3->cascade->lock); | ||
1696 | 1715 | ||
1697 | pos += seq_printf(s, "DeviceId = %d\n", id); | 1716 | pos += seq_printf(s, "DeviceId = %d\n", id); |
1698 | return pos; | 1717 | return pos; |
@@ -1705,6 +1724,7 @@ static int dbg_protection_show(struct seq_file *s, void *p) | |||
1705 | int pos = 0; | 1724 | int pos = 0; |
1706 | int protect, dps0, dps0_low, dps0_high, dps1, dps1_low, dps1_high; | 1725 | int protect, dps0, dps0_low, dps0_high, dps1, dps1_low, dps1_high; |
1707 | 1726 | ||
1727 | mutex_lock(&docg3->cascade->lock); | ||
1708 | protect = doc_register_readb(docg3, DOC_PROTECTION); | 1728 | protect = doc_register_readb(docg3, DOC_PROTECTION); |
1709 | dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS); | 1729 | dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS); |
1710 | dps0_low = doc_register_readw(docg3, DOC_DPS0_ADDRLOW); | 1730 | dps0_low = doc_register_readw(docg3, DOC_DPS0_ADDRLOW); |
@@ -1712,6 +1732,7 @@ static int dbg_protection_show(struct seq_file *s, void *p) | |||
1712 | dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS); | 1732 | dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS); |
1713 | dps1_low = doc_register_readw(docg3, DOC_DPS1_ADDRLOW); | 1733 | dps1_low = doc_register_readw(docg3, DOC_DPS1_ADDRLOW); |
1714 | dps1_high = doc_register_readw(docg3, DOC_DPS1_ADDRHIGH); | 1734 | dps1_high = doc_register_readw(docg3, DOC_DPS1_ADDRHIGH); |
1735 | mutex_unlock(&docg3->cascade->lock); | ||
1715 | 1736 | ||
1716 | pos += seq_printf(s, "Protection = 0x%02x (", | 1737 | pos += seq_printf(s, "Protection = 0x%02x (", |
1717 | protect); | 1738 | protect); |
@@ -1804,7 +1825,7 @@ static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) | |||
1804 | 1825 | ||
1805 | switch (chip_id) { | 1826 | switch (chip_id) { |
1806 | case DOC_CHIPID_G3: | 1827 | case DOC_CHIPID_G3: |
1807 | mtd->name = kasprintf(GFP_KERNEL, "DiskOnChip G3 floor %d", | 1828 | mtd->name = kasprintf(GFP_KERNEL, "docg3.%d", |
1808 | docg3->device_id); | 1829 | docg3->device_id); |
1809 | docg3->max_block = 2047; | 1830 | docg3->max_block = 2047; |
1810 | break; | 1831 | break; |
@@ -1817,16 +1838,17 @@ static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) | |||
1817 | mtd->erasesize = DOC_LAYOUT_BLOCK_SIZE * DOC_LAYOUT_NBPLANES; | 1838 | mtd->erasesize = DOC_LAYOUT_BLOCK_SIZE * DOC_LAYOUT_NBPLANES; |
1818 | if (docg3->reliable == 2) | 1839 | if (docg3->reliable == 2) |
1819 | mtd->erasesize /= 2; | 1840 | mtd->erasesize /= 2; |
1820 | mtd->writesize = DOC_LAYOUT_PAGE_SIZE; | 1841 | mtd->writebufsize = mtd->writesize = DOC_LAYOUT_PAGE_SIZE; |
1821 | mtd->oobsize = DOC_LAYOUT_OOB_SIZE; | 1842 | mtd->oobsize = DOC_LAYOUT_OOB_SIZE; |
1822 | mtd->owner = THIS_MODULE; | 1843 | mtd->owner = THIS_MODULE; |
1823 | mtd->erase = doc_erase; | 1844 | mtd->_erase = doc_erase; |
1824 | mtd->read = doc_read; | 1845 | mtd->_read = doc_read; |
1825 | mtd->write = doc_write; | 1846 | mtd->_write = doc_write; |
1826 | mtd->read_oob = doc_read_oob; | 1847 | mtd->_read_oob = doc_read_oob; |
1827 | mtd->write_oob = doc_write_oob; | 1848 | mtd->_write_oob = doc_write_oob; |
1828 | mtd->block_isbad = doc_block_isbad; | 1849 | mtd->_block_isbad = doc_block_isbad; |
1829 | mtd->ecclayout = &docg3_oobinfo; | 1850 | mtd->ecclayout = &docg3_oobinfo; |
1851 | mtd->ecc_strength = DOC_ECC_BCH_T; | ||
1830 | } | 1852 | } |
1831 | 1853 | ||
1832 | /** | 1854 | /** |
@@ -1834,6 +1856,7 @@ static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) | |||
1834 | * @base: the io space where the device is probed | 1856 | * @base: the io space where the device is probed |
1835 | * @floor: the floor of the probed device | 1857 | * @floor: the floor of the probed device |
1836 | * @dev: the device | 1858 | * @dev: the device |
1859 | * @cascade: the cascade of chips this devices will belong to | ||
1837 | * | 1860 | * |
1838 | * Checks whether a device at the specified IO range, and floor is available. | 1861 | * Checks whether a device at the specified IO range, and floor is available. |
1839 | * | 1862 | * |
@@ -1841,8 +1864,8 @@ static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) | |||
1841 | * if a memory allocation failed. If floor 0 is checked, a reset of the ASIC is | 1864 | * if a memory allocation failed. If floor 0 is checked, a reset of the ASIC is |
1842 | * launched. | 1865 | * launched. |
1843 | */ | 1866 | */ |
1844 | static struct mtd_info *doc_probe_device(void __iomem *base, int floor, | 1867 | static struct mtd_info * __init |
1845 | struct device *dev) | 1868 | doc_probe_device(struct docg3_cascade *cascade, int floor, struct device *dev) |
1846 | { | 1869 | { |
1847 | int ret, bbt_nbpages; | 1870 | int ret, bbt_nbpages; |
1848 | u16 chip_id, chip_id_inv; | 1871 | u16 chip_id, chip_id_inv; |
@@ -1865,7 +1888,7 @@ static struct mtd_info *doc_probe_device(void __iomem *base, int floor, | |||
1865 | 1888 | ||
1866 | docg3->dev = dev; | 1889 | docg3->dev = dev; |
1867 | docg3->device_id = floor; | 1890 | docg3->device_id = floor; |
1868 | docg3->base = base; | 1891 | docg3->cascade = cascade; |
1869 | doc_set_device_id(docg3, docg3->device_id); | 1892 | doc_set_device_id(docg3, docg3->device_id); |
1870 | if (!floor) | 1893 | if (!floor) |
1871 | doc_set_asic_mode(docg3, DOC_ASICMODE_RESET); | 1894 | doc_set_asic_mode(docg3, DOC_ASICMODE_RESET); |
@@ -1882,7 +1905,7 @@ static struct mtd_info *doc_probe_device(void __iomem *base, int floor, | |||
1882 | switch (chip_id) { | 1905 | switch (chip_id) { |
1883 | case DOC_CHIPID_G3: | 1906 | case DOC_CHIPID_G3: |
1884 | doc_info("Found a G3 DiskOnChip at addr %p, floor %d\n", | 1907 | doc_info("Found a G3 DiskOnChip at addr %p, floor %d\n", |
1885 | base, floor); | 1908 | docg3->cascade->base, floor); |
1886 | break; | 1909 | break; |
1887 | default: | 1910 | default: |
1888 | doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id); | 1911 | doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id); |
@@ -1927,10 +1950,12 @@ static void doc_release_device(struct mtd_info *mtd) | |||
1927 | static int docg3_resume(struct platform_device *pdev) | 1950 | static int docg3_resume(struct platform_device *pdev) |
1928 | { | 1951 | { |
1929 | int i; | 1952 | int i; |
1953 | struct docg3_cascade *cascade; | ||
1930 | struct mtd_info **docg3_floors, *mtd; | 1954 | struct mtd_info **docg3_floors, *mtd; |
1931 | struct docg3 *docg3; | 1955 | struct docg3 *docg3; |
1932 | 1956 | ||
1933 | docg3_floors = platform_get_drvdata(pdev); | 1957 | cascade = platform_get_drvdata(pdev); |
1958 | docg3_floors = cascade->floors; | ||
1934 | mtd = docg3_floors[0]; | 1959 | mtd = docg3_floors[0]; |
1935 | docg3 = mtd->priv; | 1960 | docg3 = mtd->priv; |
1936 | 1961 | ||
@@ -1952,11 +1977,13 @@ static int docg3_resume(struct platform_device *pdev) | |||
1952 | static int docg3_suspend(struct platform_device *pdev, pm_message_t state) | 1977 | static int docg3_suspend(struct platform_device *pdev, pm_message_t state) |
1953 | { | 1978 | { |
1954 | int floor, i; | 1979 | int floor, i; |
1980 | struct docg3_cascade *cascade; | ||
1955 | struct mtd_info **docg3_floors, *mtd; | 1981 | struct mtd_info **docg3_floors, *mtd; |
1956 | struct docg3 *docg3; | 1982 | struct docg3 *docg3; |
1957 | u8 ctrl, pwr_down; | 1983 | u8 ctrl, pwr_down; |
1958 | 1984 | ||
1959 | docg3_floors = platform_get_drvdata(pdev); | 1985 | cascade = platform_get_drvdata(pdev); |
1986 | docg3_floors = cascade->floors; | ||
1960 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) { | 1987 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) { |
1961 | mtd = docg3_floors[floor]; | 1988 | mtd = docg3_floors[floor]; |
1962 | if (!mtd) | 1989 | if (!mtd) |
@@ -2006,7 +2033,7 @@ static int __init docg3_probe(struct platform_device *pdev) | |||
2006 | struct resource *ress; | 2033 | struct resource *ress; |
2007 | void __iomem *base; | 2034 | void __iomem *base; |
2008 | int ret, floor, found = 0; | 2035 | int ret, floor, found = 0; |
2009 | struct mtd_info **docg3_floors; | 2036 | struct docg3_cascade *cascade; |
2010 | 2037 | ||
2011 | ret = -ENXIO; | 2038 | ret = -ENXIO; |
2012 | ress = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2039 | ress = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -2017,17 +2044,19 @@ static int __init docg3_probe(struct platform_device *pdev) | |||
2017 | base = ioremap(ress->start, DOC_IOSPACE_SIZE); | 2044 | base = ioremap(ress->start, DOC_IOSPACE_SIZE); |
2018 | 2045 | ||
2019 | ret = -ENOMEM; | 2046 | ret = -ENOMEM; |
2020 | docg3_floors = kzalloc(sizeof(*docg3_floors) * DOC_MAX_NBFLOORS, | 2047 | cascade = kzalloc(sizeof(*cascade) * DOC_MAX_NBFLOORS, |
2021 | GFP_KERNEL); | 2048 | GFP_KERNEL); |
2022 | if (!docg3_floors) | 2049 | if (!cascade) |
2023 | goto nomem1; | 2050 | goto nomem1; |
2024 | docg3_bch = init_bch(DOC_ECC_BCH_M, DOC_ECC_BCH_T, | 2051 | cascade->base = base; |
2052 | mutex_init(&cascade->lock); | ||
2053 | cascade->bch = init_bch(DOC_ECC_BCH_M, DOC_ECC_BCH_T, | ||
2025 | DOC_ECC_BCH_PRIMPOLY); | 2054 | DOC_ECC_BCH_PRIMPOLY); |
2026 | if (!docg3_bch) | 2055 | if (!cascade->bch) |
2027 | goto nomem2; | 2056 | goto nomem2; |
2028 | 2057 | ||
2029 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) { | 2058 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) { |
2030 | mtd = doc_probe_device(base, floor, dev); | 2059 | mtd = doc_probe_device(cascade, floor, dev); |
2031 | if (IS_ERR(mtd)) { | 2060 | if (IS_ERR(mtd)) { |
2032 | ret = PTR_ERR(mtd); | 2061 | ret = PTR_ERR(mtd); |
2033 | goto err_probe; | 2062 | goto err_probe; |
@@ -2038,7 +2067,7 @@ static int __init docg3_probe(struct platform_device *pdev) | |||
2038 | else | 2067 | else |
2039 | continue; | 2068 | continue; |
2040 | } | 2069 | } |
2041 | docg3_floors[floor] = mtd; | 2070 | cascade->floors[floor] = mtd; |
2042 | ret = mtd_device_parse_register(mtd, part_probes, NULL, NULL, | 2071 | ret = mtd_device_parse_register(mtd, part_probes, NULL, NULL, |
2043 | 0); | 2072 | 0); |
2044 | if (ret) | 2073 | if (ret) |
@@ -2046,26 +2075,26 @@ static int __init docg3_probe(struct platform_device *pdev) | |||
2046 | found++; | 2075 | found++; |
2047 | } | 2076 | } |
2048 | 2077 | ||
2049 | ret = doc_register_sysfs(pdev, docg3_floors); | 2078 | ret = doc_register_sysfs(pdev, cascade); |
2050 | if (ret) | 2079 | if (ret) |
2051 | goto err_probe; | 2080 | goto err_probe; |
2052 | if (!found) | 2081 | if (!found) |
2053 | goto notfound; | 2082 | goto notfound; |
2054 | 2083 | ||
2055 | platform_set_drvdata(pdev, docg3_floors); | 2084 | platform_set_drvdata(pdev, cascade); |
2056 | doc_dbg_register(docg3_floors[0]->priv); | 2085 | doc_dbg_register(cascade->floors[0]->priv); |
2057 | return 0; | 2086 | return 0; |
2058 | 2087 | ||
2059 | notfound: | 2088 | notfound: |
2060 | ret = -ENODEV; | 2089 | ret = -ENODEV; |
2061 | dev_info(dev, "No supported DiskOnChip found\n"); | 2090 | dev_info(dev, "No supported DiskOnChip found\n"); |
2062 | err_probe: | 2091 | err_probe: |
2063 | free_bch(docg3_bch); | 2092 | kfree(cascade->bch); |
2064 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) | 2093 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) |
2065 | if (docg3_floors[floor]) | 2094 | if (cascade->floors[floor]) |
2066 | doc_release_device(docg3_floors[floor]); | 2095 | doc_release_device(cascade->floors[floor]); |
2067 | nomem2: | 2096 | nomem2: |
2068 | kfree(docg3_floors); | 2097 | kfree(cascade); |
2069 | nomem1: | 2098 | nomem1: |
2070 | iounmap(base); | 2099 | iounmap(base); |
2071 | noress: | 2100 | noress: |
@@ -2080,19 +2109,19 @@ noress: | |||
2080 | */ | 2109 | */ |
2081 | static int __exit docg3_release(struct platform_device *pdev) | 2110 | static int __exit docg3_release(struct platform_device *pdev) |
2082 | { | 2111 | { |
2083 | struct mtd_info **docg3_floors = platform_get_drvdata(pdev); | 2112 | struct docg3_cascade *cascade = platform_get_drvdata(pdev); |
2084 | struct docg3 *docg3 = docg3_floors[0]->priv; | 2113 | struct docg3 *docg3 = cascade->floors[0]->priv; |
2085 | void __iomem *base = docg3->base; | 2114 | void __iomem *base = cascade->base; |
2086 | int floor; | 2115 | int floor; |
2087 | 2116 | ||
2088 | doc_unregister_sysfs(pdev, docg3_floors); | 2117 | doc_unregister_sysfs(pdev, cascade); |
2089 | doc_dbg_unregister(docg3); | 2118 | doc_dbg_unregister(docg3); |
2090 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) | 2119 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) |
2091 | if (docg3_floors[floor]) | 2120 | if (cascade->floors[floor]) |
2092 | doc_release_device(docg3_floors[floor]); | 2121 | doc_release_device(cascade->floors[floor]); |
2093 | 2122 | ||
2094 | kfree(docg3_floors); | 2123 | free_bch(docg3->cascade->bch); |
2095 | free_bch(docg3_bch); | 2124 | kfree(cascade); |
2096 | iounmap(base); | 2125 | iounmap(base); |
2097 | return 0; | 2126 | return 0; |
2098 | } | 2127 | } |