From: John Jacques <john.jacq...@lsi.com> Signed-off-by: John Jacques <john.jacq...@lsi.com> --- drivers/mtd/nand/lsi_acp_nand.c | 174 +++++++++++++++++++--------------------- 1 file changed, 84 insertions(+), 90 deletions(-)
diff --git a/drivers/mtd/nand/lsi_acp_nand.c b/drivers/mtd/nand/lsi_acp_nand.c index dbb95b5..3f9e79d 100644 --- a/drivers/mtd/nand/lsi_acp_nand.c +++ b/drivers/mtd/nand/lsi_acp_nand.c @@ -342,16 +342,11 @@ _WRITEL(const char *file, int line, unsigned long value, unsigned long address) */ static void *gpreg_base; - -#define LSI_NAND_PECC_BUSY_REGISTER (gpreg_base + 0x00c) - -#ifdef CONFIG_ACP_X1V1 -#define LSI_NAND_PECC_BUSY_MASK (1 << 25) -#else -#define LSI_NAND_PECC_BUSY_MASK (1 << 28) -#endif +static void *pecc_busy_register; +static unsigned long pecc_busy_mask; #define MAX_READ_BUF 16 + /* ---------------------------------------------------------------------- MTD structures @@ -602,17 +597,6 @@ lsi_nand_command(struct mtd_info *mtd, unsigned int command, unsigned int status = 0; struct lsi_nand_private *priv = &lsi_nand_private; struct device_node *np = NULL; - void *busy_reg; - unsigned long busy_mask; - - np = of_find_compatible_node(NULL, NULL, "lsi,acp3500"); - if (NULL != np) { - busy_reg = (gpreg_base + 0x80); - busy_mask = (1 << 20); - } else { - busy_reg = LSI_NAND_PECC_BUSY_REGISTER; - busy_mask = LSI_NAND_PECC_BUSY_MASK; - } DEBUG_PRINT("command=0x%x\n", command); command &= 0xff; @@ -717,8 +701,8 @@ lsi_nand_command(struct mtd_info *mtd, unsigned int command, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); do { udelay(chip->chip_delay); - status = READL((void *)busy_reg); - } while (0 != (status & busy_mask)); + status = READL((void *)pecc_busy_register); + } while (0 != (status & pecc_busy_mask)); /* wait until CHIP_BUSY goes low */ do { @@ -815,17 +799,6 @@ static int lsi_nand_wait(struct mtd_info *mtd, struct nand_chip *chip) unsigned long status = 0; loff_t offset = 0; struct device_node *np = NULL; - void *busy_reg; - unsigned long busy_mask; - - np = of_find_compatible_node(NULL, NULL, "lsi,acp3500"); - if (NULL != np) { - busy_reg = (gpreg_base + 0x80); - busy_mask = (1 << 20); - } else { - busy_reg = LSI_NAND_PECC_BUSY_REGISTER; - busy_mask = LSI_NAND_PECC_BUSY_MASK; - } /* When reading or writing, wait for the @@ -834,9 +807,9 @@ static int lsi_nand_wait(struct mtd_info *mtd, struct nand_chip *chip) #ifdef NOT_USED if (FL_READING == chip->state || FL_WRITING == chip->state) { for (;;) { - status = READL((void *)busy_reg); + status = READL((void *)pecc_busy_register); - if (0 == (status & busy_mask)) + if (0 == (status & pecc_busy_mask)) break; udelay(chip->chip_delay); @@ -844,9 +817,9 @@ static int lsi_nand_wait(struct mtd_info *mtd, struct nand_chip *chip) } #else for (;;) { - status = READL((void *)busy_reg); + status = READL((void *)pecc_busy_register); - if (0 == (status & busy_mask)) + if (0 == (status & pecc_busy_mask)) break; udelay(chip->chip_delay); @@ -3455,7 +3428,16 @@ lsi_nand_init(void) struct device_node *np = NULL; struct mtd_part_parser_data ppdata; static const char *part_probe_types[] - = { "cmdlinepart", "ofpart", NULL }; + = { "cmdlinepart", "ofpart", NULL }; + const u32 *reg; + int reglen; + u64 nand_address; + unsigned long nand_length; + u64 gpreg_address; + unsigned long gpreg_length; + const u32 *enabled; + unsigned long cr; + unsigned long cr_save; memset(&ppdata, 0, sizeof(ppdata)); @@ -3464,45 +3446,62 @@ lsi_nand_init(void) while (np && !of_device_is_compatible(np, "acp-nand")) np = of_find_node_by_type(np, "nand"); - if (np) { - const u32 *reg; - int reglen; - u64 nand_address; - unsigned long nand_length; - u64 gpreg_address; - unsigned long gpreg_length; - const u32 *enabled; + if (NULL == np) { + printk(KERN_ERR "No NAND Nodes in Device Tree\n"); - enabled = of_get_property(np, "enabled", NULL); + return -1; + } - if (!enabled || (enabled && (0 == *enabled))) { - pr_err("ACP NAND Controller Isn't Enabled.\n"); - return -ENODEV; - } + enabled = of_get_property(np, "enabled", NULL); - reg = of_get_property(np, "reg", ®len); - - if (reg && (16 == reglen)) { - nand_address = of_translate_address(np, reg); - nand_length = reg[1]; - reg += 2; - gpreg_address = of_translate_address(np, reg); - gpreg_length = reg[1]; - pr_info("nand_address=0x%08llx nand_length=0x%lx\n" - "gpreg_address=0x%08llx gpreg_length=0x%lx\n", - nand_address, nand_length, - gpreg_address, gpreg_length); - nand_base = ioremap(nand_address, nand_length); - gpreg_base = ioremap(gpreg_address, gpreg_length); - } else { - return -1; - } + if (!enabled || (enabled && (0 == *enabled))) { + pr_err("ACP NAND Controller Isn't Enabled.\n"); + return -ENODEV; + } - ppdata.of_node = np; + reg = of_get_property(np, "reg", ®len); + + if (reg && (16 == reglen)) { + nand_address = of_translate_address(np, reg); + nand_length = reg[1]; + reg += 2; + gpreg_address = of_translate_address(np, reg); + gpreg_length = reg[1]; + pr_info("nand_address=0x%08llx nand_length=0x%lx\n" + "gpreg_address=0x%08llx gpreg_length=0x%lx\n", + nand_address, nand_length, + gpreg_address, gpreg_length); + nand_base = ioremap(nand_address, nand_length); + gpreg_base = ioremap(gpreg_address, gpreg_length); } else { - pr_info("ACP NAND: Using Static Addresses.\n"); - nand_base = ioremap(0x002000440000ULL, 0x20000); - gpreg_base = ioremap(0x00200040c000ULL, 0x1000); + return -1; + } + + ppdata.of_node = np; + + /* + Determine the Axxia system type. + + The ECC status register and mask are different on 344x, 342x, 35xx... + */ + + if (of_machine_is_compatible("lsi,acp3500")) { + pecc_busy_register = (gpreg_base + 0x8c); + pecc_busy_mask = (1 << 20); + } else { + if (of_machine_is_compatible("lsi,acp3420")) { + pecc_busy_register = (gpreg_base + 0xc); + pecc_busy_mask = (1 << 28); + } else { + if (of_machine_is_compatible("lsi,acp3440")) { + pecc_busy_register = (gpreg_base + 0xc); + pecc_busy_mask = (1 << 28); + } else { + printk(KERN_ERR "Unsupported NAND Target\n"); + + return -1; + } + } } /* @@ -3513,25 +3512,20 @@ lsi_nand_init(void) case and aren't in the EP501G1 case. */ - { - unsigned long cr; - unsigned long cr_save; - - cr = cr_save = READL((void *)(nand_base + NAND_CONFIG_REG)); - cr = 0x2038; - WRITEL(cr, (void *)(nand_base + EP501_NAND_CONFIG_REG)); - cr = READL((void *)nand_base + EP501_NAND_CONFIG_REG); - WRITEL(cr_save, (void *)(nand_base + EP501_NAND_CONFIG_REG)); - - if (0 == (cr & 0x2038)) - lsi_nand_type = LSI_NAND_EP501G1; - else if (0x38 == (cr & 0x2038)) - lsi_nand_type = LSI_NAND_EP501; - else if (0x2000 == (cr & 0x2038)) - lsi_nand_type = LSI_NAND_EP501G3; - else - lsi_nand_type = LSI_NAND_NONE; - } + cr = cr_save = READL((void *)(nand_base + NAND_CONFIG_REG)); + cr = 0x2038; + WRITEL(cr, (void *)(nand_base + EP501_NAND_CONFIG_REG)); + cr = READL((void *)nand_base + EP501_NAND_CONFIG_REG); + WRITEL(cr_save, (void *)(nand_base + EP501_NAND_CONFIG_REG)); + + if (0 == (cr & 0x2038)) + lsi_nand_type = LSI_NAND_EP501G1; + else if (0x38 == (cr & 0x2038)) + lsi_nand_type = LSI_NAND_EP501; + else if (0x2000 == (cr & 0x2038)) + lsi_nand_type = LSI_NAND_EP501G3; + else + lsi_nand_type = LSI_NAND_NONE; switch (lsi_nand_type) { case LSI_NAND_EP501: -- 1.8.1.4 -- _______________________________________________ linux-yocto mailing list linux-yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/linux-yocto