From: Vinicius Pedrosa <vinicius.eduardo.pedrosa@gmail.com>
To: linusw@kernel.org
Cc: wens@kernel.org, jernej.skrabec@gmail.com, samuel@sholland.org,
andre.przywara@arm.com, linux-gpio@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org
Subject: [PATCH 1/2] pinctrl: sunxi: a733: program the two-bit I/O voltage fields
Date: Mon, 12 Oct 2026 15:41:28 -0300 [thread overview]
Message-ID: <20261012184130.548261-2-vinicius.eduardo.pedrosa@gmail.com> (raw)
In-Reply-To: <20261012184130.548261-1-vinicius.eduardo.pedrosa@gmail.com>
The A733 GPIO_POW_MOD_SEL register has a two-bit field per bank, but
the A733 uses the helper written for one bit per bank, so a request
for one bank can change the field of another one. With the register
as firmware leaves it on a Radxa Cubie A7Z (the fields of PB, PC, PD,
PE, PG, PH, PJ and PK in automatic mode, 0x01155550), a PJ request at
1.8 V turns the PE field into fixed 1.8 V (0x01155750).
Add a variant that takes the field of each bank from a mask table. It
keeps automatic mode and a fixed 3.3 V mode that already fits, and
writes only the field of the requested bank. PF is left out: its field
(11:10) is known, but it is tied to the MMC vqmmc voltage switching.
PI is left out as well, since its supply domain is not documented.
Only silicon revision B, as reported through SMCCC, is programmed,
since the encoding is documented for that revision only.
Computed with both helpers on that register value, the old one changes
it and the new one leaves it as it is.
Fixes: 0535bfbfa97b ("pinctrl: sunxi: add support for the Allwinner A733")
Signed-off-by: Vinicius Pedrosa <vinicius.eduardo.pedrosa@gmail.com>
---
drivers/pinctrl/sunxi/pinctrl-sun60i-a733.c | 15 +++++-
drivers/pinctrl/sunxi/pinctrl-sunxi.c | 57 +++++++++++++++++++++
drivers/pinctrl/sunxi/pinctrl-sunxi.h | 6 +++
3 files changed, 77 insertions(+), 1 deletion(-)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun60i-a733.c b/drivers/pinctrl/sunxi/pinctrl-sun60i-a733.c
index ca82f08a3a65..6f5757b8adea 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun60i-a733.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun60i-a733.c
@@ -21,10 +21,23 @@ static const u8 a733_irq_bank_muxes[SUNXI_PINCTRL_MAX_BANKS] =
/* PA PB PC PD PE PF PG PH PI PJ PK */
{ 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14};
+/* PA is not implemented. PF and PI are left to the firmware, so are not listed. */
+static const u32 a733_io_bias_masks[SUNXI_PINCTRL_MAX_BANKS] = {
+ [1] = GENMASK(25, 24), /* PB, VCC-IO */
+ [2] = GENMASK(5, 4), /* PC */
+ [3] = GENMASK(7, 6), /* PD */
+ [4] = GENMASK(9, 8), /* PE */
+ [6] = GENMASK(13, 12), /* PG */
+ [7] = GENMASK(15, 14), /* PH */
+ [9] = GENMASK(19, 18), /* PJ */
+ [10] = GENMASK(21, 20), /* PK */
+};
+
static struct sunxi_pinctrl_desc a733_pinctrl_data = {
.irq_banks = 10,
.irq_read_needs_mux = true,
- .io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
+ .io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL_2BIT,
+ .io_bias_masks = a733_io_bias_masks,
};
static int a733_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 3ee5012463da..8e62111d3409 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -10,6 +10,8 @@
* warranty of any kind, whether express or implied.
*/
+#include <linux/arm-smccc.h>
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/export.h>
#include <linux/gpio/driver.h>
@@ -722,6 +724,58 @@ static const struct pinconf_ops sunxi_pconf_ops = {
.pin_config_group_set = sunxi_pconf_group_set,
};
+/*
+ * The two-bit encoding is documented for A733 silicon revision B, which
+ * firmware reports through the SMCCC SOC_ID call. Do not assume it for any
+ * other revision, or when the firmware does not tell.
+ */
+#define SUNXI_A733_SOC_ID 0x091e1903
+#define SUNXI_A733_REV_B 1
+
+static bool sunxi_pinctrl_a733_rev_b(void)
+{
+#ifdef CONFIG_HAVE_ARM_SMCCC_DISCOVERY
+ s32 id = arm_smccc_get_soc_id_version();
+
+ /* Bit 23 is the JEP106 parity bit. */
+ return id >= 0 && (id & ~BIT(23)) == SUNXI_A733_SOC_ID &&
+ arm_smccc_get_soc_id_revision() == SUNXI_A733_REV_B;
+#else
+ return false;
+#endif
+}
+
+/*
+ * Fields: 0 and 2 fixed 3.3V, 1 automatic, 3 fixed 1.8V. Leave automatic
+ * mode and any other supply voltage to the firmware, and touch only the
+ * field of this bank.
+ */
+static void sunxi_pinctrl_set_io_bias_2bit(struct sunxi_pinctrl *pctl,
+ unsigned int bank, int uV)
+{
+ u32 mask = pctl->desc->io_bias_masks[bank];
+ unsigned long flags;
+ u32 val, cur, reg;
+
+ if (!mask || !sunxi_pinctrl_a733_rev_b())
+ return;
+
+ if (uV >= 1620000 && uV <= 1980000)
+ val = 3;
+ else if (uV >= 2970000 && uV <= 3630000)
+ val = 2;
+ else
+ return;
+
+ raw_spin_lock_irqsave(&pctl->lock, flags);
+ reg = readl(pctl->membase + pctl->pow_mod_sel_offset);
+ cur = field_get(mask, reg);
+ if (cur != 1 && cur != val && !(val == 2 && cur == 0))
+ writel((reg & ~mask) | field_prep(mask, val),
+ pctl->membase + pctl->pow_mod_sel_offset);
+ raw_spin_unlock_irqrestore(&pctl->lock, flags);
+}
+
static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
unsigned pin,
struct regulator *supply)
@@ -795,6 +849,9 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
pctl->membase + pctl->pow_mod_sel_offset);
raw_spin_unlock_irqrestore(&pctl->lock, flags);
return 0;
+ case BIAS_VOLTAGE_PIO_POW_MODE_SEL_2BIT:
+ sunxi_pinctrl_set_io_bias_2bit(pctl, bank, uV);
+ return 0;
default:
return -EINVAL;
}
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index 7c2f29e75519..c37170b2e4f4 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -130,6 +130,11 @@ enum sunxi_desc_bias_voltage {
*/
BIAS_VOLTAGE_PIO_POW_MODE_CTL,
BIAS_VOLTAGE_PIO_POW_MODE_CTL_INV,
+ /*
+ * Bias voltage is set through two-bit fields in PIO_POW_MOD_SEL_REG,
+ * whose positions are given by io_bias_masks[], as seen on A733.
+ */
+ BIAS_VOLTAGE_PIO_POW_MODE_SEL_2BIT,
};
struct sunxi_desc_function {
@@ -155,6 +160,7 @@ struct sunxi_pinctrl_desc {
bool irq_read_needs_mux;
bool disable_strict_mode;
enum sunxi_desc_bias_voltage io_bias_cfg_variant;
+ const u32 *io_bias_masks;
};
struct sunxi_pinctrl_function {
--
2.43.0
next prev parent reply other threads:[~2026-10-12 18:41 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-12 18:41 [PATCH 0/2] pinctrl: sunxi: A733: use " Vinicius Pedrosa
2026-10-12 18:41 ` Vinicius Pedrosa [this message]
2026-10-13 14:03 ` [PATCH 1/2] pinctrl: sunxi: a733: program " Andre Przywara
2026-10-12 18:41 ` [PATCH 2/2] pinctrl: sunxi: a733-r: use the A733 " Vinicius Pedrosa
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261012184130.548261-2-vinicius.eduardo.pedrosa@gmail.com \
--to=vinicius.eduardo.pedrosa@gmail.com \
--cc=andre.przywara@arm.com \
--cc=jernej.skrabec@gmail.com \
--cc=linusw@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sunxi@lists.linux.dev \
--cc=samuel@sholland.org \
--cc=wens@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®