drivers: mtd: nand: support rockchip nand driver as a DT device

Change-Id: I0023502f5121354863ed63fefa380643ec49b1e1
Signed-off-by: Yifeng Zhao <zyf@rock-chips.com>
This commit is contained in:
Yifeng Zhao 2019-05-30 17:24:48 +08:00 committed by Jianhong Chen
parent 124f23c66c
commit 411568d7eb
3 changed files with 178 additions and 3 deletions

View File

@ -90,6 +90,15 @@ config NAND_ROCKCHIP_V9
---help---
Enable support for Rockchip nand v9.
if NAND_ROCKCHIP || NAND_ROCKCHIP_V9
config NAND_ROCKCHIP_DT
bool "Support Rockchip NAND controller as a DT device"
default y
help
Enable the driver for Rockchip NAND flash on platforms
using device tree.
endif
config NAND_SUNXI
bool "Support for NAND on Allwinner SoCs"
depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I

View File

@ -6,14 +6,16 @@
*/
#include <common.h>
#include <dm.h>
#include <fdtdec.h>
#include <inttypes.h>
#include <nand.h>
#include <linux/io.h>
#include <linux/ioport.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;
@ -83,6 +85,7 @@ struct rk_nand {
bool bootromblocks;
void __iomem *regs;
int selected_bank;
struct udevice *dev;
};
static struct nand_ecclayout nand_oob_fix = {
@ -445,7 +448,7 @@ 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++)
@ -590,6 +593,9 @@ static int rockchip_nand_chip_init(int node, struct rk_nand *rknand, int devnum)
mtd = nand_to_mtd(chip);
mtd->name = "rknand";
mtd->dev = rknand->dev;
if (rknand->dev)
rknand->dev->priv = mtd;
ret = nand_scan_ident(mtd, 1, NULL);
if (ret)
@ -632,6 +638,81 @@ static int rockchip_nand_chips_init(int node, struct rk_nand *rknand)
return 0;
}
#ifdef CONFIG_NAND_ROCKCHIP_DT
static const struct udevice_id rockchip_nandc_ids[] = {
{ .compatible = "rockchip,nandc" },
{ }
};
static int rockchip_nandc_probe(struct udevice *dev)
{
const void *blob = gd->fdt_blob;
struct rk_nand *rknand = dev_get_priv(dev);
fdt_addr_t regs;
int ret = 0, node;
node = fdtdec_next_compatible(blob, 0, COMPAT_ROCKCHIP_NANDC);
rknand->dev = dev;
regs = dev_read_addr(dev);
if (regs == FDT_ADDR_T_NONE) {
debug("Nand address not found\n");
return ret;
}
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");
return ret;
}
static int rockchip_nandc_bind(struct udevice *udev)
{
int ret = 0;
#ifdef CONFIG_MTD_BLK
struct udevice *bdev;
ret = blk_create_devicef(udev, "mtd_blk", "blk", IF_TYPE_MTD,
0, 512, 0, &bdev);
if (ret)
printf("Cannot create block device\n");
#endif
return ret;
}
U_BOOT_DRIVER(rk_nandc_v6) = {
.name = "rk_nandc_v6",
.id = UCLASS_MTD,
.of_match = rockchip_nandc_ids,
.bind = rockchip_nandc_bind,
.probe = rockchip_nandc_probe,
.priv_auto_alloc_size = sizeof(struct rk_nand),
};
void board_nand_init(void)
{
struct udevice *dev;
int ret;
ret = uclass_get_device_by_driver(UCLASS_MTD,
DM_GET_DRIVER(rk_nandc_v6),
&dev);
if (ret && ret != -ENODEV)
pr_err("Failed to initialize NAND controller. (error %d)\n",
ret);
}
#else
void board_nand_init(void)
{
const void *blob = gd->fdt_blob;
@ -678,6 +759,8 @@ err:
kfree(rknand);
}
#endif
int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
{
struct mtd_info *mtd;

View File

@ -6,14 +6,16 @@
*/
#include <common.h>
#include <dm.h>
#include <fdtdec.h>
#include <inttypes.h>
#include <nand.h>
#include <linux/io.h>
#include <linux/ioport.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;
@ -81,6 +83,7 @@ struct rk_nand {
bool bootromblocks;
void __iomem *regs;
int selected_bank;
struct udevice *dev;
};
static struct nand_ecclayout nand_oob_fix = {
@ -591,6 +594,9 @@ static int rockchip_nand_chip_init(int node, struct rk_nand *rknand, int devnum)
mtd = nand_to_mtd(chip);
mtd->name = "rknand";
mtd->dev = rknand->dev;
if (rknand->dev)
rknand->dev->priv = mtd;
ret = nand_scan_ident(mtd, 1, NULL);
if (ret)
@ -633,6 +639,81 @@ static int rockchip_nand_chips_init(int node, struct rk_nand *rknand)
return 0;
}
#ifdef CONFIG_NAND_ROCKCHIP_DT
static const struct udevice_id rockchip_nandc_ids[] = {
{ .compatible = "rockchip,nandc" },
{ }
};
static int rockchip_nandc_probe(struct udevice *dev)
{
const void *blob = gd->fdt_blob;
struct rk_nand *rknand = dev_get_priv(dev);
fdt_addr_t regs;
int ret = 0, node;
node = fdtdec_next_compatible(blob, 0, COMPAT_ROCKCHIP_NANDC);
rknand->dev = dev;
regs = dev_read_addr(dev);
if (regs == FDT_ADDR_T_NONE) {
debug("Nand address not found\n");
return ret;
}
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");
return ret;
}
static int rockchip_nandc_bind(struct udevice *udev)
{
int ret = 0;
#ifdef CONFIG_MTD_BLK
struct udevice *bdev;
ret = blk_create_devicef(udev, "mtd_blk", "blk", IF_TYPE_MTD,
0, 512, 0, &bdev);
if (ret)
printf("Cannot create block device\n");
#endif
return ret;
}
U_BOOT_DRIVER(rk_nandc_v9) = {
.name = "rk_nandc_v9",
.id = UCLASS_MTD,
.of_match = rockchip_nandc_ids,
.bind = rockchip_nandc_bind,
.probe = rockchip_nandc_probe,
.priv_auto_alloc_size = sizeof(struct rk_nand),
};
void board_nand_init(void)
{
struct udevice *dev;
int ret;
ret = uclass_get_device_by_driver(UCLASS_MTD,
DM_GET_DRIVER(rk_nandc_v9),
&dev);
if (ret && ret != -ENODEV)
pr_err("Failed to initialize NAND controller. (error %d)\n",
ret);
}
#else
void board_nand_init(void)
{
const void *blob = gd->fdt_blob;
@ -679,6 +760,8 @@ err:
kfree(rknand);
}
#endif
int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
{
struct mtd_info *mtd;