From patchwork Fri Mar 31 16:30:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 13196357 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 20B99C77B60 for ; Fri, 31 Mar 2023 16:34:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229758AbjCaQe4 (ORCPT ); Fri, 31 Mar 2023 12:34:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46978 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230064AbjCaQe0 (ORCPT ); Fri, 31 Mar 2023 12:34:26 -0400 Received: from madras.collabora.co.uk (madras.collabora.co.uk [46.235.227.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2AD2523B77; Fri, 31 Mar 2023 09:31:10 -0700 (PDT) Received: from jupiter.universe (dyndsl-091-248-213-136.ewe-ip-backbone.de [91.248.213.136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: sre) by madras.collabora.co.uk (Postfix) with ESMTPSA id 01B9D6603196; Fri, 31 Mar 2023 17:31:08 +0100 (BST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1680280268; bh=pkfuM6Rnn3TuDfL3bWotBSugc5TTFUmOiPf9WrErtIw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WBq67bhLzN+1dsiIX0z0RJG7HGys4MES0f3q799B/XkptgeXtxTPyj9Cf9yulH6bw pknM7kgar9nktAwTZb0l7aCFMrOZVdA4FZVr9Da/NALJt7qWIQHcOnyGjN72MyKySN HDNSIur0BjwKquZJ0hGWXu/e7BrRPYJdyWjAOIpiqPua5Ro/cAyBUqIwdeWGFeuF/X l7Cgld9fqoW0+CKwe+Vr6rrTSFi70oQnPaIA7BhFbdGm7Sainwapd2Vm7RdGE2ZWzA A096EHqWTcXks8JS4/LSpFUVS9MNwfNBsAXfsYsEDyVcKddYeHKqoKqe/xPpiP6WGW ceKbkb0bD3B3g== Received: by jupiter.universe (Postfix, from userid 1000) id 599A94807E2; Fri, 31 Mar 2023 18:31:06 +0200 (CEST) From: Sebastian Reichel To: Heiko Stuebner , linux-rockchip@lists.infradead.org Cc: Peter Geis , Elaine Zhang , Finley Xiao , Jagan Teki , Michael Turquette , Stephen Boyd , Boris Brezillon , linux-clk@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Sebastian Reichel , kernel@collabora.com Subject: [PATCHv1 1/2] clk: rockchip: rk3588: make gate linked clocks ignore unused Date: Fri, 31 Mar 2023 18:30:57 +0200 Message-Id: <20230331163058.5688-2-sebastian.reichel@collabora.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230331163058.5688-1-sebastian.reichel@collabora.com> References: <20230331163058.5688-1-sebastian.reichel@collabora.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org RK3588 has a couple of hardware blocks called Native Interface Unit (NIU) that gate the clocks to devices behind them. Effectively this means that some clocks require two parent clocks being enabled. Downstream implemented this by using a separate clock driver ("clk-link") for them, which enables the second clock using PM framework. In the upstream kernel we are currently missing support for the second parent. The information about it is in the GATE_LINK() macro as linkname, but that is not used. Thus the second parent clock is not properly enabled. So far this did not really matter, since these clocks are mostly required for the more advanced IP blocks, that are not yet supported upstream. As this is about to change we need a fix. There are three options available: 1. Properly implement support for having two parent clocks in the clock framework. 2. Mark the affected clocks CLK_IGNORE_UNUSED, so that they are not disabled. This wastes some power, but keeps the hack contained within the clock driver. Going from this to the first solution is easy once that has been implemented. 3. Enabling the extra clock in the consumer driver. This leaks some implementation details into DT. This patch implements the second option as an intermediate solution until the first one is available. I used an alias for CLK_IS_CRITICAL, so that it's easy to see which clocks are not really critical once the clock framework supports a better way to implement this. Signed-off-by: Sebastian Reichel --- drivers/clk/rockchip/clk-rk3588.c | 42 +++++++++++++++++++------------ 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3588.c b/drivers/clk/rockchip/clk-rk3588.c index b7ce3fbd6fa6..6994165e0395 100644 --- a/drivers/clk/rockchip/clk-rk3588.c +++ b/drivers/clk/rockchip/clk-rk3588.c @@ -13,15 +13,25 @@ #include "clk.h" /* - * GATE with additional linked clock. Downstream enables the linked clock - * (via runtime PM) whenever the gate is enabled. The downstream implementation - * does this via separate clock nodes for each of the linked gate clocks, - * which leaks parts of the clock tree into DT. It is unclear why this is - * actually needed and things work without it for simple use cases. Thus - * the linked clock is ignored for now. + * Recent Rockchip SoCs have a new hardware block called Native Interface + * Unit (NIU), which gates clocks to devices behind them. These effectively + * need two parent clocks. + * + * Downstream enables the linked clock via runtime PM whenever the gate is + * enabled. This implementation uses separate clock nodes for each of the + * linked gate clocks, which leaks parts of the clock tree into DT. + * + * The GATE_LINK macro instead takes the second parent via 'linkname', but + * ignores the information. Once the clock framework is ready to handle it, the + * information should be passed on here. But since these clocks are required to + * access multiple relevant IP blocks, such as PCIe or USB, we mark all linked + * clocks critical until a better solution is available. This will waste some + * power, but avoids leaking implementation details into DT or hanging the + * system. */ #define GATE_LINK(_id, cname, pname, linkname, f, o, b, gf) \ GATE(_id, cname, pname, f, o, b, gf) +#define RK3588_LINKED_CLK CLK_IS_CRITICAL #define RK3588_GRF_SOC_STATUS0 0x600 @@ -1446,7 +1456,7 @@ static struct rockchip_clk_branch rk3588_clk_branches[] __initdata = { COMPOSITE_NODIV(HCLK_NVM_ROOT, "hclk_nvm_root", mux_200m_100m_50m_24m_p, 0, RK3588_CLKSEL_CON(77), 0, 2, MFLAGS, RK3588_CLKGATE_CON(31), 0, GFLAGS), - COMPOSITE(ACLK_NVM_ROOT, "aclk_nvm_root", gpll_cpll_p, 0, + COMPOSITE(ACLK_NVM_ROOT, "aclk_nvm_root", gpll_cpll_p, RK3588_LINKED_CLK, RK3588_CLKSEL_CON(77), 7, 1, MFLAGS, 2, 5, DFLAGS, RK3588_CLKGATE_CON(31), 1, GFLAGS), GATE(ACLK_EMMC, "aclk_emmc", "aclk_nvm_root", 0, @@ -1675,13 +1685,13 @@ static struct rockchip_clk_branch rk3588_clk_branches[] __initdata = { RK3588_CLKGATE_CON(42), 9, GFLAGS), /* vdpu */ - COMPOSITE(ACLK_VDPU_ROOT, "aclk_vdpu_root", gpll_cpll_aupll_p, 0, + COMPOSITE(ACLK_VDPU_ROOT, "aclk_vdpu_root", gpll_cpll_aupll_p, RK3588_LINKED_CLK, RK3588_CLKSEL_CON(98), 5, 2, MFLAGS, 0, 5, DFLAGS, RK3588_CLKGATE_CON(44), 0, GFLAGS), COMPOSITE_NODIV(ACLK_VDPU_LOW_ROOT, "aclk_vdpu_low_root", mux_400m_200m_100m_24m_p, 0, RK3588_CLKSEL_CON(98), 7, 2, MFLAGS, RK3588_CLKGATE_CON(44), 1, GFLAGS), - COMPOSITE_NODIV(HCLK_VDPU_ROOT, "hclk_vdpu_root", mux_200m_100m_50m_24m_p, 0, + COMPOSITE_NODIV(HCLK_VDPU_ROOT, "hclk_vdpu_root", mux_200m_100m_50m_24m_p, RK3588_LINKED_CLK, RK3588_CLKSEL_CON(98), 9, 2, MFLAGS, RK3588_CLKGATE_CON(44), 2, GFLAGS), COMPOSITE(ACLK_JPEG_DECODER_ROOT, "aclk_jpeg_decoder_root", gpll_cpll_aupll_spll_p, 0, @@ -1732,9 +1742,9 @@ static struct rockchip_clk_branch rk3588_clk_branches[] __initdata = { COMPOSITE(ACLK_RKVENC0_ROOT, "aclk_rkvenc0_root", gpll_cpll_npll_p, 0, RK3588_CLKSEL_CON(102), 7, 2, MFLAGS, 2, 5, DFLAGS, RK3588_CLKGATE_CON(47), 1, GFLAGS), - GATE(HCLK_RKVENC0, "hclk_rkvenc0", "hclk_rkvenc0_root", 0, + GATE(HCLK_RKVENC0, "hclk_rkvenc0", "hclk_rkvenc0_root", RK3588_LINKED_CLK, RK3588_CLKGATE_CON(47), 4, GFLAGS), - GATE(ACLK_RKVENC0, "aclk_rkvenc0", "aclk_rkvenc0_root", 0, + GATE(ACLK_RKVENC0, "aclk_rkvenc0", "aclk_rkvenc0_root", RK3588_LINKED_CLK, RK3588_CLKGATE_CON(47), 5, GFLAGS), COMPOSITE(CLK_RKVENC0_CORE, "clk_rkvenc0_core", gpll_cpll_aupll_npll_p, 0, RK3588_CLKSEL_CON(102), 14, 2, MFLAGS, 9, 5, DFLAGS, @@ -1744,10 +1754,10 @@ static struct rockchip_clk_branch rk3588_clk_branches[] __initdata = { RK3588_CLKGATE_CON(48), 6, GFLAGS), /* vi */ - COMPOSITE(ACLK_VI_ROOT, "aclk_vi_root", gpll_cpll_npll_aupll_spll_p, 0, + COMPOSITE(ACLK_VI_ROOT, "aclk_vi_root", gpll_cpll_npll_aupll_spll_p, RK3588_LINKED_CLK, RK3588_CLKSEL_CON(106), 5, 3, MFLAGS, 0, 5, DFLAGS, RK3588_CLKGATE_CON(49), 0, GFLAGS), - COMPOSITE_NODIV(HCLK_VI_ROOT, "hclk_vi_root", mux_200m_100m_50m_24m_p, 0, + COMPOSITE_NODIV(HCLK_VI_ROOT, "hclk_vi_root", mux_200m_100m_50m_24m_p, RK3588_LINKED_CLK, RK3588_CLKSEL_CON(106), 8, 2, MFLAGS, RK3588_CLKGATE_CON(49), 1, GFLAGS), COMPOSITE_NODIV(PCLK_VI_ROOT, "pclk_vi_root", mux_100m_50m_24m_p, 0, @@ -1919,10 +1929,10 @@ static struct rockchip_clk_branch rk3588_clk_branches[] __initdata = { COMPOSITE(ACLK_VOP_ROOT, "aclk_vop_root", gpll_cpll_dmyaupll_npll_spll_p, 0, RK3588_CLKSEL_CON(110), 5, 3, MFLAGS, 0, 5, DFLAGS, RK3588_CLKGATE_CON(52), 0, GFLAGS), - COMPOSITE_NODIV(ACLK_VOP_LOW_ROOT, "aclk_vop_low_root", mux_400m_200m_100m_24m_p, 0, + COMPOSITE_NODIV(ACLK_VOP_LOW_ROOT, "aclk_vop_low_root", mux_400m_200m_100m_24m_p, RK3588_LINKED_CLK, RK3588_CLKSEL_CON(110), 8, 2, MFLAGS, RK3588_CLKGATE_CON(52), 1, GFLAGS), - COMPOSITE_NODIV(HCLK_VOP_ROOT, "hclk_vop_root", mux_200m_100m_50m_24m_p, 0, + COMPOSITE_NODIV(HCLK_VOP_ROOT, "hclk_vop_root", mux_200m_100m_50m_24m_p, RK3588_LINKED_CLK, RK3588_CLKSEL_CON(110), 10, 2, MFLAGS, RK3588_CLKGATE_CON(52), 2, GFLAGS), COMPOSITE_NODIV(PCLK_VOP_ROOT, "pclk_vop_root", mux_100m_50m_24m_p, 0, @@ -2425,7 +2435,7 @@ static struct rockchip_clk_branch rk3588_clk_branches[] __initdata = { GATE_LINK(ACLK_ISP1_PRE, "aclk_isp1_pre", "aclk_isp1_root", "aclk_vi_root", 0, RK3588_CLKGATE_CON(26), 6, GFLAGS), GATE_LINK(HCLK_ISP1_PRE, "hclk_isp1_pre", "hclk_isp1_root", "hclk_vi_root", 0, RK3588_CLKGATE_CON(26), 8, GFLAGS), - GATE_LINK(HCLK_NVM, "hclk_nvm", "hclk_nvm_root", "aclk_nvm_root", 0, RK3588_CLKGATE_CON(31), 2, GFLAGS), + GATE_LINK(HCLK_NVM, "hclk_nvm", "hclk_nvm_root", "aclk_nvm_root", RK3588_LINKED_CLK, RK3588_CLKGATE_CON(31), 2, GFLAGS), GATE_LINK(ACLK_USB, "aclk_usb", "aclk_usb_root", "aclk_vo1usb_top_root", 0, RK3588_CLKGATE_CON(42), 2, GFLAGS), GATE_LINK(HCLK_USB, "hclk_usb", "hclk_usb_root", "hclk_vo1usb_top_root", 0, RK3588_CLKGATE_CON(42), 3, GFLAGS), GATE_LINK(ACLK_JPEG_DECODER_PRE, "aclk_jpeg_decoder_pre", "aclk_jpeg_decoder_root", "aclk_vdpu_root", 0, RK3588_CLKGATE_CON(44), 7, GFLAGS), From patchwork Fri Mar 31 16:30:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 13196356 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 79E39C761A6 for ; Fri, 31 Mar 2023 16:34:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230269AbjCaQez (ORCPT ); Fri, 31 Mar 2023 12:34:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47004 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232035AbjCaQe0 (ORCPT ); Fri, 31 Mar 2023 12:34:26 -0400 Received: from madras.collabora.co.uk (madras.collabora.co.uk [IPv6:2a00:1098:0:82:1000:25:2eeb:e5ab]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 464201FD2E; Fri, 31 Mar 2023 09:31:10 -0700 (PDT) Received: from jupiter.universe (dyndsl-091-248-213-136.ewe-ip-backbone.de [91.248.213.136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: sre) by madras.collabora.co.uk (Postfix) with ESMTPSA id 0A834660319B; Fri, 31 Mar 2023 17:31:08 +0100 (BST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1680280268; bh=i9BGs9btRS2BixYzGSGiY/eZWnra7PBJGPH/Gfsqa5Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SJ/LjGbI66nhSuRZXYkGXnqnwz0uAZB+ruqqNBAOrtyg0QpLNdNIJ+rU4ykx28gEA uIEEwak+ANqFBVilGO47JbjBB/i9GszhHec58FO/R4M/94lHcTgIPqrZP3UHmsGCUb tyVYrSN3v9ZraU3WeqATVPtr3x1gcLCKo+WSa2Po+q9xZwti2H+pkgeInEZrFlAHbr 00J1JR1XsWclHnmyv5Iuy+dGoMwzD7wdbm7gunxqyfj7t8fIzHH9x5ujTG1vzyr9mg K2jaIjkOV5OOMlaqwlsuHZMzQgyXusyrYbToZfVvXh82fmiMIHjIhDSaixGk64C+6k QYdfO+CK05xTw== Received: by jupiter.universe (Postfix, from userid 1000) id 5C1344807E3; Fri, 31 Mar 2023 18:31:06 +0200 (CEST) From: Sebastian Reichel To: Heiko Stuebner , linux-rockchip@lists.infradead.org Cc: Peter Geis , Elaine Zhang , Finley Xiao , Jagan Teki , Michael Turquette , Stephen Boyd , Boris Brezillon , linux-clk@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, kernel@collabora.com, Sebastian Reichel Subject: [PATCHv1 2/2] soc: rockchip: power-domain: add rk3588 mem module support Date: Fri, 31 Mar 2023 18:30:58 +0200 Message-Id: <20230331163058.5688-3-sebastian.reichel@collabora.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230331163058.5688-1-sebastian.reichel@collabora.com> References: <20230331163058.5688-1-sebastian.reichel@collabora.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org From: Boris Brezillon 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. Co-Developed-by: Finley Xiao Signed-off-by: Finley Xiao Signed-off-by: Boris Brezillon Signed-off-by: Sebastian Reichel --- drivers/soc/rockchip/pm_domains.c | 160 +++++++++++++++++++++++------- 1 file changed, 125 insertions(+), 35 deletions(-) diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 84bc022f9e5b..8b3c745925a3 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)); + dsb(sy); + + 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); + dsb(sy); + + 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),