diff options
| author | Robert Jarzmik <robert.jarzmik@free.fr> | 2012-03-22 16:00:52 -0400 |
|---|---|---|
| committer | David Woodhouse <David.Woodhouse@intel.com> | 2012-03-26 20:03:14 -0400 |
| commit | 1b15a5f93bbd9a6f5346cfa449720a7e32115f86 (patch) | |
| tree | d04e9b90f2fe443cbe3079abf3730cd58bd84a2f | |
| parent | a2b3d284ed65b9ada18fd2ffb66daffe9c0ff168 (diff) | |
mtd: docg3 refactor cascade floors structure
Group floors into a common cascade structure. This will provide a common
structure to store common data to all cascaded docg3 chips, like IO
addressing, locking protection.
Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
| -rw-r--r-- | drivers/mtd/devices/docg3.c | 88 | ||||
| -rw-r--r-- | drivers/mtd/devices/docg3.h | 18 |
2 files changed, 61 insertions, 45 deletions
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index be88eb6217cb..935d4c6e9321 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) |
| @@ -1599,13 +1595,13 @@ static struct device_attribute doc_sys_attrs[DOC_MAX_NBFLOORS][4] = { | |||
| 1599 | }; | 1595 | }; |
| 1600 | 1596 | ||
| 1601 | static int doc_register_sysfs(struct platform_device *pdev, | 1597 | static int doc_register_sysfs(struct platform_device *pdev, |
| 1602 | struct mtd_info **floors) | 1598 | struct docg3_cascade *cascade) |
| 1603 | { | 1599 | { |
| 1604 | int ret = 0, floor, i = 0; | 1600 | int ret = 0, floor, i = 0; |
| 1605 | struct device *dev = &pdev->dev; | 1601 | struct device *dev = &pdev->dev; |
| 1606 | 1602 | ||
| 1607 | for (floor = 0; !ret && floor < DOC_MAX_NBFLOORS && floors[floor]; | 1603 | for (floor = 0; !ret && floor < DOC_MAX_NBFLOORS && |
| 1608 | floor++) | 1604 | cascade->floors[floor]; floor++) |
| 1609 | for (i = 0; !ret && i < 4; i++) | 1605 | for (i = 0; !ret && i < 4; i++) |
| 1610 | ret = device_create_file(dev, &doc_sys_attrs[floor][i]); | 1606 | ret = device_create_file(dev, &doc_sys_attrs[floor][i]); |
| 1611 | if (!ret) | 1607 | if (!ret) |
| @@ -1619,12 +1615,12 @@ static int doc_register_sysfs(struct platform_device *pdev, | |||
| 1619 | } | 1615 | } |
| 1620 | 1616 | ||
| 1621 | static void doc_unregister_sysfs(struct platform_device *pdev, | 1617 | static void doc_unregister_sysfs(struct platform_device *pdev, |
| 1622 | struct mtd_info **floors) | 1618 | struct docg3_cascade *cascade) |
| 1623 | { | 1619 | { |
| 1624 | struct device *dev = &pdev->dev; | 1620 | struct device *dev = &pdev->dev; |
| 1625 | int floor, i; | 1621 | int floor, i; |
| 1626 | 1622 | ||
| 1627 | for (floor = 0; floor < DOC_MAX_NBFLOORS && floors[floor]; | 1623 | for (floor = 0; floor < DOC_MAX_NBFLOORS && cascade->floors[floor]; |
| 1628 | floor++) | 1624 | floor++) |
| 1629 | for (i = 0; i < 4; i++) | 1625 | for (i = 0; i < 4; i++) |
| 1630 | device_remove_file(dev, &doc_sys_attrs[floor][i]); | 1626 | device_remove_file(dev, &doc_sys_attrs[floor][i]); |
| @@ -1833,6 +1829,7 @@ static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) | |||
| 1833 | * @base: the io space where the device is probed | 1829 | * @base: the io space where the device is probed |
| 1834 | * @floor: the floor of the probed device | 1830 | * @floor: the floor of the probed device |
| 1835 | * @dev: the device | 1831 | * @dev: the device |
| 1832 | * @cascade: the cascade of chips this devices will belong to | ||
| 1836 | * | 1833 | * |
| 1837 | * Checks whether a device at the specified IO range, and floor is available. | 1834 | * Checks whether a device at the specified IO range, and floor is available. |
| 1838 | * | 1835 | * |
| @@ -1841,7 +1838,7 @@ static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) | |||
| 1841 | * launched. | 1838 | * launched. |
| 1842 | */ | 1839 | */ |
| 1843 | static struct mtd_info * __init | 1840 | static struct mtd_info * __init |
| 1844 | doc_probe_device(void __iomem *base, int floor, struct device *dev) | 1841 | doc_probe_device(struct docg3_cascade *cascade, int floor, struct device *dev) |
| 1845 | { | 1842 | { |
| 1846 | int ret, bbt_nbpages; | 1843 | int ret, bbt_nbpages; |
| 1847 | u16 chip_id, chip_id_inv; | 1844 | u16 chip_id, chip_id_inv; |
| @@ -1864,7 +1861,7 @@ doc_probe_device(void __iomem *base, int floor, struct device *dev) | |||
| 1864 | 1861 | ||
| 1865 | docg3->dev = dev; | 1862 | docg3->dev = dev; |
| 1866 | docg3->device_id = floor; | 1863 | docg3->device_id = floor; |
| 1867 | docg3->base = base; | 1864 | docg3->cascade = cascade; |
| 1868 | doc_set_device_id(docg3, docg3->device_id); | 1865 | doc_set_device_id(docg3, docg3->device_id); |
| 1869 | if (!floor) | 1866 | if (!floor) |
| 1870 | doc_set_asic_mode(docg3, DOC_ASICMODE_RESET); | 1867 | doc_set_asic_mode(docg3, DOC_ASICMODE_RESET); |
| @@ -1881,7 +1878,7 @@ doc_probe_device(void __iomem *base, int floor, struct device *dev) | |||
| 1881 | switch (chip_id) { | 1878 | switch (chip_id) { |
| 1882 | case DOC_CHIPID_G3: | 1879 | case DOC_CHIPID_G3: |
| 1883 | doc_info("Found a G3 DiskOnChip at addr %p, floor %d\n", | 1880 | doc_info("Found a G3 DiskOnChip at addr %p, floor %d\n", |
| 1884 | base, floor); | 1881 | docg3->cascade->base, floor); |
| 1885 | break; | 1882 | break; |
| 1886 | default: | 1883 | default: |
| 1887 | doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id); | 1884 | doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id); |
| @@ -1926,10 +1923,12 @@ static void doc_release_device(struct mtd_info *mtd) | |||
| 1926 | static int docg3_resume(struct platform_device *pdev) | 1923 | static int docg3_resume(struct platform_device *pdev) |
| 1927 | { | 1924 | { |
| 1928 | int i; | 1925 | int i; |
| 1926 | struct docg3_cascade *cascade; | ||
| 1929 | struct mtd_info **docg3_floors, *mtd; | 1927 | struct mtd_info **docg3_floors, *mtd; |
| 1930 | struct docg3 *docg3; | 1928 | struct docg3 *docg3; |
| 1931 | 1929 | ||
| 1932 | docg3_floors = platform_get_drvdata(pdev); | 1930 | cascade = platform_get_drvdata(pdev); |
| 1931 | docg3_floors = cascade->floors; | ||
| 1933 | mtd = docg3_floors[0]; | 1932 | mtd = docg3_floors[0]; |
| 1934 | docg3 = mtd->priv; | 1933 | docg3 = mtd->priv; |
| 1935 | 1934 | ||
| @@ -1951,11 +1950,13 @@ static int docg3_resume(struct platform_device *pdev) | |||
| 1951 | static int docg3_suspend(struct platform_device *pdev, pm_message_t state) | 1950 | static int docg3_suspend(struct platform_device *pdev, pm_message_t state) |
| 1952 | { | 1951 | { |
| 1953 | int floor, i; | 1952 | int floor, i; |
| 1953 | struct docg3_cascade *cascade; | ||
| 1954 | struct mtd_info **docg3_floors, *mtd; | 1954 | struct mtd_info **docg3_floors, *mtd; |
| 1955 | struct docg3 *docg3; | 1955 | struct docg3 *docg3; |
| 1956 | u8 ctrl, pwr_down; | 1956 | u8 ctrl, pwr_down; |
| 1957 | 1957 | ||
| 1958 | docg3_floors = platform_get_drvdata(pdev); | 1958 | cascade = platform_get_drvdata(pdev); |
| 1959 | docg3_floors = cascade->floors; | ||
| 1959 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) { | 1960 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) { |
| 1960 | mtd = docg3_floors[floor]; | 1961 | mtd = docg3_floors[floor]; |
| 1961 | if (!mtd) | 1962 | if (!mtd) |
| @@ -2005,7 +2006,7 @@ static int __init docg3_probe(struct platform_device *pdev) | |||
| 2005 | struct resource *ress; | 2006 | struct resource *ress; |
| 2006 | void __iomem *base; | 2007 | void __iomem *base; |
| 2007 | int ret, floor, found = 0; | 2008 | int ret, floor, found = 0; |
| 2008 | struct mtd_info **docg3_floors; | 2009 | struct docg3_cascade *cascade; |
| 2009 | 2010 | ||
| 2010 | ret = -ENXIO; | 2011 | ret = -ENXIO; |
| 2011 | ress = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2012 | ress = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| @@ -2016,17 +2017,18 @@ static int __init docg3_probe(struct platform_device *pdev) | |||
| 2016 | base = ioremap(ress->start, DOC_IOSPACE_SIZE); | 2017 | base = ioremap(ress->start, DOC_IOSPACE_SIZE); |
| 2017 | 2018 | ||
| 2018 | ret = -ENOMEM; | 2019 | ret = -ENOMEM; |
| 2019 | docg3_floors = kzalloc(sizeof(*docg3_floors) * DOC_MAX_NBFLOORS, | 2020 | cascade = kzalloc(sizeof(*cascade) * DOC_MAX_NBFLOORS, |
| 2020 | GFP_KERNEL); | 2021 | GFP_KERNEL); |
| 2021 | if (!docg3_floors) | 2022 | if (!cascade) |
| 2022 | goto nomem1; | 2023 | goto nomem1; |
| 2023 | docg3_bch = init_bch(DOC_ECC_BCH_M, DOC_ECC_BCH_T, | 2024 | cascade->base = base; |
| 2025 | cascade->bch = init_bch(DOC_ECC_BCH_M, DOC_ECC_BCH_T, | ||
| 2024 | DOC_ECC_BCH_PRIMPOLY); | 2026 | DOC_ECC_BCH_PRIMPOLY); |
| 2025 | if (!docg3_bch) | 2027 | if (!cascade->bch) |
| 2026 | goto nomem2; | 2028 | goto nomem2; |
| 2027 | 2029 | ||
| 2028 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) { | 2030 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) { |
| 2029 | mtd = doc_probe_device(base, floor, dev); | 2031 | mtd = doc_probe_device(cascade, floor, dev); |
| 2030 | if (IS_ERR(mtd)) { | 2032 | if (IS_ERR(mtd)) { |
| 2031 | ret = PTR_ERR(mtd); | 2033 | ret = PTR_ERR(mtd); |
| 2032 | goto err_probe; | 2034 | goto err_probe; |
| @@ -2037,7 +2039,7 @@ static int __init docg3_probe(struct platform_device *pdev) | |||
| 2037 | else | 2039 | else |
| 2038 | continue; | 2040 | continue; |
| 2039 | } | 2041 | } |
| 2040 | docg3_floors[floor] = mtd; | 2042 | cascade->floors[floor] = mtd; |
| 2041 | ret = mtd_device_parse_register(mtd, part_probes, NULL, NULL, | 2043 | ret = mtd_device_parse_register(mtd, part_probes, NULL, NULL, |
| 2042 | 0); | 2044 | 0); |
| 2043 | if (ret) | 2045 | if (ret) |
| @@ -2045,26 +2047,26 @@ static int __init docg3_probe(struct platform_device *pdev) | |||
| 2045 | found++; | 2047 | found++; |
| 2046 | } | 2048 | } |
| 2047 | 2049 | ||
| 2048 | ret = doc_register_sysfs(pdev, docg3_floors); | 2050 | ret = doc_register_sysfs(pdev, cascade); |
| 2049 | if (ret) | 2051 | if (ret) |
| 2050 | goto err_probe; | 2052 | goto err_probe; |
| 2051 | if (!found) | 2053 | if (!found) |
| 2052 | goto notfound; | 2054 | goto notfound; |
| 2053 | 2055 | ||
| 2054 | platform_set_drvdata(pdev, docg3_floors); | 2056 | platform_set_drvdata(pdev, cascade); |
| 2055 | doc_dbg_register(docg3_floors[0]->priv); | 2057 | doc_dbg_register(cascade->floors[0]->priv); |
| 2056 | return 0; | 2058 | return 0; |
| 2057 | 2059 | ||
| 2058 | notfound: | 2060 | notfound: |
| 2059 | ret = -ENODEV; | 2061 | ret = -ENODEV; |
| 2060 | dev_info(dev, "No supported DiskOnChip found\n"); | 2062 | dev_info(dev, "No supported DiskOnChip found\n"); |
| 2061 | err_probe: | 2063 | err_probe: |
| 2062 | free_bch(docg3_bch); | 2064 | kfree(cascade->bch); |
| 2063 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) | 2065 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) |
| 2064 | if (docg3_floors[floor]) | 2066 | if (cascade->floors[floor]) |
| 2065 | doc_release_device(docg3_floors[floor]); | 2067 | doc_release_device(cascade->floors[floor]); |
| 2066 | nomem2: | 2068 | nomem2: |
| 2067 | kfree(docg3_floors); | 2069 | kfree(cascade); |
| 2068 | nomem1: | 2070 | nomem1: |
| 2069 | iounmap(base); | 2071 | iounmap(base); |
| 2070 | noress: | 2072 | noress: |
| @@ -2079,19 +2081,19 @@ noress: | |||
| 2079 | */ | 2081 | */ |
| 2080 | static int __exit docg3_release(struct platform_device *pdev) | 2082 | static int __exit docg3_release(struct platform_device *pdev) |
| 2081 | { | 2083 | { |
| 2082 | struct mtd_info **docg3_floors = platform_get_drvdata(pdev); | 2084 | struct docg3_cascade *cascade = platform_get_drvdata(pdev); |
| 2083 | struct docg3 *docg3 = docg3_floors[0]->priv; | 2085 | struct docg3 *docg3 = cascade->floors[0]->priv; |
| 2084 | void __iomem *base = docg3->base; | 2086 | void __iomem *base = cascade->base; |
| 2085 | int floor; | 2087 | int floor; |
| 2086 | 2088 | ||
| 2087 | doc_unregister_sysfs(pdev, docg3_floors); | 2089 | doc_unregister_sysfs(pdev, cascade); |
| 2088 | doc_dbg_unregister(docg3); | 2090 | doc_dbg_unregister(docg3); |
| 2089 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) | 2091 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) |
| 2090 | if (docg3_floors[floor]) | 2092 | if (cascade->floors[floor]) |
| 2091 | doc_release_device(docg3_floors[floor]); | 2093 | doc_release_device(cascade->floors[floor]); |
| 2092 | 2094 | ||
| 2093 | kfree(docg3_floors); | 2095 | free_bch(docg3->cascade->bch); |
| 2094 | free_bch(docg3_bch); | 2096 | kfree(cascade); |
| 2095 | iounmap(base); | 2097 | iounmap(base); |
| 2096 | return 0; | 2098 | return 0; |
| 2097 | } | 2099 | } |
diff --git a/drivers/mtd/devices/docg3.h b/drivers/mtd/devices/docg3.h index db0da436b493..642e60667cfd 100644 --- a/drivers/mtd/devices/docg3.h +++ b/drivers/mtd/devices/docg3.h | |||
| @@ -22,6 +22,8 @@ | |||
| 22 | #ifndef _MTD_DOCG3_H | 22 | #ifndef _MTD_DOCG3_H |
| 23 | #define _MTD_DOCG3_H | 23 | #define _MTD_DOCG3_H |
| 24 | 24 | ||
| 25 | #include <linux/mtd/mtd.h> | ||
| 26 | |||
| 25 | /* | 27 | /* |
| 26 | * Flash memory areas : | 28 | * Flash memory areas : |
| 27 | * - 0x0000 .. 0x07ff : IPL | 29 | * - 0x0000 .. 0x07ff : IPL |
| @@ -267,9 +269,21 @@ | |||
| 267 | #define DOC_LAYOUT_DPS_KEY_LENGTH 8 | 269 | #define DOC_LAYOUT_DPS_KEY_LENGTH 8 |
| 268 | 270 | ||
| 269 | /** | 271 | /** |
| 272 | * struct docg3_cascade - Cascade of 1 to 4 docg3 chips | ||
| 273 | * @floors: floors (ie. one physical docg3 chip is one floor) | ||
| 274 | * @base: IO space to access all chips in the cascade | ||
| 275 | * @bch: the BCH correcting control structure | ||
| 276 | */ | ||
| 277 | struct docg3_cascade { | ||
| 278 | struct mtd_info *floors[DOC_MAX_NBFLOORS]; | ||
| 279 | void __iomem *base; | ||
| 280 | struct bch_control *bch; | ||
| 281 | }; | ||
| 282 | |||
| 283 | /** | ||
| 270 | * struct docg3 - DiskOnChip driver private data | 284 | * struct docg3 - DiskOnChip driver private data |
| 271 | * @dev: the device currently under control | 285 | * @dev: the device currently under control |
| 272 | * @base: mapped IO space | 286 | * @cascade: the cascade this device belongs to |
| 273 | * @device_id: number of the cascaded DoCG3 device (0, 1, 2 or 3) | 287 | * @device_id: number of the cascaded DoCG3 device (0, 1, 2 or 3) |
| 274 | * @if_cfg: if true, reads are on 16bits, else reads are on 8bits | 288 | * @if_cfg: if true, reads are on 16bits, else reads are on 8bits |
| 275 | 289 | ||
| @@ -287,7 +301,7 @@ | |||
| 287 | */ | 301 | */ |
| 288 | struct docg3 { | 302 | struct docg3 { |
| 289 | struct device *dev; | 303 | struct device *dev; |
| 290 | void __iomem *base; | 304 | struct docg3_cascade *cascade; |
| 291 | unsigned int device_id:4; | 305 | unsigned int device_id:4; |
| 292 | unsigned int if_cfg:1; | 306 | unsigned int if_cfg:1; |
| 293 | unsigned int reliable:2; | 307 | unsigned int reliable:2; |
