summaryrefslogtreecommitdiff
path: root/drivers/soc/mediatek/mtk-scpsys.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-09-11 06:40:00 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2017-09-11 06:40:00 +0300
commitae46654bcff303b33facbbd04a3ad9c21d303f9b (patch)
treeb0027d47d6c949162fa6ae306f34abeb76c559a9 /drivers/soc/mediatek/mtk-scpsys.c
parent7f1b9be13a7dbe8e51ea541bbcd6c47adae39c71 (diff)
parenta48a7b6b54927159bac77735df00e5b9fc3415fb (diff)
downloadlinux-ae46654bcff303b33facbbd04a3ad9c21d303f9b.tar.xz
Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC driver updates from Olof Johansson: "This branch contains platform-related driver updates for ARM and ARM64. Among them: - Reset driver updates: + New API for dealing with arrays of resets + Make unimplemented {de,}assert return success on shared resets + MSDKv1 driver + Removal of obsolete Gemini reset driver + Misc updates for sunxi and Uniphier - SoC drivers: + Platform SoC driver registration on Tegra + Shuffle of Qualcomm drivers into a submenu + Allwinner A64 support for SRAM + Renesas R-Car R3 support + Power domains for Rockchip RK3366 - Misc updates and smaller fixes for TEE and memory driver subsystems" * tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (54 commits) firmware: arm_scpi: fix endianness of dev_id in struct dev_pstate_set soc/tegra: fuse: Add missing semi-colon soc/tegra: Restrict SoC device registration to Tegra drivers: soc: sunxi: add support for A64 and its SRAM C drivers: soc: sunxi: add support for remapping func value to reg value drivers: soc: sunxi: fix error processing on base address when claiming dt-bindings: add binding for Allwinner A64 SRAM controller and SRAM C bus: sunxi-rsb: Enable by default for ARM64 soc/tegra: Register SoC device firmware: tegra: set drvdata earlier memory: Convert to using %pOF instead of full_name soc: Convert to using %pOF instead of full_name bus: Convert to using %pOF instead of full_name firmware: Convert to using %pOF instead of full_name soc: mediatek: add SCPSYS power domain driver for MediaTek MT7622 SoC soc: mediatek: add header files required for MT7622 SCPSYS dt-binding soc: mediatek: reduce code duplication of scpsys_probe across all SoCs dt-bindings: soc: update the binding document for SCPSYS on MediaTek MT7622 SoC reset: uniphier: add analog amplifiers reset control reset: uniphier: add video input subsystem reset control ...
Diffstat (limited to 'drivers/soc/mediatek/mtk-scpsys.c')
-rw-r--r--drivers/soc/mediatek/mtk-scpsys.c247
1 files changed, 147 insertions, 100 deletions
diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index ceb2cc495cd0..e1ce8b1b5090 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -22,6 +22,7 @@
#include <dt-bindings/power/mt2701-power.h>
#include <dt-bindings/power/mt6797-power.h>
+#include <dt-bindings/power/mt7622-power.h>
#include <dt-bindings/power/mt8173-power.h>
#define SPM_VDE_PWR_CON 0x0210
@@ -39,6 +40,11 @@
#define SPM_MFG_2D_PWR_CON 0x02c0
#define SPM_MFG_ASYNC_PWR_CON 0x02c4
#define SPM_USB_PWR_CON 0x02cc
+#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
@@ -64,6 +70,10 @@
#define PWR_STATUS_MFG_ASYNC BIT(23)
#define PWR_STATUS_AUDIO BIT(24)
#define PWR_STATUS_USB BIT(25)
+#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,
@@ -73,6 +83,7 @@ enum clk_id {
CLK_VENC_LT,
CLK_ETHIF,
CLK_VDEC,
+ CLK_HIFSEL,
CLK_MAX,
};
@@ -84,6 +95,7 @@ static const char * const clk_names[] = {
"venc_lt",
"ethif",
"vdec",
+ "hif_sel",
NULL,
};
@@ -124,6 +136,19 @@ struct scp {
struct scp_ctrl_reg ctrl_reg;
};
+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;
+};
+
static int scpsys_domain_is_on(struct scp_domain *scpd)
{
struct scp *scp = scpd->scp;
@@ -357,7 +382,7 @@ static void init_clks(struct platform_device *pdev, struct clk **clk)
static struct scp *init_scp(struct platform_device *pdev,
const struct scp_domain_data *scp_domain_data, int num,
- struct scp_ctrl_reg *scp_ctrl_reg)
+ const struct scp_ctrl_reg *scp_ctrl_reg)
{
struct genpd_onecell_data *pd_data;
struct resource *res;
@@ -565,26 +590,6 @@ static const struct scp_domain_data scp_domain_data_mt2701[] = {
},
};
-#define NUM_DOMAINS_MT2701 ARRAY_SIZE(scp_domain_data_mt2701)
-
-static int __init scpsys_probe_mt2701(struct platform_device *pdev)
-{
- struct scp *scp;
- struct scp_ctrl_reg scp_reg;
-
- scp_reg.pwr_sta_offs = SPM_PWR_STATUS;
- scp_reg.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND;
-
- scp = init_scp(pdev, scp_domain_data_mt2701, NUM_DOMAINS_MT2701,
- &scp_reg);
- if (IS_ERR(scp))
- return PTR_ERR(scp);
-
- mtk_register_power_domains(pdev, scp, NUM_DOMAINS_MT2701);
-
- return 0;
-}
-
/*
* MT6797 power domain support
*/
@@ -649,51 +654,62 @@ static const struct scp_domain_data scp_domain_data_mt6797[] = {
},
};
-#define NUM_DOMAINS_MT6797 ARRAY_SIZE(scp_domain_data_mt6797)
#define SPM_PWR_STATUS_MT6797 0x0180
#define SPM_PWR_STATUS_2ND_MT6797 0x0184
-static int __init scpsys_probe_mt6797(struct platform_device *pdev)
-{
- struct scp *scp;
- struct genpd_onecell_data *pd_data;
- int ret;
- struct scp_ctrl_reg scp_reg;
-
- scp_reg.pwr_sta_offs = SPM_PWR_STATUS_MT6797;
- scp_reg.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797;
-
- scp = init_scp(pdev, scp_domain_data_mt6797, NUM_DOMAINS_MT6797,
- &scp_reg);
- if (IS_ERR(scp))
- return PTR_ERR(scp);
-
- mtk_register_power_domains(pdev, scp, NUM_DOMAINS_MT6797);
-
- pd_data = &scp->pd_data;
-
- ret = pm_genpd_add_subdomain(pd_data->domains[MT6797_POWER_DOMAIN_MM],
- pd_data->domains[MT6797_POWER_DOMAIN_VDEC]);
- 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[MT6797_POWER_DOMAIN_MM],
- pd_data->domains[MT6797_POWER_DOMAIN_ISP]);
- 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[MT6797_POWER_DOMAIN_MM],
- pd_data->domains[MT6797_POWER_DOMAIN_VENC]);
- if (ret && IS_ENABLED(CONFIG_PM))
- dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
+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},
+};
- ret = pm_genpd_add_subdomain(pd_data->domains[MT6797_POWER_DOMAIN_MM],
- pd_data->domains[MT6797_POWER_DOMAIN_MJC]);
- if (ret && IS_ENABLED(CONFIG_PM))
- dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
+/*
+ * MT7622 power domain support
+ */
- return 0;
-}
+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,
+ .active_wakeup = true,
+ },
+ [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,
+ .active_wakeup = true,
+ },
+ [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,
+ .active_wakeup = true,
+ },
+ [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,
+ .active_wakeup = true,
+ },
+};
/*
* MT8173 power domain support
@@ -789,39 +805,50 @@ static const struct scp_domain_data scp_domain_data_mt8173[] = {
},
};
-#define NUM_DOMAINS_MT8173 ARRAY_SIZE(scp_domain_data_mt8173)
-
-static int __init scpsys_probe_mt8173(struct platform_device *pdev)
-{
- struct scp *scp;
- struct genpd_onecell_data *pd_data;
- int ret;
- struct scp_ctrl_reg scp_reg;
-
- scp_reg.pwr_sta_offs = SPM_PWR_STATUS;
- scp_reg.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND;
-
- scp = init_scp(pdev, scp_domain_data_mt8173, NUM_DOMAINS_MT8173,
- &scp_reg);
- if (IS_ERR(scp))
- return PTR_ERR(scp);
-
- mtk_register_power_domains(pdev, scp, NUM_DOMAINS_MT8173);
+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},
+};
- pd_data = &scp->pd_data;
+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
+ }
+};
- 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);
+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
+ }
+};
- 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);
+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
+ }
+};
- return 0;
-}
+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
+ }
+};
/*
* scpsys driver init
@@ -830,13 +857,16 @@ static int __init scpsys_probe_mt8173(struct platform_device *pdev)
static const struct of_device_id of_scpsys_match_tbl[] = {
{
.compatible = "mediatek,mt2701-scpsys",
- .data = scpsys_probe_mt2701,
+ .data = &mt2701_data,
}, {
.compatible = "mediatek,mt6797-scpsys",
- .data = scpsys_probe_mt6797,
+ .data = &mt6797_data,
+ }, {
+ .compatible = "mediatek,mt7622-scpsys",
+ .data = &mt7622_data,
}, {
.compatible = "mediatek,mt8173-scpsys",
- .data = scpsys_probe_mt8173,
+ .data = &mt8173_data,
}, {
/* sentinel */
}
@@ -844,16 +874,33 @@ static const struct of_device_id of_scpsys_match_tbl[] = {
static int scpsys_probe(struct platform_device *pdev)
{
- int (*probe)(struct platform_device *);
- const struct of_device_id *of_id;
+ const struct of_device_id *match;
+ const struct scp_subdomain *sd;
+ const struct scp_soc_data *soc;
+ struct scp *scp;
+ struct genpd_onecell_data *pd_data;
+ int i, ret;
- of_id = of_match_node(of_scpsys_match_tbl, pdev->dev.of_node);
- if (!of_id || !of_id->data)
- return -EINVAL;
+ match = of_match_device(of_scpsys_match_tbl, &pdev->dev);
+ soc = (const struct scp_soc_data *)match->data;
+
+ scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs);
+ if (IS_ERR(scp))
+ return PTR_ERR(scp);
- probe = of_id->data;
+ mtk_register_power_domains(pdev, scp, soc->num_domains);
- return probe(pdev);
+ pd_data = &scp->pd_data;
+
+ for (i = 0, sd = soc->subdomains ; i < soc->num_subdomains ; i++) {
+ 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 = {