diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 806e3bcb694..7a43448f49d 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -306,7 +306,7 @@ int dram_init(void) return 0; } -#if defined(CONFIG_NAND_SUNXI) +#if defined(CONFIG_NAND_SUNXI) && defined(CONFIG_SPL_BUILD) static void nand_pinmux_setup(void) { unsigned int pin; @@ -342,9 +342,6 @@ void board_nand_init(void) { nand_pinmux_setup(); nand_clock_setup(); -#ifndef CONFIG_SPL_BUILD - sunxi_nand_init(); -#endif } #endif diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 4564375c042..352bef69e4c 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -24,11 +24,13 @@ * GNU General Public License for more details. */ +#include #include #include #include #include #include +#include #include #include #include @@ -260,7 +262,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand) * NAND Controller structure: stores sunxi NAND controller information * * @controller: base controller structure - * @dev: parent device (used to print error messages) + * @dev: DM device (used to print error messages) * @regs: NAND controller registers * @ahb_clk: NAND Controller AHB clock * @mod_clk: NAND Controller mod clock @@ -273,7 +275,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand) */ struct sunxi_nfc { struct nand_hw_control controller; - struct device *dev; + struct udevice *dev; void __iomem *regs; struct clk *ahb_clk; struct clk *mod_clk; @@ -1773,54 +1775,67 @@ static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc) } #endif /* __UBOOT__ */ -void sunxi_nand_init(void) +static int sunxi_nand_probe(struct udevice *dev) { - struct sunxi_nfc *nfc; - phys_addr_t regs; - ofnode node; + struct sunxi_nfc *nfc = dev_get_priv(dev); + struct reset_ctl_bulk rst_bulk; + struct clk_bulk clk_bulk; int ret; - nfc = kzalloc(sizeof(*nfc), GFP_KERNEL); - if (!nfc) - return; - + nfc->dev = dev; spin_lock_init(&nfc->controller.lock); init_waitqueue_head(&nfc->controller.wq); INIT_LIST_HEAD(&nfc->chips); - node = ofnode_by_compatible(ofnode_null(), "allwinner,sun4i-a10-nand"); - if (!ofnode_valid(node)) { - pr_err("unable to find nfc node in device tree\n"); - goto err; - } + nfc->regs = dev_read_addr_ptr(dev); + if (!nfc->regs) + return -EINVAL; - if (!ofnode_is_enabled(node)) { - pr_err("nfc disabled in device tree\n"); - goto err; - } + ret = reset_get_bulk(dev, &rst_bulk); + if (!ret) + reset_deassert_bulk(&rst_bulk); - regs = ofnode_get_addr(node); - if (regs == FDT_ADDR_T_NONE) { - pr_err("unable to find nfc address in device tree\n"); - goto err; - } - - nfc->regs = (void *)regs; + ret = clk_get_bulk(dev, &clk_bulk); + if (!ret) + clk_enable_bulk(&clk_bulk); ret = sunxi_nfc_rst(nfc); if (ret) - goto err; + return ret; - ret = sunxi_nand_chips_init(node, nfc); + ret = sunxi_nand_chips_init(dev_ofnode(dev), nfc); if (ret) { - dev_err(nfc->dev, "failed to init nand chips\n"); - goto err; + dev_err(dev, "failed to init nand chips\n"); + return ret; } - return; + return 0; +} -err: - kfree(nfc); +static const struct udevice_id sunxi_nand_ids[] = { + { + .compatible = "allwinner,sun4i-a10-nand", + }, + { } +}; + +U_BOOT_DRIVER(sunxi_nand) = { + .name = "sunxi_nand", + .id = UCLASS_MTD, + .of_match = sunxi_nand_ids, + .probe = sunxi_nand_probe, + .priv_auto = sizeof(struct sunxi_nfc), +}; + +void board_nand_init(void) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_MTD, + DM_DRIVER_GET(sunxi_nand), &dev); + if (ret && ret != -ENODEV) + pr_err("Failed to initialize sunxi NAND controller: %d\n", ret); } MODULE_LICENSE("GPL v2");