aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHuang Shijie <b32955@freescale.com>2014-03-21 01:30:21 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:58:04 -0400
commitad296e2a577d0ef82e15239df776130e6b5f4532 (patch)
tree570897f531cc6ce501d745203e5e3b2369419850
parent9997e70a44328a31aee41911810390832f54c951 (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>
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-lib.c7
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-nand.c55
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-nand.h30
3 files changed, 49 insertions, 43 deletions
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
index dd1df605a1d6..cec019fdbee2 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Freescale GPMI NAND Flash Driver 2 * Freescale GPMI NAND Flash Driver
3 * 3 *
4 * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. 4 * Copyright (C) 2008-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
@@ -861,7 +861,7 @@ static void gpmi_compute_edo_timing(struct gpmi_nand_data *this,
861 struct resources *r = &this->resources; 861 struct resources *r = &this->resources;
862 unsigned long rate = clk_get_rate(r->clock[0]); 862 unsigned long rate = clk_get_rate(r->clock[0]);
863 int mode = this->timing_mode; 863 int mode = this->timing_mode;
864 int dll_threshold = 16; /* in ns */ 864 int dll_threshold = this->devdata->max_chain_delay;
865 unsigned long delay; 865 unsigned long delay;
866 unsigned long clk_period; 866 unsigned long clk_period;
867 int t_rea; 867 int t_rea;
@@ -886,9 +886,6 @@ static void gpmi_compute_edo_timing(struct gpmi_nand_data *this,
886 /* [3] for GPMI_HW_GPMI_CTRL1 */ 886 /* [3] for GPMI_HW_GPMI_CTRL1 */
887 hw->wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY; 887 hw->wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
888 888
889 if (GPMI_IS_MX6Q(this))
890 dll_threshold = 12;
891
892 /* 889 /*
893 * Enlarge 10 times for the numerator and denominator in {3}. 890 * Enlarge 10 times for the numerator and denominator in {3}.
894 * This make us to get more accurate result. 891 * This make us to get more accurate result.
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
56static const struct gpmi_devdata gpmi_devdata_imx23 = {
57 .type = IS_MX23,
58 .bch_max_ecc_strength = 20,
59 .max_chain_delay = 16,
60};
61
62static const struct gpmi_devdata gpmi_devdata_imx28 = {
63 .type = IS_MX28,
64 .bch_max_ecc_strength = 20,
65 .max_chain_delay = 16,
66};
67
68static const struct gpmi_devdata gpmi_devdata_imx6q = {
69 .type = IS_MX6Q,
70 .bch_max_ecc_strength = 40,
71 .max_chain_delay = 12,
72};
73
56static irqreturn_t bch_irq(int irq, void *cookie) 74static 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
1743static 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
1750static const struct of_device_id gpmi_nand_id_table[] = { 1754static 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};
1762MODULE_DEVICE_TABLE(of, gpmi_nand_id_table); 1766MODULE_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};
1828module_platform_driver(gpmi_nand_driver); 1831module_platform_driver(gpmi_nand_driver);
1829 1832
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
index 4c801fa18725..1b7c6aeb97a5 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
@@ -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
@@ -119,11 +119,24 @@ struct nand_timing {
119 int8_t tRHOH_in_ns; 119 int8_t tRHOH_in_ns;
120}; 120};
121 121
122enum gpmi_type {
123 IS_MX23,
124 IS_MX28,
125 IS_MX6Q
126};
127
128struct gpmi_devdata {
129 enum gpmi_type type;
130 int bch_max_ecc_strength;
131 int max_chain_delay; /* See the async EDO mode */
132};
133
122struct gpmi_nand_data { 134struct gpmi_nand_data {
123 /* flags */ 135 /* flags */
124#define GPMI_ASYNC_EDO_ENABLED (1 << 0) 136#define GPMI_ASYNC_EDO_ENABLED (1 << 0)
125#define GPMI_TIMING_INIT_OK (1 << 1) 137#define GPMI_TIMING_INIT_OK (1 << 1)
126 int flags; 138 int flags;
139 const struct gpmi_devdata *devdata;
127 140
128 /* System Interface */ 141 /* System Interface */
129 struct device *dev; 142 struct device *dev;
@@ -281,15 +294,8 @@ extern int gpmi_read_page(struct gpmi_nand_data *,
281#define STATUS_ERASED 0xff 294#define STATUS_ERASED 0xff
282#define STATUS_UNCORRECTABLE 0xfe 295#define STATUS_UNCORRECTABLE 0xfe
283 296
284/* BCH's bit correction capability. */ 297/* Use the devdata to distinguish different Archs. */
285#define MXS_ECC_STRENGTH_MAX 20 /* mx23 and mx28 */ 298#define GPMI_IS_MX23(x) ((x)->devdata->type == IS_MX23)
286#define MX6_ECC_STRENGTH_MAX 40 299#define GPMI_IS_MX28(x) ((x)->devdata->type == IS_MX28)
287 300#define GPMI_IS_MX6Q(x) ((x)->devdata->type == IS_MX6Q)
288/* Use the platform_id to distinguish different Archs. */
289#define IS_MX23 0x0
290#define IS_MX28 0x1
291#define IS_MX6Q 0x2
292#define GPMI_IS_MX23(x) ((x)->pdev->id_entry->driver_data == IS_MX23)
293#define GPMI_IS_MX28(x) ((x)->pdev->id_entry->driver_data == IS_MX28)
294#define GPMI_IS_MX6Q(x) ((x)->pdev->id_entry->driver_data == IS_MX6Q)
295#endif 301#endif