Commit 91f5498e authored by Huang Shijie's avatar Huang Shijie Committed by Brian Norris

mtd: gpmi: add gpmi support for imx6sx

The gpmi's IP for imx6sx is nearly the same as the gpmi's IP for imx6q,
except the following two new features:

     (1) the new BCH contoller has 62-BIT correcting ECC strength
            (The BCH for imx6q only has 40-BIT ECC strength).

     (2) add the hardware Randomizer support.

This patch does the follow changes:

     (1) add a new macro GPMI_IS_MX6SX to represent the imx6sx's gpmi.

     (2) add a new macro GPMI_IS_MX6.
           We use this macro to initialize the same registers for both
         imx6sx and imx6q, and so on.

     (3) add a new gpmi_devdata instance, the gpmi_devdata_imx6sx, for
         imx6sx.
Signed-off-by: default avatarHuang Shijie <b32955@freescale.com>
Signed-off-by: default avatarBrian Norris <computersforpeace@gmail.com>
parent 390e9eac
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
#define MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0 11 #define MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0 11
#define MX6Q_BM_BCH_FLASH0LAYOUT0_ECC0 (0x1f << MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0) #define MX6Q_BM_BCH_FLASH0LAYOUT0_ECC0 (0x1f << MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0)
#define BF_BCH_FLASH0LAYOUT0_ECC0(v, x) \ #define BF_BCH_FLASH0LAYOUT0_ECC0(v, x) \
(GPMI_IS_MX6Q(x) \ (GPMI_IS_MX6(x) \
? (((v) << MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0) \ ? (((v) << MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0) \
& MX6Q_BM_BCH_FLASH0LAYOUT0_ECC0) \ & MX6Q_BM_BCH_FLASH0LAYOUT0_ECC0) \
: (((v) << BP_BCH_FLASH0LAYOUT0_ECC0) \ : (((v) << BP_BCH_FLASH0LAYOUT0_ECC0) \
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
#define MX6Q_BM_BCH_FLASH0LAYOUT0_GF_13_14 \ #define MX6Q_BM_BCH_FLASH0LAYOUT0_GF_13_14 \
(0x1 << MX6Q_BP_BCH_FLASH0LAYOUT0_GF_13_14) (0x1 << MX6Q_BP_BCH_FLASH0LAYOUT0_GF_13_14)
#define BF_BCH_FLASH0LAYOUT0_GF(v, x) \ #define BF_BCH_FLASH0LAYOUT0_GF(v, x) \
((GPMI_IS_MX6Q(x) && ((v) == 14)) \ ((GPMI_IS_MX6(x) && ((v) == 14)) \
? (((1) << MX6Q_BP_BCH_FLASH0LAYOUT0_GF_13_14) \ ? (((1) << MX6Q_BP_BCH_FLASH0LAYOUT0_GF_13_14) \
& MX6Q_BM_BCH_FLASH0LAYOUT0_GF_13_14) \ & MX6Q_BM_BCH_FLASH0LAYOUT0_GF_13_14) \
: 0 \ : 0 \
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
#define MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE \ #define MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE \
(0x3ff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE) (0x3ff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE)
#define BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(v, x) \ #define BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(v, x) \
(GPMI_IS_MX6Q(x) \ (GPMI_IS_MX6(x) \
? (((v) >> 2) & MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) \ ? (((v) >> 2) & MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) \
: ((v) & BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) \ : ((v) & BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) \
) )
...@@ -96,7 +96,7 @@ ...@@ -96,7 +96,7 @@
#define MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN 11 #define MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN 11
#define MX6Q_BM_BCH_FLASH0LAYOUT1_ECCN (0x1f << MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN) #define MX6Q_BM_BCH_FLASH0LAYOUT1_ECCN (0x1f << MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN)
#define BF_BCH_FLASH0LAYOUT1_ECCN(v, x) \ #define BF_BCH_FLASH0LAYOUT1_ECCN(v, x) \
(GPMI_IS_MX6Q(x) \ (GPMI_IS_MX6(x) \
? (((v) << MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN) \ ? (((v) << MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN) \
& MX6Q_BM_BCH_FLASH0LAYOUT1_ECCN) \ & MX6Q_BM_BCH_FLASH0LAYOUT1_ECCN) \
: (((v) << BP_BCH_FLASH0LAYOUT1_ECCN) \ : (((v) << BP_BCH_FLASH0LAYOUT1_ECCN) \
...@@ -107,7 +107,7 @@ ...@@ -107,7 +107,7 @@
#define MX6Q_BM_BCH_FLASH0LAYOUT1_GF_13_14 \ #define MX6Q_BM_BCH_FLASH0LAYOUT1_GF_13_14 \
(0x1 << MX6Q_BP_BCH_FLASH0LAYOUT1_GF_13_14) (0x1 << MX6Q_BP_BCH_FLASH0LAYOUT1_GF_13_14)
#define BF_BCH_FLASH0LAYOUT1_GF(v, x) \ #define BF_BCH_FLASH0LAYOUT1_GF(v, x) \
((GPMI_IS_MX6Q(x) && ((v) == 14)) \ ((GPMI_IS_MX6(x) && ((v) == 14)) \
? (((1) << MX6Q_BP_BCH_FLASH0LAYOUT1_GF_13_14) \ ? (((1) << MX6Q_BP_BCH_FLASH0LAYOUT1_GF_13_14) \
& MX6Q_BM_BCH_FLASH0LAYOUT1_GF_13_14) \ & MX6Q_BM_BCH_FLASH0LAYOUT1_GF_13_14) \
: 0 \ : 0 \
...@@ -119,7 +119,7 @@ ...@@ -119,7 +119,7 @@
#define MX6Q_BM_BCH_FLASH0LAYOUT1_DATAN_SIZE \ #define MX6Q_BM_BCH_FLASH0LAYOUT1_DATAN_SIZE \
(0x3ff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) (0x3ff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE)
#define BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(v, x) \ #define BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(v, x) \
(GPMI_IS_MX6Q(x) \ (GPMI_IS_MX6(x) \
? (((v) >> 2) & MX6Q_BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) \ ? (((v) >> 2) & MX6Q_BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) \
: ((v) & BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) \ : ((v) & BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) \
) )
......
...@@ -971,7 +971,7 @@ int gpmi_extra_init(struct gpmi_nand_data *this) ...@@ -971,7 +971,7 @@ int gpmi_extra_init(struct gpmi_nand_data *this)
struct nand_chip *chip = &this->nand; struct nand_chip *chip = &this->nand;
/* Enable the asynchronous EDO feature. */ /* Enable the asynchronous EDO feature. */
if (GPMI_IS_MX6Q(this) && chip->onfi_version) { if (GPMI_IS_MX6(this) && chip->onfi_version) {
int mode = onfi_get_async_timing_mode(chip); int mode = onfi_get_async_timing_mode(chip);
/* We only support the timing mode 4 and mode 5. */ /* We only support the timing mode 4 and mode 5. */
...@@ -1093,12 +1093,12 @@ int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip) ...@@ -1093,12 +1093,12 @@ int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip)
if (GPMI_IS_MX23(this)) { if (GPMI_IS_MX23(this)) {
mask = MX23_BM_GPMI_DEBUG_READY0 << chip; mask = MX23_BM_GPMI_DEBUG_READY0 << chip;
reg = readl(r->gpmi_regs + HW_GPMI_DEBUG); reg = readl(r->gpmi_regs + HW_GPMI_DEBUG);
} else if (GPMI_IS_MX28(this) || GPMI_IS_MX6Q(this)) { } else if (GPMI_IS_MX28(this) || GPMI_IS_MX6(this)) {
/* /*
* In the imx6, all the ready/busy pins are bound * In the imx6, all the ready/busy pins are bound
* together. So we only need to check chip 0. * together. So we only need to check chip 0.
*/ */
if (GPMI_IS_MX6Q(this)) if (GPMI_IS_MX6(this))
chip = 0; chip = 0;
/* MX28 shares the same R/B register as MX6Q. */ /* MX28 shares the same R/B register as MX6Q. */
......
...@@ -71,6 +71,12 @@ static const struct gpmi_devdata gpmi_devdata_imx6q = { ...@@ -71,6 +71,12 @@ static const struct gpmi_devdata gpmi_devdata_imx6q = {
.max_chain_delay = 12, .max_chain_delay = 12,
}; };
static const struct gpmi_devdata gpmi_devdata_imx6sx = {
.type = IS_MX6SX,
.bch_max_ecc_strength = 62,
.max_chain_delay = 12,
};
static irqreturn_t bch_irq(int irq, void *cookie) static irqreturn_t bch_irq(int irq, void *cookie)
{ {
struct gpmi_nand_data *this = cookie; struct gpmi_nand_data *this = cookie;
...@@ -583,7 +589,7 @@ static int gpmi_get_clks(struct gpmi_nand_data *this) ...@@ -583,7 +589,7 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
} }
/* Get extra clocks */ /* Get extra clocks */
if (GPMI_IS_MX6Q(this)) if (GPMI_IS_MX6(this))
extra_clks = extra_clks_for_mx6q; extra_clks = extra_clks_for_mx6q;
if (!extra_clks) if (!extra_clks)
return 0; return 0;
...@@ -601,9 +607,9 @@ static int gpmi_get_clks(struct gpmi_nand_data *this) ...@@ -601,9 +607,9 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
r->clock[i] = clk; r->clock[i] = clk;
} }
if (GPMI_IS_MX6Q(this)) if (GPMI_IS_MX6(this))
/* /*
* Set the default value for the gpmi clock in mx6q: * Set the default value for the gpmi clock.
* *
* If you want to use the ONFI nand which is in the * If you want to use the ONFI nand which is in the
* Synchronous Mode, you should change the clock as you need. * Synchronous Mode, you should change the clock as you need.
...@@ -1666,7 +1672,7 @@ static int gpmi_init_last(struct gpmi_nand_data *this) ...@@ -1666,7 +1672,7 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
* (1) the chip is imx6, and * (1) the chip is imx6, and
* (2) the size of the ECC parity is byte aligned. * (2) the size of the ECC parity is byte aligned.
*/ */
if (GPMI_IS_MX6Q(this) && if (GPMI_IS_MX6(this) &&
((bch_geo->gf_len * bch_geo->ecc_strength) % 8) == 0) { ((bch_geo->gf_len * bch_geo->ecc_strength) % 8) == 0) {
ecc->read_subpage = gpmi_ecc_read_subpage; ecc->read_subpage = gpmi_ecc_read_subpage;
chip->options |= NAND_SUBPAGE_READ; chip->options |= NAND_SUBPAGE_READ;
...@@ -1722,7 +1728,7 @@ static int gpmi_nand_init(struct gpmi_nand_data *this) ...@@ -1722,7 +1728,7 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
if (ret) if (ret)
goto err_out; goto err_out;
ret = nand_scan_ident(mtd, GPMI_IS_MX6Q(this) ? 2 : 1, NULL); ret = nand_scan_ident(mtd, GPMI_IS_MX6(this) ? 2 : 1, NULL);
if (ret) if (ret)
goto err_out; goto err_out;
...@@ -1761,6 +1767,9 @@ static const struct of_device_id gpmi_nand_id_table[] = { ...@@ -1761,6 +1767,9 @@ static const struct of_device_id gpmi_nand_id_table[] = {
}, { }, {
.compatible = "fsl,imx6q-gpmi-nand", .compatible = "fsl,imx6q-gpmi-nand",
.data = (void *)&gpmi_devdata_imx6q, .data = (void *)&gpmi_devdata_imx6q,
}, {
.compatible = "fsl,imx6sx-gpmi-nand",
.data = (void *)&gpmi_devdata_imx6sx,
}, {} }, {}
}; };
MODULE_DEVICE_TABLE(of, gpmi_nand_id_table); MODULE_DEVICE_TABLE(of, gpmi_nand_id_table);
......
...@@ -122,7 +122,8 @@ struct nand_timing { ...@@ -122,7 +122,8 @@ struct nand_timing {
enum gpmi_type { enum gpmi_type {
IS_MX23, IS_MX23,
IS_MX28, IS_MX28,
IS_MX6Q IS_MX6Q,
IS_MX6SX
}; };
struct gpmi_devdata { struct gpmi_devdata {
...@@ -298,4 +299,7 @@ extern int gpmi_read_page(struct gpmi_nand_data *, ...@@ -298,4 +299,7 @@ extern int gpmi_read_page(struct gpmi_nand_data *,
#define GPMI_IS_MX23(x) ((x)->devdata->type == IS_MX23) #define GPMI_IS_MX23(x) ((x)->devdata->type == IS_MX23)
#define GPMI_IS_MX28(x) ((x)->devdata->type == IS_MX28) #define GPMI_IS_MX28(x) ((x)->devdata->type == IS_MX28)
#define GPMI_IS_MX6Q(x) ((x)->devdata->type == IS_MX6Q) #define GPMI_IS_MX6Q(x) ((x)->devdata->type == IS_MX6Q)
#define GPMI_IS_MX6SX(x) ((x)->devdata->type == IS_MX6SX)
#define GPMI_IS_MX6(x) (GPMI_IS_MX6Q(x) || GPMI_IS_MX6SX(x))
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment