Messages in this thread Patch in this message | | | From | Flora Fu <> | Subject | [PATCH 3/6] soc: mediatek: apu: Add MT8195 apu power domain | Date | Sat, 11 Dec 2021 01:37:40 +0800 |
| |
Add MT8195 apu power domain settings. The clock and pll controller shall be accessed through SMC call and the power domain shall be enable before access MT8195 APU.
Signed-off-by: Flora Fu <flora.fu@mediatek.com>
--- drivers/soc/mediatek/apusys/mtk-apu-pm.c | 124 +++++++++++++++++++++++ 1 file changed, 124 insertions(+)
diff --git a/drivers/soc/mediatek/apusys/mtk-apu-pm.c b/drivers/soc/mediatek/apusys/mtk-apu-pm.c index 10dd30052c46..7be5acb75d78 100644 --- a/drivers/soc/mediatek/apusys/mtk-apu-pm.c +++ b/drivers/soc/mediatek/apusys/mtk-apu-pm.c @@ -3,6 +3,7 @@ * Copyright (c) 2021 MediaTek Inc. */ +#include <linux/arm-smccc.h> #include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/init.h> @@ -18,9 +19,12 @@ #include <linux/pm_domain.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> +#include <linux/soc/mediatek/mtk_sip_svc.h> #define APU_PD_IPUIF_HW_CG BIT(0) #define APU_PD_RPC_AUTO_BUCK BIT(1) +#define APU_PD_ACC BIT(2) +#define APU_PD_SEC_PWR BIT(3) #define APU_PD_CAPS(_pd, _x) ((_pd)->data->caps & (_x)) #define MTK_POLL_DELAY_US 10 @@ -44,6 +48,11 @@ static const struct reg_sequence mt8192_rpc_sw_type[] = { { MT8192_RPC_SW_TYPE(6), 0x3 }, }; +#define MTK_SIP_APUPWR_BUS_PROT_CG_ON 0x02U +#define MTK_SIP_APUPWR_BULK_PLL 0x03U +#define MTK_SIP_APUPWR_ACC_INIT_ALL 0x04U +#define MTK_SIP_APUPWR_ACC_TOP 0x05U + struct apu_top_domain { u32 spm_ext_buck_iso; u32 spm_ext_buck_iso_mask; @@ -81,6 +90,23 @@ static struct apu_top_domain mt8192_top_reg = { .num_rpc_sw = ARRAY_SIZE(mt8192_rpc_sw_type), }; +static struct apu_top_domain mt8195_top_reg = { + .spm_ext_buck_iso = 0x3EC, + .spm_ext_buck_iso_mask = 0x21, + .spm_cross_wake_m01 = 0x670, + .wake_apu = BIT(0), + .spm_other_pwr = 0x198, + .pwr_status = BIT(4), + .conn_clr = 0x8, + .conn1_clr = 0x8, + .vcore_clr = 0x8, + .rpc_top_con = 0x0, + .rpc_top_con_init_mask = 0x9E, + .rpc_top_sel = 0x4, + .rpc_top_intf_pwr_rdy = 0x44, + .pwr_rdy = BIT(0), +}; + struct apusys { struct device *dev; struct regmap *scpsys; @@ -125,6 +151,7 @@ static int apu_top_init_hw(struct apu_domain *pd) { struct apusys *apusys = pd->apusys; int ret; + struct arm_smccc_res res; if (APU_PD_CAPS(pd, APU_PD_IPUIF_HW_CG)) { ret = clk_prepare_enable(pd->clk_top_conn); @@ -148,6 +175,15 @@ static int apu_top_init_hw(struct apu_domain *pd) } } } else { + if (APU_PD_CAPS(pd, APU_PD_SEC_PWR)) { + arm_smccc_smc(MTK_SIP_APUSYS_CONTROL, MTK_SIP_APUPWR_BULK_PLL, + 1, 0, 0, 0, 0, 0, &res); + ret = res.a0; + if (ret) { + dev_err(apusys->dev, "apu pll smc fail: %lu\n", res.a0); + goto err_clk; + } + } ret = clk_bulk_prepare_enable(pd->num_clks, pd->clks); if (ret) goto err_clk; @@ -181,6 +217,18 @@ static int apu_top_init_hw(struct apu_domain *pd) goto err_clk; } + if (APU_PD_CAPS(pd, APU_PD_SEC_PWR)) { + if (APU_PD_CAPS(pd, APU_PD_ACC)) { + arm_smccc_smc(MTK_SIP_APUSYS_CONTROL, MTK_SIP_APUPWR_ACC_INIT_ALL, + 0, 0, 0, 0, 0, 0, &res); + ret = res.a0; + if (ret) { + dev_err(apusys->dev, "apu acc init all fail: %lu\n", res.a0); + goto err_clk; + } + } + } + if (APU_PD_CAPS(pd, APU_PD_IPUIF_HW_CG)) { clk_disable_unprepare(pd->clk_top_conn); ret = clk_set_parent(pd->clk_top_ipu_if, pd->clk_off); @@ -189,6 +237,9 @@ static int apu_top_init_hw(struct apu_domain *pd) goto err_clk; } } else { + if (APU_PD_CAPS(pd, APU_PD_SEC_PWR)) + arm_smccc_smc(MTK_SIP_APUSYS_CONTROL, MTK_SIP_APUPWR_BULK_PLL, + 0, 0, 0, 0, 0, 0, &res); clk_bulk_disable_unprepare(pd->num_clks, pd->clks); } @@ -199,6 +250,9 @@ static int apu_top_init_hw(struct apu_domain *pd) clk_disable_unprepare(pd->clk_top_conn); clk_disable_unprepare(pd->clk_top_ipu_if); } else { + if (APU_PD_CAPS(pd, APU_PD_SEC_PWR)) + arm_smccc_smc(MTK_SIP_APUSYS_CONTROL, MTK_SIP_APUPWR_BULK_PLL, + 0, 0, 0, 0, 0, 0, &res); clk_bulk_disable_unprepare(pd->num_clks, pd->clks); } @@ -214,16 +268,31 @@ static const struct apu_domain_data apu_domain_data_mt8192[] = { } }; +static const struct apu_domain_data apu_domain_data_mt8195[] = { + { + .domain_idx = 0, + .name = "apu-top", + .caps = APU_PD_RPC_AUTO_BUCK | APU_PD_ACC | APU_PD_SEC_PWR, + .topd = &mt8195_top_reg, + } +}; + static const struct apu_pm_data mt8192_apu_pm_data = { .domains_data = apu_domain_data_mt8192, .num_domains = ARRAY_SIZE(apu_domain_data_mt8192), }; +static const struct apu_pm_data mt8195_apu_pm_data = { + .domains_data = apu_domain_data_mt8195, + .num_domains = ARRAY_SIZE(apu_domain_data_mt8195), +}; + static int apu_top_power_on(struct generic_pm_domain *genpd) { struct apu_domain *pd = to_apu_domain(genpd); struct apusys *apusys = pd->apusys; int ret, tmp; + struct arm_smccc_res res; if (apusys->vsram_supply) { ret = regulator_enable(apusys->vsram_supply); @@ -269,6 +338,25 @@ static int apu_top_power_on(struct generic_pm_domain *genpd) } } } else { + if (APU_PD_CAPS(pd, APU_PD_SEC_PWR)) { + arm_smccc_smc(MTK_SIP_APUSYS_CONTROL, MTK_SIP_APUPWR_BULK_PLL, + 1, 0, 0, 0, 0, 0, &res); + ret = res.a0; + if (ret) { + dev_err(apusys->dev, "apu pll smc fail: %lu\n", res.a0); + goto err_clk; + } + + if (APU_PD_CAPS(pd, APU_PD_ACC)) { + arm_smccc_smc(MTK_SIP_APUSYS_CONTROL, MTK_SIP_APUPWR_ACC_TOP, + 1, 0, 0, 0, 0, 0, &res); + ret = res.a0; + if (ret) { + dev_err(apusys->dev, "apu acc top smc fail: %lu\n", res.a0); + goto err_clk; + } + } + } ret = clk_bulk_prepare_enable(pd->num_clks, pd->clks); if (ret) goto err_clk; @@ -301,6 +389,15 @@ static int apu_top_power_on(struct generic_pm_domain *genpd) goto err_clk; } + if (APU_PD_CAPS(pd, APU_PD_SEC_PWR)) { + arm_smccc_smc(MTK_SIP_APUSYS_CONTROL, MTK_SIP_APUPWR_BUS_PROT_CG_ON, + 0, 0, 0, 0, 0, 0, &res); + if (res.a0) { + dev_err(apusys->dev, "apu bus_prot smc fail: %lu\n", res.a0); + goto err_clk; + } + } + if (apusys->vcore) { ret = regmap_write(apusys->vcore, pd->data->topd->vcore_clr, CG_CLR); @@ -329,6 +426,9 @@ static int apu_top_power_on(struct generic_pm_domain *genpd) clk_disable_unprepare(pd->clk_top_conn); clk_disable_unprepare(pd->clk_top_ipu_if); } else { + if (APU_PD_CAPS(pd, APU_PD_SEC_PWR)) + arm_smccc_smc(MTK_SIP_APUSYS_CONTROL, MTK_SIP_APUPWR_BULK_PLL, + 0, 0, 0, 0, 0, 0, &res); clk_bulk_disable_unprepare(pd->num_clks, pd->clks); } if (pd->domain_supply) @@ -345,6 +445,7 @@ static int apu_top_power_off(struct generic_pm_domain *genpd) struct apu_domain *pd = to_apu_domain(genpd); struct apusys *apusys = pd->apusys; int ret, tmp; + struct arm_smccc_res res; if (apusys->vcore) { ret = regmap_write(apusys->vcore, @@ -405,6 +506,25 @@ static int apu_top_power_off(struct generic_pm_domain *genpd) return ret; } } else { + if (APU_PD_CAPS(pd, APU_PD_SEC_PWR)) { + if (APU_PD_CAPS(pd, APU_PD_ACC)) { + arm_smccc_smc(MTK_SIP_APUSYS_CONTROL, MTK_SIP_APUPWR_ACC_TOP, + 0, 0, 0, 0, 0, 0, &res); + ret = res.a0; + if (ret) { + dev_err(apusys->dev, "apu acc top smc fail: %lu\n", res.a0); + return ret; + } + } + + arm_smccc_smc(MTK_SIP_APUSYS_CONTROL, MTK_SIP_APUPWR_BULK_PLL, + 0, 0, 0, 0, 0, 0, &res); + ret = res.a0; + if (ret) { + dev_err(apusys->dev, "apu pll smc fail: %lu\n", res.a0); + return ret; + } + } clk_bulk_disable_unprepare(pd->num_clks, pd->clks); } @@ -610,6 +730,10 @@ static const struct of_device_id apu_pm_of_match[] = { .compatible = "mediatek,mt8192-apu-pm", .data = &mt8192_apu_pm_data, }, + { + .compatible = "mediatek,mt8195-apu-pm", + .data = &mt8195_apu_pm_data, + }, { } }; -- 2.18.0
| |