summaryrefslogtreecommitdiff
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorSiva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com>2017-05-25 14:25:55 +0530
committerMichal Simek <michal.simek@xilinx.com>2018-05-11 09:23:43 +0200
commit9ca8388059de8f10e035fbdcaa418ec3caeb0599 (patch)
tree36e2b08b16920c55baaa66c614b61faa0b6cdf4e /drivers/mtd/nand
parent6de7a5b90701fb306b150d0ed32f7b59b51bbbc5 (diff)
downloadu-boot-9ca8388059de8f10e035fbdcaa418ec3caeb0599.tar.gz
nand: zynq: Add support for 16-bit buswidth
This patch adds support for 16-bit buswidth by determining the bus width based on mio configuration. Signed-off-by: Siva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/zynq_nand.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/drivers/mtd/nand/zynq_nand.c b/drivers/mtd/nand/zynq_nand.c
index efd3c9b798..4d0ea9e6b9 100644
--- a/drivers/mtd/nand/zynq_nand.c
+++ b/drivers/mtd/nand/zynq_nand.c
@@ -16,6 +16,7 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand_ecc.h>
#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
/* The NAND flash driver defines */
#define ZYNQ_NAND_CMD_PHASE 1
@@ -83,6 +84,15 @@
#define ZYNQ_NAND_ECC_BUSY (1 << 6) /* ECC block is busy */
#define ZYNQ_NAND_ECC_MASK 0x00FFFFFF /* ECC value mask */
+#define ZYNQ_NAND_MIO_NUM_NAND_8BIT 13
+#define ZYNQ_NAND_MIO_NUM_NAND_16BIT 8
+
+enum zynq_nand_bus_width {
+ NAND_BW_UNKNOWN = -1,
+ NAND_BW_8BIT,
+ NAND_BW_16BIT,
+};
+
#ifndef NAND_CMD_LOCK_TIGHT
#define NAND_CMD_LOCK_TIGHT 0x2c
#endif
@@ -1005,6 +1015,23 @@ static int zynq_nand_device_ready(struct mtd_info *mtd)
return 0;
}
+static int zynq_nand_check_is_16bit_bw_flash(void)
+{
+ int is_16bit_bw = NAND_BW_UNKNOWN;
+ int mio_num_8bit = 0, mio_num_16bit = 0;
+
+ mio_num_8bit = zynq_slcr_get_mio_pin_status("nand8");
+ if (mio_num_8bit == ZYNQ_NAND_MIO_NUM_NAND_8BIT)
+ is_16bit_bw = NAND_BW_8BIT;
+
+ mio_num_16bit = zynq_slcr_get_mio_pin_status("nand16");
+ if (mio_num_8bit == ZYNQ_NAND_MIO_NUM_NAND_8BIT &&
+ mio_num_16bit == ZYNQ_NAND_MIO_NUM_NAND_16BIT)
+ is_16bit_bw = NAND_BW_16BIT;
+
+ return is_16bit_bw;
+}
+
static int zynq_nand_init(struct nand_chip *nand_chip, int devnum)
{
struct zynq_nand_info *xnand;
@@ -1016,6 +1043,7 @@ static int zynq_nand_init(struct nand_chip *nand_chip, int devnum)
unsigned long ecc_cfg;
int ondie_ecc_enabled = 0;
int err = -1;
+ int is_16bit_bw;
xnand = calloc(1, sizeof(struct zynq_nand_info));
if (!xnand) {
@@ -1045,6 +1073,16 @@ static int zynq_nand_init(struct nand_chip *nand_chip, int devnum)
nand_chip->read_buf = zynq_nand_read_buf;
nand_chip->write_buf = zynq_nand_write_buf;
+ is_16bit_bw = zynq_nand_check_is_16bit_bw_flash();
+ if (is_16bit_bw == NAND_BW_UNKNOWN) {
+ printf("%s: Unable detect NAND based on MIO settings\n",
+ __func__);
+ goto fail;
+ }
+
+ if (is_16bit_bw == NAND_BW_16BIT)
+ nand_chip->options = NAND_BUSWIDTH_16;
+
nand_chip->bbt_options = NAND_BBT_USE_FLASH;
/* Initialize the NAND flash interface on NAND controller */