[PATCH 2/2] zynq: mtd: nand: Remove hardcoded base addresses

Michal Simek michal.simek at xilinx.com
Mon Jan 6 10:32:33 CET 2020


From: Ashok Reddy Soma <ashok.reddy.soma at xilinx.com>

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 <ashok.reddy.soma at xilinx.com>
Signed-off-by: Michal Simek <michal.simek at xilinx.com>
---

 arch/arm/mach-zynq/include/mach/hardware.h |  2 -
 drivers/mtd/nand/raw/zynq_nand.c           | 94 +++++++++++++---------
 2 files changed, 57 insertions(+), 39 deletions(-)

diff --git a/arch/arm/mach-zynq/include/mach/hardware.h b/arch/arm/mach-zynq/include/mach/hardware.h
index 5412ed682797..0fe49aeb2276 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 f322d1a81930..28db4153f5e0 100644
--- a/drivers/mtd/nand/raw/zynq_nand.c
+++ b/drivers/mtd/nand/raw/zynq_nand.c
@@ -11,6 +11,7 @@
 #include <asm/io.h>
 #include <linux/errno.h>
 #include <nand.h>
+#include <linux/ioport.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
@@ -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 at 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;
-- 
2.24.0



More information about the U-Boot mailing list