diff --git a/Makefile b/Makefile index bccfbaa11db76c4d85d70b34db1ed8a1ab69774c..99cc8cf2f701b4f3782dc7835127f3c3813a0674 100644 --- a/Makefile +++ b/Makefile @@ -638,6 +638,7 @@ libs-y += drivers/net/ libs-y += drivers/net/phy/ libs-y += drivers/pci/ libs-y += drivers/power/ \ + drivers/power/domain/ \ drivers/power/fuel_gauge/ \ drivers/power/mfd/ \ drivers/power/pmic/ \ diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4a62d4b1083dd21c7bf120a00548c5923f1a670f..6de734f8f20f04b604294d45bc3f68bfbc89e513 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -657,10 +657,13 @@ config ARCH_ZYNQ select DM_GPIO select SPL_DM if SPL select DM_MMC + select DM_MMC_OPS select DM_SPI select DM_SERIAL select DM_SPI_FLASH select SPL_SEPARATE_BSS if SPL + select DM_USB if USB + select BLK config ARCH_ZYNQMP bool "Support Xilinx ZynqMP Platform" @@ -671,6 +674,10 @@ config ARCH_ZYNQMP select SUPPORT_SPL select CLK select SPL_CLK + select DM_USB if USB + select DM_MMC + select DM_MMC_OPS + select BLK config TEGRA bool "NVIDIA Tegra" diff --git a/arch/arm/cpu/armv8/zynqmp/Kconfig b/arch/arm/cpu/armv8/zynqmp/Kconfig index 6c71d7840eb5428778660cb29633f91823dd3180..ed3305d71821f3421f403eceddd4420ec045bc61 100644 --- a/arch/arm/cpu/armv8/zynqmp/Kconfig +++ b/arch/arm/cpu/armv8/zynqmp/Kconfig @@ -20,4 +20,8 @@ config SYS_CONFIG_NAME config ZYNQMP_USB bool "Configure ZynqMP USB" +config SYS_MALLOC_F_LEN + default 0x600 + + endif diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig index db3c5792939e837d9445de839e5e6867d75e50b3..a98232097b2830dfce95e17d56752a7ec9f24537 100644 --- a/arch/arm/mach-zynq/Kconfig +++ b/arch/arm/mach-zynq/Kconfig @@ -17,4 +17,7 @@ config SYS_CONFIG_NAME Based on this option include/configs/<CONFIG_SYS_CONFIG_NAME>.h header will be used for board configuration. +config SYS_MALLOC_F_LEN + default 0x600 + endif diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 9e46f9e815a6628b16669fb427b7f178b1bd5808..fff175d1b7a2da54a1d636b02c51a36571e55275 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -262,6 +262,16 @@ }; }; + pwrdom: power-domain { + compatible = "sandbox,power-domain"; + #power-domain-cells = <1>; + }; + + power-domain-test { + compatible = "sandbox,power-domain-test"; + power-domains = <&pwrdom 2>; + }; + ram { compatible = "sandbox,ram"; }; diff --git a/arch/sandbox/include/asm/power-domain.h b/arch/sandbox/include/asm/power-domain.h new file mode 100644 index 0000000000000000000000000000000000000000..cad388549eefbbc586d9d41289243a7076e807be --- /dev/null +++ b/arch/sandbox/include/asm/power-domain.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef __SANDBOX_POWER_DOMAIN_H +#define __SANDBOX_POWER_DOMAIN_H + +#include <common.h> + +struct udevice; + +int sandbox_power_domain_query(struct udevice *dev, unsigned long id); + +int sandbox_power_domain_test_get(struct udevice *dev); +int sandbox_power_domain_test_on(struct udevice *dev); +int sandbox_power_domain_test_off(struct udevice *dev); +int sandbox_power_domain_test_free(struct udevice *dev); + +#endif diff --git a/arch/x86/lib/lpc-uclass.c b/arch/x86/lib/lpc-uclass.c index c6e8f73d2254934497e9938bb8938188fd750d81..eb033e6b3f6312fc0ea82a054af9ac57383941b8 100644 --- a/arch/x86/lib/lpc-uclass.c +++ b/arch/x86/lib/lpc-uclass.c @@ -7,24 +7,11 @@ #include <common.h> #include <dm.h> -#include <dm/root.h> DECLARE_GLOBAL_DATA_PTR; -static int lpc_uclass_post_bind(struct udevice *bus) -{ - /* - * Scan the device tree for devices - * - * Before relocation, only bind devices marked for pre-relocation - * use. - */ - return dm_scan_fdt_node(bus, gd->fdt_blob, bus->of_offset, - gd->flags & GD_FLG_RELOC ? false : true); -} - UCLASS_DRIVER(lpc) = { .id = UCLASS_LPC, .name = "lpc", - .post_bind = lpc_uclass_post_bind, + .post_bind = dm_scan_fdt_dev, }; diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c index f2435ab7e52e51e8969787257dfdd1b1386906fc..1fb66c49174ad63b05f74e21f15e3b9f4db09505 100644 --- a/cmd/bdinfo.c +++ b/cmd/bdinfo.c @@ -416,6 +416,11 @@ static int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, #ifdef CONFIG_BOARD_TYPES printf("Board Type = %ld\n", gd->board_type); #endif +#ifdef CONFIG_SYS_MALLOC_F + printf("Early malloc usage: %lx / %x\n", gd->malloc_ptr, + CONFIG_SYS_MALLOC_F_LEN); +#endif + return 0; } diff --git a/cmd/usb_mass_storage.c b/cmd/usb_mass_storage.c index b05913ac34464903bbc285f52b7a129843bbf5cf..86398fc24e8bf799887d46a60fb4b2b091cba98f 100644 --- a/cmd/usb_mass_storage.c +++ b/cmd/usb_mass_storage.c @@ -22,7 +22,7 @@ static int ums_read_sector(struct ums *ums_dev, struct blk_desc *block_dev = &ums_dev->block_dev; lbaint_t blkstart = start + ums_dev->start_sector; - return block_dev->block_read(block_dev, blkstart, blkcnt, buf); + return blk_dread(block_dev, blkstart, blkcnt, buf); } static int ums_write_sector(struct ums *ums_dev, @@ -31,7 +31,7 @@ static int ums_write_sector(struct ums *ums_dev, struct blk_desc *block_dev = &ums_dev->block_dev; lbaint_t blkstart = start + ums_dev->start_sector; - return block_dev->block_write(block_dev, blkstart, blkcnt, buf); + return blk_dwrite(block_dev, blkstart, blkcnt, buf); } static struct ums *ums; diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 6b3e9e4a17a0e6be63179c9a944fb98313d3d76e..7c7f32959b224a44b789bc8b4642c60b2e28655f 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -155,7 +155,7 @@ static int mmc_load_image_raw_partition(struct mmc *mmc, int partition) disk_partition_t info; int err; - err = part_get_info(&mmc->block_dev, partition, &info); + err = part_get_info(mmc_get_blk_desc(mmc), partition, &info); if (err) { #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT puts("spl: partition error\n"); diff --git a/common/usb_hub.c b/common/usb_hub.c index 0f39c9faf7ea4248cd8e60da5fc1b6446208ebf7..ff9cd50eab7c4f7a335572f0e226f53bb285c04c 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -36,7 +36,6 @@ #include <asm/state.h> #endif #include <asm/unaligned.h> -#include <dm/root.h> DECLARE_GLOBAL_DATA_PTR; @@ -755,12 +754,6 @@ int usb_hub_scan(struct udevice *hub) return usb_hub_configure(udev); } -static int usb_hub_post_bind(struct udevice *dev) -{ - /* Scan the bus for devices */ - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); -} - static int usb_hub_post_probe(struct udevice *dev) { debug("%s\n", __func__); @@ -782,7 +775,7 @@ U_BOOT_DRIVER(usb_generic_hub) = { UCLASS_DRIVER(usb_hub) = { .id = UCLASS_USB_HUB, .name = "usb_hub", - .post_bind = usb_hub_post_bind, + .post_bind = dm_scan_fdt_dev, .post_probe = usb_hub_post_probe, .child_pre_probe = usb_child_pre_probe, .per_child_auto_alloc_size = sizeof(struct usb_device), diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 29e6d85bd4c44de25f5dcb4e41782b8ab142ad35..887d83acfd5e35d164c9d8c2af5e531aa77cc6ce 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -176,3 +176,5 @@ CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y CONFIG_UT_ENV=y +CONFIG_POWER_DOMAIN=y +CONFIG_SANDBOX_POWER_DOMAIN=y diff --git a/drivers/core/root.c b/drivers/core/root.c index 158702406ed19e617307de370a9ba4d6ab6b1565..33dc9c0b2db5acd8b2a7c1bd4be1b762eab70e48 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -218,6 +218,15 @@ int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset, return ret; } +int dm_scan_fdt_dev(struct udevice *dev) +{ + if (dev->of_offset == -1) + return 0; + + return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, + gd->flags & GD_FLG_RELOC ? false : true); +} + int dm_scan_fdt(const void *blob, bool pre_reloc_only) { return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only); diff --git a/drivers/core/simple-bus.c b/drivers/core/simple-bus.c index 1a9c864ef377e65334f0cf50a1e83e49be8675a2..5c955da3346b2c1ff665060100b2f875a87cbe50 100644 --- a/drivers/core/simple-bus.c +++ b/drivers/core/simple-bus.c @@ -6,7 +6,6 @@ #include <common.h> #include <dm.h> -#include <dm/root.h> DECLARE_GLOBAL_DATA_PTR; @@ -41,7 +40,7 @@ static int simple_bus_post_bind(struct udevice *dev) plat->size = cell[2]; } - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); + return dm_scan_fdt_dev(dev); } UCLASS_DRIVER(simple_bus) = { diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c index 20b30ffbeb5197217c382a84fa37f5b87c6b96e9..dbd3789747dfdacc1ca2fc013203ff8d4f416e05 100644 --- a/drivers/i2c/i2c-uclass.c +++ b/drivers/i2c/i2c-uclass.c @@ -12,7 +12,6 @@ #include <malloc.h> #include <dm/device-internal.h> #include <dm/lists.h> -#include <dm/root.h> DECLARE_GLOBAL_DATA_PTR; @@ -499,16 +498,6 @@ static int i2c_post_probe(struct udevice *dev) #endif } -static int i2c_post_bind(struct udevice *dev) -{ -#if CONFIG_IS_ENABLED(OF_CONTROL) - /* Scan the bus for devices */ - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); -#else - return 0; -#endif -} - static int i2c_child_post_bind(struct udevice *dev) { #if CONFIG_IS_ENABLED(OF_CONTROL) @@ -527,7 +516,9 @@ UCLASS_DRIVER(i2c) = { .id = UCLASS_I2C, .name = "i2c", .flags = DM_UC_FLAG_SEQ_ALIAS, - .post_bind = i2c_post_bind, +#if CONFIG_IS_ENABLED(OF_CONTROL) + .post_bind = dm_scan_fdt_dev, +#endif .post_probe = i2c_post_probe, .per_device_auto_alloc_size = sizeof(struct dm_i2c_bus), .per_child_platdata_auto_alloc_size = sizeof(struct dm_i2c_chip), diff --git a/drivers/i2c/sandbox_i2c.c b/drivers/i2c/sandbox_i2c.c index 2c84c41643c8b442dea3634ac36367b97903b917..4696a1ae62a96650192e3234e7e4453513583101 100644 --- a/drivers/i2c/sandbox_i2c.c +++ b/drivers/i2c/sandbox_i2c.c @@ -14,7 +14,6 @@ #include <asm/test.h> #include <dm/lists.h> #include <dm/device-internal.h> -#include <dm/root.h> DECLARE_GLOBAL_DATA_PTR; @@ -33,8 +32,7 @@ static int get_emul(struct udevice *dev, struct udevice **devp, *opsp = NULL; plat = dev_get_parent_platdata(dev); if (!plat->emul) { - ret = dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, - false); + ret = dm_scan_fdt_dev(dev); if (ret) return ret; diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index e3229efed0bb44529653b662765705949e852b13..aea8d61f347df8bceb15450174ab249490da0e59 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -26,7 +26,6 @@ #include <asm/io.h> #include <asm-generic/gpio.h> #include <dm/device-internal.h> -#include <dm/root.h> #include <dm/uclass-internal.h> #ifdef DEBUG_TRACE @@ -1450,12 +1449,6 @@ static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return ret; } -int cros_ec_post_bind(struct udevice *dev) -{ - /* Scan for available EC devices (e.g. I2C tunnel) */ - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); -} - U_BOOT_CMD( crosec, 6, 1, do_cros_ec, "CROS-EC utility command", @@ -1482,5 +1475,5 @@ UCLASS_DRIVER(cros_ec) = { .id = UCLASS_CROS_EC, .name = "cros_ec", .per_device_auto_alloc_size = sizeof(struct cros_ec_dev), - .post_bind = cros_ec_post_bind, + .post_bind = dm_scan_fdt_dev, }; diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 2cf7bae79232dac03f45ca30e293097179537870..b58c2824167328151357035b39202f2b78167ea7 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -182,7 +182,7 @@ static int dwmci_set_transfer_mode(struct dwmci_host *host, } #ifdef CONFIG_DM_MMC_OPS -int dwmci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, +static int dwmci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, struct mmc_data *data) { struct mmc *mmc = mmc_get_mmc_dev(dev); @@ -195,7 +195,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac, data ? DIV_ROUND_UP(data->blocks, 8) : 0); int ret = 0, flags = 0, i; - unsigned int timeout = 100000; + unsigned int timeout = 500; u32 retry = 100000; u32 mask, ctrl; ulong start = get_timer(0); @@ -381,7 +381,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq) } #ifdef CONFIG_DM_MMC_OPS -int dwmci_set_ios(struct udevice *dev) +static int dwmci_set_ios(struct udevice *dev) { struct mmc *mmc = mmc_get_mmc_dev(dev); #else diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c index 6a0e9719b8a49cb354b46ed711350e2bb47a2293..8a9630208c5b5f27b70c884864b8aefad53e7348 100644 --- a/drivers/mmc/socfpga_dw_mmc.c +++ b/drivers/mmc/socfpga_dw_mmc.c @@ -22,6 +22,11 @@ static const struct socfpga_clock_manager *clock_manager_base = static const struct socfpga_system_manager *system_manager_base = (void *)SOCFPGA_SYSMGR_ADDRESS; +struct socfpga_dwmci_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + /* socfpga implmentation specific driver private data */ struct dwmci_socfpga_priv_data { struct dwmci_host host; @@ -98,21 +103,45 @@ static int socfpga_dwmmc_ofdata_to_platdata(struct udevice *dev) static int socfpga_dwmmc_probe(struct udevice *dev) { +#ifdef CONFIG_BLK + struct socfpga_dwmci_plat *plat = dev_get_platdata(dev); +#endif struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct dwmci_socfpga_priv_data *priv = dev_get_priv(dev); struct dwmci_host *host = &priv->host; + +#ifdef CONFIG_BLK + dwmci_setup_cfg(&plat->cfg, dev->name, host->buswidth, host->caps, + host->bus_hz, 400000); + host->mmc = &plat->mmc; +#else int ret; ret = add_dwmci(host, host->bus_hz, 400000); if (ret) return ret; - +#endif + host->mmc->priv = &priv->host; upriv->mmc = host->mmc; host->mmc->dev = dev; return 0; } +static int socfpga_dwmmc_bind(struct udevice *dev) +{ +#ifdef CONFIG_BLK + struct socfpga_dwmci_plat *plat = dev_get_platdata(dev); + int ret; + + ret = dwmci_bind(dev, &plat->mmc, &plat->cfg); + if (ret) + return ret; +#endif + + return 0; +} + static const struct udevice_id socfpga_dwmmc_ids[] = { { .compatible = "altr,socfpga-dw-mshc" }, { } @@ -123,6 +152,7 @@ U_BOOT_DRIVER(socfpga_dwmmc_drv) = { .id = UCLASS_MMC, .of_match = socfpga_dwmmc_ids, .ofdata_to_platdata = socfpga_dwmmc_ofdata_to_platdata, + .bind = socfpga_dwmmc_bind, .probe = socfpga_dwmmc_probe, .priv_auto_alloc_size = sizeof(struct dwmci_socfpga_priv_data), }; diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index d405929b64140fa4355bf7c399850ab76a3da645..bcd154a70745e6f2b43ea4a524b23fa181167a10 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -17,10 +17,18 @@ # define CONFIG_ZYNQ_SDHCI_MIN_FREQ 0 #endif +struct arasan_sdhci_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + static int arasan_sdhci_probe(struct udevice *dev) { + struct arasan_sdhci_plat *plat = dev_get_platdata(dev); struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct sdhci_host *host = dev_get_priv(dev); + u32 caps; + int ret; host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B; @@ -31,13 +39,19 @@ static int arasan_sdhci_probe(struct udevice *dev) host->version = sdhci_readw(host, SDHCI_HOST_VERSION); - add_sdhci(host, CONFIG_ZYNQ_SDHCI_MAX_FREQ, - CONFIG_ZYNQ_SDHCI_MIN_FREQ); - - upriv->mmc = host->mmc; + caps = sdhci_readl(host, SDHCI_CAPABILITIES); + ret = sdhci_setup_cfg(&plat->cfg, dev->name, host->bus_width, + caps, CONFIG_ZYNQ_SDHCI_MAX_FREQ, + CONFIG_ZYNQ_SDHCI_MIN_FREQ, host->version, + host->quirks, 0); + host->mmc = &plat->mmc; + if (ret) + return ret; + host->mmc->priv = host; host->mmc->dev = dev; + upriv->mmc = host->mmc; - return 0; + return sdhci_probe(dev); } static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) @@ -50,6 +64,18 @@ static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) return 0; } +static int arasan_sdhci_bind(struct udevice *dev) +{ + struct arasan_sdhci_plat *plat = dev_get_platdata(dev); + int ret; + + ret = sdhci_bind(dev, &plat->mmc, &plat->cfg); + if (ret) + return ret; + + return 0; +} + static const struct udevice_id arasan_sdhci_ids[] = { { .compatible = "arasan,sdhci-8.9a" }, { } @@ -60,6 +86,9 @@ U_BOOT_DRIVER(arasan_sdhci_drv) = { .id = UCLASS_MMC, .of_match = arasan_sdhci_ids, .ofdata_to_platdata = arasan_sdhci_ofdata_to_platdata, + .ops = &sdhci_ops, + .bind = arasan_sdhci_bind, .probe = arasan_sdhci_probe, .priv_auto_alloc_size = sizeof(struct sdhci_host), + .platdata_auto_alloc_size = sizeof(struct arasan_sdhci_plat), }; diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 58d287bb071eed5ce1af2ce037625b17fbc183d6..4eeb0f6ede8c88e82ed5bb859976d0e328d31423 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -8,6 +8,7 @@ */ #include <config.h> #include <common.h> +#include <errno.h> #include <phy.h> #define PHY_AUTONEGOTIATE_TIMEOUT 5000 diff --git a/drivers/pch/pch-uclass.c b/drivers/pch/pch-uclass.c index 7216660a24c773e5910e2c3658a9d540d74135fc..af794eb5a128e845b84bd6fe996544b01feb43dd 100644 --- a/drivers/pch/pch-uclass.c +++ b/drivers/pch/pch-uclass.c @@ -8,7 +8,6 @@ #include <common.h> #include <dm.h> #include <pch.h> -#include <dm/root.h> DECLARE_GLOBAL_DATA_PTR; @@ -55,20 +54,8 @@ int pch_get_io_base(struct udevice *dev, u32 *iobasep) return ops->get_io_base(dev, iobasep); } -static int pch_uclass_post_bind(struct udevice *bus) -{ - /* - * Scan the device tree for devices - * - * Before relocation, only bind devices marked for pre-relocation - * use. - */ - return dm_scan_fdt_node(bus, gd->fdt_blob, bus->of_offset, - gd->flags & GD_FLG_RELOC ? false : true); -} - UCLASS_DRIVER(pch) = { .id = UCLASS_PCH, .name = "pch", - .post_bind = pch_uclass_post_bind, + .post_bind = dm_scan_fdt_dev, }; diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 32590ce498a7505971faaefe4324d0205d581f16..342b78c0c4ba566518284fe04d5e64468e921c72 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -13,7 +13,6 @@ #include <pci.h> #include <asm/io.h> #include <dm/lists.h> -#include <dm/root.h> #include <dm/device-internal.h> #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) #include <asm/fsp/fsp_support.h> @@ -753,27 +752,6 @@ error: return ret; } -static int pci_uclass_post_bind(struct udevice *bus) -{ - /* - * If there is no pci device listed in the device tree, - * don't bother scanning the device tree. - */ - if (bus->of_offset == -1) - return 0; - - /* - * Scan the device tree for devices. This does not probe the PCI bus, - * as this is not permitted while binding. It just finds devices - * mentioned in the device tree. - * - * Before relocation, only bind devices marked for pre-relocation - * use. - */ - return dm_scan_fdt_node(bus, gd->fdt_blob, bus->of_offset, - gd->flags & GD_FLG_RELOC ? false : true); -} - static int decode_regions(struct pci_controller *hose, const void *blob, int parent_node, int node) { @@ -1254,7 +1232,7 @@ UCLASS_DRIVER(pci) = { .id = UCLASS_PCI, .name = "pci", .flags = DM_UC_FLAG_SEQ_ALIAS, - .post_bind = pci_uclass_post_bind, + .post_bind = dm_scan_fdt_dev, .pre_probe = pci_uclass_pre_probe, .post_probe = pci_uclass_post_probe, .child_post_bind = pci_uclass_child_post_bind, diff --git a/drivers/pci/pci_sandbox.c b/drivers/pci/pci_sandbox.c index 6de5130c2a89748a87a683c1e35614ed1b9d0aed..6a84ee386d796e3422325824b02f357898bb0b44 100644 --- a/drivers/pci/pci_sandbox.c +++ b/drivers/pci/pci_sandbox.c @@ -10,7 +10,6 @@ #include <fdtdec.h> #include <inttypes.h> #include <pci.h> -#include <dm/root.h> DECLARE_GLOBAL_DATA_PTR; @@ -52,12 +51,6 @@ static int sandbox_pci_read_config(struct udevice *bus, pci_dev_t devfn, return ops->read_config(emul, offset, valuep, size); } -static int sandbox_pci_child_post_bind(struct udevice *dev) -{ - /* Attach an emulator if we can */ - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); -} - static const struct dm_pci_ops sandbox_pci_ops = { .read_config = sandbox_pci_read_config, .write_config = sandbox_pci_write_config, @@ -73,7 +66,9 @@ U_BOOT_DRIVER(pci_sandbox) = { .id = UCLASS_PCI, .of_match = sandbox_pci_ids, .ops = &sandbox_pci_ops, - .child_post_bind = sandbox_pci_child_post_bind, + + /* Attach an emulator if we can */ + .child_post_bind = dm_scan_fdt_dev, .per_child_platdata_auto_alloc_size = sizeof(struct pci_child_platdata), }; diff --git a/drivers/pinctrl/pinctrl_pic32.c b/drivers/pinctrl/pinctrl_pic32.c index 5cf97ecec86fce1d3d4808a527d359ca1badaec5..9acac29133cb900259eab828c7aa90a771060dbe 100644 --- a/drivers/pinctrl/pinctrl_pic32.c +++ b/drivers/pinctrl/pinctrl_pic32.c @@ -10,7 +10,6 @@ #include <errno.h> #include <asm/io.h> #include <dm/pinctrl.h> -#include <dm/root.h> #include <mach/pic32.h> DECLARE_GLOBAL_DATA_PTR; @@ -341,12 +340,6 @@ static int pic32_pinctrl_probe(struct udevice *dev) return 0; } -static int pic32_pinctrl_bind(struct udevice *dev) -{ - /* scan child GPIO banks */ - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); -} - static const struct udevice_id pic32_pinctrl_ids[] = { { .compatible = "microchip,pic32mzda-pinctrl" }, { } @@ -358,6 +351,6 @@ U_BOOT_DRIVER(pinctrl_pic32) = { .of_match = pic32_pinctrl_ids, .ops = &pic32_pinctrl_ops, .probe = pic32_pinctrl_probe, - .bind = pic32_pinctrl_bind, + .bind = dm_scan_fdt_dev, .priv_auto_alloc_size = sizeof(struct pic32_pinctrl_priv), }; diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3036.c b/drivers/pinctrl/rockchip/pinctrl_rk3036.c index 1f78bf862dbc6f0255c07d347dc12e72fb6a0d92..6aea856aa63f119b816ac62ac0879e7e711411f1 100644 --- a/drivers/pinctrl/rockchip/pinctrl_rk3036.c +++ b/drivers/pinctrl/rockchip/pinctrl_rk3036.c @@ -15,7 +15,6 @@ #include <asm/arch/hardware.h> #include <asm/arch/periph.h> #include <dm/pinctrl.h> -#include <dm/root.h> DECLARE_GLOBAL_DATA_PTR; @@ -253,12 +252,6 @@ static struct pinctrl_ops rk3036_pinctrl_ops = { .get_periph_id = rk3036_pinctrl_get_periph_id, }; -static int rk3036_pinctrl_bind(struct udevice *dev) -{ - /* scan child GPIO banks */ - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); -} - static int rk3036_pinctrl_probe(struct udevice *dev) { struct rk3036_pinctrl_priv *priv = dev_get_priv(dev); @@ -279,6 +272,6 @@ U_BOOT_DRIVER(pinctrl_rk3036) = { .of_match = rk3036_pinctrl_ids, .priv_auto_alloc_size = sizeof(struct rk3036_pinctrl_priv), .ops = &rk3036_pinctrl_ops, - .bind = rk3036_pinctrl_bind, + .bind = dm_scan_fdt_dev, .probe = rk3036_pinctrl_probe, }; diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3288.c b/drivers/pinctrl/rockchip/pinctrl_rk3288.c index 8cb3b8228ed3aa4f61e68d8684e045448505a2d3..ae8a4f1fde681b44ff4545805338e683a531245e 100644 --- a/drivers/pinctrl/rockchip/pinctrl_rk3288.c +++ b/drivers/pinctrl/rockchip/pinctrl_rk3288.c @@ -17,7 +17,6 @@ #include <asm/arch/periph.h> #include <asm/arch/pmu_rk3288.h> #include <dm/pinctrl.h> -#include <dm/root.h> DECLARE_GLOBAL_DATA_PTR; @@ -664,16 +663,6 @@ static struct pinctrl_ops rk3288_pinctrl_ops = { .get_periph_id = rk3288_pinctrl_get_periph_id, }; -static int rk3288_pinctrl_bind(struct udevice *dev) -{ -#if CONFIG_IS_ENABLED(OF_PLATDATA) - return 0; -#else - /* scan child GPIO banks */ - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); -#endif -} - #ifndef CONFIG_SPL_BUILD static int rk3288_pinctrl_parse_tables(struct rk3288_pinctrl_priv *priv, struct rockchip_pin_bank *banks, @@ -730,6 +719,8 @@ U_BOOT_DRIVER(pinctrl_rk3288) = { .of_match = rk3288_pinctrl_ids, .priv_auto_alloc_size = sizeof(struct rk3288_pinctrl_priv), .ops = &rk3288_pinctrl_ops, - .bind = rk3288_pinctrl_bind, +#if !CONFIG_IS_ENABLED(OF_PLATDATA) + .bind = dm_scan_fdt_dev, +#endif .probe = rk3288_pinctrl_probe, }; diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 3c4416780591e6cc1a47a595b49d52e709eb3684..b4227031265077a0c1e7fdb03e4a7266dfa164f9 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -1,5 +1,7 @@ menu "Power" +source "drivers/power/domain/Kconfig" + source "drivers/power/pmic/Kconfig" source "drivers/power/regulator/Kconfig" diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..b9040974339855ba9353ef484782e4f305c63728 --- /dev/null +++ b/drivers/power/domain/Kconfig @@ -0,0 +1,20 @@ +menu "Power Domain Support" + +config POWER_DOMAIN + bool "Enable power domain support using Driver Model" + depends on DM && OF_CONTROL + help + Enable support for the power domain driver class. Many SoCs allow + power to be applied to or removed from portions of the SoC (power + domains). This may be used to save power. This API provides the + means to control such power management hardware. + +config SANDBOX_POWER_DOMAIN + bool "Enable the sandbox power domain test driver" + depends on POWER_DOMAIN && SANDBOX + help + Enable support for a test power domain driver implementation, which + simply accepts requests to power on/off various HW modules without + actually doing anything beyond a little error checking. + +endmenu diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c18292f0ec881b7460c6557c903e5ca40662a3dd --- /dev/null +++ b/drivers/power/domain/Makefile @@ -0,0 +1,7 @@ +# Copyright (c) 2016, NVIDIA CORPORATION. +# +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_POWER_DOMAIN) += power-domain-uclass.o +obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain.o +obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain-test.o diff --git a/drivers/power/domain/power-domain-uclass.c b/drivers/power/domain/power-domain-uclass.c new file mode 100644 index 0000000000000000000000000000000000000000..1bb6262fa1b9b799f19ff0eec542b8a7fc1eee47 --- /dev/null +++ b/drivers/power/domain/power-domain-uclass.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <dm.h> +#include <fdtdec.h> +#include <power-domain.h> +#include <power-domain-uclass.h> + +DECLARE_GLOBAL_DATA_PTR; + +static inline struct power_domain_ops *power_domain_dev_ops(struct udevice *dev) +{ + return (struct power_domain_ops *)dev->driver->ops; +} + +static int power_domain_of_xlate_default(struct power_domain *power_domain, + struct fdtdec_phandle_args *args) +{ + debug("%s(power_domain=%p)\n", __func__, power_domain); + + if (args->args_count != 1) { + debug("Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + power_domain->id = args->args[0]; + + return 0; +} + +int power_domain_get(struct udevice *dev, struct power_domain *power_domain) +{ + struct fdtdec_phandle_args args; + int ret; + struct udevice *dev_power_domain; + struct power_domain_ops *ops; + + debug("%s(dev=%p, power_domain=%p)\n", __func__, dev, power_domain); + + ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset, + "power-domains", + "#power-domain-cells", 0, 0, + &args); + if (ret) { + debug("%s: fdtdec_parse_phandle_with_args failed: %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_of_offset(UCLASS_POWER_DOMAIN, args.node, + &dev_power_domain); + if (ret) { + debug("%s: uclass_get_device_by_of_offset failed: %d\n", + __func__, ret); + return ret; + } + ops = power_domain_dev_ops(dev_power_domain); + + power_domain->dev = dev_power_domain; + if (ops->of_xlate) + ret = ops->of_xlate(power_domain, &args); + else + ret = power_domain_of_xlate_default(power_domain, &args); + if (ret) { + debug("of_xlate() failed: %d\n", ret); + return ret; + } + + ret = ops->request(power_domain); + if (ret) { + debug("ops->request() failed: %d\n", ret); + return ret; + } + + return 0; +} + +int power_domain_free(struct power_domain *power_domain) +{ + struct power_domain_ops *ops = power_domain_dev_ops(power_domain->dev); + + debug("%s(power_domain=%p)\n", __func__, power_domain); + + return ops->free(power_domain); +} + +int power_domain_on(struct power_domain *power_domain) +{ + struct power_domain_ops *ops = power_domain_dev_ops(power_domain->dev); + + debug("%s(power_domain=%p)\n", __func__, power_domain); + + return ops->on(power_domain); +} + +int power_domain_off(struct power_domain *power_domain) +{ + struct power_domain_ops *ops = power_domain_dev_ops(power_domain->dev); + + debug("%s(power_domain=%p)\n", __func__, power_domain); + + return ops->off(power_domain); +} + +UCLASS_DRIVER(power_domain) = { + .id = UCLASS_POWER_DOMAIN, + .name = "power_domain", +}; diff --git a/drivers/power/domain/sandbox-power-domain-test.c b/drivers/power/domain/sandbox-power-domain-test.c new file mode 100644 index 0000000000000000000000000000000000000000..92a3a2a5273b4fb5a775fdbea3f2e6a4243f9ecd --- /dev/null +++ b/drivers/power/domain/sandbox-power-domain-test.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <dm.h> +#include <power-domain.h> +#include <asm/io.h> +#include <asm/power-domain.h> + +struct sandbox_power_domain_test { + struct power_domain pd; +}; + +int sandbox_power_domain_test_get(struct udevice *dev) +{ + struct sandbox_power_domain_test *sbrt = dev_get_priv(dev); + + return power_domain_get(dev, &sbrt->pd); +} + +int sandbox_power_domain_test_on(struct udevice *dev) +{ + struct sandbox_power_domain_test *sbrt = dev_get_priv(dev); + + return power_domain_on(&sbrt->pd); +} + +int sandbox_power_domain_test_off(struct udevice *dev) +{ + struct sandbox_power_domain_test *sbrt = dev_get_priv(dev); + + return power_domain_off(&sbrt->pd); +} + +int sandbox_power_domain_test_free(struct udevice *dev) +{ + struct sandbox_power_domain_test *sbrt = dev_get_priv(dev); + + return power_domain_free(&sbrt->pd); +} + +static const struct udevice_id sandbox_power_domain_test_ids[] = { + { .compatible = "sandbox,power-domain-test" }, + { } +}; + +U_BOOT_DRIVER(sandbox_power_domain_test) = { + .name = "sandbox_power_domain_test", + .id = UCLASS_MISC, + .of_match = sandbox_power_domain_test_ids, + .priv_auto_alloc_size = sizeof(struct sandbox_power_domain_test), +}; diff --git a/drivers/power/domain/sandbox-power-domain.c b/drivers/power/domain/sandbox-power-domain.c new file mode 100644 index 0000000000000000000000000000000000000000..9071346f9844eb7c2c186c29672890165d19b66e --- /dev/null +++ b/drivers/power/domain/sandbox-power-domain.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <dm.h> +#include <power-domain-uclass.h> +#include <asm/io.h> +#include <asm/power-domain.h> + +#define SANDBOX_POWER_DOMAINS 3 + +struct sandbox_power_domain { + bool on[SANDBOX_POWER_DOMAINS]; +}; + +static int sandbox_power_domain_request(struct power_domain *power_domain) +{ + debug("%s(power_domain=%p)\n", __func__, power_domain); + + if (power_domain->id >= SANDBOX_POWER_DOMAINS) + return -EINVAL; + + return 0; +} + +static int sandbox_power_domain_free(struct power_domain *power_domain) +{ + debug("%s(power_domain=%p)\n", __func__, power_domain); + + return 0; +} + +static int sandbox_power_domain_on(struct power_domain *power_domain) +{ + struct sandbox_power_domain *sbr = dev_get_priv(power_domain->dev); + + debug("%s(power_domain=%p)\n", __func__, power_domain); + + sbr->on[power_domain->id] = true; + + return 0; +} + +static int sandbox_power_domain_off(struct power_domain *power_domain) +{ + struct sandbox_power_domain *sbr = dev_get_priv(power_domain->dev); + + debug("%s(power_domain=%p)\n", __func__, power_domain); + + sbr->on[power_domain->id] = false; + + return 0; +} + +static int sandbox_power_domain_bind(struct udevice *dev) +{ + debug("%s(dev=%p)\n", __func__, dev); + + return 0; +} + +static int sandbox_power_domain_probe(struct udevice *dev) +{ + debug("%s(dev=%p)\n", __func__, dev); + + return 0; +} + +static const struct udevice_id sandbox_power_domain_ids[] = { + { .compatible = "sandbox,power-domain" }, + { } +}; + +struct power_domain_ops sandbox_power_domain_ops = { + .request = sandbox_power_domain_request, + .free = sandbox_power_domain_free, + .on = sandbox_power_domain_on, + .off = sandbox_power_domain_off, +}; + +U_BOOT_DRIVER(sandbox_power_domain) = { + .name = "sandbox_power_domain", + .id = UCLASS_POWER_DOMAIN, + .of_match = sandbox_power_domain_ids, + .bind = sandbox_power_domain_bind, + .probe = sandbox_power_domain_probe, + .priv_auto_alloc_size = sizeof(struct sandbox_power_domain), + .ops = &sandbox_power_domain_ops, +}; + +int sandbox_power_domain_query(struct udevice *dev, unsigned long id) +{ + struct sandbox_power_domain *sbr = dev_get_priv(dev); + + debug("%s(dev=%p, id=%ld)\n", __func__, dev, id); + + if (id >= SANDBOX_POWER_DOMAINS) + return -EINVAL; + + return sbr->on[id]; +} diff --git a/drivers/power/pmic/pm8916.c b/drivers/power/pmic/pm8916.c index d4c7d4adff1fd53fb1db33ec495ac175a84f4a81..2b65c697ec9431a87497b29011638464fcef628e 100644 --- a/drivers/power/pmic/pm8916.c +++ b/drivers/power/pmic/pm8916.c @@ -7,7 +7,6 @@ */ #include <common.h> #include <dm.h> -#include <dm/root.h> #include <power/pmic.h> #include <spmi/spmi.h> @@ -79,17 +78,11 @@ static int pm8916_probe(struct udevice *dev) return 0; } - -static int pm8916_bind(struct udevice *dev) -{ - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); -} - U_BOOT_DRIVER(pmic_pm8916) = { .name = "pmic_pm8916", .id = UCLASS_PMIC, .of_match = pm8916_ids, - .bind = pm8916_bind, + .bind = dm_scan_fdt_dev, .probe = pm8916_probe, .ops = &pm8916_ops, .priv_auto_alloc_size = sizeof(struct pm8916_priv), diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index 465ff3fda616055daf964ca15bf2797b058c4695..17f22dda2bdd21158853b1724cfb96e9d801bcc8 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -13,7 +13,7 @@ config DM_REGULATOR - 'drivers/power/pmic/regulator-uclass.c' It's important to call the device_bind() with the proper node offset, when binding the regulator devices. The pmic_bind_childs() can be used - for this purpose if PMIC I/O driver is implemented or dm_scan_fdt_node() + for this purpose if PMIC I/O driver is implemented or dm_scan_fdt_dev() otherwise. Detailed information can be found in the header file. config SPL_DM_REGULATOR diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c index 8003f9bfc8635cb32d0f7808f7c5a3e11bf2c2ed..247abfa72ba1c28f904bd8df846df2e17464e441 100644 --- a/drivers/spi/spi-uclass.c +++ b/drivers/spi/spi-uclass.c @@ -12,7 +12,6 @@ #include <spi.h> #include <dm/device-internal.h> #include <dm/uclass-internal.h> -#include <dm/root.h> #include <dm/lists.h> #include <dm/util.h> @@ -109,12 +108,6 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, return dm_spi_xfer(slave->dev, bitlen, dout, din, flags); } -static int spi_post_bind(struct udevice *dev) -{ - /* Scan the bus for devices */ - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); -} - static int spi_child_post_bind(struct udevice *dev) { struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); @@ -446,7 +439,7 @@ UCLASS_DRIVER(spi) = { .id = UCLASS_SPI, .name = "spi", .flags = DM_UC_FLAG_SEQ_ALIAS, - .post_bind = spi_post_bind, + .post_bind = dm_scan_fdt_dev, .post_probe = spi_post_probe, .child_pre_probe = spi_child_pre_probe, .per_device_auto_alloc_size = sizeof(struct dm_spi_bus), diff --git a/drivers/spmi/spmi-uclass.c b/drivers/spmi/spmi-uclass.c index 4ddd51b556ec1e3092ffe82dcd23ca1c2ea0db87..6edece23d82bf991d0cf0d484cbd60c2b2142475 100644 --- a/drivers/spmi/spmi-uclass.c +++ b/drivers/spmi/spmi-uclass.c @@ -9,7 +9,6 @@ #include <common.h> #include <dm.h> #include <errno.h> -#include <dm/root.h> #include <spmi/spmi.h> #include <linux/ctype.h> @@ -36,13 +35,8 @@ int spmi_reg_write(struct udevice *dev, int usid, int pid, int reg, return ops->write(dev, usid, pid, reg, value); } -static int spmi_post_bind(struct udevice *dev) -{ - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); -} - UCLASS_DRIVER(spmi) = { .id = UCLASS_SPMI, .name = "spmi", - .post_bind = spmi_post_bind, + .post_bind = dm_scan_fdt_dev, }; diff --git a/drivers/usb/emul/usb-emul-uclass.c b/drivers/usb/emul/usb-emul-uclass.c index ee7ea5ad91cf2b9238c470a823cdf547e915bded..6e03c1e0d9e7f1273990fd2967e77a17c2efa862 100644 --- a/drivers/usb/emul/usb-emul-uclass.c +++ b/drivers/usb/emul/usb-emul-uclass.c @@ -8,7 +8,6 @@ #include <common.h> #include <dm.h> #include <usb.h> -#include <dm/root.h> #include <dm/device-internal.h> DECLARE_GLOBAL_DATA_PTR; @@ -265,12 +264,6 @@ int usb_emul_setup_device(struct udevice *dev, int maxpacketsize, return 0; } -int usb_emul_post_bind(struct udevice *dev) -{ - /* Scan the bus for devices */ - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); -} - void usb_emul_reset(struct udevice *dev) { struct usb_dev_platdata *plat = dev_get_parent_platdata(dev); @@ -282,7 +275,7 @@ void usb_emul_reset(struct udevice *dev) UCLASS_DRIVER(usb_emul) = { .id = UCLASS_USB_EMUL, .name = "usb_emul", - .post_bind = usb_emul_post_bind, + .post_bind = dm_scan_fdt_dev, .per_child_auto_alloc_size = sizeof(struct usb_device), .per_child_platdata_auto_alloc_size = sizeof(struct usb_dev_platdata), }; diff --git a/drivers/usb/host/ehci-zynq.c b/drivers/usb/host/ehci-zynq.c index 37a7935b436d52877097bab4f98a7ba4b97bbae4..76642cdad7de1b05b740cd3a505b62f7e4f803eb 100644 --- a/drivers/usb/host/ehci-zynq.c +++ b/drivers/usb/host/ehci-zynq.c @@ -7,55 +7,48 @@ */ #include <common.h> +#include <dm.h> +#include <usb.h> #include <asm/arch/hardware.h> #include <asm/arch/sys_proto.h> #include <asm/io.h> -#include <usb.h> #include <usb/ehci-ci.h> #include <usb/ulpi.h> #include "ehci.h" -#define ZYNQ_USB_USBCMD_RST 0x0000002 -#define ZYNQ_USB_USBCMD_STOP 0x0000000 -#define ZYNQ_USB_NUM_MIO 12 +struct zynq_ehci_priv { + struct ehci_ctrl ehcictrl; + struct usb_ehci *ehci; +}; -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, - struct ehci_hcor **hcor) +static int ehci_zynq_ofdata_to_platdata(struct udevice *dev) { - struct usb_ehci *ehci; + struct zynq_ehci_priv *priv = dev_get_priv(dev); + + priv->ehci = (struct usb_ehci *)dev_get_addr_ptr(dev); + if (!priv->ehci) + return -EINVAL; + + return 0; +} + +static int ehci_zynq_probe(struct udevice *dev) +{ + struct usb_platdata *plat = dev_get_platdata(dev); + struct zynq_ehci_priv *priv = dev_get_priv(dev); + struct ehci_hccr *hccr; + struct ehci_hcor *hcor; struct ulpi_viewport ulpi_vp; - int ret, mio_usb; /* Used for writing the ULPI data address */ struct ulpi_regs *ulpi = (struct ulpi_regs *)0; + int ret; - if (!index) { - mio_usb = zynq_slcr_get_mio_pin_status("usb0"); - if (mio_usb != ZYNQ_USB_NUM_MIO) { - printf("usb0 wrong num MIO: %d, Index %d\n", mio_usb, - index); - return -1; - } - ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR0; - } else { - mio_usb = zynq_slcr_get_mio_pin_status("usb1"); - if (mio_usb != ZYNQ_USB_NUM_MIO) { - printf("usb1 wrong num MIO: %d, Index %d\n", mio_usb, - index); - return -1; - } - ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR1; - } - - *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); - *hcor = (struct ehci_hcor *)((uint32_t) *hccr + - HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); + hccr = (struct ehci_hccr *)((uint32_t)&priv->ehci->caplength); + hcor = (struct ehci_hcor *)((uint32_t) hccr + + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); - ulpi_vp.viewport_addr = (u32)&ehci->ulpi_viewpoint; + ulpi_vp.viewport_addr = (u32)&priv->ehci->ulpi_viewpoint; ulpi_vp.port_num = 0; ret = ulpi_init(&ulpi_vp); @@ -77,28 +70,34 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, ulpi_write(&ulpi_vp, &ulpi->otg_ctrl_set, ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT); - return 0; + return ehci_register(dev, hccr, hcor, NULL, 0, plat->init_type); } -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) +static int ehci_zynq_remove(struct udevice *dev) { - struct usb_ehci *ehci; - - if (!index) - ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR0; - else - ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR1; + int ret; - /* Stop controller */ - writel(ZYNQ_USB_USBCMD_STOP, &ehci->usbcmd); - udelay(1000); - - /* Initiate controller reset */ - writel(ZYNQ_USB_USBCMD_RST, &ehci->usbcmd); + ret = ehci_deregister(dev); + if (ret) + return ret; return 0; } + +static const struct udevice_id ehci_zynq_ids[] = { + { .compatible = "xlnx,zynq-usb-2.20a" }, + { } +}; + +U_BOOT_DRIVER(ehci_zynq) = { + .name = "ehci_zynq", + .id = UCLASS_USB, + .of_match = ehci_zynq_ids, + .ofdata_to_platdata = ehci_zynq_ofdata_to_platdata, + .probe = ehci_zynq_probe, + .remove = ehci_zynq_remove, + .ops = &ehci_usb_ops, + .platdata_auto_alloc_size = sizeof(struct usb_platdata), + .priv_auto_alloc_size = sizeof(struct zynq_ehci_priv), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index 69c9a504ebb8ad8489523868b8991d871115c3d4..be114fc07715b3a900551cc1a55ba2da5198ecdb 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -14,7 +14,6 @@ #include <usb.h> #include <dm/device-internal.h> #include <dm/lists.h> -#include <dm/root.h> #include <dm/uclass-internal.h> DECLARE_GLOBAL_DATA_PTR; @@ -349,12 +348,6 @@ struct usb_device *usb_get_dev_index(struct udevice *bus, int index) } #endif -int usb_post_bind(struct udevice *dev) -{ - /* Scan the bus for devices */ - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); -} - int usb_setup_ehci_gadget(struct ehci_ctrl **ctlrp) { struct usb_platdata *plat; @@ -768,7 +761,7 @@ UCLASS_DRIVER(usb) = { .id = UCLASS_USB, .name = "usb", .flags = DM_UC_FLAG_SEQ_ALIAS, - .post_bind = usb_post_bind, + .post_bind = dm_scan_fdt_dev, .priv_auto_alloc_size = sizeof(struct usb_uclass_priv), .per_child_auto_alloc_size = sizeof(struct usb_device), .per_device_auto_alloc_size = sizeof(struct usb_bus_priv), diff --git a/include/dm/device.h b/include/dm/device.h index 705849b228c648b427a2b1c2d58d7b3e19867380..babf8ac8f078c97e7f9e6c081dc7f1a68214dc36 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -612,6 +612,22 @@ static inline bool device_is_on_pci_bus(struct udevice *dev) #define device_foreach_child_safe(pos, next, parent) \ list_for_each_entry_safe(pos, next, &parent->child_head, sibling_node) +/** + * dm_scan_fdt_dev() - Bind child device in a the device tree + * + * This handles device which have sub-nodes in the device tree. It scans all + * sub-nodes and binds drivers for each node where a driver can be found. + * + * If this is called prior to relocation, only pre-relocation devices will be + * bound (those marked with u-boot,dm-pre-reloc in the device tree, or where + * the driver has the DM_FLAG_PRE_RELOC flag set). Otherwise, all devices will + * be bound. + * + * @dev: Device to scan + * @return 0 if OK, -ve on error + */ +int dm_scan_fdt_dev(struct udevice *dev); + /* device resource management */ typedef void (*dr_release_t)(struct udevice *dev, void *res); typedef int (*dr_match_t)(struct udevice *dev, void *res, void *match_data); diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index c5cdfc79d101103f153cdc039e01c739818cbd17..eb78c4dac485ac7a5bbe901b83b009ff827db278 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -59,6 +59,7 @@ enum uclass_id { UCLASS_PINCTRL, /* Pinctrl (pin muxing/configuration) device */ UCLASS_PMIC, /* PMIC I/O device */ UCLASS_PWM, /* Pulse-width modulator */ + UCLASS_POWER_DOMAIN, /* (SoC) Power domains */ UCLASS_PWRSEQ, /* Power sequence device */ UCLASS_RAM, /* RAM controller */ UCLASS_REGULATOR, /* Regulator device */ diff --git a/include/dwmmc.h b/include/dwmmc.h index 6aebe96b97bc795b711e51ef33a4d2d5434fca5c..d18ec8463b672ef08bd1c0807c158d2d6d838980 100644 --- a/include/dwmmc.h +++ b/include/dwmmc.h @@ -256,8 +256,8 @@ static inline u8 dwmci_readb(struct dwmci_host *host, int reg) * @name: Device name (normally dev->name) * @buswidth: Bus width (in bits, such as 4 or 8) * @caps: Host capabilities (MMC_MODE_...) - * @max_clk: Maximum supported clock speed in HZ (e.g. 400000) - * @min_clk: Minimum supported clock speed in HZ (e.g. 150000000) + * @max_clk: Maximum supported clock speed in HZ (e.g. 150000000) + * @min_clk: Minimum supported clock speed in HZ (e.g. 400000) */ void dwmci_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth, uint caps, u32 max_clk, u32 min_clk); @@ -286,8 +286,8 @@ int dwmci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg); * This is used when you are not using CONFIG_BLK. Convert your driver over! * * @host: DWMMC host structure - * @max_clk: Maximum supported clock speed in HZ (e.g. 400000) - * @min_clk: Minimum supported clock speed in HZ (e.g. 150000000) + * @max_clk: Maximum supported clock speed in HZ (e.g. 150000000) + * @min_clk: Minimum supported clock speed in HZ (e.g. 400000) * @return 0 if OK, -ve on error */ int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk); @@ -295,9 +295,6 @@ int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk); #ifdef CONFIG_DM_MMC_OPS /* Export the operations to drivers */ -int dwmci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, - struct mmc_data *data); -int dwmci_set_ios(struct udevice *dev); int dwmci_probe(struct udevice *dev); extern const struct dm_mmc_ops dm_dwmci_ops; #endif diff --git a/include/power-domain-uclass.h b/include/power-domain-uclass.h new file mode 100644 index 0000000000000000000000000000000000000000..5878021e32c2567548bf30cf1498cc477ff0dbe6 --- /dev/null +++ b/include/power-domain-uclass.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _POWER_DOMAIN_UCLASS_H +#define _POWER_DOMAIN_UCLASS_H + +/* See power-domain.h for background documentation. */ + +#include <power-domain.h> + +struct udevice; + +/** + * struct power_domain_ops - The functions that a power domain controller driver + * must implement. + */ +struct power_domain_ops { + /** + * of_xlate - Translate a client's device-tree (OF) power domain + * specifier. + * + * The power domain core calls this function as the first step in + * implementing a client's power_domain_get() call. + * + * If this function pointer is set to NULL, the power domain core will + * use a default implementation, which assumes #power-domain-cells = + * <1>, and that the DT cell contains a simple integer power domain ID. + * + * At present, the power domain API solely supports device-tree. If + * this changes, other xxx_xlate() functions may be added to support + * those other mechanisms. + * + * @power_domain: The power domain struct to hold the + * translation result. + * @args: The power domain specifier values from device + * tree. + * @return 0 if OK, or a negative error code. + */ + int (*of_xlate)(struct power_domain *power_domain, + struct fdtdec_phandle_args *args); + /** + * request - Request a translated power domain. + * + * The power domain core calls this function as the second step in + * implementing a client's power_domain_get() call, following a + * successful xxx_xlate() call. + * + * @power_domain: The power domain to request; this has been + * filled in by a previous xxx_xlate() function + * call. + * @return 0 if OK, or a negative error code. + */ + int (*request)(struct power_domain *power_domain); + /** + * free - Free a previously requested power domain. + * + * This is the implementation of the client power_domain_free() API. + * + * @power_domain: The power domain to free. + * @return 0 if OK, or a negative error code. + */ + int (*free)(struct power_domain *power_domain); + /** + * on - Power on a power domain. + * + * @power_domain: The power domain to turn on. + * @return 0 if OK, or a negative error code. + */ + int (*on)(struct power_domain *power_domain); + /** + * off - Power off a power domain. + * + * @power_domain: The power domain to turn off. + * @return 0 if OK, or a negative error code. + */ + int (*off)(struct power_domain *power_domain); +}; + +#endif diff --git a/include/power-domain.h b/include/power-domain.h new file mode 100644 index 0000000000000000000000000000000000000000..10999790b568880c689bca12bfd5520fb00f42fc --- /dev/null +++ b/include/power-domain.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _POWER_DOMAIN_H +#define _POWER_DOMAIN_H + +/** + * A power domain is a portion of an SoC or chip that is powered by a + * switchable source of power. In many cases, software has control over the + * power domain, and can turn the power source on or off. This is typically + * done to save power by powering off unused devices, or to enable software + * sequencing of initial powerup at boot. This API provides a means for + * drivers to turn power domains on and off. + * + * A driver that implements UCLASS_POWER_DOMAIN is a power domain controller or + * provider. A controller will often implement multiple separate power domains, + * since the hardware it manages often has this capability. + * power-domain-uclass.h describes the interface which power domain controllers + * must implement. + * + * Depending on the power domain controller hardware, changing the state of a + * power domain may require performing related operations on other resources. + * For example, some power domains may require certain clocks to be enabled + * whenever the power domain is powered on, or during the time when the power + * domain is transitioning state. These details are implementation-specific + * and should ideally be encapsulated entirely within the provider driver, or + * configured through mechanisms (e.g. device tree) that do not require client + * drivers to provide extra configuration information. + * + * Power domain consumers/clients are the drivers for HW modules within the + * power domain. This header file describes the API used by those drivers. + * + * In many cases, a single complex IO controller (e.g. a PCIe controller) will + * be the sole logic contained within a power domain. In such cases, it is + * logical for the relevant device driver to directly control that power + * domain. In other cases, multiple controllers, each with their own driver, + * may be contained in a single power domain. Any logic require to co-ordinate + * between drivers for these multiple controllers is beyond the scope of this + * API at present. Equally, this API does not define or implement any policy + * by which power domains are managed. + */ + +struct udevice; + +/** + * struct power_domain - A handle to (allowing control of) a single power domain. + * + * Clients provide storage for power domain handles. The content of the + * structure is managed solely by the power domain API and power domain + * drivers. A power domain struct is initialized by "get"ing the power domain + * struct. The power domain struct is passed to all other power domain APIs to + * identify which power domain to operate upon. + * + * @dev: The device which implements the power domain. + * @id: The power domain ID within the provider. + * + * Currently, the power domain API assumes that a single integer ID is enough + * to identify and configure any power domain for any power domain provider. If + * this assumption becomes invalid in the future, the struct could be expanded + * to either (a) add more fields to allow power domain providers to store + * additional information, or (b) replace the id field with an opaque pointer, + * which the provider would dynamically allocate during its .of_xlate op, and + * process during is .request op. This may require the addition of an extra op + * to clean up the allocation. + */ +struct power_domain { + struct udevice *dev; + /* + * Written by of_xlate. We assume a single id is enough for now. In the + * future, we might add more fields here. + */ + unsigned long id; +}; + +/** + * power_domain_get - Get/request the power domain for a device. + * + * This looks up and requests a power domain. Each device is assumed to have + * a single (or, at least one) power domain associated with it somehow, and + * that domain, or the first/default domain. The mapping of client device to + * provider power domain may be via device-tree properties, board-provided + * mapping tables, or some other mechanism. + * + * @dev: The client device. + * @power_domain A pointer to a power domain struct to initialize. + * @return 0 if OK, or a negative error code. + */ +int power_domain_get(struct udevice *dev, struct power_domain *power_domain); + +/** + * power_domain_free - Free a previously requested power domain. + * + * @power_domain: A power domain struct that was previously successfully + * requested by power_domain_get(). + * @return 0 if OK, or a negative error code. + */ +int power_domain_free(struct power_domain *power_domain); + +/** + * power_domain_on - Enable power to a power domain. + * + * @power_domain: A power domain struct that was previously successfully + * requested by power_domain_get(). + * @return 0 if OK, or a negative error code. + */ +int power_domain_on(struct power_domain *power_domain); + +/** + * power_domain_off - Disable power ot a power domain. + * + * @power_domain: A power domain struct that was previously successfully + * requested by power_domain_get(). + * @return 0 if OK, or a negative error code. + */ +int power_domain_off(struct power_domain *power_domain); + +#endif diff --git a/include/power/regulator.h b/include/power/regulator.h index 63c0814fe83cea2be9bb800940971c7f420395de..9bcd728120aa9a53b2f4d1a4ebe157539a7d1675 100644 --- a/include/power/regulator.h +++ b/include/power/regulator.h @@ -54,7 +54,7 @@ * which does the scan on the device node, for the 'regulator-name' constraint. * If the parent is not a PMIC device, and the child is not bind by function: * 'pmic_bind_childs()', then it's recommended to bind the device by call to - * dm_scan_fdt_node() - this is usually done automatically for bus devices, + * dm_scan_fdt_dev() - this is usually done automatically for bus devices, * as a post bind method. * * Regulator get: diff --git a/test/dm/Makefile b/test/dm/Makefile index cad3374e43d67694b32804af00a47691800fd1fb..1885e17c38d39d2dfa65238288db8898951460b7 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_LED) += led.o obj-$(CONFIG_DM_MAILBOX) += mailbox.o obj-$(CONFIG_DM_MMC) += mmc.o obj-$(CONFIG_DM_PCI) += pci.o +obj-$(CONFIG_POWER_DOMAIN) += power-domain.o obj-$(CONFIG_RAM) += ram.o obj-y += regmap.o obj-$(CONFIG_REMOTEPROC) += remoteproc.o diff --git a/test/dm/bus.c b/test/dm/bus.c index 3b5a23b934e3678b7527cbf8c6b3919e259a5e4b..d94dcf7a60d87988d9c50dae5f959c056a3777be 100644 --- a/test/dm/bus.c +++ b/test/dm/bus.c @@ -7,7 +7,6 @@ #include <common.h> #include <dm.h> #include <dm/device-internal.h> -#include <dm/root.h> #include <dm/test.h> #include <dm/uclass-internal.h> #include <dm/util.h> @@ -30,7 +29,7 @@ static struct dm_test_state *test_state; static int testbus_drv_probe(struct udevice *dev) { - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); + return dm_scan_fdt_dev(dev); } static int testbus_child_post_bind(struct udevice *dev) diff --git a/test/dm/i2c.c b/test/dm/i2c.c index 23d612eb81eb77368181891a3ef123d51d88bbcd..e2688bfbe9c06d29cf7806253adc5d5e8ba18ec2 100644 --- a/test/dm/i2c.c +++ b/test/dm/i2c.c @@ -31,8 +31,8 @@ static int dm_test_i2c_find(struct unit_test_state *uts) false, &bus)); /* - * i2c_post_bind() will bind devices to chip selects. Check this then - * remove the emulation and the slave device. + * The post_bind() method will bind devices to chip selects. Check + * this then remove the emulation and the slave device. */ ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus)); ut_assertok(dm_i2c_probe(bus, chip, 0, &dev)); diff --git a/test/dm/power-domain.c b/test/dm/power-domain.c new file mode 100644 index 0000000000000000000000000000000000000000..379a8fa3d6e881b0214eee415d902e5b48415d60 --- /dev/null +++ b/test/dm/power-domain.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <dm.h> +#include <dm/test.h> +#include <asm/power-domain.h> +#include <test/ut.h> + +/* This must match the specifier for power-domains in the DT node */ +#define TEST_POWER_DOMAIN 2 + +static int dm_test_power_domain(struct unit_test_state *uts) +{ + struct udevice *dev_power_domain; + struct udevice *dev_test; + + ut_assertok(uclass_get_device_by_name(UCLASS_POWER_DOMAIN, + "power-domain", + &dev_power_domain)); + ut_asserteq(0, sandbox_power_domain_query(dev_power_domain, 0)); + ut_asserteq(0, sandbox_power_domain_query(dev_power_domain, + TEST_POWER_DOMAIN)); + + ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "power-domain-test", + &dev_test)); + ut_assertok(sandbox_power_domain_test_get(dev_test)); + + ut_assertok(sandbox_power_domain_test_on(dev_test)); + ut_asserteq(0, sandbox_power_domain_query(dev_power_domain, 0)); + ut_asserteq(1, sandbox_power_domain_query(dev_power_domain, + TEST_POWER_DOMAIN)); + + ut_assertok(sandbox_power_domain_test_off(dev_test)); + ut_asserteq(0, sandbox_power_domain_query(dev_power_domain, 0)); + ut_asserteq(0, sandbox_power_domain_query(dev_power_domain, + TEST_POWER_DOMAIN)); + + ut_assertok(sandbox_power_domain_test_free(dev_test)); + + return 0; +} +DM_TEST(dm_test_power_domain, DM_TESTF_SCAN_FDT); diff --git a/test/dm/spi.c b/test/dm/spi.c index 2e27da72d505c6afe2df467c0f89fad1ad08c4a5..5733096066c9780a4539270856b03ef4840ffab3 100644 --- a/test/dm/spi.c +++ b/test/dm/spi.c @@ -30,8 +30,8 @@ static int dm_test_spi_find(struct unit_test_state *uts) false, &bus)); /* - * spi_post_bind() will bind devices to chip selects. Check this then - * remove the emulation and the slave device. + * The post_bind() method will bind devices to chip selects. Check + * this then remove the emulation and the slave device. */ ut_asserteq(0, uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus)); ut_assertok(spi_cs_info(bus, cs, &info));