mtd: nand: add the rockchip nand controller driver

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.

Change-Id: I8e766afe7358a2357d75cfe094c4cd6fe92bd281
Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
This commit is contained in:
Paweł Jarosz 2017-08-17 15:14:09 +02:00 committed by Kever Yang
parent 037e961371
commit a3584243c9
5 changed files with 669 additions and 0 deletions

View File

@ -76,6 +76,12 @@ config NAND_PXA3XX
This enables the driver for the NAND flash device found on This enables the driver for the NAND flash device found on
PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2). 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 config NAND_SUNXI
bool "Support for NAND on Allwinner SoCs" bool "Support for NAND on Allwinner SoCs"
depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I

View File

@ -66,6 +66,7 @@ obj-$(CONFIG_NAND_OMAP_ELM) += omap_elm.o
obj-$(CONFIG_NAND_PLAT) += nand_plat.o obj-$(CONFIG_NAND_PLAT) += nand_plat.o
obj-$(CONFIG_NAND_SUNXI) += sunxi_nand.o obj-$(CONFIG_NAND_SUNXI) += sunxi_nand.o
obj-$(CONFIG_NAND_ZYNQ) += zynq_nand.o obj-$(CONFIG_NAND_ZYNQ) += zynq_nand.o
obj-$(CONFIG_NAND_ROCKCHIP) += rockchip_nand.o
else # minimal SPL drivers else # minimal SPL drivers

View File

@ -0,0 +1,660 @@
/*
* Copyright (c) 2017 Yifeng Zhao <yifeng.zhao@rock-chips.com>
* Copyright (c) 2017 Paweł Jarosz <paweljarosz3691@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) {}

View File

@ -159,6 +159,7 @@ enum fdt_compat_id {
COMPAT_ALTERA_SOCFPGA_F2SDR0, /* SoCFPGA fpga2SDRAM0 bridge */ COMPAT_ALTERA_SOCFPGA_F2SDR0, /* SoCFPGA fpga2SDRAM0 bridge */
COMPAT_ALTERA_SOCFPGA_F2SDR1, /* SoCFPGA fpga2SDRAM1 bridge */ COMPAT_ALTERA_SOCFPGA_F2SDR1, /* SoCFPGA fpga2SDRAM1 bridge */
COMPAT_ALTERA_SOCFPGA_F2SDR2, /* SoCFPGA fpga2SDRAM2 bridge */ COMPAT_ALTERA_SOCFPGA_F2SDR2, /* SoCFPGA fpga2SDRAM2 bridge */
COMPAT_ROCKCHIP_NANDC, /* Rockchip NAND controller */
COMPAT_COUNT, COMPAT_COUNT,
}; };

View File

@ -70,6 +70,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
COMPAT(ALTERA_SOCFPGA_F2SDR0, "altr,socfpga-fpga2sdram0-bridge"), COMPAT(ALTERA_SOCFPGA_F2SDR0, "altr,socfpga-fpga2sdram0-bridge"),
COMPAT(ALTERA_SOCFPGA_F2SDR1, "altr,socfpga-fpga2sdram1-bridge"), COMPAT(ALTERA_SOCFPGA_F2SDR1, "altr,socfpga-fpga2sdram1-bridge"),
COMPAT(ALTERA_SOCFPGA_F2SDR2, "altr,socfpga-fpga2sdram2-bridge"), COMPAT(ALTERA_SOCFPGA_F2SDR2, "altr,socfpga-fpga2sdram2-bridge"),
COMPAT(ROCKCHIP_NANDC, "rockchip,nandc"),
}; };
const char *fdtdec_get_compatible(enum fdt_compat_id id) const char *fdtdec_get_compatible(enum fdt_compat_id id)