Commit 6d38af25 authored by Uwe Kleine-König's avatar Uwe Kleine-König Committed by David Woodhouse

mtd: mxc_nand: split some functions to get rid of more nfc_is_vX()

Signed-off-by: default avatarUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: default avatarArtem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent e4303b25
...@@ -151,6 +151,7 @@ struct mxc_nand_devtype_data { ...@@ -151,6 +151,7 @@ struct mxc_nand_devtype_data {
uint16_t (*get_dev_status)(struct mxc_nand_host *); uint16_t (*get_dev_status)(struct mxc_nand_host *);
int (*check_int)(struct mxc_nand_host *); int (*check_int)(struct mxc_nand_host *);
void (*irq_control)(struct mxc_nand_host *, int); void (*irq_control)(struct mxc_nand_host *, int);
u32 (*get_ecc_status)(struct mxc_nand_host *);
}; };
struct mxc_nand_host { struct mxc_nand_host {
...@@ -325,6 +326,21 @@ static void irq_control(struct mxc_nand_host *host, int activate) ...@@ -325,6 +326,21 @@ static void irq_control(struct mxc_nand_host *host, int activate)
} }
} }
static u32 get_ecc_status_v1(struct mxc_nand_host *host)
{
return readw(NFC_V1_V2_ECC_STATUS_RESULT);
}
static u32 get_ecc_status_v2(struct mxc_nand_host *host)
{
return readl(NFC_V1_V2_ECC_STATUS_RESULT);
}
static u32 get_ecc_status_v3(struct mxc_nand_host *host)
{
return readl(NFC_V3_ECC_STATUS_RESULT);
}
static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
{ {
struct mxc_nand_host *host = dev_id; struct mxc_nand_host *host = dev_id;
...@@ -444,13 +460,27 @@ static void send_page_v3(struct mtd_info *mtd, unsigned int ops) ...@@ -444,13 +460,27 @@ static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
wait_op_done(host, false); wait_op_done(host, false);
} }
static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops) static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
{
struct nand_chip *nand_chip = mtd->priv;
struct mxc_nand_host *host = nand_chip->priv;
/* NANDFC buffer 0 is used for page read/write */
writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
writew(ops, NFC_V1_V2_CONFIG2);
/* Wait for operation to complete */
wait_op_done(host, true);
}
static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
{ {
struct nand_chip *nand_chip = mtd->priv; struct nand_chip *nand_chip = mtd->priv;
struct mxc_nand_host *host = nand_chip->priv; struct mxc_nand_host *host = nand_chip->priv;
int bufs, i; int bufs, i;
if (nfc_is_v1() && mtd->writesize > 512) if (mtd->writesize > 512)
bufs = 4; bufs = 4;
else else
bufs = 1; bufs = 1;
...@@ -566,7 +596,7 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat, ...@@ -566,7 +596,7 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
* additional correction. 2-Bit errors cannot be corrected by * additional correction. 2-Bit errors cannot be corrected by
* HW ECC, so we need to return failure * HW ECC, so we need to return failure
*/ */
uint16_t ecc_status = readw(NFC_V1_V2_ECC_STATUS_RESULT); uint16_t ecc_status = get_ecc_status_v1(host);
if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n"); pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
...@@ -591,10 +621,7 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat, ...@@ -591,10 +621,7 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
no_subpages = mtd->writesize >> 9; no_subpages = mtd->writesize >> 9;
if (nfc_is_v21()) ecc_stat = host->devtype_data->get_ecc_status(host);
ecc_stat = readl(NFC_V1_V2_ECC_STATUS_RESULT);
else
ecc_stat = readl(NFC_V3_ECC_STATUS_RESULT);
do { do {
err = ecc_stat & ecc_bit_mask; err = ecc_stat & ecc_bit_mask;
...@@ -821,7 +848,7 @@ static int get_eccsize(struct mtd_info *mtd) ...@@ -821,7 +848,7 @@ static int get_eccsize(struct mtd_info *mtd)
return 8; return 8;
} }
static void preset_v1_v2(struct mtd_info *mtd) static void preset_v1(struct mtd_info *mtd)
{ {
struct nand_chip *nand_chip = mtd->priv; struct nand_chip *nand_chip = mtd->priv;
struct mxc_nand_host *host = nand_chip->priv; struct mxc_nand_host *host = nand_chip->priv;
...@@ -830,13 +857,40 @@ static void preset_v1_v2(struct mtd_info *mtd) ...@@ -830,13 +857,40 @@ static void preset_v1_v2(struct mtd_info *mtd)
if (nand_chip->ecc.mode == NAND_ECC_HW) if (nand_chip->ecc.mode == NAND_ECC_HW)
config1 |= NFC_V1_V2_CONFIG1_ECC_EN; config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
if (nfc_is_v21()) if (!host->irqpending_quirk)
config1 |= NFC_V2_CONFIG1_FP_INT; config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
host->eccsize = 1;
writew(config1, NFC_V1_V2_CONFIG1);
/* preset operation */
/* Unlock the internal RAM Buffer */
writew(0x2, NFC_V1_V2_CONFIG);
/* Blocks to be unlocked */
writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
/* Unlock Block Command for given address range */
writew(0x4, NFC_V1_V2_WRPROT);
}
static void preset_v2(struct mtd_info *mtd)
{
struct nand_chip *nand_chip = mtd->priv;
struct mxc_nand_host *host = nand_chip->priv;
uint16_t config1 = 0;
if (nand_chip->ecc.mode == NAND_ECC_HW)
config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
config1 |= NFC_V2_CONFIG1_FP_INT;
if (!host->irqpending_quirk) if (!host->irqpending_quirk)
config1 |= NFC_V1_V2_CONFIG1_INT_MSK; config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
if (nfc_is_v21() && mtd->writesize) { if (mtd->writesize) {
uint16_t pages_per_block = mtd->erasesize / mtd->writesize; uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
host->eccsize = get_eccsize(mtd); host->eccsize = get_eccsize(mtd);
...@@ -855,20 +909,14 @@ static void preset_v1_v2(struct mtd_info *mtd) ...@@ -855,20 +909,14 @@ static void preset_v1_v2(struct mtd_info *mtd)
writew(0x2, NFC_V1_V2_CONFIG); writew(0x2, NFC_V1_V2_CONFIG);
/* Blocks to be unlocked */ /* Blocks to be unlocked */
if (nfc_is_v21()) { writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0); writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1); writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2); writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3); writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0); writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1); writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2); writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
} else if (nfc_is_v1()) {
writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
} else
BUG();
/* Unlock Block Command for given address range */ /* Unlock Block Command for given address range */
writew(0x4, NFC_V1_V2_WRPROT); writew(0x4, NFC_V1_V2_WRPROT);
...@@ -1056,26 +1104,28 @@ static struct nand_bbt_descr bbt_mirror_descr = { ...@@ -1056,26 +1104,28 @@ static struct nand_bbt_descr bbt_mirror_descr = {
/* v1: i.MX21, i.MX27, i.MX31 */ /* v1: i.MX21, i.MX27, i.MX31 */
static const struct mxc_nand_devtype_data imx21_nand_devtype_data = { static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
.preset = preset_v1_v2, .preset = preset_v1,
.send_cmd = send_cmd_v1_v2, .send_cmd = send_cmd_v1_v2,
.send_addr = send_addr_v1_v2, .send_addr = send_addr_v1_v2,
.send_page = send_page_v1_v2, .send_page = send_page_v1,
.send_read_id = send_read_id_v1_v2, .send_read_id = send_read_id_v1_v2,
.get_dev_status = get_dev_status_v1_v2, .get_dev_status = get_dev_status_v1_v2,
.check_int = check_int_v1_v2, .check_int = check_int_v1_v2,
.irq_control = irq_control_v1_v2, .irq_control = irq_control_v1_v2,
.get_ecc_status = get_ecc_status_v1,
}; };
/* v21: i.MX25, i.MX35 */ /* v21: i.MX25, i.MX35 */
static const struct mxc_nand_devtype_data imx25_nand_devtype_data = { static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
.preset = preset_v1_v2, .preset = preset_v2,
.send_cmd = send_cmd_v1_v2, .send_cmd = send_cmd_v1_v2,
.send_addr = send_addr_v1_v2, .send_addr = send_addr_v1_v2,
.send_page = send_page_v1_v2, .send_page = send_page_v2,
.send_read_id = send_read_id_v1_v2, .send_read_id = send_read_id_v1_v2,
.get_dev_status = get_dev_status_v1_v2, .get_dev_status = get_dev_status_v1_v2,
.check_int = check_int_v1_v2, .check_int = check_int_v1_v2,
.irq_control = irq_control_v1_v2, .irq_control = irq_control_v1_v2,
.get_ecc_status = get_ecc_status_v2,
}; };
/* v3: i.MX51, i.MX53 */ /* v3: i.MX51, i.MX53 */
...@@ -1088,6 +1138,7 @@ static const struct mxc_nand_devtype_data imx51_nand_devtype_data = { ...@@ -1088,6 +1138,7 @@ static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
.get_dev_status = get_dev_status_v3, .get_dev_status = get_dev_status_v3,
.check_int = check_int_v3, .check_int = check_int_v3,
.irq_control = irq_control_v3, .irq_control = irq_control_v3,
.get_ecc_status = get_ecc_status_v3,
}; };
static int __init mxcnd_probe(struct platform_device *pdev) static int __init mxcnd_probe(struct platform_device *pdev)
......
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