diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-08-30 16:37:00 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-08-30 16:37:00 -0700 |
commit | c66403f62717e1af3be2a1873d52d2cf4724feba (patch) | |
tree | d2cde77d83f6c1d5500b3aae2fb67fe963a287a2 /drivers/soc | |
parent | 4fb0dacb78c6a041bbd38ddd998df806af5c2c69 (diff) | |
parent | 5e536362f6ab97f709c07bfda962a7bb036c2563 (diff) |
Merge tag 'genpd-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm
Pull ARM SoC generic power domain driver updates from Ulf Hansson:
"This adds a new subsystem for generic power domain providers in
drivers/genpd and starts moving some of the corresponding code in
there.
We have currently ~60 users of the genpd provider interface, which are
sprinkled across various subsystems. To release some burden from the
soc maintainers (Arnd Bergmann, etc) in particular, but also to gain a
better overall view of what goes on in the area, I will help out with
maintenance"
[ I find the "genpd" name singularly uninformative, so we'll probably
end up moving this driver subsystem somewhere else, but that's still
being discussed - Linus ]
* tag 'genpd-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm: (30 commits)
genpd: ti: Use for_each_node_with_property() simplify code logic
genpd: Explicitly include correct DT includes
genpd: imx: scu-pd: initialize is_off according to HW state
genpd: imx: scu-pd: Suppress bind attrs
genpd: imx: scu-pd: do not power off console if no_console_suspend
genpd: imx: scu-pd: add more PDs
genpd: imx: scu-pd: enlarge PD range
genpd: imx: relocate scu-pd under genpd
MAINTAINERS: adjust file entry in STARFIVE JH71XX PMU CONTROLLER DRIVER
genpd: Makefile: build imx
genpd: move owl-sps-helper.c from drivers/soc
soc: starfive: remove stale Makefile entry
ARM: ux500: Move power-domain driver to the genpd dir
ARM: ux500: Convert power-domain code into a regular platform driver
soc: xilinx: Move power-domain driver to the genpd dir
soc: ti: Mover power-domain drivers to the genpd dir
soc: tegra: Move powergate-bpmp driver to the genpd dir
soc: sunxi: Move power-domain driver to the genpd dir
soc: starfive: Move the power-domain driver to the genpd dir
soc: samsung: Move power-domain driver to the genpd dir
...
Diffstat (limited to 'drivers/soc')
85 files changed, 22 insertions, 22705 deletions
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index 3b0f9fb3b5c8..708eaad8f590 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -3,7 +3,6 @@ # Makefile for the Linux Kernel SOC specific device drivers. # -obj-$(CONFIG_ARCH_ACTIONS) += actions/ obj-y += apple/ obj-y += aspeed/ obj-$(CONFIG_ARCH_AT91) += atmel/ @@ -29,7 +28,6 @@ obj-y += renesas/ obj-y += rockchip/ obj-$(CONFIG_SOC_SAMSUNG) += samsung/ obj-y += sifive/ -obj-$(CONFIG_SOC_STARFIVE) += starfive/ obj-y += sunxi/ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-y += ti/ diff --git a/drivers/soc/actions/Makefile b/drivers/soc/actions/Makefile deleted file mode 100644 index 4db9e7b050e5..000000000000 --- a/drivers/soc/actions/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0+ - -obj-$(CONFIG_OWL_PM_DOMAINS_HELPER) += owl-sps-helper.o -obj-$(CONFIG_OWL_PM_DOMAINS) += owl-sps.o diff --git a/drivers/soc/actions/owl-sps-helper.c b/drivers/soc/actions/owl-sps-helper.c deleted file mode 100644 index e3f36603dd53..000000000000 --- a/drivers/soc/actions/owl-sps-helper.c +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Actions Semi Owl Smart Power System (SPS) shared helpers - * - * Copyright 2012 Actions Semi Inc. - * Author: Actions Semi, Inc. - * - * Copyright (c) 2017 Andreas Färber - */ - -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/soc/actions/owl-sps.h> - -#define OWL_SPS_PG_CTL 0x0 - -int owl_sps_set_pg(void __iomem *base, u32 pwr_mask, u32 ack_mask, bool enable) -{ - u32 val; - bool ack; - int timeout; - - val = readl(base + OWL_SPS_PG_CTL); - ack = val & ack_mask; - if (ack == enable) - return 0; - - if (enable) - val |= pwr_mask; - else - val &= ~pwr_mask; - - writel(val, base + OWL_SPS_PG_CTL); - - for (timeout = 5000; timeout > 0; timeout -= 50) { - val = readl(base + OWL_SPS_PG_CTL); - if ((val & ack_mask) == (enable ? ack_mask : 0)) - break; - udelay(50); - } - if (timeout <= 0) - return -ETIMEDOUT; - - udelay(10); - - return 0; -} -EXPORT_SYMBOL_GPL(owl_sps_set_pg); diff --git a/drivers/soc/actions/owl-sps.c b/drivers/soc/actions/owl-sps.c deleted file mode 100644 index 73a9e0bb7e8e..000000000000 --- a/drivers/soc/actions/owl-sps.c +++ /dev/null @@ -1,320 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Actions Semi Owl Smart Power System (SPS) - * - * Copyright 2012 Actions Semi Inc. - * Author: Actions Semi, Inc. - * - * Copyright (c) 2017 Andreas Färber - */ - -#include <linux/of_address.h> -#include <linux/of_platform.h> -#include <linux/pm_domain.h> -#include <linux/soc/actions/owl-sps.h> -#include <dt-bindings/power/owl-s500-powergate.h> -#include <dt-bindings/power/owl-s700-powergate.h> -#include <dt-bindings/power/owl-s900-powergate.h> - -struct owl_sps_domain_info { - const char *name; - int pwr_bit; - int ack_bit; - unsigned int genpd_flags; -}; - -struct owl_sps_info { - unsigned num_domains; - const struct owl_sps_domain_info *domains; -}; - -struct owl_sps { - struct device *dev; - const struct owl_sps_info *info; - void __iomem *base; - struct genpd_onecell_data genpd_data; - struct generic_pm_domain *domains[]; -}; - -#define to_owl_pd(gpd) container_of(gpd, struct owl_sps_domain, genpd) - -struct owl_sps_domain { - struct generic_pm_domain genpd; - const struct owl_sps_domain_info *info; - struct owl_sps *sps; -}; - -static int owl_sps_set_power(struct owl_sps_domain *pd, bool enable) -{ - u32 pwr_mask, ack_mask; - - ack_mask = BIT(pd->info->ack_bit); - pwr_mask = BIT(pd->info->pwr_bit); - - return owl_sps_set_pg(pd->sps->base, pwr_mask, ack_mask, enable); -} - -static int owl_sps_power_on(struct generic_pm_domain *domain) -{ - struct owl_sps_domain *pd = to_owl_pd(domain); - - dev_dbg(pd->sps->dev, "%s power on", pd->info->name); - - return owl_sps_set_power(pd, true); -} - -static int owl_sps_power_off(struct generic_pm_domain *domain) -{ - struct owl_sps_domain *pd = to_owl_pd(domain); - - dev_dbg(pd->sps->dev, "%s power off", pd->info->name); - - return owl_sps_set_power(pd, false); -} - -static int owl_sps_init_domain(struct owl_sps *sps, int index) -{ - struct owl_sps_domain *pd; - - pd = devm_kzalloc(sps->dev, sizeof(*pd), GFP_KERNEL); - if (!pd) - return -ENOMEM; - - pd->info = &sps->info->domains[index]; - pd->sps = sps; - - pd->genpd.name = pd->info->name; - pd->genpd.power_on = owl_sps_power_on; - pd->genpd.power_off = owl_sps_power_off; - pd->genpd.flags = pd->info->genpd_flags; - pm_genpd_init(&pd->genpd, NULL, false); - - sps->genpd_data.domains[index] = &pd->genpd; - - return 0; -} - -static int owl_sps_probe(struct platform_device *pdev) -{ - const struct of_device_id *match; - const struct owl_sps_info *sps_info; - struct owl_sps *sps; - int i, ret; - - if (!pdev->dev.of_node) { - dev_err(&pdev->dev, "no device node\n"); - return -ENODEV; - } - - match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev); - if (!match || !match->data) { - dev_err(&pdev->dev, "unknown compatible or missing data\n"); - return -EINVAL; - } - - sps_info = match->data; - - sps = devm_kzalloc(&pdev->dev, - struct_size(sps, domains, sps_info->num_domains), - GFP_KERNEL); - if (!sps) - return -ENOMEM; - - sps->base = of_io_request_and_map(pdev->dev.of_node, 0, "owl-sps"); - if (IS_ERR(sps->base)) { - dev_err(&pdev->dev, "failed to map sps registers\n"); - return PTR_ERR(sps->base); - } - - sps->dev = &pdev->dev; - sps->info = sps_info; - sps->genpd_data.domains = sps->domains; - sps->genpd_data.num_domains = sps_info->num_domains; - - for (i = 0; i < sps_info->num_domains; i++) { - ret = owl_sps_init_domain(sps, i); - if (ret) - return ret; - } - - ret = of_genpd_add_provider_onecell(pdev->dev.of_node, &sps->genpd_data); - if (ret) { - dev_err(&pdev->dev, "failed to add provider (%d)", ret); - return ret; - } - - return 0; -} - -static const struct owl_sps_domain_info s500_sps_domains[] = { - [S500_PD_VDE] = { - .name = "VDE", - .pwr_bit = 0, - .ack_bit = 16, - }, - [S500_PD_VCE_SI] = { - .name = "VCE_SI", - .pwr_bit = 1, - .ack_bit = 17, - }, - [S500_PD_USB2_1] = { - .name = "USB2_1", - .pwr_bit = 2, - .ack_bit = 18, - }, - [S500_PD_CPU2] = { - .name = "CPU2", - .pwr_bit = 5, - .ack_bit = 21, - .genpd_flags = GENPD_FLAG_ALWAYS_ON, - }, - [S500_PD_CPU3] = { - .name = "CPU3", - .pwr_bit = 6, - .ack_bit = 22, - .genpd_flags = GENPD_FLAG_ALWAYS_ON, - }, - [S500_PD_DMA] = { - .name = "DMA", - .pwr_bit = 8, - .ack_bit = 12, - }, - [S500_PD_DS] = { - .name = "DS", - .pwr_bit = 9, - .ack_bit = 13, - }, - [S500_PD_USB3] = { - .name = "USB3", - .pwr_bit = 10, - .ack_bit = 14, - }, - [S500_PD_USB2_0] = { - .name = "USB2_0", - .pwr_bit = 11, - .ack_bit = 15, - }, -}; - -static const struct owl_sps_info s500_sps_info = { - .num_domains = ARRAY_SIZE(s500_sps_domains), - .domains = s500_sps_domains, -}; - -static const struct owl_sps_domain_info s700_sps_domains[] = { - [S700_PD_VDE] = { - .name = "VDE", - .pwr_bit = 0, - }, - [S700_PD_VCE_SI] = { - .name = "VCE_SI", - .pwr_bit = 1, - }, - [S700_PD_USB2_1] = { - .name = "USB2_1", - .pwr_bit = 2, - }, - [S700_PD_HDE] = { - .name = "HDE", - .pwr_bit = 7, - }, - [S700_PD_DMA] = { - .name = "DMA", - .pwr_bit = 8, - }, - [S700_PD_DS] = { - .name = "DS", - .pwr_bit = 9, - }, - [S700_PD_USB3] = { - .name = "USB3", - .pwr_bit = 10, - }, - [S700_PD_USB2_0] = { - .name = "USB2_0", - .pwr_bit = 11, - }, -}; - -static const struct owl_sps_info s700_sps_info = { - .num_domains = ARRAY_SIZE(s700_sps_domains), - .domains = s700_sps_domains, -}; - -static const struct owl_sps_domain_info s900_sps_domains[] = { - [S900_PD_GPU_B] = { - .name = "GPU_B", - .pwr_bit = 3, - }, - [S900_PD_VCE] = { - .name = "VCE", - .pwr_bit = 4, - }, - [S900_PD_SENSOR] = { - .name = "SENSOR", - .pwr_bit = 5, - }, - [S900_PD_VDE] = { - .name = "VDE", - .pwr_bit = 6, - }, - [S900_PD_HDE] = { - .name = "HDE", - .pwr_bit = 7, - }, - [S900_PD_USB3] = { - .name = "USB3", - .pwr_bit = 8, - }, - [S900_PD_DDR0] = { - .name = "DDR0", - .pwr_bit = 9, - }, - [S900_PD_DDR1] = { - .name = "DDR1", - .pwr_bit = 10, - }, - [S900_PD_DE] = { - .name = "DE", - .pwr_bit = 13, - }, - [S900_PD_NAND] = { - .name = "NAND", - .pwr_bit = 14, - }, - [S900_PD_USB2_H0] = { - .name = "USB2_H0", - .pwr_bit = 15, - }, - [S900_PD_USB2_H1] = { - .name = "USB2_H1", - .pwr_bit = 16, - }, -}; - -static const struct owl_sps_info s900_sps_info = { - .num_domains = ARRAY_SIZE(s900_sps_domains), - .domains = s900_sps_domains, -}; - -static const struct of_device_id owl_sps_of_matches[] = { - { .compatible = "actions,s500-sps", .data = &s500_sps_info }, - { .compatible = "actions,s700-sps", .data = &s700_sps_info }, - { .compatible = "actions,s900-sps", .data = &s900_sps_info }, - { } -}; - -static struct platform_driver owl_sps_platform_driver = { - .probe = owl_sps_probe, - .driver = { - .name = "owl-sps", - .of_match_table = owl_sps_of_matches, - .suppress_bind_attrs = true, - }, -}; - -static int __init owl_sps_init(void) -{ - return platform_driver_register(&owl_sps_platform_driver); -} -postcore_initcall(owl_sps_init); diff --git a/drivers/soc/amlogic/Makefile b/drivers/soc/amlogic/Makefile index 7b8c5d323f5c..c25f835e6a26 100644 --- a/drivers/soc/amlogic/Makefile +++ b/drivers/soc/amlogic/Makefile @@ -2,7 +2,4 @@ obj-$(CONFIG_MESON_CANVAS) += meson-canvas.o obj-$(CONFIG_MESON_CLK_MEASURE) += meson-clk-measure.o obj-$(CONFIG_MESON_GX_SOCINFO) += meson-gx-socinfo.o -obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-gx-pwrc-vpu.o obj-$(CONFIG_MESON_MX_SOCINFO) += meson-mx-socinfo.o -obj-$(CONFIG_MESON_EE_PM_DOMAINS) += meson-ee-pwrc.o -obj-$(CONFIG_MESON_SECURE_PM_DOMAINS) += meson-secure-pwrc.o diff --git a/drivers/soc/amlogic/meson-ee-pwrc.c b/drivers/soc/amlogic/meson-ee-pwrc.c deleted file mode 100644 index f54acffc83f9..000000000000 --- a/drivers/soc/amlogic/meson-ee-pwrc.c +++ /dev/null @@ -1,636 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 2019 BayLibre, SAS - * Author: Neil Armstrong <narmstrong@baylibre.com> - */ - -#include <linux/of_address.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <linux/bitfield.h> -#include <linux/regmap.h> -#include <linux/mfd/syscon.h> -#include <linux/of_device.h> -#include <linux/reset-controller.h> -#include <linux/reset.h> -#include <linux/clk.h> -#include <linux/module.h> -#include <dt-bindings/power/meson8-power.h> -#include <dt-bindings/power/meson-axg-power.h> -#include <dt-bindings/power/meson-g12a-power.h> -#include <dt-bindings/power/meson-gxbb-power.h> -#include <dt-bindings/power/meson-sm1-power.h> - -/* AO Offsets */ - -#define GX_AO_RTI_GEN_PWR_SLEEP0 (0x3a << 2) -#define GX_AO_RTI_GEN_PWR_ISO0 (0x3b << 2) - -/* - * Meson8/Meson8b/Meson8m2 only expose the power management registers of the - * AO-bus as syscon. 0x3a from GX translates to 0x02, 0x3b translates to 0x03 - * and so on. - */ -#define MESON8_AO_RTI_GEN_PWR_SLEEP0 (0x02 << 2) -#define MESON8_AO_RTI_GEN_PWR_ISO0 (0x03 << 2) - -/* HHI Offsets */ - -#define HHI_MEM_PD_REG0 (0x40 << 2) -#define HHI_VPU_MEM_PD_REG0 (0x41 << 2) -#define HHI_VPU_MEM_PD_REG1 (0x42 << 2) -#define HHI_VPU_MEM_PD_REG3 (0x43 << 2) -#define HHI_VPU_MEM_PD_REG4 (0x44 << 2) -#define HHI_AUDIO_MEM_PD_REG0 (0x45 << 2) -#define HHI_NANOQ_MEM_PD_REG0 (0x46 << 2) -#define HHI_NANOQ_MEM_PD_REG1 (0x47 << 2) -#define HHI_VPU_MEM_PD_REG2 (0x4d << 2) - -#define G12A_HHI_NANOQ_MEM_PD_REG0 (0x43 << 2) -#define G12A_HHI_NANOQ_MEM_PD_REG1 (0x44 << 2) - -struct meson_ee_pwrc; -struct meson_ee_pwrc_domain; - -struct meson_ee_pwrc_mem_domain { - unsigned int reg; - unsigned int mask; -}; - -struct meson_ee_pwrc_top_domain { - unsigned int sleep_reg; - unsigned int sleep_mask; - unsigned int iso_reg; - unsigned int iso_mask; -}; - -struct meson_ee_pwrc_domain_desc { - char *name; - unsigned int reset_names_count; - unsigned int clk_names_count; - struct meson_ee_pwrc_top_domain *top_pd; - unsigned int mem_pd_count; - struct meson_ee_pwrc_mem_domain *mem_pd; - bool (*is_powered_off)(struct meson_ee_pwrc_domain *pwrc_domain); -}; - -struct meson_ee_pwrc_domain_data { - unsigned int count; - struct meson_ee_pwrc_domain_desc *domains; -}; - -/* TOP Power Domains */ - -static struct meson_ee_pwrc_top_domain gx_pwrc_vpu = { - .sleep_reg = GX_AO_RTI_GEN_PWR_SLEEP0, - .sleep_mask = BIT(8), - .iso_reg = GX_AO_RTI_GEN_PWR_SLEEP0, - .iso_mask = BIT(9), -}; - -static struct meson_ee_pwrc_top_domain meson8_pwrc_vpu = { - .sleep_reg = MESON8_AO_RTI_GEN_PWR_SLEEP0, - .sleep_mask = BIT(8), - .iso_reg = MESON8_AO_RTI_GEN_PWR_SLEEP0, - .iso_mask = BIT(9), -}; - -#define SM1_EE_PD(__bit) \ - { \ - .sleep_reg = GX_AO_RTI_GEN_PWR_SLEEP0, \ - .sleep_mask = BIT(__bit), \ - .iso_reg = GX_AO_RTI_GEN_PWR_ISO0, \ - .iso_mask = BIT(__bit), \ - } - -static struct meson_ee_pwrc_top_domain sm1_pwrc_vpu = SM1_EE_PD(8); -static struct meson_ee_pwrc_top_domain sm1_pwrc_nna = SM1_EE_PD(16); -static struct meson_ee_pwrc_top_domain sm1_pwrc_usb = SM1_EE_PD(17); -static struct meson_ee_pwrc_top_domain sm1_pwrc_pci = SM1_EE_PD(18); -static struct meson_ee_pwrc_top_domain sm1_pwrc_ge2d = SM1_EE_PD(19); - -static struct meson_ee_pwrc_top_domain g12a_pwrc_nna = { - .sleep_reg = GX_AO_RTI_GEN_PWR_SLEEP0, - .sleep_mask = BIT(16) | BIT(17), - .iso_reg = GX_AO_RTI_GEN_PWR_ISO0, - .iso_mask = BIT(16) | BIT(17), -}; - -/* Memory PD Domains */ - -#define VPU_MEMPD(__reg) \ - { __reg, GENMASK(1, 0) }, \ - { __reg, GENMASK(3, 2) }, \ - { __reg, GENMASK(5, 4) }, \ - { __reg, GENMASK(7, 6) }, \ - { __reg, GENMASK(9, 8) }, \ - { __reg, GENMASK(11, 10) }, \ - { __reg, GENMASK(13, 12) }, \ - { __reg, GENMASK(15, 14) }, \ - { __reg, GENMASK(17, 16) }, \ - { __reg, GENMASK(19, 18) }, \ - { __reg, GENMASK(21, 20) }, \ - { __reg, GENMASK(23, 22) }, \ - { __reg, GENMASK(25, 24) }, \ - { __reg, GENMASK(27, 26) }, \ - { __reg, GENMASK(29, 28) }, \ - { __reg, GENMASK(31, 30) } - -#define VPU_HHI_MEMPD(__reg) \ - { __reg, BIT(8) }, \ - { __reg, BIT(9) }, \ - { __reg, BIT(10) }, \ - { __reg, BIT(11) }, \ - { __reg, BIT(12) }, \ - { __reg, BIT(13) }, \ - { __reg, BIT(14) }, \ - { __reg, BIT(15) } - -static struct meson_ee_pwrc_mem_domain axg_pwrc_mem_vpu[] = { - VPU_MEMPD(HHI_VPU_MEM_PD_REG0), - VPU_HHI_MEMPD(HHI_MEM_PD_REG0), -}; - -static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_vpu[] = { - VPU_MEMPD(HHI_VPU_MEM_PD_REG0), - VPU_MEMPD(HHI_VPU_MEM_PD_REG1), - VPU_MEMPD(HHI_VPU_MEM_PD_REG2), - VPU_HHI_MEMPD(HHI_MEM_PD_REG0), -}; - -static struct meson_ee_pwrc_mem_domain gxbb_pwrc_mem_vpu[] = { - VPU_MEMPD(HHI_VPU_MEM_PD_REG0), - VPU_MEMPD(HHI_VPU_MEM_PD_REG1), - VPU_HHI_MEMPD(HHI_MEM_PD_REG0), -}; - -static struct meson_ee_pwrc_mem_domain meson_pwrc_mem_eth[] = { - { HHI_MEM_PD_REG0, GENMASK(3, 2) }, -}; - -static struct meson_ee_pwrc_mem_domain meson8_pwrc_audio_dsp_mem[] = { - { HHI_MEM_PD_REG0, GENMASK(1, 0) }, -}; - -static struct meson_ee_pwrc_mem_domain meson8_pwrc_mem_vpu[] = { - VPU_MEMPD(HHI_VPU_MEM_PD_REG0), - VPU_MEMPD(HHI_VPU_MEM_PD_REG1), - VPU_HHI_MEMPD(HHI_MEM_PD_REG0), -}; - -static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_vpu[] = { - VPU_MEMPD(HHI_VPU_MEM_PD_REG0), - VPU_MEMPD(HHI_VPU_MEM_PD_REG1), - VPU_MEMPD(HHI_VPU_MEM_PD_REG2), - VPU_MEMPD(HHI_VPU_MEM_PD_REG3), - { HHI_VPU_MEM_PD_REG4, GENMASK(1, 0) }, - { HHI_VPU_MEM_PD_REG4, GENMASK(3, 2) }, - { HHI_VPU_MEM_PD_REG4, GENMASK(5, 4) }, - { HHI_VPU_MEM_PD_REG4, GENMASK(7, 6) }, - VPU_HHI_MEMPD(HHI_MEM_PD_REG0), -}; - -static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_nna[] = { - { HHI_NANOQ_MEM_PD_REG0, 0xff }, - { HHI_NANOQ_MEM_PD_REG1, 0xff }, -}; - -static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_usb[] = { - { HHI_MEM_PD_REG0, GENMASK(31, 30) }, -}; - -static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_pcie[] = { - { HHI_MEM_PD_REG0, GENMASK(29, 26) }, -}; - -static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_ge2d[] = { - { HHI_MEM_PD_REG0, GENMASK(25, 18) }, -}; - -static struct meson_ee_pwrc_mem_domain axg_pwrc_mem_audio[] = { - { HHI_MEM_PD_REG0, GENMASK(5, 4) }, -}; - -static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_audio[] = { - { HHI_MEM_PD_REG0, GENMASK(5, 4) }, - { HHI_AUDIO_MEM_PD_REG0, GENMASK(1, 0) }, - { HHI_AUDIO_MEM_PD_REG0, GENMASK(3, 2) }, - { HHI_AUDIO_MEM_PD_REG0, GENMASK(5, 4) }, - { HHI_AUDIO_MEM_PD_REG0, GENMASK(7, 6) }, - { HHI_AUDIO_MEM_PD_REG0, GENMASK(13, 12) }, - { HHI_AUDIO_MEM_PD_REG0, GENMASK(15, 14) }, - { HHI_AUDIO_MEM_PD_REG0, GENMASK(17, 16) }, - { HHI_AUDIO_MEM_PD_REG0, GENMASK(19, 18) }, - { HHI_AUDIO_MEM_PD_REG0, GENMASK(21, 20) }, - { HHI_AUDIO_MEM_PD_REG0, GENMASK(23, 22) }, - { HHI_AUDIO_MEM_PD_REG0, GENMASK(25, 24) }, - { HHI_AUDIO_MEM_PD_REG0, GENMASK(27, 26) }, -}; - -static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_nna[] = { - { G12A_HHI_NANOQ_MEM_PD_REG0, GENMASK(31, 0) }, - { G12A_HHI_NANOQ_MEM_PD_REG1, GENMASK(23, 0) }, -}; - -#define VPU_PD(__name, __top_pd, __mem, __is_pwr_off, __resets, __clks) \ - { \ - .name = __name, \ - .reset_names_count = __resets, \ - .clk_names_count = __clks, \ - .top_pd = __top_pd, \ - .mem_pd_count = ARRAY_SIZE(__mem), \ - .mem_pd = __mem, \ - .is_powered_off = __is_pwr_off, \ - } - -#define TOP_PD(__name, __top_pd, __mem, __is_pwr_off) \ - { \ - .name = __name, \ - .top_pd = __top_pd, \ - .mem_pd_count = ARRAY_SIZE(__mem), \ - .mem_pd = __mem, \ - .is_powered_off = __is_pwr_off, \ - } - -#define MEM_PD(__name, __mem) \ - TOP_PD(__name, NULL, __mem, NULL) - -static bool pwrc_ee_is_powered_off(struct meson_ee_pwrc_domain *pwrc_domain); - -static struct meson_ee_pwrc_domain_desc axg_pwrc_domains[] = { - [PWRC_AXG_VPU_ID] = VPU_PD("VPU", &gx_pwrc_vpu, axg_pwrc_mem_vpu, - pwrc_ee_is_powered_off, 5, 2), - [PWRC_AXG_ETHERNET_MEM_ID] = MEM_PD("ETH", meson_pwrc_mem_eth), - [PWRC_AXG_AUDIO_ID] = MEM_PD("AUDIO", axg_pwrc_mem_audio), -}; - -static struct meson_ee_pwrc_domain_desc g12a_pwrc_domains[] = { - [PWRC_G12A_VPU_ID] = VPU_PD("VPU", &gx_pwrc_vpu, g12a_pwrc_mem_vpu, - pwrc_ee_is_powered_off, 11, 2), - [PWRC_G12A_ETH_ID] = MEM_PD("ETH", meson_pwrc_mem_eth), - [PWRC_G12A_NNA_ID] = TOP_PD("NNA", &g12a_pwrc_nna, g12a_pwrc_mem_nna, - pwrc_ee_is_powered_off), -}; - -static struct meson_ee_pwrc_domain_desc gxbb_pwrc_domains[] = { - [PWRC_GXBB_VPU_ID] = VPU_PD("VPU", &gx_pwrc_vpu, gxbb_pwrc_mem_vpu, - pwrc_ee_is_powered_off, 12, 2), - [PWRC_GXBB_ETHERNET_MEM_ID] = MEM_PD("ETH", meson_pwrc_mem_eth), -}; - -static struct meson_ee_pwrc_domain_desc meson8_pwrc_domains[] = { - [PWRC_MESON8_VPU_ID] = VPU_PD("VPU", &meson8_pwrc_vpu, - meson8_pwrc_mem_vpu, - pwrc_ee_is_powered_off, 0, 1), - [PWRC_MESON8_ETHERNET_MEM_ID] = MEM_PD("ETHERNET_MEM", - meson_pwrc_mem_eth), - [PWRC_MESON8_AUDIO_DSP_MEM_ID] = MEM_PD("AUDIO_DSP_MEM", - meson8_pwrc_audio_dsp_mem), -}; - -static struct meson_ee_pwrc_domain_desc meson8b_pwrc_domains[] = { - [PWRC_MESON8_VPU_ID] = VPU_PD("VPU", &meson8_pwrc_vpu, - meson8_pwrc_mem_vpu, - pwrc_ee_is_powered_off, 11, 1), - [PWRC_MESON8_ETHERNET_MEM_ID] = MEM_PD("ETHERNET_MEM", - meson_pwrc_mem_eth), - [PWRC_MESON8_AUDIO_DSP_MEM_ID] = MEM_PD("AUDIO_DSP_MEM", - meson8_pwrc_audio_dsp_mem), -}; - -static struct meson_ee_pwrc_domain_desc sm1_pwrc_domains[] = { - [PWRC_SM1_VPU_ID] = VPU_PD("VPU", &sm1_pwrc_vpu, sm1_pwrc_mem_vpu, - pwrc_ee_is_powered_off, 11, 2), - [PWRC_SM1_NNA_ID] = TOP_PD("NNA", &sm1_pwrc_nna, sm1_pwrc_mem_nna, - pwrc_ee_is_powered_off), - [PWRC_SM1_USB_ID] = TOP_PD("USB", &sm1_pwrc_usb, sm1_pwrc_mem_usb, - pwrc_ee_is_powered_off), - [PWRC_SM1_PCIE_ID] = TOP_PD("PCI", &sm1_pwrc_pci, sm1_pwrc_mem_pcie, - pwrc_ee_is_powered_off), - [PWRC_SM1_GE2D_ID] = TOP_PD("GE2D", &sm1_pwrc_ge2d, sm1_pwrc_mem_ge2d, - pwrc_ee_is_powered_off), - [PWRC_SM1_AUDIO_ID] = MEM_PD("AUDIO", sm1_pwrc_mem_audio), - [PWRC_SM1_ETH_ID] = MEM_PD("ETH", meson_pwrc_mem_eth), -}; - -struct meson_ee_pwrc_domain { - struct generic_pm_domain base; - bool enabled; - struct meson_ee_pwrc *pwrc; - struct meson_ee_pwrc_domain_desc desc; - struct clk_bulk_data *clks; - int num_clks; - struct reset_control *rstc; - int num_rstc; -}; - -struct meson_ee_pwrc { - struct regmap *regmap_ao; - struct regmap *regmap_hhi; - struct meson_ee_pwrc_domain *domains; - struct genpd_onecell_data xlate; -}; - -static bool pwrc_ee_is_powered_off(struct meson_ee_pwrc_domain *pwrc_domain) -{ - u32 reg; - - regmap_read(pwrc_domain->pwrc->regmap_ao, - pwrc_domain->desc.top_pd->sleep_reg, ®); - - return (reg & pwrc_domain->desc.top_pd->sleep_mask); -} - -static int meson_ee_pwrc_off(struct generic_pm_domain *domain) -{ - struct meson_ee_pwrc_domain *pwrc_domain = - container_of(domain, struct meson_ee_pwrc_domain, base); - int i; - - if (pwrc_domain->desc.top_pd) - regmap_update_bits(pwrc_domain->pwrc->regmap_ao, - pwrc_domain->desc.top_pd->sleep_reg, - pwrc_domain->desc.top_pd->sleep_mask, - pwrc_domain->desc.top_pd->sleep_mask); - udelay(20); - - for (i = 0 ; i < pwrc_domain->desc.mem_pd_count ; ++i) - regmap_update_bits(pwrc_domain->pwrc->regmap_hhi, - pwrc_domain->desc.mem_pd[i].reg, - pwrc_domain->desc.mem_pd[i].mask, - pwrc_domain->desc.mem_pd[i].mask); - - udelay(20); - - if (pwrc_domain->desc.top_pd) - regmap_update_bits(pwrc_domain->pwrc->regmap_ao, - pwrc_domain->desc.top_pd->iso_reg, - pwrc_domain->desc.top_pd->iso_mask, - pwrc_domain->desc.top_pd->iso_mask); - - if (pwrc_domain->num_clks) { - msleep(20); - clk_bulk_disable_unprepare(pwrc_domain->num_clks, - pwrc_domain->clks); - } - - return 0; -} - -static int meson_ee_pwrc_on(struct generic_pm_domain *domain) -{ - struct meson_ee_pwrc_domain *pwrc_domain = - container_of(domain, struct meson_ee_pwrc_domain, base); - int i, ret; - - if (pwrc_domain->desc.top_pd) - regmap_update_bits(pwrc_domain->pwrc->regmap_ao, - pwrc_domain->desc.top_pd->sleep_reg, - pwrc_domain->desc.top_pd->sleep_mask, 0); - udelay(20); - - for (i = 0 ; i < pwrc_domain->desc.mem_pd_count ; ++i) - regmap_update_bits(pwrc_domain->pwrc->regmap_hhi, - pwrc_domain->desc.mem_pd[i].reg, - pwrc_domain->desc.mem_pd[i].mask, 0); - - udelay(20); - - ret = reset_control_assert(pwrc_domain->rstc); - if (ret) - return ret; - - if (pwrc_domain->desc.top_pd) - regmap_update_bits(pwrc_domain->pwrc->regmap_ao, - pwrc_domain->desc.top_pd->iso_reg, - pwrc_domain->desc.top_pd->iso_mask, 0); - - ret = reset_control_deassert(pwrc_domain->rstc); - if (ret) - return ret; - - return clk_bulk_prepare_enable(pwrc_domain->num_clks, - pwrc_domain->clks); -} - -static int meson_ee_pwrc_init_domain(struct platform_device *pdev, - struct meson_ee_pwrc *pwrc, - struct meson_ee_pwrc_domain *dom) -{ - int ret; - - dom->pwrc = pwrc; - dom->num_rstc = dom->desc.reset_names_count; - dom->num_clks = dom->desc.clk_names_count; - - if (dom->num_rstc) { - int count = reset_control_get_count(&pdev->dev); - - if (count != dom->num_rstc) - dev_warn(&pdev->dev, "Invalid resets count %d for domain %s\n", - count, dom->desc.name); - - dom->rstc = devm_reset_control_array_get_exclusive(&pdev->dev); - if (IS_ERR(dom->rstc)) - return PTR_ERR(dom->rstc); - } - - if (dom->num_clks) { - int ret = devm_clk_bulk_get_all(&pdev->dev, &dom->clks); - if (ret < 0) - return ret; - - if (dom->num_clks != ret) { - dev_warn(&pdev->dev, "Invalid clocks count %d for domain %s\n", - ret, dom->desc.name); - dom->num_clks = ret; - } - } - - dom->base.name = dom->desc.name; - dom->base.power_on = meson_ee_pwrc_on; - dom->base.power_off = meson_ee_pwrc_off; - - /* - * TOFIX: This is a special case for the VPU power domain, which can - * be enabled previously by the bootloader. In this case the VPU - * pipeline may be functional but no driver maybe never attach - * to this power domain, and if the domain is disabled it could - * cause system errors. This is why the pm_domain_always_on_gov - * is used here. - * For the same reason, the clocks should be enabled in case - * we need to power the domain off, otherwise the internal clocks - * prepare/enable counters won't be in sync. - */ - if (dom->num_clks && dom->desc.is_powered_off && !dom->desc.is_powered_off(dom)) { - ret = clk_bulk_prepare_enable(dom->num_clks, dom->clks); - if (ret) - return ret; - - dom->base.flags = GENPD_FLAG_ALWAYS_ON; - ret = pm_genpd_init(&dom->base, NULL, false); - if (ret) - return ret; - } else { - ret = pm_genpd_init(&dom->base, NULL, - (dom->desc.is_powered_off ? - dom->desc.is_powered_off(dom) : true)); - if (ret) - return ret; - } - - return 0; -} - -static int meson_ee_pwrc_probe(struct platform_device *pdev) -{ - const struct meson_ee_pwrc_domain_data *match; - struct regmap *regmap_ao, *regmap_hhi; - struct device_node *parent_np; - struct meson_ee_pwrc *pwrc; - int i, ret; - - match = of_device_get_match_data(&pdev->dev); - if (!match) { - dev_err(&pdev->dev, "failed to get match data\n"); - return -ENODEV; - } - - pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL); - if (!pwrc) - return -ENOMEM; - - pwrc->xlate.domains = devm_kcalloc(&pdev->dev, match->count, - sizeof(*pwrc->xlate.domains), - GFP_KERNEL); - if (!pwrc->xlate.domains) - return -ENOMEM; - - pwrc->domains = devm_kcalloc(&pdev->dev, match->count, - sizeof(*pwrc->domains), GFP_KERNEL); - if (!pwrc->domains) - return -ENOMEM; - - pwrc->xlate.num_domains = match->count; - - parent_np = of_get_parent(pdev->dev.of_node); - regmap_hhi = syscon_node_to_regmap(parent_np); - of_node_put(parent_np); - if (IS_ERR(regmap_hhi)) { - dev_err(&pdev->dev, "failed to get HHI regmap\n"); - return PTR_ERR(regmap_hhi); - } - - regmap_ao = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, - "amlogic,ao-sysctrl"); - if (IS_ERR(regmap_ao)) { - dev_err(&pdev->dev, "failed to get AO regmap\n"); - return PTR_ERR(regmap_ao); - } - - pwrc->regmap_ao = regmap_ao; - pwrc->regmap_hhi = regmap_hhi; - - platform_set_drvdata(pdev, pwrc); - - for (i = 0 ; i < match->count ; ++i) { - struct meson_ee_pwrc_domain *dom = &pwrc->domains[i]; - - memcpy(&dom->desc, &match->domains[i], sizeof(dom->desc)); - - ret = meson_ee_pwrc_init_domain(pdev, pwrc, dom); - if (ret) - return ret; - - pwrc->xlate.domains[i] = &dom->base; - } - - return of_genpd_add_provider_onecell(pdev->dev.of_node, &pwrc->xlate); -} - -static void meson_ee_pwrc_shutdown(struct platform_device *pdev) -{ - struct meson_ee_pwrc *pwrc = platform_get_drvdata(pdev); - int i; - - for (i = 0 ; i < pwrc->xlate.num_domains ; ++i) { - struct meson_ee_pwrc_domain *dom = &pwrc->domains[i]; - - if (dom->desc.is_powered_off && !dom->desc.is_powered_off(dom)) - meson_ee_pwrc_off(&dom->base); - } -} - -static struct meson_ee_pwrc_domain_data meson_ee_g12a_pwrc_data = { - .count = ARRAY_SIZE(g12a_pwrc_domains), - .domains = g12a_pwrc_domains, -}; - -static struct meson_ee_pwrc_domain_data meson_ee_axg_pwrc_data = { - .count = ARRAY_SIZE(axg_pwrc_domains), - .domains = axg_pwrc_domains, -}; - -static struct meson_ee_pwrc_domain_data meson_ee_gxbb_pwrc_data = { - .count = ARRAY_SIZE(gxbb_pwrc_domains), - .domains = gxbb_pwrc_domains, -}; - -static struct meson_ee_pwrc_domain_data meson_ee_m8_pwrc_data = { - .count = ARRAY_SIZE(meson8_pwrc_domains), - .domains = meson8_pwrc_domains, -}; - -static struct meson_ee_pwrc_domain_data meson_ee_m8b_pwrc_data = { - .count = ARRAY_SIZE(meson8b_pwrc_domains), - .domains = meson8b_pwrc_domains, -}; - -static struct meson_ee_pwrc_domain_data meson_ee_sm1_pwrc_data = { - .count = ARRAY_SIZE(sm1_pwrc_domains), - .domains = sm1_pwrc_domains, -}; - -static const struct of_device_id meson_ee_pwrc_match_table[] = { - { - .compatible = "amlogic,meson8-pwrc", - .data = &meson_ee_m8_pwrc_data, - }, - { - .compatible = "amlogic,meson8b-pwrc", - .data = &meson_ee_m8b_pwrc_data, - }, - { - .compatible = "amlogic,meson8m2-pwrc", - .data = &meson_ee_m8b_pwrc_data, - }, - { - .compatible = "amlogic,meson-axg-pwrc", - .data = &meson_ee_axg_pwrc_data, - }, - { - .compatible = "amlogic,meson-gxbb-pwrc", - .data = &meson_ee_gxbb_pwrc_data, - }, - { - .compatible = "amlogic,meson-g12a-pwrc", - .data = &meson_ee_g12a_pwrc_data, - }, - { - .compatible = "amlogic,meson-sm1-pwrc", - .data = &meson_ee_sm1_pwrc_data, - }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, meson_ee_pwrc_match_table); - -static struct platform_driver meson_ee_pwrc_driver = { - .probe = meson_ee_pwrc_probe, - .shutdown = meson_ee_pwrc_shutdown, - .driver = { - .name = "meson_ee_pwrc", - .of_match_table = meson_ee_pwrc_match_table, - }, -}; -module_platform_driver(meson_ee_pwrc_driver); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/amlogic/meson-gx-pwrc-vpu.c b/drivers/soc/amlogic/meson-gx-pwrc-vpu.c deleted file mode 100644 index 5d4f12800d93..000000000000 --- a/drivers/soc/amlogic/meson-gx-pwrc-vpu.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (c) 2017 BayLibre, SAS - * Author: Neil Armstrong <narmstrong@baylibre.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <linux/of_address.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <linux/bitfield.h> -#include <linux/regmap.h> -#include <linux/mfd/syscon.h> -#include <linux/of_device.h> -#include <linux/reset.h> -#include <linux/clk.h> -#include <linux/module.h> - -/* AO Offsets */ - -#define AO_RTI_GEN_PWR_SLEEP0 (0x3a << 2) - -#define GEN_PWR_VPU_HDMI BIT(8) -#define GEN_PWR_VPU_HDMI_ISO BIT(9) - -/* HHI Offsets */ - -#define HHI_MEM_PD_REG0 (0x40 << 2) -#define HHI_VPU_MEM_PD_REG0 (0x41 << 2) -#define HHI_VPU_MEM_PD_REG1 (0x42 << 2) -#define HHI_VPU_MEM_PD_REG2 (0x4d << 2) - -struct meson_gx_pwrc_vpu { - struct generic_pm_domain genpd; - struct regmap *regmap_ao; - struct regmap *regmap_hhi; - struct reset_control *rstc; - struct clk *vpu_clk; - struct clk *vapb_clk; -}; - -static inline -struct meson_gx_pwrc_vpu *genpd_to_pd(struct generic_pm_domain *d) -{ - return container_of(d, struct meson_gx_pwrc_vpu, genpd); -} - -static int meson_gx_pwrc_vpu_power_off(struct generic_pm_domain *genpd) -{ - struct meson_gx_pwrc_vpu *pd = genpd_to_pd(genpd); - int i; - - regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, - GEN_PWR_VPU_HDMI_ISO, GEN_PWR_VPU_HDMI_ISO); - udelay(20); - - /* Power Down Memories */ - for (i = 0; i < 32; i += 2) { - regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0, - 0x3 << i, 0x3 << i); - udelay(5); - } - for (i = 0; i < 32; i += 2) { - regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1, - 0x3 << i, 0x3 << i); - udelay(5); - } - for (i = 8; i < 16; i++) { - regmap_update_bits(pd->regmap_hhi, HHI_MEM_PD_REG0, - BIT(i), BIT(i)); - udelay(5); - } - udelay(20); - - regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, - GEN_PWR_VPU_HDMI, GEN_PWR_VPU_HDMI); - - msleep(20); - - clk_disable_unprepare(pd->vpu_clk); - clk_disable_unprepare(pd->vapb_clk); - - return 0; -} - -static int meson_g12a_pwrc_vpu_power_off(struct generic_pm_domain *genpd) -{ - struct meson_gx_pwrc_vpu *pd = genpd_to_pd(genpd); - int i; - - regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, - GEN_PWR_VPU_HDMI_ISO, GEN_PWR_VPU_HDMI_ISO); - udelay(20); - - /* Power Down Memories */ - for (i = 0; i < 32; i += 2) { - regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0, - 0x3 << i, 0x3 << i); - udelay(5); - } - for (i = 0; i < 32; i += 2) { - regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1, - 0x3 << i, 0x3 << i); - udelay(5); - } - for (i = 0; i < 32; i += 2) { - regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG2, - 0x3 << i, 0x3 << i); - udelay(5); - } - for (i = 8; i < 16; i++) { - regmap_update_bits(pd->regmap_hhi, HHI_MEM_PD_REG0, - BIT(i), BIT(i)); - udelay(5); - } - udelay(20); - - regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, - GEN_PWR_VPU_HDMI, GEN_PWR_VPU_HDMI); - - msleep(20); - - clk_disable_unprepare(pd->vpu_clk); - clk_disable_unprepare(pd->vapb_clk); - - return 0; -} - -static int meson_gx_pwrc_vpu_setup_clk(struct meson_gx_pwrc_vpu *pd) -{ - int ret; - - ret = clk_prepare_enable(pd->vpu_clk); - if (ret) - return ret; - - ret = clk_prepare_enable(pd->vapb_clk); - if (ret) - clk_disable_unprepare(pd->vpu_clk); - - return ret; -} - -static int meson_gx_pwrc_vpu_power_on(struct generic_pm_domain *genpd) -{ - struct meson_gx_pwrc_vpu *pd = genpd_to_pd(genpd); - int ret; - int i; - - regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, - GEN_PWR_VPU_HDMI, 0); - udelay(20); - - /* Power Up Memories */ - for (i = 0; i < 32; i += 2) { - regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0, - 0x3 << i, 0); - udelay(5); - } - - for (i = 0; i < 32; i += 2) { - regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1, - 0x3 << i, 0); - udelay(5); - } - - for (i = 8; i < 16; i++) { - regmap_update_bits(pd->regmap_hhi, HHI_MEM_PD_REG0, - BIT(i), 0); - udelay(5); - } - udelay(20); - - ret = reset_control_assert(pd->rstc); - if (ret) - return ret; - - regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, - GEN_PWR_VPU_HDMI_ISO, 0); - - ret = reset_control_deassert(pd->rstc); - if (ret) - return ret; - - ret = meson_gx_pwrc_vpu_setup_clk(pd); - if (ret) - return ret; - - return 0; -} - -static int meson_g12a_pwrc_vpu_power_on(struct generic_pm_domain *genpd) -{ - struct meson_gx_pwrc_vpu *pd = genpd_to_pd(genpd); - int ret; - int i; - - regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, - GEN_PWR_VPU_HDMI, 0); - udelay(20); - - /* Power Up Memories */ - for (i = 0; i < 32; i += 2) { - regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0, - 0x3 << i, 0); - udelay(5); - } - - for (i = 0; i < 32; i += 2) { - regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1, - 0x3 << i, 0); - udelay(5); - } - - for (i = 0; i < 32; i += 2) { - regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG2, - 0x3 << i, 0); - udelay(5); - } - - for (i = 8; i < 16; i++) { - regmap_update_bits(pd->regmap_hhi, HHI_MEM_PD_REG0, - BIT(i), 0); - udelay(5); - } - udelay(20); - - ret = reset_control_assert(pd->rstc); - if (ret) - return ret; - - regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, - GEN_PWR_VPU_HDMI_ISO, 0); - - ret = reset_control_deassert(pd->rstc); - if (ret) - return ret; - - ret = meson_gx_pwrc_vpu_setup_clk(pd); - if (ret) - return ret; - - return 0; -} - -static bool meson_gx_pwrc_vpu_get_power(struct meson_gx_pwrc_vpu *pd) -{ - u32 reg; - - regmap_read(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, ®); - - return (reg & GEN_PWR_VPU_HDMI); -} - -static struct meson_gx_pwrc_vpu vpu_hdmi_pd = { - .genpd = { - .name = "vpu_hdmi", - .power_off = meson_gx_pwrc_vpu_power_off, - .power_on = meson_gx_pwrc_vpu_power_on, - }, -}; - -static struct meson_gx_pwrc_vpu vpu_hdmi_pd_g12a = { - .genpd = { - .name = "vpu_hdmi", - .power_off = meson_g12a_pwrc_vpu_power_off, - .power_on = meson_g12a_pwrc_vpu_power_on, - }, -}; - -static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev) -{ - const struct meson_gx_pwrc_vpu *vpu_pd_match; - struct regmap *regmap_ao, *regmap_hhi; - struct meson_gx_pwrc_vpu *vpu_pd; - struct device_node *parent_np; - struct reset_control *rstc; - struct clk *vpu_clk; - struct clk *vapb_clk; - bool powered_off; - int ret; - - vpu_pd_match = of_device_get_match_data(&pdev->dev); - if (!vpu_pd_match) { - dev_err(&pdev->dev, "failed to get match data\n"); - return -ENODEV; - } - - vpu_pd = devm_kzalloc(&pdev->dev, sizeof(*vpu_pd), GFP_KERNEL); - if (!vpu_pd) - return -ENOMEM; - - memcpy(vpu_pd, vpu_pd_match, sizeof(*vpu_pd)); - - parent_np = of_get_parent(pdev->dev.of_node); - regmap_ao = syscon_node_to_regmap(parent_np); - of_node_put(parent_np); - if (IS_ERR(regmap_ao)) { - dev_err(&pdev->dev, "failed to get regmap\n"); - return PTR_ERR(regmap_ao); - } - - regmap_hhi = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, - "amlogic,hhi-sysctrl"); - if (IS_ERR(regmap_hhi)) { - dev_err(&pdev->dev, "failed to get HHI regmap\n"); - return PTR_ERR(regmap_hhi); - } - - rstc = devm_reset_control_array_get_exclusive(&pdev->dev); - if (IS_ERR(rstc)) - return dev_err_probe(&pdev->dev, PTR_ERR(rstc), - "failed to get reset lines\n"); - - vpu_clk = devm_clk_get(&pdev->dev, "vpu"); - if (IS_ERR(vpu_clk)) { - dev_err(&pdev->dev, "vpu clock request failed\n"); - return PTR_ERR(vpu_clk); - } - - vapb_clk = devm_clk_get(&pdev->dev, "vapb"); - if (IS_ERR(vapb_clk)) { - dev_err(&pdev->dev, "vapb clock request failed\n"); - return PTR_ERR(vapb_clk); - } - - vpu_pd->regmap_ao = regmap_ao; - vpu_pd->regmap_hhi = regmap_hhi; - vpu_pd->rstc = rstc; - vpu_pd->vpu_clk = vpu_clk; - vpu_pd->vapb_clk = vapb_clk; - - platform_set_drvdata(pdev, vpu_pd); - - powered_off = meson_gx_pwrc_vpu_get_power(vpu_pd); - - /* If already powered, sync the clock states */ - if (!powered_off) { - ret = meson_gx_pwrc_vpu_setup_clk(vpu_pd); - if (ret) - return ret; - } - - vpu_pd->genpd.flags = GENPD_FLAG_ALWAYS_ON; - pm_genpd_init(&vpu_pd->genpd, NULL, powered_off); - - return of_genpd_add_provider_simple(pdev->dev.of_node, - &vpu_pd->genpd); -} - -static void meson_gx_pwrc_vpu_shutdown(struct platform_device *pdev) -{ - struct meson_gx_pwrc_vpu *vpu_pd = platform_get_drvdata(pdev); - bool powered_off; - - powered_off = meson_gx_pwrc_vpu_get_power(vpu_pd); - if (!powered_off) - vpu_pd->genpd.power_off(&vpu_pd->genpd); -} - -static const struct of_device_id meson_gx_pwrc_vpu_match_table[] = { - { .compatible = "amlogic,meson-gx-pwrc-vpu", .data = &vpu_hdmi_pd }, - { - .compatible = "amlogic,meson-g12a-pwrc-vpu", - .data = &vpu_hdmi_pd_g12a - }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, meson_gx_pwrc_vpu_match_table); - -static struct platform_driver meson_gx_pwrc_vpu_driver = { - .probe = meson_gx_pwrc_vpu_probe, - .shutdown = meson_gx_pwrc_vpu_shutdown, - .driver = { - .name = "meson_gx_pwrc_vpu", - .of_match_table = meson_gx_pwrc_vpu_match_table, - }, -}; -module_platform_driver(meson_gx_pwrc_vpu_driver); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/amlogic/meson-secure-pwrc.c b/drivers/soc/amlogic/meson-secure-pwrc.c deleted file mode 100644 index 25b4b71df9b8..000000000000 --- a/drivers/soc/amlogic/meson-secure-pwrc.c +++ /dev/null @@ -1,231 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Copyright (c) 2019 Amlogic, Inc. - * Author: Jianxin Pan <jianxin.pan@amlogic.com> - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/io.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <dt-bindings/power/meson-a1-power.h> -#include <dt-bindings/power/meson-s4-power.h> -#include <linux/arm-smccc.h> -#include <linux/firmware/meson/meson_sm.h> -#include <linux/module.h> - -#define PWRC_ON 1 -#define PWRC_OFF 0 - -struct meson_secure_pwrc_domain { - struct generic_pm_domain base; - unsigned int index; - struct meson_secure_pwrc *pwrc; -}; - -struct meson_secure_pwrc { - struct meson_secure_pwrc_domain *domains; - struct genpd_onecell_data xlate; - struct meson_sm_firmware *fw; -}; - -struct meson_secure_pwrc_domain_desc { - unsigned int index; - unsigned int flags; - char *name; - bool (*is_off)(struct meson_secure_pwrc_domain *pwrc_domain); -}; - -struct meson_secure_pwrc_domain_data { - unsigned int count; - struct meson_secure_pwrc_domain_desc *domains; -}; - -static bool pwrc_secure_is_off(struct meson_secure_pwrc_domain *pwrc_domain) -{ - int is_off = 1; - - if (meson_sm_call(pwrc_domain->pwrc->fw, SM_A1_PWRC_GET, &is_off, - pwrc_domain->index, 0, 0, 0, 0) < 0) - pr_err("failed to get power domain status\n"); - - return is_off; -} - -static int meson_secure_pwrc_off(struct generic_pm_domain *domain) -{ - int ret = 0; - struct meson_secure_pwrc_domain *pwrc_domain = - container_of(domain, struct meson_secure_pwrc_domain, base); - - if (meson_sm_call(pwrc_domain->pwrc->fw, SM_A1_PWRC_SET, NULL, - pwrc_domain->index, PWRC_OFF, 0, 0, 0) < 0) { - pr_err("failed to set power domain off\n"); - ret = -EINVAL; - } - - return ret; -} - -static int meson_secure_pwrc_on(struct generic_pm_domain *domain) -{ - int ret = 0; - struct meson_secure_pwrc_domain *pwrc_domain = - container_of(domain, struct meson_secure_pwrc_domain, base); - - if (meson_sm_call(pwrc_domain->pwrc->fw, SM_A1_PWRC_SET, NULL, - pwrc_domain->index, PWRC_ON, 0, 0, 0) < 0) { - pr_err("failed to set power domain on\n"); - ret = -EINVAL; - } - - return ret; -} - -#define SEC_PD(__name, __flag) \ -[PWRC_##__name##_ID] = \ -{ \ - .name = #__name, \ - .index = PWRC_##__name##_ID, \ - .is_off = pwrc_secure_is_off, \ - .flags = __flag, \ -} - -static struct meson_secure_pwrc_domain_desc a1_pwrc_domains[] = { - SEC_PD(DSPA, 0), - SEC_PD(DSPB, 0), - /* UART should keep working in ATF after suspend and before resume */ - SEC_PD(UART, GENPD_FLAG_ALWAYS_ON), - /* DMC is for DDR PHY ana/dig and DMC, and should be always on */ - SEC_PD(DMC, GENPD_FLAG_ALWAYS_ON), - SEC_PD(I2C, 0), - SEC_PD(PSRAM, 0), - SEC_PD(ACODEC, 0), - SEC_PD(AUDIO, 0), - SEC_PD(OTP, 0), - SEC_PD(DMA, GENPD_FLAG_ALWAYS_ON | GENPD_FLAG_IRQ_SAFE), - SEC_PD(SD_EMMC, 0), - SEC_PD(RAMA, 0), - /* SRAMB is used as ATF runtime memory, and should be always on */ - SEC_PD(RAMB, GENPD_FLAG_ALWAYS_ON), - SEC_PD(IR, 0), - SEC_PD(SPICC, 0), - SEC_PD(SPIFC, 0), - SEC_PD(USB, 0), - /* NIC is for the Arm NIC-400 interconnect, and should be always on */ - SEC_PD(NIC, GENPD_FLAG_ALWAYS_ON), - SEC_PD(PDMIN, 0), - SEC_PD(RSA, 0), -}; - -static struct meson_secure_pwrc_domain_desc s4_pwrc_domains[] = { - SEC_PD(S4_DOS_HEVC, 0), - SEC_PD(S4_DOS_VDEC, 0), - SEC_PD(S4_VPU_HDMI, 0), - SEC_PD(S4_USB_COMB, 0), - SEC_PD(S4_GE2D, 0), - /* ETH is for ethernet online wakeup, and should be always on */ - SEC_PD(S4_ETH, GENPD_FLAG_ALWAYS_ON), - SEC_PD(S4_DEMOD, 0), - SEC_PD(S4_AUDIO, 0), -}; - -static int meson_secure_pwrc_probe(struct platform_device *pdev) -{ - int i; - struct device_node *sm_np; - struct meson_secure_pwrc *pwrc; - const struct meson_secure_pwrc_domain_data *match; - - match = of_device_get_match_data(&pdev->dev); - if (!match) { - dev_err(&pdev->dev, "failed to get match data\n"); - return -ENODEV; - } - - sm_np = of_find_compatible_node(NULL, NULL, "amlogic,meson-gxbb-sm"); - if (!sm_np) { - dev_err(&pdev->dev, "no secure-monitor node\n"); - return -ENODEV; - } - - pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL); - if (!pwrc) { - of_node_put(sm_np); - return -ENOMEM; - } - - pwrc->fw = meson_sm_get(sm_np); - of_node_put(sm_np); - if (!pwrc->fw) - return -EPROBE_DEFER; - - pwrc->xlate.domains = devm_kcalloc(&pdev->dev, match->count, - sizeof(*pwrc->xlate.domains), - GFP_KERNEL); - if (!pwrc->xlate.domains) - return -ENOMEM; - - pwrc->domains = devm_kcalloc(&pdev->dev, match->count, - sizeof(*pwrc->domains), GFP_KERNEL); - if (!pwrc->domains) - return -ENOMEM; - - pwrc->xlate.num_domains = match->count; - platform_set_drvdata(pdev, pwrc); - - for (i = 0 ; i < match->count ; ++i) { - struct meson_secure_pwrc_domain *dom = &pwrc->domains[i]; - - if (!match->domains[i].index) - continue; - - dom->pwrc = pwrc; - dom->index = match->domains[i].index; - dom->base.name = match->domains[i].name; - dom->base.flags = match->domains[i].flags; - dom->base.power_on = meson_secure_pwrc_on; - dom->base.power_off = meson_secure_pwrc_off; - - pm_genpd_init(&dom->base, NULL, match->domains[i].is_off(dom)); - - pwrc->xlate.domains[i] = &dom->base; - } - - return of_genpd_add_provider_onecell(pdev->dev.of_node, &pwrc->xlate); -} - -static struct meson_secure_pwrc_domain_data meson_secure_a1_pwrc_data = { - .domains = a1_pwrc_domains, - .count = ARRAY_SIZE(a1_pwrc_domains), -}; - -static struct meson_secure_pwrc_domain_data meson_secure_s4_pwrc_data = { - .domains = s4_pwrc_domains, - .count = ARRAY_SIZE(s4_pwrc_domains), -}; - -static const struct of_device_id meson_secure_pwrc_match_table[] = { - { - .compatible = "amlogic,meson-a1-pwrc", - .data = &meson_secure_a1_pwrc_data, - }, - { - .compatible = "amlogic,meson-s4-pwrc", - .data = &meson_secure_s4_pwrc_data, - }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, meson_secure_pwrc_match_table); - -static struct platform_driver meson_secure_pwrc_driver = { - .probe = meson_secure_pwrc_probe, - .driver = { - .name = "meson_secure_pwrc", - .of_match_table = meson_secure_pwrc_match_table, - }, -}; -module_platform_driver(meson_secure_pwrc_driver); -MODULE_LICENSE("Dual MIT/GPL"); diff --git a/drivers/soc/apple/Makefile b/drivers/soc/apple/Makefile index e293770cf66d..b241e6a65e5b 100644 --- a/drivers/soc/apple/Makefile +++ b/drivers/soc/apple/Makefile @@ -1,6 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_APPLE_PMGR_PWRSTATE) += apple-pmgr-pwrstate.o - obj-$(CONFIG_APPLE_RTKIT) += apple-rtkit.o apple-rtkit-y = rtkit.o rtkit-crashlog.o diff --git a/drivers/soc/apple/apple-pmgr-pwrstate.c b/drivers/soc/apple/apple-pmgr-pwrstate.c deleted file mode 100644 index d62a776c89a1..000000000000 --- a/drivers/soc/apple/apple-pmgr-pwrstate.c +++ /dev/null @@ -1,326 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only OR MIT -/* - * Apple SoC PMGR device power state driver - * - * Copyright The Asahi Linux Contributors - */ - -#include <linux/bitops.h> -#include <linux/bitfield.h> -#include <linux/err.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <linux/regmap.h> -#include <linux/mfd/syscon.h> -#include <linux/reset-controller.h> -#include <linux/module.h> - -#define APPLE_PMGR_RESET BIT(31) -#define APPLE_PMGR_AUTO_ENABLE BIT(28) -#define APPLE_PMGR_PS_AUTO GENMASK(27, 24) -#define APPLE_PMGR_PS_MIN GENMASK(19, 16) -#define APPLE_PMGR_PARENT_OFF BIT(11) -#define APPLE_PMGR_DEV_DISABLE BIT(10) -#define APPLE_PMGR_WAS_CLKGATED BIT(9) -#define APPLE_PMGR_WAS_PWRGATED BIT(8) -#define APPLE_PMGR_PS_ACTUAL GENMASK(7, 4) -#define APPLE_PMGR_PS_TARGET GENMASK(3, 0) - -#define APPLE_PMGR_FLAGS (APPLE_PMGR_WAS_CLKGATED | APPLE_PMGR_WAS_PWRGATED) - -#define APPLE_PMGR_PS_ACTIVE 0xf -#define APPLE_PMGR_PS_CLKGATE 0x4 -#define APPLE_PMGR_PS_PWRGATE 0x0 - -#define APPLE_PMGR_PS_SET_TIMEOUT 100 -#define APPLE_PMGR_RESET_TIME 1 - -struct apple_pmgr_ps { - struct device *dev; - struct generic_pm_domain genpd; - struct reset_controller_dev rcdev; - struct regmap *regmap; - u32 offset; - u32 min_state; -}; - -#define genpd_to_apple_pmgr_ps(_genpd) container_of(_genpd, struct apple_pmgr_ps, genpd) -#define rcdev_to_apple_pmgr_ps(_rcdev) container_of(_rcdev, struct apple_pmgr_ps, rcdev) - -static int apple_pmgr_ps_set(struct generic_pm_domain *genpd, u32 pstate, bool auto_enable) -{ - int ret; - struct apple_pmgr_ps *ps = genpd_to_apple_pmgr_ps(genpd); - u32 reg; - - ret = regmap_read(ps->regmap, ps->offset, ®); - if (ret < 0) - return ret; - - /* Resets are synchronous, and only work if the device is powered and clocked. */ - if (reg & APPLE_PMGR_RESET && pstate != APPLE_PMGR_PS_ACTIVE) - dev_err(ps->dev, "PS %s: powering off with RESET active\n", - genpd->name); - - reg &= ~(APPLE_PMGR_AUTO_ENABLE | APPLE_PMGR_FLAGS | APPLE_PMGR_PS_TARGET); - reg |= FIELD_PREP(APPLE_PMGR_PS_TARGET, pstate); - - dev_dbg(ps->dev, "PS %s: pwrstate = 0x%x: 0x%x\n", genpd->name, pstate, reg); - - regmap_write(ps->regmap, ps->offset, reg); - - ret = regmap_read_poll_timeout_atomic( - ps->regmap, ps->offset, reg, - (FIELD_GET(APPLE_PMGR_PS_ACTUAL, reg) == pstate), 1, - APPLE_PMGR_PS_SET_TIMEOUT); - if (ret < 0) - dev_err(ps->dev, "PS %s: Failed to reach power state 0x%x (now: 0x%x)\n", - genpd->name, pstate, reg); - - if (auto_enable) { - /* Not all devices implement this; this is a no-op where not implemented. */ - reg &= ~APPLE_PMGR_FLAGS; - reg |= APPLE_PMGR_AUTO_ENABLE; - regmap_write(ps->regmap, ps->offset, reg); - } - - return ret; -} - -static bool apple_pmgr_ps_is_active(struct apple_pmgr_ps *ps) -{ - u32 reg = 0; - - regmap_read(ps->regmap, ps->offset, ®); - /* - * We consider domains as active if they are actually on, or if they have auto-PM - * enabled and the intended target is on. - */ - return (FIELD_GET(APPLE_PMGR_PS_ACTUAL, reg) == APPLE_PMGR_PS_ACTIVE || - (FIELD_GET(APPLE_PMGR_PS_TARGET, reg) == APPLE_PMGR_PS_ACTIVE && - reg & APPLE_PMGR_AUTO_ENABLE)); -} - -static int apple_pmgr_ps_power_on(struct generic_pm_domain *genpd) -{ - return apple_pmgr_ps_set(genpd, APPLE_PMGR_PS_ACTIVE, true); -} - -static int apple_pmgr_ps_power_off(struct generic_pm_domain *genpd) -{ - return apple_pmgr_ps_set(genpd, APPLE_PMGR_PS_PWRGATE, false); -} - -static int apple_pmgr_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) -{ - struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev); - unsigned long flags; - - spin_lock_irqsave(&ps->genpd.slock, flags); - - if (ps->genpd.status == GENPD_STATE_OFF) - dev_err(ps->dev, "PS 0x%x: asserting RESET while powered down\n", ps->offset); - - dev_dbg(ps->dev, "PS 0x%x: assert reset\n", ps->offset); - /* Quiesce device before asserting reset */ - regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_DEV_DISABLE, - APPLE_PMGR_DEV_DISABLE); - regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_RESET, - APPLE_PMGR_RESET); - - spin_unlock_irqrestore(&ps->genpd.slock, flags); - - return 0; -} - -static int apple_pmgr_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) -{ - struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev); - unsigned long flags; - - spin_lock_irqsave(&ps->genpd.slock, flags); - - dev_dbg(ps->dev, "PS 0x%x: deassert reset\n", ps->offset); - regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_RESET, 0); - regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_DEV_DISABLE, 0); - - if (ps->genpd.status == GENPD_STATE_OFF) - dev_err(ps->dev, "PS 0x%x: RESET was deasserted while powered down\n", ps->offset); - - spin_unlock_irqrestore(&ps->genpd.slock, flags); - - return 0; -} - -static int apple_pmgr_reset_reset(struct reset_controller_dev *rcdev, unsigned long id) -{ - int ret; - - ret = apple_pmgr_reset_assert(rcdev, id); - if (ret) - return ret; - - usleep_range(APPLE_PMGR_RESET_TIME, 2 * APPLE_PMGR_RESET_TIME); - - return apple_pmgr_reset_deassert(rcdev, id); -} - -static int apple_pmgr_reset_status(struct reset_controller_dev *rcdev, unsigned long id) -{ - struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev); - u32 reg = 0; - - regmap_read(ps->regmap, ps->offset, ®); - - return !!(reg & APPLE_PMGR_RESET); -} - -const struct reset_control_ops apple_pmgr_reset_ops = { - .assert = apple_pmgr_reset_assert, - .deassert = apple_pmgr_reset_deassert, - .reset = apple_pmgr_reset_reset, - .status = apple_pmgr_reset_status, -}; - -static int apple_pmgr_reset_xlate(struct reset_controller_dev *rcdev, - const struct of_phandle_args *reset_spec) -{ - return 0; -} - -static int apple_pmgr_ps_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *node = dev->of_node; - struct apple_pmgr_ps *ps; - struct regmap *regmap; - struct of_phandle_iterator it; - int ret; - const char *name; - bool active; - - regmap = syscon_node_to_regmap(node->parent); - if (IS_ERR(regmap)) - return PTR_ERR(regmap); - - ps = devm_kzalloc(dev, sizeof(*ps), GFP_KERNEL); - if (!ps) - return -ENOMEM; - - ps->dev = dev; - ps->regmap = regmap; - - ret = of_property_read_string(node, "label", &name); - if (ret < 0) { - dev_err(dev, "missing label property\n"); - return ret; - } - - ret = of_property_read_u32(node, "reg", &ps->offset); - if (ret < 0) { - dev_err(dev, "missing reg property\n"); - return ret; - } - - ps->genpd.flags |= GENPD_FLAG_IRQ_SAFE; - ps->genpd.name = name; - ps->genpd.power_on = apple_pmgr_ps_power_on; - ps->genpd.power_off = apple_pmgr_ps_power_off; - - ret = of_property_read_u32(node, "apple,min-state", &ps->min_state); - if (ret == 0 && ps->min_state <= APPLE_PMGR_PS_ACTIVE) - regmap_update_bits(regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_PS_MIN, - FIELD_PREP(APPLE_PMGR_PS_MIN, ps->min_state)); - - active = apple_pmgr_ps_is_active(ps); - if (of_property_read_bool(node, "apple,always-on")) { - ps->genpd.flags |= GENPD_FLAG_ALWAYS_ON; - if (!active) { - dev_warn(dev, "always-on domain %s is not on at boot\n", name); - /* Turn it on so pm_genpd_init does not fail */ - active = apple_pmgr_ps_power_on(&ps->genpd) == 0; - } - } - - /* Turn on auto-PM if the domain is already on */ - if (active) - regmap_update_bits(regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_AUTO_ENABLE, - APPLE_PMGR_AUTO_ENABLE); - - ret = pm_genpd_init(&ps->genpd, NULL, !active); - if (ret < 0) { - dev_err(dev, "pm_genpd_init failed\n"); - return ret; - } - - ret = of_genpd_add_provider_simple(node, &ps->genpd); - if (ret < 0) { - dev_err(dev, "of_genpd_add_provider_simple failed\n"); - return ret; - } - - of_for_each_phandle(&it, ret, node, "power-domains", "#power-domain-cells", -1) { - struct of_phandle_args parent, child; - - parent.np = it.node; - parent.args_count = of_phandle_iterator_args(&it, parent.args, MAX_PHANDLE_ARGS); - child.np = node; - child.args_count = 0; - ret = of_genpd_add_subdomain(&parent, &child); - - if (ret == -EPROBE_DEFER) { - of_node_put(parent.np); - goto err_remove; - } else if (ret < 0) { - dev_err(dev, "failed to add to parent domain: %d (%s -> %s)\n", - ret, it.node->name, node->name); - of_node_put(parent.np); - goto err_remove; - } - } - - /* - * Do not participate in regular PM; parent power domains are handled via the - * genpd hierarchy. - */ - pm_genpd_remove_device(dev); - - ps->rcdev.owner = THIS_MODULE; - ps->rcdev.nr_resets = 1; - ps->rcdev.ops = &apple_pmgr_reset_ops; - ps->rcdev.of_node = dev->of_node; - ps->rcdev.of_reset_n_cells = 0; - ps->rcdev.of_xlate = apple_pmgr_reset_xlate; - - ret = devm_reset_controller_register(dev, &ps->rcdev); - if (ret < 0) - goto err_remove; - - return 0; -err_remove: - of_genpd_del_provider(node); - pm_genpd_remove(&ps->genpd); - return ret; -} - -static const struct of_device_id apple_pmgr_ps_of_match[] = { - { .compatible = "apple,pmgr-pwrstate" }, - {} -}; - -MODULE_DEVICE_TABLE(of, apple_pmgr_ps_of_match); - -static struct platform_driver apple_pmgr_ps_driver = { - .probe = apple_pmgr_ps_probe, - .driver = { - .name = "apple-pmgr-pwrstate", - .of_match_table = apple_pmgr_ps_of_match, - }, -}; - -MODULE_AUTHOR("Hector Martin <marcan@marcan.st>"); -MODULE_DESCRIPTION("PMGR power state driver for Apple SoCs"); - -module_platform_driver(apple_pmgr_ps_driver); diff --git a/drivers/soc/bcm/Kconfig b/drivers/soc/bcm/Kconfig index 24f92a6e882a..f96906795fa6 100644 --- a/drivers/soc/bcm/Kconfig +++ b/drivers/soc/bcm/Kconfig @@ -42,7 +42,27 @@ config SOC_BRCMSTB If unsure, say N. -source "drivers/soc/bcm/bcm63xx/Kconfig" +config BCM_PMB + bool "Broadcom PMB (Power Management Bus) driver" + depends on ARCH_BCMBCA || (COMPILE_TEST && OF) + default ARCH_BCMBCA + select PM_GENERIC_DOMAINS if PM + help + This enables support for the Broadcom's PMB (Power Management Bus) that + is used for disabling and enabling SoC devices. + +if SOC_BCM63XX + +config BCM63XX_POWER + bool "BCM63xx power domain driver" + depends on BMIPS_GENERIC || (COMPILE_TEST && OF) + select PM_GENERIC_DOMAINS if PM + help + This enables support for the BCM63xx power domains controller on + BCM6318, BCM6328, BCM6362 and BCM63268 SoCs. + +endif # SOC_BCM63XX + source "drivers/soc/bcm/brcmstb/Kconfig" endmenu diff --git a/drivers/soc/bcm/Makefile b/drivers/soc/bcm/Makefile index 0f0efa28d92b..32424b1032c7 100644 --- a/drivers/soc/bcm/Makefile +++ b/drivers/soc/bcm/Makefile @@ -1,5 +1,2 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_BCM2835_POWER) += bcm2835-power.o -obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o -obj-y += bcm63xx/ obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/ diff --git a/drivers/soc/bcm/bcm2835-power.c b/drivers/soc/bcm/bcm2835-power.c deleted file mode 100644 index 1a179d4e011c..000000000000 --- a/drivers/soc/bcm/bcm2835-power.c +++ /dev/null @@ -1,713 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Power domain driver for Broadcom BCM2835 - * - * Copyright (C) 2018 Broadcom - */ - -#include <dt-bindings/soc/bcm2835-pm.h> -#include <linux/clk.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/mfd/bcm2835-pm.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <linux/reset-controller.h> -#include <linux/types.h> - -#define PM_GNRIC 0x00 -#define PM_AUDIO 0x04 -#define PM_STATUS 0x18 -#define PM_RSTC 0x1c -#define PM_RSTS 0x20 -#define PM_WDOG 0x24 -#define PM_PADS0 0x28 -#define PM_PADS2 0x2c -#define PM_PADS3 0x30 -#define PM_PADS4 0x34 -#define PM_PADS5 0x38 -#define PM_PADS6 0x3c -#define PM_CAM0 0x44 -#define PM_CAM0_LDOHPEN BIT(2) -#define PM_CAM0_LDOLPEN BIT(1) -#define PM_CAM0_CTRLEN BIT(0) - -#define PM_CAM1 0x48 -#define PM_CAM1_LDOHPEN BIT(2) -#define PM_CAM1_LDOLPEN BIT(1) -#define PM_CAM1_CTRLEN BIT(0) - -#define PM_CCP2TX 0x4c -#define PM_CCP2TX_LDOEN BIT(1) -#define PM_CCP2TX_CTRLEN BIT(0) - -#define PM_DSI0 0x50 -#define PM_DSI0_LDOHPEN BIT(2) -#define PM_DSI0_LDOLPEN BIT(1) -#define PM_DSI0_CTRLEN BIT(0) - -#define PM_DSI1 0x54 -#define PM_DSI1_LDOHPEN BIT(2) -#define PM_DSI1_LDOLPEN BIT(1) -#define PM_DSI1_CTRLEN BIT(0) - -#define PM_HDMI 0x58 -#define PM_HDMI_RSTDR BIT(19) -#define PM_HDMI_LDOPD BIT(1) -#define PM_HDMI_CTRLEN BIT(0) - -#define PM_USB 0x5c -/* The power gates must be enabled with this bit before enabling the LDO in the - * USB block. - */ -#define PM_USB_CTRLEN BIT(0) - -#define PM_PXLDO 0x60 -#define PM_PXBG 0x64 -#define PM_DFT 0x68 -#define PM_SMPS 0x6c -#define PM_XOSC 0x70 -#define PM_SPAREW 0x74 -#define PM_SPARER 0x78 -#define PM_AVS_RSTDR 0x7c -#define PM_AVS_STAT 0x80 -#define PM_AVS_EVENT 0x84 -#define PM_AVS_INTEN 0x88 -#define PM_DUMMY 0xfc - -#define PM_IMAGE 0x108 -#define PM_GRAFX 0x10c -#define PM_PROC 0x110 -#define PM_ENAB BIT(12) -#define PM_ISPRSTN BIT(8) -#define PM_H264RSTN BIT(7) -#define PM_PERIRSTN BIT(6) -#define PM_V3DRSTN BIT(6) -#define PM_ISFUNC BIT(5) -#define PM_MRDONE BIT(4) -#define PM_MEMREP BIT(3) -#define PM_ISPOW BIT(2) -#define PM_POWOK BIT(1) -#define PM_POWUP BIT(0) -#define PM_INRUSH_SHIFT 13 -#define PM_INRUSH_3_5_MA 0 -#define PM_INRUSH_5_MA 1 -#define PM_INRUSH_10_MA 2 -#define PM_INRUSH_20_MA 3 -#define PM_INRUSH_MASK (3 << PM_INRUSH_SHIFT) - -#define PM_PASSWORD 0x5a000000 - -#define PM_WDOG_TIME_SET 0x000fffff -#define PM_RSTC_WRCFG_CLR 0xffffffcf -#define PM_RSTS_HADWRH_SET 0x00000040 -#define PM_RSTC_WRCFG_SET 0x00000030 -#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 -#define PM_RSTC_RESET 0x00000102 - -#define PM_READ(reg) readl(power->base + (reg)) -#define PM_WRITE(reg, val) writel(PM_PASSWORD | (val), power->base + (reg)) - -#define ASB_BRDG_VERSION 0x00 -#define ASB_CPR_CTRL 0x04 - -#define ASB_V3D_S_CTRL 0x08 -#define ASB_V3D_M_CTRL 0x0c -#define ASB_ISP_S_CTRL 0x10 -#define ASB_ISP_M_CTRL 0x14 -#define ASB_H264_S_CTRL 0x18 -#define ASB_H264_M_CTRL 0x1c - -#define ASB_REQ_STOP BIT(0) -#define ASB_ACK BIT(1) -#define ASB_EMPTY BIT(2) -#define ASB_FULL BIT(3) - -#define ASB_AXI_BRDG_ID 0x20 - -#define BCM2835_BRDG_ID 0x62726467 - -struct bcm2835_power_domain { - struct generic_pm_domain base; - struct bcm2835_power *power; - u32 domain; - struct clk *clk; -}; - -struct bcm2835_power { - struct device *dev; - /* PM registers. */ - void __iomem *base; - /* AXI Async bridge registers. */ - void __iomem *asb; - /* RPiVid bridge registers. */ - void __iomem *rpivid_asb; - - struct genpd_onecell_data pd_xlate; - struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT]; - struct reset_controller_dev reset; -}; - -static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable) -{ - void __iomem *base = power->asb; - u64 start; - u32 val; - - switch (reg) { - case 0: - return 0; - case ASB_V3D_S_CTRL: - case ASB_V3D_M_CTRL: - if (power->rpivid_asb) - base = power->rpivid_asb; - break; - } - - start = ktime_get_ns(); - - /* Enable the module's async AXI bridges. */ - if (enable) { - val = readl(base + reg) & ~ASB_REQ_STOP; - } else { - val = readl(base + reg) | ASB_REQ_STOP; - } - writel(PM_PASSWORD | val, base + reg); - - while (readl(base + reg) & ASB_ACK) { - cpu_relax(); - if (ktime_get_ns() - start >= 1000) - return -ETIMEDOUT; - } - - return 0; -} - -static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg) -{ - return bcm2835_asb_control(power, reg, true); -} - -static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg) -{ - return bcm2835_asb_control(power, reg, false); -} - -static int bcm2835_power_power_off(struct bcm2835_power_domain *pd, u32 pm_reg) -{ - struct bcm2835_power *power = pd->power; - - /* We don't run this on BCM2711 */ - if (power->rpivid_asb) - return 0; - - /* Enable functional isolation */ - PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC); - - /* Enable electrical isolation */ - PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW); - - /* Open the power switches. */ - PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_POWUP); - - return 0; -} - -static int bcm2835_power_power_on(struct bcm2835_power_domain *pd, u32 pm_reg) -{ - struct bcm2835_power *power = pd->power; - struct device *dev = power->dev; - u64 start; - int ret; - int inrush; - bool powok; - - /* We don't run this on BCM2711 */ - if (power->rpivid_asb) - return 0; - - /* If it was already powered on by the fw, leave it that way. */ - if (PM_READ(pm_reg) & PM_POWUP) - return 0; - - /* Enable power. Allowing too much current at once may result - * in POWOK never getting set, so start low and ramp it up as - * necessary to succeed. - */ - powok = false; - for (inrush = PM_INRUSH_3_5_MA; inrush <= PM_INRUSH_20_MA; inrush++) { - PM_WRITE(pm_reg, - (PM_READ(pm_reg) & ~PM_INRUSH_MASK) | - (inrush << PM_INRUSH_SHIFT) | - PM_POWUP); - - start = ktime_get_ns(); - while (!(powok = !!(PM_READ(pm_reg) & PM_POWOK))) { - cpu_relax(); - if (ktime_get_ns() - start >= 3000) - break; - } - } - if (!powok) { - dev_err(dev, "Timeout waiting for %s power OK\n", - pd->base.name); - ret = -ETIMEDOUT; - goto err_disable_powup; - } - - /* Disable electrical isolation */ - PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISPOW); - - /* Repair memory */ - PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_MEMREP); - start = ktime_get_ns(); - while (!(PM_READ(pm_reg) & PM_MRDONE)) { - cpu_relax(); - if (ktime_get_ns() - start >= 1000) { - dev_err(dev, "Timeout waiting for %s memory repair\n", - pd->base.name); - ret = -ETIMEDOUT; - goto err_disable_ispow; - } - } - - /* Disable functional isolation */ - PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISFUNC); - - return 0; - -err_disable_ispow: - PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW); -err_disable_powup: - PM_WRITE(pm_reg, PM_READ(pm_reg) & ~(PM_POWUP | PM_INRUSH_MASK)); - return ret; -} - -static int bcm2835_asb_power_on(struct bcm2835_power_domain *pd, - u32 pm_reg, - u32 asb_m_reg, - u32 asb_s_reg, - u32 reset_flags) -{ - struct bcm2835_power *power = pd->power; - int ret; - - ret = clk_prepare_enable(pd->clk); - if (ret) { - dev_err(power->dev, "Failed to enable clock for %s\n", - pd->base.name); - return ret; - } - - /* Wait 32 clocks for reset to propagate, 1 us will be enough */ - udelay(1); - - clk_disable_unprepare(pd->clk); - - /* Deassert the resets. */ - PM_WRITE(pm_reg, PM_READ(pm_reg) | reset_flags); - - ret = clk_prepare_enable(pd->clk); - if (ret) { - dev_err(power->dev, "Failed to enable clock for %s\n", - pd->base.name); - goto err_enable_resets; - } - - ret = bcm2835_asb_enable(power, asb_m_reg); - if (ret) { - dev_err(power->dev, "Failed to enable ASB master for %s\n", - pd->base.name); - goto err_disable_clk; - } - ret = bcm2835_asb_enable(power, asb_s_reg); - if (ret) { - dev_err(power->dev, "Failed to enable ASB slave for %s\n", - pd->base.name); - goto err_disable_asb_master; - } - - return 0; - -err_disable_asb_master: - bcm2835_asb_disable(power, asb_m_reg); -err_disable_clk: - clk_disable_unprepare(pd->clk); -err_enable_resets: - PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags); - return ret; -} - -static int bcm2835_asb_power_off(struct bcm2835_power_domain *pd, - u32 pm_reg, - u32 asb_m_reg, - u32 asb_s_reg, - u32 reset_flags) -{ - struct bcm2835_power *power = pd->power; - int ret; - - ret = bcm2835_asb_disable(power, asb_s_reg); - if (ret) { - dev_warn(power->dev, "Failed to disable ASB slave for %s\n", - pd->base.name); - return ret; - } - ret = bcm2835_asb_disable(power, asb_m_reg); - if (ret) { - dev_warn(power->dev, "Failed to disable ASB master for %s\n", - pd->base.name); - bcm2835_asb_enable(power, asb_s_reg); - return ret; - } - - clk_disable_unprepare(pd->clk); - - /* Assert the resets. */ - PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags); - - return 0; -} - -static int bcm2835_power_pd_power_on(struct generic_pm_domain *domain) -{ - struct bcm2835_power_domain *pd = - container_of(domain, struct bcm2835_power_domain, base); - struct bcm2835_power *power = pd->power; - - switch (pd->domain) { - case BCM2835_POWER_DOMAIN_GRAFX: - return bcm2835_power_power_on(pd, PM_GRAFX); - - case BCM2835_POWER_DOMAIN_GRAFX_V3D: - return bcm2835_asb_power_on(pd, PM_GRAFX, - ASB_V3D_M_CTRL, ASB_V3D_S_CTRL, - PM_V3DRSTN); - - case BCM2835_POWER_DOMAIN_IMAGE: - return bcm2835_power_power_on(pd, PM_IMAGE); - - case BCM2835_POWER_DOMAIN_IMAGE_PERI: - return bcm2835_asb_power_on(pd, PM_IMAGE, - 0, 0, - PM_PERIRSTN); - - case BCM2835_POWER_DOMAIN_IMAGE_ISP: - return bcm2835_asb_power_on(pd, PM_IMAGE, - ASB_ISP_M_CTRL, ASB_ISP_S_CTRL, - PM_ISPRSTN); - - case BCM2835_POWER_DOMAIN_IMAGE_H264: - return bcm2835_asb_power_on(pd, PM_IMAGE, - ASB_H264_M_CTRL, ASB_H264_S_CTRL, - PM_H264RSTN); - - case BCM2835_POWER_DOMAIN_USB: - PM_WRITE(PM_USB, PM_USB_CTRLEN); - return 0; - - case BCM2835_POWER_DOMAIN_DSI0: - PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN); - PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN | PM_DSI0_LDOHPEN); - return 0; - - case BCM2835_POWER_DOMAIN_DSI1: - PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN); - PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN | PM_DSI1_LDOHPEN); - return 0; - - case BCM2835_POWER_DOMAIN_CCP2TX: - PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN); - PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN | PM_CCP2TX_LDOEN); - return 0; - - case BCM2835_POWER_DOMAIN_HDMI: - PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_RSTDR); - PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_CTRLEN); - PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_LDOPD); - usleep_range(100, 200); - PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_RSTDR); - return 0; - - default: - dev_err(power->dev, "Invalid domain %d\n", pd->domain); - return -EINVAL; - } -} - -static int bcm2835_power_pd_power_off(struct generic_pm_domain *domain) -{ - struct bcm2835_power_domain *pd = - container_of(domain, struct bcm2835_power_domain, base); - struct bcm2835_power *power = pd->power; - - switch (pd->domain) { - case BCM2835_POWER_DOMAIN_GRAFX: - return bcm2835_power_power_off(pd, PM_GRAFX); - - case BCM2835_POWER_DOMAIN_GRAFX_V3D: - return bcm2835_asb_power_off(pd, PM_GRAFX, - ASB_V3D_M_CTRL, ASB_V3D_S_CTRL, - PM_V3DRSTN); - - case BCM2835_POWER_DOMAIN_IMAGE: - return bcm2835_power_power_off(pd, PM_IMAGE); - - case BCM2835_POWER_DOMAIN_IMAGE_PERI: - return bcm2835_asb_power_off(pd, PM_IMAGE, - 0, 0, - PM_PERIRSTN); - - case BCM2835_POWER_DOMAIN_IMAGE_ISP: - return bcm2835_asb_power_off(pd, PM_IMAGE, - ASB_ISP_M_CTRL, ASB_ISP_S_CTRL, - PM_ISPRSTN); - - case BCM2835_POWER_DOMAIN_IMAGE_H264: - return bcm2835_asb_power_off(pd, PM_IMAGE, - ASB_H264_M_CTRL, ASB_H264_S_CTRL, - PM_H264RSTN); - - case BCM2835_POWER_DOMAIN_USB: - PM_WRITE(PM_USB, 0); - return 0; - - case BCM2835_POWER_DOMAIN_DSI0: - PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN); - PM_WRITE(PM_DSI0, 0); - return 0; - - case BCM2835_POWER_DOMAIN_DSI1: - PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN); - PM_WRITE(PM_DSI1, 0); - return 0; - - case BCM2835_POWER_DOMAIN_CCP2TX: - PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN); - PM_WRITE(PM_CCP2TX, 0); - return 0; - - case BCM2835_POWER_DOMAIN_HDMI: - PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_LDOPD); - PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_CTRLEN); - return 0; - - default: - dev_err(power->dev, "Invalid domain %d\n", pd->domain); - return -EINVAL; - } -} - -static int -bcm2835_init_power_domain(struct bcm2835_power *power, - int pd_xlate_index, const char *name) -{ - struct device *dev = power->dev; - struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index]; - - dom->clk = devm_clk_get(dev->parent, name); - if (IS_ERR(dom->clk)) { - int ret = PTR_ERR(dom->clk); - - if (ret == -EPROBE_DEFER) - return ret; - - /* Some domains don't have a clk, so make sure that we - * don't deref an error pointer later. - */ - dom->clk = NULL; - } - - dom->base.name = name; - dom->base.power_on = bcm2835_power_pd_power_on; - dom->base.power_off = bcm2835_power_pd_power_off; - - dom->domain = pd_xlate_index; - dom->power = power; - - /* XXX: on/off at boot? */ - pm_genpd_init(&dom->base, NULL, true); - - power->pd_xlate.domains[pd_xlate_index] = &dom->base; - - return 0; -} - -/** bcm2835_reset_reset - Resets a block that has a reset line in the - * PM block. - * - * The consumer of the reset controller must have the power domain up - * -- there's no reset ability with the power domain down. To reset - * the sub-block, we just disable its access to memory through the - * ASB, reset, and re-enable. - */ -static int bcm2835_reset_reset(struct reset_controller_dev *rcdev, - unsigned long id) -{ - struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power, - reset); - struct bcm2835_power_domain *pd; - int ret; - - switch (id) { - case BCM2835_RESET_V3D: - pd = &power->domains[BCM2835_POWER_DOMAIN_GRAFX_V3D]; - break; - case BCM2835_RESET_H264: - pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_H264]; - break; - case BCM2835_RESET_ISP: - pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_ISP]; - break; - default: - dev_err(power->dev, "Bad reset id %ld\n", id); - return -EINVAL; - } - - ret = bcm2835_power_pd_power_off(&pd->base); - if (ret) - return ret; - - return bcm2835_power_pd_power_on(&pd->base); -} - -static int bcm2835_reset_status(struct reset_controller_dev *rcdev, - unsigned long id) -{ - struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power, - reset); - - switch (id) { - case BCM2835_RESET_V3D: - return !PM_READ(PM_GRAFX & PM_V3DRSTN); - case BCM2835_RESET_H264: - return !PM_READ(PM_IMAGE & PM_H264RSTN); - case BCM2835_RESET_ISP: - return !PM_READ(PM_IMAGE & PM_ISPRSTN); - default: - return -EINVAL; - } -} - -static const struct reset_control_ops bcm2835_reset_ops = { - .reset = bcm2835_reset_reset, - .status = bcm2835_reset_status, -}; - -static const char *const power_domain_names[] = { - [BCM2835_POWER_DOMAIN_GRAFX] = "grafx", - [BCM2835_POWER_DOMAIN_GRAFX_V3D] = "v3d", - - [BCM2835_POWER_DOMAIN_IMAGE] = "image", - [BCM2835_POWER_DOMAIN_IMAGE_PERI] = "peri_image", - [BCM2835_POWER_DOMAIN_IMAGE_H264] = "h264", - [BCM2835_POWER_DOMAIN_IMAGE_ISP] = "isp", - - [BCM2835_POWER_DOMAIN_USB] = "usb", - [BCM2835_POWER_DOMAIN_DSI0] = "dsi0", - [BCM2835_POWER_DOMAIN_DSI1] = "dsi1", - [BCM2835_POWER_DOMAIN_CAM0] = "cam0", - [BCM2835_POWER_DOMAIN_CAM1] = "cam1", - [BCM2835_POWER_DOMAIN_CCP2TX] = "ccp2tx", - [BCM2835_POWER_DOMAIN_HDMI] = "hdmi", -}; - -static int bcm2835_power_probe(struct platform_device *pdev) -{ - struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent); - struct device *dev = &pdev->dev; - struct bcm2835_power *power; - static const struct { - int parent, child; - } domain_deps[] = { - { BCM2835_POWER_DOMAIN_GRAFX, BCM2835_POWER_DOMAIN_GRAFX_V3D }, - { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_PERI }, - { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_H264 }, - { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_ISP }, - { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_USB }, - { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM0 }, - { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM1 }, - }; - int ret = 0, i; - u32 id; - - power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL); - if (!power) - return -ENOMEM; - platform_set_drvdata(pdev, power); - - power->dev = dev; - power->base = pm->base; - power->asb = pm->asb; - power->rpivid_asb = pm->rpivid_asb; - - id = readl(power->asb + ASB_AXI_BRDG_ID); - if (id != BCM2835_BRDG_ID /* "BRDG" */) { - dev_err(dev, "ASB register ID returned 0x%08x\n", id); - return -ENODEV; - } - - if (power->rpivid_asb) { - id = readl(power->rpivid_asb + ASB_AXI_BRDG_ID); - if (id != BCM2835_BRDG_ID /* "BRDG" */) { - dev_err(dev, "RPiVid ASB register ID returned 0x%08x\n", - id); - return -ENODEV; - } - } - - power->pd_xlate.domains = devm_kcalloc(dev, - ARRAY_SIZE(power_domain_names), - sizeof(*power->pd_xlate.domains), - GFP_KERNEL); - if (!power->pd_xlate.domains) - return -ENOMEM; - - power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names); - - for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) { - ret = bcm2835_init_power_domain(power, i, power_domain_names[i]); - if (ret) - goto fail; - } - - for (i = 0; i < ARRAY_SIZE(domain_deps); i++) { - pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base, - &power->domains[domain_deps[i].child].base); - } - - power->reset.owner = THIS_MODULE; - power->reset.nr_resets = BCM2835_RESET_COUNT; - power->reset.ops = &bcm2835_reset_ops; - power->reset.of_node = dev->parent->of_node; - - ret = devm_reset_controller_register(dev, &power->reset); - if (ret) - goto fail; - - of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate); - - dev_info(dev, "Broadcom BCM2835 power domains driver"); - return 0; - -fail: - for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) { - struct generic_pm_domain *dom = &power->domains[i].base; - - if (dom->name) - pm_genpd_remove(dom); - } - return ret; -} - -static struct platform_driver bcm2835_power_driver = { - .probe = bcm2835_power_probe, - .driver = { - .name = "bcm2835-power", - }, -}; -module_platform_driver(bcm2835_power_driver); - -MODULE_AUTHOR("Eric Anholt <eric@anholt.net>"); -MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM power domains and reset"); diff --git a/drivers/soc/bcm/bcm63xx/Kconfig b/drivers/soc/bcm/bcm63xx/Kconfig deleted file mode 100644 index 355c34482076..000000000000 --- a/drivers/soc/bcm/bcm63xx/Kconfig +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -if SOC_BCM63XX - -config BCM63XX_POWER - bool "BCM63xx power domain driver" - depends on BMIPS_GENERIC || (COMPILE_TEST && OF) - select PM_GENERIC_DOMAINS if PM - help - This enables support for the BCM63xx power domains controller on - BCM6318, BCM6328, BCM6362 and BCM63268 SoCs. - -endif # SOC_BCM63XX - -config BCM_PMB - bool "Broadcom PMB (Power Management Bus) driver" - depends on ARCH_BCMBCA || (COMPILE_TEST && OF) - default ARCH_BCMBCA - select PM_GENERIC_DOMAINS if PM - help - This enables support for the Broadcom's PMB (Power Management Bus) that - is used for disabling and enabling SoC devices. diff --git a/drivers/soc/bcm/bcm63xx/Makefile b/drivers/soc/bcm/bcm63xx/Makefile deleted file mode 100644 index 557eed3d67bd..000000000000 --- a/drivers/soc/bcm/bcm63xx/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_BCM63XX_POWER) += bcm63xx-power.o -obj-$(CONFIG_BCM_PMB) += bcm-pmb.o diff --git a/drivers/soc/bcm/bcm63xx/bcm-pmb.c b/drivers/soc/bcm/bcm63xx/bcm-pmb.c deleted file mode 100644 index 9407cac47fdb..000000000000 --- a/drivers/soc/bcm/bcm63xx/bcm-pmb.c +++ /dev/null @@ -1,364 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (c) 2013 Broadcom - * Copyright (C) 2020 Rafał Miłecki <rafal@milecki.pl> - */ - -#include <dt-bindings/soc/bcm-pmb.h> -#include <linux/io.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <linux/reset/bcm63xx_pmb.h> - -#define BPCM_ID_REG 0x00 -#define BPCM_CAPABILITIES 0x04 -#define BPCM_CAP_NUM_ZONES 0x000000ff -#define BPCM_CAP_SR_REG_BITS 0x0000ff00 -#define BPCM_CAP_PLLTYPE 0x00030000 -#define BPCM_CAP_UBUS 0x00080000 -#define BPCM_CONTROL 0x08 -#define BPCM_STATUS 0x0c -#define BPCM_ROSC_CONTROL 0x10 -#define BPCM_ROSC_THRESH_H 0x14 -#define BPCM_ROSC_THRESHOLD_BCM6838 0x14 -#define BPCM_ROSC_THRESH_S 0x18 -#define BPCM_ROSC_COUNT_BCM6838 0x18 -#define BPCM_ROSC_COUNT 0x1c -#define BPCM_PWD_CONTROL_BCM6838 0x1c -#define BPCM_PWD_CONTROL 0x20 -#define BPCM_SR_CONTROL_BCM6838 0x20 -#define BPCM_PWD_ACCUM_CONTROL 0x24 -#define BPCM_SR_CONTROL 0x28 -#define BPCM_GLOBAL_CONTROL 0x2c -#define BPCM_MISC_CONTROL 0x30 -#define BPCM_MISC_CONTROL2 0x34 -#define BPCM_SGPHY_CNTL 0x38 -#define BPCM_SGPHY_STATUS 0x3c -#define BPCM_ZONE0 0x40 -#define BPCM_ZONE_CONTROL 0x00 -#define BPCM_ZONE_CONTROL_MANUAL_CLK_EN 0x00000001 -#define BPCM_ZONE_CONTROL_MANUAL_RESET_CTL 0x00000002 -#define BPCM_ZONE_CONTROL_FREQ_SCALE_USED 0x00000004 /* R/O */ -#define BPCM_ZONE_CONTROL_DPG_CAPABLE 0x00000008 /* R/O */ -#define BPCM_ZONE_CONTROL_MANUAL_MEM_PWR 0x00000030 -#define BPCM_ZONE_CONTROL_MANUAL_ISO_CTL 0x00000040 -#define BPCM_ZONE_CONTROL_MANUAL_CTL 0x00000080 -#define BPCM_ZONE_CONTROL_DPG_CTL_EN 0x00000100 -#define BPCM_ZONE_CONTROL_PWR_DN_REQ 0x00000200 -#define BPCM_ZONE_CONTROL_PWR_UP_REQ 0x00000400 -#define BPCM_ZONE_CONTROL_MEM_PWR_CTL_EN 0x00000800 -#define BPCM_ZONE_CONTROL_BLK_RESET_ASSERT 0x00001000 -#define BPCM_ZONE_CONTROL_MEM_STBY 0x00002000 -#define BPCM_ZONE_CONTROL_RESERVED 0x0007c000 -#define BPCM_ZONE_CONTROL_PWR_CNTL_STATE 0x00f80000 -#define BPCM_ZONE_CONTROL_FREQ_SCALAR_DYN_SEL 0x01000000 /* R/O */ -#define BPCM_ZONE_CONTROL_PWR_OFF_STATE 0x02000000 /* R/O */ -#define BPCM_ZONE_CONTROL_PWR_ON_STATE 0x04000000 /* R/O */ -#define BPCM_ZONE_CONTROL_PWR_GOOD 0x08000000 /* R/O */ -#define BPCM_ZONE_CONTROL_DPG_PWR_STATE 0x10000000 /* R/O */ -#define BPCM_ZONE_CONTROL_MEM_PWR_STATE 0x20000000 /* R/O */ -#define BPCM_ZONE_CONTROL_ISO_STATE 0x40000000 /* R/O */ -#define BPCM_ZONE_CONTROL_RESET_STATE 0x80000000 /* R/O */ -#define BPCM_ZONE_CONFIG1 0x04 -#define BPCM_ZONE_CONFIG2 0x08 -#define BPCM_ZONE_FREQ_SCALAR_CONTROL 0x0c -#define BPCM_ZONE_SIZE 0x10 - -struct bcm_pmb { - struct device *dev; - void __iomem *base; - spinlock_t lock; - bool little_endian; - struct genpd_onecell_data genpd_onecell_data; -}; - -struct bcm_pmb_pd_data { - const char * const name; - int id; - u8 bus; - u8 device; -}; - -struct bcm_pmb_pm_domain { - struct bcm_pmb *pmb; - const struct bcm_pmb_pd_data *data; - struct generic_pm_domain genpd; -}; - -static int bcm_pmb_bpcm_read(struct bcm_pmb *pmb, int bus, u8 device, - int offset, u32 *val) -{ - void __iomem *base = pmb->base + bus * 0x20; - unsigned long flags; - int err; - - spin_lock_irqsave(&pmb->lock, flags); - err = bpcm_rd(base, device, offset, val); - spin_unlock_irqrestore(&pmb->lock, flags); - - if (!err) - *val = pmb->little_endian ? le32_to_cpu(*val) : be32_to_cpu(*val); - - return err; -} - -static int bcm_pmb_bpcm_write(struct bcm_pmb *pmb, int bus, u8 device, - int offset, u32 val) -{ - void __iomem *base = pmb->base + bus * 0x20; - unsigned long flags; - int err; - - val = pmb->little_endian ? cpu_to_le32(val) : cpu_to_be32(val); - - spin_lock_irqsave(&pmb->lock, flags); - err = bpcm_wr(base, device, offset, val); - spin_unlock_irqrestore(&pmb->lock, flags); - - return err; -} - -static int bcm_pmb_power_off_zone(struct bcm_pmb *pmb, int bus, u8 device, - int zone) -{ - int offset; - u32 val; - int err; - - offset = BPCM_ZONE0 + zone * BPCM_ZONE_SIZE + BPCM_ZONE_CONTROL; - - err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val); - if (err) - return err; - - val |= BPCM_ZONE_CONTROL_PWR_DN_REQ; - val &= ~BPCM_ZONE_CONTROL_PWR_UP_REQ; - - err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val); - - return err; -} - -static int bcm_pmb_power_on_zone(struct bcm_pmb *pmb, int bus, u8 device, - int zone) -{ - int offset; - u32 val; - int err; - - offset = BPCM_ZONE0 + zone * BPCM_ZONE_SIZE + BPCM_ZONE_CONTROL; - - err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val); - if (err) - return err; - - if (!(val & BPCM_ZONE_CONTROL_PWR_ON_STATE)) { - val &= ~BPCM_ZONE_CONTROL_PWR_DN_REQ; - val |= BPCM_ZONE_CONTROL_DPG_CTL_EN; - val |= BPCM_ZONE_CONTROL_PWR_UP_REQ; - val |= BPCM_ZONE_CONTROL_MEM_PWR_CTL_EN; - val |= BPCM_ZONE_CONTROL_BLK_RESET_ASSERT; - - err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val); - } - - return err; -} - -static int bcm_pmb_power_off_device(struct bcm_pmb *pmb, int bus, u8 device) -{ - int offset; - u32 val; - int err; - - /* Entire device can be powered off by powering off the 0th zone */ - offset = BPCM_ZONE0 + BPCM_ZONE_CONTROL; - - err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val); - if (err) - return err; - - if (!(val & BPCM_ZONE_CONTROL_PWR_OFF_STATE)) { - val = BPCM_ZONE_CONTROL_PWR_DN_REQ; - - err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val); - } - - return err; -} - -static int bcm_pmb_power_on_device(struct bcm_pmb *pmb, int bus, u8 device) -{ - u32 val; - int err; - int i; - - err = bcm_pmb_bpcm_read(pmb, bus, device, BPCM_CAPABILITIES, &val); - if (err) - return err; - - for (i = 0; i < (val & BPCM_CAP_NUM_ZONES); i++) { - err = bcm_pmb_power_on_zone(pmb, bus, device, i); - if (err) - return err; - } - - return err; -} - -static int bcm_pmb_power_on_sata(struct bcm_pmb *pmb, int bus, u8 device) -{ - int err; - - err = bcm_pmb_power_on_zone(pmb, bus, device, 0); - if (err) - return err; - - /* Does not apply to the BCM963158 */ - err = bcm_pmb_bpcm_write(pmb, bus, device, BPCM_MISC_CONTROL, 0); - if (err) - return err; - - err = bcm_pmb_bpcm_write(pmb, bus, device, BPCM_SR_CONTROL, 0xffffffff); - if (err) - return err; - - err = bcm_pmb_bpcm_write(pmb, bus, device, BPCM_SR_CONTROL, 0); - - return err; -} - -static int bcm_pmb_power_on(struct generic_pm_domain *genpd) -{ - struct bcm_pmb_pm_domain *pd = container_of(genpd, struct bcm_pmb_pm_domain, genpd); - const struct bcm_pmb_pd_data *data = pd->data; - struct bcm_pmb *pmb = pd->pmb; - - switch (data->id) { - case BCM_PMB_PCIE0: - case BCM_PMB_PCIE1: - case BCM_PMB_PCIE2: - return bcm_pmb_power_on_zone(pmb, data->bus, data->device, 0); - case BCM_PMB_HOST_USB: - return bcm_pmb_power_on_device(pmb, data->bus, data->device); - case BCM_PMB_SATA: - return bcm_pmb_power_on_sata(pmb, data->bus, data->device); - default: - dev_err(pmb->dev, "unsupported device id: %d\n", data->id); - return -EINVAL; - } -} - -static int bcm_pmb_power_off(struct generic_pm_domain *genpd) -{ - struct bcm_pmb_pm_domain *pd = container_of(genpd, struct bcm_pmb_pm_domain, genpd); - const struct bcm_pmb_pd_data *data = pd->data; - struct bcm_pmb *pmb = pd->pmb; - - switch (data->id) { - case BCM_PMB_PCIE0: - case BCM_PMB_PCIE1: - case BCM_PMB_PCIE2: - return bcm_pmb_power_off_zone(pmb, data->bus, data->device, 0); - case BCM_PMB_HOST_USB: - return bcm_pmb_power_off_device(pmb, data->bus, data->device); - default: - dev_err(pmb->dev, "unsupported device id: %d\n", data->id); - return -EINVAL; - } -} - -static int bcm_pmb_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - const struct bcm_pmb_pd_data *table; - const struct bcm_pmb_pd_data *e; - struct bcm_pmb *pmb; - int max_id; - int err; - - pmb = devm_kzalloc(dev, sizeof(*pmb), GFP_KERNEL); - if (!pmb) - return -ENOMEM; - - pmb->dev = dev; - - pmb->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(pmb->base)) - return PTR_ERR(pmb->base); - - spin_lock_init(&pmb->lock); - - pmb->little_endian = !of_device_is_big_endian(dev->of_node); - - table = of_device_get_match_data(dev); - if (!table) - return -EINVAL; - - max_id = 0; - for (e = table; e->name; e++) - max_id = max(max_id, e->id); - - pmb->genpd_onecell_data.num_domains = max_id + 1; - pmb->genpd_onecell_data.domains = - devm_kcalloc(dev, pmb->genpd_onecell_data.num_domains, - sizeof(struct generic_pm_domain *), GFP_KERNEL); - if (!pmb->genpd_onecell_data.domains) - return -ENOMEM; - - for (e = table; e->name; e++) { - struct bcm_pmb_pm_domain *pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); - - if (!pd) - return -ENOMEM; - - pd->pmb = pmb; - pd->data = e; - pd->genpd.name = e->name; - pd->genpd.power_on = bcm_pmb_power_on; - pd->genpd.power_off = bcm_pmb_power_off; - - pm_genpd_init(&pd->genpd, NULL, true); - pmb->genpd_onecell_data.domains[e->id] = &pd->genpd; - } - - err = of_genpd_add_provider_onecell(dev->of_node, &pmb->genpd_onecell_data); - if (err) { - dev_err(dev, "failed to add genpd provider: %d\n", err); - return err; - } - - return 0; -} - -static const struct bcm_pmb_pd_data bcm_pmb_bcm4908_data[] = { - { .name = "pcie2", .id = BCM_PMB_PCIE2, .bus = 0, .device = 2, }, - { .name = "pcie0", .id = BCM_PMB_PCIE0, .bus = 1, .device = 14, }, - { .name = "pcie1", .id = BCM_PMB_PCIE1, .bus = 1, .device = 15, }, - { .name = "usb", .id = BCM_PMB_HOST_USB, .bus = 1, .device = 17, }, - { }, -}; - -static const struct bcm_pmb_pd_data bcm_pmb_bcm63138_data[] = { - { .name = "sata", .id = BCM_PMB_SATA, .bus = 0, .device = 3, }, - { }, -}; - -static const struct of_device_id bcm_pmb_of_match[] = { - { .compatible = "brcm,bcm4908-pmb", .data = &bcm_pmb_bcm4908_data, }, - { .compatible = "brcm,bcm63138-pmb", .data = &bcm_pmb_bcm63138_data, }, - { }, -}; - -static struct platform_driver bcm_pmb_driver = { - .driver = { - .name = "bcm-pmb", - .of_match_table = bcm_pmb_of_match, - }, - .probe = bcm_pmb_probe, -}; - -builtin_platform_driver(bcm_pmb_driver); diff --git a/drivers/soc/bcm/bcm63xx/bcm63xx-power.c b/drivers/soc/bcm/bcm63xx/bcm63xx-power.c deleted file mode 100644 index aa72e13d5d0e..000000000000 --- a/drivers/soc/bcm/bcm63xx/bcm63xx-power.c +++ /dev/null @@ -1,376 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * BCM63xx Power Domain Controller Driver - * - * Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com> - */ - -#include <dt-bindings/soc/bcm6318-pm.h> -#include <dt-bindings/soc/bcm6328-pm.h> -#include <dt-bindings/soc/bcm6362-pm.h> -#include <dt-bindings/soc/bcm63268-pm.h> -#include <linux/io.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <linux/of.h> -#include <linux/of_device.h> - -struct bcm63xx_power_dev { - struct generic_pm_domain genpd; - struct bcm63xx_power *power; - uint32_t mask; -}; - -struct bcm63xx_power { - void __iomem *base; - spinlock_t lock; - struct bcm63xx_power_dev *dev; - struct genpd_onecell_data genpd_data; - struct generic_pm_domain **genpd; -}; - -struct bcm63xx_power_data { - const char * const name; - uint8_t bit; - unsigned int flags; -}; - -static int bcm63xx_power_get_state(struct bcm63xx_power_dev *pmd, bool *is_on) -{ - struct bcm63xx_power *power = pmd->power; - - if (!pmd->mask) { - *is_on = false; - return -EINVAL; - } - - *is_on = !(__raw_readl(power->base) & pmd->mask); - - return 0; -} - -static int bcm63xx_power_set_state(struct bcm63xx_power_dev *pmd, bool on) -{ - struct bcm63xx_power *power = pmd->power; - unsigned long flags; - uint32_t val; - - if (!pmd->mask) - return -EINVAL; - - spin_lock_irqsave(&power->lock, flags); - val = __raw_readl(power->base); - if (on) - val &= ~pmd->mask; - else - val |= pmd->mask; - __raw_writel(val, power->base); - spin_unlock_irqrestore(&power->lock, flags); - - return 0; -} - -static int bcm63xx_power_on(struct generic_pm_domain *genpd) -{ - struct bcm63xx_power_dev *pmd = container_of(genpd, - struct bcm63xx_power_dev, genpd); - - return bcm63xx_power_set_state(pmd, true); -} - -static int bcm63xx_power_off(struct generic_pm_domain *genpd) -{ - struct bcm63xx_power_dev *pmd = container_of(genpd, - struct bcm63xx_power_dev, genpd); - - return bcm63xx_power_set_state(pmd, false); -} - -static int bcm63xx_power_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - const struct bcm63xx_power_data *entry, *table; - struct bcm63xx_power *power; - unsigned int ndom; - uint8_t max_bit = 0; - int ret; - - power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL); - if (!power) - return -ENOMEM; - - power->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(power->base)) - return PTR_ERR(power->base); - - table = of_device_get_match_data(dev); - if (!table) - return -EINVAL; - - power->genpd_data.num_domains = 0; - ndom = 0; - for (entry = table; entry->name; entry++) { - max_bit = max(max_bit, entry->bit); - ndom++; - } - - if (!ndom) - return -ENODEV; - - power->genpd_data.num_domains = max_bit + 1; - - power->dev = devm_kcalloc(dev, power->genpd_data.num_domains, - sizeof(struct bcm63xx_power_dev), - GFP_KERNEL); - if (!power->dev) - return -ENOMEM; - - power->genpd = devm_kcalloc(dev, power->genpd_data.num_domains, - sizeof(struct generic_pm_domain *), - GFP_KERNEL); - if (!power->genpd) - return -ENOMEM; - - power->genpd_data.domains = power->genpd; - - ndom = 0; - for (entry = table; entry->name; entry++) { - struct bcm63xx_power_dev *pmd = &power->dev[ndom]; - bool is_on; - - pmd->power = power; - pmd->mask = BIT(entry->bit); - pmd->genpd.name = entry->name; - pmd->genpd.flags = entry->flags; - - ret = bcm63xx_power_get_state(pmd, &is_on); - if (ret) - dev_warn(dev, "unable to get current state for %s\n", - pmd->genpd.name); - - pmd->genpd.power_on = bcm63xx_power_on; - pmd->genpd.power_off = bcm63xx_power_off; - - pm_genpd_init(&pmd->genpd, NULL, !is_on); - power->genpd[entry->bit] = &pmd->genpd; - - ndom++; - } - - spin_lock_init(&power->lock); - - ret = of_genpd_add_provider_onecell(np, &power->genpd_data); - if (ret) { - dev_err(dev, "failed to register genpd driver: %d\n", ret); - return ret; - } - - dev_info(dev, "registered %u power domains\n", ndom); - - return 0; -} - -static const struct bcm63xx_power_data bcm6318_power_domains[] = { - { - .name = "pcie", - .bit = BCM6318_POWER_DOMAIN_PCIE, - }, { - .name = "usb", - .bit = BCM6318_POWER_DOMAIN_USB, - }, { - .name = "ephy0", - .bit = BCM6318_POWER_DOMAIN_EPHY0, - }, { - .name = "ephy1", - .bit = BCM6318_POWER_DOMAIN_EPHY1, - }, { - .name = "ephy2", - .bit = BCM6318_POWER_DOMAIN_EPHY2, - }, { - .name = "ephy3", - .bit = BCM6318_POWER_DOMAIN_EPHY3, - }, { - .name = "ldo2p5", - .bit = BCM6318_POWER_DOMAIN_LDO2P5, - .flags = GENPD_FLAG_ALWAYS_ON, - }, { - .name = "ldo2p9", - .bit = BCM6318_POWER_DOMAIN_LDO2P9, - .flags = GENPD_FLAG_ALWAYS_ON, - }, { - .name = "sw1p0", - .bit = BCM6318_POWER_DOMAIN_SW1P0, - .flags = GENPD_FLAG_ALWAYS_ON, - }, { - .name = "pad", - .bit = BCM6318_POWER_DOMAIN_PAD, - .flags = GENPD_FLAG_ALWAYS_ON, - }, { - /* sentinel */ - }, -}; - -static const struct bcm63xx_power_data bcm6328_power_domains[] = { - { - .name = "adsl2-mips", - .bit = BCM6328_POWER_DOMAIN_ADSL2_MIPS, - }, { - .name = "adsl2-phy", - .bit = BCM6328_POWER_DOMAIN_ADSL2_PHY, - }, { - .name = "adsl2-afe", - .bit = BCM6328_POWER_DOMAIN_ADSL2_AFE, - }, { - .name = "sar", - .bit = BCM6328_POWER_DOMAIN_SAR, - }, { - .name = "pcm", - .bit = BCM6328_POWER_DOMAIN_PCM, - }, { - .name = "usbd", - .bit = BCM6328_POWER_DOMAIN_USBD, - }, { - .name = "usbh", - .bit = BCM6328_POWER_DOMAIN_USBH, - }, { - .name = "pcie", - .bit = BCM6328_POWER_DOMAIN_PCIE, - }, { - .name = "robosw", - .bit = BCM6328_POWER_DOMAIN_ROBOSW, - }, { - .name = "ephy", - .bit = BCM6328_POWER_DOMAIN_EPHY, - }, { - /* sentinel */ - }, -}; - -static const struct bcm63xx_power_data bcm6362_power_domains[] = { - { - .name = "sar", - .bit = BCM6362_POWER_DOMAIN_SAR, - }, { - .name = "ipsec", - .bit = BCM6362_POWER_DOMAIN_IPSEC, - }, { - .name = "mips", - .bit = BCM6362_POWER_DOMAIN_MIPS, - .flags = GENPD_FLAG_ALWAYS_ON, - }, { - .name = "dect", - .bit = BCM6362_POWER_DOMAIN_DECT, - }, { - .name = "usbh", - .bit = BCM6362_POWER_DOMAIN_USBH, - }, { - .name = "usbd", - .bit = BCM6362_POWER_DOMAIN_USBD, - }, { - .name = "robosw", - .bit = BCM6362_POWER_DOMAIN_ROBOSW, - }, { - .name = "pcm", - .bit = BCM6362_POWER_DOMAIN_PCM, - }, { - .name = "periph", - .bit = BCM6362_POWER_DOMAIN_PERIPH, - .flags = GENPD_FLAG_ALWAYS_ON, - }, { - .name = "adsl-phy", - .bit = BCM6362_POWER_DOMAIN_ADSL_PHY, - }, { - .name = "gmii-pads", - .bit = BCM6362_POWER_DOMAIN_GMII_PADS, - }, { - .name = "fap", - .bit = BCM6362_POWER_DOMAIN_FAP, - }, { - .name = "pcie", - .bit = BCM6362_POWER_DOMAIN_PCIE, - }, { - .name = "wlan-pads", - .bit = BCM6362_POWER_DOMAIN_WLAN_PADS, - }, { - /* sentinel */ - }, -}; - -static const struct bcm63xx_power_data bcm63268_power_domains[] = { - { - .name = "sar", - .bit = BCM63268_POWER_DOMAIN_SAR, - }, { - .name = "ipsec", - .bit = BCM63268_POWER_DOMAIN_IPSEC, - }, { - .name = "mips", - .bit = BCM63268_POWER_DOMAIN_MIPS, - .flags = GENPD_FLAG_ALWAYS_ON, - }, { - .name = "dect", - .bit = BCM63268_POWER_DOMAIN_DECT, - }, { - .name = "usbh", - .bit = BCM63268_POWER_DOMAIN_USBH, - }, { - .name = "usbd", - .bit = BCM63268_POWER_DOMAIN_USBD, - }, { - .name = "robosw", - .bit = BCM63268_POWER_DOMAIN_ROBOSW, - }, { - .name = "pcm", - .bit = BCM63268_POWER_DOMAIN_PCM, - }, { - .name = "periph", - .bit = BCM63268_POWER_DOMAIN_PERIPH, - .flags = GENPD_FLAG_ALWAYS_ON, - }, { - .name = "vdsl-phy", - .bit = BCM63268_POWER_DOMAIN_VDSL_PHY, - }, { - .name = "vdsl-mips", - .bit = BCM63268_POWER_DOMAIN_VDSL_MIPS, - }, { - .name = "fap", - .bit = BCM63268_POWER_DOMAIN_FAP, - }, { - .name = "pcie", - .bit = BCM63268_POWER_DOMAIN_PCIE, - }, { - .name = "wlan-pads", - .bit = BCM63268_POWER_DOMAIN_WLAN_PADS, - }, { - /* sentinel */ - }, -}; - -static const struct of_device_id bcm63xx_power_of_match[] = { - { - .compatible = "brcm,bcm6318-power-controller", - .data = &bcm6318_power_domains, - }, { - .compatible = "brcm,bcm6328-power-controller", - .data = &bcm6328_power_domains, - }, { - .compatible = "brcm,bcm6362-power-controller", - .data = &bcm6362_power_domains, - }, { - .compatible = "brcm,bcm63268-power-controller", - .data = &bcm63268_power_domains, - }, { - /* sentinel */ - } -}; - -static struct platform_driver bcm63xx_power_driver = { - .driver = { - .name = "bcm63xx-power-controller", - .of_match_table = bcm63xx_power_of_match, - }, - .probe = bcm63xx_power_probe, -}; -builtin_platform_driver(bcm63xx_power_driver); diff --git a/drivers/soc/bcm/raspberrypi-power.c b/drivers/soc/bcm/raspberrypi-power.c deleted file mode 100644 index 58175af982a0..000000000000 --- a/drivers/soc/bcm/raspberrypi-power.c +++ /dev/null @@ -1,245 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* (C) 2015 Pengutronix, Alexander Aring <aar@pengutronix.de> - * - * Authors: - * Alexander Aring <aar@pengutronix.de> - * Eric Anholt <eric@anholt.net> - */ - -#include <linux/module.h> -#include <linux/of_platform.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <dt-bindings/power/raspberrypi-power.h> -#include <soc/bcm2835/raspberrypi-firmware.h> - -/* - * Firmware indices for the old power domains interface. Only a few - * of them were actually implemented. - */ -#define RPI_OLD_POWER_DOMAIN_USB 3 -#define RPI_OLD_POWER_DOMAIN_V3D 10 - -struct rpi_power_domain { - u32 domain; - bool enabled; - bool old_interface; - struct generic_pm_domain base; - struct rpi_firmware *fw; -}; - -struct rpi_power_domains { - bool has_new_interface; - struct genpd_onecell_data xlate; - struct rpi_firmware *fw; - struct rpi_power_domain domains[RPI_POWER_DOMAIN_COUNT]; -}; - -/* - * Packet definition used by RPI_FIRMWARE_SET_POWER_STATE and - * RPI_FIRMWARE_SET_DOMAIN_STATE - */ -struct rpi_power_domain_packet { - u32 domain; - u32 on; -}; - -/* - * Asks the firmware to enable or disable power on a specific power - * domain. - */ -static int rpi_firmware_set_power(struct rpi_power_domain *rpi_domain, bool on) -{ - struct rpi_power_domain_packet packet; - - packet.domain = rpi_domain->domain; - packet.on = on; - return rpi_firmware_property(rpi_domain->fw, - rpi_domain->old_interface ? - RPI_FIRMWARE_SET_POWER_STATE : - RPI_FIRMWARE_SET_DOMAIN_STATE, - &packet, sizeof(packet)); -} - -static int rpi_domain_off(struct generic_pm_domain *domain) -{ - struct rpi_power_domain *rpi_domain = - container_of(domain, struct rpi_power_domain, base); - - return rpi_firmware_set_power(rpi_domain, false); -} - -static int rpi_domain_on(struct generic_pm_domain *domain) -{ - struct rpi_power_domain *rpi_domain = - container_of(domain, struct rpi_power_domain, base); - - return rpi_firmware_set_power(rpi_domain, true); -} - -static void rpi_common_init_power_domain(struct rpi_power_domains *rpi_domains, - int xlate_index, const char *name) -{ - struct rpi_power_domain *dom = &rpi_domains->domains[xlate_index]; - - dom->fw = rpi_domains->fw; - - dom->base.name = name; - dom->base.power_on = rpi_domain_on; - dom->base.power_off = rpi_domain_off; - - /* - * Treat all power domains as off at boot. - * - * The firmware itself may be keeping some domains on, but - * from Linux's perspective all we control is the refcounts - * that we give to the firmware, and we can't ask the firmware - * to turn off something that we haven't ourselves turned on. - */ - pm_genpd_init(&dom->base, NULL, true); - - rpi_domains->xlate.domains[xlate_index] = &dom->base; -} - -static void rpi_init_power_domain(struct rpi_power_domains *rpi_domains, - int xlate_index, const char *name) -{ - struct rpi_power_domain *dom = &rpi_domains->domains[xlate_index]; - - if (!rpi_domains->has_new_interface) - return; - - /* The DT binding index is the firmware's domain index minus one. */ - dom->domain = xlate_index + 1; - - rpi_common_init_power_domain(rpi_domains, xlate_index, name); -} - -static void rpi_init_old_power_domain(struct rpi_power_domains *rpi_domains, - int xlate_index, int domain, - const char *name) -{ - struct rpi_power_domain *dom = &rpi_domains->domains[xlate_index]; - - dom->old_interface = true; - dom->domain = domain; - - rpi_common_init_power_domain(rpi_domains, xlate_index, name); -} - -/* - * Detects whether the firmware supports the new power domains interface. - * - * The firmware doesn't actually return an error on an unknown tag, - * and just skips over it, so we do the detection by putting an - * unexpected value in the return field and checking if it was - * unchanged. - */ -static bool -rpi_has_new_domain_support(struct rpi_power_domains *rpi_domains) -{ - struct rpi_power_domain_packet packet; - int ret; - - packet.domain = RPI_POWER_DOMAIN_ARM; - packet.on = ~0; - - ret = rpi_firmware_property(rpi_domains->fw, - RPI_FIRMWARE_GET_DOMAIN_STATE, - &packet, sizeof(packet)); - - return ret == 0 && packet.on != ~0; -} - -static int rpi_power_probe(struct platform_device *pdev) -{ - struct device_node *fw_np; - struct device *dev = &pdev->dev; - struct rpi_power_domains *rpi_domains; - - rpi_domains = devm_kzalloc(dev, sizeof(*rpi_domains), GFP_KERNEL); - if (!rpi_domains) - return -ENOMEM; - - rpi_domains->xlate.domains = - devm_kcalloc(dev, - RPI_POWER_DOMAIN_COUNT, - sizeof(*rpi_domains->xlate.domains), - GFP_KERNEL); - if (!rpi_domains->xlate.domains) - return -ENOMEM; - - rpi_domains->xlate.num_domains = RPI_POWER_DOMAIN_COUNT; - - fw_np = of_parse_phandle(pdev->dev.of_node, "firmware", 0); - if (!fw_np) { - dev_err(&pdev->dev, "no firmware node\n"); - return -ENODEV; - } - - rpi_domains->fw = devm_rpi_firmware_get(&pdev->dev, fw_np); - of_node_put(fw_np); - if (!rpi_domains->fw) - return -EPROBE_DEFER; - - rpi_domains->has_new_interface = - rpi_has_new_domain_support(rpi_domains); - - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_I2C0, "I2C0"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_I2C1, "I2C1"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_I2C2, "I2C2"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_VIDEO_SCALER, - "VIDEO_SCALER"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_VPU1, "VPU1"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_HDMI, "HDMI"); - - /* - * Use the old firmware interface for USB power, so that we - * can turn it on even if the firmware hasn't been updated. - */ - rpi_init_old_power_domain(rpi_domains, RPI_POWER_DOMAIN_USB, - RPI_OLD_POWER_DOMAIN_USB, "USB"); - - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_VEC, "VEC"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_JPEG, "JPEG"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_H264, "H264"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_V3D, "V3D"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_ISP, "ISP"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_UNICAM0, "UNICAM0"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_UNICAM1, "UNICAM1"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CCP2RX, "CCP2RX"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CSI2, "CSI2"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CPI, "CPI"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_DSI0, "DSI0"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_DSI1, "DSI1"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_TRANSPOSER, - "TRANSPOSER"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CCP2TX, "CCP2TX"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CDP, "CDP"); - rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_ARM, "ARM"); - - of_genpd_add_provider_onecell(dev->of_node, &rpi_domains->xlate); - - platform_set_drvdata(pdev, rpi_domains); - - return 0; -} - -static const struct of_device_id rpi_power_of_match[] = { - { .compatible = "raspberrypi,bcm2835-power", }, - {}, -}; -MODULE_DEVICE_TABLE(of, rpi_power_of_match); - -static struct platform_driver rpi_power_driver = { - .driver = { - .name = "raspberrypi-power", - .of_match_table = rpi_power_of_match, - }, - .probe = rpi_power_probe, -}; -builtin_platform_driver(rpi_power_driver); - -MODULE_AUTHOR("Alexander Aring <aar@pengutronix.de>"); -MODULE_AUTHOR("Eric Anholt <eric@anholt.net>"); -MODULE_DESCRIPTION("Raspberry Pi power domain driver"); diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile index a28c44a1f16a..3ad321ca608a 100644 --- a/drivers/soc/imx/Makefile +++ b/drivers/soc/imx/Makefile @@ -2,10 +2,5 @@ ifeq ($(CONFIG_ARM),y) obj-$(CONFIG_ARCH_MXC) += soc-imx.o endif -obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o -obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o -obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8m-blk-ctrl.o -obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8mp-blk-ctrl.o -obj-$(CONFIG_SOC_IMX9) += imx93-src.o imx93-pd.o -obj-$(CONFIG_IMX9_BLK_CTRL) += imx93-blk-ctrl.o +obj-$(CONFIG_SOC_IMX9) += imx93-src.o diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c deleted file mode 100644 index 90a8b2c0676f..000000000000 --- a/drivers/soc/imx/gpc.c +++ /dev/null @@ -1,554 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de> - * Copyright 2011-2013 Freescale Semiconductor, Inc. - */ - -#include <linux/clk.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <linux/regmap.h> -#include <linux/regulator/consumer.h> - -#define GPC_CNTR 0x000 - -#define GPC_PGC_CTRL_OFFS 0x0 -#define GPC_PGC_PUPSCR_OFFS 0x4 -#define GPC_PGC_PDNSCR_OFFS 0x8 -#define GPC_PGC_SW2ISO_SHIFT 0x8 -#define GPC_PGC_SW_SHIFT 0x0 - -#define GPC_PGC_PCI_PDN 0x200 -#define GPC_PGC_PCI_SR 0x20c - -#define GPC_PGC_GPU_PDN 0x260 -#define GPC_PGC_GPU_PUPSCR 0x264 -#define GPC_PGC_GPU_PDNSCR 0x268 -#define GPC_PGC_GPU_SR 0x26c - -#define GPC_PGC_DISP_PDN 0x240 -#define GPC_PGC_DISP_SR 0x24c - -#define GPU_VPU_PUP_REQ BIT(1) -#define GPU_VPU_PDN_REQ BIT(0) - -#define GPC_CLK_MAX 7 - -#define PGC_DOMAIN_FLAG_NO_PD BIT(0) - -struct imx_pm_domain { - struct generic_pm_domain base; - struct regmap *regmap; - struct regulator *supply; - struct clk *clk[GPC_CLK_MAX]; - int num_clks; - unsigned int reg_offs; - signed char cntr_pdn_bit; - unsigned int ipg_rate_mhz; -}; - -static inline struct imx_pm_domain * -to_imx_pm_domain(struct generic_pm_domain *genpd) -{ - return container_of(genpd, struct imx_pm_domain, base); -} - -static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd) -{ - struct imx_pm_domain *pd = to_imx_pm_domain(genpd); - int iso, iso2sw; - u32 val; - - /* Read ISO and ISO2SW power down delays */ - regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PDNSCR_OFFS, &val); - iso = val & 0x3f; - iso2sw = (val >> 8) & 0x3f; - - /* Gate off domain when powered down */ - regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS, - 0x1, 0x1); - - /* Request GPC to power down domain */ - val = BIT(pd->cntr_pdn_bit); - regmap_update_bits(pd->regmap, GPC_CNTR, val, val); - - /* Wait ISO + ISO2SW IPG clock cycles */ - udelay(DIV_ROUND_UP(iso + iso2sw, pd->ipg_rate_mhz)); - - if (pd->supply) - regulator_disable(pd->supply); - - return 0; -} - -static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd) -{ - struct imx_pm_domain *pd = to_imx_pm_domain(genpd); - int i, ret; - u32 val, req; - - if (pd->supply) { - ret = regulator_enable(pd->supply); - if (ret) { - pr_err("%s: failed to enable regulator: %d\n", - __func__, ret); - return ret; - } - } - - /* Enable reset clocks for all devices in the domain */ - for (i = 0; i < pd->num_clks; i++) - clk_prepare_enable(pd->clk[i]); - - /* Gate off domain when powered down */ - regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS, - 0x1, 0x1); - - /* Request GPC to power up domain */ - req = BIT(pd->cntr_pdn_bit + 1); - regmap_update_bits(pd->regmap, GPC_CNTR, req, req); - - /* Wait for the PGC to handle the request */ - ret = regmap_read_poll_timeout(pd->regmap, GPC_CNTR, val, !(val & req), - 1, 50); - if (ret) - pr_err("powerup request on domain %s timed out\n", genpd->name); - - /* Wait for reset to propagate through peripherals */ - usleep_range(5, 10); - - /* Disable reset clocks for all devices in the domain */ - for (i = 0; i < pd->num_clks; i++) - clk_disable_unprepare(pd->clk[i]); - - return 0; -} - -static int imx_pgc_get_clocks(struct device *dev, struct imx_pm_domain *domain) -{ - int i, ret; - - for (i = 0; ; i++) { - struct clk *clk = of_clk_get(dev->of_node, i); - if (IS_ERR(clk)) - break; - if (i >= GPC_CLK_MAX) { - dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX); - ret = -EINVAL; - goto clk_err; - } - domain->clk[i] = clk; - } - domain->num_clks = i; - - return 0; - -clk_err: - while (i--) - clk_put(domain->clk[i]); - - return ret; -} - -static void imx_pgc_put_clocks(struct imx_pm_domain *domain) -{ - int i; - - for (i = domain->num_clks - 1; i >= 0; i--) - clk_put(domain->clk[i]); -} - -static int imx_pgc_parse_dt(struct device *dev, struct imx_pm_domain *domain) -{ - /* try to get the domain supply regulator */ - domain->supply = devm_regulator_get_optional(dev, "power"); - if (IS_ERR(domain->supply)) { - if (PTR_ERR(domain->supply) == -ENODEV) - domain->supply = NULL; - else - return PTR_ERR(domain->supply); - } - - /* try to get all clocks needed for reset propagation */ - return imx_pgc_get_clocks(dev, domain); -} - -static int imx_pgc_power_domain_probe(struct platform_device *pdev) -{ - struct imx_pm_domain *domain = pdev->dev.platform_data; - struct device *dev = &pdev->dev; - int ret; - - /* if this PD is associated with a DT node try to parse it */ - if (dev->of_node) { - ret = imx_pgc_parse_dt(dev, domain); - if (ret) - return ret; - } - - /* initially power on the domain */ - if (domain->base.power_on) - domain->base.power_on(&domain->base); - - if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) { - pm_genpd_init(&domain->base, NULL, false); - ret = of_genpd_add_provider_simple(dev->of_node, &domain->base); - if (ret) - goto genpd_err; - } - - device_link_add(dev, dev->parent, DL_FLAG_AUTOREMOVE_CONSUMER); - - return 0; - -genpd_err: - pm_genpd_remove(&domain->base); - imx_pgc_put_clocks(domain); - - return ret; -} - -static int imx_pgc_power_domain_remove(struct platform_device *pdev) -{ - struct imx_pm_domain *domain = pdev->dev.platform_data; - - if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) { - of_genpd_del_provider(pdev->dev.of_node); - pm_genpd_remove(&domain->base); - imx_pgc_put_clocks(domain); - } - - return 0; -} - -static const struct platform_device_id imx_pgc_power_domain_id[] = { - { "imx-pgc-power-domain"}, - { }, -}; - -static struct platform_driver imx_pgc_power_domain_driver = { - .driver = { - .name = "imx-pgc-pd", - }, - .probe = imx_pgc_power_domain_probe, - .remove = imx_pgc_power_domain_remove, - .id_table = imx_pgc_power_domain_id, -}; -builtin_platform_driver(imx_pgc_power_domain_driver) - -#define GPC_PGC_DOMAIN_ARM 0 -#define GPC_PGC_DOMAIN_PU 1 -#define GPC_PGC_DOMAIN_DISPLAY 2 -#define GPC_PGC_DOMAIN_PCI 3 - -static struct genpd_power_state imx6_pm_domain_pu_state = { - .power_off_latency_ns = 25000, - .power_on_latency_ns = 2000000, -}; - -static struct imx_pm_domain imx_gpc_domains[] = { - [GPC_PGC_DOMAIN_ARM] = { - .base = { - .name = "ARM", - .flags = GENPD_FLAG_ALWAYS_ON, - }, - }, - [GPC_PGC_DOMAIN_PU] = { - .base = { - .name = "PU", - .power_off = imx6_pm_domain_power_off, - .power_on = imx6_pm_domain_power_on, - .states = &imx6_pm_domain_pu_state, - .state_count = 1, - }, - .reg_offs = 0x260, - .cntr_pdn_bit = 0, - }, - [GPC_PGC_DOMAIN_DISPLAY] = { - .base = { - .name = "DISPLAY", - .power_off = imx6_pm_domain_power_off, - .power_on = imx6_pm_domain_power_on, - }, - .reg_offs = 0x240, - .cntr_pdn_bit = 4, - }, - [GPC_PGC_DOMAIN_PCI] = { - .base = { - .name = "PCI", - .power_off = imx6_pm_domain_power_off, - .power_on = imx6_pm_domain_power_on, - }, - .reg_offs = 0x200, - .cntr_pdn_bit = 6, - }, -}; - -struct imx_gpc_dt_data { - int num_domains; - bool err009619_present; - bool err006287_present; -}; - -static const struct imx_gpc_dt_data imx6q_dt_data = { - .num_domains = 2, - .err009619_present = false, - .err006287_present = false, -}; - -static const struct imx_gpc_dt_data imx6qp_dt_data = { - .num_domains = 2, - .err009619_present = true, - .err006287_present = false, -}; - -static const struct imx_gpc_dt_data imx6sl_dt_data = { - .num_domains = 3, - .err009619_present = false, - .err006287_present = true, -}; - -static const struct imx_gpc_dt_data imx6sx_dt_data = { - .num_domains = 4, - .err009619_present = false, - .err006287_present = false, -}; - -static const struct of_device_id imx_gpc_dt_ids[] = { - { .compatible = "fsl,imx6q-gpc", .data = &imx6q_dt_data }, - { .compatible = "fsl,imx6qp-gpc", .data = &imx6qp_dt_data }, - { .compatible = "fsl,imx6sl-gpc", .data = &imx6sl_dt_data }, - { .compatible = "fsl,imx6sx-gpc", .data = &imx6sx_dt_data }, - { } -}; - -static const struct regmap_range yes_ranges[] = { - regmap_reg_range(GPC_CNTR, GPC_CNTR), - regmap_reg_range(GPC_PGC_PCI_PDN, GPC_PGC_PCI_SR), - regmap_reg_range(GPC_PGC_GPU_PDN, GPC_PGC_GPU_SR), - regmap_reg_range(GPC_PGC_DISP_PDN, GPC_PGC_DISP_SR), -}; - -static const struct regmap_access_table access_table = { - .yes_ranges = yes_ranges, - .n_yes_ranges = ARRAY_SIZE(yes_ranges), -}; - -static const struct regmap_config imx_gpc_regmap_config = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .rd_table = &access_table, - .wr_table = &access_table, - .max_register = 0x2ac, - .fast_io = true, -}; - -static struct generic_pm_domain *imx_gpc_onecell_domains[] = { - &imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base, - &imx_gpc_domains[GPC_PGC_DOMAIN_PU].base, -}; - -static struct genpd_onecell_data imx_gpc_onecell_data = { - .domains = imx_gpc_onecell_domains, - .num_domains = 2, -}; - -static int imx_gpc_old_dt_init(struct device *dev, struct regmap *regmap, - unsigned int num_domains) -{ - struct imx_pm_domain *domain; - int i, ret; - - for (i = 0; i < num_domains; i++) { - domain = &imx_gpc_domains[i]; - domain->regmap = regmap; - domain->ipg_rate_mhz = 66; - - if (i == 1) { - domain->supply = devm_regulator_get(dev, "pu"); - if (IS_ERR(domain->supply)) - return PTR_ERR(domain->supply); - - ret = imx_pgc_get_clocks(dev, domain); - if (ret) - goto clk_err; - - domain->base.power_on(&domain->base); - } - } - - for (i = 0; i < num_domains; i++) - pm_genpd_init(&imx_gpc_domains[i].base, NULL, false); - - if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) { - ret = of_genpd_add_provider_onecell(dev->of_node, - &imx_gpc_onecell_data); - if (ret) - goto genpd_err; - } - - return 0; - -genpd_err: - for (i = 0; i < num_domains; i++) - pm_genpd_remove(&imx_gpc_domains[i].base); - imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]); -clk_err: - return ret; -} - -static int imx_gpc_probe(struct platform_device *pdev) -{ - const struct of_device_id *of_id = - of_match_device(imx_gpc_dt_ids, &pdev->dev); - const struct imx_gpc_dt_data *of_id_data = of_id->data; - struct device_node *pgc_node; - struct regmap *regmap; - void __iomem *base; - int ret; - - pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc"); - - /* bail out if DT too old and doesn't provide the necessary info */ - if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") && - !pgc_node) - return 0; - - base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(base)) - return PTR_ERR(base); - - regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base, - &imx_gpc_regmap_config); - if (IS_ERR(regmap)) { - ret = PTR_ERR(regmap); - dev_err(&pdev->dev, "failed to init regmap: %d\n", - ret); - return ret; - } - - /* - * Disable PU power down by runtime PM if ERR009619 is present. - * - * The PRE clock will be paused for several cycles when turning on the - * PU domain LDO from power down state. If PRE is in use at that time, - * the IPU/PRG cannot get the correct display data from the PRE. - * - * This is not a concern when the whole system enters suspend state, so - * it's safe to power down PU in this case. - */ - if (of_id_data->err009619_present) - imx_gpc_domains[GPC_PGC_DOMAIN_PU].base.flags |= - GENPD_FLAG_RPM_ALWAYS_ON; - - /* Keep DISP always on if ERR006287 is present */ - if (of_id_data->err006287_present) - imx_gpc_domains[GPC_PGC_DOMAIN_DISPLAY].base.flags |= - GENPD_FLAG_ALWAYS_ON; - - if (!pgc_node) { - ret = imx_gpc_old_dt_init(&pdev->dev, regmap, - of_id_data->num_domains); - if (ret) - return ret; - } else { - struct imx_pm_domain *domain; - struct platform_device *pd_pdev; - struct device_node *np; - struct clk *ipg_clk; - unsigned int ipg_rate_mhz; - int domain_index; - - ipg_clk = devm_clk_get(&pdev->dev, "ipg"); - if (IS_ERR(ipg_clk)) - return PTR_ERR(ipg_clk); - ipg_rate_mhz = clk_get_rate(ipg_clk) / 1000000; - - for_each_child_of_node(pgc_node, np) { - ret = of_property_read_u32(np, "reg", &domain_index); - if (ret) { - of_node_put(np); - return ret; - } - if (domain_index >= of_id_data->num_domains) - continue; - - pd_pdev = platform_device_alloc("imx-pgc-power-domain", - domain_index); - if (!pd_pdev) { - of_node_put(np); - return -ENOMEM; - } - - ret = platform_device_add_data(pd_pdev, - &imx_gpc_domains[domain_index], - sizeof(imx_gpc_domains[domain_index])); - if (ret) { - platform_device_put(pd_pdev); - of_node_put(np); - return ret; - } - domain = pd_pdev->dev.platform_data; - domain->regmap = regmap; - domain->ipg_rate_mhz = ipg_rate_mhz; - - pd_pdev->dev.parent = &pdev->dev; - pd_pdev->dev.of_node = np; - - ret = platform_device_add(pd_pdev); - if (ret) { - platform_device_put(pd_pdev); - of_node_put(np); - return ret; - } - } - } - - return 0; -} - -static int imx_gpc_remove(struct platform_device *pdev) -{ - struct device_node *pgc_node; - int ret; - - pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc"); - - /* bail out if DT too old and doesn't provide the necessary info */ - if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") && - !pgc_node) - return 0; - - /* - * If the old DT binding is used the toplevel driver needs to - * de-register the power domains - */ - if (!pgc_node) { - of_genpd_del_provider(pdev->dev.of_node); - - ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_PU].base); - if (ret) - return ret; - imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]); - - ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base); - if (ret) - return ret; - } - - return 0; -} - -static struct platform_driver imx_gpc_driver = { - .driver = { - .name = "imx-gpc", - .of_match_table = imx_gpc_dt_ids, - }, - .probe = imx_gpc_probe, - .remove = imx_gpc_remove, -}; -builtin_platform_driver(imx_gpc_driver) diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c deleted file mode 100644 index 4b3300b090a8..000000000000 --- a/drivers/soc/imx/gpcv2.c +++ /dev/null @@ -1,1550 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright 2017 Impinj, Inc - * Author: Andrey Smirnov <andrew.smirnov@gmail.com> - * - * Based on the code of analogus driver: - * - * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de> - */ - -#include <linux/clk.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <linux/pm_runtime.h> -#include <linux/regmap.h> -#include <linux/regulator/consumer.h> -#include <linux/reset.h> -#include <linux/sizes.h> -#include <dt-bindings/power/imx7-power.h> -#include <dt-bindings/power/imx8mq-power.h> -#include <dt-bindings/power/imx8mm-power.h> -#include <dt-bindings/power/imx8mn-power.h> -#include <dt-bindings/power/imx8mp-power.h> - -#define GPC_LPCR_A_CORE_BSC 0x000 - -#define GPC_PGC_CPU_MAPPING 0x0ec -#define IMX8MP_GPC_PGC_CPU_MAPPING 0x1cc - -#define IMX7_USB_HSIC_PHY_A_CORE_DOMAIN BIT(6) -#define IMX7_USB_OTG2_PHY_A_CORE_DOMAIN BIT(5) -#define IMX7_USB_OTG1_PHY_A_CORE_DOMAIN BIT(4) -#define IMX7_PCIE_PHY_A_CORE_DOMAIN BIT(3) -#define IMX7_MIPI_PHY_A_CORE_DOMAIN BIT(2) - -#define IMX8M_PCIE2_A53_DOMAIN BIT(15) -#define IMX8M_MIPI_CSI2_A53_DOMAIN BIT(14) -#define IMX8M_MIPI_CSI1_A53_DOMAIN BIT(13) -#define IMX8M_DISP_A53_DOMAIN BIT(12) -#define IMX8M_HDMI_A53_DOMAIN BIT(11) -#define IMX8M_VPU_A53_DOMAIN BIT(10) -#define IMX8M_GPU_A53_DOMAIN BIT(9) -#define IMX8M_DDR2_A53_DOMAIN BIT(8) -#define IMX8M_DDR1_A53_DOMAIN BIT(7) -#define IMX8M_OTG2_A53_DOMAIN BIT(5) -#define IMX8M_OTG1_A53_DOMAIN BIT(4) -#define IMX8M_PCIE1_A53_DOMAIN BIT(3) -#define IMX8M_MIPI_A53_DOMAIN BIT(2) - -#define IMX8MM_VPUH1_A53_DOMAIN BIT(15) -#define IMX8MM_VPUG2_A53_DOMAIN BIT(14) -#define IMX8MM_VPUG1_A53_DOMAIN BIT(13) -#define IMX8MM_DISPMIX_A53_DOMAIN BIT(12) -#define IMX8MM_VPUMIX_A53_DOMAIN BIT(10) -#define IMX8MM_GPUMIX_A53_DOMAIN BIT(9) -#define IMX8MM_GPU_A53_DOMAIN (BIT(8) | BIT(11)) -#define IMX8MM_DDR1_A53_DOMAIN BIT(7) -#define IMX8MM_OTG2_A53_DOMAIN BIT(5) -#define IMX8MM_OTG1_A53_DOMAIN BIT(4) -#define IMX8MM_PCIE_A53_DOMAIN BIT(3) -#define IMX8MM_MIPI_A53_DOMAIN BIT(2) - -#define IMX8MN_DISPMIX_A53_DOMAIN BIT(12) -#define IMX8MN_GPUMIX_A53_DOMAIN BIT(9) -#define IMX8MN_DDR1_A53_DOMAIN BIT(7) -#define IMX8MN_OTG1_A53_DOMAIN BIT(4) -#define IMX8MN_MIPI_A53_DOMAIN BIT(2) - -#define IMX8MP_MEDIA_ISPDWP_A53_DOMAIN BIT(20) -#define IMX8MP_HSIOMIX_A53_DOMAIN BIT(19) -#define IMX8MP_MIPI_PHY2_A53_DOMAIN BIT(18) -#define IMX8MP_HDMI_PHY_A53_DOMAIN BIT(17) -#define IMX8MP_HDMIMIX_A53_DOMAIN BIT(16) -#define IMX8MP_VPU_VC8000E_A53_DOMAIN BIT(15) -#define IMX8MP_VPU_G2_A53_DOMAIN BIT(14) -#define IMX8MP_VPU_G1_A53_DOMAIN BIT(13) -#define IMX8MP_MEDIAMIX_A53_DOMAIN BIT(12) -#define IMX8MP_GPU3D_A53_DOMAIN BIT(11) -#define IMX8MP_VPUMIX_A53_DOMAIN BIT(10) -#define IMX8MP_GPUMIX_A53_DOMAIN BIT(9) -#define IMX8MP_GPU2D_A53_DOMAIN BIT(8) -#define IMX8MP_AUDIOMIX_A53_DOMAIN BIT(7) -#define IMX8MP_MLMIX_A53_DOMAIN BIT(6) -#define IMX8MP_USB2_PHY_A53_DOMAIN BIT(5) -#define IMX8MP_USB1_PHY_A53_DOMAIN BIT(4) -#define IMX8MP_PCIE_PHY_A53_DOMAIN BIT(3) -#define IMX8MP_MIPI_PHY1_A53_DOMAIN BIT(2) - -#define IMX8MP_GPC_PU_PGC_SW_PUP_REQ 0x0d8 -#define IMX8MP_GPC_PU_PGC_SW_PDN_REQ 0x0e4 - -#define GPC_PU_PGC_SW_PUP_REQ 0x0f8 -#define GPC_PU_PGC_SW_PDN_REQ 0x104 - -#define IMX7_USB_HSIC_PHY_SW_Pxx_REQ BIT(4) -#define IMX7_USB_OTG2_PHY_SW_Pxx_REQ BIT(3) -#define IMX7_USB_OTG1_PHY_SW_Pxx_REQ BIT(2) -#define IMX7_PCIE_PHY_SW_Pxx_REQ BIT(1) -#define IMX7_MIPI_PHY_SW_Pxx_REQ BIT(0) - -#define IMX8M_PCIE2_SW_Pxx_REQ BIT(13) -#define IMX8M_MIPI_CSI2_SW_Pxx_REQ BIT(12) -#define IMX8M_MIPI_CSI1_SW_Pxx_REQ BIT(11) -#define IMX8M_DISP_SW_Pxx_REQ BIT(10) -#define IMX8M_HDMI_SW_Pxx_REQ BIT(9) -#define IMX8M_VPU_SW_Pxx_REQ BIT(8) -#define IMX8M_GPU_SW_Pxx_REQ BIT(7) -#define IMX8M_DDR2_SW_Pxx_REQ BIT(6) -#define IMX8M_DDR1_SW_Pxx_REQ BIT(5) -#define IMX8M_OTG2_SW_Pxx_REQ BIT(3) -#define IMX8M_OTG1_SW_Pxx_REQ BIT(2) -#define IMX8M_PCIE1_SW_Pxx_REQ BIT(1) -#define IMX8M_MIPI_SW_Pxx_REQ BIT(0) - -#define IMX8MM_VPUH1_SW_Pxx_REQ BIT(13) -#define IMX8MM_VPUG2_SW_Pxx_REQ BIT(12) -#define IMX8MM_VPUG1_SW_Pxx_REQ BIT(11) -#define IMX8MM_DISPMIX_SW_Pxx_REQ BIT(10) -#define IMX8MM_VPUMIX_SW_Pxx_REQ BIT(8) -#define IMX8MM_GPUMIX_SW_Pxx_REQ BIT(7) -#define IMX8MM_GPU_SW_Pxx_REQ (BIT(6) | BIT(9)) -#define IMX8MM_DDR1_SW_Pxx_REQ BIT(5) -#define IMX8MM_OTG2_SW_Pxx_REQ BIT(3) -#define IMX8MM_OTG1_SW_Pxx_REQ BIT(2) -#define IMX8MM_PCIE_SW_Pxx_REQ BIT(1) -#define IMX8MM_MIPI_SW_Pxx_REQ BIT(0) - -#define IMX8MN_DISPMIX_SW_Pxx_REQ BIT(10) -#define IMX8MN_GPUMIX_SW_Pxx_REQ BIT(7) -#define IMX8MN_DDR1_SW_Pxx_REQ BIT(5) -#define IMX8MN_OTG1_SW_Pxx_REQ BIT(2) -#define IMX8MN_MIPI_SW_Pxx_REQ BIT(0) - -#define IMX8MP_DDRMIX_Pxx_REQ BIT(19) -#define IMX8MP_MEDIA_ISP_DWP_Pxx_REQ BIT(18) -#define IMX8MP_HSIOMIX_Pxx_REQ BIT(17) -#define IMX8MP_MIPI_PHY2_Pxx_REQ BIT(16) -#define IMX8MP_HDMI_PHY_Pxx_REQ BIT(15) -#define IMX8MP_HDMIMIX_Pxx_REQ BIT(14) -#define IMX8MP_VPU_VC8K_Pxx_REQ BIT(13) -#define IMX8MP_VPU_G2_Pxx_REQ BIT(12) -#define IMX8MP_VPU_G1_Pxx_REQ BIT(11) -#define IMX8MP_MEDIMIX_Pxx_REQ BIT(10) -#define IMX8MP_GPU_3D_Pxx_REQ BIT(9) -#define IMX8MP_VPU_MIX_SHARE_LOGIC_Pxx_REQ BIT(8) -#define IMX8MP_GPU_SHARE_LOGIC_Pxx_REQ BIT(7) -#define IMX8MP_GPU_2D_Pxx_REQ BIT(6) -#define IMX8MP_AUDIOMIX_Pxx_REQ BIT(5) -#define IMX8MP_MLMIX_Pxx_REQ BIT(4) -#define IMX8MP_USB2_PHY_Pxx_REQ BIT(3) -#define IMX8MP_USB1_PHY_Pxx_REQ BIT(2) -#define IMX8MP_PCIE_PHY_SW_Pxx_REQ BIT(1) -#define IMX8MP_MIPI_PHY1_SW_Pxx_REQ BIT(0) - -#define GPC_M4_PU_PDN_FLG 0x1bc - -#define IMX8MP_GPC_PU_PWRHSK 0x190 -#define GPC_PU_PWRHSK 0x1fc - -#define IMX8M_GPU_HSK_PWRDNACKN BIT(26) -#define IMX8M_VPU_HSK_PWRDNACKN BIT(25) -#define IMX8M_DISP_HSK_PWRDNACKN BIT(24) -#define IMX8M_GPU_HSK_PWRDNREQN BIT(6) -#define IMX8M_VPU_HSK_PWRDNREQN BIT(5) -#define IMX8M_DISP_HSK_PWRDNREQN BIT(4) - -#define IMX8MM_GPUMIX_HSK_PWRDNACKN BIT(29) -#define IMX8MM_GPU_HSK_PWRDNACKN (BIT(27) | BIT(28)) -#define IMX8MM_VPUMIX_HSK_PWRDNACKN BIT(26) -#define IMX8MM_DISPMIX_HSK_PWRDNACKN BIT(25) -#define IMX8MM_HSIO_HSK_PWRDNACKN (BIT(23) | BIT(24)) -#define IMX8MM_GPUMIX_HSK_PWRDNREQN BIT(11) -#define IMX8MM_GPU_HSK_PWRDNREQN (BIT(9) | BIT(10)) -#define IMX8MM_VPUMIX_HSK_PWRDNREQN BIT(8) -#define IMX8MM_DISPMIX_HSK_PWRDNREQN BIT(7) -#define IMX8MM_HSIO_HSK_PWRDNREQN (BIT(5) | BIT(6)) - -#define IMX8MN_GPUMIX_HSK_PWRDNACKN (BIT(29) | BIT(27)) -#define IMX8MN_DISPMIX_HSK_PWRDNACKN BIT(25) -#define IMX8MN_HSIO_HSK_PWRDNACKN BIT(23) -#define IMX8MN_GPUMIX_HSK_PWRDNREQN (BIT(11) | BIT(9)) -#define IMX8MN_DISPMIX_HSK_PWRDNREQN BIT(7) -#define IMX8MN_HSIO_HSK_PWRDNREQN BIT(5) - -#define IMX8MP_MEDIAMIX_PWRDNACKN BIT(30) -#define IMX8MP_HDMIMIX_PWRDNACKN BIT(29) -#define IMX8MP_HSIOMIX_PWRDNACKN BIT(28) -#define IMX8MP_VPUMIX_PWRDNACKN BIT(26) -#define IMX8MP_GPUMIX_PWRDNACKN BIT(25) -#define IMX8MP_MLMIX_PWRDNACKN (BIT(23) | BIT(24)) -#define IMX8MP_AUDIOMIX_PWRDNACKN (BIT(20) | BIT(31)) -#define IMX8MP_MEDIAMIX_PWRDNREQN BIT(14) -#define IMX8MP_HDMIMIX_PWRDNREQN BIT(13) -#define IMX8MP_HSIOMIX_PWRDNREQN BIT(12) -#define IMX8MP_VPUMIX_PWRDNREQN BIT(10) -#define IMX8MP_GPUMIX_PWRDNREQN BIT(9) -#define IMX8MP_MLMIX_PWRDNREQN (BIT(7) | BIT(8)) -#define IMX8MP_AUDIOMIX_PWRDNREQN (BIT(4) | BIT(15)) - -/* - * The PGC offset values in Reference Manual - * (Rev. 1, 01/2018 and the older ones) GPC chapter's - * GPC_PGC memory map are incorrect, below offset - * values are from design RTL. - */ -#define IMX7_PGC_MIPI 16 -#define IMX7_PGC_PCIE 17 -#define IMX7_PGC_USB_HSIC 20 - -#define IMX8M_PGC_MIPI 16 -#define IMX8M_PGC_PCIE1 17 -#define IMX8M_PGC_OTG1 18 -#define IMX8M_PGC_OTG2 19 -#define IMX8M_PGC_DDR1 21 -#define IMX8M_PGC_GPU 23 -#define IMX8M_PGC_VPU 24 -#define IMX8M_PGC_DISP 26 -#define IMX8M_PGC_MIPI_CSI1 27 -#define IMX8M_PGC_MIPI_CSI2 28 -#define IMX8M_PGC_PCIE2 29 - -#define IMX8MM_PGC_MIPI 16 -#define IMX8MM_PGC_PCIE 17 -#define IMX8MM_PGC_OTG1 18 -#define IMX8MM_PGC_OTG2 19 -#define IMX8MM_PGC_DDR1 21 -#define IMX8MM_PGC_GPU2D 22 -#define IMX8MM_PGC_GPUMIX 23 -#define IMX8MM_PGC_VPUMIX 24 -#define IMX8MM_PGC_GPU3D 25 -#define IMX8MM_PGC_DISPMIX 26 -#define IMX8MM_PGC_VPUG1 27 -#define IMX8MM_PGC_VPUG2 28 -#define IMX8MM_PGC_VPUH1 29 - -#define IMX8MN_PGC_MIPI 16 -#define IMX8MN_PGC_OTG1 18 -#define IMX8MN_PGC_DDR1 21 -#define IMX8MN_PGC_GPUMIX 23 -#define IMX8MN_PGC_DISPMIX 26 - -#define IMX8MP_PGC_NOC 9 -#define IMX8MP_PGC_MIPI1 12 -#define IMX8MP_PGC_PCIE 13 -#define IMX8MP_PGC_USB1 14 -#define IMX8MP_PGC_USB2 15 -#define IMX8MP_PGC_MLMIX 16 -#define IMX8MP_PGC_AUDIOMIX 17 -#define IMX8MP_PGC_GPU2D 18 -#define IMX8MP_PGC_GPUMIX 19 -#define IMX8MP_PGC_VPUMIX 20 -#define IMX8MP_PGC_GPU3D 21 -#define IMX8MP_PGC_MEDIAMIX 22 -#define IMX8MP_PGC_VPU_G1 23 -#define IMX8MP_PGC_VPU_G2 24 -#define IMX8MP_PGC_VPU_VC8000E 25 -#define IMX8MP_PGC_HDMIMIX 26 -#define IMX8MP_PGC_HDMI 27 -#define IMX8MP_PGC_MIPI2 28 -#define IMX8MP_PGC_HSIOMIX 29 -#define IMX8MP_PGC_MEDIA_ISP_DWP 30 -#define IMX8MP_PGC_DDRMIX 31 - -#define GPC_PGC_CTRL(n) (0x800 + (n) * 0x40) -#define GPC_PGC_SR(n) (GPC_PGC_CTRL(n) + 0xc) - -#define GPC_PGC_CTRL_PCR BIT(0) - -struct imx_pgc_regs { - u16 map; - u16 pup; - u16 pdn; - u16 hsk; -}; - -struct imx_pgc_domain { - struct generic_pm_domain genpd; - struct regmap *regmap; - const struct imx_pgc_regs *regs; - struct regulator *regulator; - struct reset_control *reset; - struct clk_bulk_data *clks; - int num_clks; - - unsigned long pgc; - - const struct { - u32 pxx; - u32 map; - u32 hskreq; - u32 hskack; - } bits; - - const int voltage; - const bool keep_clocks; - struct device *dev; - - unsigned int pgc_sw_pup_reg; - unsigned int pgc_sw_pdn_reg; -}; - -struct imx_pgc_domain_data { - const struct imx_pgc_domain *domains; - size_t domains_num; - const struct regmap_access_table *reg_access_table; - const struct imx_pgc_regs *pgc_regs; -}; - -static inline struct imx_pgc_domain * -to_imx_pgc_domain(struct generic_pm_domain *genpd) -{ - return container_of(genpd, struct imx_pgc_domain, genpd); -} - -static int imx_pgc_power_up(struct generic_pm_domain *genpd) -{ - struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd); - u32 reg_val, pgc; - int ret; - - ret = pm_runtime_get_sync(domain->dev); - if (ret < 0) { - pm_runtime_put_noidle(domain->dev); - return ret; - } - - if (!IS_ERR(domain->regulator)) { - ret = regulator_enable(domain->regulator); - if (ret) { - dev_err(domain->dev, - "failed to enable regulator: %pe\n", - ERR_PTR(ret)); - goto out_put_pm; - } - } - - reset_control_assert(domain->reset); - - /* Enable reset clocks for all devices in the domain */ - ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks); - if (ret) { - dev_err(domain->dev, "failed to enable reset clocks\n"); - goto out_regulator_disable; - } - - /* delays for reset to propagate */ - udelay(5); - - if (domain->bits.pxx) { - /* request the domain to power up */ - regmap_update_bits(domain->regmap, domain->regs->pup, - domain->bits.pxx, domain->bits.pxx); - /* - * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait - * for PUP_REQ/PDN_REQ bit to be cleared - */ - ret = regmap_read_poll_timeout(domain->regmap, - domain->regs->pup, reg_val, - !(reg_val & domain->bits.pxx), - 0, USEC_PER_MSEC); - if (ret) { - dev_err(domain->dev, "failed to command PGC\n"); - goto out_clk_disable; - } - - /* disable power control */ - for_each_set_bit(pgc, &domain->pgc, 32) { - regmap_clear_bits(domain->regmap, GPC_PGC_CTRL(pgc), - GPC_PGC_CTRL_PCR); - } - } - - /* delay for reset to propagate */ - udelay(5); - - reset_control_deassert(domain->reset); - - /* request the ADB400 to power up */ - if (domain->bits.hskreq) { - regmap_update_bits(domain->regmap, domain->regs->hsk, - domain->bits.hskreq, domain->bits.hskreq); - - /* - * ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk, reg_val, - * (reg_val & domain->bits.hskack), 0, - * USEC_PER_MSEC); - * Technically we need the commented code to wait handshake. But that needs - * the BLK-CTL module BUS clk-en bit being set. - * - * There is a separate BLK-CTL module and we will have such a driver for it, - * that driver will set the BUS clk-en bit and handshake will be triggered - * automatically there. Just add a delay and suppose the handshake finish - * after that. - */ - } - - /* Disable reset clocks for all devices in the domain */ - if (!domain->keep_clocks) - clk_bulk_disable_unprepare(domain->num_clks, domain->clks); - - return 0; - -out_clk_disable: - clk_bulk_disable_unprepare(domain->num_clks, domain->clks); -out_regulator_disable: - if (!IS_ERR(domain->regulator)) - regulator_disable(domain->regulator); -out_put_pm: - pm_runtime_put(domain->dev); - - return ret; -} - -static int imx_pgc_power_down(struct generic_pm_domain *genpd) -{ - struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd); - u32 reg_val, pgc; - int ret; - - /* Enable reset clocks for all devices in the domain */ - if (!domain->keep_clocks) { - ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks); - if (ret) { - dev_err(domain->dev, "failed to enable reset clocks\n"); - return ret; - } - } - - /* request the ADB400 to power down */ - if (domain->bits.hskreq) { - regmap_clear_bits(domain->regmap, domain->regs->hsk, - domain->bits.hskreq); - - ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk, - reg_val, - !(reg_val & domain->bits.hskack), - 0, USEC_PER_MSEC); - if (ret) { - dev_err(domain->dev, "failed to power down ADB400\n"); - goto out_clk_disable; - } - } - - if (domain->bits.pxx) { - /* enable power control */ - for_each_set_bit(pgc, &domain->pgc, 32) { - regmap_update_bits(domain->regmap, GPC_PGC_CTRL(pgc), - GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR); - } - - /* request the domain to power down */ - regmap_update_bits(domain->regmap, domain->regs->pdn, - domain->bits.pxx, domain->bits.pxx); - /* - * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait - * for PUP_REQ/PDN_REQ bit to be cleared - */ - ret = regmap_read_poll_timeout(domain->regmap, - domain->regs->pdn, reg_val, - !(reg_val & domain->bits.pxx), - 0, USEC_PER_MSEC); - if (ret) { - dev_err(domain->dev, "failed to command PGC\n"); - goto out_clk_disable; - } - } - - /* Disable reset clocks for all devices in the domain */ - clk_bulk_disable_unprepare(domain->num_clks, domain->clks); - - if (!IS_ERR(domain->regulator)) { - ret = regulator_disable(domain->regulator); - if (ret) { - dev_err(domain->dev, - "failed to disable regulator: %pe\n", - ERR_PTR(ret)); - return ret; - } - } - - pm_runtime_put_sync_suspend(domain->dev); - - return 0; - -out_clk_disable: - if (!domain->keep_clocks) - clk_bulk_disable_unprepare(domain->num_clks, domain->clks); - - return ret; -} - -static const struct imx_pgc_domain imx7_pgc_domains[] = { - [IMX7_POWER_DOMAIN_MIPI_PHY] = { - .genpd = { - .name = "mipi-phy", - }, - .bits = { - .pxx = IMX7_MIPI_PHY_SW_Pxx_REQ, - .map = IMX7_MIPI_PHY_A_CORE_DOMAIN, - }, - .voltage = 1000000, - .pgc = BIT(IMX7_PGC_MIPI), - }, - - [IMX7_POWER_DOMAIN_PCIE_PHY] = { - .genpd = { - .name = "pcie-phy", - }, - .bits = { - .pxx = IMX7_PCIE_PHY_SW_Pxx_REQ, - .map = IMX7_PCIE_PHY_A_CORE_DOMAIN, - }, - .voltage = 1000000, - .pgc = BIT(IMX7_PGC_PCIE), - }, - - [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = { - .genpd = { - .name = "usb-hsic-phy", - }, - .bits = { - .pxx = IMX7_USB_HSIC_PHY_SW_Pxx_REQ, - .map = IMX7_USB_HSIC_PHY_A_CORE_DOMAIN, - }, - .voltage = 1200000, - .pgc = BIT(IMX7_PGC_USB_HSIC), - }, -}; - -static const struct regmap_range imx7_yes_ranges[] = { - regmap_reg_range(GPC_LPCR_A_CORE_BSC, - GPC_M4_PU_PDN_FLG), - regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_MIPI), - GPC_PGC_SR(IMX7_PGC_MIPI)), - regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_PCIE), - GPC_PGC_SR(IMX7_PGC_PCIE)), - regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_USB_HSIC), - GPC_PGC_SR(IMX7_PGC_USB_HSIC)), -}; - -static const struct regmap_access_table imx7_access_table = { - .yes_ranges = imx7_yes_ranges, - .n_yes_ranges = ARRAY_SIZE(imx7_yes_ranges), -}; - -static const struct imx_pgc_regs imx7_pgc_regs = { - .map = GPC_PGC_CPU_MAPPING, - .pup = GPC_PU_PGC_SW_PUP_REQ, - .pdn = GPC_PU_PGC_SW_PDN_REQ, - .hsk = GPC_PU_PWRHSK, -}; - -static const struct imx_pgc_domain_data imx7_pgc_domain_data = { - .domains = imx7_pgc_domains, - .domains_num = ARRAY_SIZE(imx7_pgc_domains), - .reg_access_table = &imx7_access_table, - .pgc_regs = &imx7_pgc_regs, -}; - -static const struct imx_pgc_domain imx8m_pgc_domains[] = { - [IMX8M_POWER_DOMAIN_MIPI] = { - .genpd = { - .name = "mipi", - }, - .bits = { - .pxx = IMX8M_MIPI_SW_Pxx_REQ, - .map = IMX8M_MIPI_A53_DOMAIN, - }, - .pgc = BIT(IMX8M_PGC_MIPI), - }, - - [IMX8M_POWER_DOMAIN_PCIE1] = { - .genpd = { - .name = "pcie1", - }, - .bits = { - .pxx = IMX8M_PCIE1_SW_Pxx_REQ, - .map = IMX8M_PCIE1_A53_DOMAIN, - }, - .pgc = BIT(IMX8M_PGC_PCIE1), - }, - - [IMX8M_POWER_DOMAIN_USB_OTG1] = { - .genpd = { - .name = "usb-otg1", - }, - .bits = { - .pxx = IMX8M_OTG1_SW_Pxx_REQ, - .map = IMX8M_OTG1_A53_DOMAIN, - }, - .pgc = BIT(IMX8M_PGC_OTG1), - }, - - [IMX8M_POWER_DOMAIN_USB_OTG2] = { - .genpd = { - .name = "usb-otg2", - }, - .bits = { - .pxx = IMX8M_OTG2_SW_Pxx_REQ, - .map = IMX8M_OTG2_A53_DOMAIN, - }, - .pgc = BIT(IMX8M_PGC_OTG2), - }, - - [IMX8M_POWER_DOMAIN_DDR1] = { - .genpd = { - .name = "ddr1", - }, - .bits = { - .pxx = IMX8M_DDR1_SW_Pxx_REQ, - .map = IMX8M_DDR2_A53_DOMAIN, - }, - .pgc = BIT(IMX8M_PGC_DDR1), - }, - - [IMX8M_POWER_DOMAIN_GPU] = { - .genpd = { - .name = "gpu", - }, - .bits = { - .pxx = IMX8M_GPU_SW_Pxx_REQ, - .map = IMX8M_GPU_A53_DOMAIN, - .hskreq = IMX8M_GPU_HSK_PWRDNREQN, - .hskack = IMX8M_GPU_HSK_PWRDNACKN, - }, - .pgc = BIT(IMX8M_PGC_GPU), - }, - - [IMX8M_POWER_DOMAIN_VPU] = { - .genpd = { - .name = "vpu", - }, - .bits = { - .pxx = IMX8M_VPU_SW_Pxx_REQ, - .map = IMX8M_VPU_A53_DOMAIN, - .hskreq = IMX8M_VPU_HSK_PWRDNREQN, - .hskack = IMX8M_VPU_HSK_PWRDNACKN, - }, - .pgc = BIT(IMX8M_PGC_VPU), - .keep_clocks = true, - }, - - [IMX8M_POWER_DOMAIN_DISP] = { - .genpd = { - .name = "disp", - }, - .bits = { - .pxx = IMX8M_DISP_SW_Pxx_REQ, - .map = IMX8M_DISP_A53_DOMAIN, - .hskreq = IMX8M_DISP_HSK_PWRDNREQN, - .hskack = IMX8M_DISP_HSK_PWRDNACKN, - }, - .pgc = BIT(IMX8M_PGC_DISP), - }, - - [IMX8M_POWER_DOMAIN_MIPI_CSI1] = { - .genpd = { - .name = "mipi-csi1", - }, - .bits = { - .pxx = IMX8M_MIPI_CSI1_SW_Pxx_REQ, - .map = IMX8M_MIPI_CSI1_A53_DOMAIN, - }, - .pgc = BIT(IMX8M_PGC_MIPI_CSI1), - }, - - [IMX8M_POWER_DOMAIN_MIPI_CSI2] = { - .genpd = { - .name = "mipi-csi2", - }, - .bits = { - .pxx = IMX8M_MIPI_CSI2_SW_Pxx_REQ, - .map = IMX8M_MIPI_CSI2_A53_DOMAIN, - }, - .pgc = BIT(IMX8M_PGC_MIPI_CSI2), - }, - - [IMX8M_POWER_DOMAIN_PCIE2] = { - .genpd = { - .name = "pcie2", - }, - .bits = { - .pxx = IMX8M_PCIE2_SW_Pxx_REQ, - .map = IMX8M_PCIE2_A53_DOMAIN, - }, - .pgc = BIT(IMX8M_PGC_PCIE2), - }, -}; - -static const struct regmap_range imx8m_yes_ranges[] = { - regmap_reg_range(GPC_LPCR_A_CORE_BSC, - GPC_PU_PWRHSK), - regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI), - GPC_PGC_SR(IMX8M_PGC_MIPI)), - regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE1), - GPC_PGC_SR(IMX8M_PGC_PCIE1)), - regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG1), - GPC_PGC_SR(IMX8M_PGC_OTG1)), - regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG2), - GPC_PGC_SR(IMX8M_PGC_OTG2)), - regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DDR1), - GPC_PGC_SR(IMX8M_PGC_DDR1)), - regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_GPU), - GPC_PGC_SR(IMX8M_PGC_GPU)), - regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_VPU), - GPC_PGC_SR(IMX8M_PGC_VPU)), - regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DISP), - GPC_PGC_SR(IMX8M_PGC_DISP)), - regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI1), - GPC_PGC_SR(IMX8M_PGC_MIPI_CSI1)), - regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI2), - GPC_PGC_SR(IMX8M_PGC_MIPI_CSI2)), - regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE2), - GPC_PGC_SR(IMX8M_PGC_PCIE2)), -}; - -static const struct regmap_access_table imx8m_access_table = { - .yes_ranges = imx8m_yes_ranges, - .n_yes_ranges = ARRAY_SIZE(imx8m_yes_ranges), -}; - -static const struct imx_pgc_domain_data imx8m_pgc_domain_data = { - .domains = imx8m_pgc_domains, - .domains_num = ARRAY_SIZE(imx8m_pgc_domains), - .reg_access_table = &imx8m_access_table, - .pgc_regs = &imx7_pgc_regs, -}; - -static const struct imx_pgc_domain imx8mm_pgc_domains[] = { - [IMX8MM_POWER_DOMAIN_HSIOMIX] = { - .genpd = { - .name = "hsiomix", - }, - .bits = { - .pxx = 0, /* no power sequence control */ - .map = 0, /* no power sequence control */ - .hskreq = IMX8MM_HSIO_HSK_PWRDNREQN, - .hskack = IMX8MM_HSIO_HSK_PWRDNACKN, - }, - .keep_clocks = true, - }, - - [IMX8MM_POWER_DOMAIN_PCIE] = { - .genpd = { - .name = "pcie", - }, - .bits = { - .pxx = IMX8MM_PCIE_SW_Pxx_REQ, - .map = IMX8MM_PCIE_A53_DOMAIN, - }, - .pgc = BIT(IMX8MM_PGC_PCIE), - }, - - [IMX8MM_POWER_DOMAIN_OTG1] = { - .genpd = { - .name = "usb-otg1", - .flags = GENPD_FLAG_ACTIVE_WAKEUP, - }, - .bits = { - .pxx = IMX8MM_OTG1_SW_Pxx_REQ, - .map = IMX8MM_OTG1_A53_DOMAIN, - }, - .pgc = BIT(IMX8MM_PGC_OTG1), - }, - - [IMX8MM_POWER_DOMAIN_OTG2] = { - .genpd = { - .name = "usb-otg2", - .flags = GENPD_FLAG_ACTIVE_WAKEUP, - }, - .bits = { - .pxx = IMX8MM_OTG2_SW_Pxx_REQ, - .map = IMX8MM_OTG2_A53_DOMAIN, - }, - .pgc = BIT(IMX8MM_PGC_OTG2), - }, - - [IMX8MM_POWER_DOMAIN_GPUMIX] = { - .genpd = { - .name = "gpumix", - }, - .bits = { - .pxx = IMX8MM_GPUMIX_SW_Pxx_REQ, - .map = IMX8MM_GPUMIX_A53_DOMAIN, - .hskreq = IMX8MM_GPUMIX_HSK_PWRDNREQN, - .hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN, - }, - .pgc = BIT(IMX8MM_PGC_GPUMIX), - .keep_clocks = true, - }, - - [IMX8MM_POWER_DOMAIN_GPU] = { - .genpd = { - .name = "gpu", - }, - .bits = { - .pxx = IMX8MM_GPU_SW_Pxx_REQ, - .map = IMX8MM_GPU_A53_DOMAIN, - .hskreq = IMX8MM_GPU_HSK_PWRDNREQN, - .hskack = IMX8MM_GPU_HSK_PWRDNACKN, - }, - .pgc = BIT(IMX8MM_PGC_GPU2D) | BIT(IMX8MM_PGC_GPU3D), - }, - - [IMX8MM_POWER_DOMAIN_VPUMIX] = { - .genpd = { - .name = "vpumix", - }, - .bits = { - .pxx = IMX8MM_VPUMIX_SW_Pxx_REQ, - .map = IMX8MM_VPUMIX_A53_DOMAIN, - .hskreq = IMX8MM_VPUMIX_HSK_PWRDNREQN, - .hskack = IMX8MM_VPUMIX_HSK_PWRDNACKN, - }, - .pgc = BIT(IMX8MM_PGC_VPUMIX), - .keep_clocks = true, - }, - - [IMX8MM_POWER_DOMAIN_VPUG1] = { - .genpd = { - .name = "vpu-g1", - }, - .bits = { - .pxx = IMX8MM_VPUG1_SW_Pxx_REQ, - .map = IMX8MM_VPUG1_A53_DOMAIN, - }, - .pgc = BIT(IMX8MM_PGC_VPUG1), - }, - - [IMX8MM_POWER_DOMAIN_VPUG2] = { - .genpd = { - .name = "vpu-g2", - }, - .bits = { - .pxx = IMX8MM_VPUG2_SW_Pxx_REQ, - .map = IMX8MM_VPUG2_A53_DOMAIN, - }, - .pgc = BIT(IMX8MM_PGC_VPUG2), - }, - - [IMX8MM_POWER_DOMAIN_VPUH1] = { - .genpd = { - .name = "vpu-h1", - }, - .bits = { - .pxx = IMX8MM_VPUH1_SW_Pxx_REQ, - .map = IMX8MM_VPUH1_A53_DOMAIN, - }, - .pgc = BIT(IMX8MM_PGC_VPUH1), - .keep_clocks = true, - }, - - [IMX8MM_POWER_DOMAIN_DISPMIX] = { - .genpd = { - .name = "dispmix", - }, - .bits = { - .pxx = IMX8MM_DISPMIX_SW_Pxx_REQ, - .map = IMX8MM_DISPMIX_A53_DOMAIN, - .hskreq = IMX8MM_DISPMIX_HSK_PWRDNREQN, - .hskack = IMX8MM_DISPMIX_HSK_PWRDNACKN, - }, - .pgc = BIT(IMX8MM_PGC_DISPMIX), - .keep_clocks = true, - }, - - [IMX8MM_POWER_DOMAIN_MIPI] = { - .genpd = { - .name = "mipi", - }, - .bits = { - .pxx = IMX8MM_MIPI_SW_Pxx_REQ, - .map = IMX8MM_MIPI_A53_DOMAIN, - }, - .pgc = BIT(IMX8MM_PGC_MIPI), - }, -}; - -static const struct regmap_range imx8mm_yes_ranges[] = { - regmap_reg_range(GPC_LPCR_A_CORE_BSC, - GPC_PU_PWRHSK), - regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_MIPI), - GPC_PGC_SR(IMX8MM_PGC_MIPI)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_PCIE), - GPC_PGC_SR(IMX8MM_PGC_PCIE)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_OTG1), - GPC_PGC_SR(IMX8MM_PGC_OTG1)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_OTG2), - GPC_PGC_SR(IMX8MM_PGC_OTG2)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_DDR1), - GPC_PGC_SR(IMX8MM_PGC_DDR1)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPU2D), - GPC_PGC_SR(IMX8MM_PGC_GPU2D)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPUMIX), - GPC_PGC_SR(IMX8MM_PGC_GPUMIX)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUMIX), - GPC_PGC_SR(IMX8MM_PGC_VPUMIX)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPU3D), - GPC_PGC_SR(IMX8MM_PGC_GPU3D)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_DISPMIX), - GPC_PGC_SR(IMX8MM_PGC_DISPMIX)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUG1), - GPC_PGC_SR(IMX8MM_PGC_VPUG1)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUG2), - GPC_PGC_SR(IMX8MM_PGC_VPUG2)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUH1), - GPC_PGC_SR(IMX8MM_PGC_VPUH1)), -}; - -static const struct regmap_access_table imx8mm_access_table = { - .yes_ranges = imx8mm_yes_ranges, - .n_yes_ranges = ARRAY_SIZE(imx8mm_yes_ranges), -}; - -static const struct imx_pgc_domain_data imx8mm_pgc_domain_data = { - .domains = imx8mm_pgc_domains, - .domains_num = ARRAY_SIZE(imx8mm_pgc_domains), - .reg_access_table = &imx8mm_access_table, - .pgc_regs = &imx7_pgc_regs, -}; - -static const struct imx_pgc_domain imx8mp_pgc_domains[] = { - [IMX8MP_POWER_DOMAIN_MIPI_PHY1] = { - .genpd = { - .name = "mipi-phy1", - }, - .bits = { - .pxx = IMX8MP_MIPI_PHY1_SW_Pxx_REQ, - .map = IMX8MP_MIPI_PHY1_A53_DOMAIN, - }, - .pgc = BIT(IMX8MP_PGC_MIPI1), - }, - - [IMX8MP_POWER_DOMAIN_PCIE_PHY] = { - .genpd = { - .name = "pcie-phy1", - }, - .bits = { - .pxx = IMX8MP_PCIE_PHY_SW_Pxx_REQ, - .map = IMX8MP_PCIE_PHY_A53_DOMAIN, - }, - .pgc = BIT(IMX8MP_PGC_PCIE), - }, - - [IMX8MP_POWER_DOMAIN_USB1_PHY] = { - .genpd = { - .name = "usb-otg1", - }, - .bits = { - .pxx = IMX8MP_USB1_PHY_Pxx_REQ, - .map = IMX8MP_USB1_PHY_A53_DOMAIN, - }, - .pgc = BIT(IMX8MP_PGC_USB1), - }, - - [IMX8MP_POWER_DOMAIN_USB2_PHY] = { - .genpd = { - .name = "usb-otg2", - }, - .bits = { - .pxx = IMX8MP_USB2_PHY_Pxx_REQ, - .map = IMX8MP_USB2_PHY_A53_DOMAIN, - }, - .pgc = BIT(IMX8MP_PGC_USB2), - }, - - [IMX8MP_POWER_DOMAIN_MLMIX] = { - .genpd = { - .name = "mlmix", - }, - .bits = { - .pxx = IMX8MP_MLMIX_Pxx_REQ, - .map = IMX8MP_MLMIX_A53_DOMAIN, - .hskreq = IMX8MP_MLMIX_PWRDNREQN, - .hskack = IMX8MP_MLMIX_PWRDNACKN, - }, - .pgc = BIT(IMX8MP_PGC_MLMIX), - .keep_clocks = true, - }, - - [IMX8MP_POWER_DOMAIN_AUDIOMIX] = { - .genpd = { - .name = "audiomix", - }, - .bits = { - .pxx = IMX8MP_AUDIOMIX_Pxx_REQ, - .map = IMX8MP_AUDIOMIX_A53_DOMAIN, - .hskreq = IMX8MP_AUDIOMIX_PWRDNREQN, - .hskack = IMX8MP_AUDIOMIX_PWRDNACKN, - }, - .pgc = BIT(IMX8MP_PGC_AUDIOMIX), - .keep_clocks = true, - }, - - [IMX8MP_POWER_DOMAIN_GPU2D] = { - .genpd = { - .name = "gpu2d", - }, - .bits = { - .pxx = IMX8MP_GPU_2D_Pxx_REQ, - .map = IMX8MP_GPU2D_A53_DOMAIN, - }, - .pgc = BIT(IMX8MP_PGC_GPU2D), - }, - - [IMX8MP_POWER_DOMAIN_GPUMIX] = { - .genpd = { - .name = "gpumix", - }, - .bits = { - .pxx = IMX8MP_GPU_SHARE_LOGIC_Pxx_REQ, - .map = IMX8MP_GPUMIX_A53_DOMAIN, - .hskreq = IMX8MP_GPUMIX_PWRDNREQN, - .hskack = IMX8MP_GPUMIX_PWRDNACKN, - }, - .pgc = BIT(IMX8MP_PGC_GPUMIX), - .keep_clocks = true, - }, - - [IMX8MP_POWER_DOMAIN_VPUMIX] = { - .genpd = { - .name = "vpumix", - }, - .bits = { - .pxx = IMX8MP_VPU_MIX_SHARE_LOGIC_Pxx_REQ, - .map = IMX8MP_VPUMIX_A53_DOMAIN, - .hskreq = IMX8MP_VPUMIX_PWRDNREQN, - .hskack = IMX8MP_VPUMIX_PWRDNACKN, - }, - .pgc = BIT(IMX8MP_PGC_VPUMIX), - .keep_clocks = true, - }, - - [IMX8MP_POWER_DOMAIN_GPU3D] = { - .genpd = { - .name = "gpu3d", - }, - .bits = { - .pxx = IMX8MP_GPU_3D_Pxx_REQ, - .map = IMX8MP_GPU3D_A53_DOMAIN, - }, - .pgc = BIT(IMX8MP_PGC_GPU3D), - }, - - [IMX8MP_POWER_DOMAIN_MEDIAMIX] = { - .genpd = { - .name = "mediamix", - }, - .bits = { - .pxx = IMX8MP_MEDIMIX_Pxx_REQ, - .map = IMX8MP_MEDIAMIX_A53_DOMAIN, - .hskreq = IMX8MP_MEDIAMIX_PWRDNREQN, - .hskack = IMX8MP_MEDIAMIX_PWRDNACKN, - }, - .pgc = BIT(IMX8MP_PGC_MEDIAMIX), - .keep_clocks = true, - }, - - [IMX8MP_POWER_DOMAIN_VPU_G1] = { - .genpd = { - .name = "vpu-g1", - }, - .bits = { - .pxx = IMX8MP_VPU_G1_Pxx_REQ, - .map = IMX8MP_VPU_G1_A53_DOMAIN, - }, - .pgc = BIT(IMX8MP_PGC_VPU_G1), - }, - - [IMX8MP_POWER_DOMAIN_VPU_G2] = { - .genpd = { - .name = "vpu-g2", - }, - .bits = { - .pxx = IMX8MP_VPU_G2_Pxx_REQ, - .map = IMX8MP_VPU_G2_A53_DOMAIN - }, - .pgc = BIT(IMX8MP_PGC_VPU_G2), - }, - - [IMX8MP_POWER_DOMAIN_VPU_VC8000E] = { - .genpd = { - .name = "vpu-h1", - }, - .bits = { - .pxx = IMX8MP_VPU_VC8K_Pxx_REQ, - .map = IMX8MP_VPU_VC8000E_A53_DOMAIN, - }, - .pgc = BIT(IMX8MP_PGC_VPU_VC8000E), - }, - - [IMX8MP_POWER_DOMAIN_HDMIMIX] = { - .genpd = { - .name = "hdmimix", - }, - .bits = { - .pxx = IMX8MP_HDMIMIX_Pxx_REQ, - .map = IMX8MP_HDMIMIX_A53_DOMAIN, - .hskreq = IMX8MP_HDMIMIX_PWRDNREQN, - .hskack = IMX8MP_HDMIMIX_PWRDNACKN, - }, - .pgc = BIT(IMX8MP_PGC_HDMIMIX), - .keep_clocks = true, - }, - - [IMX8MP_POWER_DOMAIN_HDMI_PHY] = { - .genpd = { - .name = "hdmi-phy", - }, - .bits = { - .pxx = IMX8MP_HDMI_PHY_Pxx_REQ, - .map = IMX8MP_HDMI_PHY_A53_DOMAIN, - }, - .pgc = BIT(IMX8MP_PGC_HDMI), - }, - - [IMX8MP_POWER_DOMAIN_MIPI_PHY2] = { - .genpd = { - .name = "mipi-phy2", - }, - .bits = { - .pxx = IMX8MP_MIPI_PHY2_Pxx_REQ, - .map = IMX8MP_MIPI_PHY2_A53_DOMAIN, - }, - .pgc = BIT(IMX8MP_PGC_MIPI2), - }, - - [IMX8MP_POWER_DOMAIN_HSIOMIX] = { - .genpd = { - .name = "hsiomix", - }, - .bits = { - .pxx = IMX8MP_HSIOMIX_Pxx_REQ, - .map = IMX8MP_HSIOMIX_A53_DOMAIN, - .hskreq = IMX8MP_HSIOMIX_PWRDNREQN, - .hskack = IMX8MP_HSIOMIX_PWRDNACKN, - }, - .pgc = BIT(IMX8MP_PGC_HSIOMIX), - .keep_clocks = true, - }, - - [IMX8MP_POWER_DOMAIN_MEDIAMIX_ISPDWP] = { - .genpd = { - .name = "mediamix-isp-dwp", - }, - .bits = { - .pxx = IMX8MP_MEDIA_ISP_DWP_Pxx_REQ, - .map = IMX8MP_MEDIA_ISPDWP_A53_DOMAIN, - }, - .pgc = BIT(IMX8MP_PGC_MEDIA_ISP_DWP), - }, -}; - -static const struct regmap_range imx8mp_yes_ranges[] = { - regmap_reg_range(GPC_LPCR_A_CORE_BSC, - IMX8MP_GPC_PGC_CPU_MAPPING), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_NOC), - GPC_PGC_SR(IMX8MP_PGC_NOC)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MIPI1), - GPC_PGC_SR(IMX8MP_PGC_MIPI1)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_PCIE), - GPC_PGC_SR(IMX8MP_PGC_PCIE)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_USB1), - GPC_PGC_SR(IMX8MP_PGC_USB1)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_USB2), - GPC_PGC_SR(IMX8MP_PGC_USB2)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MLMIX), - GPC_PGC_SR(IMX8MP_PGC_MLMIX)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_AUDIOMIX), - GPC_PGC_SR(IMX8MP_PGC_AUDIOMIX)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_GPU2D), - GPC_PGC_SR(IMX8MP_PGC_GPU2D)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_GPUMIX), - GPC_PGC_SR(IMX8MP_PGC_GPUMIX)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPUMIX), - GPC_PGC_SR(IMX8MP_PGC_VPUMIX)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_GPU3D), - GPC_PGC_SR(IMX8MP_PGC_GPU3D)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MEDIAMIX), - GPC_PGC_SR(IMX8MP_PGC_MEDIAMIX)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPU_G1), - GPC_PGC_SR(IMX8MP_PGC_VPU_G1)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPU_G2), - GPC_PGC_SR(IMX8MP_PGC_VPU_G2)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPU_VC8000E), - GPC_PGC_SR(IMX8MP_PGC_VPU_VC8000E)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_HDMIMIX), - GPC_PGC_SR(IMX8MP_PGC_HDMIMIX)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_HDMI), - GPC_PGC_SR(IMX8MP_PGC_HDMI)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MIPI2), - GPC_PGC_SR(IMX8MP_PGC_MIPI2)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_HSIOMIX), - GPC_PGC_SR(IMX8MP_PGC_HSIOMIX)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MEDIA_ISP_DWP), - GPC_PGC_SR(IMX8MP_PGC_MEDIA_ISP_DWP)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_DDRMIX), - GPC_PGC_SR(IMX8MP_PGC_DDRMIX)), -}; - -static const struct regmap_access_table imx8mp_access_table = { - .yes_ranges = imx8mp_yes_ranges, - .n_yes_ranges = ARRAY_SIZE(imx8mp_yes_ranges), -}; - -static const struct imx_pgc_regs imx8mp_pgc_regs = { - .map = IMX8MP_GPC_PGC_CPU_MAPPING, - .pup = IMX8MP_GPC_PU_PGC_SW_PUP_REQ, - .pdn = IMX8MP_GPC_PU_PGC_SW_PDN_REQ, - .hsk = IMX8MP_GPC_PU_PWRHSK, -}; -static const struct imx_pgc_domain_data imx8mp_pgc_domain_data = { - .domains = imx8mp_pgc_domains, - .domains_num = ARRAY_SIZE(imx8mp_pgc_domains), - .reg_access_table = &imx8mp_access_table, - .pgc_regs = &imx8mp_pgc_regs, -}; - -static const struct imx_pgc_domain imx8mn_pgc_domains[] = { - [IMX8MN_POWER_DOMAIN_HSIOMIX] = { - .genpd = { - .name = "hsiomix", - }, - .bits = { - .pxx = 0, /* no power sequence control */ - .map = 0, /* no power sequence control */ - .hskreq = IMX8MN_HSIO_HSK_PWRDNREQN, - .hskack = IMX8MN_HSIO_HSK_PWRDNACKN, - }, - .keep_clocks = true, - }, - - [IMX8MN_POWER_DOMAIN_OTG1] = { - .genpd = { - .name = "usb-otg1", - .flags = GENPD_FLAG_ACTIVE_WAKEUP, - }, - .bits = { - .pxx = IMX8MN_OTG1_SW_Pxx_REQ, - .map = IMX8MN_OTG1_A53_DOMAIN, - }, - .pgc = BIT(IMX8MN_PGC_OTG1), - }, - - [IMX8MN_POWER_DOMAIN_GPUMIX] = { - .genpd = { - .name = "gpumix", - }, - .bits = { - .pxx = IMX8MN_GPUMIX_SW_Pxx_REQ, - .map = IMX8MN_GPUMIX_A53_DOMAIN, - .hskreq = IMX8MN_GPUMIX_HSK_PWRDNREQN, - .hskack = IMX8MN_GPUMIX_HSK_PWRDNACKN, - }, - .pgc = BIT(IMX8MN_PGC_GPUMIX), - .keep_clocks = true, - }, - - [IMX8MN_POWER_DOMAIN_DISPMIX] = { - .genpd = { - .name = "dispmix", - }, - .bits = { - .pxx = IMX8MN_DISPMIX_SW_Pxx_REQ, - .map = IMX8MN_DISPMIX_A53_DOMAIN, - .hskreq = IMX8MN_DISPMIX_HSK_PWRDNREQN, - .hskack = IMX8MN_DISPMIX_HSK_PWRDNACKN, - }, - .pgc = BIT(IMX8MN_PGC_DISPMIX), - .keep_clocks = true, - }, - - [IMX8MN_POWER_DOMAIN_MIPI] = { - .genpd = { - .name = "mipi", - }, - .bits = { - .pxx = IMX8MN_MIPI_SW_Pxx_REQ, - .map = IMX8MN_MIPI_A53_DOMAIN, - }, - .pgc = BIT(IMX8MN_PGC_MIPI), - }, -}; - -static const struct regmap_range imx8mn_yes_ranges[] = { - regmap_reg_range(GPC_LPCR_A_CORE_BSC, - GPC_PU_PWRHSK), - regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_MIPI), - GPC_PGC_SR(IMX8MN_PGC_MIPI)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_OTG1), - GPC_PGC_SR(IMX8MN_PGC_OTG1)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_DDR1), - GPC_PGC_SR(IMX8MN_PGC_DDR1)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_GPUMIX), - GPC_PGC_SR(IMX8MN_PGC_GPUMIX)), - regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_DISPMIX), - GPC_PGC_SR(IMX8MN_PGC_DISPMIX)), -}; - -static const struct regmap_access_table imx8mn_access_table = { - .yes_ranges = imx8mn_yes_ranges, - .n_yes_ranges = ARRAY_SIZE(imx8mn_yes_ranges), -}; - -static const struct imx_pgc_domain_data imx8mn_pgc_domain_data = { - .domains = imx8mn_pgc_domains, - .domains_num = ARRAY_SIZE(imx8mn_pgc_domains), - .reg_access_table = &imx8mn_access_table, - .pgc_regs = &imx7_pgc_regs, -}; - -static int imx_pgc_domain_probe(struct platform_device *pdev) -{ - struct imx_pgc_domain *domain = pdev->dev.platform_data; - int ret; - - domain->dev = &pdev->dev; - - domain->regulator = devm_regulator_get_optional(domain->dev, "power"); - if (IS_ERR(domain->regulator)) { - if (PTR_ERR(domain->regulator) != -ENODEV) - return dev_err_probe(domain->dev, PTR_ERR(domain->regulator), - "Failed to get domain's regulator\n"); - } else if (domain->voltage) { - regulator_set_voltage(domain->regulator, - domain->voltage, domain->voltage); - } - - domain->num_clks = devm_clk_bulk_get_all(domain->dev, &domain->clks); - if (domain->num_clks < 0) - return dev_err_probe(domain->dev, domain->num_clks, - "Failed to get domain's clocks\n"); - - domain->reset = devm_reset_control_array_get_optional_exclusive(domain->dev); - if (IS_ERR(domain->reset)) - return dev_err_probe(domain->dev, PTR_ERR(domain->reset), - "Failed to get domain's resets\n"); - - pm_runtime_enable(domain->dev); - - if (domain->bits.map) - regmap_update_bits(domain->regmap, domain->regs->map, - domain->bits.map, domain->bits.map); - - ret = pm_genpd_init(&domain->genpd, NULL, true); - if (ret) { - dev_err(domain->dev, "Failed to init power domain\n"); - goto out_domain_unmap; - } - - if (IS_ENABLED(CONFIG_LOCKDEP) && - of_property_read_bool(domain->dev->of_node, "power-domains")) - lockdep_set_subclass(&domain->genpd.mlock, 1); - - ret = of_genpd_add_provider_simple(domain->dev->of_node, - &domain->genpd); - if (ret) { - dev_err(domain->dev, "Failed to add genpd provider\n"); - goto out_genpd_remove; - } - - return 0; - -out_genpd_remove: - pm_genpd_remove(&domain->genpd); -out_domain_unmap: - if (domain->bits.map) - regmap_update_bits(domain->regmap, domain->regs->map, - domain->bits.map, 0); - pm_runtime_disable(domain->dev); - - return ret; -} - -static int imx_pgc_domain_remove(struct platform_device *pdev) -{ - struct imx_pgc_domain *domain = pdev->dev.platform_data; - - of_genpd_del_provider(domain->dev->of_node); - pm_genpd_remove(&domain->genpd); - - if (domain->bits.map) - regmap_update_bits(domain->regmap, domain->regs->map, - domain->bits.map, 0); - - pm_runtime_disable(domain->dev); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int imx_pgc_domain_suspend(struct device *dev) -{ - int ret; - - /* - * This may look strange, but is done so the generic PM_SLEEP code - * can power down our domain and more importantly power it up again - * after resume, without tripping over our usage of runtime PM to - * power up/down the nested domains. - */ - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - pm_runtime_put_noidle(dev); - return ret; - } - - return 0; -} - -static int imx_pgc_domain_resume(struct device *dev) -{ - return pm_runtime_put(dev); -} -#endif - -static const struct dev_pm_ops imx_pgc_domain_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(imx_pgc_domain_suspend, imx_pgc_domain_resume) -}; - -static const struct platform_device_id imx_pgc_domain_id[] = { - { "imx-pgc-domain", }, - { }, -}; - -static struct platform_driver imx_pgc_domain_driver = { - .driver = { - .name = "imx-pgc", - .pm = &imx_pgc_domain_pm_ops, - }, - .probe = imx_pgc_domain_probe, - .remove = imx_pgc_domain_remove, - .id_table = imx_pgc_domain_id, -}; -builtin_platform_driver(imx_pgc_domain_driver) - -static int imx_gpcv2_probe(struct platform_device *pdev) -{ - const struct imx_pgc_domain_data *domain_data = - of_device_get_match_data(&pdev->dev); - - struct regmap_config regmap_config = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .rd_table = domain_data->reg_access_table, - .wr_table = domain_data->reg_access_table, - .max_register = SZ_4K, - }; - struct device *dev = &pdev->dev; - struct device_node *pgc_np, *np; - struct regmap *regmap; - void __iomem *base; - int ret; - - pgc_np = of_get_child_by_name(dev->of_node, "pgc"); - if (!pgc_np) { - dev_err(dev, "No power domains specified in DT\n"); - return -EINVAL; - } - - base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(base)) - return PTR_ERR(base); - - regmap = devm_regmap_init_mmio(dev, base, ®map_config); - if (IS_ERR(regmap)) { - ret = PTR_ERR(regmap); - dev_err(dev, "failed to init regmap (%d)\n", ret); - return ret; - } - - for_each_child_of_node(pgc_np, np) { - struct platform_device *pd_pdev; - struct imx_pgc_domain *domain; - u32 domain_index; - - if (!of_device_is_available(np)) - continue; - - ret = of_property_read_u32(np, "reg", &domain_index); - if (ret) { - dev_err(dev, "Failed to read 'reg' property\n"); - of_node_put(np); - return ret; - } - - if (domain_index >= domain_data->domains_num) { - dev_warn(dev, - "Domain index %d is out of bounds\n", - domain_index); - continue; - } - - pd_pdev = platform_device_alloc("imx-pgc-domain", - domain_index); - if (!pd_pdev) { - dev_err(dev, "Failed to allocate platform device\n"); - of_node_put(np); - return -ENOMEM; - } - - ret = platform_device_add_data(pd_pdev, - &domain_data->domains[domain_index], - sizeof(domain_data->domains[domain_index])); - if (ret) { - platform_device_put(pd_pdev); - of_node_put(np); - return ret; - } - - domain = pd_pdev->dev.platform_data; - domain->regmap = regmap; - domain->regs = domain_data->pgc_regs; - - domain->genpd.power_on = imx_pgc_power_up; - domain->genpd.power_off = imx_pgc_power_down; - - pd_pdev->dev.parent = dev; - device_set_node(&pd_pdev->dev, of_fwnode_handle(np)); - - ret = platform_device_add(pd_pdev); - if (ret) { - platform_device_put(pd_pdev); - of_node_put(np); - return ret; - } - } - - return 0; -} - -static const struct of_device_id imx_gpcv2_dt_ids[] = { - { .compatible = "fsl,imx7d-gpc", .data = &imx7_pgc_domain_data, }, - { .compatible = "fsl,imx8mm-gpc", .data = &imx8mm_pgc_domain_data, }, - { .compatible = "fsl,imx8mn-gpc", .data = &imx8mn_pgc_domain_data, }, - { .compatible = "fsl,imx8mp-gpc", .data = &imx8mp_pgc_domain_data, }, - { .compatible = "fsl,imx8mq-gpc", .data = &imx8m_pgc_domain_data, }, - { } -}; - -static struct platform_driver imx_gpc_driver = { - .driver = { - .name = "imx-gpcv2", - .of_match_table = imx_gpcv2_dt_ids, - }, - .probe = imx_gpcv2_probe, -}; -builtin_platform_driver(imx_gpc_driver) diff --git a/drivers/soc/imx/imx8m-blk-ctrl.c b/drivers/soc/imx/imx8m-blk-ctrl.c deleted file mode 100644 index afbca0d48c14..000000000000 --- a/drivers/soc/imx/imx8m-blk-ctrl.c +++ /dev/null @@ -1,898 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ - -/* - * Copyright 2021 Pengutronix, Lucas Stach <kernel@pengutronix.de> - */ - -#include <linux/bitfield.h> -#include <linux/device.h> -#include <linux/interconnect.h> -#include <linux/module.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <linux/pm_runtime.h> -#include <linux/regmap.h> -#include <linux/clk.h> - -#include <dt-bindings/power/imx8mm-power.h> -#include <dt-bindings/power/imx8mn-power.h> -#include <dt-bindings/power/imx8mp-power.h> -#include <dt-bindings/power/imx8mq-power.h> - -#define BLK_SFT_RSTN 0x0 -#define BLK_CLK_EN 0x4 -#define BLK_MIPI_RESET_DIV 0x8 /* Mini/Nano/Plus DISPLAY_BLK_CTRL only */ - -struct imx8m_blk_ctrl_domain; - -struct imx8m_blk_ctrl { - struct device *dev; - struct notifier_block power_nb; - struct device *bus_power_dev; - struct regmap *regmap; - struct imx8m_blk_ctrl_domain *domains; - struct genpd_onecell_data onecell_data; -}; - -struct imx8m_blk_ctrl_domain_data { - const char *name; - const char * const *clk_names; - const char * const *path_names; - const char *gpc_name; - int num_clks; - int num_paths; - u32 rst_mask; - u32 clk_mask; - - /* - * i.MX8M Mini, Nano and Plus have a third DISPLAY_BLK_CTRL register - * which is used to control the reset for the MIPI Phy. - * Since it's only present in certain circumstances, - * an if-statement should be used before setting and clearing this - * register. - */ - u32 mipi_phy_rst_mask; -}; - -#define DOMAIN_MAX_CLKS 4 -#define DOMAIN_MAX_PATHS 4 - -struct imx8m_blk_ctrl_domain { - struct generic_pm_domain genpd; - const struct imx8m_blk_ctrl_domain_data *data; - struct clk_bulk_data clks[DOMAIN_MAX_CLKS]; - struct icc_bulk_data paths[DOMAIN_MAX_PATHS]; - struct device *power_dev; - struct imx8m_blk_ctrl *bc; - int num_paths; -}; - -struct imx8m_blk_ctrl_data { - int max_reg; - notifier_fn_t power_notifier_fn; - const struct imx8m_blk_ctrl_domain_data *domains; - int num_domains; -}; - -static inline struct imx8m_blk_ctrl_domain * -to_imx8m_blk_ctrl_domain(struct generic_pm_domain *genpd) -{ - return container_of(genpd, struct imx8m_blk_ctrl_domain, genpd); -} - -static int imx8m_blk_ctrl_power_on(struct generic_pm_domain *genpd) -{ - struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd); - const struct imx8m_blk_ctrl_domain_data *data = domain->data; - struct imx8m_blk_ctrl *bc = domain->bc; - int ret; - - /* make sure bus domain is awake */ - ret = pm_runtime_get_sync(bc->bus_power_dev); - if (ret < 0) { - pm_runtime_put_noidle(bc->bus_power_dev); - dev_err(bc->dev, "failed to power up bus domain\n"); - return ret; - } - - /* put devices into reset */ - regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask); - if (data->mipi_phy_rst_mask) - regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask); - - /* enable upstream and blk-ctrl clocks to allow reset to propagate */ - ret = clk_bulk_prepare_enable(data->num_clks, domain->clks); - if (ret) { - dev_err(bc->dev, "failed to enable clocks\n"); - goto bus_put; - } - regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask); - - /* power up upstream GPC domain */ - ret = pm_runtime_get_sync(domain->power_dev); - if (ret < 0) { - dev_err(bc->dev, "failed to power up peripheral domain\n"); - goto clk_disable; - } - - /* wait for reset to propagate */ - udelay(5); - - /* release reset */ - regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask); - if (data->mipi_phy_rst_mask) - regmap_set_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask); - - ret = icc_bulk_set_bw(domain->num_paths, domain->paths); - if (ret) - dev_err(bc->dev, "failed to set icc bw\n"); - - /* disable upstream clocks */ - clk_bulk_disable_unprepare(data->num_clks, domain->clks); - - return 0; - -clk_disable: - clk_bulk_disable_unprepare(data->num_clks, domain->clks); -bus_put: - pm_runtime_put(bc->bus_power_dev); - - return ret; -} - -static int imx8m_blk_ctrl_power_off(struct generic_pm_domain *genpd) -{ - struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd); - const struct imx8m_blk_ctrl_domain_data *data = domain->data; - struct imx8m_blk_ctrl *bc = domain->bc; - - /* put devices into reset and disable clocks */ - if (data->mipi_phy_rst_mask) - regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask); - - regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask); - regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask); - - /* power down upstream GPC domain */ - pm_runtime_put(domain->power_dev); - - /* allow bus domain to suspend */ - pm_runtime_put(bc->bus_power_dev); - - return 0; -} - -static struct lock_class_key blk_ctrl_genpd_lock_class; - -static int imx8m_blk_ctrl_probe(struct platform_device *pdev) -{ - const struct imx8m_blk_ctrl_data *bc_data; - struct device *dev = &pdev->dev; - struct imx8m_blk_ctrl *bc; - void __iomem *base; - int i, ret; - - struct regmap_config regmap_config = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - }; - - bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL); - if (!bc) - return -ENOMEM; - - bc->dev = dev; - - bc_data = of_device_get_match_data(dev); - - base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(base)) - return PTR_ERR(base); - - regmap_config.max_register = bc_data->max_reg; - bc->regmap = devm_regmap_init_mmio(dev, base, ®map_config); - if (IS_ERR(bc->regmap)) - return dev_err_probe(dev, PTR_ERR(bc->regmap), - "failed to init regmap\n"); - - bc->domains = devm_kcalloc(dev, bc_data->num_domains, - sizeof(struct imx8m_blk_ctrl_domain), - GFP_KERNEL); - if (!bc->domains) - return -ENOMEM; - - bc->onecell_data.num_domains = bc_data->num_domains; - bc->onecell_data.domains = - devm_kcalloc(dev, bc_data->num_domains, - sizeof(struct generic_pm_domain *), GFP_KERNEL); - if (!bc->onecell_data.domains) - return -ENOMEM; - - bc->bus_power_dev = dev_pm_domain_attach_by_name(dev, "bus"); - if (IS_ERR(bc->bus_power_dev)) { - if (PTR_ERR(bc->bus_power_dev) == -ENODEV) - return dev_err_probe(dev, -EPROBE_DEFER, - "failed to attach power domain \"bus\"\n"); - else - return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev), - "failed to attach power domain \"bus\"\n"); - } - - for (i = 0; i < bc_data->num_domains; i++) { - const struct imx8m_blk_ctrl_domain_data *data = &bc_data->domains[i]; - struct imx8m_blk_ctrl_domain *domain = &bc->domains[i]; - int j; - - domain->data = data; - domain->num_paths = data->num_paths; - - for (j = 0; j < data->num_clks; j++) - domain->clks[j].id = data->clk_names[j]; - - for (j = 0; j < data->num_paths; j++) { - domain->paths[j].name = data->path_names[j]; - /* Fake value for now, just let ICC could configure NoC mode/priority */ - domain->paths[j].avg_bw = 1; - domain->paths[j].peak_bw = 1; - } - - ret = devm_of_icc_bulk_get(dev, data->num_paths, domain->paths); - if (ret) { - if (ret != -EPROBE_DEFER) { - dev_warn_once(dev, "Could not get interconnect paths, NoC will stay unconfigured!\n"); - domain->num_paths = 0; - } else { - dev_err_probe(dev, ret, "failed to get noc entries\n"); - goto cleanup_pds; - } - } - - ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks); - if (ret) { - dev_err_probe(dev, ret, "failed to get clock\n"); - goto cleanup_pds; - } - - domain->power_dev = - dev_pm_domain_attach_by_name(dev, data->gpc_name); - if (IS_ERR(domain->power_dev)) { - dev_err_probe(dev, PTR_ERR(domain->power_dev), - "failed to attach power domain \"%s\"\n", - data->gpc_name); - ret = PTR_ERR(domain->power_dev); - goto cleanup_pds; - } - - domain->genpd.name = data->name; - domain->genpd.power_on = imx8m_blk_ctrl_power_on; - domain->genpd.power_off = imx8m_blk_ctrl_power_off; - domain->bc = bc; - - ret = pm_genpd_init(&domain->genpd, NULL, true); - if (ret) { - dev_err_probe(dev, ret, - "failed to init power domain \"%s\"\n", - data->gpc_name); - dev_pm_domain_detach(domain->power_dev, true); - goto cleanup_pds; - } - - /* - * We use runtime PM to trigger power on/off of the upstream GPC - * domain, as a strict hierarchical parent/child power domain - * setup doesn't allow us to meet the sequencing requirements. - * This means we have nested locking of genpd locks, without the - * nesting being visible at the genpd level, so we need a - * separate lock class to make lockdep aware of the fact that - * this are separate domain locks that can be nested without a - * self-deadlock. - */ - lockdep_set_class(&domain->genpd.mlock, - &blk_ctrl_genpd_lock_class); - - bc->onecell_data.domains[i] = &domain->genpd; - } - - ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data); - if (ret) { - dev_err_probe(dev, ret, "failed to add power domain provider\n"); - goto cleanup_pds; - } - - bc->power_nb.notifier_call = bc_data->power_notifier_fn; - ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb); - if (ret) { - dev_err_probe(dev, ret, "failed to add power notifier\n"); - goto cleanup_provider; - } - - dev_set_drvdata(dev, bc); - - ret = devm_of_platform_populate(dev); - if (ret) - goto cleanup_provider; - - return 0; - -cleanup_provider: - of_genpd_del_provider(dev->of_node); -cleanup_pds: - for (i--; i >= 0; i--) { - pm_genpd_remove(&bc->domains[i].genpd); - dev_pm_domain_detach(bc->domains[i].power_dev, true); - } - - dev_pm_domain_detach(bc->bus_power_dev, true); - - return ret; -} - -static int imx8m_blk_ctrl_remove(struct platform_device *pdev) -{ - struct imx8m_blk_ctrl *bc = dev_get_drvdata(&pdev->dev); - int i; - - of_genpd_del_provider(pdev->dev.of_node); - - for (i = 0; bc->onecell_data.num_domains; i++) { - struct imx8m_blk_ctrl_domain *domain = &bc->domains[i]; - - pm_genpd_remove(&domain->genpd); - dev_pm_domain_detach(domain->power_dev, true); - } - - dev_pm_genpd_remove_notifier(bc->bus_power_dev); - - dev_pm_domain_detach(bc->bus_power_dev, true); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int imx8m_blk_ctrl_suspend(struct device *dev) -{ - struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev); - int ret, i; - - /* - * This may look strange, but is done so the generic PM_SLEEP code - * can power down our domains and more importantly power them up again - * after resume, without tripping over our usage of runtime PM to - * control the upstream GPC domains. Things happen in the right order - * in the system suspend/resume paths due to the device parent/child - * hierarchy. - */ - ret = pm_runtime_get_sync(bc->bus_power_dev); - if (ret < 0) { - pm_runtime_put_noidle(bc->bus_power_dev); - return ret; - } - - for (i = 0; i < bc->onecell_data.num_domains; i++) { - struct imx8m_blk_ctrl_domain *domain = &bc->domains[i]; - - ret = pm_runtime_get_sync(domain->power_dev); - if (ret < 0) { - pm_runtime_put_noidle(domain->power_dev); - goto out_fail; - } - } - - return 0; - -out_fail: - for (i--; i >= 0; i--) - pm_runtime_put(bc->domains[i].power_dev); - - pm_runtime_put(bc->bus_power_dev); - - return ret; -} - -static int imx8m_blk_ctrl_resume(struct device *dev) -{ - struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev); - int i; - - for (i = 0; i < bc->onecell_data.num_domains; i++) - pm_runtime_put(bc->domains[i].power_dev); - - pm_runtime_put(bc->bus_power_dev); - - return 0; -} -#endif - -static const struct dev_pm_ops imx8m_blk_ctrl_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(imx8m_blk_ctrl_suspend, imx8m_blk_ctrl_resume) -}; - -static int imx8mm_vpu_power_notifier(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl, - power_nb); - - if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF) - return NOTIFY_OK; - - /* - * The ADB in the VPUMIX domain has no separate reset and clock - * enable bits, but is ungated together with the VPU clocks. To - * allow the handshake with the GPC to progress we put the VPUs - * in reset and ungate the clocks. - */ - regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1) | BIT(2)); - regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1) | BIT(2)); - - if (action == GENPD_NOTIFY_ON) { - /* - * On power up we have no software backchannel to the GPC to - * wait for the ADB handshake to happen, so we just delay for a - * bit. On power down the GPC driver waits for the handshake. - */ - udelay(5); - - /* set "fuse" bits to enable the VPUs */ - regmap_set_bits(bc->regmap, 0x8, 0xffffffff); - regmap_set_bits(bc->regmap, 0xc, 0xffffffff); - regmap_set_bits(bc->regmap, 0x10, 0xffffffff); - regmap_set_bits(bc->regmap, 0x14, 0xffffffff); - } - - return NOTIFY_OK; -} - -static const struct imx8m_blk_ctrl_domain_data imx8mm_vpu_blk_ctl_domain_data[] = { - [IMX8MM_VPUBLK_PD_G1] = { - .name = "vpublk-g1", - .clk_names = (const char *[]){ "g1", }, - .num_clks = 1, - .gpc_name = "g1", - .rst_mask = BIT(1), - .clk_mask = BIT(1), - }, - [IMX8MM_VPUBLK_PD_G2] = { - .name = "vpublk-g2", - .clk_names = (const char *[]){ "g2", }, - .num_clks = 1, - .gpc_name = "g2", - .rst_mask = BIT(0), - .clk_mask = BIT(0), - }, - [IMX8MM_VPUBLK_PD_H1] = { - .name = "vpublk-h1", - .clk_names = (const char *[]){ "h1", }, - .num_clks = 1, - .gpc_name = "h1", - .rst_mask = BIT(2), - .clk_mask = BIT(2), - }, -}; - -static const struct imx8m_blk_ctrl_data imx8mm_vpu_blk_ctl_dev_data = { - .max_reg = 0x18, - .power_notifier_fn = imx8mm_vpu_power_notifier, - .domains = imx8mm_vpu_blk_ctl_domain_data, - .num_domains = ARRAY_SIZE(imx8mm_vpu_blk_ctl_domain_data), -}; - -static const struct imx8m_blk_ctrl_domain_data imx8mp_vpu_blk_ctl_domain_data[] = { - [IMX8MP_VPUBLK_PD_G1] = { - .name = "vpublk-g1", - .clk_names = (const char *[]){ "g1", }, - .num_clks = 1, - .gpc_name = "g1", - .rst_mask = BIT(1), - .clk_mask = BIT(1), - .path_names = (const char *[]){"g1"}, - .num_paths = 1, - }, - [IMX8MP_VPUBLK_PD_G2] = { - .name = "vpublk-g2", - .clk_names = (const char *[]){ "g2", }, - .num_clks = 1, - .gpc_name = "g2", - .rst_mask = BIT(0), - .clk_mask = BIT(0), - .path_names = (const char *[]){"g2"}, - .num_paths = 1, - }, - [IMX8MP_VPUBLK_PD_VC8000E] = { - .name = "vpublk-vc8000e", - .clk_names = (const char *[]){ "vc8000e", }, - .num_clks = 1, - .gpc_name = "vc8000e", - .rst_mask = BIT(2), - .clk_mask = BIT(2), - .path_names = (const char *[]){"vc8000e"}, - .num_paths = 1, - }, -}; - -static const struct imx8m_blk_ctrl_data imx8mp_vpu_blk_ctl_dev_data = { - .max_reg = 0x18, - .power_notifier_fn = imx8mm_vpu_power_notifier, - .domains = imx8mp_vpu_blk_ctl_domain_data, - .num_domains = ARRAY_SIZE(imx8mp_vpu_blk_ctl_domain_data), -}; - -static int imx8mm_disp_power_notifier(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl, - power_nb); - - if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF) - return NOTIFY_OK; - - /* Enable bus clock and deassert bus reset */ - regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(12)); - regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(6)); - - /* - * On power up we have no software backchannel to the GPC to - * wait for the ADB handshake to happen, so we just delay for a - * bit. On power down the GPC driver waits for the handshake. - */ - if (action == GENPD_NOTIFY_ON) - udelay(5); - - - return NOTIFY_OK; -} - -static const struct imx8m_blk_ctrl_domain_data imx8mm_disp_blk_ctl_domain_data[] = { - [IMX8MM_DISPBLK_PD_CSI_BRIDGE] = { - .name = "dispblk-csi-bridge", - .clk_names = (const char *[]){ "csi-bridge-axi", "csi-bridge-apb", - "csi-bridge-core", }, - .num_clks = 3, - .gpc_name = "csi-bridge", - .rst_mask = BIT(0) | BIT(1) | BIT(2), - .clk_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5), - }, - [IMX8MM_DISPBLK_PD_LCDIF] = { - .name = "dispblk-lcdif", - .clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", }, - .num_clks = 3, - .gpc_name = "lcdif", - .clk_mask = BIT(6) | BIT(7), - }, - [IMX8MM_DISPBLK_PD_MIPI_DSI] = { - .name = "dispblk-mipi-dsi", - .clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", }, - .num_clks = 2, - .gpc_name = "mipi-dsi", - .rst_mask = BIT(5), - .clk_mask = BIT(8) | BIT(9), - .mipi_phy_rst_mask = BIT(17), - }, - [IMX8MM_DISPBLK_PD_MIPI_CSI] = { - .name = "dispblk-mipi-csi", - .clk_names = (const char *[]){ "csi-aclk", "csi-pclk" }, - .num_clks = 2, - .gpc_name = "mipi-csi", - .rst_mask = BIT(3) | BIT(4), - .clk_mask = BIT(10) | BIT(11), - .mipi_phy_rst_mask = BIT(16), - }, -}; - -static const struct imx8m_blk_ctrl_data imx8mm_disp_blk_ctl_dev_data = { - .max_reg = 0x2c, - .power_notifier_fn = imx8mm_disp_power_notifier, - .domains = imx8mm_disp_blk_ctl_domain_data, - .num_domains = ARRAY_SIZE(imx8mm_disp_blk_ctl_domain_data), -}; - - -static int imx8mn_disp_power_notifier(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl, - power_nb); - - if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF) - return NOTIFY_OK; - - /* Enable bus clock and deassert bus reset */ - regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(8)); - regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(8)); - - /* - * On power up we have no software backchannel to the GPC to - * wait for the ADB handshake to happen, so we just delay for a - * bit. On power down the GPC driver waits for the handshake. - */ - if (action == GENPD_NOTIFY_ON) - udelay(5); - - - return NOTIFY_OK; -} - -static const struct imx8m_blk_ctrl_domain_data imx8mn_disp_blk_ctl_domain_data[] = { - [IMX8MN_DISPBLK_PD_MIPI_DSI] = { - .name = "dispblk-mipi-dsi", - .clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", }, - .num_clks = 2, - .gpc_name = "mipi-dsi", - .rst_mask = BIT(0) | BIT(1), - .clk_mask = BIT(0) | BIT(1), - .mipi_phy_rst_mask = BIT(17), - }, - [IMX8MN_DISPBLK_PD_MIPI_CSI] = { - .name = "dispblk-mipi-csi", - .clk_names = (const char *[]){ "csi-aclk", "csi-pclk" }, - .num_clks = 2, - .gpc_name = "mipi-csi", - .rst_mask = BIT(2) | BIT(3), - .clk_mask = BIT(2) | BIT(3), - .mipi_phy_rst_mask = BIT(16), - }, - [IMX8MN_DISPBLK_PD_LCDIF] = { - .name = "dispblk-lcdif", - .clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", }, - .num_clks = 3, - .gpc_name = "lcdif", - .rst_mask = BIT(4) | BIT(5), - .clk_mask = BIT(4) | BIT(5), - }, - [IMX8MN_DISPBLK_PD_ISI] = { - .name = "dispblk-isi", - .clk_names = (const char *[]){ "disp_axi", "disp_apb", "disp_axi_root", - "disp_apb_root"}, - .num_clks = 4, - .gpc_name = "isi", - .rst_mask = BIT(6) | BIT(7), - .clk_mask = BIT(6) | BIT(7), - }, -}; - -static const struct imx8m_blk_ctrl_data imx8mn_disp_blk_ctl_dev_data = { - .max_reg = 0x84, - .power_notifier_fn = imx8mn_disp_power_notifier, - .domains = imx8mn_disp_blk_ctl_domain_data, - .num_domains = ARRAY_SIZE(imx8mn_disp_blk_ctl_domain_data), -}; - -#define LCDIF_ARCACHE_CTRL 0x4c -#define LCDIF_1_RD_HURRY GENMASK(15, 13) -#define LCDIF_0_RD_HURRY GENMASK(12, 10) - -static int imx8mp_media_power_notifier(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl, - power_nb); - - if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF) - return NOTIFY_OK; - - /* Enable bus clock and deassert bus reset */ - regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(8)); - regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(8)); - - if (action == GENPD_NOTIFY_ON) { - /* - * On power up we have no software backchannel to the GPC to - * wait for the ADB handshake to happen, so we just delay for a - * bit. On power down the GPC driver waits for the handshake. - */ - udelay(5); - - /* - * Set panic read hurry level for both LCDIF interfaces to - * maximum priority to minimize chances of display FIFO - * underflow. - */ - regmap_set_bits(bc->regmap, LCDIF_ARCACHE_CTRL, - FIELD_PREP(LCDIF_1_RD_HURRY, 7) | - FIELD_PREP(LCDIF_0_RD_HURRY, 7)); - } - - return NOTIFY_OK; -} - -/* - * From i.MX 8M Plus Applications Processor Reference Manual, Rev. 1, - * section 13.2.2, 13.2.3 - * isp-ahb and dwe are not in Figure 13-5. Media BLK_CTRL Clocks - */ -static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[] = { - [IMX8MP_MEDIABLK_PD_MIPI_DSI_1] = { - .name = "mediablk-mipi-dsi-1", - .clk_names = (const char *[]){ "apb", "phy", }, - .num_clks = 2, - .gpc_name = "mipi-dsi1", - .rst_mask = BIT(0) | BIT(1), - .clk_mask = BIT(0) | BIT(1), - .mipi_phy_rst_mask = BIT(17), - }, - [IMX8MP_MEDIABLK_PD_MIPI_CSI2_1] = { - .name = "mediablk-mipi-csi2-1", - .clk_names = (const char *[]){ "apb", "cam1" }, - .num_clks = 2, - .gpc_name = "mipi-csi1", - .rst_mask = BIT(2) | BIT(3), - .clk_mask = BIT(2) | BIT(3), - .mipi_phy_rst_mask = BIT(16), - }, - [IMX8MP_MEDIABLK_PD_LCDIF_1] = { - .name = "mediablk-lcdif-1", - .clk_names = (const char *[]){ "disp1", "apb", "axi", }, - .num_clks = 3, - .gpc_name = "lcdif1", - .rst_mask = BIT(4) | BIT(5) | BIT(23), - .clk_mask = BIT(4) | BIT(5) | BIT(23), - .path_names = (const char *[]){"lcdif-rd", "lcdif-wr"}, - .num_paths = 2, - }, - [IMX8MP_MEDIABLK_PD_ISI] = { - .name = "mediablk-isi", - .clk_names = (const char *[]){ "axi", "apb" }, - .num_clks = 2, - .gpc_name = "isi", - .rst_mask = BIT(6) | BIT(7), - .clk_mask = BIT(6) | BIT(7), - .path_names = (const char *[]){"isi0", "isi1", "isi2"}, - .num_paths = 3, - }, - [IMX8MP_MEDIABLK_PD_MIPI_CSI2_2] = { - .name = "mediablk-mipi-csi2-2", - .clk_names = (const char *[]){ "apb", "cam2" }, - .num_clks = 2, - .gpc_name = "mipi-csi2", - .rst_mask = BIT(9) | BIT(10), - .clk_mask = BIT(9) | BIT(10), - .mipi_phy_rst_mask = BIT(30), - }, - [IMX8MP_MEDIABLK_PD_LCDIF_2] = { - .name = "mediablk-lcdif-2", - .clk_names = (const char *[]){ "disp2", "apb", "axi", }, - .num_clks = 3, - .gpc_name = "lcdif2", - .rst_mask = BIT(11) | BIT(12) | BIT(24), - .clk_mask = BIT(11) | BIT(12) | BIT(24), - .path_names = (const char *[]){"lcdif-rd", "lcdif-wr"}, - .num_paths = 2, - }, - [IMX8MP_MEDIABLK_PD_ISP] = { - .name = "mediablk-isp", - .clk_names = (const char *[]){ "isp", "axi", "apb" }, - .num_clks = 3, - .gpc_name = "isp", - .rst_mask = BIT(16) | BIT(17) | BIT(18), - .clk_mask = BIT(16) | BIT(17) | BIT(18), - .path_names = (const char *[]){"isp0", "isp1"}, - .num_paths = 2, - }, - [IMX8MP_MEDIABLK_PD_DWE] = { - .name = "mediablk-dwe", - .clk_names = (const char *[]){ "axi", "apb" }, - .num_clks = 2, - .gpc_name = "dwe", - .rst_mask = BIT(19) | BIT(20) | BIT(21), - .clk_mask = BIT(19) | BIT(20) | BIT(21), - .path_names = (const char *[]){"dwe"}, - .num_paths = 1, - }, - [IMX8MP_MEDIABLK_PD_MIPI_DSI_2] = { - .name = "mediablk-mipi-dsi-2", - .clk_names = (const char *[]){ "phy", }, - .num_clks = 1, - .gpc_name = "mipi-dsi2", - .rst_mask = BIT(22), - .clk_mask = BIT(22), - .mipi_phy_rst_mask = BIT(29), - }, -}; - -static const struct imx8m_blk_ctrl_data imx8mp_media_blk_ctl_dev_data = { - .max_reg = 0x138, - .power_notifier_fn = imx8mp_media_power_notifier, - .domains = imx8mp_media_blk_ctl_domain_data, - .num_domains = ARRAY_SIZE(imx8mp_media_blk_ctl_domain_data), -}; - -static int imx8mq_vpu_power_notifier(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl, - power_nb); - - if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF) - return NOTIFY_OK; - - /* - * The ADB in the VPUMIX domain has no separate reset and clock - * enable bits, but is ungated and reset together with the VPUs. The - * reset and clock enable inputs to the ADB is a logical OR of the - * VPU bits. In order to set the G2 fuse bits, the G2 clock must - * also be enabled. - */ - regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1)); - regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1)); - - if (action == GENPD_NOTIFY_ON) { - /* - * On power up we have no software backchannel to the GPC to - * wait for the ADB handshake to happen, so we just delay for a - * bit. On power down the GPC driver waits for the handshake. - */ - udelay(5); - - /* set "fuse" bits to enable the VPUs */ - regmap_set_bits(bc->regmap, 0x8, 0xffffffff); - regmap_set_bits(bc->regmap, 0xc, 0xffffffff); - regmap_set_bits(bc->regmap, 0x10, 0xffffffff); - } - - return NOTIFY_OK; -} - -static const struct imx8m_blk_ctrl_domain_data imx8mq_vpu_blk_ctl_domain_data[] = { - [IMX8MQ_VPUBLK_PD_G1] = { - .name = "vpublk-g1", - .clk_names = (const char *[]){ "g1", }, - .num_clks = 1, - .gpc_name = "g1", - .rst_mask = BIT(1), - .clk_mask = BIT(1), - }, - [IMX8MQ_VPUBLK_PD_G2] = { - .name = "vpublk-g2", - .clk_names = (const char *[]){ "g2", }, - .num_clks = 1, - .gpc_name = "g2", - .rst_mask = BIT(0), - .clk_mask = BIT(0), - }, -}; - -static const struct imx8m_blk_ctrl_data imx8mq_vpu_blk_ctl_dev_data = { - .max_reg = 0x14, - .power_notifier_fn = imx8mq_vpu_power_notifier, - .domains = imx8mq_vpu_blk_ctl_domain_data, - .num_domains = ARRAY_SIZE(imx8mq_vpu_blk_ctl_domain_data), -}; - -static const struct of_device_id imx8m_blk_ctrl_of_match[] = { - { - .compatible = "fsl,imx8mm-vpu-blk-ctrl", - .data = &imx8mm_vpu_blk_ctl_dev_data - }, { - .compatible = "fsl,imx8mm-disp-blk-ctrl", - .data = &imx8mm_disp_blk_ctl_dev_data - }, { - .compatible = "fsl,imx8mn-disp-blk-ctrl", - .data = &imx8mn_disp_blk_ctl_dev_data - }, { - .compatible = "fsl,imx8mp-media-blk-ctrl", - .data = &imx8mp_media_blk_ctl_dev_data - }, { - .compatible = "fsl,imx8mq-vpu-blk-ctrl", - .data = &imx8mq_vpu_blk_ctl_dev_data - }, { - .compatible = "fsl,imx8mp-vpu-blk-ctrl", - .data = &imx8mp_vpu_blk_ctl_dev_data - }, { - /* Sentinel */ - } -}; -MODULE_DEVICE_TABLE(of, imx8m_blk_ctrl_of_match); - -static struct platform_driver imx8m_blk_ctrl_driver = { - .probe = imx8m_blk_ctrl_probe, - .remove = imx8m_blk_ctrl_remove, - .driver = { - .name = "imx8m-blk-ctrl", - .pm = &imx8m_blk_ctrl_pm_ops, - .of_match_table = imx8m_blk_ctrl_of_match, - }, -}; -module_platform_driver(imx8m_blk_ctrl_driver); -MODULE_LICENSE("GPL"); diff --git a/drivers/soc/imx/imx8mp-blk-ctrl.c b/drivers/soc/imx/imx8mp-blk-ctrl.c deleted file mode 100644 index 1c1fcab4979a..000000000000 --- a/drivers/soc/imx/imx8mp-blk-ctrl.c +++ /dev/null @@ -1,867 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ - -/* - * Copyright 2022 Pengutronix, Lucas Stach <kernel@pengutronix.de> - */ - -#include <linux/bitfield.h> -#include <linux/clk.h> -#include <linux/clk-provider.h> -#include <linux/device.h> -#include <linux/interconnect.h> -#include <linux/module.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <linux/pm_runtime.h> -#include <linux/regmap.h> - -#include <dt-bindings/power/imx8mp-power.h> - -#define GPR_REG0 0x0 -#define PCIE_CLOCK_MODULE_EN BIT(0) -#define USB_CLOCK_MODULE_EN BIT(1) -#define PCIE_PHY_APB_RST BIT(4) -#define PCIE_PHY_INIT_RST BIT(5) -#define GPR_REG1 0x4 -#define PLL_LOCK BIT(13) -#define GPR_REG2 0x8 -#define P_PLL_MASK GENMASK(5, 0) -#define M_PLL_MASK GENMASK(15, 6) -#define S_PLL_MASK GENMASK(18, 16) -#define GPR_REG3 0xc -#define PLL_CKE BIT(17) -#define PLL_RST BIT(31) - -struct imx8mp_blk_ctrl_domain; - -struct imx8mp_blk_ctrl { - struct device *dev; - struct notifier_block power_nb; - struct device *bus_power_dev; - struct regmap *regmap; - struct imx8mp_blk_ctrl_domain *domains; - struct genpd_onecell_data onecell_data; - void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain); - void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain); -}; - -struct imx8mp_blk_ctrl_domain_data { - const char *name; - const char * const *clk_names; - int num_clks; - const char * const *path_names; - int num_paths; - const char *gpc_name; -}; - -#define DOMAIN_MAX_CLKS 2 -#define DOMAIN_MAX_PATHS 3 - -struct imx8mp_blk_ctrl_domain { - struct generic_pm_domain genpd; - const struct imx8mp_blk_ctrl_domain_data *data; - struct clk_bulk_data clks[DOMAIN_MAX_CLKS]; - struct icc_bulk_data paths[DOMAIN_MAX_PATHS]; - struct device *power_dev; - struct imx8mp_blk_ctrl *bc; - int num_paths; - int id; -}; - -struct imx8mp_blk_ctrl_data { - int max_reg; - int (*probe) (struct imx8mp_blk_ctrl *bc); - notifier_fn_t power_notifier_fn; - void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain); - void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain); - const struct imx8mp_blk_ctrl_domain_data *domains; - int num_domains; -}; - -static inline struct imx8mp_blk_ctrl_domain * -to_imx8mp_blk_ctrl_domain(struct generic_pm_domain *genpd) -{ - return container_of(genpd, struct imx8mp_blk_ctrl_domain, genpd); -} - -struct clk_hsio_pll { - struct clk_hw hw; - struct regmap *regmap; -}; - -static inline struct clk_hsio_pll *to_clk_hsio_pll(struct clk_hw *hw) -{ - return container_of(hw, struct clk_hsio_pll, hw); -} - -static int clk_hsio_pll_prepare(struct clk_hw *hw) -{ - struct clk_hsio_pll *clk = to_clk_hsio_pll(hw); - u32 val; - - /* set the PLL configuration */ - regmap_update_bits(clk->regmap, GPR_REG2, - P_PLL_MASK | M_PLL_MASK | S_PLL_MASK, - FIELD_PREP(P_PLL_MASK, 12) | - FIELD_PREP(M_PLL_MASK, 800) | - FIELD_PREP(S_PLL_MASK, 4)); - - /* de-assert PLL reset */ - regmap_update_bits(clk->regmap, GPR_REG3, PLL_RST, PLL_RST); - - /* enable PLL */ - regmap_update_bits(clk->regmap, GPR_REG3, PLL_CKE, PLL_CKE); - - return regmap_read_poll_timeout(clk->regmap, GPR_REG1, val, - val & PLL_LOCK, 10, 100); -} - -static void clk_hsio_pll_unprepare(struct clk_hw *hw) -{ - struct clk_hsio_pll *clk = to_clk_hsio_pll(hw); - - regmap_update_bits(clk->regmap, GPR_REG3, PLL_RST | PLL_CKE, 0); -} - -static int clk_hsio_pll_is_prepared(struct clk_hw *hw) -{ - struct clk_hsio_pll *clk = to_clk_hsio_pll(hw); - - return regmap_test_bits(clk->regmap, GPR_REG1, PLL_LOCK); -} - -static unsigned long clk_hsio_pll_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return 100000000; -} - -static const struct clk_ops clk_hsio_pll_ops = { - .prepare = clk_hsio_pll_prepare, - .unprepare = clk_hsio_pll_unprepare, - .is_prepared = clk_hsio_pll_is_prepared, - .recalc_rate = clk_hsio_pll_recalc_rate, -}; - -static int imx8mp_hsio_blk_ctrl_probe(struct imx8mp_blk_ctrl *bc) -{ - struct clk_hsio_pll *clk_hsio_pll; - struct clk_hw *hw; - struct clk_init_data init = {}; - int ret; - - clk_hsio_pll = devm_kzalloc(bc->dev, sizeof(*clk_hsio_pll), GFP_KERNEL); - if (!clk_hsio_pll) - return -ENOMEM; - - init.name = "hsio_pll"; - init.ops = &clk_hsio_pll_ops; - init.parent_names = (const char *[]){"osc_24m"}; - init.num_parents = 1; - - clk_hsio_pll->regmap = bc->regmap; - clk_hsio_pll->hw.init = &init; - - hw = &clk_hsio_pll->hw; - ret = devm_clk_hw_register(bc->bus_power_dev, hw); - if (ret) - return ret; - - return devm_of_clk_add_hw_provider(bc->dev, of_clk_hw_simple_get, hw); -} - -static void imx8mp_hsio_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc, - struct imx8mp_blk_ctrl_domain *domain) -{ - switch (domain->id) { - case IMX8MP_HSIOBLK_PD_USB: - regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN); - break; - case IMX8MP_HSIOBLK_PD_PCIE: - regmap_set_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN); - break; - case IMX8MP_HSIOBLK_PD_PCIE_PHY: - regmap_set_bits(bc->regmap, GPR_REG0, - PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST); - break; - default: - break; - } -} - -static void imx8mp_hsio_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc, - struct imx8mp_blk_ctrl_domain *domain) -{ - switch (domain->id) { - case IMX8MP_HSIOBLK_PD_USB: - regmap_clear_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN); - break; - case IMX8MP_HSIOBLK_PD_PCIE: - regmap_clear_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN); - break; - case IMX8MP_HSIOBLK_PD_PCIE_PHY: - regmap_clear_bits(bc->regmap, GPR_REG0, - PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST); - break; - default: - break; - } -} - -static int imx8mp_hsio_power_notifier(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct imx8mp_blk_ctrl *bc = container_of(nb, struct imx8mp_blk_ctrl, - power_nb); - struct clk_bulk_data *usb_clk = bc->domains[IMX8MP_HSIOBLK_PD_USB].clks; - int num_clks = bc->domains[IMX8MP_HSIOBLK_PD_USB].data->num_clks; - int ret; - - switch (action) { - case GENPD_NOTIFY_ON: - /* - * enable USB clock for a moment for the power-on ADB handshake - * to proceed - */ - ret = clk_bulk_prepare_enable(num_clks, usb_clk); - if (ret) - return NOTIFY_BAD; - regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN); - - udelay(5); - - regmap_clear_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN); - clk_bulk_disable_unprepare(num_clks, usb_clk); - break; - case GENPD_NOTIFY_PRE_OFF: - /* enable USB clock for the power-down ADB handshake to work */ - ret = clk_bulk_prepare_enable(num_clks, usb_clk); - if (ret) - return NOTIFY_BAD; - - regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN); - break; - case GENPD_NOTIFY_OFF: - clk_bulk_disable_unprepare(num_clks, usb_clk); - break; - default: - break; - } - - return NOTIFY_OK; -} - -static const struct imx8mp_blk_ctrl_domain_data imx8mp_hsio_domain_data[] = { - [IMX8MP_HSIOBLK_PD_USB] = { - .name = "hsioblk-usb", - .clk_names = (const char *[]){ "usb" }, - .num_clks = 1, - .gpc_name = "usb", - .path_names = (const char *[]){"usb1", "usb2"}, - .num_paths = 2, - }, - [IMX8MP_HSIOBLK_PD_USB_PHY1] = { - .name = "hsioblk-usb-phy1", - .gpc_name = "usb-phy1", - }, - [IMX8MP_HSIOBLK_PD_USB_PHY2] = { - .name = "hsioblk-usb-phy2", - .gpc_name = "usb-phy2", - }, - [IMX8MP_HSIOBLK_PD_PCIE] = { - .name = "hsioblk-pcie", - .clk_names = (const char *[]){ "pcie" }, - .num_clks = 1, - .gpc_name = "pcie", - .path_names = (const char *[]){"noc-pcie", "pcie"}, - .num_paths = 2, - }, - [IMX8MP_HSIOBLK_PD_PCIE_PHY] = { - .name = "hsioblk-pcie-phy", - .gpc_name = "pcie-phy", - }, -}; - -static const struct imx8mp_blk_ctrl_data imx8mp_hsio_blk_ctl_dev_data = { - .max_reg = 0x24, - .probe = imx8mp_hsio_blk_ctrl_probe, - .power_on = imx8mp_hsio_blk_ctrl_power_on, - .power_off = imx8mp_hsio_blk_ctrl_power_off, - .power_notifier_fn = imx8mp_hsio_power_notifier, - .domains = imx8mp_hsio_domain_data, - .num_domains = ARRAY_SIZE(imx8mp_hsio_domain_data), -}; - -#define HDMI_RTX_RESET_CTL0 0x20 -#define HDMI_RTX_CLK_CTL0 0x40 -#define HDMI_RTX_CLK_CTL1 0x50 -#define HDMI_RTX_CLK_CTL2 0x60 -#define HDMI_RTX_CLK_CTL3 0x70 -#define HDMI_RTX_CLK_CTL4 0x80 -#define HDMI_TX_CONTROL0 0x200 -#define HDMI_LCDIF_NOC_HURRY_MASK GENMASK(14, 12) - -static void imx8mp_hdmi_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc, - struct imx8mp_blk_ctrl_domain *domain) -{ - switch (domain->id) { - case IMX8MP_HDMIBLK_PD_IRQSTEER: - regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(9)); - regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(16)); - break; - case IMX8MP_HDMIBLK_PD_LCDIF: - regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, - BIT(16) | BIT(17) | BIT(18) | - BIT(19) | BIT(20)); - regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11)); - regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, - BIT(4) | BIT(5) | BIT(6)); - regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, - FIELD_PREP(HDMI_LCDIF_NOC_HURRY_MASK, 7)); - break; - case IMX8MP_HDMIBLK_PD_PAI: - regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(17)); - regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(18)); - break; - case IMX8MP_HDMIBLK_PD_PVI: - regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(28)); - regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(22)); - break; - case IMX8MP_HDMIBLK_PD_TRNG: - regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(27) | BIT(30)); - regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(20)); - break; - case IMX8MP_HDMIBLK_PD_HDMI_TX: - regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, - BIT(2) | BIT(4) | BIT(5)); - regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, - BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) | - BIT(18) | BIT(19) | BIT(20) | BIT(21)); - regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, - BIT(7) | BIT(10) | BIT(11)); - regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1)); - break; - case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY: - regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7)); - regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24)); - regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12)); - regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3)); - break; - case IMX8MP_HDMIBLK_PD_HDCP: - regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(11)); - break; - case IMX8MP_HDMIBLK_PD_HRV: - regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(3) | BIT(4) | BIT(5)); - regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(15)); - break; - default: - break; - } -} - -static void imx8mp_hdmi_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc, - struct imx8mp_blk_ctrl_domain *domain) -{ - switch (domain->id) { - case IMX8MP_HDMIBLK_PD_IRQSTEER: - regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(9)); - regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(16)); - break; - case IMX8MP_HDMIBLK_PD_LCDIF: - regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, - BIT(4) | BIT(5) | BIT(6)); - regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11)); - regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, - BIT(16) | BIT(17) | BIT(18) | - BIT(19) | BIT(20)); - break; - case IMX8MP_HDMIBLK_PD_PAI: - regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(18)); - regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(17)); - break; - case IMX8MP_HDMIBLK_PD_PVI: - regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(22)); - regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(28)); - break; - case IMX8MP_HDMIBLK_PD_TRNG: - regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(20)); - regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(27) | BIT(30)); - break; - case IMX8MP_HDMIBLK_PD_HDMI_TX: - regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1)); - regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, - BIT(7) | BIT(10) | BIT(11)); - regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, - BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) | - BIT(18) | BIT(19) | BIT(20) | BIT(21)); - regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, - BIT(2) | BIT(4) | BIT(5)); - break; - case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY: - regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3)); - regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12)); - regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7)); - regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24)); - break; - case IMX8MP_HDMIBLK_PD_HDCP: - regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(11)); - break; - case IMX8MP_HDMIBLK_PD_HRV: - regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(15)); - regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(3) | BIT(4) | BIT(5)); - break; - default: - break; - } -} - -static int imx8mp_hdmi_power_notifier(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct imx8mp_blk_ctrl *bc = container_of(nb, struct imx8mp_blk_ctrl, - power_nb); - - if (action != GENPD_NOTIFY_ON) - return NOTIFY_OK; - - /* - * Contrary to other blk-ctrls the reset and clock don't clear when the - * power domain is powered down. To ensure the proper reset pulsing, - * first clear them all to asserted state, then enable the bus clocks - * and then release the ADB reset. - */ - regmap_write(bc->regmap, HDMI_RTX_RESET_CTL0, 0x0); - regmap_write(bc->regmap, HDMI_RTX_CLK_CTL0, 0x0); - regmap_write(bc->regmap, HDMI_RTX_CLK_CTL1, 0x0); - regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, - BIT(0) | BIT(1) | BIT(10)); - regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(0)); - - /* - * On power up we have no software backchannel to the GPC to - * wait for the ADB handshake to happen, so we just delay for a - * bit. On power down the GPC driver waits for the handshake. - */ - udelay(5); - - return NOTIFY_OK; -} - -static const struct imx8mp_blk_ctrl_domain_data imx8mp_hdmi_domain_data[] = { - [IMX8MP_HDMIBLK_PD_IRQSTEER] = { - .name = "hdmiblk-irqsteer", - .clk_names = (const char *[]){ "apb" }, - .num_clks = 1, - .gpc_name = "irqsteer", - }, - [IMX8MP_HDMIBLK_PD_LCDIF] = { - .name = "hdmiblk-lcdif", - .clk_names = (const char *[]){ "axi", "apb" }, - .num_clks = 2, - .gpc_name = "lcdif", - .path_names = (const char *[]){"lcdif-hdmi"}, - .num_paths = 1, - }, - [IMX8MP_HDMIBLK_PD_PAI] = { - .name = "hdmiblk-pai", - .clk_names = (const char *[]){ "apb" }, - .num_clks = 1, - .gpc_name = "pai", - }, - [IMX8MP_HDMIBLK_PD_PVI] = { - .name = "hdmiblk-pvi", - .clk_names = (const char *[]){ "apb" }, - .num_clks = 1, - .gpc_name = "pvi", - }, - [IMX8MP_HDMIBLK_PD_TRNG] = { - .name = "hdmiblk-trng", - .clk_names = (const char *[]){ "apb" }, - .num_clks = 1, - .gpc_name = "trng", - }, - [IMX8MP_HDMIBLK_PD_HDMI_TX] = { - .name = "hdmiblk-hdmi-tx", - .clk_names = (const char *[]){ "apb", "ref_266m" }, - .num_clks = 2, - .gpc_name = "hdmi-tx", - }, - [IMX8MP_HDMIBLK_PD_HDMI_TX_PHY] = { - .name = "hdmiblk-hdmi-tx-phy", - .clk_names = (const char *[]){ "apb", "ref_24m" }, - .num_clks = 2, - .gpc_name = "hdmi-tx-phy", - }, - [IMX8MP_HDMIBLK_PD_HRV] = { - .name = "hdmiblk-hrv", - .clk_names = (const char *[]){ "axi", "apb" }, - .num_clks = 2, - .gpc_name = "hrv", - .path_names = (const char *[]){"hrv"}, - .num_paths = 1, - }, - [IMX8MP_HDMIBLK_PD_HDCP] = { - .name = "hdmiblk-hdcp", - .clk_names = (const char *[]){ "axi", "apb" }, - .num_clks = 2, - .gpc_name = "hdcp", - .path_names = (const char *[]){"hdcp"}, - .num_paths = 1, - }, -}; - -static const struct imx8mp_blk_ctrl_data imx8mp_hdmi_blk_ctl_dev_data = { - .max_reg = 0x23c, - .power_on = imx8mp_hdmi_blk_ctrl_power_on, - .power_off = imx8mp_hdmi_blk_ctrl_power_off, - .power_notifier_fn = imx8mp_hdmi_power_notifier, - .domains = imx8mp_hdmi_domain_data, - .num_domains = ARRAY_SIZE(imx8mp_hdmi_domain_data), -}; - -static int imx8mp_blk_ctrl_power_on(struct generic_pm_domain *genpd) -{ - struct imx8mp_blk_ctrl_domain *domain = to_imx8mp_blk_ctrl_domain(genpd); - const struct imx8mp_blk_ctrl_domain_data *data = domain->data; - struct imx8mp_blk_ctrl *bc = domain->bc; - int ret; - - /* make sure bus domain is awake */ - ret = pm_runtime_resume_and_get(bc->bus_power_dev); - if (ret < 0) { - dev_err(bc->dev, "failed to power up bus domain\n"); - return ret; - } - - /* enable upstream clocks */ - ret = clk_bulk_prepare_enable(data->num_clks, domain->clks); - if (ret) { - dev_err(bc->dev, "failed to enable clocks\n"); - goto bus_put; - } - - /* domain specific blk-ctrl manipulation */ - bc->power_on(bc, domain); - - /* power up upstream GPC domain */ - ret = pm_runtime_resume_and_get(domain->power_dev); - if (ret < 0) { - dev_err(bc->dev, "failed to power up peripheral domain\n"); - goto clk_disable; - } - - ret = icc_bulk_set_bw(domain->num_paths, domain->paths); - if (ret) - dev_err(bc->dev, "failed to set icc bw\n"); - - clk_bulk_disable_unprepare(data->num_clks, domain->clks); - - return 0; - -clk_disable: - clk_bulk_disable_unprepare(data->num_clks, domain->clks); -bus_put: - pm_runtime_put(bc->bus_power_dev); - - return ret; -} - -static int imx8mp_blk_ctrl_power_off(struct generic_pm_domain *genpd) -{ - struct imx8mp_blk_ctrl_domain *domain = to_imx8mp_blk_ctrl_domain(genpd); - const struct imx8mp_blk_ctrl_domain_data *data = domain->data; - struct imx8mp_blk_ctrl *bc = domain->bc; - int ret; - - ret = clk_bulk_prepare_enable(data->num_clks, domain->clks); - if (ret) { - dev_err(bc->dev, "failed to enable clocks\n"); - return ret; - } - - /* domain specific blk-ctrl manipulation */ - bc->power_off(bc, domain); - - clk_bulk_disable_unprepare(data->num_clks, domain->clks); - - /* power down upstream GPC domain */ - pm_runtime_put(domain->power_dev); - - /* allow bus domain to suspend */ - pm_runtime_put(bc->bus_power_dev); - - return 0; -} - -static struct lock_class_key blk_ctrl_genpd_lock_class; - -static int imx8mp_blk_ctrl_probe(struct platform_device *pdev) -{ - const struct imx8mp_blk_ctrl_data *bc_data; - struct device *dev = &pdev->dev; - struct imx8mp_blk_ctrl *bc; - void __iomem *base; - int num_domains, i, ret; - - struct regmap_config regmap_config = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - }; - - bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL); - if (!bc) - return -ENOMEM; - - bc->dev = dev; - - bc_data = of_device_get_match_data(dev); - num_domains = bc_data->num_domains; - - base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(base)) - return PTR_ERR(base); - - regmap_config.max_register = bc_data->max_reg; - bc->regmap = devm_regmap_init_mmio(dev, base, ®map_config); - if (IS_ERR(bc->regmap)) - return dev_err_probe(dev, PTR_ERR(bc->regmap), - "failed to init regmap\n"); - - bc->domains = devm_kcalloc(dev, num_domains, - sizeof(struct imx8mp_blk_ctrl_domain), - GFP_KERNEL); - if (!bc->domains) - return -ENOMEM; - - bc->onecell_data.num_domains = num_domains; - bc->onecell_data.domains = - devm_kcalloc(dev, num_domains, - sizeof(struct generic_pm_domain *), GFP_KERNEL); - if (!bc->onecell_data.domains) - return -ENOMEM; - - bc->bus_power_dev = dev_pm_domain_attach_by_name(dev, "bus"); - if (IS_ERR(bc->bus_power_dev)) - return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev), - "failed to attach bus power domain\n"); - - bc->power_off = bc_data->power_off; - bc->power_on = bc_data->power_on; - - for (i = 0; i < num_domains; i++) { - const struct imx8mp_blk_ctrl_domain_data *data = &bc_data->domains[i]; - struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i]; - int j; - - domain->data = data; - domain->num_paths = data->num_paths; - - for (j = 0; j < data->num_clks; j++) - domain->clks[j].id = data->clk_names[j]; - - for (j = 0; j < data->num_paths; j++) { - domain->paths[j].name = data->path_names[j]; - /* Fake value for now, just let ICC could configure NoC mode/priority */ - domain->paths[j].avg_bw = 1; - domain->paths[j].peak_bw = 1; - } - - ret = devm_of_icc_bulk_get(dev, data->num_paths, domain->paths); - if (ret) { - if (ret != -EPROBE_DEFER) { - dev_warn_once(dev, "Could not get interconnect paths, NoC will stay unconfigured!\n"); - domain->num_paths = 0; - } else { - dev_err_probe(dev, ret, "failed to get noc entries\n"); - goto cleanup_pds; - } - } - - ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks); - if (ret) { - dev_err_probe(dev, ret, "failed to get clock\n"); - goto cleanup_pds; - } - - domain->power_dev = - dev_pm_domain_attach_by_name(dev, data->gpc_name); - if (IS_ERR(domain->power_dev)) { - dev_err_probe(dev, PTR_ERR(domain->power_dev), - "failed to attach power domain %s\n", - data->gpc_name); - ret = PTR_ERR(domain->power_dev); - goto cleanup_pds; - } - - domain->genpd.name = data->name; - domain->genpd.power_on = imx8mp_blk_ctrl_power_on; - domain->genpd.power_off = imx8mp_blk_ctrl_power_off; - domain->bc = bc; - domain->id = i; - - ret = pm_genpd_init(&domain->genpd, NULL, true); - if (ret) { - dev_err_probe(dev, ret, "failed to init power domain\n"); - dev_pm_domain_detach(domain->power_dev, true); - goto cleanup_pds; - } - - /* - * We use runtime PM to trigger power on/off of the upstream GPC - * domain, as a strict hierarchical parent/child power domain - * setup doesn't allow us to meet the sequencing requirements. - * This means we have nested locking of genpd locks, without the - * nesting being visible at the genpd level, so we need a - * separate lock class to make lockdep aware of the fact that - * this are separate domain locks that can be nested without a - * self-deadlock. - */ - lockdep_set_class(&domain->genpd.mlock, - &blk_ctrl_genpd_lock_class); - - bc->onecell_data.domains[i] = &domain->genpd; - } - - ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data); - if (ret) { - dev_err_probe(dev, ret, "failed to add power domain provider\n"); - goto cleanup_pds; - } - - bc->power_nb.notifier_call = bc_data->power_notifier_fn; - ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb); - if (ret) { - dev_err_probe(dev, ret, "failed to add power notifier\n"); - goto cleanup_provider; - } - - if (bc_data->probe) { - ret = bc_data->probe(bc); - if (ret) - goto cleanup_provider; - } - - dev_set_drvdata(dev, bc); - - return 0; - -cleanup_provider: - of_genpd_del_provider(dev->of_node); -cleanup_pds: - for (i--; i >= 0; i--) { - pm_genpd_remove(&bc->domains[i].genpd); - dev_pm_domain_detach(bc->domains[i].power_dev, true); - } - - dev_pm_domain_detach(bc->bus_power_dev, true); - - return ret; -} - -static int imx8mp_blk_ctrl_remove(struct platform_device *pdev) -{ - struct imx8mp_blk_ctrl *bc = dev_get_drvdata(&pdev->dev); - int i; - - of_genpd_del_provider(pdev->dev.of_node); - - for (i = 0; bc->onecell_data.num_domains; i++) { - struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i]; - - pm_genpd_remove(&domain->genpd); - dev_pm_domain_detach(domain->power_dev, true); - } - - dev_pm_genpd_remove_notifier(bc->bus_power_dev); - - dev_pm_domain_detach(bc->bus_power_dev, true); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int imx8mp_blk_ctrl_suspend(struct device *dev) -{ - struct imx8mp_blk_ctrl *bc = dev_get_drvdata(dev); - int ret, i; - - /* - * This may look strange, but is done so the generic PM_SLEEP code - * can power down our domains and more importantly power them up again - * after resume, without tripping over our usage of runtime PM to - * control the upstream GPC domains. Things happen in the right order - * in the system suspend/resume paths due to the device parent/child - * hierarchy. - */ - ret = pm_runtime_get_sync(bc->bus_power_dev); - if (ret < 0) { - pm_runtime_put_noidle(bc->bus_power_dev); - return ret; - } - - for (i = 0; i < bc->onecell_data.num_domains; i++) { - struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i]; - - ret = pm_runtime_get_sync(domain->power_dev); - if (ret < 0) { - pm_runtime_put_noidle(domain->power_dev); - goto out_fail; - } - } - - return 0; - -out_fail: - for (i--; i >= 0; i--) - pm_runtime_put(bc->domains[i].power_dev); - - pm_runtime_put(bc->bus_power_dev); - - return ret; -} - -static int imx8mp_blk_ctrl_resume(struct device *dev) -{ - struct imx8mp_blk_ctrl *bc = dev_get_drvdata(dev); - int i; - - for (i = 0; i < bc->onecell_data.num_domains; i++) - pm_runtime_put(bc->domains[i].power_dev); - - pm_runtime_put(bc->bus_power_dev); - - return 0; -} -#endif - -static const struct dev_pm_ops imx8mp_blk_ctrl_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(imx8mp_blk_ctrl_suspend, - imx8mp_blk_ctrl_resume) -}; - -static const struct of_device_id imx8mp_blk_ctrl_of_match[] = { - { - .compatible = "fsl,imx8mp-hsio-blk-ctrl", - .data = &imx8mp_hsio_blk_ctl_dev_data, - }, { - .compatible = "fsl,imx8mp-hdmi-blk-ctrl", - .data = &imx8mp_hdmi_blk_ctl_dev_data, - }, { - /* Sentinel */ - } -}; -MODULE_DEVICE_TABLE(of, imx8mp_blk_ctrl_of_match); - -static struct platform_driver imx8mp_blk_ctrl_driver = { - .probe = imx8mp_blk_ctrl_probe, - .remove = imx8mp_blk_ctrl_remove, - .driver = { - .name = "imx8mp-blk-ctrl", - .pm = &imx8mp_blk_ctrl_pm_ops, - .of_match_table = imx8mp_blk_ctrl_of_match, - }, -}; -module_platform_driver(imx8mp_blk_ctrl_driver); -MODULE_LICENSE("GPL"); diff --git a/drivers/soc/imx/imx93-blk-ctrl.c b/drivers/soc/imx/imx93-blk-ctrl.c deleted file mode 100644 index 2c600329436c..000000000000 --- a/drivers/soc/imx/imx93-blk-ctrl.c +++ /dev/null @@ -1,436 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2022 NXP, Peng Fan <peng.fan@nxp.com> - */ - -#include <linux/clk.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <linux/pm_runtime.h> -#include <linux/regmap.h> -#include <linux/sizes.h> - -#include <dt-bindings/power/fsl,imx93-power.h> - -#define BLK_SFT_RSTN 0x0 -#define BLK_CLK_EN 0x4 -#define BLK_MAX_CLKS 4 - -#define DOMAIN_MAX_CLKS 4 - -#define LCDIF_QOS_REG 0xC -#define LCDIF_DEFAULT_QOS_OFF 12 -#define LCDIF_CFG_QOS_OFF 8 - -#define PXP_QOS_REG 0x10 -#define PXP_R_DEFAULT_QOS_OFF 28 -#define PXP_R_CFG_QOS_OFF 24 -#define PXP_W_DEFAULT_QOS_OFF 20 -#define PXP_W_CFG_QOS_OFF 16 - -#define ISI_CACHE_REG 0x14 - -#define ISI_QOS_REG 0x1C -#define ISI_V_DEFAULT_QOS_OFF 28 -#define ISI_V_CFG_QOS_OFF 24 -#define ISI_U_DEFAULT_QOS_OFF 20 -#define ISI_U_CFG_QOS_OFF 16 -#define ISI_Y_R_DEFAULT_QOS_OFF 12 -#define ISI_Y_R_CFG_QOS_OFF 8 -#define ISI_Y_W_DEFAULT_QOS_OFF 4 -#define ISI_Y_W_CFG_QOS_OFF 0 - -#define PRIO_MASK 0xF - -#define PRIO(X) (X) - -struct imx93_blk_ctrl_domain; - -struct imx93_blk_ctrl { - struct device *dev; - struct regmap *regmap; - int num_clks; - struct clk_bulk_data clks[BLK_MAX_CLKS]; - struct imx93_blk_ctrl_domain *domains; - struct genpd_onecell_data onecell_data; -}; - -#define DOMAIN_MAX_QOS 4 - -struct imx93_blk_ctrl_qos { - u32 reg; - u32 cfg_off; - u32 default_prio; - u32 cfg_prio; -}; - -struct imx93_blk_ctrl_domain_data { - const char *name; - const char * const *clk_names; - int num_clks; - u32 rst_mask; - u32 clk_mask; - int num_qos; - struct imx93_blk_ctrl_qos qos[DOMAIN_MAX_QOS]; -}; - -struct imx93_blk_ctrl_domain { - struct generic_pm_domain genpd; - const struct imx93_blk_ctrl_domain_data *data; - struct clk_bulk_data clks[DOMAIN_MAX_CLKS]; - struct imx93_blk_ctrl *bc; -}; - -struct imx93_blk_ctrl_data { - const struct imx93_blk_ctrl_domain_data *domains; - int num_domains; - const char * const *clk_names; - int num_clks; - const struct regmap_access_table *reg_access_table; -}; - -static inline struct imx93_blk_ctrl_domain * -to_imx93_blk_ctrl_domain(struct generic_pm_domain *genpd) -{ - return container_of(genpd, struct imx93_blk_ctrl_domain, genpd); -} - -static int imx93_blk_ctrl_set_qos(struct imx93_blk_ctrl_domain *domain) -{ - const struct imx93_blk_ctrl_domain_data *data = domain->data; - struct imx93_blk_ctrl *bc = domain->bc; - const struct imx93_blk_ctrl_qos *qos; - u32 val, mask; - int i; - - for (i = 0; i < data->num_qos; i++) { - qos = &data->qos[i]; - - mask = PRIO_MASK << qos->cfg_off; - mask |= PRIO_MASK << (qos->cfg_off + 4); - val = qos->cfg_prio << qos->cfg_off; - val |= qos->default_prio << (qos->cfg_off + 4); - - regmap_write_bits(bc->regmap, qos->reg, mask, val); - - dev_dbg(bc->dev, "data->qos[i].reg 0x%x 0x%x\n", qos->reg, val); - } - - return 0; -} - -static int imx93_blk_ctrl_power_on(struct generic_pm_domain *genpd) -{ - struct imx93_blk_ctrl_domain *domain = to_imx93_blk_ctrl_domain(genpd); - const struct imx93_blk_ctrl_domain_data *data = domain->data; - struct imx93_blk_ctrl *bc = domain->bc; - int ret; - - ret = clk_bulk_prepare_enable(bc->num_clks, bc->clks); - if (ret) { - dev_err(bc->dev, "failed to enable bus clocks\n"); - return ret; - } - - ret = clk_bulk_prepare_enable(data->num_clks, domain->clks); - if (ret) { - clk_bulk_disable_unprepare(bc->num_clks, bc->clks); - dev_err(bc->dev, "failed to enable clocks\n"); - return ret; - } - - ret = pm_runtime_get_sync(bc->dev); - if (ret < 0) { - pm_runtime_put_noidle(bc->dev); - dev_err(bc->dev, "failed to power up domain\n"); - goto disable_clk; - } - - /* ungate clk */ - regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask); - - /* release reset */ - regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask); - - dev_dbg(bc->dev, "pd_on: name: %s\n", genpd->name); - - return imx93_blk_ctrl_set_qos(domain); - -disable_clk: - clk_bulk_disable_unprepare(data->num_clks, domain->clks); - - clk_bulk_disable_unprepare(bc->num_clks, bc->clks); - - return ret; -} - -static int imx93_blk_ctrl_power_off(struct generic_pm_domain *genpd) -{ - struct imx93_blk_ctrl_domain *domain = to_imx93_blk_ctrl_domain(genpd); - const struct imx93_blk_ctrl_domain_data *data = domain->data; - struct imx93_blk_ctrl *bc = domain->bc; - - dev_dbg(bc->dev, "pd_off: name: %s\n", genpd->name); - - regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask); - regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask); - - pm_runtime_put(bc->dev); - - clk_bulk_disable_unprepare(data->num_clks, domain->clks); - - clk_bulk_disable_unprepare(bc->num_clks, bc->clks); - - return 0; -} - -static int imx93_blk_ctrl_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - const struct imx93_blk_ctrl_data *bc_data = of_device_get_match_data(dev); - struct imx93_blk_ctrl *bc; - void __iomem *base; - int i, ret; - - struct regmap_config regmap_config = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .rd_table = bc_data->reg_access_table, - .wr_table = bc_data->reg_access_table, - .max_register = SZ_4K, - }; - - bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL); - if (!bc) - return -ENOMEM; - - bc->dev = dev; - - base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(base)) - return PTR_ERR(base); - - bc->regmap = devm_regmap_init_mmio(dev, base, ®map_config); - if (IS_ERR(bc->regmap)) - return dev_err_probe(dev, PTR_ERR(bc->regmap), - "failed to init regmap\n"); - - bc->domains = devm_kcalloc(dev, bc_data->num_domains, - sizeof(struct imx93_blk_ctrl_domain), - GFP_KERNEL); - if (!bc->domains) - return -ENOMEM; - - bc->onecell_data.num_domains = bc_data->num_domains; - bc->onecell_data.domains = - devm_kcalloc(dev, bc_data->num_domains, - sizeof(struct generic_pm_domain *), GFP_KERNEL); - if (!bc->onecell_data.domains) - return -ENOMEM; - - for (i = 0; i < bc_data->num_clks; i++) - bc->clks[i].id = bc_data->clk_names[i]; - bc->num_clks = bc_data->num_clks; - - ret = devm_clk_bulk_get(dev, bc->num_clks, bc->clks); - if (ret) { - dev_err_probe(dev, ret, "failed to get bus clock\n"); - return ret; - } - - for (i = 0; i < bc_data->num_domains; i++) { - const struct imx93_blk_ctrl_domain_data *data = &bc_data->domains[i]; - struct imx93_blk_ctrl_domain *domain = &bc->domains[i]; - int j; - - domain->data = data; - - for (j = 0; j < data->num_clks; j++) - domain->clks[j].id = data->clk_names[j]; - - ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks); - if (ret) { - dev_err_probe(dev, ret, "failed to get clock\n"); - goto cleanup_pds; - } - - domain->genpd.name = data->name; - domain->genpd.power_on = imx93_blk_ctrl_power_on; - domain->genpd.power_off = imx93_blk_ctrl_power_off; - domain->bc = bc; - - ret = pm_genpd_init(&domain->genpd, NULL, true); - if (ret) { - dev_err_probe(dev, ret, "failed to init power domain\n"); - goto cleanup_pds; - } - - bc->onecell_data.domains[i] = &domain->genpd; - } - - pm_runtime_enable(dev); - - ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data); - if (ret) { - dev_err_probe(dev, ret, "failed to add power domain provider\n"); - goto cleanup_pds; - } - - dev_set_drvdata(dev, bc); - - return 0; - -cleanup_pds: - for (i--; i >= 0; i--) - pm_genpd_remove(&bc->domains[i].genpd); - - return ret; -} - -static int imx93_blk_ctrl_remove(struct platform_device *pdev) -{ - struct imx93_blk_ctrl *bc = dev_get_drvdata(&pdev->dev); - int i; - - of_genpd_del_provider(pdev->dev.of_node); - - for (i = 0; bc->onecell_data.num_domains; i++) { - struct imx93_blk_ctrl_domain *domain = &bc->domains[i]; - - pm_genpd_remove(&domain->genpd); - } - - return 0; -} - -static const struct imx93_blk_ctrl_domain_data imx93_media_blk_ctl_domain_data[] = { - [IMX93_MEDIABLK_PD_MIPI_DSI] = { - .name = "mediablk-mipi-dsi", - .clk_names = (const char *[]){ "dsi" }, - .num_clks = 1, - .rst_mask = BIT(11) | BIT(12), - .clk_mask = BIT(11) | BIT(12), - }, - [IMX93_MEDIABLK_PD_MIPI_CSI] = { - .name = "mediablk-mipi-csi", - .clk_names = (const char *[]){ "cam", "csi" }, - .num_clks = 2, - .rst_mask = BIT(9) | BIT(10), - .clk_mask = BIT(9) | BIT(10), - }, - [IMX93_MEDIABLK_PD_PXP] = { - .name = "mediablk-pxp", - .clk_names = (const char *[]){ "pxp" }, - .num_clks = 1, - .rst_mask = BIT(7) | BIT(8), - .clk_mask = BIT(7) | BIT(8), - .num_qos = 2, - .qos = { - { - .reg = PXP_QOS_REG, - .cfg_off = PXP_R_CFG_QOS_OFF, - .default_prio = PRIO(3), - .cfg_prio = PRIO(6), - }, { - .reg = PXP_QOS_REG, - .cfg_off = PXP_W_CFG_QOS_OFF, - .default_prio = PRIO(3), - .cfg_prio = PRIO(6), - } - } - }, - [IMX93_MEDIABLK_PD_LCDIF] = { - .name = "mediablk-lcdif", - .clk_names = (const char *[]){ "disp", "lcdif" }, - .num_clks = 2, - .rst_mask = BIT(4) | BIT(5) | BIT(6), - .clk_mask = BIT(4) | BIT(5) | BIT(6), - .num_qos = 1, - .qos = { - { - .reg = LCDIF_QOS_REG, - .cfg_off = LCDIF_CFG_QOS_OFF, - .default_prio = PRIO(3), - .cfg_prio = PRIO(7), - } - } - }, - [IMX93_MEDIABLK_PD_ISI] = { - .name = "mediablk-isi", - .clk_names = (const char *[]){ "isi" }, - .num_clks = 1, - .rst_mask = BIT(2) | BIT(3), - .clk_mask = BIT(2) | BIT(3), - .num_qos = 4, - .qos = { - { - .reg = ISI_QOS_REG, - .cfg_off = ISI_Y_W_CFG_QOS_OFF, - .default_prio = PRIO(3), - .cfg_prio = PRIO(7), - }, { - .reg = ISI_QOS_REG, - .cfg_off = ISI_Y_R_CFG_QOS_OFF, - .default_prio = PRIO(3), - .cfg_prio = PRIO(7), - }, { - .reg = ISI_QOS_REG, - .cfg_off = ISI_U_CFG_QOS_OFF, - .default_prio = PRIO(3), - .cfg_prio = PRIO(7), - }, { - .reg = ISI_QOS_REG, - .cfg_off = ISI_V_CFG_QOS_OFF, - .default_prio = PRIO(3), - .cfg_prio = PRIO(7), - } - } - }, -}; - -static const struct regmap_range imx93_media_blk_ctl_yes_ranges[] = { - regmap_reg_range(BLK_SFT_RSTN, BLK_CLK_EN), - regmap_reg_range(LCDIF_QOS_REG, ISI_CACHE_REG), - regmap_reg_range(ISI_QOS_REG, ISI_QOS_REG), -}; - -static const struct regmap_access_table imx93_media_blk_ctl_access_table = { - .yes_ranges = imx93_media_blk_ctl_yes_ranges, - .n_yes_ranges = ARRAY_SIZE(imx93_media_blk_ctl_yes_ranges), -}; - -static const struct imx93_blk_ctrl_data imx93_media_blk_ctl_dev_data = { - .domains = imx93_media_blk_ctl_domain_data, - .num_domains = ARRAY_SIZE(imx93_media_blk_ctl_domain_data), - .clk_names = (const char *[]){ "axi", "apb", "nic", }, - .num_clks = 3, - .reg_access_table = &imx93_media_blk_ctl_access_table, -}; - -static const struct of_device_id imx93_blk_ctrl_of_match[] = { - { - .compatible = "fsl,imx93-media-blk-ctrl", - .data = &imx93_media_blk_ctl_dev_data - }, { - /* Sentinel */ - } -}; -MODULE_DEVICE_TABLE(of, imx93_blk_ctrl_of_match); - -static struct platform_driver imx93_blk_ctrl_driver = { - .probe = imx93_blk_ctrl_probe, - .remove = imx93_blk_ctrl_remove, - .driver = { - .name = "imx93-blk-ctrl", - .of_match_table = imx93_blk_ctrl_of_match, - }, -}; -module_platform_driver(imx93_blk_ctrl_driver); - -MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>"); -MODULE_DESCRIPTION("i.MX93 BLK CTRL driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/soc/imx/imx93-pd.c b/drivers/soc/imx/imx93-pd.c deleted file mode 100644 index 832deeed8fd6..000000000000 --- a/drivers/soc/imx/imx93-pd.c +++ /dev/null @@ -1,176 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2022 NXP - */ - -#include <linux/clk.h> -#include <linux/delay.h> -#include <linux/of_device.h> -#include <linux/iopoll.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/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) - -struct imx93_power_domain { - struct generic_pm_domain genpd; - struct device *dev; - void __iomem *addr; - struct clk_bulk_data *clks; - int num_clks; - bool init_off; -}; - -#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_ISO_STAT_MASK), 1, 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, 1, 1000); - 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_remove(struct platform_device *pdev) -{ - struct imx93_power_domain *domain = platform_get_drvdata(pdev); - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - - if (!domain->init_off) - clk_bulk_disable_unprepare(domain->num_clks, domain->clks); - - of_genpd_del_provider(np); - pm_genpd_remove(&domain->genpd); - - return 0; -} - -static int imx93_pd_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - struct imx93_power_domain *domain; - int ret; - - domain = devm_kzalloc(dev, sizeof(*domain), GFP_KERNEL); - if (!domain) - return -ENOMEM; - - domain->addr = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(domain->addr)) - return PTR_ERR(domain->addr); - - domain->num_clks = devm_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; - - domain->init_off = readl(domain->addr + MIX_FUNC_STAT_OFF) & FUNC_STAT_ISO_STAT_MASK; - /* Just to sync the status of hardware */ - if (!domain->init_off) { - ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks); - if (ret) { - dev_err(domain->dev, "failed to enable clocks for domain: %s\n", - domain->genpd.name); - return ret; - } - } - - ret = pm_genpd_init(&domain->genpd, NULL, domain->init_off); - if (ret) - goto err_clk_unprepare; - - platform_set_drvdata(pdev, domain); - - 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 (!domain->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 platform_driver imx93_power_domain_driver = { - .driver = { - .name = "imx93_power_domain", - .of_match_table = imx93_pd_ids, - }, - .probe = imx93_pd_probe, - .remove = imx93_pd_remove, -}; -module_platform_driver(imx93_power_domain_driver); - -MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>"); -MODULE_DESCRIPTION("NXP i.MX93 power domain driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile index 8c0ddacbcde8..9d3ce7878c5c 100644 --- a/drivers/soc/mediatek/Makefile +++ b/drivers/soc/mediatek/Makefile @@ -4,8 +4,6 @@ obj-$(CONFIG_MTK_DEVAPC) += mtk-devapc.o obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o obj-$(CONFIG_MTK_REGULATOR_COUPLER) += mtk-regulator-coupler.o -obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o -obj-$(CONFIG_MTK_SCPSYS_PM_DOMAINS) += mtk-pm-domains.o obj-$(CONFIG_MTK_MMSYS) += mtk-mmsys.o obj-$(CONFIG_MTK_MMSYS) += mtk-mutex.o obj-$(CONFIG_MTK_SVS) += mtk-svs.o diff --git a/drivers/soc/mediatek/mt6795-pm-domains.h b/drivers/soc/mediatek/mt6795-pm-domains.h deleted file mode 100644 index ef07c9dfdd9b..000000000000 --- a/drivers/soc/mediatek/mt6795-pm-domains.h +++ /dev/null @@ -1,112 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#ifndef __SOC_MEDIATEK_MT6795_PM_DOMAINS_H -#define __SOC_MEDIATEK_MT6795_PM_DOMAINS_H - -#include "mtk-pm-domains.h" -#include <dt-bindings/power/mt6795-power.h> - -/* - * MT6795 power domain support - */ - -static const struct scpsys_domain_data scpsys_domain_data_mt6795[] = { - [MT6795_POWER_DOMAIN_VDEC] = { - .name = "vdec", - .sta_mask = PWR_STATUS_VDEC, - .ctl_offs = SPM_VDE_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - }, - [MT6795_POWER_DOMAIN_VENC] = { - .name = "venc", - .sta_mask = PWR_STATUS_VENC, - .ctl_offs = SPM_VEN_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - }, - [MT6795_POWER_DOMAIN_ISP] = { - .name = "isp", - .sta_mask = PWR_STATUS_ISP, - .ctl_offs = SPM_ISP_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(13, 12), - }, - [MT6795_POWER_DOMAIN_MM] = { - .name = "mm", - .sta_mask = PWR_STATUS_DISP, - .ctl_offs = SPM_DIS_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MM_M0 | - MT8173_TOP_AXI_PROT_EN_MM_M1), - }, - }, - [MT6795_POWER_DOMAIN_MJC] = { - .name = "mjc", - .sta_mask = BIT(20), - .ctl_offs = 0x298, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - }, - [MT6795_POWER_DOMAIN_AUDIO] = { - .name = "audio", - .sta_mask = PWR_STATUS_AUDIO, - .ctl_offs = SPM_AUDIO_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - }, - [MT6795_POWER_DOMAIN_MFG_ASYNC] = { - .name = "mfg_async", - .sta_mask = PWR_STATUS_MFG_ASYNC, - .ctl_offs = SPM_MFG_ASYNC_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = 0, - }, - [MT6795_POWER_DOMAIN_MFG_2D] = { - .name = "mfg_2d", - .sta_mask = PWR_STATUS_MFG_2D, - .ctl_offs = SPM_MFG_2D_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(13, 12), - }, - [MT6795_POWER_DOMAIN_MFG] = { - .name = "mfg", - .sta_mask = PWR_STATUS_MFG, - .ctl_offs = SPM_MFG_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(13, 8), - .sram_pdn_ack_bits = GENMASK(21, 16), - .bp_infracfg = { - BUS_PROT_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MFG_S | - MT8173_TOP_AXI_PROT_EN_MFG_M0 | - MT8173_TOP_AXI_PROT_EN_MFG_M1 | - MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT), - }, - }, -}; - -static const struct scpsys_soc_data mt6795_scpsys_data = { - .domains_data = scpsys_domain_data_mt6795, - .num_domains = ARRAY_SIZE(scpsys_domain_data_mt6795), -}; - -#endif /* __SOC_MEDIATEK_MT6795_PM_DOMAINS_H */ diff --git a/drivers/soc/mediatek/mt8167-pm-domains.h b/drivers/soc/mediatek/mt8167-pm-domains.h deleted file mode 100644 index 4d6c32759606..000000000000 --- a/drivers/soc/mediatek/mt8167-pm-domains.h +++ /dev/null @@ -1,105 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#ifndef __SOC_MEDIATEK_MT8167_PM_DOMAINS_H -#define __SOC_MEDIATEK_MT8167_PM_DOMAINS_H - -#include "mtk-pm-domains.h" -#include <dt-bindings/power/mt8167-power.h> - -#define MT8167_PWR_STATUS_MFG_2D BIT(24) -#define MT8167_PWR_STATUS_MFG_ASYNC BIT(25) - -/* - * MT8167 power domain support - */ - -static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = { - [MT8167_POWER_DOMAIN_MM] = { - .name = "mm", - .sta_mask = PWR_STATUS_DISP, - .ctl_offs = SPM_DIS_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_MM_EMI | - MT8167_TOP_AXI_PROT_EN_MCU_MM), - }, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT8167_POWER_DOMAIN_VDEC] = { - .name = "vdec", - .sta_mask = PWR_STATUS_VDEC, - .ctl_offs = SPM_VDE_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT8167_POWER_DOMAIN_ISP] = { - .name = "isp", - .sta_mask = PWR_STATUS_ISP, - .ctl_offs = SPM_ISP_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(13, 12), - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT8167_POWER_DOMAIN_MFG_ASYNC] = { - .name = "mfg_async", - .sta_mask = MT8167_PWR_STATUS_MFG_ASYNC, - .ctl_offs = SPM_MFG_ASYNC_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = 0, - .sram_pdn_ack_bits = 0, - .bp_infracfg = { - BUS_PROT_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_MCU_MFG | - MT8167_TOP_AXI_PROT_EN_MFG_EMI), - }, - }, - [MT8167_POWER_DOMAIN_MFG_2D] = { - .name = "mfg_2d", - .sta_mask = MT8167_PWR_STATUS_MFG_2D, - .ctl_offs = SPM_MFG_2D_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - }, - [MT8167_POWER_DOMAIN_MFG] = { - .name = "mfg", - .sta_mask = PWR_STATUS_MFG, - .ctl_offs = SPM_MFG_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - }, - [MT8167_POWER_DOMAIN_CONN] = { - .name = "conn", - .sta_mask = PWR_STATUS_CONN, - .ctl_offs = SPM_CONN_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = 0, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - .bp_infracfg = { - BUS_PROT_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_CONN_EMI | - MT8167_TOP_AXI_PROT_EN_CONN_MCU | - MT8167_TOP_AXI_PROT_EN_MCU_CONN), - }, - }, -}; - -static const struct scpsys_soc_data mt8167_scpsys_data = { - .domains_data = scpsys_domain_data_mt8167, - .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8167), -}; - -#endif /* __SOC_MEDIATEK_MT8167_PM_DOMAINS_H */ - diff --git a/drivers/soc/mediatek/mt8173-pm-domains.h b/drivers/soc/mediatek/mt8173-pm-domains.h deleted file mode 100644 index 1a5dc63b7357..000000000000 --- a/drivers/soc/mediatek/mt8173-pm-domains.h +++ /dev/null @@ -1,123 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#ifndef __SOC_MEDIATEK_MT8173_PM_DOMAINS_H -#define __SOC_MEDIATEK_MT8173_PM_DOMAINS_H - -#include "mtk-pm-domains.h" -#include <dt-bindings/power/mt8173-power.h> - -/* - * MT8173 power domain support - */ - -static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = { - [MT8173_POWER_DOMAIN_VDEC] = { - .name = "vdec", - .sta_mask = PWR_STATUS_VDEC, - .ctl_offs = SPM_VDE_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - }, - [MT8173_POWER_DOMAIN_VENC] = { - .name = "venc", - .sta_mask = PWR_STATUS_VENC, - .ctl_offs = SPM_VEN_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - }, - [MT8173_POWER_DOMAIN_ISP] = { - .name = "isp", - .sta_mask = PWR_STATUS_ISP, - .ctl_offs = SPM_ISP_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(13, 12), - }, - [MT8173_POWER_DOMAIN_MM] = { - .name = "mm", - .sta_mask = PWR_STATUS_DISP, - .ctl_offs = SPM_DIS_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MM_M0 | - MT8173_TOP_AXI_PROT_EN_MM_M1), - }, - }, - [MT8173_POWER_DOMAIN_VENC_LT] = { - .name = "venc_lt", - .sta_mask = PWR_STATUS_VENC_LT, - .ctl_offs = SPM_VEN2_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - }, - [MT8173_POWER_DOMAIN_AUDIO] = { - .name = "audio", - .sta_mask = PWR_STATUS_AUDIO, - .ctl_offs = SPM_AUDIO_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - }, - [MT8173_POWER_DOMAIN_USB] = { - .name = "usb", - .sta_mask = PWR_STATUS_USB, - .ctl_offs = SPM_USB_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT8173_POWER_DOMAIN_MFG_ASYNC] = { - .name = "mfg_async", - .sta_mask = PWR_STATUS_MFG_ASYNC, - .ctl_offs = SPM_MFG_ASYNC_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = 0, - .caps = MTK_SCPD_DOMAIN_SUPPLY, - }, - [MT8173_POWER_DOMAIN_MFG_2D] = { - .name = "mfg_2d", - .sta_mask = PWR_STATUS_MFG_2D, - .ctl_offs = SPM_MFG_2D_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(13, 12), - }, - [MT8173_POWER_DOMAIN_MFG] = { - .name = "mfg", - .sta_mask = PWR_STATUS_MFG, - .ctl_offs = SPM_MFG_PWR_CON, - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, - .sram_pdn_bits = GENMASK(13, 8), - .sram_pdn_ack_bits = GENMASK(21, 16), - .bp_infracfg = { - BUS_PROT_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MFG_S | - MT8173_TOP_AXI_PROT_EN_MFG_M0 | - MT8173_TOP_AXI_PROT_EN_MFG_M1 | - MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT), - }, - }, -}; - -static const struct scpsys_soc_data mt8173_scpsys_data = { - .domains_data = scpsys_domain_data_mt8173, - .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8173), -}; - -#endif /* __SOC_MEDIATEK_MT8173_PM_DOMAINS_H */ diff --git a/drivers/soc/mediatek/mt8183-pm-domains.h b/drivers/soc/mediatek/mt8183-pm-domains.h deleted file mode 100644 index 99de67fe5de8..000000000000 --- a/drivers/soc/mediatek/mt8183-pm-domains.h +++ /dev/null @@ -1,266 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#ifndef __SOC_MEDIATEK_MT8183_PM_DOMAINS_H -#define __SOC_MEDIATEK_MT8183_PM_DOMAINS_H - -#include "mtk-pm-domains.h" -#include <dt-bindings/power/mt8183-power.h> - -/* - * MT8183 power domain support - */ - -static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { - [MT8183_POWER_DOMAIN_AUDIO] = { - .name = "audio", - .sta_mask = PWR_STATUS_AUDIO, - .ctl_offs = 0x0314, - .pwr_sta_offs = 0x0180, - .pwr_sta2nd_offs = 0x0184, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - }, - [MT8183_POWER_DOMAIN_CONN] = { - .name = "conn", - .sta_mask = PWR_STATUS_CONN, - .ctl_offs = 0x032c, - .pwr_sta_offs = 0x0180, - .pwr_sta2nd_offs = 0x0184, - .sram_pdn_bits = 0, - .sram_pdn_ack_bits = 0, - .bp_infracfg = { - BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_CONN, MT8183_TOP_AXI_PROT_EN_SET, - MT8183_TOP_AXI_PROT_EN_CLR, MT8183_TOP_AXI_PROT_EN_STA1), - }, - }, - [MT8183_POWER_DOMAIN_MFG_ASYNC] = { - .name = "mfg_async", - .sta_mask = PWR_STATUS_MFG_ASYNC, - .ctl_offs = 0x0334, - .pwr_sta_offs = 0x0180, - .pwr_sta2nd_offs = 0x0184, - .sram_pdn_bits = 0, - .sram_pdn_ack_bits = 0, - .caps = MTK_SCPD_DOMAIN_SUPPLY, - }, - [MT8183_POWER_DOMAIN_MFG] = { - .name = "mfg", - .sta_mask = PWR_STATUS_MFG, - .ctl_offs = 0x0338, - .pwr_sta_offs = 0x0180, - .pwr_sta2nd_offs = 0x0184, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .caps = MTK_SCPD_DOMAIN_SUPPLY, - }, - [MT8183_POWER_DOMAIN_MFG_CORE0] = { - .name = "mfg_core0", - .sta_mask = BIT(7), - .ctl_offs = 0x034c, - .pwr_sta_offs = 0x0180, - .pwr_sta2nd_offs = 0x0184, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - }, - [MT8183_POWER_DOMAIN_MFG_CORE1] = { - .name = "mfg_core1", - .sta_mask = BIT(20), - .ctl_offs = 0x0310, - .pwr_sta_offs = 0x0180, - .pwr_sta2nd_offs = 0x0184, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - }, - [MT8183_POWER_DOMAIN_MFG_2D] = { - .name = "mfg_2d", - .sta_mask = PWR_STATUS_MFG_2D, - .ctl_offs = 0x0348, - .pwr_sta_offs = 0x0180, - .pwr_sta2nd_offs = 0x0184, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_1_MFG, MT8183_TOP_AXI_PROT_EN_1_SET, - MT8183_TOP_AXI_PROT_EN_1_CLR, MT8183_TOP_AXI_PROT_EN_STA1_1), - BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MFG, MT8183_TOP_AXI_PROT_EN_SET, - MT8183_TOP_AXI_PROT_EN_CLR, MT8183_TOP_AXI_PROT_EN_STA1), - }, - }, - [MT8183_POWER_DOMAIN_DISP] = { - .name = "disp", - .sta_mask = PWR_STATUS_DISP, - .ctl_offs = 0x030c, - .pwr_sta_offs = 0x0180, - .pwr_sta2nd_offs = 0x0184, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_1_DISP, MT8183_TOP_AXI_PROT_EN_1_SET, - MT8183_TOP_AXI_PROT_EN_1_CLR, MT8183_TOP_AXI_PROT_EN_STA1_1), - BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_DISP, MT8183_TOP_AXI_PROT_EN_SET, - MT8183_TOP_AXI_PROT_EN_CLR, MT8183_TOP_AXI_PROT_EN_STA1), - }, - .bp_smi = { - BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_DISP, - MT8183_SMI_COMMON_CLAMP_EN_SET, - MT8183_SMI_COMMON_CLAMP_EN_CLR, - MT8183_SMI_COMMON_CLAMP_EN), - }, - }, - [MT8183_POWER_DOMAIN_CAM] = { - .name = "cam", - .sta_mask = BIT(25), - .ctl_offs = 0x0344, - .pwr_sta_offs = 0x0180, - .pwr_sta2nd_offs = 0x0184, - .sram_pdn_bits = GENMASK(9, 8), - .sram_pdn_ack_bits = GENMASK(13, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MM_CAM, MT8183_TOP_AXI_PROT_EN_MM_SET, - MT8183_TOP_AXI_PROT_EN_MM_CLR, MT8183_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_CAM, MT8183_TOP_AXI_PROT_EN_SET, - MT8183_TOP_AXI_PROT_EN_CLR, MT8183_TOP_AXI_PROT_EN_STA1), - BUS_PROT_WR_IGN(MT8183_TOP_AXI_PROT_EN_MM_CAM_2ND, - MT8183_TOP_AXI_PROT_EN_MM_SET, - MT8183_TOP_AXI_PROT_EN_MM_CLR, - MT8183_TOP_AXI_PROT_EN_MM_STA1), - }, - .bp_smi = { - BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_CAM, - MT8183_SMI_COMMON_CLAMP_EN_SET, - MT8183_SMI_COMMON_CLAMP_EN_CLR, - MT8183_SMI_COMMON_CLAMP_EN), - }, - }, - [MT8183_POWER_DOMAIN_ISP] = { - .name = "isp", - .sta_mask = PWR_STATUS_ISP, - .ctl_offs = 0x0308, - .pwr_sta_offs = 0x0180, - .pwr_sta2nd_offs = 0x0184, - .sram_pdn_bits = GENMASK(9, 8), - .sram_pdn_ack_bits = GENMASK(13, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MM_ISP, - MT8183_TOP_AXI_PROT_EN_MM_SET, - MT8183_TOP_AXI_PROT_EN_MM_CLR, - MT8183_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR_IGN(MT8183_TOP_AXI_PROT_EN_MM_ISP_2ND, - MT8183_TOP_AXI_PROT_EN_MM_SET, - MT8183_TOP_AXI_PROT_EN_MM_CLR, - MT8183_TOP_AXI_PROT_EN_MM_STA1), - }, - .bp_smi = { - BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_ISP, - MT8183_SMI_COMMON_CLAMP_EN_SET, - MT8183_SMI_COMMON_CLAMP_EN_CLR, - MT8183_SMI_COMMON_CLAMP_EN), - }, - }, - [MT8183_POWER_DOMAIN_VDEC] = { - .name = "vdec", - .sta_mask = BIT(31), - .ctl_offs = 0x0300, - .pwr_sta_offs = 0x0180, - .pwr_sta2nd_offs = 0x0184, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_smi = { - BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_VDEC, - MT8183_SMI_COMMON_CLAMP_EN_SET, - MT8183_SMI_COMMON_CLAMP_EN_CLR, - MT8183_SMI_COMMON_CLAMP_EN), - }, - }, - [MT8183_POWER_DOMAIN_VENC] = { - .name = "venc", - .sta_mask = PWR_STATUS_VENC, - .ctl_offs = 0x0304, - .pwr_sta_offs = 0x0180, - .pwr_sta2nd_offs = 0x0184, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .bp_smi = { - BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_VENC, - MT8183_SMI_COMMON_CLAMP_EN_SET, - MT8183_SMI_COMMON_CLAMP_EN_CLR, - MT8183_SMI_COMMON_CLAMP_EN), - }, - }, - [MT8183_POWER_DOMAIN_VPU_TOP] = { - .name = "vpu_top", - .sta_mask = BIT(26), - .ctl_offs = 0x0324, - .pwr_sta_offs = 0x0180, - .pwr_sta2nd_offs = 0x0184, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MM_VPU_TOP, - MT8183_TOP_AXI_PROT_EN_MM_SET, - MT8183_TOP_AXI_PROT_EN_MM_CLR, - MT8183_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_VPU_TOP, - MT8183_TOP_AXI_PROT_EN_SET, - MT8183_TOP_AXI_PROT_EN_CLR, - MT8183_TOP_AXI_PROT_EN_STA1), - BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MM_VPU_TOP_2ND, - MT8183_TOP_AXI_PROT_EN_MM_SET, - MT8183_TOP_AXI_PROT_EN_MM_CLR, - MT8183_TOP_AXI_PROT_EN_MM_STA1), - }, - .bp_smi = { - BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_VPU_TOP, - MT8183_SMI_COMMON_CLAMP_EN_SET, - MT8183_SMI_COMMON_CLAMP_EN_CLR, - MT8183_SMI_COMMON_CLAMP_EN), - }, - }, - [MT8183_POWER_DOMAIN_VPU_CORE0] = { - .name = "vpu_core0", - .sta_mask = BIT(27), - .ctl_offs = 0x33c, - .pwr_sta_offs = 0x0180, - .pwr_sta2nd_offs = 0x0184, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(13, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE0, - MT8183_TOP_AXI_PROT_EN_MCU_SET, - MT8183_TOP_AXI_PROT_EN_MCU_CLR, - MT8183_TOP_AXI_PROT_EN_MCU_STA1), - BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE0_2ND, - MT8183_TOP_AXI_PROT_EN_MCU_SET, - MT8183_TOP_AXI_PROT_EN_MCU_CLR, - MT8183_TOP_AXI_PROT_EN_MCU_STA1), - }, - .caps = MTK_SCPD_SRAM_ISO, - }, - [MT8183_POWER_DOMAIN_VPU_CORE1] = { - .name = "vpu_core1", - .sta_mask = BIT(28), - .ctl_offs = 0x0340, - .pwr_sta_offs = 0x0180, - .pwr_sta2nd_offs = 0x0184, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(13, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE1, - MT8183_TOP_AXI_PROT_EN_MCU_SET, - MT8183_TOP_AXI_PROT_EN_MCU_CLR, - MT8183_TOP_AXI_PROT_EN_MCU_STA1), - BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE1_2ND, - MT8183_TOP_AXI_PROT_EN_MCU_SET, - MT8183_TOP_AXI_PROT_EN_MCU_CLR, - MT8183_TOP_AXI_PROT_EN_MCU_STA1), - }, - .caps = MTK_SCPD_SRAM_ISO, - }, -}; - -static const struct scpsys_soc_data mt8183_scpsys_data = { - .domains_data = scpsys_domain_data_mt8183, - .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8183), -}; - -#endif /* __SOC_MEDIATEK_MT8183_PM_DOMAINS_H */ diff --git a/drivers/soc/mediatek/mt8186-pm-domains.h b/drivers/soc/mediatek/mt8186-pm-domains.h deleted file mode 100644 index fce86f79c505..000000000000 --- a/drivers/soc/mediatek/mt8186-pm-domains.h +++ /dev/null @@ -1,342 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2022 MediaTek Inc. - * Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> - */ - -#ifndef __SOC_MEDIATEK_MT8186_PM_DOMAINS_H -#define __SOC_MEDIATEK_MT8186_PM_DOMAINS_H - -#include "mtk-pm-domains.h" -#include <dt-bindings/power/mt8186-power.h> - -/* - * MT8186 power domain support - */ - -static const struct scpsys_domain_data scpsys_domain_data_mt8186[] = { - [MT8186_POWER_DOMAIN_MFG0] = { - .name = "mfg0", - .sta_mask = BIT(2), - .ctl_offs = 0x308, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY, - }, - [MT8186_POWER_DOMAIN_MFG1] = { - .name = "mfg1", - .sta_mask = BIT(3), - .ctl_offs = 0x30c, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_MFG1_STEP1, - MT8186_TOP_AXI_PROT_EN_1_SET, - MT8186_TOP_AXI_PROT_EN_1_CLR, - MT8186_TOP_AXI_PROT_EN_1_STA), - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_MFG1_STEP2, - MT8186_TOP_AXI_PROT_EN_SET, - MT8186_TOP_AXI_PROT_EN_CLR, - MT8186_TOP_AXI_PROT_EN_STA), - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_MFG1_STEP3, - MT8186_TOP_AXI_PROT_EN_SET, - MT8186_TOP_AXI_PROT_EN_CLR, - MT8186_TOP_AXI_PROT_EN_STA), - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_MFG1_STEP4, - MT8186_TOP_AXI_PROT_EN_1_SET, - MT8186_TOP_AXI_PROT_EN_1_CLR, - MT8186_TOP_AXI_PROT_EN_1_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY, - }, - [MT8186_POWER_DOMAIN_MFG2] = { - .name = "mfg2", - .sta_mask = BIT(4), - .ctl_offs = 0x310, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8186_POWER_DOMAIN_MFG3] = { - .name = "mfg3", - .sta_mask = BIT(5), - .ctl_offs = 0x314, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8186_POWER_DOMAIN_SSUSB] = { - .name = "ssusb", - .sta_mask = BIT(20), - .ctl_offs = 0x9F0, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT8186_POWER_DOMAIN_SSUSB_P1] = { - .name = "ssusb_p1", - .sta_mask = BIT(19), - .ctl_offs = 0x9F4, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT8186_POWER_DOMAIN_DIS] = { - .name = "dis", - .sta_mask = BIT(21), - .ctl_offs = 0x354, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_DIS_STEP1, - MT8186_TOP_AXI_PROT_EN_1_SET, - MT8186_TOP_AXI_PROT_EN_1_CLR, - MT8186_TOP_AXI_PROT_EN_1_STA), - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_DIS_STEP2, - MT8186_TOP_AXI_PROT_EN_SET, - MT8186_TOP_AXI_PROT_EN_CLR, - MT8186_TOP_AXI_PROT_EN_STA), - }, - }, - [MT8186_POWER_DOMAIN_IMG] = { - .name = "img", - .sta_mask = BIT(13), - .ctl_offs = 0x334, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_IMG_STEP1, - MT8186_TOP_AXI_PROT_EN_1_SET, - MT8186_TOP_AXI_PROT_EN_1_CLR, - MT8186_TOP_AXI_PROT_EN_1_STA), - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_IMG_STEP2, - MT8186_TOP_AXI_PROT_EN_1_SET, - MT8186_TOP_AXI_PROT_EN_1_CLR, - MT8186_TOP_AXI_PROT_EN_1_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8186_POWER_DOMAIN_IMG2] = { - .name = "img2", - .sta_mask = BIT(14), - .ctl_offs = 0x338, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8186_POWER_DOMAIN_IPE] = { - .name = "ipe", - .sta_mask = BIT(15), - .ctl_offs = 0x33C, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_IPE_STEP1, - MT8186_TOP_AXI_PROT_EN_1_SET, - MT8186_TOP_AXI_PROT_EN_1_CLR, - MT8186_TOP_AXI_PROT_EN_1_STA), - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_IPE_STEP2, - MT8186_TOP_AXI_PROT_EN_1_SET, - MT8186_TOP_AXI_PROT_EN_1_CLR, - MT8186_TOP_AXI_PROT_EN_1_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8186_POWER_DOMAIN_CAM] = { - .name = "cam", - .sta_mask = BIT(23), - .ctl_offs = 0x35C, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_CAM_STEP1, - MT8186_TOP_AXI_PROT_EN_1_SET, - MT8186_TOP_AXI_PROT_EN_1_CLR, - MT8186_TOP_AXI_PROT_EN_1_STA), - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_CAM_STEP2, - MT8186_TOP_AXI_PROT_EN_1_SET, - MT8186_TOP_AXI_PROT_EN_1_CLR, - MT8186_TOP_AXI_PROT_EN_1_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8186_POWER_DOMAIN_CAM_RAWA] = { - .name = "cam_rawa", - .sta_mask = BIT(24), - .ctl_offs = 0x360, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8186_POWER_DOMAIN_CAM_RAWB] = { - .name = "cam_rawb", - .sta_mask = BIT(25), - .ctl_offs = 0x364, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8186_POWER_DOMAIN_VENC] = { - .name = "venc", - .sta_mask = BIT(18), - .ctl_offs = 0x348, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_VENC_STEP1, - MT8186_TOP_AXI_PROT_EN_1_SET, - MT8186_TOP_AXI_PROT_EN_1_CLR, - MT8186_TOP_AXI_PROT_EN_1_STA), - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_VENC_STEP2, - MT8186_TOP_AXI_PROT_EN_1_SET, - MT8186_TOP_AXI_PROT_EN_1_CLR, - MT8186_TOP_AXI_PROT_EN_1_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8186_POWER_DOMAIN_VDEC] = { - .name = "vdec", - .sta_mask = BIT(16), - .ctl_offs = 0x340, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_VDEC_STEP1, - MT8186_TOP_AXI_PROT_EN_1_SET, - MT8186_TOP_AXI_PROT_EN_1_CLR, - MT8186_TOP_AXI_PROT_EN_1_STA), - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_VDEC_STEP2, - MT8186_TOP_AXI_PROT_EN_1_SET, - MT8186_TOP_AXI_PROT_EN_1_CLR, - MT8186_TOP_AXI_PROT_EN_1_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8186_POWER_DOMAIN_WPE] = { - .name = "wpe", - .sta_mask = BIT(0), - .ctl_offs = 0x3F8, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_2_WPE_STEP1, - MT8186_TOP_AXI_PROT_EN_2_SET, - MT8186_TOP_AXI_PROT_EN_2_CLR, - MT8186_TOP_AXI_PROT_EN_2_STA), - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_2_WPE_STEP2, - MT8186_TOP_AXI_PROT_EN_2_SET, - MT8186_TOP_AXI_PROT_EN_2_CLR, - MT8186_TOP_AXI_PROT_EN_2_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8186_POWER_DOMAIN_CONN_ON] = { - .name = "conn_on", - .sta_mask = BIT(1), - .ctl_offs = 0x304, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .bp_infracfg = { - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_CONN_ON_STEP1, - MT8186_TOP_AXI_PROT_EN_1_SET, - MT8186_TOP_AXI_PROT_EN_1_CLR, - MT8186_TOP_AXI_PROT_EN_1_STA), - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_CONN_ON_STEP2, - MT8186_TOP_AXI_PROT_EN_SET, - MT8186_TOP_AXI_PROT_EN_CLR, - MT8186_TOP_AXI_PROT_EN_STA), - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_CONN_ON_STEP3, - MT8186_TOP_AXI_PROT_EN_SET, - MT8186_TOP_AXI_PROT_EN_CLR, - MT8186_TOP_AXI_PROT_EN_STA), - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_CONN_ON_STEP4, - MT8186_TOP_AXI_PROT_EN_SET, - MT8186_TOP_AXI_PROT_EN_CLR, - MT8186_TOP_AXI_PROT_EN_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT8186_POWER_DOMAIN_CSIRX_TOP] = { - .name = "csirx_top", - .sta_mask = BIT(6), - .ctl_offs = 0x318, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8186_POWER_DOMAIN_ADSP_AO] = { - .name = "adsp_ao", - .sta_mask = BIT(17), - .ctl_offs = 0x9FC, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - }, - [MT8186_POWER_DOMAIN_ADSP_INFRA] = { - .name = "adsp_infra", - .sta_mask = BIT(10), - .ctl_offs = 0x9F8, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - }, - [MT8186_POWER_DOMAIN_ADSP_TOP] = { - .name = "adsp_top", - .sta_mask = BIT(31), - .ctl_offs = 0x3E4, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_3_ADSP_TOP_STEP1, - MT8186_TOP_AXI_PROT_EN_3_SET, - MT8186_TOP_AXI_PROT_EN_3_CLR, - MT8186_TOP_AXI_PROT_EN_3_STA), - BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_3_ADSP_TOP_STEP2, - MT8186_TOP_AXI_PROT_EN_3_SET, - MT8186_TOP_AXI_PROT_EN_3_CLR, - MT8186_TOP_AXI_PROT_EN_3_STA), - }, - .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_ACTIVE_WAKEUP, - }, -}; - -static const struct scpsys_soc_data mt8186_scpsys_data = { - .domains_data = scpsys_domain_data_mt8186, - .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8186), -}; - -#endif /* __SOC_MEDIATEK_MT8186_PM_DOMAINS_H */ diff --git a/drivers/soc/mediatek/mt8188-pm-domains.h b/drivers/soc/mediatek/mt8188-pm-domains.h deleted file mode 100644 index 0692cb444ed0..000000000000 --- a/drivers/soc/mediatek/mt8188-pm-domains.h +++ /dev/null @@ -1,623 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2022 MediaTek Inc. - * Author: Garmin Chang <garmin.chang@mediatek.com> - */ - -#ifndef __SOC_MEDIATEK_MT8188_PM_DOMAINS_H -#define __SOC_MEDIATEK_MT8188_PM_DOMAINS_H - -#include "mtk-pm-domains.h" -#include <dt-bindings/power/mediatek,mt8188-power.h> - -/* - * MT8188 power domain support - */ - -static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = { - [MT8188_POWER_DOMAIN_MFG0] = { - .name = "mfg0", - .sta_mask = BIT(1), - .ctl_offs = 0x300, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY, - }, - [MT8188_POWER_DOMAIN_MFG1] = { - .name = "mfg1", - .sta_mask = BIT(2), - .ctl_offs = 0x304, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MFG1_STEP1, - MT8188_TOP_AXI_PROT_EN_SET, - MT8188_TOP_AXI_PROT_EN_CLR, - MT8188_TOP_AXI_PROT_EN_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_MFG1_STEP2, - MT8188_TOP_AXI_PROT_EN_2_SET, - MT8188_TOP_AXI_PROT_EN_2_CLR, - MT8188_TOP_AXI_PROT_EN_2_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_1_MFG1_STEP3, - MT8188_TOP_AXI_PROT_EN_1_SET, - MT8188_TOP_AXI_PROT_EN_1_CLR, - MT8188_TOP_AXI_PROT_EN_1_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_MFG1_STEP4, - MT8188_TOP_AXI_PROT_EN_2_SET, - MT8188_TOP_AXI_PROT_EN_2_CLR, - MT8188_TOP_AXI_PROT_EN_2_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MFG1_STEP5, - MT8188_TOP_AXI_PROT_EN_SET, - MT8188_TOP_AXI_PROT_EN_CLR, - MT8188_TOP_AXI_PROT_EN_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_MFG1_STEP6, - MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET, - MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR, - MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY, - }, - [MT8188_POWER_DOMAIN_MFG2] = { - .name = "mfg2", - .sta_mask = BIT(3), - .ctl_offs = 0x308, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8188_POWER_DOMAIN_MFG3] = { - .name = "mfg3", - .sta_mask = BIT(4), - .ctl_offs = 0x30C, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8188_POWER_DOMAIN_MFG4] = { - .name = "mfg4", - .sta_mask = BIT(5), - .ctl_offs = 0x310, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8188_POWER_DOMAIN_PEXTP_MAC_P0] = { - .name = "pextp_mac_p0", - .sta_mask = BIT(10), - .ctl_offs = 0x324, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_PEXTP_MAC_P0_STEP1, - MT8188_TOP_AXI_PROT_EN_SET, - MT8188_TOP_AXI_PROT_EN_CLR, - MT8188_TOP_AXI_PROT_EN_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_PEXTP_MAC_P0_STEP2, - MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET, - MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR, - MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8188_POWER_DOMAIN_PEXTP_PHY_TOP] = { - .name = "pextp_phy_top", - .sta_mask = BIT(12), - .ctl_offs = 0x328, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8188_POWER_DOMAIN_CSIRX_TOP] = { - .name = "pextp_csirx_top", - .sta_mask = BIT(17), - .ctl_offs = 0x3C4, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8188_POWER_DOMAIN_ETHER] = { - .name = "ether", - .sta_mask = BIT(1), - .ctl_offs = 0x338, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_ETHER_STEP1, - MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET, - MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR, - MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT8188_POWER_DOMAIN_HDMI_TX] = { - .name = "hdmi_tx", - .sta_mask = BIT(18), - .ctl_offs = 0x37C, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_HDMI_TX_STEP1, - MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET, - MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR, - MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT8188_POWER_DOMAIN_ADSP_AO] = { - .name = "adsp_ao", - .sta_mask = BIT(10), - .ctl_offs = 0x35C, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_AO_STEP1, - MT8188_TOP_AXI_PROT_EN_2_SET, - MT8188_TOP_AXI_PROT_EN_2_CLR, - MT8188_TOP_AXI_PROT_EN_2_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_AO_STEP2, - MT8188_TOP_AXI_PROT_EN_2_SET, - MT8188_TOP_AXI_PROT_EN_2_CLR, - MT8188_TOP_AXI_PROT_EN_2_STA), - }, - .caps = MTK_SCPD_ALWAYS_ON, - }, - [MT8188_POWER_DOMAIN_ADSP_INFRA] = { - .name = "adsp_infra", - .sta_mask = BIT(9), - .ctl_offs = 0x358, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_INFRA_STEP1, - MT8188_TOP_AXI_PROT_EN_2_SET, - MT8188_TOP_AXI_PROT_EN_2_CLR, - MT8188_TOP_AXI_PROT_EN_2_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_INFRA_STEP2, - MT8188_TOP_AXI_PROT_EN_2_SET, - MT8188_TOP_AXI_PROT_EN_2_CLR, - MT8188_TOP_AXI_PROT_EN_2_STA), - }, - .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_ALWAYS_ON, - }, - [MT8188_POWER_DOMAIN_ADSP] = { - .name = "adsp", - .sta_mask = BIT(8), - .ctl_offs = 0x354, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_STEP1, - MT8188_TOP_AXI_PROT_EN_2_SET, - MT8188_TOP_AXI_PROT_EN_2_CLR, - MT8188_TOP_AXI_PROT_EN_2_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_STEP2, - MT8188_TOP_AXI_PROT_EN_2_SET, - MT8188_TOP_AXI_PROT_EN_2_CLR, - MT8188_TOP_AXI_PROT_EN_2_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_SRAM_ISO | MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT8188_POWER_DOMAIN_AUDIO] = { - .name = "audio", - .sta_mask = BIT(6), - .ctl_offs = 0x34C, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP1, - MT8188_TOP_AXI_PROT_EN_2_SET, - MT8188_TOP_AXI_PROT_EN_2_CLR, - MT8188_TOP_AXI_PROT_EN_2_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP2, - MT8188_TOP_AXI_PROT_EN_2_SET, - MT8188_TOP_AXI_PROT_EN_2_CLR, - MT8188_TOP_AXI_PROT_EN_2_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT8188_POWER_DOMAIN_AUDIO_ASRC] = { - .name = "audio_asrc", - .sta_mask = BIT(7), - .ctl_offs = 0x350, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_ASRC_STEP1, - MT8188_TOP_AXI_PROT_EN_2_SET, - MT8188_TOP_AXI_PROT_EN_2_CLR, - MT8188_TOP_AXI_PROT_EN_2_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_ASRC_STEP2, - MT8188_TOP_AXI_PROT_EN_2_SET, - MT8188_TOP_AXI_PROT_EN_2_CLR, - MT8188_TOP_AXI_PROT_EN_2_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8188_POWER_DOMAIN_VPPSYS0] = { - .name = "vppsys0", - .sta_mask = BIT(11), - .ctl_offs = 0x360, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_VPPSYS0_STEP1, - MT8188_TOP_AXI_PROT_EN_SET, - MT8188_TOP_AXI_PROT_EN_CLR, - MT8188_TOP_AXI_PROT_EN_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS0_STEP2, - MT8188_TOP_AXI_PROT_EN_MM_2_SET, - MT8188_TOP_AXI_PROT_EN_MM_2_CLR, - MT8188_TOP_AXI_PROT_EN_MM_2_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_VPPSYS0_STEP3, - MT8188_TOP_AXI_PROT_EN_SET, - MT8188_TOP_AXI_PROT_EN_CLR, - MT8188_TOP_AXI_PROT_EN_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS0_STEP4, - MT8188_TOP_AXI_PROT_EN_MM_2_SET, - MT8188_TOP_AXI_PROT_EN_MM_2_CLR, - MT8188_TOP_AXI_PROT_EN_MM_2_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VPPSYS0_STEP5, - MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET, - MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR, - MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA), - }, - }, - [MT8188_POWER_DOMAIN_VDOSYS0] = { - .name = "vdosys0", - .sta_mask = BIT(13), - .ctl_offs = 0x368, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDOSYS0_STEP1, - MT8188_TOP_AXI_PROT_EN_MM_SET, - MT8188_TOP_AXI_PROT_EN_MM_CLR, - MT8188_TOP_AXI_PROT_EN_MM_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_VDOSYS0_STEP2, - MT8188_TOP_AXI_PROT_EN_SET, - MT8188_TOP_AXI_PROT_EN_CLR, - MT8188_TOP_AXI_PROT_EN_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VDOSYS0_STEP3, - MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET, - MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR, - MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA), - }, - }, - [MT8188_POWER_DOMAIN_VDOSYS1] = { - .name = "vdosys1", - .sta_mask = BIT(14), - .ctl_offs = 0x36C, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDOSYS1_STEP1, - MT8188_TOP_AXI_PROT_EN_MM_SET, - MT8188_TOP_AXI_PROT_EN_MM_CLR, - MT8188_TOP_AXI_PROT_EN_MM_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDOSYS1_STEP2, - MT8188_TOP_AXI_PROT_EN_MM_SET, - MT8188_TOP_AXI_PROT_EN_MM_CLR, - MT8188_TOP_AXI_PROT_EN_MM_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VDOSYS1_STEP3, - MT8188_TOP_AXI_PROT_EN_MM_2_SET, - MT8188_TOP_AXI_PROT_EN_MM_2_CLR, - MT8188_TOP_AXI_PROT_EN_MM_2_STA), - }, - }, - [MT8188_POWER_DOMAIN_DP_TX] = { - .name = "dp_tx", - .sta_mask = BIT(16), - .ctl_offs = 0x374, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_DP_TX_STEP1, - MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET, - MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR, - MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8188_POWER_DOMAIN_EDP_TX] = { - .name = "edp_tx", - .sta_mask = BIT(17), - .ctl_offs = 0x378, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_EDP_TX_STEP1, - MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET, - MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR, - MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8188_POWER_DOMAIN_VPPSYS1] = { - .name = "vppsys1", - .sta_mask = BIT(12), - .ctl_offs = 0x364, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VPPSYS1_STEP1, - MT8188_TOP_AXI_PROT_EN_MM_SET, - MT8188_TOP_AXI_PROT_EN_MM_CLR, - MT8188_TOP_AXI_PROT_EN_MM_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VPPSYS1_STEP2, - MT8188_TOP_AXI_PROT_EN_MM_SET, - MT8188_TOP_AXI_PROT_EN_MM_CLR, - MT8188_TOP_AXI_PROT_EN_MM_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS1_STEP3, - MT8188_TOP_AXI_PROT_EN_MM_2_SET, - MT8188_TOP_AXI_PROT_EN_MM_2_CLR, - MT8188_TOP_AXI_PROT_EN_MM_2_STA), - }, - }, - [MT8188_POWER_DOMAIN_WPE] = { - .name = "wpe", - .sta_mask = BIT(15), - .ctl_offs = 0x370, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_WPE_STEP1, - MT8188_TOP_AXI_PROT_EN_MM_2_SET, - MT8188_TOP_AXI_PROT_EN_MM_2_CLR, - MT8188_TOP_AXI_PROT_EN_MM_2_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_WPE_STEP2, - MT8188_TOP_AXI_PROT_EN_MM_2_SET, - MT8188_TOP_AXI_PROT_EN_MM_2_CLR, - MT8188_TOP_AXI_PROT_EN_MM_2_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8188_POWER_DOMAIN_VDEC0] = { - .name = "vdec0", - .sta_mask = BIT(19), - .ctl_offs = 0x380, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDEC0_STEP1, - MT8188_TOP_AXI_PROT_EN_MM_SET, - MT8188_TOP_AXI_PROT_EN_MM_CLR, - MT8188_TOP_AXI_PROT_EN_MM_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VDEC0_STEP2, - MT8188_TOP_AXI_PROT_EN_MM_2_SET, - MT8188_TOP_AXI_PROT_EN_MM_2_CLR, - MT8188_TOP_AXI_PROT_EN_MM_2_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8188_POWER_DOMAIN_VDEC1] = { - .name = "vdec1", - .sta_mask = BIT(20), - .ctl_offs = 0x384, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDEC1_STEP1, - MT8188_TOP_AXI_PROT_EN_MM_SET, - MT8188_TOP_AXI_PROT_EN_MM_CLR, - MT8188_TOP_AXI_PROT_EN_MM_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDEC1_STEP2, - MT8188_TOP_AXI_PROT_EN_MM_SET, - MT8188_TOP_AXI_PROT_EN_MM_CLR, - MT8188_TOP_AXI_PROT_EN_MM_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8188_POWER_DOMAIN_VENC] = { - .name = "venc", - .sta_mask = BIT(22), - .ctl_offs = 0x38C, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VENC_STEP1, - MT8188_TOP_AXI_PROT_EN_MM_SET, - MT8188_TOP_AXI_PROT_EN_MM_CLR, - MT8188_TOP_AXI_PROT_EN_MM_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VENC_STEP2, - MT8188_TOP_AXI_PROT_EN_MM_SET, - MT8188_TOP_AXI_PROT_EN_MM_CLR, - MT8188_TOP_AXI_PROT_EN_MM_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VENC_STEP3, - MT8188_TOP_AXI_PROT_EN_MM_2_SET, - MT8188_TOP_AXI_PROT_EN_MM_2_CLR, - MT8188_TOP_AXI_PROT_EN_MM_2_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8188_POWER_DOMAIN_IMG_VCORE] = { - .name = "vcore", - .sta_mask = BIT(28), - .ctl_offs = 0x3A4, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_IMG_VCORE_STEP1, - MT8188_TOP_AXI_PROT_EN_MM_SET, - MT8188_TOP_AXI_PROT_EN_MM_CLR, - MT8188_TOP_AXI_PROT_EN_MM_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_IMG_VCORE_STEP2, - MT8188_TOP_AXI_PROT_EN_MM_SET, - MT8188_TOP_AXI_PROT_EN_MM_CLR, - MT8188_TOP_AXI_PROT_EN_MM_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_IMG_VCORE_STEP3, - MT8188_TOP_AXI_PROT_EN_MM_2_SET, - MT8188_TOP_AXI_PROT_EN_MM_2_CLR, - MT8188_TOP_AXI_PROT_EN_MM_2_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY, - }, - [MT8188_POWER_DOMAIN_IMG_MAIN] = { - .name = "img_main", - .sta_mask = BIT(29), - .ctl_offs = 0x3A8, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_IMG_MAIN_STEP1, - MT8188_TOP_AXI_PROT_EN_MM_2_SET, - MT8188_TOP_AXI_PROT_EN_MM_2_CLR, - MT8188_TOP_AXI_PROT_EN_MM_2_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_IMG_MAIN_STEP2, - MT8188_TOP_AXI_PROT_EN_MM_2_SET, - MT8188_TOP_AXI_PROT_EN_MM_2_CLR, - MT8188_TOP_AXI_PROT_EN_MM_2_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8188_POWER_DOMAIN_DIP] = { - .name = "dip", - .sta_mask = BIT(30), - .ctl_offs = 0x3AC, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8188_POWER_DOMAIN_IPE] = { - .name = "ipe", - .sta_mask = BIT(31), - .ctl_offs = 0x3B0, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8188_POWER_DOMAIN_CAM_VCORE] = { - .name = "cam_vcore", - .sta_mask = BIT(27), - .ctl_offs = 0x3A0, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_CAM_VCORE_STEP1, - MT8188_TOP_AXI_PROT_EN_MM_SET, - MT8188_TOP_AXI_PROT_EN_MM_CLR, - MT8188_TOP_AXI_PROT_EN_MM_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_CAM_VCORE_STEP2, - MT8188_TOP_AXI_PROT_EN_2_SET, - MT8188_TOP_AXI_PROT_EN_2_CLR, - MT8188_TOP_AXI_PROT_EN_2_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_1_CAM_VCORE_STEP3, - MT8188_TOP_AXI_PROT_EN_1_SET, - MT8188_TOP_AXI_PROT_EN_1_CLR, - MT8188_TOP_AXI_PROT_EN_1_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_CAM_VCORE_STEP4, - MT8188_TOP_AXI_PROT_EN_MM_SET, - MT8188_TOP_AXI_PROT_EN_MM_CLR, - MT8188_TOP_AXI_PROT_EN_MM_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_CAM_VCORE_STEP5, - MT8188_TOP_AXI_PROT_EN_MM_2_SET, - MT8188_TOP_AXI_PROT_EN_MM_2_CLR, - MT8188_TOP_AXI_PROT_EN_MM_2_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY, - }, - [MT8188_POWER_DOMAIN_CAM_MAIN] = { - .name = "cam_main", - .sta_mask = BIT(24), - .ctl_offs = 0x394, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .bp_infracfg = { - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_CAM_MAIN_STEP1, - MT8188_TOP_AXI_PROT_EN_MM_2_SET, - MT8188_TOP_AXI_PROT_EN_MM_2_CLR, - MT8188_TOP_AXI_PROT_EN_MM_2_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_CAM_MAIN_STEP2, - MT8188_TOP_AXI_PROT_EN_2_SET, - MT8188_TOP_AXI_PROT_EN_2_CLR, - MT8188_TOP_AXI_PROT_EN_2_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_CAM_MAIN_STEP3, - MT8188_TOP_AXI_PROT_EN_MM_2_SET, - MT8188_TOP_AXI_PROT_EN_MM_2_CLR, - MT8188_TOP_AXI_PROT_EN_MM_2_STA), - BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_CAM_MAIN_STEP4, - MT8188_TOP_AXI_PROT_EN_2_SET, - MT8188_TOP_AXI_PROT_EN_2_CLR, - MT8188_TOP_AXI_PROT_EN_2_STA), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8188_POWER_DOMAIN_CAM_SUBA] = { - .name = "cam_suba", - .sta_mask = BIT(25), - .ctl_offs = 0x398, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8188_POWER_DOMAIN_CAM_SUBB] = { - .name = "cam_subb", - .sta_mask = BIT(26), - .ctl_offs = 0x39C, - .pwr_sta_offs = 0x16C, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = BIT(8), - .sram_pdn_ack_bits = BIT(12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, -}; - -static const struct scpsys_soc_data mt8188_scpsys_data = { - .domains_data = scpsys_domain_data_mt8188, - .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8188), -}; - -#endif /* __SOC_MEDIATEK_MT8188_PM_DOMAINS_H */ diff --git a/drivers/soc/mediatek/mt8192-pm-domains.h b/drivers/soc/mediatek/mt8192-pm-domains.h deleted file mode 100644 index b97b2051920f..000000000000 --- a/drivers/soc/mediatek/mt8192-pm-domains.h +++ /dev/null @@ -1,355 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#ifndef __SOC_MEDIATEK_MT8192_PM_DOMAINS_H -#define __SOC_MEDIATEK_MT8192_PM_DOMAINS_H - -#include "mtk-pm-domains.h" -#include <dt-bindings/power/mt8192-power.h> - -/* - * MT8192 power domain support - */ - -static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { - [MT8192_POWER_DOMAIN_AUDIO] = { - .name = "audio", - .sta_mask = BIT(21), - .ctl_offs = 0x0354, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_AUDIO, - MT8192_TOP_AXI_PROT_EN_2_SET, - MT8192_TOP_AXI_PROT_EN_2_CLR, - MT8192_TOP_AXI_PROT_EN_2_STA1), - }, - }, - [MT8192_POWER_DOMAIN_CONN] = { - .name = "conn", - .sta_mask = PWR_STATUS_CONN, - .ctl_offs = 0x0304, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = 0, - .sram_pdn_ack_bits = 0, - .bp_infracfg = { - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_CONN, - MT8192_TOP_AXI_PROT_EN_SET, - MT8192_TOP_AXI_PROT_EN_CLR, - MT8192_TOP_AXI_PROT_EN_STA1), - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_CONN_2ND, - MT8192_TOP_AXI_PROT_EN_SET, - MT8192_TOP_AXI_PROT_EN_CLR, - MT8192_TOP_AXI_PROT_EN_STA1), - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_1_CONN, - MT8192_TOP_AXI_PROT_EN_1_SET, - MT8192_TOP_AXI_PROT_EN_1_CLR, - MT8192_TOP_AXI_PROT_EN_1_STA1), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8192_POWER_DOMAIN_MFG0] = { - .name = "mfg0", - .sta_mask = BIT(2), - .ctl_offs = 0x0308, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .caps = MTK_SCPD_DOMAIN_SUPPLY, - }, - [MT8192_POWER_DOMAIN_MFG1] = { - .name = "mfg1", - .sta_mask = BIT(3), - .ctl_offs = 0x030c, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_1_MFG1, - MT8192_TOP_AXI_PROT_EN_1_SET, - MT8192_TOP_AXI_PROT_EN_1_CLR, - MT8192_TOP_AXI_PROT_EN_1_STA1), - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_MFG1, - MT8192_TOP_AXI_PROT_EN_2_SET, - MT8192_TOP_AXI_PROT_EN_2_CLR, - MT8192_TOP_AXI_PROT_EN_2_STA1), - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MFG1, - MT8192_TOP_AXI_PROT_EN_SET, - MT8192_TOP_AXI_PROT_EN_CLR, - MT8192_TOP_AXI_PROT_EN_STA1), - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_MFG1_2ND, - MT8192_TOP_AXI_PROT_EN_2_SET, - MT8192_TOP_AXI_PROT_EN_2_CLR, - MT8192_TOP_AXI_PROT_EN_2_STA1), - }, - .caps = MTK_SCPD_DOMAIN_SUPPLY, - }, - [MT8192_POWER_DOMAIN_MFG2] = { - .name = "mfg2", - .sta_mask = BIT(4), - .ctl_offs = 0x0310, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - }, - [MT8192_POWER_DOMAIN_MFG3] = { - .name = "mfg3", - .sta_mask = BIT(5), - .ctl_offs = 0x0314, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - }, - [MT8192_POWER_DOMAIN_MFG4] = { - .name = "mfg4", - .sta_mask = BIT(6), - .ctl_offs = 0x0318, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - }, - [MT8192_POWER_DOMAIN_MFG5] = { - .name = "mfg5", - .sta_mask = BIT(7), - .ctl_offs = 0x031c, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - }, - [MT8192_POWER_DOMAIN_MFG6] = { - .name = "mfg6", - .sta_mask = BIT(8), - .ctl_offs = 0x0320, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - }, - [MT8192_POWER_DOMAIN_DISP] = { - .name = "disp", - .sta_mask = BIT(20), - .ctl_offs = 0x0350, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR_IGN(MT8192_TOP_AXI_PROT_EN_MM_DISP, - MT8192_TOP_AXI_PROT_EN_MM_SET, - MT8192_TOP_AXI_PROT_EN_MM_CLR, - MT8192_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR_IGN(MT8192_TOP_AXI_PROT_EN_MM_2_DISP, - MT8192_TOP_AXI_PROT_EN_MM_2_SET, - MT8192_TOP_AXI_PROT_EN_MM_2_CLR, - MT8192_TOP_AXI_PROT_EN_MM_2_STA1), - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_DISP, - MT8192_TOP_AXI_PROT_EN_SET, - MT8192_TOP_AXI_PROT_EN_CLR, - MT8192_TOP_AXI_PROT_EN_STA1), - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_DISP_2ND, - MT8192_TOP_AXI_PROT_EN_MM_SET, - MT8192_TOP_AXI_PROT_EN_MM_CLR, - MT8192_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_DISP_2ND, - MT8192_TOP_AXI_PROT_EN_MM_2_SET, - MT8192_TOP_AXI_PROT_EN_MM_2_CLR, - MT8192_TOP_AXI_PROT_EN_MM_2_STA1), - }, - }, - [MT8192_POWER_DOMAIN_IPE] = { - .name = "ipe", - .sta_mask = BIT(14), - .ctl_offs = 0x0338, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_IPE, - MT8192_TOP_AXI_PROT_EN_MM_SET, - MT8192_TOP_AXI_PROT_EN_MM_CLR, - MT8192_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_IPE_2ND, - MT8192_TOP_AXI_PROT_EN_MM_SET, - MT8192_TOP_AXI_PROT_EN_MM_CLR, - MT8192_TOP_AXI_PROT_EN_MM_STA1), - }, - }, - [MT8192_POWER_DOMAIN_ISP] = { - .name = "isp", - .sta_mask = BIT(12), - .ctl_offs = 0x0330, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_ISP, - MT8192_TOP_AXI_PROT_EN_MM_2_SET, - MT8192_TOP_AXI_PROT_EN_MM_2_CLR, - MT8192_TOP_AXI_PROT_EN_MM_2_STA1), - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_ISP_2ND, - MT8192_TOP_AXI_PROT_EN_MM_2_SET, - MT8192_TOP_AXI_PROT_EN_MM_2_CLR, - MT8192_TOP_AXI_PROT_EN_MM_2_STA1), - }, - }, - [MT8192_POWER_DOMAIN_ISP2] = { - .name = "isp2", - .sta_mask = BIT(13), - .ctl_offs = 0x0334, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_ISP2, - MT8192_TOP_AXI_PROT_EN_MM_SET, - MT8192_TOP_AXI_PROT_EN_MM_CLR, - MT8192_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_ISP2_2ND, - MT8192_TOP_AXI_PROT_EN_MM_SET, - MT8192_TOP_AXI_PROT_EN_MM_CLR, - MT8192_TOP_AXI_PROT_EN_MM_STA1), - }, - }, - [MT8192_POWER_DOMAIN_MDP] = { - .name = "mdp", - .sta_mask = BIT(19), - .ctl_offs = 0x034c, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_MDP, - MT8192_TOP_AXI_PROT_EN_MM_2_SET, - MT8192_TOP_AXI_PROT_EN_MM_2_CLR, - MT8192_TOP_AXI_PROT_EN_MM_2_STA1), - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_MDP_2ND, - MT8192_TOP_AXI_PROT_EN_MM_2_SET, - MT8192_TOP_AXI_PROT_EN_MM_2_CLR, - MT8192_TOP_AXI_PROT_EN_MM_2_STA1), - }, - }, - [MT8192_POWER_DOMAIN_VENC] = { - .name = "venc", - .sta_mask = BIT(17), - .ctl_offs = 0x0344, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VENC, - MT8192_TOP_AXI_PROT_EN_MM_SET, - MT8192_TOP_AXI_PROT_EN_MM_CLR, - MT8192_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VENC_2ND, - MT8192_TOP_AXI_PROT_EN_MM_SET, - MT8192_TOP_AXI_PROT_EN_MM_CLR, - MT8192_TOP_AXI_PROT_EN_MM_STA1), - }, - }, - [MT8192_POWER_DOMAIN_VDEC] = { - .name = "vdec", - .sta_mask = BIT(15), - .ctl_offs = 0x033c, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VDEC, - MT8192_TOP_AXI_PROT_EN_MM_SET, - MT8192_TOP_AXI_PROT_EN_MM_CLR, - MT8192_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VDEC_2ND, - MT8192_TOP_AXI_PROT_EN_MM_SET, - MT8192_TOP_AXI_PROT_EN_MM_CLR, - MT8192_TOP_AXI_PROT_EN_MM_STA1), - }, - }, - [MT8192_POWER_DOMAIN_VDEC2] = { - .name = "vdec2", - .sta_mask = BIT(16), - .ctl_offs = 0x0340, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - }, - [MT8192_POWER_DOMAIN_CAM] = { - .name = "cam", - .sta_mask = BIT(23), - .ctl_offs = 0x035c, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_CAM, - MT8192_TOP_AXI_PROT_EN_2_SET, - MT8192_TOP_AXI_PROT_EN_2_CLR, - MT8192_TOP_AXI_PROT_EN_2_STA1), - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_CAM, - MT8192_TOP_AXI_PROT_EN_MM_SET, - MT8192_TOP_AXI_PROT_EN_MM_CLR, - MT8192_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_1_CAM, - MT8192_TOP_AXI_PROT_EN_1_SET, - MT8192_TOP_AXI_PROT_EN_1_CLR, - MT8192_TOP_AXI_PROT_EN_1_STA1), - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_CAM_2ND, - MT8192_TOP_AXI_PROT_EN_MM_SET, - MT8192_TOP_AXI_PROT_EN_MM_CLR, - MT8192_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_VDNR_CAM, - MT8192_TOP_AXI_PROT_EN_VDNR_SET, - MT8192_TOP_AXI_PROT_EN_VDNR_CLR, - MT8192_TOP_AXI_PROT_EN_VDNR_STA1), - }, - }, - [MT8192_POWER_DOMAIN_CAM_RAWA] = { - .name = "cam_rawa", - .sta_mask = BIT(24), - .ctl_offs = 0x0360, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - }, - [MT8192_POWER_DOMAIN_CAM_RAWB] = { - .name = "cam_rawb", - .sta_mask = BIT(25), - .ctl_offs = 0x0364, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - }, - [MT8192_POWER_DOMAIN_CAM_RAWC] = { - .name = "cam_rawc", - .sta_mask = BIT(26), - .ctl_offs = 0x0368, - .pwr_sta_offs = 0x016c, - .pwr_sta2nd_offs = 0x0170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - }, -}; - -static const struct scpsys_soc_data mt8192_scpsys_data = { - .domains_data = scpsys_domain_data_mt8192, - .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8192), -}; - -#endif /* __SOC_MEDIATEK_MT8192_PM_DOMAINS_H */ diff --git a/drivers/soc/mediatek/mt8195-pm-domains.h b/drivers/soc/mediatek/mt8195-pm-domains.h deleted file mode 100644 index d7387ea1b9c9..000000000000 --- a/drivers/soc/mediatek/mt8195-pm-domains.h +++ /dev/null @@ -1,613 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2021 MediaTek Inc. - * Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> - */ - -#ifndef __SOC_MEDIATEK_MT8195_PM_DOMAINS_H -#define __SOC_MEDIATEK_MT8195_PM_DOMAINS_H - -#include "mtk-pm-domains.h" -#include <dt-bindings/power/mt8195-power.h> - -/* - * MT8195 power domain support - */ - -static const struct scpsys_domain_data scpsys_domain_data_mt8195[] = { - [MT8195_POWER_DOMAIN_PCIE_MAC_P0] = { - .name = "pcie_mac_p0", - .sta_mask = BIT(11), - .ctl_offs = 0x328, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_PCIE_MAC_P0, - MT8195_TOP_AXI_PROT_EN_VDNR_SET, - MT8195_TOP_AXI_PROT_EN_VDNR_CLR, - MT8195_TOP_AXI_PROT_EN_VDNR_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_1_PCIE_MAC_P0, - MT8195_TOP_AXI_PROT_EN_VDNR_1_SET, - MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR, - MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1), - }, - }, - [MT8195_POWER_DOMAIN_PCIE_MAC_P1] = { - .name = "pcie_mac_p1", - .sta_mask = BIT(12), - .ctl_offs = 0x32C, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_PCIE_MAC_P1, - MT8195_TOP_AXI_PROT_EN_VDNR_SET, - MT8195_TOP_AXI_PROT_EN_VDNR_CLR, - MT8195_TOP_AXI_PROT_EN_VDNR_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_1_PCIE_MAC_P1, - MT8195_TOP_AXI_PROT_EN_VDNR_1_SET, - MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR, - MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1), - }, - }, - [MT8195_POWER_DOMAIN_PCIE_PHY] = { - .name = "pcie_phy", - .sta_mask = BIT(13), - .ctl_offs = 0x330, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT8195_POWER_DOMAIN_SSUSB_PCIE_PHY] = { - .name = "ssusb_pcie_phy", - .sta_mask = BIT(14), - .ctl_offs = 0x334, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .caps = MTK_SCPD_ACTIVE_WAKEUP | MTK_SCPD_ALWAYS_ON, - }, - [MT8195_POWER_DOMAIN_CSI_RX_TOP] = { - .name = "csi_rx_top", - .sta_mask = BIT(18), - .ctl_offs = 0x3C4, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_ETHER] = { - .name = "ether", - .sta_mask = BIT(3), - .ctl_offs = 0x344, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT8195_POWER_DOMAIN_ADSP] = { - .name = "adsp", - .sta_mask = BIT(10), - .ctl_offs = 0x360, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_ADSP, - MT8195_TOP_AXI_PROT_EN_2_SET, - MT8195_TOP_AXI_PROT_EN_2_CLR, - MT8195_TOP_AXI_PROT_EN_2_STA1), - }, - .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT8195_POWER_DOMAIN_AUDIO] = { - .name = "audio", - .sta_mask = BIT(8), - .ctl_offs = 0x358, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_AUDIO, - MT8195_TOP_AXI_PROT_EN_2_SET, - MT8195_TOP_AXI_PROT_EN_2_CLR, - MT8195_TOP_AXI_PROT_EN_2_STA1), - }, - }, - [MT8195_POWER_DOMAIN_MFG0] = { - .name = "mfg0", - .sta_mask = BIT(1), - .ctl_offs = 0x300, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY, - }, - [MT8195_POWER_DOMAIN_MFG1] = { - .name = "mfg1", - .sta_mask = BIT(2), - .ctl_offs = 0x304, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MFG1, - MT8195_TOP_AXI_PROT_EN_SET, - MT8195_TOP_AXI_PROT_EN_CLR, - MT8195_TOP_AXI_PROT_EN_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_MFG1, - MT8195_TOP_AXI_PROT_EN_2_SET, - MT8195_TOP_AXI_PROT_EN_2_CLR, - MT8195_TOP_AXI_PROT_EN_2_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_1_MFG1, - MT8195_TOP_AXI_PROT_EN_1_SET, - MT8195_TOP_AXI_PROT_EN_1_CLR, - MT8195_TOP_AXI_PROT_EN_1_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_MFG1_2ND, - MT8195_TOP_AXI_PROT_EN_2_SET, - MT8195_TOP_AXI_PROT_EN_2_CLR, - MT8195_TOP_AXI_PROT_EN_2_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MFG1_2ND, - MT8195_TOP_AXI_PROT_EN_SET, - MT8195_TOP_AXI_PROT_EN_CLR, - MT8195_TOP_AXI_PROT_EN_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_MFG1, - MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET, - MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR, - MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY, - }, - [MT8195_POWER_DOMAIN_MFG2] = { - .name = "mfg2", - .sta_mask = BIT(3), - .ctl_offs = 0x308, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_MFG3] = { - .name = "mfg3", - .sta_mask = BIT(4), - .ctl_offs = 0x30C, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_MFG4] = { - .name = "mfg4", - .sta_mask = BIT(5), - .ctl_offs = 0x310, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_MFG5] = { - .name = "mfg5", - .sta_mask = BIT(6), - .ctl_offs = 0x314, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_MFG6] = { - .name = "mfg6", - .sta_mask = BIT(7), - .ctl_offs = 0x318, - .pwr_sta_offs = 0x174, - .pwr_sta2nd_offs = 0x178, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_VPPSYS0] = { - .name = "vppsys0", - .sta_mask = BIT(11), - .ctl_offs = 0x364, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VPPSYS0, - MT8195_TOP_AXI_PROT_EN_SET, - MT8195_TOP_AXI_PROT_EN_CLR, - MT8195_TOP_AXI_PROT_EN_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VPPSYS0, - MT8195_TOP_AXI_PROT_EN_MM_2_SET, - MT8195_TOP_AXI_PROT_EN_MM_2_CLR, - MT8195_TOP_AXI_PROT_EN_MM_2_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VPPSYS0_2ND, - MT8195_TOP_AXI_PROT_EN_SET, - MT8195_TOP_AXI_PROT_EN_CLR, - MT8195_TOP_AXI_PROT_EN_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VPPSYS0_2ND, - MT8195_TOP_AXI_PROT_EN_MM_2_SET, - MT8195_TOP_AXI_PROT_EN_MM_2_CLR, - MT8195_TOP_AXI_PROT_EN_MM_2_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VPPSYS0, - MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET, - MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR, - MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1), - }, - }, - [MT8195_POWER_DOMAIN_VDOSYS0] = { - .name = "vdosys0", - .sta_mask = BIT(13), - .ctl_offs = 0x36C, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDOSYS0, - MT8195_TOP_AXI_PROT_EN_MM_SET, - MT8195_TOP_AXI_PROT_EN_MM_CLR, - MT8195_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDOSYS0, - MT8195_TOP_AXI_PROT_EN_SET, - MT8195_TOP_AXI_PROT_EN_CLR, - MT8195_TOP_AXI_PROT_EN_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VDOSYS0, - MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET, - MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR, - MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1), - }, - }, - [MT8195_POWER_DOMAIN_VPPSYS1] = { - .name = "vppsys1", - .sta_mask = BIT(12), - .ctl_offs = 0x368, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VPPSYS1, - MT8195_TOP_AXI_PROT_EN_MM_SET, - MT8195_TOP_AXI_PROT_EN_MM_CLR, - MT8195_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VPPSYS1_2ND, - MT8195_TOP_AXI_PROT_EN_MM_SET, - MT8195_TOP_AXI_PROT_EN_MM_CLR, - MT8195_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VPPSYS1, - MT8195_TOP_AXI_PROT_EN_MM_2_SET, - MT8195_TOP_AXI_PROT_EN_MM_2_CLR, - MT8195_TOP_AXI_PROT_EN_MM_2_STA1), - }, - }, - [MT8195_POWER_DOMAIN_VDOSYS1] = { - .name = "vdosys1", - .sta_mask = BIT(14), - .ctl_offs = 0x370, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDOSYS1, - MT8195_TOP_AXI_PROT_EN_MM_SET, - MT8195_TOP_AXI_PROT_EN_MM_CLR, - MT8195_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDOSYS1_2ND, - MT8195_TOP_AXI_PROT_EN_MM_SET, - MT8195_TOP_AXI_PROT_EN_MM_CLR, - MT8195_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDOSYS1, - MT8195_TOP_AXI_PROT_EN_MM_2_SET, - MT8195_TOP_AXI_PROT_EN_MM_2_CLR, - MT8195_TOP_AXI_PROT_EN_MM_2_STA1), - }, - }, - [MT8195_POWER_DOMAIN_DP_TX] = { - .name = "dp_tx", - .sta_mask = BIT(16), - .ctl_offs = 0x378, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_1_DP_TX, - MT8195_TOP_AXI_PROT_EN_VDNR_1_SET, - MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR, - MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_EPD_TX] = { - .name = "epd_tx", - .sta_mask = BIT(17), - .ctl_offs = 0x37C, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_1_EPD_TX, - MT8195_TOP_AXI_PROT_EN_VDNR_1_SET, - MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR, - MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_HDMI_TX] = { - .name = "hdmi_tx", - .sta_mask = BIT(18), - .ctl_offs = 0x380, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT8195_POWER_DOMAIN_WPESYS] = { - .name = "wpesys", - .sta_mask = BIT(15), - .ctl_offs = 0x374, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_WPESYS, - MT8195_TOP_AXI_PROT_EN_MM_2_SET, - MT8195_TOP_AXI_PROT_EN_MM_2_CLR, - MT8195_TOP_AXI_PROT_EN_MM_2_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_WPESYS, - MT8195_TOP_AXI_PROT_EN_MM_SET, - MT8195_TOP_AXI_PROT_EN_MM_CLR, - MT8195_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_WPESYS_2ND, - MT8195_TOP_AXI_PROT_EN_MM_2_SET, - MT8195_TOP_AXI_PROT_EN_MM_2_CLR, - MT8195_TOP_AXI_PROT_EN_MM_2_STA1), - }, - }, - [MT8195_POWER_DOMAIN_VDEC0] = { - .name = "vdec0", - .sta_mask = BIT(20), - .ctl_offs = 0x388, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDEC0, - MT8195_TOP_AXI_PROT_EN_MM_SET, - MT8195_TOP_AXI_PROT_EN_MM_CLR, - MT8195_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDEC0, - MT8195_TOP_AXI_PROT_EN_MM_2_SET, - MT8195_TOP_AXI_PROT_EN_MM_2_CLR, - MT8195_TOP_AXI_PROT_EN_MM_2_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDEC0_2ND, - MT8195_TOP_AXI_PROT_EN_MM_SET, - MT8195_TOP_AXI_PROT_EN_MM_CLR, - MT8195_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDEC0_2ND, - MT8195_TOP_AXI_PROT_EN_MM_2_SET, - MT8195_TOP_AXI_PROT_EN_MM_2_CLR, - MT8195_TOP_AXI_PROT_EN_MM_2_STA1), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_VDEC1] = { - .name = "vdec1", - .sta_mask = BIT(21), - .ctl_offs = 0x38C, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDEC1, - MT8195_TOP_AXI_PROT_EN_MM_SET, - MT8195_TOP_AXI_PROT_EN_MM_CLR, - MT8195_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDEC1_2ND, - MT8195_TOP_AXI_PROT_EN_MM_SET, - MT8195_TOP_AXI_PROT_EN_MM_CLR, - MT8195_TOP_AXI_PROT_EN_MM_STA1), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_VDEC2] = { - .name = "vdec2", - .sta_mask = BIT(22), - .ctl_offs = 0x390, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDEC2, - MT8195_TOP_AXI_PROT_EN_MM_2_SET, - MT8195_TOP_AXI_PROT_EN_MM_2_CLR, - MT8195_TOP_AXI_PROT_EN_MM_2_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDEC2_2ND, - MT8195_TOP_AXI_PROT_EN_MM_2_SET, - MT8195_TOP_AXI_PROT_EN_MM_2_CLR, - MT8195_TOP_AXI_PROT_EN_MM_2_STA1), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_VENC] = { - .name = "venc", - .sta_mask = BIT(23), - .ctl_offs = 0x394, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VENC, - MT8195_TOP_AXI_PROT_EN_MM_SET, - MT8195_TOP_AXI_PROT_EN_MM_CLR, - MT8195_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VENC_2ND, - MT8195_TOP_AXI_PROT_EN_MM_SET, - MT8195_TOP_AXI_PROT_EN_MM_CLR, - MT8195_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VENC, - MT8195_TOP_AXI_PROT_EN_MM_2_SET, - MT8195_TOP_AXI_PROT_EN_MM_2_CLR, - MT8195_TOP_AXI_PROT_EN_MM_2_STA1), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_VENC_CORE1] = { - .name = "venc_core1", - .sta_mask = BIT(24), - .ctl_offs = 0x398, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VENC_CORE1, - MT8195_TOP_AXI_PROT_EN_MM_SET, - MT8195_TOP_AXI_PROT_EN_MM_CLR, - MT8195_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VENC_CORE1, - MT8195_TOP_AXI_PROT_EN_MM_2_SET, - MT8195_TOP_AXI_PROT_EN_MM_2_CLR, - MT8195_TOP_AXI_PROT_EN_MM_2_STA1), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_IMG] = { - .name = "img", - .sta_mask = BIT(29), - .ctl_offs = 0x3AC, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_IMG, - MT8195_TOP_AXI_PROT_EN_MM_SET, - MT8195_TOP_AXI_PROT_EN_MM_CLR, - MT8195_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_IMG_2ND, - MT8195_TOP_AXI_PROT_EN_MM_SET, - MT8195_TOP_AXI_PROT_EN_MM_CLR, - MT8195_TOP_AXI_PROT_EN_MM_STA1), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_DIP] = { - .name = "dip", - .sta_mask = BIT(30), - .ctl_offs = 0x3B0, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_IPE] = { - .name = "ipe", - .sta_mask = BIT(31), - .ctl_offs = 0x3B4, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_IPE, - MT8195_TOP_AXI_PROT_EN_MM_SET, - MT8195_TOP_AXI_PROT_EN_MM_CLR, - MT8195_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_IPE, - MT8195_TOP_AXI_PROT_EN_MM_2_SET, - MT8195_TOP_AXI_PROT_EN_MM_2_CLR, - MT8195_TOP_AXI_PROT_EN_MM_2_STA1), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_CAM] = { - .name = "cam", - .sta_mask = BIT(25), - .ctl_offs = 0x39C, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .bp_infracfg = { - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_CAM, - MT8195_TOP_AXI_PROT_EN_2_SET, - MT8195_TOP_AXI_PROT_EN_2_CLR, - MT8195_TOP_AXI_PROT_EN_2_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_CAM, - MT8195_TOP_AXI_PROT_EN_MM_SET, - MT8195_TOP_AXI_PROT_EN_MM_CLR, - MT8195_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_1_CAM, - MT8195_TOP_AXI_PROT_EN_1_SET, - MT8195_TOP_AXI_PROT_EN_1_CLR, - MT8195_TOP_AXI_PROT_EN_1_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_CAM_2ND, - MT8195_TOP_AXI_PROT_EN_MM_SET, - MT8195_TOP_AXI_PROT_EN_MM_CLR, - MT8195_TOP_AXI_PROT_EN_MM_STA1), - BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_CAM, - MT8195_TOP_AXI_PROT_EN_MM_2_SET, - MT8195_TOP_AXI_PROT_EN_MM_2_CLR, - MT8195_TOP_AXI_PROT_EN_MM_2_STA1), - }, - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_CAM_RAWA] = { - .name = "cam_rawa", - .sta_mask = BIT(26), - .ctl_offs = 0x3A0, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_CAM_RAWB] = { - .name = "cam_rawb", - .sta_mask = BIT(27), - .ctl_offs = 0x3A4, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, - [MT8195_POWER_DOMAIN_CAM_MRAW] = { - .name = "cam_mraw", - .sta_mask = BIT(28), - .ctl_offs = 0x3A8, - .pwr_sta_offs = 0x16c, - .pwr_sta2nd_offs = 0x170, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .caps = MTK_SCPD_KEEP_DEFAULT_OFF, - }, -}; - -static const struct scpsys_soc_data mt8195_scpsys_data = { - .domains_data = scpsys_domain_data_mt8195, - .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8195), -}; - -#endif /* __SOC_MEDIATEK_MT8195_PM_DOMAINS_H */ diff --git a/drivers/soc/mediatek/mtk-pm-domains.c b/drivers/soc/mediatek/mtk-pm-domains.c deleted file mode 100644 index 354249cc1b12..000000000000 --- a/drivers/soc/mediatek/mtk-pm-domains.c +++ /dev/null @@ -1,688 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2020 Collabora Ltd. - */ -#include <linux/clk.h> -#include <linux/clk-provider.h> -#include <linux/init.h> -#include <linux/io.h> -#include <linux/iopoll.h> -#include <linux/mfd/syscon.h> -#include <linux/of_clk.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <linux/regmap.h> -#include <linux/regulator/consumer.h> -#include <linux/soc/mediatek/infracfg.h> - -#include "mt6795-pm-domains.h" -#include "mt8167-pm-domains.h" -#include "mt8173-pm-domains.h" -#include "mt8183-pm-domains.h" -#include "mt8186-pm-domains.h" -#include "mt8188-pm-domains.h" -#include "mt8192-pm-domains.h" -#include "mt8195-pm-domains.h" - -#define MTK_POLL_DELAY_US 10 -#define MTK_POLL_TIMEOUT USEC_PER_SEC - -#define PWR_RST_B_BIT BIT(0) -#define PWR_ISO_BIT BIT(1) -#define PWR_ON_BIT BIT(2) -#define PWR_ON_2ND_BIT BIT(3) -#define PWR_CLK_DIS_BIT BIT(4) -#define PWR_SRAM_CLKISO_BIT BIT(5) -#define PWR_SRAM_ISOINT_B_BIT BIT(6) - -struct scpsys_domain { - struct generic_pm_domain genpd; - const struct scpsys_domain_data *data; - struct scpsys *scpsys; - int num_clks; - struct clk_bulk_data *clks; - int num_subsys_clks; - struct clk_bulk_data *subsys_clks; - struct regmap *infracfg; - struct regmap *smi; - struct regulator *supply; -}; - -struct scpsys { - struct device *dev; - struct regmap *base; - const struct scpsys_soc_data *soc_data; - struct genpd_onecell_data pd_data; - struct generic_pm_domain *domains[]; -}; - -#define to_scpsys_domain(gpd) container_of(gpd, struct scpsys_domain, genpd) - -static bool scpsys_domain_is_on(struct scpsys_domain *pd) -{ - struct scpsys *scpsys = pd->scpsys; - u32 status, status2; - - regmap_read(scpsys->base, pd->data->pwr_sta_offs, &status); - status &= pd->data->sta_mask; - - regmap_read(scpsys->base, pd->data->pwr_sta2nd_offs, &status2); - status2 &= pd->data->sta_mask; - - /* A domain is on when both status bits are set. */ - return status && status2; -} - -static int scpsys_sram_enable(struct scpsys_domain *pd) -{ - u32 pdn_ack = pd->data->sram_pdn_ack_bits; - struct scpsys *scpsys = pd->scpsys; - unsigned int tmp; - int ret; - - regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits); - - /* Either wait until SRAM_PDN_ACK all 1 or 0 */ - ret = regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp, - (tmp & pdn_ack) == 0, MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); - if (ret < 0) - return ret; - - if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_ISO)) { - regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT); - udelay(1); - regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT); - } - - return 0; -} - -static int scpsys_sram_disable(struct scpsys_domain *pd) -{ - u32 pdn_ack = pd->data->sram_pdn_ack_bits; - struct scpsys *scpsys = pd->scpsys; - unsigned int tmp; - - if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_ISO)) { - regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT); - udelay(1); - regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT); - } - - regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits); - - /* Either wait until SRAM_PDN_ACK all 1 or 0 */ - return regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp, - (tmp & pdn_ack) == pdn_ack, MTK_POLL_DELAY_US, - MTK_POLL_TIMEOUT); -} - -static int _scpsys_bus_protect_enable(const struct scpsys_bus_prot_data *bpd, struct regmap *regmap) -{ - int i, ret; - - for (i = 0; i < SPM_MAX_BUS_PROT_DATA; i++) { - u32 val, mask = bpd[i].bus_prot_mask; - - if (!mask) - break; - - if (bpd[i].bus_prot_reg_update) - regmap_set_bits(regmap, bpd[i].bus_prot_set, mask); - else - regmap_write(regmap, bpd[i].bus_prot_set, mask); - - ret = regmap_read_poll_timeout(regmap, bpd[i].bus_prot_sta, - val, (val & mask) == mask, - MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); - if (ret) - return ret; - } - - return 0; -} - -static int scpsys_bus_protect_enable(struct scpsys_domain *pd) -{ - int ret; - - ret = _scpsys_bus_protect_enable(pd->data->bp_infracfg, pd->infracfg); - if (ret) - return ret; - - return _scpsys_bus_protect_enable(pd->data->bp_smi, pd->smi); -} - -static int _scpsys_bus_protect_disable(const struct scpsys_bus_prot_data *bpd, - struct regmap *regmap) -{ - int i, ret; - - for (i = SPM_MAX_BUS_PROT_DATA - 1; i >= 0; i--) { - u32 val, mask = bpd[i].bus_prot_mask; - - if (!mask) - continue; - - if (bpd[i].bus_prot_reg_update) - regmap_clear_bits(regmap, bpd[i].bus_prot_clr, mask); - else - regmap_write(regmap, bpd[i].bus_prot_clr, mask); - - if (bpd[i].ignore_clr_ack) - continue; - - ret = regmap_read_poll_timeout(regmap, bpd[i].bus_prot_sta, - val, !(val & mask), - MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); - if (ret) - return ret; - } - - return 0; -} - -static int scpsys_bus_protect_disable(struct scpsys_domain *pd) -{ - int ret; - - ret = _scpsys_bus_protect_disable(pd->data->bp_smi, pd->smi); - if (ret) - return ret; - - return _scpsys_bus_protect_disable(pd->data->bp_infracfg, pd->infracfg); -} - -static int scpsys_regulator_enable(struct regulator *supply) -{ - return supply ? regulator_enable(supply) : 0; -} - -static int scpsys_regulator_disable(struct regulator *supply) -{ - return supply ? regulator_disable(supply) : 0; -} - -static int scpsys_power_on(struct generic_pm_domain *genpd) -{ - struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd); - struct scpsys *scpsys = pd->scpsys; - bool tmp; - int ret; - - ret = scpsys_regulator_enable(pd->supply); - if (ret) - return ret; - - ret = clk_bulk_prepare_enable(pd->num_clks, pd->clks); - if (ret) - goto err_reg; - - if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO)) - regmap_clear_bits(scpsys->base, pd->data->ext_buck_iso_offs, - pd->data->ext_buck_iso_mask); - - /* subsys power on */ - regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT); - regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT); - - /* wait until PWR_ACK = 1 */ - ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, tmp, MTK_POLL_DELAY_US, - MTK_POLL_TIMEOUT); - if (ret < 0) - goto err_pwr_ack; - - regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT); - regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT); - regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT); - - ret = clk_bulk_prepare_enable(pd->num_subsys_clks, pd->subsys_clks); - if (ret) - goto err_pwr_ack; - - ret = scpsys_sram_enable(pd); - if (ret < 0) - goto err_disable_subsys_clks; - - ret = scpsys_bus_protect_disable(pd); - if (ret < 0) - goto err_disable_sram; - - return 0; - -err_disable_sram: - scpsys_sram_disable(pd); -err_disable_subsys_clks: - clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks); -err_pwr_ack: - clk_bulk_disable_unprepare(pd->num_clks, pd->clks); -err_reg: - scpsys_regulator_disable(pd->supply); - return ret; -} - -static int scpsys_power_off(struct generic_pm_domain *genpd) -{ - struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd); - struct scpsys *scpsys = pd->scpsys; - bool tmp; - int ret; - - ret = scpsys_bus_protect_enable(pd); - if (ret < 0) - return ret; - - ret = scpsys_sram_disable(pd); - if (ret < 0) - return ret; - - if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO)) - regmap_set_bits(scpsys->base, pd->data->ext_buck_iso_offs, - pd->data->ext_buck_iso_mask); - - clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks); - - /* subsys power off */ - regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT); - regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT); - regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT); - regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT); - regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT); - - /* wait until PWR_ACK = 0 */ - ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, !tmp, MTK_POLL_DELAY_US, - MTK_POLL_TIMEOUT); - if (ret < 0) - return ret; - - clk_bulk_disable_unprepare(pd->num_clks, pd->clks); - - scpsys_regulator_disable(pd->supply); - - return 0; -} - -static struct -generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_node *node) -{ - const struct scpsys_domain_data *domain_data; - struct scpsys_domain *pd; - struct device_node *root_node = scpsys->dev->of_node; - struct device_node *smi_node; - struct property *prop; - const char *clk_name; - int i, ret, num_clks; - struct clk *clk; - int clk_ind = 0; - u32 id; - - ret = of_property_read_u32(node, "reg", &id); - if (ret) { - dev_err(scpsys->dev, "%pOF: failed to retrieve domain id from reg: %d\n", - node, ret); - return ERR_PTR(-EINVAL); - } - - if (id >= scpsys->soc_data->num_domains) { - dev_err(scpsys->dev, "%pOF: invalid domain id %d\n", node, id); - return ERR_PTR(-EINVAL); - } - - domain_data = &scpsys->soc_data->domains_data[id]; - if (domain_data->sta_mask == 0) { - dev_err(scpsys->dev, "%pOF: undefined domain id %d\n", node, id); - return ERR_PTR(-EINVAL); - } - - pd = devm_kzalloc(scpsys->dev, sizeof(*pd), GFP_KERNEL); - if (!pd) - return ERR_PTR(-ENOMEM); - - pd->data = domain_data; - pd->scpsys = scpsys; - - if (MTK_SCPD_CAPS(pd, MTK_SCPD_DOMAIN_SUPPLY)) { - /* - * Find regulator in current power domain node. - * devm_regulator_get() finds regulator in a node and its child - * node, so set of_node to current power domain node then change - * back to original node after regulator is found for current - * power domain node. - */ - scpsys->dev->of_node = node; - pd->supply = devm_regulator_get(scpsys->dev, "domain"); - scpsys->dev->of_node = root_node; - if (IS_ERR(pd->supply)) { - dev_err_probe(scpsys->dev, PTR_ERR(pd->supply), - "%pOF: failed to get power supply.\n", - node); - return ERR_CAST(pd->supply); - } - } - - pd->infracfg = syscon_regmap_lookup_by_phandle_optional(node, "mediatek,infracfg"); - if (IS_ERR(pd->infracfg)) - return ERR_CAST(pd->infracfg); - - smi_node = of_parse_phandle(node, "mediatek,smi", 0); - if (smi_node) { - pd->smi = device_node_to_regmap(smi_node); - of_node_put(smi_node); - if (IS_ERR(pd->smi)) - return ERR_CAST(pd->smi); - } - - num_clks = of_clk_get_parent_count(node); - if (num_clks > 0) { - /* Calculate number of subsys_clks */ - of_property_for_each_string(node, "clock-names", prop, clk_name) { - char *subsys; - - subsys = strchr(clk_name, '-'); - if (subsys) - pd->num_subsys_clks++; - else - pd->num_clks++; - } - - pd->clks = devm_kcalloc(scpsys->dev, pd->num_clks, sizeof(*pd->clks), GFP_KERNEL); - if (!pd->clks) - return ERR_PTR(-ENOMEM); - - pd->subsys_clks = devm_kcalloc(scpsys->dev, pd->num_subsys_clks, - sizeof(*pd->subsys_clks), GFP_KERNEL); - if (!pd->subsys_clks) - return ERR_PTR(-ENOMEM); - - } - - for (i = 0; i < pd->num_clks; i++) { - clk = of_clk_get(node, i); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - dev_err_probe(scpsys->dev, ret, - "%pOF: failed to get clk at index %d\n", node, i); - goto err_put_clocks; - } - - pd->clks[clk_ind++].clk = clk; - } - - for (i = 0; i < pd->num_subsys_clks; i++) { - clk = of_clk_get(node, i + clk_ind); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - dev_err_probe(scpsys->dev, ret, - "%pOF: failed to get clk at index %d\n", node, - i + clk_ind); - goto err_put_subsys_clocks; - } - - pd->subsys_clks[i].clk = clk; - } - - /* - * Initially turn on all domains to make the domains usable - * with !CONFIG_PM and to get the hardware in sync with the - * software. The unused domains will be switched off during - * late_init time. - */ - if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF)) { - if (scpsys_domain_is_on(pd)) - dev_warn(scpsys->dev, - "%pOF: A default off power domain has been ON\n", node); - } else { - ret = scpsys_power_on(&pd->genpd); - if (ret < 0) { - dev_err(scpsys->dev, "%pOF: failed to power on domain: %d\n", node, ret); - goto err_put_subsys_clocks; - } - - if (MTK_SCPD_CAPS(pd, MTK_SCPD_ALWAYS_ON)) - pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON; - } - - if (scpsys->domains[id]) { - ret = -EINVAL; - dev_err(scpsys->dev, - "power domain with id %d already exists, check your device-tree\n", id); - goto err_put_subsys_clocks; - } - - if (!pd->data->name) - pd->genpd.name = node->name; - else - pd->genpd.name = pd->data->name; - - pd->genpd.power_off = scpsys_power_off; - pd->genpd.power_on = scpsys_power_on; - - if (MTK_SCPD_CAPS(pd, MTK_SCPD_ACTIVE_WAKEUP)) - pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP; - - if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF)) - pm_genpd_init(&pd->genpd, NULL, true); - else - pm_genpd_init(&pd->genpd, NULL, false); - - scpsys->domains[id] = &pd->genpd; - - return scpsys->pd_data.domains[id]; - -err_put_subsys_clocks: - clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks); -err_put_clocks: - clk_bulk_put(pd->num_clks, pd->clks); - return ERR_PTR(ret); -} - -static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *parent) -{ - struct generic_pm_domain *child_pd, *parent_pd; - struct device_node *child; - int ret; - - for_each_child_of_node(parent, child) { - u32 id; - - ret = of_property_read_u32(parent, "reg", &id); - if (ret) { - dev_err(scpsys->dev, "%pOF: failed to get parent domain id\n", child); - goto err_put_node; - } - - if (!scpsys->pd_data.domains[id]) { - ret = -EINVAL; - dev_err(scpsys->dev, "power domain with id %d does not exist\n", id); - goto err_put_node; - } - - parent_pd = scpsys->pd_data.domains[id]; - - child_pd = scpsys_add_one_domain(scpsys, child); - if (IS_ERR(child_pd)) { - ret = PTR_ERR(child_pd); - dev_err_probe(scpsys->dev, ret, "%pOF: failed to get child domain id\n", - child); - goto err_put_node; - } - - ret = pm_genpd_add_subdomain(parent_pd, child_pd); - if (ret) { - dev_err(scpsys->dev, "failed to add %s subdomain to parent %s\n", - child_pd->name, parent_pd->name); - goto err_put_node; - } else { - dev_dbg(scpsys->dev, "%s add subdomain: %s\n", parent_pd->name, - child_pd->name); - } - - /* recursive call to add all subdomains */ - ret = scpsys_add_subdomain(scpsys, child); - if (ret) - goto err_put_node; - } - - return 0; - -err_put_node: - of_node_put(child); - return ret; -} - -static void scpsys_remove_one_domain(struct scpsys_domain *pd) -{ - int ret; - - if (scpsys_domain_is_on(pd)) - scpsys_power_off(&pd->genpd); - - /* - * We're in the error cleanup already, so we only complain, - * but won't emit another error on top of the original one. - */ - ret = pm_genpd_remove(&pd->genpd); - if (ret < 0) - dev_err(pd->scpsys->dev, - "failed to remove domain '%s' : %d - state may be inconsistent\n", - pd->genpd.name, ret); - - clk_bulk_put(pd->num_clks, pd->clks); - clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks); -} - -static void scpsys_domain_cleanup(struct scpsys *scpsys) -{ - struct generic_pm_domain *genpd; - struct scpsys_domain *pd; - int i; - - for (i = scpsys->pd_data.num_domains - 1; i >= 0; i--) { - genpd = scpsys->pd_data.domains[i]; - if (genpd) { - pd = to_scpsys_domain(genpd); - scpsys_remove_one_domain(pd); - } - } -} - -static const struct of_device_id scpsys_of_match[] = { - { - .compatible = "mediatek,mt6795-power-controller", - .data = &mt6795_scpsys_data, - }, - { - .compatible = "mediatek,mt8167-power-controller", - .data = &mt8167_scpsys_data, - }, - { - .compatible = "mediatek,mt8173-power-controller", - .data = &mt8173_scpsys_data, - }, - { - .compatible = "mediatek,mt8183-power-controller", - .data = &mt8183_scpsys_data, - }, - { - .compatible = "mediatek,mt8186-power-controller", - .data = &mt8186_scpsys_data, - }, - { - .compatible = "mediatek,mt8188-power-controller", - .data = &mt8188_scpsys_data, - }, - { - .compatible = "mediatek,mt8192-power-controller", - .data = &mt8192_scpsys_data, - }, - { - .compatible = "mediatek,mt8195-power-controller", - .data = &mt8195_scpsys_data, - }, - { } -}; - -static int scpsys_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - const struct scpsys_soc_data *soc; - struct device_node *node; - struct device *parent; - struct scpsys *scpsys; - int ret; - - soc = of_device_get_match_data(&pdev->dev); - if (!soc) { - dev_err(&pdev->dev, "no power controller data\n"); - return -EINVAL; - } - - scpsys = devm_kzalloc(dev, struct_size(scpsys, domains, soc->num_domains), GFP_KERNEL); - if (!scpsys) - return -ENOMEM; - - scpsys->dev = dev; - scpsys->soc_data = soc; - - scpsys->pd_data.domains = scpsys->domains; - scpsys->pd_data.num_domains = soc->num_domains; - - parent = dev->parent; - if (!parent) { - dev_err(dev, "no parent for syscon devices\n"); - return -ENODEV; - } - - scpsys->base = syscon_node_to_regmap(parent->of_node); - if (IS_ERR(scpsys->base)) { - dev_err(dev, "no regmap available\n"); - return PTR_ERR(scpsys->base); - } - - ret = -ENODEV; - for_each_available_child_of_node(np, node) { - struct generic_pm_domain *domain; - - domain = scpsys_add_one_domain(scpsys, node); - if (IS_ERR(domain)) { - ret = PTR_ERR(domain); - of_node_put(node); - goto err_cleanup_domains; - } - - ret = scpsys_add_subdomain(scpsys, node); - if (ret) { - of_node_put(node); - goto err_cleanup_domains; - } - } - - if (ret) { - dev_dbg(dev, "no power domains present\n"); - return ret; - } - - ret = of_genpd_add_provider_onecell(np, &scpsys->pd_data); - if (ret) { - dev_err(dev, "failed to add provider: %d\n", ret); - goto err_cleanup_domains; - } - - return 0; - -err_cleanup_domains: - scpsys_domain_cleanup(scpsys); - return ret; -} - -static struct platform_driver scpsys_pm_domain_driver = { - .probe = scpsys_probe, - .driver = { - .name = "mtk-power-controller", - .suppress_bind_attrs = true, - .of_match_table = scpsys_of_match, - }, -}; -builtin_platform_driver(scpsys_pm_domain_driver); diff --git a/drivers/soc/mediatek/mtk-pm-domains.h b/drivers/soc/mediatek/mtk-pm-domains.h deleted file mode 100644 index 5ec53ee073c4..000000000000 --- a/drivers/soc/mediatek/mtk-pm-domains.h +++ /dev/null @@ -1,111 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#ifndef __SOC_MEDIATEK_MTK_PM_DOMAINS_H -#define __SOC_MEDIATEK_MTK_PM_DOMAINS_H - -#define MTK_SCPD_ACTIVE_WAKEUP BIT(0) -#define MTK_SCPD_FWAIT_SRAM BIT(1) -#define MTK_SCPD_SRAM_ISO BIT(2) -#define MTK_SCPD_KEEP_DEFAULT_OFF BIT(3) -#define MTK_SCPD_DOMAIN_SUPPLY BIT(4) -/* can't set MTK_SCPD_KEEP_DEFAULT_OFF at the same time */ -#define MTK_SCPD_ALWAYS_ON BIT(5) -#define MTK_SCPD_EXT_BUCK_ISO BIT(6) -#define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data->caps & (_x)) - -#define SPM_VDE_PWR_CON 0x0210 -#define SPM_MFG_PWR_CON 0x0214 -#define SPM_VEN_PWR_CON 0x0230 -#define SPM_ISP_PWR_CON 0x0238 -#define SPM_DIS_PWR_CON 0x023c -#define SPM_CONN_PWR_CON 0x0280 -#define SPM_VEN2_PWR_CON 0x0298 -#define SPM_AUDIO_PWR_CON 0x029c -#define SPM_MFG_2D_PWR_CON 0x02c0 -#define SPM_MFG_ASYNC_PWR_CON 0x02c4 -#define SPM_USB_PWR_CON 0x02cc - -#define SPM_PWR_STATUS 0x060c -#define SPM_PWR_STATUS_2ND 0x0610 - -#define PWR_STATUS_CONN BIT(1) -#define PWR_STATUS_DISP BIT(3) -#define PWR_STATUS_MFG BIT(4) -#define PWR_STATUS_ISP BIT(5) -#define PWR_STATUS_VDEC BIT(7) -#define PWR_STATUS_VENC_LT BIT(20) -#define PWR_STATUS_VENC BIT(21) -#define PWR_STATUS_MFG_2D BIT(22) -#define PWR_STATUS_MFG_ASYNC BIT(23) -#define PWR_STATUS_AUDIO BIT(24) -#define PWR_STATUS_USB BIT(25) - -#define SPM_MAX_BUS_PROT_DATA 6 - -#define _BUS_PROT(_mask, _set, _clr, _sta, _update, _ignore) { \ - .bus_prot_mask = (_mask), \ - .bus_prot_set = _set, \ - .bus_prot_clr = _clr, \ - .bus_prot_sta = _sta, \ - .bus_prot_reg_update = _update, \ - .ignore_clr_ack = _ignore, \ - } - -#define BUS_PROT_WR(_mask, _set, _clr, _sta) \ - _BUS_PROT(_mask, _set, _clr, _sta, false, false) - -#define BUS_PROT_WR_IGN(_mask, _set, _clr, _sta) \ - _BUS_PROT(_mask, _set, _clr, _sta, false, true) - -#define BUS_PROT_UPDATE(_mask, _set, _clr, _sta) \ - _BUS_PROT(_mask, _set, _clr, _sta, true, false) - -#define BUS_PROT_UPDATE_TOPAXI(_mask) \ - BUS_PROT_UPDATE(_mask, \ - INFRA_TOPAXI_PROTECTEN, \ - INFRA_TOPAXI_PROTECTEN, \ - INFRA_TOPAXI_PROTECTSTA1) - -struct scpsys_bus_prot_data { - u32 bus_prot_mask; - u32 bus_prot_set; - u32 bus_prot_clr; - u32 bus_prot_sta; - bool bus_prot_reg_update; - bool ignore_clr_ack; -}; - -/** - * struct scpsys_domain_data - scp domain data for power on/off flow - * @name: The name of the power domain. - * @sta_mask: The mask for power on/off status bit. - * @ctl_offs: The offset for main power control register. - * @sram_pdn_bits: The mask for sram power control bits. - * @sram_pdn_ack_bits: The mask for sram power control acked bits. - * @ext_buck_iso_offs: The offset for external buck isolation - * @ext_buck_iso_mask: The mask for external buck isolation - * @caps: The flag for active wake-up action. - * @bp_infracfg: bus protection for infracfg subsystem - * @bp_smi: bus protection for smi subsystem - */ -struct scpsys_domain_data { - const char *name; - u32 sta_mask; - int ctl_offs; - u32 sram_pdn_bits; - u32 sram_pdn_ack_bits; - int ext_buck_iso_offs; - u32 ext_buck_iso_mask; - u8 caps; - const struct scpsys_bus_prot_data bp_infracfg[SPM_MAX_BUS_PROT_DATA]; - const struct scpsys_bus_prot_data bp_smi[SPM_MAX_BUS_PROT_DATA]; - int pwr_sta_offs; - int pwr_sta2nd_offs; -}; - -struct scpsys_soc_data { - const struct scpsys_domain_data *domains_data; - int num_domains; -}; - -#endif /* __SOC_MEDIATEK_MTK_PM_DOMAINS_H */ diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c deleted file mode 100644 index 7a668888111c..000000000000 --- a/drivers/soc/mediatek/mtk-scpsys.c +++ /dev/null @@ -1,1147 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de> - */ -#include <linux/clk.h> -#include <linux/init.h> -#include <linux/io.h> -#include <linux/iopoll.h> -#include <linux/mfd/syscon.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <linux/regulator/consumer.h> -#include <linux/soc/mediatek/infracfg.h> - -#include <dt-bindings/power/mt2701-power.h> -#include <dt-bindings/power/mt2712-power.h> -#include <dt-bindings/power/mt6797-power.h> -#include <dt-bindings/power/mt7622-power.h> -#include <dt-bindings/power/mt7623a-power.h> -#include <dt-bindings/power/mt8173-power.h> - -#define MTK_POLL_DELAY_US 10 -#define MTK_POLL_TIMEOUT USEC_PER_SEC - -#define MTK_SCPD_ACTIVE_WAKEUP BIT(0) -#define MTK_SCPD_FWAIT_SRAM BIT(1) -#define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data->caps & (_x)) - -#define SPM_VDE_PWR_CON 0x0210 -#define SPM_MFG_PWR_CON 0x0214 -#define SPM_VEN_PWR_CON 0x0230 -#define SPM_ISP_PWR_CON 0x0238 -#define SPM_DIS_PWR_CON 0x023c -#define SPM_CONN_PWR_CON 0x0280 -#define SPM_VEN2_PWR_CON 0x0298 -#define SPM_AUDIO_PWR_CON 0x029c /* MT8173, MT2712 */ -#define SPM_BDP_PWR_CON 0x029c /* MT2701 */ -#define SPM_ETH_PWR_CON 0x02a0 -#define SPM_HIF_PWR_CON 0x02a4 -#define SPM_IFR_MSC_PWR_CON 0x02a8 -#define SPM_MFG_2D_PWR_CON 0x02c0 -#define SPM_MFG_ASYNC_PWR_CON 0x02c4 -#define SPM_USB_PWR_CON 0x02cc -#define SPM_USB2_PWR_CON 0x02d4 /* MT2712 */ -#define SPM_ETHSYS_PWR_CON 0x02e0 /* MT7622 */ -#define SPM_HIF0_PWR_CON 0x02e4 /* MT7622 */ -#define SPM_HIF1_PWR_CON 0x02e8 /* MT7622 */ -#define SPM_WB_PWR_CON 0x02ec /* MT7622 */ - -#define SPM_PWR_STATUS 0x060c -#define SPM_PWR_STATUS_2ND 0x0610 - -#define PWR_RST_B_BIT BIT(0) -#define PWR_ISO_BIT BIT(1) -#define PWR_ON_BIT BIT(2) -#define PWR_ON_2ND_BIT BIT(3) -#define PWR_CLK_DIS_BIT BIT(4) - -#define PWR_STATUS_CONN BIT(1) -#define PWR_STATUS_DISP BIT(3) -#define PWR_STATUS_MFG BIT(4) -#define PWR_STATUS_ISP BIT(5) -#define PWR_STATUS_VDEC BIT(7) -#define PWR_STATUS_BDP BIT(14) -#define PWR_STATUS_ETH BIT(15) -#define PWR_STATUS_HIF BIT(16) -#define PWR_STATUS_IFR_MSC BIT(17) -#define PWR_STATUS_USB2 BIT(19) /* MT2712 */ -#define PWR_STATUS_VENC_LT BIT(20) -#define PWR_STATUS_VENC BIT(21) -#define PWR_STATUS_MFG_2D BIT(22) /* MT8173 */ -#define PWR_STATUS_MFG_ASYNC BIT(23) /* MT8173 */ -#define PWR_STATUS_AUDIO BIT(24) /* MT8173, MT2712 */ -#define PWR_STATUS_USB BIT(25) /* MT8173, MT2712 */ -#define PWR_STATUS_ETHSYS BIT(24) /* MT7622 */ -#define PWR_STATUS_HIF0 BIT(25) /* MT7622 */ -#define PWR_STATUS_HIF1 BIT(26) /* MT7622 */ -#define PWR_STATUS_WB BIT(27) /* MT7622 */ - -enum clk_id { - CLK_NONE, - CLK_MM, - CLK_MFG, - CLK_VENC, - CLK_VENC_LT, - CLK_ETHIF, - CLK_VDEC, - CLK_HIFSEL, - CLK_JPGDEC, - CLK_AUDIO, - CLK_MAX, -}; - -static const char * const clk_names[] = { - NULL, - "mm", - "mfg", - "venc", - "venc_lt", - "ethif", - "vdec", - "hif_sel", - "jpgdec", - "audio", - NULL, -}; - -#define MAX_CLKS 3 - -/** - * struct scp_domain_data - scp domain data for power on/off flow - * @name: The domain name. - * @sta_mask: The mask for power on/off status bit. - * @ctl_offs: The offset for main power control register. - * @sram_pdn_bits: The mask for sram power control bits. - * @sram_pdn_ack_bits: The mask for sram power control acked bits. - * @bus_prot_mask: The mask for single step bus protection. - * @clk_id: The basic clocks required by this power domain. - * @caps: The flag for active wake-up action. - */ -struct scp_domain_data { - const char *name; - u32 sta_mask; - int ctl_offs; - u32 sram_pdn_bits; - u32 sram_pdn_ack_bits; - u32 bus_prot_mask; - enum clk_id clk_id[MAX_CLKS]; - u8 caps; -}; - -struct scp; - -struct scp_domain { - struct generic_pm_domain genpd; - struct scp *scp; - struct clk *clk[MAX_CLKS]; - const struct scp_domain_data *data; - struct regulator *supply; -}; - -struct scp_ctrl_reg { - int pwr_sta_offs; - int pwr_sta2nd_offs; -}; - -struct scp { - struct scp_domain *domains; - struct genpd_onecell_data pd_data; - struct device *dev; - void __iomem *base; - struct regmap *infracfg; - struct scp_ctrl_reg ctrl_reg; - bool bus_prot_reg_update; -}; - -struct scp_subdomain { - int origin; - int subdomain; -}; - -struct scp_soc_data { - const struct scp_domain_data *domains; - int num_domains; - const struct scp_subdomain *subdomains; - int num_subdomains; - const struct scp_ctrl_reg regs; - bool bus_prot_reg_update; -}; - -static int scpsys_domain_is_on(struct scp_domain *scpd) -{ - struct scp *scp = scpd->scp; - - u32 status = readl(scp->base + scp->ctrl_reg.pwr_sta_offs) & - scpd->data->sta_mask; - u32 status2 = readl(scp->base + scp->ctrl_reg.pwr_sta2nd_offs) & - scpd->data->sta_mask; - - /* - * A domain is on when both status bits are set. If only one is set - * return an error. This happens while powering up a domain - */ - - if (status && status2) - return true; - if (!status && !status2) - return false; - - return -EINVAL; -} - -static int scpsys_regulator_enable(struct scp_domain *scpd) -{ - if (!scpd->supply) - return 0; - - return regulator_enable(scpd->supply); -} - -static int scpsys_regulator_disable(struct scp_domain *scpd) -{ - if (!scpd->supply) - return 0; - - return regulator_disable(scpd->supply); -} - -static void scpsys_clk_disable(struct clk *clk[], int max_num) -{ - int i; - - for (i = max_num - 1; i >= 0; i--) - clk_disable_unprepare(clk[i]); -} - -static int scpsys_clk_enable(struct clk *clk[], int max_num) -{ - int i, ret = 0; - - for (i = 0; i < max_num && clk[i]; i++) { - ret = clk_prepare_enable(clk[i]); - if (ret) { - scpsys_clk_disable(clk, i); - break; - } - } - - return ret; -} - -static int scpsys_sram_enable(struct scp_domain *scpd, void __iomem *ctl_addr) -{ - u32 val; - u32 pdn_ack = scpd->data->sram_pdn_ack_bits; - int tmp; - - val = readl(ctl_addr); - val &= ~scpd->data->sram_pdn_bits; - writel(val, ctl_addr); - - /* Either wait until SRAM_PDN_ACK all 0 or have a force wait */ - if (MTK_SCPD_CAPS(scpd, MTK_SCPD_FWAIT_SRAM)) { - /* - * Currently, MTK_SCPD_FWAIT_SRAM is necessary only for - * MT7622_POWER_DOMAIN_WB and thus just a trivial setup - * is applied here. - */ - usleep_range(12000, 12100); - } else { - /* Either wait until SRAM_PDN_ACK all 1 or 0 */ - int ret = readl_poll_timeout(ctl_addr, tmp, - (tmp & pdn_ack) == 0, - MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); - if (ret < 0) - return ret; - } - - return 0; -} - -static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr) -{ - u32 val; - u32 pdn_ack = scpd->data->sram_pdn_ack_bits; - int tmp; - - val = readl(ctl_addr); - val |= scpd->data->sram_pdn_bits; - writel(val, ctl_addr); - - /* Either wait until SRAM_PDN_ACK all 1 or 0 */ - return readl_poll_timeout(ctl_addr, tmp, - (tmp & pdn_ack) == pdn_ack, - MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); -} - -static int scpsys_bus_protect_enable(struct scp_domain *scpd) -{ - struct scp *scp = scpd->scp; - - if (!scpd->data->bus_prot_mask) - return 0; - - return mtk_infracfg_set_bus_protection(scp->infracfg, - scpd->data->bus_prot_mask, - scp->bus_prot_reg_update); -} - -static int scpsys_bus_protect_disable(struct scp_domain *scpd) -{ - struct scp *scp = scpd->scp; - - if (!scpd->data->bus_prot_mask) - return 0; - - return mtk_infracfg_clear_bus_protection(scp->infracfg, - scpd->data->bus_prot_mask, - scp->bus_prot_reg_update); -} - -static int scpsys_power_on(struct generic_pm_domain *genpd) -{ - struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); - struct scp *scp = scpd->scp; - void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs; - u32 val; - int ret, tmp; - - ret = scpsys_regulator_enable(scpd); - if (ret < 0) - return ret; - - ret = scpsys_clk_enable(scpd->clk, MAX_CLKS); - if (ret) - goto err_clk; - - /* subsys power on */ - val = readl(ctl_addr); - val |= PWR_ON_BIT; - writel(val, ctl_addr); - val |= PWR_ON_2ND_BIT; - writel(val, ctl_addr); - - /* wait until PWR_ACK = 1 */ - ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp > 0, - MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); - if (ret < 0) - goto err_pwr_ack; - - val &= ~PWR_CLK_DIS_BIT; - writel(val, ctl_addr); - - val &= ~PWR_ISO_BIT; - writel(val, ctl_addr); - - val |= PWR_RST_B_BIT; - writel(val, ctl_addr); - - ret = scpsys_sram_enable(scpd, ctl_addr); - if (ret < 0) - goto err_pwr_ack; - - ret = scpsys_bus_protect_disable(scpd); - if (ret < 0) - goto err_pwr_ack; - - return 0; - -err_pwr_ack: - scpsys_clk_disable(scpd->clk, MAX_CLKS); -err_clk: - scpsys_regulator_disable(scpd); - - dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name); - - return ret; -} - -static int scpsys_power_off(struct generic_pm_domain *genpd) -{ - struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); - struct scp *scp = scpd->scp; - void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs; - u32 val; - int ret, tmp; - - ret = scpsys_bus_protect_enable(scpd); - if (ret < 0) - goto out; - - ret = scpsys_sram_disable(scpd, ctl_addr); - if (ret < 0) - goto out; - - /* subsys power off */ - val = readl(ctl_addr); - val |= PWR_ISO_BIT; - writel(val, ctl_addr); - - val &= ~PWR_RST_B_BIT; - writel(val, ctl_addr); - - val |= PWR_CLK_DIS_BIT; - writel(val, ctl_addr); - - val &= ~PWR_ON_BIT; - writel(val, ctl_addr); - - val &= ~PWR_ON_2ND_BIT; - writel(val, ctl_addr); - - /* wait until PWR_ACK = 0 */ - ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp == 0, - MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); - if (ret < 0) - goto out; - - scpsys_clk_disable(scpd->clk, MAX_CLKS); - - ret = scpsys_regulator_disable(scpd); - if (ret < 0) - goto out; - - return 0; - -out: - dev_err(scp->dev, "Failed to power off domain %s\n", genpd->name); - - return ret; -} - -static void init_clks(struct platform_device *pdev, struct clk **clk) -{ - int i; - - for (i = CLK_NONE + 1; i < CLK_MAX; i++) - clk[i] = devm_clk_get(&pdev->dev, clk_names[i]); -} - -static struct scp *init_scp(struct platform_device *pdev, - const struct scp_domain_data *scp_domain_data, int num, - const struct scp_ctrl_reg *scp_ctrl_reg, - bool bus_prot_reg_update) -{ - struct genpd_onecell_data *pd_data; - struct resource *res; - int i, j; - struct scp *scp; - struct clk *clk[CLK_MAX]; - - scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL); - if (!scp) - return ERR_PTR(-ENOMEM); - - scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs; - scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs; - - scp->bus_prot_reg_update = bus_prot_reg_update; - - scp->dev = &pdev->dev; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - scp->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(scp->base)) - return ERR_CAST(scp->base); - - scp->domains = devm_kcalloc(&pdev->dev, - num, sizeof(*scp->domains), GFP_KERNEL); - if (!scp->domains) - return ERR_PTR(-ENOMEM); - - pd_data = &scp->pd_data; - - pd_data->domains = devm_kcalloc(&pdev->dev, - num, sizeof(*pd_data->domains), GFP_KERNEL); - if (!pd_data->domains) - return ERR_PTR(-ENOMEM); - - scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, - "infracfg"); - if (IS_ERR(scp->infracfg)) { - dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n", - PTR_ERR(scp->infracfg)); - return ERR_CAST(scp->infracfg); - } - - for (i = 0; i < num; i++) { - struct scp_domain *scpd = &scp->domains[i]; - const struct scp_domain_data *data = &scp_domain_data[i]; - - scpd->supply = devm_regulator_get_optional(&pdev->dev, data->name); - if (IS_ERR(scpd->supply)) { - if (PTR_ERR(scpd->supply) == -ENODEV) - scpd->supply = NULL; - else - return ERR_CAST(scpd->supply); - } - } - - pd_data->num_domains = num; - - init_clks(pdev, clk); - - for (i = 0; i < num; i++) { - struct scp_domain *scpd = &scp->domains[i]; - struct generic_pm_domain *genpd = &scpd->genpd; - const struct scp_domain_data *data = &scp_domain_data[i]; - - pd_data->domains[i] = genpd; - scpd->scp = scp; - - scpd->data = data; - - for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) { - struct clk *c = clk[data->clk_id[j]]; - - if (IS_ERR(c)) { - dev_err(&pdev->dev, "%s: clk unavailable\n", - data->name); - return ERR_CAST(c); - } - - scpd->clk[j] = c; - } - - genpd->name = data->name; - genpd->power_off = scpsys_power_off; - genpd->power_on = scpsys_power_on; - if (MTK_SCPD_CAPS(scpd, MTK_SCPD_ACTIVE_WAKEUP)) - genpd->flags |= GENPD_FLAG_ACTIVE_WAKEUP; - } - - return scp; -} - -static void mtk_register_power_domains(struct platform_device *pdev, - struct scp *scp, int num) -{ - struct genpd_onecell_data *pd_data; - int i, ret; - - for (i = 0; i < num; i++) { - struct scp_domain *scpd = &scp->domains[i]; - struct generic_pm_domain *genpd = &scpd->genpd; - bool on; - - /* - * Initially turn on all domains to make the domains usable - * with !CONFIG_PM and to get the hardware in sync with the - * software. The unused domains will be switched off during - * late_init time. - */ - on = !WARN_ON(genpd->power_on(genpd) < 0); - - pm_genpd_init(genpd, NULL, !on); - } - - /* - * We are not allowed to fail here since there is no way to unregister - * a power domain. Once registered above we have to keep the domains - * valid. - */ - - pd_data = &scp->pd_data; - - ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data); - if (ret) - dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret); -} - -/* - * MT2701 power domain support - */ - -static const struct scp_domain_data scp_domain_data_mt2701[] = { - [MT2701_POWER_DOMAIN_CONN] = { - .name = "conn", - .sta_mask = PWR_STATUS_CONN, - .ctl_offs = SPM_CONN_PWR_CON, - .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M | - MT2701_TOP_AXI_PROT_EN_CONN_S, - .clk_id = {CLK_NONE}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT2701_POWER_DOMAIN_DISP] = { - .name = "disp", - .sta_mask = PWR_STATUS_DISP, - .ctl_offs = SPM_DIS_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .clk_id = {CLK_MM}, - .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_MM_M0, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT2701_POWER_DOMAIN_MFG] = { - .name = "mfg", - .sta_mask = PWR_STATUS_MFG, - .ctl_offs = SPM_MFG_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .clk_id = {CLK_MFG}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT2701_POWER_DOMAIN_VDEC] = { - .name = "vdec", - .sta_mask = PWR_STATUS_VDEC, - .ctl_offs = SPM_VDE_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .clk_id = {CLK_MM}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT2701_POWER_DOMAIN_ISP] = { - .name = "isp", - .sta_mask = PWR_STATUS_ISP, - .ctl_offs = SPM_ISP_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(13, 12), - .clk_id = {CLK_MM}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT2701_POWER_DOMAIN_BDP] = { - .name = "bdp", - .sta_mask = PWR_STATUS_BDP, - .ctl_offs = SPM_BDP_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .clk_id = {CLK_NONE}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT2701_POWER_DOMAIN_ETH] = { - .name = "eth", - .sta_mask = PWR_STATUS_ETH, - .ctl_offs = SPM_ETH_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {CLK_ETHIF}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT2701_POWER_DOMAIN_HIF] = { - .name = "hif", - .sta_mask = PWR_STATUS_HIF, - .ctl_offs = SPM_HIF_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {CLK_ETHIF}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT2701_POWER_DOMAIN_IFR_MSC] = { - .name = "ifr_msc", - .sta_mask = PWR_STATUS_IFR_MSC, - .ctl_offs = SPM_IFR_MSC_PWR_CON, - .clk_id = {CLK_NONE}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, -}; - -/* - * MT2712 power domain support - */ -static const struct scp_domain_data scp_domain_data_mt2712[] = { - [MT2712_POWER_DOMAIN_MM] = { - .name = "mm", - .sta_mask = PWR_STATUS_DISP, - .ctl_offs = SPM_DIS_PWR_CON, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .clk_id = {CLK_MM}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT2712_POWER_DOMAIN_VDEC] = { - .name = "vdec", - .sta_mask = PWR_STATUS_VDEC, - .ctl_offs = SPM_VDE_PWR_CON, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .clk_id = {CLK_MM, CLK_VDEC}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT2712_POWER_DOMAIN_VENC] = { - .name = "venc", - .sta_mask = PWR_STATUS_VENC, - .ctl_offs = SPM_VEN_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {CLK_MM, CLK_VENC, CLK_JPGDEC}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT2712_POWER_DOMAIN_ISP] = { - .name = "isp", - .sta_mask = PWR_STATUS_ISP, - .ctl_offs = SPM_ISP_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(13, 12), - .clk_id = {CLK_MM}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT2712_POWER_DOMAIN_AUDIO] = { - .name = "audio", - .sta_mask = PWR_STATUS_AUDIO, - .ctl_offs = SPM_AUDIO_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {CLK_AUDIO}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT2712_POWER_DOMAIN_USB] = { - .name = "usb", - .sta_mask = PWR_STATUS_USB, - .ctl_offs = SPM_USB_PWR_CON, - .sram_pdn_bits = GENMASK(10, 8), - .sram_pdn_ack_bits = GENMASK(14, 12), - .clk_id = {CLK_NONE}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT2712_POWER_DOMAIN_USB2] = { - .name = "usb2", - .sta_mask = PWR_STATUS_USB2, - .ctl_offs = SPM_USB2_PWR_CON, - .sram_pdn_bits = GENMASK(10, 8), - .sram_pdn_ack_bits = GENMASK(14, 12), - .clk_id = {CLK_NONE}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT2712_POWER_DOMAIN_MFG] = { - .name = "mfg", - .sta_mask = PWR_STATUS_MFG, - .ctl_offs = SPM_MFG_PWR_CON, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(16, 16), - .clk_id = {CLK_MFG}, - .bus_prot_mask = BIT(14) | BIT(21) | BIT(23), - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT2712_POWER_DOMAIN_MFG_SC1] = { - .name = "mfg_sc1", - .sta_mask = BIT(22), - .ctl_offs = 0x02c0, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(16, 16), - .clk_id = {CLK_NONE}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT2712_POWER_DOMAIN_MFG_SC2] = { - .name = "mfg_sc2", - .sta_mask = BIT(23), - .ctl_offs = 0x02c4, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(16, 16), - .clk_id = {CLK_NONE}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT2712_POWER_DOMAIN_MFG_SC3] = { - .name = "mfg_sc3", - .sta_mask = BIT(30), - .ctl_offs = 0x01f8, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(16, 16), - .clk_id = {CLK_NONE}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, -}; - -static const struct scp_subdomain scp_subdomain_mt2712[] = { - {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_VDEC}, - {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_VENC}, - {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_ISP}, - {MT2712_POWER_DOMAIN_MFG, MT2712_POWER_DOMAIN_MFG_SC1}, - {MT2712_POWER_DOMAIN_MFG_SC1, MT2712_POWER_DOMAIN_MFG_SC2}, - {MT2712_POWER_DOMAIN_MFG_SC2, MT2712_POWER_DOMAIN_MFG_SC3}, -}; - -/* - * MT6797 power domain support - */ - -static const struct scp_domain_data scp_domain_data_mt6797[] = { - [MT6797_POWER_DOMAIN_VDEC] = { - .name = "vdec", - .sta_mask = BIT(7), - .ctl_offs = 0x300, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .clk_id = {CLK_VDEC}, - }, - [MT6797_POWER_DOMAIN_VENC] = { - .name = "venc", - .sta_mask = BIT(21), - .ctl_offs = 0x304, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {CLK_NONE}, - }, - [MT6797_POWER_DOMAIN_ISP] = { - .name = "isp", - .sta_mask = BIT(5), - .ctl_offs = 0x308, - .sram_pdn_bits = GENMASK(9, 8), - .sram_pdn_ack_bits = GENMASK(13, 12), - .clk_id = {CLK_NONE}, - }, - [MT6797_POWER_DOMAIN_MM] = { - .name = "mm", - .sta_mask = BIT(3), - .ctl_offs = 0x30C, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .clk_id = {CLK_MM}, - .bus_prot_mask = (BIT(1) | BIT(2)), - }, - [MT6797_POWER_DOMAIN_AUDIO] = { - .name = "audio", - .sta_mask = BIT(24), - .ctl_offs = 0x314, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {CLK_NONE}, - }, - [MT6797_POWER_DOMAIN_MFG_ASYNC] = { - .name = "mfg_async", - .sta_mask = BIT(13), - .ctl_offs = 0x334, - .sram_pdn_bits = 0, - .sram_pdn_ack_bits = 0, - .clk_id = {CLK_MFG}, - }, - [MT6797_POWER_DOMAIN_MJC] = { - .name = "mjc", - .sta_mask = BIT(20), - .ctl_offs = 0x310, - .sram_pdn_bits = GENMASK(8, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .clk_id = {CLK_NONE}, - }, -}; - -#define SPM_PWR_STATUS_MT6797 0x0180 -#define SPM_PWR_STATUS_2ND_MT6797 0x0184 - -static const struct scp_subdomain scp_subdomain_mt6797[] = { - {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VDEC}, - {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_ISP}, - {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VENC}, - {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_MJC}, -}; - -/* - * MT7622 power domain support - */ - -static const struct scp_domain_data scp_domain_data_mt7622[] = { - [MT7622_POWER_DOMAIN_ETHSYS] = { - .name = "ethsys", - .sta_mask = PWR_STATUS_ETHSYS, - .ctl_offs = SPM_ETHSYS_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {CLK_NONE}, - .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_ETHSYS, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT7622_POWER_DOMAIN_HIF0] = { - .name = "hif0", - .sta_mask = PWR_STATUS_HIF0, - .ctl_offs = SPM_HIF0_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {CLK_HIFSEL}, - .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF0, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT7622_POWER_DOMAIN_HIF1] = { - .name = "hif1", - .sta_mask = PWR_STATUS_HIF1, - .ctl_offs = SPM_HIF1_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {CLK_HIFSEL}, - .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF1, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT7622_POWER_DOMAIN_WB] = { - .name = "wb", - .sta_mask = PWR_STATUS_WB, - .ctl_offs = SPM_WB_PWR_CON, - .sram_pdn_bits = 0, - .sram_pdn_ack_bits = 0, - .clk_id = {CLK_NONE}, - .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_WB, - .caps = MTK_SCPD_ACTIVE_WAKEUP | MTK_SCPD_FWAIT_SRAM, - }, -}; - -/* - * MT7623A power domain support - */ - -static const struct scp_domain_data scp_domain_data_mt7623a[] = { - [MT7623A_POWER_DOMAIN_CONN] = { - .name = "conn", - .sta_mask = PWR_STATUS_CONN, - .ctl_offs = SPM_CONN_PWR_CON, - .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M | - MT2701_TOP_AXI_PROT_EN_CONN_S, - .clk_id = {CLK_NONE}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT7623A_POWER_DOMAIN_ETH] = { - .name = "eth", - .sta_mask = PWR_STATUS_ETH, - .ctl_offs = SPM_ETH_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {CLK_ETHIF}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT7623A_POWER_DOMAIN_HIF] = { - .name = "hif", - .sta_mask = PWR_STATUS_HIF, - .ctl_offs = SPM_HIF_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {CLK_ETHIF}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT7623A_POWER_DOMAIN_IFR_MSC] = { - .name = "ifr_msc", - .sta_mask = PWR_STATUS_IFR_MSC, - .ctl_offs = SPM_IFR_MSC_PWR_CON, - .clk_id = {CLK_NONE}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, -}; - -/* - * MT8173 power domain support - */ - -static const struct scp_domain_data scp_domain_data_mt8173[] = { - [MT8173_POWER_DOMAIN_VDEC] = { - .name = "vdec", - .sta_mask = PWR_STATUS_VDEC, - .ctl_offs = SPM_VDE_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .clk_id = {CLK_MM}, - }, - [MT8173_POWER_DOMAIN_VENC] = { - .name = "venc", - .sta_mask = PWR_STATUS_VENC, - .ctl_offs = SPM_VEN_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {CLK_MM, CLK_VENC}, - }, - [MT8173_POWER_DOMAIN_ISP] = { - .name = "isp", - .sta_mask = PWR_STATUS_ISP, - .ctl_offs = SPM_ISP_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(13, 12), - .clk_id = {CLK_MM}, - }, - [MT8173_POWER_DOMAIN_MM] = { - .name = "mm", - .sta_mask = PWR_STATUS_DISP, - .ctl_offs = SPM_DIS_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(12, 12), - .clk_id = {CLK_MM}, - .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 | - MT8173_TOP_AXI_PROT_EN_MM_M1, - }, - [MT8173_POWER_DOMAIN_VENC_LT] = { - .name = "venc_lt", - .sta_mask = PWR_STATUS_VENC_LT, - .ctl_offs = SPM_VEN2_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {CLK_MM, CLK_VENC_LT}, - }, - [MT8173_POWER_DOMAIN_AUDIO] = { - .name = "audio", - .sta_mask = PWR_STATUS_AUDIO, - .ctl_offs = SPM_AUDIO_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {CLK_NONE}, - }, - [MT8173_POWER_DOMAIN_USB] = { - .name = "usb", - .sta_mask = PWR_STATUS_USB, - .ctl_offs = SPM_USB_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(15, 12), - .clk_id = {CLK_NONE}, - .caps = MTK_SCPD_ACTIVE_WAKEUP, - }, - [MT8173_POWER_DOMAIN_MFG_ASYNC] = { - .name = "mfg_async", - .sta_mask = PWR_STATUS_MFG_ASYNC, - .ctl_offs = SPM_MFG_ASYNC_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = 0, - .clk_id = {CLK_MFG}, - }, - [MT8173_POWER_DOMAIN_MFG_2D] = { - .name = "mfg_2d", - .sta_mask = PWR_STATUS_MFG_2D, - .ctl_offs = SPM_MFG_2D_PWR_CON, - .sram_pdn_bits = GENMASK(11, 8), - .sram_pdn_ack_bits = GENMASK(13, 12), - .clk_id = {CLK_NONE}, - }, - [MT8173_POWER_DOMAIN_MFG] = { - .name = "mfg", - .sta_mask = PWR_STATUS_MFG, - .ctl_offs = SPM_MFG_PWR_CON, - .sram_pdn_bits = GENMASK(13, 8), - .sram_pdn_ack_bits = GENMASK(21, 16), - .clk_id = {CLK_NONE}, - .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S | - MT8173_TOP_AXI_PROT_EN_MFG_M0 | - MT8173_TOP_AXI_PROT_EN_MFG_M1 | - MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT, - }, -}; - -static const struct scp_subdomain scp_subdomain_mt8173[] = { - {MT8173_POWER_DOMAIN_MFG_ASYNC, MT8173_POWER_DOMAIN_MFG_2D}, - {MT8173_POWER_DOMAIN_MFG_2D, MT8173_POWER_DOMAIN_MFG}, -}; - -static const struct scp_soc_data mt2701_data = { - .domains = scp_domain_data_mt2701, - .num_domains = ARRAY_SIZE(scp_domain_data_mt2701), - .regs = { - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND - }, - .bus_prot_reg_update = true, -}; - -static const struct scp_soc_data mt2712_data = { - .domains = scp_domain_data_mt2712, - .num_domains = ARRAY_SIZE(scp_domain_data_mt2712), - .subdomains = scp_subdomain_mt2712, - .num_subdomains = ARRAY_SIZE(scp_subdomain_mt2712), - .regs = { - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND - }, - .bus_prot_reg_update = false, -}; - -static const struct scp_soc_data mt6797_data = { - .domains = scp_domain_data_mt6797, - .num_domains = ARRAY_SIZE(scp_domain_data_mt6797), - .subdomains = scp_subdomain_mt6797, - .num_subdomains = ARRAY_SIZE(scp_subdomain_mt6797), - .regs = { - .pwr_sta_offs = SPM_PWR_STATUS_MT6797, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797 - }, - .bus_prot_reg_update = true, -}; - -static const struct scp_soc_data mt7622_data = { - .domains = scp_domain_data_mt7622, - .num_domains = ARRAY_SIZE(scp_domain_data_mt7622), - .regs = { - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND - }, - .bus_prot_reg_update = true, -}; - -static const struct scp_soc_data mt7623a_data = { - .domains = scp_domain_data_mt7623a, - .num_domains = ARRAY_SIZE(scp_domain_data_mt7623a), - .regs = { - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND - }, - .bus_prot_reg_update = true, -}; - -static const struct scp_soc_data mt8173_data = { - .domains = scp_domain_data_mt8173, - .num_domains = ARRAY_SIZE(scp_domain_data_mt8173), - .subdomains = scp_subdomain_mt8173, - .num_subdomains = ARRAY_SIZE(scp_subdomain_mt8173), - .regs = { - .pwr_sta_offs = SPM_PWR_STATUS, - .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND - }, - .bus_prot_reg_update = true, -}; - -/* - * scpsys driver init - */ - -static const struct of_device_id of_scpsys_match_tbl[] = { - { - .compatible = "mediatek,mt2701-scpsys", - .data = &mt2701_data, - }, { - .compatible = "mediatek,mt2712-scpsys", - .data = &mt2712_data, - }, { - .compatible = "mediatek,mt6797-scpsys", - .data = &mt6797_data, - }, { - .compatible = "mediatek,mt7622-scpsys", - .data = &mt7622_data, - }, { - .compatible = "mediatek,mt7623a-scpsys", - .data = &mt7623a_data, - }, { - .compatible = "mediatek,mt8173-scpsys", - .data = &mt8173_data, - }, { - /* sentinel */ - } -}; - -static int scpsys_probe(struct platform_device *pdev) -{ - const struct scp_subdomain *sd; - const struct scp_soc_data *soc; - struct scp *scp; - struct genpd_onecell_data *pd_data; - int i, ret; - - soc = of_device_get_match_data(&pdev->dev); - - scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs, - soc->bus_prot_reg_update); - if (IS_ERR(scp)) - return PTR_ERR(scp); - - mtk_register_power_domains(pdev, scp, soc->num_domains); - - pd_data = &scp->pd_data; - - for (i = 0, sd = soc->subdomains; i < soc->num_subdomains; i++, sd++) { - ret = pm_genpd_add_subdomain(pd_data->domains[sd->origin], - pd_data->domains[sd->subdomain]); - if (ret && IS_ENABLED(CONFIG_PM)) - dev_err(&pdev->dev, "Failed to add subdomain: %d\n", - ret); - } - - return 0; -} - -static struct platform_driver scpsys_drv = { - .probe = scpsys_probe, - .driver = { - .name = "mtk-scpsys", - .suppress_bind_attrs = true, - .owner = THIS_MODULE, - .of_match_table = of_scpsys_match_tbl, - }, -}; -builtin_platform_driver(scpsys_drv); diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 99114c71092b..f548a7150bb2 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -3,7 +3,6 @@ CFLAGS_rpmh-rsc.o := -I$(src) obj-$(CONFIG_QCOM_AOSS_QMP) += qcom_aoss.o obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o -obj-$(CONFIG_QCOM_CPR) += cpr.o obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o obj-$(CONFIG_QCOM_OCMEM) += ocmem.o @@ -29,8 +28,6 @@ obj-$(CONFIG_QCOM_STATS) += qcom_stats.o obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o obj-$(CONFIG_QCOM_APR) += apr.o obj-$(CONFIG_QCOM_LLCC) += llcc-qcom.o -obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o -obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o obj-$(CONFIG_QCOM_KRYO_L2_ACCESSORS) += kryo-l2-accessors.o obj-$(CONFIG_QCOM_ICC_BWMON) += icc-bwmon.o qcom_ice-objs += ice.o diff --git a/drivers/soc/qcom/cpr.c b/drivers/soc/qcom/cpr.c deleted file mode 100644 index 144ea68e0920..000000000000 --- a/drivers/soc/qcom/cpr.c +++ /dev/null @@ -1,1757 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. - * Copyright (c) 2019, Linaro Limited - */ - -#include <linux/module.h> -#include <linux/err.h> -#include <linux/debugfs.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/init.h> -#include <linux/io.h> -#include <linux/bitops.h> -#include <linux/slab.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <linux/pm_opp.h> -#include <linux/interrupt.h> -#include <linux/regmap.h> -#include <linux/mfd/syscon.h> -#include <linux/regulator/consumer.h> -#include <linux/clk.h> -#include <linux/nvmem-consumer.h> - -/* Register Offsets for RB-CPR and Bit Definitions */ - -/* RBCPR Version Register */ -#define REG_RBCPR_VERSION 0 -#define RBCPR_VER_2 0x02 -#define FLAGS_IGNORE_1ST_IRQ_STATUS BIT(0) - -/* RBCPR Gate Count and Target Registers */ -#define REG_RBCPR_GCNT_TARGET(n) (0x60 + 4 * (n)) - -#define RBCPR_GCNT_TARGET_TARGET_SHIFT 0 -#define RBCPR_GCNT_TARGET_TARGET_MASK GENMASK(11, 0) -#define RBCPR_GCNT_TARGET_GCNT_SHIFT 12 -#define RBCPR_GCNT_TARGET_GCNT_MASK GENMASK(9, 0) - -/* RBCPR Timer Control */ -#define REG_RBCPR_TIMER_INTERVAL 0x44 -#define REG_RBIF_TIMER_ADJUST 0x4c - -#define RBIF_TIMER_ADJ_CONS_UP_MASK GENMASK(3, 0) -#define RBIF_TIMER_ADJ_CONS_UP_SHIFT 0 -#define RBIF_TIMER_ADJ_CONS_DOWN_MASK GENMASK(3, 0) -#define RBIF_TIMER_ADJ_CONS_DOWN_SHIFT 4 -#define RBIF_TIMER_ADJ_CLAMP_INT_MASK GENMASK(7, 0) -#define RBIF_TIMER_ADJ_CLAMP_INT_SHIFT 8 - -/* RBCPR Config Register */ -#define REG_RBIF_LIMIT 0x48 -#define RBIF_LIMIT_CEILING_MASK GENMASK(5, 0) -#define RBIF_LIMIT_CEILING_SHIFT 6 -#define RBIF_LIMIT_FLOOR_BITS 6 -#define RBIF_LIMIT_FLOOR_MASK GENMASK(5, 0) - -#define RBIF_LIMIT_CEILING_DEFAULT RBIF_LIMIT_CEILING_MASK -#define RBIF_LIMIT_FLOOR_DEFAULT 0 - -#define REG_RBIF_SW_VLEVEL 0x94 -#define RBIF_SW_VLEVEL_DEFAULT 0x20 - -#define REG_RBCPR_STEP_QUOT 0x80 -#define RBCPR_STEP_QUOT_STEPQUOT_MASK GENMASK(7, 0) -#define RBCPR_STEP_QUOT_IDLE_CLK_MASK GENMASK(3, 0) -#define RBCPR_STEP_QUOT_IDLE_CLK_SHIFT 8 - -/* RBCPR Control Register */ -#define REG_RBCPR_CTL 0x90 - -#define RBCPR_CTL_LOOP_EN BIT(0) -#define RBCPR_CTL_TIMER_EN BIT(3) -#define RBCPR_CTL_SW_AUTO_CONT_ACK_EN BIT(5) -#define RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN BIT(6) -#define RBCPR_CTL_COUNT_MODE BIT(10) -#define RBCPR_CTL_UP_THRESHOLD_MASK GENMASK(3, 0) -#define RBCPR_CTL_UP_THRESHOLD_SHIFT 24 -#define RBCPR_CTL_DN_THRESHOLD_MASK GENMASK(3, 0) -#define RBCPR_CTL_DN_THRESHOLD_SHIFT 28 - -/* RBCPR Ack/Nack Response */ -#define REG_RBIF_CONT_ACK_CMD 0x98 -#define REG_RBIF_CONT_NACK_CMD 0x9c - -/* RBCPR Result status Register */ -#define REG_RBCPR_RESULT_0 0xa0 - -#define RBCPR_RESULT0_BUSY_SHIFT 19 -#define RBCPR_RESULT0_BUSY_MASK BIT(RBCPR_RESULT0_BUSY_SHIFT) -#define RBCPR_RESULT0_ERROR_LT0_SHIFT 18 -#define RBCPR_RESULT0_ERROR_SHIFT 6 -#define RBCPR_RESULT0_ERROR_MASK GENMASK(11, 0) -#define RBCPR_RESULT0_ERROR_STEPS_SHIFT 2 -#define RBCPR_RESULT0_ERROR_STEPS_MASK GENMASK(3, 0) -#define RBCPR_RESULT0_STEP_UP_SHIFT 1 - -/* RBCPR Interrupt Control Register */ -#define REG_RBIF_IRQ_EN(n) (0x100 + 4 * (n)) -#define REG_RBIF_IRQ_CLEAR 0x110 -#define REG_RBIF_IRQ_STATUS 0x114 - -#define CPR_INT_DONE BIT(0) -#define CPR_INT_MIN BIT(1) -#define CPR_INT_DOWN BIT(2) -#define CPR_INT_MID BIT(3) -#define CPR_INT_UP BIT(4) -#define CPR_INT_MAX BIT(5) -#define CPR_INT_CLAMP BIT(6) -#define CPR_INT_ALL (CPR_INT_DONE | CPR_INT_MIN | CPR_INT_DOWN | \ - CPR_INT_MID | CPR_INT_UP | CPR_INT_MAX | CPR_INT_CLAMP) -#define CPR_INT_DEFAULT (CPR_INT_UP | CPR_INT_DOWN) - -#define CPR_NUM_RING_OSC 8 - -/* CPR eFuse parameters */ -#define CPR_FUSE_TARGET_QUOT_BITS_MASK GENMASK(11, 0) - -#define CPR_FUSE_MIN_QUOT_DIFF 50 - -#define FUSE_REVISION_UNKNOWN (-1) - -enum voltage_change_dir { - NO_CHANGE, - DOWN, - UP, -}; - -struct cpr_fuse { - char *ring_osc; - char *init_voltage; - char *quotient; - char *quotient_offset; -}; - -struct fuse_corner_data { - int ref_uV; - int max_uV; - int min_uV; - int max_volt_scale; - int max_quot_scale; - /* fuse quot */ - int quot_offset; - int quot_scale; - int quot_adjust; - /* fuse quot_offset */ - int quot_offset_scale; - int quot_offset_adjust; -}; - -struct cpr_fuses { - int init_voltage_step; - int init_voltage_width; - struct fuse_corner_data *fuse_corner_data; -}; - -struct corner_data { - unsigned int fuse_corner; - unsigned long freq; -}; - -struct cpr_desc { - unsigned int num_fuse_corners; - int min_diff_quot; - int *step_quot; - - unsigned int timer_delay_us; - unsigned int timer_cons_up; - unsigned int timer_cons_down; - unsigned int up_threshold; - unsigned int down_threshold; - unsigned int idle_clocks; - unsigned int gcnt_us; - unsigned int vdd_apc_step_up_limit; - unsigned int vdd_apc_step_down_limit; - unsigned int clamp_timer_interval; - - struct cpr_fuses cpr_fuses; - bool reduce_to_fuse_uV; - bool reduce_to_corner_uV; -}; - -struct acc_desc { - unsigned int enable_reg; - u32 enable_mask; - - struct reg_sequence *config; - struct reg_sequence *settings; - int num_regs_per_fuse; -}; - -struct cpr_acc_desc { - const struct cpr_desc *cpr_desc; - const struct acc_desc *acc_desc; -}; - -struct fuse_corner { - int min_uV; - int max_uV; - int uV; - int quot; - int step_quot; - const struct reg_sequence *accs; - int num_accs; - unsigned long max_freq; - u8 ring_osc_idx; -}; - -struct corner { - int min_uV; - int max_uV; - int uV; - int last_uV; - int quot_adjust; - u32 save_ctl; - u32 save_irq; - unsigned long freq; - struct fuse_corner *fuse_corner; -}; - -struct cpr_drv { - unsigned int num_corners; - unsigned int ref_clk_khz; - - struct generic_pm_domain pd; - struct device *dev; - struct device *attached_cpu_dev; - struct mutex lock; - void __iomem *base; - struct corner *corner; - struct regulator *vdd_apc; - struct clk *cpu_clk; - struct regmap *tcsr; - bool loop_disabled; - u32 gcnt; - unsigned long flags; - - struct fuse_corner *fuse_corners; - struct corner *corners; - - const struct cpr_desc *desc; - const struct acc_desc *acc_desc; - const struct cpr_fuse *cpr_fuses; - - struct dentry *debugfs; -}; - -static bool cpr_is_allowed(struct cpr_drv *drv) -{ - return !drv->loop_disabled; -} - -static void cpr_write(struct cpr_drv *drv, u32 offset, u32 value) -{ - writel_relaxed(value, drv->base + offset); -} - -static u32 cpr_read(struct cpr_drv *drv, u32 offset) -{ - return readl_relaxed(drv->base + offset); -} - -static void -cpr_masked_write(struct cpr_drv *drv, u32 offset, u32 mask, u32 value) -{ - u32 val; - - val = readl_relaxed(drv->base + offset); - val &= ~mask; - val |= value & mask; - writel_relaxed(val, drv->base + offset); -} - -static void cpr_irq_clr(struct cpr_drv *drv) -{ - cpr_write(drv, REG_RBIF_IRQ_CLEAR, CPR_INT_ALL); -} - -static void cpr_irq_clr_nack(struct cpr_drv *drv) -{ - cpr_irq_clr(drv); - cpr_write(drv, REG_RBIF_CONT_NACK_CMD, 1); -} - -static void cpr_irq_clr_ack(struct cpr_drv *drv) -{ - cpr_irq_clr(drv); - cpr_write(drv, REG_RBIF_CONT_ACK_CMD, 1); -} - -static void cpr_irq_set(struct cpr_drv *drv, u32 int_bits) -{ - cpr_write(drv, REG_RBIF_IRQ_EN(0), int_bits); -} - -static void cpr_ctl_modify(struct cpr_drv *drv, u32 mask, u32 value) -{ - cpr_masked_write(drv, REG_RBCPR_CTL, mask, value); -} - -static void cpr_ctl_enable(struct cpr_drv *drv, struct corner *corner) -{ - u32 val, mask; - const struct cpr_desc *desc = drv->desc; - - /* Program Consecutive Up & Down */ - val = desc->timer_cons_down << RBIF_TIMER_ADJ_CONS_DOWN_SHIFT; - val |= desc->timer_cons_up << RBIF_TIMER_ADJ_CONS_UP_SHIFT; - mask = RBIF_TIMER_ADJ_CONS_UP_MASK | RBIF_TIMER_ADJ_CONS_DOWN_MASK; - cpr_masked_write(drv, REG_RBIF_TIMER_ADJUST, mask, val); - cpr_masked_write(drv, REG_RBCPR_CTL, - RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN | - RBCPR_CTL_SW_AUTO_CONT_ACK_EN, - corner->save_ctl); - cpr_irq_set(drv, corner->save_irq); - - if (cpr_is_allowed(drv) && corner->max_uV > corner->min_uV) - val = RBCPR_CTL_LOOP_EN; - else - val = 0; - cpr_ctl_modify(drv, RBCPR_CTL_LOOP_EN, val); -} - -static void cpr_ctl_disable(struct cpr_drv *drv) -{ - cpr_irq_set(drv, 0); - cpr_ctl_modify(drv, RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN | - RBCPR_CTL_SW_AUTO_CONT_ACK_EN, 0); - cpr_masked_write(drv, REG_RBIF_TIMER_ADJUST, - RBIF_TIMER_ADJ_CONS_UP_MASK | - RBIF_TIMER_ADJ_CONS_DOWN_MASK, 0); - cpr_irq_clr(drv); - cpr_write(drv, REG_RBIF_CONT_ACK_CMD, 1); - cpr_write(drv, REG_RBIF_CONT_NACK_CMD, 1); - cpr_ctl_modify(drv, RBCPR_CTL_LOOP_EN, 0); -} - -static bool cpr_ctl_is_enabled(struct cpr_drv *drv) -{ - u32 reg_val; - - reg_val = cpr_read(drv, REG_RBCPR_CTL); - return reg_val & RBCPR_CTL_LOOP_EN; -} - -static bool cpr_ctl_is_busy(struct cpr_drv *drv) -{ - u32 reg_val; - - reg_val = cpr_read(drv, REG_RBCPR_RESULT_0); - return reg_val & RBCPR_RESULT0_BUSY_MASK; -} - -static void cpr_corner_save(struct cpr_drv *drv, struct corner *corner) -{ - corner->save_ctl = cpr_read(drv, REG_RBCPR_CTL); - corner->save_irq = cpr_read(drv, REG_RBIF_IRQ_EN(0)); -} - -static void cpr_corner_restore(struct cpr_drv *drv, struct corner *corner) -{ - u32 gcnt, ctl, irq, ro_sel, step_quot; - struct fuse_corner *fuse = corner->fuse_corner; - const struct cpr_desc *desc = drv->desc; - int i; - - ro_sel = fuse->ring_osc_idx; - gcnt = drv->gcnt; - gcnt |= fuse->quot - corner->quot_adjust; - - /* Program the step quotient and idle clocks */ - step_quot = desc->idle_clocks << RBCPR_STEP_QUOT_IDLE_CLK_SHIFT; - step_quot |= fuse->step_quot & RBCPR_STEP_QUOT_STEPQUOT_MASK; - cpr_write(drv, REG_RBCPR_STEP_QUOT, step_quot); - - /* Clear the target quotient value and gate count of all ROs */ - for (i = 0; i < CPR_NUM_RING_OSC; i++) - cpr_write(drv, REG_RBCPR_GCNT_TARGET(i), 0); - - cpr_write(drv, REG_RBCPR_GCNT_TARGET(ro_sel), gcnt); - ctl = corner->save_ctl; - cpr_write(drv, REG_RBCPR_CTL, ctl); - irq = corner->save_irq; - cpr_irq_set(drv, irq); - dev_dbg(drv->dev, "gcnt = %#08x, ctl = %#08x, irq = %#08x\n", gcnt, - ctl, irq); -} - -static void cpr_set_acc(struct regmap *tcsr, struct fuse_corner *f, - struct fuse_corner *end) -{ - if (f == end) - return; - - if (f < end) { - for (f += 1; f <= end; f++) - regmap_multi_reg_write(tcsr, f->accs, f->num_accs); - } else { - for (f -= 1; f >= end; f--) - regmap_multi_reg_write(tcsr, f->accs, f->num_accs); - } -} - -static int cpr_pre_voltage(struct cpr_drv *drv, - struct fuse_corner *fuse_corner, - enum voltage_change_dir dir) -{ - struct fuse_corner *prev_fuse_corner = drv->corner->fuse_corner; - - if (drv->tcsr && dir == DOWN) - cpr_set_acc(drv->tcsr, prev_fuse_corner, fuse_corner); - - return 0; -} - -static int cpr_post_voltage(struct cpr_drv *drv, - struct fuse_corner *fuse_corner, - enum voltage_change_dir dir) -{ - struct fuse_corner *prev_fuse_corner = drv->corner->fuse_corner; - - if (drv->tcsr && dir == UP) - cpr_set_acc(drv->tcsr, prev_fuse_corner, fuse_corner); - - return 0; -} - -static int cpr_scale_voltage(struct cpr_drv *drv, struct corner *corner, - int new_uV, enum voltage_change_dir dir) -{ - int ret; - struct fuse_corner *fuse_corner = corner->fuse_corner; - - ret = cpr_pre_voltage(drv, fuse_corner, dir); - if (ret) - return ret; - - ret = regulator_set_voltage(drv->vdd_apc, new_uV, new_uV); - if (ret) { - dev_err_ratelimited(drv->dev, "failed to set apc voltage %d\n", - new_uV); - return ret; - } - - ret = cpr_post_voltage(drv, fuse_corner, dir); - if (ret) - return ret; - - return 0; -} - -static unsigned int cpr_get_cur_perf_state(struct cpr_drv *drv) -{ - return drv->corner ? drv->corner - drv->corners + 1 : 0; -} - -static int cpr_scale(struct cpr_drv *drv, enum voltage_change_dir dir) -{ - u32 val, error_steps, reg_mask; - int last_uV, new_uV, step_uV, ret; - struct corner *corner; - const struct cpr_desc *desc = drv->desc; - - if (dir != UP && dir != DOWN) - return 0; - - step_uV = regulator_get_linear_step(drv->vdd_apc); - if (!step_uV) - return -EINVAL; - - corner = drv->corner; - - val = cpr_read(drv, REG_RBCPR_RESULT_0); - - error_steps = val >> RBCPR_RESULT0_ERROR_STEPS_SHIFT; - error_steps &= RBCPR_RESULT0_ERROR_STEPS_MASK; - last_uV = corner->last_uV; - - if (dir == UP) { - if (desc->clamp_timer_interval && - error_steps < desc->up_threshold) { - /* - * Handle the case where another measurement started - * after the interrupt was triggered due to a core - * exiting from power collapse. - */ - error_steps = max(desc->up_threshold, - desc->vdd_apc_step_up_limit); - } - - if (last_uV >= corner->max_uV) { - cpr_irq_clr_nack(drv); - - /* Maximize the UP threshold */ - reg_mask = RBCPR_CTL_UP_THRESHOLD_MASK; - reg_mask <<= RBCPR_CTL_UP_THRESHOLD_SHIFT; - val = reg_mask; - cpr_ctl_modify(drv, reg_mask, val); - - /* Disable UP interrupt */ - cpr_irq_set(drv, CPR_INT_DEFAULT & ~CPR_INT_UP); - - return 0; - } - - if (error_steps > desc->vdd_apc_step_up_limit) - error_steps = desc->vdd_apc_step_up_limit; - - /* Calculate new voltage */ - new_uV = last_uV + error_steps * step_uV; - new_uV = min(new_uV, corner->max_uV); - - dev_dbg(drv->dev, - "UP: -> new_uV: %d last_uV: %d perf state: %u\n", - new_uV, last_uV, cpr_get_cur_perf_state(drv)); - } else { - if (desc->clamp_timer_interval && - error_steps < desc->down_threshold) { - /* - * Handle the case where another measurement started - * after the interrupt was triggered due to a core - * exiting from power collapse. - */ - error_steps = max(desc->down_threshold, - desc->vdd_apc_step_down_limit); - } - - if (last_uV <= corner->min_uV) { - cpr_irq_clr_nack(drv); - - /* Enable auto nack down */ - reg_mask = RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN; - val = RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN; - - cpr_ctl_modify(drv, reg_mask, val); - - /* Disable DOWN interrupt */ - cpr_irq_set(drv, CPR_INT_DEFAULT & ~CPR_INT_DOWN); - - return 0; - } - - if (error_steps > desc->vdd_apc_step_down_limit) - error_steps = desc->vdd_apc_step_down_limit; - - /* Calculate new voltage */ - new_uV = last_uV - error_steps * step_uV; - new_uV = max(new_uV, corner->min_uV); - - dev_dbg(drv->dev, - "DOWN: -> new_uV: %d last_uV: %d perf state: %u\n", - new_uV, last_uV, cpr_get_cur_perf_state(drv)); - } - - ret = cpr_scale_voltage(drv, corner, new_uV, dir); - if (ret) { - cpr_irq_clr_nack(drv); - return ret; - } - drv->corner->last_uV = new_uV; - - if (dir == UP) { - /* Disable auto nack down */ - reg_mask = RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN; - val = 0; - } else { - /* Restore default threshold for UP */ - reg_mask = RBCPR_CTL_UP_THRESHOLD_MASK; - reg_mask <<= RBCPR_CTL_UP_THRESHOLD_SHIFT; - val = desc->up_threshold; - val <<= RBCPR_CTL_UP_THRESHOLD_SHIFT; - } - - cpr_ctl_modify(drv, reg_mask, val); - - /* Re-enable default interrupts */ - cpr_irq_set(drv, CPR_INT_DEFAULT); - - /* Ack */ - cpr_irq_clr_ack(drv); - - return 0; -} - -static irqreturn_t cpr_irq_handler(int irq, void *dev) -{ - struct cpr_drv *drv = dev; - const struct cpr_desc *desc = drv->desc; - irqreturn_t ret = IRQ_HANDLED; - u32 val; - - mutex_lock(&drv->lock); - - val = cpr_read(drv, REG_RBIF_IRQ_STATUS); - if (drv->flags & FLAGS_IGNORE_1ST_IRQ_STATUS) - val = cpr_read(drv, REG_RBIF_IRQ_STATUS); - - dev_dbg(drv->dev, "IRQ_STATUS = %#02x\n", val); - - if (!cpr_ctl_is_enabled(drv)) { - dev_dbg(drv->dev, "CPR is disabled\n"); - ret = IRQ_NONE; - } else if (cpr_ctl_is_busy(drv) && !desc->clamp_timer_interval) { - dev_dbg(drv->dev, "CPR measurement is not ready\n"); - } else if (!cpr_is_allowed(drv)) { - val = cpr_read(drv, REG_RBCPR_CTL); - dev_err_ratelimited(drv->dev, - "Interrupt broken? RBCPR_CTL = %#02x\n", - val); - ret = IRQ_NONE; - } else { - /* - * Following sequence of handling is as per each IRQ's - * priority - */ - if (val & CPR_INT_UP) { - cpr_scale(drv, UP); - } else if (val & CPR_INT_DOWN) { - cpr_scale(drv, DOWN); - } else if (val & CPR_INT_MIN) { - cpr_irq_clr_nack(drv); - } else if (val & CPR_INT_MAX) { - cpr_irq_clr_nack(drv); - } else if (val & CPR_INT_MID) { - /* RBCPR_CTL_SW_AUTO_CONT_ACK_EN is enabled */ - dev_dbg(drv->dev, "IRQ occurred for Mid Flag\n"); - } else { - dev_dbg(drv->dev, - "IRQ occurred for unknown flag (%#08x)\n", val); - } - - /* Save register values for the corner */ - cpr_corner_save(drv, drv->corner); - } - - mutex_unlock(&drv->lock); - - return ret; -} - -static int cpr_enable(struct cpr_drv *drv) -{ - int ret; - - ret = regulator_enable(drv->vdd_apc); - if (ret) - return ret; - - mutex_lock(&drv->lock); - - if (cpr_is_allowed(drv) && drv->corner) { - cpr_irq_clr(drv); - cpr_corner_restore(drv, drv->corner); - cpr_ctl_enable(drv, drv->corner); - } - - mutex_unlock(&drv->lock); - - return 0; -} - -static int cpr_disable(struct cpr_drv *drv) -{ - mutex_lock(&drv->lock); - - if (cpr_is_allowed(drv)) { - cpr_ctl_disable(drv); - cpr_irq_clr(drv); - } - - mutex_unlock(&drv->lock); - - return regulator_disable(drv->vdd_apc); -} - -static int cpr_config(struct cpr_drv *drv) -{ - int i; - u32 val, gcnt; - struct corner *corner; - const struct cpr_desc *desc = drv->desc; - - /* Disable interrupt and CPR */ - cpr_write(drv, REG_RBIF_IRQ_EN(0), 0); - cpr_write(drv, REG_RBCPR_CTL, 0); - - /* Program the default HW ceiling, floor and vlevel */ - val = (RBIF_LIMIT_CEILING_DEFAULT & RBIF_LIMIT_CEILING_MASK) - << RBIF_LIMIT_CEILING_SHIFT; - val |= RBIF_LIMIT_FLOOR_DEFAULT & RBIF_LIMIT_FLOOR_MASK; - cpr_write(drv, REG_RBIF_LIMIT, val); - cpr_write(drv, REG_RBIF_SW_VLEVEL, RBIF_SW_VLEVEL_DEFAULT); - - /* - * Clear the target quotient value and gate count of all - * ring oscillators - */ - for (i = 0; i < CPR_NUM_RING_OSC; i++) - cpr_write(drv, REG_RBCPR_GCNT_TARGET(i), 0); - - /* Init and save gcnt */ - gcnt = (drv->ref_clk_khz * desc->gcnt_us) / 1000; - gcnt = gcnt & RBCPR_GCNT_TARGET_GCNT_MASK; - gcnt <<= RBCPR_GCNT_TARGET_GCNT_SHIFT; - drv->gcnt = gcnt; - - /* Program the delay count for the timer */ - val = (drv->ref_clk_khz * desc->timer_delay_us) / 1000; - cpr_write(drv, REG_RBCPR_TIMER_INTERVAL, val); - dev_dbg(drv->dev, "Timer count: %#0x (for %d us)\n", val, - desc->timer_delay_us); - - /* Program Consecutive Up & Down */ - val = desc->timer_cons_down << RBIF_TIMER_ADJ_CONS_DOWN_SHIFT; - val |= desc->timer_cons_up << RBIF_TIMER_ADJ_CONS_UP_SHIFT; - val |= desc->clamp_timer_interval << RBIF_TIMER_ADJ_CLAMP_INT_SHIFT; - cpr_write(drv, REG_RBIF_TIMER_ADJUST, val); - - /* Program the control register */ - val = desc->up_threshold << RBCPR_CTL_UP_THRESHOLD_SHIFT; - val |= desc->down_threshold << RBCPR_CTL_DN_THRESHOLD_SHIFT; - val |= RBCPR_CTL_TIMER_EN | RBCPR_CTL_COUNT_MODE; - val |= RBCPR_CTL_SW_AUTO_CONT_ACK_EN; - cpr_write(drv, REG_RBCPR_CTL, val); - - for (i = 0; i < drv->num_corners; i++) { - corner = &drv->corners[i]; - corner->save_ctl = val; - corner->save_irq = CPR_INT_DEFAULT; - } - - cpr_irq_set(drv, CPR_INT_DEFAULT); - - val = cpr_read(drv, REG_RBCPR_VERSION); - if (val <= RBCPR_VER_2) - drv->flags |= FLAGS_IGNORE_1ST_IRQ_STATUS; - - return 0; -} - -static int cpr_set_performance_state(struct generic_pm_domain *domain, - unsigned int state) -{ - struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd); - struct corner *corner, *end; - enum voltage_change_dir dir; - int ret = 0, new_uV; - - mutex_lock(&drv->lock); - - dev_dbg(drv->dev, "%s: setting perf state: %u (prev state: %u)\n", - __func__, state, cpr_get_cur_perf_state(drv)); - - /* - * Determine new corner we're going to. - * Remove one since lowest performance state is 1. - */ - corner = drv->corners + state - 1; - end = &drv->corners[drv->num_corners - 1]; - if (corner > end || corner < drv->corners) { - ret = -EINVAL; - goto unlock; - } - - /* Determine direction */ - if (drv->corner > corner) - dir = DOWN; - else if (drv->corner < corner) - dir = UP; - else - dir = NO_CHANGE; - - if (cpr_is_allowed(drv)) - new_uV = corner->last_uV; - else - new_uV = corner->uV; - - if (cpr_is_allowed(drv)) - cpr_ctl_disable(drv); - - ret = cpr_scale_voltage(drv, corner, new_uV, dir); - if (ret) - goto unlock; - - if (cpr_is_allowed(drv)) { - cpr_irq_clr(drv); - if (drv->corner != corner) - cpr_corner_restore(drv, corner); - cpr_ctl_enable(drv, corner); - } - - drv->corner = corner; - -unlock: - mutex_unlock(&drv->lock); - - return ret; -} - -static int -cpr_populate_ring_osc_idx(struct cpr_drv *drv) -{ - struct fuse_corner *fuse = drv->fuse_corners; - struct fuse_corner *end = fuse + drv->desc->num_fuse_corners; - const struct cpr_fuse *fuses = drv->cpr_fuses; - u32 data; - int ret; - - for (; fuse < end; fuse++, fuses++) { - ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->ring_osc, &data); - if (ret) - return ret; - fuse->ring_osc_idx = data; - } - - return 0; -} - -static int cpr_read_fuse_uV(const struct cpr_desc *desc, - const struct fuse_corner_data *fdata, - const char *init_v_efuse, - int step_volt, - struct cpr_drv *drv) -{ - int step_size_uV, steps, uV; - u32 bits = 0; - int ret; - - ret = nvmem_cell_read_variable_le_u32(drv->dev, init_v_efuse, &bits); - if (ret) - return ret; - - steps = bits & ~BIT(desc->cpr_fuses.init_voltage_width - 1); - /* Not two's complement.. instead highest bit is sign bit */ - if (bits & BIT(desc->cpr_fuses.init_voltage_width - 1)) - steps = -steps; - - step_size_uV = desc->cpr_fuses.init_voltage_step; - - uV = fdata->ref_uV + steps * step_size_uV; - return DIV_ROUND_UP(uV, step_volt) * step_volt; -} - -static int cpr_fuse_corner_init(struct cpr_drv *drv) -{ - const struct cpr_desc *desc = drv->desc; - const struct cpr_fuse *fuses = drv->cpr_fuses; - const struct acc_desc *acc_desc = drv->acc_desc; - int i; - unsigned int step_volt; - struct fuse_corner_data *fdata; - struct fuse_corner *fuse, *end; - int uV; - const struct reg_sequence *accs; - int ret; - - accs = acc_desc->settings; - - step_volt = regulator_get_linear_step(drv->vdd_apc); - if (!step_volt) - return -EINVAL; - - /* Populate fuse_corner members */ - fuse = drv->fuse_corners; - end = &fuse[desc->num_fuse_corners - 1]; - fdata = desc->cpr_fuses.fuse_corner_data; - - for (i = 0; fuse <= end; fuse++, fuses++, i++, fdata++) { - /* - * Update SoC voltages: platforms might choose a different - * regulators than the one used to characterize the algorithms - * (ie, init_voltage_step). - */ - fdata->min_uV = roundup(fdata->min_uV, step_volt); - fdata->max_uV = roundup(fdata->max_uV, step_volt); - - /* Populate uV */ - uV = cpr_read_fuse_uV(desc, fdata, fuses->init_voltage, - step_volt, drv); - if (uV < 0) - return uV; - - fuse->min_uV = fdata->min_uV; - fuse->max_uV = fdata->max_uV; - fuse->uV = clamp(uV, fuse->min_uV, fuse->max_uV); - - if (fuse == end) { - /* - * Allow the highest fuse corner's PVS voltage to - * define the ceiling voltage for that corner in order - * to support SoC's in which variable ceiling values - * are required. - */ - end->max_uV = max(end->max_uV, end->uV); - } - - /* Populate target quotient by scaling */ - ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->quotient, &fuse->quot); - if (ret) - return ret; - - fuse->quot *= fdata->quot_scale; - fuse->quot += fdata->quot_offset; - fuse->quot += fdata->quot_adjust; - fuse->step_quot = desc->step_quot[fuse->ring_osc_idx]; - - /* Populate acc settings */ - fuse->accs = accs; - fuse->num_accs = acc_desc->num_regs_per_fuse; - accs += acc_desc->num_regs_per_fuse; - } - - /* - * Restrict all fuse corner PVS voltages based upon per corner - * ceiling and floor voltages. - */ - for (fuse = drv->fuse_corners, i = 0; fuse <= end; fuse++, i++) { - if (fuse->uV > fuse->max_uV) - fuse->uV = fuse->max_uV; - else if (fuse->uV < fuse->min_uV) - fuse->uV = fuse->min_uV; - - ret = regulator_is_supported_voltage(drv->vdd_apc, - fuse->min_uV, - fuse->min_uV); - if (!ret) { - dev_err(drv->dev, - "min uV: %d (fuse corner: %d) not supported by regulator\n", - fuse->min_uV, i); - return -EINVAL; - } - - ret = regulator_is_supported_voltage(drv->vdd_apc, - fuse->max_uV, - fuse->max_uV); - if (!ret) { - dev_err(drv->dev, - "max uV: %d (fuse corner: %d) not supported by regulator\n", - fuse->max_uV, i); - return -EINVAL; - } - - dev_dbg(drv->dev, - "fuse corner %d: [%d %d %d] RO%hhu quot %d squot %d\n", - i, fuse->min_uV, fuse->uV, fuse->max_uV, - fuse->ring_osc_idx, fuse->quot, fuse->step_quot); - } - - return 0; -} - -static int cpr_calculate_scaling(const char *quot_offset, - struct cpr_drv *drv, - const struct fuse_corner_data *fdata, - const struct corner *corner) -{ - u32 quot_diff = 0; - unsigned long freq_diff; - int scaling; - const struct fuse_corner *fuse, *prev_fuse; - int ret; - - fuse = corner->fuse_corner; - prev_fuse = fuse - 1; - - if (quot_offset) { - ret = nvmem_cell_read_variable_le_u32(drv->dev, quot_offset, "_diff); - if (ret) - return ret; - - quot_diff *= fdata->quot_offset_scale; - quot_diff += fdata->quot_offset_adjust; - } else { - quot_diff = fuse->quot - prev_fuse->quot; - } - - freq_diff = fuse->max_freq - prev_fuse->max_freq; - freq_diff /= 1000000; /* Convert to MHz */ - scaling = 1000 * quot_diff / freq_diff; - return min(scaling, fdata->max_quot_scale); -} - -static int cpr_interpolate(const struct corner *corner, int step_volt, - const struct fuse_corner_data *fdata) -{ - unsigned long f_high, f_low, f_diff; - int uV_high, uV_low, uV; - u64 temp, temp_limit; - const struct fuse_corner *fuse, *prev_fuse; - - fuse = corner->fuse_corner; - prev_fuse = fuse - 1; - - f_high = fuse->max_freq; - f_low = prev_fuse->max_freq; - uV_high = fuse->uV; - uV_low = prev_fuse->uV; - f_diff = fuse->max_freq - corner->freq; - - /* - * Don't interpolate in the wrong direction. This could happen - * if the adjusted fuse voltage overlaps with the previous fuse's - * adjusted voltage. - */ - if (f_high <= f_low || uV_high <= uV_low || f_high <= corner->freq) - return corner->uV; - - temp = f_diff * (uV_high - uV_low); - temp = div64_ul(temp, f_high - f_low); - - /* - * max_volt_scale has units of uV/MHz while freq values - * have units of Hz. Divide by 1000000 to convert to. - */ - temp_limit = f_diff * fdata->max_volt_scale; - do_div(temp_limit, 1000000); - - uV = uV_high - min(temp, temp_limit); - return roundup(uV, step_volt); -} - -static unsigned int cpr_get_fuse_corner(struct dev_pm_opp *opp) -{ - struct device_node *np; - unsigned int fuse_corner = 0; - - np = dev_pm_opp_get_of_node(opp); - if (of_property_read_u32(np, "qcom,opp-fuse-level", &fuse_corner)) - pr_err("%s: missing 'qcom,opp-fuse-level' property\n", - __func__); - - of_node_put(np); - - return fuse_corner; -} - -static unsigned long cpr_get_opp_hz_for_req(struct dev_pm_opp *ref, - struct device *cpu_dev) -{ - u64 rate = 0; - struct device_node *ref_np; - struct device_node *desc_np; - struct device_node *child_np = NULL; - struct device_node *child_req_np = NULL; - - desc_np = dev_pm_opp_of_get_opp_desc_node(cpu_dev); - if (!desc_np) - return 0; - - ref_np = dev_pm_opp_get_of_node(ref); - if (!ref_np) - goto out_ref; - - do { - of_node_put(child_req_np); - child_np = of_get_next_available_child(desc_np, child_np); - child_req_np = of_parse_phandle(child_np, "required-opps", 0); - } while (child_np && child_req_np != ref_np); - - if (child_np && child_req_np == ref_np) - of_property_read_u64(child_np, "opp-hz", &rate); - - of_node_put(child_req_np); - of_node_put(child_np); - of_node_put(ref_np); -out_ref: - of_node_put(desc_np); - - return (unsigned long) rate; -} - -static int cpr_corner_init(struct cpr_drv *drv) -{ - const struct cpr_desc *desc = drv->desc; - const struct cpr_fuse *fuses = drv->cpr_fuses; - int i, level, scaling = 0; - unsigned int fnum, fc; - const char *quot_offset; - struct fuse_corner *fuse, *prev_fuse; - struct corner *corner, *end; - struct corner_data *cdata; - const struct fuse_corner_data *fdata; - bool apply_scaling; - unsigned long freq_diff, freq_diff_mhz; - unsigned long freq; - int step_volt = regulator_get_linear_step(drv->vdd_apc); - struct dev_pm_opp *opp; - - if (!step_volt) - return -EINVAL; - - corner = drv->corners; - end = &corner[drv->num_corners - 1]; - - cdata = devm_kcalloc(drv->dev, drv->num_corners, - sizeof(struct corner_data), - GFP_KERNEL); - if (!cdata) - return -ENOMEM; - - /* - * Store maximum frequency for each fuse corner based on the frequency - * plan - */ - for (level = 1; level <= drv->num_corners; level++) { - opp = dev_pm_opp_find_level_exact(&drv->pd.dev, level); - if (IS_ERR(opp)) - return -EINVAL; - fc = cpr_get_fuse_corner(opp); - if (!fc) { - dev_pm_opp_put(opp); - return -EINVAL; - } - fnum = fc - 1; - freq = cpr_get_opp_hz_for_req(opp, drv->attached_cpu_dev); - if (!freq) { - dev_pm_opp_put(opp); - return -EINVAL; - } - cdata[level - 1].fuse_corner = fnum; - cdata[level - 1].freq = freq; - - fuse = &drv->fuse_corners[fnum]; - dev_dbg(drv->dev, "freq: %lu level: %u fuse level: %u\n", - freq, dev_pm_opp_get_level(opp) - 1, fnum); - if (freq > fuse->max_freq) - fuse->max_freq = freq; - dev_pm_opp_put(opp); - } - - /* - * Get the quotient adjustment scaling factor, according to: - * - * scaling = min(1000 * (QUOT(corner_N) - QUOT(corner_N-1)) - * / (freq(corner_N) - freq(corner_N-1)), max_factor) - * - * QUOT(corner_N): quotient read from fuse for fuse corner N - * QUOT(corner_N-1): quotient read from fuse for fuse corner (N - 1) - * freq(corner_N): max frequency in MHz supported by fuse corner N - * freq(corner_N-1): max frequency in MHz supported by fuse corner - * (N - 1) - * - * Then walk through the corners mapped to each fuse corner - * and calculate the quotient adjustment for each one using the - * following formula: - * - * quot_adjust = (freq_max - freq_corner) * scaling / 1000 - * - * freq_max: max frequency in MHz supported by the fuse corner - * freq_corner: frequency in MHz corresponding to the corner - * scaling: calculated from above equation - * - * - * + + - * | v | - * q | f c o | f c - * u | c l | c - * o | f t | f - * t | c a | c - * | c f g | c f - * | e | - * +--------------- +---------------- - * 0 1 2 3 4 5 6 0 1 2 3 4 5 6 - * corner corner - * - * c = corner - * f = fuse corner - * - */ - for (apply_scaling = false, i = 0; corner <= end; corner++, i++) { - fnum = cdata[i].fuse_corner; - fdata = &desc->cpr_fuses.fuse_corner_data[fnum]; - quot_offset = fuses[fnum].quotient_offset; - fuse = &drv->fuse_corners[fnum]; - if (fnum) - prev_fuse = &drv->fuse_corners[fnum - 1]; - else - prev_fuse = NULL; - - corner->fuse_corner = fuse; - corner->freq = cdata[i].freq; - corner->uV = fuse->uV; - - if (prev_fuse && cdata[i - 1].freq == prev_fuse->max_freq) { - scaling = cpr_calculate_scaling(quot_offset, drv, - fdata, corner); - if (scaling < 0) - return scaling; - - apply_scaling = true; - } else if (corner->freq == fuse->max_freq) { - /* This is a fuse corner; don't scale anything */ - apply_scaling = false; - } - - if (apply_scaling) { - freq_diff = fuse->max_freq - corner->freq; - freq_diff_mhz = freq_diff / 1000000; - corner->quot_adjust = scaling * freq_diff_mhz / 1000; - - corner->uV = cpr_interpolate(corner, step_volt, fdata); - } - - corner->max_uV = fuse->max_uV; - corner->min_uV = fuse->min_uV; - corner->uV = clamp(corner->uV, corner->min_uV, corner->max_uV); - corner->last_uV = corner->uV; - - /* Reduce the ceiling voltage if needed */ - if (desc->reduce_to_corner_uV && corner->uV < corner->max_uV) - corner->max_uV = corner->uV; - else if (desc->reduce_to_fuse_uV && fuse->uV < corner->max_uV) - corner->max_uV = max(corner->min_uV, fuse->uV); - - dev_dbg(drv->dev, "corner %d: [%d %d %d] quot %d\n", i, - corner->min_uV, corner->uV, corner->max_uV, - fuse->quot - corner->quot_adjust); - } - - return 0; -} - -static const struct cpr_fuse *cpr_get_fuses(struct cpr_drv *drv) -{ - const struct cpr_desc *desc = drv->desc; - struct cpr_fuse *fuses; - int i; - - fuses = devm_kcalloc(drv->dev, desc->num_fuse_corners, - sizeof(struct cpr_fuse), - GFP_KERNEL); - if (!fuses) - return ERR_PTR(-ENOMEM); - - for (i = 0; i < desc->num_fuse_corners; i++) { - char tbuf[32]; - - snprintf(tbuf, 32, "cpr_ring_osc%d", i + 1); - fuses[i].ring_osc = devm_kstrdup(drv->dev, tbuf, GFP_KERNEL); - if (!fuses[i].ring_osc) - return ERR_PTR(-ENOMEM); - - snprintf(tbuf, 32, "cpr_init_voltage%d", i + 1); - fuses[i].init_voltage = devm_kstrdup(drv->dev, tbuf, - GFP_KERNEL); - if (!fuses[i].init_voltage) - return ERR_PTR(-ENOMEM); - - snprintf(tbuf, 32, "cpr_quotient%d", i + 1); - fuses[i].quotient = devm_kstrdup(drv->dev, tbuf, GFP_KERNEL); - if (!fuses[i].quotient) - return ERR_PTR(-ENOMEM); - - snprintf(tbuf, 32, "cpr_quotient_offset%d", i + 1); - fuses[i].quotient_offset = devm_kstrdup(drv->dev, tbuf, - GFP_KERNEL); - if (!fuses[i].quotient_offset) - return ERR_PTR(-ENOMEM); - } - - return fuses; -} - -static void cpr_set_loop_allowed(struct cpr_drv *drv) -{ - drv->loop_disabled = false; -} - -static int cpr_init_parameters(struct cpr_drv *drv) -{ - const struct cpr_desc *desc = drv->desc; - struct clk *clk; - - clk = clk_get(drv->dev, "ref"); - if (IS_ERR(clk)) - return PTR_ERR(clk); - - drv->ref_clk_khz = clk_get_rate(clk) / 1000; - clk_put(clk); - - if (desc->timer_cons_up > RBIF_TIMER_ADJ_CONS_UP_MASK || - desc->timer_cons_down > RBIF_TIMER_ADJ_CONS_DOWN_MASK || - desc->up_threshold > RBCPR_CTL_UP_THRESHOLD_MASK || - desc->down_threshold > RBCPR_CTL_DN_THRESHOLD_MASK || - desc->idle_clocks > RBCPR_STEP_QUOT_IDLE_CLK_MASK || - desc->clamp_timer_interval > RBIF_TIMER_ADJ_CLAMP_INT_MASK) - return -EINVAL; - - dev_dbg(drv->dev, "up threshold = %u, down threshold = %u\n", - desc->up_threshold, desc->down_threshold); - - return 0; -} - -static int cpr_find_initial_corner(struct cpr_drv *drv) -{ - unsigned long rate; - const struct corner *end; - struct corner *iter; - unsigned int i = 0; - - if (!drv->cpu_clk) { - dev_err(drv->dev, "cannot get rate from NULL clk\n"); - return -EINVAL; - } - - end = &drv->corners[drv->num_corners - 1]; - rate = clk_get_rate(drv->cpu_clk); - - /* - * Some bootloaders set a CPU clock frequency that is not defined - * in the OPP table. When running at an unlisted frequency, - * cpufreq_online() will change to the OPP which has the lowest - * frequency, at or above the unlisted frequency. - * Since cpufreq_online() always "rounds up" in the case of an - * unlisted frequency, this function always "rounds down" in case - * of an unlisted frequency. That way, when cpufreq_online() - * triggers the first ever call to cpr_set_performance_state(), - * it will correctly determine the direction as UP. - */ - for (iter = drv->corners; iter <= end; iter++) { - if (iter->freq > rate) - break; - i++; - if (iter->freq == rate) { - drv->corner = iter; - break; - } - if (iter->freq < rate) - drv->corner = iter; - } - - if (!drv->corner) { - dev_err(drv->dev, "boot up corner not found\n"); - return -EINVAL; - } - - dev_dbg(drv->dev, "boot up perf state: %u\n", i); - - return 0; -} - -static const struct cpr_desc qcs404_cpr_desc = { - .num_fuse_corners = 3, - .min_diff_quot = CPR_FUSE_MIN_QUOT_DIFF, - .step_quot = (int []){ 25, 25, 25, }, - .timer_delay_us = 5000, - .timer_cons_up = 0, - .timer_cons_down = 2, - .up_threshold = 1, - .down_threshold = 3, - .idle_clocks = 15, - .gcnt_us = 1, - .vdd_apc_step_up_limit = 1, - .vdd_apc_step_down_limit = 1, - .cpr_fuses = { - .init_voltage_step = 8000, - .init_voltage_width = 6, - .fuse_corner_data = (struct fuse_corner_data[]){ - /* fuse corner 0 */ - { - .ref_uV = 1224000, - .max_uV = 1224000, - .min_uV = 1048000, - .max_volt_scale = 0, - .max_quot_scale = 0, - .quot_offset = 0, - .quot_scale = 1, - .quot_adjust = 0, - .quot_offset_scale = 5, - .quot_offset_adjust = 0, - }, - /* fuse corner 1 */ - { - .ref_uV = 1288000, - .max_uV = 1288000, - .min_uV = 1048000, - .max_volt_scale = 2000, - .max_quot_scale = 1400, - .quot_offset = 0, - .quot_scale = 1, - .quot_adjust = -20, - .quot_offset_scale = 5, - .quot_offset_adjust = 0, - }, - /* fuse corner 2 */ - { - .ref_uV = 1352000, - .max_uV = 1384000, - .min_uV = 1088000, - .max_volt_scale = 2000, - .max_quot_scale = 1400, - .quot_offset = 0, - .quot_scale = 1, - .quot_adjust = 0, - .quot_offset_scale = 5, - .quot_offset_adjust = 0, - }, - }, - }, -}; - -static const struct acc_desc qcs404_acc_desc = { - .settings = (struct reg_sequence[]){ - { 0xb120, 0x1041040 }, - { 0xb124, 0x41 }, - { 0xb120, 0x0 }, - { 0xb124, 0x0 }, - { 0xb120, 0x0 }, - { 0xb124, 0x0 }, - }, - .config = (struct reg_sequence[]){ - { 0xb138, 0xff }, - { 0xb130, 0x5555 }, - }, - .num_regs_per_fuse = 2, -}; - -static const struct cpr_acc_desc qcs404_cpr_acc_desc = { - .cpr_desc = &qcs404_cpr_desc, - .acc_desc = &qcs404_acc_desc, -}; - -static unsigned int cpr_get_performance_state(struct generic_pm_domain *genpd, - struct dev_pm_opp *opp) -{ - return dev_pm_opp_get_level(opp); -} - -static int cpr_power_off(struct generic_pm_domain *domain) -{ - struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd); - - return cpr_disable(drv); -} - -static int cpr_power_on(struct generic_pm_domain *domain) -{ - struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd); - - return cpr_enable(drv); -} - -static int cpr_pd_attach_dev(struct generic_pm_domain *domain, - struct device *dev) -{ - struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd); - const struct acc_desc *acc_desc = drv->acc_desc; - int ret = 0; - - mutex_lock(&drv->lock); - - dev_dbg(drv->dev, "attach callback for: %s\n", dev_name(dev)); - - /* - * This driver only supports scaling voltage for a CPU cluster - * where all CPUs in the cluster share a single regulator. - * Therefore, save the struct device pointer only for the first - * CPU device that gets attached. There is no need to do any - * additional initialization when further CPUs get attached. - */ - if (drv->attached_cpu_dev) - goto unlock; - - /* - * cpr_scale_voltage() requires the direction (if we are changing - * to a higher or lower OPP). The first time - * cpr_set_performance_state() is called, there is no previous - * performance state defined. Therefore, we call - * cpr_find_initial_corner() that gets the CPU clock frequency - * set by the bootloader, so that we can determine the direction - * the first time cpr_set_performance_state() is called. - */ - drv->cpu_clk = devm_clk_get(dev, NULL); - if (IS_ERR(drv->cpu_clk)) { - ret = PTR_ERR(drv->cpu_clk); - if (ret != -EPROBE_DEFER) - dev_err(drv->dev, "could not get cpu clk: %d\n", ret); - goto unlock; - } - drv->attached_cpu_dev = dev; - - dev_dbg(drv->dev, "using cpu clk from: %s\n", - dev_name(drv->attached_cpu_dev)); - - /* - * Everything related to (virtual) corners has to be initialized - * here, when attaching to the power domain, since we need to know - * the maximum frequency for each fuse corner, and this is only - * available after the cpufreq driver has attached to us. - * The reason for this is that we need to know the highest - * frequency associated with each fuse corner. - */ - ret = dev_pm_opp_get_opp_count(&drv->pd.dev); - if (ret < 0) { - dev_err(drv->dev, "could not get OPP count\n"); - goto unlock; - } - drv->num_corners = ret; - - if (drv->num_corners < 2) { - dev_err(drv->dev, "need at least 2 OPPs to use CPR\n"); - ret = -EINVAL; - goto unlock; - } - - drv->corners = devm_kcalloc(drv->dev, drv->num_corners, - sizeof(*drv->corners), - GFP_KERNEL); - if (!drv->corners) { - ret = -ENOMEM; - goto unlock; - } - - ret = cpr_corner_init(drv); - if (ret) - goto unlock; - - cpr_set_loop_allowed(drv); - - ret = cpr_init_parameters(drv); - if (ret) - goto unlock; - - /* Configure CPR HW but keep it disabled */ - ret = cpr_config(drv); - if (ret) - goto unlock; - - ret = cpr_find_initial_corner(drv); - if (ret) - goto unlock; - - if (acc_desc->config) - regmap_multi_reg_write(drv->tcsr, acc_desc->config, - acc_desc->num_regs_per_fuse); - - /* Enable ACC if required */ - if (acc_desc->enable_mask) - regmap_update_bits(drv->tcsr, acc_desc->enable_reg, - acc_desc->enable_mask, - acc_desc->enable_mask); - - dev_info(drv->dev, "driver initialized with %u OPPs\n", - drv->num_corners); - -unlock: - mutex_unlock(&drv->lock); - - return ret; -} - -static int cpr_debug_info_show(struct seq_file *s, void *unused) -{ - u32 gcnt, ro_sel, ctl, irq_status, reg, error_steps; - u32 step_dn, step_up, error, error_lt0, busy; - struct cpr_drv *drv = s->private; - struct fuse_corner *fuse_corner; - struct corner *corner; - - corner = drv->corner; - fuse_corner = corner->fuse_corner; - - seq_printf(s, "corner, current_volt = %d uV\n", - corner->last_uV); - - ro_sel = fuse_corner->ring_osc_idx; - gcnt = cpr_read(drv, REG_RBCPR_GCNT_TARGET(ro_sel)); - seq_printf(s, "rbcpr_gcnt_target (%u) = %#02X\n", ro_sel, gcnt); - - ctl = cpr_read(drv, REG_RBCPR_CTL); - seq_printf(s, "rbcpr_ctl = %#02X\n", ctl); - - irq_status = cpr_read(drv, REG_RBIF_IRQ_STATUS); - seq_printf(s, "rbcpr_irq_status = %#02X\n", irq_status); - - reg = cpr_read(drv, REG_RBCPR_RESULT_0); - seq_printf(s, "rbcpr_result_0 = %#02X\n", reg); - - step_dn = reg & 0x01; - step_up = (reg >> RBCPR_RESULT0_STEP_UP_SHIFT) & 0x01; - seq_printf(s, " [step_dn = %u", step_dn); - - seq_printf(s, ", step_up = %u", step_up); - - error_steps = (reg >> RBCPR_RESULT0_ERROR_STEPS_SHIFT) - & RBCPR_RESULT0_ERROR_STEPS_MASK; - seq_printf(s, ", error_steps = %u", error_steps); - - error = (reg >> RBCPR_RESULT0_ERROR_SHIFT) & RBCPR_RESULT0_ERROR_MASK; - seq_printf(s, ", error = %u", error); - - error_lt0 = (reg >> RBCPR_RESULT0_ERROR_LT0_SHIFT) & 0x01; - seq_printf(s, ", error_lt_0 = %u", error_lt0); - - busy = (reg >> RBCPR_RESULT0_BUSY_SHIFT) & 0x01; - seq_printf(s, ", busy = %u]\n", busy); - - return 0; -} -DEFINE_SHOW_ATTRIBUTE(cpr_debug_info); - -static void cpr_debugfs_init(struct cpr_drv *drv) -{ - drv->debugfs = debugfs_create_dir("qcom_cpr", NULL); - - debugfs_create_file("debug_info", 0444, drv->debugfs, - drv, &cpr_debug_info_fops); -} - -static int cpr_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct cpr_drv *drv; - int irq, ret; - const struct cpr_acc_desc *data; - struct device_node *np; - u32 cpr_rev = FUSE_REVISION_UNKNOWN; - - data = of_device_get_match_data(dev); - if (!data || !data->cpr_desc || !data->acc_desc) - return -EINVAL; - - drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL); - if (!drv) - return -ENOMEM; - drv->dev = dev; - drv->desc = data->cpr_desc; - drv->acc_desc = data->acc_desc; - - drv->fuse_corners = devm_kcalloc(dev, drv->desc->num_fuse_corners, - sizeof(*drv->fuse_corners), - GFP_KERNEL); - if (!drv->fuse_corners) - return -ENOMEM; - - np = of_parse_phandle(dev->of_node, "acc-syscon", 0); - if (!np) - return -ENODEV; - - drv->tcsr = syscon_node_to_regmap(np); - of_node_put(np); - if (IS_ERR(drv->tcsr)) - return PTR_ERR(drv->tcsr); - - drv->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(drv->base)) - return PTR_ERR(drv->base); - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return -EINVAL; - - drv->vdd_apc = devm_regulator_get(dev, "vdd-apc"); - if (IS_ERR(drv->vdd_apc)) - return PTR_ERR(drv->vdd_apc); - - /* - * Initialize fuse corners, since it simply depends - * on data in efuses. - * Everything related to (virtual) corners has to be - * initialized after attaching to the power domain, - * since it depends on the CPU's OPP table. - */ - ret = nvmem_cell_read_variable_le_u32(dev, "cpr_fuse_revision", &cpr_rev); - if (ret) - return ret; - - drv->cpr_fuses = cpr_get_fuses(drv); - if (IS_ERR(drv->cpr_fuses)) - return PTR_ERR(drv->cpr_fuses); - - ret = cpr_populate_ring_osc_idx(drv); - if (ret) - return ret; - - ret = cpr_fuse_corner_init(drv); - if (ret) - return ret; - - mutex_init(&drv->lock); - - ret = devm_request_threaded_irq(dev, irq, NULL, - cpr_irq_handler, - IRQF_ONESHOT | IRQF_TRIGGER_RISING, - "cpr", drv); - if (ret) - return ret; - - drv->pd.name = devm_kstrdup_const(dev, dev->of_node->full_name, - GFP_KERNEL); - if (!drv->pd.name) - return -EINVAL; - - drv->pd.power_off = cpr_power_off; - drv->pd.power_on = cpr_power_on; - drv->pd.set_performance_state = cpr_set_performance_state; - drv->pd.opp_to_performance_state = cpr_get_performance_state; - drv->pd.attach_dev = cpr_pd_attach_dev; - - ret = pm_genpd_init(&drv->pd, NULL, true); - if (ret) - return ret; - - ret = of_genpd_add_provider_simple(dev->of_node, &drv->pd); - if (ret) - goto err_remove_genpd; - - platform_set_drvdata(pdev, drv); - cpr_debugfs_init(drv); - - return 0; - -err_remove_genpd: - pm_genpd_remove(&drv->pd); - return ret; -} - -static int cpr_remove(struct platform_device *pdev) -{ - struct cpr_drv *drv = platform_get_drvdata(pdev); - - if (cpr_is_allowed(drv)) { - cpr_ctl_disable(drv); - cpr_irq_set(drv, 0); - } - - of_genpd_del_provider(pdev->dev.of_node); - pm_genpd_remove(&drv->pd); - - debugfs_remove_recursive(drv->debugfs); - - return 0; -} - -static const struct of_device_id cpr_match_table[] = { - { .compatible = "qcom,qcs404-cpr", .data = &qcs404_cpr_acc_desc }, - { } -}; -MODULE_DEVICE_TABLE(of, cpr_match_table); - -static struct platform_driver cpr_driver = { - .probe = cpr_probe, - .remove = cpr_remove, - .driver = { - .name = "qcom-cpr", - .of_match_table = cpr_match_table, - }, -}; -module_platform_driver(cpr_driver); - -MODULE_DESCRIPTION("Core Power Reduction (CPR) driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c deleted file mode 100644 index 63c35a32065b..000000000000 --- a/drivers/soc/qcom/rpmhpd.c +++ /dev/null @@ -1,870 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2018, The Linux Foundation. All rights reserved.*/ - -#include <linux/err.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/pm_domain.h> -#include <linux/slab.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/pm_opp.h> -#include <soc/qcom/cmd-db.h> -#include <soc/qcom/rpmh.h> -#include <dt-bindings/power/qcom-rpmpd.h> - -#define domain_to_rpmhpd(domain) container_of(domain, struct rpmhpd, pd) - -#define RPMH_ARC_MAX_LEVELS 16 - -/** - * struct rpmhpd - top level RPMh power domain resource data structure - * @dev: rpmh power domain controller device - * @pd: generic_pm_domain corresponding to the power domain - * @parent: generic_pm_domain corresponding to the parent's power domain - * @peer: A peer power domain in case Active only Voting is - * supported - * @active_only: True if it represents an Active only peer - * @corner: current corner - * @active_corner: current active corner - * @enable_corner: lowest non-zero corner - * @level: An array of level (vlvl) to corner (hlvl) mappings - * derived from cmd-db - * @level_count: Number of levels supported by the power domain. max - * being 16 (0 - 15) - * @enabled: true if the power domain is enabled - * @res_name: Resource name used for cmd-db lookup - * @addr: Resource address as looped up using resource name from - * cmd-db - * @state_synced: Indicator that sync_state has been invoked for the rpmhpd resource - */ -struct rpmhpd { - struct device *dev; - struct generic_pm_domain pd; - struct generic_pm_domain *parent; - struct rpmhpd *peer; - const bool active_only; - unsigned int corner; - unsigned int active_corner; - unsigned int enable_corner; - u32 level[RPMH_ARC_MAX_LEVELS]; - size_t level_count; - bool enabled; - const char *res_name; - u32 addr; - bool state_synced; -}; - -struct rpmhpd_desc { - struct rpmhpd **rpmhpds; - size_t num_pds; -}; - -static DEFINE_MUTEX(rpmhpd_lock); - -/* RPMH powerdomains */ - -static struct rpmhpd cx_ao; -static struct rpmhpd mx; -static struct rpmhpd mx_ao; -static struct rpmhpd cx = { - .pd = { .name = "cx", }, - .peer = &cx_ao, - .res_name = "cx.lvl", -}; - -static struct rpmhpd cx_ao = { - .pd = { .name = "cx_ao", }, - .active_only = true, - .peer = &cx, - .res_name = "cx.lvl", -}; - -static struct rpmhpd cx_ao_w_mx_parent; -static struct rpmhpd cx_w_mx_parent = { - .pd = { .name = "cx", }, - .peer = &cx_ao_w_mx_parent, - .parent = &mx.pd, - .res_name = "cx.lvl", -}; - -static struct rpmhpd cx_ao_w_mx_parent = { - .pd = { .name = "cx_ao", }, - .active_only = true, - .peer = &cx_w_mx_parent, - .parent = &mx_ao.pd, - .res_name = "cx.lvl", -}; - -static struct rpmhpd ebi = { - .pd = { .name = "ebi", }, - .res_name = "ebi.lvl", -}; - -static struct rpmhpd gfx = { - .pd = { .name = "gfx", }, - .res_name = "gfx.lvl", -}; - -static struct rpmhpd lcx = { - .pd = { .name = "lcx", }, - .res_name = "lcx.lvl", -}; - -static struct rpmhpd lmx = { - .pd = { .name = "lmx", }, - .res_name = "lmx.lvl", -}; - -static struct rpmhpd mmcx_ao; -static struct rpmhpd mmcx = { - .pd = { .name = "mmcx", }, - .peer = &mmcx_ao, - .res_name = "mmcx.lvl", -}; - -static struct rpmhpd mmcx_ao = { - .pd = { .name = "mmcx_ao", }, - .active_only = true, - .peer = &mmcx, - .res_name = "mmcx.lvl", -}; - -static struct rpmhpd mmcx_ao_w_cx_parent; -static struct rpmhpd mmcx_w_cx_parent = { - .pd = { .name = "mmcx", }, - .peer = &mmcx_ao_w_cx_parent, - .parent = &cx.pd, - .res_name = "mmcx.lvl", -}; - -static struct rpmhpd mmcx_ao_w_cx_parent = { - .pd = { .name = "mmcx_ao", }, - .active_only = true, - .peer = &mmcx_w_cx_parent, - .parent = &cx_ao.pd, - .res_name = "mmcx.lvl", -}; - -static struct rpmhpd mss = { - .pd = { .name = "mss", }, - .res_name = "mss.lvl", -}; - -static struct rpmhpd mx_ao; -static struct rpmhpd mx = { - .pd = { .name = "mx", }, - .peer = &mx_ao, - .res_name = "mx.lvl", -}; - -static struct rpmhpd mx_ao = { - .pd = { .name = "mx_ao", }, - .active_only = true, - .peer = &mx, - .res_name = "mx.lvl", -}; - -static struct rpmhpd mxc_ao; -static struct rpmhpd mxc = { - .pd = { .name = "mxc", }, - .peer = &mxc_ao, - .res_name = "mxc.lvl", -}; - -static struct rpmhpd mxc_ao = { - .pd = { .name = "mxc_ao", }, - .active_only = true, - .peer = &mxc, - .res_name = "mxc.lvl", -}; - -static struct rpmhpd nsp = { - .pd = { .name = "nsp", }, - .res_name = "nsp.lvl", -}; - -static struct rpmhpd nsp0 = { - .pd = { .name = "nsp0", }, - .res_name = "nsp0.lvl", -}; - -static struct rpmhpd nsp1 = { - .pd = { .name = "nsp1", }, - .res_name = "nsp1.lvl", -}; - -static struct rpmhpd qphy = { - .pd = { .name = "qphy", }, - .res_name = "qphy.lvl", -}; - -/* SA8540P RPMH powerdomains */ -static struct rpmhpd *sa8540p_rpmhpds[] = { - [SC8280XP_CX] = &cx, - [SC8280XP_CX_AO] = &cx_ao, - [SC8280XP_EBI] = &ebi, - [SC8280XP_GFX] = &gfx, - [SC8280XP_LCX] = &lcx, - [SC8280XP_LMX] = &lmx, - [SC8280XP_MMCX] = &mmcx, - [SC8280XP_MMCX_AO] = &mmcx_ao, - [SC8280XP_MX] = &mx, - [SC8280XP_MX_AO] = &mx_ao, - [SC8280XP_NSP] = &nsp, -}; - -static const struct rpmhpd_desc sa8540p_desc = { - .rpmhpds = sa8540p_rpmhpds, - .num_pds = ARRAY_SIZE(sa8540p_rpmhpds), -}; - -/* SA8775P RPMH power domains */ -static struct rpmhpd *sa8775p_rpmhpds[] = { - [SA8775P_CX] = &cx, - [SA8775P_CX_AO] = &cx_ao, - [SA8775P_EBI] = &ebi, - [SA8775P_GFX] = &gfx, - [SA8775P_LCX] = &lcx, - [SA8775P_LMX] = &lmx, - [SA8775P_MMCX] = &mmcx, - [SA8775P_MMCX_AO] = &mmcx_ao, - [SA8775P_MXC] = &mxc, - [SA8775P_MXC_AO] = &mxc_ao, - [SA8775P_MX] = &mx, - [SA8775P_MX_AO] = &mx_ao, - [SA8775P_NSP0] = &nsp0, - [SA8775P_NSP1] = &nsp1, -}; - -static const struct rpmhpd_desc sa8775p_desc = { - .rpmhpds = sa8775p_rpmhpds, - .num_pds = ARRAY_SIZE(sa8775p_rpmhpds), -}; - -/* SDM670 RPMH powerdomains */ -static struct rpmhpd *sdm670_rpmhpds[] = { - [SDM670_CX] = &cx_w_mx_parent, - [SDM670_CX_AO] = &cx_ao_w_mx_parent, - [SDM670_GFX] = &gfx, - [SDM670_LCX] = &lcx, - [SDM670_LMX] = &lmx, - [SDM670_MSS] = &mss, - [SDM670_MX] = &mx, - [SDM670_MX_AO] = &mx_ao, -}; - -static const struct rpmhpd_desc sdm670_desc = { - .rpmhpds = sdm670_rpmhpds, - .num_pds = ARRAY_SIZE(sdm670_rpmhpds), -}; - -/* SDM845 RPMH powerdomains */ -static struct rpmhpd *sdm845_rpmhpds[] = { - [SDM845_CX] = &cx_w_mx_parent, - [SDM845_CX_AO] = &cx_ao_w_mx_parent, - [SDM845_EBI] = &ebi, - [SDM845_GFX] = &gfx, - [SDM845_LCX] = &lcx, - [SDM845_LMX] = &lmx, - [SDM845_MSS] = &mss, - [SDM845_MX] = &mx, - [SDM845_MX_AO] = &mx_ao, -}; - -static const struct rpmhpd_desc sdm845_desc = { - .rpmhpds = sdm845_rpmhpds, - .num_pds = ARRAY_SIZE(sdm845_rpmhpds), -}; - -/* SDX55 RPMH powerdomains */ -static struct rpmhpd *sdx55_rpmhpds[] = { - [SDX55_CX] = &cx_w_mx_parent, - [SDX55_MSS] = &mss, - [SDX55_MX] = &mx, -}; - -static const struct rpmhpd_desc sdx55_desc = { - .rpmhpds = sdx55_rpmhpds, - .num_pds = ARRAY_SIZE(sdx55_rpmhpds), -}; - -/* SDX65 RPMH powerdomains */ -static struct rpmhpd *sdx65_rpmhpds[] = { - [SDX65_CX] = &cx_w_mx_parent, - [SDX65_CX_AO] = &cx_ao_w_mx_parent, - [SDX65_MSS] = &mss, - [SDX65_MX] = &mx, - [SDX65_MX_AO] = &mx_ao, - [SDX65_MXC] = &mxc, -}; - -static const struct rpmhpd_desc sdx65_desc = { - .rpmhpds = sdx65_rpmhpds, - .num_pds = ARRAY_SIZE(sdx65_rpmhpds), -}; - -/* SM6350 RPMH powerdomains */ -static struct rpmhpd *sm6350_rpmhpds[] = { - [SM6350_CX] = &cx_w_mx_parent, - [SM6350_GFX] = &gfx, - [SM6350_LCX] = &lcx, - [SM6350_LMX] = &lmx, - [SM6350_MSS] = &mss, - [SM6350_MX] = &mx, -}; - -static const struct rpmhpd_desc sm6350_desc = { - .rpmhpds = sm6350_rpmhpds, - .num_pds = ARRAY_SIZE(sm6350_rpmhpds), -}; - -/* SM8150 RPMH powerdomains */ -static struct rpmhpd *sm8150_rpmhpds[] = { - [SM8150_CX] = &cx_w_mx_parent, - [SM8150_CX_AO] = &cx_ao_w_mx_parent, - [SM8150_EBI] = &ebi, - [SM8150_GFX] = &gfx, - [SM8150_LCX] = &lcx, - [SM8150_LMX] = &lmx, - [SM8150_MMCX] = &mmcx, - [SM8150_MMCX_AO] = &mmcx_ao, - [SM8150_MSS] = &mss, - [SM8150_MX] = &mx, - [SM8150_MX_AO] = &mx_ao, -}; - -static const struct rpmhpd_desc sm8150_desc = { - .rpmhpds = sm8150_rpmhpds, - .num_pds = ARRAY_SIZE(sm8150_rpmhpds), -}; - -static struct rpmhpd *sa8155p_rpmhpds[] = { - [SA8155P_CX] = &cx_w_mx_parent, - [SA8155P_CX_AO] = &cx_ao_w_mx_parent, - [SA8155P_EBI] = &ebi, - [SA8155P_GFX] = &gfx, - [SA8155P_MSS] = &mss, - [SA8155P_MX] = &mx, - [SA8155P_MX_AO] = &mx_ao, -}; - -static const struct rpmhpd_desc sa8155p_desc = { - .rpmhpds = sa8155p_rpmhpds, - .num_pds = ARRAY_SIZE(sa8155p_rpmhpds), -}; - -/* SM8250 RPMH powerdomains */ -static struct rpmhpd *sm8250_rpmhpds[] = { - [SM8250_CX] = &cx_w_mx_parent, - [SM8250_CX_AO] = &cx_ao_w_mx_parent, - [SM8250_EBI] = &ebi, - [SM8250_GFX] = &gfx, - [SM8250_LCX] = &lcx, - [SM8250_LMX] = &lmx, - [SM8250_MMCX] = &mmcx, - [SM8250_MMCX_AO] = &mmcx_ao, - [SM8250_MX] = &mx, - [SM8250_MX_AO] = &mx_ao, -}; - -static const struct rpmhpd_desc sm8250_desc = { - .rpmhpds = sm8250_rpmhpds, - .num_pds = ARRAY_SIZE(sm8250_rpmhpds), -}; - -/* SM8350 Power domains */ -static struct rpmhpd *sm8350_rpmhpds[] = { - [SM8350_CX] = &cx_w_mx_parent, - [SM8350_CX_AO] = &cx_ao_w_mx_parent, - [SM8350_EBI] = &ebi, - [SM8350_GFX] = &gfx, - [SM8350_LCX] = &lcx, - [SM8350_LMX] = &lmx, - [SM8350_MMCX] = &mmcx, - [SM8350_MMCX_AO] = &mmcx_ao, - [SM8350_MSS] = &mss, - [SM8350_MX] = &mx, - [SM8350_MX_AO] = &mx_ao, - [SM8350_MXC] = &mxc, - [SM8350_MXC_AO] = &mxc_ao, -}; - -static const struct rpmhpd_desc sm8350_desc = { - .rpmhpds = sm8350_rpmhpds, - .num_pds = ARRAY_SIZE(sm8350_rpmhpds), -}; - -/* SM8450 RPMH powerdomains */ -static struct rpmhpd *sm8450_rpmhpds[] = { - [SM8450_CX] = &cx, - [SM8450_CX_AO] = &cx_ao, - [SM8450_EBI] = &ebi, - [SM8450_GFX] = &gfx, - [SM8450_LCX] = &lcx, - [SM8450_LMX] = &lmx, - [SM8450_MMCX] = &mmcx_w_cx_parent, - [SM8450_MMCX_AO] = &mmcx_ao_w_cx_parent, - [SM8450_MSS] = &mss, - [SM8450_MX] = &mx, - [SM8450_MX_AO] = &mx_ao, - [SM8450_MXC] = &mxc, - [SM8450_MXC_AO] = &mxc_ao, -}; - -static const struct rpmhpd_desc sm8450_desc = { - .rpmhpds = sm8450_rpmhpds, - .num_pds = ARRAY_SIZE(sm8450_rpmhpds), -}; - -/* SM8550 RPMH powerdomains */ -static struct rpmhpd *sm8550_rpmhpds[] = { - [SM8550_CX] = &cx, - [SM8550_CX_AO] = &cx_ao, - [SM8550_EBI] = &ebi, - [SM8550_GFX] = &gfx, - [SM8550_LCX] = &lcx, - [SM8550_LMX] = &lmx, - [SM8550_MMCX] = &mmcx_w_cx_parent, - [SM8550_MMCX_AO] = &mmcx_ao_w_cx_parent, - [SM8550_MSS] = &mss, - [SM8550_MX] = &mx, - [SM8550_MX_AO] = &mx_ao, - [SM8550_MXC] = &mxc, - [SM8550_MXC_AO] = &mxc_ao, - [SM8550_NSP] = &nsp, -}; - -static const struct rpmhpd_desc sm8550_desc = { - .rpmhpds = sm8550_rpmhpds, - .num_pds = ARRAY_SIZE(sm8550_rpmhpds), -}; - -/* QDU1000/QRU1000 RPMH powerdomains */ -static struct rpmhpd *qdu1000_rpmhpds[] = { - [QDU1000_CX] = &cx, - [QDU1000_EBI] = &ebi, - [QDU1000_MSS] = &mss, - [QDU1000_MX] = &mx, -}; - -static const struct rpmhpd_desc qdu1000_desc = { - .rpmhpds = qdu1000_rpmhpds, - .num_pds = ARRAY_SIZE(qdu1000_rpmhpds), -}; - -/* SC7180 RPMH powerdomains */ -static struct rpmhpd *sc7180_rpmhpds[] = { - [SC7180_CX] = &cx_w_mx_parent, - [SC7180_CX_AO] = &cx_ao_w_mx_parent, - [SC7180_GFX] = &gfx, - [SC7180_LCX] = &lcx, - [SC7180_LMX] = &lmx, - [SC7180_MSS] = &mss, - [SC7180_MX] = &mx, - [SC7180_MX_AO] = &mx_ao, -}; - -static const struct rpmhpd_desc sc7180_desc = { - .rpmhpds = sc7180_rpmhpds, - .num_pds = ARRAY_SIZE(sc7180_rpmhpds), -}; - -/* SC7280 RPMH powerdomains */ -static struct rpmhpd *sc7280_rpmhpds[] = { - [SC7280_CX] = &cx, - [SC7280_CX_AO] = &cx_ao, - [SC7280_EBI] = &ebi, - [SC7280_GFX] = &gfx, - [SC7280_LCX] = &lcx, - [SC7280_LMX] = &lmx, - [SC7280_MSS] = &mss, - [SC7280_MX] = &mx, - [SC7280_MX_AO] = &mx_ao, -}; - -static const struct rpmhpd_desc sc7280_desc = { - .rpmhpds = sc7280_rpmhpds, - .num_pds = ARRAY_SIZE(sc7280_rpmhpds), -}; - -/* SC8180x RPMH powerdomains */ -static struct rpmhpd *sc8180x_rpmhpds[] = { - [SC8180X_CX] = &cx_w_mx_parent, - [SC8180X_CX_AO] = &cx_ao_w_mx_parent, - [SC8180X_EBI] = &ebi, - [SC8180X_GFX] = &gfx, - [SC8180X_LCX] = &lcx, - [SC8180X_LMX] = &lmx, - [SC8180X_MMCX] = &mmcx, - [SC8180X_MMCX_AO] = &mmcx_ao, - [SC8180X_MSS] = &mss, - [SC8180X_MX] = &mx, - [SC8180X_MX_AO] = &mx_ao, -}; - -static const struct rpmhpd_desc sc8180x_desc = { - .rpmhpds = sc8180x_rpmhpds, - .num_pds = ARRAY_SIZE(sc8180x_rpmhpds), -}; - -/* SC8280xp RPMH powerdomains */ -static struct rpmhpd *sc8280xp_rpmhpds[] = { - [SC8280XP_CX] = &cx, - [SC8280XP_CX_AO] = &cx_ao, - [SC8280XP_EBI] = &ebi, - [SC8280XP_GFX] = &gfx, - [SC8280XP_LCX] = &lcx, - [SC8280XP_LMX] = &lmx, - [SC8280XP_MMCX] = &mmcx, - [SC8280XP_MMCX_AO] = &mmcx_ao, - [SC8280XP_MX] = &mx, - [SC8280XP_MX_AO] = &mx_ao, - [SC8280XP_NSP] = &nsp, - [SC8280XP_QPHY] = &qphy, -}; - -static const struct rpmhpd_desc sc8280xp_desc = { - .rpmhpds = sc8280xp_rpmhpds, - .num_pds = ARRAY_SIZE(sc8280xp_rpmhpds), -}; - -static const struct of_device_id rpmhpd_match_table[] = { - { .compatible = "qcom,qdu1000-rpmhpd", .data = &qdu1000_desc }, - { .compatible = "qcom,sa8155p-rpmhpd", .data = &sa8155p_desc }, - { .compatible = "qcom,sa8540p-rpmhpd", .data = &sa8540p_desc }, - { .compatible = "qcom,sa8775p-rpmhpd", .data = &sa8775p_desc }, - { .compatible = "qcom,sc7180-rpmhpd", .data = &sc7180_desc }, - { .compatible = "qcom,sc7280-rpmhpd", .data = &sc7280_desc }, - { .compatible = "qcom,sc8180x-rpmhpd", .data = &sc8180x_desc }, - { .compatible = "qcom,sc8280xp-rpmhpd", .data = &sc8280xp_desc }, - { .compatible = "qcom,sdm670-rpmhpd", .data = &sdm670_desc }, - { .compatible = "qcom,sdm845-rpmhpd", .data = &sdm845_desc }, - { .compatible = "qcom,sdx55-rpmhpd", .data = &sdx55_desc}, - { .compatible = "qcom,sdx65-rpmhpd", .data = &sdx65_desc}, - { .compatible = "qcom,sm6350-rpmhpd", .data = &sm6350_desc }, - { .compatible = "qcom,sm8150-rpmhpd", .data = &sm8150_desc }, - { .compatible = "qcom,sm8250-rpmhpd", .data = &sm8250_desc }, - { .compatible = "qcom,sm8350-rpmhpd", .data = &sm8350_desc }, - { .compatible = "qcom,sm8450-rpmhpd", .data = &sm8450_desc }, - { .compatible = "qcom,sm8550-rpmhpd", .data = &sm8550_desc }, - { } -}; -MODULE_DEVICE_TABLE(of, rpmhpd_match_table); - -static int rpmhpd_send_corner(struct rpmhpd *pd, int state, - unsigned int corner, bool sync) -{ - struct tcs_cmd cmd = { - .addr = pd->addr, - .data = corner, - }; - - /* - * Wait for an ack only when we are increasing the - * perf state of the power domain - */ - if (sync) - return rpmh_write(pd->dev, state, &cmd, 1); - else - return rpmh_write_async(pd->dev, state, &cmd, 1); -} - -static void to_active_sleep(struct rpmhpd *pd, unsigned int corner, - unsigned int *active, unsigned int *sleep) -{ - *active = corner; - - if (pd->active_only) - *sleep = 0; - else - *sleep = *active; -} - -/* - * This function is used to aggregate the votes across the active only - * resources and its peers. The aggregated votes are sent to RPMh as - * ACTIVE_ONLY votes (which take effect immediately), as WAKE_ONLY votes - * (applied by RPMh on system wakeup) and as SLEEP votes (applied by RPMh - * on system sleep). - * We send ACTIVE_ONLY votes for resources without any peers. For others, - * which have an active only peer, all 3 votes are sent. - */ -static int rpmhpd_aggregate_corner(struct rpmhpd *pd, unsigned int corner) -{ - int ret; - struct rpmhpd *peer = pd->peer; - unsigned int active_corner, sleep_corner; - unsigned int this_active_corner = 0, this_sleep_corner = 0; - unsigned int peer_active_corner = 0, peer_sleep_corner = 0; - - if (pd->state_synced) { - to_active_sleep(pd, corner, &this_active_corner, &this_sleep_corner); - } else { - /* Clamp to highest corner if sync_state hasn't happened */ - this_active_corner = pd->level_count - 1; - this_sleep_corner = pd->level_count - 1; - } - - if (peer && peer->enabled) - to_active_sleep(peer, peer->corner, &peer_active_corner, - &peer_sleep_corner); - - active_corner = max(this_active_corner, peer_active_corner); - - ret = rpmhpd_send_corner(pd, RPMH_ACTIVE_ONLY_STATE, active_corner, - active_corner > pd->active_corner); - if (ret) - return ret; - - pd->active_corner = active_corner; - - if (peer) { - peer->active_corner = active_corner; - - ret = rpmhpd_send_corner(pd, RPMH_WAKE_ONLY_STATE, - active_corner, false); - if (ret) - return ret; - - sleep_corner = max(this_sleep_corner, peer_sleep_corner); - - return rpmhpd_send_corner(pd, RPMH_SLEEP_STATE, sleep_corner, - false); - } - - return ret; -} - -static int rpmhpd_power_on(struct generic_pm_domain *domain) -{ - struct rpmhpd *pd = domain_to_rpmhpd(domain); - unsigned int corner; - int ret; - - mutex_lock(&rpmhpd_lock); - - corner = max(pd->corner, pd->enable_corner); - ret = rpmhpd_aggregate_corner(pd, corner); - if (!ret) - pd->enabled = true; - - mutex_unlock(&rpmhpd_lock); - - return ret; -} - -static int rpmhpd_power_off(struct generic_pm_domain *domain) -{ - struct rpmhpd *pd = domain_to_rpmhpd(domain); - int ret; - - mutex_lock(&rpmhpd_lock); - - ret = rpmhpd_aggregate_corner(pd, 0); - if (!ret) - pd->enabled = false; - - mutex_unlock(&rpmhpd_lock); - - return ret; -} - -static int rpmhpd_set_performance_state(struct generic_pm_domain *domain, - unsigned int level) -{ - struct rpmhpd *pd = domain_to_rpmhpd(domain); - int ret = 0, i; - - mutex_lock(&rpmhpd_lock); - - for (i = 0; i < pd->level_count; i++) - if (level <= pd->level[i]) - break; - - /* - * If the level requested is more than that supported by the - * max corner, just set it to max anyway. - */ - if (i == pd->level_count) - i--; - - if (pd->enabled) { - /* Ensure that the domain isn't turn off */ - if (i < pd->enable_corner) - i = pd->enable_corner; - - ret = rpmhpd_aggregate_corner(pd, i); - if (ret) - goto out; - } - - pd->corner = i; -out: - mutex_unlock(&rpmhpd_lock); - - return ret; -} - -static unsigned int rpmhpd_get_performance_state(struct generic_pm_domain *genpd, - struct dev_pm_opp *opp) -{ - return dev_pm_opp_get_level(opp); -} - -static int rpmhpd_update_level_mapping(struct rpmhpd *rpmhpd) -{ - int i; - const u16 *buf; - - buf = cmd_db_read_aux_data(rpmhpd->res_name, &rpmhpd->level_count); - if (IS_ERR(buf)) - return PTR_ERR(buf); - - /* 2 bytes used for each command DB aux data entry */ - rpmhpd->level_count >>= 1; - - if (rpmhpd->level_count > RPMH_ARC_MAX_LEVELS) - return -EINVAL; - - for (i = 0; i < rpmhpd->level_count; i++) { - rpmhpd->level[i] = buf[i]; - - /* Remember the first corner with non-zero level */ - if (!rpmhpd->level[rpmhpd->enable_corner] && rpmhpd->level[i]) - rpmhpd->enable_corner = i; - - /* - * The AUX data may be zero padded. These 0 valued entries at - * the end of the map must be ignored. - */ - if (i > 0 && rpmhpd->level[i] == 0) { - rpmhpd->level_count = i; - break; - } - pr_debug("%s: ARC hlvl=%2d --> vlvl=%4u\n", rpmhpd->res_name, i, - rpmhpd->level[i]); - } - - return 0; -} - -static int rpmhpd_probe(struct platform_device *pdev) -{ - int i, ret; - size_t num_pds; - struct device *dev = &pdev->dev; - struct genpd_onecell_data *data; - struct rpmhpd **rpmhpds; - const struct rpmhpd_desc *desc; - - desc = of_device_get_match_data(dev); - if (!desc) - return -EINVAL; - - rpmhpds = desc->rpmhpds; - num_pds = desc->num_pds; - - data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->domains = devm_kcalloc(dev, num_pds, sizeof(*data->domains), - GFP_KERNEL); - if (!data->domains) - return -ENOMEM; - - data->num_domains = num_pds; - - for (i = 0; i < num_pds; i++) { - if (!rpmhpds[i]) - continue; - - rpmhpds[i]->dev = dev; - rpmhpds[i]->addr = cmd_db_read_addr(rpmhpds[i]->res_name); - if (!rpmhpds[i]->addr) { - dev_err(dev, "Could not find RPMh address for resource %s\n", - rpmhpds[i]->res_name); - return -ENODEV; - } - - ret = cmd_db_read_slave_id(rpmhpds[i]->res_name); - if (ret != CMD_DB_HW_ARC) { - dev_err(dev, "RPMh slave ID mismatch\n"); - return -EINVAL; - } - - ret = rpmhpd_update_level_mapping(rpmhpds[i]); - if (ret) - return ret; - - rpmhpds[i]->pd.power_off = rpmhpd_power_off; - rpmhpds[i]->pd.power_on = rpmhpd_power_on; - rpmhpds[i]->pd.set_performance_state = rpmhpd_set_performance_state; - rpmhpds[i]->pd.opp_to_performance_state = rpmhpd_get_performance_state; - pm_genpd_init(&rpmhpds[i]->pd, NULL, true); - - data->domains[i] = &rpmhpds[i]->pd; - } - - /* Add subdomains */ - for (i = 0; i < num_pds; i++) { - if (!rpmhpds[i]) - continue; - if (rpmhpds[i]->parent) - pm_genpd_add_subdomain(rpmhpds[i]->parent, - &rpmhpds[i]->pd); - } - - return of_genpd_add_provider_onecell(pdev->dev.of_node, data); -} - -static void rpmhpd_sync_state(struct device *dev) -{ - const struct rpmhpd_desc *desc = of_device_get_match_data(dev); - struct rpmhpd **rpmhpds = desc->rpmhpds; - unsigned int corner; - struct rpmhpd *pd; - unsigned int i; - int ret; - - mutex_lock(&rpmhpd_lock); - for (i = 0; i < desc->num_pds; i++) { - pd = rpmhpds[i]; - if (!pd) - continue; - - pd->state_synced = true; - if (pd->enabled) - corner = max(pd->corner, pd->enable_corner); - else - corner = 0; - - ret = rpmhpd_aggregate_corner(pd, corner); - if (ret) - dev_err(dev, "failed to sync %s\n", pd->res_name); - } - mutex_unlock(&rpmhpd_lock); -} - -static struct platform_driver rpmhpd_driver = { - .driver = { - .name = "qcom-rpmhpd", - .of_match_table = rpmhpd_match_table, - .suppress_bind_attrs = true, - .sync_state = rpmhpd_sync_state, - }, - .probe = rpmhpd_probe, -}; - -static int __init rpmhpd_init(void) -{ - return platform_driver_register(&rpmhpd_driver); -} -core_initcall(rpmhpd_init); - -MODULE_DESCRIPTION("Qualcomm Technologies, Inc. RPMh Power Domain Driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c deleted file mode 100644 index 99b017fd76b7..000000000000 --- a/drivers/soc/qcom/rpmpd.c +++ /dev/null @@ -1,992 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. */ - -#include <linux/err.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/pm_domain.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/pm_opp.h> -#include <linux/soc/qcom/smd-rpm.h> - -#include <dt-bindings/power/qcom-rpmpd.h> - -#define domain_to_rpmpd(domain) container_of(domain, struct rpmpd, pd) - -/* Resource types: - * RPMPD_X is X encoded as a little-endian, lower-case, ASCII string */ -#define RPMPD_SMPA 0x61706d73 -#define RPMPD_LDOA 0x616f646c -#define RPMPD_SMPB 0x62706d73 -#define RPMPD_LDOB 0x626f646c -#define RPMPD_RWCX 0x78637772 -#define RPMPD_RWMX 0x786d7772 -#define RPMPD_RWLC 0x636c7772 -#define RPMPD_RWLM 0x6d6c7772 -#define RPMPD_RWSC 0x63737772 -#define RPMPD_RWSM 0x6d737772 -#define RPMPD_RWGX 0x78677772 - -/* Operation Keys */ -#define KEY_CORNER 0x6e726f63 /* corn */ -#define KEY_ENABLE 0x6e657773 /* swen */ -#define KEY_FLOOR_CORNER 0x636676 /* vfc */ -#define KEY_FLOOR_LEVEL 0x6c6676 /* vfl */ -#define KEY_LEVEL 0x6c766c76 /* vlvl */ - -#define MAX_CORNER_RPMPD_STATE 6 - -struct rpmpd_req { - __le32 key; - __le32 nbytes; - __le32 value; -}; - -struct rpmpd { - struct generic_pm_domain pd; - struct generic_pm_domain *parent; - struct rpmpd *peer; - const bool active_only; - unsigned int corner; - bool enabled; - const int res_type; - const int res_id; - struct qcom_smd_rpm *rpm; - unsigned int max_state; - __le32 key; -}; - -struct rpmpd_desc { - struct rpmpd **rpmpds; - size_t num_pds; - unsigned int max_state; -}; - -static DEFINE_MUTEX(rpmpd_lock); - -/* CX */ -static struct rpmpd cx_rwcx0_lvl_ao; -static struct rpmpd cx_rwcx0_lvl = { - .pd = { .name = "cx", }, - .peer = &cx_rwcx0_lvl_ao, - .res_type = RPMPD_RWCX, - .res_id = 0, - .key = KEY_LEVEL, -}; - -static struct rpmpd cx_rwcx0_lvl_ao = { - .pd = { .name = "cx_ao", }, - .peer = &cx_rwcx0_lvl, - .active_only = true, - .res_type = RPMPD_RWCX, - .res_id = 0, - .key = KEY_LEVEL, -}; - -static struct rpmpd cx_s1a_corner_ao; -static struct rpmpd cx_s1a_corner = { - .pd = { .name = "cx", }, - .peer = &cx_s1a_corner_ao, - .res_type = RPMPD_SMPA, - .res_id = 1, - .key = KEY_CORNER, -}; - -static struct rpmpd cx_s1a_corner_ao = { - .pd = { .name = "cx_ao", }, - .peer = &cx_s1a_corner, - .active_only = true, - .res_type = RPMPD_SMPA, - .res_id = 1, - .key = KEY_CORNER, -}; - -static struct rpmpd cx_s2a_corner_ao; -static struct rpmpd cx_s2a_corner = { - .pd = { .name = "cx", }, - .peer = &cx_s2a_corner_ao, - .res_type = RPMPD_SMPA, - .res_id = 2, - .key = KEY_CORNER, -}; - -static struct rpmpd cx_s2a_corner_ao = { - .pd = { .name = "cx_ao", }, - .peer = &cx_s2a_corner, - .active_only = true, - .res_type = RPMPD_SMPA, - .res_id = 2, - .key = KEY_CORNER, -}; - -static struct rpmpd cx_s2a_lvl_ao; -static struct rpmpd cx_s2a_lvl = { - .pd = { .name = "cx", }, - .peer = &cx_s2a_lvl_ao, - .res_type = RPMPD_SMPA, - .res_id = 2, - .key = KEY_LEVEL, -}; - -static struct rpmpd cx_s2a_lvl_ao = { - .pd = { .name = "cx_ao", }, - .peer = &cx_s2a_lvl, - .active_only = true, - .res_type = RPMPD_SMPA, - .res_id = 2, - .key = KEY_LEVEL, -}; - -static struct rpmpd cx_s3a_lvl_ao; -static struct rpmpd cx_s3a_lvl = { - .pd = { .name = "cx", }, - .peer = &cx_s3a_lvl_ao, - .res_type = RPMPD_SMPA, - .res_id = 3, - .key = KEY_LEVEL, -}; - -static struct rpmpd cx_s3a_lvl_ao = { - .pd = { .name = "cx_ao", }, - .peer = &cx_s3a_lvl, - .active_only = true, - .res_type = RPMPD_SMPA, - .res_id = 3, - .key = KEY_LEVEL, -}; - -static struct rpmpd cx_rwcx0_vfl = { - .pd = { .name = "cx_vfl", }, - .res_type = RPMPD_RWCX, - .res_id = 0, - .key = KEY_FLOOR_LEVEL, -}; - -static struct rpmpd cx_rwsc2_vfl = { - .pd = { .name = "cx_vfl", }, - .res_type = RPMPD_RWSC, - .res_id = 2, - .key = KEY_FLOOR_LEVEL, -}; - -static struct rpmpd cx_s1a_vfc = { - .pd = { .name = "cx_vfc", }, - .res_type = RPMPD_SMPA, - .res_id = 1, - .key = KEY_FLOOR_CORNER, -}; - -static struct rpmpd cx_s2a_vfc = { - .pd = { .name = "cx_vfc", }, - .res_type = RPMPD_SMPA, - .res_id = 2, - .key = KEY_FLOOR_CORNER, -}; - -static struct rpmpd cx_s2a_vfl = { - .pd = { .name = "cx_vfl", }, - .res_type = RPMPD_SMPA, - .res_id = 2, - .key = KEY_FLOOR_LEVEL, -}; - -static struct rpmpd cx_s3a_vfl = { - .pd = { .name = "cx_vfl", }, - .res_type = RPMPD_SMPA, - .res_id = 3, - .key = KEY_FLOOR_LEVEL, -}; - -/* G(F)X */ -static struct rpmpd gfx_s2b_corner = { - .pd = { .name = "gfx", }, - .res_type = RPMPD_SMPB, - .res_id = 2, - .key = KEY_CORNER, -}; - -static struct rpmpd gfx_s2b_vfc = { - .pd = { .name = "gfx_vfc", }, - .res_type = RPMPD_SMPB, - .res_id = 2, - .key = KEY_FLOOR_CORNER, -}; - -static struct rpmpd mx_rwmx0_lvl; -static struct rpmpd gx_rwgx0_lvl_ao; -static struct rpmpd gx_rwgx0_lvl = { - .pd = { .name = "gx", }, - .peer = &gx_rwgx0_lvl_ao, - .res_type = RPMPD_RWGX, - .parent = &mx_rwmx0_lvl.pd, - .res_id = 0, - .key = KEY_LEVEL, -}; - -static struct rpmpd mx_rwmx0_lvl_ao; -static struct rpmpd gx_rwgx0_lvl_ao = { - .pd = { .name = "gx_ao", }, - .peer = &gx_rwgx0_lvl, - .parent = &mx_rwmx0_lvl_ao.pd, - .active_only = true, - .res_type = RPMPD_RWGX, - .res_id = 0, - .key = KEY_LEVEL, -}; - -/* MX */ -static struct rpmpd mx_l3a_corner_ao; -static struct rpmpd mx_l3a_corner = { - .pd = { .name = "mx", }, - .peer = &mx_l3a_corner_ao, - .res_type = RPMPD_LDOA, - .res_id = 3, - .key = KEY_CORNER, -}; - -static struct rpmpd mx_l3a_corner_ao = { - .pd = { .name = "mx_ao", }, - .peer = &mx_l3a_corner, - .active_only = true, - .res_type = RPMPD_LDOA, - .res_id = 3, - .key = KEY_CORNER, -}; - -static struct rpmpd mx_l12a_lvl_ao; -static struct rpmpd mx_l12a_lvl = { - .pd = { .name = "mx", }, - .peer = &mx_l12a_lvl_ao, - .res_type = RPMPD_LDOA, - .res_id = 12, - .key = KEY_LEVEL, -}; - -static struct rpmpd mx_l12a_lvl_ao = { - .pd = { .name = "mx_ao", }, - .peer = &mx_l12a_lvl, - .active_only = true, - .res_type = RPMPD_LDOA, - .res_id = 12, - .key = KEY_LEVEL, -}; - -static struct rpmpd mx_s2a_corner_ao; -static struct rpmpd mx_s2a_corner = { - .pd = { .name = "mx", }, - .peer = &mx_s2a_corner_ao, - .res_type = RPMPD_SMPA, - .res_id = 2, - .key = KEY_CORNER, -}; - -static struct rpmpd mx_s2a_corner_ao = { - .pd = { .name = "mx_ao", }, - .peer = &mx_s2a_corner, - .active_only = true, - .res_type = RPMPD_SMPA, - .res_id = 2, - .key = KEY_CORNER, -}; - -static struct rpmpd mx_rwmx0_lvl_ao; -static struct rpmpd mx_rwmx0_lvl = { - .pd = { .name = "mx", }, - .peer = &mx_rwmx0_lvl_ao, - .res_type = RPMPD_RWMX, - .res_id = 0, - .key = KEY_LEVEL, -}; - -static struct rpmpd mx_rwmx0_lvl_ao = { - .pd = { .name = "mx_ao", }, - .peer = &mx_rwmx0_lvl, - .active_only = true, - .res_type = RPMPD_RWMX, - .res_id = 0, - .key = KEY_LEVEL, -}; - -static struct rpmpd mx_s6a_lvl_ao; -static struct rpmpd mx_s6a_lvl = { - .pd = { .name = "mx", }, - .peer = &mx_s6a_lvl_ao, - .res_type = RPMPD_SMPA, - .res_id = 6, - .key = KEY_LEVEL, -}; - -static struct rpmpd mx_s6a_lvl_ao = { - .pd = { .name = "mx_ao", }, - .peer = &mx_s6a_lvl, - .active_only = true, - .res_type = RPMPD_SMPA, - .res_id = 6, - .key = KEY_LEVEL, -}; - -static struct rpmpd mx_s7a_lvl_ao; -static struct rpmpd mx_s7a_lvl = { - .pd = { .name = "mx", }, - .peer = &mx_s7a_lvl_ao, - .res_type = RPMPD_SMPA, - .res_id = 7, - .key = KEY_LEVEL, -}; - -static struct rpmpd mx_s7a_lvl_ao = { - .pd = { .name = "mx_ao", }, - .peer = &mx_s7a_lvl, - .active_only = true, - .res_type = RPMPD_SMPA, - .res_id = 7, - .key = KEY_LEVEL, -}; - -static struct rpmpd mx_l12a_vfl = { - .pd = { .name = "mx_vfl", }, - .res_type = RPMPD_LDOA, - .res_id = 12, - .key = KEY_FLOOR_LEVEL, -}; - -static struct rpmpd mx_rwmx0_vfl = { - .pd = { .name = "mx_vfl", }, - .res_type = RPMPD_RWMX, - .res_id = 0, - .key = KEY_FLOOR_LEVEL, -}; - -static struct rpmpd mx_rwsm6_vfl = { - .pd = { .name = "mx_vfl", }, - .res_type = RPMPD_RWSM, - .res_id = 6, - .key = KEY_FLOOR_LEVEL, -}; - -/* MD */ -static struct rpmpd md_s1a_corner_ao; -static struct rpmpd md_s1a_corner = { - .pd = { .name = "md", }, - .peer = &md_s1a_corner_ao, - .res_type = RPMPD_SMPA, - .res_id = 1, - .key = KEY_CORNER, -}; - -static struct rpmpd md_s1a_corner_ao = { - .pd = { .name = "md_ao", }, - .peer = &md_s1a_corner, - .active_only = true, - .res_type = RPMPD_SMPA, - .res_id = 1, - .key = KEY_CORNER, -}; - -static struct rpmpd md_s1a_lvl_ao; -static struct rpmpd md_s1a_lvl = { - .pd = { .name = "md", }, - .peer = &md_s1a_lvl_ao, - .res_type = RPMPD_SMPA, - .res_id = 1, - .key = KEY_LEVEL, -}; - -static struct rpmpd md_s1a_lvl_ao = { - .pd = { .name = "md_ao", }, - .peer = &md_s1a_lvl, - .active_only = true, - .res_type = RPMPD_SMPA, - .res_id = 1, - .key = KEY_LEVEL, -}; - -static struct rpmpd md_s1a_vfc = { - .pd = { .name = "md_vfc", }, - .res_type = RPMPD_SMPA, - .res_id = 1, - .key = KEY_FLOOR_CORNER, -}; - -/* LPI_CX */ -static struct rpmpd lpi_cx_rwlc0_lvl = { - .pd = { .name = "lpi_cx", }, - .res_type = RPMPD_RWLC, - .res_id = 0, - .key = KEY_LEVEL, -}; - -static struct rpmpd lpi_cx_rwlc0_vfl = { - .pd = { .name = "lpi_cx_vfl", }, - .res_type = RPMPD_RWLC, - .res_id = 0, - .key = KEY_FLOOR_LEVEL, -}; - -/* LPI_MX */ -static struct rpmpd lpi_mx_rwlm0_lvl = { - .pd = { .name = "lpi_mx", }, - .res_type = RPMPD_RWLM, - .res_id = 0, - .key = KEY_LEVEL, -}; - -static struct rpmpd lpi_mx_rwlm0_vfl = { - .pd = { .name = "lpi_mx_vfl", }, - .res_type = RPMPD_RWLM, - .res_id = 0, - .key = KEY_FLOOR_LEVEL, -}; - -/* SSC_CX */ -static struct rpmpd ssc_cx_l26a_corner = { - .pd = { .name = "ssc_cx", }, - .res_type = RPMPD_LDOA, - .res_id = 26, - .key = KEY_CORNER, -}; - -static struct rpmpd ssc_cx_rwlc0_lvl = { - .pd = { .name = "ssc_cx", }, - .res_type = RPMPD_RWLC, - .res_id = 0, - .key = KEY_LEVEL, -}; - -static struct rpmpd ssc_cx_rwsc0_lvl = { - .pd = { .name = "ssc_cx", }, - .res_type = RPMPD_RWSC, - .res_id = 0, - .key = KEY_LEVEL, -}; - -static struct rpmpd ssc_cx_l26a_vfc = { - .pd = { .name = "ssc_cx_vfc", }, - .res_type = RPMPD_LDOA, - .res_id = 26, - .key = KEY_FLOOR_CORNER, -}; - -static struct rpmpd ssc_cx_rwlc0_vfl = { - .pd = { .name = "ssc_cx_vfl", }, - .res_type = RPMPD_RWLC, - .res_id = 0, - .key = KEY_FLOOR_LEVEL, -}; - -static struct rpmpd ssc_cx_rwsc0_vfl = { - .pd = { .name = "ssc_cx_vfl", }, - .res_type = RPMPD_RWSC, - .res_id = 0, - .key = KEY_FLOOR_LEVEL, -}; - -/* SSC_MX */ -static struct rpmpd ssc_mx_rwlm0_lvl = { - .pd = { .name = "ssc_mx", }, - .res_type = RPMPD_RWLM, - .res_id = 0, - .key = KEY_LEVEL, -}; - -static struct rpmpd ssc_mx_rwsm0_lvl = { - .pd = { .name = "ssc_mx", }, - .res_type = RPMPD_RWSM, - .res_id = 0, - .key = KEY_LEVEL, -}; - -static struct rpmpd ssc_mx_rwlm0_vfl = { - .pd = { .name = "ssc_mx_vfl", }, - .res_type = RPMPD_RWLM, - .res_id = 0, - .key = KEY_FLOOR_LEVEL, -}; - -static struct rpmpd ssc_mx_rwsm0_vfl = { - .pd = { .name = "ssc_mx_vfl", }, - .res_type = RPMPD_RWSM, - .res_id = 0, - .key = KEY_FLOOR_LEVEL, -}; - -static struct rpmpd *mdm9607_rpmpds[] = { - [MDM9607_VDDCX] = &cx_s3a_lvl, - [MDM9607_VDDCX_AO] = &cx_s3a_lvl_ao, - [MDM9607_VDDCX_VFL] = &cx_s3a_vfl, - [MDM9607_VDDMX] = &mx_l12a_lvl, - [MDM9607_VDDMX_AO] = &mx_l12a_lvl_ao, - [MDM9607_VDDMX_VFL] = &mx_l12a_vfl, -}; - -static const struct rpmpd_desc mdm9607_desc = { - .rpmpds = mdm9607_rpmpds, - .num_pds = ARRAY_SIZE(mdm9607_rpmpds), - .max_state = RPM_SMD_LEVEL_TURBO, -}; - -static struct rpmpd *msm8226_rpmpds[] = { - [MSM8226_VDDCX] = &cx_s1a_corner, - [MSM8226_VDDCX_AO] = &cx_s1a_corner_ao, - [MSM8226_VDDCX_VFC] = &cx_s1a_vfc, -}; - -static const struct rpmpd_desc msm8226_desc = { - .rpmpds = msm8226_rpmpds, - .num_pds = ARRAY_SIZE(msm8226_rpmpds), - .max_state = MAX_CORNER_RPMPD_STATE, -}; - -static struct rpmpd *msm8939_rpmpds[] = { - [MSM8939_VDDMDCX] = &md_s1a_corner, - [MSM8939_VDDMDCX_AO] = &md_s1a_corner_ao, - [MSM8939_VDDMDCX_VFC] = &md_s1a_vfc, - [MSM8939_VDDCX] = &cx_s2a_corner, - [MSM8939_VDDCX_AO] = &cx_s2a_corner_ao, - [MSM8939_VDDCX_VFC] = &cx_s2a_vfc, - [MSM8939_VDDMX] = &mx_l3a_corner, - [MSM8939_VDDMX_AO] = &mx_l3a_corner_ao, -}; - -static const struct rpmpd_desc msm8939_desc = { - .rpmpds = msm8939_rpmpds, - .num_pds = ARRAY_SIZE(msm8939_rpmpds), - .max_state = MAX_CORNER_RPMPD_STATE, -}; - -static struct rpmpd *msm8916_rpmpds[] = { - [MSM8916_VDDCX] = &cx_s1a_corner, - [MSM8916_VDDCX_AO] = &cx_s1a_corner_ao, - [MSM8916_VDDCX_VFC] = &cx_s1a_vfc, - [MSM8916_VDDMX] = &mx_l3a_corner, - [MSM8916_VDDMX_AO] = &mx_l3a_corner_ao, -}; - -static const struct rpmpd_desc msm8916_desc = { - .rpmpds = msm8916_rpmpds, - .num_pds = ARRAY_SIZE(msm8916_rpmpds), - .max_state = MAX_CORNER_RPMPD_STATE, -}; - -static struct rpmpd *msm8953_rpmpds[] = { - [MSM8953_VDDMD] = &md_s1a_lvl, - [MSM8953_VDDMD_AO] = &md_s1a_lvl_ao, - [MSM8953_VDDCX] = &cx_s2a_lvl, - [MSM8953_VDDCX_AO] = &cx_s2a_lvl_ao, - [MSM8953_VDDCX_VFL] = &cx_s2a_vfl, - [MSM8953_VDDMX] = &mx_s7a_lvl, - [MSM8953_VDDMX_AO] = &mx_s7a_lvl_ao, -}; - -static const struct rpmpd_desc msm8953_desc = { - .rpmpds = msm8953_rpmpds, - .num_pds = ARRAY_SIZE(msm8953_rpmpds), - .max_state = RPM_SMD_LEVEL_TURBO, -}; - -static struct rpmpd *msm8976_rpmpds[] = { - [MSM8976_VDDCX] = &cx_s2a_lvl, - [MSM8976_VDDCX_AO] = &cx_s2a_lvl_ao, - [MSM8976_VDDCX_VFL] = &cx_rwsc2_vfl, - [MSM8976_VDDMX] = &mx_s6a_lvl, - [MSM8976_VDDMX_AO] = &mx_s6a_lvl_ao, - [MSM8976_VDDMX_VFL] = &mx_rwsm6_vfl, -}; - -static const struct rpmpd_desc msm8976_desc = { - .rpmpds = msm8976_rpmpds, - .num_pds = ARRAY_SIZE(msm8976_rpmpds), - .max_state = RPM_SMD_LEVEL_TURBO_HIGH, -}; - -static struct rpmpd *msm8994_rpmpds[] = { - [MSM8994_VDDCX] = &cx_s1a_corner, - [MSM8994_VDDCX_AO] = &cx_s1a_corner_ao, - [MSM8994_VDDCX_VFC] = &cx_s1a_vfc, - [MSM8994_VDDMX] = &mx_s2a_corner, - [MSM8994_VDDMX_AO] = &mx_s2a_corner_ao, - - /* Attention! *Some* 8994 boards with pm8004 may use SMPC here! */ - [MSM8994_VDDGFX] = &gfx_s2b_corner, - [MSM8994_VDDGFX_VFC] = &gfx_s2b_vfc, -}; - -static const struct rpmpd_desc msm8994_desc = { - .rpmpds = msm8994_rpmpds, - .num_pds = ARRAY_SIZE(msm8994_rpmpds), - .max_state = MAX_CORNER_RPMPD_STATE, -}; - -static struct rpmpd *msm8996_rpmpds[] = { - [MSM8996_VDDCX] = &cx_s1a_corner, - [MSM8996_VDDCX_AO] = &cx_s1a_corner_ao, - [MSM8996_VDDCX_VFC] = &cx_s1a_vfc, - [MSM8996_VDDMX] = &mx_s2a_corner, - [MSM8996_VDDMX_AO] = &mx_s2a_corner_ao, - [MSM8996_VDDSSCX] = &ssc_cx_l26a_corner, - [MSM8996_VDDSSCX_VFC] = &ssc_cx_l26a_vfc, -}; - -static const struct rpmpd_desc msm8996_desc = { - .rpmpds = msm8996_rpmpds, - .num_pds = ARRAY_SIZE(msm8996_rpmpds), - .max_state = MAX_CORNER_RPMPD_STATE, -}; - -static struct rpmpd *msm8998_rpmpds[] = { - [MSM8998_VDDCX] = &cx_rwcx0_lvl, - [MSM8998_VDDCX_AO] = &cx_rwcx0_lvl_ao, - [MSM8998_VDDCX_VFL] = &cx_rwcx0_vfl, - [MSM8998_VDDMX] = &mx_rwmx0_lvl, - [MSM8998_VDDMX_AO] = &mx_rwmx0_lvl_ao, - [MSM8998_VDDMX_VFL] = &mx_rwmx0_vfl, - [MSM8998_SSCCX] = &ssc_cx_rwsc0_lvl, - [MSM8998_SSCCX_VFL] = &ssc_cx_rwsc0_vfl, - [MSM8998_SSCMX] = &ssc_mx_rwsm0_lvl, - [MSM8998_SSCMX_VFL] = &ssc_mx_rwsm0_vfl, -}; - -static const struct rpmpd_desc msm8998_desc = { - .rpmpds = msm8998_rpmpds, - .num_pds = ARRAY_SIZE(msm8998_rpmpds), - .max_state = RPM_SMD_LEVEL_BINNING, -}; - -static struct rpmpd *qcs404_rpmpds[] = { - [QCS404_VDDMX] = &mx_rwmx0_lvl, - [QCS404_VDDMX_AO] = &mx_rwmx0_lvl_ao, - [QCS404_VDDMX_VFL] = &mx_rwmx0_vfl, - [QCS404_LPICX] = &lpi_cx_rwlc0_lvl, - [QCS404_LPICX_VFL] = &lpi_cx_rwlc0_vfl, - [QCS404_LPIMX] = &lpi_mx_rwlm0_lvl, - [QCS404_LPIMX_VFL] = &lpi_mx_rwlm0_vfl, -}; - -static const struct rpmpd_desc qcs404_desc = { - .rpmpds = qcs404_rpmpds, - .num_pds = ARRAY_SIZE(qcs404_rpmpds), - .max_state = RPM_SMD_LEVEL_BINNING, -}; - -static struct rpmpd *sdm660_rpmpds[] = { - [SDM660_VDDCX] = &cx_rwcx0_lvl, - [SDM660_VDDCX_AO] = &cx_rwcx0_lvl_ao, - [SDM660_VDDCX_VFL] = &cx_rwcx0_vfl, - [SDM660_VDDMX] = &mx_rwmx0_lvl, - [SDM660_VDDMX_AO] = &mx_rwmx0_lvl_ao, - [SDM660_VDDMX_VFL] = &mx_rwmx0_vfl, - [SDM660_SSCCX] = &ssc_cx_rwlc0_lvl, - [SDM660_SSCCX_VFL] = &ssc_cx_rwlc0_vfl, - [SDM660_SSCMX] = &ssc_mx_rwlm0_lvl, - [SDM660_SSCMX_VFL] = &ssc_mx_rwlm0_vfl, -}; - -static const struct rpmpd_desc sdm660_desc = { - .rpmpds = sdm660_rpmpds, - .num_pds = ARRAY_SIZE(sdm660_rpmpds), - .max_state = RPM_SMD_LEVEL_TURBO, -}; - -static struct rpmpd *sm6115_rpmpds[] = { - [SM6115_VDDCX] = &cx_rwcx0_lvl, - [SM6115_VDDCX_AO] = &cx_rwcx0_lvl_ao, - [SM6115_VDDCX_VFL] = &cx_rwcx0_vfl, - [SM6115_VDDMX] = &mx_rwmx0_lvl, - [SM6115_VDDMX_AO] = &mx_rwmx0_lvl_ao, - [SM6115_VDDMX_VFL] = &mx_rwmx0_vfl, - [SM6115_VDD_LPI_CX] = &lpi_cx_rwlc0_lvl, - [SM6115_VDD_LPI_MX] = &lpi_mx_rwlm0_lvl, -}; - -static const struct rpmpd_desc sm6115_desc = { - .rpmpds = sm6115_rpmpds, - .num_pds = ARRAY_SIZE(sm6115_rpmpds), - .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR, -}; - -static struct rpmpd *sm6125_rpmpds[] = { - [SM6125_VDDCX] = &cx_rwcx0_lvl, - [SM6125_VDDCX_AO] = &cx_rwcx0_lvl_ao, - [SM6125_VDDCX_VFL] = &cx_rwcx0_vfl, - [SM6125_VDDMX] = &mx_rwmx0_lvl, - [SM6125_VDDMX_AO] = &mx_rwmx0_lvl_ao, - [SM6125_VDDMX_VFL] = &mx_rwmx0_vfl, -}; - -static const struct rpmpd_desc sm6125_desc = { - .rpmpds = sm6125_rpmpds, - .num_pds = ARRAY_SIZE(sm6125_rpmpds), - .max_state = RPM_SMD_LEVEL_BINNING, -}; - -static struct rpmpd *sm6375_rpmpds[] = { - [SM6375_VDDCX] = &cx_rwcx0_lvl, - [SM6375_VDDCX_AO] = &cx_rwcx0_lvl_ao, - [SM6375_VDDCX_VFL] = &cx_rwcx0_vfl, - [SM6375_VDDMX] = &mx_rwmx0_lvl, - [SM6375_VDDMX_AO] = &mx_rwmx0_lvl_ao, - [SM6375_VDDMX_VFL] = &mx_rwmx0_vfl, - [SM6375_VDDGX] = &gx_rwgx0_lvl, - [SM6375_VDDGX_AO] = &gx_rwgx0_lvl_ao, - [SM6375_VDD_LPI_CX] = &lpi_cx_rwlc0_lvl, - [SM6375_VDD_LPI_MX] = &lpi_mx_rwlm0_lvl, -}; - -static const struct rpmpd_desc sm6375_desc = { - .rpmpds = sm6375_rpmpds, - .num_pds = ARRAY_SIZE(sm6375_rpmpds), - .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR, -}; - -static struct rpmpd *qcm2290_rpmpds[] = { - [QCM2290_VDDCX] = &cx_rwcx0_lvl, - [QCM2290_VDDCX_AO] = &cx_rwcx0_lvl_ao, - [QCM2290_VDDCX_VFL] = &cx_rwcx0_vfl, - [QCM2290_VDDMX] = &mx_rwmx0_lvl, - [QCM2290_VDDMX_AO] = &mx_rwmx0_lvl_ao, - [QCM2290_VDDMX_VFL] = &mx_rwmx0_vfl, - [QCM2290_VDD_LPI_CX] = &lpi_cx_rwlc0_lvl, - [QCM2290_VDD_LPI_MX] = &lpi_mx_rwlm0_lvl, -}; - -static const struct rpmpd_desc qcm2290_desc = { - .rpmpds = qcm2290_rpmpds, - .num_pds = ARRAY_SIZE(qcm2290_rpmpds), - .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR, -}; - -static const struct of_device_id rpmpd_match_table[] = { - { .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc }, - { .compatible = "qcom,msm8226-rpmpd", .data = &msm8226_desc }, - { .compatible = "qcom,msm8909-rpmpd", .data = &msm8916_desc }, - { .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc }, - { .compatible = "qcom,msm8939-rpmpd", .data = &msm8939_desc }, - { .compatible = "qcom,msm8953-rpmpd", .data = &msm8953_desc }, - { .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc }, - { .compatible = "qcom,msm8994-rpmpd", .data = &msm8994_desc }, - { .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc }, - { .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc }, - { .compatible = "qcom,qcm2290-rpmpd", .data = &qcm2290_desc }, - { .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc }, - { .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc }, - { .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc }, - { .compatible = "qcom,sm6125-rpmpd", .data = &sm6125_desc }, - { .compatible = "qcom,sm6375-rpmpd", .data = &sm6375_desc }, - { } -}; -MODULE_DEVICE_TABLE(of, rpmpd_match_table); - -static int rpmpd_send_enable(struct rpmpd *pd, bool enable) -{ - struct rpmpd_req req = { - .key = KEY_ENABLE, - .nbytes = cpu_to_le32(sizeof(u32)), - .value = cpu_to_le32(enable), - }; - - return qcom_rpm_smd_write(pd->rpm, QCOM_SMD_RPM_ACTIVE_STATE, - pd->res_type, pd->res_id, &req, sizeof(req)); -} - -static int rpmpd_send_corner(struct rpmpd *pd, int state, unsigned int corner) -{ - struct rpmpd_req req = { - .key = pd->key, - .nbytes = cpu_to_le32(sizeof(u32)), - .value = cpu_to_le32(corner), - }; - - return qcom_rpm_smd_write(pd->rpm, state, pd->res_type, pd->res_id, - &req, sizeof(req)); -}; - -static void to_active_sleep(struct rpmpd *pd, unsigned int corner, - unsigned int *active, unsigned int *sleep) -{ - *active = corner; - - if (pd->active_only) - *sleep = 0; - else - *sleep = *active; -} - -static int rpmpd_aggregate_corner(struct rpmpd *pd) -{ - int ret; - struct rpmpd *peer = pd->peer; - unsigned int active_corner, sleep_corner; - unsigned int this_active_corner = 0, this_sleep_corner = 0; - unsigned int peer_active_corner = 0, peer_sleep_corner = 0; - - to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner); - - if (peer && peer->enabled) - to_active_sleep(peer, peer->corner, &peer_active_corner, - &peer_sleep_corner); - - active_corner = max(this_active_corner, peer_active_corner); - - ret = rpmpd_send_corner(pd, QCOM_SMD_RPM_ACTIVE_STATE, active_corner); - if (ret) - return ret; - - sleep_corner = max(this_sleep_corner, peer_sleep_corner); - - return rpmpd_send_corner(pd, QCOM_SMD_RPM_SLEEP_STATE, sleep_corner); -} - -static int rpmpd_power_on(struct generic_pm_domain *domain) -{ - int ret; - struct rpmpd *pd = domain_to_rpmpd(domain); - - mutex_lock(&rpmpd_lock); - - ret = rpmpd_send_enable(pd, true); - if (ret) - goto out; - - pd->enabled = true; - - if (pd->corner) - ret = rpmpd_aggregate_corner(pd); - -out: - mutex_unlock(&rpmpd_lock); - - return ret; -} - -static int rpmpd_power_off(struct generic_pm_domain *domain) -{ - int ret; - struct rpmpd *pd = domain_to_rpmpd(domain); - - mutex_lock(&rpmpd_lock); - - ret = rpmpd_send_enable(pd, false); - if (!ret) - pd->enabled = false; - - mutex_unlock(&rpmpd_lock); - - return ret; -} - -static int rpmpd_set_performance(struct generic_pm_domain *domain, - unsigned int state) -{ - int ret = 0; - struct rpmpd *pd = domain_to_rpmpd(domain); - - if (state > pd->max_state) - state = pd->max_state; - - mutex_lock(&rpmpd_lock); - - pd->corner = state; - - /* Always send updates for vfc and vfl */ - if (!pd->enabled && pd->key != cpu_to_le32(KEY_FLOOR_CORNER) && - pd->key != cpu_to_le32(KEY_FLOOR_LEVEL)) - goto out; - - ret = rpmpd_aggregate_corner(pd); - -out: - mutex_unlock(&rpmpd_lock); - - return ret; -} - -static unsigned int rpmpd_get_performance(struct generic_pm_domain *genpd, - struct dev_pm_opp *opp) -{ - return dev_pm_opp_get_level(opp); -} - -static int rpmpd_probe(struct platform_device *pdev) -{ - int i; - size_t num; - struct genpd_onecell_data *data; - struct qcom_smd_rpm *rpm; - struct rpmpd **rpmpds; - const struct rpmpd_desc *desc; - - rpm = dev_get_drvdata(pdev->dev.parent); - if (!rpm) { - dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n"); - return -ENODEV; - } - - desc = of_device_get_match_data(&pdev->dev); - if (!desc) - return -EINVAL; - - rpmpds = desc->rpmpds; - num = desc->num_pds; - - data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->domains = devm_kcalloc(&pdev->dev, num, sizeof(*data->domains), - GFP_KERNEL); - if (!data->domains) - return -ENOMEM; - - data->num_domains = num; - - for (i = 0; i < num; i++) { - if (!rpmpds[i]) { - dev_warn(&pdev->dev, "rpmpds[] with empty entry at index=%d\n", - i); - continue; - } - - rpmpds[i]->rpm = rpm; - rpmpds[i]->max_state = desc->max_state; - rpmpds[i]->pd.power_off = rpmpd_power_off; - rpmpds[i]->pd.power_on = rpmpd_power_on; - rpmpds[i]->pd.set_performance_state = rpmpd_set_performance; - rpmpds[i]->pd.opp_to_performance_state = rpmpd_get_performance; - pm_genpd_init(&rpmpds[i]->pd, NULL, true); - - data->domains[i] = &rpmpds[i]->pd; - } - - /* Add subdomains */ - for (i = 0; i < num; i++) { - if (!rpmpds[i]) - continue; - - if (rpmpds[i]->parent) - pm_genpd_add_subdomain(rpmpds[i]->parent, &rpmpds[i]->pd); - } - - return of_genpd_add_provider_onecell(pdev->dev.of_node, data); -} - -static struct platform_driver rpmpd_driver = { - .driver = { - .name = "qcom-rpmpd", - .of_match_table = rpmpd_match_table, - .suppress_bind_attrs = true, - }, - .probe = rpmpd_probe, -}; - -static int __init rpmpd_init(void) -{ - return platform_driver_register(&rpmpd_driver); -} -core_initcall(rpmpd_init); - -MODULE_DESCRIPTION("Qualcomm Technologies, Inc. RPM Power Domain Driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index 6e4e77b0afff..734f8f8cefa4 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile @@ -3,30 +3,6 @@ obj-$(CONFIG_SOC_RENESAS) += renesas-soc.o # SoC -obj-$(CONFIG_SYSC_R8A7742) += r8a7742-sysc.o -obj-$(CONFIG_SYSC_R8A7743) += r8a7743-sysc.o -obj-$(CONFIG_SYSC_R8A7745) += r8a7745-sysc.o -obj-$(CONFIG_SYSC_R8A77470) += r8a77470-sysc.o -obj-$(CONFIG_SYSC_R8A774A1) += r8a774a1-sysc.o -obj-$(CONFIG_SYSC_R8A774B1) += r8a774b1-sysc.o -obj-$(CONFIG_SYSC_R8A774C0) += r8a774c0-sysc.o -obj-$(CONFIG_SYSC_R8A774E1) += r8a774e1-sysc.o -obj-$(CONFIG_SYSC_R8A7779) += r8a7779-sysc.o -obj-$(CONFIG_SYSC_R8A7790) += r8a7790-sysc.o -obj-$(CONFIG_SYSC_R8A7791) += r8a7791-sysc.o -obj-$(CONFIG_SYSC_R8A7792) += r8a7792-sysc.o -obj-$(CONFIG_SYSC_R8A7794) += r8a7794-sysc.o -obj-$(CONFIG_SYSC_R8A7795) += r8a7795-sysc.o -obj-$(CONFIG_SYSC_R8A77960) += r8a7796-sysc.o -obj-$(CONFIG_SYSC_R8A77961) += r8a7796-sysc.o -obj-$(CONFIG_SYSC_R8A77965) += r8a77965-sysc.o -obj-$(CONFIG_SYSC_R8A77970) += r8a77970-sysc.o -obj-$(CONFIG_SYSC_R8A77980) += r8a77980-sysc.o -obj-$(CONFIG_SYSC_R8A77990) += r8a77990-sysc.o -obj-$(CONFIG_SYSC_R8A77995) += r8a77995-sysc.o -obj-$(CONFIG_SYSC_R8A779A0) += r8a779a0-sysc.o -obj-$(CONFIG_SYSC_R8A779F0) += r8a779f0-sysc.o -obj-$(CONFIG_SYSC_R8A779G0) += r8a779g0-sysc.o ifdef CONFIG_SMP obj-$(CONFIG_ARCH_R9A06G032) += r9a06g032-smp.o endif @@ -34,6 +10,3 @@ endif # Family obj-$(CONFIG_PWC_RZV2M) += pwc-rzv2m.o obj-$(CONFIG_RST_RCAR) += rcar-rst.o -obj-$(CONFIG_SYSC_RCAR) += rcar-sysc.o -obj-$(CONFIG_SYSC_RCAR_GEN4) += rcar-gen4-sysc.o -obj-$(CONFIG_SYSC_RMOBILE) += rmobile-sysc.o diff --git a/drivers/soc/renesas/r8a7742-sysc.c b/drivers/soc/renesas/r8a7742-sysc.c deleted file mode 100644 index 219a675f83f4..000000000000 --- a/drivers/soc/renesas/r8a7742-sysc.c +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas RZ/G1H System Controller - * - * Copyright (C) 2020 Renesas Electronics Corp. - */ - -#include <linux/kernel.h> - -#include <dt-bindings/power/r8a7742-sysc.h> - -#include "rcar-sysc.h" - -static const struct rcar_sysc_area r8a7742_areas[] __initconst = { - { "always-on", 0, 0, R8A7742_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca15-scu", 0x180, 0, R8A7742_PD_CA15_SCU, R8A7742_PD_ALWAYS_ON, - PD_SCU }, - { "ca15-cpu0", 0x40, 0, R8A7742_PD_CA15_CPU0, R8A7742_PD_CA15_SCU, - PD_CPU_NOCR }, - { "ca15-cpu1", 0x40, 1, R8A7742_PD_CA15_CPU1, R8A7742_PD_CA15_SCU, - PD_CPU_NOCR }, - { "ca15-cpu2", 0x40, 2, R8A7742_PD_CA15_CPU2, R8A7742_PD_CA15_SCU, - PD_CPU_NOCR }, - { "ca15-cpu3", 0x40, 3, R8A7742_PD_CA15_CPU3, R8A7742_PD_CA15_SCU, - PD_CPU_NOCR }, - { "ca7-scu", 0x100, 0, R8A7742_PD_CA7_SCU, R8A7742_PD_ALWAYS_ON, - PD_SCU }, - { "ca7-cpu0", 0x1c0, 0, R8A7742_PD_CA7_CPU0, R8A7742_PD_CA7_SCU, - PD_CPU_NOCR }, - { "ca7-cpu1", 0x1c0, 1, R8A7742_PD_CA7_CPU1, R8A7742_PD_CA7_SCU, - PD_CPU_NOCR }, - { "ca7-cpu2", 0x1c0, 2, R8A7742_PD_CA7_CPU2, R8A7742_PD_CA7_SCU, - PD_CPU_NOCR }, - { "ca7-cpu3", 0x1c0, 3, R8A7742_PD_CA7_CPU3, R8A7742_PD_CA7_SCU, - PD_CPU_NOCR }, - { "rgx", 0xc0, 0, R8A7742_PD_RGX, R8A7742_PD_ALWAYS_ON }, -}; - -const struct rcar_sysc_info r8a7742_sysc_info __initconst = { - .areas = r8a7742_areas, - .num_areas = ARRAY_SIZE(r8a7742_areas), -}; diff --git a/drivers/soc/renesas/r8a7743-sysc.c b/drivers/soc/renesas/r8a7743-sysc.c deleted file mode 100644 index 4e2c0ab951b3..000000000000 --- a/drivers/soc/renesas/r8a7743-sysc.c +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas RZ/G1M System Controller - * - * Copyright (C) 2016 Cogent Embedded Inc. - */ - -#include <linux/kernel.h> - -#include <dt-bindings/power/r8a7743-sysc.h> - -#include "rcar-sysc.h" - -static const struct rcar_sysc_area r8a7743_areas[] __initconst = { - { "always-on", 0, 0, R8A7743_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca15-scu", 0x180, 0, R8A7743_PD_CA15_SCU, R8A7743_PD_ALWAYS_ON, - PD_SCU }, - { "ca15-cpu0", 0x40, 0, R8A7743_PD_CA15_CPU0, R8A7743_PD_CA15_SCU, - PD_CPU_NOCR }, - { "ca15-cpu1", 0x40, 1, R8A7743_PD_CA15_CPU1, R8A7743_PD_CA15_SCU, - PD_CPU_NOCR }, - { "sgx", 0xc0, 0, R8A7743_PD_SGX, R8A7743_PD_ALWAYS_ON }, -}; - -const struct rcar_sysc_info r8a7743_sysc_info __initconst = { - .areas = r8a7743_areas, - .num_areas = ARRAY_SIZE(r8a7743_areas), -}; diff --git a/drivers/soc/renesas/r8a7745-sysc.c b/drivers/soc/renesas/r8a7745-sysc.c deleted file mode 100644 index 865821a2f0c6..000000000000 --- a/drivers/soc/renesas/r8a7745-sysc.c +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas RZ/G1E System Controller - * - * Copyright (C) 2016 Cogent Embedded Inc. - */ - -#include <linux/kernel.h> - -#include <dt-bindings/power/r8a7745-sysc.h> - -#include "rcar-sysc.h" - -static const struct rcar_sysc_area r8a7745_areas[] __initconst = { - { "always-on", 0, 0, R8A7745_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca7-scu", 0x100, 0, R8A7745_PD_CA7_SCU, R8A7745_PD_ALWAYS_ON, - PD_SCU }, - { "ca7-cpu0", 0x1c0, 0, R8A7745_PD_CA7_CPU0, R8A7745_PD_CA7_SCU, - PD_CPU_NOCR }, - { "ca7-cpu1", 0x1c0, 1, R8A7745_PD_CA7_CPU1, R8A7745_PD_CA7_SCU, - PD_CPU_NOCR }, - { "sgx", 0xc0, 0, R8A7745_PD_SGX, R8A7745_PD_ALWAYS_ON }, -}; - -const struct rcar_sysc_info r8a7745_sysc_info __initconst = { - .areas = r8a7745_areas, - .num_areas = ARRAY_SIZE(r8a7745_areas), -}; diff --git a/drivers/soc/renesas/r8a77470-sysc.c b/drivers/soc/renesas/r8a77470-sysc.c deleted file mode 100644 index 1eeb8018df50..000000000000 --- a/drivers/soc/renesas/r8a77470-sysc.c +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas RZ/G1C System Controller - * - * Copyright (C) 2018 Renesas Electronics Corp. - */ - -#include <linux/kernel.h> - -#include <dt-bindings/power/r8a77470-sysc.h> - -#include "rcar-sysc.h" - -static const struct rcar_sysc_area r8a77470_areas[] __initconst = { - { "always-on", 0, 0, R8A77470_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca7-scu", 0x100, 0, R8A77470_PD_CA7_SCU, R8A77470_PD_ALWAYS_ON, - PD_SCU }, - { "ca7-cpu0", 0x1c0, 0, R8A77470_PD_CA7_CPU0, R8A77470_PD_CA7_SCU, - PD_CPU_NOCR }, - { "ca7-cpu1", 0x1c0, 1, R8A77470_PD_CA7_CPU1, R8A77470_PD_CA7_SCU, - PD_CPU_NOCR }, - { "sgx", 0xc0, 0, R8A77470_PD_SGX, R8A77470_PD_ALWAYS_ON }, -}; - -const struct rcar_sysc_info r8a77470_sysc_info __initconst = { - .areas = r8a77470_areas, - .num_areas = ARRAY_SIZE(r8a77470_areas), -}; diff --git a/drivers/soc/renesas/r8a774a1-sysc.c b/drivers/soc/renesas/r8a774a1-sysc.c deleted file mode 100644 index 38ac2c689ff0..000000000000 --- a/drivers/soc/renesas/r8a774a1-sysc.c +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas RZ/G2M System Controller - * Copyright (C) 2018 Renesas Electronics Corp. - * - * Based on Renesas R-Car M3-W System Controller - * Copyright (C) 2016 Glider bvba - */ - -#include <linux/kernel.h> - -#include <dt-bindings/power/r8a774a1-sysc.h> - -#include "rcar-sysc.h" - -static const struct rcar_sysc_area r8a774a1_areas[] __initconst = { - { "always-on", 0, 0, R8A774A1_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca57-scu", 0x1c0, 0, R8A774A1_PD_CA57_SCU, R8A774A1_PD_ALWAYS_ON, - PD_SCU }, - { "ca57-cpu0", 0x80, 0, R8A774A1_PD_CA57_CPU0, R8A774A1_PD_CA57_SCU, - PD_CPU_NOCR }, - { "ca57-cpu1", 0x80, 1, R8A774A1_PD_CA57_CPU1, R8A774A1_PD_CA57_SCU, - PD_CPU_NOCR }, - { "ca53-scu", 0x140, 0, R8A774A1_PD_CA53_SCU, R8A774A1_PD_ALWAYS_ON, - PD_SCU }, - { "ca53-cpu0", 0x200, 0, R8A774A1_PD_CA53_CPU0, R8A774A1_PD_CA53_SCU, - PD_CPU_NOCR }, - { "ca53-cpu1", 0x200, 1, R8A774A1_PD_CA53_CPU1, R8A774A1_PD_CA53_SCU, - PD_CPU_NOCR }, - { "ca53-cpu2", 0x200, 2, R8A774A1_PD_CA53_CPU2, R8A774A1_PD_CA53_SCU, - PD_CPU_NOCR }, - { "ca53-cpu3", 0x200, 3, R8A774A1_PD_CA53_CPU3, R8A774A1_PD_CA53_SCU, - PD_CPU_NOCR }, - { "a3vc", 0x380, 0, R8A774A1_PD_A3VC, R8A774A1_PD_ALWAYS_ON }, - { "a2vc0", 0x3c0, 0, R8A774A1_PD_A2VC0, R8A774A1_PD_A3VC }, - { "a2vc1", 0x3c0, 1, R8A774A1_PD_A2VC1, R8A774A1_PD_A3VC }, - { "3dg-a", 0x100, 0, R8A774A1_PD_3DG_A, R8A774A1_PD_ALWAYS_ON }, - { "3dg-b", 0x100, 1, R8A774A1_PD_3DG_B, R8A774A1_PD_3DG_A }, -}; - -const struct rcar_sysc_info r8a774a1_sysc_info __initconst = { - .areas = r8a774a1_areas, - .num_areas = ARRAY_SIZE(r8a774a1_areas), -}; diff --git a/drivers/soc/renesas/r8a774b1-sysc.c b/drivers/soc/renesas/r8a774b1-sysc.c deleted file mode 100644 index 5f97ff26f3f8..000000000000 --- a/drivers/soc/renesas/r8a774b1-sysc.c +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas RZ/G2N System Controller - * Copyright (C) 2019 Renesas Electronics Corp. - * - * Based on Renesas R-Car M3-W System Controller - * Copyright (C) 2016 Glider bvba - */ - -#include <linux/bits.h> -#include <linux/kernel.h> - -#include <dt-bindings/power/r8a774b1-sysc.h> - -#include "rcar-sysc.h" - -static const struct rcar_sysc_area r8a774b1_areas[] __initconst = { - { "always-on", 0, 0, R8A774B1_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca57-scu", 0x1c0, 0, R8A774B1_PD_CA57_SCU, R8A774B1_PD_ALWAYS_ON, - PD_SCU }, - { "ca57-cpu0", 0x80, 0, R8A774B1_PD_CA57_CPU0, R8A774B1_PD_CA57_SCU, - PD_CPU_NOCR }, - { "ca57-cpu1", 0x80, 1, R8A774B1_PD_CA57_CPU1, R8A774B1_PD_CA57_SCU, - PD_CPU_NOCR }, - { "a3vc", 0x380, 0, R8A774B1_PD_A3VC, R8A774B1_PD_ALWAYS_ON }, - { "a3vp", 0x340, 0, R8A774B1_PD_A3VP, R8A774B1_PD_ALWAYS_ON }, - { "a2vc1", 0x3c0, 1, R8A774B1_PD_A2VC1, R8A774B1_PD_A3VC }, - { "3dg-a", 0x100, 0, R8A774B1_PD_3DG_A, R8A774B1_PD_ALWAYS_ON }, - { "3dg-b", 0x100, 1, R8A774B1_PD_3DG_B, R8A774B1_PD_3DG_A }, -}; - -const struct rcar_sysc_info r8a774b1_sysc_info __initconst = { - .areas = r8a774b1_areas, - .num_areas = ARRAY_SIZE(r8a774b1_areas), - .extmask_offs = 0x2f8, - .extmask_val = BIT(0), -}; diff --git a/drivers/soc/renesas/r8a774c0-sysc.c b/drivers/soc/renesas/r8a774c0-sysc.c deleted file mode 100644 index c1c216f7d073..000000000000 --- a/drivers/soc/renesas/r8a774c0-sysc.c +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas RZ/G2E System Controller - * Copyright (C) 2018 Renesas Electronics Corp. - * - * Based on Renesas R-Car E3 System Controller - */ - -#include <linux/bits.h> -#include <linux/kernel.h> -#include <linux/sys_soc.h> - -#include <dt-bindings/power/r8a774c0-sysc.h> - -#include "rcar-sysc.h" - -static struct rcar_sysc_area r8a774c0_areas[] __initdata = { - { "always-on", 0, 0, R8A774C0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca53-scu", 0x140, 0, R8A774C0_PD_CA53_SCU, R8A774C0_PD_ALWAYS_ON, - PD_SCU }, - { "ca53-cpu0", 0x200, 0, R8A774C0_PD_CA53_CPU0, R8A774C0_PD_CA53_SCU, - PD_CPU_NOCR }, - { "ca53-cpu1", 0x200, 1, R8A774C0_PD_CA53_CPU1, R8A774C0_PD_CA53_SCU, - PD_CPU_NOCR }, - { "a3vc", 0x380, 0, R8A774C0_PD_A3VC, R8A774C0_PD_ALWAYS_ON }, - { "a2vc1", 0x3c0, 1, R8A774C0_PD_A2VC1, R8A774C0_PD_A3VC }, - { "3dg-a", 0x100, 0, R8A774C0_PD_3DG_A, R8A774C0_PD_ALWAYS_ON }, - { "3dg-b", 0x100, 1, R8A774C0_PD_3DG_B, R8A774C0_PD_3DG_A }, -}; - -/* Fixups for RZ/G2E ES1.0 revision */ -static const struct soc_device_attribute r8a774c0[] __initconst = { - { .soc_id = "r8a774c0", .revision = "ES1.0" }, - { /* sentinel */ } -}; - -static int __init r8a774c0_sysc_init(void) -{ - if (soc_device_match(r8a774c0)) { - /* Fix incorrect 3DG hierarchy */ - swap(r8a774c0_areas[6], r8a774c0_areas[7]); - r8a774c0_areas[6].parent = R8A774C0_PD_ALWAYS_ON; - r8a774c0_areas[7].parent = R8A774C0_PD_3DG_B; - } - - return 0; -} - -const struct rcar_sysc_info r8a774c0_sysc_info __initconst = { - .init = r8a774c0_sysc_init, - .areas = r8a774c0_areas, - .num_areas = ARRAY_SIZE(r8a774c0_areas), - .extmask_offs = 0x2f8, - .extmask_val = BIT(0), -}; diff --git a/drivers/soc/renesas/r8a774e1-sysc.c b/drivers/soc/renesas/r8a774e1-sysc.c deleted file mode 100644 index 18449f746455..000000000000 --- a/drivers/soc/renesas/r8a774e1-sysc.c +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas RZ/G2H System Controller - * Copyright (C) 2020 Renesas Electronics Corp. - * - * Based on Renesas R-Car H3 System Controller - * Copyright (C) 2016-2017 Glider bvba - */ - -#include <linux/kernel.h> - -#include <dt-bindings/power/r8a774e1-sysc.h> - -#include "rcar-sysc.h" - -static const struct rcar_sysc_area r8a774e1_areas[] __initconst = { - { "always-on", 0, 0, R8A774E1_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca57-scu", 0x1c0, 0, R8A774E1_PD_CA57_SCU, R8A774E1_PD_ALWAYS_ON, PD_SCU }, - { "ca57-cpu0", 0x80, 0, R8A774E1_PD_CA57_CPU0, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR }, - { "ca57-cpu1", 0x80, 1, R8A774E1_PD_CA57_CPU1, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR }, - { "ca57-cpu2", 0x80, 2, R8A774E1_PD_CA57_CPU2, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR }, - { "ca57-cpu3", 0x80, 3, R8A774E1_PD_CA57_CPU3, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR }, - { "ca53-scu", 0x140, 0, R8A774E1_PD_CA53_SCU, R8A774E1_PD_ALWAYS_ON, PD_SCU }, - { "ca53-cpu0", 0x200, 0, R8A774E1_PD_CA53_CPU0, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR }, - { "ca53-cpu1", 0x200, 1, R8A774E1_PD_CA53_CPU1, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR }, - { "ca53-cpu2", 0x200, 2, R8A774E1_PD_CA53_CPU2, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR }, - { "ca53-cpu3", 0x200, 3, R8A774E1_PD_CA53_CPU3, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR }, - { "a3vp", 0x340, 0, R8A774E1_PD_A3VP, R8A774E1_PD_ALWAYS_ON }, - { "a3vc", 0x380, 0, R8A774E1_PD_A3VC, R8A774E1_PD_ALWAYS_ON }, - { "a2vc1", 0x3c0, 1, R8A774E1_PD_A2VC1, R8A774E1_PD_A3VC }, - { "3dg-a", 0x100, 0, R8A774E1_PD_3DG_A, R8A774E1_PD_ALWAYS_ON }, - { "3dg-b", 0x100, 1, R8A774E1_PD_3DG_B, R8A774E1_PD_3DG_A }, - { "3dg-c", 0x100, 2, R8A774E1_PD_3DG_C, R8A774E1_PD_3DG_B }, - { "3dg-d", 0x100, 3, R8A774E1_PD_3DG_D, R8A774E1_PD_3DG_C }, - { "3dg-e", 0x100, 4, R8A774E1_PD_3DG_E, R8A774E1_PD_3DG_D }, -}; - -const struct rcar_sysc_info r8a774e1_sysc_info __initconst = { - .areas = r8a774e1_areas, - .num_areas = ARRAY_SIZE(r8a774e1_areas), - .extmask_offs = 0x2f8, - .extmask_val = BIT(0), -}; diff --git a/drivers/soc/renesas/r8a7779-sysc.c b/drivers/soc/renesas/r8a7779-sysc.c deleted file mode 100644 index e24a7151d55f..000000000000 --- a/drivers/soc/renesas/r8a7779-sysc.c +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas R-Car H1 System Controller - * - * Copyright (C) 2016 Glider bvba - */ - -#include <linux/kernel.h> - -#include <dt-bindings/power/r8a7779-sysc.h> - -#include "rcar-sysc.h" - -static const struct rcar_sysc_area r8a7779_areas[] __initconst = { - { "always-on", 0, 0, R8A7779_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "arm1", 0x40, 1, R8A7779_PD_ARM1, R8A7779_PD_ALWAYS_ON, - PD_CPU_CR }, - { "arm2", 0x40, 2, R8A7779_PD_ARM2, R8A7779_PD_ALWAYS_ON, - PD_CPU_CR }, - { "arm3", 0x40, 3, R8A7779_PD_ARM3, R8A7779_PD_ALWAYS_ON, - PD_CPU_CR }, - { "sgx", 0xc0, 0, R8A7779_PD_SGX, R8A7779_PD_ALWAYS_ON }, - { "vdp", 0x100, 0, R8A7779_PD_VDP, R8A7779_PD_ALWAYS_ON }, - { "imp", 0x140, 0, R8A7779_PD_IMP, R8A7779_PD_ALWAYS_ON }, -}; - -const struct rcar_sysc_info r8a7779_sysc_info __initconst = { - .areas = r8a7779_areas, - .num_areas = ARRAY_SIZE(r8a7779_areas), -}; diff --git a/drivers/soc/renesas/r8a7790-sysc.c b/drivers/soc/renesas/r8a7790-sysc.c deleted file mode 100644 index b9afe7f6245b..000000000000 --- a/drivers/soc/renesas/r8a7790-sysc.c +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas R-Car H2 System Controller - * - * Copyright (C) 2016 Glider bvba - */ - -#include <linux/kernel.h> - -#include <dt-bindings/power/r8a7790-sysc.h> - -#include "rcar-sysc.h" - -static const struct rcar_sysc_area r8a7790_areas[] __initconst = { - { "always-on", 0, 0, R8A7790_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca15-scu", 0x180, 0, R8A7790_PD_CA15_SCU, R8A7790_PD_ALWAYS_ON, - PD_SCU }, - { "ca15-cpu0", 0x40, 0, R8A7790_PD_CA15_CPU0, R8A7790_PD_CA15_SCU, - PD_CPU_NOCR }, - { "ca15-cpu1", 0x40, 1, R8A7790_PD_CA15_CPU1, R8A7790_PD_CA15_SCU, - PD_CPU_NOCR }, - { "ca15-cpu2", 0x40, 2, R8A7790_PD_CA15_CPU2, R8A7790_PD_CA15_SCU, - PD_CPU_NOCR }, - { "ca15-cpu3", 0x40, 3, R8A7790_PD_CA15_CPU3, R8A7790_PD_CA15_SCU, - PD_CPU_NOCR }, - { "ca7-scu", 0x100, 0, R8A7790_PD_CA7_SCU, R8A7790_PD_ALWAYS_ON, - PD_SCU }, - { "ca7-cpu0", 0x1c0, 0, R8A7790_PD_CA7_CPU0, R8A7790_PD_CA7_SCU, - PD_CPU_NOCR }, - { "ca7-cpu1", 0x1c0, 1, R8A7790_PD_CA7_CPU1, R8A7790_PD_CA7_SCU, - PD_CPU_NOCR }, - { "ca7-cpu2", 0x1c0, 2, R8A7790_PD_CA7_CPU2, R8A7790_PD_CA7_SCU, - PD_CPU_NOCR }, - { "ca7-cpu3", 0x1c0, 3, R8A7790_PD_CA7_CPU3, R8A7790_PD_CA7_SCU, - PD_CPU_NOCR }, - { "sh-4a", 0x80, 0, R8A7790_PD_SH_4A, R8A7790_PD_ALWAYS_ON }, - { "rgx", 0xc0, 0, R8A7790_PD_RGX, R8A7790_PD_ALWAYS_ON }, - { "imp", 0x140, 0, R8A7790_PD_IMP, R8A7790_PD_ALWAYS_ON }, -}; - -const struct rcar_sysc_info r8a7790_sysc_info __initconst = { - .areas = r8a7790_areas, - .num_areas = ARRAY_SIZE(r8a7790_areas), -}; diff --git a/drivers/soc/renesas/r8a7791-sysc.c b/drivers/soc/renesas/r8a7791-sysc.c deleted file mode 100644 index f00fa24522a3..000000000000 --- a/drivers/soc/renesas/r8a7791-sysc.c +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas R-Car M2-W/N System Controller - * - * Copyright (C) 2016 Glider bvba - */ - -#include <linux/kernel.h> - -#include <dt-bindings/power/r8a7791-sysc.h> - -#include "rcar-sysc.h" - -static const struct rcar_sysc_area r8a7791_areas[] __initconst = { - { "always-on", 0, 0, R8A7791_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca15-scu", 0x180, 0, R8A7791_PD_CA15_SCU, R8A7791_PD_ALWAYS_ON, - PD_SCU }, - { "ca15-cpu0", 0x40, 0, R8A7791_PD_CA15_CPU0, R8A7791_PD_CA15_SCU, - PD_CPU_NOCR }, - { "ca15-cpu1", 0x40, 1, R8A7791_PD_CA15_CPU1, R8A7791_PD_CA15_SCU, - PD_CPU_NOCR }, - { "sh-4a", 0x80, 0, R8A7791_PD_SH_4A, R8A7791_PD_ALWAYS_ON }, - { "sgx", 0xc0, 0, R8A7791_PD_SGX, R8A7791_PD_ALWAYS_ON }, -}; - -const struct rcar_sysc_info r8a7791_sysc_info __initconst = { - .areas = r8a7791_areas, - .num_areas = ARRAY_SIZE(r8a7791_areas), -}; diff --git a/drivers/soc/renesas/r8a7792-sysc.c b/drivers/soc/renesas/r8a7792-sysc.c deleted file mode 100644 index 60aae242c43f..000000000000 --- a/drivers/soc/renesas/r8a7792-sysc.c +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas R-Car V2H (R8A7792) System Controller - * - * Copyright (C) 2016 Cogent Embedded Inc. - */ - -#include <linux/init.h> -#include <linux/kernel.h> - -#include <dt-bindings/power/r8a7792-sysc.h> - -#include "rcar-sysc.h" - -static const struct rcar_sysc_area r8a7792_areas[] __initconst = { - { "always-on", 0, 0, R8A7792_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca15-scu", 0x180, 0, R8A7792_PD_CA15_SCU, R8A7792_PD_ALWAYS_ON, - PD_SCU }, - { "ca15-cpu0", 0x40, 0, R8A7792_PD_CA15_CPU0, R8A7792_PD_CA15_SCU, - PD_CPU_NOCR }, - { "ca15-cpu1", 0x40, 1, R8A7792_PD_CA15_CPU1, R8A7792_PD_CA15_SCU, - PD_CPU_NOCR }, - { "sgx", 0xc0, 0, R8A7792_PD_SGX, R8A7792_PD_ALWAYS_ON }, - { "imp", 0x140, 0, R8A7792_PD_IMP, R8A7792_PD_ALWAYS_ON }, -}; - -const struct rcar_sysc_info r8a7792_sysc_info __initconst = { - .areas = r8a7792_areas, - .num_areas = ARRAY_SIZE(r8a7792_areas), -}; diff --git a/drivers/soc/renesas/r8a7794-sysc.c b/drivers/soc/renesas/r8a7794-sysc.c deleted file mode 100644 index 72ef4e85458f..000000000000 --- a/drivers/soc/renesas/r8a7794-sysc.c +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas R-Car E2 System Controller - * - * Copyright (C) 2016 Glider bvba - */ - -#include <linux/kernel.h> - -#include <dt-bindings/power/r8a7794-sysc.h> - -#include "rcar-sysc.h" - -static const struct rcar_sysc_area r8a7794_areas[] __initconst = { - { "always-on", 0, 0, R8A7794_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca7-scu", 0x100, 0, R8A7794_PD_CA7_SCU, R8A7794_PD_ALWAYS_ON, - PD_SCU }, - { "ca7-cpu0", 0x1c0, 0, R8A7794_PD_CA7_CPU0, R8A7794_PD_CA7_SCU, - PD_CPU_NOCR }, - { "ca7-cpu1", 0x1c0, 1, R8A7794_PD_CA7_CPU1, R8A7794_PD_CA7_SCU, - PD_CPU_NOCR }, - { "sh-4a", 0x80, 0, R8A7794_PD_SH_4A, R8A7794_PD_ALWAYS_ON }, - { "sgx", 0xc0, 0, R8A7794_PD_SGX, R8A7794_PD_ALWAYS_ON }, -}; - -const struct rcar_sysc_info r8a7794_sysc_info __initconst = { - .areas = r8a7794_areas, - .num_areas = ARRAY_SIZE(r8a7794_areas), -}; diff --git a/drivers/soc/renesas/r8a7795-sysc.c b/drivers/soc/renesas/r8a7795-sysc.c deleted file mode 100644 index cbe1ff0fc583..000000000000 --- a/drivers/soc/renesas/r8a7795-sysc.c +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas R-Car H3 System Controller - * - * Copyright (C) 2016-2017 Glider bvba - */ - -#include <linux/bits.h> -#include <linux/kernel.h> -#include <linux/sys_soc.h> - -#include <dt-bindings/power/r8a7795-sysc.h> - -#include "rcar-sysc.h" - -static struct rcar_sysc_area r8a7795_areas[] __initdata = { - { "always-on", 0, 0, R8A7795_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca57-scu", 0x1c0, 0, R8A7795_PD_CA57_SCU, R8A7795_PD_ALWAYS_ON, - PD_SCU }, - { "ca57-cpu0", 0x80, 0, R8A7795_PD_CA57_CPU0, R8A7795_PD_CA57_SCU, - PD_CPU_NOCR }, - { "ca57-cpu1", 0x80, 1, R8A7795_PD_CA57_CPU1, R8A7795_PD_CA57_SCU, - PD_CPU_NOCR }, - { "ca57-cpu2", 0x80, 2, R8A7795_PD_CA57_CPU2, R8A7795_PD_CA57_SCU, - PD_CPU_NOCR }, - { "ca57-cpu3", 0x80, 3, R8A7795_PD_CA57_CPU3, R8A7795_PD_CA57_SCU, - PD_CPU_NOCR }, - { "ca53-scu", 0x140, 0, R8A7795_PD_CA53_SCU, R8A7795_PD_ALWAYS_ON, - PD_SCU }, - { "ca53-cpu0", 0x200, 0, R8A7795_PD_CA53_CPU0, R8A7795_PD_CA53_SCU, - PD_CPU_NOCR }, - { "ca53-cpu1", 0x200, 1, R8A7795_PD_CA53_CPU1, R8A7795_PD_CA53_SCU, - PD_CPU_NOCR }, - { "ca53-cpu2", 0x200, 2, R8A7795_PD_CA53_CPU2, R8A7795_PD_CA53_SCU, - PD_CPU_NOCR }, - { "ca53-cpu3", 0x200, 3, R8A7795_PD_CA53_CPU3, R8A7795_PD_CA53_SCU, - PD_CPU_NOCR }, - { "a3vp", 0x340, 0, R8A7795_PD_A3VP, R8A7795_PD_ALWAYS_ON }, - { "cr7", 0x240, 0, R8A7795_PD_CR7, R8A7795_PD_ALWAYS_ON }, - { "a3vc", 0x380, 0, R8A7795_PD_A3VC, R8A7795_PD_ALWAYS_ON }, - { "a2vc1", 0x3c0, 1, R8A7795_PD_A2VC1, R8A7795_PD_A3VC }, - { "3dg-a", 0x100, 0, R8A7795_PD_3DG_A, R8A7795_PD_ALWAYS_ON }, - { "3dg-b", 0x100, 1, R8A7795_PD_3DG_B, R8A7795_PD_3DG_A }, - { "3dg-c", 0x100, 2, R8A7795_PD_3DG_C, R8A7795_PD_3DG_B }, - { "3dg-d", 0x100, 3, R8A7795_PD_3DG_D, R8A7795_PD_3DG_C }, - { "3dg-e", 0x100, 4, R8A7795_PD_3DG_E, R8A7795_PD_3DG_D }, - { "a3ir", 0x180, 0, R8A7795_PD_A3IR, R8A7795_PD_ALWAYS_ON }, -}; - - - /* - * Fixups for R-Car H3 revisions - */ - -#define NO_EXTMASK BIT(1) /* Missing SYSCEXTMASK register */ - -static const struct soc_device_attribute r8a7795_quirks_match[] __initconst = { - { - .soc_id = "r8a7795", .revision = "ES2.*", - .data = (void *)(NO_EXTMASK), - }, - { /* sentinel */ } -}; - -static int __init r8a7795_sysc_init(void) -{ - const struct soc_device_attribute *attr; - u32 quirks = 0; - - attr = soc_device_match(r8a7795_quirks_match); - if (attr) - quirks = (uintptr_t)attr->data; - - if (quirks & NO_EXTMASK) - r8a7795_sysc_info.extmask_val = 0; - - return 0; -} - -struct rcar_sysc_info r8a7795_sysc_info __initdata = { - .init = r8a7795_sysc_init, - .areas = r8a7795_areas, - .num_areas = ARRAY_SIZE(r8a7795_areas), - .extmask_offs = 0x2f8, - .extmask_val = BIT(0), -}; diff --git a/drivers/soc/renesas/r8a7796-sysc.c b/drivers/soc/renesas/r8a7796-sysc.c deleted file mode 100644 index 471bd5b3b6ad..000000000000 --- a/drivers/soc/renesas/r8a7796-sysc.c +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas R-Car M3-W/W+ System Controller - * - * Copyright (C) 2016 Glider bvba - * Copyright (C) 2018-2019 Renesas Electronics Corporation - */ - -#include <linux/bits.h> -#include <linux/kernel.h> - -#include <dt-bindings/power/r8a7796-sysc.h> - -#include "rcar-sysc.h" - -static struct rcar_sysc_area r8a7796_areas[] __initdata = { - { "always-on", 0, 0, R8A7796_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca57-scu", 0x1c0, 0, R8A7796_PD_CA57_SCU, R8A7796_PD_ALWAYS_ON, - PD_SCU }, - { "ca57-cpu0", 0x80, 0, R8A7796_PD_CA57_CPU0, R8A7796_PD_CA57_SCU, - PD_CPU_NOCR }, - { "ca57-cpu1", 0x80, 1, R8A7796_PD_CA57_CPU1, R8A7796_PD_CA57_SCU, - PD_CPU_NOCR }, - { "ca53-scu", 0x140, 0, R8A7796_PD_CA53_SCU, R8A7796_PD_ALWAYS_ON, - PD_SCU }, - { "ca53-cpu0", 0x200, 0, R8A7796_PD_CA53_CPU0, R8A7796_PD_CA53_SCU, - PD_CPU_NOCR }, - { "ca53-cpu1", 0x200, 1, R8A7796_PD_CA53_CPU1, R8A7796_PD_CA53_SCU, - PD_CPU_NOCR }, - { "ca53-cpu2", 0x200, 2, R8A7796_PD_CA53_CPU2, R8A7796_PD_CA53_SCU, - PD_CPU_NOCR }, - { "ca53-cpu3", 0x200, 3, R8A7796_PD_CA53_CPU3, R8A7796_PD_CA53_SCU, - PD_CPU_NOCR }, - { "cr7", 0x240, 0, R8A7796_PD_CR7, R8A7796_PD_ALWAYS_ON }, - { "a3vc", 0x380, 0, R8A7796_PD_A3VC, R8A7796_PD_ALWAYS_ON }, - { "a2vc0", 0x3c0, 0, R8A7796_PD_A2VC0, R8A7796_PD_A3VC }, - { "a2vc1", 0x3c0, 1, R8A7796_PD_A2VC1, R8A7796_PD_A3VC }, - { "3dg-a", 0x100, 0, R8A7796_PD_3DG_A, R8A7796_PD_ALWAYS_ON }, - { "3dg-b", 0x100, 1, R8A7796_PD_3DG_B, R8A7796_PD_3DG_A }, - { "a3ir", 0x180, 0, R8A7796_PD_A3IR, R8A7796_PD_ALWAYS_ON }, -}; - - -#ifdef CONFIG_SYSC_R8A77960 -const struct rcar_sysc_info r8a77960_sysc_info __initconst = { - .areas = r8a7796_areas, - .num_areas = ARRAY_SIZE(r8a7796_areas), -}; -#endif /* CONFIG_SYSC_R8A77960 */ - -#ifdef CONFIG_SYSC_R8A77961 -static int __init r8a77961_sysc_init(void) -{ - rcar_sysc_nullify(r8a7796_areas, ARRAY_SIZE(r8a7796_areas), - R8A7796_PD_A2VC0); - - return 0; -} - -const struct rcar_sysc_info r8a77961_sysc_info __initconst = { - .init = r8a77961_sysc_init, - .areas = r8a7796_areas, - .num_areas = ARRAY_SIZE(r8a7796_areas), - .extmask_offs = 0x2f8, - .extmask_val = BIT(0), -}; -#endif /* CONFIG_SYSC_R8A77961 */ diff --git a/drivers/soc/renesas/r8a77965-sysc.c b/drivers/soc/renesas/r8a77965-sysc.c deleted file mode 100644 index ff0b0d116992..000000000000 --- a/drivers/soc/renesas/r8a77965-sysc.c +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas R-Car M3-N System Controller - * Copyright (C) 2018 Jacopo Mondi <jacopo+renesas@jmondi.org> - * - * Based on Renesas R-Car M3-W System Controller - * Copyright (C) 2016 Glider bvba - */ - -#include <linux/bits.h> -#include <linux/kernel.h> - -#include <dt-bindings/power/r8a77965-sysc.h> - -#include "rcar-sysc.h" - -static const struct rcar_sysc_area r8a77965_areas[] __initconst = { - { "always-on", 0, 0, R8A77965_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca57-scu", 0x1c0, 0, R8A77965_PD_CA57_SCU, R8A77965_PD_ALWAYS_ON, - PD_SCU }, - { "ca57-cpu0", 0x80, 0, R8A77965_PD_CA57_CPU0, R8A77965_PD_CA57_SCU, - PD_CPU_NOCR }, - { "ca57-cpu1", 0x80, 1, R8A77965_PD_CA57_CPU1, R8A77965_PD_CA57_SCU, - PD_CPU_NOCR }, - { "cr7", 0x240, 0, R8A77965_PD_CR7, R8A77965_PD_ALWAYS_ON }, - { "a3vc", 0x380, 0, R8A77965_PD_A3VC, R8A77965_PD_ALWAYS_ON }, - { "a3vp", 0x340, 0, R8A77965_PD_A3VP, R8A77965_PD_ALWAYS_ON }, - { "a2vc1", 0x3c0, 1, R8A77965_PD_A2VC1, R8A77965_PD_A3VC }, - { "3dg-a", 0x100, 0, R8A77965_PD_3DG_A, R8A77965_PD_ALWAYS_ON }, - { "3dg-b", 0x100, 1, R8A77965_PD_3DG_B, R8A77965_PD_3DG_A }, -}; - -const struct rcar_sysc_info r8a77965_sysc_info __initconst = { - .areas = r8a77965_areas, - .num_areas = ARRAY_SIZE(r8a77965_areas), - .extmask_offs = 0x2f8, - .extmask_val = BIT(0), -}; diff --git a/drivers/soc/renesas/r8a77970-sysc.c b/drivers/soc/renesas/r8a77970-sysc.c deleted file mode 100644 index 706258250600..000000000000 --- a/drivers/soc/renesas/r8a77970-sysc.c +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas R-Car V3M System Controller - * - * Copyright (C) 2017 Cogent Embedded Inc. - */ - -#include <linux/bits.h> -#include <linux/kernel.h> - -#include <dt-bindings/power/r8a77970-sysc.h> - -#include "rcar-sysc.h" - -static const struct rcar_sysc_area r8a77970_areas[] __initconst = { - { "always-on", 0, 0, R8A77970_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca53-scu", 0x140, 0, R8A77970_PD_CA53_SCU, R8A77970_PD_ALWAYS_ON, - PD_SCU }, - { "ca53-cpu0", 0x200, 0, R8A77970_PD_CA53_CPU0, R8A77970_PD_CA53_SCU, - PD_CPU_NOCR }, - { "ca53-cpu1", 0x200, 1, R8A77970_PD_CA53_CPU1, R8A77970_PD_CA53_SCU, - PD_CPU_NOCR }, - { "a3ir", 0x180, 0, R8A77970_PD_A3IR, R8A77970_PD_ALWAYS_ON }, - { "a2ir0", 0x400, 0, R8A77970_PD_A2IR0, R8A77970_PD_A3IR }, - { "a2ir1", 0x400, 1, R8A77970_PD_A2IR1, R8A77970_PD_A3IR }, - { "a2dp", 0x400, 2, R8A77970_PD_A2DP, R8A77970_PD_A3IR }, - { "a2cn", 0x400, 3, R8A77970_PD_A2CN, R8A77970_PD_A3IR }, - { "a2sc0", 0x400, 4, R8A77970_PD_A2SC0, R8A77970_PD_A3IR }, - { "a2sc1", 0x400, 5, R8A77970_PD_A2SC1, R8A77970_PD_A3IR }, -}; - -const struct rcar_sysc_info r8a77970_sysc_info __initconst = { - .areas = r8a77970_areas, - .num_areas = ARRAY_SIZE(r8a77970_areas), - .extmask_offs = 0x1b0, - .extmask_val = BIT(0), -}; diff --git a/drivers/soc/renesas/r8a77980-sysc.c b/drivers/soc/renesas/r8a77980-sysc.c deleted file mode 100644 index 39ca84a67daa..000000000000 --- a/drivers/soc/renesas/r8a77980-sysc.c +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas R-Car V3H System Controller - * - * Copyright (C) 2018 Renesas Electronics Corp. - * Copyright (C) 2018 Cogent Embedded, Inc. - */ - -#include <linux/bits.h> -#include <linux/kernel.h> - -#include <dt-bindings/power/r8a77980-sysc.h> - -#include "rcar-sysc.h" - -static const struct rcar_sysc_area r8a77980_areas[] __initconst = { - { "always-on", 0, 0, R8A77980_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca53-scu", 0x140, 0, R8A77980_PD_CA53_SCU, R8A77980_PD_ALWAYS_ON, - PD_SCU }, - { "ca53-cpu0", 0x200, 0, R8A77980_PD_CA53_CPU0, R8A77980_PD_CA53_SCU, - PD_CPU_NOCR }, - { "ca53-cpu1", 0x200, 1, R8A77980_PD_CA53_CPU1, R8A77980_PD_CA53_SCU, - PD_CPU_NOCR }, - { "ca53-cpu2", 0x200, 2, R8A77980_PD_CA53_CPU2, R8A77980_PD_CA53_SCU, - PD_CPU_NOCR }, - { "ca53-cpu3", 0x200, 3, R8A77980_PD_CA53_CPU3, R8A77980_PD_CA53_SCU, - PD_CPU_NOCR }, - { "cr7", 0x240, 0, R8A77980_PD_CR7, R8A77980_PD_ALWAYS_ON }, - { "a3ir", 0x180, 0, R8A77980_PD_A3IR, R8A77980_PD_ALWAYS_ON }, - { "a2ir0", 0x400, 0, R8A77980_PD_A2IR0, R8A77980_PD_A3IR }, - { "a2ir1", 0x400, 1, R8A77980_PD_A2IR1, R8A77980_PD_A3IR }, - { "a2ir2", 0x400, 2, R8A77980_PD_A2IR2, R8A77980_PD_A3IR }, - { "a2ir3", 0x400, 3, R8A77980_PD_A2IR3, R8A77980_PD_A3IR }, - { "a2ir4", 0x400, 4, R8A77980_PD_A2IR4, R8A77980_PD_A3IR }, - { "a2ir5", 0x400, 5, R8A77980_PD_A2IR5, R8A77980_PD_A3IR }, - { "a2sc0", 0x400, 6, R8A77980_PD_A2SC0, R8A77980_PD_A3IR }, - { "a2sc1", 0x400, 7, R8A77980_PD_A2SC1, R8A77980_PD_A3IR }, - { "a2sc2", 0x400, 8, R8A77980_PD_A2SC2, R8A77980_PD_A3IR }, - { "a2sc3", 0x400, 9, R8A77980_PD_A2SC3, R8A77980_PD_A3IR }, - { "a2sc4", 0x400, 10, R8A77980_PD_A2SC4, R8A77980_PD_A3IR }, - { "a2dp0", 0x400, 11, R8A77980_PD_A2DP0, R8A77980_PD_A3IR }, - { "a2dp1", 0x400, 12, R8A77980_PD_A2DP1, R8A77980_PD_A3IR }, - { "a2cn", 0x400, 13, R8A77980_PD_A2CN, R8A77980_PD_A3IR }, - { "a3vip0", 0x2c0, 0, R8A77980_PD_A3VIP0, R8A77980_PD_ALWAYS_ON }, - { "a3vip1", 0x300, 0, R8A77980_PD_A3VIP1, R8A77980_PD_ALWAYS_ON }, - { "a3vip2", 0x280, 0, R8A77980_PD_A3VIP2, R8A77980_PD_ALWAYS_ON }, -}; - -const struct rcar_sysc_info r8a77980_sysc_info __initconst = { - .areas = r8a77980_areas, - .num_areas = ARRAY_SIZE(r8a77980_areas), - .extmask_offs = 0x138, - .extmask_val = BIT(0), -}; diff --git a/drivers/soc/renesas/r8a77990-sysc.c b/drivers/soc/renesas/r8a77990-sysc.c deleted file mode 100644 index 9f92737dc352..000000000000 --- a/drivers/soc/renesas/r8a77990-sysc.c +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas R-Car E3 System Controller - * - * Copyright (C) 2018 Renesas Electronics Corp. - */ - -#include <linux/bits.h> -#include <linux/kernel.h> -#include <linux/sys_soc.h> - -#include <dt-bindings/power/r8a77990-sysc.h> - -#include "rcar-sysc.h" - -static struct rcar_sysc_area r8a77990_areas[] __initdata = { - { "always-on", 0, 0, R8A77990_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca53-scu", 0x140, 0, R8A77990_PD_CA53_SCU, R8A77990_PD_ALWAYS_ON, - PD_SCU }, - { "ca53-cpu0", 0x200, 0, R8A77990_PD_CA53_CPU0, R8A77990_PD_CA53_SCU, - PD_CPU_NOCR }, - { "ca53-cpu1", 0x200, 1, R8A77990_PD_CA53_CPU1, R8A77990_PD_CA53_SCU, - PD_CPU_NOCR }, - { "cr7", 0x240, 0, R8A77990_PD_CR7, R8A77990_PD_ALWAYS_ON }, - { "a3vc", 0x380, 0, R8A77990_PD_A3VC, R8A77990_PD_ALWAYS_ON }, - { "a2vc1", 0x3c0, 1, R8A77990_PD_A2VC1, R8A77990_PD_A3VC }, - { "3dg-a", 0x100, 0, R8A77990_PD_3DG_A, R8A77990_PD_ALWAYS_ON }, - { "3dg-b", 0x100, 1, R8A77990_PD_3DG_B, R8A77990_PD_3DG_A }, -}; - -/* Fixups for R-Car E3 ES1.0 revision */ -static const struct soc_device_attribute r8a77990[] __initconst = { - { .soc_id = "r8a77990", .revision = "ES1.0" }, - { /* sentinel */ } -}; - -static int __init r8a77990_sysc_init(void) -{ - if (soc_device_match(r8a77990)) { - /* Fix incorrect 3DG hierarchy */ - swap(r8a77990_areas[7], r8a77990_areas[8]); - r8a77990_areas[7].parent = R8A77990_PD_ALWAYS_ON; - r8a77990_areas[8].parent = R8A77990_PD_3DG_B; - } - - return 0; -} - -const struct rcar_sysc_info r8a77990_sysc_info __initconst = { - .init = r8a77990_sysc_init, - .areas = r8a77990_areas, - .num_areas = ARRAY_SIZE(r8a77990_areas), - .extmask_offs = 0x2f8, - .extmask_val = BIT(0), -}; diff --git a/drivers/soc/renesas/r8a77995-sysc.c b/drivers/soc/renesas/r8a77995-sysc.c deleted file mode 100644 index efcc67e3d76d..000000000000 --- a/drivers/soc/renesas/r8a77995-sysc.c +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas R-Car D3 System Controller - * - * Copyright (C) 2017 Glider bvba - */ - -#include <linux/kernel.h> - -#include <dt-bindings/power/r8a77995-sysc.h> - -#include "rcar-sysc.h" - -static const struct rcar_sysc_area r8a77995_areas[] __initconst = { - { "always-on", 0, 0, R8A77995_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "ca53-scu", 0x140, 0, R8A77995_PD_CA53_SCU, R8A77995_PD_ALWAYS_ON, - PD_SCU }, - { "ca53-cpu0", 0x200, 0, R8A77995_PD_CA53_CPU0, R8A77995_PD_CA53_SCU, - PD_CPU_NOCR }, -}; - - -const struct rcar_sysc_info r8a77995_sysc_info __initconst = { - .areas = r8a77995_areas, - .num_areas = ARRAY_SIZE(r8a77995_areas), -}; diff --git a/drivers/soc/renesas/r8a779a0-sysc.c b/drivers/soc/renesas/r8a779a0-sysc.c deleted file mode 100644 index 04f1bc322ae7..000000000000 --- a/drivers/soc/renesas/r8a779a0-sysc.c +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas R-Car V3U System Controller - * - * Copyright (C) 2020 Renesas Electronics Corp. - */ - -#include <linux/bits.h> -#include <linux/clk/renesas.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/iopoll.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/of_address.h> -#include <linux/pm_domain.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/types.h> - -#include <dt-bindings/power/r8a779a0-sysc.h> - -#include "rcar-gen4-sysc.h" - -static struct rcar_gen4_sysc_area r8a779a0_areas[] __initdata = { - { "always-on", R8A779A0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "a3e0", R8A779A0_PD_A3E0, R8A779A0_PD_ALWAYS_ON, PD_SCU }, - { "a3e1", R8A779A0_PD_A3E1, R8A779A0_PD_ALWAYS_ON, PD_SCU }, - { "a2e0d0", R8A779A0_PD_A2E0D0, R8A779A0_PD_A3E0, PD_SCU }, - { "a2e0d1", R8A779A0_PD_A2E0D1, R8A779A0_PD_A3E0, PD_SCU }, - { "a2e1d0", R8A779A0_PD_A2E1D0, R8A779A0_PD_A3E1, PD_SCU }, - { "a2e1d1", R8A779A0_PD_A2E1D1, R8A779A0_PD_A3E1, PD_SCU }, - { "a1e0d0c0", R8A779A0_PD_A1E0D0C0, R8A779A0_PD_A2E0D0, PD_CPU_NOCR }, - { "a1e0d0c1", R8A779A0_PD_A1E0D0C1, R8A779A0_PD_A2E0D0, PD_CPU_NOCR }, - { "a1e0d1c0", R8A779A0_PD_A1E0D1C0, R8A779A0_PD_A2E0D1, PD_CPU_NOCR }, - { "a1e0d1c1", R8A779A0_PD_A1E0D1C1, R8A779A0_PD_A2E0D1, PD_CPU_NOCR }, - { "a1e1d0c0", R8A779A0_PD_A1E1D0C0, R8A779A0_PD_A2E1D0, PD_CPU_NOCR }, - { "a1e1d0c1", R8A779A0_PD_A1E1D0C1, R8A779A0_PD_A2E1D0, PD_CPU_NOCR }, - { "a1e1d1c0", R8A779A0_PD_A1E1D1C0, R8A779A0_PD_A2E1D1, PD_CPU_NOCR }, - { "a1e1d1c1", R8A779A0_PD_A1E1D1C1, R8A779A0_PD_A2E1D1, PD_CPU_NOCR }, - { "3dg-a", R8A779A0_PD_3DG_A, R8A779A0_PD_ALWAYS_ON }, - { "3dg-b", R8A779A0_PD_3DG_B, R8A779A0_PD_3DG_A }, - { "a3vip0", R8A779A0_PD_A3VIP0, R8A779A0_PD_ALWAYS_ON }, - { "a3vip1", R8A779A0_PD_A3VIP1, R8A779A0_PD_ALWAYS_ON }, - { "a3vip3", R8A779A0_PD_A3VIP3, R8A779A0_PD_ALWAYS_ON }, - { "a3vip2", R8A779A0_PD_A3VIP2, R8A779A0_PD_ALWAYS_ON }, - { "a3isp01", R8A779A0_PD_A3ISP01, R8A779A0_PD_ALWAYS_ON }, - { "a3isp23", R8A779A0_PD_A3ISP23, R8A779A0_PD_ALWAYS_ON }, - { "a3ir", R8A779A0_PD_A3IR, R8A779A0_PD_ALWAYS_ON }, - { "a2cn0", R8A779A0_PD_A2CN0, R8A779A0_PD_A3IR }, - { "a2imp01", R8A779A0_PD_A2IMP01, R8A779A0_PD_A3IR }, - { "a2dp0", R8A779A0_PD_A2DP0, R8A779A0_PD_A3IR }, - { "a2cv0", R8A779A0_PD_A2CV0, R8A779A0_PD_A3IR }, - { "a2cv1", R8A779A0_PD_A2CV1, R8A779A0_PD_A3IR }, - { "a2cv4", R8A779A0_PD_A2CV4, R8A779A0_PD_A3IR }, - { "a2cv6", R8A779A0_PD_A2CV6, R8A779A0_PD_A3IR }, - { "a2cn2", R8A779A0_PD_A2CN2, R8A779A0_PD_A3IR }, - { "a2imp23", R8A779A0_PD_A2IMP23, R8A779A0_PD_A3IR }, - { "a2dp1", R8A779A0_PD_A2DP1, R8A779A0_PD_A3IR }, - { "a2cv2", R8A779A0_PD_A2CV2, R8A779A0_PD_A3IR }, - { "a2cv3", R8A779A0_PD_A2CV3, R8A779A0_PD_A3IR }, - { "a2cv5", R8A779A0_PD_A2CV5, R8A779A0_PD_A3IR }, - { "a2cv7", R8A779A0_PD_A2CV7, R8A779A0_PD_A3IR }, - { "a2cn1", R8A779A0_PD_A2CN1, R8A779A0_PD_A3IR }, - { "a1cnn0", R8A779A0_PD_A1CNN0, R8A779A0_PD_A2CN0 }, - { "a1cnn2", R8A779A0_PD_A1CNN2, R8A779A0_PD_A2CN2 }, - { "a1dsp0", R8A779A0_PD_A1DSP0, R8A779A0_PD_A2CN2 }, - { "a1cnn1", R8A779A0_PD_A1CNN1, R8A779A0_PD_A2CN1 }, - { "a1dsp1", R8A779A0_PD_A1DSP1, R8A779A0_PD_A2CN1 }, -}; - -const struct rcar_gen4_sysc_info r8a779a0_sysc_info __initconst = { - .areas = r8a779a0_areas, - .num_areas = ARRAY_SIZE(r8a779a0_areas), -}; diff --git a/drivers/soc/renesas/r8a779f0-sysc.c b/drivers/soc/renesas/r8a779f0-sysc.c deleted file mode 100644 index 5602aa6bd7ed..000000000000 --- a/drivers/soc/renesas/r8a779f0-sysc.c +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas R-Car S4-8 System Controller - * - * Copyright (C) 2021 Renesas Electronics Corp. - */ - -#include <linux/bits.h> -#include <linux/clk/renesas.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/iopoll.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/of_address.h> -#include <linux/pm_domain.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/types.h> - -#include <dt-bindings/power/r8a779f0-sysc.h> - -#include "rcar-gen4-sysc.h" - -static struct rcar_gen4_sysc_area r8a779f0_areas[] __initdata = { - { "always-on", R8A779F0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "a3e0", R8A779F0_PD_A3E0, R8A779F0_PD_ALWAYS_ON, PD_SCU }, - { "a3e1", R8A779F0_PD_A3E1, R8A779F0_PD_ALWAYS_ON, PD_SCU }, - { "a2e0d0", R8A779F0_PD_A2E0D0, R8A779F0_PD_A3E0, PD_SCU }, - { "a2e0d1", R8A779F0_PD_A2E0D1, R8A779F0_PD_A3E0, PD_SCU }, - { "a2e1d0", R8A779F0_PD_A2E1D0, R8A779F0_PD_A3E1, PD_SCU }, - { "a2e1d1", R8A779F0_PD_A2E1D1, R8A779F0_PD_A3E1, PD_SCU }, - { "a1e0d0c0", R8A779F0_PD_A1E0D0C0, R8A779F0_PD_A2E0D0, PD_CPU_NOCR }, - { "a1e0d0c1", R8A779F0_PD_A1E0D0C1, R8A779F0_PD_A2E0D0, PD_CPU_NOCR }, - { "a1e0d1c0", R8A779F0_PD_A1E0D1C0, R8A779F0_PD_A2E0D1, PD_CPU_NOCR }, - { "a1e0d1c1", R8A779F0_PD_A1E0D1C1, R8A779F0_PD_A2E0D1, PD_CPU_NOCR }, - { "a1e1d0c0", R8A779F0_PD_A1E1D0C0, R8A779F0_PD_A2E1D0, PD_CPU_NOCR }, - { "a1e1d0c1", R8A779F0_PD_A1E1D0C1, R8A779F0_PD_A2E1D0, PD_CPU_NOCR }, - { "a1e1d1c0", R8A779F0_PD_A1E1D1C0, R8A779F0_PD_A2E1D1, PD_CPU_NOCR }, - { "a1e1d1c1", R8A779F0_PD_A1E1D1C1, R8A779F0_PD_A2E1D1, PD_CPU_NOCR }, -}; - -const struct rcar_gen4_sysc_info r8a779f0_sysc_info __initconst = { - .areas = r8a779f0_areas, - .num_areas = ARRAY_SIZE(r8a779f0_areas), -}; diff --git a/drivers/soc/renesas/r8a779g0-sysc.c b/drivers/soc/renesas/r8a779g0-sysc.c deleted file mode 100644 index b932eba1b804..000000000000 --- a/drivers/soc/renesas/r8a779g0-sysc.c +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Renesas R-Car V4H System Controller - * - * Copyright (C) 2022 Renesas Electronics Corp. - */ - -#include <linux/bits.h> -#include <linux/clk/renesas.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/iopoll.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/of_address.h> -#include <linux/pm_domain.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/types.h> - -#include <dt-bindings/power/r8a779g0-sysc.h> - -#include "rcar-gen4-sysc.h" - -static struct rcar_gen4_sysc_area r8a779g0_areas[] __initdata = { - { "always-on", R8A779G0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, - { "a3e0", R8A779G0_PD_A3E0, R8A779G0_PD_ALWAYS_ON, PD_SCU }, - { "a2e0d0", R8A779G0_PD_A2E0D0, R8A779G0_PD_A3E0, PD_SCU }, - { "a2e0d1", R8A779G0_PD_A2E0D1, R8A779G0_PD_A3E0, PD_SCU }, - { "a1e0d0c0", R8A779G0_PD_A1E0D0C0, R8A779G0_PD_A2E0D0, PD_CPU_NOCR }, - { "a1e0d0c1", R8A779G0_PD_A1E0D0C1, R8A779G0_PD_A2E0D0, PD_CPU_NOCR }, - { "a1e0d1c0", R8A779G0_PD_A1E0D1C0, R8A779G0_PD_A2E0D1, PD_CPU_NOCR }, - { "a1e0d1c1", R8A779G0_PD_A1E0D1C1, R8A779G0_PD_A2E0D1, PD_CPU_NOCR }, - { "a33dga", R8A779G0_PD_A33DGA, R8A779G0_PD_ALWAYS_ON }, - { "a23dgb", R8A779G0_PD_A23DGB, R8A779G0_PD_A33DGA }, - { "a3vip0", R8A779G0_PD_A3VIP0, R8A779G0_PD_ALWAYS_ON }, - { "a3vip1", R8A779G0_PD_A3VIP1, R8A779G0_PD_ALWAYS_ON }, - { "a3vip2", R8A779G0_PD_A3VIP2, R8A779G0_PD_ALWAYS_ON }, - { "a3dul", R8A779G0_PD_A3DUL, R8A779G0_PD_ALWAYS_ON }, - { "a3isp0", R8A779G0_PD_A3ISP0, R8A779G0_PD_ALWAYS_ON }, - { "a3isp1", R8A779G0_PD_A3ISP1, R8A779G0_PD_ALWAYS_ON }, - { "a3ir", R8A779G0_PD_A3IR, R8A779G0_PD_ALWAYS_ON }, - { "a2cn0", R8A779G0_PD_A2CN0, R8A779G0_PD_A3IR }, - { "a1cnn0", R8A779G0_PD_A1CNN0, R8A779G0_PD_A2CN0 }, - { "a1dsp0", R8A779G0_PD_A1DSP0, R8A779G0_PD_A2CN0 }, - { "a1dsp1", R8A779G0_PD_A1DSP1, R8A779G0_PD_A2CN0 }, - { "a1dsp2", R8A779G0_PD_A1DSP2, R8A779G0_PD_A2CN0 }, - { "a1dsp3", R8A779G0_PD_A1DSP3, R8A779G0_PD_A2CN0 }, - { "a2imp01", R8A779G0_PD_A2IMP01, R8A779G0_PD_A3IR }, - { "a2imp23", R8A779G0_PD_A2IMP23, R8A779G0_PD_A3IR }, - { "a2psc", R8A779G0_PD_A2PSC, R8A779G0_PD_A3IR }, - { "a2dma", R8A779G0_PD_A2DMA, R8A779G0_PD_A3IR }, - { "a2cv0", R8A779G0_PD_A2CV0, R8A779G0_PD_A3IR }, - { "a2cv1", R8A779G0_PD_A2CV1, R8A779G0_PD_A3IR }, - { "a2cv2", R8A779G0_PD_A2CV2, R8A779G0_PD_A3IR }, - { "a2cv3", R8A779G0_PD_A2CV3, R8A779G0_PD_A3IR }, -}; - -const struct rcar_gen4_sysc_info r8a779g0_sysc_info __initconst = { - .areas = r8a779g0_areas, - .num_areas = ARRAY_SIZE(r8a779g0_areas), -}; diff --git a/drivers/soc/renesas/rcar-gen4-sysc.c b/drivers/soc/renesas/rcar-gen4-sysc.c deleted file mode 100644 index 9e5e6e077abc..000000000000 --- a/drivers/soc/renesas/rcar-gen4-sysc.c +++ /dev/null @@ -1,379 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * R-Car Gen4 SYSC Power management support - * - * Copyright (C) 2021 Renesas Electronics Corp. - */ - -#include <linux/bits.h> -#include <linux/clk/renesas.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/iopoll.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/of_address.h> -#include <linux/pm_domain.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/types.h> - -#include "rcar-gen4-sysc.h" - -/* SYSC Common */ -#define SYSCSR 0x000 /* SYSC Status Register */ -#define SYSCPONSR(x) (0x800 + ((x) * 0x4)) /* Power-ON Status Register 0 */ -#define SYSCPOFFSR(x) (0x808 + ((x) * 0x4)) /* Power-OFF Status Register */ -#define SYSCISCR(x) (0x810 + ((x) * 0x4)) /* Interrupt Status/Clear Register */ -#define SYSCIER(x) (0x820 + ((x) * 0x4)) /* Interrupt Enable Register */ -#define SYSCIMR(x) (0x830 + ((x) * 0x4)) /* Interrupt Mask Register */ - -/* Power Domain Registers */ -#define PDRSR(n) (0x1000 + ((n) * 0x40)) -#define PDRONCR(n) (0x1004 + ((n) * 0x40)) -#define PDROFFCR(n) (0x1008 + ((n) * 0x40)) -#define PDRESR(n) (0x100C + ((n) * 0x40)) - -/* PWRON/PWROFF */ -#define PWRON_PWROFF BIT(0) /* Power-ON/OFF request */ - -/* PDRESR */ -#define PDRESR_ERR BIT(0) - -/* PDRSR */ -#define PDRSR_OFF BIT(0) /* Power-OFF state */ -#define PDRSR_ON BIT(4) /* Power-ON state */ -#define PDRSR_OFF_STATE BIT(8) /* Processing Power-OFF sequence */ -#define PDRSR_ON_STATE BIT(12) /* Processing Power-ON sequence */ - -#define SYSCSR_BUSY GENMASK(1, 0) /* All bit sets is not busy */ - -#define SYSCSR_TIMEOUT 10000 -#define SYSCSR_DELAY_US 10 - -#define PDRESR_RETRIES 1000 -#define PDRESR_DELAY_US 10 - -#define SYSCISR_TIMEOUT 10000 -#define SYSCISR_DELAY_US 10 - -#define RCAR_GEN4_PD_ALWAYS_ON 64 -#define NUM_DOMAINS_EACH_REG BITS_PER_TYPE(u32) - -static void __iomem *rcar_gen4_sysc_base; -static DEFINE_SPINLOCK(rcar_gen4_sysc_lock); /* SMP CPUs + I/O devices */ - -static int rcar_gen4_sysc_pwr_on_off(u8 pdr, bool on) -{ - unsigned int reg_offs; - u32 val; - int ret; - - if (on) - reg_offs = PDRONCR(pdr); - else - reg_offs = PDROFFCR(pdr); - - /* Wait until SYSC is ready to accept a power request */ - ret = readl_poll_timeout_atomic(rcar_gen4_sysc_base + SYSCSR, val, - (val & SYSCSR_BUSY) == SYSCSR_BUSY, - SYSCSR_DELAY_US, SYSCSR_TIMEOUT); - if (ret < 0) - return -EAGAIN; - - /* Submit power shutoff or power resume request */ - iowrite32(PWRON_PWROFF, rcar_gen4_sysc_base + reg_offs); - - return 0; -} - -static int clear_irq_flags(unsigned int reg_idx, unsigned int isr_mask) -{ - u32 val; - int ret; - - iowrite32(isr_mask, rcar_gen4_sysc_base + SYSCISCR(reg_idx)); - - ret = readl_poll_timeout_atomic(rcar_gen4_sysc_base + SYSCISCR(reg_idx), - val, !(val & isr_mask), - SYSCISR_DELAY_US, SYSCISR_TIMEOUT); - if (ret < 0) { - pr_err("\n %s : Can not clear IRQ flags in SYSCISCR", __func__); - return -EIO; - } - - return 0; -} - -static int rcar_gen4_sysc_power(u8 pdr, bool on) -{ - unsigned int isr_mask; - unsigned int reg_idx, bit_idx; - unsigned int status; - unsigned long flags; - int ret = 0; - u32 val; - int k; - - spin_lock_irqsave(&rcar_gen4_sysc_lock, flags); - - reg_idx = pdr / NUM_DOMAINS_EACH_REG; - bit_idx = pdr % NUM_DOMAINS_EACH_REG; - - isr_mask = BIT(bit_idx); - - /* - * The interrupt source needs to be enabled, but masked, to prevent the - * CPU from receiving it. - */ - iowrite32(ioread32(rcar_gen4_sysc_base + SYSCIER(reg_idx)) | isr_mask, - rcar_gen4_sysc_base + SYSCIER(reg_idx)); - iowrite32(ioread32(rcar_gen4_sysc_base + SYSCIMR(reg_idx)) | isr_mask, - rcar_gen4_sysc_base + SYSCIMR(reg_idx)); - - ret = clear_irq_flags(reg_idx, isr_mask); - if (ret) - goto out; - - /* Submit power shutoff or resume request until it was accepted */ - for (k = 0; k < PDRESR_RETRIES; k++) { - ret = rcar_gen4_sysc_pwr_on_off(pdr, on); - if (ret) - goto out; - - status = ioread32(rcar_gen4_sysc_base + PDRESR(pdr)); - if (!(status & PDRESR_ERR)) - break; - - udelay(PDRESR_DELAY_US); - } - - if (k == PDRESR_RETRIES) { - ret = -EIO; - goto out; - } - - /* Wait until the power shutoff or resume request has completed * */ - ret = readl_poll_timeout_atomic(rcar_gen4_sysc_base + SYSCISCR(reg_idx), - val, (val & isr_mask), - SYSCISR_DELAY_US, SYSCISR_TIMEOUT); - if (ret < 0) { - ret = -EIO; - goto out; - } - - /* Clear interrupt flags */ - ret = clear_irq_flags(reg_idx, isr_mask); - if (ret) - goto out; - - out: - spin_unlock_irqrestore(&rcar_gen4_sysc_lock, flags); - - pr_debug("sysc power %s domain %d: %08x -> %d\n", on ? "on" : "off", - pdr, ioread32(rcar_gen4_sysc_base + SYSCISCR(reg_idx)), ret); - return ret; -} - -static bool rcar_gen4_sysc_power_is_off(u8 pdr) -{ - unsigned int st; - - st = ioread32(rcar_gen4_sysc_base + PDRSR(pdr)); - - if (st & PDRSR_OFF) - return true; - - return false; -} - -struct rcar_gen4_sysc_pd { - struct generic_pm_domain genpd; - u8 pdr; - unsigned int flags; - char name[]; -}; - -static inline struct rcar_gen4_sysc_pd *to_rcar_gen4_pd(struct generic_pm_domain *d) -{ - return container_of(d, struct rcar_gen4_sysc_pd, genpd); -} - -static int rcar_gen4_sysc_pd_power_off(struct generic_pm_domain *genpd) -{ - struct rcar_gen4_sysc_pd *pd = to_rcar_gen4_pd(genpd); - - pr_debug("%s: %s\n", __func__, genpd->name); - return rcar_gen4_sysc_power(pd->pdr, false); -} - -static int rcar_gen4_sysc_pd_power_on(struct generic_pm_domain *genpd) -{ - struct rcar_gen4_sysc_pd *pd = to_rcar_gen4_pd(genpd); - - pr_debug("%s: %s\n", __func__, genpd->name); - return rcar_gen4_sysc_power(pd->pdr, true); -} - -static int __init rcar_gen4_sysc_pd_setup(struct rcar_gen4_sysc_pd *pd) -{ - struct generic_pm_domain *genpd = &pd->genpd; - const char *name = pd->genpd.name; - int error; - - if (pd->flags & PD_CPU) { - /* - * This domain contains a CPU core and therefore it should - * only be turned off if the CPU is not in use. - */ - pr_debug("PM domain %s contains %s\n", name, "CPU"); - genpd->flags |= GENPD_FLAG_ALWAYS_ON; - } else if (pd->flags & PD_SCU) { - /* - * This domain contains an SCU and cache-controller, and - * therefore it should only be turned off if the CPU cores are - * not in use. - */ - pr_debug("PM domain %s contains %s\n", name, "SCU"); - genpd->flags |= GENPD_FLAG_ALWAYS_ON; - } else if (pd->flags & PD_NO_CR) { - /* - * This domain cannot be turned off. - */ - genpd->flags |= GENPD_FLAG_ALWAYS_ON; - } - - if (!(pd->flags & (PD_CPU | PD_SCU))) { - /* Enable Clock Domain for I/O devices */ - genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP; - genpd->attach_dev = cpg_mssr_attach_dev; - genpd->detach_dev = cpg_mssr_detach_dev; - } - - genpd->power_off = rcar_gen4_sysc_pd_power_off; - genpd->power_on = rcar_gen4_sysc_pd_power_on; - - if (pd->flags & (PD_CPU | PD_NO_CR)) { - /* Skip CPUs (handled by SMP code) and areas without control */ - pr_debug("%s: Not touching %s\n", __func__, genpd->name); - goto finalize; - } - - if (!rcar_gen4_sysc_power_is_off(pd->pdr)) { - pr_debug("%s: %s is already powered\n", __func__, genpd->name); - goto finalize; - } - - rcar_gen4_sysc_power(pd->pdr, true); - -finalize: - error = pm_genpd_init(genpd, &simple_qos_governor, false); - if (error) - pr_err("Failed to init PM domain %s: %d\n", name, error); - - return error; -} - -static const struct of_device_id rcar_gen4_sysc_matches[] __initconst = { -#ifdef CONFIG_SYSC_R8A779A0 - { .compatible = "renesas,r8a779a0-sysc", .data = &r8a779a0_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A779F0 - { .compatible = "renesas,r8a779f0-sysc", .data = &r8a779f0_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A779G0 - { .compatible = "renesas,r8a779g0-sysc", .data = &r8a779g0_sysc_info }, -#endif - { /* sentinel */ } -}; - -struct rcar_gen4_pm_domains { - struct genpd_onecell_data onecell_data; - struct generic_pm_domain *domains[RCAR_GEN4_PD_ALWAYS_ON + 1]; -}; - -static struct genpd_onecell_data *rcar_gen4_sysc_onecell_data; - -static int __init rcar_gen4_sysc_pd_init(void) -{ - const struct rcar_gen4_sysc_info *info; - const struct of_device_id *match; - struct rcar_gen4_pm_domains *domains; - struct device_node *np; - void __iomem *base; - unsigned int i; - int error; - - np = of_find_matching_node_and_match(NULL, rcar_gen4_sysc_matches, &match); - if (!np) - return -ENODEV; - - info = match->data; - - base = of_iomap(np, 0); - if (!base) { - pr_warn("%pOF: Cannot map regs\n", np); - error = -ENOMEM; - goto out_put; - } - - rcar_gen4_sysc_base = base; - - domains = kzalloc(sizeof(*domains), GFP_KERNEL); - if (!domains) { - error = -ENOMEM; - goto out_put; - } - - domains->onecell_data.domains = domains->domains; - domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains); - rcar_gen4_sysc_onecell_data = &domains->onecell_data; - - for (i = 0; i < info->num_areas; i++) { - const struct rcar_gen4_sysc_area *area = &info->areas[i]; - struct rcar_gen4_sysc_pd *pd; - size_t n; - - if (!area->name) { - /* Skip NULLified area */ - continue; - } - - n = strlen(area->name) + 1; - pd = kzalloc(sizeof(*pd) + n, GFP_KERNEL); - if (!pd) { - error = -ENOMEM; - goto out_put; - } - - memcpy(pd->name, area->name, n); - pd->genpd.name = pd->name; - pd->pdr = area->pdr; - pd->flags = area->flags; - - error = rcar_gen4_sysc_pd_setup(pd); - if (error) - goto out_put; - - domains->domains[area->pdr] = &pd->genpd; - - if (area->parent < 0) - continue; - - error = pm_genpd_add_subdomain(domains->domains[area->parent], - &pd->genpd); - if (error) { - pr_warn("Failed to add PM subdomain %s to parent %u\n", - area->name, area->parent); - goto out_put; - } - } - - error = of_genpd_add_provider_onecell(np, &domains->onecell_data); - -out_put: - of_node_put(np); - return error; -} -early_initcall(rcar_gen4_sysc_pd_init); diff --git a/drivers/soc/renesas/rcar-gen4-sysc.h b/drivers/soc/renesas/rcar-gen4-sysc.h deleted file mode 100644 index 388cfa8f8f9f..000000000000 --- a/drivers/soc/renesas/rcar-gen4-sysc.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * R-Car Gen4 System Controller - * - * Copyright (C) 2021 Renesas Electronics Corp. - */ -#ifndef __SOC_RENESAS_RCAR_GEN4_SYSC_H__ -#define __SOC_RENESAS_RCAR_GEN4_SYSC_H__ - -#include <linux/types.h> - -/* - * Power Domain flags - */ -#define PD_CPU BIT(0) /* Area contains main CPU core */ -#define PD_SCU BIT(1) /* Area contains SCU and L2 cache */ -#define PD_NO_CR BIT(2) /* Area lacks PWR{ON,OFF}CR registers */ - -#define PD_CPU_NOCR (PD_CPU | PD_NO_CR) /* CPU area lacks CR */ -#define PD_ALWAYS_ON PD_NO_CR /* Always-on area */ - -/* - * Description of a Power Area - */ -struct rcar_gen4_sysc_area { - const char *name; - u8 pdr; /* PDRn */ - s8 parent; /* -1 if none */ - u8 flags; /* See PD_* */ -}; - -/* - * SoC-specific Power Area Description - */ -struct rcar_gen4_sysc_info { - const struct rcar_gen4_sysc_area *areas; - unsigned int num_areas; -}; - -extern const struct rcar_gen4_sysc_info r8a779a0_sysc_info; -extern const struct rcar_gen4_sysc_info r8a779f0_sysc_info; -extern const struct rcar_gen4_sysc_info r8a779g0_sysc_info; - -#endif /* __SOC_RENESAS_RCAR_GEN4_SYSC_H__ */ diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c deleted file mode 100644 index eed47696e825..000000000000 --- a/drivers/soc/renesas/rcar-sysc.c +++ /dev/null @@ -1,494 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * R-Car SYSC Power management support - * - * Copyright (C) 2014 Magnus Damm - * Copyright (C) 2015-2017 Glider bvba - */ - -#include <linux/clk/renesas.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/mm.h> -#include <linux/of_address.h> -#include <linux/pm_domain.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/io.h> -#include <linux/iopoll.h> -#include <linux/soc/renesas/rcar-sysc.h> - -#include "rcar-sysc.h" - -/* SYSC Common */ -#define SYSCSR 0x00 /* SYSC Status Register */ -#define SYSCISR 0x04 /* Interrupt Status Register */ -#define SYSCISCR 0x08 /* Interrupt Status Clear Register */ -#define SYSCIER 0x0c /* Interrupt Enable Register */ -#define SYSCIMR 0x10 /* Interrupt Mask Register */ - -/* SYSC Status Register */ -#define SYSCSR_PONENB 1 /* Ready for power resume requests */ -#define SYSCSR_POFFENB 0 /* Ready for power shutoff requests */ - -/* - * Power Control Register Offsets inside the register block for each domain - * Note: The "CR" registers for ARM cores exist on H1 only - * Use WFI to power off, CPG/APMU to resume ARM cores on R-Car Gen2 - * Use PSCI on R-Car Gen3 - */ -#define PWRSR_OFFS 0x00 /* Power Status Register */ -#define PWROFFCR_OFFS 0x04 /* Power Shutoff Control Register */ -#define PWROFFSR_OFFS 0x08 /* Power Shutoff Status Register */ -#define PWRONCR_OFFS 0x0c /* Power Resume Control Register */ -#define PWRONSR_OFFS 0x10 /* Power Resume Status Register */ -#define PWRER_OFFS 0x14 /* Power Shutoff/Resume Error */ - - -#define SYSCSR_TIMEOUT 100 -#define SYSCSR_DELAY_US 1 - -#define PWRER_RETRIES 100 -#define PWRER_DELAY_US 1 - -#define SYSCISR_TIMEOUT 1000 -#define SYSCISR_DELAY_US 1 - -#define RCAR_PD_ALWAYS_ON 32 /* Always-on power area */ - -struct rcar_sysc_ch { - u16 chan_offs; - u8 chan_bit; - u8 isr_bit; -}; - -static void __iomem *rcar_sysc_base; -static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */ -static u32 rcar_sysc_extmask_offs, rcar_sysc_extmask_val; - -static int rcar_sysc_pwr_on_off(const struct rcar_sysc_ch *sysc_ch, bool on) -{ - unsigned int sr_bit, reg_offs; - u32 val; - int ret; - - if (on) { - sr_bit = SYSCSR_PONENB; - reg_offs = PWRONCR_OFFS; - } else { - sr_bit = SYSCSR_POFFENB; - reg_offs = PWROFFCR_OFFS; - } - - /* Wait until SYSC is ready to accept a power request */ - ret = readl_poll_timeout_atomic(rcar_sysc_base + SYSCSR, val, - val & BIT(sr_bit), SYSCSR_DELAY_US, - SYSCSR_TIMEOUT); - if (ret) - return -EAGAIN; - - /* Submit power shutoff or power resume request */ - iowrite32(BIT(sysc_ch->chan_bit), - rcar_sysc_base + sysc_ch->chan_offs + reg_offs); - - return 0; -} - -static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on) -{ - unsigned int isr_mask = BIT(sysc_ch->isr_bit); - unsigned int chan_mask = BIT(sysc_ch->chan_bit); - unsigned int status, k; - unsigned long flags; - int ret; - - spin_lock_irqsave(&rcar_sysc_lock, flags); - - /* - * Mask external power requests for CPU or 3DG domains - */ - if (rcar_sysc_extmask_val) { - iowrite32(rcar_sysc_extmask_val, - rcar_sysc_base + rcar_sysc_extmask_offs); - } - - /* - * The interrupt source needs to be enabled, but masked, to prevent the - * CPU from receiving it. - */ - iowrite32(ioread32(rcar_sysc_base + SYSCIMR) | isr_mask, - rcar_sysc_base + SYSCIMR); - iowrite32(ioread32(rcar_sysc_base + SYSCIER) | isr_mask, - rcar_sysc_base + SYSCIER); - - iowrite32(isr_mask, rcar_sysc_base + SYSCISCR); - - /* Submit power shutoff or resume request until it was accepted */ - for (k = 0; k < PWRER_RETRIES; k++) { - ret = rcar_sysc_pwr_on_off(sysc_ch, on); - if (ret) - goto out; - - status = ioread32(rcar_sysc_base + - sysc_ch->chan_offs + PWRER_OFFS); - if (!(status & chan_mask)) - break; - - udelay(PWRER_DELAY_US); - } - - if (k == PWRER_RETRIES) { - ret = -EIO; - goto out; - } - - /* Wait until the power shutoff or resume request has completed * */ - ret = readl_poll_timeout_atomic(rcar_sysc_base + SYSCISR, status, - status & isr_mask, SYSCISR_DELAY_US, - SYSCISR_TIMEOUT); - if (ret) - ret = -EIO; - - iowrite32(isr_mask, rcar_sysc_base + SYSCISCR); - - out: - if (rcar_sysc_extmask_val) - iowrite32(0, rcar_sysc_base + rcar_sysc_extmask_offs); - - spin_unlock_irqrestore(&rcar_sysc_lock, flags); - - pr_debug("sysc power %s domain %d: %08x -> %d\n", on ? "on" : "off", - sysc_ch->isr_bit, ioread32(rcar_sysc_base + SYSCISR), ret); - return ret; -} - -static bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch) -{ - unsigned int st; - - st = ioread32(rcar_sysc_base + sysc_ch->chan_offs + PWRSR_OFFS); - if (st & BIT(sysc_ch->chan_bit)) - return true; - - return false; -} - -struct rcar_sysc_pd { - struct generic_pm_domain genpd; - struct rcar_sysc_ch ch; - unsigned int flags; - char name[]; -}; - -static inline struct rcar_sysc_pd *to_rcar_pd(struct generic_pm_domain *d) -{ - return container_of(d, struct rcar_sysc_pd, genpd); -} - -static int rcar_sysc_pd_power_off(struct generic_pm_domain *genpd) -{ - struct rcar_sysc_pd *pd = to_rcar_pd(genpd); - - pr_debug("%s: %s\n", __func__, genpd->name); - return rcar_sysc_power(&pd->ch, false); -} - -static int rcar_sysc_pd_power_on(struct generic_pm_domain *genpd) -{ - struct rcar_sysc_pd *pd = to_rcar_pd(genpd); - - pr_debug("%s: %s\n", __func__, genpd->name); - return rcar_sysc_power(&pd->ch, true); -} - -static bool has_cpg_mstp; - -static int __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) -{ - struct generic_pm_domain *genpd = &pd->genpd; - const char *name = pd->genpd.name; - int error; - - if (pd->flags & PD_CPU) { - /* - * This domain contains a CPU core and therefore it should - * only be turned off if the CPU is not in use. - */ - pr_debug("PM domain %s contains %s\n", name, "CPU"); - genpd->flags |= GENPD_FLAG_ALWAYS_ON; - } else if (pd->flags & PD_SCU) { - /* - * This domain contains an SCU and cache-controller, and - * therefore it should only be turned off if the CPU cores are - * not in use. - */ - pr_debug("PM domain %s contains %s\n", name, "SCU"); - genpd->flags |= GENPD_FLAG_ALWAYS_ON; - } else if (pd->flags & PD_NO_CR) { - /* - * This domain cannot be turned off. - */ - genpd->flags |= GENPD_FLAG_ALWAYS_ON; - } - - if (!(pd->flags & (PD_CPU | PD_SCU))) { - /* Enable Clock Domain for I/O devices */ - genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP; - if (has_cpg_mstp) { - genpd->attach_dev = cpg_mstp_attach_dev; - genpd->detach_dev = cpg_mstp_detach_dev; - } else { - genpd->attach_dev = cpg_mssr_attach_dev; - genpd->detach_dev = cpg_mssr_detach_dev; - } - } - - genpd->power_off = rcar_sysc_pd_power_off; - genpd->power_on = rcar_sysc_pd_power_on; - - if (pd->flags & (PD_CPU | PD_NO_CR)) { - /* Skip CPUs (handled by SMP code) and areas without control */ - pr_debug("%s: Not touching %s\n", __func__, genpd->name); - goto finalize; - } - - if (!rcar_sysc_power_is_off(&pd->ch)) { - pr_debug("%s: %s is already powered\n", __func__, genpd->name); - goto finalize; - } - - rcar_sysc_power(&pd->ch, true); - -finalize: - error = pm_genpd_init(genpd, &simple_qos_governor, false); - if (error) - pr_err("Failed to init PM domain %s: %d\n", name, error); - - return error; -} - -static const struct of_device_id rcar_sysc_matches[] __initconst = { -#ifdef CONFIG_SYSC_R8A7742 - { .compatible = "renesas,r8a7742-sysc", .data = &r8a7742_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A7743 - { .compatible = "renesas,r8a7743-sysc", .data = &r8a7743_sysc_info }, - /* RZ/G1N is identical to RZ/G2M w.r.t. power domains. */ - { .compatible = "renesas,r8a7744-sysc", .data = &r8a7743_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A7745 - { .compatible = "renesas,r8a7745-sysc", .data = &r8a7745_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A77470 - { .compatible = "renesas,r8a77470-sysc", .data = &r8a77470_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A774A1 - { .compatible = "renesas,r8a774a1-sysc", .data = &r8a774a1_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A774B1 - { .compatible = "renesas,r8a774b1-sysc", .data = &r8a774b1_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A774C0 - { .compatible = "renesas,r8a774c0-sysc", .data = &r8a774c0_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A774E1 - { .compatible = "renesas,r8a774e1-sysc", .data = &r8a774e1_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A7779 - { .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A7790 - { .compatible = "renesas,r8a7790-sysc", .data = &r8a7790_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A7791 - { .compatible = "renesas,r8a7791-sysc", .data = &r8a7791_sysc_info }, - /* R-Car M2-N is identical to R-Car M2-W w.r.t. power domains. */ - { .compatible = "renesas,r8a7793-sysc", .data = &r8a7791_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A7792 - { .compatible = "renesas,r8a7792-sysc", .data = &r8a7792_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A7794 - { .compatible = "renesas,r8a7794-sysc", .data = &r8a7794_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A7795 - { .compatible = "renesas,r8a7795-sysc", .data = &r8a7795_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A77960 - { .compatible = "renesas,r8a7796-sysc", .data = &r8a77960_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A77961 - { .compatible = "renesas,r8a77961-sysc", .data = &r8a77961_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A77965 - { .compatible = "renesas,r8a77965-sysc", .data = &r8a77965_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A77970 - { .compatible = "renesas,r8a77970-sysc", .data = &r8a77970_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A77980 - { .compatible = "renesas,r8a77980-sysc", .data = &r8a77980_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A77990 - { .compatible = "renesas,r8a77990-sysc", .data = &r8a77990_sysc_info }, -#endif -#ifdef CONFIG_SYSC_R8A77995 - { .compatible = "renesas,r8a77995-sysc", .data = &r8a77995_sysc_info }, -#endif - { /* sentinel */ } -}; - -struct rcar_pm_domains { - struct genpd_onecell_data onecell_data; - struct generic_pm_domain *domains[RCAR_PD_ALWAYS_ON + 1]; -}; - -static struct genpd_onecell_data *rcar_sysc_onecell_data; - -static int __init rcar_sysc_pd_init(void) -{ - const struct rcar_sysc_info *info; - const struct of_device_id *match; - struct rcar_pm_domains *domains; - struct device_node *np; - void __iomem *base; - unsigned int i; - int error; - - np = of_find_matching_node_and_match(NULL, rcar_sysc_matches, &match); - if (!np) - return -ENODEV; - - info = match->data; - - if (info->init) { - error = info->init(); - if (error) - goto out_put; - } - - has_cpg_mstp = of_find_compatible_node(NULL, NULL, - "renesas,cpg-mstp-clocks"); - - base = of_iomap(np, 0); - if (!base) { - pr_warn("%pOF: Cannot map regs\n", np); - error = -ENOMEM; - goto out_put; - } - - rcar_sysc_base = base; - - /* Optional External Request Mask Register */ - rcar_sysc_extmask_offs = info->extmask_offs; - rcar_sysc_extmask_val = info->extmask_val; - - domains = kzalloc(sizeof(*domains), GFP_KERNEL); - if (!domains) { - error = -ENOMEM; - goto out_put; - } - - domains->onecell_data.domains = domains->domains; - domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains); - rcar_sysc_onecell_data = &domains->onecell_data; - - for (i = 0; i < info->num_areas; i++) { - const struct rcar_sysc_area *area = &info->areas[i]; - struct rcar_sysc_pd *pd; - size_t n; - - if (!area->name) { - /* Skip NULLified area */ - continue; - } - - n = strlen(area->name) + 1; - pd = kzalloc(sizeof(*pd) + n, GFP_KERNEL); - if (!pd) { - error = -ENOMEM; - goto out_put; - } - - memcpy(pd->name, area->name, n); - pd->genpd.name = pd->name; - pd->ch.chan_offs = area->chan_offs; - pd->ch.chan_bit = area->chan_bit; - pd->ch.isr_bit = area->isr_bit; - pd->flags = area->flags; - - error = rcar_sysc_pd_setup(pd); - if (error) - goto out_put; - - domains->domains[area->isr_bit] = &pd->genpd; - - if (area->parent < 0) - continue; - - error = pm_genpd_add_subdomain(domains->domains[area->parent], - &pd->genpd); - if (error) { - pr_warn("Failed to add PM subdomain %s to parent %u\n", - area->name, area->parent); - goto out_put; - } - } - - error = of_genpd_add_provider_onecell(np, &domains->onecell_data); - if (!error) - fwnode_dev_initialized(of_fwnode_handle(np), true); - -out_put: - of_node_put(np); - return error; -} -early_initcall(rcar_sysc_pd_init); - -void __init rcar_sysc_nullify(struct rcar_sysc_area *areas, - unsigned int num_areas, u8 id) -{ - unsigned int i; - - for (i = 0; i < num_areas; i++) - if (areas[i].isr_bit == id) { - areas[i].name = NULL; - return; - } -} - -#ifdef CONFIG_ARCH_R8A7779 -static int rcar_sysc_power_cpu(unsigned int idx, bool on) -{ - struct generic_pm_domain *genpd; - struct rcar_sysc_pd *pd; - unsigned int i; - - if (!rcar_sysc_onecell_data) - return -ENODEV; - - for (i = 0; i < rcar_sysc_onecell_data->num_domains; i++) { - genpd = rcar_sysc_onecell_data->domains[i]; - if (!genpd) - continue; - - pd = to_rcar_pd(genpd); - if (!(pd->flags & PD_CPU) || pd->ch.chan_bit != idx) - continue; - - return rcar_sysc_power(&pd->ch, on); - } - - return -ENOENT; -} - -int rcar_sysc_power_down_cpu(unsigned int cpu) -{ - return rcar_sysc_power_cpu(cpu, false); -} - -int rcar_sysc_power_up_cpu(unsigned int cpu) -{ - return rcar_sysc_power_cpu(cpu, true); -} -#endif /* CONFIG_ARCH_R8A7779 */ diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h deleted file mode 100644 index 266c599a0a9b..000000000000 --- a/drivers/soc/renesas/rcar-sysc.h +++ /dev/null @@ -1,82 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Renesas R-Car System Controller - * - * Copyright (C) 2016 Glider bvba - */ -#ifndef __SOC_RENESAS_RCAR_SYSC_H__ -#define __SOC_RENESAS_RCAR_SYSC_H__ - -#include <linux/types.h> - - -/* - * Power Domain flags - */ -#define PD_CPU BIT(0) /* Area contains main CPU core */ -#define PD_SCU BIT(1) /* Area contains SCU and L2 cache */ -#define PD_NO_CR BIT(2) /* Area lacks PWR{ON,OFF}CR registers */ - -#define PD_CPU_CR PD_CPU /* CPU area has CR (R-Car H1) */ -#define PD_CPU_NOCR PD_CPU | PD_NO_CR /* CPU area lacks CR (R-Car Gen2/3) */ -#define PD_ALWAYS_ON PD_NO_CR /* Always-on area */ - - -/* - * Description of a Power Area - */ - -struct rcar_sysc_area { - const char *name; - u16 chan_offs; /* Offset of PWRSR register for this area */ - u8 chan_bit; /* Bit in PWR* (except for PWRUP in PWRSR) */ - u8 isr_bit; /* Bit in SYSCI*R */ - s8 parent; /* -1 if none */ - u8 flags; /* See PD_* */ -}; - - -/* - * SoC-specific Power Area Description - */ - -struct rcar_sysc_info { - int (*init)(void); /* Optional */ - const struct rcar_sysc_area *areas; - unsigned int num_areas; - /* Optional External Request Mask Register */ - u32 extmask_offs; /* SYSCEXTMASK register offset */ - u32 extmask_val; /* SYSCEXTMASK register mask value */ -}; - -extern const struct rcar_sysc_info r8a7742_sysc_info; -extern const struct rcar_sysc_info r8a7743_sysc_info; -extern const struct rcar_sysc_info r8a7745_sysc_info; -extern const struct rcar_sysc_info r8a77470_sysc_info; -extern const struct rcar_sysc_info r8a774a1_sysc_info; -extern const struct rcar_sysc_info r8a774b1_sysc_info; -extern const struct rcar_sysc_info r8a774c0_sysc_info; -extern const struct rcar_sysc_info r8a774e1_sysc_info; -extern const struct rcar_sysc_info r8a7779_sysc_info; -extern const struct rcar_sysc_info r8a7790_sysc_info; -extern const struct rcar_sysc_info r8a7791_sysc_info; -extern const struct rcar_sysc_info r8a7792_sysc_info; -extern const struct rcar_sysc_info r8a7794_sysc_info; -extern struct rcar_sysc_info r8a7795_sysc_info; -extern const struct rcar_sysc_info r8a77960_sysc_info; -extern const struct rcar_sysc_info r8a77961_sysc_info; -extern const struct rcar_sysc_info r8a77965_sysc_info; -extern const struct rcar_sysc_info r8a77970_sysc_info; -extern const struct rcar_sysc_info r8a77980_sysc_info; -extern const struct rcar_sysc_info r8a77990_sysc_info; -extern const struct rcar_sysc_info r8a77995_sysc_info; - - - /* - * Helpers for fixing up power area tables depending on SoC revision - */ - -extern void rcar_sysc_nullify(struct rcar_sysc_area *areas, - unsigned int num_areas, u8 id); - -#endif /* __SOC_RENESAS_RCAR_SYSC_H__ */ diff --git a/drivers/soc/renesas/rmobile-sysc.c b/drivers/soc/renesas/rmobile-sysc.c deleted file mode 100644 index 912daadaa10d..000000000000 --- a/drivers/soc/renesas/rmobile-sysc.c +++ /dev/null @@ -1,343 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * rmobile power management support - * - * Copyright (C) 2012 Renesas Solutions Corp. - * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> - * Copyright (C) 2014 Glider bvba - * - * based on pm-sh7372.c - * Copyright (C) 2011 Magnus Damm - */ -#include <linux/clk/renesas.h> -#include <linux/console.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/iopoll.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/pm.h> -#include <linux/pm_clock.h> -#include <linux/pm_domain.h> -#include <linux/slab.h> - -/* SYSC */ -#define SPDCR 0x08 /* SYS Power Down Control Register */ -#define SWUCR 0x14 /* SYS Wakeup Control Register */ -#define PSTR 0x80 /* Power Status Register */ - -#define PSTR_RETRIES 100 -#define PSTR_DELAY_US 10 - -struct rmobile_pm_domain { - struct generic_pm_domain genpd; - struct dev_power_governor *gov; - int (*suspend)(void); - void __iomem *base; - unsigned int bit_shift; -}; - -static inline -struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d) -{ - return container_of(d, struct rmobile_pm_domain, genpd); -} - -static int rmobile_pd_power_down(struct generic_pm_domain *genpd) -{ - struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd); - unsigned int mask = BIT(rmobile_pd->bit_shift); - u32 val; - - if (rmobile_pd->suspend) { - int ret = rmobile_pd->suspend(); - - if (ret) - return ret; - } - - if (readl(rmobile_pd->base + PSTR) & mask) { - writel(mask, rmobile_pd->base + SPDCR); - - readl_poll_timeout_atomic(rmobile_pd->base + SPDCR, val, - !(val & mask), 0, PSTR_RETRIES); - } - - pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", genpd->name, mask, - readl(rmobile_pd->base + PSTR)); - - return 0; -} - -static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd) -{ - unsigned int val, mask = BIT(rmobile_pd->bit_shift); - int ret = 0; - - if (readl(rmobile_pd->base + PSTR) & mask) - return ret; - - writel(mask, rmobile_pd->base + SWUCR); - - ret = readl_poll_timeout_atomic(rmobile_pd->base + SWUCR, val, - (val & mask), PSTR_DELAY_US, - PSTR_RETRIES * PSTR_DELAY_US); - - pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n", - rmobile_pd->genpd.name, mask, - readl(rmobile_pd->base + PSTR)); - - return ret; -} - -static int rmobile_pd_power_up(struct generic_pm_domain *genpd) -{ - return __rmobile_pd_power_up(to_rmobile_pd(genpd)); -} - -static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) -{ - struct generic_pm_domain *genpd = &rmobile_pd->genpd; - struct dev_power_governor *gov = rmobile_pd->gov; - - genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP; - genpd->attach_dev = cpg_mstp_attach_dev; - genpd->detach_dev = cpg_mstp_detach_dev; - - if (!(genpd->flags & GENPD_FLAG_ALWAYS_ON)) { - genpd->power_off = rmobile_pd_power_down; - genpd->power_on = rmobile_pd_power_up; - __rmobile_pd_power_up(rmobile_pd); - } - - pm_genpd_init(genpd, gov ? : &simple_qos_governor, false); -} - -static int rmobile_pd_suspend_console(void) -{ - /* - * Serial consoles make use of SCIF hardware located in this domain, - * hence keep the power domain on if "no_console_suspend" is set. - */ - return console_suspend_enabled ? 0 : -EBUSY; -} - -enum pd_types { - PD_NORMAL, - PD_CPU, - PD_CONSOLE, - PD_DEBUG, - PD_MEMCTL, -}; - -#define MAX_NUM_SPECIAL_PDS 16 - -static struct special_pd { - struct device_node *pd; - enum pd_types type; -} special_pds[MAX_NUM_SPECIAL_PDS] __initdata; - -static unsigned int num_special_pds __initdata; - -static const struct of_device_id special_ids[] __initconst = { - { .compatible = "arm,coresight-etm3x", .data = (void *)PD_DEBUG }, - { .compatible = "renesas,dbsc-r8a73a4", .data = (void *)PD_MEMCTL, }, - { .compatible = "renesas,dbsc3-r8a7740", .data = (void *)PD_MEMCTL, }, - { .compatible = "renesas,sbsc-sh73a0", .data = (void *)PD_MEMCTL, }, - { /* sentinel */ }, -}; - -static void __init add_special_pd(struct device_node *np, enum pd_types type) -{ - unsigned int i; - struct device_node *pd; - - pd = of_parse_phandle(np, "power-domains", 0); - if (!pd) - return; - - for (i = 0; i < num_special_pds; i++) - if (pd == special_pds[i].pd && type == special_pds[i].type) { - of_node_put(pd); - return; - } - - if (num_special_pds == ARRAY_SIZE(special_pds)) { - pr_warn("Too many special PM domains\n"); - of_node_put(pd); - return; - } - - pr_debug("Special PM domain %pOFn type %d for %pOF\n", pd, type, np); - - special_pds[num_special_pds].pd = pd; - special_pds[num_special_pds].type = type; - num_special_pds++; -} - -static void __init get_special_pds(void) -{ - struct device_node *np; - const struct of_device_id *id; - - /* PM domains containing CPUs */ - for_each_of_cpu_node(np) - add_special_pd(np, PD_CPU); - - /* PM domain containing console */ - if (of_stdout) - add_special_pd(of_stdout, PD_CONSOLE); - - /* PM domains containing other special devices */ - for_each_matching_node_and_match(np, special_ids, &id) - add_special_pd(np, (enum pd_types)id->data); -} - -static void __init put_special_pds(void) -{ - unsigned int i; - - for (i = 0; i < num_special_pds; i++) - of_node_put(special_pds[i].pd); -} - -static enum pd_types __init pd_type(const struct device_node *pd) -{ - unsigned int i; - - for (i = 0; i < num_special_pds; i++) - if (pd == special_pds[i].pd) - return special_pds[i].type; - - return PD_NORMAL; -} - -static void __init rmobile_setup_pm_domain(struct device_node *np, - struct rmobile_pm_domain *pd) -{ - const char *name = pd->genpd.name; - - switch (pd_type(np)) { - case PD_CPU: - /* - * This domain contains the CPU core and therefore it should - * only be turned off if the CPU is not in use. - */ - pr_debug("PM domain %s contains CPU\n", name); - pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON; - break; - - case PD_CONSOLE: - pr_debug("PM domain %s contains serial console\n", name); - pd->gov = &pm_domain_always_on_gov; - pd->suspend = rmobile_pd_suspend_console; - break; - - case PD_DEBUG: - /* - * This domain contains the Coresight-ETM hardware block and - * therefore it should only be turned off if the debug module - * is not in use. - */ - pr_debug("PM domain %s contains Coresight-ETM\n", name); - pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON; - break; - - case PD_MEMCTL: - /* - * This domain contains a memory-controller and therefore it - * should only be turned off if memory is not in use. - */ - pr_debug("PM domain %s contains MEMCTL\n", name); - pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON; - break; - - case PD_NORMAL: - if (pd->bit_shift == ~0) { - /* Top-level always-on domain */ - pr_debug("PM domain %s is always-on domain\n", name); - pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON; - } - break; - } - - rmobile_init_pm_domain(pd); -} - -static int __init rmobile_add_pm_domains(void __iomem *base, - struct device_node *parent, - struct generic_pm_domain *genpd_parent) -{ - struct device_node *np; - - for_each_child_of_node(parent, np) { - struct rmobile_pm_domain *pd; - u32 idx = ~0; - - if (of_property_read_u32(np, "reg", &idx)) { - /* always-on domain */ - } - - pd = kzalloc(sizeof(*pd), GFP_KERNEL); - if (!pd) { - of_node_put(np); - return -ENOMEM; - } - - pd->genpd.name = np->name; - pd->base = base; - pd->bit_shift = idx; - - rmobile_setup_pm_domain(np, pd); - if (genpd_parent) - pm_genpd_add_subdomain(genpd_parent, &pd->genpd); - of_genpd_add_provider_simple(np, &pd->genpd); - - rmobile_add_pm_domains(base, np, &pd->genpd); - } - return 0; -} - -static int __init rmobile_init_pm_domains(void) -{ - struct device_node *np, *pmd; - bool scanned = false; - void __iomem *base; - int ret = 0; - - for_each_compatible_node(np, NULL, "renesas,sysc-rmobile") { - base = of_iomap(np, 0); - if (!base) { - pr_warn("%pOF cannot map reg 0\n", np); - continue; - } - - pmd = of_get_child_by_name(np, "pm-domains"); - if (!pmd) { - iounmap(base); - pr_warn("%pOF lacks pm-domains node\n", np); - continue; - } - - if (!scanned) { - /* Find PM domains containing special blocks */ - get_special_pds(); - scanned = true; - } - - ret = rmobile_add_pm_domains(base, pmd, NULL); - of_node_put(pmd); - if (ret) { - of_node_put(np); - break; - } - - fwnode_dev_initialized(of_fwnode_handle(np), true); - } - - put_special_pds(); - - return ret; -} - -core_initcall(rmobile_init_pm_domains); diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile index 05f31a4e743c..23d414433c8c 100644 --- a/drivers/soc/rockchip/Makefile +++ b/drivers/soc/rockchip/Makefile @@ -4,5 +4,4 @@ # obj-$(CONFIG_ROCKCHIP_GRF) += grf.o obj-$(CONFIG_ROCKCHIP_IODOMAIN) += io-domain.o -obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o obj-$(CONFIG_ROCKCHIP_DTPM) += dtpm.o diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c deleted file mode 100644 index e3de49e671dc..000000000000 --- a/drivers/soc/rockchip/pm_domains.c +++ /dev/null @@ -1,1395 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Rockchip Generic power domain support. - * - * Copyright (c) 2015 ROCKCHIP, Co. Ltd. - */ - -#include <linux/io.h> -#include <linux/iopoll.h> -#include <linux/err.h> -#include <linux/mutex.h> -#include <linux/pm_clock.h> -#include <linux/pm_domain.h> -#include <linux/of_address.h> -#include <linux/of_clk.h> -#include <linux/of_platform.h> -#include <linux/clk.h> -#include <linux/regmap.h> -#include <linux/mfd/syscon.h> -#include <soc/rockchip/pm_domains.h> -#include <dt-bindings/power/px30-power.h> -#include <dt-bindings/power/rockchip,rv1126-power.h> -#include <dt-bindings/power/rk3036-power.h> -#include <dt-bindings/power/rk3066-power.h> -#include <dt-bindings/power/rk3128-power.h> -#include <dt-bindings/power/rk3188-power.h> -#include <dt-bindings/power/rk3228-power.h> -#include <dt-bindings/power/rk3288-power.h> -#include <dt-bindings/power/rk3328-power.h> -#include <dt-bindings/power/rk3366-power.h> -#include <dt-bindings/power/rk3368-power.h> -#include <dt-bindings/power/rk3399-power.h> -#include <dt-bindings/power/rk3568-power.h> -#include <dt-bindings/power/rk3588-power.h> - -struct rockchip_domain_info { - const char *name; - int pwr_mask; - int status_mask; - int req_mask; - int idle_mask; - int ack_mask; - bool active_wakeup; - int pwr_w_mask; - int req_w_mask; - int mem_status_mask; - int repair_status_mask; - u32 pwr_offset; - u32 mem_offset; - u32 req_offset; -}; - -struct rockchip_pmu_info { - u32 pwr_offset; - u32 status_offset; - u32 req_offset; - u32 idle_offset; - u32 ack_offset; - u32 mem_pwr_offset; - u32 chain_status_offset; - u32 mem_status_offset; - u32 repair_status_offset; - - u32 core_pwrcnt_offset; - u32 gpu_pwrcnt_offset; - - unsigned int core_power_transition_time; - unsigned int gpu_power_transition_time; - - int num_domains; - const struct rockchip_domain_info *domain_info; -}; - -#define MAX_QOS_REGS_NUM 5 -#define QOS_PRIORITY 0x08 -#define QOS_MODE 0x0c -#define QOS_BANDWIDTH 0x10 -#define QOS_SATURATION 0x14 -#define QOS_EXTCONTROL 0x18 - -struct rockchip_pm_domain { - struct generic_pm_domain genpd; - const struct rockchip_domain_info *info; - struct rockchip_pmu *pmu; - int num_qos; - struct regmap **qos_regmap; - u32 *qos_save_regs[MAX_QOS_REGS_NUM]; - int num_clks; - struct clk_bulk_data *clks; -}; - -struct rockchip_pmu { - struct device *dev; - struct regmap *regmap; - const struct rockchip_pmu_info *info; - struct mutex mutex; /* mutex lock for pmu */ - struct genpd_onecell_data genpd_data; - struct generic_pm_domain *domains[]; -}; - -#define to_rockchip_pd(gpd) container_of(gpd, struct rockchip_pm_domain, genpd) - -#define DOMAIN(_name, pwr, status, req, idle, ack, wakeup) \ -{ \ - .name = _name, \ - .pwr_mask = (pwr), \ - .status_mask = (status), \ - .req_mask = (req), \ - .idle_mask = (idle), \ - .ack_mask = (ack), \ - .active_wakeup = (wakeup), \ -} - -#define DOMAIN_M(_name, pwr, status, req, idle, ack, wakeup) \ -{ \ - .name = _name, \ - .pwr_w_mask = (pwr) << 16, \ - .pwr_mask = (pwr), \ - .status_mask = (status), \ - .req_w_mask = (req) << 16, \ - .req_mask = (req), \ - .idle_mask = (idle), \ - .ack_mask = (ack), \ - .active_wakeup = wakeup, \ -} - -#define DOMAIN_M_O_R(_name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, ack, wakeup) \ -{ \ - .name = _name, \ - .pwr_offset = p_offset, \ - .pwr_w_mask = (pwr) << 16, \ - .pwr_mask = (pwr), \ - .status_mask = (status), \ - .mem_offset = m_offset, \ - .mem_status_mask = (m_status), \ - .repair_status_mask = (r_status), \ - .req_offset = r_offset, \ - .req_w_mask = (req) << 16, \ - .req_mask = (req), \ - .idle_mask = (idle), \ - .ack_mask = (ack), \ - .active_wakeup = wakeup, \ -} - -#define DOMAIN_RK3036(_name, req, ack, idle, wakeup) \ -{ \ - .name = _name, \ - .req_mask = (req), \ - .req_w_mask = (req) << 16, \ - .ack_mask = (ack), \ - .idle_mask = (idle), \ - .active_wakeup = wakeup, \ -} - -#define DOMAIN_PX30(name, pwr, status, req, wakeup) \ - DOMAIN_M(name, pwr, status, req, (req) << 16, req, wakeup) - -#define DOMAIN_RV1126(name, pwr, req, idle, wakeup) \ - DOMAIN_M(name, pwr, pwr, req, idle, idle, wakeup) - -#define DOMAIN_RK3288(name, pwr, status, req, wakeup) \ - DOMAIN(name, pwr, status, req, req, (req) << 16, wakeup) - -#define DOMAIN_RK3328(name, pwr, status, req, wakeup) \ - DOMAIN_M(name, pwr, pwr, req, (req) << 10, req, wakeup) - -#define DOMAIN_RK3368(name, pwr, status, req, wakeup) \ - DOMAIN(name, pwr, status, req, (req) << 16, req, wakeup) - -#define DOMAIN_RK3399(name, pwr, status, req, wakeup) \ - DOMAIN(name, pwr, status, req, req, req, wakeup) - -#define DOMAIN_RK3568(name, pwr, req, wakeup) \ - DOMAIN_M(name, pwr, pwr, req, req, req, wakeup) - -/* - * Dynamic Memory Controller may need to coordinate with us -- see - * rockchip_pmu_block(). - * - * dmc_pmu_mutex protects registration-time races, so DMC driver doesn't try to - * block() while we're initializing the PMU. - */ -static DEFINE_MUTEX(dmc_pmu_mutex); -static struct rockchip_pmu *dmc_pmu; - -/* - * Block PMU transitions and make sure they don't interfere with ARM Trusted - * Firmware operations. There are two conflicts, noted in the comments below. - * - * Caller must unblock PMU transitions via rockchip_pmu_unblock(). - */ -int rockchip_pmu_block(void) -{ - struct rockchip_pmu *pmu; - struct generic_pm_domain *genpd; - struct rockchip_pm_domain *pd; - int i, ret; - - mutex_lock(&dmc_pmu_mutex); - - /* No PMU (yet)? Then we just block rockchip_pmu_probe(). */ - if (!dmc_pmu) - return 0; - pmu = dmc_pmu; - - /* - * mutex blocks all idle transitions: we can't touch the - * PMU_BUS_IDLE_REQ (our ".idle_offset") register while ARM Trusted - * Firmware might be using it. - */ - mutex_lock(&pmu->mutex); - - /* - * Power domain clocks: Per Rockchip, we *must* keep certain clocks - * enabled for the duration of power-domain transitions. Most - * transitions are handled by this driver, but some cases (in - * particular, DRAM DVFS / memory-controller idle) must be handled by - * firmware. Firmware can handle most clock management via a special - * "ungate" register (PMU_CRU_GATEDIS_CON0), but unfortunately, this - * doesn't handle PLLs. We can assist this transition by doing the - * clock management on behalf of firmware. - */ - for (i = 0; i < pmu->genpd_data.num_domains; i++) { - genpd = pmu->genpd_data.domains[i]; - if (genpd) { - pd = to_rockchip_pd(genpd); - ret = clk_bulk_enable(pd->num_clks, pd->clks); - if (ret < 0) { - dev_err(pmu->dev, - "failed to enable clks for domain '%s': %d\n", - genpd->name, ret); - goto err; - } - } - } - - return 0; - -err: - for (i = i - 1; i >= 0; i--) { - genpd = pmu->genpd_data.domains[i]; - if (genpd) { - pd = to_rockchip_pd(genpd); - clk_bulk_disable(pd->num_clks, pd->clks); - } - } - mutex_unlock(&pmu->mutex); - mutex_unlock(&dmc_pmu_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(rockchip_pmu_block); - -/* Unblock PMU transitions. */ -void rockchip_pmu_unblock(void) -{ - struct rockchip_pmu *pmu; - struct generic_pm_domain *genpd; - struct rockchip_pm_domain *pd; - int i; - - if (dmc_pmu) { - pmu = dmc_pmu; - for (i = 0; i < pmu->genpd_data.num_domains; i++) { - genpd = pmu->genpd_data.domains[i]; - if (genpd) { - pd = to_rockchip_pd(genpd); - clk_bulk_disable(pd->num_clks, pd->clks); - } - } - - mutex_unlock(&pmu->mutex); - } - - mutex_unlock(&dmc_pmu_mutex); -} -EXPORT_SYMBOL_GPL(rockchip_pmu_unblock); - -#define DOMAIN_RK3588(name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, wakeup) \ - DOMAIN_M_O_R(name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, idle, wakeup) - -static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd) -{ - struct rockchip_pmu *pmu = pd->pmu; - const struct rockchip_domain_info *pd_info = pd->info; - unsigned int val; - - regmap_read(pmu->regmap, pmu->info->idle_offset, &val); - return (val & pd_info->idle_mask) == pd_info->idle_mask; -} - -static unsigned int rockchip_pmu_read_ack(struct rockchip_pmu *pmu) -{ - unsigned int val; - - regmap_read(pmu->regmap, pmu->info->ack_offset, &val); - return val; -} - -static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd, - bool idle) -{ - const struct rockchip_domain_info *pd_info = pd->info; - struct generic_pm_domain *genpd = &pd->genpd; - struct rockchip_pmu *pmu = pd->pmu; - u32 pd_req_offset = pd_info->req_offset; - unsigned int target_ack; - unsigned int val; - bool is_idle; - int ret; - - if (pd_info->req_mask == 0) - return 0; - else if (pd_info->req_w_mask) - regmap_write(pmu->regmap, pmu->info->req_offset + pd_req_offset, - idle ? (pd_info->req_mask | pd_info->req_w_mask) : - pd_info->req_w_mask); - else - regmap_update_bits(pmu->regmap, pmu->info->req_offset + pd_req_offset, - pd_info->req_mask, idle ? -1U : 0); - - wmb(); - - /* Wait util idle_ack = 1 */ - target_ack = idle ? pd_info->ack_mask : 0; - ret = readx_poll_timeout_atomic(rockchip_pmu_read_ack, pmu, val, - (val & pd_info->ack_mask) == target_ack, - 0, 10000); - if (ret) { - dev_err(pmu->dev, - "failed to get ack on domain '%s', val=0x%x\n", - genpd->name, val); - return ret; - } - - ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_idle, pd, - is_idle, is_idle == idle, 0, 10000); - if (ret) { - dev_err(pmu->dev, - "failed to set idle on domain '%s', val=%d\n", - genpd->name, is_idle); - return ret; - } - - return 0; -} - -static int rockchip_pmu_save_qos(struct rockchip_pm_domain *pd) -{ - int i; - - for (i = 0; i < pd->num_qos; i++) { - regmap_read(pd->qos_regmap[i], - QOS_PRIORITY, - &pd->qos_save_regs[0][i]); - regmap_read(pd->qos_regmap[i], - QOS_MODE, - &pd->qos_save_regs[1][i]); - regmap_read(pd->qos_regmap[i], - QOS_BANDWIDTH, - &pd->qos_save_regs[2][i]); - regmap_read(pd->qos_regmap[i], - QOS_SATURATION, - &pd->qos_save_regs[3][i]); - regmap_read(pd->qos_regmap[i], - QOS_EXTCONTROL, - &pd->qos_save_regs[4][i]); - } - return 0; -} - -static int rockchip_pmu_restore_qos(struct rockchip_pm_domain *pd) -{ - int i; - - for (i = 0; i < pd->num_qos; i++) { - regmap_write(pd->qos_regmap[i], - QOS_PRIORITY, - pd->qos_save_regs[0][i]); - regmap_write(pd->qos_regmap[i], - QOS_MODE, - pd->qos_save_regs[1][i]); - regmap_write(pd->qos_regmap[i], - QOS_BANDWIDTH, - pd->qos_save_regs[2][i]); - regmap_write(pd->qos_regmap[i], - QOS_SATURATION, - pd->qos_save_regs[3][i]); - regmap_write(pd->qos_regmap[i], - QOS_EXTCONTROL, - pd->qos_save_regs[4][i]); - } - - return 0; -} - -static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd) -{ - struct rockchip_pmu *pmu = pd->pmu; - unsigned int val; - - if (pd->info->repair_status_mask) { - regmap_read(pmu->regmap, pmu->info->repair_status_offset, &val); - /* 1'b1: power on, 1'b0: power off */ - return val & pd->info->repair_status_mask; - } - - /* check idle status for idle-only domains */ - if (pd->info->status_mask == 0) - return !rockchip_pmu_domain_is_idle(pd); - - regmap_read(pmu->regmap, pmu->info->status_offset, &val); - - /* 1'b0: power on, 1'b1: power off */ - return !(val & pd->info->status_mask); -} - -static bool rockchip_pmu_domain_is_mem_on(struct rockchip_pm_domain *pd) -{ - struct rockchip_pmu *pmu = pd->pmu; - unsigned int val; - - regmap_read(pmu->regmap, - pmu->info->mem_status_offset + pd->info->mem_offset, &val); - - /* 1'b0: power on, 1'b1: power off */ - return !(val & pd->info->mem_status_mask); -} - -static bool rockchip_pmu_domain_is_chain_on(struct rockchip_pm_domain *pd) -{ - struct rockchip_pmu *pmu = pd->pmu; - unsigned int val; - - regmap_read(pmu->regmap, - pmu->info->chain_status_offset + pd->info->mem_offset, &val); - - /* 1'b1: power on, 1'b0: power off */ - return val & pd->info->mem_status_mask; -} - -static int rockchip_pmu_domain_mem_reset(struct rockchip_pm_domain *pd) -{ - struct rockchip_pmu *pmu = pd->pmu; - struct generic_pm_domain *genpd = &pd->genpd; - bool is_on; - int ret = 0; - - ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_chain_on, pd, is_on, - is_on == true, 0, 10000); - if (ret) { - dev_err(pmu->dev, - "failed to get chain status '%s', target_on=1, val=%d\n", - genpd->name, is_on); - goto error; - } - - udelay(20); - - regmap_write(pmu->regmap, pmu->info->mem_pwr_offset + pd->info->pwr_offset, - (pd->info->pwr_mask | pd->info->pwr_w_mask)); - wmb(); - - ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_mem_on, pd, is_on, - is_on == false, 0, 10000); - if (ret) { - dev_err(pmu->dev, - "failed to get mem status '%s', target_on=0, val=%d\n", - genpd->name, is_on); - goto error; - } - - regmap_write(pmu->regmap, pmu->info->mem_pwr_offset + pd->info->pwr_offset, - pd->info->pwr_w_mask); - wmb(); - - ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_mem_on, pd, is_on, - is_on == true, 0, 10000); - if (ret) { - dev_err(pmu->dev, - "failed to get mem status '%s', target_on=1, val=%d\n", - genpd->name, is_on); - } - -error: - return ret; -} - -static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd, - bool on) -{ - struct rockchip_pmu *pmu = pd->pmu; - struct generic_pm_domain *genpd = &pd->genpd; - u32 pd_pwr_offset = pd->info->pwr_offset; - bool is_on, is_mem_on = false; - - if (pd->info->pwr_mask == 0) - return; - - if (on && pd->info->mem_status_mask) - is_mem_on = rockchip_pmu_domain_is_mem_on(pd); - - if (pd->info->pwr_w_mask) - regmap_write(pmu->regmap, pmu->info->pwr_offset + pd_pwr_offset, - on ? pd->info->pwr_w_mask : - (pd->info->pwr_mask | pd->info->pwr_w_mask)); - else - regmap_update_bits(pmu->regmap, pmu->info->pwr_offset + pd_pwr_offset, - pd->info->pwr_mask, on ? 0 : -1U); - - wmb(); - - if (is_mem_on && rockchip_pmu_domain_mem_reset(pd)) - return; - - if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on, - is_on == on, 0, 10000)) { - dev_err(pmu->dev, - "failed to set domain '%s', val=%d\n", - genpd->name, is_on); - return; - } -} - -static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on) -{ - struct rockchip_pmu *pmu = pd->pmu; - int ret; - - mutex_lock(&pmu->mutex); - - if (rockchip_pmu_domain_is_on(pd) != power_on) { - ret = clk_bulk_enable(pd->num_clks, pd->clks); - if (ret < 0) { - dev_err(pmu->dev, "failed to enable clocks\n"); - mutex_unlock(&pmu->mutex); - return ret; - } - - if (!power_on) { - rockchip_pmu_save_qos(pd); - - /* if powering down, idle request to NIU first */ - rockchip_pmu_set_idle_request(pd, true); - } - - rockchip_do_pmu_set_power_domain(pd, power_on); - - if (power_on) { - /* if powering up, leave idle mode */ - rockchip_pmu_set_idle_request(pd, false); - - rockchip_pmu_restore_qos(pd); - } - - clk_bulk_disable(pd->num_clks, pd->clks); - } - - mutex_unlock(&pmu->mutex); - return 0; -} - -static int rockchip_pd_power_on(struct generic_pm_domain *domain) -{ - struct rockchip_pm_domain *pd = to_rockchip_pd(domain); - - return rockchip_pd_power(pd, true); -} - -static int rockchip_pd_power_off(struct generic_pm_domain *domain) -{ - struct rockchip_pm_domain *pd = to_rockchip_pd(domain); - - return rockchip_pd_power(pd, false); -} - -static int rockchip_pd_attach_dev(struct generic_pm_domain *genpd, - struct device *dev) -{ - struct clk *clk; - int i; - int error; - - dev_dbg(dev, "attaching to power domain '%s'\n", genpd->name); - - error = pm_clk_create(dev); - if (error) { - dev_err(dev, "pm_clk_create failed %d\n", error); - return error; - } - - i = 0; - while ((clk = of_clk_get(dev->of_node, i++)) && !IS_ERR(clk)) { - dev_dbg(dev, "adding clock '%pC' to list of PM clocks\n", clk); - error = pm_clk_add_clk(dev, clk); - if (error) { - dev_err(dev, "pm_clk_add_clk failed %d\n", error); - clk_put(clk); - pm_clk_destroy(dev); - return error; - } - } - - return 0; -} - -static void rockchip_pd_detach_dev(struct generic_pm_domain *genpd, - struct device *dev) -{ - dev_dbg(dev, "detaching from power domain '%s'\n", genpd->name); - - pm_clk_destroy(dev); -} - -static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, - struct device_node *node) -{ - const struct rockchip_domain_info *pd_info; - struct rockchip_pm_domain *pd; - struct device_node *qos_node; - int i, j; - u32 id; - int error; - - error = of_property_read_u32(node, "reg", &id); - if (error) { - dev_err(pmu->dev, - "%pOFn: failed to retrieve domain id (reg): %d\n", - node, error); - return -EINVAL; - } - - if (id >= pmu->info->num_domains) { - dev_err(pmu->dev, "%pOFn: invalid domain id %d\n", - node, id); - return -EINVAL; - } - /* RK3588 has domains with two parents (RKVDEC0/RKVDEC1) */ - if (pmu->genpd_data.domains[id]) - return 0; - - pd_info = &pmu->info->domain_info[id]; - if (!pd_info) { - dev_err(pmu->dev, "%pOFn: undefined domain id %d\n", - node, id); - return -EINVAL; - } - - pd = devm_kzalloc(pmu->dev, sizeof(*pd), GFP_KERNEL); - if (!pd) - return -ENOMEM; - - pd->info = pd_info; - pd->pmu = pmu; - - pd->num_clks = of_clk_get_parent_count(node); - if (pd->num_clks > 0) { - pd->clks = devm_kcalloc(pmu->dev, pd->num_clks, - sizeof(*pd->clks), GFP_KERNEL); - if (!pd->clks) - return -ENOMEM; - } else { - dev_dbg(pmu->dev, "%pOFn: doesn't have clocks: %d\n", - node, pd->num_clks); - pd->num_clks = 0; - } - - for (i = 0; i < pd->num_clks; i++) { - pd->clks[i].clk = of_clk_get(node, i); - if (IS_ERR(pd->clks[i].clk)) { - error = PTR_ERR(pd->clks[i].clk); - dev_err(pmu->dev, - "%pOFn: failed to get clk at index %d: %d\n", - node, i, error); - return error; - } - } - - error = clk_bulk_prepare(pd->num_clks, pd->clks); - if (error) - goto err_put_clocks; - - pd->num_qos = of_count_phandle_with_args(node, "pm_qos", - NULL); - - if (pd->num_qos > 0) { - pd->qos_regmap = devm_kcalloc(pmu->dev, pd->num_qos, - sizeof(*pd->qos_regmap), - GFP_KERNEL); - if (!pd->qos_regmap) { - error = -ENOMEM; - goto err_unprepare_clocks; - } - - for (j = 0; j < MAX_QOS_REGS_NUM; j++) { - pd->qos_save_regs[j] = devm_kcalloc(pmu->dev, - pd->num_qos, - sizeof(u32), - GFP_KERNEL); - if (!pd->qos_save_regs[j]) { - error = -ENOMEM; - goto err_unprepare_clocks; - } - } - - for (j = 0; j < pd->num_qos; j++) { - qos_node = of_parse_phandle(node, "pm_qos", j); - if (!qos_node) { - error = -ENODEV; - goto err_unprepare_clocks; - } - pd->qos_regmap[j] = syscon_node_to_regmap(qos_node); - if (IS_ERR(pd->qos_regmap[j])) { - error = -ENODEV; - of_node_put(qos_node); - goto err_unprepare_clocks; - } - of_node_put(qos_node); - } - } - - if (pd->info->name) - pd->genpd.name = pd->info->name; - else - pd->genpd.name = kbasename(node->full_name); - pd->genpd.power_off = rockchip_pd_power_off; - pd->genpd.power_on = rockchip_pd_power_on; - pd->genpd.attach_dev = rockchip_pd_attach_dev; - pd->genpd.detach_dev = rockchip_pd_detach_dev; - pd->genpd.flags = GENPD_FLAG_PM_CLK; - if (pd_info->active_wakeup) - pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP; - pm_genpd_init(&pd->genpd, NULL, - !rockchip_pmu_domain_is_on(pd) || - (pd->info->mem_status_mask && !rockchip_pmu_domain_is_mem_on(pd))); - - pmu->genpd_data.domains[id] = &pd->genpd; - return 0; - -err_unprepare_clocks: - clk_bulk_unprepare(pd->num_clks, pd->clks); -err_put_clocks: - clk_bulk_put(pd->num_clks, pd->clks); - return error; -} - -static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd) -{ - int ret; - - /* - * We're in the error cleanup already, so we only complain, - * but won't emit another error on top of the original one. - */ - ret = pm_genpd_remove(&pd->genpd); - if (ret < 0) - dev_err(pd->pmu->dev, "failed to remove domain '%s' : %d - state may be inconsistent\n", - pd->genpd.name, ret); - - clk_bulk_unprepare(pd->num_clks, pd->clks); - clk_bulk_put(pd->num_clks, pd->clks); - - /* protect the zeroing of pm->num_clks */ - mutex_lock(&pd->pmu->mutex); - pd->num_clks = 0; - mutex_unlock(&pd->pmu->mutex); - - /* devm will free our memory */ -} - -static void rockchip_pm_domain_cleanup(struct rockchip_pmu *pmu) -{ - struct generic_pm_domain *genpd; - struct rockchip_pm_domain *pd; - int i; - - for (i = 0; i < pmu->genpd_data.num_domains; i++) { - genpd = pmu->genpd_data.domains[i]; - if (genpd) { - pd = to_rockchip_pd(genpd); - rockchip_pm_remove_one_domain(pd); - } - } - - /* devm will free our memory */ -} - -static void rockchip_configure_pd_cnt(struct rockchip_pmu *pmu, - u32 domain_reg_offset, - unsigned int count) -{ - /* First configure domain power down transition count ... */ - regmap_write(pmu->regmap, domain_reg_offset, count); - /* ... and then power up count. */ - regmap_write(pmu->regmap, domain_reg_offset + 4, count); -} - -static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu, - struct device_node *parent) -{ - struct device_node *np; - struct generic_pm_domain *child_domain, *parent_domain; - int error; - - for_each_child_of_node(parent, np) { - u32 idx; - - error = of_property_read_u32(parent, "reg", &idx); - if (error) { - dev_err(pmu->dev, - "%pOFn: failed to retrieve domain id (reg): %d\n", - parent, error); - goto err_out; - } - parent_domain = pmu->genpd_data.domains[idx]; - - error = rockchip_pm_add_one_domain(pmu, np); - if (error) { - dev_err(pmu->dev, "failed to handle node %pOFn: %d\n", - np, error); - goto err_out; - } - - error = of_property_read_u32(np, "reg", &idx); - if (error) { - dev_err(pmu->dev, - "%pOFn: failed to retrieve domain id (reg): %d\n", - np, error); - goto err_out; - } - child_domain = pmu->genpd_data.domains[idx]; - - error = pm_genpd_add_subdomain(parent_domain, child_domain); - if (error) { - dev_err(pmu->dev, "%s failed to add subdomain %s: %d\n", - parent_domain->name, child_domain->name, error); - goto err_out; - } else { - dev_dbg(pmu->dev, "%s add subdomain: %s\n", - parent_domain->name, child_domain->name); - } - - rockchip_pm_add_subdomain(pmu, np); - } - - return 0; - -err_out: - of_node_put(np); - return error; -} - -static int rockchip_pm_domain_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - struct device_node *node; - struct device *parent; - struct rockchip_pmu *pmu; - const struct of_device_id *match; - const struct rockchip_pmu_info *pmu_info; - int error; - - if (!np) { - dev_err(dev, "device tree node not found\n"); - return -ENODEV; - } - - match = of_match_device(dev->driver->of_match_table, dev); - if (!match || !match->data) { - dev_err(dev, "missing pmu data\n"); - return -EINVAL; - } - - pmu_info = match->data; - - pmu = devm_kzalloc(dev, - struct_size(pmu, domains, pmu_info->num_domains), - GFP_KERNEL); - if (!pmu) - return -ENOMEM; - - pmu->dev = &pdev->dev; - mutex_init(&pmu->mutex); - - pmu->info = pmu_info; - - pmu->genpd_data.domains = pmu->domains; - pmu->genpd_data.num_domains = pmu_info->num_domains; - - parent = dev->parent; - if (!parent) { - dev_err(dev, "no parent for syscon devices\n"); - return -ENODEV; - } - - pmu->regmap = syscon_node_to_regmap(parent->of_node); - if (IS_ERR(pmu->regmap)) { - dev_err(dev, "no regmap available\n"); - return PTR_ERR(pmu->regmap); - } - - /* - * Configure power up and down transition delays for CORE - * and GPU domains. - */ - if (pmu_info->core_power_transition_time) - rockchip_configure_pd_cnt(pmu, pmu_info->core_pwrcnt_offset, - pmu_info->core_power_transition_time); - if (pmu_info->gpu_pwrcnt_offset) - rockchip_configure_pd_cnt(pmu, pmu_info->gpu_pwrcnt_offset, - pmu_info->gpu_power_transition_time); - - error = -ENODEV; - - /* - * Prevent any rockchip_pmu_block() from racing with the remainder of - * setup (clocks, register initialization). - */ - mutex_lock(&dmc_pmu_mutex); - - for_each_available_child_of_node(np, node) { - error = rockchip_pm_add_one_domain(pmu, node); - if (error) { - dev_err(dev, "failed to handle node %pOFn: %d\n", - node, error); - of_node_put(node); - goto err_out; - } - - error = rockchip_pm_add_subdomain(pmu, node); - if (error < 0) { - dev_err(dev, "failed to handle subdomain node %pOFn: %d\n", - node, error); - of_node_put(node); - goto err_out; - } - } - - if (error) { - dev_dbg(dev, "no power domains defined\n"); - goto err_out; - } - - error = of_genpd_add_provider_onecell(np, &pmu->genpd_data); - if (error) { - dev_err(dev, "failed to add provider: %d\n", error); - goto err_out; - } - - /* We only expect one PMU. */ - if (!WARN_ON_ONCE(dmc_pmu)) - dmc_pmu = pmu; - - mutex_unlock(&dmc_pmu_mutex); - - return 0; - -err_out: - rockchip_pm_domain_cleanup(pmu); - mutex_unlock(&dmc_pmu_mutex); - return error; -} - -static const struct rockchip_domain_info px30_pm_domains[] = { - [PX30_PD_USB] = DOMAIN_PX30("usb", BIT(5), BIT(5), BIT(10), false), - [PX30_PD_SDCARD] = DOMAIN_PX30("sdcard", BIT(8), BIT(8), BIT(9), false), - [PX30_PD_GMAC] = DOMAIN_PX30("gmac", BIT(10), BIT(10), BIT(6), false), - [PX30_PD_MMC_NAND] = DOMAIN_PX30("mmc_nand", BIT(11), BIT(11), BIT(5), false), - [PX30_PD_VPU] = DOMAIN_PX30("vpu", BIT(12), BIT(12), BIT(14), false), - [PX30_PD_VO] = DOMAIN_PX30("vo", BIT(13), BIT(13), BIT(7), false), - [PX30_PD_VI] = DOMAIN_PX30("vi", BIT(14), BIT(14), BIT(8), false), - [PX30_PD_GPU] = DOMAIN_PX30("gpu", BIT(15), BIT(15), BIT(2), false), -}; - -static const struct rockchip_domain_info rv1126_pm_domains[] = { - [RV1126_PD_VEPU] = DOMAIN_RV1126("vepu", BIT(2), BIT(9), BIT(9), false), - [RV1126_PD_VI] = DOMAIN_RV1126("vi", BIT(4), BIT(6), BIT(6), false), - [RV1126_PD_ISPP] = DOMAIN_RV1126("ispp", BIT(1), BIT(8), BIT(8), false), - [RV1126_PD_VDPU] = DOMAIN_RV1126("vdpu", BIT(3), BIT(10), BIT(10), false), - [RV1126_PD_NVM] = DOMAIN_RV1126("nvm", BIT(7), BIT(11), BIT(11), false), - [RV1126_PD_SDIO] = DOMAIN_RV1126("sdio", BIT(8), BIT(13), BIT(13), false), - [RV1126_PD_USB] = DOMAIN_RV1126("usb", BIT(9), BIT(15), BIT(15), false), -}; - -static const struct rockchip_domain_info rk3036_pm_domains[] = { - [RK3036_PD_MSCH] = DOMAIN_RK3036("msch", BIT(14), BIT(23), BIT(30), true), - [RK3036_PD_CORE] = DOMAIN_RK3036("core", BIT(13), BIT(17), BIT(24), false), - [RK3036_PD_PERI] = DOMAIN_RK3036("peri", BIT(12), BIT(18), BIT(25), false), - [RK3036_PD_VIO] = DOMAIN_RK3036("vio", BIT(11), BIT(19), BIT(26), false), - [RK3036_PD_VPU] = DOMAIN_RK3036("vpu", BIT(10), BIT(20), BIT(27), false), - [RK3036_PD_GPU] = DOMAIN_RK3036("gpu", BIT(9), BIT(21), BIT(28), false), - [RK3036_PD_SYS] = DOMAIN_RK3036("sys", BIT(8), BIT(22), BIT(29), false), -}; - -static const struct rockchip_domain_info rk3066_pm_domains[] = { - [RK3066_PD_GPU] = DOMAIN("gpu", BIT(9), BIT(9), BIT(3), BIT(24), BIT(29), false), - [RK3066_PD_VIDEO] = DOMAIN("video", BIT(8), BIT(8), BIT(4), BIT(23), BIT(28), false), - [RK3066_PD_VIO] = DOMAIN("vio", BIT(7), BIT(7), BIT(5), BIT(22), BIT(27), false), - [RK3066_PD_PERI] = DOMAIN("peri", BIT(6), BIT(6), BIT(2), BIT(25), BIT(30), false), - [RK3066_PD_CPU] = DOMAIN("cpu", 0, BIT(5), BIT(1), BIT(26), BIT(31), false), -}; - -static const struct rockchip_domain_info rk3128_pm_domains[] = { - [RK3128_PD_CORE] = DOMAIN_RK3288("core", BIT(0), BIT(0), BIT(4), false), - [RK3128_PD_MSCH] = DOMAIN_RK3288("msch", 0, 0, BIT(6), true), - [RK3128_PD_VIO] = DOMAIN_RK3288("vio", BIT(3), BIT(3), BIT(2), false), - [RK3128_PD_VIDEO] = DOMAIN_RK3288("video", BIT(2), BIT(2), BIT(1), false), - [RK3128_PD_GPU] = DOMAIN_RK3288("gpu", BIT(1), BIT(1), BIT(3), false), -}; - -static const struct rockchip_domain_info rk3188_pm_domains[] = { - [RK3188_PD_GPU] = DOMAIN("gpu", BIT(9), BIT(9), BIT(3), BIT(24), BIT(29), false), - [RK3188_PD_VIDEO] = DOMAIN("video", BIT(8), BIT(8), BIT(4), BIT(23), BIT(28), false), - [RK3188_PD_VIO] = DOMAIN("vio", BIT(7), BIT(7), BIT(5), BIT(22), BIT(27), false), - [RK3188_PD_PERI] = DOMAIN("peri", BIT(6), BIT(6), BIT(2), BIT(25), BIT(30), false), - [RK3188_PD_CPU] = DOMAIN("cpu", BIT(5), BIT(5), BIT(1), BIT(26), BIT(31), false), -}; - -static const struct rockchip_domain_info rk3228_pm_domains[] = { - [RK3228_PD_CORE] = DOMAIN_RK3036("core", BIT(0), BIT(0), BIT(16), true), - [RK3228_PD_MSCH] = DOMAIN_RK3036("msch", BIT(1), BIT(1), BIT(17), true), - [RK3228_PD_BUS] = DOMAIN_RK3036("bus", BIT(2), BIT(2), BIT(18), true), - [RK3228_PD_SYS] = DOMAIN_RK3036("sys", BIT(3), BIT(3), BIT(19), true), - [RK3228_PD_VIO] = DOMAIN_RK3036("vio", BIT(4), BIT(4), BIT(20), false), - [RK3228_PD_VOP] = DOMAIN_RK3036("vop", BIT(5), BIT(5), BIT(21), false), - [RK3228_PD_VPU] = DOMAIN_RK3036("vpu", BIT(6), BIT(6), BIT(22), false), - [RK3228_PD_RKVDEC] = DOMAIN_RK3036("vdec", BIT(7), BIT(7), BIT(23), false), - [RK3228_PD_GPU] = DOMAIN_RK3036("gpu", BIT(8), BIT(8), BIT(24), false), - [RK3228_PD_PERI] = DOMAIN_RK3036("peri", BIT(9), BIT(9), BIT(25), true), - [RK3228_PD_GMAC] = DOMAIN_RK3036("gmac", BIT(10), BIT(10), BIT(26), false), -}; - -static const struct rockchip_domain_info rk3288_pm_domains[] = { - [RK3288_PD_VIO] = DOMAIN_RK3288("vio", BIT(7), BIT(7), BIT(4), false), - [RK3288_PD_HEVC] = DOMAIN_RK3288("hevc", BIT(14), BIT(10), BIT(9), false), - [RK3288_PD_VIDEO] = DOMAIN_RK3288("video", BIT(8), BIT(8), BIT(3), false), - [RK3288_PD_GPU] = DOMAIN_RK3288("gpu", BIT(9), BIT(9), BIT(2), false), -}; - -static const struct rockchip_domain_info rk3328_pm_domains[] = { - [RK3328_PD_CORE] = DOMAIN_RK3328("core", 0, BIT(0), BIT(0), false), - [RK3328_PD_GPU] = DOMAIN_RK3328("gpu", 0, BIT(1), BIT(1), false), - [RK3328_PD_BUS] = DOMAIN_RK3328("bus", 0, BIT(2), BIT(2), true), - [RK3328_PD_MSCH] = DOMAIN_RK3328("msch", 0, BIT(3), BIT(3), true), - [RK3328_PD_PERI] = DOMAIN_RK3328("peri", 0, BIT(4), BIT(4), true), - [RK3328_PD_VIDEO] = DOMAIN_RK3328("video", 0, BIT(5), BIT(5), false), - [RK3328_PD_HEVC] = DOMAIN_RK3328("hevc", 0, BIT(6), BIT(6), false), - [RK3328_PD_VIO] = DOMAIN_RK3328("vio", 0, BIT(8), BIT(8), false), - [RK3328_PD_VPU] = DOMAIN_RK3328("vpu", 0, BIT(9), BIT(9), false), -}; - -static const struct rockchip_domain_info rk3366_pm_domains[] = { - [RK3366_PD_PERI] = DOMAIN_RK3368("peri", BIT(10), BIT(10), BIT(6), true), - [RK3366_PD_VIO] = DOMAIN_RK3368("vio", BIT(14), BIT(14), BIT(8), false), - [RK3366_PD_VIDEO] = DOMAIN_RK3368("video", BIT(13), BIT(13), BIT(7), false), - [RK3366_PD_RKVDEC] = DOMAIN_RK3368("vdec", BIT(11), BIT(11), BIT(7), false), - [RK3366_PD_WIFIBT] = DOMAIN_RK3368("wifibt", BIT(8), BIT(8), BIT(9), false), - [RK3366_PD_VPU] = DOMAIN_RK3368("vpu", BIT(12), BIT(12), BIT(7), false), - [RK3366_PD_GPU] = DOMAIN_RK3368("gpu", BIT(15), BIT(15), BIT(2), false), -}; - -static const struct rockchip_domain_info rk3368_pm_domains[] = { - [RK3368_PD_PERI] = DOMAIN_RK3368("peri", BIT(13), BIT(12), BIT(6), true), - [RK3368_PD_VIO] = DOMAIN_RK3368("vio", BIT(15), BIT(14), BIT(8), false), - [RK3368_PD_VIDEO] = DOMAIN_RK3368("video", BIT(14), BIT(13), BIT(7), false), - [RK3368_PD_GPU_0] = DOMAIN_RK3368("gpu_0", BIT(16), BIT(15), BIT(2), false), - [RK3368_PD_GPU_1] = DOMAIN_RK3368("gpu_1", BIT(17), BIT(16), BIT(2), false), -}; - -static const struct rockchip_domain_info rk3399_pm_domains[] = { - [RK3399_PD_TCPD0] = DOMAIN_RK3399("tcpd0", BIT(8), BIT(8), 0, false), - [RK3399_PD_TCPD1] = DOMAIN_RK3399("tcpd1", BIT(9), BIT(9), 0, false), - [RK3399_PD_CCI] = DOMAIN_RK3399("cci", BIT(10), BIT(10), 0, true), - [RK3399_PD_CCI0] = DOMAIN_RK3399("cci0", 0, 0, BIT(15), true), - [RK3399_PD_CCI1] = DOMAIN_RK3399("cci1", 0, 0, BIT(16), true), - [RK3399_PD_PERILP] = DOMAIN_RK3399("perilp", BIT(11), BIT(11), BIT(1), true), - [RK3399_PD_PERIHP] = DOMAIN_RK3399("perihp", BIT(12), BIT(12), BIT(2), true), - [RK3399_PD_CENTER] = DOMAIN_RK3399("center", BIT(13), BIT(13), BIT(14), true), - [RK3399_PD_VIO] = DOMAIN_RK3399("vio", BIT(14), BIT(14), BIT(17), false), - [RK3399_PD_GPU] = DOMAIN_RK3399("gpu", BIT(15), BIT(15), BIT(0), false), - [RK3399_PD_VCODEC] = DOMAIN_RK3399("vcodec", BIT(16), BIT(16), BIT(3), false), - [RK3399_PD_VDU] = DOMAIN_RK3399("vdu", BIT(17), BIT(17), BIT(4), false), - [RK3399_PD_RGA] = DOMAIN_RK3399("rga", BIT(18), BIT(18), BIT(5), false), - [RK3399_PD_IEP] = DOMAIN_RK3399("iep", BIT(19), BIT(19), BIT(6), false), - [RK3399_PD_VO] = DOMAIN_RK3399("vo", BIT(20), BIT(20), 0, false), - [RK3399_PD_VOPB] = DOMAIN_RK3399("vopb", 0, 0, BIT(7), false), - [RK3399_PD_VOPL] = DOMAIN_RK3399("vopl", 0, 0, BIT(8), false), - [RK3399_PD_ISP0] = DOMAIN_RK3399("isp0", BIT(22), BIT(22), BIT(9), false), - [RK3399_PD_ISP1] = DOMAIN_RK3399("isp1", BIT(23), BIT(23), BIT(10), false), - [RK3399_PD_HDCP] = DOMAIN_RK3399("hdcp", BIT(24), BIT(24), BIT(11), false), - [RK3399_PD_GMAC] = DOMAIN_RK3399("gmac", BIT(25), BIT(25), BIT(23), true), - [RK3399_PD_EMMC] = DOMAIN_RK3399("emmc", BIT(26), BIT(26), BIT(24), true), - [RK3399_PD_USB3] = DOMAIN_RK3399("usb3", BIT(27), BIT(27), BIT(12), true), - [RK3399_PD_EDP] = DOMAIN_RK3399("edp", BIT(28), BIT(28), BIT(22), false), - [RK3399_PD_GIC] = DOMAIN_RK3399("gic", BIT(29), BIT(29), BIT(27), true), - [RK3399_PD_SD] = DOMAIN_RK3399("sd", BIT(30), BIT(30), BIT(28), true), - [RK3399_PD_SDIOAUDIO] = DOMAIN_RK3399("sdioaudio", BIT(31), BIT(31), BIT(29), true), -}; - -static const struct rockchip_domain_info rk3568_pm_domains[] = { - [RK3568_PD_NPU] = DOMAIN_RK3568("npu", BIT(1), BIT(2), false), - [RK3568_PD_GPU] = DOMAIN_RK3568("gpu", BIT(0), BIT(1), false), - [RK3568_PD_VI] = DOMAIN_RK3568("vi", BIT(6), BIT(3), false), - [RK3568_PD_VO] = DOMAIN_RK3568("vo", BIT(7), BIT(4), false), - [RK3568_PD_RGA] = DOMAIN_RK3568("rga", BIT(5), BIT(5), false), - [RK3568_PD_VPU] = DOMAIN_RK3568("vpu", BIT(2), BIT(6), false), - [RK3568_PD_RKVDEC] = DOMAIN_RK3568("vdec", BIT(4), BIT(8), false), - [RK3568_PD_RKVENC] = DOMAIN_RK3568("venc", BIT(3), BIT(7), false), - [RK3568_PD_PIPE] = DOMAIN_RK3568("pipe", BIT(8), BIT(11), false), -}; - -static const struct rockchip_domain_info rk3588_pm_domains[] = { - [RK3588_PD_GPU] = DOMAIN_RK3588("gpu", 0x0, BIT(0), 0, 0x0, 0, BIT(1), 0x0, BIT(0), BIT(0), false), - [RK3588_PD_NPU] = DOMAIN_RK3588("npu", 0x0, BIT(1), BIT(1), 0x0, 0, 0, 0x0, 0, 0, false), - [RK3588_PD_VCODEC] = DOMAIN_RK3588("vcodec", 0x0, BIT(2), BIT(2), 0x0, 0, 0, 0x0, 0, 0, false), - [RK3588_PD_NPUTOP] = DOMAIN_RK3588("nputop", 0x0, BIT(3), 0, 0x0, BIT(11), BIT(2), 0x0, BIT(1), BIT(1), false), - [RK3588_PD_NPU1] = DOMAIN_RK3588("npu1", 0x0, BIT(4), 0, 0x0, BIT(12), BIT(3), 0x0, BIT(2), BIT(2), false), - [RK3588_PD_NPU2] = DOMAIN_RK3588("npu2", 0x0, BIT(5), 0, 0x0, BIT(13), BIT(4), 0x0, BIT(3), BIT(3), false), - [RK3588_PD_VENC0] = DOMAIN_RK3588("venc0", 0x0, BIT(6), 0, 0x0, BIT(14), BIT(5), 0x0, BIT(4), BIT(4), false), - [RK3588_PD_VENC1] = DOMAIN_RK3588("venc1", 0x0, BIT(7), 0, 0x0, BIT(15), BIT(6), 0x0, BIT(5), BIT(5), false), - [RK3588_PD_RKVDEC0] = DOMAIN_RK3588("rkvdec0", 0x0, BIT(8), 0, 0x0, BIT(16), BIT(7), 0x0, BIT(6), BIT(6), false), - [RK3588_PD_RKVDEC1] = DOMAIN_RK3588("rkvdec1", 0x0, BIT(9), 0, 0x0, BIT(17), BIT(8), 0x0, BIT(7), BIT(7), false), - [RK3588_PD_VDPU] = DOMAIN_RK3588("vdpu", 0x0, BIT(10), 0, 0x0, BIT(18), BIT(9), 0x0, BIT(8), BIT(8), false), - [RK3588_PD_RGA30] = DOMAIN_RK3588("rga30", 0x0, BIT(11), 0, 0x0, BIT(19), BIT(10), 0x0, 0, 0, false), - [RK3588_PD_AV1] = DOMAIN_RK3588("av1", 0x0, BIT(12), 0, 0x0, BIT(20), BIT(11), 0x0, BIT(9), BIT(9), false), - [RK3588_PD_VI] = DOMAIN_RK3588("vi", 0x0, BIT(13), 0, 0x0, BIT(21), BIT(12), 0x0, BIT(10), BIT(10), false), - [RK3588_PD_FEC] = DOMAIN_RK3588("fec", 0x0, BIT(14), 0, 0x0, BIT(22), BIT(13), 0x0, 0, 0, false), - [RK3588_PD_ISP1] = DOMAIN_RK3588("isp1", 0x0, BIT(15), 0, 0x0, BIT(23), BIT(14), 0x0, BIT(11), BIT(11), false), - [RK3588_PD_RGA31] = DOMAIN_RK3588("rga31", 0x4, BIT(0), 0, 0x0, BIT(24), BIT(15), 0x0, BIT(12), BIT(12), false), - [RK3588_PD_VOP] = DOMAIN_RK3588("vop", 0x4, BIT(1), 0, 0x0, BIT(25), BIT(16), 0x0, BIT(13) | BIT(14), BIT(13) | BIT(14), false), - [RK3588_PD_VO0] = DOMAIN_RK3588("vo0", 0x4, BIT(2), 0, 0x0, BIT(26), BIT(17), 0x0, BIT(15), BIT(15), false), - [RK3588_PD_VO1] = DOMAIN_RK3588("vo1", 0x4, BIT(3), 0, 0x0, BIT(27), BIT(18), 0x4, BIT(0), BIT(16), false), - [RK3588_PD_AUDIO] = DOMAIN_RK3588("audio", 0x4, BIT(4), 0, 0x0, BIT(28), BIT(19), 0x4, BIT(1), BIT(17), false), - [RK3588_PD_PHP] = DOMAIN_RK3588("php", 0x4, BIT(5), 0, 0x0, BIT(29), BIT(20), 0x4, BIT(5), BIT(21), false), - [RK3588_PD_GMAC] = DOMAIN_RK3588("gmac", 0x4, BIT(6), 0, 0x0, BIT(30), BIT(21), 0x0, 0, 0, false), - [RK3588_PD_PCIE] = DOMAIN_RK3588("pcie", 0x4, BIT(7), 0, 0x0, BIT(31), BIT(22), 0x0, 0, 0, true), - [RK3588_PD_NVM] = DOMAIN_RK3588("nvm", 0x4, BIT(8), BIT(24), 0x4, 0, 0, 0x4, BIT(2), BIT(18), false), - [RK3588_PD_NVM0] = DOMAIN_RK3588("nvm0", 0x4, BIT(9), 0, 0x4, BIT(1), BIT(23), 0x0, 0, 0, false), - [RK3588_PD_SDIO] = DOMAIN_RK3588("sdio", 0x4, BIT(10), 0, 0x4, BIT(2), BIT(24), 0x4, BIT(3), BIT(19), false), - [RK3588_PD_USB] = DOMAIN_RK3588("usb", 0x4, BIT(11), 0, 0x4, BIT(3), BIT(25), 0x4, BIT(4), BIT(20), true), - [RK3588_PD_SDMMC] = DOMAIN_RK3588("sdmmc", 0x4, BIT(13), 0, 0x4, BIT(5), BIT(26), 0x0, 0, 0, false), -}; - -static const struct rockchip_pmu_info px30_pmu = { - .pwr_offset = 0x18, - .status_offset = 0x20, - .req_offset = 0x64, - .idle_offset = 0x6c, - .ack_offset = 0x6c, - - .num_domains = ARRAY_SIZE(px30_pm_domains), - .domain_info = px30_pm_domains, -}; - -static const struct rockchip_pmu_info rk3036_pmu = { - .req_offset = 0x148, - .idle_offset = 0x14c, - .ack_offset = 0x14c, - - .num_domains = ARRAY_SIZE(rk3036_pm_domains), - .domain_info = rk3036_pm_domains, -}; - -static const struct rockchip_pmu_info rk3066_pmu = { - .pwr_offset = 0x08, - .status_offset = 0x0c, - .req_offset = 0x38, /* PMU_MISC_CON1 */ - .idle_offset = 0x0c, - .ack_offset = 0x0c, - - .num_domains = ARRAY_SIZE(rk3066_pm_domains), - .domain_info = rk3066_pm_domains, -}; - -static const struct rockchip_pmu_info rk3128_pmu = { - .pwr_offset = 0x04, - .status_offset = 0x08, - .req_offset = 0x0c, - .idle_offset = 0x10, - .ack_offset = 0x10, - - .num_domains = ARRAY_SIZE(rk3128_pm_domains), - .domain_info = rk3128_pm_domains, -}; - -static const struct rockchip_pmu_info rk3188_pmu = { - .pwr_offset = 0x08, - .status_offset = 0x0c, - .req_offset = 0x38, /* PMU_MISC_CON1 */ - .idle_offset = 0x0c, - .ack_offset = 0x0c, - - .num_domains = ARRAY_SIZE(rk3188_pm_domains), - .domain_info = rk3188_pm_domains, -}; - -static const struct rockchip_pmu_info rk3228_pmu = { - .req_offset = 0x40c, - .idle_offset = 0x488, - .ack_offset = 0x488, - - .num_domains = ARRAY_SIZE(rk3228_pm_domains), - .domain_info = rk3228_pm_domains, -}; - -static const struct rockchip_pmu_info rk3288_pmu = { - .pwr_offset = 0x08, - .status_offset = 0x0c, - .req_offset = 0x10, - .idle_offset = 0x14, - .ack_offset = 0x14, - - .core_pwrcnt_offset = 0x34, - .gpu_pwrcnt_offset = 0x3c, - - .core_power_transition_time = 24, /* 1us */ - .gpu_power_transition_time = 24, /* 1us */ - - .num_domains = ARRAY_SIZE(rk3288_pm_domains), - .domain_info = rk3288_pm_domains, -}; - -static const struct rockchip_pmu_info rk3328_pmu = { - .req_offset = 0x414, - .idle_offset = 0x484, - .ack_offset = 0x484, - - .num_domains = ARRAY_SIZE(rk3328_pm_domains), - .domain_info = rk3328_pm_domains, -}; - -static const struct rockchip_pmu_info rk3366_pmu = { - .pwr_offset = 0x0c, - .status_offset = 0x10, - .req_offset = 0x3c, - .idle_offset = 0x40, - .ack_offset = 0x40, - - .core_pwrcnt_offset = 0x48, - .gpu_pwrcnt_offset = 0x50, - - .core_power_transition_time = 24, - .gpu_power_transition_time = 24, - - .num_domains = ARRAY_SIZE(rk3366_pm_domains), - .domain_info = rk3366_pm_domains, -}; - -static const struct rockchip_pmu_info rk3368_pmu = { - .pwr_offset = 0x0c, - .status_offset = 0x10, - .req_offset = 0x3c, - .idle_offset = 0x40, - .ack_offset = 0x40, - - .core_pwrcnt_offset = 0x48, - .gpu_pwrcnt_offset = 0x50, - - .core_power_transition_time = 24, - .gpu_power_transition_time = 24, - - .num_domains = ARRAY_SIZE(rk3368_pm_domains), - .domain_info = rk3368_pm_domains, -}; - -static const struct rockchip_pmu_info rk3399_pmu = { - .pwr_offset = 0x14, - .status_offset = 0x18, - .req_offset = 0x60, - .idle_offset = 0x64, - .ack_offset = 0x68, - - /* ARM Trusted Firmware manages power transition times */ - - .num_domains = ARRAY_SIZE(rk3399_pm_domains), - .domain_info = rk3399_pm_domains, -}; - -static const struct rockchip_pmu_info rk3568_pmu = { - .pwr_offset = 0xa0, - .status_offset = 0x98, - .req_offset = 0x50, - .idle_offset = 0x68, - .ack_offset = 0x60, - - .num_domains = ARRAY_SIZE(rk3568_pm_domains), - .domain_info = rk3568_pm_domains, -}; - -static const struct rockchip_pmu_info rk3588_pmu = { - .pwr_offset = 0x14c, - .status_offset = 0x180, - .req_offset = 0x10c, - .idle_offset = 0x120, - .ack_offset = 0x118, - .mem_pwr_offset = 0x1a0, - .chain_status_offset = 0x1f0, - .mem_status_offset = 0x1f8, - .repair_status_offset = 0x290, - - .num_domains = ARRAY_SIZE(rk3588_pm_domains), - .domain_info = rk3588_pm_domains, -}; - -static const struct rockchip_pmu_info rv1126_pmu = { - .pwr_offset = 0x110, - .status_offset = 0x108, - .req_offset = 0xc0, - .idle_offset = 0xd8, - .ack_offset = 0xd0, - - .num_domains = ARRAY_SIZE(rv1126_pm_domains), - .domain_info = rv1126_pm_domains, -}; - -static const struct of_device_id rockchip_pm_domain_dt_match[] = { - { - .compatible = "rockchip,px30-power-controller", - .data = (void *)&px30_pmu, - }, - { - .compatible = "rockchip,rk3036-power-controller", - .data = (void *)&rk3036_pmu, - }, - { - .compatible = "rockchip,rk3066-power-controller", - .data = (void *)&rk3066_pmu, - }, - { - .compatible = "rockchip,rk3128-power-controller", - .data = (void *)&rk3128_pmu, - }, - { - .compatible = "rockchip,rk3188-power-controller", - .data = (void *)&rk3188_pmu, - }, - { - .compatible = "rockchip,rk3228-power-controller", - .data = (void *)&rk3228_pmu, - }, - { - .compatible = "rockchip,rk3288-power-controller", - .data = (void *)&rk3288_pmu, - }, - { - .compatible = "rockchip,rk3328-power-controller", - .data = (void *)&rk3328_pmu, - }, - { - .compatible = "rockchip,rk3366-power-controller", - .data = (void *)&rk3366_pmu, - }, - { - .compatible = "rockchip,rk3368-power-controller", - .data = (void *)&rk3368_pmu, - }, - { - .compatible = "rockchip,rk3399-power-controller", - .data = (void *)&rk3399_pmu, - }, - { - .compatible = "rockchip,rk3568-power-controller", - .data = (void *)&rk3568_pmu, - }, - { - .compatible = "rockchip,rk3588-power-controller", - .data = (void *)&rk3588_pmu, - }, - { - .compatible = "rockchip,rv1126-power-controller", - .data = (void *)&rv1126_pmu, - }, - { /* sentinel */ }, -}; - -static struct platform_driver rockchip_pm_domain_driver = { - .probe = rockchip_pm_domain_probe, - .driver = { - .name = "rockchip-pm-domain", - .of_match_table = rockchip_pm_domain_dt_match, - /* - * We can't forcibly eject devices from the power - * domain, so we can't really remove power domains - * once they were added. - */ - .suppress_bind_attrs = true, - }, -}; - -static int __init rockchip_pm_domain_drv_register(void) -{ - return platform_driver_register(&rockchip_pm_domain_driver); -} -postcore_initcall(rockchip_pm_domain_drv_register); diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile index d35270fc6b2b..248a33d7754a 100644 --- a/drivers/soc/samsung/Makefile +++ b/drivers/soc/samsung/Makefile @@ -10,7 +10,6 @@ obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o obj-$(CONFIG_EXYNOS_PMU_ARM_DRIVERS) += exynos3250-pmu.o exynos4-pmu.o \ exynos5250-pmu.o exynos5420-pmu.o -obj-$(CONFIG_EXYNOS_PM_DOMAINS) += pm_domains.o obj-$(CONFIG_EXYNOS_REGULATOR_COUPLER) += exynos-regulator-coupler.o obj-$(CONFIG_SAMSUNG_PM_CHECK) += s3c-pm-check.o diff --git a/drivers/soc/samsung/pm_domains.c b/drivers/soc/samsung/pm_domains.c deleted file mode 100644 index d07f3c9d6903..000000000000 --- a/drivers/soc/samsung/pm_domains.c +++ /dev/null @@ -1,166 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -// -// Exynos Generic power domain support. -// -// Copyright (c) 2012 Samsung Electronics Co., Ltd. -// http://www.samsung.com -// -// Implementation of Exynos specific power domain control which is used in -// conjunction with runtime-pm. Support for both device-tree and non-device-tree -// based power domain support is included. - -#include <linux/io.h> -#include <linux/err.h> -#include <linux/slab.h> -#include <linux/pm_domain.h> -#include <linux/delay.h> -#include <linux/of_address.h> -#include <linux/of_platform.h> -#include <linux/pm_runtime.h> - -struct exynos_pm_domain_config { - /* Value for LOCAL_PWR_CFG and STATUS fields for each domain */ - u32 local_pwr_cfg; -}; - -/* - * Exynos specific wrapper around the generic power domain - */ -struct exynos_pm_domain { - void __iomem *base; - struct generic_pm_domain pd; - u32 local_pwr_cfg; -}; - -static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on) -{ - struct exynos_pm_domain *pd; - void __iomem *base; - u32 timeout, pwr; - char *op; - - pd = container_of(domain, struct exynos_pm_domain, pd); - base = pd->base; - - pwr = power_on ? pd->local_pwr_cfg : 0; - writel_relaxed(pwr, base); - - /* Wait max 1ms */ - timeout = 10; - - while ((readl_relaxed(base + 0x4) & pd->local_pwr_cfg) != pwr) { - if (!timeout) { - op = (power_on) ? "enable" : "disable"; - pr_err("Power domain %s %s failed\n", domain->name, op); - return -ETIMEDOUT; - } - timeout--; - cpu_relax(); - usleep_range(80, 100); - } - - return 0; -} - -static int exynos_pd_power_on(struct generic_pm_domain *domain) -{ - return exynos_pd_power(domain, true); -} - -static int exynos_pd_power_off(struct generic_pm_domain *domain) -{ - return exynos_pd_power(domain, false); -} - -static const struct exynos_pm_domain_config exynos4210_cfg = { - .local_pwr_cfg = 0x7, -}; - -static const struct exynos_pm_domain_config exynos5433_cfg = { - .local_pwr_cfg = 0xf, -}; - -static const struct of_device_id exynos_pm_domain_of_match[] = { - { - .compatible = "samsung,exynos4210-pd", - .data = &exynos4210_cfg, - }, { - .compatible = "samsung,exynos5433-pd", - .data = &exynos5433_cfg, - }, - { }, -}; - -static const char *exynos_get_domain_name(struct device_node *node) -{ - const char *name; - - if (of_property_read_string(node, "label", &name) < 0) - name = kbasename(node->full_name); - return kstrdup_const(name, GFP_KERNEL); -} - -static int exynos_pd_probe(struct platform_device *pdev) -{ - const struct exynos_pm_domain_config *pm_domain_cfg; - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - struct of_phandle_args child, parent; - struct exynos_pm_domain *pd; - int on, ret; - - pm_domain_cfg = of_device_get_match_data(dev); - pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); - if (!pd) - return -ENOMEM; - - pd->pd.name = exynos_get_domain_name(np); - if (!pd->pd.name) - return -ENOMEM; - - pd->base = of_iomap(np, 0); - if (!pd->base) { - kfree_const(pd->pd.name); - return -ENODEV; - } - - pd->pd.power_off = exynos_pd_power_off; - pd->pd.power_on = exynos_pd_power_on; - pd->local_pwr_cfg = pm_domain_cfg->local_pwr_cfg; - - on = readl_relaxed(pd->base + 0x4) & pd->local_pwr_cfg; - - pm_genpd_init(&pd->pd, NULL, !on); - ret = of_genpd_add_provider_simple(np, &pd->pd); - - if (ret == 0 && of_parse_phandle_with_args(np, "power-domains", - "#power-domain-cells", 0, &parent) == 0) { - child.np = np; - child.args_count = 0; - - if (of_genpd_add_subdomain(&parent, &child)) - pr_warn("%pOF failed to add subdomain: %pOF\n", - parent.np, child.np); - else - pr_info("%pOF has as child subdomain: %pOF.\n", - parent.np, child.np); - } - - pm_runtime_enable(dev); - return ret; -} - -static struct platform_driver exynos_pd_driver = { - .probe = exynos_pd_probe, - .driver = { - .name = "exynos-pd", - .of_match_table = exynos_pm_domain_of_match, - .suppress_bind_attrs = true, - } -}; - -static __init int exynos4_pm_init_power_domain(void) -{ - return platform_driver_register(&exynos_pd_driver); -} -core_initcall(exynos4_pm_init_power_domain); diff --git a/drivers/soc/starfive/Makefile b/drivers/soc/starfive/Makefile deleted file mode 100644 index 13b589d6b5f3..000000000000 --- a/drivers/soc/starfive/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -obj-$(CONFIG_JH71XX_PMU) += jh71xx_pmu.o diff --git a/drivers/soc/starfive/jh71xx_pmu.c b/drivers/soc/starfive/jh71xx_pmu.c deleted file mode 100644 index 7d5f50d71c0d..000000000000 --- a/drivers/soc/starfive/jh71xx_pmu.c +++ /dev/null @@ -1,383 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * StarFive JH71XX PMU (Power Management Unit) Controller Driver - * - * Copyright (C) 2022 StarFive Technology Co., Ltd. - */ - -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/iopoll.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <dt-bindings/power/starfive,jh7110-pmu.h> - -/* register offset */ -#define JH71XX_PMU_SW_TURN_ON_POWER 0x0C -#define JH71XX_PMU_SW_TURN_OFF_POWER 0x10 -#define JH71XX_PMU_SW_ENCOURAGE 0x44 -#define JH71XX_PMU_TIMER_INT_MASK 0x48 -#define JH71XX_PMU_CURR_POWER_MODE 0x80 -#define JH71XX_PMU_EVENT_STATUS 0x88 -#define JH71XX_PMU_INT_STATUS 0x8C - -/* sw encourage cfg */ -#define JH71XX_PMU_SW_ENCOURAGE_EN_LO 0x05 -#define JH71XX_PMU_SW_ENCOURAGE_EN_HI 0x50 -#define JH71XX_PMU_SW_ENCOURAGE_DIS_LO 0x0A -#define JH71XX_PMU_SW_ENCOURAGE_DIS_HI 0xA0 -#define JH71XX_PMU_SW_ENCOURAGE_ON 0xFF - -/* pmu int status */ -#define JH71XX_PMU_INT_SEQ_DONE BIT(0) -#define JH71XX_PMU_INT_HW_REQ BIT(1) -#define JH71XX_PMU_INT_SW_FAIL GENMASK(3, 2) -#define JH71XX_PMU_INT_HW_FAIL GENMASK(5, 4) -#define JH71XX_PMU_INT_PCH_FAIL GENMASK(8, 6) -#define JH71XX_PMU_INT_ALL_MASK GENMASK(8, 0) - -/* - * The time required for switching power status is based on the time - * to turn on the largest domain's power, which is at microsecond level - */ -#define JH71XX_PMU_TIMEOUT_US 100 - -struct jh71xx_domain_info { - const char * const name; - unsigned int flags; - u8 bit; -}; - -struct jh71xx_pmu_match_data { - const struct jh71xx_domain_info *domain_info; - int num_domains; -}; - -struct jh71xx_pmu { - struct device *dev; - const struct jh71xx_pmu_match_data *match_data; - void __iomem *base; - struct generic_pm_domain **genpd; - struct genpd_onecell_data genpd_data; - int irq; - spinlock_t lock; /* protects pmu reg */ -}; - -struct jh71xx_pmu_dev { - const struct jh71xx_domain_info *domain_info; - struct jh71xx_pmu *pmu; - struct generic_pm_domain genpd; -}; - -static int jh71xx_pmu_get_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool *is_on) -{ - struct jh71xx_pmu *pmu = pmd->pmu; - - if (!mask) - return -EINVAL; - - *is_on = readl(pmu->base + JH71XX_PMU_CURR_POWER_MODE) & mask; - - return 0; -} - -static int jh71xx_pmu_set_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool on) -{ - struct jh71xx_pmu *pmu = pmd->pmu; - unsigned long flags; - u32 val; - u32 mode; - u32 encourage_lo; - u32 encourage_hi; - bool is_on; - int ret; - - ret = jh71xx_pmu_get_state(pmd, mask, &is_on); - if (ret) { - dev_dbg(pmu->dev, "unable to get current state for %s\n", - pmd->genpd.name); - return ret; - } - - if (is_on == on) { - dev_dbg(pmu->dev, "pm domain [%s] is already %sable status.\n", - pmd->genpd.name, on ? "en" : "dis"); - return 0; - } - - spin_lock_irqsave(&pmu->lock, flags); - - /* - * The PMU accepts software encourage to switch power mode in the following 2 steps: - * - * 1.Configure the register SW_TURN_ON_POWER (offset 0x0c) by writing 1 to - * the bit corresponding to the power domain that will be turned on - * and writing 0 to the others. - * Likewise, configure the register SW_TURN_OFF_POWER (offset 0x10) by - * writing 1 to the bit corresponding to the power domain that will be - * turned off and writing 0 to the others. - */ - if (on) { - mode = JH71XX_PMU_SW_TURN_ON_POWER; - encourage_lo = JH71XX_PMU_SW_ENCOURAGE_EN_LO; - encourage_hi = JH71XX_PMU_SW_ENCOURAGE_EN_HI; - } else { - mode = JH71XX_PMU_SW_TURN_OFF_POWER; - encourage_lo = JH71XX_PMU_SW_ENCOURAGE_DIS_LO; - encourage_hi = JH71XX_PMU_SW_ENCOURAGE_DIS_HI; - } - - writel(mask, pmu->base + mode); - - /* - * 2.Write SW encourage command sequence to the Software Encourage Reg (offset 0x44) - * First write SW_MODE_ENCOURAGE_ON to JH71XX_PMU_SW_ENCOURAGE. This will reset - * the state machine which parses the command sequence. This register must be - * written every time software wants to power on/off a domain. - * Then write the lower bits of the command sequence, followed by the upper - * bits. The sequence differs between powering on & off a domain. - */ - writel(JH71XX_PMU_SW_ENCOURAGE_ON, pmu->base + JH71XX_PMU_SW_ENCOURAGE); - writel(encourage_lo, pmu->base + JH71XX_PMU_SW_ENCOURAGE); - writel(encourage_hi, pmu->base + JH71XX_PMU_SW_ENCOURAGE); - - spin_unlock_irqrestore(&pmu->lock, flags); - - /* Wait for the power domain bit to be enabled / disabled */ - if (on) { - ret = readl_poll_timeout_atomic(pmu->base + JH71XX_PMU_CURR_POWER_MODE, - val, val & mask, - 1, JH71XX_PMU_TIMEOUT_US); - } else { - ret = readl_poll_timeout_atomic(pmu->base + JH71XX_PMU_CURR_POWER_MODE, - val, !(val & mask), - 1, JH71XX_PMU_TIMEOUT_US); - } - - if (ret) { - dev_err(pmu->dev, "%s: failed to power %s\n", - pmd->genpd.name, on ? "on" : "off"); - return -ETIMEDOUT; - } - - return 0; -} - -static int jh71xx_pmu_on(struct generic_pm_domain *genpd) -{ - struct jh71xx_pmu_dev *pmd = container_of(genpd, - struct jh71xx_pmu_dev, genpd); - u32 pwr_mask = BIT(pmd->domain_info->bit); - - return jh71xx_pmu_set_state(pmd, pwr_mask, true); -} - -static int jh71xx_pmu_off(struct generic_pm_domain *genpd) -{ - struct jh71xx_pmu_dev *pmd = container_of(genpd, - struct jh71xx_pmu_dev, genpd); - u32 pwr_mask = BIT(pmd->domain_info->bit); - - return jh71xx_pmu_set_state(pmd, pwr_mask, false); -} - -static void jh71xx_pmu_int_enable(struct jh71xx_pmu *pmu, u32 mask, bool enable) -{ - u32 val; - unsigned long flags; - - spin_lock_irqsave(&pmu->lock, flags); - val = readl(pmu->base + JH71XX_PMU_TIMER_INT_MASK); - - if (enable) - val &= ~mask; - else - val |= mask; - - writel(val, pmu->base + JH71XX_PMU_TIMER_INT_MASK); - spin_unlock_irqrestore(&pmu->lock, flags); -} - -static irqreturn_t jh71xx_pmu_interrupt(int irq, void *data) -{ - struct jh71xx_pmu *pmu = data; - u32 val; - - val = readl(pmu->base + JH71XX_PMU_INT_STATUS); - - if (val & JH71XX_PMU_INT_SEQ_DONE) - dev_dbg(pmu->dev, "sequence done.\n"); - if (val & JH71XX_PMU_INT_HW_REQ) - dev_dbg(pmu->dev, "hardware encourage requestion.\n"); - if (val & JH71XX_PMU_INT_SW_FAIL) - dev_err(pmu->dev, "software encourage fail.\n"); - if (val & JH71XX_PMU_INT_HW_FAIL) - dev_err(pmu->dev, "hardware encourage fail.\n"); - if (val & JH71XX_PMU_INT_PCH_FAIL) - dev_err(pmu->dev, "p-channel fail event.\n"); - - /* clear interrupts */ - writel(val, pmu->base + JH71XX_PMU_INT_STATUS); - writel(val, pmu->base + JH71XX_PMU_EVENT_STATUS); - - return IRQ_HANDLED; -} - -static int jh71xx_pmu_init_domain(struct jh71xx_pmu *pmu, int index) -{ - struct jh71xx_pmu_dev *pmd; - u32 pwr_mask; - int ret; - bool is_on = false; - - pmd = devm_kzalloc(pmu->dev, sizeof(*pmd), GFP_KERNEL); - if (!pmd) - return -ENOMEM; - - pmd->domain_info = &pmu->match_data->domain_info[index]; - pmd->pmu = pmu; - pwr_mask = BIT(pmd->domain_info->bit); - - pmd->genpd.name = pmd->domain_info->name; - pmd->genpd.flags = pmd->domain_info->flags; - - ret = jh71xx_pmu_get_state(pmd, pwr_mask, &is_on); - if (ret) - dev_warn(pmu->dev, "unable to get current state for %s\n", - pmd->genpd.name); - - pmd->genpd.power_on = jh71xx_pmu_on; - pmd->genpd.power_off = jh71xx_pmu_off; - pm_genpd_init(&pmd->genpd, NULL, !is_on); - - pmu->genpd_data.domains[index] = &pmd->genpd; - - return 0; -} - -static int jh71xx_pmu_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - const struct jh71xx_pmu_match_data *match_data; - struct jh71xx_pmu *pmu; - unsigned int i; - int ret; - - pmu = devm_kzalloc(dev, sizeof(*pmu), GFP_KERNEL); - if (!pmu) - return -ENOMEM; - - pmu->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(pmu->base)) - return PTR_ERR(pmu->base); - - pmu->irq = platform_get_irq(pdev, 0); - if (pmu->irq < 0) - return pmu->irq; - - ret = devm_request_irq(dev, pmu->irq, jh71xx_pmu_interrupt, - 0, pdev->name, pmu); - if (ret) - dev_err(dev, "failed to request irq\n"); - - match_data = of_device_get_match_data(dev); - if (!match_data) - return -EINVAL; - - pmu->genpd = devm_kcalloc(dev, match_data->num_domains, - sizeof(struct generic_pm_domain *), - GFP_KERNEL); - if (!pmu->genpd) - return -ENOMEM; - - pmu->dev = dev; - pmu->match_data = match_data; - pmu->genpd_data.domains = pmu->genpd; - pmu->genpd_data.num_domains = match_data->num_domains; - - for (i = 0; i < match_data->num_domains; i++) { - ret = jh71xx_pmu_init_domain(pmu, i); - if (ret) { - dev_err(dev, "failed to initialize power domain\n"); - return ret; - } - } - - spin_lock_init(&pmu->lock); - jh71xx_pmu_int_enable(pmu, JH71XX_PMU_INT_ALL_MASK & ~JH71XX_PMU_INT_PCH_FAIL, true); - - ret = of_genpd_add_provider_onecell(np, &pmu->genpd_data); - if (ret) { - dev_err(dev, "failed to register genpd driver: %d\n", ret); - return ret; - } - - dev_dbg(dev, "registered %u power domains\n", i); - - return 0; -} - -static const struct jh71xx_domain_info jh7110_power_domains[] = { - [JH7110_PD_SYSTOP] = { - .name = "SYSTOP", - .bit = 0, - .flags = GENPD_FLAG_ALWAYS_ON, - }, - [JH7110_PD_CPU] = { - .name = "CPU", - .bit = 1, - .flags = GENPD_FLAG_ALWAYS_ON, - }, - [JH7110_PD_GPUA] = { - .name = "GPUA", - .bit = 2, - }, - [JH7110_PD_VDEC] = { - .name = "VDEC", - .bit = 3, - }, - [JH7110_PD_VOUT] = { - .name = "VOUT", - .bit = 4, - }, - [JH7110_PD_ISP] = { - .name = "ISP", - .bit = 5, - }, - [JH7110_PD_VENC] = { - .name = "VENC", - .bit = 6, - }, -}; - -static const struct jh71xx_pmu_match_data jh7110_pmu = { - .num_domains = ARRAY_SIZE(jh7110_power_domains), - .domain_info = jh7110_power_domains, -}; - -static const struct of_device_id jh71xx_pmu_of_match[] = { - { - .compatible = "starfive,jh7110-pmu", - .data = (void *)&jh7110_pmu, - }, { - /* sentinel */ - } -}; - -static struct platform_driver jh71xx_pmu_driver = { - .probe = jh71xx_pmu_probe, - .driver = { - .name = "jh71xx-pmu", - .of_match_table = jh71xx_pmu_of_match, - .suppress_bind_attrs = true, - }, -}; -builtin_platform_driver(jh71xx_pmu_driver); - -MODULE_AUTHOR("Walker Chen <walker.chen@starfivetech.com>"); -MODULE_DESCRIPTION("StarFive JH71XX PMU Driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/soc/sunxi/Makefile b/drivers/soc/sunxi/Makefile index 90ff2ebe7655..549159571d4f 100644 --- a/drivers/soc/sunxi/Makefile +++ b/drivers/soc/sunxi/Makefile @@ -1,4 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_SUNXI_MBUS) += sunxi_mbus.o obj-$(CONFIG_SUNXI_SRAM) += sunxi_sram.o -obj-$(CONFIG_SUN20I_PPU) += sun20i-ppu.o diff --git a/drivers/soc/sunxi/sun20i-ppu.c b/drivers/soc/sunxi/sun20i-ppu.c deleted file mode 100644 index 98cb41d36560..000000000000 --- a/drivers/soc/sunxi/sun20i-ppu.c +++ /dev/null @@ -1,207 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only - -#include <linux/bitfield.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/iopoll.h> -#include <linux/module.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <linux/reset.h> - -#define PD_STATE_ON 1 -#define PD_STATE_OFF 2 - -#define PD_RSTN_REG 0x00 -#define PD_CLK_GATE_REG 0x04 -#define PD_PWROFF_GATE_REG 0x08 -#define PD_PSW_ON_REG 0x0c -#define PD_PSW_OFF_REG 0x10 -#define PD_PSW_DELAY_REG 0x14 -#define PD_OFF_DELAY_REG 0x18 -#define PD_ON_DELAY_REG 0x1c -#define PD_COMMAND_REG 0x20 -#define PD_STATUS_REG 0x24 -#define PD_STATUS_COMPLETE BIT(1) -#define PD_STATUS_BUSY BIT(3) -#define PD_STATUS_STATE GENMASK(17, 16) -#define PD_ACTIVE_CTRL_REG 0x2c -#define PD_GATE_STATUS_REG 0x30 -#define PD_RSTN_STATUS BIT(0) -#define PD_CLK_GATE_STATUS BIT(1) -#define PD_PWROFF_GATE_STATUS BIT(2) -#define PD_PSW_STATUS_REG 0x34 - -#define PD_REGS_SIZE 0x80 - -struct sun20i_ppu_desc { - const char *const *names; - unsigned int num_domains; -}; - -struct sun20i_ppu_pd { - struct generic_pm_domain genpd; - void __iomem *base; -}; - -#define to_sun20i_ppu_pd(_genpd) \ - container_of(_genpd, struct sun20i_ppu_pd, genpd) - -static bool sun20i_ppu_pd_is_on(const struct sun20i_ppu_pd *pd) -{ - u32 status = readl(pd->base + PD_STATUS_REG); - - return FIELD_GET(PD_STATUS_STATE, status) == PD_STATE_ON; -} - -static int sun20i_ppu_pd_set_power(const struct sun20i_ppu_pd *pd, bool power_on) -{ - u32 state, status; - int ret; - - if (sun20i_ppu_pd_is_on(pd) == power_on) - return 0; - - /* Wait for the power controller to be idle. */ - ret = readl_poll_timeout(pd->base + PD_STATUS_REG, status, - !(status & PD_STATUS_BUSY), 100, 1000); - if (ret) - return ret; - - state = power_on ? PD_STATE_ON : PD_STATE_OFF; - writel(state, pd->base + PD_COMMAND_REG); - - /* Wait for the state transition to complete. */ - ret = readl_poll_timeout(pd->base + PD_STATUS_REG, status, - FIELD_GET(PD_STATUS_STATE, status) == state && - (status & PD_STATUS_COMPLETE), 100, 1000); - if (ret) - return ret; - - /* Clear the completion flag. */ - writel(status, pd->base + PD_STATUS_REG); - - return 0; -} - -static int sun20i_ppu_pd_power_on(struct generic_pm_domain *genpd) -{ - const struct sun20i_ppu_pd *pd = to_sun20i_ppu_pd(genpd); - - return sun20i_ppu_pd_set_power(pd, true); -} - -static int sun20i_ppu_pd_power_off(struct generic_pm_domain *genpd) -{ - const struct sun20i_ppu_pd *pd = to_sun20i_ppu_pd(genpd); - - return sun20i_ppu_pd_set_power(pd, false); -} - -static int sun20i_ppu_probe(struct platform_device *pdev) -{ - const struct sun20i_ppu_desc *desc; - struct device *dev = &pdev->dev; - struct genpd_onecell_data *ppu; - struct sun20i_ppu_pd *pds; - struct reset_control *rst; - void __iomem *base; - struct clk *clk; - int ret; - - desc = of_device_get_match_data(dev); - if (!desc) - return -EINVAL; - - pds = devm_kcalloc(dev, desc->num_domains, sizeof(*pds), GFP_KERNEL); - if (!pds) - return -ENOMEM; - - ppu = devm_kzalloc(dev, sizeof(*ppu), GFP_KERNEL); - if (!ppu) - return -ENOMEM; - - ppu->domains = devm_kcalloc(dev, desc->num_domains, - sizeof(*ppu->domains), GFP_KERNEL); - if (!ppu->domains) - return -ENOMEM; - - ppu->num_domains = desc->num_domains; - platform_set_drvdata(pdev, ppu); - - base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(base)) - return PTR_ERR(base); - - clk = devm_clk_get_enabled(dev, NULL); - if (IS_ERR(clk)) - return PTR_ERR(clk); - - rst = devm_reset_control_get_exclusive(dev, NULL); - if (IS_ERR(rst)) - return PTR_ERR(rst); - - ret = reset_control_deassert(rst); - if (ret) - return ret; - - for (unsigned int i = 0; i < ppu->num_domains; ++i) { - struct sun20i_ppu_pd *pd = &pds[i]; - - pd->genpd.name = desc->names[i]; - pd->genpd.power_off = sun20i_ppu_pd_power_off; - pd->genpd.power_on = sun20i_ppu_pd_power_on; - pd->base = base + PD_REGS_SIZE * i; - - ret = pm_genpd_init(&pd->genpd, NULL, sun20i_ppu_pd_is_on(pd)); - if (ret) { - dev_warn(dev, "Failed to add '%s' domain: %d\n", - pd->genpd.name, ret); - continue; - } - - ppu->domains[i] = &pd->genpd; - } - - ret = of_genpd_add_provider_onecell(dev->of_node, ppu); - if (ret) - dev_warn(dev, "Failed to add provider: %d\n", ret); - - return 0; -} - -static const char *const sun20i_d1_ppu_pd_names[] = { - "CPU", - "VE", - "DSP", -}; - -static const struct sun20i_ppu_desc sun20i_d1_ppu_desc = { - .names = sun20i_d1_ppu_pd_names, - .num_domains = ARRAY_SIZE(sun20i_d1_ppu_pd_names), -}; - -static const struct of_device_id sun20i_ppu_of_match[] = { - { - .compatible = "allwinner,sun20i-d1-ppu", - .data = &sun20i_d1_ppu_desc, - }, - { } -}; -MODULE_DEVICE_TABLE(of, sun20i_ppu_of_match); - -static struct platform_driver sun20i_ppu_driver = { - .probe = sun20i_ppu_probe, - .driver = { - .name = "sun20i-ppu", - .of_match_table = sun20i_ppu_of_match, - /* Power domains cannot be removed while they are in use. */ - .suppress_bind_attrs = true, - }, -}; -module_platform_driver(sun20i_ppu_driver); - -MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>"); -MODULE_DESCRIPTION("Allwinner D1 PPU power domain driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/soc/tegra/Makefile b/drivers/soc/tegra/Makefile index d722f512dc9d..01059619e764 100644 --- a/drivers/soc/tegra/Makefile +++ b/drivers/soc/tegra/Makefile @@ -5,7 +5,6 @@ obj-y += cbb/ obj-y += common.o obj-$(CONFIG_SOC_TEGRA_FLOWCTRL) += flowctrl.o obj-$(CONFIG_SOC_TEGRA_PMC) += pmc.o -obj-$(CONFIG_SOC_TEGRA_POWERGATE_BPMP) += powergate-bpmp.o obj-$(CONFIG_SOC_TEGRA20_VOLTAGE_COUPLER) += regulators-tegra20.o obj-$(CONFIG_SOC_TEGRA30_VOLTAGE_COUPLER) += regulators-tegra30.o obj-$(CONFIG_ARCH_TEGRA_186_SOC) += ari-tegra186.o diff --git a/drivers/soc/tegra/powergate-bpmp.c b/drivers/soc/tegra/powergate-bpmp.c deleted file mode 100644 index 179ed895c279..000000000000 --- a/drivers/soc/tegra/powergate-bpmp.c +++ /dev/null @@ -1,361 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved - */ - -#include <linux/of.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <linux/slab.h> - -#include <soc/tegra/bpmp.h> -#include <soc/tegra/bpmp-abi.h> - -struct tegra_powergate_info { - unsigned int id; - char *name; -}; - -struct tegra_powergate { - struct generic_pm_domain genpd; - struct tegra_bpmp *bpmp; - unsigned int id; -}; - -static inline struct tegra_powergate * -to_tegra_powergate(struct generic_pm_domain *genpd) -{ - return container_of(genpd, struct tegra_powergate, genpd); -} - -static int tegra_bpmp_powergate_set_state(struct tegra_bpmp *bpmp, - unsigned int id, u32 state) -{ - struct mrq_pg_request request; - struct tegra_bpmp_message msg; - int err; - - memset(&request, 0, sizeof(request)); - request.cmd = CMD_PG_SET_STATE; - request.id = id; - request.set_state.state = state; - - memset(&msg, 0, sizeof(msg)); - msg.mrq = MRQ_PG; - msg.tx.data = &request; - msg.tx.size = sizeof(request); - - err = tegra_bpmp_transfer(bpmp, &msg); - if (err < 0) - return err; - else if (msg.rx.ret < 0) - return -EINVAL; - - return 0; -} - -static int tegra_bpmp_powergate_get_state(struct tegra_bpmp *bpmp, - unsigned int id) -{ - struct mrq_pg_response response; - struct mrq_pg_request request; - struct tegra_bpmp_message msg; - int err; - - memset(&request, 0, sizeof(request)); - request.cmd = CMD_PG_GET_STATE; - request.id = id; - - memset(&response, 0, sizeof(response)); - - memset(&msg, 0, sizeof(msg)); - msg.mrq = MRQ_PG; - msg.tx.data = &request; - msg.tx.size = sizeof(request); - msg.rx.data = &response; - msg.rx.size = sizeof(response); - - err = tegra_bpmp_transfer(bpmp, &msg); - if (err < 0) - return PG_STATE_OFF; - else if (msg.rx.ret < 0) - return -EINVAL; - - return response.get_state.state; -} - -static int tegra_bpmp_powergate_get_max_id(struct tegra_bpmp *bpmp) -{ - struct mrq_pg_response response; - struct mrq_pg_request request; - struct tegra_bpmp_message msg; - int err; - - memset(&request, 0, sizeof(request)); - request.cmd = CMD_PG_GET_MAX_ID; - - memset(&response, 0, sizeof(response)); - - memset(&msg, 0, sizeof(msg)); - msg.mrq = MRQ_PG; - msg.tx.data = &request; - msg.tx.size = sizeof(request); - msg.rx.data = &response; - msg.rx.size = sizeof(response); - - err = tegra_bpmp_transfer(bpmp, &msg); - if (err < 0) - return err; - else if (msg.rx.ret < 0) - return -EINVAL; - - return response.get_max_id.max_id; -} - -static char *tegra_bpmp_powergate_get_name(struct tegra_bpmp *bpmp, - unsigned int id) -{ - struct mrq_pg_response response; - struct mrq_pg_request request; - struct tegra_bpmp_message msg; - int err; - - memset(&request, 0, sizeof(request)); - request.cmd = CMD_PG_GET_NAME; - request.id = id; - - memset(&response, 0, sizeof(response)); - - memset(&msg, 0, sizeof(msg)); - msg.mrq = MRQ_PG; - msg.tx.data = &request; - msg.tx.size = sizeof(request); - msg.rx.data = &response; - msg.rx.size = sizeof(response); - - err = tegra_bpmp_transfer(bpmp, &msg); - if (err < 0 || msg.rx.ret < 0) - return NULL; - - return kstrdup(response.get_name.name, GFP_KERNEL); -} - -static inline bool tegra_bpmp_powergate_is_powered(struct tegra_bpmp *bpmp, - unsigned int id) -{ - return tegra_bpmp_powergate_get_state(bpmp, id) != PG_STATE_OFF; -} - -static int tegra_powergate_power_on(struct generic_pm_domain *domain) -{ - struct tegra_powergate *powergate = to_tegra_powergate(domain); - struct tegra_bpmp *bpmp = powergate->bpmp; - - return tegra_bpmp_powergate_set_state(bpmp, powergate->id, - PG_STATE_ON); -} - -static int tegra_powergate_power_off(struct generic_pm_domain *domain) -{ - struct tegra_powergate *powergate = to_tegra_powergate(domain); - struct tegra_bpmp *bpmp = powergate->bpmp; - - return tegra_bpmp_powergate_set_state(bpmp, powergate->id, - PG_STATE_OFF); -} - -static struct tegra_powergate * -tegra_powergate_add(struct tegra_bpmp *bpmp, - const struct tegra_powergate_info *info) -{ - struct tegra_powergate *powergate; - bool off; - int err; - - off = !tegra_bpmp_powergate_is_powered(bpmp, info->id); - - powergate = devm_kzalloc(bpmp->dev, sizeof(*powergate), GFP_KERNEL); - if (!powergate) - return ERR_PTR(-ENOMEM); - - powergate->id = info->id; - powergate->bpmp = bpmp; - - powergate->genpd.name = kstrdup(info->name, GFP_KERNEL); - powergate->genpd.power_on = tegra_powergate_power_on; - powergate->genpd.power_off = tegra_powergate_power_off; - - err = pm_genpd_init(&powergate->genpd, NULL, off); - if (err < 0) { - kfree(powergate->genpd.name); - return ERR_PTR(err); - } - - return powergate; -} - -static void tegra_powergate_remove(struct tegra_powergate *powergate) -{ - struct generic_pm_domain *genpd = &powergate->genpd; - struct tegra_bpmp *bpmp = powergate->bpmp; - int err; - - err = pm_genpd_remove(genpd); - if (err < 0) - dev_err(bpmp->dev, "failed to remove power domain %s: %d\n", - genpd->name, err); - - kfree(genpd->name); -} - -static int -tegra_bpmp_probe_powergates(struct tegra_bpmp *bpmp, - struct tegra_powergate_info **powergatesp) -{ - struct tegra_powergate_info *powergates; - unsigned int max_id, id, count = 0; - unsigned int num_holes = 0; - int err; - - err = tegra_bpmp_powergate_get_max_id(bpmp); - if (err < 0) - return err; - - max_id = err; - - dev_dbg(bpmp->dev, "maximum powergate ID: %u\n", max_id); - - powergates = kcalloc(max_id + 1, sizeof(*powergates), GFP_KERNEL); - if (!powergates) - return -ENOMEM; - - for (id = 0; id <= max_id; id++) { - struct tegra_powergate_info *info = &powergates[count]; - - info->name = tegra_bpmp_powergate_get_name(bpmp, id); - if (!info->name || info->name[0] == '\0') { - num_holes++; - continue; - } - - info->id = id; - count++; - } - - dev_dbg(bpmp->dev, "holes: %u\n", num_holes); - - *powergatesp = powergates; - - return count; -} - -static int tegra_bpmp_add_powergates(struct tegra_bpmp *bpmp, - struct tegra_powergate_info *powergates, - unsigned int count) -{ - struct genpd_onecell_data *genpd = &bpmp->genpd; - struct generic_pm_domain **domains; - struct tegra_powergate *powergate; - unsigned int i; - int err; - - domains = kcalloc(count, sizeof(*domains), GFP_KERNEL); - if (!domains) - return -ENOMEM; - - for (i = 0; i < count; i++) { - powergate = tegra_powergate_add(bpmp, &powergates[i]); - if (IS_ERR(powergate)) { - err = PTR_ERR(powergate); - goto remove; - } - - dev_dbg(bpmp->dev, "added power domain %s\n", - powergate->genpd.name); - domains[i] = &powergate->genpd; - } - - genpd->num_domains = count; - genpd->domains = domains; - - return 0; - -remove: - while (i--) { - powergate = to_tegra_powergate(domains[i]); - tegra_powergate_remove(powergate); - } - - kfree(domains); - return err; -} - -static void tegra_bpmp_remove_powergates(struct tegra_bpmp *bpmp) -{ - struct genpd_onecell_data *genpd = &bpmp->genpd; - unsigned int i = genpd->num_domains; - struct tegra_powergate *powergate; - - while (i--) { - dev_dbg(bpmp->dev, "removing power domain %s\n", - genpd->domains[i]->name); - powergate = to_tegra_powergate(genpd->domains[i]); - tegra_powergate_remove(powergate); - } -} - -static struct generic_pm_domain * -tegra_powergate_xlate(struct of_phandle_args *spec, void *data) -{ - struct generic_pm_domain *domain = ERR_PTR(-ENOENT); - struct genpd_onecell_data *genpd = data; - unsigned int i; - - for (i = 0; i < genpd->num_domains; i++) { - struct tegra_powergate *powergate; - - powergate = to_tegra_powergate(genpd->domains[i]); - if (powergate->id == spec->args[0]) { - domain = &powergate->genpd; - break; - } - } - - return domain; -} - -int tegra_bpmp_init_powergates(struct tegra_bpmp *bpmp) -{ - struct device_node *np = bpmp->dev->of_node; - struct tegra_powergate_info *powergates; - struct device *dev = bpmp->dev; - unsigned int count, i; - int err; - - err = tegra_bpmp_probe_powergates(bpmp, &powergates); - if (err < 0) - return err; - - count = err; - - dev_dbg(dev, "%u power domains probed\n", count); - - err = tegra_bpmp_add_powergates(bpmp, powergates, count); - if (err < 0) - goto free; - - bpmp->genpd.xlate = tegra_powergate_xlate; - - err = of_genpd_add_provider_onecell(np, &bpmp->genpd); - if (err < 0) { - dev_err(dev, "failed to add power domain provider: %d\n", err); - tegra_bpmp_remove_powergates(bpmp); - } - -free: - for (i = 0; i < count; i++) - kfree(powergates[i].name); - - kfree(powergates); - return err; -} diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile index cc3c972fad2e..cb800a745e66 100644 --- a/drivers/soc/ti/Makefile +++ b/drivers/soc/ti/Makefile @@ -6,9 +6,7 @@ obj-$(CONFIG_KEYSTONE_NAVIGATOR_QMSS) += knav_qmss.o knav_qmss-y := knav_qmss_queue.o knav_qmss_acc.o obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA) += knav_dma.o obj-$(CONFIG_AMX3_PM) += pm33xx.o -obj-$(CONFIG_ARCH_OMAP2PLUS) += omap_prm.o obj-$(CONFIG_WKUP_M3_IPC) += wkup_m3_ipc.o -obj-$(CONFIG_TI_SCI_PM_DOMAINS) += ti_sci_pm_domains.o obj-$(CONFIG_TI_SCI_INTA_MSI_DOMAIN) += ti_sci_inta_msi.o obj-$(CONFIG_TI_K3_RINGACC) += k3-ringacc.o obj-$(CONFIG_TI_K3_SOCINFO) += k3-socinfo.o diff --git a/drivers/soc/ti/omap_prm.c b/drivers/soc/ti/omap_prm.c deleted file mode 100644 index ecd9a8bdd7c0..000000000000 --- a/drivers/soc/ti/omap_prm.c +++ /dev/null @@ -1,994 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * OMAP2+ PRM driver - * - * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ - * Tero Kristo <t-kristo@ti.com> - */ - -#include <linux/kernel.h> -#include <linux/clk.h> -#include <linux/device.h> -#include <linux/io.h> -#include <linux/iopoll.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/pm_clock.h> -#include <linux/pm_domain.h> -#include <linux/reset-controller.h> -#include <linux/delay.h> - -#include <linux/platform_data/ti-prm.h> - -enum omap_prm_domain_mode { - OMAP_PRMD_OFF, - OMAP_PRMD_RETENTION, - OMAP_PRMD_ON_INACTIVE, - OMAP_PRMD_ON_ACTIVE, -}; - -struct omap_prm_domain_map { - unsigned int usable_modes; /* Mask of hardware supported modes */ - unsigned long statechange:1; /* Optional low-power state change */ - unsigned long logicretstate:1; /* Optional logic off mode */ -}; - -struct omap_prm_domain { - struct device *dev; - struct omap_prm *prm; - struct generic_pm_domain pd; - u16 pwrstctrl; - u16 pwrstst; - const struct omap_prm_domain_map *cap; - u32 pwrstctrl_saved; - unsigned int uses_pm_clk:1; -}; - -struct omap_rst_map { - s8 rst; - s8 st; -}; - -struct omap_prm_data { - u32 base; - const char *name; - const char *clkdm_name; - u16 pwrstctrl; - u16 pwrstst; - const struct omap_prm_domain_map *dmap; - u16 rstctrl; - u16 rstst; - const struct omap_rst_map *rstmap; - u8 flags; -}; - -struct omap_prm { - const struct omap_prm_data *data; - void __iomem *base; - struct omap_prm_domain *prmd; -}; - -struct omap_reset_data { - struct reset_controller_dev rcdev; - struct omap_prm *prm; - u32 mask; - spinlock_t lock; - struct clockdomain *clkdm; - struct device *dev; -}; - -#define genpd_to_prm_domain(gpd) container_of(gpd, struct omap_prm_domain, pd) -#define to_omap_reset_data(p) container_of((p), struct omap_reset_data, rcdev) - -#define OMAP_MAX_RESETS 8 -#define OMAP_RESET_MAX_WAIT 10000 - -#define OMAP_PRM_HAS_RSTCTRL BIT(0) -#define OMAP_PRM_HAS_RSTST BIT(1) -#define OMAP_PRM_HAS_NO_CLKDM BIT(2) -#define OMAP_PRM_RET_WHEN_IDLE BIT(3) - -#define OMAP_PRM_HAS_RESETS (OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_RSTST) - -#define PRM_STATE_MAX_WAIT 10000 -#define PRM_LOGICRETSTATE BIT(2) -#define PRM_LOWPOWERSTATECHANGE BIT(4) -#define PRM_POWERSTATE_MASK OMAP_PRMD_ON_ACTIVE - -#define PRM_ST_INTRANSITION BIT(20) - -static const struct omap_prm_domain_map omap_prm_all = { - .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_ON_INACTIVE) | - BIT(OMAP_PRMD_RETENTION) | BIT(OMAP_PRMD_OFF), - .statechange = 1, - .logicretstate = 1, -}; - -static const struct omap_prm_domain_map omap_prm_noinact = { - .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_RETENTION) | - BIT(OMAP_PRMD_OFF), - .statechange = 1, - .logicretstate = 1, -}; - -static const struct omap_prm_domain_map omap_prm_nooff = { - .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_ON_INACTIVE) | - BIT(OMAP_PRMD_RETENTION), - .statechange = 1, - .logicretstate = 1, -}; - -static const struct omap_prm_domain_map omap_prm_onoff_noauto = { - .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_OFF), - .statechange = 1, -}; - -static const struct omap_prm_domain_map omap_prm_alwon = { - .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE), -}; - -static const struct omap_prm_domain_map omap_prm_reton = { - .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_RETENTION), - .statechange = 1, - .logicretstate = 1, -}; - -static const struct omap_rst_map rst_map_0[] = { - { .rst = 0, .st = 0 }, - { .rst = -1 }, -}; - -static const struct omap_rst_map rst_map_01[] = { - { .rst = 0, .st = 0 }, - { .rst = 1, .st = 1 }, - { .rst = -1 }, -}; - -static const struct omap_rst_map rst_map_012[] = { - { .rst = 0, .st = 0 }, - { .rst = 1, .st = 1 }, - { .rst = 2, .st = 2 }, - { .rst = -1 }, -}; - -static const struct omap_prm_data omap4_prm_data[] = { - { - .name = "mpu", .base = 0x4a306300, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton, - }, - { - .name = "tesla", .base = 0x4a306400, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact, - .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 - }, - { - .name = "abe", .base = 0x4a306500, - .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_all, - }, - { - .name = "always_on_core", .base = 0x4a306600, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, - }, - { - .name = "core", .base = 0x4a306700, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton, - .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ducati", - .rstmap = rst_map_012, - .flags = OMAP_PRM_RET_WHEN_IDLE, - }, - { - .name = "ivahd", .base = 0x4a306f00, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact, - .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012 - }, - { - .name = "cam", .base = 0x4a307000, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, - }, - { - .name = "dss", .base = 0x4a307100, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact - }, - { - .name = "gfx", .base = 0x4a307200, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto - }, - { - .name = "l3init", .base = 0x4a307300, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton - }, - { - .name = "l4per", .base = 0x4a307400, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton, - .flags = OMAP_PRM_RET_WHEN_IDLE, - }, - { - .name = "cefuse", .base = 0x4a307600, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto - }, - { - .name = "wkup", .base = 0x4a307700, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon - }, - { - .name = "emu", .base = 0x4a307900, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto - }, - { - .name = "device", .base = 0x4a307b00, - .rstctrl = 0x0, .rstst = 0x4, .rstmap = rst_map_01, - .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM - }, - { }, -}; - -static const struct omap_prm_data omap5_prm_data[] = { - { - .name = "mpu", .base = 0x4ae06300, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton, - }, - { - .name = "dsp", .base = 0x4ae06400, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact, - .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 - }, - { - .name = "abe", .base = 0x4ae06500, - .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_nooff, - }, - { - .name = "coreaon", .base = 0x4ae06600, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon - }, - { - .name = "core", .base = 0x4ae06700, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton, - .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ipu", - .rstmap = rst_map_012 - }, - { - .name = "iva", .base = 0x4ae07200, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact, - .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012 - }, - { - .name = "cam", .base = 0x4ae07300, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto - }, - { - .name = "dss", .base = 0x4ae07400, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact - }, - { - .name = "gpu", .base = 0x4ae07500, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto - }, - { - .name = "l3init", .base = 0x4ae07600, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton - }, - { - .name = "custefuse", .base = 0x4ae07700, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto - }, - { - .name = "wkupaon", .base = 0x4ae07800, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon - }, - { - .name = "emu", .base = 0x4ae07a00, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto - }, - { - .name = "device", .base = 0x4ae07c00, - .rstctrl = 0x0, .rstst = 0x4, .rstmap = rst_map_01, - .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM - }, - { }, -}; - -static const struct omap_prm_data dra7_prm_data[] = { - { - .name = "mpu", .base = 0x4ae06300, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton, - }, - { - .name = "dsp1", .base = 0x4ae06400, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, - .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01, - }, - { - .name = "ipu", .base = 0x4ae06500, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, - .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012, - .clkdm_name = "ipu1" - }, - { - .name = "coreaon", .base = 0x4ae06628, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, - }, - { - .name = "core", .base = 0x4ae06700, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, - .rstctrl = 0x210, .rstst = 0x214, .rstmap = rst_map_012, - .clkdm_name = "ipu2" - }, - { - .name = "iva", .base = 0x4ae06f00, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, - .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012, - }, - { - .name = "cam", .base = 0x4ae07000, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, - }, - { - .name = "dss", .base = 0x4ae07100, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, - }, - { - .name = "gpu", .base = 0x4ae07200, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, - }, - { - .name = "l3init", .base = 0x4ae07300, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, - .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01, - .clkdm_name = "pcie" - }, - { - .name = "l4per", .base = 0x4ae07400, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, - }, - { - .name = "custefuse", .base = 0x4ae07600, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, - }, - { - .name = "wkupaon", .base = 0x4ae07724, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, - }, - { - .name = "emu", .base = 0x4ae07900, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, - }, - { - .name = "dsp2", .base = 0x4ae07b00, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, - .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 - }, - { - .name = "eve1", .base = 0x4ae07b40, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, - .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 - }, - { - .name = "eve2", .base = 0x4ae07b80, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, - .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 - }, - { - .name = "eve3", .base = 0x4ae07bc0, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, - .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 - }, - { - .name = "eve4", .base = 0x4ae07c00, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, - .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 - }, - { - .name = "rtc", .base = 0x4ae07c60, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, - }, - { - .name = "vpe", .base = 0x4ae07c80, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, - }, - { }, -}; - -static const struct omap_rst_map am3_per_rst_map[] = { - { .rst = 1 }, - { .rst = -1 }, -}; - -static const struct omap_rst_map am3_wkup_rst_map[] = { - { .rst = 3, .st = 5 }, - { .rst = -1 }, -}; - -static const struct omap_prm_data am3_prm_data[] = { - { - .name = "per", .base = 0x44e00c00, - .pwrstctrl = 0xc, .pwrstst = 0x8, .dmap = &omap_prm_noinact, - .rstctrl = 0x0, .rstmap = am3_per_rst_map, - .flags = OMAP_PRM_HAS_RSTCTRL, .clkdm_name = "pruss_ocp" - }, - { - .name = "wkup", .base = 0x44e00d00, - .pwrstctrl = 0x4, .pwrstst = 0x4, .dmap = &omap_prm_alwon, - .rstctrl = 0x0, .rstst = 0xc, .rstmap = am3_wkup_rst_map, - .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM - }, - { - .name = "mpu", .base = 0x44e00e00, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact, - }, - { - .name = "device", .base = 0x44e00f00, - .rstctrl = 0x0, .rstst = 0x8, .rstmap = rst_map_01, - .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM - }, - { - .name = "rtc", .base = 0x44e01000, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, - }, - { - .name = "gfx", .base = 0x44e01100, - .pwrstctrl = 0, .pwrstst = 0x10, .dmap = &omap_prm_noinact, - .rstctrl = 0x4, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3", - }, - { - .name = "cefuse", .base = 0x44e01200, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, - }, - { }, -}; - -static const struct omap_rst_map am4_per_rst_map[] = { - { .rst = 1, .st = 0 }, - { .rst = -1 }, -}; - -static const struct omap_rst_map am4_device_rst_map[] = { - { .rst = 0, .st = 1 }, - { .rst = 1, .st = 0 }, - { .rst = -1 }, -}; - -static const struct omap_prm_data am4_prm_data[] = { - { - .name = "mpu", .base = 0x44df0300, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact, - }, - { - .name = "gfx", .base = 0x44df0400, - .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, - .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3", - }, - { - .name = "rtc", .base = 0x44df0500, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, - }, - { - .name = "tamper", .base = 0x44df0600, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, - }, - { - .name = "cefuse", .base = 0x44df0700, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, - }, - { - .name = "per", .base = 0x44df0800, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact, - .rstctrl = 0x10, .rstst = 0x14, .rstmap = am4_per_rst_map, - .clkdm_name = "pruss_ocp" - }, - { - .name = "wkup", .base = 0x44df2000, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, - .rstctrl = 0x10, .rstst = 0x14, .rstmap = am3_wkup_rst_map, - .flags = OMAP_PRM_HAS_NO_CLKDM - }, - { - .name = "device", .base = 0x44df4000, - .rstctrl = 0x0, .rstst = 0x4, .rstmap = am4_device_rst_map, - .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM - }, - { }, -}; - -static const struct of_device_id omap_prm_id_table[] = { - { .compatible = "ti,omap4-prm-inst", .data = omap4_prm_data }, - { .compatible = "ti,omap5-prm-inst", .data = omap5_prm_data }, - { .compatible = "ti,dra7-prm-inst", .data = dra7_prm_data }, - { .compatible = "ti,am3-prm-inst", .data = am3_prm_data }, - { .compatible = "ti,am4-prm-inst", .data = am4_prm_data }, - { }, -}; - -#ifdef DEBUG -static void omap_prm_domain_show_state(struct omap_prm_domain *prmd, - const char *desc) -{ - dev_dbg(prmd->dev, "%s %s: %08x/%08x\n", - prmd->pd.name, desc, - readl_relaxed(prmd->prm->base + prmd->pwrstctrl), - readl_relaxed(prmd->prm->base + prmd->pwrstst)); -} -#else -static inline void omap_prm_domain_show_state(struct omap_prm_domain *prmd, - const char *desc) -{ -} -#endif - -static int omap_prm_domain_power_on(struct generic_pm_domain *domain) -{ - struct omap_prm_domain *prmd; - int ret; - u32 v, mode; - - prmd = genpd_to_prm_domain(domain); - if (!prmd->cap) - return 0; - - omap_prm_domain_show_state(prmd, "on: previous state"); - - if (prmd->pwrstctrl_saved) - v = prmd->pwrstctrl_saved; - else - v = readl_relaxed(prmd->prm->base + prmd->pwrstctrl); - - if (prmd->prm->data->flags & OMAP_PRM_RET_WHEN_IDLE) - mode = OMAP_PRMD_RETENTION; - else - mode = OMAP_PRMD_ON_ACTIVE; - - writel_relaxed((v & ~PRM_POWERSTATE_MASK) | mode, - prmd->prm->base + prmd->pwrstctrl); - - /* wait for the transition bit to get cleared */ - ret = readl_relaxed_poll_timeout(prmd->prm->base + prmd->pwrstst, - v, !(v & PRM_ST_INTRANSITION), 1, - PRM_STATE_MAX_WAIT); - if (ret) - dev_err(prmd->dev, "%s: %s timed out\n", - prmd->pd.name, __func__); - - omap_prm_domain_show_state(prmd, "on: new state"); - - return ret; -} - -/* No need to check for holes in the mask for the lowest mode */ -static int omap_prm_domain_find_lowest(struct omap_prm_domain *prmd) -{ - return __ffs(prmd->cap->usable_modes); -} - -static int omap_prm_domain_power_off(struct generic_pm_domain *domain) -{ - struct omap_prm_domain *prmd; - int ret; - u32 v; - - prmd = genpd_to_prm_domain(domain); - if (!prmd->cap) - return 0; - - omap_prm_domain_show_state(prmd, "off: previous state"); - - v = readl_relaxed(prmd->prm->base + prmd->pwrstctrl); - prmd->pwrstctrl_saved = v; - - v &= ~PRM_POWERSTATE_MASK; - v |= omap_prm_domain_find_lowest(prmd); - - if (prmd->cap->statechange) - v |= PRM_LOWPOWERSTATECHANGE; - if (prmd->cap->logicretstate) - v &= ~PRM_LOGICRETSTATE; - else - v |= PRM_LOGICRETSTATE; - - writel_relaxed(v, prmd->prm->base + prmd->pwrstctrl); - - /* wait for the transition bit to get cleared */ - ret = readl_relaxed_poll_timeout(prmd->prm->base + prmd->pwrstst, - v, !(v & PRM_ST_INTRANSITION), 1, - PRM_STATE_MAX_WAIT); - if (ret) - dev_warn(prmd->dev, "%s: %s timed out\n", - __func__, prmd->pd.name); - - omap_prm_domain_show_state(prmd, "off: new state"); - - return 0; -} - -/* - * Note that ti-sysc already manages the module clocks separately so - * no need to manage those. Interconnect instances need clocks managed - * for simple-pm-bus. - */ -static int omap_prm_domain_attach_clock(struct device *dev, - struct omap_prm_domain *prmd) -{ - struct device_node *np = dev->of_node; - int error; - - if (!of_device_is_compatible(np, "simple-pm-bus")) - return 0; - - if (!of_property_read_bool(np, "clocks")) - return 0; - - error = pm_clk_create(dev); - if (error) - return error; - - error = of_pm_clk_add_clks(dev); - if (error < 0) { - pm_clk_destroy(dev); - return error; - } - - prmd->uses_pm_clk = 1; - - return 0; -} - -static int omap_prm_domain_attach_dev(struct generic_pm_domain *domain, - struct device *dev) -{ - struct generic_pm_domain_data *genpd_data; - struct of_phandle_args pd_args; - struct omap_prm_domain *prmd; - struct device_node *np; - int ret; - - prmd = genpd_to_prm_domain(domain); - np = dev->of_node; - - ret = of_parse_phandle_with_args(np, "power-domains", - "#power-domain-cells", 0, &pd_args); - if (ret < 0) - return ret; - - if (pd_args.args_count != 0) - dev_warn(dev, "%s: unusupported #power-domain-cells: %i\n", - prmd->pd.name, pd_args.args_count); - - genpd_data = dev_gpd_data(dev); - genpd_data->data = NULL; - - ret = omap_prm_domain_attach_clock(dev, prmd); - if (ret) - return ret; - - return 0; -} - -static void omap_prm_domain_detach_dev(struct generic_pm_domain *domain, - struct device *dev) -{ - struct generic_pm_domain_data *genpd_data; - struct omap_prm_domain *prmd; - - prmd = genpd_to_prm_domain(domain); - if (prmd->uses_pm_clk) - pm_clk_destroy(dev); - genpd_data = dev_gpd_data(dev); - genpd_data->data = NULL; -} - -static int omap_prm_domain_init(struct device *dev, struct omap_prm *prm) -{ - struct omap_prm_domain *prmd; - struct device_node *np = dev->of_node; - const struct omap_prm_data *data; - const char *name; - int error; - - if (!of_property_present(dev->of_node, "#power-domain-cells")) - return 0; - - of_node_put(dev->of_node); - - prmd = devm_kzalloc(dev, sizeof(*prmd), GFP_KERNEL); - if (!prmd) - return -ENOMEM; - - data = prm->data; - name = devm_kasprintf(dev, GFP_KERNEL, "prm_%s", - data->name); - - prmd->dev = dev; - prmd->prm = prm; - prmd->cap = prmd->prm->data->dmap; - prmd->pwrstctrl = prmd->prm->data->pwrstctrl; - prmd->pwrstst = prmd->prm->data->pwrstst; - - prmd->pd.name = name; - prmd->pd.power_on = omap_prm_domain_power_on; - prmd->pd.power_off = omap_prm_domain_power_off; - prmd->pd.attach_dev = omap_prm_domain_attach_dev; - prmd->pd.detach_dev = omap_prm_domain_detach_dev; - prmd->pd.flags = GENPD_FLAG_PM_CLK; - - pm_genpd_init(&prmd->pd, NULL, true); - error = of_genpd_add_provider_simple(np, &prmd->pd); - if (error) - pm_genpd_remove(&prmd->pd); - else - prm->prmd = prmd; - - return error; -} - -static bool _is_valid_reset(struct omap_reset_data *reset, unsigned long id) -{ - if (reset->mask & BIT(id)) - return true; - - return false; -} - -static int omap_reset_get_st_bit(struct omap_reset_data *reset, - unsigned long id) -{ - const struct omap_rst_map *map = reset->prm->data->rstmap; - - while (map->rst >= 0) { - if (map->rst == id) - return map->st; - - map++; - } - - return id; -} - -static int omap_reset_status(struct reset_controller_dev *rcdev, - unsigned long id) -{ - struct omap_reset_data *reset = to_omap_reset_data(rcdev); - u32 v; - int st_bit = omap_reset_get_st_bit(reset, id); - bool has_rstst = reset->prm->data->rstst || - (reset->prm->data->flags & OMAP_PRM_HAS_RSTST); - - /* Check if we have rstst */ - if (!has_rstst) - return -ENOTSUPP; - - /* Check if hw reset line is asserted */ - v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl); - if (v & BIT(id)) - return 1; - - /* - * Check reset status, high value means reset sequence has been - * completed successfully so we can return 0 here (reset deasserted) - */ - v = readl_relaxed(reset->prm->base + reset->prm->data->rstst); - v >>= st_bit; - v &= 1; - - return !v; -} - -static int omap_reset_assert(struct reset_controller_dev *rcdev, - unsigned long id) -{ - struct omap_reset_data *reset = to_omap_reset_data(rcdev); - u32 v; - unsigned long flags; - - /* assert the reset control line */ - spin_lock_irqsave(&reset->lock, flags); - v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl); - v |= 1 << id; - writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl); - spin_unlock_irqrestore(&reset->lock, flags); - - return 0; -} - -static int omap_reset_deassert(struct reset_controller_dev *rcdev, - unsigned long id) -{ - struct omap_reset_data *reset = to_omap_reset_data(rcdev); - u32 v; - int st_bit; - bool has_rstst; - unsigned long flags; - struct ti_prm_platform_data *pdata = dev_get_platdata(reset->dev); - int ret = 0; - - /* Nothing to do if the reset is already deasserted */ - if (!omap_reset_status(rcdev, id)) - return 0; - - has_rstst = reset->prm->data->rstst || - (reset->prm->data->flags & OMAP_PRM_HAS_RSTST); - - if (has_rstst) { - st_bit = omap_reset_get_st_bit(reset, id); - - /* Clear the reset status by writing 1 to the status bit */ - v = 1 << st_bit; - writel_relaxed(v, reset->prm->base + reset->prm->data->rstst); - } - - if (reset->clkdm) - pdata->clkdm_deny_idle(reset->clkdm); - - /* de-assert the reset control line */ - spin_lock_irqsave(&reset->lock, flags); - v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl); - v &= ~(1 << id); - writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl); - spin_unlock_irqrestore(&reset->lock, flags); - - /* wait for the reset bit to clear */ - ret = readl_relaxed_poll_timeout_atomic(reset->prm->base + - reset->prm->data->rstctrl, - v, !(v & BIT(id)), 1, - OMAP_RESET_MAX_WAIT); - if (ret) - pr_err("%s: timedout waiting for %s:%lu\n", __func__, - reset->prm->data->name, id); - - /* wait for the status to be set */ - if (has_rstst) { - ret = readl_relaxed_poll_timeout_atomic(reset->prm->base + - reset->prm->data->rstst, - v, v & BIT(st_bit), 1, - OMAP_RESET_MAX_WAIT); - if (ret) - pr_err("%s: timedout waiting for %s:%lu\n", __func__, - reset->prm->data->name, id); - } - - if (reset->clkdm) - pdata->clkdm_allow_idle(reset->clkdm); - - return ret; -} - -static const struct reset_control_ops omap_reset_ops = { - .assert = omap_reset_assert, - .deassert = omap_reset_deassert, - .status = omap_reset_status, -}; - -static int omap_prm_reset_xlate(struct reset_controller_dev *rcdev, - const struct of_phandle_args *reset_spec) -{ - struct omap_reset_data *reset = to_omap_reset_data(rcdev); - - if (!_is_valid_reset(reset, reset_spec->args[0])) - return -EINVAL; - - return reset_spec->args[0]; -} - -static int omap_prm_reset_init(struct platform_device *pdev, - struct omap_prm *prm) -{ - struct omap_reset_data *reset; - const struct omap_rst_map *map; - struct ti_prm_platform_data *pdata = dev_get_platdata(&pdev->dev); - char buf[32]; - u32 v; - - /* - * Check if we have controllable resets. If either rstctrl is non-zero - * or OMAP_PRM_HAS_RSTCTRL flag is set, we have reset control register - * for the domain. - */ - if (!prm->data->rstctrl && !(prm->data->flags & OMAP_PRM_HAS_RSTCTRL)) - return 0; - - /* Check if we have the pdata callbacks in place */ - if (!pdata || !pdata->clkdm_lookup || !pdata->clkdm_deny_idle || - !pdata->clkdm_allow_idle) - return -EINVAL; - - map = prm->data->rstmap; - if (!map) - return -EINVAL; - - reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL); - if (!reset) - return -ENOMEM; - - reset->rcdev.owner = THIS_MODULE; - reset->rcdev.ops = &omap_reset_ops; - reset->rcdev.of_node = pdev->dev.of_node; - reset->rcdev.nr_resets = OMAP_MAX_RESETS; - reset->rcdev.of_xlate = omap_prm_reset_xlate; - reset->rcdev.of_reset_n_cells = 1; - reset->dev = &pdev->dev; - spin_lock_init(&reset->lock); - - reset->prm = prm; - - sprintf(buf, "%s_clkdm", prm->data->clkdm_name ? prm->data->clkdm_name : - prm->data->name); - - if (!(prm->data->flags & OMAP_PRM_HAS_NO_CLKDM)) { - reset->clkdm = pdata->clkdm_lookup(buf); - if (!reset->clkdm) - return -EINVAL; - } - - while (map->rst >= 0) { - reset->mask |= BIT(map->rst); - map++; - } - - /* Quirk handling to assert rst_map_012 bits on reset and avoid errors */ - if (prm->data->rstmap == rst_map_012) { - v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl); - if ((v & reset->mask) != reset->mask) { - dev_dbg(&pdev->dev, "Asserting all resets: %08x\n", v); - writel_relaxed(reset->mask, reset->prm->base + - reset->prm->data->rstctrl); - } - } - - return devm_reset_controller_register(&pdev->dev, &reset->rcdev); -} - -static int omap_prm_probe(struct platform_device *pdev) -{ - struct resource *res; - const struct omap_prm_data *data; - struct omap_prm *prm; - int ret; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; - - data = of_device_get_match_data(&pdev->dev); - if (!data) - return -ENOTSUPP; - - prm = devm_kzalloc(&pdev->dev, sizeof(*prm), GFP_KERNEL); - if (!prm) - return -ENOMEM; - - while (data->base != res->start) { - if (!data->base) - return -EINVAL; - data++; - } - - prm->data = data; - - prm->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(prm->base)) - return PTR_ERR(prm->base); - - ret = omap_prm_domain_init(&pdev->dev, prm); - if (ret) - return ret; - - ret = omap_prm_reset_init(pdev, prm); - if (ret) - goto err_domain; - - return 0; - -err_domain: - of_genpd_del_provider(pdev->dev.of_node); - pm_genpd_remove(&prm->prmd->pd); - - return ret; -} - -static struct platform_driver omap_prm_driver = { - .probe = omap_prm_probe, - .driver = { - .name = KBUILD_MODNAME, - .of_match_table = omap_prm_id_table, - }, -}; -builtin_platform_driver(omap_prm_driver); diff --git a/drivers/soc/ti/ti_sci_pm_domains.c b/drivers/soc/ti/ti_sci_pm_domains.c deleted file mode 100644 index a33ec7eaf23d..000000000000 --- a/drivers/soc/ti/ti_sci_pm_domains.c +++ /dev/null @@ -1,208 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * TI SCI Generic Power Domain Driver - * - * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/ - * J Keerthy <j-keerthy@ti.com> - * Dave Gerlach <d-gerlach@ti.com> - */ - -#include <linux/err.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <linux/slab.h> -#include <linux/soc/ti/ti_sci_protocol.h> -#include <dt-bindings/soc/ti,sci_pm_domain.h> - -/** - * struct ti_sci_genpd_provider: holds common TI SCI genpd provider data - * @ti_sci: handle to TI SCI protocol driver that provides ops to - * communicate with system control processor. - * @dev: pointer to dev for the driver for devm allocs - * @pd_list: list of all the power domains on the device - * @data: onecell data for genpd core - */ -struct ti_sci_genpd_provider { - const struct ti_sci_handle *ti_sci; - struct device *dev; - struct list_head pd_list; - struct genpd_onecell_data data; -}; - -/** - * struct ti_sci_pm_domain: TI specific data needed for power domain - * @idx: index of the device that identifies it with the system - * control processor. - * @exclusive: Permissions for exclusive request or shared request of the - * device. - * @pd: generic_pm_domain for use with the genpd framework - * @node: link for the genpd list - * @parent: link to the parent TI SCI genpd provider - */ -struct ti_sci_pm_domain { - int idx; - u8 exclusive; - struct generic_pm_domain pd; - struct list_head node; - struct ti_sci_genpd_provider *parent; -}; - -#define genpd_to_ti_sci_pd(gpd) container_of(gpd, struct ti_sci_pm_domain, pd) - -/* - * ti_sci_pd_power_off(): genpd power down hook - * @domain: pointer to the powerdomain to power off - */ -static int ti_sci_pd_power_off(struct generic_pm_domain *domain) -{ - struct ti_sci_pm_domain *pd = genpd_to_ti_sci_pd(domain); - const struct ti_sci_handle *ti_sci = pd->parent->ti_sci; - - return ti_sci->ops.dev_ops.put_device(ti_sci, pd->idx); -} - -/* - * ti_sci_pd_power_on(): genpd power up hook - * @domain: pointer to the powerdomain to power on - */ -static int ti_sci_pd_power_on(struct generic_pm_domain *domain) -{ - struct ti_sci_pm_domain *pd = genpd_to_ti_sci_pd(domain); - const struct ti_sci_handle *ti_sci = pd->parent->ti_sci; - - if (pd->exclusive) - return ti_sci->ops.dev_ops.get_device_exclusive(ti_sci, - pd->idx); - else - return ti_sci->ops.dev_ops.get_device(ti_sci, pd->idx); -} - -/* - * ti_sci_pd_xlate(): translation service for TI SCI genpds - * @genpdspec: DT identification data for the genpd - * @data: genpd core data for all the powerdomains on the device - */ -static struct generic_pm_domain *ti_sci_pd_xlate( - struct of_phandle_args *genpdspec, - void *data) -{ - struct genpd_onecell_data *genpd_data = data; - unsigned int idx = genpdspec->args[0]; - - if (genpdspec->args_count != 1 && genpdspec->args_count != 2) - return ERR_PTR(-EINVAL); - - if (idx >= genpd_data->num_domains) { - pr_err("%s: invalid domain index %u\n", __func__, idx); - return ERR_PTR(-EINVAL); - } - - if (!genpd_data->domains[idx]) - return ERR_PTR(-ENOENT); - - genpd_to_ti_sci_pd(genpd_data->domains[idx])->exclusive = - genpdspec->args[1]; - - return genpd_data->domains[idx]; -} - -static const struct of_device_id ti_sci_pm_domain_matches[] = { - { .compatible = "ti,sci-pm-domain", }, - { }, -}; -MODULE_DEVICE_TABLE(of, ti_sci_pm_domain_matches); - -static int ti_sci_pm_domain_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct ti_sci_genpd_provider *pd_provider; - struct ti_sci_pm_domain *pd; - struct device_node *np = NULL; - struct of_phandle_args args; - int ret; - u32 max_id = 0; - int index; - - pd_provider = devm_kzalloc(dev, sizeof(*pd_provider), GFP_KERNEL); - if (!pd_provider) - return -ENOMEM; - - pd_provider->ti_sci = devm_ti_sci_get_handle(dev); - if (IS_ERR(pd_provider->ti_sci)) - return PTR_ERR(pd_provider->ti_sci); - - pd_provider->dev = dev; - - INIT_LIST_HEAD(&pd_provider->pd_list); - - /* Find highest device ID used for power domains */ - while (1) { - np = of_find_node_with_property(np, "power-domains"); - if (!np) - break; - - index = 0; - - while (1) { - ret = of_parse_phandle_with_args(np, "power-domains", - "#power-domain-cells", - index, &args); - if (ret) - break; - - if (args.args_count >= 1 && args.np == dev->of_node) { - if (args.args[0] > max_id) - max_id = args.args[0]; - - pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); - if (!pd) - return -ENOMEM; - - pd->pd.name = devm_kasprintf(dev, GFP_KERNEL, - "pd:%d", - args.args[0]); - if (!pd->pd.name) - return -ENOMEM; - - pd->pd.power_off = ti_sci_pd_power_off; - pd->pd.power_on = ti_sci_pd_power_on; - pd->idx = args.args[0]; - pd->parent = pd_provider; - - pm_genpd_init(&pd->pd, NULL, true); - - list_add(&pd->node, &pd_provider->pd_list); - } - index++; - } - } - - pd_provider->data.domains = - devm_kcalloc(dev, max_id + 1, - sizeof(*pd_provider->data.domains), - GFP_KERNEL); - if (!pd_provider->data.domains) - return -ENOMEM; - - pd_provider->data.num_domains = max_id + 1; - pd_provider->data.xlate = ti_sci_pd_xlate; - - list_for_each_entry(pd, &pd_provider->pd_list, node) - pd_provider->data.domains[pd->idx] = &pd->pd; - - return of_genpd_add_provider_onecell(dev->of_node, &pd_provider->data); -} - -static struct platform_driver ti_sci_pm_domains_driver = { - .probe = ti_sci_pm_domain_probe, - .driver = { - .name = "ti_sci_pm_domains", - .of_match_table = ti_sci_pm_domain_matches, - }, -}; -module_platform_driver(ti_sci_pm_domains_driver); -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("TI System Control Interface (SCI) Power Domain driver"); -MODULE_AUTHOR("Dave Gerlach"); diff --git a/drivers/soc/xilinx/Makefile b/drivers/soc/xilinx/Makefile index 41e585bc9c67..33d94395fd87 100644 --- a/drivers/soc/xilinx/Makefile +++ b/drivers/soc/xilinx/Makefile @@ -1,4 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_ZYNQMP_POWER) += zynqmp_power.o -obj-$(CONFIG_ZYNQMP_PM_DOMAINS) += zynqmp_pm_domains.o obj-$(CONFIG_XLNX_EVENT_MANAGER) += xlnx_event_manager.o diff --git a/drivers/soc/xilinx/zynqmp_pm_domains.c b/drivers/soc/xilinx/zynqmp_pm_domains.c deleted file mode 100644 index 69d03ad4cf1e..000000000000 --- a/drivers/soc/xilinx/zynqmp_pm_domains.c +++ /dev/null @@ -1,322 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * ZynqMP Generic PM domain support - * - * Copyright (C) 2015-2019 Xilinx, Inc. - * - * Davorin Mista <davorin.mista@aggios.com> - * Jolly Shah <jollys@xilinx.com> - * Rajan Vaja <rajan.vaja@xilinx.com> - */ - -#include <linux/err.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/of_platform.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> -#include <linux/slab.h> - -#include <linux/firmware/xlnx-zynqmp.h> - -#define ZYNQMP_NUM_DOMAINS (100) - -static int min_capability; - -/** - * struct zynqmp_pm_domain - Wrapper around struct generic_pm_domain - * @gpd: Generic power domain - * @node_id: PM node ID corresponding to device inside PM domain - * @requested: The PM node mapped to the PM domain has been requested - */ -struct zynqmp_pm_domain { - struct generic_pm_domain gpd; - u32 node_id; - bool requested; -}; - -#define to_zynqmp_pm_domain(pm_domain) \ - container_of(pm_domain, struct zynqmp_pm_domain, gpd) - -/** - * zynqmp_gpd_is_active_wakeup_path() - Check if device is in wakeup source - * path - * @dev: Device to check for wakeup source path - * @not_used: Data member (not required) - * - * This function is checks device's child hierarchy and checks if any device is - * set as wakeup source. - * - * Return: 1 if device is in wakeup source path else 0 - */ -static int zynqmp_gpd_is_active_wakeup_path(struct device *dev, void *not_used) -{ - int may_wakeup; - - may_wakeup = device_may_wakeup(dev); - if (may_wakeup) - return may_wakeup; - - return device_for_each_child(dev, NULL, - zynqmp_gpd_is_active_wakeup_path); -} - -/** - * zynqmp_gpd_power_on() - Power on PM domain - * @domain: Generic PM domain - * - * This function is called before devices inside a PM domain are resumed, to - * power on PM domain. - * - * Return: 0 on success, error code otherwise - */ -static int zynqmp_gpd_power_on(struct generic_pm_domain *domain) -{ - struct zynqmp_pm_domain *pd = to_zynqmp_pm_domain(domain); - int ret; - - ret = zynqmp_pm_set_requirement(pd->node_id, - ZYNQMP_PM_CAPABILITY_ACCESS, - ZYNQMP_PM_MAX_QOS, - ZYNQMP_PM_REQUEST_ACK_BLOCKING); - if (ret) { - dev_err(&domain->dev, - "failed to set requirement to 0x%x for PM node id %d: %d\n", - ZYNQMP_PM_CAPABILITY_ACCESS, pd->node_id, ret); - return ret; - } - - dev_dbg(&domain->dev, "set requirement to 0x%x for PM node id %d\n", - ZYNQMP_PM_CAPABILITY_ACCESS, pd->node_id); - - return 0; -} - -/** - * zynqmp_gpd_power_off() - Power off PM domain - * @domain: Generic PM domain - * - * This function is called after devices inside a PM domain are suspended, to - * power off PM domain. - * - * Return: 0 on success, error code otherwise - */ -static int zynqmp_gpd_power_off(struct generic_pm_domain *domain) -{ - struct zynqmp_pm_domain *pd = to_zynqmp_pm_domain(domain); - int ret; - struct pm_domain_data *pdd, *tmp; - u32 capabilities = min_capability; - bool may_wakeup; - - /* If domain is already released there is nothing to be done */ - if (!pd->requested) { - dev_dbg(&domain->dev, "PM node id %d is already released\n", - pd->node_id); - return 0; - } - - list_for_each_entry_safe(pdd, tmp, &domain->dev_list, list_node) { - /* If device is in wakeup path, set capability to WAKEUP */ - may_wakeup = zynqmp_gpd_is_active_wakeup_path(pdd->dev, NULL); - if (may_wakeup) { - dev_dbg(pdd->dev, "device is in wakeup path in %s\n", - domain->name); - capabilities = ZYNQMP_PM_CAPABILITY_WAKEUP; - break; - } - } - - ret = zynqmp_pm_set_requirement(pd->node_id, capabilities, 0, - ZYNQMP_PM_REQUEST_ACK_NO); - if (ret) { - dev_err(&domain->dev, - "failed to set requirement to 0x%x for PM node id %d: %d\n", - capabilities, pd->node_id, ret); - return ret; - } - - dev_dbg(&domain->dev, "set requirement to 0x%x for PM node id %d\n", - capabilities, pd->node_id); - - return 0; -} - -/** - * zynqmp_gpd_attach_dev() - Attach device to the PM domain - * @domain: Generic PM domain - * @dev: Device to attach - * - * Return: 0 on success, error code otherwise - */ -static int zynqmp_gpd_attach_dev(struct generic_pm_domain *domain, - struct device *dev) -{ - struct zynqmp_pm_domain *pd = to_zynqmp_pm_domain(domain); - struct device_link *link; - int ret; - - link = device_link_add(dev, &domain->dev, DL_FLAG_SYNC_STATE_ONLY); - if (!link) - dev_dbg(&domain->dev, "failed to create device link for %s\n", - dev_name(dev)); - - /* If this is not the first device to attach there is nothing to do */ - if (domain->device_count) - return 0; - - ret = zynqmp_pm_request_node(pd->node_id, 0, 0, - ZYNQMP_PM_REQUEST_ACK_BLOCKING); - if (ret) { - dev_err(&domain->dev, "%s request failed for node %d: %d\n", - domain->name, pd->node_id, ret); - return ret; - } - - pd->requested = true; - - dev_dbg(&domain->dev, "%s requested PM node id %d\n", - dev_name(dev), pd->node_id); - - return 0; -} - -/** - * zynqmp_gpd_detach_dev() - Detach device from the PM domain - * @domain: Generic PM domain - * @dev: Device to detach - */ -static void zynqmp_gpd_detach_dev(struct generic_pm_domain *domain, - struct device *dev) -{ - struct zynqmp_pm_domain *pd = to_zynqmp_pm_domain(domain); - int ret; - - /* If this is not the last device to detach there is nothing to do */ - if (domain->device_count) - return; - - ret = zynqmp_pm_release_node(pd->node_id); - if (ret) { - dev_err(&domain->dev, "failed to release PM node id %d: %d\n", - pd->node_id, ret); - return; - } - - pd->requested = false; - - dev_dbg(&domain->dev, "%s released PM node id %d\n", - dev_name(dev), pd->node_id); -} - -static struct generic_pm_domain *zynqmp_gpd_xlate - (struct of_phandle_args *genpdspec, void *data) -{ - struct genpd_onecell_data *genpd_data = data; - unsigned int i, idx = genpdspec->args[0]; - struct zynqmp_pm_domain *pd; - - pd = to_zynqmp_pm_domain(genpd_data->domains[0]); - - if (genpdspec->args_count != 1) - return ERR_PTR(-EINVAL); - - /* Check for existing pm domains */ - for (i = 0; i < ZYNQMP_NUM_DOMAINS; i++) { - if (pd[i].node_id == idx) - goto done; - } - - /* - * Add index in empty node_id of power domain list as no existing - * power domain found for current index. - */ - for (i = 0; i < ZYNQMP_NUM_DOMAINS; i++) { - if (pd[i].node_id == 0) { - pd[i].node_id = idx; - break; - } - } - -done: - if (!genpd_data->domains[i] || i == ZYNQMP_NUM_DOMAINS) - return ERR_PTR(-ENOENT); - - return genpd_data->domains[i]; -} - -static int zynqmp_gpd_probe(struct platform_device *pdev) -{ - int i; - struct genpd_onecell_data *zynqmp_pd_data; - struct generic_pm_domain **domains; - struct zynqmp_pm_domain *pd; - struct device *dev = &pdev->dev; - - pd = devm_kcalloc(dev, ZYNQMP_NUM_DOMAINS, sizeof(*pd), GFP_KERNEL); - if (!pd) - return -ENOMEM; - - zynqmp_pd_data = devm_kzalloc(dev, sizeof(*zynqmp_pd_data), GFP_KERNEL); - if (!zynqmp_pd_data) - return -ENOMEM; - - zynqmp_pd_data->xlate = zynqmp_gpd_xlate; - - domains = devm_kcalloc(dev, ZYNQMP_NUM_DOMAINS, sizeof(*domains), - GFP_KERNEL); - if (!domains) - return -ENOMEM; - - if (!of_device_is_compatible(dev->parent->of_node, - "xlnx,zynqmp-firmware")) - min_capability = ZYNQMP_PM_CAPABILITY_UNUSABLE; - - for (i = 0; i < ZYNQMP_NUM_DOMAINS; i++, pd++) { - pd->node_id = 0; - pd->gpd.name = kasprintf(GFP_KERNEL, "domain%d", i); - pd->gpd.power_off = zynqmp_gpd_power_off; - pd->gpd.power_on = zynqmp_gpd_power_on; - pd->gpd.attach_dev = zynqmp_gpd_attach_dev; - pd->gpd.detach_dev = zynqmp_gpd_detach_dev; - - domains[i] = &pd->gpd; - - /* Mark all PM domains as initially powered off */ - pm_genpd_init(&pd->gpd, NULL, true); - } - - zynqmp_pd_data->domains = domains; - zynqmp_pd_data->num_domains = ZYNQMP_NUM_DOMAINS; - of_genpd_add_provider_onecell(dev->parent->of_node, zynqmp_pd_data); - - return 0; -} - -static int zynqmp_gpd_remove(struct platform_device *pdev) -{ - of_genpd_del_provider(pdev->dev.parent->of_node); - - return 0; -} - -static void zynqmp_gpd_sync_state(struct device *dev) -{ - int ret; - - ret = zynqmp_pm_init_finalize(); - if (ret) - dev_warn(dev, "failed to release power management to firmware\n"); -} - -static struct platform_driver zynqmp_power_domain_driver = { - .driver = { - .name = "zynqmp_power_controller", - .sync_state = zynqmp_gpd_sync_state, - }, - .probe = zynqmp_gpd_probe, - .remove = zynqmp_gpd_remove, -}; -module_platform_driver(zynqmp_power_domain_driver); - -MODULE_ALIAS("platform:zynqmp_power_controller"); |