diff options
author | Huang Shijie <b32955@freescale.com> | 2014-03-21 01:30:21 -0400 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 09:58:04 -0400 |
commit | ad296e2a577d0ef82e15239df776130e6b5f4532 (patch) | |
tree | 570897f531cc6ce501d745203e5e3b2369419850 /drivers/mtd/nand/gpmi-nand/gpmi-nand.c | |
parent | 9997e70a44328a31aee41911810390832f54c951 (diff) |
ENGR00304574-4 mtd: gpmi: add gpmi_devdata{} to simplify the code
More and more chips use the GPMI controller, but these chips may use
different version of the IPs for GPMI and BCH. The different IPs have
different features, such as the BCH's maximum ECC strength:
imx23/imx28 -- the BCH's maximum ECC strength is 20
imx6q -- the BCH's maximum ECC strength is 40
imx6sx -- the BCH's maximum ECC strength is 62
This patch does the following things:
[1] add a new data structure, gpmi_devdata{}, to store the information for
each IP. Beside the IP version, we stores the following informations:
<1> BCH's maximum ECC strength.
<2> the maximum chain delay in the EDO mode.
but we may add more information in future.
[2] add the gpmi_devdata_imx{23|28|6q} to replace the gpmi_ids.
[3] simplify the code by using the ECC strength from gpmi_devdata, such as
gpmi_check_ecc() and legacy_set_geometry();
[4] use the maximum chain delay to initialize the EDO mode,
see gpmi_compute_edo_timing().
[5] rewrite the macros, such GPMI_IS_MX{23|28|6Q}.
Signed-off-by: Huang Shijie <b32955@freescale.com>
Diffstat (limited to 'drivers/mtd/nand/gpmi-nand/gpmi-nand.c')
-rw-r--r-- | drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 55 |
1 files changed, 29 insertions, 26 deletions
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index bb77f750e75a..de668d848f90 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Freescale GPMI NAND Flash Driver | 2 | * Freescale GPMI NAND Flash Driver |
3 | * | 3 | * |
4 | * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. | 4 | * Copyright (C) 2010-2014 Freescale Semiconductor, Inc. |
5 | * Copyright (C) 2008 Embedded Alley Solutions, Inc. | 5 | * Copyright (C) 2008 Embedded Alley Solutions, Inc. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -53,6 +53,24 @@ static struct nand_ecclayout gpmi_hw_ecclayout = { | |||
53 | .oobfree = { {.offset = 0, .length = 0} } | 53 | .oobfree = { {.offset = 0, .length = 0} } |
54 | }; | 54 | }; |
55 | 55 | ||
56 | static const struct gpmi_devdata gpmi_devdata_imx23 = { | ||
57 | .type = IS_MX23, | ||
58 | .bch_max_ecc_strength = 20, | ||
59 | .max_chain_delay = 16, | ||
60 | }; | ||
61 | |||
62 | static const struct gpmi_devdata gpmi_devdata_imx28 = { | ||
63 | .type = IS_MX28, | ||
64 | .bch_max_ecc_strength = 20, | ||
65 | .max_chain_delay = 16, | ||
66 | }; | ||
67 | |||
68 | static const struct gpmi_devdata gpmi_devdata_imx6q = { | ||
69 | .type = IS_MX6Q, | ||
70 | .bch_max_ecc_strength = 40, | ||
71 | .max_chain_delay = 12, | ||
72 | }; | ||
73 | |||
56 | static irqreturn_t bch_irq(int irq, void *cookie) | 74 | static irqreturn_t bch_irq(int irq, void *cookie) |
57 | { | 75 | { |
58 | struct gpmi_nand_data *this = cookie; | 76 | struct gpmi_nand_data *this = cookie; |
@@ -102,14 +120,8 @@ static inline bool gpmi_check_ecc(struct gpmi_nand_data *this) | |||
102 | /* The mx23/mx28 only support the GF13. */ | 120 | /* The mx23/mx28 only support the GF13. */ |
103 | if (geo->gf_len == 14) | 121 | if (geo->gf_len == 14) |
104 | return false; | 122 | return false; |
105 | |||
106 | if (geo->ecc_strength > MXS_ECC_STRENGTH_MAX) | ||
107 | return false; | ||
108 | } else if (GPMI_IS_MX6Q(this)) { | ||
109 | if (geo->ecc_strength > MX6_ECC_STRENGTH_MAX) | ||
110 | return false; | ||
111 | } | 123 | } |
112 | return true; | 124 | return geo->ecc_strength <= this->devdata->bch_max_ecc_strength; |
113 | } | 125 | } |
114 | 126 | ||
115 | /* | 127 | /* |
@@ -270,8 +282,7 @@ static int legacy_set_geometry(struct gpmi_nand_data *this) | |||
270 | "We can not support this nand chip." | 282 | "We can not support this nand chip." |
271 | " Its required ecc strength(%d) is beyond our" | 283 | " Its required ecc strength(%d) is beyond our" |
272 | " capability(%d).\n", geo->ecc_strength, | 284 | " capability(%d).\n", geo->ecc_strength, |
273 | (GPMI_IS_MX6Q(this) ? MX6_ECC_STRENGTH_MAX | 285 | this->devdata->bch_max_ecc_strength); |
274 | : MXS_ECC_STRENGTH_MAX)); | ||
275 | return -EINVAL; | 286 | return -EINVAL; |
276 | } | 287 | } |
277 | 288 | ||
@@ -1740,23 +1751,16 @@ err_out: | |||
1740 | return ret; | 1751 | return ret; |
1741 | } | 1752 | } |
1742 | 1753 | ||
1743 | static const struct platform_device_id gpmi_ids[] = { | ||
1744 | { .name = "imx23-gpmi-nand", .driver_data = IS_MX23, }, | ||
1745 | { .name = "imx28-gpmi-nand", .driver_data = IS_MX28, }, | ||
1746 | { .name = "imx6q-gpmi-nand", .driver_data = IS_MX6Q, }, | ||
1747 | {} | ||
1748 | }; | ||
1749 | |||
1750 | static const struct of_device_id gpmi_nand_id_table[] = { | 1754 | static const struct of_device_id gpmi_nand_id_table[] = { |
1751 | { | 1755 | { |
1752 | .compatible = "fsl,imx23-gpmi-nand", | 1756 | .compatible = "fsl,imx23-gpmi-nand", |
1753 | .data = (void *)&gpmi_ids[IS_MX23], | 1757 | .data = (void *)&gpmi_devdata_imx23, |
1754 | }, { | 1758 | }, { |
1755 | .compatible = "fsl,imx28-gpmi-nand", | 1759 | .compatible = "fsl,imx28-gpmi-nand", |
1756 | .data = (void *)&gpmi_ids[IS_MX28], | 1760 | .data = (void *)&gpmi_devdata_imx28, |
1757 | }, { | 1761 | }, { |
1758 | .compatible = "fsl,imx6q-gpmi-nand", | 1762 | .compatible = "fsl,imx6q-gpmi-nand", |
1759 | .data = (void *)&gpmi_ids[IS_MX6Q], | 1763 | .data = (void *)&gpmi_devdata_imx6q, |
1760 | }, {} | 1764 | }, {} |
1761 | }; | 1765 | }; |
1762 | MODULE_DEVICE_TABLE(of, gpmi_nand_id_table); | 1766 | MODULE_DEVICE_TABLE(of, gpmi_nand_id_table); |
@@ -1767,18 +1771,18 @@ static int gpmi_nand_probe(struct platform_device *pdev) | |||
1767 | const struct of_device_id *of_id; | 1771 | const struct of_device_id *of_id; |
1768 | int ret; | 1772 | int ret; |
1769 | 1773 | ||
1774 | this = devm_kzalloc(&pdev->dev, sizeof(*this), GFP_KERNEL); | ||
1775 | if (!this) | ||
1776 | return -ENOMEM; | ||
1777 | |||
1770 | of_id = of_match_device(gpmi_nand_id_table, &pdev->dev); | 1778 | of_id = of_match_device(gpmi_nand_id_table, &pdev->dev); |
1771 | if (of_id) { | 1779 | if (of_id) { |
1772 | pdev->id_entry = of_id->data; | 1780 | this->devdata = of_id->data; |
1773 | } else { | 1781 | } else { |
1774 | dev_err(&pdev->dev, "Failed to find the right device id.\n"); | 1782 | dev_err(&pdev->dev, "Failed to find the right device id.\n"); |
1775 | return -ENODEV; | 1783 | return -ENODEV; |
1776 | } | 1784 | } |
1777 | 1785 | ||
1778 | this = devm_kzalloc(&pdev->dev, sizeof(*this), GFP_KERNEL); | ||
1779 | if (!this) | ||
1780 | return -ENOMEM; | ||
1781 | |||
1782 | platform_set_drvdata(pdev, this); | 1786 | platform_set_drvdata(pdev, this); |
1783 | this->pdev = pdev; | 1787 | this->pdev = pdev; |
1784 | this->dev = &pdev->dev; | 1788 | this->dev = &pdev->dev; |
@@ -1823,7 +1827,6 @@ static struct platform_driver gpmi_nand_driver = { | |||
1823 | }, | 1827 | }, |
1824 | .probe = gpmi_nand_probe, | 1828 | .probe = gpmi_nand_probe, |
1825 | .remove = gpmi_nand_remove, | 1829 | .remove = gpmi_nand_remove, |
1826 | .id_table = gpmi_ids, | ||
1827 | }; | 1830 | }; |
1828 | module_platform_driver(gpmi_nand_driver); | 1831 | module_platform_driver(gpmi_nand_driver); |
1829 | 1832 | ||