From patchwork Fri Mar 7 03:44:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guangjie Song X-Patchwork-Id: 14005937 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A6A54C282D0 for ; Fri, 7 Mar 2025 04:37:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Type: Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date :Subject:CC:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=Gn5fVtPWjhwE/dkaw+mHySONmW2E1NkGCUMO1sHmiBU=; b=zJox3qWCXIA8+JU3/GdMkhz8Ga Q2K4uQMt1iNM48x2fXd9h1MdMLt8eqZX2hRaYW0g3nekiLZDla+v5Rid3S7C8pKqHHEyKmB58ywTt +G99jhUVw2j76bz7fE6quUIX85m8TMP/6znx2yJGq7Cfgm+IuhjPSPyarJa2c2gxvTXshH1gG70Nd FWcUqnYGkyro/fXh4jcEOpObsv9jYV9KICbbclNFFXvvlRItMDhk2LKoob08jDexFYLh5tcYA93ix OUwcSukqukZ7qPT2z2kYr2eSCWHwm77VsLktnWStgtgTVeWe/61kLQSP5LHkbTg0szU7ZmVyd4ytf Fp5stJ5w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tqPS9-0000000D8LD-1f5a; Fri, 07 Mar 2025 04:36:53 +0000 Received: from mailgw01.mediatek.com ([216.200.240.184]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tqOe8-0000000D25p-3H30; Fri, 07 Mar 2025 03:45:14 +0000 X-UUID: 906413c8fb0611ef83f2a1c9db70dae0-20250306 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=Gn5fVtPWjhwE/dkaw+mHySONmW2E1NkGCUMO1sHmiBU=; b=azh6aSE0FW2rtR+h02vtzEf+s4H2fg7Wdcaf4UoAu7QBCXWMkwgM21xI2HNm04Y+3nwwy1FgsX89dgBdVTBF50C2G1ipGI/uxLic8Z8wr14ndIw9K46Gpyg7QLVjvaALxBqda2WkIFAccjMOMPAsKDC7+sLz/QWV2EcNykOqp2E=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.2.1,REQID:4756d2e5-cf3f-4f6b-ae10-d75a12180408,IP:0,UR L:0,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTION:r elease,TS:0 X-CID-META: VersionHash:0ef645f,CLOUDID:690d08c6-16da-468a-87f7-8ca8d6b3b9f7,B ulkID:nil,BulkQuantity:0,Recheck:0,SF:81|82|102,TC:nil,Content:0|50,EDM:-3 ,IP:nil,URL:0,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV :0,LES:1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0,ARC:0 X-CID-BVR: 0 X-CID-BAS: 0,_,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR X-UUID: 906413c8fb0611ef83f2a1c9db70dae0-20250306 Received: from mtkmbs14n2.mediatek.inc [(172.21.101.76)] by mailgw01.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 1400350988; Thu, 06 Mar 2025 20:45:08 -0700 Received: from mtkmbs11n1.mediatek.inc (172.21.101.185) by MTKMBS14N1.mediatek.inc (172.21.101.75) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.28; Fri, 7 Mar 2025 11:45:05 +0800 Received: from mhfsdcap04.gcn.mediatek.inc (10.17.3.154) by mtkmbs11n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1258.28 via Frontend Transport; Fri, 7 Mar 2025 11:45:04 +0800 From: Guangjie Song To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matthias Brugger , AngeloGioacchino Del Regno , Ulf Hansson CC: , , , , , Guangjie Song , Subject: [PATCH 10/13] pmdomain: mediatek: Support bus protect with table Date: Fri, 7 Mar 2025 11:44:34 +0800 Message-ID: <20250307034454.12243-11-guangjie.song@mediatek.com> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20250307034454.12243-1-guangjie.song@mediatek.com> References: <20250307034454.12243-1-guangjie.song@mediatek.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250306_194512_858448_F073E4A6 X-CRM114-Status: GOOD ( 21.18 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Support bus protect with table which can contain multiple items. Signed-off-by: Guangjie Song --- drivers/pmdomain/mediatek/mtk-scpsys.c | 179 ++++++++++++++++++++++++- 1 file changed, 173 insertions(+), 6 deletions(-) diff --git a/drivers/pmdomain/mediatek/mtk-scpsys.c b/drivers/pmdomain/mediatek/mtk-scpsys.c index 47d5d5abcaee..c10756fa1685 100644 --- a/drivers/pmdomain/mediatek/mtk-scpsys.c +++ b/drivers/pmdomain/mediatek/mtk-scpsys.c @@ -31,6 +31,8 @@ #define MTK_RTFF_DELAY_US 10 #define MTK_STABLE_DELAY_US 100 +#define MTK_BUS_PROTECTION_RETY_TIMES 10 + #define MTK_SCPD_ACTIVE_WAKEUP BIT(0) #define MTK_SCPD_FWAIT_SRAM BIT(1) #define MTK_SCPD_SRAM_ISO BIT(2) @@ -106,6 +108,24 @@ #define PWR_STATUS_HIF1 BIT(26) /* MT7622 */ #define PWR_STATUS_WB BIT(27) /* MT7622 */ +#define _BUS_PROT(_type, _set_ofs, _clr_ofs, \ + _en_ofs, _sta_ofs, _mask, _ack_mask, \ + _ignore_clr_ack) { \ + .type = _type, \ + .set_ofs = _set_ofs, \ + .clr_ofs = _clr_ofs, \ + .en_ofs = _en_ofs, \ + .sta_ofs = _sta_ofs, \ + .mask = _mask, \ + .ack_mask = _ack_mask, \ + .ignore_clr_ack = _ignore_clr_ack, \ + } + +#define BUS_PROT_IGN(_type, _set_ofs, _clr_ofs, \ + _en_ofs, _sta_ofs, _mask) \ + _BUS_PROT(_type, _set_ofs, _clr_ofs, \ + _en_ofs, _sta_ofs, _mask, _mask, true) + enum clk_id { CLK_NONE, CLK_MM, @@ -135,6 +155,18 @@ static const char * const clk_names[] = { }; #define MAX_CLKS 3 +#define MAX_STEPS 3 + +struct bus_prot { + u32 type; + u32 set_ofs; + u32 clr_ofs; + u32 en_ofs; + u32 sta_ofs; + u32 mask; + u32 ack_mask; + bool ignore_clr_ack; +}; /** * struct scp_domain_data - scp domain data for power on/off flow @@ -157,6 +189,7 @@ static const char * const clk_names[] = { * @sram_slp_ack_bits: The mask for sram low power control acked bits. * @bus_prot_mask: The mask for single step bus protection. * @clk_id: The basic clocks required by this power domain. + * @bp_table: The bus protect configs for the power domain. * @caps: The flag for active wake-up action. */ struct scp_domain_data { @@ -179,6 +212,7 @@ struct scp_domain_data { u32 sram_slp_ack_bits; u32 bus_prot_mask; enum clk_id clk_id[MAX_CLKS]; + struct bus_prot bp_table[MAX_STEPS]; u32 caps; }; @@ -207,6 +241,8 @@ struct scp { struct regmap *infracfg; struct scp_ctrl_reg ctrl_reg; bool bus_prot_reg_update; + struct regmap **bp_regmap; + int num_bp; }; struct scp_subdomain { @@ -221,6 +257,8 @@ struct scp_soc_data { int num_subdomains; const struct scp_ctrl_reg regs; bool bus_prot_reg_update; + const char **bp_list; + int num_bp; }; static int scpsys_domain_is_on(struct scp_domain *scpd) @@ -375,10 +413,121 @@ static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr) MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); } +static int set_bus_protection(struct regmap *map, struct bus_prot *bp) +{ + u32 val = 0; + int retry = 0; + int ret = 0; + + while (retry <= MTK_BUS_PROTECTION_RETY_TIMES) { + if (bp->set_ofs) + regmap_write(map, bp->set_ofs, bp->mask); + else + regmap_update_bits(map, bp->en_ofs, bp->mask, bp->mask); + + /* check bus protect enable setting */ + regmap_read(map, bp->en_ofs, &val); + if ((val & bp->mask) == bp->mask) + break; + + retry++; + } + + ret = regmap_read_poll_timeout_atomic(map, bp->sta_ofs, val, + (val & bp->ack_mask) == bp->ack_mask, + MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); + if (ret < 0) { + pr_err("%s val=0x%x, mask=0x%x, (val & mask)=0x%x\n", + __func__, val, bp->ack_mask, (val & bp->ack_mask)); + } + + return ret; +} + +static int clear_bus_protection(struct regmap *map, struct bus_prot *bp) +{ + u32 val = 0; + int ret = 0; + + if (bp->clr_ofs) + regmap_write(map, bp->clr_ofs, bp->mask); + else + regmap_update_bits(map, bp->en_ofs, bp->mask, 0); + + if (bp->ignore_clr_ack) + return 0; + + ret = regmap_read_poll_timeout_atomic(map, bp->sta_ofs, val, + !(val & bp->ack_mask), + MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); + if (ret < 0) { + pr_err("%s val=0x%x, mask=0x%x, (val & mask)=0x%x\n", + __func__, val, bp->ack_mask, (val & bp->ack_mask)); + } + return ret; +} + +static int scpsys_bus_protect_table_disable(struct scp_domain *scpd, unsigned int index) +{ + struct scp *scp = scpd->scp; + const struct bus_prot *bp_table = scpd->data->bp_table; + int ret = 0; + int i; + + for (i = index; i >= 0; i--) { + struct regmap *map; + struct bus_prot bp = bp_table[i]; + + if (bp.type == 0 || bp.type >= scp->num_bp) + continue; + + map = scp->bp_regmap[bp.type]; + if (!map) + continue; + + ret = clear_bus_protection(map, &bp); + if (ret) + break; + } + + return ret; +} + +static int scpsys_bus_protect_table_enable(struct scp_domain *scpd) +{ + struct scp *scp = scpd->scp; + const struct bus_prot *bp_table = scpd->data->bp_table; + int ret = 0; + int i; + + for (i = 0; i < MAX_STEPS; i++) { + struct regmap *map; + struct bus_prot bp = bp_table[i]; + + if (bp.type == 0 || bp.type >= scp->num_bp) + continue; + + map = scp->bp_regmap[bp.type]; + if (!map) + continue; + + ret = set_bus_protection(map, &bp); + if (ret) { + scpsys_bus_protect_table_disable(scpd, i); + return ret; + } + } + + return ret; +} + static int scpsys_bus_protect_enable(struct scp_domain *scpd) { struct scp *scp = scpd->scp; + if (scp->bp_regmap && scp->num_bp > 0) + return scpsys_bus_protect_table_enable(scpd); + if (!scpd->data->bus_prot_mask) return 0; @@ -391,6 +540,9 @@ static int scpsys_bus_protect_disable(struct scp_domain *scpd) { struct scp *scp = scpd->scp; + if (scp->bp_regmap && scp->num_bp > 0) + return scpsys_bus_protect_table_disable(scpd, MAX_STEPS - 1); + if (!scpd->data->bus_prot_mask) return 0; @@ -833,12 +985,27 @@ static struct scp *init_scp(struct platform_device *pdev, const struct scp_soc_d if (!pd_data->domains) return ERR_PTR(-ENOMEM); - scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, - "infracfg"); - if (IS_ERR(scp->infracfg)) { - dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n", - PTR_ERR(scp->infracfg)); - return ERR_CAST(scp->infracfg); + if (soc->bp_list && soc->num_bp > 0) { + scp->num_bp = soc->num_bp; + scp->bp_regmap = devm_kcalloc(&pdev->dev, scp->num_bp, + sizeof(*scp->bp_regmap), GFP_KERNEL); + if (!scp->bp_regmap) + return ERR_PTR(-ENOMEM); + + /* get bus prot regmap from dts node, 0 means invalid bus type */ + for (i = 1; i < scp->num_bp; i++) { + ret = mtk_pd_get_regmap(pdev, &scp->bp_regmap[i], soc->bp_list[i]); + if (ret) + return ERR_PTR(ret); + } + } else { + scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "infracfg"); + if (IS_ERR(scp->infracfg)) { + dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n", + PTR_ERR(scp->infracfg)); + return ERR_CAST(scp->infracfg); + } } for (i = 0; i < soc->num_domains; i++) {