From 814f5a42520ebf0bf26a06e2d0ddd1c7d08f32c2 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Mon, 3 Apr 2023 21:32:50 +0200 Subject: soc: rockchip: power-domain: add rk3588 mem module support On RK3588 it's also possible to power down the memory used by the particular power domains via PMU_MEM_PWR_GATE_SFTCON. This adds support for this feature. Tested-by: Vincent Legoll Co-Developed-by: Finley Xiao Signed-off-by: Finley Xiao Signed-off-by: Boris Brezillon Signed-off-by: Sebastian Reichel Link: https://lore.kernel.org/r/20230403193250.108693-3-sebastian.reichel@collabora.com Signed-off-by: Heiko Stuebner --- drivers/soc/rockchip/pm_domains.c | 160 +++++++++++++++++++++++++++++--------- 1 file changed, 125 insertions(+), 35 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 84bc022f9e5b..e3de49e671dc 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -43,8 +43,10 @@ struct rockchip_domain_info { 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; }; @@ -54,6 +56,9 @@ struct rockchip_pmu_info { 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; @@ -119,13 +124,15 @@ struct rockchip_pmu { .active_wakeup = wakeup, \ } -#define DOMAIN_M_O_R(_name, p_offset, pwr, status, r_status, r_offset, req, idle, ack, 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, \ @@ -269,8 +276,8 @@ void rockchip_pmu_unblock(void) } EXPORT_SYMBOL_GPL(rockchip_pmu_unblock); -#define DOMAIN_RK3588(name, p_offset, pwr, status, r_status, r_offset, req, idle, wakeup) \ - DOMAIN_M_O_R(name, p_offset, pwr, status, r_status, r_offset, req, idle, idle, wakeup) +#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) { @@ -408,17 +415,92 @@ static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd) 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; + bool is_on, is_mem_on = false; if (pd->info->pwr_mask == 0) return; - else if (pd->info->pwr_w_mask) + + 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)); @@ -428,6 +510,9 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd, 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, @@ -645,7 +730,9 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, 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)); + 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; @@ -1024,35 +1111,35 @@ static const struct rockchip_domain_info rk3568_pm_domains[] = { }; static const struct rockchip_domain_info rk3588_pm_domains[] = { - [RK3588_PD_GPU] = DOMAIN_RK3588("gpu", 0x0, BIT(0), 0, BIT(1), 0x0, BIT(0), BIT(0), false), - [RK3588_PD_NPU] = DOMAIN_RK3588("npu", 0x0, BIT(1), BIT(1), 0, 0x0, 0, 0, false), - [RK3588_PD_VCODEC] = DOMAIN_RK3588("vcodec", 0x0, BIT(2), BIT(2), 0, 0x0, 0, 0, false), - [RK3588_PD_NPUTOP] = DOMAIN_RK3588("nputop", 0x0, BIT(3), 0, BIT(2), 0x0, BIT(1), BIT(1), false), - [RK3588_PD_NPU1] = DOMAIN_RK3588("npu1", 0x0, BIT(4), 0, BIT(3), 0x0, BIT(2), BIT(2), false), - [RK3588_PD_NPU2] = DOMAIN_RK3588("npu2", 0x0, BIT(5), 0, BIT(4), 0x0, BIT(3), BIT(3), false), - [RK3588_PD_VENC0] = DOMAIN_RK3588("venc0", 0x0, BIT(6), 0, BIT(5), 0x0, BIT(4), BIT(4), false), - [RK3588_PD_VENC1] = DOMAIN_RK3588("venc1", 0x0, BIT(7), 0, BIT(6), 0x0, BIT(5), BIT(5), false), - [RK3588_PD_RKVDEC0] = DOMAIN_RK3588("rkvdec0", 0x0, BIT(8), 0, BIT(7), 0x0, BIT(6), BIT(6), false), - [RK3588_PD_RKVDEC1] = DOMAIN_RK3588("rkvdec1", 0x0, BIT(9), 0, BIT(8), 0x0, BIT(7), BIT(7), false), - [RK3588_PD_VDPU] = DOMAIN_RK3588("vdpu", 0x0, BIT(10), 0, BIT(9), 0x0, BIT(8), BIT(8), false), - [RK3588_PD_RGA30] = DOMAIN_RK3588("rga30", 0x0, BIT(11), 0, BIT(10), 0x0, 0, 0, false), - [RK3588_PD_AV1] = DOMAIN_RK3588("av1", 0x0, BIT(12), 0, BIT(11), 0x0, BIT(9), BIT(9), false), - [RK3588_PD_VI] = DOMAIN_RK3588("vi", 0x0, BIT(13), 0, BIT(12), 0x0, BIT(10), BIT(10), false), - [RK3588_PD_FEC] = DOMAIN_RK3588("fec", 0x0, BIT(14), 0, BIT(13), 0x0, 0, 0, false), - [RK3588_PD_ISP1] = DOMAIN_RK3588("isp1", 0x0, BIT(15), 0, BIT(14), 0x0, BIT(11), BIT(11), false), - [RK3588_PD_RGA31] = DOMAIN_RK3588("rga31", 0x4, BIT(0), 0, BIT(15), 0x0, BIT(12), BIT(12), false), - [RK3588_PD_VOP] = DOMAIN_RK3588("vop", 0x4, BIT(1), 0, BIT(16), 0x0, BIT(13) | BIT(14), BIT(13) | BIT(14), false), - [RK3588_PD_VO0] = DOMAIN_RK3588("vo0", 0x4, BIT(2), 0, BIT(17), 0x0, BIT(15), BIT(15), false), - [RK3588_PD_VO1] = DOMAIN_RK3588("vo1", 0x4, BIT(3), 0, BIT(18), 0x4, BIT(0), BIT(16), false), - [RK3588_PD_AUDIO] = DOMAIN_RK3588("audio", 0x4, BIT(4), 0, BIT(19), 0x4, BIT(1), BIT(17), false), - [RK3588_PD_PHP] = DOMAIN_RK3588("php", 0x4, BIT(5), 0, BIT(20), 0x4, BIT(5), BIT(21), false), - [RK3588_PD_GMAC] = DOMAIN_RK3588("gmac", 0x4, BIT(6), 0, BIT(21), 0x0, 0, 0, false), - [RK3588_PD_PCIE] = DOMAIN_RK3588("pcie", 0x4, BIT(7), 0, BIT(22), 0x0, 0, 0, true), - [RK3588_PD_NVM] = DOMAIN_RK3588("nvm", 0x4, BIT(8), BIT(24), 0, 0x4, BIT(2), BIT(18), false), - [RK3588_PD_NVM0] = DOMAIN_RK3588("nvm0", 0x4, BIT(9), 0, BIT(23), 0x0, 0, 0, false), - [RK3588_PD_SDIO] = DOMAIN_RK3588("sdio", 0x4, BIT(10), 0, BIT(24), 0x4, BIT(3), BIT(19), false), - [RK3588_PD_USB] = DOMAIN_RK3588("usb", 0x4, BIT(11), 0, BIT(25), 0x4, BIT(4), BIT(20), true), - [RK3588_PD_SDMMC] = DOMAIN_RK3588("sdmmc", 0x4, BIT(13), 0, BIT(26), 0x0, 0, 0, false), + [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 = { @@ -1207,6 +1294,9 @@ static const struct rockchip_pmu_info rk3588_pmu = { .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), -- cgit v1.2.3 From 514a935fd0d4d522a08257f5acbc5439174c7cf0 Mon Sep 17 00:00:00 2001 From: Artur Weber Date: Mon, 1 May 2023 21:55:16 +0200 Subject: soc: samsung: exynos-pmu: Re-introduce Exynos4212 support Support for the Exynos4212 SoC was originally dropped as there were no boards using it. We will be adding a device that uses it, so add it back. This reverts commit c40610198f35e8264f9175dafe74db6288a07eda. Signed-off-by: Artur Weber Link: https://lore.kernel.org/r/20230501195525.6268-5-aweber.kernel@gmail.com Signed-off-by: Krzysztof Kozlowski --- drivers/soc/samsung/exynos-pmu.c | 9 +++++++++ drivers/soc/samsung/exynos-pmu.h | 2 ++ drivers/soc/samsung/exynos4-pmu.c | 13 +++++++++++-- 3 files changed, 22 insertions(+), 2 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c index 732c86ce2be8..5b2664da9853 100644 --- a/drivers/soc/samsung/exynos-pmu.c +++ b/drivers/soc/samsung/exynos-pmu.c @@ -57,6 +57,12 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode) if (pmu_data->powerdown_conf_extra) pmu_data->powerdown_conf_extra(mode); + + if (pmu_data->pmu_config_extra) { + for (i = 0; pmu_data->pmu_config_extra[i].offset != PMU_TABLE_END; i++) + pmu_raw_writel(pmu_data->pmu_config_extra[i].val[mode], + pmu_data->pmu_config_extra[i].offset); + } } /* @@ -79,6 +85,9 @@ static const struct of_device_id exynos_pmu_of_device_ids[] = { }, { .compatible = "samsung,exynos4210-pmu", .data = exynos_pmu_data_arm_ptr(exynos4210_pmu_data), + }, { + .compatible = "samsung,exynos4212-pmu", + .data = exynos_pmu_data_arm_ptr(exynos4212_pmu_data), }, { .compatible = "samsung,exynos4412-pmu", .data = exynos_pmu_data_arm_ptr(exynos4412_pmu_data), diff --git a/drivers/soc/samsung/exynos-pmu.h b/drivers/soc/samsung/exynos-pmu.h index 5e851f32307e..1c652ffd79b4 100644 --- a/drivers/soc/samsung/exynos-pmu.h +++ b/drivers/soc/samsung/exynos-pmu.h @@ -20,6 +20,7 @@ struct exynos_pmu_conf { struct exynos_pmu_data { const struct exynos_pmu_conf *pmu_config; + const struct exynos_pmu_conf *pmu_config_extra; void (*pmu_init)(void); void (*powerdown_conf)(enum sys_powerdown); @@ -32,6 +33,7 @@ extern void __iomem *pmu_base_addr; /* list of all exported SoC specific data */ extern const struct exynos_pmu_data exynos3250_pmu_data; extern const struct exynos_pmu_data exynos4210_pmu_data; +extern const struct exynos_pmu_data exynos4212_pmu_data; extern const struct exynos_pmu_data exynos4412_pmu_data; extern const struct exynos_pmu_data exynos5250_pmu_data; extern const struct exynos_pmu_data exynos5420_pmu_data; diff --git a/drivers/soc/samsung/exynos4-pmu.c b/drivers/soc/samsung/exynos4-pmu.c index cb35103565a6..f8092190b938 100644 --- a/drivers/soc/samsung/exynos4-pmu.c +++ b/drivers/soc/samsung/exynos4-pmu.c @@ -86,7 +86,7 @@ static const struct exynos_pmu_conf exynos4210_pmu_config[] = { { PMU_TABLE_END,}, }; -static const struct exynos_pmu_conf exynos4412_pmu_config[] = { +static const struct exynos_pmu_conf exynos4x12_pmu_config[] = { { S5P_ARM_CORE0_LOWPWR, { 0x0, 0x0, 0x2 } }, { S5P_DIS_IRQ_CORE0, { 0x0, 0x0, 0x0 } }, { S5P_DIS_IRQ_CENTRAL0, { 0x0, 0x0, 0x0 } }, @@ -191,6 +191,10 @@ static const struct exynos_pmu_conf exynos4412_pmu_config[] = { { S5P_GPS_ALIVE_LOWPWR, { 0x7, 0x0, 0x0 } }, { S5P_CMU_SYSCLK_ISP_LOWPWR, { 0x1, 0x0, 0x0 } }, { S5P_CMU_SYSCLK_GPS_LOWPWR, { 0x1, 0x0, 0x0 } }, + { PMU_TABLE_END,}, +}; + +static const struct exynos_pmu_conf exynos4412_pmu_config[] = { { S5P_ARM_CORE2_LOWPWR, { 0x0, 0x0, 0x2 } }, { S5P_DIS_IRQ_CORE2, { 0x0, 0x0, 0x0 } }, { S5P_DIS_IRQ_CENTRAL2, { 0x0, 0x0, 0x0 } }, @@ -204,6 +208,11 @@ const struct exynos_pmu_data exynos4210_pmu_data = { .pmu_config = exynos4210_pmu_config, }; +const struct exynos_pmu_data exynos4212_pmu_data = { + .pmu_config = exynos4x12_pmu_config, +}; + const struct exynos_pmu_data exynos4412_pmu_data = { - .pmu_config = exynos4412_pmu_config, + .pmu_config = exynos4x12_pmu_config, + .pmu_config_extra = exynos4412_pmu_config, }; -- cgit v1.2.3 From be11d67a144db79408a19642d0a8d65fb9f52105 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 10 Mar 2023 08:47:24 -0600 Subject: soc: xilinx: Use of_property_present() for testing DT property presence It is preferred to use typed property access functions (i.e. of_property_read_ functions) rather than low-level of_get_property/of_find_property functions for reading properties. As part of this, convert of_get_property/of_find_property calls to the recently added of_property_present() helper when we just want to test for presence of a property and nothing more. Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20230310144725.1545315-1-robh@kernel.org Signed-off-by: Michal Simek --- drivers/soc/xilinx/zynqmp_power.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/xilinx/zynqmp_power.c b/drivers/soc/xilinx/zynqmp_power.c index 78a8a7545d1e..641dcc958911 100644 --- a/drivers/soc/xilinx/zynqmp_power.c +++ b/drivers/soc/xilinx/zynqmp_power.c @@ -218,7 +218,7 @@ static int zynqmp_pm_probe(struct platform_device *pdev) } else if (ret != -EACCES && ret != -ENODEV) { dev_err(&pdev->dev, "Failed to Register with Xilinx Event manager %d\n", ret); return ret; - } else if (of_find_property(pdev->dev.of_node, "mboxes", NULL)) { + } else if (of_property_present(pdev->dev.of_node, "mboxes")) { zynqmp_pm_init_suspend_work = devm_kzalloc(&pdev->dev, sizeof(struct zynqmp_pm_work_struct), @@ -240,7 +240,7 @@ static int zynqmp_pm_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to request rx channel\n"); return PTR_ERR(rx_chan); } - } else if (of_find_property(pdev->dev.of_node, "interrupts", NULL)) { + } else if (of_property_present(pdev->dev.of_node, "interrupts")) { irq = platform_get_irq(pdev, 0); if (irq <= 0) return -ENXIO; -- cgit v1.2.3 From c58da0ba3e5c86e51e2c1557afaf6f71e00c4533 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 21 Apr 2023 13:44:54 +0300 Subject: driver: soc: xilinx: use _safe loop iterator to avoid a use after free The hash_for_each_possible() loop dereferences "eve_data" to get the next item on the list. However the loop frees eve_data so it leads to a use after free. Use hash_for_each_possible_safe() instead. Fixes: c7fdb2404f66 ("drivers: soc: xilinx: add xilinx event management driver") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/761e0e4a-4caf-4a71-8f47-1c6ad908a848@kili.mountain Signed-off-by: Michal Simek --- drivers/soc/xilinx/xlnx_event_manager.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/xilinx/xlnx_event_manager.c b/drivers/soc/xilinx/xlnx_event_manager.c index c76381899ef4..f9d9b82b562d 100644 --- a/drivers/soc/xilinx/xlnx_event_manager.c +++ b/drivers/soc/xilinx/xlnx_event_manager.c @@ -192,11 +192,12 @@ static int xlnx_remove_cb_for_suspend(event_cb_func_t cb_fun) struct registered_event_data *eve_data; struct agent_cb *cb_pos; struct agent_cb *cb_next; + struct hlist_node *tmp; is_need_to_unregister = false; /* Check for existing entry in hash table for given cb_type */ - hash_for_each_possible(reg_driver_map, eve_data, hentry, PM_INIT_SUSPEND_CB) { + hash_for_each_possible_safe(reg_driver_map, eve_data, tmp, hentry, PM_INIT_SUSPEND_CB) { if (eve_data->cb_type == PM_INIT_SUSPEND_CB) { /* Delete the list of callback */ list_for_each_entry_safe(cb_pos, cb_next, &eve_data->cb_list_head, list) { @@ -228,11 +229,12 @@ static int xlnx_remove_cb_for_notify_event(const u32 node_id, const u32 event, u64 key = ((u64)node_id << 32U) | (u64)event; struct agent_cb *cb_pos; struct agent_cb *cb_next; + struct hlist_node *tmp; is_need_to_unregister = false; /* Check for existing entry in hash table for given key id */ - hash_for_each_possible(reg_driver_map, eve_data, hentry, key) { + hash_for_each_possible_safe(reg_driver_map, eve_data, tmp, hentry, key) { if (eve_data->key == key) { /* Delete the list of callback */ list_for_each_entry_safe(cb_pos, cb_next, &eve_data->cb_list_head, list) { -- cgit v1.2.3 From cb9a39aacd3d6387b6f1f178a96eadceba90454e Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 19 Apr 2023 22:15:11 +0200 Subject: soc: renesas: rcar-rst: Allow WDT reset on R-Car V3U V3U firmware misses to enable WDT resets. Because there won't be any updates to the firmware anymore, enable that in Linux. Signed-off-by: Wolfram Sang Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230419201511.31648-1-wsa+renesas@sang-engineering.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/rcar-rst.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c index e1c7e91f5a86..98fd97da6cd4 100644 --- a/drivers/soc/renesas/rcar-rst.c +++ b/drivers/soc/renesas/rcar-rst.c @@ -12,6 +12,7 @@ #define WDTRSTCR_RESET 0xA55A0002 #define WDTRSTCR 0x0054 +#define GEN4_WDTRSTCR 0x0010 #define CR7BAR 0x0070 #define CR7BAREN BIT(4) @@ -27,6 +28,12 @@ static int rcar_rst_enable_wdt_reset(void __iomem *base) return 0; } +static int rcar_rst_v3u_enable_wdt_reset(void __iomem *base) +{ + iowrite32(WDTRSTCR_RESET, base + GEN4_WDTRSTCR); + return 0; +} + /* * Most of the R-Car Gen3 SoCs have an ARM Realtime Core. * Firmware boot address has to be set in CR7BAR before @@ -66,6 +73,12 @@ static const struct rst_config rcar_rst_gen3 __initconst = { .set_rproc_boot_addr = rcar_rst_set_gen3_rproc_boot_addr, }; +/* V3U firmware doesn't enable WDT reset and there won't be updates anymore */ +static const struct rst_config rcar_rst_v3u __initconst = { + .modemr = 0x00, /* MODEMR0 and it has CPG related bits */ + .configure = rcar_rst_v3u_enable_wdt_reset, +}; + static const struct rst_config rcar_rst_gen4 __initconst = { .modemr = 0x00, /* MODEMR0 and it has CPG related bits */ }; @@ -101,7 +114,7 @@ static const struct of_device_id rcar_rst_matches[] __initconst = { { .compatible = "renesas,r8a77990-rst", .data = &rcar_rst_gen3 }, { .compatible = "renesas,r8a77995-rst", .data = &rcar_rst_gen3 }, /* R-Car Gen4 */ - { .compatible = "renesas,r8a779a0-rst", .data = &rcar_rst_gen4 }, + { .compatible = "renesas,r8a779a0-rst", .data = &rcar_rst_v3u }, { .compatible = "renesas,r8a779f0-rst", .data = &rcar_rst_gen4 }, { .compatible = "renesas,r8a779g0-rst", .data = &rcar_rst_gen4 }, { /* sentinel */ } -- cgit v1.2.3 From d94436465152465555c8e5efbe611db40c9749f7 Mon Sep 17 00:00:00 2001 From: Stefan Kristiansson Date: Thu, 11 May 2023 16:20:48 +0300 Subject: soc/tegra: fuse: Add support for Tegra264 Add support for Tegra264 to the fuse handling code. Signed-off-by: Stefan Kristiansson Signed-off-by: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/soc/tegra/fuse/tegra-apbmisc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c index 4591c5bcb690..eb0a1d924526 100644 --- a/drivers/soc/tegra/fuse/tegra-apbmisc.c +++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved. */ #include @@ -62,6 +62,7 @@ bool tegra_is_silicon(void) switch (tegra_get_chip_id()) { case TEGRA194: case TEGRA234: + case TEGRA264: if (tegra_get_platform() == 0) return true; -- cgit v1.2.3 From 9f60d9d310b94c5869a5b6a2f1707b90bd60245c Mon Sep 17 00:00:00 2001 From: Yang Li Date: Fri, 28 Apr 2023 14:28:25 +0800 Subject: soc: ti: smartreflex: Use devm_platform_ioremap_resource() Convert platform_get_resource(),devm_ioremap_resource() to a single call to devm_platform_ioremap_resource(), as this is exactly what this function does. Signed-off-by: Yang Li Reviewed-by: Dhruva Gole Link: https://lore.kernel.org/r/20230428062825.126448-1-yang.lee@linux.alibaba.com Signed-off-by: Nishanth Menon --- drivers/soc/ti/smartreflex.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/ti/smartreflex.c b/drivers/soc/ti/smartreflex.c index da7898239a46..62b2f1464e46 100644 --- a/drivers/soc/ti/smartreflex.c +++ b/drivers/soc/ti/smartreflex.c @@ -815,7 +815,6 @@ static int omap_sr_probe(struct platform_device *pdev) { struct omap_sr *sr_info; struct omap_sr_data *pdata = pdev->dev.platform_data; - struct resource *mem; struct dentry *nvalue_dir; int i, ret = 0; @@ -835,8 +834,7 @@ static int omap_sr_probe(struct platform_device *pdev) return -EINVAL; } - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sr_info->base = devm_ioremap_resource(&pdev->dev, mem); + sr_info->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sr_info->base)) return PTR_ERR(sr_info->base); -- cgit v1.2.3 From 413552b360e72604b8c0cf3f60f9e6f01c8ff963 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 18 Apr 2023 13:41:48 +0200 Subject: soc: ti: pruss: Avoid cast to incompatible function type Rather than casting clk_unregister_mux to an incompatible function type provide a trivial wrapper with the correct signature for the use-case. Reported by clang-16 with W=1: drivers/soc/ti/pruss.c:158:38: error: cast from 'void (*)(struct clk *)' to 'void (*)(void *)' converts to incompatible function type [-Werror,-Wcast-function-type-strict] ret = devm_add_action_or_reset(dev, (void(*)(void *))clk_unregister_mux, No functional change intended. Compile tested only. Signed-off-by: Simon Horman Reviewed-by: MD Danish Anwar Reviewed-by: Nick Desaulniers Reviewed-by: Nathan Chancellor Link: https://lore.kernel.org/r/20230418-pruss-clk-cb-v1-1-549a7e7febe4@kernel.org Signed-off-by: Nishanth Menon --- drivers/soc/ti/pruss.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index 6882c86b3ce5..e68441bd7b30 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -38,6 +38,11 @@ static void pruss_of_free_clk_provider(void *data) of_node_put(clk_mux_np); } +static void pruss_clk_unregister_mux(void *data) +{ + clk_unregister_mux(data); +} + static int pruss_clk_mux_setup(struct pruss *pruss, struct clk *clk_mux, char *mux_name, struct device_node *clks_np) { @@ -93,8 +98,7 @@ static int pruss_clk_mux_setup(struct pruss *pruss, struct clk *clk_mux, goto put_clk_mux_np; } - ret = devm_add_action_or_reset(dev, (void(*)(void *))clk_unregister_mux, - clk_mux); + ret = devm_add_action_or_reset(dev, pruss_clk_unregister_mux, clk_mux); if (ret) { dev_err(dev, "failed to add clkmux unregister action %d", ret); goto put_clk_mux_np; -- cgit v1.2.3 From e752f9b924a1fd1afcf36e51b03dfa9c3096a3bd Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 11 May 2023 16:54:36 +0200 Subject: soc: ti: pruss: Allow compile-testing Allow compile testing of TI PRU-ICSS Subsystem Platform drivers. This allows for improved build-test coverage. No functional change intended. Signed-off-by: Simon Horman Link: https://lore.kernel.org/r/20230511-ti-pruss-compile-testing-v1-1-56291309a60c@kernel.org Signed-off-by: Nishanth Menon --- drivers/soc/ti/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index 8c2a1036bef5..2cae17b65fd9 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig @@ -85,7 +85,7 @@ config TI_K3_SOCINFO config TI_PRUSS tristate "TI PRU-ICSS Subsystem Platform drivers" - depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX || ARCH_KEYSTONE || ARCH_K3 + depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX || ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST select MFD_SYSCON help TI PRU-ICSS Subsystem platform specific support. -- cgit v1.2.3 From 67d1b0a1030fb20d54b720df6e976c06b893fb00 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 14 Apr 2023 10:25:39 +0530 Subject: soc: ti: pruss: Add pruss_get()/put() API Add two new get and put API, pruss_get() and pruss_put() to the PRUSS platform driver to allow client drivers to request a handle to a PRUSS device. This handle will be used by client drivers to request various operations of the PRUSS platform driver through additional API that will be added in the following patches. The pruss_get() function returns the pruss handle corresponding to a PRUSS device referenced by a PRU remoteproc instance. The pruss_put() is the complimentary function to pruss_get(). Co-developed-by: Suman Anna Signed-off-by: Suman Anna Signed-off-by: Tero Kristo Co-developed-by: Grzegorz Jaszczyk Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Puranjay Mohan Reviewed-by: Roger Quadros Reviewed-by: Tony Lindgren Reviewed-by: Simon Horman Acked-by: Mathieu Poirier Signed-off-by: MD Danish Anwar Link: https://lore.kernel.org/r/20230414045542.3249939-2-danishanwar@ti.com Signed-off-by: Nishanth Menon --- drivers/soc/ti/pruss.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'drivers/soc') diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index e68441bd7b30..f836660dac64 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -6,6 +6,7 @@ * Author(s): * Suman Anna * Andrew F. Davis + * Tero Kristo */ #include @@ -18,6 +19,7 @@ #include #include #include +#include #include /** @@ -30,6 +32,66 @@ struct pruss_private_data { bool has_core_mux_clock; }; +/** + * pruss_get() - get the pruss for a given PRU remoteproc + * @rproc: remoteproc handle of a PRU instance + * + * Finds the parent pruss device for a PRU given the @rproc handle of the + * PRU remote processor. This function increments the pruss device's refcount, + * so always use pruss_put() to decrement it back once pruss isn't needed + * anymore. + * + * This API doesn't check if @rproc is valid or not. It is expected the caller + * will have done a pru_rproc_get() on @rproc, before calling this API to make + * sure that @rproc is valid. + * + * Return: pruss handle on success, and an ERR_PTR on failure using one + * of the following error values + * -EINVAL if invalid parameter + * -ENODEV if PRU device or PRUSS device is not found + */ +struct pruss *pruss_get(struct rproc *rproc) +{ + struct pruss *pruss; + struct device *dev; + struct platform_device *ppdev; + + if (IS_ERR_OR_NULL(rproc)) + return ERR_PTR(-EINVAL); + + dev = &rproc->dev; + + /* make sure it is PRU rproc */ + if (!dev->parent || !is_pru_rproc(dev->parent)) + return ERR_PTR(-ENODEV); + + ppdev = to_platform_device(dev->parent->parent); + pruss = platform_get_drvdata(ppdev); + if (!pruss) + return ERR_PTR(-ENODEV); + + get_device(pruss->dev); + + return pruss; +} +EXPORT_SYMBOL_GPL(pruss_get); + +/** + * pruss_put() - decrement pruss device's usecount + * @pruss: pruss handle + * + * Complimentary function for pruss_get(). Needs to be called + * after the PRUSS is used, and only if the pruss_get() succeeds. + */ +void pruss_put(struct pruss *pruss) +{ + if (IS_ERR_OR_NULL(pruss)) + return; + + put_device(pruss->dev); +} +EXPORT_SYMBOL_GPL(pruss_put); + static void pruss_of_free_clk_provider(void *data) { struct device_node *clk_mux_np = data; -- cgit v1.2.3 From b789ca1e3380ab63b60c3356c026a7e8eb26ba01 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Fri, 14 Apr 2023 10:25:40 +0530 Subject: soc: ti: pruss: Add pruss_{request,release}_mem_region() API Add two new API - pruss_request_mem_region() & pruss_release_mem_region(), to the PRUSS platform driver to allow client drivers to acquire and release the common memory resources present within a PRU-ICSS subsystem. This allows the client drivers to directly manipulate the respective memories, as per their design contract with the associated firmware. Co-developed-by: Suman Anna Signed-off-by: Suman Anna Signed-off-by: Andrew F. Davis Co-developed-by: Grzegorz Jaszczyk Signed-off-by: Grzegorz Jaszczyk Reviewed-by: Roger Quadros Acked-by: Mathieu Poirier Reviewed-by: Tony Lindgren Reviewed-by: Simon Horman Signed-off-by: MD Danish Anwar Link: https://lore.kernel.org/r/20230414045542.3249939-3-danishanwar@ti.com Signed-off-by: Nishanth Menon --- drivers/soc/ti/pruss.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'drivers/soc') diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index f836660dac64..df5eb4d959f8 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -92,6 +92,82 @@ void pruss_put(struct pruss *pruss) } EXPORT_SYMBOL_GPL(pruss_put); +/** + * pruss_request_mem_region() - request a memory resource + * @pruss: the pruss instance + * @mem_id: the memory resource id + * @region: pointer to memory region structure to be filled in + * + * This function allows a client driver to request a memory resource, + * and if successful, will let the client driver own the particular + * memory region until released using the pruss_release_mem_region() + * API. + * + * Return: 0 if requested memory region is available (in such case pointer to + * memory region is returned via @region), an error otherwise + */ +int pruss_request_mem_region(struct pruss *pruss, enum pruss_mem mem_id, + struct pruss_mem_region *region) +{ + if (!pruss || !region || mem_id >= PRUSS_MEM_MAX) + return -EINVAL; + + mutex_lock(&pruss->lock); + + if (pruss->mem_in_use[mem_id]) { + mutex_unlock(&pruss->lock); + return -EBUSY; + } + + *region = pruss->mem_regions[mem_id]; + pruss->mem_in_use[mem_id] = region; + + mutex_unlock(&pruss->lock); + + return 0; +} +EXPORT_SYMBOL_GPL(pruss_request_mem_region); + +/** + * pruss_release_mem_region() - release a memory resource + * @pruss: the pruss instance + * @region: the memory region to release + * + * This function is the complimentary function to + * pruss_request_mem_region(), and allows the client drivers to + * release back a memory resource. + * + * Return: 0 on success, an error code otherwise + */ +int pruss_release_mem_region(struct pruss *pruss, + struct pruss_mem_region *region) +{ + int id; + + if (!pruss || !region) + return -EINVAL; + + mutex_lock(&pruss->lock); + + /* find out the memory region being released */ + for (id = 0; id < PRUSS_MEM_MAX; id++) { + if (pruss->mem_in_use[id] == region) + break; + } + + if (id == PRUSS_MEM_MAX) { + mutex_unlock(&pruss->lock); + return -EINVAL; + } + + pruss->mem_in_use[id] = NULL; + + mutex_unlock(&pruss->lock); + + return 0; +} +EXPORT_SYMBOL_GPL(pruss_release_mem_region); + static void pruss_of_free_clk_provider(void *data) { struct device_node *clk_mux_np = data; @@ -298,6 +374,7 @@ static int pruss_probe(struct platform_device *pdev) return -ENOMEM; pruss->dev = dev; + mutex_init(&pruss->lock); child = of_get_child_by_name(np, "memories"); if (!child) { -- cgit v1.2.3 From 51b5760e56ef19106a3c4487a66d186d46ccc6f4 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 14 Apr 2023 10:25:41 +0530 Subject: soc: ti: pruss: Add pruss_cfg_read()/update(), pruss_cfg_get_gpmux()/set_gpmux() APIs Add two new generic API pruss_cfg_read() and pruss_cfg_update() to the PRUSS platform driver to read and program respectively a register within the PRUSS CFG sub-module represented by a syscon driver. These APIs are internal to PRUSS driver. Add two new helper functions pruss_cfg_get_gpmux() & pruss_cfg_set_gpmux() to get and set the GP MUX mode for programming the PRUSS internal wrapper mux functionality as needed by usecases. Various useful registers and macros for certain register bit-fields and their values have also been added. Signed-off-by: Suman Anna Co-developed-by: Grzegorz Jaszczyk Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Puranjay Mohan Reviewed-by: Roger Quadros Reviewed-by: Tony Lindgren Reviewed-by: Simon Horman Acked-by: Mathieu Poirier Signed-off-by: MD Danish Anwar Link: https://lore.kernel.org/r/20230414045542.3249939-4-danishanwar@ti.com Signed-off-by: Nishanth Menon --- drivers/soc/ti/pruss.c | 45 ++++++++++++++++++++++++++ drivers/soc/ti/pruss.h | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 drivers/soc/ti/pruss.h (limited to 'drivers/soc') diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index df5eb4d959f8..2c44913c083b 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -21,6 +21,7 @@ #include #include #include +#include "pruss.h" /** * struct pruss_private_data - PRUSS driver private data @@ -168,6 +169,50 @@ int pruss_release_mem_region(struct pruss *pruss, } EXPORT_SYMBOL_GPL(pruss_release_mem_region); +/** + * pruss_cfg_get_gpmux() - get the current GPMUX value for a PRU device + * @pruss: pruss instance + * @pru_id: PRU identifier (0-1) + * @mux: pointer to store the current mux value into + * + * Return: 0 on success, or an error code otherwise + */ +int pruss_cfg_get_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 *mux) +{ + int ret; + u32 val; + + if (pru_id >= PRUSS_NUM_PRUS || !mux) + return -EINVAL; + + ret = pruss_cfg_read(pruss, PRUSS_CFG_GPCFG(pru_id), &val); + if (!ret) + *mux = (u8)((val & PRUSS_GPCFG_PRU_MUX_SEL_MASK) >> + PRUSS_GPCFG_PRU_MUX_SEL_SHIFT); + return ret; +} +EXPORT_SYMBOL_GPL(pruss_cfg_get_gpmux); + +/** + * pruss_cfg_set_gpmux() - set the GPMUX value for a PRU device + * @pruss: pruss instance + * @pru_id: PRU identifier (0-1) + * @mux: new mux value for PRU + * + * Return: 0 on success, or an error code otherwise + */ +int pruss_cfg_set_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 mux) +{ + if (mux >= PRUSS_GP_MUX_SEL_MAX || + pru_id >= PRUSS_NUM_PRUS) + return -EINVAL; + + return pruss_cfg_update(pruss, PRUSS_CFG_GPCFG(pru_id), + PRUSS_GPCFG_PRU_MUX_SEL_MASK, + (u32)mux << PRUSS_GPCFG_PRU_MUX_SEL_SHIFT); +} +EXPORT_SYMBOL_GPL(pruss_cfg_set_gpmux); + static void pruss_of_free_clk_provider(void *data) { struct device_node *clk_mux_np = data; diff --git a/drivers/soc/ti/pruss.h b/drivers/soc/ti/pruss.h new file mode 100644 index 000000000000..6c55987e0e55 --- /dev/null +++ b/drivers/soc/ti/pruss.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * PRU-ICSS Subsystem user interfaces + * + * Copyright (C) 2015-2023 Texas Instruments Incorporated - http://www.ti.com + * MD Danish Anwar + */ + +#ifndef _SOC_TI_PRUSS_H_ +#define _SOC_TI_PRUSS_H_ + +#include +#include + +/* + * PRU_ICSS_CFG registers + * SYSCFG, ISRP, ISP, IESP, IECP, SCRP applicable on AMxxxx devices only + */ +#define PRUSS_CFG_REVID 0x00 +#define PRUSS_CFG_SYSCFG 0x04 +#define PRUSS_CFG_GPCFG(x) (0x08 + (x) * 4) +#define PRUSS_CFG_CGR 0x10 +#define PRUSS_CFG_ISRP 0x14 +#define PRUSS_CFG_ISP 0x18 +#define PRUSS_CFG_IESP 0x1C +#define PRUSS_CFG_IECP 0x20 +#define PRUSS_CFG_SCRP 0x24 +#define PRUSS_CFG_PMAO 0x28 +#define PRUSS_CFG_MII_RT 0x2C +#define PRUSS_CFG_IEPCLK 0x30 +#define PRUSS_CFG_SPP 0x34 +#define PRUSS_CFG_PIN_MX 0x40 + +/* PRUSS_GPCFG register bits */ +#define PRUSS_GPCFG_PRU_GPI_MODE_MASK GENMASK(1, 0) +#define PRUSS_GPCFG_PRU_GPI_MODE_SHIFT 0 + +#define PRUSS_GPCFG_PRU_MUX_SEL_SHIFT 26 +#define PRUSS_GPCFG_PRU_MUX_SEL_MASK GENMASK(29, 26) + +/* PRUSS_MII_RT register bits */ +#define PRUSS_MII_RT_EVENT_EN BIT(0) + +/* PRUSS_SPP register bits */ +#define PRUSS_SPP_XFER_SHIFT_EN BIT(1) +#define PRUSS_SPP_PRU1_PAD_HP_EN BIT(0) +#define PRUSS_SPP_RTU_XFR_SHIFT_EN BIT(3) + +/** + * pruss_cfg_read() - read a PRUSS CFG sub-module register + * @pruss: the pruss instance handle + * @reg: register offset within the CFG sub-module + * @val: pointer to return the value in + * + * Reads a given register within the PRUSS CFG sub-module and + * returns it through the passed-in @val pointer + * + * Return: 0 on success, or an error code otherwise + */ +static int pruss_cfg_read(struct pruss *pruss, unsigned int reg, unsigned int *val) +{ + if (IS_ERR_OR_NULL(pruss)) + return -EINVAL; + + return regmap_read(pruss->cfg_regmap, reg, val); +} + +/** + * pruss_cfg_update() - configure a PRUSS CFG sub-module register + * @pruss: the pruss instance handle + * @reg: register offset within the CFG sub-module + * @mask: bit mask to use for programming the @val + * @val: value to write + * + * Programs a given register within the PRUSS CFG sub-module + * + * Return: 0 on success, or an error code otherwise + */ +static int pruss_cfg_update(struct pruss *pruss, unsigned int reg, + unsigned int mask, unsigned int val) +{ + if (IS_ERR_OR_NULL(pruss)) + return -EINVAL; + + return regmap_update_bits(pruss->cfg_regmap, reg, mask, val); +} + +#endif /* _SOC_TI_PRUSS_H_ */ -- cgit v1.2.3 From 0211cc1e4fbbc81853227147bf0982c47362c567 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 14 Apr 2023 10:25:42 +0530 Subject: soc: ti: pruss: Add helper functions to set GPI mode, MII_RT_event and XFR The PRUSS CFG module is represented as a syscon node and is currently managed by the PRUSS platform driver. Add easy accessor functions to set GPI mode, MII_RT event enable/disable and XFR (XIN XOUT) enable/disable to enable the PRUSS Ethernet usecase. These functions reuse the generic pruss_cfg_update() API function. Signed-off-by: Suman Anna Co-developed-by: Grzegorz Jaszczyk Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Puranjay Mohan Reviewed-by: Roger Quadros Reviewed-by: Tony Lindgren Reviewed-by: Simon Horman Reviewed-by: Mathieu Poirier Signed-off-by: MD Danish Anwar Link: https://lore.kernel.org/r/20230414045542.3249939-5-danishanwar@ti.com Signed-off-by: Nishanth Menon --- drivers/soc/ti/pruss.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'drivers/soc') diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index 2c44913c083b..7fdefee1ed87 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -213,6 +213,77 @@ int pruss_cfg_set_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 mux) } EXPORT_SYMBOL_GPL(pruss_cfg_set_gpmux); +/** + * pruss_cfg_gpimode() - set the GPI mode of the PRU + * @pruss: the pruss instance handle + * @pru_id: id of the PRU core within the PRUSS + * @mode: GPI mode to set + * + * Sets the GPI mode for a given PRU by programming the + * corresponding PRUSS_CFG_GPCFGx register + * + * Return: 0 on success, or an error code otherwise + */ +int pruss_cfg_gpimode(struct pruss *pruss, enum pruss_pru_id pru_id, + enum pruss_gpi_mode mode) +{ + if (pru_id >= PRUSS_NUM_PRUS || mode >= PRUSS_GPI_MODE_MAX) + return -EINVAL; + + return pruss_cfg_update(pruss, PRUSS_CFG_GPCFG(pru_id), + PRUSS_GPCFG_PRU_GPI_MODE_MASK, + mode << PRUSS_GPCFG_PRU_GPI_MODE_SHIFT); +} +EXPORT_SYMBOL_GPL(pruss_cfg_gpimode); + +/** + * pruss_cfg_miirt_enable() - Enable/disable MII RT Events + * @pruss: the pruss instance + * @enable: enable/disable + * + * Enable/disable the MII RT Events for the PRUSS. + * + * Return: 0 on success, or an error code otherwise + */ +int pruss_cfg_miirt_enable(struct pruss *pruss, bool enable) +{ + u32 set = enable ? PRUSS_MII_RT_EVENT_EN : 0; + + return pruss_cfg_update(pruss, PRUSS_CFG_MII_RT, + PRUSS_MII_RT_EVENT_EN, set); +} +EXPORT_SYMBOL_GPL(pruss_cfg_miirt_enable); + +/** + * pruss_cfg_xfr_enable() - Enable/disable XIN XOUT shift functionality + * @pruss: the pruss instance + * @pru_type: PRU core type identifier + * @enable: enable/disable + * + * Return: 0 on success, or an error code otherwise + */ +int pruss_cfg_xfr_enable(struct pruss *pruss, enum pru_type pru_type, + bool enable) +{ + u32 mask, set; + + switch (pru_type) { + case PRU_TYPE_PRU: + mask = PRUSS_SPP_XFER_SHIFT_EN; + break; + case PRU_TYPE_RTU: + mask = PRUSS_SPP_RTU_XFR_SHIFT_EN; + break; + default: + return -EINVAL; + } + + set = enable ? mask : 0; + + return pruss_cfg_update(pruss, PRUSS_CFG_SPP, mask, set); +} +EXPORT_SYMBOL_GPL(pruss_cfg_xfr_enable); + static void pruss_of_free_clk_provider(void *data) { struct device_node *clk_mux_np = data; -- cgit v1.2.3 From 4b11fa4f0737aae1a3fc3cdf367acd4ebb5bc941 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 23 May 2023 09:15:50 +0200 Subject: qcom: pmic_glink: enable altmode for SM8450 Create a separate bitmask for sm8550 and enable altmode aux driver for sm8450 platform to enable pmic-glink altmode events. Signed-off-by: Neil Armstrong Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230503-topic-sm8450-graphics-dp-next-v3-6-6c43d293995f@linaro.org --- drivers/soc/qcom/pmic_glink.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c index 8bf95df0a56a..c87056769ebd 100644 --- a/drivers/soc/qcom/pmic_glink.c +++ b/drivers/soc/qcom/pmic_glink.c @@ -338,13 +338,17 @@ static int pmic_glink_remove(struct platform_device *pdev) return 0; } -/* Do not handle altmode for now on those platforms */ static const unsigned long pmic_glink_sm8450_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) | + BIT(PMIC_GLINK_CLIENT_ALTMODE) | + BIT(PMIC_GLINK_CLIENT_UCSI); + +/* Do not handle altmode for now on those platforms */ +static const unsigned long pmic_glink_sm8550_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) | BIT(PMIC_GLINK_CLIENT_UCSI); static const struct of_device_id pmic_glink_of_match[] = { { .compatible = "qcom,sm8450-pmic-glink", .data = &pmic_glink_sm8450_client_mask }, - { .compatible = "qcom,sm8550-pmic-glink", .data = &pmic_glink_sm8450_client_mask }, + { .compatible = "qcom,sm8550-pmic-glink", .data = &pmic_glink_sm8550_client_mask }, { .compatible = "qcom,pmic-glink" }, {} }; -- cgit v1.2.3 From 210d12c8197a551caa2979be421aa42381156aec Mon Sep 17 00:00:00 2001 From: Gokul krishna Krishnakumar Date: Mon, 8 May 2023 17:18:21 -0700 Subject: soc: qcom: mdt_loader: Enhance split binary detection It may be that the offset of the first program header lies inside the mdt's filesize, in this case the loader would incorrectly assume that the bins were not split and in this scenario the firmware authentication fails. This change updates the logic used by the mdt loader to understand whether the firmware images are split or not. It figures this out by checking if each programs header's segment lies within the file or not. Co-developed-by: Melody Olvera Signed-off-by: Melody Olvera Signed-off-by: Gokul krishna Krishnakumar Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230509001821.24010-1-quic_gokukris@quicinc.com --- drivers/soc/qcom/mdt_loader.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c index 33dd8c315eb7..892b1648d693 100644 --- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -258,6 +258,26 @@ out: } EXPORT_SYMBOL_GPL(qcom_mdt_pas_init); +static bool qcom_mdt_bins_are_split(const struct firmware *fw, const char *fw_name) +{ + const struct elf32_phdr *phdrs; + const struct elf32_hdr *ehdr; + uint64_t seg_start, seg_end; + int i; + + ehdr = (struct elf32_hdr *)fw->data; + phdrs = (struct elf32_phdr *)(ehdr + 1); + + for (i = 0; i < ehdr->e_phnum; i++) { + seg_start = phdrs[i].p_offset; + seg_end = phdrs[i].p_offset + phdrs[i].p_filesz; + if (seg_start > fw->size || seg_end > fw->size) + return true; + } + + return false; +} + static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, const char *fw_name, int pas_id, void *mem_region, phys_addr_t mem_phys, size_t mem_size, @@ -270,6 +290,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, phys_addr_t min_addr = PHYS_ADDR_MAX; ssize_t offset; bool relocate = false; + bool is_split; void *ptr; int ret = 0; int i; @@ -277,6 +298,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, if (!fw || !mem_region || !mem_phys || !mem_size) return -EINVAL; + is_split = qcom_mdt_bins_are_split(fw, fw_name); ehdr = (struct elf32_hdr *)fw->data; phdrs = (struct elf32_phdr *)(ehdr + 1); @@ -330,8 +352,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, ptr = mem_region + offset; - if (phdr->p_filesz && phdr->p_offset < fw->size && - phdr->p_offset + phdr->p_filesz <= fw->size) { + if (phdr->p_filesz && !is_split) { /* Firmware is large enough to be non-split */ if (phdr->p_offset + phdr->p_filesz > fw->size) { dev_err(dev, "file %s segment %d would be truncated\n", -- cgit v1.2.3 From 4b819e7e89fedc90150a78152bfa6e6e3534e64b Mon Sep 17 00:00:00 2001 From: Min-Hua Chen Date: Tue, 23 May 2023 00:07:56 +0800 Subject: soc: qcom: rpmpd: use correct __le32 type Use cpu_to_le32 to cast constants to __le32 before comparing them with __le32 type pd->key. This fixes the following sparse warnings: drivers/soc/qcom/rpmpd.c:895:31: sparse: warning: restricted __le32 degrades to integer drivers/soc/qcom/rpmpd.c:896:15: sparse: warning: restricted __le32 degrades to integer Signed-off-by: Min-Hua Chen Reviewed-by: Konrad Dybcio Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230522160757.284165-1-minhuadotchen@gmail.com --- drivers/soc/qcom/rpmpd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c index f8397dcb146c..99b017fd76b7 100644 --- a/drivers/soc/qcom/rpmpd.c +++ b/drivers/soc/qcom/rpmpd.c @@ -892,8 +892,8 @@ static int rpmpd_set_performance(struct generic_pm_domain *domain, pd->corner = state; /* Always send updates for vfc and vfl */ - if (!pd->enabled && pd->key != KEY_FLOOR_CORNER && - pd->key != KEY_FLOOR_LEVEL) + 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); -- cgit v1.2.3 From c72e31718a8fb9bc070ee99f273446e05caa687d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sat, 15 Apr 2023 22:18:48 +0200 Subject: soc: qcom: ramp_controller: Improve error message for failure in .remove() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a platform_driver's .remove() callback returns an error, the driver core emits remove callback returned a non-zero value. This will be ignored. . Replace this by a more specific error message. Then convert to .remove_new() which is equivalent to returning zero unconditionally in .remove(). See commit 5c5a7680e67b ("platform: Provide a remove callback that returns no value") for its rationale. Signed-off-by: Uwe Kleine-König Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230415201848.3779001-1-u.kleine-koenig@pengutronix.de --- drivers/soc/qcom/ramp_controller.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/ramp_controller.c b/drivers/soc/qcom/ramp_controller.c index dc74d2a19de2..1ff13661bcce 100644 --- a/drivers/soc/qcom/ramp_controller.c +++ b/drivers/soc/qcom/ramp_controller.c @@ -308,12 +308,15 @@ static int qcom_ramp_controller_probe(struct platform_device *pdev) return qcom_ramp_controller_start(qrc); } -static int qcom_ramp_controller_remove(struct platform_device *pdev) +static void qcom_ramp_controller_remove(struct platform_device *pdev) { struct qcom_ramp_controller *qrc = platform_get_drvdata(pdev); + int ret; - return rc_write_cfg(qrc, qrc->desc->cfg_ramp_dis, - RC_DCVS_CFG_SID, qrc->desc->num_ramp_dis); + ret = rc_write_cfg(qrc, qrc->desc->cfg_ramp_dis, + RC_DCVS_CFG_SID, qrc->desc->num_ramp_dis); + if (ret) + dev_err(&pdev->dev, "Failed to send disable sequence\n"); } static const struct of_device_id qcom_ramp_controller_match_table[] = { @@ -329,7 +332,7 @@ static struct platform_driver qcom_ramp_controller_driver = { .suppress_bind_attrs = true, }, .probe = qcom_ramp_controller_probe, - .remove = qcom_ramp_controller_remove, + .remove_new = qcom_ramp_controller_remove, }; static int __init qcom_ramp_controller_init(void) -- cgit v1.2.3 From 56310520308ab863030e9baa9a8f63bb31c94e27 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 20 Apr 2023 16:50:38 -1000 Subject: soc: qcom: qmi: Use alloc_ordered_workqueue() to create ordered workqueues BACKGROUND ========== When multiple work items are queued to a workqueue, their execution order doesn't match the queueing order. They may get executed in any order and simultaneously. When fully serialized execution - one by one in the queueing order - is needed, an ordered workqueue should be used which can be created with alloc_ordered_workqueue(). However, alloc_ordered_workqueue() was a later addition. Before it, an ordered workqueue could be obtained by creating an UNBOUND workqueue with @max_active==1. This originally was an implementation side-effect which was broken by 4c16bd327c74 ("workqueue: restore WQ_UNBOUND/max_active==1 to be ordered"). Because there were users that depended on the ordered execution, 5c0338c68706 ("workqueue: restore WQ_UNBOUND/max_active==1 to be ordered") made workqueue allocation path to implicitly promote UNBOUND workqueues w/ @max_active==1 to ordered workqueues. While this has worked okay, overloading the UNBOUND allocation interface this way creates other issues. It's difficult to tell whether a given workqueue actually needs to be ordered and users that legitimately want a min concurrency level wq unexpectedly gets an ordered one instead. With planned UNBOUND workqueue updates to improve execution locality and more prevalence of chiplet designs which can benefit from such improvements, this isn't a state we wanna be in forever. This patch series audits all callsites that create an UNBOUND workqueue w/ @max_active==1 and converts them to alloc_ordered_workqueue() as necessary. WHAT TO LOOK FOR ================ The conversions are from alloc_workqueue(WQ_UNBOUND | flags, 1, args..) to alloc_ordered_workqueue(flags, args...) which don't cause any functional changes. If you know that fully ordered execution is not ncessary, please let me know. I'll drop the conversion and instead add a comment noting the fact to reduce confusion while conversion is in progress. If you aren't fully sure, it's completely fine to let the conversion through. The behavior will stay exactly the same and we can always reconsider later. As there are follow-up workqueue core changes, I'd really appreciate if the patch can be routed through the workqueue tree w/ your acks. Thanks. Signed-off-by: Tejun Heo Cc: Andy Gross Cc: Bjorn Andersson Cc: Konrad Dybcio Cc: linux-arm-msm@vger.kernel.org Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230421025046.4008499-15-tj@kernel.org --- drivers/soc/qcom/qmi_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c index 820bdd9f8e46..78d7361fdcf2 100644 --- a/drivers/soc/qcom/qmi_interface.c +++ b/drivers/soc/qcom/qmi_interface.c @@ -650,7 +650,7 @@ int qmi_handle_init(struct qmi_handle *qmi, size_t recv_buf_size, if (!qmi->recv_buf) return -ENOMEM; - qmi->wq = alloc_workqueue("qmi_msg_handler", WQ_UNBOUND, 1); + qmi->wq = alloc_ordered_workqueue("qmi_msg_handler", 0); if (!qmi->wq) { ret = -ENOMEM; goto err_free_recv_buf; -- cgit v1.2.3 From a77b2a0b12801a232226d227636236ed89b77043 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Thu, 20 Apr 2023 19:36:18 +0200 Subject: soc: qcom: Introduce RPM master stats driver Introduce a driver to query and expose detailed, per-subsystem (as opposed to the existing qcom_stats driver which exposes SoC-wide data) about low power mode states of a given RPM master. That includes the APSS (ARM), MPSS (modem) and other remote cores, depending on the platform configuration. This is a vastly cleaned up and restructured version of a similar driver found in msm-5.4. Reviewed-by: Manivannan Sadhasivam Signed-off-by: Konrad Dybcio Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230405-topic-master_stats-v6-2-2277b4433748@linaro.org --- drivers/soc/qcom/Kconfig | 11 +++ drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/rpm_master_stats.c | 163 ++++++++++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+) create mode 100644 drivers/soc/qcom/rpm_master_stats.c (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index a491718f8064..e597799e8121 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -135,6 +135,17 @@ config QCOM_RMTFS_MEM Say y here if you intend to boot the modem remoteproc. +config QCOM_RPM_MASTER_STATS + tristate "Qualcomm RPM Master stats" + depends on ARCH_QCOM || COMPILE_TEST + help + The RPM Master sleep stats driver provides detailed per-subsystem + sleep/wake data, read from the RPM message RAM. It can be used to + assess whether all the low-power modes available are entered as + expected or to check which part of the SoC prevents it from sleeping. + + Say y here if you intend to debug or monitor platform sleep. + config QCOM_RPMH tristate "Qualcomm RPM-Hardened (RPMH) Communication" depends on ARCH_QCOM || COMPILE_TEST diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 0f43a88b4894..7349371fdea1 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_QCOM_QMI_HELPERS) += qmi_helpers.o qmi_helpers-y += qmi_encdec.o qmi_interface.o obj-$(CONFIG_QCOM_RAMP_CTRL) += ramp_controller.o obj-$(CONFIG_QCOM_RMTFS_MEM) += rmtfs_mem.o +obj-$(CONFIG_QCOM_RPM_MASTER_STATS) += rpm_master_stats.o obj-$(CONFIG_QCOM_RPMH) += qcom_rpmh.o qcom_rpmh-y += rpmh-rsc.o qcom_rpmh-y += rpmh.o diff --git a/drivers/soc/qcom/rpm_master_stats.c b/drivers/soc/qcom/rpm_master_stats.c new file mode 100644 index 000000000000..6dd98b9f7129 --- /dev/null +++ b/drivers/soc/qcom/rpm_master_stats.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Linaro Limited + * + * This driver supports what is known as "Master Stats v2" in Qualcomm + * downstream kernel terms, which seems to be the only version which has + * ever shipped, all the way from 2013 to 2023. + */ + +#include +#include +#include +#include +#include +#include + +struct master_stats_data { + void __iomem *base; + const char *label; +}; + +struct rpm_master_stats { + u32 active_cores; + u32 num_shutdowns; + u64 shutdown_req; + u64 wakeup_idx; + u64 bringup_req; + u64 bringup_ack; + u32 wakeup_reason; /* 0 = "rude wakeup", 1 = scheduled wakeup */ + u32 last_sleep_trans_dur; + u32 last_wake_trans_dur; + + /* Per-subsystem (*not necessarily* SoC-wide) XO shutdown stats */ + u32 xo_count; + u64 xo_last_enter; + u64 last_exit; + u64 xo_total_dur; +} __packed; + +static int master_stats_show(struct seq_file *s, void *unused) +{ + struct master_stats_data *data = s->private; + struct rpm_master_stats stat; + + memcpy_fromio(&stat, data->base, sizeof(stat)); + + seq_printf(s, "%s:\n", data->label); + + seq_printf(s, "\tLast shutdown @ %llu\n", stat.shutdown_req); + seq_printf(s, "\tLast bringup req @ %llu\n", stat.bringup_req); + seq_printf(s, "\tLast bringup ack @ %llu\n", stat.bringup_ack); + seq_printf(s, "\tLast wakeup idx: %llu\n", stat.wakeup_idx); + seq_printf(s, "\tLast XO shutdown enter @ %llu\n", stat.xo_last_enter); + seq_printf(s, "\tLast XO shutdown exit @ %llu\n", stat.last_exit); + seq_printf(s, "\tXO total duration: %llu\n", stat.xo_total_dur); + seq_printf(s, "\tLast sleep transition duration: %u\n", stat.last_sleep_trans_dur); + seq_printf(s, "\tLast wake transition duration: %u\n", stat.last_wake_trans_dur); + seq_printf(s, "\tXO shutdown count: %u\n", stat.xo_count); + seq_printf(s, "\tWakeup reason: 0x%x\n", stat.wakeup_reason); + seq_printf(s, "\tShutdown count: %u\n", stat.num_shutdowns); + seq_printf(s, "\tActive cores bitmask: 0x%x\n", stat.active_cores); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(master_stats); + +static int master_stats_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct master_stats_data *data; + struct device_node *msgram_np; + struct dentry *dent, *root; + struct resource res; + int count, i, ret; + + count = of_property_count_strings(dev->of_node, "qcom,master-names"); + if (count < 0) + return count; + + data = devm_kzalloc(dev, count * sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + root = debugfs_create_dir("qcom_rpm_master_stats", NULL); + platform_set_drvdata(pdev, root); + + for (i = 0; i < count; i++) { + msgram_np = of_parse_phandle(dev->of_node, "qcom,rpm-msg-ram", i); + if (!msgram_np) { + debugfs_remove_recursive(root); + return dev_err_probe(dev, -ENODEV, + "Couldn't parse MSG RAM phandle idx %d", i); + } + + /* + * Purposefully skip devm_platform helpers as we're using a + * shared resource. + */ + ret = of_address_to_resource(msgram_np, 0, &res); + of_node_put(msgram_np); + if (ret < 0) { + debugfs_remove_recursive(root); + return ret; + } + + data[i].base = devm_ioremap(dev, res.start, resource_size(&res)); + if (IS_ERR(data[i].base)) { + debugfs_remove_recursive(root); + return dev_err_probe(dev, -EINVAL, + "Could not map the MSG RAM slice idx %d!\n", i); + } + + ret = of_property_read_string_index(dev->of_node, "qcom,master-names", i, + &data[i].label); + if (ret < 0) { + debugfs_remove_recursive(root); + return dev_err_probe(dev, ret, + "Could not read name idx %d!\n", i); + } + + /* + * Generally it's not advised to fail on debugfs errors, but this + * driver's only job is exposing data therein. + */ + dent = debugfs_create_file(data[i].label, 0444, root, + &data[i], &master_stats_fops); + if (IS_ERR(dent)) { + debugfs_remove_recursive(root); + return dev_err_probe(dev, PTR_ERR(dent), + "Failed to create debugfs file %s!\n", data[i].label); + } + } + + device_set_pm_not_required(dev); + + return 0; +} + +static void master_stats_remove(struct platform_device *pdev) +{ + struct dentry *root = platform_get_drvdata(pdev); + + debugfs_remove_recursive(root); +} + +static const struct of_device_id rpm_master_table[] = { + { .compatible = "qcom,rpm-master-stats" }, + { }, +}; + +static struct platform_driver master_stats_driver = { + .probe = master_stats_probe, + .remove_new = master_stats_remove, + .driver = { + .name = "qcom_rpm_master_stats", + .of_match_table = rpm_master_table, + }, +}; +module_platform_driver(master_stats_driver); + +MODULE_DESCRIPTION("Qualcomm RPM Master Statistics driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 0369a5906e46a2431a8fe04aa79cba6583e53e73 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sat, 29 Apr 2023 21:33:36 +0200 Subject: soc: qcom: socinfo: Add IDs for IPQ5018 family Add SOC IDs for the IPQ5018 family. Signed-off-by: Robert Marko Reviewed-by: Krzysztof Kozlowski Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230429193336.600629-2-robimarko@gmail.com --- drivers/soc/qcom/socinfo.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index c2e4a57dd666..c61a93b4dcaf 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -434,6 +434,9 @@ static const struct soc_id soc_id[] = { { qcom_board_id(SM8350) }, { qcom_board_id(QCM2290) }, { qcom_board_id(SM6115) }, + { qcom_board_id(IPQ5010) }, + { qcom_board_id(IPQ5018) }, + { qcom_board_id(IPQ5028) }, { qcom_board_id(SC8280XP) }, { qcom_board_id(IPQ6005) }, { qcom_board_id(QRB5165) }, @@ -447,6 +450,9 @@ static const struct soc_id soc_id[] = { { qcom_board_id_named(SM8450_3, "SM8450") }, { qcom_board_id(SC7280) }, { qcom_board_id(SC7180P) }, + { qcom_board_id(IPQ5000) }, + { qcom_board_id(IPQ0509) }, + { qcom_board_id(IPQ0518) }, { qcom_board_id(SM6375) }, { qcom_board_id(IPQ9514) }, { qcom_board_id(IPQ9550) }, @@ -454,6 +460,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(IPQ9570) }, { qcom_board_id(IPQ9574) }, { qcom_board_id(SM8550) }, + { qcom_board_id(IPQ5016) }, { qcom_board_id(IPQ9510) }, { qcom_board_id(QRB4210) }, { qcom_board_id(QRB2210) }, @@ -461,6 +468,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(QRU1000) }, { qcom_board_id(QDU1000) }, { qcom_board_id(QDU1010) }, + { qcom_board_id(IPQ5019) }, { qcom_board_id(QRU1032) }, { qcom_board_id(QRU1052) }, { qcom_board_id(QRU1062) }, -- cgit v1.2.3 From 7f6e0028a0ca4317aeb070084e72d44ca39ace7e Mon Sep 17 00:00:00 2001 From: Kathiravan T Date: Tue, 9 May 2023 09:05:31 +0530 Subject: soc: qcom: socinfo: Add Soc ID for IPQ5312 and IPQ5302 Add the SoC ID for IPQ5312 and IPQ5302, which belong to the family of IPQ5332 SoC. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Kathiravan T Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230509033531.21468-3-quic_kathirav@quicinc.com --- drivers/soc/qcom/socinfo.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index c61a93b4dcaf..0decf0a08468 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -474,6 +474,8 @@ static const struct soc_id soc_id[] = { { qcom_board_id(QRU1062) }, { qcom_board_id(IPQ5332) }, { qcom_board_id(IPQ5322) }, + { qcom_board_id(IPQ5312) }, + { qcom_board_id(IPQ5302) }, }; static const char *socinfo_machine(struct device *dev, unsigned int id) -- cgit v1.2.3 From bcb889891371c3cf767f2b9e8768cfe2fdd3810f Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Fri, 26 May 2023 13:55:11 +0200 Subject: soc: qcom: mdt_loader: Fix unconditional call to scm_pas_mem_setup Commit ebeb20a9cd3f ("soc: qcom: mdt_loader: Always invoke PAS mem_setup") dropped the relocate check and made pas_mem_setup run unconditionally. The code was later moved with commit f4e526ff7e38 ("soc: qcom: mdt_loader: Extract PAS operations") to qcom_mdt_pas_init() effectively losing track of what was actually done. The assumption that PAS mem_setup can be done anytime was effectively wrong, with no good reason and this caused regression on some SoC that use remoteproc to bringup ath11k. One example is IPQ8074 SoC that effectively broke resulting in remoteproc silently die and ath11k not working. On this SoC FW relocate is not enabled and PAS mem_setup was correctly skipped in previous kernel version resulting in correct bringup and function of remoteproc and ath11k. To fix the regression, reintroduce the relocate check in qcom_mdt_pas_init() and correctly skip PAS mem_setup where relocate is not enabled. Fixes: ebeb20a9cd3f ("soc: qcom: mdt_loader: Always invoke PAS mem_setup") Tested-by: Robert Marko Co-developed-by: Robert Marko Signed-off-by: Robert Marko Signed-off-by: Christian Marangi Cc: stable@vger.kernel.org Reviewed-by: Mukesh Ojha Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230526115511.3328-1-ansuelsmth@gmail.com --- drivers/soc/qcom/mdt_loader.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c index 892b1648d693..9418993a3a92 100644 --- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -210,6 +210,7 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, const struct elf32_hdr *ehdr; phys_addr_t min_addr = PHYS_ADDR_MAX; phys_addr_t max_addr = 0; + bool relocate = false; size_t metadata_len; void *metadata; int ret; @@ -224,6 +225,9 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, if (!mdt_phdr_valid(phdr)) continue; + if (phdr->p_flags & QCOM_MDT_RELOCATABLE) + relocate = true; + if (phdr->p_paddr < min_addr) min_addr = phdr->p_paddr; @@ -246,11 +250,13 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, goto out; } - ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr); - if (ret) { - /* Unable to set up relocation */ - dev_err(dev, "error %d setting up firmware %s\n", ret, fw_name); - goto out; + if (relocate) { + ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr); + if (ret) { + /* Unable to set up relocation */ + dev_err(dev, "error %d setting up firmware %s\n", ret, fw_name); + goto out; + } } out: -- cgit v1.2.3 From ec001bb71e4476f7f5be9db693d5f43e65b9d8cb Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Fri, 26 May 2023 22:47:58 +0200 Subject: soc: qcom: socinfo: move SMEM item struct and defines to a header Move SMEM item struct and related defines to a header in order to be able to reuse them in the SMEM driver instead of duplicating them. Signed-off-by: Robert Marko Reviewed-by: Konrad Dybcio Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230526204802.3081168-1-robimarko@gmail.com --- drivers/soc/qcom/socinfo.c | 67 +--------------------------------------------- 1 file changed, 1 insertion(+), 66 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 0decf0a08468..dfd4330daef5 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -32,15 +33,6 @@ #define qcom_board_id(id) QCOM_ID_ ## id, __stringify(id) #define qcom_board_id_named(id, name) QCOM_ID_ ## id, (name) -#define SMEM_SOCINFO_BUILD_ID_LENGTH 32 -#define SMEM_SOCINFO_CHIP_ID_LENGTH 32 - -/* - * SMEM item id, used to acquire handles to respective - * SMEM region. - */ -#define SMEM_HW_SW_BUILD_ID 137 - #ifdef CONFIG_DEBUG_FS #define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32 #define SMEM_IMAGE_VERSION_SIZE 4096 @@ -126,64 +118,7 @@ static const char *const pmic_models[] = { [58] = "PM8450", [65] = "PM8010", }; -#endif /* CONFIG_DEBUG_FS */ - -/* Socinfo SMEM item structure */ -struct socinfo { - __le32 fmt; - __le32 id; - __le32 ver; - char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH]; - /* Version 2 */ - __le32 raw_id; - __le32 raw_ver; - /* Version 3 */ - __le32 hw_plat; - /* Version 4 */ - __le32 plat_ver; - /* Version 5 */ - __le32 accessory_chip; - /* Version 6 */ - __le32 hw_plat_subtype; - /* Version 7 */ - __le32 pmic_model; - __le32 pmic_die_rev; - /* Version 8 */ - __le32 pmic_model_1; - __le32 pmic_die_rev_1; - __le32 pmic_model_2; - __le32 pmic_die_rev_2; - /* Version 9 */ - __le32 foundry_id; - /* Version 10 */ - __le32 serial_num; - /* Version 11 */ - __le32 num_pmics; - __le32 pmic_array_offset; - /* Version 12 */ - __le32 chip_family; - __le32 raw_device_family; - __le32 raw_device_num; - /* Version 13 */ - __le32 nproduct_id; - char chip_id[SMEM_SOCINFO_CHIP_ID_LENGTH]; - /* Version 14 */ - __le32 num_clusters; - __le32 ncluster_array_offset; - __le32 num_defective_parts; - __le32 ndefective_parts_array_offset; - /* Version 15 */ - __le32 nmodem_supported; - /* Version 16 */ - __le32 feature_code; - __le32 pcode; - __le32 npartnamemap_offset; - __le32 nnum_partname_mapping; - /* Version 17 */ - __le32 oem_variant; -}; -#ifdef CONFIG_DEBUG_FS struct socinfo_params { u32 raw_device_family; u32 hw_plat_subtype; -- cgit v1.2.3 From 10615007483b6938da9df290fe5bf460f6a07c60 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Fri, 26 May 2023 22:47:59 +0200 Subject: soc: qcom: smem: Switch to EXPORT_SYMBOL_GPL() SMEM has been GPL licensed from the start, and there is no reason to use EXPORT_SYMBOL() so switch to the GPL version. Signed-off-by: Robert Marko Reviewed-by: Konrad Dybcio Reviewed-by: Trilok Soni Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230526204802.3081168-2-robimarko@gmail.com --- drivers/soc/qcom/smem.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 6be7ea93c78c..bc98520c4969 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -500,7 +500,7 @@ int qcom_smem_alloc(unsigned host, unsigned item, size_t size) return ret; } -EXPORT_SYMBOL(qcom_smem_alloc); +EXPORT_SYMBOL_GPL(qcom_smem_alloc); static void *qcom_smem_get_global(struct qcom_smem *smem, unsigned item, @@ -674,7 +674,7 @@ void *qcom_smem_get(unsigned host, unsigned item, size_t *size) return ptr; } -EXPORT_SYMBOL(qcom_smem_get); +EXPORT_SYMBOL_GPL(qcom_smem_get); /** * qcom_smem_get_free_space() - retrieve amount of free space in a partition @@ -719,7 +719,7 @@ int qcom_smem_get_free_space(unsigned host) return ret; } -EXPORT_SYMBOL(qcom_smem_get_free_space); +EXPORT_SYMBOL_GPL(qcom_smem_get_free_space); static bool addr_in_range(void __iomem *base, size_t size, void *addr) { @@ -770,7 +770,7 @@ phys_addr_t qcom_smem_virt_to_phys(void *p) return 0; } -EXPORT_SYMBOL(qcom_smem_virt_to_phys); +EXPORT_SYMBOL_GPL(qcom_smem_virt_to_phys); static int qcom_smem_get_sbl_version(struct qcom_smem *smem) { -- cgit v1.2.3 From 17051d2c3cd696439adb900e9af547ba162fb982 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Fri, 26 May 2023 22:48:00 +0200 Subject: soc: qcom: smem: introduce qcom_smem_get_soc_id() Introduce a helper to return the SoC SMEM ID, which is used to identify the exact SoC model as there may be differences in the same SoC family. Currently, cpufreq-nvmem does this completely in the driver and there has been more interest expresed for other drivers to use this information so lets expose a common helper to prevent redoing it in individual drivers since this field is present on every SMEM table version. Signed-off-by: Robert Marko Reviewed-by: Konrad Dybcio Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230526204802.3081168-3-robimarko@gmail.com --- drivers/soc/qcom/smem.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index bc98520c4969..b0d59e815c3b 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -14,6 +14,7 @@ #include #include #include +#include /* * The Qualcomm shared memory system is a allocate only heap structure that @@ -772,6 +773,28 @@ phys_addr_t qcom_smem_virt_to_phys(void *p) } EXPORT_SYMBOL_GPL(qcom_smem_virt_to_phys); +/** + * qcom_smem_get_soc_id() - return the SoC ID + * @id: On success, we return the SoC ID here. + * + * Look up SoC ID from HW/SW build ID and return it. + * + * Return: 0 on success, negative errno on failure. + */ +int qcom_smem_get_soc_id(u32 *id) +{ + struct socinfo *info; + + info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, NULL); + if (IS_ERR(info)) + return PTR_ERR(info); + + *id = __le32_to_cpu(info->id); + + return 0; +} +EXPORT_SYMBOL_GPL(qcom_smem_get_soc_id); + static int qcom_smem_get_sbl_version(struct qcom_smem *smem) { struct smem_header *header; -- cgit v1.2.3 From db9f132122afe5b2a7bb9ba132b9e562b9ca1aef Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Wed, 12 Apr 2023 15:12:12 +0200 Subject: soc: mediatek: pwrap: Move PMIC read test sequence in function The PMIC read test is performed in two places: pwrap_init_dual_io() and pwrap_init_sidly(). In preparation for adding support for PMICs requiring a companion part, move this sequence to a new function pwrap_pmic_read_test(). Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Alexandre Mergnat Link: https://lore.kernel.org/r/20230412131216.198313-3-angelogioacchino.delregno@collabora.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index 15789a03e6c6..5c500be48f7c 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -1455,6 +1455,18 @@ static int pwrap_regmap_write(void *context, u32 adr, u32 wdata) return pwrap_write(context, adr, wdata); } +static bool pwrap_pmic_read_test(struct pmic_wrapper *wrp, const u32 *dew_regs, + u16 read_test_val) +{ + bool is_success; + u32 rdata; + + pwrap_read(wrp, dew_regs[PWRAP_DEW_READ_TEST], &rdata); + is_success = ((rdata & U16_MAX) == read_test_val); + + return is_success; +} + static int pwrap_reset_spislave(struct pmic_wrapper *wrp) { bool tmp; @@ -1498,18 +1510,18 @@ static int pwrap_reset_spislave(struct pmic_wrapper *wrp) */ static int pwrap_init_sidly(struct pmic_wrapper *wrp) { - u32 rdata; u32 i; u32 pass = 0; + bool read_ok; signed char dly[16] = { -1, 0, 1, 0, 2, -1, 1, 1, 3, -1, -1, -1, 3, -1, 2, 1 }; for (i = 0; i < 4; i++) { pwrap_writel(wrp, i, PWRAP_SIDLY); - pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_READ_TEST], - &rdata); - if (rdata == PWRAP_DEW_READ_TEST_VAL) { + read_ok = pwrap_pmic_read_test(wrp, wrp->slave->dew_regs, + PWRAP_DEW_READ_TEST_VAL); + if (read_ok) { dev_dbg(wrp->dev, "[Read Test] pass, SIDLY=%x\n", i); pass |= 1 << i; } @@ -1529,8 +1541,7 @@ static int pwrap_init_sidly(struct pmic_wrapper *wrp) static int pwrap_init_dual_io(struct pmic_wrapper *wrp) { int ret; - bool tmp; - u32 rdata; + bool read_ok, tmp; /* Enable dual IO mode */ pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_DIO_EN], 1); @@ -1546,12 +1557,9 @@ static int pwrap_init_dual_io(struct pmic_wrapper *wrp) pwrap_writel(wrp, 1, PWRAP_DIO_EN); /* Read Test */ - pwrap_read(wrp, - wrp->slave->dew_regs[PWRAP_DEW_READ_TEST], &rdata); - if (rdata != PWRAP_DEW_READ_TEST_VAL) { - dev_err(wrp->dev, - "Read failed on DIO mode: 0x%04x!=0x%04x\n", - PWRAP_DEW_READ_TEST_VAL, rdata); + read_ok = pwrap_pmic_read_test(wrp, wrp->slave->dew_regs, PWRAP_DEW_READ_TEST_VAL); + if (!read_ok) { + dev_err(wrp->dev, "Read failed on DIO mode.\n"); return -EFAULT; } -- cgit v1.2.3 From 2eb27302346520908f89ee4db80fdba12c686278 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Wed, 12 Apr 2023 15:12:13 +0200 Subject: soc: mediatek: pwrap: Add kerneldoc for struct pwrap_slv_type In preparation for adding new members with name abbreviations describe the struct pwrap_slv_type with kerneldoc to enhance human readability. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Alexandre Mergnat Link: https://lore.kernel.org/r/20230412131216.198313-4-angelogioacchino.delregno@collabora.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index 5c500be48f7c..a33a1b1820cb 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -1218,11 +1218,17 @@ struct pwrap_slv_regops { int (*pwrap_write)(struct pmic_wrapper *wrp, u32 adr, u32 wdata); }; +/** + * struct pwrap_slv_type - PMIC device wrapper definitions + * @dew_regs: Device Wrapper (DeW) register offsets + * @type: PMIC Type (model) + * @regops: Register R/W ops + * @caps: Capability flags for the target device + */ struct pwrap_slv_type { const u32 *dew_regs; enum pmic_type type; const struct pwrap_slv_regops *regops; - /* Flags indicating the capability for the target slave */ u32 caps; }; -- cgit v1.2.3 From 41ae95aaa0d7576a5be1d9fd9225beafc179e019 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Wed, 12 Apr 2023 15:12:14 +0200 Subject: soc: mediatek: mtk-pmic-wrap: Add support for companion PMICs Some PMICs are designed to work with a companion part, which provides more regulators and/or companion devices such as LED controllers, display backlight controllers, battery charging, fuel gauge, etc: this kind of PMICs are usually present in smartphone platforms, where tight integration is required. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Alexandre Mergnat Link: https://lore.kernel.org/r/20230412131216.198313-5-angelogioacchino.delregno@collabora.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 73 +++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 14 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index a33a1b1820cb..366e40b802e4 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -47,6 +47,7 @@ /* macro for device wrapper default value */ #define PWRAP_DEW_READ_TEST_VAL 0x5aa5 +#define PWRAP_DEW_COMP_READ_TEST_VAL 0xa55a #define PWRAP_DEW_WRITE_TEST_VAL 0xa55a /* macro for manual command */ @@ -1222,12 +1223,16 @@ struct pwrap_slv_regops { * struct pwrap_slv_type - PMIC device wrapper definitions * @dew_regs: Device Wrapper (DeW) register offsets * @type: PMIC Type (model) + * @comp_dew_regs: Device Wrapper (DeW) register offsets for companion device + * @comp_type: Companion PMIC Type (model) * @regops: Register R/W ops * @caps: Capability flags for the target device */ struct pwrap_slv_type { const u32 *dew_regs; enum pmic_type type; + const u32 *comp_dew_regs; + enum pmic_type comp_type; const struct pwrap_slv_regops *regops; u32 caps; }; @@ -1548,9 +1553,12 @@ static int pwrap_init_dual_io(struct pmic_wrapper *wrp) { int ret; bool read_ok, tmp; + bool comp_read_ok = true; /* Enable dual IO mode */ pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_DIO_EN], 1); + if (wrp->slave->comp_dew_regs) + pwrap_write(wrp, wrp->slave->comp_dew_regs[PWRAP_DEW_DIO_EN], 1); /* Check IDLE & INIT_DONE in advance */ ret = readx_poll_timeout(pwrap_is_fsm_idle_and_sync_idle, wrp, tmp, tmp, @@ -1564,8 +1572,14 @@ static int pwrap_init_dual_io(struct pmic_wrapper *wrp) /* Read Test */ read_ok = pwrap_pmic_read_test(wrp, wrp->slave->dew_regs, PWRAP_DEW_READ_TEST_VAL); - if (!read_ok) { - dev_err(wrp->dev, "Read failed on DIO mode.\n"); + if (wrp->slave->comp_dew_regs) + comp_read_ok = pwrap_pmic_read_test(wrp, wrp->slave->comp_dew_regs, + PWRAP_DEW_COMP_READ_TEST_VAL); + if (!read_ok || !comp_read_ok) { + dev_err(wrp->dev, "Read failed on DIO mode. Main PMIC %s%s\n", + !read_ok ? "fail" : "success", + wrp->slave->comp_dew_regs && !comp_read_ok ? + ", Companion PMIC fail" : ""); return -EFAULT; } @@ -1640,19 +1654,41 @@ static bool pwrap_is_cipher_ready(struct pmic_wrapper *wrp) return pwrap_readl(wrp, PWRAP_CIPHER_RDY) & 1; } -static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp) +static bool __pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp, const u32 *dew_regs) { u32 rdata; int ret; - ret = pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_RDY], - &rdata); + ret = pwrap_read(wrp, dew_regs[PWRAP_DEW_CIPHER_RDY], &rdata); if (ret) return false; return rdata == 1; } + +static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp) +{ + bool ret = __pwrap_is_pmic_cipher_ready(wrp, wrp->slave->dew_regs); + + if (!ret) + return ret; + + /* If there's any companion, wait for it to be ready too */ + if (wrp->slave->comp_dew_regs) + ret = __pwrap_is_pmic_cipher_ready(wrp, wrp->slave->comp_dew_regs); + + return ret; +} + +static void pwrap_config_cipher(struct pmic_wrapper *wrp, const u32 *dew_regs) +{ + pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x1); + pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0); + pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1); + pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2); +} + static int pwrap_init_cipher(struct pmic_wrapper *wrp) { int ret; @@ -1689,10 +1725,11 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) } /* Config cipher mode @PMIC */ - pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x1); - pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0); - pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1); - pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2); + pwrap_config_cipher(wrp, wrp->slave->dew_regs); + + /* If there is any companion PMIC, configure cipher mode there too */ + if (wrp->slave->comp_type > 0) + pwrap_config_cipher(wrp, wrp->slave->comp_dew_regs); switch (wrp->slave->type) { case PMIC_MT6397: @@ -1754,6 +1791,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) static int pwrap_init_security(struct pmic_wrapper *wrp) { + u32 crc_val; int ret; /* Enable encryption */ @@ -1762,14 +1800,21 @@ static int pwrap_init_security(struct pmic_wrapper *wrp) return ret; /* Signature checking - using CRC */ - if (pwrap_write(wrp, - wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1)) - return -EFAULT; + ret = pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1); + if (ret == 0 && wrp->slave->comp_dew_regs) + ret = pwrap_write(wrp, wrp->slave->comp_dew_regs[PWRAP_DEW_CRC_EN], 0x1); pwrap_writel(wrp, 0x1, PWRAP_CRC_EN); pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE); - pwrap_writel(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_VAL], - PWRAP_SIG_ADR); + + /* CRC value */ + crc_val = wrp->slave->dew_regs[PWRAP_DEW_CRC_VAL]; + if (wrp->slave->comp_dew_regs) + crc_val |= wrp->slave->comp_dew_regs[PWRAP_DEW_CRC_VAL] << 16; + + pwrap_writel(wrp, crc_val, PWRAP_SIG_ADR); + + /* PMIC Wrapper Arbiter priority */ pwrap_writel(wrp, wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN); -- cgit v1.2.3 From 10f5c409a81a327743f15441f7fed3975e7a5a0f Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Wed, 12 Apr 2023 15:12:15 +0200 Subject: soc: mediatek: mtk-pmic-wrap: Add support for MT6331 w/ MT6332 companion Add support for the MT6331 PMIC and for its companion MT6332 PMIC. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Alexandre Mergnat Link: https://lore.kernel.org/r/20230412131216.198313-6-angelogioacchino.delregno@collabora.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 47 ++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'drivers/soc') diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index 366e40b802e4..ceeac43f7bd1 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -170,6 +170,40 @@ static const u32 mt6323_regs[] = { [PWRAP_DEW_RDDMY_NO] = 0x01a4, }; +static const u32 mt6331_regs[] = { + [PWRAP_DEW_DIO_EN] = 0x018c, + [PWRAP_DEW_READ_TEST] = 0x018e, + [PWRAP_DEW_WRITE_TEST] = 0x0190, + [PWRAP_DEW_CRC_SWRST] = 0x0192, + [PWRAP_DEW_CRC_EN] = 0x0194, + [PWRAP_DEW_CRC_VAL] = 0x0196, + [PWRAP_DEW_MON_GRP_SEL] = 0x0198, + [PWRAP_DEW_CIPHER_KEY_SEL] = 0x019a, + [PWRAP_DEW_CIPHER_IV_SEL] = 0x019c, + [PWRAP_DEW_CIPHER_EN] = 0x019e, + [PWRAP_DEW_CIPHER_RDY] = 0x01a0, + [PWRAP_DEW_CIPHER_MODE] = 0x01a2, + [PWRAP_DEW_CIPHER_SWRST] = 0x01a4, + [PWRAP_DEW_RDDMY_NO] = 0x01a6, +}; + +static const u32 mt6332_regs[] = { + [PWRAP_DEW_DIO_EN] = 0x80f6, + [PWRAP_DEW_READ_TEST] = 0x80f8, + [PWRAP_DEW_WRITE_TEST] = 0x80fa, + [PWRAP_DEW_CRC_SWRST] = 0x80fc, + [PWRAP_DEW_CRC_EN] = 0x80fe, + [PWRAP_DEW_CRC_VAL] = 0x8100, + [PWRAP_DEW_MON_GRP_SEL] = 0x8102, + [PWRAP_DEW_CIPHER_KEY_SEL] = 0x8104, + [PWRAP_DEW_CIPHER_IV_SEL] = 0x8106, + [PWRAP_DEW_CIPHER_EN] = 0x8108, + [PWRAP_DEW_CIPHER_RDY] = 0x810a, + [PWRAP_DEW_CIPHER_MODE] = 0x810c, + [PWRAP_DEW_CIPHER_SWRST] = 0x810e, + [PWRAP_DEW_RDDMY_NO] = 0x8110, +}; + static const u32 mt6351_regs[] = { [PWRAP_DEW_DIO_EN] = 0x02F2, [PWRAP_DEW_READ_TEST] = 0x02F4, @@ -1182,6 +1216,8 @@ static int mt8186_regs[] = { enum pmic_type { PMIC_MT6323, + PMIC_MT6331, + PMIC_MT6332, PMIC_MT6351, PMIC_MT6357, PMIC_MT6358, @@ -2041,6 +2077,16 @@ static const struct pwrap_slv_type pmic_mt6323 = { PWRAP_SLV_CAP_SECURITY, }; +static const struct pwrap_slv_type pmic_mt6331 = { + .dew_regs = mt6331_regs, + .type = PMIC_MT6331, + .comp_dew_regs = mt6332_regs, + .comp_type = PMIC_MT6332, + .regops = &pwrap_regops16, + .caps = PWRAP_SLV_CAP_SPI | PWRAP_SLV_CAP_DUALIO | + PWRAP_SLV_CAP_SECURITY, +}; + static const struct pwrap_slv_type pmic_mt6351 = { .dew_regs = mt6351_regs, .type = PMIC_MT6351, @@ -2086,6 +2132,7 @@ static const struct pwrap_slv_type pmic_mt6397 = { static const struct of_device_id of_slave_match_tbl[] = { { .compatible = "mediatek,mt6323", .data = &pmic_mt6323 }, + { .compatible = "mediatek,mt6331", .data = &pmic_mt6331 }, { .compatible = "mediatek,mt6351", .data = &pmic_mt6351 }, { .compatible = "mediatek,mt6357", .data = &pmic_mt6357 }, { .compatible = "mediatek,mt6358", .data = &pmic_mt6358 }, -- cgit v1.2.3 From b7f61f9c7ec402633c10f6456415cab04d3838d5 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Wed, 12 Apr 2023 15:12:16 +0200 Subject: soc: mediatek: pwrap: Add support for MT6795 Helio X10 Add the necessary bits to support the MT6795 Helio X10 smartphone SoC: this is always paired with a MT6331 PMIC, with MT6332 companion. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Alexandre Mergnat Link: https://lore.kernel.org/r/20230412131216.198313-7-angelogioacchino.delregno@collabora.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 136 ++++++++++++++++++++++++++++++++++- 1 file changed, 135 insertions(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index ceeac43f7bd1..11095b8de71a 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -639,6 +639,91 @@ static int mt6779_regs[] = { [PWRAP_WACS2_VLDCLR] = 0xC28, }; +static int mt6795_regs[] = { + [PWRAP_MUX_SEL] = 0x0, + [PWRAP_WRAP_EN] = 0x4, + [PWRAP_DIO_EN] = 0x8, + [PWRAP_SIDLY] = 0xc, + [PWRAP_RDDMY] = 0x10, + [PWRAP_SI_CK_CON] = 0x14, + [PWRAP_CSHEXT_WRITE] = 0x18, + [PWRAP_CSHEXT_READ] = 0x1c, + [PWRAP_CSLEXT_START] = 0x20, + [PWRAP_CSLEXT_END] = 0x24, + [PWRAP_STAUPD_PRD] = 0x28, + [PWRAP_STAUPD_GRPEN] = 0x2c, + [PWRAP_EINT_STA0_ADR] = 0x30, + [PWRAP_EINT_STA1_ADR] = 0x34, + [PWRAP_STAUPD_MAN_TRIG] = 0x40, + [PWRAP_STAUPD_STA] = 0x44, + [PWRAP_WRAP_STA] = 0x48, + [PWRAP_HARB_INIT] = 0x4c, + [PWRAP_HARB_HPRIO] = 0x50, + [PWRAP_HIPRIO_ARB_EN] = 0x54, + [PWRAP_HARB_STA0] = 0x58, + [PWRAP_HARB_STA1] = 0x5c, + [PWRAP_MAN_EN] = 0x60, + [PWRAP_MAN_CMD] = 0x64, + [PWRAP_MAN_RDATA] = 0x68, + [PWRAP_MAN_VLDCLR] = 0x6c, + [PWRAP_WACS0_EN] = 0x70, + [PWRAP_INIT_DONE0] = 0x74, + [PWRAP_WACS0_CMD] = 0x78, + [PWRAP_WACS0_RDATA] = 0x7c, + [PWRAP_WACS0_VLDCLR] = 0x80, + [PWRAP_WACS1_EN] = 0x84, + [PWRAP_INIT_DONE1] = 0x88, + [PWRAP_WACS1_CMD] = 0x8c, + [PWRAP_WACS1_RDATA] = 0x90, + [PWRAP_WACS1_VLDCLR] = 0x94, + [PWRAP_WACS2_EN] = 0x98, + [PWRAP_INIT_DONE2] = 0x9c, + [PWRAP_WACS2_CMD] = 0xa0, + [PWRAP_WACS2_RDATA] = 0xa4, + [PWRAP_WACS2_VLDCLR] = 0xa8, + [PWRAP_INT_EN] = 0xac, + [PWRAP_INT_FLG_RAW] = 0xb0, + [PWRAP_INT_FLG] = 0xb4, + [PWRAP_INT_CLR] = 0xb8, + [PWRAP_SIG_ADR] = 0xbc, + [PWRAP_SIG_MODE] = 0xc0, + [PWRAP_SIG_VALUE] = 0xc4, + [PWRAP_SIG_ERRVAL] = 0xc8, + [PWRAP_CRC_EN] = 0xcc, + [PWRAP_TIMER_EN] = 0xd0, + [PWRAP_TIMER_STA] = 0xd4, + [PWRAP_WDT_UNIT] = 0xd8, + [PWRAP_WDT_SRC_EN] = 0xdc, + [PWRAP_WDT_FLG] = 0xe0, + [PWRAP_DEBUG_INT_SEL] = 0xe4, + [PWRAP_DVFS_ADR0] = 0xe8, + [PWRAP_DVFS_WDATA0] = 0xec, + [PWRAP_DVFS_ADR1] = 0xf0, + [PWRAP_DVFS_WDATA1] = 0xf4, + [PWRAP_DVFS_ADR2] = 0xf8, + [PWRAP_DVFS_WDATA2] = 0xfc, + [PWRAP_DVFS_ADR3] = 0x100, + [PWRAP_DVFS_WDATA3] = 0x104, + [PWRAP_DVFS_ADR4] = 0x108, + [PWRAP_DVFS_WDATA4] = 0x10c, + [PWRAP_DVFS_ADR5] = 0x110, + [PWRAP_DVFS_WDATA5] = 0x114, + [PWRAP_DVFS_ADR6] = 0x118, + [PWRAP_DVFS_WDATA6] = 0x11c, + [PWRAP_DVFS_ADR7] = 0x120, + [PWRAP_DVFS_WDATA7] = 0x124, + [PWRAP_SPMINF_STA] = 0x128, + [PWRAP_CIPHER_KEY_SEL] = 0x12c, + [PWRAP_CIPHER_IV_SEL] = 0x130, + [PWRAP_CIPHER_EN] = 0x134, + [PWRAP_CIPHER_RDY] = 0x138, + [PWRAP_CIPHER_MODE] = 0x13c, + [PWRAP_CIPHER_SWRST] = 0x140, + [PWRAP_DCM_EN] = 0x144, + [PWRAP_DCM_DBC_PRD] = 0x148, + [PWRAP_EXT_CK] = 0x14c, +}; + static int mt6797_regs[] = { [PWRAP_MUX_SEL] = 0x0, [PWRAP_WRAP_EN] = 0x4, @@ -1230,6 +1315,7 @@ enum pwrap_type { PWRAP_MT2701, PWRAP_MT6765, PWRAP_MT6779, + PWRAP_MT6795, PWRAP_MT6797, PWRAP_MT6873, PWRAP_MT7622, @@ -1650,6 +1736,20 @@ static void pwrap_init_chip_select_ext(struct pmic_wrapper *wrp, u8 hext_write, static int pwrap_common_init_reg_clock(struct pmic_wrapper *wrp) { switch (wrp->master->type) { + case PWRAP_MT6795: + if (wrp->slave->type == PMIC_MT6331) { + const u32 *dew_regs = wrp->slave->dew_regs; + + pwrap_write(wrp, dew_regs[PWRAP_DEW_RDDMY_NO], 0x8); + + if (wrp->slave->comp_type == PMIC_MT6332) { + dew_regs = wrp->slave->comp_dew_regs; + pwrap_write(wrp, dew_regs[PWRAP_DEW_RDDMY_NO], 0x8); + } + } + pwrap_writel(wrp, 0x88, PWRAP_RDDMY); + pwrap_init_chip_select_ext(wrp, 15, 15, 15, 15); + break; case PWRAP_MT8173: pwrap_init_chip_select_ext(wrp, 0, 4, 2, 2); break; @@ -1744,6 +1844,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) case PWRAP_MT2701: case PWRAP_MT6765: case PWRAP_MT6779: + case PWRAP_MT6795: case PWRAP_MT6797: case PWRAP_MT8173: case PWRAP_MT8186: @@ -1914,6 +2015,19 @@ static int pwrap_mt2701_init_soc_specific(struct pmic_wrapper *wrp) return 0; } +static int pwrap_mt6795_init_soc_specific(struct pmic_wrapper *wrp) +{ + pwrap_writel(wrp, 0xf, PWRAP_STAUPD_GRPEN); + + if (wrp->slave->type == PMIC_MT6331) + pwrap_writel(wrp, 0x1b4, PWRAP_EINT_STA0_ADR); + + if (wrp->slave->comp_type == PMIC_MT6332) + pwrap_writel(wrp, 0x8112, PWRAP_EINT_STA1_ADR); + + return 0; +} + static int pwrap_mt7622_init_soc_specific(struct pmic_wrapper *wrp) { pwrap_writel(wrp, 0, PWRAP_STAUPD_PRD); @@ -1949,10 +2063,16 @@ static int pwrap_init(struct pmic_wrapper *wrp) if (wrp->rstc_bridge) reset_control_reset(wrp->rstc_bridge); - if (wrp->master->type == PWRAP_MT8173) { + switch (wrp->master->type) { + case PWRAP_MT6795: + fallthrough; + case PWRAP_MT8173: /* Enable DCM */ pwrap_writel(wrp, 3, PWRAP_DCM_EN); pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD); + break; + default: + break; } if (HAS_CAP(wrp->slave->caps, PWRAP_SLV_CAP_SPI)) { @@ -2185,6 +2305,19 @@ static const struct pmic_wrapper_type pwrap_mt6779 = { .init_soc_specific = NULL, }; +static const struct pmic_wrapper_type pwrap_mt6795 = { + .regs = mt6795_regs, + .type = PWRAP_MT6795, + .arb_en_all = 0x3f, + .int_en_all = ~(u32)(BIT(31) | BIT(2) | BIT(1)), + .int1_en_all = 0, + .spi_w = PWRAP_MAN_CMD_SPI_WRITE, + .wdt_src = PWRAP_WDT_SRC_MASK_NO_STAUPD, + .caps = PWRAP_CAP_RESET | PWRAP_CAP_DCM, + .init_reg_clock = pwrap_common_init_reg_clock, + .init_soc_specific = pwrap_mt6795_init_soc_specific, +}; + static const struct pmic_wrapper_type pwrap_mt6797 = { .regs = mt6797_regs, .type = PWRAP_MT6797, @@ -2318,6 +2451,7 @@ static const struct of_device_id of_pwrap_match_tbl[] = { { .compatible = "mediatek,mt2701-pwrap", .data = &pwrap_mt2701 }, { .compatible = "mediatek,mt6765-pwrap", .data = &pwrap_mt6765 }, { .compatible = "mediatek,mt6779-pwrap", .data = &pwrap_mt6779 }, + { .compatible = "mediatek,mt6795-pwrap", .data = &pwrap_mt6795 }, { .compatible = "mediatek,mt6797-pwrap", .data = &pwrap_mt6797 }, { .compatible = "mediatek,mt6873-pwrap", .data = &pwrap_mt6873 }, { .compatible = "mediatek,mt7622-pwrap", .data = &pwrap_mt7622 }, -- cgit v1.2.3 From 57bf5b2d1002cfd6e8d363fc2caebe415bf33ba4 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Fri, 5 May 2023 14:19:50 +0800 Subject: soc: mediatek: mtk-mutex: Remove unnecessary .owner Remove .owner field if calls are used which set it automatically. ./drivers/soc/mediatek/mtk-mutex.c:1054:3-8: No need to set .owner here. The core will do it. Reported-by: Abaci Robot Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=4869 Signed-off-by: Jiapeng Chong Link: https://lore.kernel.org/r/20230505061950.25977-1-jiapeng.chong@linux.alibaba.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-mutex.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c index 26f3d9a41496..4aa0913817ae 100644 --- a/drivers/soc/mediatek/mtk-mutex.c +++ b/drivers/soc/mediatek/mtk-mutex.c @@ -1051,7 +1051,6 @@ static struct platform_driver mtk_mutex_driver = { .probe = mtk_mutex_probe, .driver = { .name = "mediatek-mutex", - .owner = THIS_MODULE, .of_match_table = mutex_driver_dt_match, }, }; -- cgit v1.2.3 From e81a16e77259294cd4ff0a9c1fbe5aa0e311a47d Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Mon, 29 May 2023 10:41:15 +0200 Subject: soc: qcom: ocmem: Add OCMEM hardware version print It might be useful to know what hardware version of the OCMEM block the SoC contains. Add a debug print for that. Signed-off-by: Luca Weiss Reviewed-by: Konrad Dybcio Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230509-ocmem-hwver-v3-1-e51f3488e0f4@z3ntu.xyz --- drivers/soc/qcom/ocmem.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c index 199fe9872035..aaddc3cc53b7 100644 --- a/drivers/soc/qcom/ocmem.c +++ b/drivers/soc/qcom/ocmem.c @@ -76,6 +76,10 @@ struct ocmem { #define OCMEM_REG_GFX_MPU_START 0x00001004 #define OCMEM_REG_GFX_MPU_END 0x00001008 +#define OCMEM_HW_VERSION_MAJOR(val) FIELD_GET(GENMASK(31, 28), val) +#define OCMEM_HW_VERSION_MINOR(val) FIELD_GET(GENMASK(27, 16), val) +#define OCMEM_HW_VERSION_STEP(val) FIELD_GET(GENMASK(15, 0), val) + #define OCMEM_HW_PROFILE_NUM_PORTS(val) FIELD_PREP(0x0000000f, (val)) #define OCMEM_HW_PROFILE_NUM_MACROS(val) FIELD_PREP(0x00003f00, (val)) @@ -355,6 +359,12 @@ static int ocmem_dev_probe(struct platform_device *pdev) } } + reg = ocmem_read(ocmem, OCMEM_REG_HW_VERSION); + dev_dbg(dev, "OCMEM hardware version: %lu.%lu.%lu\n", + OCMEM_HW_VERSION_MAJOR(reg), + OCMEM_HW_VERSION_MINOR(reg), + OCMEM_HW_VERSION_STEP(reg)); + reg = ocmem_read(ocmem, OCMEM_REG_HW_PROFILE); ocmem->num_ports = OCMEM_HW_PROFILE_NUM_PORTS(reg); ocmem->num_macros = OCMEM_HW_PROFILE_NUM_MACROS(reg); -- cgit v1.2.3 From c27ea8e6325cad44c8c5bc2e8e7cc7635f358f31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 10 Mar 2023 23:41:27 +0100 Subject: soc: fsl: dpio: Suppress duplicated error reporting on device remove MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Returning an error code from a fsl_mc_driver's remove callback results in a generic error message, otherwise the value is ignored and the device gets unbound. As the only error path in dpaa2_dpio_remove() already emits an error message, return zero unconditionally to suppress another (less helpful) error report. Signed-off-by: Uwe Kleine-König Reviewed-by: Ioana Ciornei Tested-by: Ioana Ciornei # sanity checks Reviewed-by: Laurentiu Tudor Tested-by: Laurentiu Tudor Signed-off-by: Li Yang --- drivers/soc/fsl/dpio/dpio-driver.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/fsl/dpio/dpio-driver.c b/drivers/soc/fsl/dpio/dpio-driver.c index 74eace3109a1..09df5302d255 100644 --- a/drivers/soc/fsl/dpio/dpio-driver.c +++ b/drivers/soc/fsl/dpio/dpio-driver.c @@ -297,14 +297,10 @@ static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); - fsl_mc_portal_free(dpio_dev->mc_io); - - return 0; - err_open: fsl_mc_portal_free(dpio_dev->mc_io); - return err; + return 0; } static const struct fsl_mc_device_id dpaa2_dpio_match_id_table[] = { -- cgit v1.2.3 From 59272ad8d9e8ea6398a96f8c6d62da284bf2ae6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 10 Mar 2023 23:41:28 +0100 Subject: bus: fsl-mc: Make remove function return void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The value returned by an fsl-mc driver's remove function is mostly ignored. (Only an error message is printed if the value is non-zero and then device removal continues unconditionally.) So change the prototype of the remove function to return no value. This way driver authors are not tempted to assume that passing an error to the upper layer is a good idea. All drivers are adapted accordingly. There is no intended change of behaviour, all callbacks were prepared to return 0 before. Signed-off-by: Uwe Kleine-König Reviewed-by: Ioana Ciornei Tested-by: Ioana Ciornei # sanity checks Reviewed-by: Laurentiu Tudor Tested-by: Laurentiu Tudor Signed-off-by: Li Yang --- drivers/soc/fsl/dpio/dpio-driver.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/fsl/dpio/dpio-driver.c b/drivers/soc/fsl/dpio/dpio-driver.c index 09df5302d255..9e3fddd8f5a9 100644 --- a/drivers/soc/fsl/dpio/dpio-driver.c +++ b/drivers/soc/fsl/dpio/dpio-driver.c @@ -270,7 +270,7 @@ static void dpio_teardown_irqs(struct fsl_mc_device *dpio_dev) fsl_mc_free_irqs(dpio_dev); } -static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) +static void dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) { struct device *dev; struct dpio_priv *priv; @@ -299,8 +299,6 @@ static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) err_open: fsl_mc_portal_free(dpio_dev->mc_io); - - return 0; } static const struct fsl_mc_device_id dpaa2_dpio_match_id_table[] = { -- cgit v1.2.3 From 7b1a78babd0d2cd27aa07255dee0c2d7ac0f31e3 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 21 May 2023 15:52:16 -0700 Subject: soc/fsl/qe: fix usb.c build errors Fix build errors in soc/fsl/qe/usb.c when QUICC_ENGINE is not set. This happens when PPC_EP88XC is set, which selects CPM1 & CPM. When CPM is set, USB_FSL_QE can be set without QUICC_ENGINE being set. When USB_FSL_QE is set, QE_USB deafults to y, which causes build errors when QUICC_ENGINE is not set. Making QE_USB depend on QUICC_ENGINE prevents QE_USB from defaulting to y. Fixes these build errors: drivers/soc/fsl/qe/usb.o: in function `qe_usb_clock_set': usb.c:(.text+0x1e): undefined reference to `qe_immr' powerpc-linux-ld: usb.c:(.text+0x2a): undefined reference to `qe_immr' powerpc-linux-ld: usb.c:(.text+0xbc): undefined reference to `qe_setbrg' powerpc-linux-ld: usb.c:(.text+0xca): undefined reference to `cmxgcr_lock' powerpc-linux-ld: usb.c:(.text+0xce): undefined reference to `cmxgcr_lock' Fixes: 5e41486c408e ("powerpc/QE: add support for QE USB clocks routing") Signed-off-by: Randy Dunlap Reported-by: kernel test robot Link: https://lore.kernel.org/all/202301101500.pillNv6R-lkp@intel.com/ Suggested-by: Michael Ellerman Cc: Christophe Leroy Cc: Leo Li Cc: Masahiro Yamada Cc: Nicolas Schier Cc: Qiang Zhao Cc: linuxppc-dev Cc: linux-arm-kernel@lists.infradead.org Cc: Kumar Gala Acked-by: Nicolas Schier Signed-off-by: Li Yang --- drivers/soc/fsl/qe/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/soc') diff --git a/drivers/soc/fsl/qe/Kconfig b/drivers/soc/fsl/qe/Kconfig index 7268c2fbcbc1..160c8877b0c9 100644 --- a/drivers/soc/fsl/qe/Kconfig +++ b/drivers/soc/fsl/qe/Kconfig @@ -62,6 +62,7 @@ config QE_TDM config QE_USB bool + depends on QUICC_ENGINE default y if USB_FSL_QE help QE USB Controller support -- cgit v1.2.3 From a00d47f7645d6e840a38a62fd961c8aa2c8fed6c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 2 Jun 2023 10:50:41 +0200 Subject: soc: renesas: rmobile-sysc: Convert to readl_poll_timeout_atomic() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use readl_poll_timeout_atomic() instead of open-coding the same operation. 1. rmobile_pd_power_down(): as typically less than 20 retries are needed, PSTR_RETRIES (100) µs is a suitable timeout value. 2. __rmobile_pd_power_up(): the old method of first polling some cycles with a 1 µs delay, followed by more polling cycles without any delay didn't make much sense, as the latter was insignificant compared to the former. Furthermore, typically no retries are needed. Hence just retain the polling with delay. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/ae4bf03ab8fd5a557c683086958d6764babc0723.1685692810.git.geert+renesas@glider.be --- drivers/soc/renesas/rmobile-sysc.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/renesas/rmobile-sysc.c b/drivers/soc/renesas/rmobile-sysc.c index 728ebac98e14..912daadaa10d 100644 --- a/drivers/soc/renesas/rmobile-sysc.c +++ b/drivers/soc/renesas/rmobile-sysc.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -19,8 +21,6 @@ #include #include -#include - /* SYSC */ #define SPDCR 0x08 /* SYS Power Down Control Register */ #define SWUCR 0x14 /* SYS Wakeup Control Register */ @@ -47,6 +47,7 @@ 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(); @@ -56,14 +57,10 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd) } if (readl(rmobile_pd->base + PSTR) & mask) { - unsigned int retry_count; writel(mask, rmobile_pd->base + SPDCR); - for (retry_count = PSTR_RETRIES; retry_count; retry_count--) { - if (!(readl(rmobile_pd->base + SPDCR) & mask)) - break; - cpu_relax(); - } + 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, @@ -74,8 +71,7 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd) static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd) { - unsigned int mask = BIT(rmobile_pd->bit_shift); - unsigned int retry_count; + unsigned int val, mask = BIT(rmobile_pd->bit_shift); int ret = 0; if (readl(rmobile_pd->base + PSTR) & mask) @@ -83,16 +79,9 @@ static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd) writel(mask, rmobile_pd->base + SWUCR); - for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) { - if (!(readl(rmobile_pd->base + SWUCR) & mask)) - break; - if (retry_count > PSTR_RETRIES) - udelay(PSTR_DELAY_US); - else - cpu_relax(); - } - if (!retry_count) - ret = -EIO; + 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, -- cgit v1.2.3 From b11403c93b7cddc8916b132a395b1524c02447a3 Mon Sep 17 00:00:00 2001 From: Osama Muhammad Date: Wed, 17 May 2023 22:24:31 +0500 Subject: wkup_m3_ipc.c: Fix error checking for debugfs_create_dir This patch fixes the error checking in wkup_m3_ipc.c in debugfs_create_dir. The correct way to check if an error occurred is 'IS_ERR' inline function. Signed-off-by: Osama Muhammad Link: https://lore.kernel.org/r/20230517172431.13507-1-osmtendev@gmail.com Signed-off-by: Nishanth Menon --- drivers/soc/ti/wkup_m3_ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/ti/wkup_m3_ipc.c b/drivers/soc/ti/wkup_m3_ipc.c index c9197912ec24..3aff106fc11a 100644 --- a/drivers/soc/ti/wkup_m3_ipc.c +++ b/drivers/soc/ti/wkup_m3_ipc.c @@ -202,7 +202,7 @@ static int wkup_m3_ipc_dbg_init(struct wkup_m3_ipc *m3_ipc) { m3_ipc->dbg_path = debugfs_create_dir("wkup_m3_ipc", NULL); - if (!m3_ipc->dbg_path) + if (IS_ERR(m3_ipc->dbg_path)) return -EINVAL; (void)debugfs_create_file("enable_late_halt", 0644, -- cgit v1.2.3 From c3a1c97c72601f8c00678f0ebafb574ec6e26d54 Mon Sep 17 00:00:00 2001 From: Viswanath L Date: Tue, 6 Jun 2023 16:36:07 +0100 Subject: soc/tegra: pmc: Add AON SW Wake support for Tegra234 Wake-up signal 83 on Tegra234 is triggered by software writing to WAKE_AOWAKE_SW_WAKE_TIER0_TRIGGER_0 register. This wake-up is mapped to CPU interrupt 179 and is used by the Sensor Processing Engine (SPE) in the Always-on (AON) power domain for waking up the system. Signed-off-by: Viswanath L Signed-off-by: Kartik Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/soc') diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 5d17799524c9..b562b005744d 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -4250,6 +4250,7 @@ static const struct tegra_wake_event tegra234_wake_events[] = { TEGRA_WAKE_GPIO("power", 29, 1, TEGRA234_AON_GPIO(EE, 4)), TEGRA_WAKE_GPIO("mgbe", 56, 0, TEGRA234_MAIN_GPIO(Y, 3)), TEGRA_WAKE_IRQ("rtc", 73, 10), + TEGRA_WAKE_IRQ("sw-wake", SW_WAKE_ID, 179), }; static const struct tegra_pmc_soc tegra234_pmc_soc = { -- cgit v1.2.3 From e180cf836433185d0674ade52f8db911d89f6422 Mon Sep 17 00:00:00 2001 From: Kartik Date: Tue, 6 Jun 2023 16:36:08 +0100 Subject: soc/tegra: fuse: Fix Tegra234 fuse size The Tegra234 fuse size is incorrectly defined as 0x98c. The actual size of the Tegra234 fuses is 0xf8c and so update the size of the Tegra234 fuses to fix this. Signed-off-by: Kartik Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/fuse/fuse-tegra30.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c index 932a03c64534..c759fb7c8adc 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra30.c +++ b/drivers/soc/tegra/fuse/fuse-tegra30.c @@ -663,7 +663,7 @@ static const struct nvmem_keepout tegra234_fuse_keepouts[] = { static const struct tegra_fuse_info tegra234_fuse_info = { .read = tegra30_fuse_read, - .size = 0x98c, + .size = 0xf90, .spare = 0x280, }; -- cgit v1.2.3 From 95094495401bdf6a0649d220dfd095e6079b5e39 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 31 May 2023 14:35:30 +0800 Subject: soc: mediatek: SVS: Fix MT8192 GPU node name Device tree node names should be generic. The planned device node name for the GPU, according to the bindings and posted DT changes, is "gpu", not "mali". Fix the GPU node name in the SVS driver to follow. Fixes: 0bbb09b2af9d ("soc: mediatek: SVS: add mt8192 SVS GPU driver") Signed-off-by: Chen-Yu Tsai Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Alexandre Mergnat Link: https://lore.kernel.org/r/20230531063532.2240038-1-wenst@chromium.org Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-svs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c index 81585733c8a9..3a2f97cd5272 100644 --- a/drivers/soc/mediatek/mtk-svs.c +++ b/drivers/soc/mediatek/mtk-svs.c @@ -2061,9 +2061,9 @@ static int svs_mt8192_platform_probe(struct svs_platform *svsp) svsb = &svsp->banks[idx]; if (svsb->type == SVSB_HIGH) - svsb->opp_dev = svs_add_device_link(svsp, "mali"); + svsb->opp_dev = svs_add_device_link(svsp, "gpu"); else if (svsb->type == SVSB_LOW) - svsb->opp_dev = svs_get_subsys_device(svsp, "mali"); + svsb->opp_dev = svs_get_subsys_device(svsp, "gpu"); if (IS_ERR(svsb->opp_dev)) return dev_err_probe(svsp->dev, PTR_ERR(svsb->opp_dev), -- cgit v1.2.3 From bae9fb2d39b73822379b9bda02f3b9335fc77e13 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 9 Jun 2023 16:42:24 +0200 Subject: soc/tegra: pmc: Simplify debugfs initialization debugfs calls should generally not be error-checked to simplify the case where debugfs is disabled. Since this driver is built-in and has the sysfs bind/unbind attributes disabled, it cannot be unloaded, so there is no need to hold onto a reference to the debugfs files that are created. We can further simplify this by moving the debugfs file creation to a later stage to avoid any cleanup we might have to do during error unwind operations. This is also a little cleaner because the debugfs file relies on data structures that are created at a later point than when the file was previously created. Suggested-by: Jon Hunter Reviewed-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index b562b005744d..438c30c5d473 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -396,7 +396,6 @@ struct tegra_pmc_soc { * @clk: pointer to pclk clock * @soc: pointer to SoC data structure * @tz_only: flag specifying if the PMC can only be accessed via TrustZone - * @debugfs: pointer to debugfs entry * @rate: currently configured rate of pclk * @suspend_mode: lowest suspend mode available * @cpu_good_time: CPU power good time (in microseconds) @@ -431,7 +430,6 @@ struct tegra_pmc { void __iomem *aotag; void __iomem *scratch; struct clk *clk; - struct dentry *debugfs; const struct tegra_pmc_soc *soc; bool tz_only; @@ -1190,16 +1188,6 @@ static int powergate_show(struct seq_file *s, void *data) DEFINE_SHOW_ATTRIBUTE(powergate); -static int tegra_powergate_debugfs_init(void) -{ - pmc->debugfs = debugfs_create_file("powergate", S_IRUGO, NULL, NULL, - &powergate_fops); - if (!pmc->debugfs) - return -ENOMEM; - - return 0; -} - static int tegra_powergate_of_get_clks(struct tegra_powergate *pg, struct device_node *np) { @@ -3026,19 +3014,13 @@ static int tegra_pmc_probe(struct platform_device *pdev) tegra_pmc_reset_sysfs_init(pmc); - if (IS_ENABLED(CONFIG_DEBUG_FS)) { - err = tegra_powergate_debugfs_init(); - if (err < 0) - goto cleanup_sysfs; - } - err = tegra_pmc_pinctrl_init(pmc); if (err) - goto cleanup_debugfs; + goto cleanup_sysfs; err = tegra_pmc_regmap_init(pmc); if (err < 0) - goto cleanup_debugfs; + goto cleanup_sysfs; err = tegra_powergate_init(pmc, pdev->dev.of_node); if (err < 0) @@ -3061,12 +3043,12 @@ static int tegra_pmc_probe(struct platform_device *pdev) if (pmc->soc->set_wake_filters) pmc->soc->set_wake_filters(pmc); + debugfs_create_file("powergate", 0444, NULL, NULL, &powergate_fops); + return 0; cleanup_powergates: tegra_powergate_remove_all(pdev->dev.of_node); -cleanup_debugfs: - debugfs_remove(pmc->debugfs); cleanup_sysfs: device_remove_file(&pdev->dev, &dev_attr_reset_reason); device_remove_file(&pdev->dev, &dev_attr_reset_level); -- cgit v1.2.3 From c954cd7ad041251d903707c463a2c4d6cc30e5ae Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 9 Jun 2023 16:42:25 +0200 Subject: soc/tegra: pmc: Use devm_clk_notifier_register() Move to the device-managed version of clk_notifier_register() to remove the need for manual cleanup. This fixes a potential issue where the clock notifier would stick around after the driver fails to probe at a later point. Reviewed-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 438c30c5d473..162f52456f65 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -2992,7 +2992,8 @@ static int tegra_pmc_probe(struct platform_device *pdev) */ if (pmc->clk) { pmc->clk_nb.notifier_call = tegra_pmc_clk_notify_cb; - err = clk_notifier_register(pmc->clk, &pmc->clk_nb); + err = devm_clk_notifier_register(&pdev->dev, pmc->clk, + &pmc->clk_nb); if (err) { dev_err(&pdev->dev, "failed to register clk notifier\n"); @@ -3052,7 +3053,6 @@ cleanup_powergates: cleanup_sysfs: device_remove_file(&pdev->dev, &dev_attr_reset_reason); device_remove_file(&pdev->dev, &dev_attr_reset_level); - clk_notifier_unregister(pmc->clk, &pmc->clk_nb); return err; } -- cgit v1.2.3 From a10b3841f901714dbe16a8f9b0f2bbe1034e6454 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 30 Apr 2023 19:49:50 -0700 Subject: soc: rockchip: dtpm: use C99 array init syntax Eliminate sparse warnings in soc/rockchip/dtpm.c: drivers/soc/rockchip/dtpm.c:15:12: sparse: warning: obsolete array initializer, use C99 syntax drivers/soc/rockchip/dtpm.c:17:12: sparse: warning: obsolete array initializer, use C99 syntax drivers/soc/rockchip/dtpm.c:20:12: sparse: warning: obsolete array initializer, use C99 syntax drivers/soc/rockchip/dtpm.c:23:12: sparse: warning: obsolete array initializer, use C99 syntax drivers/soc/rockchip/dtpm.c:26:12: sparse: warning: obsolete array initializer, use C99 syntax drivers/soc/rockchip/dtpm.c:29:12: sparse: warning: obsolete array initializer, use C99 syntax drivers/soc/rockchip/dtpm.c:32:12: sparse: warning: obsolete array initializer, use C99 syntax drivers/soc/rockchip/dtpm.c:35:12: sparse: warning: obsolete array initializer, use C99 syntax drivers/soc/rockchip/dtpm.c:38:12: sparse: warning: obsolete array initializer, use C99 syntax drivers/soc/rockchip/dtpm.c:41:12: sparse: warning: obsolete array initializer, use C99 syntax Fixes: b9d6c47a2be8 ("rockchip/soc/drivers: Add DTPM description for rk3399") Signed-off-by: Randy Dunlap Cc: Daniel Lezcano Cc: Heiko Stuebner Cc: linux-rockchip@lists.infradead.org Acked-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230501024950.31518-1-rdunlap@infradead.org Signed-off-by: Heiko Stuebner --- drivers/soc/rockchip/dtpm.c | 54 ++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/rockchip/dtpm.c b/drivers/soc/rockchip/dtpm.c index 5a23784b5221..b36d4f752c30 100644 --- a/drivers/soc/rockchip/dtpm.c +++ b/drivers/soc/rockchip/dtpm.c @@ -12,33 +12,33 @@ #include static struct dtpm_node __initdata rk3399_hierarchy[] = { - [0]{ .name = "rk3399", - .type = DTPM_NODE_VIRTUAL }, - [1]{ .name = "package", - .type = DTPM_NODE_VIRTUAL, - .parent = &rk3399_hierarchy[0] }, - [2]{ .name = "/cpus/cpu@0", - .type = DTPM_NODE_DT, - .parent = &rk3399_hierarchy[1] }, - [3]{ .name = "/cpus/cpu@1", - .type = DTPM_NODE_DT, - .parent = &rk3399_hierarchy[1] }, - [4]{ .name = "/cpus/cpu@2", - .type = DTPM_NODE_DT, - .parent = &rk3399_hierarchy[1] }, - [5]{ .name = "/cpus/cpu@3", - .type = DTPM_NODE_DT, - .parent = &rk3399_hierarchy[1] }, - [6]{ .name = "/cpus/cpu@100", - .type = DTPM_NODE_DT, - .parent = &rk3399_hierarchy[1] }, - [7]{ .name = "/cpus/cpu@101", - .type = DTPM_NODE_DT, - .parent = &rk3399_hierarchy[1] }, - [8]{ .name = "/gpu@ff9a0000", - .type = DTPM_NODE_DT, - .parent = &rk3399_hierarchy[1] }, - [9]{ /* sentinel */ } + [0] = { .name = "rk3399", + .type = DTPM_NODE_VIRTUAL }, + [1] = { .name = "package", + .type = DTPM_NODE_VIRTUAL, + .parent = &rk3399_hierarchy[0] }, + [2] = { .name = "/cpus/cpu@0", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [3] = { .name = "/cpus/cpu@1", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [4] = { .name = "/cpus/cpu@2", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [5] = { .name = "/cpus/cpu@3", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [6] = { .name = "/cpus/cpu@100", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [7] = { .name = "/cpus/cpu@101", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [8] = { .name = "/gpu@ff9a0000", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [9] = { /* sentinel */ } }; static struct of_device_id __initdata rockchip_dtpm_match_table[] = { -- cgit v1.2.3 From 0d25da8e7e1e35bdbb521d586be1954bdedd1cca Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 12 Jun 2023 14:58:04 -0700 Subject: soc: qcom: mdt_loader: Fix split image detection The enhanced detection introduced in commit '210d12c8197a ("soc: qcom: mdt_loader: Enhance split binary detection")' requires that all segments lies within the file on disk. But the Qualcomm firmware files consistently has a BSS-like segment at the end, with a p_offset aligned to the next 4k boundary. As the p_size is 0 and there's nothing to load, the image is not padded to cover this (empty) segment. Ignore zero-sized segments when determining if the image is split, to avoid this problem. Fixes: 210d12c8197a ("soc: qcom: mdt_loader: Enhance split binary detection") Signed-off-by: Bjorn Andersson Reviewed-by: Dmitry Baryshkov Tested-by: Dmitry Baryshkov # qrb5165-rb5 Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230612215804.1883458-1-quic_bjorande@quicinc.com --- drivers/soc/qcom/mdt_loader.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c index 9418993a3a92..6f177e46fa0f 100644 --- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -275,6 +275,14 @@ static bool qcom_mdt_bins_are_split(const struct firmware *fw, const char *fw_na phdrs = (struct elf32_phdr *)(ehdr + 1); for (i = 0; i < ehdr->e_phnum; i++) { + /* + * The size of the MDT file is not padded to include any + * zero-sized segments at the end. Ignore these, as they should + * not affect the decision about image being split or not. + */ + if (!phdrs[i].p_filesz) + continue; + seg_start = phdrs[i].p_offset; seg_end = phdrs[i].p_offset + phdrs[i].p_filesz; if (seg_start > fw->size || seg_end > fw->size) -- cgit v1.2.3 From 158826c73d48097f843bacc1bcafa6dbc114f4e5 Mon Sep 17 00:00:00 2001 From: Naman Jain Date: Tue, 6 Jun 2023 19:16:25 +0530 Subject: soc: qcom: socinfo: Add support for new fields in revision 18 Add support for below fields coming in socinfo structure under v18: * num_kvps: number of key value pairs (KVP) * kvps_offset: the offset of the KVP table from the base address of socinfo structure in SMEM KVP table has boolean values for certain feature flags, used to determine hardware configuration. Signed-off-by: Naman Jain Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230606134626.18790-2-quic_namajain@quicinc.com --- drivers/soc/qcom/socinfo.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index dfd4330daef5..cb70f8439cfa 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -565,6 +565,7 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, &qcom_socinfo->info.fmt); switch (qcom_socinfo->info.fmt) { + case SOCINFO_VERSION(0, 18): case SOCINFO_VERSION(0, 17): qcom_socinfo->info.oem_variant = __le32_to_cpu(info->oem_variant); debugfs_create_u32("oem_variant", 0444, qcom_socinfo->dbg_root, -- cgit v1.2.3 From d9c2a255cfe026c8bf85a39631734f022ecefaff Mon Sep 17 00:00:00 2001 From: Naman Jain Date: Tue, 6 Jun 2023 19:16:26 +0530 Subject: soc: qcom: socinfo: Add support for new fields in revision 19 Add support for below fields coming in socinfo structure under v19: * num_func_clusters: number of clusters with at least one functional core * boot_cluster: cluster selected as boot cluster * boot_core: core selected as boot core While at it, rename some variables to align them with their functionalities. Signed-off-by: Naman Jain Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230606134626.18790-3-quic_namajain@quicinc.com --- drivers/soc/qcom/socinfo.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index cb70f8439cfa..a30d8bb6e938 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -133,12 +133,15 @@ struct socinfo_params { u32 nproduct_id; u32 num_clusters; u32 ncluster_array_offset; - u32 num_defective_parts; - u32 ndefective_parts_array_offset; + u32 num_subset_parts; + u32 nsubset_parts_array_offset; u32 nmodem_supported; u32 feature_code; u32 pcode; u32 oem_variant; + u32 num_func_clusters; + u32 boot_cluster; + u32 boot_core; }; struct smem_image_version { @@ -565,6 +568,18 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, &qcom_socinfo->info.fmt); switch (qcom_socinfo->info.fmt) { + case SOCINFO_VERSION(0, 19): + qcom_socinfo->info.num_func_clusters = __le32_to_cpu(info->num_func_clusters); + qcom_socinfo->info.boot_cluster = __le32_to_cpu(info->boot_cluster); + qcom_socinfo->info.boot_core = __le32_to_cpu(info->boot_core); + + debugfs_create_u32("num_func_clusters", 0444, qcom_socinfo->dbg_root, + &qcom_socinfo->info.num_func_clusters); + debugfs_create_u32("boot_cluster", 0444, qcom_socinfo->dbg_root, + &qcom_socinfo->info.boot_cluster); + debugfs_create_u32("boot_core", 0444, qcom_socinfo->dbg_root, + &qcom_socinfo->info.boot_core); + fallthrough; case SOCINFO_VERSION(0, 18): case SOCINFO_VERSION(0, 17): qcom_socinfo->info.oem_variant = __le32_to_cpu(info->oem_variant); @@ -589,17 +604,18 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, case SOCINFO_VERSION(0, 14): qcom_socinfo->info.num_clusters = __le32_to_cpu(info->num_clusters); qcom_socinfo->info.ncluster_array_offset = __le32_to_cpu(info->ncluster_array_offset); - qcom_socinfo->info.num_defective_parts = __le32_to_cpu(info->num_defective_parts); - qcom_socinfo->info.ndefective_parts_array_offset = __le32_to_cpu(info->ndefective_parts_array_offset); + qcom_socinfo->info.num_subset_parts = __le32_to_cpu(info->num_subset_parts); + qcom_socinfo->info.nsubset_parts_array_offset = + __le32_to_cpu(info->nsubset_parts_array_offset); debugfs_create_u32("num_clusters", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.num_clusters); debugfs_create_u32("ncluster_array_offset", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.ncluster_array_offset); - debugfs_create_u32("num_defective_parts", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.num_defective_parts); - debugfs_create_u32("ndefective_parts_array_offset", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.ndefective_parts_array_offset); + debugfs_create_u32("num_subset_parts", 0444, qcom_socinfo->dbg_root, + &qcom_socinfo->info.num_subset_parts); + debugfs_create_u32("nsubset_parts_array_offset", 0444, qcom_socinfo->dbg_root, + &qcom_socinfo->info.nsubset_parts_array_offset); fallthrough; case SOCINFO_VERSION(0, 13): qcom_socinfo->info.nproduct_id = __le32_to_cpu(info->nproduct_id); -- cgit v1.2.3 From 3aed112953b1877ede66ae77afa4e5a5024be7cb Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 6 Jun 2023 11:21:22 +0300 Subject: soc: qcom: Fix a IS_ERR() vs NULL bug in probe The devm_ioremap() function returns NULL on error, it never returns error pointers. Fixes: a77b2a0b1280 ("soc: qcom: Introduce RPM master stats driver") Signed-off-by: Dan Carpenter Reviewed-by: Konrad Dybcio Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/ZH7sgpLAN23bCz9v@moroto --- drivers/soc/qcom/rpm_master_stats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/rpm_master_stats.c b/drivers/soc/qcom/rpm_master_stats.c index 6dd98b9f7129..9ca13bcf67d3 100644 --- a/drivers/soc/qcom/rpm_master_stats.c +++ b/drivers/soc/qcom/rpm_master_stats.c @@ -105,7 +105,7 @@ static int master_stats_probe(struct platform_device *pdev) } data[i].base = devm_ioremap(dev, res.start, resource_size(&res)); - if (IS_ERR(data[i].base)) { + if (!data[i].base) { debugfs_remove_recursive(root); return dev_err_probe(dev, -EINVAL, "Could not map the MSG RAM slice idx %d!\n", i); -- cgit v1.2.3 From f471f91a0d63539107004a8e826ff017ed4d2588 Mon Sep 17 00:00:00 2001 From: Kathiravan T Date: Mon, 5 Jun 2023 13:35:29 +0530 Subject: soc: qcom: socinfo: Add Soc ID for IPQ5300 Add the SoC ID for IPQ5300, which belong to the family of IPQ5332 SoC. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Kathiravan T Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230605080531.3879-3-quic_kathirav@quicinc.com --- drivers/soc/qcom/socinfo.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index a30d8bb6e938..4d49945b3a35 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -414,6 +414,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(IPQ5322) }, { qcom_board_id(IPQ5312) }, { qcom_board_id(IPQ5302) }, + { qcom_board_id(IPQ5300) }, }; static const char *socinfo_machine(struct device *dev, unsigned int id) -- cgit v1.2.3 From 1c8267cd14ed6a592a2c2a8eb0fefad4eabe5b4f Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Wed, 31 May 2023 18:33:03 +0200 Subject: soc: qcom: icc-bwmon: Fix MSM8998 count unit MSM8998's BWMON counts in megabytes. Fix it. Signed-off-by: Konrad Dybcio Acked-by: Krzysztof Kozlowski Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230531-topic-msm8998-bwmon-v1-1-454f9d550ee5@linaro.org --- drivers/soc/qcom/icc-bwmon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index fd58c5b69897..6c6da73214e4 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -806,7 +806,7 @@ static int bwmon_remove(struct platform_device *pdev) static const struct icc_bwmon_data msm8998_bwmon_data = { .sample_ms = 4, - .count_unit_kb = 64, + .count_unit_kb = 1024, .default_highbw_kbps = 4800 * 1024, /* 4.8 GBps */ .default_medbw_kbps = 512 * 1024, /* 512 MBps */ .default_lowbw_kbps = 0, -- cgit v1.2.3 From 5d85ea2c879781d296bd770f562d33a58161d2b1 Mon Sep 17 00:00:00 2001 From: Vijaya Krishna Nivarthi Date: Wed, 14 Jun 2023 16:58:07 +0530 Subject: soc: qcom: geni-se: Do not bother about enable/disable of interrupts in secondary sequencer The select_fifo/dma_mode() functions in geni driver enable/disable interrupts (secondary included) conditionally for non-uart modes, while uart is supposed to manage this internally. However, only uart uses secondary IRQs while spi, i2c do not care about these at all making their enablement (or disablement) totally unnecessary for these protos. Similarly, select_gpi_mode() also does disable s_irq and its useless again. Drop enabling/disabling secondary IRQs. This doesn't solve any observed problem but only gets rid of code pieces that are not required. Signed-off-by: Vijaya Krishna Nivarthi Reviewed-by: Douglas Anderson Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/1686742087-30731-1-git-send-email-quic_vnivarth@quicinc.com --- drivers/soc/qcom/qcom-geni-se.c | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 795a2e1d59b3..0e01a31dde7a 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -281,27 +281,14 @@ static void geni_se_select_fifo_mode(struct geni_se *se) geni_se_irq_clear(se); - /* - * The RX path for the UART is asynchronous and so needs more - * complex logic for enabling / disabling its interrupts. - * - * Specific notes: - * - The done and TX-related interrupts are managed manually. - * - We don't RX from the main sequencer (we use the secondary) so - * we don't need the RX-related interrupts enabled in the main - * sequencer for UART. - */ + /* UART driver manages enabling / disabling interrupts internally */ if (proto != GENI_SE_UART) { + /* Non-UART use only primary sequencer so dont bother about S_IRQ */ val_old = val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN); val |= M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN; val |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN; if (val != val_old) writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN); - - val_old = val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN); - val |= S_CMD_DONE_EN; - if (val != val_old) - writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN); } val_old = val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN); @@ -317,17 +304,14 @@ static void geni_se_select_dma_mode(struct geni_se *se) geni_se_irq_clear(se); + /* UART driver manages enabling / disabling interrupts internally */ if (proto != GENI_SE_UART) { + /* Non-UART use only primary sequencer so dont bother about S_IRQ */ val_old = val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN); val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN); val &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN); if (val != val_old) writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN); - - val_old = val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN); - val &= ~S_CMD_DONE_EN; - if (val != val_old) - writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN); } val_old = val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN); @@ -344,10 +328,6 @@ static void geni_se_select_gpi_mode(struct geni_se *se) writel(0, se->base + SE_IRQ_EN); - val = readl(se->base + SE_GENI_S_IRQ_EN); - val &= ~S_CMD_DONE_EN; - writel(val, se->base + SE_GENI_S_IRQ_EN); - val = readl(se->base + SE_GENI_M_IRQ_EN); val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN | M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN); -- cgit v1.2.3 From 0bb4644d583789c97e74d3e3047189f0c59c4742 Mon Sep 17 00:00:00 2001 From: Alexey Romanov Date: Sat, 10 Jun 2023 12:04:14 +0300 Subject: drivers: meson: secure-pwrc: always enable DMA domain Starting from commit e45f243409db ("firmware: meson_sm: populate platform devices from sm device tree data") pwrc is probed successfully and disables unused pwr domains. By A1 SoC family design, any TEE requires DMA pwr domain always enabled. Fixes: b3dde5013e13 ("soc: amlogic: Add support for Secure power domains controller") Signed-off-by: Alexey Romanov Acked-by: Neil Armstrong Link: https://lore.kernel.org/r/20230610090414.90529-1-avromanov@sberdevices.ru [narmstrong: added fixes tag] Signed-off-by: Neil Armstrong --- drivers/soc/amlogic/meson-secure-pwrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/amlogic/meson-secure-pwrc.c b/drivers/soc/amlogic/meson-secure-pwrc.c index e93518763526..25b4b71df9b8 100644 --- a/drivers/soc/amlogic/meson-secure-pwrc.c +++ b/drivers/soc/amlogic/meson-secure-pwrc.c @@ -105,7 +105,7 @@ static struct meson_secure_pwrc_domain_desc a1_pwrc_domains[] = { SEC_PD(ACODEC, 0), SEC_PD(AUDIO, 0), SEC_PD(OTP, 0), - SEC_PD(DMA, 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 */ -- cgit v1.2.3