diff options
Diffstat (limited to 'target/linux/mediatek/patches-4.4/0002-soc-mediatek-Separate-scpsys-driver-common-code.patch')
-rw-r--r-- | target/linux/mediatek/patches-4.4/0002-soc-mediatek-Separate-scpsys-driver-common-code.patch | 681 |
1 files changed, 681 insertions, 0 deletions
diff --git a/target/linux/mediatek/patches-4.4/0002-soc-mediatek-Separate-scpsys-driver-common-code.patch b/target/linux/mediatek/patches-4.4/0002-soc-mediatek-Separate-scpsys-driver-common-code.patch new file mode 100644 index 0000000000..53781dc3be --- /dev/null +++ b/target/linux/mediatek/patches-4.4/0002-soc-mediatek-Separate-scpsys-driver-common-code.patch @@ -0,0 +1,681 @@ +From 2c93328ed05061a50e3bd4111379dbcf6946d3ac Mon Sep 17 00:00:00 2001 +From: James Liao <jamesjj.liao@mediatek.com> +Date: Wed, 30 Dec 2015 14:41:43 +0800 +Subject: [PATCH 02/53] soc: mediatek: Separate scpsys driver common code + +Separate scpsys driver common code to mtk-scpsys.c, and move MT8173 +platform code to mtk-scpsys-mt8173.c. + +Signed-off-by: James Liao <jamesjj.liao@mediatek.com> +--- + drivers/soc/mediatek/Kconfig | 13 +- + drivers/soc/mediatek/Makefile | 1 + + drivers/soc/mediatek/mtk-scpsys-mt8173.c | 179 ++++++++++++++++++ + drivers/soc/mediatek/mtk-scpsys.c | 301 ++++++++---------------------- + drivers/soc/mediatek/mtk-scpsys.h | 54 ++++++ + 5 files changed, 320 insertions(+), 228 deletions(-) + create mode 100644 drivers/soc/mediatek/mtk-scpsys-mt8173.c + create mode 100644 drivers/soc/mediatek/mtk-scpsys.h + +diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig +index 0a4ea80..eca6fb7 100644 +--- a/drivers/soc/mediatek/Kconfig ++++ b/drivers/soc/mediatek/Kconfig +@@ -22,11 +22,20 @@ config MTK_PMIC_WRAP + + config MTK_SCPSYS + bool "MediaTek SCPSYS Support" +- depends on ARCH_MEDIATEK || COMPILE_TEST +- default ARM64 && ARCH_MEDIATEK + select REGMAP + select MTK_INFRACFG + select PM_GENERIC_DOMAINS if PM + help + Say yes here to add support for the MediaTek SCPSYS power domain + driver. ++ ++config MTK_SCPSYS_MT8173 ++ bool "MediaTek MT8173 SCPSYS Support" ++ depends on ARCH_MEDIATEK || COMPILE_TEST ++ select MTK_SCPSYS ++ default ARCH_MEDIATEK ++ help ++ Say yes here to add support for the MT8173 SCPSYS power domain ++ driver. ++ The System Control Processor System (SCPSYS) has several power ++ management related tasks in the system. +diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile +index 12998b0..3b22baa 100644 +--- a/drivers/soc/mediatek/Makefile ++++ b/drivers/soc/mediatek/Makefile +@@ -1,3 +1,4 @@ + obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o + obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o + obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o ++obj-$(CONFIG_MTK_SCPSYS_MT8173) += mtk-scpsys-mt8173.o +diff --git a/drivers/soc/mediatek/mtk-scpsys-mt8173.c b/drivers/soc/mediatek/mtk-scpsys-mt8173.c +new file mode 100644 +index 0000000..3c7b569 +--- /dev/null ++++ b/drivers/soc/mediatek/mtk-scpsys-mt8173.c +@@ -0,0 +1,179 @@ ++/* ++ * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#include <linux/mfd/syscon.h> ++#include <linux/module.h> ++#include <linux/of_device.h> ++#include <linux/pm_domain.h> ++#include <linux/soc/mediatek/infracfg.h> ++#include <dt-bindings/power/mt8173-power.h> ++ ++#include "mtk-scpsys.h" ++ ++#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_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 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) ++ ++static const struct scp_domain_data scp_domain_data[] __initconst = { ++ [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}, ++ .active_wakeup = true, ++ }, ++ [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, ++ }, ++}; ++ ++#define NUM_DOMAINS ARRAY_SIZE(scp_domain_data) ++ ++static int __init scpsys_probe(struct platform_device *pdev) ++{ ++ struct scp *scp; ++ struct genpd_onecell_data *pd_data; ++ int ret; ++ ++ scp = init_scp(pdev, scp_domain_data, NUM_DOMAINS); ++ if (IS_ERR(scp)) ++ return PTR_ERR(scp); ++ ++ mtk_register_power_domains(pdev, scp, NUM_DOMAINS); ++ ++ pd_data = &scp->pd_data; ++ ++ ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_ASYNC], ++ pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D]); ++ if (ret && IS_ENABLED(CONFIG_PM)) ++ dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret); ++ ++ ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D], ++ pd_data->domains[MT8173_POWER_DOMAIN_MFG]); ++ if (ret && IS_ENABLED(CONFIG_PM)) ++ dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret); ++ ++ return 0; ++} ++ ++static const struct of_device_id of_scpsys_match_tbl[] = { ++ { ++ .compatible = "mediatek,mt8173-scpsys", ++ }, { ++ /* sentinel */ ++ } ++}; ++ ++static struct platform_driver scpsys_drv = { ++ .driver = { ++ .name = "mtk-scpsys-mt8173", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(of_scpsys_match_tbl), ++ }, ++}; ++ ++module_platform_driver_probe(scpsys_drv, scpsys_probe); +diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c +index 4d4203c..a0943c5 100644 +--- a/drivers/soc/mediatek/mtk-scpsys.c ++++ b/drivers/soc/mediatek/mtk-scpsys.c +@@ -11,28 +11,14 @@ + * GNU General Public License for more details. + */ + #include <linux/clk.h> +-#include <linux/delay.h> + #include <linux/io.h> +-#include <linux/kernel.h> + #include <linux/mfd/syscon.h> +-#include <linux/module.h> +-#include <linux/of_device.h> + #include <linux/platform_device.h> + #include <linux/pm_domain.h> +-#include <linux/regmap.h> + #include <linux/soc/mediatek/infracfg.h> +-#include <dt-bindings/power/mt8173-power.h> +- +-#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_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 ++ ++#include "mtk-scpsys.h" ++ + #define SPM_PWR_STATUS 0x060c + #define SPM_PWR_STATUS_2ND 0x0610 + +@@ -42,153 +28,6 @@ + #define PWR_ON_2ND_BIT BIT(3) + #define PWR_CLK_DIS_BIT BIT(4) + +-#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) +- +-enum clk_id { +- MT8173_CLK_NONE, +- MT8173_CLK_MM, +- MT8173_CLK_MFG, +- MT8173_CLK_VENC, +- MT8173_CLK_VENC_LT, +- MT8173_CLK_MAX, +-}; +- +-#define MAX_CLKS 2 +- +-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]; +- bool active_wakeup; +-}; +- +-static const struct scp_domain_data scp_domain_data[] __initconst = { +- [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 = {MT8173_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 = {MT8173_CLK_MM, MT8173_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 = {MT8173_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 = {MT8173_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 = {MT8173_CLK_MM, MT8173_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 = {MT8173_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 = {MT8173_CLK_NONE}, +- .active_wakeup = true, +- }, +- [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 = {MT8173_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 = {MT8173_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 = {MT8173_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, +- }, +-}; +- +-#define NUM_DOMAINS ARRAY_SIZE(scp_domain_data) +- +-struct scp; +- +-struct scp_domain { +- struct generic_pm_domain genpd; +- struct scp *scp; +- struct clk *clk[MAX_CLKS]; +- u32 sta_mask; +- void __iomem *ctl_addr; +- u32 sram_pdn_bits; +- u32 sram_pdn_ack_bits; +- u32 bus_prot_mask; +- bool active_wakeup; +-}; +- +-struct scp { +- struct scp_domain domains[NUM_DOMAINS]; +- struct genpd_onecell_data pd_data; +- struct device *dev; +- void __iomem *base; +- struct regmap *infracfg; +-}; +- + static int scpsys_domain_is_on(struct scp_domain *scpd) + { + struct scp *scp = scpd->scp; +@@ -398,63 +237,89 @@ static bool scpsys_active_wakeup(struct device *dev) + return scpd->active_wakeup; + } + +-static int __init scpsys_probe(struct platform_device *pdev) ++static void init_clks(struct platform_device *pdev, struct clk *clk[CLK_MAX]) ++{ ++ enum clk_id clk_ids[] = { ++ CLK_MM, ++ CLK_MFG, ++ CLK_VENC, ++ CLK_VENC_LT ++ }; ++ ++ static const char * const clk_names[] = { ++ "mm", ++ "mfg", ++ "venc", ++ "venc_lt", ++ }; ++ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(clk_ids); i++) ++ clk[clk_ids[i]] = devm_clk_get(&pdev->dev, clk_names[i]); ++} ++ ++struct scp *init_scp(struct platform_device *pdev, ++ const struct scp_domain_data *scp_domain_data, int num) + { + struct genpd_onecell_data *pd_data; + struct resource *res; +- int i, j, ret; ++ int i, j; + struct scp *scp; +- struct clk *clk[MT8173_CLK_MAX]; ++ struct clk *clk[CLK_MAX]; + + scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL); + if (!scp) +- return -ENOMEM; ++ return ERR_PTR(-ENOMEM); + + 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 PTR_ERR(scp->base); +- +- pd_data = &scp->pd_data; +- +- pd_data->domains = devm_kzalloc(&pdev->dev, +- sizeof(*pd_data->domains) * NUM_DOMAINS, GFP_KERNEL); +- if (!pd_data->domains) +- return -ENOMEM; +- +- clk[MT8173_CLK_MM] = devm_clk_get(&pdev->dev, "mm"); +- if (IS_ERR(clk[MT8173_CLK_MM])) +- return PTR_ERR(clk[MT8173_CLK_MM]); +- +- clk[MT8173_CLK_MFG] = devm_clk_get(&pdev->dev, "mfg"); +- if (IS_ERR(clk[MT8173_CLK_MFG])) +- return PTR_ERR(clk[MT8173_CLK_MFG]); +- +- clk[MT8173_CLK_VENC] = devm_clk_get(&pdev->dev, "venc"); +- if (IS_ERR(clk[MT8173_CLK_VENC])) +- return PTR_ERR(clk[MT8173_CLK_VENC]); +- +- clk[MT8173_CLK_VENC_LT] = devm_clk_get(&pdev->dev, "venc_lt"); +- if (IS_ERR(clk[MT8173_CLK_VENC_LT])) +- return PTR_ERR(clk[MT8173_CLK_VENC_LT]); ++ return ERR_CAST(scp->base); + + 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 PTR_ERR(scp->infracfg); ++ return ERR_CAST(scp->infracfg); + } + +- pd_data->num_domains = NUM_DOMAINS; ++ scp->domains = devm_kzalloc(&pdev->dev, ++ sizeof(*scp->domains) * num, GFP_KERNEL); ++ if (!scp->domains) ++ return ERR_PTR(-ENOMEM); ++ ++ pd_data = &scp->pd_data; ++ ++ pd_data->domains = devm_kzalloc(&pdev->dev, ++ sizeof(*pd_data->domains) * num, GFP_KERNEL); ++ if (!pd_data->domains) ++ return ERR_PTR(-ENOMEM); + +- for (i = 0; i < NUM_DOMAINS; i++) { ++ 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]; + ++ 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; ++ } ++ + pd_data->domains[i] = genpd; + scpd->scp = scp; + +@@ -464,13 +329,25 @@ static int __init scpsys_probe(struct platform_device *pdev) + scpd->sram_pdn_ack_bits = data->sram_pdn_ack_bits; + scpd->bus_prot_mask = data->bus_prot_mask; + scpd->active_wakeup = data->active_wakeup; +- for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) +- scpd->clk[j] = clk[data->clk_id[j]]; + + genpd->name = data->name; + genpd->power_off = scpsys_power_off; + genpd->power_on = scpsys_power_on; + genpd->dev_ops.active_wakeup = scpsys_active_wakeup; ++ } ++ ++ return scp; ++} ++ ++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; + + /* + * Initially turn on all domains to make the domains usable +@@ -489,37 +366,9 @@ static int __init scpsys_probe(struct platform_device *pdev) + * valid. + */ + +- ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_ASYNC], +- pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D]); +- if (ret && IS_ENABLED(CONFIG_PM)) +- dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret); +- +- ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D], +- pd_data->domains[MT8173_POWER_DOMAIN_MFG]); +- if (ret && IS_ENABLED(CONFIG_PM)) +- dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret); ++ 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); +- +- return 0; + } +- +-static const struct of_device_id of_scpsys_match_tbl[] = { +- { +- .compatible = "mediatek,mt8173-scpsys", +- }, { +- /* sentinel */ +- } +-}; +- +-static struct platform_driver scpsys_drv = { +- .driver = { +- .name = "mtk-scpsys", +- .owner = THIS_MODULE, +- .of_match_table = of_match_ptr(of_scpsys_match_tbl), +- }, +-}; +- +-module_platform_driver_probe(scpsys_drv, scpsys_probe); +diff --git a/drivers/soc/mediatek/mtk-scpsys.h b/drivers/soc/mediatek/mtk-scpsys.h +new file mode 100644 +index 0000000..466728d +--- /dev/null ++++ b/drivers/soc/mediatek/mtk-scpsys.h +@@ -0,0 +1,54 @@ ++#ifndef __DRV_SOC_MTK_H ++#define __DRV_SOC_MTK_H ++ ++enum clk_id { ++ CLK_NONE, ++ CLK_MM, ++ CLK_MFG, ++ CLK_VENC, ++ CLK_VENC_LT, ++ CLK_MAX, ++}; ++ ++#define MAX_CLKS 2 ++ ++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]; ++ bool active_wakeup; ++}; ++ ++struct scp; ++ ++struct scp_domain { ++ struct generic_pm_domain genpd; ++ struct scp *scp; ++ struct clk *clk[MAX_CLKS]; ++ u32 sta_mask; ++ void __iomem *ctl_addr; ++ u32 sram_pdn_bits; ++ u32 sram_pdn_ack_bits; ++ u32 bus_prot_mask; ++ bool active_wakeup; ++}; ++ ++struct scp { ++ struct scp_domain *domains; ++ struct genpd_onecell_data pd_data; ++ struct device *dev; ++ void __iomem *base; ++ struct regmap *infracfg; ++}; ++ ++struct scp *init_scp(struct platform_device *pdev, ++ const struct scp_domain_data *scp_domain_data, int num); ++ ++void mtk_register_power_domains(struct platform_device *pdev, ++ struct scp *scp, int num); ++ ++#endif /* __DRV_SOC_MTK_H */ +-- +1.7.10.4 + |