From patchwork Mon Mar 18 01:12:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 13594940 X-Patchwork-Delegate: viresh.linux@gmail.com Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id EA300168C7; Mon, 18 Mar 2024 01:13:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710724389; cv=none; b=NHK6Ua6pddRIofX0afe8eTyyD6zyhzK1MhbK6fBDYS2yrhk+17JnauYPjEfG6I7Q5yTRU9obg8Ev/4Vb+X7P1liZ3QNCbD2dH8M2ZPa5/iXYSNMLgnyS4Yz2q/rQG7V18Mp4o6qocaqtY1G/+vH26FW61ZFiL1ze1ZQrZF498fE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710724389; c=relaxed/simple; bh=ecrX/U3x8eoES7yGJRH8+HCGP3ruxSQbzWfeB5XCjqM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=pQ8OygK8sLkyOWH3/KKn6DWldreL2XRqSs5eDGAUbam/gvRRlr6q0qLdjox18YH6SxtpeMhwwZqIIZhypTu6Typ5xuNsXP4BT92GwVV+Jaz8+2TDdLy4qikMkphrDBGpjAIqhwRRx1ooS+gCrTM4f6eJUk+TmMwT1WZq/tFVdx8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id EBDCF14BF; Sun, 17 Mar 2024 18:13:41 -0700 (PDT) Received: from localhost.localdomain (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id C6D653F23F; Sun, 17 Mar 2024 18:13:04 -0700 (PDT) From: Andre Przywara To: Yangtao Li , Viresh Kumar , Nishanth Menon , Stephen Boyd , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , "Rafael J . Wysocki" Cc: linux-pm@vger.kernel.org, devicetree@vger.kernel.org, linux-sunxi@lists.linux.dev, linux-arm-kernel@lists.infradead.org, Brandon Cheo Fusi , Martin Botka , Martin Botka Subject: [PATCH v2 4/8] cpufreq: sun50i: Refactor speed bin decoding Date: Mon, 18 Mar 2024 01:12:24 +0000 Message-Id: <20240318011228.2626-5-andre.przywara@arm.com> X-Mailer: git-send-email 2.35.8 In-Reply-To: <20240318011228.2626-1-andre.przywara@arm.com> References: <20240318011228.2626-1-andre.przywara@arm.com> Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Brandon Cheo Fusi Make converting the speed bin value into a speed grade generic and determined by a platform specific callback. Also change the prototypes involved to encode the speed bin directly in the return value. This allows to extend the driver more easily to support more SoCs. Signed-off-by: Brandon Cheo Fusi [Andre: merge output into return value] Signed-off-by: Andre Przywara --- drivers/cpufreq/sun50i-cpufreq-nvmem.c | 74 +++++++++++++++++--------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c index 32a9c88f8ff6d..7b44f3b13e7d2 100644 --- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c +++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c @@ -25,19 +25,52 @@ static struct platform_device *cpufreq_dt_pdev, *sun50i_cpufreq_pdev; +struct sunxi_cpufreq_data { + u32 (*efuse_xlate)(u32 speedbin); +}; + +static u32 sun50i_h6_efuse_xlate(u32 speedbin) +{ + u32 efuse_value; + + efuse_value = (speedbin >> NVMEM_SHIFT) & NVMEM_MASK; + + /* + * We treat unexpected efuse values as if the SoC was from + * the slowest bin. Expected efuse values are 1-3, slowest + * to fastest. + */ + if (efuse_value >= 1 && efuse_value <= 3) + return efuse_value - 1; + else + return 0; +} + +static struct sunxi_cpufreq_data sun50i_h6_cpufreq_data = { + .efuse_xlate = sun50i_h6_efuse_xlate, +}; + +static const struct of_device_id cpu_opp_match_list[] = { + { .compatible = "allwinner,sun50i-h6-operating-points", + .data = &sun50i_h6_cpufreq_data, + }, + {} +}; + /** * sun50i_cpufreq_get_efuse() - Determine speed grade from efuse value - * @versions: Set to the value parsed from efuse * - * Returns 0 if success. + * Returns non-negative speed bin index on success, a negative error + * value otherwise. */ -static int sun50i_cpufreq_get_efuse(u32 *versions) +static int sun50i_cpufreq_get_efuse(void) { struct nvmem_cell *speedbin_nvmem; struct device_node *np; struct device *cpu_dev; - u32 *speedbin, efuse_value; - size_t len; + const struct of_device_id *match; + const struct sunxi_cpufreq_data *opp_data; + u32 *speedbin; int ret; cpu_dev = get_cpu_device(0); @@ -48,12 +81,12 @@ static int sun50i_cpufreq_get_efuse(u32 *versions) if (!np) return -ENOENT; - ret = of_device_is_compatible(np, - "allwinner,sun50i-h6-operating-points"); - if (!ret) { + match = of_match_node(cpu_opp_match_list, np); + if (!match) { of_node_put(np); return -ENOENT; } + opp_data = match->data; speedbin_nvmem = of_nvmem_cell_get(np, NULL); of_node_put(np); @@ -61,25 +94,16 @@ static int sun50i_cpufreq_get_efuse(u32 *versions) return dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem), "Could not get nvmem cell\n"); - speedbin = nvmem_cell_read(speedbin_nvmem, &len); + speedbin = nvmem_cell_read(speedbin_nvmem, NULL); nvmem_cell_put(speedbin_nvmem); if (IS_ERR(speedbin)) return PTR_ERR(speedbin); - efuse_value = (*speedbin >> NVMEM_SHIFT) & NVMEM_MASK; - - /* - * We treat unexpected efuse values as if the SoC was from - * the slowest bin. Expected efuse values are 1-3, slowest - * to fastest. - */ - if (efuse_value >= 1 && efuse_value <= 3) - *versions = efuse_value - 1; - else - *versions = 0; + ret = opp_data->efuse_xlate(*speedbin); kfree(speedbin); - return 0; + + return ret; }; static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev) @@ -87,7 +111,7 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev) int *opp_tokens; char name[MAX_NAME_LEN]; unsigned int cpu; - u32 speed = 0; + int speed; int ret; opp_tokens = kcalloc(num_possible_cpus(), sizeof(*opp_tokens), @@ -95,10 +119,10 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev) if (!opp_tokens) return -ENOMEM; - ret = sun50i_cpufreq_get_efuse(&speed); - if (ret) { + speed = sun50i_cpufreq_get_efuse(); + if (speed < 0) { kfree(opp_tokens); - return ret; + return speed; } snprintf(name, MAX_NAME_LEN, "speed%d", speed);