From patchwork Mon Aug 3 18:07:53 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Juan_Manuel_L=C3=B3pez_Carrillo?= X-Patchwork-Id: 2934 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id 3BA1F1C0839 for ; Mon, 3 Aug 2026 20:27:12 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-25003-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-25003-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id C460432FF036 for ; Mon, 3 Aug 2026 18:10:25 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8B7D843801F; Mon, 3 Aug 2026 18:08:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QlKUqYMj" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-wr1-f49.google.com (mail-wr1-f49.google.com [209.85.221.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D821E43231D for ; Mon, 3 Aug 2026 18:08:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785780486; cv=none; b=VHU4dwk1G/QqQTGs/BGpJEfxC+FUDIfzOtoY9iMrMueOQZ/0l5Atz96dx2bxVO0t+EwwzRyG0QXsS2G7JbIt2QzRnlhp88w7McynX2veNWhsbnwrYnqhPsfAqHXrCS7XKcq9whxbqutn17s3iVdIe+q/f0FiKJwFf6dHb9mhGVQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785780486; c=relaxed/simple; bh=dA2uXTgNNR86KHbjxMP39oPXSrapg6wgRAAEbxfVTkA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=GSEyqT9ERYh71oBl128U/1aI6fh+phBTGq7TybU0plB+ejhCAe8a2M529Spy210AGIVvrQy51UQdI0PVcYPfxdlm8je02KJXiuaJqpVilSe4znYqVmjntNHU+GVJPFwcJBBVBxTZYTNhI+K06jbTvG38hleAjZ5WMe/7UoobgsE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=QlKUqYMj; arc=none smtp.client-ip=209.85.221.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wr1-f49.google.com with SMTP id ffacd0b85a97d-47f703a9d05so2241696f8f.0 for ; Mon, 03 Aug 2026 11:08:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785780482; x=1786385282; darn=lists.linux.dev; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=FrlG6RlhnBaNqMMkw4zNAoZMeZEfrMq/GASnuyPUjjg=; b=QlKUqYMjIOQOvEj2wRFfjNw8uPE0JTf0947lzeXkqQfO6c7QUq4/TwpOp9wB7GROZv e0+2HmZ9pcJvuwqKdPLoGyRIngoltzKp4IMIArPZ1TORJTyRv9KjK+VrMBBkRjHC1C8W 9Ic2WAWwHubLdENIMpwzIvoudii/9ZjrmUaWxuLx2sNP3QY/xhbC/sM69FzQlwEwBgmw oS8ZDkPsPdXgtmJC5eB233zXUVrDfXDGtE9+Ol31a5o5b3B6Qhp4ZRAtNDv7GNSYfjjl JjIg+FlhzPYTHn8qBnQJFmWqBvNHZomK0H0SK/ctD2hfLozeP+rN0wfrF3HNkwSNWHxj cr/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785780482; x=1786385282; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=FrlG6RlhnBaNqMMkw4zNAoZMeZEfrMq/GASnuyPUjjg=; b=AOxOlwENg09wxf70JLML36dwKYVDsXe3N8TJq/IfDw54TC3u0tbi2lFvSsgrE5iGwe Aca1z4UpzY1fhWP5xUS6AaBJYp0hbwk9j1mBCMBV3oPDrAlhlmVhAUz4teBaVMR5S+gr MdL0CyRj/3lmSi6JH1xoYbWIEHFIq/WKB9Y6EQ++msQIQO/zq6/Dlf1tHkalwQEsQlvs RQcZbYmWffcNfy81cc51JGxliwfliHUZYcJpoJPuyNoKPUZNGHMPQZ+B9nF2+3mV+/4I g16fXjUWgaIfkMQVgx+dE2zpEEJOFg2uEoGC64jcZAOJAGPlEhfuOpAbhLNywTh9MIf8 UmrQ== X-Forwarded-Encrypted: i=1; AHgh+RrbYx1gHAwr1gkqa6OBY/c5z5LyeOyRChyudLKWYtKStksZqE2r87vgbb6JBbLUP0vdO2C/qJF9HjucTw==@lists.linux.dev X-Gm-Message-State: AOJu0YxyqbOdyfyeGDPynHI1ilGlITXsZqjumC50mGXrI8g5fJzLh78p 2aa7p0E2ZzHWMNIPlQrGR1QzelNx+jl4U7335K79ghAIqu08osgGvvmt X-Gm-Gg: AR+sD10yOMsUxkBKL0FC/1X+d6OxaPrwCeLcpixHynJ0itiOZuibcFhpt2IdN3G2tVJ ya0BC8wv9bsZz9YBzfTBQre06lQAkPufKsEv1PSo0PjA9PraDFmA4JoWHZRlV+022IkP2A/BMHP DLs6znLv8TyKYruQMAaQ28r0SicGiDBAxepn+8hbDMqaR2Muh06r0Fd8WhdaV8hH+qg8ucFx0Q1 WSnfkwZkyFk6XFEWjSpjS2mMF3Z73gyiAKuBaKNvboTLNXj5oZkS0zB/UTnkaIbsjnqHSpsUaeQ SUNX9nqtMzqLcH7vsmeGzwiSTh3B8WWLRMXe3z7JnK6ZDx7nYeGXtuHVtVwlIzELdz6vevq3BbS Opsc6QLQdtlqZ2b1Xh896asB3RIrrSLFXYQN6i/8/cQ2NLUudzUcNp3R/UhXBPmoa5yYYz8kSCW NRJWBxbCYDbaY1Gzc3F5S5bKD6nj62m0eJ83e+iyBmGb1hQhRjkkOP6MjGWGi0HV2qww5g+zWPQ CvRDR4kfCykrLIX5wgm/bc= X-Received: by 2002:a05:6000:2709:b0:474:d7a5:4b7a with SMTP id ffacd0b85a97d-47fd73098d1mr21312162f8f.28.1785780481921; Mon, 03 Aug 2026 11:08:01 -0700 (PDT) Received: from localhost.localdomain ([2a0d:3344:2841:7708:a101:2b8a:f76:a00f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-47fd42d91b3sm37950955f8f.14.2026.08.03.11.07.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Aug 2026 11:08:01 -0700 (PDT) From: =?utf-8?q?Juan_Manuel_L=C3=B3pez_Carrillo?= To: mturquette@baylibre.com, sboyd@kernel.org, wens@kernel.org, jernej.skrabec@gmail.com, samuel@sholland.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org Cc: andre.przywara@arm.com, bmasney@redhat.com, linux-clk@vger.kernel.org, linux-sunxi@lists.linux.dev, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, =?utf-8?q?Juan_Ma?= =?utf-8?q?nuel_L=C3=B3pez_Carrillo?= Subject: [PATCH v2 1/3] clk: sunxi-ng: add cycle-masking divider (maskdiv) clock type Date: Mon, 3 Aug 2026 20:07:53 +0200 Message-ID: <20260803180755.288793-2-juanmanuellopezcarrillo@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260803180755.288793-1-juanmanuellopezcarrillo@gmail.com> References: <20260803180755.288793-1-juanmanuellopezcarrillo@gmail.com> Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= Some mod clocks do not divide their parent with a linear M+1 divider: the M factor masks (swallows) M pulses out of every 2^width parent cycles, so the average output rate is rate = parent * (2^width - M) / 2^width and the surviving pulses keep the parent period. The A523/T527 GPU clock (GPU_CLK_REG, 0x670) is such a divider: "FACTOR_M: mask M cycles at 16 cycles", GPU_CLK = Clock Source * ((16-M)/16) (T527 user manual v0.92, section 2.7.6.58). Modelling these registers with the linear ccu_div type programs a faster clock than requested for every M > 0 (e.g. M=1 on a 800 MHz parent yields 750 MHz, not 400 MHz). Add a small ccu type implementing the masking semantics. Because the masked output is not an even pulse train, determine_rate prefers, among the parents that reach the requested rate, the one needing the least masking, and clamps the result to the request's min_rate/max_rate bounds. set_rate_and_parent follows the same ordering rule as clk_composite_set_rate_and_parent() so no intermediate configuration overshoots both the old and the new rate, and honours the CCU_FEATURE_UPDATE_BIT and CCU_FEATURE_KEY_FIELD features, so the type can be reused on registers that need them. CLK_SET_RATE_PARENT is deliberately not supported: the masking factor and a parent rate change are two independent knobs and picking a combination of both is out of scope for this type. Signed-off-by: Juan Manuel López Carrillo --- drivers/clk/sunxi-ng/Makefile | 1 + drivers/clk/sunxi-ng/ccu_common.h | 3 + drivers/clk/sunxi-ng/ccu_maskdiv.c | 213 +++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu_maskdiv.h | 76 ++++++++++ drivers/clk/sunxi-ng/ccu_mux.c | 2 - 5 files changed, 293 insertions(+), 2 deletions(-) create mode 100644 drivers/clk/sunxi-ng/ccu_maskdiv.c create mode 100644 drivers/clk/sunxi-ng/ccu_maskdiv.h diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index a1c4087d7241..26313083c2f8 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -10,6 +10,7 @@ sunxi-ccu-y += ccu_reset.o # Base clock types sunxi-ccu-y += ccu_div.o sunxi-ccu-y += ccu_frac.o +sunxi-ccu-y += ccu_maskdiv.o sunxi-ccu-y += ccu_gate.o sunxi-ccu-y += ccu_mux.o sunxi-ccu-y += ccu_mult.o diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h index d9dc24ad5503..0260af263d05 100644 --- a/drivers/clk/sunxi-ng/ccu_common.h +++ b/drivers/clk/sunxi-ng/ccu_common.h @@ -29,6 +29,9 @@ /* Some clocks need this bit to actually apply register changes */ #define CCU_SUNXI_UPDATE_BIT BIT(27) +/* Key value for clocks with CCU_FEATURE_KEY_FIELD (reads as zero) */ +#define CCU_MUX_KEY_VALUE 0x16aa0000 + struct device_node; struct ccu_common { diff --git a/drivers/clk/sunxi-ng/ccu_maskdiv.c b/drivers/clk/sunxi-ng/ccu_maskdiv.c new file mode 100644 index 000000000000..4ad49d51405b --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_maskdiv.c @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2026 Juan Manuel López Carrillo + * + * Cycle-masking divider: the M factor masks M pulses out of every + * 2^width parent cycles instead of dividing the parent rate, so + * + * rate = parent * (2^width - M) / 2^width + * + * The masked output is not an even pulse train: the surviving pulses + * keep the parent period. Rate selection therefore prefers, among the + * parents that reach the requested rate, the one needing the least + * masking. + */ + +#include +#include +#include + +#include "ccu_gate.h" +#include "ccu_maskdiv.h" + +static unsigned long ccu_maskdiv_calc_rate(unsigned long parent_rate, + unsigned int m, unsigned int width) +{ + unsigned int n = 1 << width; + + return div_u64((u64)parent_rate * (n - m), n); +} + +/* + * Smallest M (least masking) whose output does not exceed the requested + * rate; masking everything (M == 2^width) is never returned. + */ +static unsigned int ccu_maskdiv_find_m(unsigned long parent_rate, + unsigned long rate, unsigned int width) +{ + unsigned int n = 1 << width; + u64 kept; + + if (!parent_rate || rate >= parent_rate) + return 0; + + kept = div64_ul((u64)rate * n, parent_rate); + if (!kept) + kept = 1; + + return n - (unsigned int)kept; +} + +static void ccu_maskdiv_disable(struct clk_hw *hw) +{ + struct ccu_maskdiv *cmd = hw_to_ccu_maskdiv(hw); + + return ccu_gate_helper_disable(&cmd->common, cmd->enable); +} + +static int ccu_maskdiv_enable(struct clk_hw *hw) +{ + struct ccu_maskdiv *cmd = hw_to_ccu_maskdiv(hw); + + return ccu_gate_helper_enable(&cmd->common, cmd->enable); +} + +static int ccu_maskdiv_is_enabled(struct clk_hw *hw) +{ + struct ccu_maskdiv *cmd = hw_to_ccu_maskdiv(hw); + + return ccu_gate_helper_is_enabled(&cmd->common, cmd->enable); +} + +static unsigned long ccu_maskdiv_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct ccu_maskdiv *cmd = hw_to_ccu_maskdiv(hw); + unsigned int m; + u32 reg; + + reg = readl(cmd->common.base + cmd->common.reg); + m = (reg >> cmd->shift) & ((1 << cmd->width) - 1); + + return ccu_maskdiv_calc_rate(parent_rate, m, cmd->width); +} + +static int ccu_maskdiv_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct ccu_maskdiv *cmd = hw_to_ccu_maskdiv(hw); + unsigned long best_rate = 0, best_parent_rate = 0; + struct clk_hw *best_parent = NULL; + unsigned int best_m = UINT_MAX; + unsigned int i; + + for (i = 0; i < clk_hw_get_num_parents(hw); i++) { + struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i); + unsigned long parent_rate, new_rate; + unsigned int m; + + if (!parent) + continue; + + parent_rate = clk_hw_get_rate(parent); + m = ccu_maskdiv_find_m(parent_rate, req->rate, cmd->width); + new_rate = ccu_maskdiv_calc_rate(parent_rate, m, cmd->width); + + if (new_rate > req->rate) + continue; + + /* + * Reject rates outside the framework's bounds: a maskdiv + * rounds by masking parent cycles, so it can only produce + * sub-multiples of a parent rate; without this check a + * consumer asking for, say, a tight [max_rate, max_rate] + * window would silently get a smaller rate. + */ + if (new_rate < req->min_rate || new_rate > req->max_rate) + continue; + + /* Closest rate first; on ties, the least masking */ + if (new_rate > best_rate || + (new_rate == best_rate && m < best_m)) { + best_rate = new_rate; + best_parent_rate = parent_rate; + best_parent = parent; + best_m = m; + } + } + + if (!best_parent) + return -EINVAL; + + req->best_parent_hw = best_parent; + req->best_parent_rate = best_parent_rate; + req->rate = best_rate; + + return 0; +} + +static int ccu_maskdiv_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct ccu_maskdiv *cmd = hw_to_ccu_maskdiv(hw); + unsigned int m; + unsigned long flags; + u32 reg; + + m = ccu_maskdiv_find_m(parent_rate, rate, cmd->width); + + spin_lock_irqsave(cmd->common.lock, flags); + + reg = readl(cmd->common.base + cmd->common.reg); + reg &= ~GENMASK(cmd->shift + cmd->width - 1, cmd->shift); + if (cmd->common.features & CCU_FEATURE_KEY_FIELD) + reg |= CCU_MUX_KEY_VALUE; + if (cmd->common.features & CCU_FEATURE_UPDATE_BIT) + reg |= CCU_SUNXI_UPDATE_BIT; + writel(reg | (m << cmd->shift), cmd->common.base + cmd->common.reg); + + spin_unlock_irqrestore(cmd->common.lock, flags); + + return 0; +} + +static u8 ccu_maskdiv_get_parent(struct clk_hw *hw) +{ + struct ccu_maskdiv *cmd = hw_to_ccu_maskdiv(hw); + + return ccu_mux_helper_get_parent(&cmd->common, &cmd->mux); +} + +static int ccu_maskdiv_set_parent(struct clk_hw *hw, u8 index) +{ + struct ccu_maskdiv *cmd = hw_to_ccu_maskdiv(hw); + + return ccu_mux_helper_set_parent(&cmd->common, &cmd->mux, index); +} + +static int ccu_maskdiv_set_rate_and_parent(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate, u8 index) +{ + /* + * Same ordering rule as clk_composite_set_rate_and_parent(): if + * switching the mux with the current M would overshoot the + * requested rate, program the divider first, so the + * intermediate rate never exceeds both the old and the new + * rate. + */ + if (ccu_maskdiv_recalc_rate(hw, parent_rate) > rate) { + ccu_maskdiv_set_rate(hw, rate, parent_rate); + ccu_maskdiv_set_parent(hw, index); + } else { + ccu_maskdiv_set_parent(hw, index); + ccu_maskdiv_set_rate(hw, rate, parent_rate); + } + + return 0; +} + +const struct clk_ops ccu_maskdiv_ops = { + .disable = ccu_maskdiv_disable, + .enable = ccu_maskdiv_enable, + .is_enabled = ccu_maskdiv_is_enabled, + + .get_parent = ccu_maskdiv_get_parent, + .set_parent = ccu_maskdiv_set_parent, + + .determine_rate = ccu_maskdiv_determine_rate, + .recalc_rate = ccu_maskdiv_recalc_rate, + .set_rate = ccu_maskdiv_set_rate, + .set_rate_and_parent = ccu_maskdiv_set_rate_and_parent, +}; +EXPORT_SYMBOL_NS_GPL(ccu_maskdiv_ops, "SUNXI_CCU"); diff --git a/drivers/clk/sunxi-ng/ccu_maskdiv.h b/drivers/clk/sunxi-ng/ccu_maskdiv.h new file mode 100644 index 000000000000..e070798f1533 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_maskdiv.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2026 Juan Manuel López Carrillo + */ + +#ifndef _CCU_MASKDIV_H_ +#define _CCU_MASKDIV_H_ + +#include + +#include "ccu_common.h" +#include "ccu_mux.h" + +/* + * struct ccu_maskdiv - cycle-masking ("fractional") divider + * + * This divider does not divide the parent clock: it masks (swallows) M + * pulses out of every 2^width parent cycles, so the average output rate + * is + * + * rate = parent * (2^width - M) / 2^width + * + * with the remaining pulses keeping the parent period. The A523/T527 + * GPU clock (GPU_CLK_REG, 0x670) is such a divider: "FACTOR_M: mask M + * cycles at 16 cycles", GPU_CLK = Clock Source * ((16-M)/16) (T527 user + * manual v0.92, section 2.7.6.58). + * + * This type does not support CLK_SET_RATE_PARENT: determine_rate + * evaluates parents at their current rate and does not propagate rate + * requests upstream. If a future user needs parent rate propagation, + * switch to clk_hw_round_rate() in the determine_rate loop. + * + * @shift: shift of the M field in the register + * @width: width of the M field; the mask window is 2^width cycles + */ +struct ccu_maskdiv { + u32 enable; + + u8 shift; + u8 width; + + struct ccu_mux_internal mux; + struct ccu_common common; +}; + +#define SUNXI_CCU_MASKDIV_HW_WITH_MUX_TABLE_GATE(_struct, _name, \ + _parents, _table, \ + _reg, \ + _mshift, _mwidth, \ + _muxshift, _muxwidth, \ + _gate, _flags) \ + struct ccu_maskdiv _struct = { \ + .enable = _gate, \ + .shift = _mshift, \ + .width = _mwidth, \ + .mux = _SUNXI_CCU_MUX_TABLE(_muxshift, _muxwidth, \ + _table), \ + .common = { \ + .reg = _reg, \ + .hw.init = CLK_HW_INIT_PARENTS_HW(_name, \ + _parents, \ + &ccu_maskdiv_ops, \ + _flags), \ + }, \ + } + +static inline struct ccu_maskdiv *hw_to_ccu_maskdiv(struct clk_hw *hw) +{ + struct ccu_common *common = hw_to_ccu_common(hw); + + return container_of(common, struct ccu_maskdiv, common); +} + +extern const struct clk_ops ccu_maskdiv_ops; + +#endif /* _CCU_MASKDIV_H_ */ diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c index 4503c9780c39..fa1f5fd2a1fd 100644 --- a/drivers/clk/sunxi-ng/ccu_mux.c +++ b/drivers/clk/sunxi-ng/ccu_mux.c @@ -12,8 +12,6 @@ #include "ccu_gate.h" #include "ccu_mux.h" -#define CCU_MUX_KEY_VALUE 0x16aa0000 - static u16 ccu_mux_get_prediv(struct ccu_common *common, struct ccu_mux_internal *cm, int parent_index) From patchwork Mon Aug 3 18:07:54 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Juan_Manuel_L=C3=B3pez_Carrillo?= X-Patchwork-Id: 2933 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from tor.lore.kernel.org (tor.lore.kernel.org [172.105.105.114]) by mxe881.netcup.net (Postfix) with ESMTPS id E9CF91C0244 for ; Mon, 3 Aug 2026 20:17:53 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.105.105.114) smtp.mailfrom=linux-sunxi+bounces-25004-noreply=patchwork.local@lists.linux.dev smtp.helo=tor.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.105.105.114 as permitted sender) client-ip=172.105.105.114; envelope-from=linux-sunxi+bounces-25004-noreply=patchwork.local@lists.linux.dev; helo=tor.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by tor.lore.kernel.org (Postfix) with ESMTP id 525B530DA77B for ; Mon, 3 Aug 2026 18:10:32 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 0F26543847F; Mon, 3 Aug 2026 18:08:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ZqtMslQ8" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-wr1-f53.google.com (mail-wr1-f53.google.com [209.85.221.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DAA28438011 for ; Mon, 3 Aug 2026 18:08:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785780487; cv=none; b=Zah3UwtZ5Ug0v+iVFeJ4Jt6tq0XOtPPd265tLlJkHDNDltCcNC1lSJBnt6IFqn1K0WhuF83My0WsLUHzjs3MC0Vu1tbn6CqNFa8ymDisadgMji+2GqnzYA842OQ1N2YHTvoV6AE//MWCmQADlO/oJNOnQJeuUw4iLto8/6oXTEM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785780487; c=relaxed/simple; bh=oiNY1UIn6YQNbReVM+ZIKN2X4hpTZ/t+jCzScRipcW8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=EgBtyUyI2zOcq2DEknFehX1G8Cv0s1VZkxhhEucgnGzVgaD2b0U96XQL8wlNwAK37S+b3u7RY18+CU0KxY2ltYTqn8iGG9HxD0Ug4qGa/g9N6szXmrzc20QJ9GjE87azdNIvlRIoOGux4nO1FIrw2OF71lg3LPOiHyrL7ag7tug= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ZqtMslQ8; arc=none smtp.client-ip=209.85.221.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wr1-f53.google.com with SMTP id ffacd0b85a97d-4798bea72f9so2654261f8f.1 for ; Mon, 03 Aug 2026 11:08:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785780484; x=1786385284; darn=lists.linux.dev; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=+eQVck/8/EmRztvhd8Uz87RWfrINzUZUMP2w+5sPTpA=; b=ZqtMslQ8IS4piYx6GTQZhh51FIurvwhMJnTdFheKepP9PqZcV0rmrrXlB+4YjjkRvn lYPpRizaoD9UTr3S0TCQmh7Qjcan09G1t4N8fYqOVDIvJzlc2EsdGdzE5+PHg/dAT25Y YV3tQVaSjmKHYaOjZc6LsJr/WOLG5liQpVKsQ8GVKWTWrEgfZuEW9plACnfIzOuVknfS 9d1StdgXwh4Z7LxtoELZus6c8jJNmEFTlBvtWFv3sKvTnOtGAqHo49B3g8XG5sbC6JHH VzLXimwkQMURHne2ZqTYqPZ92x7uuDgOehZDbXgD/sJZJOse0fsH0eUgZ21ODPAfzSMw 5sCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785780484; x=1786385284; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=+eQVck/8/EmRztvhd8Uz87RWfrINzUZUMP2w+5sPTpA=; b=JM1EsI4RZ6gEBZIx1vkWED0v0Hjb7R89Fu1IYhl+N/2yTsFhNL4AGujKmzZ59l/vJM IDotj2ZxGXre4BpYBESWzqKwlS1s96a8qdrRBtQ7/1kw1A7EnedJOxEXS7je491TQB7X ysNr94k3cUcIeipLt6b+ITDdAt+nhThNJOJFAI1y9KHnBoRe2NcSWdMPAt2Qf0SDqywq COtoOoMFa9/kEpFSALEThAOryw3N+EONHnfwWKcBMMRQ2wtE095bgmkCeXJU+ItQRwy1 TK0OuNTRkPDb5jvFTVHbSh8iQUVOHrrgj+G76o7HuuEhPgCUYYUEEtDvLNM7tGqh7731 OloQ== X-Forwarded-Encrypted: i=1; AHgh+RoeeulK6Z5oJPPLxmBbN1W/pXLMmEA/7+OR6FAGaXeLtVlK0Cir/5Nhlud6KJiXfLc87p7qdrcfpObILw==@lists.linux.dev X-Gm-Message-State: AOJu0Ywxk7tqa68TdIAUKFjTgVmtEDpZgxHXVzH2Yma7mD49q4gqDE// LYwOGC9lRhPND1fH3rzUu7wT3iBhLM6oFvUQyshu7dk1ujrnsRI7uSL+ X-Gm-Gg: AR+sD106MbuxVeXw9KG6jkiLM67cD0RfoeQRxhBCtdfCVf6LiNlEoxG66ugH7OZ2q/Y R9JZOUb8Rzu+hefFM1oe8nqVFmClgh6maaxID1qGyRSSuSMBd0hxPZEKjwaX2pcc7F3Ks3712Kb IWi7xpvE6SJWkSdeGjIXllB7tzFuc1tqeMHMno8I0U9CBUwHIrk7SL+tYUYmSETYRMekIZSrclA IJEZtbTqpBGMxrHzNDlD9i4vQ6Gg8+5lIAWcYTCTMVD12ulG43CDrChDwe8pHiYWMnDNX/IC0E5 2kIpgAEEvdWL3+lPZqxy3vDIoUiCY7DlpWCO4/LavBcvCViecxbULXWJmo3EzZHyDnBVYPe4qlu o5d/tR0cxTIk5eVuefqymwl5SQK8raFaUdC4C/QgCTrKZqjDdL3ahQeuaLhE0UKiVEmoR2RoUtI UVM2B4Dp8T+CZY75Xt/lahr6wL3glTWbwzE4Z/dqxEwtSbyAzogB4zXoWF8rbez5PhIAQ8bzRwg 5RkFbI5qu9aAl1MAtb19JaI X-Received: by 2002:adf:e90f:0:b0:47f:9d0e:f8f with SMTP id ffacd0b85a97d-47fd72e6079mr24242189f8f.26.1785780483886; Mon, 03 Aug 2026 11:08:03 -0700 (PDT) Received: from localhost.localdomain ([2a0d:3344:2841:7708:a101:2b8a:f76:a00f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-47fd42d91b3sm37950955f8f.14.2026.08.03.11.08.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Aug 2026 11:08:03 -0700 (PDT) From: =?utf-8?q?Juan_Manuel_L=C3=B3pez_Carrillo?= To: mturquette@baylibre.com, sboyd@kernel.org, wens@kernel.org, jernej.skrabec@gmail.com, samuel@sholland.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org Cc: andre.przywara@arm.com, bmasney@redhat.com, linux-clk@vger.kernel.org, linux-sunxi@lists.linux.dev, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, =?utf-8?q?Juan_Ma?= =?utf-8?q?nuel_L=C3=B3pez_Carrillo?= Subject: [PATCH v2 2/3] clk: sunxi-ng: sun55i-a523: GPU clock divider is fractional, not linear Date: Mon, 3 Aug 2026 20:07:54 +0200 Message-ID: <20260803180755.288793-3-juanmanuellopezcarrillo@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260803180755.288793-1-juanmanuellopezcarrillo@gmail.com> References: <20260803180755.288793-1-juanmanuellopezcarrillo@gmail.com> Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= The GPU mod clock (0x670) was modelled as a linear M+1 divider, but the M factor of this register is a cycle-masking divider: GPU_CLK = Clock Source * ((16-M)/16) (T527 user manual v0.92, section 2.7.6.58). With the linear model every OPP that needed M > 0 silently ran the GPU faster than requested. Measured on an Orange Pi 4A (T527) with the Mali cycle counter against the programmed register: OPP request programmed real rate 150 MHz 600M, M=3 487.5 MHz 200 MHz 800M, M=3 650 MHz 300 MHz 600M, M=1 562.5 MHz 400 MHz 800M, M=1 750 MHz 600 MHz 600M, M=0 600 MHz i.e. the "400 MHz" OPP ran the GPU at 750 MHz, 25% above the vendor ceiling of 600 MHz, at the low-OPP voltage. Thermal throttling to "400 MHz" actually overclocked the GPU. Switch the clock to the maskdiv type. With least-masking preference the vendor OPP set now resolves to 600/400/300/200 MHz taken undivided from their periph outputs and 150 MHz = pll-periph0-200M * 12/16, all verified exact on hardware with the same cycle-counter method. Drop pll-periph0-800M from the selectable parents (the mux table skips hardware index 1): the vendor BSP removed it from its parent list with the comment "If GPU use pll-peri0-800m, gpu will occur job fault", and with the masking semantics every vendor OPP matches exactly from the 800M parent first, so it would otherwise always be chosen. Also drop CLK_SET_RATE_PARENT: every OPP is reachable from the fixed pll-periph0 outputs, and pll-gpu must never be reprogrammed through this mux. Once the GPU moves off pll-gpu the PLL is no longer prepared, so it loses the rate protection of CLK_SET_RATE_GATE; a propagated rate request would then reprogram the PLL while its gate is off (the lock bit never asserts, 70 ms poll timeout per transition) and switch the running GPU onto it before it locks. Fixes: 6702d17f54a8 ("clk: sunxi-ng: a523: add video mod clocks") Signed-off-by: Juan Manuel López Carrillo --- drivers/clk/sunxi-ng/ccu-sun55i-a523.c | 32 +++++++++++++++++++++----- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c index 20dad06b37ca..979e53e63522 100644 --- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c +++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c @@ -21,6 +21,7 @@ #include "ccu_div.h" #include "ccu_gate.h" +#include "ccu_maskdiv.h" #include "ccu_mp.h" #include "ccu_mult.h" #include "ccu_nk.h" @@ -442,18 +443,37 @@ static SUNXI_CCU_GATE_HWS(bus_g2d_clk, "bus-g2d", ahb_hws, 0x63c, BIT(0), 0); static const struct clk_hw *gpu_parents[] = { &pll_gpu_clk.common.hw, - &pll_periph0_800M_clk.common.hw, &pll_periph0_600M_clk.hw, &pll_periph0_400M_clk.hw, &pll_periph0_300M_clk.hw, &pll_periph0_200M_clk.hw, }; -static SUNXI_CCU_M_HW_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670, - 0, 4, /* M */ - 24, 3, /* mux */ - BIT(31), /* gate */ - CLK_SET_RATE_PARENT); +/* + * Mux index 1 (pll-periph0-800M) is skipped: the vendor BSP removed it + * from the parent list ("If GPU use pll-peri0-800m, gpu will occur job + * fault"), and with the masking divider every OPP would match exactly + * from it first. + */ +static const u8 gpu_mux_table[] = { 0, 2, 3, 4, 5 }; + +/* + * The M factor is a cycle-masking (fractional) divider, not a linear + * one: rate = source * (16 - M) / 16 (T527 manual, GPU_CLK_REG). + * + * No CLK_SET_RATE_PARENT: every GPU OPP is reachable from the fixed + * pll-periph0 outputs, and pll-gpu must never be reprogrammed through this mux. + * Once the GPU moves off pll-gpu the PLL is no longer prepared, so it loses + * the rate protection of CLK_SET_RATE_GATE; a propagated rate request would + * then reprogram the PLL while its gate is off (the lock bit never asserts, + * 70 ms timeout) and switch the running GPU onto it before it locks. + */ +static SUNXI_CCU_MASKDIV_HW_WITH_MUX_TABLE_GATE(gpu_clk, "gpu", gpu_parents, + gpu_mux_table, 0x670, + 0, 4, /* M */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); static SUNXI_CCU_GATE_HWS(bus_gpu_clk, "bus-gpu", ahb_hws, 0x67c, BIT(0), 0); From patchwork Mon Aug 3 18:07:55 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Juan_Manuel_L=C3=B3pez_Carrillo?= X-Patchwork-Id: 2935 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id 49A511C209E for ; Mon, 3 Aug 2026 20:42:54 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-25005-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-25005-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id B9178308E868 for ; Mon, 3 Aug 2026 18:10:37 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 4F53B438FED; Mon, 3 Aug 2026 18:08:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="GtJwR/Oe" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-wr1-f42.google.com (mail-wr1-f42.google.com [209.85.221.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B625A438033 for ; Mon, 3 Aug 2026 18:08:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785780489; cv=none; b=GY0trAyymvgnKj5mIryEKGBW2mvshUE61PM/oJ6FaoO0pmbSR+TuStzk28joAMN1VDJv2pP40XqwjyN59lju4KPjOcpiBv4qCC9Ev63NKjb45bbIP7QyrHDbu2ET8bMWhmQzITzJ0PXC45ibTUOxDkA0OUV0sKffzsHm9tr5dE8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785780489; c=relaxed/simple; bh=PVzzc9du/j/IIUtVI0EpD2qkwZbInKS9/yBMHMA5D4g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=U14aHZoArNkEoKLAM3qrTyl8d8FqbqPmo2gONqm0MOcSEfay4E51szO/vyzaMwqbNmpRdR0/kpv1rFcc9iojZtvtiYhyayxZ+LAkbndOhS2BH3rwNJiHnyzCFj0E06lrEhzFj++Px7IYgUc30bsEtUL5Suw0NlHFE95+im4ZiYs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=GtJwR/Oe; arc=none smtp.client-ip=209.85.221.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wr1-f42.google.com with SMTP id ffacd0b85a97d-47f703a9e5dso1871718f8f.0 for ; Mon, 03 Aug 2026 11:08:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785780486; x=1786385286; darn=lists.linux.dev; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=6BWR8dmRaEKQHkFK66ev0gVEIwNsNYFwR9W/SfWvzP8=; b=GtJwR/OeIQ9Y4K+/Gol+UU7qKHlQwjNb3zyWi/I4GF5ctQbmwdCKfdAoJ4Gxr20oYG bYo4yTmpE919XxKGkKoDKAY3d29nIUbgk8y0IzxnWA6J7/oS9r1uyctVGc5Gx/cFzhpu lGww94T637QkGzO/KTCGbST3gtj0r6f4WstsQ9R6SjBG4lsrTV9L50e/lVuVNOrcq8GH OhXDbRpROm4BDAo9ME7PYFaYf4DgvcN9seUYYdphlKddBozEP0VWMp0212o/UHz51JUD AOk4IHYHb0UywPcIZzr/chQaC0ym1ChrbL5G2njBeTabl5Nl4GtBVNT5P9LtAejdbxjt C4HA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785780486; x=1786385286; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=6BWR8dmRaEKQHkFK66ev0gVEIwNsNYFwR9W/SfWvzP8=; b=gr39ZlulvsPNEPN3tMtIOw7Utq0GJGTRroJeWhUmweb/wOmiRCAaZMH1KCMvF/AKhY jdrYe7Yabj2NMRnVe+VYFxP4nplzE8n7Z/3hKiHxgxpX9WjxN9CmZxsPdYphss9rDwRf DGIIujlqKAVwb8S0MS5vkwt1O+6u6lfU/soh2FN9u0uL83R0ypFRoCA4oEo8ZYutRGrq BEzfehTJ6ryGFLTy+uUigo5dWchkOjGqDb6jCg/76m44LmNmwTqS1l1tH1d9cmREurJB 3xLaN9hkfGIZfrjvGZTXAeiq+gvYAjxBijY1S2tg6ttLNpEXH/98cpfCYnHP3vVC+Hvx F51g== X-Forwarded-Encrypted: i=1; AHgh+Rr/oX3DO322I3t8AlnXuSRg/V7VQ5keGLkULfTgrG8rSkdMApnsaqnGhbFpp1vDngD5WcEvpMtCowBERQ==@lists.linux.dev X-Gm-Message-State: AOJu0Yw66IQFSvKtAKSeZj72M3H4nHPD71rHwG+J62D9UVyMoYtZaCRb PkNwgHXTRnr94QaQ9tjeVT2HTRrLlm9SqlEHwmJYF/1qITqCbNEN5cW1 X-Gm-Gg: AR+sD12ZEuMMKXX8ScimroV4BoxMGVBdHDo7gOaqOqdgsJTaT1zJ3C9/dPSlE0WcYmj QDM/QJhN0PyDuF+nMTVc9ECMQQorsU1VjFne843Gs7NYBiqQCm5ePl2noasXdno+Y0Qnr6b82qY zTRDAlboBkE8eoVo3jcPe5IQZNVHhlQSKtJF/RAcVEsAXufmlv3xmkdfnyj3GUwBzSMje917jlq Q1E/4vQkk/hbSaov7wlOdjaw7LLB/XXOPWeaDtyvi1mAmlSsIdKzzdZB9wRvF4bWxwrZuZqJycV JCmgEPjqkw4NltQpj3epnlM+8yZ1D5fKiq1Aq63zum5CaU8K/vjlqMhy7xBsGqDntmAB8rSYZI2 wqZCOf+zE9HtVAhY3thlrto47ZyjyiG+BTd+hPGuF8fpWvLS4mFgXm2jSue1OtYF4Eb26VusAXB 8pqN8HrvdgKkWPse6Bt2lIAKlhJn3CAKqxaKOASGM03UBx2pG9IqvfTL82Thh0kVxmWRBQFbXQh GYWeYNz3cifUboZaLhm7kNu X-Received: by 2002:a5d:59c8:0:b0:47f:9404:5185 with SMTP id ffacd0b85a97d-47fd72c78ebmr26973780f8f.24.1785780485932; Mon, 03 Aug 2026 11:08:05 -0700 (PDT) Received: from localhost.localdomain ([2a0d:3344:2841:7708:a101:2b8a:f76:a00f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-47fd42d91b3sm37950955f8f.14.2026.08.03.11.08.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Aug 2026 11:08:05 -0700 (PDT) From: =?utf-8?q?Juan_Manuel_L=C3=B3pez_Carrillo?= To: mturquette@baylibre.com, sboyd@kernel.org, wens@kernel.org, jernej.skrabec@gmail.com, samuel@sholland.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org Cc: andre.przywara@arm.com, bmasney@redhat.com, linux-clk@vger.kernel.org, linux-sunxi@lists.linux.dev, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, =?utf-8?q?Juan_Ma?= =?utf-8?q?nuel_L=C3=B3pez_Carrillo?= Subject: [PATCH v2 3/3] arm64: dts: allwinner: a523: add GPU OPP table Date: Mon, 3 Aug 2026 20:07:55 +0200 Message-ID: <20260803180755.288793-4-juanmanuellopezcarrillo@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260803180755.288793-1-juanmanuellopezcarrillo@gmail.com> References: <20260803180755.288793-1-juanmanuellopezcarrillo@gmail.com> Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [-0.16 / 15.00]; BAYES_HAM(-5.50)[100.00%]; RBL_SENDERSCORE(2.00)[172.234.253.10:from]; SUSPICIOUS_RECIPS(1.50)[]; MID_CONTAINS_FROM(1.00)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; MIME_GOOD(-0.10)[text/plain]; BAD_REP_POLICIES(0.10)[]; HAS_LIST_UNSUB(-0.01)[]; RCPT_COUNT_TWELVE(0.00)[16]; TAGGED_RCPT(0.00)[dt]; FREEMAIL_FROM(0.00)[gmail.com]; TO_DN_SOME(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[0.27.119.64:email,sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo]; FORGED_SENDER_MAILLIST(0.00)[]; FREEMAIL_CC(0.00)[arm.com,redhat.com,vger.kernel.org,lists.linux.dev,lists.infradead.org,gmail.com]; FREEMAIL_TO(0.00)[baylibre.com,kernel.org,gmail.com,sholland.org]; PRECEDENCE_BULK(0.00)[]; R_SPF_ALLOW(0.00)[+ip4:172.234.253.10]; RCVD_TLS_LAST(0.00)[]; MIME_TRACE(0.00)[0:+]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; FROM_HAS_DN(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; TAGGED_FROM(0.00)[bounces-25005-noreply=patchwork.local]; ASN(0.00)[asn:63949, ipnet:172.234.224.0/19, country:SG]; RCVD_COUNT_FIVE(0.00)[6]; FROM_NEQ_ENVFROM(0.00)[juanmanuellopezcarrillo@gmail.com,linux-sunxi@lists.linux.dev]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: 49A511C209E X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= Add the Mali-G57 operating points from the vendor BSP universal table (150/200/300/400/600 MHz) so panfrost devfreq can scale the GPU instead of running at the boot clock. The table describes the SoC rather than any particular board, so it lives in the .dtsi and is referenced from the GPU node there; every A523/T527 board in tree already provides mali-supply. The BSP universal table specifies 900 mV for all of these operating points, so that is the target and minimum voltage. The maximum is set to 920 mV to also cover boards whose GPU rail is a fixed 920 mV supply (the Orange Pi 4A drives it from AXP717 DCDC2, fixed at 920 mV), where the voltage transitions are then no-ops. The higher speed-bin points of the BSP (648-792 MHz) are not included: they are gated by a SID efuse bin and need pll-gpu as a live parent. Depends on the sun55i-a523 GPU clock divider fix: the OPP rates are only produced correctly with the cycle-masking divider model. Validated on hardware with the Mali cycle counter: 149/199/300/399/597 MHz measured under load, thermal-emulation throttling included. Signed-off-by: Juan Manuel López Carrillo --- .../arm64/boot/dts/allwinner/sun55i-a523.dtsi | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi index 85ef492ffeae..a3164b5dd609 100644 --- a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi @@ -85,6 +85,35 @@ osc24M: osc24M-clk { clock-output-names = "osc24M"; }; + gpu_opp_table: opp-table-gpu { + compatible = "operating-points-v2"; + + opp-150000000 { + opp-hz = /bits/ 64 <150000000>; + opp-microvolt = <900000 900000 920000>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + opp-microvolt = <900000 900000 920000>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + opp-microvolt = <900000 900000 920000>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + opp-microvolt = <900000 900000 920000>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <900000 900000 920000>; + }; + }; + pmu { compatible = "arm,cortex-a55-pmu"; interrupts = ; @@ -121,6 +150,7 @@ gpu: gpu@1800000 { interrupt-names = "job", "mmu", "gpu"; clocks = <&ccu CLK_GPU>, <&ccu CLK_BUS_GPU>; clock-names = "core", "bus"; + operating-points-v2 = <&gpu_opp_table>; power-domains = <&pck600 PD_GPU>; resets = <&ccu RST_BUS_GPU>; status = "disabled";