Add basic Rockchip nand driver. Driver in current state has 16, 24, 40, 60 per 1024B BCH/ECC ability and 8 bit asynchronous flash interface support. Other features will come later.
Signed-off-by: Paweł Jarosz <paweljarosz3...@gmail.com> --- Changes since v1: - none drivers/mtd/nand/Kconfig | 6 + drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/rockchip_nand.c | 660 +++++++++++++++++++++++++++++++++++++++ include/fdtdec.h | 1 + lib/fdtdec.c | 1 + 5 files changed, 669 insertions(+) create mode 100644 drivers/mtd/nand/rockchip_nand.c diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 3508c62..57a870d 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -66,6 +66,12 @@ config NAND_PXA3XX This enables the driver for the NAND flash device found on PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2). +config NAND_ROCKCHIP + bool "Support for NAND on Rockchip SoCs" + select SYS_NAND_SELF_INIT + ---help--- + Enable support for Rockchip nand. + config NAND_SUNXI bool "Support for NAND on Allwinner SoCs" depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index c3d4a99..0659253 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -65,6 +65,7 @@ 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 +obj-$(CONFIG_NAND_ROCKCHIP) += rockchip_nand.o else # minimal SPL drivers diff --git a/drivers/mtd/nand/rockchip_nand.c b/drivers/mtd/nand/rockchip_nand.c new file mode 100644 index 0000000..c997c43 --- /dev/null +++ b/drivers/mtd/nand/rockchip_nand.c @@ -0,0 +1,660 @@ +/* + * Copyright (c) 2017 Yifeng Zhao <yifeng.z...@rock-chips.com> + * Copyright (c) 2017 Paweł Jarosz <paweljarosz3...@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <fdtdec.h> +#include <inttypes.h> +#include <nand.h> +#include <linux/kernel.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/partitions.h> +#include <linux/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define NANDC_V6_BOOTROM_ECC 24 +#define NANDC_V6_NUM_BANKS 8 +#define NANDC_V6_DEF_TIMEOUT 20000 +#define NANDC_V6_READ 0 +#define NANDC_V6_WRITE 1 + +#define NANDC_REG_V6_FMCTL 0x00 +#define NANDC_REG_V6_FMWAIT 0x04 +#define NANDC_REG_V6_FLCTL 0x08 +#define NANDC_REG_V6_BCHCTL 0x0c +#define NANDC_REG_V6_DMA_CFG 0x10 +#define NANDC_REG_V6_DMA_BUF0 0x14 +#define NANDC_REG_V6_DMA_BUF1 0x18 +#define NANDC_REG_V6_DMA_ST 0x1C +#define NANDC_REG_V6_BCHST 0x20 +#define NANDC_REG_V6_RANDMZ 0x150 +#define NANDC_REG_V6_VER 0x160 +#define NANDC_REG_V6_INTEN 0x16C +#define NANDC_REG_V6_INTCLR 0x170 +#define NANDC_REG_V6_INTST 0x174 +#define NANDC_REG_V6_SPARE0 0x200 +#define NANDC_REG_V6_SPARE1 0x230 +#define NANDC_REG_V6_BANK0 0x800 +#define NANDC_REG_V6_SRAM0 0x1000 +#define NANDC_REG_V6_SRAM_SIZE 0x400 + +#define NANDC_REG_V6_DATA 0x00 +#define NANDC_REG_V6_ADDR 0x04 +#define NANDC_REG_V6_CMD 0x08 + +/* FMCTL */ +#define NANDC_V6_FM_WP BIT(8) +#define NANDC_V6_FM_CE_SEL_M 0xFF +#define NANDC_V6_FM_CE_SEL(x) (1 << (x)) +#define NANDC_V6_FM_FREADY BIT(9) + +/* FLCTL */ +#define NANDC_V6_FL_RST BIT(0) +#define NANDC_V6_FL_DIR_S 0x1 +#define NANDC_V6_FL_XFER_START BIT(2) +#define NANDC_V6_FL_XFER_EN BIT(3) +#define NANDC_V6_FL_ST_BUF_S 0x4 +#define NANDC_V6_FL_XFER_COUNT BIT(5) +#define NANDC_V6_FL_ACORRECT BIT(10) +#define NANDC_V6_FL_XFER_READY BIT(20) + +/* BCHCTL */ +#define NAND_V6_BCH_REGION_S 0x5 +#define NAND_V6_BCH_REGION_M 0x7 + +/* BCHST */ +#define NANDC_V6_BCH0_ST_ERR BIT(2) +#define NANDC_V6_BCH1_ST_ERR BIT(15) +#define NANDC_V6_ECC_ERR_CNT0(x) ((((x & (0x1F << 3)) >> 3) \ + | ((x & (1 << 27)) >> 22)) & 0x3F) +#define NANDC_V6_ECC_ERR_CNT1(x) ((((x & (0x1F << 16)) >> 16) \ + | ((x & (1 << 29)) >> 24)) & 0x3F) + +struct rk_nand { + uint32_t banks[NANDC_V6_NUM_BANKS]; + struct nand_hw_control controller; + uint32_t ecc_strength; + struct mtd_info mtd; + bool bootromblocks; + void __iomem *regs; + int selected_bank; +}; + +static struct nand_ecclayout nand_oob_fix = { + .eccbytes = 24, + .eccpos = { + 4, 5, 6, 7, 8, 9, 10}, + .oobfree = { + {.offset = 0, + .length = 4} } +}; + +static inline struct rk_nand *to_rknand(struct nand_hw_control *ctrl) +{ + return container_of(ctrl, struct rk_nand, controller); +} + +static void rockchip_nand_init(struct rk_nand *rknand) +{ + writel(0, rknand->regs + NANDC_REG_V6_RANDMZ); + writel(0, rknand->regs + NANDC_REG_V6_DMA_CFG); + writel(0, rknand->regs + NANDC_REG_V6_BCHCTL); + writel(NANDC_V6_FM_WP, rknand->regs + NANDC_REG_V6_FMCTL); + writel(0x1081, rknand->regs + NANDC_REG_V6_FMWAIT); +} + +static void rockchip_nand_select_chip(struct mtd_info *mtd, int chipnr) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct rk_nand *rknand = to_rknand(chip->controller); + void __iomem *bank_base; + uint32_t reg; + int banknr; + + reg = readl(rknand->regs + NANDC_REG_V6_FMCTL); + reg &= ~NANDC_V6_FM_CE_SEL_M; + + if (chipnr == -1) { + banknr = -1; + } else { + banknr = rknand->banks[chipnr]; + bank_base = rknand->regs + NANDC_REG_V6_BANK0 + banknr * 0x100; + + chip->IO_ADDR_R = bank_base; + chip->IO_ADDR_W = bank_base; + + reg |= 1 << banknr; + } + writel(reg, rknand->regs + NANDC_REG_V6_FMCTL); + + rknand->selected_bank = banknr; +} + +static void rockchip_nand_cmd_ctrl(struct mtd_info *mtd, + int dat, + unsigned int ctrl) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct rk_nand *rknand = to_rknand(chip->controller); + void __iomem *bank_base = rknand->regs + NANDC_REG_V6_BANK0 + + rknand->selected_bank * 0x100; + + if (ctrl & NAND_CTRL_CHANGE) { + if (ctrl & NAND_ALE) + bank_base += NANDC_REG_V6_ADDR; + else if (ctrl & NAND_CLE) + bank_base += NANDC_REG_V6_CMD; + chip->IO_ADDR_W = bank_base; + } + + if (dat != NAND_CMD_NONE) + writeb(dat & 0xFF, chip->IO_ADDR_W); +} + +static void rockchip_nand_read_buf(struct mtd_info *mtd, + uint8_t *buf, + int len) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct rk_nand *rknand = to_rknand(chip->controller); + int offs = 0; + void __iomem *bank_base = rknand->regs + NANDC_REG_V6_BANK0 + + rknand->selected_bank * 0x100; + + for (offs = 0; offs < len; offs++) + buf[offs] = readb(bank_base); +} + +static void rockchip_nand_write_buf(struct mtd_info *mtd, + const uint8_t *buf, + int len) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct rk_nand *rknand = to_rknand(chip->controller); + int offs = 0; + void __iomem *bank_base = rknand->regs + NANDC_REG_V6_BANK0 + + rknand->selected_bank * 0x100; + + for (offs = 0; offs < len; offs++) + writeb(buf[offs], bank_base); +} + +static uint8_t rockchip_nand_read_byte(struct mtd_info *mtd) +{ + uint8_t ret; + + rockchip_nand_read_buf(mtd, &ret, 1); + + return ret; +} + +static int rockchip_nand_dev_ready(struct mtd_info *mtd) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct rk_nand *rknand = to_rknand(chip->controller); + + if (readl(rknand->regs + NANDC_REG_V6_FMCTL) & NANDC_V6_FM_FREADY) + return 1; + + return 0; +} + +static int rockchip_nand_hw_ecc_setup(struct mtd_info *mtd, + struct nand_ecc_ctrl *ecc, + uint32_t strength) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct rk_nand *rknand = to_rknand(chip->controller); + u32 reg; + + ecc->strength = strength; + ecc->bytes = DIV_ROUND_UP(ecc->strength * 14, 8); + ecc->bytes = ALIGN(ecc->bytes, 2); + + switch (ecc->strength) { + case 60: + reg = 0x00040010; + break; + case 40: + reg = 0x00040000; + break; + case 24: + reg = 0x00000010; + break; + case 16: + reg = 0x00000000; + break; + default: + return -EINVAL; + } + writel(reg, rknand->regs + NANDC_REG_V6_BCHCTL); + + return 0; +} + +static void rockchip_nand_pio_xfer_start(struct rk_nand *rknand, + u8 dir, + u8 st_buf) +{ + u32 reg; + + reg = readl(rknand->regs + NANDC_REG_V6_BCHCTL); + reg = (reg & (~(NAND_V6_BCH_REGION_M << NAND_V6_BCH_REGION_S))) | + (rknand->selected_bank << NAND_V6_BCH_REGION_S); + writel(reg, rknand->regs + NANDC_REG_V6_BCHCTL); + + reg = (dir << NANDC_V6_FL_DIR_S) | (st_buf << NANDC_V6_FL_ST_BUF_S) | + NANDC_V6_FL_XFER_EN | NANDC_V6_FL_XFER_COUNT | + NANDC_V6_FL_ACORRECT; + writel(reg, rknand->regs + NANDC_REG_V6_FLCTL); + + reg |= NANDC_V6_FL_XFER_START; + writel(reg, rknand->regs + NANDC_REG_V6_FLCTL); +} + +static int rockchip_nand_wait_pio_xfer_done(struct rk_nand *rknand) +{ + int timeout = NANDC_V6_DEF_TIMEOUT; + int reg; + + while (timeout--) { + reg = readl(rknand->regs + NANDC_REG_V6_FLCTL); + + if ((reg & NANDC_V6_FL_XFER_READY) != 0) + break; + + udelay(1); + } + + if (timeout == 0) + return -1; + + return 0; +} + +static void rockchip_nand_read_extra_oob(struct mtd_info *mtd, u8 *oob) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_ecc_ctrl *ecc = &chip->ecc; + int offset = ((ecc->bytes + ecc->prepad) * ecc->steps); + int len = mtd->oobsize - offset; + + if (len <= 0) + return; + + chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset + mtd->writesize, -1); + + rockchip_nand_read_buf(mtd, oob + offset, len); +} + +static void rockchip_nand_write_extra_oob(struct mtd_info *mtd, u8 *oob) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_ecc_ctrl *ecc = &chip->ecc; + int offset = ((ecc->bytes + ecc->prepad) * ecc->steps); + int len = mtd->oobsize - offset; + + if (len <= 0) + return; + + chip->cmdfunc(mtd, NAND_CMD_RNDIN, offset + mtd->writesize, -1); + + rockchip_nand_write_buf(mtd, oob + offset, len); +} + + +static int rockchip_nand_hw_syndrome_pio_read_page(struct mtd_info *mtd, + struct nand_chip *chip, + uint8_t *buf, + int oob_required, + int page) +{ + struct rk_nand *rknand = to_rknand(chip->controller); + struct nand_ecc_ctrl *ecc = &chip->ecc; + void __iomem *sram_base = rknand->regs + NANDC_REG_V6_SRAM0; + unsigned int max_bitflips = 0; + int ret, step, bch_st; + int offset = page * mtd->writesize; + + if (rknand->bootromblocks && (offset < (7 * mtd->erasesize))) + rockchip_nand_hw_ecc_setup(mtd, ecc, NANDC_V6_BOOTROM_ECC); + + rockchip_nand_pio_xfer_start(rknand, NANDC_V6_READ, 0); + + for (step = 0; step < ecc->steps; step++) { + int data_off = step * ecc->size; + int oob_off = step * (ecc->bytes + ecc->prepad); + u8 *data = buf + data_off; + u8 *oob = chip->oob_poi + oob_off; + + ret = rockchip_nand_wait_pio_xfer_done(rknand); + if (ret) + return ret; + + bch_st = readl(rknand->regs + NANDC_REG_V6_BCHST); + + if (bch_st & NANDC_V6_BCH0_ST_ERR) { + mtd->ecc_stats.failed++; + max_bitflips = -1; + } else { + ret = NANDC_V6_ECC_ERR_CNT0(bch_st); + mtd->ecc_stats.corrected += ret; + max_bitflips = max_t(unsigned int, max_bitflips, ret); + } + + if ((step + 1) < ecc->steps) + rockchip_nand_pio_xfer_start(rknand, NANDC_V6_READ, + (step + 1) & 0x1); + + memcpy_fromio(data, sram_base + NANDC_REG_V6_SRAM_SIZE * + (step & 1), ecc->size); + + if (step & 1) + memcpy_fromio(oob, rknand->regs + NANDC_REG_V6_SPARE1, 4); + else + memcpy_fromio(oob, rknand->regs + NANDC_REG_V6_SPARE0, 4); + } + + rockchip_nand_read_extra_oob(mtd, chip->oob_poi); + + if (rknand->bootromblocks) + rockchip_nand_hw_ecc_setup(mtd, ecc, rknand->ecc_strength); + + return max_bitflips; +} + +static uint32_t rockchip_nand_make_bootrom_compat(struct mtd_info *mtd, + int page, + const u8 *oob, + bool bootromblocks) +{ + int pages_per_block = mtd->erasesize / mtd->writesize; + int offset = page * mtd->writesize; + + if ((offset < (2 * mtd->erasesize)) || !(page % 2) || + (offset >= (7 * mtd->erasesize)) || !bootromblocks) + return oob[3] | (oob[2] << 8) | (oob[1] << 16) | (oob[0] << 24); + + return (page % pages_per_block + 1) * 4; +} + +static int rockchip_nand_hw_syndrome_pio_write_page(struct mtd_info *mtd, + struct nand_chip *chip, + const uint8_t *buf, + int oob_required, + int page) +{ + struct rk_nand *rknand = to_rknand(chip->controller); + struct nand_ecc_ctrl *ecc = &chip->ecc; + void __iomem *sram_base = rknand->regs + NANDC_REG_V6_SRAM0; + int ret, index, step = 0; + int offset = page * mtd->writesize; + int data_off = step * ecc->size; + int oob_off = step * (ecc->bytes + ecc->prepad); + const u8 *data = buf + data_off; + const u8 *oob = chip->oob_poi + oob_off; + + if (rknand->bootromblocks && (offset < (7 * mtd->erasesize))) + rockchip_nand_hw_ecc_setup(mtd, ecc, NANDC_V6_BOOTROM_ECC); + + index = rockchip_nand_make_bootrom_compat(mtd, page, oob, + rknand->bootromblocks); + + memcpy_toio(sram_base, data, ecc->size); + memcpy_toio(rknand->regs + NANDC_REG_V6_SPARE0, &index, ecc->prepad); + + for (step = 1; step <= ecc->steps; step++) { + rockchip_nand_pio_xfer_start(rknand, NANDC_V6_WRITE, + (step - 1) & 0x1); + + data_off = step * ecc->size; + oob_off = step * (ecc->bytes + ecc->prepad); + data = buf + data_off; + oob = chip->oob_poi + oob_off; + + if (step < ecc->steps) { + memcpy_toio(sram_base + NANDC_REG_V6_SRAM_SIZE * + (step & 1), data, ecc->size); + if (step & 1) + memcpy_toio(rknand->regs + NANDC_REG_V6_SPARE1, + oob, ecc->prepad); + else + memcpy_toio(rknand->regs + NANDC_REG_V6_SPARE0, + oob, ecc->prepad); + } + + ret = rockchip_nand_wait_pio_xfer_done(rknand); + if (ret) + return ret; + } + + rockchip_nand_write_extra_oob(mtd, chip->oob_poi); + + rockchip_nand_hw_ecc_setup(mtd, ecc, rknand->ecc_strength); + + return 0; +} + +static const u8 strengths[] = {60, 40, 24, 16}; + +static int rockchip_nand_ecc_max_strength(struct mtd_info *mtd, + struct nand_ecc_ctrl *ecc) +{ + uint32_t max_strength, index; + + max_strength = ((mtd->oobsize / ecc->steps) - ecc->prepad) * 8 / 14; + + for (index = 0; index < ARRAY_SIZE(strengths); index++) + if (max_strength >= strengths[index]) + break; + + if (index >= ARRAY_SIZE(strengths)) + return -ENOTSUPP; + + return strengths[index]; +} + +static bool rockchip_nand_strength_is_valid(int strength) +{ + uint32_t index; + + for (index = 0; index < ARRAY_SIZE(strengths); index++) + if (strength >= strengths[index]) + break; + + if (index >= ARRAY_SIZE(strengths)) + return false; + + return true; +} + +static int rockchip_nand_hw_ecc_ctrl_init(struct mtd_info *mtd, + struct nand_ecc_ctrl *ecc) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct rk_nand *rknand = to_rknand(chip->controller); + uint32_t strength; + int index; + + ecc->prepad = 4; + ecc->steps = mtd->writesize / ecc->size; + + if (fdtdec_get_bool(gd->fdt_blob, chip->flash_node, + "rockchip,protect-bootrom-blocks")) + rknand->bootromblocks = true; + else + rknand->bootromblocks = false; + + if (rockchip_nand_strength_is_valid(ecc->strength)) + strength = ecc->strength; + else + strength = rockchip_nand_ecc_max_strength(mtd, ecc); + + rockchip_nand_hw_ecc_setup(mtd, ecc, strength); + + rknand->ecc_strength = ecc->strength; + + nand_oob_fix.eccbytes = ecc->bytes * ecc->steps; + for (index = 0; index < ecc->bytes; index++) + nand_oob_fix.eccpos[index] = index + ecc->prepad; + ecc->layout = &nand_oob_fix; + + if (mtd->oobsize < ((ecc->bytes + ecc->prepad) * ecc->steps)) { + return -EINVAL; + } + + return 0; +} + +static int rockchip_nand_ecc_init(struct mtd_info *mtd, + struct nand_ecc_ctrl *ecc) +{ + int ret; + + switch (ecc->mode) { + case NAND_ECC_HW_SYNDROME: + ret = rockchip_nand_hw_ecc_ctrl_init(mtd, ecc); + if (ret) + return ret; + ecc->read_page = rockchip_nand_hw_syndrome_pio_read_page; + ecc->write_page = rockchip_nand_hw_syndrome_pio_write_page; + break; + case NAND_ECC_SOFT_BCH: + case NAND_ECC_NONE: + case NAND_ECC_SOFT: + break; + default: + return -EINVAL; + } + + return 0; +} + +static int rockchip_nand_chip_init(int node, struct rk_nand *rknand, int devnum) +{ + const void *blob = gd->fdt_blob; + struct nand_chip *chip; + struct mtd_info *mtd; + int ret; + + chip = kzalloc(sizeof(*chip), GFP_KERNEL); + + chip->chip_delay = 50; + chip->flash_node = node; + chip->select_chip = rockchip_nand_select_chip; + chip->cmd_ctrl = rockchip_nand_cmd_ctrl; + chip->read_buf = rockchip_nand_read_buf; + chip->write_buf = rockchip_nand_write_buf; + chip->read_byte = rockchip_nand_read_byte; + chip->dev_ready = rockchip_nand_dev_ready; + chip->controller = &rknand->controller; + + rknand->banks[devnum] = fdtdec_get_int(blob, node, "reg", -1); + + if (rknand->banks[devnum] < 0) + return -EINVAL; + + mtd = nand_to_mtd(chip); + mtd->name = "rknand"; + + ret = nand_scan_ident(mtd, 1, NULL); + if (ret) + return ret; + + ret = rockchip_nand_ecc_init(mtd, &chip->ecc); + if (ret) { + debug("rockchip_nand_ecc_init failed: %d\n", ret); + return ret; + } + + ret = nand_scan_tail(mtd); + if (ret) { + debug("nand_scan_tail failed: %d\n", ret); + return ret; + } + + ret = nand_register(devnum, mtd); + if (ret) { + debug("Failed to register mtd device: %d\n", ret); + return ret; + } + + return 0; +} + +static int rockchip_nand_chips_init(int node, struct rk_nand *rknand) +{ + const void *blob = gd->fdt_blob; + int nand_node; + int ret, i = 0; + + for (nand_node = fdt_first_subnode(blob, node); nand_node >= 0; + nand_node = fdt_next_subnode(blob, nand_node)) { + ret = rockchip_nand_chip_init(nand_node, rknand, i++); + if (ret) + return ret; + } + + return 0; +} + +void board_nand_init(void) +{ + const void *blob = gd->fdt_blob; + struct rk_nand *rknand; + fdt_addr_t regs; + int node; + int ret; + + rknand = kzalloc(sizeof(*rknand), GFP_KERNEL); + + node = fdtdec_next_compatible(blob, 0, COMPAT_ROCKCHIP_NANDC); + + if (node < 0) { + debug("Nand node not found\n"); + goto err; + } + + if (!fdtdec_get_is_enabled(blob, node)) { + debug("Nand disabled in device tree\n"); + goto err; + } + + regs = fdtdec_get_addr(blob, node, "reg"); + if (regs == FDT_ADDR_T_NONE) { + debug("Nand address not found\n"); + goto err; + } + + rknand->regs = (void *)regs; + + spin_lock_init(&rknand->controller.lock); + init_waitqueue_head(&rknand->controller.wq); + + rockchip_nand_init(rknand); + + ret = rockchip_nand_chips_init(node, rknand); + if (ret) { + debug("Failed to init nand chips\n"); + goto err; + } + + return; +err: + kfree(rknand); +} + +int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst) +{ + struct mtd_info *mtd; + + mtd = get_nand_dev_by_index(0); + return nand_read_skip_bad(mtd, offs, &size, NULL, size, (u_char *)dst); +} + +void nand_deselect(void) {} diff --git a/include/fdtdec.h b/include/fdtdec.h index 4a0947c..0e68788 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -157,6 +157,7 @@ enum fdt_compat_id { COMPAT_ALTERA_SOCFPGA_F2SDR0, /* SoCFPGA fpga2SDRAM0 bridge */ COMPAT_ALTERA_SOCFPGA_F2SDR1, /* SoCFPGA fpga2SDRAM1 bridge */ COMPAT_ALTERA_SOCFPGA_F2SDR2, /* SoCFPGA fpga2SDRAM2 bridge */ + COMPAT_ROCKCHIP_NANDC, /* Rockchip NAND controller */ COMPAT_COUNT, }; diff --git a/lib/fdtdec.c b/lib/fdtdec.c index d2dbd0f..6e814cf 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -70,6 +70,7 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(ALTERA_SOCFPGA_F2SDR0, "altr,socfpga-fpga2sdram0-bridge"), COMPAT(ALTERA_SOCFPGA_F2SDR1, "altr,socfpga-fpga2sdram1-bridge"), COMPAT(ALTERA_SOCFPGA_F2SDR2, "altr,socfpga-fpga2sdram2-bridge"), + COMPAT(ROCKCHIP_NANDC, "rockchip,nandc"), }; const char *fdtdec_get_compatible(enum fdt_compat_id id) -- 2.7.4 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot