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:
parent
124f23c66c
commit
411568d7eb
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue