* [PATCH 0/7] pinctrl: airoha: add AN7589 support
@ 2026-11-10 17:39 John Crispin
2026-11-10 17:39 ` [PATCH 1/7] pinctrl: airoha: make gpio register layout per SoC John Crispin
` (6 more replies)
0 siblings, 7 replies; 9+ messages in thread
From: John Crispin @ 2026-11-10 17:39 UTC (permalink / raw)
To: Lorenzo Bianconi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Linus Walleij, Bartosz Golaszewski
Cc: Ahmed Naseef, Benjamin Larsson, Christian Marangi, devicetree,
lei.dong, Linqi.zhang, linux-gpio, linux-kernel, linux-mediatek,
mfd, Mikhail Kshevetskiy, Rajeev.kumar, upstream, Weifeng.xu,
zhengping.zhang
The Airoha AN7589 has a GPIO controller like the EN7581 one, with a
third bank for 74 GPIOs in total. Its pin functions are selected
differently: a separate IOMUX block holds a 4 bit mode field per pin,
eight pins per register, and mode 0 makes any pin a GPIO.
The first four patches prepare the shared driver and change nothing
for the SoCs it serves today:
1. The GPIO register layout moves into the match data, so a SoC can
describe more than 64 pins.
2. A function group can carry one IOMUX mode per pin. A SoC
describes its IOMUX in the match data: the width of the mode
field and, from patch 4, the mode that makes a pin a GPIO.
3. The chip SCU becomes optional, as the AN7589 needs none.
4. A pin requested by gpiolib is put into GPIO mode through the
IOMUX, so no per pin gpio function is needed.
Patch 5 adds the bindings for the pin controller and the GPIO system
controller it sits under. Patch 6 moves the GPIO register offsets to
the common header, so the AN7589 data can describe its own register
table, with no functional change. Patch 7 adds the AN7589 pin data.
The series applies to next-20261105 and has no dependencies.
John Crispin (7):
pinctrl: airoha: make gpio register layout per SoC
pinctrl: airoha: add per pin mode field mux
pinctrl: airoha: make the chip SCU optional
pinctrl: airoha: mux a requested GPIO through the IOMUX
dt-bindings: pinctrl: airoha: add AN7589
pinctrl: airoha: move the GPIO register offsets to the common header
pinctrl: airoha: add support of an7589 SoC
.../mfd/airoha,an7589-gpio-sysctl.yaml | 66 ++
.../devicetree/bindings/mfd/syscon.yaml | 1 +
.../pinctrl/airoha,an7589-pinctrl.yaml | 533 +++++++++++++
MAINTAINERS | 3 +
drivers/pinctrl/airoha/Kconfig | 11 +
drivers/pinctrl/airoha/Makefile | 1 +
drivers/pinctrl/airoha/airoha-common.h | 41 +-
drivers/pinctrl/airoha/pinctrl-airoha.c | 119 ++-
drivers/pinctrl/airoha/pinctrl-an7563.c | 1 +
drivers/pinctrl/airoha/pinctrl-an7581.c | 1 +
drivers/pinctrl/airoha/pinctrl-an7583.c | 1 +
drivers/pinctrl/airoha/pinctrl-an7589.c | 721 ++++++++++++++++++
drivers/pinctrl/airoha/pinctrl-en7523.c | 1 +
drivers/pinctrl/airoha/pinctrl-en7528.c | 1 +
14 files changed, 1469 insertions(+), 32 deletions(-)
create mode 100644 Documentation/devicetree/bindings/mfd/airoha,an7589-gpio-sysctl.yaml
create mode 100644 Documentation/devicetree/bindings/pinctrl/airoha,an7589-pinctrl.yaml
create mode 100644 drivers/pinctrl/airoha/pinctrl-an7589.c
base-commit: ddfe51b0a0f5dc9e415cc2c8ad8db17532dd426b
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/7] pinctrl: airoha: make gpio register layout per SoC
2026-11-10 17:39 [PATCH 0/7] pinctrl: airoha: add AN7589 support John Crispin
@ 2026-11-10 17:39 ` John Crispin
2026-11-10 17:39 ` [PATCH 2/7] pinctrl: airoha: add per pin mode field mux John Crispin
` (5 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: John Crispin @ 2026-11-10 17:39 UTC (permalink / raw)
To: Lorenzo Bianconi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Linus Walleij, Bartosz Golaszewski
Cc: Ahmed Naseef, Benjamin Larsson, Christian Marangi, devicetree,
lei.dong, Linqi.zhang, linux-gpio, linux-kernel, linux-mediatek,
mfd, Mikhail Kshevetskiy, Rajeev.kumar, upstream, Weifeng.xu,
zhengping.zhang
The GPIO register layout is fixed to 64 pins in two 32 pin banks and
four 16 pin direction banks. Every SoC uses the single static
airoha_gpiochip_regs and the compile time AIROHA_NUM_PINS.
Move the layout into the match data. The gpiochip register table
carries its own pin count, and the five existing SoCs point at the
shared 64 pin table.
No functional change for the existing SoCs.
Signed-off-by: John Crispin <john@phrozen.org>
---
drivers/pinctrl/airoha/airoha-common.h | 6 +++++-
drivers/pinctrl/airoha/pinctrl-airoha.c | 14 ++++++++------
drivers/pinctrl/airoha/pinctrl-an7563.c | 1 +
drivers/pinctrl/airoha/pinctrl-an7581.c | 1 +
drivers/pinctrl/airoha/pinctrl-an7583.c | 1 +
drivers/pinctrl/airoha/pinctrl-en7523.c | 1 +
drivers/pinctrl/airoha/pinctrl-en7528.c | 1 +
7 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/drivers/pinctrl/airoha/airoha-common.h b/drivers/pinctrl/airoha/airoha-common.h
index 16f7abcdfb83..850e733db15a 100644
--- a/drivers/pinctrl/airoha/airoha-common.h
+++ b/drivers/pinctrl/airoha/airoha-common.h
@@ -89,6 +89,7 @@ struct airoha_pinctrl_conf {
};
struct airoha_gpiochip_regs {
+ unsigned int ngpio;
/* gpio */
const u32 *data;
const u32 *dir;
@@ -99,6 +100,8 @@ struct airoha_gpiochip_regs {
const u32 *edge;
};
+extern const struct airoha_gpiochip_regs airoha_gpiochip_regs_64;
+
struct airoha_pinctrl_confs_info {
const struct airoha_pinctrl_conf *confs;
unsigned int num_confs;
@@ -126,7 +129,7 @@ struct airoha_pinctrl {
struct regmap *regmap;
struct gpio_chip gpiochip;
- struct airoha_gpiochip_regs *gpio_regs;
+ const struct airoha_gpiochip_regs *gpio_regs;
unsigned int num_irq_pins;
};
@@ -134,6 +137,7 @@ struct airoha_pinctrl_match_data {
const char *chip_scu_compatible;
const char *pinctrl_name;
struct module *pinctrl_owner;
+ const struct airoha_gpiochip_regs *gpio_regs;
const struct pinctrl_pin_desc *pins;
const unsigned int num_pins;
const struct pingroup *grps;
diff --git a/drivers/pinctrl/airoha/pinctrl-airoha.c b/drivers/pinctrl/airoha/pinctrl-airoha.c
index 52a768c859b7..b50108826d8d 100644
--- a/drivers/pinctrl/airoha/pinctrl-airoha.c
+++ b/drivers/pinctrl/airoha/pinctrl-airoha.c
@@ -94,7 +94,8 @@ static const u32 irq_edge_regs[] = {
REG_GPIO_INT_EDGE3
};
-static struct airoha_gpiochip_regs airoha_gpiochip_regs = {
+const struct airoha_gpiochip_regs airoha_gpiochip_regs_64 = {
+ .ngpio = AIROHA_NUM_PINS,
.data = gpio_data_regs,
.dir = gpio_dir_regs,
.out = gpio_out_regs,
@@ -102,6 +103,7 @@ static struct airoha_gpiochip_regs airoha_gpiochip_regs = {
.level = irq_level_regs,
.edge = irq_edge_regs,
};
+EXPORT_SYMBOL_GPL(airoha_gpiochip_regs_64);
static int airoha_convert_pin_to_reg_offset(struct pinctrl_dev *pctrl_dev,
struct pinctrl_gpio_range *range,
@@ -207,7 +209,7 @@ static void airoha_irq_unmask(struct irq_data *data)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
struct airoha_pinctrl *pinctrl = gpiochip_get_data(gc);
- struct airoha_gpiochip_regs *gpio_regs = pinctrl->gpio_regs;
+ const struct airoha_gpiochip_regs *gpio_regs = pinctrl->gpio_regs;
u8 offset = data->hwirq % AIROHA_REG_GPIOCTRL_NUM_PIN;
u8 index = data->hwirq / AIROHA_REG_GPIOCTRL_NUM_PIN;
u32 mask = GENMASK(2 * offset + 1, 2 * offset);
@@ -244,7 +246,7 @@ static void airoha_irq_mask(struct irq_data *data)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
struct airoha_pinctrl *pinctrl = gpiochip_get_data(gc);
- struct airoha_gpiochip_regs *gpio_regs = pinctrl->gpio_regs;
+ const struct airoha_gpiochip_regs *gpio_regs = pinctrl->gpio_regs;
u8 offset = data->hwirq % AIROHA_REG_GPIOCTRL_NUM_PIN;
u8 index = data->hwirq / AIROHA_REG_GPIOCTRL_NUM_PIN;
u32 mask = GENMASK(2 * offset + 1, 2 * offset);
@@ -261,7 +263,7 @@ static void airoha_irq_ack(struct irq_data *data)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
struct airoha_pinctrl *pinctrl = gpiochip_get_data(gc);
- struct airoha_gpiochip_regs *gpio_regs = pinctrl->gpio_regs;
+ const struct airoha_gpiochip_regs *gpio_regs = pinctrl->gpio_regs;
u8 offset = data->hwirq % AIROHA_PIN_BANK_SIZE;
u8 index = data->hwirq / AIROHA_PIN_BANK_SIZE;
@@ -379,7 +381,7 @@ static int airoha_pinctrl_add_gpiochip(struct airoha_pinctrl *pinctrl,
gc->set = airoha_gpio_set;
gc->get = airoha_gpio_get;
gc->base = -1;
- gc->ngpio = AIROHA_NUM_PINS;
+ gc->ngpio = pinctrl->gpio_regs->ngpio;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_bad_irq;
@@ -831,7 +833,7 @@ int airoha_pinctrl_probe(struct platform_device *pdev)
pinctrl->desc.pins = data->pins;
pinctrl->desc.npins = data->num_pins;
- pinctrl->gpio_regs = &airoha_gpiochip_regs;
+ pinctrl->gpio_regs = data->gpio_regs;
err = devm_pinctrl_register_and_init(dev, &pinctrl->desc,
pinctrl, &pinctrl->ctrl);
diff --git a/drivers/pinctrl/airoha/pinctrl-an7563.c b/drivers/pinctrl/airoha/pinctrl-an7563.c
index f011c6c9ccce..6a2a307807e3 100644
--- a/drivers/pinctrl/airoha/pinctrl-an7563.c
+++ b/drivers/pinctrl/airoha/pinctrl-an7563.c
@@ -1063,6 +1063,7 @@ static const struct airoha_pinctrl_match_data pinctrl_match_data = {
.chip_scu_compatible = "airoha,en7581-chip-scu",
.pinctrl_name = KBUILD_MODNAME,
.pinctrl_owner = THIS_MODULE,
+ .gpio_regs = &airoha_gpiochip_regs_64,
.pins = pinctrl_pins,
.num_pins = ARRAY_SIZE(pinctrl_pins),
.grps = pinctrl_groups,
diff --git a/drivers/pinctrl/airoha/pinctrl-an7581.c b/drivers/pinctrl/airoha/pinctrl-an7581.c
index bfb777594811..6bec1d44b8a0 100644
--- a/drivers/pinctrl/airoha/pinctrl-an7581.c
+++ b/drivers/pinctrl/airoha/pinctrl-an7581.c
@@ -1435,6 +1435,7 @@ static const struct airoha_pinctrl_match_data pinctrl_match_data = {
.chip_scu_compatible = "airoha,en7581-chip-scu",
.pinctrl_name = KBUILD_MODNAME,
.pinctrl_owner = THIS_MODULE,
+ .gpio_regs = &airoha_gpiochip_regs_64,
.pins = pinctrl_pins,
.num_pins = ARRAY_SIZE(pinctrl_pins),
.grps = pinctrl_groups,
diff --git a/drivers/pinctrl/airoha/pinctrl-an7583.c b/drivers/pinctrl/airoha/pinctrl-an7583.c
index 1cd0f442ddc1..2689bbd9ebba 100644
--- a/drivers/pinctrl/airoha/pinctrl-an7583.c
+++ b/drivers/pinctrl/airoha/pinctrl-an7583.c
@@ -1465,6 +1465,7 @@ static const struct airoha_pinctrl_match_data pinctrl_match_data = {
.chip_scu_compatible = "airoha,en7581-chip-scu",
.pinctrl_name = KBUILD_MODNAME,
.pinctrl_owner = THIS_MODULE,
+ .gpio_regs = &airoha_gpiochip_regs_64,
.pins = pinctrl_pins,
.num_pins = ARRAY_SIZE(pinctrl_pins),
.grps = pinctrl_groups,
diff --git a/drivers/pinctrl/airoha/pinctrl-en7523.c b/drivers/pinctrl/airoha/pinctrl-en7523.c
index b0c5e60f0aeb..1589acef683f 100644
--- a/drivers/pinctrl/airoha/pinctrl-en7523.c
+++ b/drivers/pinctrl/airoha/pinctrl-en7523.c
@@ -1107,6 +1107,7 @@ static const struct airoha_pinctrl_match_data pinctrl_match_data = {
.chip_scu_compatible = "airoha,en7523-chip-scu",
.pinctrl_name = KBUILD_MODNAME,
.pinctrl_owner = THIS_MODULE,
+ .gpio_regs = &airoha_gpiochip_regs_64,
.pins = pinctrl_pins,
.num_pins = ARRAY_SIZE(pinctrl_pins),
.grps = pinctrl_groups,
diff --git a/drivers/pinctrl/airoha/pinctrl-en7528.c b/drivers/pinctrl/airoha/pinctrl-en7528.c
index f6c8f834421f..9854e9530219 100644
--- a/drivers/pinctrl/airoha/pinctrl-en7528.c
+++ b/drivers/pinctrl/airoha/pinctrl-en7528.c
@@ -1155,6 +1155,7 @@ static const struct airoha_pinctrl_match_data pinctrl_match_data = {
.chip_scu_compatible = "econet,en7528-chip-scu",
.pinctrl_name = KBUILD_MODNAME,
.pinctrl_owner = THIS_MODULE,
+ .gpio_regs = &airoha_gpiochip_regs_64,
.pins = pinctrl_pins,
.num_pins = ARRAY_SIZE(pinctrl_pins),
.grps = pinctrl_groups,
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/7] pinctrl: airoha: add per pin mode field mux
2026-11-10 17:39 [PATCH 0/7] pinctrl: airoha: add AN7589 support John Crispin
2026-11-10 17:39 ` [PATCH 1/7] pinctrl: airoha: make gpio register layout per SoC John Crispin
@ 2026-11-10 17:39 ` John Crispin
2026-11-10 17:39 ` [PATCH 3/7] pinctrl: airoha: make the chip SCU optional John Crispin
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: John Crispin @ 2026-11-10 17:39 UTC (permalink / raw)
To: Lorenzo Bianconi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Linus Walleij, Bartosz Golaszewski
Cc: Ahmed Naseef, Benjamin Larsson, Christian Marangi, devicetree,
lei.dong, Linqi.zhang, linux-gpio, linux-kernel, linux-mediatek,
mfd, Mikhail Kshevetskiy, Rajeev.kumar, upstream, Weifeng.xu,
zhengping.zhang
Newer Airoha SoCs select the function of a pin through a mode field in
a dedicated IOMUX block instead of through function specific bits in
the chip SCU. The AN7589 has a 4 bit field per pin, eight pins per 32
bit register. A group can then need one register write per pin, and
the two entry regmap[] of a function group cannot carry that.
Let a function group supply a pin_modes[] array, parallel to the pins
of the group. When it is set, set_mux writes each mode into the IOMUX
regmap and then applies the regmap[] entries of the group, so a group
can combine its pin modes with a register write in the GPIO block.
A SoC with an IOMUX describes it in its match data with struct
airoha_pinctrl_iomux, which holds the width of the mode field. Probe
then takes the regmap from the airoha,iomux phandle.
No functional change for the existing SoCs.
Signed-off-by: John Crispin <john@phrozen.org>
---
drivers/pinctrl/airoha/airoha-common.h | 14 ++++++++
drivers/pinctrl/airoha/pinctrl-airoha.c | 48 +++++++++++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/drivers/pinctrl/airoha/airoha-common.h b/drivers/pinctrl/airoha/airoha-common.h
index 850e733db15a..7a0cb8924e71 100644
--- a/drivers/pinctrl/airoha/airoha-common.h
+++ b/drivers/pinctrl/airoha/airoha-common.h
@@ -49,6 +49,12 @@
.group_size = ARRAY_SIZE(table##_func_group), \
}
+#define PINCTRL_MODE_FUNC_GROUP(id, table) \
+ { \
+ .name = id, \
+ .pin_modes = table##_modes, \
+ }
+
#define PINCTRL_CONF_DESC(p, offset, mask) \
{ \
.pin = p, \
@@ -75,6 +81,7 @@ struct airoha_pinctrl_func_group {
u32 val;
} regmap[2];
int regmap_size;
+ const u8 *pin_modes;
};
struct airoha_pinctrl_func {
@@ -102,6 +109,10 @@ struct airoha_gpiochip_regs {
extern const struct airoha_gpiochip_regs airoha_gpiochip_regs_64;
+struct airoha_pinctrl_iomux {
+ u8 mode_bits;
+};
+
struct airoha_pinctrl_confs_info {
const struct airoha_pinctrl_conf *confs;
unsigned int num_confs;
@@ -126,6 +137,8 @@ struct airoha_pinctrl {
const struct airoha_pinctrl_confs_info *confs_info;
struct regmap *chip_scu;
+ struct regmap *iomux;
+ const struct airoha_pinctrl_iomux *iomux_info;
struct regmap *regmap;
struct gpio_chip gpiochip;
@@ -135,6 +148,7 @@ struct airoha_pinctrl {
struct airoha_pinctrl_match_data {
const char *chip_scu_compatible;
+ const struct airoha_pinctrl_iomux *iomux_info;
const char *pinctrl_name;
struct module *pinctrl_owner;
const struct airoha_gpiochip_regs *gpio_regs;
diff --git a/drivers/pinctrl/airoha/pinctrl-airoha.c b/drivers/pinctrl/airoha/pinctrl-airoha.c
index b50108826d8d..f9ae4020b764 100644
--- a/drivers/pinctrl/airoha/pinctrl-airoha.c
+++ b/drivers/pinctrl/airoha/pinctrl-airoha.c
@@ -401,6 +401,35 @@ static int airoha_pinctrl_add_gpiochip(struct airoha_pinctrl *pinctrl,
}
/* pinmux callbacks */
+static int airoha_pinmux_set_pin_mode(struct airoha_pinctrl *pinctrl,
+ unsigned int pin, u8 mode)
+{
+ unsigned int mode_bits = pinctrl->iomux_info->mode_bits;
+ unsigned int modes_per_reg = sizeof(u32) * BITS_PER_BYTE / mode_bits;
+ unsigned int shift = (pin % modes_per_reg) * mode_bits;
+ unsigned int reg = (pin / modes_per_reg) * sizeof(u32);
+
+ return regmap_update_bits(pinctrl->iomux, reg,
+ GENMASK(mode_bits - 1, 0) << shift,
+ mode << shift);
+}
+
+static int airoha_pinmux_set_pin_modes(struct airoha_pinctrl *pinctrl,
+ const struct group_desc *grp,
+ const u8 *modes)
+{
+ int i, err;
+
+ for (i = 0; i < grp->grp.npins; i++) {
+ err = airoha_pinmux_set_pin_mode(pinctrl, grp->grp.pins[i],
+ modes[i]);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
static int airoha_pinmux_set_mux(struct pinctrl_dev *pctrl_dev,
unsigned int selector,
unsigned int group)
@@ -431,6 +460,15 @@ static int airoha_pinmux_set_mux(struct pinctrl_dev *pctrl_dev,
if (strcmp(group->name, grp->grp.name))
continue;
+ if (group->pin_modes) {
+ int err;
+
+ err = airoha_pinmux_set_pin_modes(pinctrl, grp,
+ group->pin_modes);
+ if (err)
+ return err;
+ }
+
for (j = 0; j < group->regmap_size; j++) {
switch (group->regmap[j].mux) {
case AIROHA_FUNC_PWM_EXT_MUX:
@@ -824,6 +862,16 @@ int airoha_pinctrl_probe(struct platform_device *pdev)
pinctrl->chip_scu = map;
+ if (data->iomux_info) {
+ map = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "airoha,iomux");
+ if (IS_ERR(map))
+ return PTR_ERR(map);
+
+ pinctrl->iomux = map;
+ pinctrl->iomux_info = data->iomux_info;
+ }
+
/* Init pinctrl desc struct */
pinctrl->desc.name = data->pinctrl_name;
pinctrl->desc.owner = data->pinctrl_owner;
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/7] pinctrl: airoha: make the chip SCU optional
2026-11-10 17:39 [PATCH 0/7] pinctrl: airoha: add AN7589 support John Crispin
2026-11-10 17:39 ` [PATCH 1/7] pinctrl: airoha: make gpio register layout per SoC John Crispin
2026-11-10 17:39 ` [PATCH 2/7] pinctrl: airoha: add per pin mode field mux John Crispin
@ 2026-11-10 17:39 ` John Crispin
2026-11-10 17:39 ` [PATCH 4/7] pinctrl: airoha: mux a requested GPIO through the IOMUX John Crispin
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: John Crispin @ 2026-11-10 17:39 UTC (permalink / raw)
To: Lorenzo Bianconi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Linus Walleij, Bartosz Golaszewski
Cc: Ahmed Naseef, Benjamin Larsson, Christian Marangi, devicetree,
lei.dong, Linqi.zhang, linux-gpio, linux-kernel, linux-mediatek,
mfd, Mikhail Kshevetskiy, Rajeev.kumar, upstream, Weifeng.xu,
zhengping.zhang
A SoC that muxes every pin through the IOMUX block and describes no
pin configuration has no use for the chip SCU. Skip the lookup when
the match data names no chip SCU compatible, instead of handing a
NULL compatible to syscon_regmap_lookup_by_compatible().
No functional change for the existing SoCs, which all name one.
Signed-off-by: John Crispin <john@phrozen.org>
---
drivers/pinctrl/airoha/pinctrl-airoha.c | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/drivers/pinctrl/airoha/pinctrl-airoha.c b/drivers/pinctrl/airoha/pinctrl-airoha.c
index f9ae4020b764..9116d3ded258 100644
--- a/drivers/pinctrl/airoha/pinctrl-airoha.c
+++ b/drivers/pinctrl/airoha/pinctrl-airoha.c
@@ -833,6 +833,22 @@ static const struct pinctrl_ops airoha_pctlops = {
.dt_free_map = pinconf_generic_dt_free_map,
};
+static struct regmap *
+airoha_pinctrl_chip_scu(struct device *dev,
+ const struct airoha_pinctrl_match_data *data)
+{
+ struct regmap *map;
+
+ if (!data->chip_scu_compatible)
+ return NULL;
+
+ map = syscon_regmap_lookup_by_phandle(dev->of_node, "airoha,chip-scu");
+ if (!IS_ERR_OR_NULL(map))
+ return map;
+
+ return syscon_regmap_lookup_by_compatible(data->chip_scu_compatible);
+}
+
int airoha_pinctrl_probe(struct platform_device *pdev)
{
const struct airoha_pinctrl_match_data *data;
@@ -853,12 +869,9 @@ int airoha_pinctrl_probe(struct platform_device *pdev)
if (IS_ERR(pinctrl->regmap))
return PTR_ERR(pinctrl->regmap);
- map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "airoha,chip-scu");
- if (IS_ERR_OR_NULL(map)) {
- map = syscon_regmap_lookup_by_compatible(data->chip_scu_compatible);
- if (IS_ERR(map))
- return PTR_ERR(map);
- }
+ map = airoha_pinctrl_chip_scu(dev, data);
+ if (IS_ERR(map))
+ return PTR_ERR(map);
pinctrl->chip_scu = map;
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/7] pinctrl: airoha: mux a requested GPIO through the IOMUX
2026-11-10 17:39 [PATCH 0/7] pinctrl: airoha: add AN7589 support John Crispin
` (2 preceding siblings ...)
2026-11-10 17:39 ` [PATCH 3/7] pinctrl: airoha: make the chip SCU optional John Crispin
@ 2026-11-10 17:39 ` John Crispin
2026-11-10 17:39 ` [PATCH 5/7] dt-bindings: pinctrl: airoha: add AN7589 John Crispin
` (2 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: John Crispin @ 2026-11-10 17:39 UTC (permalink / raw)
To: Lorenzo Bianconi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Linus Walleij, Bartosz Golaszewski
Cc: Ahmed Naseef, Benjamin Larsson, Christian Marangi, devicetree,
lei.dong, Linqi.zhang, linux-gpio, linux-kernel, linux-mediatek,
mfd, Mikhail Kshevetskiy, Rajeev.kumar, upstream, Weifeng.xu,
zhengping.zhang
On a SoC with an IOMUX block every pin turns into a GPIO with one mode
value, mode 0 on the AN7589. Add that value to struct
airoha_pinctrl_iomux and write it when gpiolib requests a pin, so no
SoC needs a gpio function with one group per pin.
Without an IOMUX the callback does nothing, so the existing SoCs keep
their explicit gpio functions and their behavior.
Signed-off-by: John Crispin <john@phrozen.org>
---
drivers/pinctrl/airoha/airoha-common.h | 1 +
drivers/pinctrl/airoha/pinctrl-airoha.c | 14 ++++++++++++++
2 files changed, 15 insertions(+)
diff --git a/drivers/pinctrl/airoha/airoha-common.h b/drivers/pinctrl/airoha/airoha-common.h
index 7a0cb8924e71..adfce89493f0 100644
--- a/drivers/pinctrl/airoha/airoha-common.h
+++ b/drivers/pinctrl/airoha/airoha-common.h
@@ -111,6 +111,7 @@ extern const struct airoha_gpiochip_regs airoha_gpiochip_regs_64;
struct airoha_pinctrl_iomux {
u8 mode_bits;
+ u8 gpio_mode;
};
struct airoha_pinctrl_confs_info {
diff --git a/drivers/pinctrl/airoha/pinctrl-airoha.c b/drivers/pinctrl/airoha/pinctrl-airoha.c
index 9116d3ded258..a805f542bc7b 100644
--- a/drivers/pinctrl/airoha/pinctrl-airoha.c
+++ b/drivers/pinctrl/airoha/pinctrl-airoha.c
@@ -430,6 +430,19 @@ static int airoha_pinmux_set_pin_modes(struct airoha_pinctrl *pinctrl,
return 0;
}
+static int airoha_pinmux_gpio_request_enable(struct pinctrl_dev *pctrl_dev,
+ struct pinctrl_gpio_range *range,
+ unsigned int pin)
+{
+ struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+
+ if (!pinctrl->iomux_info)
+ return 0;
+
+ return airoha_pinmux_set_pin_mode(pinctrl, pin,
+ pinctrl->iomux_info->gpio_mode);
+}
+
static int airoha_pinmux_set_mux(struct pinctrl_dev *pctrl_dev,
unsigned int selector,
unsigned int group)
@@ -510,6 +523,7 @@ static const struct pinmux_ops airoha_pmxops = {
.get_functions_count = pinmux_generic_get_function_count,
.get_function_name = pinmux_generic_get_function_name,
.get_function_groups = pinmux_generic_get_function_groups,
+ .gpio_request_enable = airoha_pinmux_gpio_request_enable,
.gpio_set_direction = airoha_pinmux_set_direction,
.set_mux = airoha_pinmux_set_mux,
.strict = true,
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 5/7] dt-bindings: pinctrl: airoha: add AN7589
2026-11-10 17:39 [PATCH 0/7] pinctrl: airoha: add AN7589 support John Crispin
` (3 preceding siblings ...)
2026-11-10 17:39 ` [PATCH 4/7] pinctrl: airoha: mux a requested GPIO through the IOMUX John Crispin
@ 2026-11-10 17:39 ` John Crispin
2026-11-10 18:27 ` Conor Dooley
2026-11-10 17:39 ` [PATCH 6/7] pinctrl: airoha: move the GPIO register offsets to the common header John Crispin
2026-11-10 17:39 ` [PATCH 7/7] pinctrl: airoha: add support of an7589 SoC John Crispin
6 siblings, 1 reply; 9+ messages in thread
From: John Crispin @ 2026-11-10 17:39 UTC (permalink / raw)
To: Lorenzo Bianconi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Linus Walleij, Bartosz Golaszewski
Cc: Ahmed Naseef, Benjamin Larsson, Christian Marangi, devicetree,
lei.dong, Linqi.zhang, linux-gpio, linux-kernel, linux-mediatek,
mfd, Mikhail Kshevetskiy, Rajeev.kumar, upstream, Weifeng.xu,
zhengping.zhang
Document the AN7589 pin controller and the GPIO system controller it
lives under. The pin controller selects functions through a separate
IOMUX syscon, referenced by the airoha,iomux phandle, and every pin is
a GPIO in mode 0.
The AN7589 has no chip SCU dependency and the vendor SDK carries no
pull or drive registers for it. Groups follow the SDK naming without
its _grp suffix. The PON groups keep the working mode only: the SDK
encodes the driver reset sequence as extra pinctrl states, which
belongs in the consumer driver.
The pwm function routes a PWM channel to one of GPIO0 to GPIO15, with
one group per pin. The pin also needs its GPIO output enabled, so conf
nodes allow the GPIO direction and output level. Pull and drive
properties are not allowed, as no registers for them are known.
Signed-off-by: John Crispin <john@phrozen.org>
---
.../mfd/airoha,an7589-gpio-sysctl.yaml | 66 +++
.../devicetree/bindings/mfd/syscon.yaml | 1 +
.../pinctrl/airoha,an7589-pinctrl.yaml | 533 ++++++++++++++++++
MAINTAINERS | 2 +
4 files changed, 602 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mfd/airoha,an7589-gpio-sysctl.yaml
create mode 100644 Documentation/devicetree/bindings/pinctrl/airoha,an7589-pinctrl.yaml
diff --git a/Documentation/devicetree/bindings/mfd/airoha,an7589-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/airoha,an7589-gpio-sysctl.yaml
new file mode 100644
index 000000000000..0785b61bdda3
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/airoha,an7589-gpio-sysctl.yaml
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/airoha,an7589-gpio-sysctl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN7589 GPIO System Controller
+
+maintainers:
+ - John Crispin <john@phrozen.org>
+
+description:
+ Airoha AN7589 SoC GPIO system controller which provides a register map
+ for controlling the GPIO and pins of the SoC.
+
+properties:
+ compatible:
+ items:
+ - const: airoha,an7589-gpio-sysctl
+ - const: syscon
+ - const: simple-mfd
+
+ reg:
+ maxItems: 1
+
+ pinctrl:
+ type: object
+ $ref: /schemas/pinctrl/airoha,an7589-pinctrl.yaml
+ description:
+ Child node definition for AN7589 Pin controller
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ system-controller@1fbf0200 {
+ compatible = "airoha,an7589-gpio-sysctl", "syscon", "simple-mfd";
+ reg = <0x1fbf0200 0x100>;
+
+ pinctrl {
+ compatible = "airoha,an7589-pinctrl";
+ airoha,iomux = <&iomux>;
+
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ mmc-pins {
+ mux {
+ function = "emmc";
+ groups = "emmc";
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index dae706ca7642..e87158d42e87 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -24,6 +24,7 @@ properties:
oneOf:
- items:
- enum:
+ - airoha,an7589-iomux
- airoha,en7581-pbus-csr
- al,alpine-sysfabric-service
- allwinner,sun8i-a83t-system-controller
diff --git a/Documentation/devicetree/bindings/pinctrl/airoha,an7589-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/airoha,an7589-pinctrl.yaml
new file mode 100644
index 000000000000..546e333f3467
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/airoha,an7589-pinctrl.yaml
@@ -0,0 +1,533 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/airoha,an7589-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN7589 Pin Controller
+
+maintainers:
+ - John Crispin <john@phrozen.org>
+
+description:
+ The Airoha AN7589 pin controller is used to control SoC pins. Pin
+ functions are selected through a separate IOMUX register block, one
+ mode field per pin. Every pin is a GPIO in mode 0.
+
+properties:
+ compatible:
+ const: airoha,an7589-pinctrl
+
+ airoha,iomux:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to the IOMUX syscon holding the per pin mode fields.
+
+ interrupts:
+ maxItems: 1
+
+ gpio-controller: true
+
+ '#gpio-cells':
+ const: 2
+
+ gpio-ranges:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ '#interrupt-cells':
+ const: 2
+
+allOf:
+ - $ref: pinctrl.yaml#
+
+required:
+ - compatible
+ - airoha,iomux
+ - interrupts
+ - gpio-controller
+ - "#gpio-cells"
+ - interrupt-controller
+ - "#interrupt-cells"
+
+patternProperties:
+ '-pins$':
+ type: object
+
+ patternProperties:
+ '^mux(-|$)':
+ type: object
+
+ description:
+ pinmux configuration nodes.
+
+ $ref: /schemas/pinctrl/pinmux-node.yaml
+
+ properties:
+ function:
+ description:
+ A string containing the name of the function to mux to the group.
+ enum: [uart1, uart2, uart3, uart4, uart5, uart6, i2c0, i2c1,
+ i2c2, i2c3, i2c4, spi, ext_spi1, ext_spi2, ext_spi3,
+ pcm1, pcm2, pcm_spi, i2s, mdio0, mdio1, mdio2, mdcs,
+ mdios, emmc, pcie0, pcie1, pcie2, pon1, pon2, sgpio0,
+ sgpio1, watchdog, shiftmux_spi, tod, sync_e, cpu_jtag,
+ npu_jtag, ibex_jtag, pma50eth_jtag, ainpu_jtag,
+ pma50pon_jtag, pwm]
+
+ groups:
+ description:
+ An array of strings. Each string contains the name of a group.
+
+ required:
+ - function
+ - groups
+
+ allOf:
+ - if:
+ properties:
+ function:
+ const: uart1
+ then:
+ properties:
+ groups:
+ enum: [uart1]
+ - if:
+ properties:
+ function:
+ const: uart2
+ then:
+ properties:
+ groups:
+ enum: [uart2]
+ - if:
+ properties:
+ function:
+ const: uart3
+ then:
+ properties:
+ groups:
+ items:
+ enum: [uart3, uart3_alt]
+ maxItems: 2
+ - if:
+ properties:
+ function:
+ const: uart4
+ then:
+ properties:
+ groups:
+ enum: [uart4]
+ - if:
+ properties:
+ function:
+ const: uart5
+ then:
+ properties:
+ groups:
+ items:
+ enum: [uart5, uart5_alt, uart5_full]
+ maxItems: 3
+ - if:
+ properties:
+ function:
+ const: uart6
+ then:
+ properties:
+ groups:
+ items:
+ enum: [uart6, uart6_full]
+ maxItems: 2
+ - if:
+ properties:
+ function:
+ const: i2c0
+ then:
+ properties:
+ groups:
+ enum: [i2c0]
+ - if:
+ properties:
+ function:
+ const: i2c1
+ then:
+ properties:
+ groups:
+ enum: [i2c1]
+ - if:
+ properties:
+ function:
+ const: i2c2
+ then:
+ properties:
+ groups:
+ enum: [i2c2]
+ - if:
+ properties:
+ function:
+ const: i2c3
+ then:
+ properties:
+ groups:
+ enum: [i2c3]
+ - if:
+ properties:
+ function:
+ const: i2c4
+ then:
+ properties:
+ groups:
+ enum: [i2c4]
+ - if:
+ properties:
+ function:
+ const: spi
+ then:
+ properties:
+ groups:
+ items:
+ enum: [spi0, ext_spi0_full]
+ maxItems: 2
+ - if:
+ properties:
+ function:
+ const: ext_spi1
+ then:
+ properties:
+ groups:
+ items:
+ enum: [ext_spi1, ext_spi1_full]
+ maxItems: 2
+ - if:
+ properties:
+ function:
+ const: ext_spi2
+ then:
+ properties:
+ groups:
+ items:
+ enum: [ext_spi2, ext_spi2_full]
+ maxItems: 2
+ - if:
+ properties:
+ function:
+ const: ext_spi3
+ then:
+ properties:
+ groups:
+ items:
+ enum: [ext_spi3, ext_spi3_full]
+ maxItems: 2
+ - if:
+ properties:
+ function:
+ const: pcm1
+ then:
+ properties:
+ groups:
+ enum: [pcm1]
+ - if:
+ properties:
+ function:
+ const: pcm2
+ then:
+ properties:
+ groups:
+ enum: [pcm2]
+ - if:
+ properties:
+ function:
+ const: pcm_spi
+ then:
+ properties:
+ groups:
+ items:
+ enum: [pcm_spi, pcm_spi_cs, pcm_ctrl]
+ maxItems: 3
+ - if:
+ properties:
+ function:
+ const: i2s
+ then:
+ properties:
+ groups:
+ enum: [i2s]
+ - if:
+ properties:
+ function:
+ const: mdio0
+ then:
+ properties:
+ groups:
+ enum: [mdio0]
+ - if:
+ properties:
+ function:
+ const: mdio1
+ then:
+ properties:
+ groups:
+ enum: [mdio1]
+ - if:
+ properties:
+ function:
+ const: mdio2
+ then:
+ properties:
+ groups:
+ enum: [mdio2]
+ - if:
+ properties:
+ function:
+ const: mdcs
+ then:
+ properties:
+ groups:
+ enum: [mdcs]
+ - if:
+ properties:
+ function:
+ const: mdios
+ then:
+ properties:
+ groups:
+ enum: [mdios]
+ - if:
+ properties:
+ function:
+ const: emmc
+ then:
+ properties:
+ groups:
+ enum: [emmc]
+ - if:
+ properties:
+ function:
+ const: pcie0
+ then:
+ properties:
+ groups:
+ items:
+ enum: [pcie0_rst, pcie0_clkreq, pcie0_wake]
+ maxItems: 3
+ - if:
+ properties:
+ function:
+ const: pcie1
+ then:
+ properties:
+ groups:
+ items:
+ enum: [pcie1_rst, pcie1_clkreq, pcie1_wake]
+ maxItems: 3
+ - if:
+ properties:
+ function:
+ const: pcie2
+ then:
+ properties:
+ groups:
+ items:
+ enum: [pcie2_rst, pcie2_clkreq, pcie2_wake]
+ maxItems: 3
+ - if:
+ properties:
+ function:
+ const: pon1
+ then:
+ properties:
+ groups:
+ enum: [pon1]
+ - if:
+ properties:
+ function:
+ const: pon2
+ then:
+ properties:
+ groups:
+ enum: [pon2]
+ - if:
+ properties:
+ function:
+ const: sgpio0
+ then:
+ properties:
+ groups:
+ enum: [sgpio0]
+ - if:
+ properties:
+ function:
+ const: sgpio1
+ then:
+ properties:
+ groups:
+ enum: [sgpio1]
+ - if:
+ properties:
+ function:
+ const: watchdog
+ then:
+ properties:
+ groups:
+ enum: [watchdog]
+ - if:
+ properties:
+ function:
+ const: shiftmux_spi
+ then:
+ properties:
+ groups:
+ enum: [shiftmux_spi]
+ - if:
+ properties:
+ function:
+ const: tod
+ then:
+ properties:
+ groups:
+ enum: [tod]
+ - if:
+ properties:
+ function:
+ const: sync_e
+ then:
+ properties:
+ groups:
+ enum: [sync_e]
+ - if:
+ properties:
+ function:
+ const: cpu_jtag
+ then:
+ properties:
+ groups:
+ enum: [cpu_jtag, cpu_jtag_alt]
+ - if:
+ properties:
+ function:
+ const: npu_jtag
+ then:
+ properties:
+ groups:
+ enum: [npu_jtag]
+ - if:
+ properties:
+ function:
+ const: ibex_jtag
+ then:
+ properties:
+ groups:
+ enum: [ibex_jtag]
+ - if:
+ properties:
+ function:
+ const: pma50eth_jtag
+ then:
+ properties:
+ groups:
+ enum: [pma50eth_jtag]
+ - if:
+ properties:
+ function:
+ const: ainpu_jtag
+ then:
+ properties:
+ groups:
+ enum: [ainpu_jtag]
+ - if:
+ properties:
+ function:
+ const: pma50pon_jtag
+ then:
+ properties:
+ groups:
+ enum: [pma50pon_jtag]
+ - if:
+ properties:
+ function:
+ const: pwm
+ then:
+ properties:
+ groups:
+ items:
+ enum: [gpio0, gpio1, gpio2, gpio3, gpio4, gpio5, gpio6,
+ gpio7, gpio8, gpio9, gpio10, gpio11, gpio12,
+ gpio13, gpio14, gpio15]
+
+ additionalProperties: false
+
+ '^conf(-|$)':
+ type: object
+
+ description:
+ pinconf configuration nodes.
+
+ $ref: /schemas/pinctrl/pincfg-node.yaml
+
+ properties:
+ pins:
+ description:
+ An array of strings. Each string contains the name of a pin.
+ items:
+ pattern: '^gpio([0-9]|[1-6][0-9]|7[0-3])$'
+ minItems: 1
+ maxItems: 74
+
+ input-enable: true
+
+ output-enable: true
+
+ output-low: true
+
+ output-high: true
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+ additionalProperties: false
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ pinctrl {
+ compatible = "airoha,an7589-pinctrl";
+ airoha,iomux = <&iomux>;
+
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ gpio-ranges = <&pinctrl 0 0 74>;
+
+ mmc-pins {
+ mux {
+ function = "emmc";
+ groups = "emmc";
+ };
+ };
+
+ pcie0-pins {
+ mux {
+ function = "pcie0";
+ groups = "pcie0_rst", "pcie0_clkreq", "pcie0_wake";
+ };
+ };
+
+ uart5-pins {
+ mux {
+ function = "uart5";
+ groups = "uart5", "uart5_full";
+ };
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index aa647f5d37dd..2041a8aed28f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22137,6 +22137,8 @@ PIN CONTROLLER - AIROHA
M: Lorenzo Bianconi <lorenzo@kernel.org>
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained
+F: Documentation/devicetree/bindings/mfd/airoha,an7589-gpio-sysctl.yaml
+F: Documentation/devicetree/bindings/pinctrl/airoha,an7589-pinctrl.yaml
F: Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml
F: drivers/pinctrl/airoha/pinctrl-airoha.c
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 6/7] pinctrl: airoha: move the GPIO register offsets to the common header
2026-11-10 17:39 [PATCH 0/7] pinctrl: airoha: add AN7589 support John Crispin
` (4 preceding siblings ...)
2026-11-10 17:39 ` [PATCH 5/7] dt-bindings: pinctrl: airoha: add AN7589 John Crispin
@ 2026-11-10 17:39 ` John Crispin
2026-11-10 17:39 ` [PATCH 7/7] pinctrl: airoha: add support of an7589 SoC John Crispin
6 siblings, 0 replies; 9+ messages in thread
From: John Crispin @ 2026-11-10 17:39 UTC (permalink / raw)
To: Lorenzo Bianconi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Linus Walleij, Bartosz Golaszewski
Cc: Ahmed Naseef, Benjamin Larsson, Christian Marangi, devicetree,
lei.dong, Linqi.zhang, linux-gpio, linux-kernel, linux-mediatek,
mfd, Mikhail Kshevetskiy, Rajeev.kumar, upstream, Weifeng.xu,
zhengping.zhang
The GPIO register offsets are private to pinctrl-airoha.c, which builds
the shared 64 pin register table from them. A SoC with more GPIO banks
needs its own table, built from the same offsets and its own for the
extra banks.
Move the offsets to airoha-common.h so the SoC drivers can use them.
No functional change.
Signed-off-by: John Crispin <john@phrozen.org>
---
drivers/pinctrl/airoha/airoha-common.h | 20 ++++++++++++++++++++
drivers/pinctrl/airoha/pinctrl-airoha.c | 20 --------------------
2 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/drivers/pinctrl/airoha/airoha-common.h b/drivers/pinctrl/airoha/airoha-common.h
index adfce89493f0..dc9b897ea77c 100644
--- a/drivers/pinctrl/airoha/airoha-common.h
+++ b/drivers/pinctrl/airoha/airoha-common.h
@@ -34,6 +34,26 @@
#include "../pinconf.h"
#include "../pinmux.h"
+/* GPIOs */
+#define REG_GPIO_CTRL 0x0000
+#define REG_GPIO_DATA 0x0004
+#define REG_GPIO_INT 0x0008
+#define REG_GPIO_INT_EDGE 0x000c
+#define REG_GPIO_INT_LEVEL 0x0010
+#define REG_GPIO_OE 0x0014
+#define REG_GPIO_CTRL1 0x0020
+#define REG_GPIO_CTRL2 0x0060
+#define REG_GPIO_CTRL3 0x0064
+#define REG_GPIO_DATA1 0x0070
+#define REG_GPIO_OE1 0x0078
+#define REG_GPIO_INT1 0x007c
+#define REG_GPIO_INT_EDGE1 0x0080
+#define REG_GPIO_INT_EDGE2 0x0084
+#define REG_GPIO_INT_EDGE3 0x0088
+#define REG_GPIO_INT_LEVEL1 0x008c
+#define REG_GPIO_INT_LEVEL2 0x0090
+#define REG_GPIO_INT_LEVEL3 0x0094
+
#define AIROHA_NUM_PINS 64
#define AIROHA_PIN_BANK_SIZE (AIROHA_NUM_PINS / 2)
#define AIROHA_REG_GPIOCTRL_NUM_PIN (AIROHA_NUM_PINS / 4)
diff --git a/drivers/pinctrl/airoha/pinctrl-airoha.c b/drivers/pinctrl/airoha/pinctrl-airoha.c
index a805f542bc7b..8f901f251c00 100644
--- a/drivers/pinctrl/airoha/pinctrl-airoha.c
+++ b/drivers/pinctrl/airoha/pinctrl-airoha.c
@@ -7,26 +7,6 @@
#include "airoha-common.h"
-/* GPIOs */
-#define REG_GPIO_CTRL 0x0000
-#define REG_GPIO_DATA 0x0004
-#define REG_GPIO_INT 0x0008
-#define REG_GPIO_INT_EDGE 0x000c
-#define REG_GPIO_INT_LEVEL 0x0010
-#define REG_GPIO_OE 0x0014
-#define REG_GPIO_CTRL1 0x0020
-#define REG_GPIO_CTRL2 0x0060
-#define REG_GPIO_CTRL3 0x0064
-#define REG_GPIO_DATA1 0x0070
-#define REG_GPIO_OE1 0x0078
-#define REG_GPIO_INT1 0x007c
-#define REG_GPIO_INT_EDGE1 0x0080
-#define REG_GPIO_INT_EDGE2 0x0084
-#define REG_GPIO_INT_EDGE3 0x0088
-#define REG_GPIO_INT_LEVEL1 0x008c
-#define REG_GPIO_INT_LEVEL2 0x0090
-#define REG_GPIO_INT_LEVEL3 0x0094
-
#define airoha_pinctrl_get_pullup_conf(pinctrl, pin, val) \
airoha_pinctrl_get_conf((pinctrl), AIROHA_PINCTRL_CONFS_PULLUP, \
(pin), (val))
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 7/7] pinctrl: airoha: add support of an7589 SoC
2026-11-10 17:39 [PATCH 0/7] pinctrl: airoha: add AN7589 support John Crispin
` (5 preceding siblings ...)
2026-11-10 17:39 ` [PATCH 6/7] pinctrl: airoha: move the GPIO register offsets to the common header John Crispin
@ 2026-11-10 17:39 ` John Crispin
6 siblings, 0 replies; 9+ messages in thread
From: John Crispin @ 2026-11-10 17:39 UTC (permalink / raw)
To: Lorenzo Bianconi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Linus Walleij, Bartosz Golaszewski
Cc: Ahmed Naseef, Benjamin Larsson, Christian Marangi, devicetree,
lei.dong, Linqi.zhang, linux-gpio, linux-kernel, linux-mediatek,
mfd, Mikhail Kshevetskiy, Rajeev.kumar, upstream, Weifeng.xu,
zhengping.zhang
Add pin controller support for the Airoha AN7589. Its GPIO block is
the EN7581 one with a third bank, giving 74 GPIOs. Pin functions are
selected through a separate IOMUX block holding a 4 bit mode per pin,
where mode 0 is GPIO.
As on the EN7581, the pwm function is available on GPIO0 to GPIO15
through the GPIO flash mode register.
Unlike on the other SoCs, the pull and drive registers of the AN7589
are not known, so no pull or drive configuration is provided.
Signed-off-by: John Crispin <john@phrozen.org>
---
MAINTAINERS | 1 +
drivers/pinctrl/airoha/Kconfig | 11 +
drivers/pinctrl/airoha/Makefile | 1 +
drivers/pinctrl/airoha/pinctrl-an7589.c | 721 ++++++++++++++++++++++++
4 files changed, 734 insertions(+)
create mode 100644 drivers/pinctrl/airoha/pinctrl-an7589.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 2041a8aed28f..159a8818e1ad 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22141,6 +22141,7 @@ F: Documentation/devicetree/bindings/mfd/airoha,an7589-gpio-sysctl.yaml
F: Documentation/devicetree/bindings/pinctrl/airoha,an7589-pinctrl.yaml
F: Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml
F: drivers/pinctrl/airoha/pinctrl-airoha.c
+F: drivers/pinctrl/airoha/pinctrl-an7589.c
PIN CONTROLLER - AMD
M: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
diff --git a/drivers/pinctrl/airoha/Kconfig b/drivers/pinctrl/airoha/Kconfig
index 0f0986c81219..1948101ae5ac 100644
--- a/drivers/pinctrl/airoha/Kconfig
+++ b/drivers/pinctrl/airoha/Kconfig
@@ -16,6 +16,7 @@ config PINCTRL_AIROHA
imply PINCTRL_AIROHA_AN7563
imply PINCTRL_AIROHA_AN7581
imply PINCTRL_AIROHA_AN7583
+ imply PINCTRL_AIROHA_AN7589
imply PINCTRL_AIROHA_EN7523
imply PINCTRL_AIROHA_EN7528
help
@@ -46,6 +47,16 @@ config PINCTRL_AIROHA_AN7583
Say yes here to support pin controller and gpio driver
on Airoha AN7583, AN7553, AN7567 and other compatible SoCs.
+config PINCTRL_AIROHA_AN7589
+ tristate "AN7589 pinctrl"
+ depends on ARM64 || COMPILE_TEST
+ depends on PINCTRL_AIROHA
+ help
+ Say yes here to support pin controller and gpio driver
+ on Airoha AN7589 and other compatible SoCs. The AN7589
+ selects pin functions through its IOMUX block and has
+ 74 GPIOs in three banks.
+
config PINCTRL_AIROHA_EN7523
tristate "EN7523 pinctrl"
depends on ARM || COMPILE_TEST
diff --git a/drivers/pinctrl/airoha/Makefile b/drivers/pinctrl/airoha/Makefile
index 4dc7c556ce4d..550803cbd5b6 100644
--- a/drivers/pinctrl/airoha/Makefile
+++ b/drivers/pinctrl/airoha/Makefile
@@ -7,5 +7,6 @@ obj-$(CONFIG_PINCTRL_AIROHA) += pinctrl-airoha.o
obj-$(CONFIG_PINCTRL_AIROHA_AN7563) += pinctrl-an7563.o
obj-$(CONFIG_PINCTRL_AIROHA_AN7581) += pinctrl-an7581.o
obj-$(CONFIG_PINCTRL_AIROHA_AN7583) += pinctrl-an7583.o
+obj-$(CONFIG_PINCTRL_AIROHA_AN7589) += pinctrl-an7589.o
obj-$(CONFIG_PINCTRL_AIROHA_EN7523) += pinctrl-en7523.o
obj-$(CONFIG_PINCTRL_AIROHA_EN7528) += pinctrl-en7528.o
diff --git a/drivers/pinctrl/airoha/pinctrl-an7589.c b/drivers/pinctrl/airoha/pinctrl-an7589.c
new file mode 100644
index 000000000000..39654a9a94e4
--- /dev/null
+++ b/drivers/pinctrl/airoha/pinctrl-an7589.c
@@ -0,0 +1,721 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Author: John Crispin <john@phrozen.org>
+ *
+ * AN7589 SoC pinctrl data for the Airoha pinctrl driver (pinctrl-airoha.c).
+ *
+ * The GPIO controller at 0x1fbf0200 is the EN7581 one with a third bank
+ * for GPIO64-GPIO79. Pin functions are selected through the IOMUX block
+ * at 0x1fa30000, one 4 bit mode field per pin. Mode 0 is GPIO on every
+ * pin, so pins 0-73 map to GPIO0-GPIO73 and carry no dedicated pads.
+ */
+
+#include "airoha-common.h"
+
+#define AN7589_NUM_PINS 74
+
+#define REG_GPIO_CTRL4 0x00c0
+#define REG_GPIO_DATA2 0x00c4
+#define REG_GPIO_OE2 0x00c8
+#define REG_GPIO_INT2 0x00cc
+#define REG_GPIO_INT_EDGE4 0x00d0
+#define REG_GPIO_INT_LEVEL4 0x00d4
+
+#define REG_GPIO_FLASH_MODE_CFG 0x0034
+#define GPIO_FLASH_MODE_CFG(n) BIT(n)
+
+#define AN7589_IOMUX_MODE_BITS 4
+#define AN7589_IOMUX_MODE_GPIO 0
+
+static const struct airoha_pinctrl_iomux iomux_info = {
+ .mode_bits = AN7589_IOMUX_MODE_BITS,
+ .gpio_mode = AN7589_IOMUX_MODE_GPIO,
+};
+
+static const u32 gpio_data_regs[] = {
+ REG_GPIO_DATA,
+ REG_GPIO_DATA1,
+ REG_GPIO_DATA2
+};
+
+static const u32 gpio_out_regs[] = {
+ REG_GPIO_OE,
+ REG_GPIO_OE1,
+ REG_GPIO_OE2
+};
+
+static const u32 gpio_dir_regs[] = {
+ REG_GPIO_CTRL,
+ REG_GPIO_CTRL1,
+ REG_GPIO_CTRL2,
+ REG_GPIO_CTRL3,
+ REG_GPIO_CTRL4
+};
+
+static const u32 irq_status_regs[] = {
+ REG_GPIO_INT,
+ REG_GPIO_INT1,
+ REG_GPIO_INT2
+};
+
+static const u32 irq_level_regs[] = {
+ REG_GPIO_INT_LEVEL,
+ REG_GPIO_INT_LEVEL1,
+ REG_GPIO_INT_LEVEL2,
+ REG_GPIO_INT_LEVEL3,
+ REG_GPIO_INT_LEVEL4
+};
+
+static const u32 irq_edge_regs[] = {
+ REG_GPIO_INT_EDGE,
+ REG_GPIO_INT_EDGE1,
+ REG_GPIO_INT_EDGE2,
+ REG_GPIO_INT_EDGE3,
+ REG_GPIO_INT_EDGE4
+};
+
+static const struct airoha_gpiochip_regs gpiochip_regs = {
+ .ngpio = AN7589_NUM_PINS,
+ .data = gpio_data_regs,
+ .dir = gpio_dir_regs,
+ .out = gpio_out_regs,
+ .status = irq_status_regs,
+ .level = irq_level_regs,
+ .edge = irq_edge_regs,
+};
+
+static const struct pinctrl_pin_desc pinctrl_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ PINCTRL_PIN(2, "gpio2"),
+ PINCTRL_PIN(3, "gpio3"),
+ PINCTRL_PIN(4, "gpio4"),
+ PINCTRL_PIN(5, "gpio5"),
+ PINCTRL_PIN(6, "gpio6"),
+ PINCTRL_PIN(7, "gpio7"),
+ PINCTRL_PIN(8, "gpio8"),
+ PINCTRL_PIN(9, "gpio9"),
+ PINCTRL_PIN(10, "gpio10"),
+ PINCTRL_PIN(11, "gpio11"),
+ PINCTRL_PIN(12, "gpio12"),
+ PINCTRL_PIN(13, "gpio13"),
+ PINCTRL_PIN(14, "gpio14"),
+ PINCTRL_PIN(15, "gpio15"),
+ PINCTRL_PIN(16, "gpio16"),
+ PINCTRL_PIN(17, "gpio17"),
+ PINCTRL_PIN(18, "gpio18"),
+ PINCTRL_PIN(19, "gpio19"),
+ PINCTRL_PIN(20, "gpio20"),
+ PINCTRL_PIN(21, "gpio21"),
+ PINCTRL_PIN(22, "gpio22"),
+ PINCTRL_PIN(23, "gpio23"),
+ PINCTRL_PIN(24, "gpio24"),
+ PINCTRL_PIN(25, "gpio25"),
+ PINCTRL_PIN(26, "gpio26"),
+ PINCTRL_PIN(27, "gpio27"),
+ PINCTRL_PIN(28, "gpio28"),
+ PINCTRL_PIN(29, "gpio29"),
+ PINCTRL_PIN(30, "gpio30"),
+ PINCTRL_PIN(31, "gpio31"),
+ PINCTRL_PIN(32, "gpio32"),
+ PINCTRL_PIN(33, "gpio33"),
+ PINCTRL_PIN(34, "gpio34"),
+ PINCTRL_PIN(35, "gpio35"),
+ PINCTRL_PIN(36, "gpio36"),
+ PINCTRL_PIN(37, "gpio37"),
+ PINCTRL_PIN(38, "gpio38"),
+ PINCTRL_PIN(39, "gpio39"),
+ PINCTRL_PIN(40, "gpio40"),
+ PINCTRL_PIN(41, "gpio41"),
+ PINCTRL_PIN(42, "gpio42"),
+ PINCTRL_PIN(43, "gpio43"),
+ PINCTRL_PIN(44, "gpio44"),
+ PINCTRL_PIN(45, "gpio45"),
+ PINCTRL_PIN(46, "gpio46"),
+ PINCTRL_PIN(47, "gpio47"),
+ PINCTRL_PIN(48, "gpio48"),
+ PINCTRL_PIN(49, "gpio49"),
+ PINCTRL_PIN(50, "gpio50"),
+ PINCTRL_PIN(51, "gpio51"),
+ PINCTRL_PIN(52, "gpio52"),
+ PINCTRL_PIN(53, "gpio53"),
+ PINCTRL_PIN(54, "gpio54"),
+ PINCTRL_PIN(55, "gpio55"),
+ PINCTRL_PIN(56, "gpio56"),
+ PINCTRL_PIN(57, "gpio57"),
+ PINCTRL_PIN(58, "gpio58"),
+ PINCTRL_PIN(59, "gpio59"),
+ PINCTRL_PIN(60, "gpio60"),
+ PINCTRL_PIN(61, "gpio61"),
+ PINCTRL_PIN(62, "gpio62"),
+ PINCTRL_PIN(63, "gpio63"),
+ PINCTRL_PIN(64, "gpio64"),
+ PINCTRL_PIN(65, "gpio65"),
+ PINCTRL_PIN(66, "gpio66"),
+ PINCTRL_PIN(67, "gpio67"),
+ PINCTRL_PIN(68, "gpio68"),
+ PINCTRL_PIN(69, "gpio69"),
+ PINCTRL_PIN(70, "gpio70"),
+ PINCTRL_PIN(71, "gpio71"),
+ PINCTRL_PIN(72, "gpio72"),
+ PINCTRL_PIN(73, "gpio73"),
+};
+
+static const int uart1_pins[] = { 55, 56 };
+static const u8 uart1_modes[] = { 1, 1 };
+static const int uart2_pins[] = { 13, 14 };
+static const u8 uart2_modes[] = { 4, 4 };
+static const int uart3_pins[] = { 25, 26 };
+static const u8 uart3_modes[] = { 4, 4 };
+static const int uart3_alt_pins[] = { 33 };
+static const u8 uart3_alt_modes[] = { 4 };
+static const int uart4_pins[] = { 41, 42 };
+static const u8 uart4_modes[] = { 4, 4 };
+static const int uart5_pins[] = { 25, 26 };
+static const u8 uart5_modes[] = { 5, 5 };
+static const int uart5_alt_pins[] = { 41, 42 };
+static const u8 uart5_alt_modes[] = { 5, 5 };
+static const int uart5_full_pins[] = { 51, 52, 27, 28 };
+static const u8 uart5_full_modes[] = { 5, 5, 5, 5 };
+static const int uart6_pins[] = { 13, 14 };
+static const u8 uart6_modes[] = { 5, 5 };
+static const int uart6_full_pins[] = { 13, 14, 15, 16 };
+static const u8 uart6_full_modes[] = { 5, 5, 5, 5 };
+static const int i2c0_pins[] = { 57, 58 };
+static const u8 i2c0_modes[] = { 1, 1 };
+static const int i2c1_pins[] = { 35, 36 };
+static const u8 i2c1_modes[] = { 4, 4 };
+static const int i2c2_pins[] = { 51, 52 };
+static const u8 i2c2_modes[] = { 4, 4 };
+static const int i2c3_pins[] = { 5, 7 };
+static const u8 i2c3_modes[] = { 5, 5 };
+static const int i2c4_pins[] = { 59, 60 };
+static const u8 i2c4_modes[] = { 4, 4 };
+static const int spi0_pins[] = { 61, 62, 63, 64 };
+static const u8 spi0_modes[] = { 1, 1, 1, 1 };
+static const int ext_spi0_full_pins[] = { 61, 62, 63, 64, 21, 22, 23 };
+static const u8 ext_spi0_full_modes[] = { 1, 1, 1, 1, 1, 2, 2 };
+static const int ext_spi1_pins[] = { 5, 6, 7, 48 };
+static const u8 ext_spi1_modes[] = { 1, 1, 1, 1 };
+static const int ext_spi1_full_pins[] = { 5, 6, 7, 48, 18, 3 };
+static const u8 ext_spi1_full_modes[] = { 1, 1, 1, 1, 1, 1 };
+static const int ext_spi2_pins[] = { 30, 31, 32, 33 };
+static const u8 ext_spi2_modes[] = { 1, 1, 1, 1 };
+static const int ext_spi2_full_pins[] = { 30, 31, 32, 33, 27, 28 };
+static const u8 ext_spi2_full_modes[] = { 1, 1, 1, 1, 1, 1 };
+static const int ext_spi3_pins[] = { 44, 34, 46, 45 };
+static const u8 ext_spi3_modes[] = { 1, 1, 1, 1 };
+static const int ext_spi3_full_pins[] = { 44, 34, 46, 45, 29, 43 };
+static const u8 ext_spi3_full_modes[] = { 1, 1, 1, 1, 1, 1 };
+static const int pcm1_pins[] = { 9, 10, 11, 12 };
+static const u8 pcm1_modes[] = { 3, 3, 3, 3 };
+static const int pcm2_pins[] = { 5, 6, 7, 48 };
+static const u8 pcm2_modes[] = { 3, 3, 3, 3 };
+static const int pcm_spi_pins[] = { 5, 6, 7, 48 };
+static const u8 pcm_spi_modes[] = { 2, 2, 2, 2 };
+static const int pcm_spi_cs_pins[] = { 13, 14, 15, 16 };
+static const u8 pcm_spi_cs_modes[] = { 2, 2, 2, 2 };
+static const int pcm_ctrl_pins[] = { 3, 4 };
+static const u8 pcm_ctrl_modes[] = { 2, 2 };
+static const int i2s_pins[] = { 13, 14, 15, 16 };
+static const u8 i2s_modes[] = { 3, 3, 3, 3 };
+static const int mdio0_pins[] = { 59, 60 };
+static const u8 mdio0_modes[] = { 1, 1 };
+static const int mdio1_pins[] = { 5, 7 };
+static const u8 mdio1_modes[] = { 7, 7 };
+static const int mdio2_pins[] = { 51, 52 };
+static const u8 mdio2_modes[] = { 2, 2 };
+static const int mdcs_pins[] = { 5 };
+static const u8 mdcs_modes[] = { 4 };
+static const int mdios_pins[] = { 7 };
+static const u8 mdios_modes[] = { 4 };
+static const int emmc_pins[] = { 17, 18, 19, 20, 21, 22, 23, 24,
+ 61, 62, 63, 64 };
+static const u8 emmc_modes[] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
+static const int pcie0_rst_pins[] = { 65 };
+static const u8 pcie0_rst_modes[] = { 1 };
+static const int pcie1_rst_pins[] = { 66 };
+static const u8 pcie1_rst_modes[] = { 1 };
+static const int pcie2_rst_pins[] = { 67 };
+static const u8 pcie2_rst_modes[] = { 1 };
+static const int pcie0_clkreq_pins[] = { 68 };
+static const u8 pcie0_clkreq_modes[] = { 1 };
+static const int pcie1_clkreq_pins[] = { 69 };
+static const u8 pcie1_clkreq_modes[] = { 1 };
+static const int pcie2_clkreq_pins[] = { 70 };
+static const u8 pcie2_clkreq_modes[] = { 1 };
+static const int pcie0_wake_pins[] = { 71 };
+static const u8 pcie0_wake_modes[] = { 1 };
+static const int pcie1_wake_pins[] = { 72 };
+static const u8 pcie1_wake_modes[] = { 1 };
+static const int pcie2_wake_pins[] = { 73 };
+static const u8 pcie2_wake_modes[] = { 1 };
+static const int pon1_pins[] = { 41, 42, 45, 46 };
+static const u8 pon1_modes[] = { 2, 2, 2, 2 };
+static const int pon2_pins[] = { 34, 37, 39 };
+static const u8 pon2_modes[] = { 2, 2, 2 };
+static const int sgpio0_pins[] = { 49, 50, 51 };
+static const u8 sgpio0_modes[] = { 5, 5, 5 };
+static const int sgpio1_pins[] = { 3, 4, 6 };
+static const u8 sgpio1_modes[] = { 5, 5, 5 };
+static const int watchdog_pins[] = { 40 };
+static const u8 watchdog_modes[] = { 3 };
+static const int shiftmux_spi_pins[] = { 61, 62, 63 };
+static const u8 shiftmux_spi_modes[] = { 2, 2, 2 };
+static const int tod_pins[] = { 31 };
+static const u8 tod_modes[] = { 4 };
+static const int sync_e_pins[] = { 28 };
+static const u8 sync_e_modes[] = { 2 };
+static const int cpu_jtag_pins[] = { 3, 13, 14, 15, 16 };
+static const u8 cpu_jtag_modes[] = { 9, 9, 9, 9, 9 };
+static const int cpu_jtag_alt_pins[] = { 41, 42, 43, 44, 45 };
+static const u8 cpu_jtag_alt_modes[] = { 8, 8, 8, 8, 8 };
+static const int npu_jtag_pins[] = { 3, 13, 14, 15, 16 };
+static const u8 npu_jtag_modes[] = { 8, 8, 8, 8, 8 };
+static const int ibex_jtag_pins[] = { 67, 69, 70, 72, 73 };
+static const u8 ibex_jtag_modes[] = { 8, 8, 8, 8, 8 };
+static const int pma50eth_jtag_pins[] = { 30, 31, 32, 33, 38 };
+static const u8 pma50eth_jtag_modes[] = { 8, 8, 8, 8, 8 };
+static const int ainpu_jtag_pins[] = { 30, 31, 32, 33, 38 };
+static const u8 ainpu_jtag_modes[] = { 9, 9, 9, 9, 9 };
+static const int pma50pon_jtag_pins[] = { 41, 42, 43, 44, 45 };
+static const u8 pma50pon_jtag_modes[] = { 9, 9, 9, 9, 9 };
+static const int gpio0_pins[] = { 0 };
+static const int gpio1_pins[] = { 1 };
+static const int gpio2_pins[] = { 2 };
+static const int gpio3_pins[] = { 3 };
+static const int gpio4_pins[] = { 4 };
+static const int gpio5_pins[] = { 5 };
+static const int gpio6_pins[] = { 6 };
+static const int gpio7_pins[] = { 7 };
+static const int gpio8_pins[] = { 8 };
+static const int gpio9_pins[] = { 9 };
+static const int gpio10_pins[] = { 10 };
+static const int gpio11_pins[] = { 11 };
+static const int gpio12_pins[] = { 12 };
+static const int gpio13_pins[] = { 13 };
+static const int gpio14_pins[] = { 14 };
+static const int gpio15_pins[] = { 15 };
+static const u8 pwm_modes[] = { AN7589_IOMUX_MODE_GPIO };
+
+static const struct pingroup pinctrl_groups[] = {
+ PINCTRL_PIN_GROUP("uart1", uart1),
+ PINCTRL_PIN_GROUP("uart2", uart2),
+ PINCTRL_PIN_GROUP("uart3", uart3),
+ PINCTRL_PIN_GROUP("uart3_alt", uart3_alt),
+ PINCTRL_PIN_GROUP("uart4", uart4),
+ PINCTRL_PIN_GROUP("uart5", uart5),
+ PINCTRL_PIN_GROUP("uart5_alt", uart5_alt),
+ PINCTRL_PIN_GROUP("uart5_full", uart5_full),
+ PINCTRL_PIN_GROUP("uart6", uart6),
+ PINCTRL_PIN_GROUP("uart6_full", uart6_full),
+ PINCTRL_PIN_GROUP("i2c0", i2c0),
+ PINCTRL_PIN_GROUP("i2c1", i2c1),
+ PINCTRL_PIN_GROUP("i2c2", i2c2),
+ PINCTRL_PIN_GROUP("i2c3", i2c3),
+ PINCTRL_PIN_GROUP("i2c4", i2c4),
+ PINCTRL_PIN_GROUP("spi0", spi0),
+ PINCTRL_PIN_GROUP("ext_spi0_full", ext_spi0_full),
+ PINCTRL_PIN_GROUP("ext_spi1", ext_spi1),
+ PINCTRL_PIN_GROUP("ext_spi1_full", ext_spi1_full),
+ PINCTRL_PIN_GROUP("ext_spi2", ext_spi2),
+ PINCTRL_PIN_GROUP("ext_spi2_full", ext_spi2_full),
+ PINCTRL_PIN_GROUP("ext_spi3", ext_spi3),
+ PINCTRL_PIN_GROUP("ext_spi3_full", ext_spi3_full),
+ PINCTRL_PIN_GROUP("pcm1", pcm1),
+ PINCTRL_PIN_GROUP("pcm2", pcm2),
+ PINCTRL_PIN_GROUP("pcm_spi", pcm_spi),
+ PINCTRL_PIN_GROUP("pcm_spi_cs", pcm_spi_cs),
+ PINCTRL_PIN_GROUP("pcm_ctrl", pcm_ctrl),
+ PINCTRL_PIN_GROUP("i2s", i2s),
+ PINCTRL_PIN_GROUP("mdio0", mdio0),
+ PINCTRL_PIN_GROUP("mdio1", mdio1),
+ PINCTRL_PIN_GROUP("mdio2", mdio2),
+ PINCTRL_PIN_GROUP("mdcs", mdcs),
+ PINCTRL_PIN_GROUP("mdios", mdios),
+ PINCTRL_PIN_GROUP("emmc", emmc),
+ PINCTRL_PIN_GROUP("pcie0_rst", pcie0_rst),
+ PINCTRL_PIN_GROUP("pcie1_rst", pcie1_rst),
+ PINCTRL_PIN_GROUP("pcie2_rst", pcie2_rst),
+ PINCTRL_PIN_GROUP("pcie0_clkreq", pcie0_clkreq),
+ PINCTRL_PIN_GROUP("pcie1_clkreq", pcie1_clkreq),
+ PINCTRL_PIN_GROUP("pcie2_clkreq", pcie2_clkreq),
+ PINCTRL_PIN_GROUP("pcie0_wake", pcie0_wake),
+ PINCTRL_PIN_GROUP("pcie1_wake", pcie1_wake),
+ PINCTRL_PIN_GROUP("pcie2_wake", pcie2_wake),
+ PINCTRL_PIN_GROUP("pon1", pon1),
+ PINCTRL_PIN_GROUP("pon2", pon2),
+ PINCTRL_PIN_GROUP("sgpio0", sgpio0),
+ PINCTRL_PIN_GROUP("sgpio1", sgpio1),
+ PINCTRL_PIN_GROUP("watchdog", watchdog),
+ PINCTRL_PIN_GROUP("shiftmux_spi", shiftmux_spi),
+ PINCTRL_PIN_GROUP("tod", tod),
+ PINCTRL_PIN_GROUP("sync_e", sync_e),
+ PINCTRL_PIN_GROUP("cpu_jtag", cpu_jtag),
+ PINCTRL_PIN_GROUP("cpu_jtag_alt", cpu_jtag_alt),
+ PINCTRL_PIN_GROUP("npu_jtag", npu_jtag),
+ PINCTRL_PIN_GROUP("ibex_jtag", ibex_jtag),
+ PINCTRL_PIN_GROUP("pma50eth_jtag", pma50eth_jtag),
+ PINCTRL_PIN_GROUP("ainpu_jtag", ainpu_jtag),
+ PINCTRL_PIN_GROUP("pma50pon_jtag", pma50pon_jtag),
+ PINCTRL_PIN_GROUP("gpio0", gpio0),
+ PINCTRL_PIN_GROUP("gpio1", gpio1),
+ PINCTRL_PIN_GROUP("gpio2", gpio2),
+ PINCTRL_PIN_GROUP("gpio3", gpio3),
+ PINCTRL_PIN_GROUP("gpio4", gpio4),
+ PINCTRL_PIN_GROUP("gpio5", gpio5),
+ PINCTRL_PIN_GROUP("gpio6", gpio6),
+ PINCTRL_PIN_GROUP("gpio7", gpio7),
+ PINCTRL_PIN_GROUP("gpio8", gpio8),
+ PINCTRL_PIN_GROUP("gpio9", gpio9),
+ PINCTRL_PIN_GROUP("gpio10", gpio10),
+ PINCTRL_PIN_GROUP("gpio11", gpio11),
+ PINCTRL_PIN_GROUP("gpio12", gpio12),
+ PINCTRL_PIN_GROUP("gpio13", gpio13),
+ PINCTRL_PIN_GROUP("gpio14", gpio14),
+ PINCTRL_PIN_GROUP("gpio15", gpio15),
+};
+
+static const char *const uart1_groups[] = { "uart1" };
+static const char *const uart2_groups[] = { "uart2" };
+static const char *const uart3_groups[] = { "uart3", "uart3_alt" };
+static const char *const uart4_groups[] = { "uart4" };
+static const char *const uart5_groups[] = { "uart5", "uart5_alt", "uart5_full" };
+static const char *const uart6_groups[] = { "uart6", "uart6_full" };
+static const char *const i2c0_groups[] = { "i2c0" };
+static const char *const i2c1_groups[] = { "i2c1" };
+static const char *const i2c2_groups[] = { "i2c2" };
+static const char *const i2c3_groups[] = { "i2c3" };
+static const char *const i2c4_groups[] = { "i2c4" };
+static const char *const spi_groups[] = { "spi0", "ext_spi0_full" };
+static const char *const ext_spi1_groups[] = { "ext_spi1", "ext_spi1_full" };
+static const char *const ext_spi2_groups[] = { "ext_spi2", "ext_spi2_full" };
+static const char *const ext_spi3_groups[] = { "ext_spi3", "ext_spi3_full" };
+static const char *const pcm1_groups[] = { "pcm1" };
+static const char *const pcm2_groups[] = { "pcm2" };
+static const char *const pcm_spi_groups[] = { "pcm_spi", "pcm_spi_cs", "pcm_ctrl" };
+static const char *const i2s_groups[] = { "i2s" };
+static const char *const mdio0_groups[] = { "mdio0" };
+static const char *const mdio1_groups[] = { "mdio1" };
+static const char *const mdio2_groups[] = { "mdio2" };
+static const char *const mdcs_groups[] = { "mdcs" };
+static const char *const mdios_groups[] = { "mdios" };
+static const char *const emmc_groups[] = { "emmc" };
+static const char *const pcie0_groups[] = { "pcie0_rst", "pcie0_clkreq", "pcie0_wake" };
+static const char *const pcie1_groups[] = { "pcie1_rst", "pcie1_clkreq", "pcie1_wake" };
+static const char *const pcie2_groups[] = { "pcie2_rst", "pcie2_clkreq", "pcie2_wake" };
+static const char *const pon1_groups[] = { "pon1" };
+static const char *const pon2_groups[] = { "pon2" };
+static const char *const sgpio0_groups[] = { "sgpio0" };
+static const char *const sgpio1_groups[] = { "sgpio1" };
+static const char *const watchdog_groups[] = { "watchdog" };
+static const char *const shiftmux_spi_groups[] = { "shiftmux_spi" };
+static const char *const tod_groups[] = { "tod" };
+static const char *const sync_e_groups[] = { "sync_e" };
+static const char *const cpu_jtag_groups[] = { "cpu_jtag", "cpu_jtag_alt" };
+static const char *const npu_jtag_groups[] = { "npu_jtag" };
+static const char *const ibex_jtag_groups[] = { "ibex_jtag" };
+static const char *const pma50eth_jtag_groups[] = { "pma50eth_jtag" };
+static const char *const ainpu_jtag_groups[] = { "ainpu_jtag" };
+static const char *const pma50pon_jtag_groups[] = { "pma50pon_jtag" };
+static const char *const pwm_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6",
+ "gpio7", "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13",
+ "gpio14", "gpio15",
+};
+
+static const struct airoha_pinctrl_func_group uart1_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("uart1", uart1),
+};
+
+static const struct airoha_pinctrl_func_group uart2_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("uart2", uart2),
+};
+
+static const struct airoha_pinctrl_func_group uart3_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("uart3", uart3),
+ PINCTRL_MODE_FUNC_GROUP("uart3_alt", uart3_alt),
+};
+
+static const struct airoha_pinctrl_func_group uart4_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("uart4", uart4),
+};
+
+static const struct airoha_pinctrl_func_group uart5_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("uart5", uart5),
+ PINCTRL_MODE_FUNC_GROUP("uart5_alt", uart5_alt),
+ PINCTRL_MODE_FUNC_GROUP("uart5_full", uart5_full),
+};
+
+static const struct airoha_pinctrl_func_group uart6_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("uart6", uart6),
+ PINCTRL_MODE_FUNC_GROUP("uart6_full", uart6_full),
+};
+
+static const struct airoha_pinctrl_func_group i2c0_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("i2c0", i2c0),
+};
+
+static const struct airoha_pinctrl_func_group i2c1_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("i2c1", i2c1),
+};
+
+static const struct airoha_pinctrl_func_group i2c2_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("i2c2", i2c2),
+};
+
+static const struct airoha_pinctrl_func_group i2c3_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("i2c3", i2c3),
+};
+
+static const struct airoha_pinctrl_func_group i2c4_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("i2c4", i2c4),
+};
+
+static const struct airoha_pinctrl_func_group spi_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("spi0", spi0),
+ PINCTRL_MODE_FUNC_GROUP("ext_spi0_full", ext_spi0_full),
+};
+
+static const struct airoha_pinctrl_func_group ext_spi1_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("ext_spi1", ext_spi1),
+ PINCTRL_MODE_FUNC_GROUP("ext_spi1_full", ext_spi1_full),
+};
+
+static const struct airoha_pinctrl_func_group ext_spi2_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("ext_spi2", ext_spi2),
+ PINCTRL_MODE_FUNC_GROUP("ext_spi2_full", ext_spi2_full),
+};
+
+static const struct airoha_pinctrl_func_group ext_spi3_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("ext_spi3", ext_spi3),
+ PINCTRL_MODE_FUNC_GROUP("ext_spi3_full", ext_spi3_full),
+};
+
+static const struct airoha_pinctrl_func_group pcm1_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("pcm1", pcm1),
+};
+
+static const struct airoha_pinctrl_func_group pcm2_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("pcm2", pcm2),
+};
+
+static const struct airoha_pinctrl_func_group pcm_spi_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("pcm_spi", pcm_spi),
+ PINCTRL_MODE_FUNC_GROUP("pcm_spi_cs", pcm_spi_cs),
+ PINCTRL_MODE_FUNC_GROUP("pcm_ctrl", pcm_ctrl),
+};
+
+static const struct airoha_pinctrl_func_group i2s_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("i2s", i2s),
+};
+
+static const struct airoha_pinctrl_func_group mdio0_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("mdio0", mdio0),
+};
+
+static const struct airoha_pinctrl_func_group mdio1_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("mdio1", mdio1),
+};
+
+static const struct airoha_pinctrl_func_group mdio2_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("mdio2", mdio2),
+};
+
+static const struct airoha_pinctrl_func_group mdcs_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("mdcs", mdcs),
+};
+
+static const struct airoha_pinctrl_func_group mdios_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("mdios", mdios),
+};
+
+static const struct airoha_pinctrl_func_group emmc_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("emmc", emmc),
+};
+
+static const struct airoha_pinctrl_func_group pcie0_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("pcie0_rst", pcie0_rst),
+ PINCTRL_MODE_FUNC_GROUP("pcie0_clkreq", pcie0_clkreq),
+ PINCTRL_MODE_FUNC_GROUP("pcie0_wake", pcie0_wake),
+};
+
+static const struct airoha_pinctrl_func_group pcie1_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("pcie1_rst", pcie1_rst),
+ PINCTRL_MODE_FUNC_GROUP("pcie1_clkreq", pcie1_clkreq),
+ PINCTRL_MODE_FUNC_GROUP("pcie1_wake", pcie1_wake),
+};
+
+static const struct airoha_pinctrl_func_group pcie2_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("pcie2_rst", pcie2_rst),
+ PINCTRL_MODE_FUNC_GROUP("pcie2_clkreq", pcie2_clkreq),
+ PINCTRL_MODE_FUNC_GROUP("pcie2_wake", pcie2_wake),
+};
+
+static const struct airoha_pinctrl_func_group pon1_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("pon1", pon1),
+};
+
+static const struct airoha_pinctrl_func_group pon2_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("pon2", pon2),
+};
+
+static const struct airoha_pinctrl_func_group sgpio0_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("sgpio0", sgpio0),
+};
+
+static const struct airoha_pinctrl_func_group sgpio1_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("sgpio1", sgpio1),
+};
+
+static const struct airoha_pinctrl_func_group watchdog_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("watchdog", watchdog),
+};
+
+static const struct airoha_pinctrl_func_group shiftmux_spi_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("shiftmux_spi", shiftmux_spi),
+};
+
+static const struct airoha_pinctrl_func_group tod_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("tod", tod),
+};
+
+static const struct airoha_pinctrl_func_group sync_e_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("sync_e", sync_e),
+};
+
+static const struct airoha_pinctrl_func_group cpu_jtag_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("cpu_jtag", cpu_jtag),
+ PINCTRL_MODE_FUNC_GROUP("cpu_jtag_alt", cpu_jtag_alt),
+};
+
+static const struct airoha_pinctrl_func_group npu_jtag_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("npu_jtag", npu_jtag),
+};
+
+static const struct airoha_pinctrl_func_group ibex_jtag_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("ibex_jtag", ibex_jtag),
+};
+
+static const struct airoha_pinctrl_func_group pma50eth_jtag_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("pma50eth_jtag", pma50eth_jtag),
+};
+
+static const struct airoha_pinctrl_func_group ainpu_jtag_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("ainpu_jtag", ainpu_jtag),
+};
+
+static const struct airoha_pinctrl_func_group pma50pon_jtag_func_group[] = {
+ PINCTRL_MODE_FUNC_GROUP("pma50pon_jtag", pma50pon_jtag),
+};
+
+#define AN7589_PINCTRL_PWM(gpio, n) \
+ { \
+ .name = (gpio), \
+ .regmap[0] = { \
+ AIROHA_FUNC_PWM_MUX, \
+ REG_GPIO_FLASH_MODE_CFG, \
+ GPIO_FLASH_MODE_CFG(n), \
+ GPIO_FLASH_MODE_CFG(n) \
+ }, \
+ .regmap_size = 1, \
+ .pin_modes = pwm_modes, \
+ }
+
+static const struct airoha_pinctrl_func_group pwm_func_group[] = {
+ AN7589_PINCTRL_PWM("gpio0", 0),
+ AN7589_PINCTRL_PWM("gpio1", 1),
+ AN7589_PINCTRL_PWM("gpio2", 2),
+ AN7589_PINCTRL_PWM("gpio3", 3),
+ AN7589_PINCTRL_PWM("gpio4", 4),
+ AN7589_PINCTRL_PWM("gpio5", 5),
+ AN7589_PINCTRL_PWM("gpio6", 6),
+ AN7589_PINCTRL_PWM("gpio7", 7),
+ AN7589_PINCTRL_PWM("gpio8", 8),
+ AN7589_PINCTRL_PWM("gpio9", 9),
+ AN7589_PINCTRL_PWM("gpio10", 10),
+ AN7589_PINCTRL_PWM("gpio11", 11),
+ AN7589_PINCTRL_PWM("gpio12", 12),
+ AN7589_PINCTRL_PWM("gpio13", 13),
+ AN7589_PINCTRL_PWM("gpio14", 14),
+ AN7589_PINCTRL_PWM("gpio15", 15),
+};
+
+static const struct airoha_pinctrl_func pinctrl_funcs[] = {
+ PINCTRL_FUNC_DESC("uart1", uart1),
+ PINCTRL_FUNC_DESC("uart2", uart2),
+ PINCTRL_FUNC_DESC("uart3", uart3),
+ PINCTRL_FUNC_DESC("uart4", uart4),
+ PINCTRL_FUNC_DESC("uart5", uart5),
+ PINCTRL_FUNC_DESC("uart6", uart6),
+ PINCTRL_FUNC_DESC("i2c0", i2c0),
+ PINCTRL_FUNC_DESC("i2c1", i2c1),
+ PINCTRL_FUNC_DESC("i2c2", i2c2),
+ PINCTRL_FUNC_DESC("i2c3", i2c3),
+ PINCTRL_FUNC_DESC("i2c4", i2c4),
+ PINCTRL_FUNC_DESC("spi", spi),
+ PINCTRL_FUNC_DESC("ext_spi1", ext_spi1),
+ PINCTRL_FUNC_DESC("ext_spi2", ext_spi2),
+ PINCTRL_FUNC_DESC("ext_spi3", ext_spi3),
+ PINCTRL_FUNC_DESC("pcm1", pcm1),
+ PINCTRL_FUNC_DESC("pcm2", pcm2),
+ PINCTRL_FUNC_DESC("pcm_spi", pcm_spi),
+ PINCTRL_FUNC_DESC("i2s", i2s),
+ PINCTRL_FUNC_DESC("mdio0", mdio0),
+ PINCTRL_FUNC_DESC("mdio1", mdio1),
+ PINCTRL_FUNC_DESC("mdio2", mdio2),
+ PINCTRL_FUNC_DESC("mdcs", mdcs),
+ PINCTRL_FUNC_DESC("mdios", mdios),
+ PINCTRL_FUNC_DESC("emmc", emmc),
+ PINCTRL_FUNC_DESC("pcie0", pcie0),
+ PINCTRL_FUNC_DESC("pcie1", pcie1),
+ PINCTRL_FUNC_DESC("pcie2", pcie2),
+ PINCTRL_FUNC_DESC("pon1", pon1),
+ PINCTRL_FUNC_DESC("pon2", pon2),
+ PINCTRL_FUNC_DESC("sgpio0", sgpio0),
+ PINCTRL_FUNC_DESC("sgpio1", sgpio1),
+ PINCTRL_FUNC_DESC("watchdog", watchdog),
+ PINCTRL_FUNC_DESC("shiftmux_spi", shiftmux_spi),
+ PINCTRL_FUNC_DESC("tod", tod),
+ PINCTRL_FUNC_DESC("sync_e", sync_e),
+ PINCTRL_FUNC_DESC("cpu_jtag", cpu_jtag),
+ PINCTRL_FUNC_DESC("npu_jtag", npu_jtag),
+ PINCTRL_FUNC_DESC("ibex_jtag", ibex_jtag),
+ PINCTRL_FUNC_DESC("pma50eth_jtag", pma50eth_jtag),
+ PINCTRL_FUNC_DESC("ainpu_jtag", ainpu_jtag),
+ PINCTRL_FUNC_DESC("pma50pon_jtag", pma50pon_jtag),
+ PINCTRL_FUNC_DESC("pwm", pwm),
+};
+
+static const struct airoha_pinctrl_match_data pinctrl_match_data = {
+ .iomux_info = &iomux_info,
+ .pinctrl_name = KBUILD_MODNAME,
+ .pinctrl_owner = THIS_MODULE,
+ .gpio_regs = &gpiochip_regs,
+ .pins = pinctrl_pins,
+ .num_pins = ARRAY_SIZE(pinctrl_pins),
+ .grps = pinctrl_groups,
+ .num_grps = ARRAY_SIZE(pinctrl_groups),
+ .funcs = pinctrl_funcs,
+ .num_funcs = ARRAY_SIZE(pinctrl_funcs),
+ .num_irq_pins = AN7589_NUM_PINS,
+};
+
+static const struct of_device_id airoha_pinctrl_of_match[] = {
+ { .compatible = "airoha,an7589-pinctrl", .data = &pinctrl_match_data },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, airoha_pinctrl_of_match);
+
+static struct platform_driver airoha_pinctrl_driver = {
+ .probe = airoha_pinctrl_probe,
+ .driver = {
+ .name = "pinctrl-airoha-an7589",
+ .of_match_table = airoha_pinctrl_of_match,
+ },
+};
+module_platform_driver(airoha_pinctrl_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("John Crispin <john@phrozen.org>");
+MODULE_DESCRIPTION("Pinctrl driver for Airoha AN7589 SoC");
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 5/7] dt-bindings: pinctrl: airoha: add AN7589
2026-11-10 17:39 ` [PATCH 5/7] dt-bindings: pinctrl: airoha: add AN7589 John Crispin
@ 2026-11-10 18:27 ` Conor Dooley
0 siblings, 0 replies; 9+ messages in thread
From: Conor Dooley @ 2026-11-10 18:27 UTC (permalink / raw)
To: John Crispin
Cc: Lorenzo Bianconi, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Linus Walleij, Bartosz Golaszewski, Ahmed Naseef,
Benjamin Larsson, Christian Marangi, devicetree, lei.dong,
Linqi.zhang, linux-gpio, linux-kernel, linux-mediatek, mfd,
Mikhail Kshevetskiy, Rajeev.kumar, upstream, Weifeng.xu,
zhengping.zhang
[-- Attachment #1: Type: text/plain, Size: 16936 bytes --]
On Tue, Nov 10, 2026 at 06:39:39PM +0100, John Crispin wrote:
> diff --git a/Documentation/devicetree/bindings/pinctrl/airoha,an7589-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/airoha,an7589-pinctrl.yaml
> new file mode 100644
> index 000000000000..546e333f3467
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/airoha,an7589-pinctrl.yaml
> @@ -0,0 +1,533 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/pinctrl/airoha,an7589-pinctrl.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Airoha AN7589 Pin Controller
> +
> +maintainers:
> + - John Crispin <john@phrozen.org>
> +
> +description:
> + The Airoha AN7589 pin controller is used to control SoC pins. Pin
> + functions are selected through a separate IOMUX register block, one
> + mode field per pin. Every pin is a GPIO in mode 0.
> +
> +properties:
> + compatible:
> + const: airoha,an7589-pinctrl
> +
> + airoha,iomux:
> + $ref: /schemas/types.yaml#/definitions/phandle
> + description:
> + Phandle to the IOMUX syscon holding the per pin mode fields.
> +
> + interrupts:
> + maxItems: 1
> +
> + gpio-controller: true
> +
> + '#gpio-cells':
> + const: 2
> +
> + gpio-ranges:
> + maxItems: 1
> +
> + interrupt-controller: true
> +
> + '#interrupt-cells':
> + const: 2
> +
> +allOf:
> + - $ref: pinctrl.yaml#
> +
> +required:
> + - compatible
> + - airoha,iomux
> + - interrupts
> + - gpio-controller
> + - "#gpio-cells"
> + - interrupt-controller
> + - "#interrupt-cells"
> +
> +patternProperties:
> + '-pins$':
> + type: object
> +
> + patternProperties:
> + '^mux(-|$)':
> + type: object
> +
> + description:
> + pinmux configuration nodes.
> +
> + $ref: /schemas/pinctrl/pinmux-node.yaml
> +
> + properties:
> + function:
> + description:
> + A string containing the name of the function to mux to the group.
> + enum: [uart1, uart2, uart3, uart4, uart5, uart6, i2c0, i2c1,
> + i2c2, i2c3, i2c4, spi, ext_spi1, ext_spi2, ext_spi3,
> + pcm1, pcm2, pcm_spi, i2s, mdio0, mdio1, mdio2, mdcs,
> + mdios, emmc, pcie0, pcie1, pcie2, pon1, pon2, sgpio0,
> + sgpio1, watchdog, shiftmux_spi, tod, sync_e, cpu_jtag,
> + npu_jtag, ibex_jtag, pma50eth_jtag, ainpu_jtag,
> + pma50pon_jtag, pwm]
> +
> + groups:
> + description:
> + An array of strings. Each string contains the name of a group.
> +
> + required:
> + - function
> + - groups
> +
> + allOf:
> + - if:
> + properties:
> + function:
> + const: uart1
> + then:
> + properties:
> + groups:
> + enum: [uart1]
This stuff here is a signal to me that the functions are too detailed.
Each group here can only be one uart, so all you need is a function
called "uart"?
That said, you need to define the groups as you've done for the
functions.
> + - if:
> + properties:
> + function:
> + const: uart2
> + then:
> + properties:
> + groups:
> + enum: [uart2]
> + - if:
> + properties:
> + function:
> + const: uart3
> + then:
> + properties:
> + groups:
> + items:
> + enum: [uart3, uart3_alt]
> + maxItems: 2
> + - if:
> + properties:
> + function:
> + const: uart4
> + then:
> + properties:
> + groups:
> + enum: [uart4]
> + - if:
> + properties:
> + function:
> + const: uart5
> + then:
> + properties:
> + groups:
> + items:
> + enum: [uart5, uart5_alt, uart5_full]
> + maxItems: 3
> + - if:
> + properties:
> + function:
> + const: uart6
> + then:
> + properties:
> + groups:
> + items:
> + enum: [uart6, uart6_full]
> + maxItems: 2
> + - if:
> + properties:
> + function:
> + const: i2c0
> + then:
> + properties:
> + groups:
> + enum: [i2c0]
It's the same ehre, seemingly i2c0 can only go to the group named i2c0,
so there's no point having each i2c as a different function.
This seems to apply to every function here, so the binding can be
simplified significantly.
pw-bot: changes-requested
Thanks,
Conor.
> + - if:
> + properties:
> + function:
> + const: i2c1
> + then:
> + properties:
> + groups:
> + enum: [i2c1]
> + - if:
> + properties:
> + function:
> + const: i2c2
> + then:
> + properties:
> + groups:
> + enum: [i2c2]
> + - if:
> + properties:
> + function:
> + const: i2c3
> + then:
> + properties:
> + groups:
> + enum: [i2c3]
> + - if:
> + properties:
> + function:
> + const: i2c4
> + then:
> + properties:
> + groups:
> + enum: [i2c4]
> + - if:
> + properties:
> + function:
> + const: spi
> + then:
> + properties:
> + groups:
> + items:
> + enum: [spi0, ext_spi0_full]
> + maxItems: 2
> + - if:
> + properties:
> + function:
> + const: ext_spi1
> + then:
> + properties:
> + groups:
> + items:
> + enum: [ext_spi1, ext_spi1_full]
> + maxItems: 2
> + - if:
> + properties:
> + function:
> + const: ext_spi2
> + then:
> + properties:
> + groups:
> + items:
> + enum: [ext_spi2, ext_spi2_full]
> + maxItems: 2
> + - if:
> + properties:
> + function:
> + const: ext_spi3
> + then:
> + properties:
> + groups:
> + items:
> + enum: [ext_spi3, ext_spi3_full]
> + maxItems: 2
> + - if:
> + properties:
> + function:
> + const: pcm1
> + then:
> + properties:
> + groups:
> + enum: [pcm1]
> + - if:
> + properties:
> + function:
> + const: pcm2
> + then:
> + properties:
> + groups:
> + enum: [pcm2]
> + - if:
> + properties:
> + function:
> + const: pcm_spi
> + then:
> + properties:
> + groups:
> + items:
> + enum: [pcm_spi, pcm_spi_cs, pcm_ctrl]
> + maxItems: 3
> + - if:
> + properties:
> + function:
> + const: i2s
> + then:
> + properties:
> + groups:
> + enum: [i2s]
> + - if:
> + properties:
> + function:
> + const: mdio0
> + then:
> + properties:
> + groups:
> + enum: [mdio0]
> + - if:
> + properties:
> + function:
> + const: mdio1
> + then:
> + properties:
> + groups:
> + enum: [mdio1]
> + - if:
> + properties:
> + function:
> + const: mdio2
> + then:
> + properties:
> + groups:
> + enum: [mdio2]
> + - if:
> + properties:
> + function:
> + const: mdcs
> + then:
> + properties:
> + groups:
> + enum: [mdcs]
> + - if:
> + properties:
> + function:
> + const: mdios
> + then:
> + properties:
> + groups:
> + enum: [mdios]
> + - if:
> + properties:
> + function:
> + const: emmc
> + then:
> + properties:
> + groups:
> + enum: [emmc]
> + - if:
> + properties:
> + function:
> + const: pcie0
> + then:
> + properties:
> + groups:
> + items:
> + enum: [pcie0_rst, pcie0_clkreq, pcie0_wake]
> + maxItems: 3
> + - if:
> + properties:
> + function:
> + const: pcie1
> + then:
> + properties:
> + groups:
> + items:
> + enum: [pcie1_rst, pcie1_clkreq, pcie1_wake]
> + maxItems: 3
> + - if:
> + properties:
> + function:
> + const: pcie2
> + then:
> + properties:
> + groups:
> + items:
> + enum: [pcie2_rst, pcie2_clkreq, pcie2_wake]
> + maxItems: 3
> + - if:
> + properties:
> + function:
> + const: pon1
> + then:
> + properties:
> + groups:
> + enum: [pon1]
> + - if:
> + properties:
> + function:
> + const: pon2
> + then:
> + properties:
> + groups:
> + enum: [pon2]
> + - if:
> + properties:
> + function:
> + const: sgpio0
> + then:
> + properties:
> + groups:
> + enum: [sgpio0]
> + - if:
> + properties:
> + function:
> + const: sgpio1
> + then:
> + properties:
> + groups:
> + enum: [sgpio1]
> + - if:
> + properties:
> + function:
> + const: watchdog
> + then:
> + properties:
> + groups:
> + enum: [watchdog]
> + - if:
> + properties:
> + function:
> + const: shiftmux_spi
> + then:
> + properties:
> + groups:
> + enum: [shiftmux_spi]
> + - if:
> + properties:
> + function:
> + const: tod
> + then:
> + properties:
> + groups:
> + enum: [tod]
> + - if:
> + properties:
> + function:
> + const: sync_e
> + then:
> + properties:
> + groups:
> + enum: [sync_e]
> + - if:
> + properties:
> + function:
> + const: cpu_jtag
> + then:
> + properties:
> + groups:
> + enum: [cpu_jtag, cpu_jtag_alt]
> + - if:
> + properties:
> + function:
> + const: npu_jtag
> + then:
> + properties:
> + groups:
> + enum: [npu_jtag]
> + - if:
> + properties:
> + function:
> + const: ibex_jtag
> + then:
> + properties:
> + groups:
> + enum: [ibex_jtag]
> + - if:
> + properties:
> + function:
> + const: pma50eth_jtag
> + then:
> + properties:
> + groups:
> + enum: [pma50eth_jtag]
> + - if:
> + properties:
> + function:
> + const: ainpu_jtag
> + then:
> + properties:
> + groups:
> + enum: [ainpu_jtag]
> + - if:
> + properties:
> + function:
> + const: pma50pon_jtag
> + then:
> + properties:
> + groups:
> + enum: [pma50pon_jtag]
> + - if:
> + properties:
> + function:
> + const: pwm
> + then:
> + properties:
> + groups:
> + items:
> + enum: [gpio0, gpio1, gpio2, gpio3, gpio4, gpio5, gpio6,
> + gpio7, gpio8, gpio9, gpio10, gpio11, gpio12,
> + gpio13, gpio14, gpio15]
> +
> + additionalProperties: false
> +
> + '^conf(-|$)':
> + type: object
> +
> + description:
> + pinconf configuration nodes.
> +
> + $ref: /schemas/pinctrl/pincfg-node.yaml
> +
> + properties:
> + pins:
> + description:
> + An array of strings. Each string contains the name of a pin.
> + items:
> + pattern: '^gpio([0-9]|[1-6][0-9]|7[0-3])$'
> + minItems: 1
> + maxItems: 74
> +
> + input-enable: true
> +
> + output-enable: true
> +
> + output-low: true
> +
> + output-high: true
> +
> + required:
> + - pins
> +
> + additionalProperties: false
> +
> + additionalProperties: false
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> + pinctrl {
> + compatible = "airoha,an7589-pinctrl";
> + airoha,iomux = <&iomux>;
> +
> + interrupt-parent = <&gic>;
> + interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
> +
> + gpio-controller;
> + #gpio-cells = <2>;
> +
> + interrupt-controller;
> + #interrupt-cells = <2>;
> +
> + gpio-ranges = <&pinctrl 0 0 74>;
> +
> + mmc-pins {
> + mux {
> + function = "emmc";
> + groups = "emmc";
> + };
> + };
> +
> + pcie0-pins {
> + mux {
> + function = "pcie0";
> + groups = "pcie0_rst", "pcie0_clkreq", "pcie0_wake";
> + };
> + };
> +
> + uart5-pins {
> + mux {
> + function = "uart5";
> + groups = "uart5", "uart5_full";
> + };
> + };
> + };
> diff --git a/MAINTAINERS b/MAINTAINERS
> index aa647f5d37dd..2041a8aed28f 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -22137,6 +22137,8 @@ PIN CONTROLLER - AIROHA
> M: Lorenzo Bianconi <lorenzo@kernel.org>
> L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
> S: Maintained
> +F: Documentation/devicetree/bindings/mfd/airoha,an7589-gpio-sysctl.yaml
> +F: Documentation/devicetree/bindings/pinctrl/airoha,an7589-pinctrl.yaml
> F: Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml
> F: drivers/pinctrl/airoha/pinctrl-airoha.c
>
> --
> 2.34.1
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-11-10 18:28 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-10 17:39 [PATCH 0/7] pinctrl: airoha: add AN7589 support John Crispin
2026-11-10 17:39 ` [PATCH 1/7] pinctrl: airoha: make gpio register layout per SoC John Crispin
2026-11-10 17:39 ` [PATCH 2/7] pinctrl: airoha: add per pin mode field mux John Crispin
2026-11-10 17:39 ` [PATCH 3/7] pinctrl: airoha: make the chip SCU optional John Crispin
2026-11-10 17:39 ` [PATCH 4/7] pinctrl: airoha: mux a requested GPIO through the IOMUX John Crispin
2026-11-10 17:39 ` [PATCH 5/7] dt-bindings: pinctrl: airoha: add AN7589 John Crispin
2026-11-10 18:27 ` Conor Dooley
2026-11-10 17:39 ` [PATCH 6/7] pinctrl: airoha: move the GPIO register offsets to the common header John Crispin
2026-11-10 17:39 ` [PATCH 7/7] pinctrl: airoha: add support of an7589 SoC John Crispin
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®