[U-Boot] [PATCH v2 1/2] mtd: nand : zynq_nand: Add nand driver support for zynq
Siva Durga Prasad Paladugu
siva.durga.paladugu at xilinx.com
Mon Sep 26 08:59:42 CEST 2016
Hi Michal,
> -----Original Message-----
> From: Michal Simek [mailto:michal.simek at xilinx.com]
> Sent: Monday, September 26, 2016 12:12 PM
> To: Siva Durga Prasad Paladugu <sivadur at xilinx.com>; u-boot at lists.denx.de
> Cc: oss at buserror.net; Siva Durga Prasad Paladugu <sivadur at xilinx.com>
> Subject: Re: [PATCH v2 1/2] mtd: nand : zynq_nand: Add nand driver support
> for zynq
>
> On 23.9.2016 14:50, Siva Durga Prasad Paladugu wrote:
> > Add nand flash controller driver support for zynq SoC.
> >
> > Signed-off-by: Siva Durga Prasad Paladugu <sivadur at xilinx.com>
> > ---
> > Changes for v2:
> > - corrected the from address
> > ---
> > drivers/mtd/nand/Kconfig | 7 +
> > drivers/mtd/nand/Makefile | 1 +
> > drivers/mtd/nand/zynq_nand.c | 1186
> > ++++++++++++++++++++++++++++++++++++++++++
> > 3 files changed, 1194 insertions(+)
> > create mode 100644 drivers/mtd/nand/zynq_nand.c
> >
> > diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index
> > 5ce7d6d..7e5c436 100644
> > --- a/drivers/mtd/nand/Kconfig
> > +++ b/drivers/mtd/nand/Kconfig
> > @@ -80,6 +80,13 @@ config NAND_ARASAN
> > controller. This uses the hardware ECC for read and
> > write operations.
> >
> > +config NAND_ZYNQ
> > + bool "Support for Zynq Nand controller"
> > + select SYS_NAND_SELF_INIT
> > + help
> > + This enables Nand driver support for Nand flash controller
> > + found on Zynq SoC.
> > +
> > comment "Generic NAND options"
> >
> > # Enhance depends when converting drivers to Kconfig which use this
> > config diff --git a/drivers/mtd/nand/Makefile
> > b/drivers/mtd/nand/Makefile index 1df9273..fd4bb66 100644
> > --- a/drivers/mtd/nand/Makefile
> > +++ b/drivers/mtd/nand/Makefile
> > @@ -67,6 +67,7 @@ obj-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o
> > obj-$(CONFIG_NAND_OMAP_ELM) += omap_elm.o
> > obj-$(CONFIG_NAND_PLAT) += nand_plat.o
> > obj-$(CONFIG_NAND_SUNXI) += sunxi_nand.o
> > +obj-$(CONFIG_NAND_ZYNQ) += zynq_nand.o
> >
> > else # minimal SPL drivers
> >
> > diff --git a/drivers/mtd/nand/zynq_nand.c
> > b/drivers/mtd/nand/zynq_nand.c new file mode 100644 index
> > 0000000..a0003a4
> > --- /dev/null
> > +++ b/drivers/mtd/nand/zynq_nand.c
> > @@ -0,0 +1,1186 @@
> > +/*
> > + * (C) Copyright 2013 Xilinx, Inc.
> > + *
> > + * Xilinx Zynq NAND Flash Controller Driver
> > + * This driver is based on plat_nand.c and mxc_nand.c drivers
> > + *
> > + * SPDX-License-Identifier: GPL-2.0+
> > + */
> > +
> > +#include <common.h>
> > +#include <malloc.h>
> > +#include <asm/io.h>
> > +#include <asm/errno.h>
>
> drivers/mtd/nand/zynq_nand.c:13:23: fatal error: asm/errno.h: No such file
> or directory #include <asm/errno.h>
> ^
> compilation terminated.
>
> Remove this header.
It might be due to latest changes on errno by Masahiro.
I made this series on top of commit on friday
"201c9d884dcadb4e76981c30e9915f73de2d09b5"
Will anyway rebase it on top of latest master and send v3.
Thanks,
Siva
>
>
> > +#include <nand.h>
> > +#include <linux/mtd/mtd.h>
> > +#include <linux/mtd/nand.h>
> > +#include <linux/mtd/partitions.h>
> > +#include <linux/mtd/nand_ecc.h>
> > +#include <asm/arch/hardware.h>
> > +
> > +/* The NAND flash driver defines */
> > +#define ZYNQ_NAND_CMD_PHASE 1
> > +#define ZYNQ_NAND_DATA_PHASE 2
> > +#define ZYNQ_NAND_ECC_SIZE 512
> > +#define ZYNQ_NAND_SET_OPMODE_8BIT (0 << 0)
> > +#define ZYNQ_NAND_SET_OPMODE_16BIT (1 << 0)
> > +#define ZYNQ_NAND_ECC_STATUS (1 << 6)
> > +#define ZYNQ_MEMC_CLRCR_INT_CLR1 (1 << 4)
> > +#define ZYNQ_MEMC_SR_RAW_INT_ST1 (1 << 6)
> > +#define ZYNQ_MEMC_SR_INT_ST1 (1 << 4)
> > +#define ZYNQ_MEMC_NAND_ECC_MODE_MASK 0xC
> > +
> > +/* Flash memory controller operating parameters */
> > +#define ZYNQ_NAND_CLR_CONFIG ((0x1 << 1) | /* Disable interrupt
> */ \
> > + (0x1 << 4) | /* Clear interrupt */ \
> > + (0x1 << 6)) /* Disable ECC interrupt */
> > +
> > +/* Assuming 50MHz clock (20ns cycle time) and 3V operation */
> > +#define ZYNQ_NAND_SET_CYCLES ((0x2 << 20) | /* t_rr from
> nand_cycles */ \
> > + (0x2 << 17) | /* t_ar from nand_cycles */ \
> > + (0x1 << 14) | /* t_clr from nand_cycles */ \
> > + (0x3 << 11) | /* t_wp from nand_cycles */
> \
> > + (0x2 << 8) | /* t_rea from nand_cycles */
> \
> > + (0x5 << 4) | /* t_wc from nand_cycles */ \
> > + (0x5 << 0)) /* t_rc from nand_cycles */
> > +
> > +
> > +#define ZYNQ_NAND_DIRECT_CMD ((0x4 << 23) | /* Chip 0 from
> interface 1 */ \
> > + (0x2 << 21)) /* UpdateRegs operation */
> > +
> > +#define ZYNQ_NAND_ECC_CONFIG ((0x1 << 2) | /* ECC available on
> APB */ \
> > + (0x1 << 4) | /* ECC read at end of page */
> \
> > + (0x0 << 5)) /* No Jumping */
> > +
> > +#define ZYNQ_NAND_ECC_CMD1 ((0x80) | /* Write command */
> \
> > + (0x00 << 8) | /* Read command */ \
> > + (0x30 << 16) | /* Read End command */ \
> > + (0x1 << 24)) /* Read End command calid
> */
> > +
> > +#define ZYNQ_NAND_ECC_CMD2 ((0x85) | /* Write col change
> cmd */ \
> > + (0x05 << 8) | /* Read col change cmd */ \
> > + (0xE0 << 16) | /* Read col change end cmd
> */ \
> > + (0x1 << 24)) /* Read col change
> > + end cmd valid */
> > +/* AXI Address definitions */
> > +#define START_CMD_SHIFT 3
> > +#define END_CMD_SHIFT 11
> > +#define END_CMD_VALID_SHIFT 20
> > +#define ADDR_CYCLES_SHIFT 21
> > +#define CLEAR_CS_SHIFT 21
> > +#define ECC_LAST_SHIFT 10
> > +#define COMMAND_PHASE (0 << 19)
> > +#define DATA_PHASE (1 << 19)
> > +#define ONDIE_ECC_FEATURE_ADDR 0x90
> > +#define ONDIE_ECC_FEATURE_ENABLE 0x08
> > +
> > +#define ZYNQ_NAND_ECC_LAST (1 << ECC_LAST_SHIFT) /* Set
> ECC_Last */
> > +#define ZYNQ_NAND_CLEAR_CS (1 << CLEAR_CS_SHIFT) /* Clear chip
> select */
> > +
> > +/* ECC block registers bit position and bit mask */
> > +#define ZYNQ_NAND_ECC_BUSY (1 << 6) /* ECC block is busy */
> > +#define ZYNQ_NAND_ECC_MASK 0x00FFFFFF /* ECC value mask */
> > +
> > +
> > +/* SMC register set */
> > +struct zynq_nand_smc_regs {
> > + u32 csr; /* 0x00 */
> > + u32 reserved0[2];
> > + u32 cfr; /* 0x0C */
> > + u32 dcr; /* 0x10 */
> > + u32 scr; /* 0x14 */
> > + u32 sor; /* 0x18 */
> > + u32 reserved1[249];
> > + u32 esr; /* 0x400 */
> > + u32 emcr; /* 0x404 */
> > + u32 emcmd1r; /* 0x408 */
> > + u32 emcmd2r; /* 0x40C */
> > + u32 reserved2[2];
> > + u32 eval0r; /* 0x418 */
> > +};
> > +#define zynq_nand_smc_base ((struct zynq_nand_smc_regs
> __iomem *)\
> > + ZYNQ_SMC_BASEADDR)
> > +
> > +/*
> > + * struct zynq_nand_info - 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 {
> > + void __iomem *nand_base;
> > + u8 end_cmd_pending;
> > + u8 end_cmd;
> > +};
> > +
> > +/*
> > + * struct zynq_nand_command_format - Defines NAND flash command
> format
> > + * @start_cmd: First cycle command (Start command)
> > + * @end_cmd: Second cycle command (Last command)
> > + * @addr_cycles: Number of address cycles required to send the
> address
> > + * @end_cmd_valid: The second cycle command is valid for cmd or data
> phase
> > + */
> > +struct zynq_nand_command_format {
> > + u8 start_cmd;
> > + u8 end_cmd;
> > + u8 addr_cycles;
> > + u8 end_cmd_valid;
> > +};
> > +
> > +/* The NAND flash operations command format */ static const struct
> > +zynq_nand_command_format zynq_nand_commands[] = {
> > + {NAND_CMD_READ0, NAND_CMD_READSTART, 5,
> ZYNQ_NAND_CMD_PHASE},
> > + {NAND_CMD_RNDOUT, NAND_CMD_RNDOUTSTART, 2,
> ZYNQ_NAND_CMD_PHASE},
> > + {NAND_CMD_READID, NAND_CMD_NONE, 1, 0},
> > + {NAND_CMD_STATUS, NAND_CMD_NONE, 0, 0},
> > + {NAND_CMD_SEQIN, NAND_CMD_PAGEPROG, 5,
> ZYNQ_NAND_DATA_PHASE},
> > + {NAND_CMD_RNDIN, NAND_CMD_NONE, 2, 0},
> > + {NAND_CMD_ERASE1, NAND_CMD_ERASE2, 3,
> ZYNQ_NAND_CMD_PHASE},
> > + {NAND_CMD_RESET, NAND_CMD_NONE, 0, 0},
> > + {NAND_CMD_PARAM, NAND_CMD_NONE, 1, 0},
> > + {NAND_CMD_GET_FEATURES, NAND_CMD_NONE, 1, 0},
> > + {NAND_CMD_SET_FEATURES, NAND_CMD_NONE, 1, 0},
> > + {NAND_CMD_NONE, NAND_CMD_NONE, 0, 0},
> > + /* Add all the flash commands supported by the flash device */ };
> > +
> > +/* Define default oob placement schemes for large and small page
> > +devices */ static struct nand_ecclayout nand_oob_16 = {
> > + .eccbytes = 3,
> > + .eccpos = {0, 1, 2},
> > + .oobfree = {
> > + { .offset = 8, .length = 8 }
> > + }
> > +};
> > +
> > +static struct nand_ecclayout nand_oob_64 = {
> > + .eccbytes = 12,
> > + .eccpos = {
> > + 52, 53, 54, 55, 56, 57,
> > + 58, 59, 60, 61, 62, 63},
> > + .oobfree = {
> > + { .offset = 2, .length = 50 }
> > + }
> > +};
> > +
> > +static struct nand_ecclayout ondie_nand_oob_64 = {
> > + .eccbytes = 32,
> > +
> > + .eccpos = {
> > + 8, 9, 10, 11, 12, 13, 14, 15,
> > + 24, 25, 26, 27, 28, 29, 30, 31,
> > + 40, 41, 42, 43, 44, 45, 46, 47,
> > + 56, 57, 58, 59, 60, 61, 62, 63
> > + },
> > +
> > + .oobfree = {
> > + { .offset = 4, .length = 4 },
> > + { .offset = 20, .length = 4 },
> > + { .offset = 36, .length = 4 },
> > + { .offset = 52, .length = 4 }
> > + }
> > +};
> > +
> > +/* bbt decriptors for chips with on-die ECC and
> > + chips with 64-byte OOB */
> > +static u8 bbt_pattern[] = {'B', 'b', 't', '0' }; static u8
> > +mirror_pattern[] = {'1', 't', 'b', 'B' };
> > +
> > +static struct nand_bbt_descr bbt_main_descr = {
> > + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE |
> NAND_BBT_WRITE |
> > + NAND_BBT_2BIT | NAND_BBT_VERSION |
> NAND_BBT_PERCHIP,
> > + .offs = 4,
> > + .len = 4,
> > + .veroffs = 20,
> > + .maxblocks = 4,
> > + .pattern = bbt_pattern
> > +};
> > +
> > +static struct nand_bbt_descr bbt_mirror_descr = {
> > + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE |
> NAND_BBT_WRITE |
> > + NAND_BBT_2BIT | NAND_BBT_VERSION |
> NAND_BBT_PERCHIP,
> > + .offs = 4,
> > + .len = 4,
> > + .veroffs = 20,
> > + .maxblocks = 4,
> > + .pattern = mirror_pattern
> > +};
> > +
> > +/*
> > + * zynq_nand_waitfor_ecc_completion - Wait for ECC completion
> > + *
> > + * returns: status for command completion, -1 for Timeout */ static
> > +int zynq_nand_waitfor_ecc_completion(void)
> > +{
> > + unsigned long timeout;
> > + u32 status;
> > +
> > + /* Wait max 10us */
> > + timeout = 10;
> > + status = readl(&zynq_nand_smc_base->esr);
> > + while (status & ZYNQ_NAND_ECC_BUSY) {
> > + status = readl(&zynq_nand_smc_base->esr);
> > + if (timeout == 0)
> > + return -1;
> > + timeout--;
> > + udelay(1);
> > + }
> > +
> > + return status;
> > +}
> > +
> > +/*
> > + * zynq_nand_init_nand_flash - Initialize NAND controller
> > + * @option: Device property flags
> > + *
> > + * This function initializes the NAND flash interface on the NAND
> controller.
> > + *
> > + * returns: 0 on success or error value on failure
> > + */
> > +static int zynq_nand_init_nand_flash(int option) {
> > + u32 status;
> > +
> > + /* disable interrupts */
> > + writel(ZYNQ_NAND_CLR_CONFIG, &zynq_nand_smc_base->cfr);
> > + /* Initialize the NAND interface by setting cycles and operation mode
> */
> > + writel(ZYNQ_NAND_SET_CYCLES, &zynq_nand_smc_base->scr);
> > + if (option & NAND_BUSWIDTH_16)
> > + writel(ZYNQ_NAND_SET_OPMODE_16BIT,
> &zynq_nand_smc_base->sor);
> > + else
> > + writel(ZYNQ_NAND_SET_OPMODE_8BIT,
> &zynq_nand_smc_base->sor);
> > +
> > + writel(ZYNQ_NAND_DIRECT_CMD, &zynq_nand_smc_base->dcr);
> > +
> > + /* Wait till the ECC operation is complete */
> > + status = zynq_nand_waitfor_ecc_completion();
> > + 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);
> > +
> > + return 0;
> > +}
> > +
> > +/*
> > + * zynq_nand_calculate_hwecc - Calculate Hardware ECC
> > + * @mtd: Pointer to the mtd_info structure
> > + * @data: Pointer to the page data
> > + * @ecc_code: Pointer to the ECC buffer where ECC data needs to
> be stored
> > + *
> > + * This function retrieves the Hardware ECC data from the controller
> > +and returns
> > + * ECC data back to the MTD subsystem.
> > + *
> > + * returns: 0 on success or error value on failure
> > + */
> > +static int zynq_nand_calculate_hwecc(struct mtd_info *mtd, const u8
> *data,
> > + u8 *ecc_code)
> > +{
> > + 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();
> > + if (ecc_status < 0) {
> > + printf("%s: Timeout\n", __func__);
> > + return ecc_status;
> > + }
> > +
> > + 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);
> > +
> > + /* Get the ecc status from ecc read value */
> > + ecc_status = (ecc_value >> 24) & 0xFF;
> > +
> > + /* ECC value valid */
> > + if (ecc_status & ZYNQ_NAND_ECC_STATUS) {
> > + for (ecc_byte = 0; ecc_byte < 3; ecc_byte++) {
> > + /* Copy ECC bytes to MTD buffer */
> > + *ecc_code = ecc_value & 0xFF;
> > + ecc_value = ecc_value >> 8;
> > + ecc_code++;
> > + }
> > + } else {
> > + debug("%s: ecc status failed\n", __func__);
> > + }
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +/*
> > + * onehot - onehot function
> > + * @value: value to check for onehot
> > + *
> > + * This function checks whether a value is onehot or not.
> > + * onehot is if and only if one bit is set.
> > + *
> > + * FIXME: Try to move this in common.h */ static bool
> > +onehot(unsigned short value) {
> > + bool onehot;
> > +
> > + onehot = value && !(value & (value - 1));
> > + return onehot;
> > +}
> > +
> > +/*
> > + * zynq_nand_correct_data - ECC correction function
> > + * @mtd: Pointer to the mtd_info structure
> > + * @buf: Pointer to the page data
> > + * @read_ecc: Pointer to the ECC value read from spare data area
> > + * @calc_ecc: Pointer to the calculated ECC value
> > + *
> > + * This function corrects the ECC single bit errors & detects 2-bit errors.
> > + *
> > + * returns: 0 if no ECC errors found
> > + * 1 if single bit error found and corrected.
> > + * -1 if multiple ECC errors found.
> > + */
> > +static int zynq_nand_correct_data(struct mtd_info *mtd, unsigned char
> *buf,
> > + unsigned char *read_ecc, unsigned char *calc_ecc) {
> > + unsigned char bit_addr;
> > + unsigned int byte_addr;
> > + unsigned short ecc_odd, ecc_even;
> > + unsigned short read_ecc_lower, read_ecc_upper;
> > + unsigned short calc_ecc_lower, calc_ecc_upper;
> > +
> > + read_ecc_lower = (read_ecc[0] | (read_ecc[1] << 8)) & 0xfff;
> > + read_ecc_upper = ((read_ecc[1] >> 4) | (read_ecc[2] << 4)) & 0xfff;
> > +
> > + calc_ecc_lower = (calc_ecc[0] | (calc_ecc[1] << 8)) & 0xfff;
> > + calc_ecc_upper = ((calc_ecc[1] >> 4) | (calc_ecc[2] << 4)) & 0xfff;
> > +
> > + ecc_odd = read_ecc_lower ^ calc_ecc_lower;
> > + ecc_even = read_ecc_upper ^ calc_ecc_upper;
> > +
> > + if ((ecc_odd == 0) && (ecc_even == 0))
> > + return 0; /* no error */
> > +
> > + if (ecc_odd == (~ecc_even & 0xfff)) {
> > + /* bits [11:3] of error code is byte offset */
> > + byte_addr = (ecc_odd >> 3) & 0x1ff;
> > + /* bits [2:0] of error code is bit offset */
> > + bit_addr = ecc_odd & 0x7;
> > + /* Toggling error bit */
> > + buf[byte_addr] ^= (1 << bit_addr);
> > + return 1;
> > + }
> > +
> > + if (onehot(ecc_odd | ecc_even))
> > + return 1; /* one error in parity */
> > +
> > + return -1; /* Uncorrectable error */ }
> > +
> > +/*
> > + * zynq_nand_read_oob - [REPLACABLE] the most common OOB data read
> function
> > + * @mtd: mtd info structure
> > + * @chip: nand chip info structure
> > + * @page: page number to read
> > + * @sndcmd: flag whether to issue read command or not
> > + */
> > +static int zynq_nand_read_oob(struct mtd_info *mtd, struct nand_chip
> *chip,
> > + int page)
> > +{
> > + unsigned long data_phase_addr = 0;
> > + int data_width = 4;
> > + u8 *p;
> > +
> > + chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
> > +
> > + p = chip->oob_poi;
> > + chip->read_buf(mtd, p, (mtd->oobsize - data_width));
> > + p += mtd->oobsize - data_width;
> > +
> > + data_phase_addr = (unsigned long)chip->IO_ADDR_R;
> > + data_phase_addr |= ZYNQ_NAND_CLEAR_CS;
> > + chip->IO_ADDR_R = (void __iomem *)data_phase_addr;
> > + chip->read_buf(mtd, p, data_width);
> > +
> > + return 0;
> > +}
> > +
> > +/*
> > + * zynq_nand_write_oob - [REPLACABLE] the most common OOB data
> write function
> > + * @mtd: mtd info structure
> > + * @chip: nand chip info structure
> > + * @page: page number to write
> > + */
> > +static int zynq_nand_write_oob(struct mtd_info *mtd, struct nand_chip
> *chip,
> > + int page)
> > +{
> > + int status = 0, data_width = 4;
> > + const u8 *buf = chip->oob_poi;
> > + unsigned long data_phase_addr = 0;
> > +
> > + chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
> > +
> > + chip->write_buf(mtd, buf, (mtd->oobsize - data_width));
> > + buf += mtd->oobsize - data_width;
> > +
> > + data_phase_addr = (unsigned long)chip->IO_ADDR_W;
> > + data_phase_addr |= ZYNQ_NAND_CLEAR_CS;
> > + data_phase_addr |= (1 << END_CMD_VALID_SHIFT);
> > + chip->IO_ADDR_W = (void __iomem *)data_phase_addr;
> > + chip->write_buf(mtd, buf, data_width);
> > +
> > + /* Send command to program the OOB data */
> > + chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
> > + status = chip->waitfunc(mtd, chip);
> > +
> > + return status & NAND_STATUS_FAIL ? -EIO : 0; }
> > +
> > +/*
> > + * zynq_nand_read_page_raw - [Intern] read raw page data without ecc
> > + * @mtd: mtd info structure
> > + * @chip: nand chip info structure
> > + * @buf: buffer to store read data
> > + * @oob_required: must write chip->oob_poi to OOB
> > + * @page: page number to read
> > + */
> > +static int zynq_nand_read_page_raw(struct mtd_info *mtd, struct
> nand_chip *chip,
> > + u8 *buf, int oob_required, int page) {
> > + unsigned long data_width = 4;
> > + unsigned long data_phase_addr = 0;
> > + u8 *p;
> > +
> > + chip->read_buf(mtd, buf, mtd->writesize);
> > +
> > + p = chip->oob_poi;
> > + chip->read_buf(mtd, p, (mtd->oobsize - data_width));
> > + p += (mtd->oobsize - data_width);
> > +
> > + data_phase_addr = (unsigned long)chip->IO_ADDR_R;
> > + data_phase_addr |= ZYNQ_NAND_CLEAR_CS;
> > + chip->IO_ADDR_R = (void __iomem *)data_phase_addr;
> > +
> > + chip->read_buf(mtd, p, data_width);
> > + return 0;
> > +}
> > +
> > +static int zynq_nand_read_page_raw_nooob(struct mtd_info *mtd,
> > + struct nand_chip *chip, u8 *buf, int oob_required, int page) {
> > + chip->read_buf(mtd, buf, mtd->writesize);
> > + return 0;
> > +}
> > +
> > +static int zynq_nand_read_subpage_raw(struct mtd_info *mtd,
> > + struct nand_chip *chip, u32 data_offs,
> > + u32 readlen, u8 *buf)
> > +{
>
> drivers/mtd/nand/zynq_nand.c: In function 'zynq_nand_init':
> drivers/mtd/nand/zynq_nand.c:1092:31: warning: assignment from
> incompatible pointer type
> nand_chip->ecc.read_subpage = zynq_nand_read_subpage_raw;
> ^
>
>
> Thanks,
> Michal
More information about the U-Boot
mailing list