diff options
author | Patrick Wildt <patrick@blueri.se> | 2019-10-03 15:51:50 +0200 |
---|---|---|
committer | Stefano Babic <sbabic@denx.de> | 2019-10-08 16:36:36 +0200 |
commit | d08a194871fdf91b2ccdbaf02e35ed9443e0e170 (patch) | |
tree | 995ae6db6f1adff7d3af8ca8edbe5367706a5cba /drivers/power/domain | |
parent | 6745dac4946656771d320ba6887e863ae64c8b3e (diff) |
imx: add support for i.MX8MQ power domain controller
Add support for the power domain controller that's used on the
i.MX8MQ. This will be needed to be able to power on the PCIe
controller. Bindings taken from Linux, driver implementation
taken from the i.MX8 power domain controller and adjusted for
the i.MX8M SoC.
Signed-off-by: Patrick Wildt <patrick@blueri.se>
Diffstat (limited to 'drivers/power/domain')
-rw-r--r-- | drivers/power/domain/Kconfig | 7 | ||||
-rw-r--r-- | drivers/power/domain/Makefile | 1 | ||||
-rw-r--r-- | drivers/power/domain/imx8m-power-domain.c | 137 |
3 files changed, 145 insertions, 0 deletions
diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig index 06bba6220b..7e2d6a90bf 100644 --- a/drivers/power/domain/Kconfig +++ b/drivers/power/domain/Kconfig @@ -23,6 +23,13 @@ config IMX8_POWER_DOMAIN Enable support for manipulating NXP i.MX8 on-SoC power domains via IPC requests to the SCU. +config IMX8M_POWER_DOMAIN + bool "Enable i.MX8M power domain driver" + depends on POWER_DOMAIN && ARCH_IMX8M + help + Enable support for manipulating NXP i.MX8M on-SoC power domains via + requests to the ATF. + config MTK_POWER_DOMAIN bool "Enable the MediaTek power domain driver" depends on POWER_DOMAIN && ARCH_MEDIATEK diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile index 695aafe17d..4d87d7c7f9 100644 --- a/drivers/power/domain/Makefile +++ b/drivers/power/domain/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_$(SPL_)POWER_DOMAIN) += power-domain-uclass.o obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o obj-$(CONFIG_IMX8_POWER_DOMAIN) += imx8-power-domain.o +obj-$(CONFIG_IMX8M_POWER_DOMAIN) += imx8m-power-domain.o obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain.o diff --git a/drivers/power/domain/imx8m-power-domain.c b/drivers/power/domain/imx8m-power-domain.c new file mode 100644 index 0000000000..164fb3d31d --- /dev/null +++ b/drivers/power/domain/imx8m-power-domain.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2017 NXP + */ + +#include <common.h> +#include <dm.h> +#include <power-domain-uclass.h> +#include <asm/io.h> +#include <asm/arch/power-domain.h> +#include <asm/mach-imx/sys_proto.h> +#include <dm/device-internal.h> +#include <dm/device.h> +#include <imx_sip.h> + +DECLARE_GLOBAL_DATA_PTR; + +static int imx8m_power_domain_request(struct power_domain *power_domain) +{ + return 0; +} + +static int imx8m_power_domain_free(struct power_domain *power_domain) +{ + return 0; +} + +static int imx8m_power_domain_on(struct power_domain *power_domain) +{ + struct udevice *dev = power_domain->dev; + struct imx8m_power_domain_platdata *pdata; + pdata = dev_get_platdata(dev); + + if (pdata->resource_id < 0) + return -EINVAL; + + if (pdata->has_pd) + power_domain_on(&pdata->pd); + + call_imx_sip(IMX_SIP_GPC, IMX_SIP_GPC_PM_DOMAIN, pdata->resource_id, 1); + + return 0; +} + +static int imx8m_power_domain_off(struct power_domain *power_domain) +{ + struct udevice *dev = power_domain->dev; + struct imx8m_power_domain_platdata *pdata; + pdata = dev_get_platdata(dev); + + if (pdata->resource_id < 0) + return -EINVAL; + + call_imx_sip(IMX_SIP_GPC, IMX_SIP_GPC_PM_DOMAIN, pdata->resource_id, 0); + + if (pdata->has_pd) + power_domain_off(&pdata->pd); + + return 0; +} + +static int imx8m_power_domain_of_xlate(struct power_domain *power_domain, + struct ofnode_phandle_args *args) +{ + return 0; +} + +static int imx8m_power_domain_bind(struct udevice *dev) +{ + int offset; + const char *name; + int ret = 0; + + offset = dev_of_offset(dev); + for (offset = fdt_first_subnode(gd->fdt_blob, offset); offset > 0; + offset = fdt_next_subnode(gd->fdt_blob, offset)) { + /* Bind the subnode to this driver */ + name = fdt_get_name(gd->fdt_blob, offset, NULL); + + ret = device_bind_with_driver_data(dev, dev->driver, name, + dev->driver_data, + offset_to_ofnode(offset), + NULL); + + if (ret == -ENODEV) + printf("Driver '%s' refuses to bind\n", + dev->driver->name); + + if (ret) + printf("Error binding driver '%s': %d\n", + dev->driver->name, ret); + } + + return 0; +} + +static int imx8m_power_domain_probe(struct udevice *dev) +{ + return 0; +} + +static int imx8m_power_domain_ofdata_to_platdata(struct udevice *dev) +{ + struct imx8m_power_domain_platdata *pdata = dev_get_platdata(dev); + + pdata->resource_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), + "reg", -1); + + if (!power_domain_get(dev, &pdata->pd)) + pdata->has_pd = 1; + + return 0; +} + +static const struct udevice_id imx8m_power_domain_ids[] = { + { .compatible = "fsl,imx8mq-gpc" }, + { } +}; + +struct power_domain_ops imx8m_power_domain_ops = { + .request = imx8m_power_domain_request, + .free = imx8m_power_domain_free, + .on = imx8m_power_domain_on, + .off = imx8m_power_domain_off, + .of_xlate = imx8m_power_domain_of_xlate, +}; + +U_BOOT_DRIVER(imx8m_power_domain) = { + .name = "imx8m_power_domain", + .id = UCLASS_POWER_DOMAIN, + .of_match = imx8m_power_domain_ids, + .bind = imx8m_power_domain_bind, + .probe = imx8m_power_domain_probe, + .ofdata_to_platdata = imx8m_power_domain_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct imx8m_power_domain_platdata), + .ops = &imx8m_power_domain_ops, +}; |