From mboxrd@z Thu Jan 1 00:00:00 1970 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 A5D5BEEF30C for ; Thu, 5 Mar 2026 06:12:20 +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:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=v9aOQtXPMrRyOq0vhd4Vrs9+A7t+qYPDJvOzQNfneMs=; b=pwNg7IpMpSAJHG8KboLrlYHzG4 F8my5ZNKTQyC8IfOiG/dy3bfLMo4WkmnA57kBA5OTDYJeekGa8hIdrxKaGEAygQ0bxyDQ9KTKuqs8 2yAjTB1i6yOV3f5u1VifuCvyYR5+O5xxsoLe/R425urf0HD9YRSpXYSK8eLpgB0IfPrVq7E1BfG3N o98K8InrfjQnSgZTJSqWxMAm/weewbcc3KO1jzYHklvVLYqDRyJ+5bPT1axHlkop6PC0AqQub6GT7 WoxLnXP9OtYZ5A1N4bRu3BfhCZHosXpoGYXDANU1totvSqrKi/ycsS58waTbzrFGFHusRC2/KiA16 KGox8aFQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.2 #2 (Red Hat Linux)) id 1vy1wO-00000000yex-2KNf; Thu, 05 Mar 2026 06:12:08 +0000 Received: from mail-ej1-x62a.google.com ([2a00:1450:4864:20::62a]) by bombadil.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux)) id 1vy1wJ-00000000yaO-12Ti for linux-arm-kernel@lists.infradead.org; Thu, 05 Mar 2026 06:12:04 +0000 Received: by mail-ej1-x62a.google.com with SMTP id a640c23a62f3a-b939cfc1e83so610661866b.0 for ; Wed, 04 Mar 2026 22:12:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1772691122; x=1773295922; darn=lists.infradead.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=v9aOQtXPMrRyOq0vhd4Vrs9+A7t+qYPDJvOzQNfneMs=; b=knE7JAl9ILWFuiizRlDf7paU6KF+Nx/zTOjoNPnohctMWrnSZERHdC1HPcLYAN95Cy GOcru6SuZO8Izbhr+Skaj7qpQ0hR50atB5zNSiEMOGXMVJMPhRfvAbSD+XwBwnb+5AOS G+ZVVszciG7Yiz5c7M+r1/NQGaXs7YWQm6YWE2G+RzU6TpFJhYBISr4L+DZ7LXtA+3/7 TVQ1ahcl/HI9VH8Bocxx0dJkH1BuxDCkPaQ3k/nOpp1VY7nthooGnS4ZdXf83PR2t4Y8 RJTcLqcWajRAElZe/JedfeCdQkm0DUbwsxKat8VyREoLAAu1sE3INrrVggPjhMBXxT/E NFnQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772691122; x=1773295922; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=v9aOQtXPMrRyOq0vhd4Vrs9+A7t+qYPDJvOzQNfneMs=; b=wlT/iKTw8DM5Ae5lRVLb+0dNF8uUrdHXThc3CfAqIrFhRwANE7YRfGIhjQmr47Acdp pAtda5W7SiA+5vla5Sn1cywlC7QrnnaP1/BKQdM9PQr88ZYN20GFKO6TX5NPj2qvFR85 BNy8DIHKbEqIrGj+UhfK21Iz3QBNWy7l14LS6sHj3OdPzBaCcr2C44Xc8K5BR7R9YNnQ v9iFselwr81+WrcytI9zNUXjhMAglVIDNURvJn2Vao73iRp5VpzyyfRTBnMiI3Tug7QL T19FDSbK/B3wMphCN9S9jJD6yk6HDPGxQehG5QoQoZD4AN5eMJc0mI4OP4panV/o1Um5 TKwg== X-Forwarded-Encrypted: i=1; AJvYcCWVZB+rPQOwOSzJPhqI58qqMgZvShMST8XsZV2r2RM6/UPOwS3wqoA7jgdwbW+tjjwM2sq88ly0xWZ7VkzBU3X/@lists.infradead.org X-Gm-Message-State: AOJu0YyZ1TBoVWcSKg82pTc9zPksTMbRuNOtbAo/6iAFbMLCmtdWGisK 1oKRdbMi7FBj6lvA1XpRTz/JWoVlkMWRArT+SGAUHG8GjA0J3WNxaFObicKeGGhW7Lw= X-Gm-Gg: ATEYQzx7UmNPWFRpgVQfRIA6VZY+ykZNljPXw9swANHUvzBHiFd30+j+G63cdzfMam4 DBaiE16M47hJCIEa/hyC9dHmXCE1TyMyf7C7t6uqSdue9geZ09K89Oy9z88HyoxvEZTJcw0t0rn 1LgPaczzfikqrdpsH6ADmZazNEpreNhLXeoQ8QuxO2V0LRCiuPM8SUcUypjxpKg62zu4QFh2Ms1 TcEVRknScz0/+fDhM3ssUT+nqp3Q+0U2FH0/N34n6HTKvtOihdEvohbBdx/BwMuRl6cUH2dcSIz /TMklqPGwce2/J8HawW3RSOCFoy3E73ns3UR8Q4xvvRbUDUiCyoH3o1qcOtR1dH6+jMt9jelmnG fdiXO+KYRbhEMnZSo9IeCfehmircSu4ach9Tl0JGacBYpCwlZRsTXdMqavKYpzvmUrjZ4lDazAO 7It02PVCfaMrT/vEWESNnVvxAf/jwUaTdGVIefgYUZnZI+8Di/aFmaWz+ZpXpTyAQH++reNz0v+ NBrH39+Dpg2rVg= X-Received: by 2002:a17:907:e106:b0:b94:e64:fe6a with SMTP id a640c23a62f3a-b940e65317amr30805866b.49.1772691121509; Wed, 04 Mar 2026 22:12:01 -0800 (PST) Received: from puffmais2.c.googlers.com (221.210.91.34.bc.googleusercontent.com. [34.91.210.221]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b935aec3243sm849355966b.53.2026.03.04.22.12.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2026 22:12:01 -0800 (PST) From: =?utf-8?q?Andr=C3=A9_Draszik?= Date: Thu, 05 Mar 2026 06:11:58 +0000 Subject: [PATCH v6 09/10] pmdomain: samsung: implement SMC to save / restore TZ config MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit Message-Id: <20260305-gs101-pd-v6-9-8cb953c1a723@linaro.org> References: <20260305-gs101-pd-v6-0-8cb953c1a723@linaro.org> In-Reply-To: <20260305-gs101-pd-v6-0-8cb953c1a723@linaro.org> To: Krzysztof Kozlowski , Alim Akhtar , Rob Herring , Conor Dooley , Krzysztof Kozlowski , Ulf Hansson , Liam Girdwood , Mark Brown Cc: Peter Griffin , Tudor Ambarus , Juan Yescas , Will McVicker , kernel-team@android.com, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, =?utf-8?q?Andr=C3=A9_Draszik?= X-Mailer: b4 0.14.3 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260304_221203_325654_61AF21B1 X-CRM114-Status: GOOD ( 28.09 ) 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 Newer Exynos platforms have a Distributed Trust Zone Protection Control (DTZPC) linked to each power domain. It controls the access permissions to various registers from secure and non-secure world. An SMC call is required to instruct the firmware that the power domain is about to be turned off and again once it was turned on. This allows the firmware to save and restore the DTZPC configuration. Without, register access to various registers becomes impossible from Linux (causing SError), as the PoR configuration doesn't allow access. Neither the requirement for the SMC call, nor its arguments appear to be specific to gs101, as at least Exynos E850 also uses the same as can be seen in [1], hence prefix the new macros simply with EXYNOS_. At least on gs101, this SMC call isn't implemented for all power domains (e.g. it's missing for HSI2 (UFS)), therefore we issue a test SMC to store the configuration during probe, and if it fails we mark a domain as always-on to avoid the SErrors and to avoid unnecessarily retrying for each domain on/off. Link: https://lore.kernel.org/all/20230308233822.31180-4-semen.protsenko@linaro.org/ [1] Signed-off-by: André Draszik --- drivers/pmdomain/samsung/exynos-pm-domains.c | 96 ++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 6 deletions(-) diff --git a/drivers/pmdomain/samsung/exynos-pm-domains.c b/drivers/pmdomain/samsung/exynos-pm-domains.c index 41a232b3cdaf..f59986b56213 100644 --- a/drivers/pmdomain/samsung/exynos-pm-domains.c +++ b/drivers/pmdomain/samsung/exynos-pm-domains.c @@ -9,6 +9,7 @@ // conjunction with runtime-pm. Support for both device-tree and non-device-tree // based power domain support is included. +#include #include #include #include @@ -16,12 +17,19 @@ #include #include #include +#include #include #include +#define EXYNOS_SMC_CMD_PREPARE_PD_ONOFF 0x82000410 +#define EXYNOS_GET_IN_PD_DOWN 0 +#define EXYNOS_WAKEUP_PD_DOWN 1 +#define EXYNOS_RUNTIME_PM_TZPC_GROUP 2 + struct exynos_pm_domain_config { /* Value for LOCAL_PWR_CFG and STATUS fields for each domain */ u32 local_pwr_cfg; + u32 smc_offset; bool use_parent_regmap; }; @@ -32,11 +40,28 @@ struct exynos_pm_domain { struct regmap *regmap; struct device *dev; struct generic_pm_domain pd; - u32 local_pwr_cfg; + const struct exynos_pm_domain_config *cfg; u32 configuration_reg; u32 status_reg; + phys_addr_t ac_pa; }; +static int exynos_pd_access_controller_power(struct exynos_pm_domain *pd, + bool power_on) +{ + struct arm_smccc_res res; + + if (!pd->ac_pa || !pd->cfg->smc_offset) + return 0; + + arm_smccc_smc(EXYNOS_SMC_CMD_PREPARE_PD_ONOFF, + power_on ? EXYNOS_WAKEUP_PD_DOWN : EXYNOS_GET_IN_PD_DOWN, + pd->ac_pa + pd->cfg->smc_offset, + EXYNOS_RUNTIME_PM_TZPC_GROUP, 0, 0, 0, 0, &res); + + return res.a0; +} + static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on) { struct exynos_pm_domain *pd; @@ -45,7 +70,17 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on) pd = container_of(domain, struct exynos_pm_domain, pd); - pwr = power_on ? pd->local_pwr_cfg : 0; + if (!power_on) { + err = exynos_pd_access_controller_power(pd, power_on); + if (err) { + dev_err(pd->dev, + "SMC for power domain %s %sable failed: %d\n", + domain->name, power_on ? "en" : "dis", err); + return err; + } + } + + pwr = power_on ? pd->cfg->local_pwr_cfg : 0; err = regmap_write(pd->regmap, pd->configuration_reg, pwr); if (err) { dev_err(pd->dev, @@ -60,7 +95,7 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on) unsigned int val; err = regmap_read(pd->regmap, pd->status_reg, &val); - if (err || ((val & pd->local_pwr_cfg) != pwr)) { + if (err || ((val & pd->cfg->local_pwr_cfg) != pwr)) { cpu_relax(); usleep_range(80, 100); continue; @@ -72,9 +107,21 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on) if (!timeout && !err) /* Only return timeout if no other error also occurred. */ err = -ETIMEDOUT; - if (err) + if (err) { dev_err(pd->dev, "Power domain %s %sable failed: %d\n", domain->name, power_on ? "en" : "dis", err); + return err; + } + + if (power_on) { + err = exynos_pd_access_controller_power(pd, power_on); + if (err) { + dev_err(pd->dev, + "SMC for power domain %s %sable failed: %d\n", + domain->name, power_on ? "en" : "dis", err); + return err; + } + } return err; } @@ -99,6 +146,7 @@ static const struct exynos_pm_domain_config exynos5433_cfg = { static const struct exynos_pm_domain_config gs101_cfg = { .local_pwr_cfg = BIT(0), + .smc_offset = 0x0204, .use_parent_regmap = true, }; @@ -126,6 +174,38 @@ static const char *exynos_get_domain_name(struct device *dev, return devm_kstrdup_const(dev, name, GFP_KERNEL); } +static int exynos_pd_get_access_controller(struct exynos_pm_domain *pd) +{ + struct device_node *ac_np; + struct resource ac_res; + int ret; + + ac_np = of_parse_phandle(pd->dev->of_node, "samsung,dtzpc", 0); + if (!ac_np) + return 0; + + ret = of_address_to_resource(ac_np, 0, &ac_res); + of_node_put(ac_np); + if (ret) + return dev_err_probe(pd->dev, ret, + "failed to get access controller\n"); + + pd->ac_pa = ac_res.start; + + /* + * For some domains, TZ save/restore might not be implemented. If that + * is the case, simply mark it as always on, as otherwise a power cycle + * will lead to lost TZ configuration, making it impossible to access + * registers from Linux afterwards. + */ + if (exynos_pd_access_controller_power(pd, false) == -ENOENT) { + pd->ac_pa = 0; + pd->pd.flags |= GENPD_FLAG_ALWAYS_ON; + } + + return 0; +} + static int exynos_pd_probe(struct platform_device *pdev) { const struct exynos_pm_domain_config *pm_domain_cfg; @@ -195,10 +275,14 @@ static int exynos_pd_probe(struct platform_device *pdev) pd->pd.power_off = exynos_pd_power_off; pd->pd.power_on = exynos_pd_power_on; - pd->local_pwr_cfg = pm_domain_cfg->local_pwr_cfg; + pd->cfg = pm_domain_cfg; pd->configuration_reg += 0; pd->status_reg += 4; + ret = exynos_pd_get_access_controller(pd); + if (ret) + return ret; + /* * Some Samsung platforms with bootloaders turning on the splash-screen * and handing it over to the kernel, requires the power-domains to be @@ -212,7 +296,7 @@ static int exynos_pd_probe(struct platform_device *pdev) if (ret) return dev_err_probe(dev, ret, "failed to read status"); - on = val & pd->local_pwr_cfg; + on = val & pd->cfg->local_pwr_cfg; pm_genpd_init(&pd->pd, NULL, !on); ret = of_genpd_add_provider_simple(np, &pd->pd); -- 2.53.0.473.g4a7958ca14-goog