From b014b833bd627d27542b50e71df9cf0628f241e7 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Thu, 19 Dec 2019 02:27:42 -0700 Subject: mtd: nand: Move arasan nand driver to driver model Make changes to arasan nand driver to move it to driver model. Select DM_MTD if arasan nand driver is selected. Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek --- drivers/mtd/nand/raw/Kconfig | 1 + drivers/mtd/nand/raw/arasan_nfc.c | 52 +++++++++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index 16165f88390..ec17653f414 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -236,6 +236,7 @@ endif config NAND_ARASAN bool "Configure Arasan Nand" select SYS_NAND_SELF_INIT + select DM_MTD imply CMD_NAND help This enables Nand driver support for Arasan nand flash diff --git a/drivers/mtd/nand/raw/arasan_nfc.c b/drivers/mtd/nand/raw/arasan_nfc.c index 2cd3f64dc63..c2f7b3a42ee 100644 --- a/drivers/mtd/nand/raw/arasan_nfc.c +++ b/drivers/mtd/nand/raw/arasan_nfc.c @@ -15,14 +15,19 @@ #include #include #include +#include #include -struct arasan_nand_info { - void __iomem *nand_base; +struct nand_config { u32 page; bool on_die_ecc_enabled; }; +struct arasan_nand_info { + struct udevice *dev; + struct nand_chip nand_chip; +}; + struct nand_regs { u32 pkt_reg; u32 memadr_reg1; @@ -259,8 +264,6 @@ static u32 buf_index; static struct nand_ecclayout nand_oob; -static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE]; - static void arasan_nand_select_chip(struct mtd_info *mtd, int chip) { u32 reg_val; @@ -323,7 +326,7 @@ static u8 arasan_nand_get_addrcycle(struct mtd_info *mtd) static int arasan_nand_read_page(struct mtd_info *mtd, u8 *buf, u32 size) { struct nand_chip *chip = mtd_to_nand(mtd); - struct arasan_nand_info *nand = nand_get_controller_data(chip); + struct nand_config *nand = nand_get_controller_data(chip); u32 reg_val, i, pktsize, pktnum; u32 *bufptr = (u32 *)buf; u32 timeout; @@ -505,7 +508,7 @@ static int arasan_nand_write_page_hwecc(struct mtd_info *mtd, u32 size = mtd->writesize; u32 rdcount = 0; u8 column_addr_cycles; - struct arasan_nand_info *nand = nand_get_controller_data(chip); + struct nand_config *nand = nand_get_controller_data(chip); if (chip->ecc_step_ds >= ARASAN_NAND_PKTSIZE_1K) pktsize = ARASAN_NAND_PKTSIZE_1K; @@ -1033,7 +1036,7 @@ static void arasan_nand_cmd_function(struct mtd_info *mtd, unsigned int command, { u32 i, ret = 0; struct nand_chip *chip = mtd_to_nand(mtd); - struct arasan_nand_info *nand = nand_get_controller_data(chip); + struct nand_config *nand = nand_get_controller_data(chip); curr_cmd = NULL; writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, @@ -1088,7 +1091,7 @@ static void arasan_nand_cmd_function(struct mtd_info *mtd, unsigned int command, static void arasan_check_ondie(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct arasan_nand_info *nand = nand_get_controller_data(nand_chip); + struct nand_config *nand = nand_get_controller_data(nand_chip); u8 maf_id, dev_id; u8 get_feature[4]; u8 set_feature[4] = {ENABLE_ONDIE_ECC, 0x00, 0x00, 0x00}; @@ -1184,19 +1187,20 @@ static int arasan_nand_ecc_init(struct mtd_info *mtd) return 0; } -static int arasan_nand_init(struct nand_chip *nand_chip, int devnum) +static int arasan_probe(struct udevice *dev) { - struct arasan_nand_info *nand; + struct arasan_nand_info *arasan = dev_get_priv(dev); + struct nand_chip *nand_chip = &arasan->nand_chip; + struct nand_config *nand; struct mtd_info *mtd; int err = -1; - nand = calloc(1, sizeof(struct arasan_nand_info)); + nand = calloc(1, sizeof(struct nand_config)); if (!nand) { printf("%s: failed to allocate\n", __func__); return err; } - nand->nand_base = arasan_nand_base; mtd = nand_to_mtd(nand_chip); nand_set_controller_data(nand_chip, nand); @@ -1253,7 +1257,7 @@ static int arasan_nand_init(struct nand_chip *nand_chip, int devnum) goto fail; } - if (nand_register(devnum, mtd)) { + if (nand_register(0, mtd)) { printf("Nand Register Fail\n"); goto fail; } @@ -1264,10 +1268,26 @@ fail: return err; } +static const struct udevice_id arasan_nand_dt_ids[] = { + {.compatible = "arasan,nfc-v3p10",}, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(arasan_nand) = { + .name = "arasan-nand", + .id = UCLASS_MTD, + .of_match = arasan_nand_dt_ids, + .probe = arasan_probe, + .priv_auto_alloc_size = sizeof(struct arasan_nand_info), +}; + void board_nand_init(void) { - struct nand_chip *nand = &nand_chip[0]; + struct udevice *dev; + int ret; - if (arasan_nand_init(nand, 0)) - puts("NAND init failed\n"); + ret = uclass_get_device_by_driver(UCLASS_MTD, + DM_GET_DRIVER(arasan_nand), &dev); + if (ret && ret != -ENODEV) + pr_err("Failed to initialize %s. (error %d)\n", dev->name, ret); } -- cgit v1.2.3 From 3dd0f8cccd6dae9740df1755ab261e72355a892d Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Thu, 19 Dec 2019 02:27:43 -0700 Subject: mtd: nand: Remove hardcoded base address of nand Remove hardcoded base address of nand and replace it with the value taken from device tree. Remove base address from header file too. Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek --- arch/arm/mach-zynqmp/include/mach/hardware.h | 2 - drivers/mtd/nand/raw/arasan_nfc.c | 322 +++++++++++++++------------ 2 files changed, 174 insertions(+), 150 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-zynqmp/include/mach/hardware.h b/arch/arm/mach-zynqmp/include/mach/hardware.h index a0d776166d0..fd361c5ce8a 100644 --- a/arch/arm/mach-zynqmp/include/mach/hardware.h +++ b/arch/arm/mach-zynqmp/include/mach/hardware.h @@ -7,8 +7,6 @@ #ifndef _ASM_ARCH_HARDWARE_H #define _ASM_ARCH_HARDWARE_H -#define ARASAN_NAND_BASEADDR 0xFF100000 - #define ZYNQMP_TCM_BASE_ADDR 0xFFE00000 #define ZYNQMP_TCM_SIZE 0x40000 diff --git a/drivers/mtd/nand/raw/arasan_nfc.c b/drivers/mtd/nand/raw/arasan_nfc.c index c2f7b3a42ee..d1b1a4263a2 100644 --- a/drivers/mtd/nand/raw/arasan_nfc.c +++ b/drivers/mtd/nand/raw/arasan_nfc.c @@ -23,8 +23,14 @@ struct nand_config { bool on_die_ecc_enabled; }; +struct nand_drv { + struct nand_regs *reg; + struct nand_config config; +}; + struct arasan_nand_info { struct udevice *dev; + struct nand_drv nand_ctrl; struct nand_chip nand_chip; }; @@ -59,8 +65,6 @@ struct nand_regs { u32 data_if_reg; }; -#define arasan_nand_base ((struct nand_regs __iomem *)ARASAN_NAND_BASEADDR) - struct arasan_nand_command_format { u8 cmd1; u8 cmd2; @@ -266,26 +270,30 @@ static struct nand_ecclayout nand_oob; static void arasan_nand_select_chip(struct mtd_info *mtd, int chip) { + struct nand_chip *nand_chip = mtd_to_nand(mtd); + struct nand_drv *info = nand_get_controller_data(nand_chip); u32 reg_val; - reg_val = readl(&arasan_nand_base->memadr_reg2); + reg_val = readl(&info->reg->memadr_reg2); if (chip == 0) { reg_val &= ~ARASAN_NAND_MEM_ADDR2_CS0_MASK; - writel(reg_val, &arasan_nand_base->memadr_reg2); + writel(reg_val, &info->reg->memadr_reg2); } else if (chip == 1) { reg_val |= ARASAN_NAND_MEM_ADDR2_CS1_MASK; - writel(reg_val, &arasan_nand_base->memadr_reg2); + writel(reg_val, &info->reg->memadr_reg2); } } -static void arasan_nand_enable_ecc(void) +static void arasan_nand_enable_ecc(struct mtd_info *mtd) { + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_drv *info = nand_get_controller_data(chip); u32 reg_val; - reg_val = readl(&arasan_nand_base->cmd_reg); + reg_val = readl(&info->reg->cmd_reg); reg_val |= ARASAN_NAND_CMD_ECC_ON_MASK; - writel(reg_val, &arasan_nand_base->cmd_reg); + writel(reg_val, &info->reg->cmd_reg); } static u8 arasan_nand_get_addrcycle(struct mtd_info *mtd) @@ -326,7 +334,8 @@ static u8 arasan_nand_get_addrcycle(struct mtd_info *mtd) static int arasan_nand_read_page(struct mtd_info *mtd, u8 *buf, u32 size) { struct nand_chip *chip = mtd_to_nand(mtd); - struct nand_config *nand = nand_get_controller_data(chip); + struct nand_drv *info = nand_get_controller_data(chip); + struct nand_config *nand = &info->config; u32 reg_val, i, pktsize, pktnum; u32 *bufptr = (u32 *)buf; u32 timeout; @@ -343,20 +352,20 @@ static int arasan_nand_read_page(struct mtd_info *mtd, u8 *buf, u32 size) else pktnum = size/pktsize; - reg_val = readl(&arasan_nand_base->intsts_enr); + reg_val = readl(&info->reg->intsts_enr); reg_val |= ARASAN_NAND_INT_STS_ERR_EN_MASK | ARASAN_NAND_INT_STS_MUL_BIT_ERR_MASK; - writel(reg_val, &arasan_nand_base->intsts_enr); + writel(reg_val, &info->reg->intsts_enr); - reg_val = readl(&arasan_nand_base->pkt_reg); + reg_val = readl(&info->reg->pkt_reg); reg_val &= ~(ARASAN_NAND_PKT_REG_PKT_CNT_MASK | ARASAN_NAND_PKT_REG_PKT_SIZE_MASK); reg_val |= (pktnum << ARASAN_NAND_PKT_REG_PKT_CNT_SHFT) | pktsize; - writel(reg_val, &arasan_nand_base->pkt_reg); + writel(reg_val, &info->reg->pkt_reg); if (!nand->on_die_ecc_enabled) { - arasan_nand_enable_ecc(); + arasan_nand_enable_ecc(mtd); addr_cycles = arasan_nand_get_addrcycle(mtd); if (addr_cycles == ARASAN_NAND_INVALID_ADDR_CYCL) return ERR_ADDR_CYCLE; @@ -364,13 +373,13 @@ static int arasan_nand_read_page(struct mtd_info *mtd, u8 *buf, u32 size) writel((NAND_CMD_RNDOUTSTART << ARASAN_NAND_CMD_CMD2_SHIFT) | NAND_CMD_RNDOUT | (addr_cycles << ARASAN_NAND_CMD_ADDR_CYCL_SHIFT), - &arasan_nand_base->ecc_sprcmd_reg); + &info->reg->ecc_sprcmd_reg); } - writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg); + writel(curr_cmd->pgm, &info->reg->pgm_reg); while (rdcount < pktnum) { timeout = ARASAN_NAND_POLL_TIMEOUT; - while (!(readl(&arasan_nand_base->intsts_reg) & + while (!(readl(&info->reg->intsts_reg) & ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK) && timeout) { udelay(1); timeout--; @@ -383,20 +392,20 @@ static int arasan_nand_read_page(struct mtd_info *mtd, u8 *buf, u32 size) rdcount++; if (pktnum == rdcount) { - reg_val = readl(&arasan_nand_base->intsts_enr); + reg_val = readl(&info->reg->intsts_enr); reg_val |= ARASAN_NAND_INT_STS_XFR_CMPLT_MASK; - writel(reg_val, &arasan_nand_base->intsts_enr); + writel(reg_val, &info->reg->intsts_enr); } else { - reg_val = readl(&arasan_nand_base->intsts_enr); + reg_val = readl(&info->reg->intsts_enr); writel(reg_val | ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK, - &arasan_nand_base->intsts_enr); + &info->reg->intsts_enr); } - reg_val = readl(&arasan_nand_base->intsts_reg); + reg_val = readl(&info->reg->intsts_reg); writel(reg_val | ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK, - &arasan_nand_base->intsts_reg); + &info->reg->intsts_reg); for (i = 0; i < pktsize/4; i++) - bufptr[i] = readl(&arasan_nand_base->buf_dataport); + bufptr[i] = readl(&info->reg->buf_dataport); bufptr += pktsize/4; @@ -405,12 +414,12 @@ static int arasan_nand_read_page(struct mtd_info *mtd, u8 *buf, u32 size) break; writel(ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK, - &arasan_nand_base->intsts_enr); + &info->reg->intsts_enr); } timeout = ARASAN_NAND_POLL_TIMEOUT; - while (!(readl(&arasan_nand_base->intsts_reg) & + while (!(readl(&info->reg->intsts_reg) & ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) { udelay(1); timeout--; @@ -420,21 +429,21 @@ static int arasan_nand_read_page(struct mtd_info *mtd, u8 *buf, u32 size) return -ETIMEDOUT; } - reg_val = readl(&arasan_nand_base->intsts_enr); + reg_val = readl(&info->reg->intsts_enr); writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, - &arasan_nand_base->intsts_enr); - reg_val = readl(&arasan_nand_base->intsts_reg); + &info->reg->intsts_enr); + reg_val = readl(&info->reg->intsts_reg); writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, - &arasan_nand_base->intsts_reg); + &info->reg->intsts_reg); if (!nand->on_die_ecc_enabled) { - if (readl(&arasan_nand_base->intsts_reg) & + if (readl(&info->reg->intsts_reg) & ARASAN_NAND_INT_STS_MUL_BIT_ERR_MASK) { printf("arasan rd_page:sbiterror\n"); return -1; } - if (readl(&arasan_nand_base->intsts_reg) & + if (readl(&info->reg->intsts_reg) & ARASAN_NAND_INT_STS_ERR_EN_MASK) { mtd->ecc_stats.failed++; printf("arasan rd_page:multibiterror\n"); @@ -458,9 +467,11 @@ static int arasan_nand_read_page_hwecc(struct mtd_info *mtd, return status; } -static void arasan_nand_fill_tx(const u8 *buf, int len) +static void arasan_nand_fill_tx(struct mtd_info *mtd, const u8 *buf, int len) { - u32 __iomem *nand = &arasan_nand_base->buf_dataport; + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_drv *info = nand_get_controller_data(chip); + u32 __iomem *nand = &info->reg->buf_dataport; if (((unsigned long)buf & 0x3) != 0) { if (((unsigned long)buf & 0x1) != 0) { @@ -502,13 +513,14 @@ static int arasan_nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, const u8 *buf, int oob_required, int page) { + struct nand_drv *info = nand_get_controller_data(chip); + struct nand_config *nand = &info->config; u32 reg_val, i, pktsize, pktnum; const u32 *bufptr = (const u32 *)buf; u32 timeout = ARASAN_NAND_POLL_TIMEOUT; u32 size = mtd->writesize; u32 rdcount = 0; u8 column_addr_cycles; - struct nand_config *nand = nand_get_controller_data(chip); if (chip->ecc_step_ds >= ARASAN_NAND_PKTSIZE_1K) pktsize = ARASAN_NAND_PKTSIZE_1K; @@ -520,25 +532,25 @@ static int arasan_nand_write_page_hwecc(struct mtd_info *mtd, else pktnum = size/pktsize; - reg_val = readl(&arasan_nand_base->pkt_reg); + reg_val = readl(&info->reg->pkt_reg); reg_val &= ~(ARASAN_NAND_PKT_REG_PKT_CNT_MASK | ARASAN_NAND_PKT_REG_PKT_SIZE_MASK); reg_val |= (pktnum << ARASAN_NAND_PKT_REG_PKT_CNT_SHFT) | pktsize; - writel(reg_val, &arasan_nand_base->pkt_reg); + writel(reg_val, &info->reg->pkt_reg); if (!nand->on_die_ecc_enabled) { - arasan_nand_enable_ecc(); + arasan_nand_enable_ecc(mtd); column_addr_cycles = (chip->onfi_params.addr_cycles & ARASAN_NAND_COL_ADDR_CYCL_MASK) >> ARASAN_NAND_COL_ADDR_CYCL_SHIFT; writel((NAND_CMD_RNDIN | (column_addr_cycles << 28)), - &arasan_nand_base->ecc_sprcmd_reg); + &info->reg->ecc_sprcmd_reg); } - writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg); + writel(curr_cmd->pgm, &info->reg->pgm_reg); while (rdcount < pktnum) { timeout = ARASAN_NAND_POLL_TIMEOUT; - while (!(readl(&arasan_nand_base->intsts_reg) & + while (!(readl(&info->reg->intsts_reg) & ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK) && timeout) { udelay(1); timeout--; @@ -552,21 +564,21 @@ static int arasan_nand_write_page_hwecc(struct mtd_info *mtd, rdcount++; if (pktnum == rdcount) { - reg_val = readl(&arasan_nand_base->intsts_enr); + reg_val = readl(&info->reg->intsts_enr); reg_val |= ARASAN_NAND_INT_STS_XFR_CMPLT_MASK; - writel(reg_val, &arasan_nand_base->intsts_enr); + writel(reg_val, &info->reg->intsts_enr); } else { - reg_val = readl(&arasan_nand_base->intsts_enr); + reg_val = readl(&info->reg->intsts_enr); writel(reg_val | ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK, - &arasan_nand_base->intsts_enr); + &info->reg->intsts_enr); } - reg_val = readl(&arasan_nand_base->intsts_reg); + reg_val = readl(&info->reg->intsts_reg); writel(reg_val | ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK, - &arasan_nand_base->intsts_reg); + &info->reg->intsts_reg); for (i = 0; i < pktsize/4; i++) - writel(bufptr[i], &arasan_nand_base->buf_dataport); + writel(bufptr[i], &info->reg->buf_dataport); bufptr += pktsize/4; @@ -574,12 +586,12 @@ static int arasan_nand_write_page_hwecc(struct mtd_info *mtd, break; writel(ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK, - &arasan_nand_base->intsts_enr); + &info->reg->intsts_enr); } timeout = ARASAN_NAND_POLL_TIMEOUT; - while (!(readl(&arasan_nand_base->intsts_reg) & + while (!(readl(&info->reg->intsts_reg) & ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) { udelay(1); timeout--; @@ -589,12 +601,12 @@ static int arasan_nand_write_page_hwecc(struct mtd_info *mtd, return -ETIMEDOUT; } - reg_val = readl(&arasan_nand_base->intsts_enr); + reg_val = readl(&info->reg->intsts_enr); writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, - &arasan_nand_base->intsts_enr); - reg_val = readl(&arasan_nand_base->intsts_reg); + &info->reg->intsts_enr); + reg_val = readl(&info->reg->intsts_reg); writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, - &arasan_nand_base->intsts_reg); + &info->reg->intsts_reg); if (oob_required) chip->ecc.write_oob(mtd, chip, nand->page); @@ -623,22 +635,25 @@ static int arasan_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, return status; } -static int arasan_nand_reset(struct arasan_nand_command_format *curr_cmd) +static int arasan_nand_reset(struct mtd_info *mtd, + struct arasan_nand_command_format *curr_cmd) { + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_drv *info = nand_get_controller_data(chip); u32 timeout = ARASAN_NAND_POLL_TIMEOUT; u32 cmd_reg = 0; writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, - &arasan_nand_base->intsts_enr); - cmd_reg = readl(&arasan_nand_base->cmd_reg); + &info->reg->intsts_enr); + cmd_reg = readl(&info->reg->cmd_reg); cmd_reg &= ~ARASAN_NAND_CMD_CMD12_MASK; cmd_reg |= curr_cmd->cmd1 | (curr_cmd->cmd2 << ARASAN_NAND_CMD_CMD2_SHIFT); - writel(cmd_reg, &arasan_nand_base->cmd_reg); - writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg); + writel(cmd_reg, &info->reg->cmd_reg); + writel(curr_cmd->pgm, &info->reg->pgm_reg); - while (!(readl(&arasan_nand_base->intsts_reg) & + while (!(readl(&info->reg->intsts_reg) & ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) { udelay(1); timeout--; @@ -649,10 +664,10 @@ static int arasan_nand_reset(struct arasan_nand_command_format *curr_cmd) } writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, - &arasan_nand_base->intsts_enr); + &info->reg->intsts_enr); writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, - &arasan_nand_base->intsts_reg); + &info->reg->intsts_reg); return 0; } @@ -691,12 +706,14 @@ static u8 arasan_nand_page(struct mtd_info *mtd) static int arasan_nand_send_wrcmd(struct arasan_nand_command_format *curr_cmd, int column, int page_addr, struct mtd_info *mtd) { + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_drv *info = nand_get_controller_data(chip); u32 reg_val, page; u8 page_val, addr_cycles; writel(ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK, - &arasan_nand_base->intsts_enr); - reg_val = readl(&arasan_nand_base->cmd_reg); + &info->reg->intsts_enr); + reg_val = readl(&info->reg->cmd_reg); reg_val &= ~ARASAN_NAND_CMD_CMD12_MASK; reg_val |= curr_cmd->cmd1 | (curr_cmd->cmd2 << ARASAN_NAND_CMD_CMD2_SHIFT); @@ -714,7 +731,7 @@ static int arasan_nand_send_wrcmd(struct arasan_nand_command_format *curr_cmd, reg_val |= (addr_cycles << ARASAN_NAND_CMD_ADDR_CYCL_SHIFT); - writel(reg_val, &arasan_nand_base->cmd_reg); + writel(reg_val, &info->reg->cmd_reg); if (page_addr == -1) page_addr = 0; @@ -722,30 +739,32 @@ static int arasan_nand_send_wrcmd(struct arasan_nand_command_format *curr_cmd, page = (page_addr << ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT) & ARASAN_NAND_MEM_ADDR1_PAGE_MASK; column &= ARASAN_NAND_MEM_ADDR1_COL_MASK; - writel(page|column, &arasan_nand_base->memadr_reg1); + writel(page | column, &info->reg->memadr_reg1); - reg_val = readl(&arasan_nand_base->memadr_reg2); + reg_val = readl(&info->reg->memadr_reg2); reg_val &= ~ARASAN_NAND_MEM_ADDR2_PAGE_MASK; reg_val |= (page_addr >> ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT); - writel(reg_val, &arasan_nand_base->memadr_reg2); + writel(reg_val, &info->reg->memadr_reg2); return 0; } static void arasan_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len) { + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_drv *info = nand_get_controller_data(chip); u32 reg_val; u32 timeout = ARASAN_NAND_POLL_TIMEOUT; - reg_val = readl(&arasan_nand_base->pkt_reg); + reg_val = readl(&info->reg->pkt_reg); reg_val &= ~(ARASAN_NAND_PKT_REG_PKT_CNT_MASK | ARASAN_NAND_PKT_REG_PKT_SIZE_MASK); reg_val |= (1 << ARASAN_NAND_PKT_REG_PKT_CNT_SHFT) | len; - writel(reg_val, &arasan_nand_base->pkt_reg); - writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg); + writel(reg_val, &info->reg->pkt_reg); + writel(curr_cmd->pgm, &info->reg->pgm_reg); - while (!(readl(&arasan_nand_base->intsts_reg) & + while (!(readl(&info->reg->intsts_reg) & ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK) && timeout) { udelay(1); timeout--; @@ -754,19 +773,19 @@ static void arasan_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len) if (!timeout) puts("ERROR:arasan_nand_write_buf timedout:Buff RDY\n"); - reg_val = readl(&arasan_nand_base->intsts_enr); + reg_val = readl(&info->reg->intsts_enr); reg_val |= ARASAN_NAND_INT_STS_XFR_CMPLT_MASK; - writel(reg_val, &arasan_nand_base->intsts_enr); + writel(reg_val, &info->reg->intsts_enr); writel(reg_val | ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK, - &arasan_nand_base->intsts_enr); - reg_val = readl(&arasan_nand_base->intsts_reg); + &info->reg->intsts_enr); + reg_val = readl(&info->reg->intsts_reg); writel(reg_val | ARASAN_NAND_INT_STS_BUF_WR_RDY_MASK, - &arasan_nand_base->intsts_reg); + &info->reg->intsts_reg); - arasan_nand_fill_tx(buf, len); + arasan_nand_fill_tx(mtd, buf, len); timeout = ARASAN_NAND_POLL_TIMEOUT; - while (!(readl(&arasan_nand_base->intsts_reg) & + while (!(readl(&info->reg->intsts_reg) & ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) { udelay(1); timeout--; @@ -774,24 +793,26 @@ static void arasan_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len) if (!timeout) puts("ERROR:arasan_nand_write_buf timedout:Xfer CMPLT\n"); - writel(readl(&arasan_nand_base->intsts_enr) | + writel(readl(&info->reg->intsts_enr) | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, - &arasan_nand_base->intsts_enr); - writel(readl(&arasan_nand_base->intsts_reg) | + &info->reg->intsts_enr); + writel(readl(&info->reg->intsts_reg) | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, - &arasan_nand_base->intsts_reg); + &info->reg->intsts_reg); } static int arasan_nand_erase(struct arasan_nand_command_format *curr_cmd, int column, int page_addr, struct mtd_info *mtd) { + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_drv *info = nand_get_controller_data(chip); u32 reg_val, page; u32 timeout = ARASAN_NAND_POLL_TIMEOUT; u8 row_addr_cycles; writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, - &arasan_nand_base->intsts_enr); - reg_val = readl(&arasan_nand_base->cmd_reg); + &info->reg->intsts_enr); + reg_val = readl(&info->reg->cmd_reg); reg_val &= ~ARASAN_NAND_CMD_CMD12_MASK; reg_val |= curr_cmd->cmd1 | (curr_cmd->cmd2 << ARASAN_NAND_CMD_CMD2_SHIFT); @@ -804,21 +825,21 @@ static int arasan_nand_erase(struct arasan_nand_command_format *curr_cmd, reg_val |= (row_addr_cycles << ARASAN_NAND_CMD_ADDR_CYCL_SHIFT); - writel(reg_val, &arasan_nand_base->cmd_reg); + writel(reg_val, &info->reg->cmd_reg); page = (page_addr >> ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT) & ARASAN_NAND_MEM_ADDR1_COL_MASK; column = page_addr & ARASAN_NAND_MEM_ADDR1_COL_MASK; writel(column | (page << ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT), - &arasan_nand_base->memadr_reg1); + &info->reg->memadr_reg1); - reg_val = readl(&arasan_nand_base->memadr_reg2); + reg_val = readl(&info->reg->memadr_reg2); reg_val &= ~ARASAN_NAND_MEM_ADDR2_PAGE_MASK; reg_val |= (page_addr >> ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT); - writel(reg_val, &arasan_nand_base->memadr_reg2); - writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg); + writel(reg_val, &info->reg->memadr_reg2); + writel(curr_cmd->pgm, &info->reg->pgm_reg); - while (!(readl(&arasan_nand_base->intsts_reg) & + while (!(readl(&info->reg->intsts_reg) & ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) { udelay(1); timeout--; @@ -828,12 +849,12 @@ static int arasan_nand_erase(struct arasan_nand_command_format *curr_cmd, return -ETIMEDOUT; } - reg_val = readl(&arasan_nand_base->intsts_enr); + reg_val = readl(&info->reg->intsts_enr); writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, - &arasan_nand_base->intsts_enr); - reg_val = readl(&arasan_nand_base->intsts_reg); + &info->reg->intsts_enr); + reg_val = readl(&info->reg->intsts_reg); writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, - &arasan_nand_base->intsts_reg); + &info->reg->intsts_reg); return 0; } @@ -841,13 +862,15 @@ static int arasan_nand_erase(struct arasan_nand_command_format *curr_cmd, static int arasan_nand_read_status(struct arasan_nand_command_format *curr_cmd, int column, int page_addr, struct mtd_info *mtd) { + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_drv *info = nand_get_controller_data(chip); u32 reg_val; u32 timeout = ARASAN_NAND_POLL_TIMEOUT; u8 addr_cycles; writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, - &arasan_nand_base->intsts_enr); - reg_val = readl(&arasan_nand_base->cmd_reg); + &info->reg->intsts_enr); + reg_val = readl(&info->reg->cmd_reg); reg_val &= ~ARASAN_NAND_CMD_CMD12_MASK; reg_val |= curr_cmd->cmd1 | (curr_cmd->cmd2 << ARASAN_NAND_CMD_CMD2_SHIFT); @@ -860,16 +883,16 @@ static int arasan_nand_read_status(struct arasan_nand_command_format *curr_cmd, reg_val |= (addr_cycles << ARASAN_NAND_CMD_ADDR_CYCL_SHIFT); - writel(reg_val, &arasan_nand_base->cmd_reg); + writel(reg_val, &info->reg->cmd_reg); - reg_val = readl(&arasan_nand_base->pkt_reg); + reg_val = readl(&info->reg->pkt_reg); reg_val &= ~(ARASAN_NAND_PKT_REG_PKT_CNT_MASK | ARASAN_NAND_PKT_REG_PKT_SIZE_MASK); reg_val |= (1 << ARASAN_NAND_PKT_REG_PKT_CNT_SHFT) | 1; - writel(reg_val, &arasan_nand_base->pkt_reg); + writel(reg_val, &info->reg->pkt_reg); - writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg); - while (!(readl(&arasan_nand_base->intsts_reg) & + writel(curr_cmd->pgm, &info->reg->pgm_reg); + while (!(readl(&info->reg->intsts_reg) & ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) { udelay(1); timeout--; @@ -880,12 +903,12 @@ static int arasan_nand_read_status(struct arasan_nand_command_format *curr_cmd, return -ETIMEDOUT; } - reg_val = readl(&arasan_nand_base->intsts_enr); + reg_val = readl(&info->reg->intsts_enr); writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, - &arasan_nand_base->intsts_enr); - reg_val = readl(&arasan_nand_base->intsts_reg); + &info->reg->intsts_enr); + reg_val = readl(&info->reg->intsts_reg); writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, - &arasan_nand_base->intsts_reg); + &info->reg->intsts_reg); return 0; } @@ -893,14 +916,16 @@ static int arasan_nand_read_status(struct arasan_nand_command_format *curr_cmd, static int arasan_nand_send_rdcmd(struct arasan_nand_command_format *curr_cmd, int column, int page_addr, struct mtd_info *mtd) { + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_drv *info = nand_get_controller_data(chip); u32 reg_val, addr_cycles, page; u8 page_val; - reg_val = readl(&arasan_nand_base->intsts_enr); + reg_val = readl(&info->reg->intsts_enr); writel(reg_val | ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK, - &arasan_nand_base->intsts_enr); + &info->reg->intsts_enr); - reg_val = readl(&arasan_nand_base->cmd_reg); + reg_val = readl(&info->reg->cmd_reg); reg_val &= ~ARASAN_NAND_CMD_CMD12_MASK; reg_val |= curr_cmd->cmd1 | (curr_cmd->cmd2 << ARASAN_NAND_CMD_CMD2_SHIFT); @@ -922,7 +947,7 @@ static int arasan_nand_send_rdcmd(struct arasan_nand_command_format *curr_cmd, return ERR_ADDR_CYCLE; reg_val |= (addr_cycles << 28); - writel(reg_val, &arasan_nand_base->cmd_reg); + writel(reg_val, &info->reg->cmd_reg); if (page_addr == -1) page_addr = 0; @@ -930,12 +955,12 @@ static int arasan_nand_send_rdcmd(struct arasan_nand_command_format *curr_cmd, page = (page_addr << ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT) & ARASAN_NAND_MEM_ADDR1_PAGE_MASK; column &= ARASAN_NAND_MEM_ADDR1_COL_MASK; - writel(page | column, &arasan_nand_base->memadr_reg1); + writel(page | column, &info->reg->memadr_reg1); - reg_val = readl(&arasan_nand_base->memadr_reg2); + reg_val = readl(&info->reg->memadr_reg2); reg_val &= ~ARASAN_NAND_MEM_ADDR2_PAGE_MASK; reg_val |= (page_addr >> ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT); - writel(reg_val, &arasan_nand_base->memadr_reg2); + writel(reg_val, &info->reg->memadr_reg2); buf_index = 0; @@ -944,19 +969,21 @@ static int arasan_nand_send_rdcmd(struct arasan_nand_command_format *curr_cmd, static void arasan_nand_read_buf(struct mtd_info *mtd, u8 *buf, int size) { + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_drv *info = nand_get_controller_data(chip); u32 reg_val, i; u32 *bufptr = (u32 *)buf; u32 timeout = ARASAN_NAND_POLL_TIMEOUT; - reg_val = readl(&arasan_nand_base->pkt_reg); + reg_val = readl(&info->reg->pkt_reg); reg_val &= ~(ARASAN_NAND_PKT_REG_PKT_CNT_MASK | ARASAN_NAND_PKT_REG_PKT_SIZE_MASK); reg_val |= (1 << ARASAN_NAND_PKT_REG_PKT_CNT_SHFT) | size; - writel(reg_val, &arasan_nand_base->pkt_reg); + writel(reg_val, &info->reg->pkt_reg); - writel(curr_cmd->pgm, &arasan_nand_base->pgm_reg); + writel(curr_cmd->pgm, &info->reg->pgm_reg); - while (!(readl(&arasan_nand_base->intsts_reg) & + while (!(readl(&info->reg->intsts_reg) & ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK) && timeout) { udelay(1); timeout--; @@ -965,26 +992,26 @@ static void arasan_nand_read_buf(struct mtd_info *mtd, u8 *buf, int size) if (!timeout) puts("ERROR:arasan_nand_read_buf timedout:Buff RDY\n"); - reg_val = readl(&arasan_nand_base->intsts_enr); + reg_val = readl(&info->reg->intsts_enr); reg_val |= ARASAN_NAND_INT_STS_XFR_CMPLT_MASK; - writel(reg_val, &arasan_nand_base->intsts_enr); + writel(reg_val, &info->reg->intsts_enr); writel(reg_val | ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK, - &arasan_nand_base->intsts_enr); - reg_val = readl(&arasan_nand_base->intsts_reg); + &info->reg->intsts_enr); + reg_val = readl(&info->reg->intsts_reg); writel(reg_val | ARASAN_NAND_INT_STS_BUF_RD_RDY_MASK, - &arasan_nand_base->intsts_reg); + &info->reg->intsts_reg); buf_index = 0; for (i = 0; i < size / 4; i++) - bufptr[i] = readl(&arasan_nand_base->buf_dataport); + bufptr[i] = readl(&info->reg->buf_dataport); if (size & 0x03) - bufptr[i] = readl(&arasan_nand_base->buf_dataport); + bufptr[i] = readl(&info->reg->buf_dataport); timeout = ARASAN_NAND_POLL_TIMEOUT; - while (!(readl(&arasan_nand_base->intsts_reg) & + while (!(readl(&info->reg->intsts_reg) & ARASAN_NAND_INT_STS_XFR_CMPLT_MASK) && timeout) { udelay(1); timeout--; @@ -993,17 +1020,18 @@ static void arasan_nand_read_buf(struct mtd_info *mtd, u8 *buf, int size) if (!timeout) puts("ERROR:arasan_nand_read_buf timedout:Xfer CMPLT\n"); - reg_val = readl(&arasan_nand_base->intsts_enr); + reg_val = readl(&info->reg->intsts_enr); writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, - &arasan_nand_base->intsts_enr); - reg_val = readl(&arasan_nand_base->intsts_reg); + &info->reg->intsts_enr); + reg_val = readl(&info->reg->intsts_reg); writel(reg_val | ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, - &arasan_nand_base->intsts_reg); + &info->reg->intsts_reg); } static u8 arasan_nand_read_byte(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_drv *info = nand_get_controller_data(chip); u32 size; u8 val; struct nand_onfi_params *p; @@ -1019,7 +1047,7 @@ static u8 arasan_nand_read_byte(struct mtd_info *mtd) else if (curr_cmd->cmd1 == NAND_CMD_GET_FEATURES) size = 4; else if (curr_cmd->cmd1 == NAND_CMD_STATUS) - return readb(&arasan_nand_base->flash_sts_reg); + return readb(&info->reg->flash_sts_reg); else size = 8; chip->read_buf(mtd, &buf_data[0], size); @@ -1034,13 +1062,14 @@ static u8 arasan_nand_read_byte(struct mtd_info *mtd) static void arasan_nand_cmd_function(struct mtd_info *mtd, unsigned int command, int column, int page_addr) { - u32 i, ret = 0; struct nand_chip *chip = mtd_to_nand(mtd); - struct nand_config *nand = nand_get_controller_data(chip); + struct nand_drv *info = nand_get_controller_data(chip); + struct nand_config *nand = &info->config; + u32 i, ret = 0; curr_cmd = NULL; writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK, - &arasan_nand_base->intsts_enr); + &info->reg->intsts_enr); if ((command == NAND_CMD_READOOB) && (mtd->writesize > 512)) { @@ -1063,7 +1092,7 @@ static void arasan_nand_cmd_function(struct mtd_info *mtd, unsigned int command, } if (curr_cmd->cmd1 == NAND_CMD_RESET) - ret = arasan_nand_reset(curr_cmd); + ret = arasan_nand_reset(mtd, curr_cmd); if ((curr_cmd->cmd1 == NAND_CMD_READID) || (curr_cmd->cmd1 == NAND_CMD_PARAM) || @@ -1134,9 +1163,10 @@ static void arasan_check_ondie(struct mtd_info *mtd) static int arasan_nand_ecc_init(struct mtd_info *mtd) { + struct nand_chip *nand_chip = mtd_to_nand(mtd); + struct nand_drv *info = nand_get_controller_data(nand_chip); int found = -1; u32 regval, eccpos_start, i, eccaddr; - struct nand_chip *nand_chip = mtd_to_nand(mtd); for (i = 0; i < ARRAY_SIZE(ecc_matrix); i++) { if ((ecc_matrix[i].pagesize == mtd->writesize) && @@ -1160,14 +1190,14 @@ static int arasan_nand_ecc_init(struct mtd_info *mtd) regval = eccaddr | (ecc_matrix[found].eccsize << ARASAN_NAND_ECC_SIZE_SHIFT) | (ecc_matrix[found].bch << ARASAN_NAND_ECC_BCH_SHIFT); - writel(regval, &arasan_nand_base->ecc_reg); + writel(regval, &info->reg->ecc_reg); if (ecc_matrix[found].bch) { - regval = readl(&arasan_nand_base->memadr_reg2); + regval = readl(&info->reg->memadr_reg2); regval &= ~ARASAN_NAND_MEM_ADDR2_BCH_MASK; regval |= (ecc_matrix[found].bchval << ARASAN_NAND_MEM_ADDR2_BCH_SHIFT); - writel(regval, &arasan_nand_base->memadr_reg2); + writel(regval, &info->reg->memadr_reg2); } nand_oob.eccbytes = ecc_matrix[found].eccsize; @@ -1191,18 +1221,14 @@ static int arasan_probe(struct udevice *dev) { struct arasan_nand_info *arasan = dev_get_priv(dev); struct nand_chip *nand_chip = &arasan->nand_chip; - struct nand_config *nand; + struct nand_drv *info = &arasan->nand_ctrl; + struct nand_config *nand = &info->config; struct mtd_info *mtd; int err = -1; - nand = calloc(1, sizeof(struct nand_config)); - if (!nand) { - printf("%s: failed to allocate\n", __func__); - return err; - } - + info->reg = (struct nand_regs *)dev_read_addr(dev); mtd = nand_to_mtd(nand_chip); - nand_set_controller_data(nand_chip, nand); + nand_set_controller_data(nand_chip, &arasan->nand_ctrl); #ifdef CONFIG_SYS_NAND_NO_SUBPAGE_WRITE nand_chip->options |= NAND_NO_SUBPAGE_WRITE; @@ -1218,8 +1244,8 @@ static int arasan_probe(struct udevice *dev) nand_chip->write_buf = arasan_nand_write_buf; nand_chip->bbt_options = NAND_BBT_USE_FLASH; - writel(0x0, &arasan_nand_base->cmd_reg); - writel(0x0, &arasan_nand_base->pgm_reg); + writel(0x0, &info->reg->cmd_reg); + writel(0x0, &info->reg->pgm_reg); /* first scan to find the device and get the page size */ if (nand_scan_ident(mtd, CONFIG_SYS_NAND_MAX_CHIPS, NULL)) { -- cgit v1.2.3 From 4d9b1afa415ddf998f6f40283f95770106cef35b Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Tue, 17 Sep 2019 00:11:02 -0600 Subject: spi: Fix manual relocation calling more times When two instances of AXI QSPI with flash are added and tested simultaneously the spi driver operations are relocated twice. As a result code is accessing addresses outside of RAM when relocated second time which is causing a crash. Tested on Microblaze. Similar change was done in past by: commit f238b3f0fbc9 ("watchdog: dm: Support manual relocation for watchdogs") commit 2588f2ddfd60 ("dm: sf: Add support for all targets which requires MANUAL_RELOC") commit 1b4c2aa25bdf ("gpio: dm: Support manual relocation for gpio") Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek --- drivers/spi/spi-uclass.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c index af910e9efce..0ca108ee3d4 100644 --- a/drivers/spi/spi-uclass.c +++ b/drivers/spi/spi-uclass.c @@ -170,21 +170,25 @@ static int spi_post_probe(struct udevice *bus) #endif #if defined(CONFIG_NEEDS_MANUAL_RELOC) struct dm_spi_ops *ops = spi_get_ops(bus); - - if (ops->claim_bus) - ops->claim_bus += gd->reloc_off; - if (ops->release_bus) - ops->release_bus += gd->reloc_off; - if (ops->set_wordlen) - ops->set_wordlen += gd->reloc_off; - if (ops->xfer) - ops->xfer += gd->reloc_off; - if (ops->set_speed) - ops->set_speed += gd->reloc_off; - if (ops->set_mode) - ops->set_mode += gd->reloc_off; - if (ops->cs_info) - ops->cs_info += gd->reloc_off; + static int reloc_done; + + if (!reloc_done) { + if (ops->claim_bus) + ops->claim_bus += gd->reloc_off; + if (ops->release_bus) + ops->release_bus += gd->reloc_off; + if (ops->set_wordlen) + ops->set_wordlen += gd->reloc_off; + if (ops->xfer) + ops->xfer += gd->reloc_off; + if (ops->set_speed) + ops->set_speed += gd->reloc_off; + if (ops->set_mode) + ops->set_mode += gd->reloc_off; + if (ops->cs_info) + ops->cs_info += gd->reloc_off; + reloc_done++; + } #endif return 0; -- cgit v1.2.3 From 45397a6ea385d486813f38fdaf37f5a92acaa32c Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Fri, 27 Dec 2019 04:47:12 -0700 Subject: zynq: mtd: nand: Move zynq nand driver to driver model Move the zynq nand driver to driver model. Select DM_MTD if zynq nand controller (NAND_ZYNQ) is selected. Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek --- drivers/mtd/nand/raw/Kconfig | 1 + drivers/mtd/nand/raw/zynq_nand.c | 44 ++++++++++++++++++++++++++++++---------- 2 files changed, 34 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index ec17653f414..5de72fb46c0 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -281,6 +281,7 @@ endif config NAND_ZYNQ bool "Support for Zynq Nand controller" select SYS_NAND_SELF_INIT + select DM_MTD imply CMD_NAND help This enables Nand driver support for Nand flash controller diff --git a/drivers/mtd/nand/raw/zynq_nand.c b/drivers/mtd/nand/raw/zynq_nand.c index e932a58bf60..f322d1a8193 100644 --- a/drivers/mtd/nand/raw/zynq_nand.c +++ b/drivers/mtd/nand/raw/zynq_nand.c @@ -17,6 +17,7 @@ #include #include #include +#include /* The NAND flash driver defines */ #define ZYNQ_NAND_CMD_PHASE 1 @@ -124,18 +125,23 @@ struct zynq_nand_smc_regs { ZYNQ_SMC_BASEADDR) /* - * struct zynq_nand_info - Defines the NAND flash driver instance + * struct nand_config - Defines the NAND flash driver instance * @parts: Pointer to the mtd_partition structure * @nand_base: Virtual address of the NAND flash device * @end_cmd_pending: End command is pending * @end_cmd: End command */ -struct zynq_nand_info { +struct nand_config { void __iomem *nand_base; u8 end_cmd_pending; u8 end_cmd; }; +struct zynq_nand_info { + struct udevice *dev; + struct nand_chip nand_chip; +}; + /* * struct zynq_nand_command_format - Defines NAND flash command format * @start_cmd: First cycle command (Start command) @@ -782,7 +788,7 @@ static void zynq_nand_cmd_function(struct mtd_info *mtd, unsigned int command, struct nand_chip *chip = mtd->priv; const struct zynq_nand_command_format *curr_cmd = NULL; u8 addr_cycles = 0; - struct zynq_nand_info *xnand = (struct zynq_nand_info *)chip->priv; + struct nand_config *xnand = (struct nand_config *)chip->priv; void *cmd_addr; unsigned long cmd_data = 0; unsigned long cmd_phase_addr = 0; @@ -1046,9 +1052,11 @@ static int zynq_nand_check_is_16bit_bw_flash(void) return is_16bit_bw; } -static int zynq_nand_init(struct nand_chip *nand_chip, int devnum) +static int zynq_nand_probe(struct udevice *dev) { - struct zynq_nand_info *xnand; + struct zynq_nand_info *zynq = dev_get_priv(dev); + struct nand_chip *nand_chip = &zynq->nand_chip; + struct nand_config *xnand; struct mtd_info *mtd; unsigned long ecc_page_size; u8 maf_id, dev_id, i; @@ -1059,7 +1067,7 @@ static int zynq_nand_init(struct nand_chip *nand_chip, int devnum) int err = -1; int is_16bit_bw; - xnand = calloc(1, sizeof(struct zynq_nand_info)); + xnand = calloc(1, sizeof(struct nand_config)); if (!xnand) { printf("%s: failed to allocate\n", __func__); goto fail; @@ -1235,7 +1243,7 @@ static int zynq_nand_init(struct nand_chip *nand_chip, int devnum) printf("%s: nand_scan_tail failed\n", __func__); goto fail; } - if (nand_register(devnum, mtd)) + if (nand_register(0, mtd)) goto fail; return 0; fail: @@ -1243,12 +1251,26 @@ fail: return err; } -static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE]; +static const struct udevice_id zynq_nand_dt_ids[] = { + {.compatible = "arm,pl353-smc-r2p1",}, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(zynq_nand) = { + .name = "zynq-nand", + .id = UCLASS_MTD, + .of_match = zynq_nand_dt_ids, + .probe = zynq_nand_probe, + .priv_auto_alloc_size = sizeof(struct zynq_nand_info), +}; void board_nand_init(void) { - struct nand_chip *nand = &nand_chip[0]; + struct udevice *dev; + int ret; - if (zynq_nand_init(nand, 0)) - puts("ZYNQ NAND init failed\n"); + ret = uclass_get_device_by_driver(UCLASS_MTD, + DM_GET_DRIVER(zynq_nand), &dev); + if (ret && ret != -ENODEV) + pr_err("Failed to initialize %s. (error %d)\n", dev->name, ret); } -- cgit v1.2.3 From 2507ecf18b295e0d115e10a4aa1f8bcaf9a3df84 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Fri, 27 Dec 2019 04:47:13 -0700 Subject: zynq: mtd: nand: Remove hardcoded base addresses Remove hardcoded base addresses of smc controller and nand controller. Get those addresses from dt and replace wherever they are used. Remove smc and nand base address from header file too. Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek --- arch/arm/mach-zynq/include/mach/hardware.h | 2 - drivers/mtd/nand/raw/zynq_nand.c | 94 ++++++++++++++++++------------ 2 files changed, 57 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-zynq/include/mach/hardware.h b/arch/arm/mach-zynq/include/mach/hardware.h index 5412ed68279..0fe49aeb227 100644 --- a/arch/arm/mach-zynq/include/mach/hardware.h +++ b/arch/arm/mach-zynq/include/mach/hardware.h @@ -10,8 +10,6 @@ #define ZYNQ_DEV_CFG_APB_BASEADDR 0xF8007000 #define ZYNQ_SCU_BASEADDR 0xF8F00000 #define ZYNQ_QSPI_BASEADDR 0xE000D000 -#define ZYNQ_SMC_BASEADDR 0xE000E000 -#define ZYNQ_NAND_BASEADDR 0xE1000000 #define ZYNQ_DDRC_BASEADDR 0xF8006000 #define ZYNQ_EFUSE_BASEADDR 0xF800D000 #define ZYNQ_USB_BASEADDR0 0xE0002000 diff --git a/drivers/mtd/nand/raw/zynq_nand.c b/drivers/mtd/nand/raw/zynq_nand.c index f322d1a8193..28db4153f5e 100644 --- a/drivers/mtd/nand/raw/zynq_nand.c +++ b/drivers/mtd/nand/raw/zynq_nand.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -121,8 +122,6 @@ struct zynq_nand_smc_regs { u32 reserved2[2]; u32 eval0r; /* 0x418 */ }; -#define zynq_nand_smc_base ((struct zynq_nand_smc_regs __iomem *)\ - ZYNQ_SMC_BASEADDR) /* * struct nand_config - Defines the NAND flash driver instance @@ -137,8 +136,14 @@ struct nand_config { u8 end_cmd; }; +struct nand_drv { + struct zynq_nand_smc_regs *reg; + struct nand_config config; +}; + struct zynq_nand_info { struct udevice *dev; + struct nand_drv nand_ctrl; struct nand_chip nand_chip; }; @@ -245,16 +250,18 @@ static struct nand_bbt_descr bbt_mirror_descr = { * * returns: status for command completion, -1 for Timeout */ -static int zynq_nand_waitfor_ecc_completion(void) +static int zynq_nand_waitfor_ecc_completion(struct mtd_info *mtd) { + struct nand_chip *nand_chip = mtd_to_nand(mtd); + struct nand_drv *smc = nand_get_controller_data(nand_chip); unsigned long timeout; u32 status; /* Wait max 10us */ timeout = 10; - status = readl(&zynq_nand_smc_base->esr); + status = readl(&smc->reg->esr); while (status & ZYNQ_NAND_ECC_BUSY) { - status = readl(&zynq_nand_smc_base->esr); + status = readl(&smc->reg->esr); if (timeout == 0) return -1; timeout--; @@ -272,33 +279,35 @@ static int zynq_nand_waitfor_ecc_completion(void) * * returns: 0 on success or error value on failure */ -static int zynq_nand_init_nand_flash(int option) +static int zynq_nand_init_nand_flash(struct mtd_info *mtd, int option) { + struct nand_chip *nand_chip = mtd_to_nand(mtd); + struct nand_drv *smc = nand_get_controller_data(nand_chip); u32 status; /* disable interrupts */ - writel(ZYNQ_NAND_CLR_CONFIG, &zynq_nand_smc_base->cfr); + writel(ZYNQ_NAND_CLR_CONFIG, &smc->reg->cfr); #ifndef CONFIG_NAND_ZYNQ_USE_BOOTLOADER1_TIMINGS /* Initialize the NAND interface by setting cycles and operation mode */ - writel(ZYNQ_NAND_SET_CYCLES, &zynq_nand_smc_base->scr); + writel(ZYNQ_NAND_SET_CYCLES, &smc->reg->scr); #endif if (option & NAND_BUSWIDTH_16) - writel(ZYNQ_NAND_SET_OPMODE_16BIT, &zynq_nand_smc_base->sor); + writel(ZYNQ_NAND_SET_OPMODE_16BIT, &smc->reg->sor); else - writel(ZYNQ_NAND_SET_OPMODE_8BIT, &zynq_nand_smc_base->sor); + writel(ZYNQ_NAND_SET_OPMODE_8BIT, &smc->reg->sor); - writel(ZYNQ_NAND_DIRECT_CMD, &zynq_nand_smc_base->dcr); + writel(ZYNQ_NAND_DIRECT_CMD, &smc->reg->dcr); /* Wait till the ECC operation is complete */ - status = zynq_nand_waitfor_ecc_completion(); + status = zynq_nand_waitfor_ecc_completion(mtd); if (status < 0) { printf("%s: Timeout\n", __func__); return status; } /* Set the command1 and command2 register */ - writel(ZYNQ_NAND_ECC_CMD1, &zynq_nand_smc_base->emcmd1r); - writel(ZYNQ_NAND_ECC_CMD2, &zynq_nand_smc_base->emcmd2r); + writel(ZYNQ_NAND_ECC_CMD1, &smc->reg->emcmd1r); + writel(ZYNQ_NAND_ECC_CMD2, &smc->reg->emcmd2r); return 0; } @@ -317,12 +326,14 @@ static int zynq_nand_init_nand_flash(int option) static int zynq_nand_calculate_hwecc(struct mtd_info *mtd, const u8 *data, u8 *ecc_code) { + struct nand_chip *nand_chip = mtd_to_nand(mtd); + struct nand_drv *smc = nand_get_controller_data(nand_chip); u32 ecc_value = 0; u8 ecc_reg, ecc_byte; u32 ecc_status; /* Wait till the ECC operation is complete */ - ecc_status = zynq_nand_waitfor_ecc_completion(); + ecc_status = zynq_nand_waitfor_ecc_completion(mtd); if (ecc_status < 0) { printf("%s: Timeout\n", __func__); return ecc_status; @@ -330,7 +341,7 @@ static int zynq_nand_calculate_hwecc(struct mtd_info *mtd, const u8 *data, for (ecc_reg = 0; ecc_reg < 4; ecc_reg++) { /* Read ECC value for each block */ - ecc_value = readl(&zynq_nand_smc_base->eval0r + ecc_reg); + ecc_value = readl(&smc->reg->eval0r + ecc_reg); /* Get the ecc status from ecc read value */ ecc_status = (ecc_value >> 24) & 0xFF; @@ -785,10 +796,11 @@ static void zynq_nand_select_chip(struct mtd_info *mtd, int chip) static void zynq_nand_cmd_function(struct mtd_info *mtd, unsigned int command, int column, int page_addr) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_drv *smc = nand_get_controller_data(chip); const struct zynq_nand_command_format *curr_cmd = NULL; u8 addr_cycles = 0; - struct nand_config *xnand = (struct nand_config *)chip->priv; + struct nand_config *xnand = &smc->config; void *cmd_addr; unsigned long cmd_data = 0; unsigned long cmd_phase_addr = 0; @@ -827,7 +839,7 @@ static void zynq_nand_cmd_function(struct mtd_info *mtd, unsigned int command, curr_cmd = &zynq_nand_commands[index]; /* Clear interrupt */ - writel(ZYNQ_MEMC_CLRCR_INT_CLR1, &zynq_nand_smc_base->cfr); + writel(ZYNQ_MEMC_CLRCR_INT_CLR1, &smc->reg->cfr); /* Get the command phase address */ if (curr_cmd->end_cmd_valid == ZYNQ_NAND_CMD_PHASE) @@ -924,7 +936,7 @@ static void zynq_nand_cmd_function(struct mtd_info *mtd, unsigned int command, */ static void zynq_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); /* Make sure that buf is 32 bit aligned */ if (((unsigned long)buf & 0x3) != 0) { @@ -972,7 +984,7 @@ static void zynq_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len) */ static void zynq_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); const u32 *nand = chip->IO_ADDR_W; /* Make sure that buf is 32 bit aligned */ @@ -1022,13 +1034,15 @@ static void zynq_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len) */ static int zynq_nand_device_ready(struct mtd_info *mtd) { + struct nand_chip *nand_chip = mtd_to_nand(mtd); + struct nand_drv *smc = nand_get_controller_data(nand_chip); u32 csr_val; - csr_val = readl(&zynq_nand_smc_base->csr); + csr_val = readl(&smc->reg->csr); /* Check the raw_int_status1 bit */ if (csr_val & ZYNQ_MEMC_SR_RAW_INT_ST1) { /* Clear the interrupt condition */ - writel(ZYNQ_MEMC_SR_INT_ST1, &zynq_nand_smc_base->cfr); + writel(ZYNQ_MEMC_SR_INT_ST1, &smc->reg->cfr); return 1; } @@ -1056,8 +1070,11 @@ static int zynq_nand_probe(struct udevice *dev) { struct zynq_nand_info *zynq = dev_get_priv(dev); struct nand_chip *nand_chip = &zynq->nand_chip; - struct nand_config *xnand; + struct nand_drv *smc = &zynq->nand_ctrl; + struct nand_config *xnand = &smc->config; struct mtd_info *mtd; + struct resource res; + ofnode of_nand; unsigned long ecc_page_size; u8 maf_id, dev_id, i; u8 get_feature[4]; @@ -1067,17 +1084,20 @@ static int zynq_nand_probe(struct udevice *dev) int err = -1; int is_16bit_bw; - xnand = calloc(1, sizeof(struct nand_config)); - if (!xnand) { - printf("%s: failed to allocate\n", __func__); + smc->reg = (struct zynq_nand_smc_regs *)dev_read_addr(dev); + of_nand = dev_read_subnode(dev, "flash@e1000000"); + if (!ofnode_valid(of_nand)) { + printf("Failed to find nand node in dt\n"); + goto fail; + } + if (ofnode_read_resource(of_nand, 0, &res)) { + printf("Failed to get nand resource\n"); goto fail; } - xnand->nand_base = (void __iomem *)ZYNQ_NAND_BASEADDR; + xnand->nand_base = (void __iomem *)res.start; mtd = nand_to_mtd(nand_chip); - - nand_chip->priv = xnand; - mtd->priv = nand_chip; + nand_set_controller_data(nand_chip, &zynq->nand_ctrl); /* Set address of NAND IO lines */ nand_chip->IO_ADDR_R = xnand->nand_base; @@ -1108,7 +1128,7 @@ static int zynq_nand_probe(struct udevice *dev) nand_chip->bbt_options = NAND_BBT_USE_FLASH; /* Initialize the NAND flash interface on NAND controller */ - if (zynq_nand_init_nand_flash(nand_chip->options) < 0) { + if (zynq_nand_init_nand_flash(mtd, nand_chip->options) < 0) { printf("%s: nand flash init failed\n", __func__); goto fail; } @@ -1156,9 +1176,9 @@ static int zynq_nand_probe(struct udevice *dev) if (ondie_ecc_enabled) { /* Bypass the controller ECC block */ - ecc_cfg = readl(&zynq_nand_smc_base->emcr); + ecc_cfg = readl(&smc->reg->emcr); ecc_cfg &= ~ZYNQ_MEMC_NAND_ECC_MODE_MASK; - writel(ecc_cfg, &zynq_nand_smc_base->emcr); + writel(ecc_cfg, &smc->reg->emcr); /* The software ECC routines won't work * with the SMC controller @@ -1206,19 +1226,19 @@ static int zynq_nand_probe(struct udevice *dev) ecc_page_size = 0x1; /* Set the ECC memory config register */ writel((ZYNQ_NAND_ECC_CONFIG | ecc_page_size), - &zynq_nand_smc_base->emcr); + &smc->reg->emcr); break; case 1024: ecc_page_size = 0x2; /* Set the ECC memory config register */ writel((ZYNQ_NAND_ECC_CONFIG | ecc_page_size), - &zynq_nand_smc_base->emcr); + &smc->reg->emcr); break; case 2048: ecc_page_size = 0x3; /* Set the ECC memory config register */ writel((ZYNQ_NAND_ECC_CONFIG | ecc_page_size), - &zynq_nand_smc_base->emcr); + &smc->reg->emcr); break; default: nand_chip->ecc.mode = NAND_ECC_SOFT; -- cgit v1.2.3 From 3f9c23905cd69b1260137a6f3cb4aa45c28e4344 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Tue, 7 Jan 2020 02:26:00 -0700 Subject: firmware: Remove probe which is causing extra bind Remove probe function dm_scan_fdt_dev from zynqmp-firmware driver. It is just binding its subnode zynqmp-clk. As a result one extra node is showing up in dm tree. This is not required, it is anyway bound from it's own zynqmp-clk driver. Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek --- drivers/firmware/firmware-zynqmp.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index dea58b55810..2a2aa2f4f16 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -187,6 +187,5 @@ static const struct udevice_id zynqmp_firmware_ids[] = { U_BOOT_DRIVER(zynqmp_firmware) = { .id = UCLASS_FIRMWARE, .name = "zynqmp-firmware", - .probe = dm_scan_fdt_dev, .of_match = zynqmp_firmware_ids, }; -- cgit v1.2.3 From 8af4c4dcbb30b5a79a9a6b507863e4dd380e6b72 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 22 May 2019 14:12:20 +0200 Subject: net: zynq: Add a note about RX_BUF macro Record note about reducing number of BDs. Signed-off-by: Michal Simek --- drivers/net/zynq_gem.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 78f94148b41..c3fe8e3c563 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -173,6 +173,7 @@ struct emac_bd { #endif }; +/* Reduce amount of BUFs if you have limited amount of memory */ #define RX_BUF 32 /* Page table entries are set to 1MB, or multiples of 1MB * (not < 1MB). driver uses less bd's so use 1MB bdspace. -- cgit v1.2.3