The src driver is populating all power domains that are controlled by the system reset controller. Currently supported power domain is the mediamix power domain.
Signed-off-by: Michael Grzeschik <[email protected]> --- arch/arm/mach-imx/imx9.c | 3 + drivers/pmdomain/imx/Makefile | 1 + drivers/pmdomain/imx/imx93-pd.c | 151 ++++++++++++++++++++++++++++++++++++++++ drivers/soc/imx/Makefile | 1 + drivers/soc/imx/imx93-src.c | 30 ++++++++ 5 files changed, 186 insertions(+) diff --git a/arch/arm/mach-imx/imx9.c b/arch/arm/mach-imx/imx9.c index dd4fbf099e601dda3c01a4e2d64a9552d2f616e5..25ba7e444843ea5ae817dd8103074e5a50fb48f0 100644 --- a/arch/arm/mach-imx/imx9.c +++ b/arch/arm/mach-imx/imx9.c @@ -2,6 +2,7 @@ #include <init.h> #include <common.h> +#include <pm_domain.h> #include <linux/clk.h> #include <mach/imx/generic.h> #include <mach/imx/ele.h> @@ -184,5 +185,7 @@ int imx93_init(void) of_register_fixup(of_optee_fixup, &optee_fixup_data); } + genpd_activate(); + return 0; } diff --git a/drivers/pmdomain/imx/Makefile b/drivers/pmdomain/imx/Makefile index 1364944d5ac52dd2faf7002a9df1f3263d48891c..f35ac69f70cd0f403b20c32638f93bbdb34f6b9a 100644 --- a/drivers/pmdomain/imx/Makefile +++ b/drivers/pmdomain/imx/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8mp-blk-ctrl.o +obj-$(CONFIG_ARCH_IMX93) += imx93-pd.o diff --git a/drivers/pmdomain/imx/imx93-pd.c b/drivers/pmdomain/imx/imx93-pd.c new file mode 100644 index 0000000000000000000000000000000000000000..3222fc17e9d02adbb6792df27d5a0fb97fc5c305 --- /dev/null +++ b/drivers/pmdomain/imx/imx93-pd.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2022 NXP + */ + +#include <linux/clk.h> +#include <linux/device.h> +#include <linux/iopoll.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <pm_domain.h> + +#define MIX_SLICE_SW_CTRL_OFF 0x20 +#define SLICE_SW_CTRL_PSW_CTRL_OFF_MASK BIT(4) +#define SLICE_SW_CTRL_PDN_SOFT_MASK BIT(31) + +#define MIX_FUNC_STAT_OFF 0xB4 + +#define FUNC_STAT_PSW_STAT_MASK BIT(0) +#define FUNC_STAT_RST_STAT_MASK BIT(2) +#define FUNC_STAT_ISO_STAT_MASK BIT(4) +#define FUNC_STAT_SSAR_STAT_MASK BIT(8) + +struct imx93_power_domain { + struct generic_pm_domain genpd; + struct device *dev; + void __iomem *addr; + struct clk_bulk_data *clks; + int num_clks; +}; + +#define to_imx93_pd(_genpd) container_of(_genpd, struct imx93_power_domain, genpd) + +static int imx93_pd_on(struct generic_pm_domain *genpd) +{ + struct imx93_power_domain *domain = to_imx93_pd(genpd); + void __iomem *addr = domain->addr; + u32 val; + int ret; + + ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks); + if (ret) { + dev_err(domain->dev, "failed to enable clocks for domain: %s\n", genpd->name); + return ret; + } + + val = readl(addr + MIX_SLICE_SW_CTRL_OFF); + val &= ~SLICE_SW_CTRL_PDN_SOFT_MASK; + writel(val, addr + MIX_SLICE_SW_CTRL_OFF); + + ret = readl_poll_timeout(addr + MIX_FUNC_STAT_OFF, val, + !(val & FUNC_STAT_SSAR_STAT_MASK), 10000); + if (ret) { + dev_err(domain->dev, "pd_on timeout: name: %s, stat: %x\n", genpd->name, val); + return ret; + } + + return 0; +} + +static int imx93_pd_off(struct generic_pm_domain *genpd) +{ + struct imx93_power_domain *domain = to_imx93_pd(genpd); + void __iomem *addr = domain->addr; + int ret; + u32 val; + + /* Power off MIX */ + val = readl(addr + MIX_SLICE_SW_CTRL_OFF); + val |= SLICE_SW_CTRL_PDN_SOFT_MASK; + writel(val, addr + MIX_SLICE_SW_CTRL_OFF); + + ret = readl_poll_timeout(addr + MIX_FUNC_STAT_OFF, val, + val & FUNC_STAT_PSW_STAT_MASK, 10000); + if (ret) { + dev_err(domain->dev, "pd_off timeout: name: %s, stat: %x\n", genpd->name, val); + return ret; + } + + clk_bulk_disable_unprepare(domain->num_clks, domain->clks); + + return 0; +}; + +static int imx93_pd_probe(struct device *dev) +{ + struct device_node *np = dev->of_node; + struct imx93_power_domain *domain; + bool init_off; + int ret; + + domain = devm_kzalloc(dev, sizeof(*domain), GFP_KERNEL); + if (!domain) + return -ENOMEM; + + domain->addr = dev_platform_ioremap_resource(dev, 0); + if (IS_ERR(domain->addr)) + return PTR_ERR(domain->addr); + + domain->num_clks = clk_bulk_get_all(dev, &domain->clks); + if (domain->num_clks < 0) + return dev_err_probe(dev, domain->num_clks, "Failed to get domain's clocks\n"); + + domain->genpd.name = dev_name(dev); + domain->genpd.power_off = imx93_pd_off; + domain->genpd.power_on = imx93_pd_on; + domain->dev = dev; + + init_off = readl(domain->addr + MIX_FUNC_STAT_OFF) & FUNC_STAT_ISO_STAT_MASK; + /* Just to sync the status of hardware */ + if (!init_off) { + ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks); + if (ret) + return dev_err_probe(domain->dev, ret, + "failed to enable clocks for domain: %s\n", + domain->genpd.name); + } + + ret = pm_genpd_init(&domain->genpd, NULL, init_off); + if (ret) + goto err_clk_unprepare; + + ret = of_genpd_add_provider_simple(np, &domain->genpd); + if (ret) + goto err_genpd_remove; + + return 0; + +err_genpd_remove: + pm_genpd_remove(&domain->genpd); + +err_clk_unprepare: + if (!init_off) + clk_bulk_disable_unprepare(domain->num_clks, domain->clks); + + return ret; +} + +static const struct of_device_id imx93_pd_ids[] = { + { .compatible = "fsl,imx93-src-slice" }, + { } +}; +MODULE_DEVICE_TABLE(of, imx93_pd_ids); + +static struct driver imx93_power_domain_driver = { + .name = "imx93_power_domain", + .of_match_table = imx93_pd_ids, + .probe = imx93_pd_probe, +}; +coredevice_platform_driver(imx93_power_domain_driver); +MODULE_LICENSE("GPL"); diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile index 65b2677f7ad5e3826655424efbc3ecd9e2ac5604..53ee0b8f5b3c7451083bdbbd47a76744ebc2b7c5 100644 --- a/drivers/soc/imx/Makefile +++ b/drivers/soc/imx/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_IMX8M_FEATCTRL) += imx8m-featctrl.o obj-$(CONFIG_ARCH_IMX8M) += soc-imx8m.o +obj-$(CONFIG_ARCH_IMX93) += imx93-src.o diff --git a/drivers/soc/imx/imx93-src.c b/drivers/soc/imx/imx93-src.c new file mode 100644 index 0000000000000000000000000000000000000000..4889948141b0f669259306d52862158894557569 --- /dev/null +++ b/drivers/soc/imx/imx93-src.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2022 NXP + */ + +#include <init.h> +#include <driver.h> +#include <linux/module.h> + +static int imx93_src_probe(struct device *dev) +{ + return of_platform_populate(dev->of_node, NULL, dev); +} + +static const struct of_device_id imx93_src_ids[] = { + { .compatible = "fsl,imx93-src" }, + { } +}; +MODULE_DEVICE_TABLE(of, imx93_src_ids); + +static struct driver imx93_src_driver = { + .name = "imx93_src", + .probe = imx93_src_probe, + .of_compatible = imx93_src_ids, +}; +core_platform_driver(imx93_src_driver); + +MODULE_AUTHOR("Peng Fan <[email protected]>"); +MODULE_DESCRIPTION("NXP i.MX93 src driver"); +MODULE_LICENSE("GPL"); -- 2.47.3
