diff options
-rw-r--r-- | drivers/soc/mediatek/mtk-pmic-wrap.c | 14 | ||||
-rw-r--r-- | drivers/soc/mediatek/mtk-scpsys.c | 149 | ||||
-rw-r--r-- | include/dt-bindings/power/mt6797-power.h | 30 |
3 files changed, 184 insertions, 9 deletions
diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index a5f10936fb9c..c80a04e1b2b1 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -1117,6 +1117,11 @@ static int pwrap_probe(struct platform_device *pdev) const struct of_device_id *of_slave_id = NULL; struct resource *res; + if (!of_id) { + dev_err(&pdev->dev, "Error: No device match found\n"); + return -ENODEV; + } + if (pdev->dev.of_node->child) of_slave_id = of_match_node(of_slave_match_tbl, pdev->dev.of_node->child); @@ -1200,7 +1205,8 @@ static int pwrap_probe(struct platform_device *pdev) if (!(pwrap_readl(wrp, PWRAP_WACS2_RDATA) & PWRAP_STATE_INIT_DONE0)) { dev_dbg(wrp->dev, "initialization isn't finished\n"); - return -ENODEV; + ret = -ENODEV; + goto err_out2; } /* Initialize watchdog, may not be done by the bootloader */ @@ -1220,8 +1226,10 @@ static int pwrap_probe(struct platform_device *pdev) goto err_out2; wrp->regmap = devm_regmap_init(wrp->dev, NULL, wrp, &pwrap_regmap_config); - if (IS_ERR(wrp->regmap)) - return PTR_ERR(wrp->regmap); + if (IS_ERR(wrp->regmap)) { + ret = PTR_ERR(wrp->regmap); + goto err_out2; + } ret = of_platform_populate(np, NULL, NULL, wrp->dev); if (ret) { diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c index beb79162369a..ceb2cc495cd0 100644 --- a/drivers/soc/mediatek/mtk-scpsys.c +++ b/drivers/soc/mediatek/mtk-scpsys.c @@ -21,6 +21,7 @@ #include <linux/soc/mediatek/infracfg.h> #include <dt-bindings/power/mt2701-power.h> +#include <dt-bindings/power/mt6797-power.h> #include <dt-bindings/power/mt8173-power.h> #define SPM_VDE_PWR_CON 0x0210 @@ -71,6 +72,7 @@ enum clk_id { CLK_VENC, CLK_VENC_LT, CLK_ETHIF, + CLK_VDEC, CLK_MAX, }; @@ -81,6 +83,7 @@ static const char * const clk_names[] = { "venc", "venc_lt", "ethif", + "vdec", NULL, }; @@ -107,21 +110,28 @@ struct scp_domain { 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; }; static int scpsys_domain_is_on(struct scp_domain *scpd) { struct scp *scp = scpd->scp; - u32 status = readl(scp->base + SPM_PWR_STATUS) & scpd->data->sta_mask; - u32 status2 = readl(scp->base + SPM_PWR_STATUS_2ND) & - scpd->data->sta_mask; + 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 @@ -346,7 +356,8 @@ 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) + const struct scp_domain_data *scp_domain_data, int num, + struct scp_ctrl_reg *scp_ctrl_reg) { struct genpd_onecell_data *pd_data; struct resource *res; @@ -358,6 +369,9 @@ static struct scp *init_scp(struct platform_device *pdev, 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->dev = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -556,8 +570,13 @@ static const struct scp_domain_data scp_domain_data_mt2701[] = { static int __init scpsys_probe_mt2701(struct platform_device *pdev) { struct scp *scp; + struct scp_ctrl_reg scp_reg; - scp = init_scp(pdev, scp_domain_data_mt2701, NUM_DOMAINS_MT2701); + 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); @@ -567,6 +586,116 @@ static int __init scpsys_probe_mt2701(struct platform_device *pdev) } /* + * 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 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); + + 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); + + return 0; +} + +/* * MT8173 power domain support */ @@ -667,8 +796,13 @@ 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 = init_scp(pdev, scp_domain_data_mt8173, NUM_DOMAINS_MT8173); + 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); @@ -698,6 +832,9 @@ static const struct of_device_id of_scpsys_match_tbl[] = { .compatible = "mediatek,mt2701-scpsys", .data = scpsys_probe_mt2701, }, { + .compatible = "mediatek,mt6797-scpsys", + .data = scpsys_probe_mt6797, + }, { .compatible = "mediatek,mt8173-scpsys", .data = scpsys_probe_mt8173, }, { diff --git a/include/dt-bindings/power/mt6797-power.h b/include/dt-bindings/power/mt6797-power.h new file mode 100644 index 000000000000..a60c1d81cf75 --- /dev/null +++ b/include/dt-bindings/power/mt6797-power.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Mars.C <mars.cheng@mediatek.com> + * + * 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, + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _DT_BINDINGS_POWER_MT6797_POWER_H +#define _DT_BINDINGS_POWER_MT6797_POWER_H + +#define MT6797_POWER_DOMAIN_VDEC 0 +#define MT6797_POWER_DOMAIN_VENC 1 +#define MT6797_POWER_DOMAIN_ISP 2 +#define MT6797_POWER_DOMAIN_MM 3 +#define MT6797_POWER_DOMAIN_AUDIO 4 +#define MT6797_POWER_DOMAIN_MFG_ASYNC 5 +#define MT6797_POWER_DOMAIN_MFG 6 +#define MT6797_POWER_DOMAIN_MFG_CORE0 7 +#define MT6797_POWER_DOMAIN_MFG_CORE1 8 +#define MT6797_POWER_DOMAIN_MFG_CORE2 9 +#define MT6797_POWER_DOMAIN_MFG_CORE3 10 +#define MT6797_POWER_DOMAIN_MJC 11 + +#endif /* _DT_BINDINGS_POWER_MT6797_POWER_H */ |