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 /drivers/mtd/devices | |
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>
Diffstat (limited to 'drivers/mtd/devices')
-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; |