* [PATCH 0/3] pinctrl: ingenic: Add X2600 support
@ 2026-11-13 8:14 H. Nikolaus Schaller
2026-11-13 8:14 ` [PATCH 1/3] dt-bindings: " H. Nikolaus Schaller
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: H. Nikolaus Schaller @ 2026-11-13 8:14 UTC (permalink / raw)
To: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Paul Cercueil, Bartosz Golaszewski
Cc: linux-gpio, devicetree, linux-kernel, linux-mips, letux-kernel,
H. Nikolaus Schaller
PATCH V1 2026-11-13 09:13:47:
This series adds pinctrl and GPIO support for the Lumissil X2600
SoC.
It introduces the devicetree bindings, adapts the register access
and GPIO interrupt handling to the X2600 hardware, and adds the
pin groups and mux functions.
The changes also correct hardware both-edge GPIO interrupt
configuration on X1600 and X2000.
The updated driver has been tested on X1600, X2000, and X2600
including GPIO both-edge interrupt handling.
The code has been tested by ChatGPT which also helped to formulate
the messages.
H. Nikolaus Schaller (3):
dt-bindings: pinctrl: ingenic: Add X2600 support
pinctrl: ingenic: Add X2600 register and GPIO IRQ support
pinctrl: ingenic: Add X2600 pin groups and functions
.../bindings/pinctrl/ingenic,pinctrl.yaml | 10 +-
drivers/pinctrl/pinctrl-ingenic.c | 573 +++++++++++++++++-
2 files changed, 566 insertions(+), 17 deletions(-)
--
2.56.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/3] dt-bindings: pinctrl: ingenic: Add X2600 support
2026-11-13 8:14 [PATCH 0/3] pinctrl: ingenic: Add X2600 support H. Nikolaus Schaller
@ 2026-11-13 8:14 ` H. Nikolaus Schaller
2026-11-13 8:14 ` [PATCH 2/3] pinctrl: ingenic: Add X2600 register and GPIO IRQ support H. Nikolaus Schaller
2026-11-13 8:14 ` [PATCH 3/3] pinctrl: ingenic: Add X2600 pin groups and functions H. Nikolaus Schaller
2 siblings, 0 replies; 6+ messages in thread
From: H. Nikolaus Schaller @ 2026-11-13 8:14 UTC (permalink / raw)
To: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Paul Cercueil, Bartosz Golaszewski
Cc: linux-gpio, devicetree, linux-kernel, linux-mips, letux-kernel,
H. Nikolaus Schaller
Add the pinctrl and GPIO compatible strings for the Lumissil
X2600 SoC.
The X2600 provides five GPIO ports with 32 pins each.
Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
---
.../devicetree/bindings/pinctrl/ingenic,pinctrl.yaml | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.yaml
index 84e960255a36d..05c1a31469a42 100644
--- a/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.yaml
@@ -19,10 +19,10 @@ description: >
pin within that GPIO port. For example PA0 is the first pin in GPIO port A,
and PB31 is the last pin in GPIO port B. The JZ4730, the JZ4740, the JZ4725B,
the X1000 and the X1830 contains 4 GPIO ports, PA to PD, for a total of 128
- pins. The X2000 and the X2100 contains 5 GPIO ports, PA to PE, for a total of
- 160 pins. The JZ4750, the JZ4755 the JZ4760, the JZ4770 and the JZ4780 contains
- 6 GPIO ports, PA to PF, for a total of 192 pins. The JZ4775 contains 7 GPIO
- ports, PA to PG, for a total of 224 pins.
+ pins. The X2000, the X2100 and the X2600 contains 5 GPIO ports, PA to PE, for a
+ total of 160 pins. The JZ4750, the JZ4755 the JZ4760, the JZ4770 and the JZ4780
+ contains 6 GPIO ports, PA to PF, for a total of 192 pins. The JZ4775 contains
+ 7 GPIO ports, PA to PG, for a total of 224 pins.
maintainers:
- Paul Cercueil <paul@crapouillou.net>
@@ -46,6 +46,7 @@ properties:
- ingenic,x1830-pinctrl
- ingenic,x2000-pinctrl
- ingenic,x2100-pinctrl
+ - ingenic,x2600-pinctrl
- items:
- const: ingenic,jz4760b-pinctrl
- const: ingenic,jz4760-pinctrl
@@ -86,6 +87,7 @@ patternProperties:
- ingenic,x1830-gpio
- ingenic,x2000-gpio
- ingenic,x2100-gpio
+ - ingenic,x2600-gpio
reg:
items:
--
2.56.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/3] pinctrl: ingenic: Add X2600 register and GPIO IRQ support
2026-11-13 8:14 [PATCH 0/3] pinctrl: ingenic: Add X2600 support H. Nikolaus Schaller
2026-11-13 8:14 ` [PATCH 1/3] dt-bindings: " H. Nikolaus Schaller
@ 2026-11-13 8:14 ` H. Nikolaus Schaller
2026-11-13 8:26 ` sashiko-bot
2026-11-13 8:14 ` [PATCH 3/3] pinctrl: ingenic: Add X2600 pin groups and functions H. Nikolaus Schaller
2 siblings, 1 reply; 6+ messages in thread
From: H. Nikolaus Schaller @ 2026-11-13 8:14 UTC (permalink / raw)
To: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Paul Cercueil, Bartosz Golaszewski
Cc: linux-gpio, devicetree, linux-kernel, linux-mips, letux-kernel,
H. Nikolaus Schaller
Add the X2600 SoC ID and adapt the GPIO register access functions
to its register layout.
Unlike earlier Ingenic SoCs, the X2600 uses a register bank
spacing of 0x1000 and provides separate shadow registers and
load registers for each GPIO port. It also uses a dedicated
register for clearing GPIO interrupt flags.
Update the GPIO interrupt configuration to account for hardware
dual-edge detection on X1600, X2000 and X2600. These SoCs require
PAT1 to be set when dual-edge detection is enabled, while X1000
and X1830 continue to use software emulation.
The corrected interrupt configuration has been tested on X1600,
X2000, and X2600, including GPIO dual-edge interrupts by a
gpio-button.
Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
---
drivers/pinctrl/pinctrl-ingenic.c | 71 +++++++++++++++++++++++++------
1 file changed, 58 insertions(+), 13 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c
index a62532c49fb60..90c734c74d267 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -70,6 +70,10 @@
#define X2000_GPIO_SR 0xd0
#define X2000_GPIO_SMT 0xe0
+#define X2600_GPIO_FLAG_CLR 0x58 /* write only */
+#define X2600_GPIO_SHADOW_OFFSET 0x800
+#define X2600_GPIO_PAGLD (X2600_GPIO_SHADOW_OFFSET + 0xf0)
+
#define REG_SET(x) ((x) + 0x4)
#define REG_CLEAR(x) ((x) + 0x8)
@@ -114,6 +118,7 @@ enum jz_version {
ID_X1830,
ID_X2000,
ID_X2100,
+ ID_X2600,
};
struct ingenic_chip_info {
@@ -164,7 +169,8 @@ static const unsigned long enabled_socs =
IS_ENABLED(CONFIG_MACH_X1600) << ID_X1600 |
IS_ENABLED(CONFIG_MACH_X1830) << ID_X1830 |
IS_ENABLED(CONFIG_MACH_X2000) << ID_X2000 |
- IS_ENABLED(CONFIG_MACH_X2100) << ID_X2100;
+ IS_ENABLED(CONFIG_MACH_X2100) << ID_X2100 |
+ IS_ENABLED(CONFIG_MACH_X2600) << ID_X2600;
static bool
is_soc_or_above(const struct ingenic_pinctrl *jzpc, enum jz_version version)
@@ -3545,15 +3551,21 @@ static void ingenic_gpio_shadow_set_bit(struct ingenic_gpio_chip *jzgc,
else
reg = REG_CLEAR(reg);
- regmap_write(jzgc->jzpc->map, REG_PZ_BASE(
- jzgc->jzpc->info->reg_offset) + reg, BIT(offset));
+ if (is_soc_or_above(jzgc->jzpc, ID_X2600))
+ regmap_write(jzgc->jzpc->map, jzgc->reg_base + X2600_GPIO_SHADOW_OFFSET + reg,
+ BIT(offset));
+ else
+ regmap_write(jzgc->jzpc->map, REG_PZ_BASE(jzgc->jzpc->info->reg_offset) + reg,
+ BIT(offset));
}
static void ingenic_gpio_shadow_set_bit_load(struct ingenic_gpio_chip *jzgc)
{
- regmap_write(jzgc->jzpc->map, REG_PZ_GID2LD(
- jzgc->jzpc->info->reg_offset),
- jzgc->gc.base / PINS_PER_GPIO_CHIP);
+ if (is_soc_or_above(jzgc->jzpc, ID_X2600))
+ regmap_write(jzgc->jzpc->map, jzgc->reg_base + X2600_GPIO_PAGLD, 1);
+ else
+ regmap_write(jzgc->jzpc->map, REG_PZ_GID2LD(jzgc->jzpc->info->reg_offset),
+ jzgc->gc.base / PINS_PER_GPIO_CHIP);
}
static void jz4730_gpio_set_bits(struct ingenic_gpio_chip *jzgc,
@@ -3618,6 +3630,12 @@ static void irq_set_type(struct ingenic_gpio_chip *jzgc,
break;
}
+ if (type == IRQ_TYPE_EDGE_BOTH &&
+ (is_soc_or_above(jzgc->jzpc, ID_X2000) ||
+ (is_soc_or_above(jzgc->jzpc, ID_X1600) &&
+ !is_soc_or_above(jzgc->jzpc, ID_X1830))))
+ val2 = true;
+
if (is_soc_or_above(jzgc->jzpc, ID_JZ4770)) {
reg1 = JZ4770_GPIO_PAT1;
reg2 = JZ4770_GPIO_PAT0;
@@ -3640,6 +3658,9 @@ static void irq_set_type(struct ingenic_gpio_chip *jzgc,
ingenic_gpio_shadow_set_bit(jzgc, reg2, offset, val1);
ingenic_gpio_shadow_set_bit(jzgc, reg1, offset, val2);
ingenic_gpio_shadow_set_bit_load(jzgc);
+
+ if (is_soc_or_above(jzgc->jzpc, ID_X1600) && !is_soc_or_above(jzgc->jzpc, ID_X1830))
+ ingenic_gpio_set_bit(jzgc, X2000_GPIO_EDG, offset, val3);
} else {
ingenic_gpio_set_bit(jzgc, reg2, offset, val1);
ingenic_gpio_set_bit(jzgc, reg1, offset, val2);
@@ -3714,7 +3735,8 @@ static void ingenic_gpio_irq_ack(struct irq_data *irqd)
bool high;
if ((irqd_get_trigger_type(irqd) == IRQ_TYPE_EDGE_BOTH) &&
- !is_soc_or_above(jzgc->jzpc, ID_X2000)) {
+ (!is_soc_or_above(jzgc->jzpc, ID_X1600) ||
+ (is_soc_or_above(jzgc->jzpc, ID_X1830) && !is_soc_or_above(jzgc->jzpc, ID_X2000)))) {
/*
* Switch to an interrupt for the opposite edge to the one that
* triggered the interrupt being ACKed.
@@ -3726,7 +3748,9 @@ static void ingenic_gpio_irq_ack(struct irq_data *irqd)
irq_set_type(jzgc, irq, IRQ_TYPE_LEVEL_HIGH);
}
- if (is_soc_or_above(jzgc->jzpc, ID_JZ4770))
+ if (is_soc_or_above(jzgc->jzpc, ID_X2600))
+ regmap_write(jzgc->jzpc->map, jzgc->reg_base + X2600_GPIO_FLAG_CLR, BIT(irq));
+ else if (is_soc_or_above(jzgc->jzpc, ID_JZ4770))
ingenic_gpio_set_bit(jzgc, JZ4770_GPIO_FLAG, irq, false);
else if (is_soc_or_above(jzgc->jzpc, ID_JZ4740))
ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_DATA, irq, true);
@@ -3754,7 +3778,9 @@ static int ingenic_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
irq_set_handler_locked(irqd, handle_bad_irq);
}
- if ((type == IRQ_TYPE_EDGE_BOTH) && !is_soc_or_above(jzgc->jzpc, ID_X2000)) {
+ if (type == IRQ_TYPE_EDGE_BOTH &&
+ (!is_soc_or_above(jzgc->jzpc, ID_X1600) ||
+ (is_soc_or_above(jzgc->jzpc, ID_X1830) && !is_soc_or_above(jzgc->jzpc, ID_X2000)))) {
/*
* The hardware does not support interrupts on both edges. The
* best we can do is to set up a single-edge interrupt and then
@@ -3849,16 +3875,35 @@ static inline void ingenic_shadow_config_pin(struct ingenic_pinctrl *jzpc,
unsigned int pin, u8 reg, bool set)
{
unsigned int idx = pin % PINS_PER_GPIO_CHIP;
+ unsigned int offt = pin / PINS_PER_GPIO_CHIP;
- regmap_write(jzpc->map, REG_PZ_BASE(jzpc->info->reg_offset) +
- (set ? REG_SET(reg) : REG_CLEAR(reg)), BIT(idx));
+ if (set)
+ reg = REG_SET(reg);
+ else
+ reg = REG_CLEAR(reg);
+
+ if (is_soc_or_above(jzpc, ID_X2600)) {
+ u32 target_reg = (offt * jzpc->info->reg_offset) + X2600_GPIO_SHADOW_OFFSET + reg;
+
+ regmap_write(jzpc->map, target_reg, BIT(idx));
+ } else {
+ regmap_write(jzpc->map, REG_PZ_BASE(jzpc->info->reg_offset) + reg, BIT(idx));
+ }
}
static inline void ingenic_shadow_config_pin_load(struct ingenic_pinctrl *jzpc,
unsigned int pin)
{
- regmap_write(jzpc->map, REG_PZ_GID2LD(jzpc->info->reg_offset),
- pin / PINS_PER_GPIO_CHIP);
+ unsigned int offt = pin / PINS_PER_GPIO_CHIP;
+
+ if (is_soc_or_above(jzpc, ID_X2600)) {
+ u32 target_load_reg = (offt * jzpc->info->reg_offset) + X2600_GPIO_PAGLD;
+
+ regmap_write(jzpc->map, target_load_reg, 1);
+ } else {
+ regmap_write(jzpc->map, REG_PZ_GID2LD(jzpc->info->reg_offset),
+ pin / PINS_PER_GPIO_CHIP);
+ }
}
static inline void jz4730_config_pin_function(struct ingenic_pinctrl *jzpc,
--
2.56.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/3] pinctrl: ingenic: Add X2600 pin groups and functions
2026-11-13 8:14 [PATCH 0/3] pinctrl: ingenic: Add X2600 support H. Nikolaus Schaller
2026-11-13 8:14 ` [PATCH 1/3] dt-bindings: " H. Nikolaus Schaller
2026-11-13 8:14 ` [PATCH 2/3] pinctrl: ingenic: Add X2600 register and GPIO IRQ support H. Nikolaus Schaller
@ 2026-11-13 8:14 ` H. Nikolaus Schaller
2026-11-13 8:37 ` sashiko-bot
2 siblings, 1 reply; 6+ messages in thread
From: H. Nikolaus Schaller @ 2026-11-13 8:14 UTC (permalink / raw)
To: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Paul Cercueil, Bartosz Golaszewski
Cc: linux-gpio, devicetree, linux-kernel, linux-mips, letux-kernel,
H. Nikolaus Schaller
Add the pin groups, mux functions and GPIO configuration data
for the Lumissil X2600 SoC.
The X2600 provides five GPIO ports with configurable pull-up
and pull-down support on selected pins.
Define the register access ranges for the X2600 GPIO controller,
which uses a bank spacing of 0x1000 instead of 0x100 and includes
additional registers beyond the first 0x100 bytes of each bank.
Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
---
drivers/pinctrl/pinctrl-ingenic.c | 502 ++++++++++++++++++++++++++++++
1 file changed, 502 insertions(+)
diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c
index 90c734c74d267..a0bdf5eb6a672 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -3517,6 +3517,503 @@ static const struct ingenic_chip_info x2100_chip_info = {
.access_table = &x2000_access_table,
};
+static const u32 x2600_pull_ups[5] = {
+ 0x000007ff, 0xffffffff, 0x7ffbfff, 0x0000ffff, 0x000ffffe,
+};
+
+static const u32 x2600_pull_downs[5] = {
+ 0x000007ff, 0xffffffff, 0x01ffff1, 0x0001e000, 0x000fffff,
+};
+
+static int x2600_can0_pins[] = { 0x47, 0x48, };
+static int x2600_can1_pins[] = { 0x49, 0x4a, };
+
+static int x2600_cim_pins[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b,
+};
+
+static int x2600_clk_pins[] = { 0x82, };
+
+static int x2600_dmic_pins[] = { 0x44, 0x45, 0x46, };
+
+static int x2600_i2c0_c_pins[] = { 0x40, 0x41, };
+static int x2600_i2c0_d_pins[] = { 0x64, 0x63, };
+
+static int x2600_i2c1_b_pins[] = { 0x20, 0x21, };
+static int x2600_i2c1_c_pins[] = { 0x42, 0x43, };
+
+static int x2600_i2c2_b_pins[] = { 0x23, 0x22, };
+static int x2600_i2c2_c_pins[] = { 0x53, 0x54, };
+static int x2600_i2c3_c_pins[] = { 0x55, 0x56, };
+static int x2600_i2c3_e_pins[] = { 0x85, 0x86, };
+
+static int x2600_i2s_clk_rx_pins[] = { 0x4f, }; /* PC15 */
+static int x2600_i2s_sysclk_pins[] = { 0x50, }; /* PC16 */
+static int x2600_i2s_clk_tx_pins[] = { 0x51, }; /* PC17 */
+static int x2600_i2s_data_pins[] = { 0x52, 0x53, }; /* PC18, PC19 */
+
+static int x2600_lcd_16bit_pins[] = {
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
+ 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
+};
+
+static int x2600_lcd_18bit_pins[] = { 0x34, 0x35, };
+
+static int x2600_lcd_24bit_pins[] = {
+ 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
+};
+
+static int x2600_lcd_sync_pins[] = { 0x3c, 0x3d, 0x3e, 0x3f, };
+
+static int x2600_lcd_none_pins[] = { };
+
+static int x2600_mac_pins[] = {
+ 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+};
+
+static int x2600_msc0_1bit_pins[] = { 0x60, 0x61, 0x62, };
+static int x2600_msc0_4bit_pins[] = { 0x63, 0x64, 0x65, };
+static int x2600_msc0_8bit_pins[] = { 0x81, 0x82, 0x83, 0x84, };
+
+static int x2600_msc1_1bit_c_pins[] = { 0x59, 0x5a, 0x5b, };
+static int x2600_msc1_4bit_c_pins[] = { 0x5c, 0x5d, 0x5e, };
+
+static int x2600_msc1_1bit_d_pins[] = { 0x66, 0x67, 0x68, };
+static int x2600_msc1_4bit_d_pins[] = { 0x69, 0x6a, 0x6b, };
+
+static int x2600_otg_pins[] = { 0x81, };
+
+static int x2600_pcm_pins[] = { 0x40, 0x41, 0x42, 0x43, }; /* PC0-PC3 (Func3) */
+
+static int x2600_pwm0_pins[] = { 0x2c, }; /* PB12 (Func2) */
+static int x2600_pwm1_pins[] = { 0x2d, }; /* PB13 (Func2) */
+static int x2600_pwm2_pins[] = { 0x2e, }; /* PB14 (Func2) */
+static int x2600_pwm3_pins[] = { 0x2f, }; /* PB15 (Func2) */
+static int x2600_pwm4_pins[] = { 0x30, }; /* PB16 (Func2) */
+static int x2600_pwm5_pins[] = { 0x31, }; /* PB17 (Func2) */
+static int x2600_pwm6_pins[] = { 0x32, }; /* PB18 (Func2) */
+static int x2600_pwm7_pins[] = { 0x33, }; /* PB19 (Func2) */
+static int x2600_pwm8_pins[] = { 0x47, }; /* PC07 (Func0) */
+static int x2600_pwm9_pins[] = { 0x48, }; /* PC08 (Func0) */
+static int x2600_pwm10_c_pins[] = { 0x49, }; /* PC09 (Func0) */
+static int x2600_pwm10_e_pins[] = { 0x82, }; /* PE02 (Func2) */
+static int x2600_pwm11_pins[] = { 0x4a, }; /* PC10 (Func0) */
+static int x2600_pwm12_pins[] = { 0x4b, }; /* PC11 (Func0) */
+static int x2600_pwm13_pins[] = { 0x4c, }; /* PC12 (Func0) */
+static int x2600_pwm14_pins[] = { 0x4d, }; /* PC13 (Func0) */
+static int x2600_pwm15_pins[] = { 0x4e, }; /* PC14 (Func0) */
+static int x2600_pwm_trig_c_pins[] = { 0x54, }; /* PC20 (Func1) */
+static int x2600_pwm_trig_d_pins[] = { 0x6c, }; /* PD12 (Func1) */
+
+static int x2600_sfc_d0_pins[] = { 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, };
+static int x2600_sfc_d6_pins[] = { 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, };
+
+static int x2600_slcd_8bit_pins[] = {
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
+};
+
+static int x2600_slcd_16bit_pins[] = {
+ 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
+};
+
+static int x2600_slcd_ctrl_pins[] = {
+ 0x34, 0x3c, 0x3d, 0x3e, 0x3f,
+};
+
+static int x2600_ssi0_dt_b_pins[] = { 0x22, };
+static int x2600_ssi0_dr_b_pins[] = { 0x21, };
+static int x2600_ssi0_clk_b_pins[] = { 0x23, };
+static int x2600_ssi0_ce0_b_pins[] = { 0x20, };
+
+static int x2600_ssi0_dt_d_pins[] = { 0x61, };
+static int x2600_ssi0_dr_d_pins[] = { 0x62, };
+static int x2600_ssi0_clk_d_pins[] = { 0x60, };
+static int x2600_ssi0_ce0_d_pins[] = { 0x65, };
+
+static int x2600_ssi1_dt_c15_pins[] = { 0x50, };
+static int x2600_ssi1_dr_c15_pins[] = { 0x51, };
+static int x2600_ssi1_clk_c15_pins[] = { 0x4f, };
+static int x2600_ssi1_ce0_c15_pins[] = { 0x52, };
+
+static int x2600_ssi1_dt_c25_pins[] = { 0x5a, };
+static int x2600_ssi1_dr_c25_pins[] = { 0x5b, };
+static int x2600_ssi1_clk_c25_pins[] = { 0x59, };
+static int x2600_ssi1_ce0_c25_pins[] = { 0x5e, };
+
+static int x2600_ssi_slv_dt_pins[] = { 0x3d, }; /* PB29 (Func2) */
+static int x2600_ssi_slv_dr_pins[] = { 0x3e, }; /* PB30 (Func2) */
+static int x2600_ssi_slv_clk_pins[] = { 0x3c, }; /* PB28 (Func2) */
+static int x2600_ssi_slv_ce0_pins[] = { 0x3f, }; /* PB31 (Func2) */
+
+static int x2600_tcu0_in0_pins[] = { 0x34, }; /* PB20 (Func2) */
+static int x2600_tcu0_in1_pins[] = { 0x35, }; /* PB21 (Func2) */
+static int x2600_tcu1_in0_pins[] = { 0x36, }; /* PB22 (Func2) */
+static int x2600_tcu1_in1_pins[] = { 0x37, }; /* PB23 (Func2) */
+static int x2600_tcu2_in0_pins[] = { 0x38, }; /* PB24 (Func2) */
+static int x2600_tcu2_in1_pins[] = { 0x39, }; /* PB25 (Func2) */
+static int x2600_tcu3_in0_pins[] = { 0x3a, }; /* PB26 (Func2) */
+static int x2600_tcu3_in1_pins[] = { 0x3b, }; /* PB27 (Func2) */
+
+static int x2600_tcu4_in0_pins[] = { 0x47, }; /* PC07 (Func1) */
+static int x2600_tcu4_in1_pins[] = { 0x48, }; /* PC08 (Func1) */
+static int x2600_tcu5_in0_pins[] = { 0x49, }; /* PC09 (Func1) */
+static int x2600_tcu5_in1_pins[] = { 0x4a, }; /* PC10 (Func1) */
+static int x2600_tcu6_in0_pins[] = { 0x4b, }; /* PC11 (Func1) */
+static int x2600_tcu6_in1_pins[] = { 0x4c, }; /* PC12 (Func1) */
+static int x2600_tcu7_in0_pins[] = { 0x4d, }; /* PC13 (Func1) */
+static int x2600_tcu7_in1_pins[] = { 0x4e, }; /* PC14 (Func1) */
+
+static int x2600_uart0_data_c_pins[] = { 0x57, 0x58, };
+static int x2600_uart0_hwflow_c_pins[] = { 0x55, 0x56, };
+static int x2600_uart0_data_e_pins[] = { 0x89, 0x8a, };
+static int x2600_uart0_hwflow_e_pins[] = { 0x8b, 0x8c, };
+
+static int x2600_uart1_data_b_pins[] = { 0x20, 0x21, };
+static int x2600_uart1_data_c_pins[] = { 0x42, 0x43, };
+static int x2600_uart1_hwflow_pins[] = { 0x44, 0x45, };
+
+static int x2600_uart2_data_pins[] = { 0x6d, 0x6c, };
+
+static int x2600_uart3_data_b_pins[] = { 0x37, 0x36, };
+static int x2600_uart3_data_c_pins[] = { 0x50, 0x4f, };
+
+static int x2600_uart4_data_b_pins[] = { 0x38, 0x39, };
+static int x2600_uart4_data_c_pins[] = { 0x51, 0x52, };
+static int x2600_uart5_data_b_pins[] = { 0x3a, 0x3b, };
+static int x2600_uart5_data_c_pins[] = { 0x47, 0x48, };
+static int x2600_uart6_data_c_pins[] = { 0x40, 0x41, };
+static int x2600_uart7_data_c_pins[] = { 0x44, 0x45, };
+static int x2600_uart7_data_e_pins[] = { 0x83, 0x84, };
+
+static int x2600_wait_pins[] = { 0x6b, };
+
+static const struct group_desc x2600_groups[] = {
+ /* CAN (Controller Area Network) */
+ INGENIC_PIN_GROUP("can0-data", x2600_can0, 2),
+ INGENIC_PIN_GROUP("can1-data", x2600_can1, 2),
+
+ /* CIM (Camera) */
+ INGENIC_PIN_GROUP("cim-data", x2600_cim, 0),
+
+ /* EXCLK (externel clock output) */
+ INGENIC_PIN_GROUP("ex-clk", x2600_clk, 1),
+
+ /* DMIC */
+ INGENIC_PIN_GROUP("dmic-data", x2600_dmic, 0),
+
+ /* I2Cs */
+ INGENIC_PIN_GROUP("i2c0-data-c", x2600_i2c0_c, 1),
+ INGENIC_PIN_GROUP("i2c0-data-d", x2600_i2c0_d, 2),
+ INGENIC_PIN_GROUP("i2c1-data-b", x2600_i2c1_b, 3),
+ INGENIC_PIN_GROUP("i2c1-data-c", x2600_i2c1_c, 1),
+ INGENIC_PIN_GROUP("i2c2-data-b", x2600_i2c2_b, 3),
+ INGENIC_PIN_GROUP("i2c2-data-c", x2600_i2c2_c, 2),
+ INGENIC_PIN_GROUP("i2c3-data-c", x2600_i2c3_c, 2),
+ INGENIC_PIN_GROUP("i2c3-data-e", x2600_i2c3_e, 1),
+
+ /* I2S (Audio) & PCM */
+ INGENIC_PIN_GROUP("i2s-clk-rx", x2600_i2s_clk_rx, 1),
+ INGENIC_PIN_GROUP("i2s-sysclk", x2600_i2s_sysclk, 1),
+ INGENIC_PIN_GROUP("i2s-clk-tx", x2600_i2s_clk_tx, 1),
+ INGENIC_PIN_GROUP("i2s-data", x2600_i2s_data, 1),
+ INGENIC_PIN_GROUP("pcm", x2600_pcm, 3),
+
+ /* LCD & SLCD */
+ INGENIC_PIN_GROUP("lcd-16bit", x2600_lcd_16bit, 0),
+ INGENIC_PIN_GROUP("lcd-18bit", x2600_lcd_18bit, 0),
+ INGENIC_PIN_GROUP("lcd-24bit", x2600_lcd_24bit, 0),
+ INGENIC_PIN_GROUP("lcd-sync", x2600_lcd_sync, 0),
+ INGENIC_PIN_GROUP("lcd-none", x2600_lcd_none, 1),
+ INGENIC_PIN_GROUP("slcd-8bit", x2600_slcd_8bit, 1),
+ INGENIC_PIN_GROUP("slcd-16bit", x2600_slcd_16bit, 1),
+ INGENIC_PIN_GROUP("slcd-ctrl", x2600_slcd_ctrl, 1),
+
+ /* MAC (Ethernet) */
+ INGENIC_PIN_GROUP("mac", x2600_mac, 0),
+
+ /* MMCs (MSC) */
+ INGENIC_PIN_GROUP("mmc0-1bit", x2600_msc0_1bit, 0),
+ INGENIC_PIN_GROUP("mmc0-4bit", x2600_msc0_4bit, 0),
+ INGENIC_PIN_GROUP("mmc0-8bit", x2600_msc0_8bit, 0),
+ INGENIC_PIN_GROUP("mmc1-1bit-c", x2600_msc1_1bit_c, 0),
+ INGENIC_PIN_GROUP("mmc1-4bit-c", x2600_msc1_4bit_c, 0),
+ INGENIC_PIN_GROUP("mmc1-1bit-d", x2600_msc1_1bit_d, 1),
+ INGENIC_PIN_GROUP("mmc1-4bit-d", x2600_msc1_4bit_d, 1),
+
+ /* OTG (Vbus driver) */
+ INGENIC_PIN_GROUP("otg-vbus", x2600_otg, 1),
+
+ /* PWMs */
+ INGENIC_PIN_GROUP("pwm0", x2600_pwm0, 2),
+ INGENIC_PIN_GROUP("pwm1", x2600_pwm1, 2),
+ INGENIC_PIN_GROUP("pwm2", x2600_pwm2, 2),
+ INGENIC_PIN_GROUP("pwm3", x2600_pwm3, 2),
+ INGENIC_PIN_GROUP("pwm4", x2600_pwm4, 2),
+ INGENIC_PIN_GROUP("pwm5", x2600_pwm5, 2),
+ INGENIC_PIN_GROUP("pwm6", x2600_pwm6, 2),
+ INGENIC_PIN_GROUP("pwm7", x2600_pwm7, 2),
+ INGENIC_PIN_GROUP("pwm8", x2600_pwm8, 0),
+ INGENIC_PIN_GROUP("pwm9", x2600_pwm9, 0),
+ INGENIC_PIN_GROUP("pwm10-c", x2600_pwm10_c, 0),
+ INGENIC_PIN_GROUP("pwm10-e", x2600_pwm10_e, 2),
+ INGENIC_PIN_GROUP("pwm11", x2600_pwm11, 0),
+ INGENIC_PIN_GROUP("pwm12", x2600_pwm12, 0),
+ INGENIC_PIN_GROUP("pwm13", x2600_pwm13, 0),
+ INGENIC_PIN_GROUP("pwm14", x2600_pwm14, 0),
+ INGENIC_PIN_GROUP("pwm15", x2600_pwm15, 0),
+ INGENIC_PIN_GROUP("pwm-trig-c", x2600_pwm_trig_c, 1),
+ INGENIC_PIN_GROUP("pwm-trig-d", x2600_pwm_trig_d, 1),
+
+ /* SFC (Serial Flash Controller) */
+ INGENIC_PIN_GROUP("sfc-d0", x2600_sfc_d0, 1),
+ INGENIC_PIN_GROUP("sfc-d6", x2600_sfc_d6, 0),
+
+ /* SSIs (SPI) */
+ INGENIC_PIN_GROUP("ssi0-dt-b", x2600_ssi0_dt_b, 0),
+ INGENIC_PIN_GROUP("ssi0-dr-b", x2600_ssi0_dr_b, 0),
+ INGENIC_PIN_GROUP("ssi0-clk-b", x2600_ssi0_clk_b, 0),
+ INGENIC_PIN_GROUP("ssi0-ce0-b", x2600_ssi0_ce0_b, 0),
+ INGENIC_PIN_GROUP("ssi0-dt-d", x2600_ssi0_dt_d, 2),
+ INGENIC_PIN_GROUP("ssi0-dr-d", x2600_ssi0_dr_d, 2),
+ INGENIC_PIN_GROUP("ssi0-clk-d", x2600_ssi0_clk_d, 2),
+ INGENIC_PIN_GROUP("ssi0-ce0-d", x2600_ssi0_ce0_d, 2),
+ INGENIC_PIN_GROUP("ssi1-dt-c15", x2600_ssi1_dt_c15, 2),
+ INGENIC_PIN_GROUP("ssi1-dr-c15", x2600_ssi1_dr_c15, 2),
+ INGENIC_PIN_GROUP("ssi1-clk-c15", x2600_ssi1_clk_c15, 2),
+ INGENIC_PIN_GROUP("ssi1-ce0-c15", x2600_ssi1_ce0_c15, 2),
+ INGENIC_PIN_GROUP("ssi1-dt-c25", x2600_ssi1_dt_c25, 1),
+ INGENIC_PIN_GROUP("ssi1-dr-c25", x2600_ssi1_dr_c25, 1),
+ INGENIC_PIN_GROUP("ssi1-clk-c25", x2600_ssi1_clk_c25, 1),
+ INGENIC_PIN_GROUP("ssi1-ce0-c25", x2600_ssi1_ce0_c25, 1),
+ INGENIC_PIN_GROUP("ssi-slv-dt-b", x2600_ssi_slv_dt, 2),
+ INGENIC_PIN_GROUP("ssi-slv-dr-b", x2600_ssi_slv_dr, 2),
+ INGENIC_PIN_GROUP("ssi-slv-clk-b", x2600_ssi_slv_clk, 2),
+ INGENIC_PIN_GROUP("ssi-slv-ce0-b", x2600_ssi_slv_ce0, 2),
+
+ /* TCUs (Timer & Counter Units) */
+ INGENIC_PIN_GROUP("tcu0_in0", x2600_tcu0_in0, 2),
+ INGENIC_PIN_GROUP("tcu0_in1", x2600_tcu0_in1, 2),
+ INGENIC_PIN_GROUP("tcu1_in0", x2600_tcu1_in0, 2),
+ INGENIC_PIN_GROUP("tcu1_in1", x2600_tcu1_in1, 2),
+ INGENIC_PIN_GROUP("tcu2_in0", x2600_tcu2_in0, 2),
+ INGENIC_PIN_GROUP("tcu2_in1", x2600_tcu2_in1, 2),
+ INGENIC_PIN_GROUP("tcu3_in0", x2600_tcu3_in0, 2),
+ INGENIC_PIN_GROUP("tcu3_in1", x2600_tcu3_in1, 2),
+ INGENIC_PIN_GROUP("tcu4_in0", x2600_tcu4_in0, 1),
+ INGENIC_PIN_GROUP("tcu4_in1", x2600_tcu4_in1, 1),
+ INGENIC_PIN_GROUP("tcu5_in0", x2600_tcu5_in0, 1),
+ INGENIC_PIN_GROUP("tcu5_in1", x2600_tcu5_in1, 1),
+ INGENIC_PIN_GROUP("tcu6_in0", x2600_tcu6_in0, 1),
+ INGENIC_PIN_GROUP("tcu6_in1", x2600_tcu6_in1, 1),
+ INGENIC_PIN_GROUP("tcu7_in0", x2600_tcu7_in0, 1),
+ INGENIC_PIN_GROUP("tcu7_in1", x2600_tcu7_in1, 1),
+
+ /* UARTs */
+ INGENIC_PIN_GROUP("uart0-data-c", x2600_uart0_data_c, 1),
+ INGENIC_PIN_GROUP("uart0-hwflow-c", x2600_uart0_hwflow_c, 1),
+ INGENIC_PIN_GROUP("uart0-data-e", x2600_uart0_data_e, 1),
+ INGENIC_PIN_GROUP("uart0-hwflow-e", x2600_uart0_hwflow_e, 1),
+ INGENIC_PIN_GROUP("uart1-data-b", x2600_uart1_data_b, 1),
+ INGENIC_PIN_GROUP("uart1-data-c", x2600_uart1_data_c, 1),
+ INGENIC_PIN_GROUP("uart1-hwflow", x2600_uart1_hwflow, 2),
+ INGENIC_PIN_GROUP("uart2-data", x2600_uart2_data, 1),
+ INGENIC_PIN_GROUP("uart3-data-b", x2600_uart3_data_b, 1),
+ INGENIC_PIN_GROUP("uart3-data-c", x2600_uart3_data_c, 3),
+ INGENIC_PIN_GROUP("uart4-data-b", x2600_uart4_data_b, 2),
+ INGENIC_PIN_GROUP("uart4-data-c", x2600_uart4_data_c, 3),
+ INGENIC_PIN_GROUP("uart5-data-b", x2600_uart5_data_b, 2),
+ INGENIC_PIN_GROUP("uart5-data-c", x2600_uart5_data_c, 3),
+ INGENIC_PIN_GROUP("uart6-data-c", x2600_uart6_data_c, 2),
+ INGENIC_PIN_GROUP("uart7-data-c", x2600_uart7_data_c, 1),
+ INGENIC_PIN_GROUP("uart7-data-e", x2600_uart7_data_e, 1),
+
+ /* WAIT */
+ INGENIC_PIN_GROUP("wait", x2600_wait, 3),
+};
+
+static const char * const x2600_can0_groups[] = { "can0-data", };
+static const char * const x2600_can1_groups[] = { "can1-data", };
+
+static const char * const x2600_cim_groups[] = { "cim-data", };
+
+static const char * const x2600_clk_groups[] = { "ex-clk", };
+
+static const char * const x2600_dmic_groups[] = { "dmic-data", };
+
+static const char * const x2600_lcd_groups[] = {
+ "lcd-16bit", "lcd-18bit", "lcd-24bit", "lcd-sync", "lcd-none",
+};
+
+static const char * const x2600_i2c0_groups[] = { "i2c0-data-c", "i2c0-data-d", };
+static const char * const x2600_i2c1_groups[] = { "i2c1-data-b", "i2c1-data-c", };
+static const char * const x2600_i2c2_groups[] = { "i2c2-data-b", "i2c2-data-c", };
+static const char * const x2600_i2c3_groups[] = { "i2c3-data-c", "i2c3-data-e", };
+
+static const char * const x2600_i2s_groups[] = {
+ "i2s-data", "i2s-clk-rx", "i2s-clk-tx", "i2s-sysclk",
+};
+
+static const char * const x2600_mac_groups[] = { "mac", };
+
+static const char * const x2600_msc0_groups[] = { "mmc0-1bit", "mmc0-4bit", "mmc0-8bit", };
+
+static const char * const x2600_msc1_groups[] = {
+ "mmc1-1bit-c", "mmc1-4bit-c", "mmc1-1bit-d", "mmc1-4bit-d",
+};
+
+static const char * const x2600_otg_groups[] = { "otg-vbus", };
+
+static const char * const x2600_pwm0_groups[] = { "pwm0", };
+static const char * const x2600_pwm1_groups[] = { "pwm1", };
+static const char * const x2600_pwm2_groups[] = { "pwm2", };
+static const char * const x2600_pwm3_groups[] = { "pwm3", };
+static const char * const x2600_pwm4_groups[] = { "pwm4", };
+static const char * const x2600_pwm5_groups[] = { "pwm5", };
+static const char * const x2600_pwm6_groups[] = { "pwm6", };
+static const char * const x2600_pwm7_groups[] = { "pwm7", };
+static const char * const x2600_pwm8_groups[] = { "pwm8", };
+static const char * const x2600_pwm9_groups[] = { "pwm9", };
+static const char * const x2600_pwm10_groups[] = { "pwm10-c", "pwm10-e", };
+
+static const char * const x2600_sfc_groups[] = { "sfc-d0", "sfc-d6", };
+
+static const char * const x2600_slcd_groups[] = { "slcd-8bit", "slcd-16bit", "slcd-ctrl", };
+
+static const char * const x2600_ssi0_groups[] = {
+ "ssi0-dt-b", "ssi0-dr-b", "ssi0-clk-b", "ssi0-ce0-b",
+ "ssi0-dt-d", "ssi0-dr-d", "ssi0-clk-d", "ssi0-ce0-d",
+};
+
+static const char * const x2600_ssi1_groups[] = {
+ "ssi1-dt-c15", "ssi1-dr-c15", "ssi1-clk-c15", "ssi1-ce0-c15",
+ "ssi1-dt-c25", "ssi1-dr-c25", "ssi1-clk-c25", "ssi1-ce0-c25",
+};
+
+static const char * const x2600_ssi_slv_groups[] = {
+ "ssi-slv-dt-b", "ssi-slv-dr-b", "ssi-slv-clk-b", "ssi-slv-ce0-b",
+};
+
+static const char * const x2600_tcu_groups[] = {
+ "tcu0_in0", "tcu0_in1",
+ "tcu1_in0", "tcu1_in1",
+ "tcu2_in0", "tcu2_in1",
+ "tcu3_in0", "tcu3_in1",
+ "tcu4_in0", "tcu4_in1",
+ "tcu5_in0", "tcu5_in1",
+ "tcu6_in0", "tcu6_in1",
+ "tcu7_in0", "tcu7_in1",
+};
+
+static const char * const x2600_uart0_groups[] = {
+ "uart0-data-c", "uart0-hwflow-c", "uart0-data-e", "uart0-hwflow-e",
+};
+
+static const char * const x2600_uart1_groups[] = {
+ "uart1-data-b", "uart1-data-c", "uart1-hwflow",
+};
+
+static const char * const x2600_uart2_groups[] = { "uart2-data", };
+static const char * const x2600_uart3_groups[] = { "uart3-data-b", "uart3-data-c", };
+static const char * const x2600_uart4_groups[] = { "uart4-data-b", "uart4-data-c", };
+static const char * const x2600_uart5_groups[] = { "uart5-data-b", "uart5-data-c", };
+static const char * const x2600_uart6_groups[] = { "uart6-data-c", };
+static const char * const x2600_uart7_groups[] = { "uart7-data-c", "uart7-data-e", };
+
+static const struct pinfunction x2600_functions[] = {
+ INGENIC_PIN_FUNCTION("can0", x2600_can0),
+ INGENIC_PIN_FUNCTION("can1", x2600_can1),
+ INGENIC_PIN_FUNCTION("cim", x2600_cim),
+ INGENIC_PIN_FUNCTION("exclk", x2600_clk),
+ INGENIC_PIN_FUNCTION("dmic", x2600_dmic),
+ INGENIC_PIN_FUNCTION("i2c0", x2600_i2c0),
+ INGENIC_PIN_FUNCTION("i2c1", x2600_i2c1),
+ INGENIC_PIN_FUNCTION("i2c2", x2600_i2c2),
+ INGENIC_PIN_FUNCTION("i2c3", x2600_i2c3),
+ INGENIC_PIN_FUNCTION("i2s", x2600_i2s),
+ INGENIC_PIN_FUNCTION("lcd", x2600_lcd),
+ INGENIC_PIN_FUNCTION("mac", x2600_mac),
+ INGENIC_PIN_FUNCTION("mmc0", x2600_msc0),
+ INGENIC_PIN_FUNCTION("mmc1", x2600_msc1),
+ INGENIC_PIN_FUNCTION("otg", x2600_otg),
+ INGENIC_PIN_FUNCTION("pwm0", x2600_pwm0),
+ INGENIC_PIN_FUNCTION("pwm1", x2600_pwm1),
+ INGENIC_PIN_FUNCTION("pwm2", x2600_pwm2),
+ INGENIC_PIN_FUNCTION("pwm3", x2600_pwm3),
+ INGENIC_PIN_FUNCTION("pwm4", x2600_pwm4),
+ INGENIC_PIN_FUNCTION("pwm5", x2600_pwm5),
+ INGENIC_PIN_FUNCTION("pwm6", x2600_pwm6),
+ INGENIC_PIN_FUNCTION("pwm7", x2600_pwm7),
+ INGENIC_PIN_FUNCTION("pwm8", x2600_pwm8),
+ INGENIC_PIN_FUNCTION("pwm9", x2600_pwm9),
+ INGENIC_PIN_FUNCTION("pwm10", x2600_pwm10),
+ INGENIC_PIN_FUNCTION("sfc", x2600_sfc),
+ INGENIC_PIN_FUNCTION("slcd", x2600_slcd),
+ INGENIC_PIN_FUNCTION("ssi0", x2600_ssi0),
+ INGENIC_PIN_FUNCTION("ssi1", x2600_ssi1),
+ INGENIC_PIN_FUNCTION("ssi-slv", x2600_ssi_slv),
+ INGENIC_PIN_FUNCTION("uart0", x2600_uart0),
+ INGENIC_PIN_FUNCTION("uart1", x2600_uart1),
+ INGENIC_PIN_FUNCTION("uart2", x2600_uart2),
+ INGENIC_PIN_FUNCTION("uart3", x2600_uart3),
+ INGENIC_PIN_FUNCTION("uart4", x2600_uart4),
+ INGENIC_PIN_FUNCTION("uart5", x2600_uart5),
+ INGENIC_PIN_FUNCTION("uart6", x2600_uart6),
+ INGENIC_PIN_FUNCTION("uart7", x2600_uart7),
+ INGENIC_PIN_FUNCTION("tcu", x2600_tcu),
+};
+
+static const struct regmap_range x2600_access_ranges[] = {
+ regmap_reg_range(0x0000 + 0x000, 0x0000 + 0x0e8),
+ regmap_reg_range(0x0000 + 0x170, 0x0000 + 0x190),
+ regmap_reg_range(0x0000 + 0x200, 0x0000 + 0x210),
+ regmap_reg_range(0x0000 + 0x814, 0x0000 + 0x8f0),
+ regmap_reg_range(0x0000 + 0x974, 0x0000 + 0x978),
+
+ regmap_reg_range(0x1000 + 0x000, 0x1000 + 0x0e8),
+ regmap_reg_range(0x1000 + 0x170, 0x1000 + 0x190),
+ regmap_reg_range(0x1000 + 0x200, 0x1000 + 0x210),
+ regmap_reg_range(0x1000 + 0x814, 0x1000 + 0x8f0),
+ regmap_reg_range(0x1000 + 0x974, 0x1000 + 0x978),
+
+ regmap_reg_range(0x2000 + 0x000, 0x2000 + 0x0e8),
+ regmap_reg_range(0x2000 + 0x170, 0x2000 + 0x190),
+ regmap_reg_range(0x2000 + 0x200, 0x2000 + 0x210),
+ regmap_reg_range(0x2000 + 0x814, 0x2000 + 0x8f0),
+ regmap_reg_range(0x2000 + 0x974, 0x2000 + 0x978),
+
+ regmap_reg_range(0x3000 + 0x000, 0x3000 + 0x0e8),
+ regmap_reg_range(0x3000 + 0x170, 0x3000 + 0x190),
+ regmap_reg_range(0x3000 + 0x200, 0x3000 + 0x210),
+ regmap_reg_range(0x3000 + 0x814, 0x3000 + 0x8f0),
+ regmap_reg_range(0x3000 + 0x974, 0x3000 + 0x978),
+
+ regmap_reg_range(0x4000 + 0x000, 0x4000 + 0x0e8),
+ regmap_reg_range(0x4000 + 0x100, 0x4000 + 0x118),
+ regmap_reg_range(0x4000 + 0x170, 0x4000 + 0x190),
+ regmap_reg_range(0x4000 + 0x200, 0x4000 + 0x210),
+ regmap_reg_range(0x4000 + 0x814, 0x4000 + 0x8f0),
+ regmap_reg_range(0x4000 + 0x974, 0x4000 + 0x978),
+};
+
+static const struct regmap_access_table x2600_access_table = {
+ .yes_ranges = x2600_access_ranges,
+ .n_yes_ranges = ARRAY_SIZE(x2600_access_ranges),
+};
+
+static const struct ingenic_chip_info x2600_chip_info = {
+ .num_chips = 5,
+ .reg_offset = 0x1000,
+ .version = ID_X2600,
+ .groups = x2600_groups,
+ .num_groups = ARRAY_SIZE(x2600_groups),
+ .functions = x2600_functions,
+ .num_functions = ARRAY_SIZE(x2600_functions),
+ .pull_ups = x2600_pull_ups,
+ .pull_downs = x2600_pull_downs,
+ .access_table = &x2600_access_table,
+};
+
static u32 ingenic_gpio_read_reg(struct ingenic_gpio_chip *jzgc, u8 reg)
{
unsigned int val;
@@ -4453,6 +4950,7 @@ static const struct of_device_id ingenic_gpio_of_matches[] __initconst = {
{ .compatible = "ingenic,x1830-gpio" },
{ .compatible = "ingenic,x2000-gpio" },
{ .compatible = "ingenic,x2100-gpio" },
+ { .compatible = "ingenic,x2600-gpio" },
{},
};
@@ -4714,6 +5212,10 @@ static const struct of_device_id ingenic_pinctrl_of_matches[] = {
.compatible = "ingenic,x2100-pinctrl",
.data = IF_ENABLED(CONFIG_MACH_X2100, &x2100_chip_info)
},
+ {
+ .compatible = "ingenic,x2600-pinctrl",
+ .data = IF_ENABLED(CONFIG_MACH_X2600, &x2600_chip_info)
+ },
{ /* sentinel */ },
};
--
2.56.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 2/3] pinctrl: ingenic: Add X2600 register and GPIO IRQ support
2026-11-13 8:14 ` [PATCH 2/3] pinctrl: ingenic: Add X2600 register and GPIO IRQ support H. Nikolaus Schaller
@ 2026-11-13 8:26 ` sashiko-bot
0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-11-13 8:26 UTC (permalink / raw)
To: H. Nikolaus Schaller; +Cc: linux-gpio, devicetree, robh, conor+dt
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [Low] pinctrl: ingenic: redundant X2600_GPIO_FLAG_CLR branch in
ingenic_gpio_irq_ack()
- [Low] pinctrl: ingenic: redundant dual-edge checks and shadow writes
in irq_set_type()
--
commit 4b5a0225ba958d5462cbfa1ae4bab23a1b574fea
Author: H. Nikolaus Schaller <hns@goldelico.com>
pinctrl: ingenic: Add X2600 register and GPIO IRQ support
This commit adds the X2600 SoC ID, adapts the GPIO shadow and interrupt
flag register accesses to the X2600 layout, and updates GPIO dual-edge
interrupt configuration for X1600, X2000, and X2600.
> diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c
> index 1aa6a6dc12095..6794c662d2afe 100644
> --- a/drivers/pinctrl/pinctrl-ingenic.c
> +++ b/drivers/pinctrl/pinctrl-ingenic.c
[ ... ]
> @@ -3616,6 +3628,12 @@ static void irq_set_type(struct ingenic_gpio_chip *jzgc,
> break;
> }
>
> + if (type == IRQ_TYPE_EDGE_BOTH &&
> + (is_soc_or_above(jzgc->jzpc, ID_X2000) ||
> + (is_soc_or_above(jzgc->jzpc, ID_X1600) &&
> + !is_soc_or_above(jzgc->jzpc, ID_X1830))))
> + val2 = true;
> +
> if (is_soc_or_above(jzgc->jzpc, ID_JZ4770)) {
> reg1 = JZ4770_GPIO_PAT1;
> reg2 = JZ4770_GPIO_PAT0;
> @@ -3638,6 +3656,9 @@ static void irq_set_type(struct ingenic_gpio_chip *jzgc,
> ingenic_gpio_shadow_set_bit(jzgc, reg2, offset, val1);
> ingenic_gpio_shadow_set_bit(jzgc, reg1, offset, val2);
> ingenic_gpio_shadow_set_bit_load(jzgc);
> +
> + if (is_soc_or_above(jzgc->jzpc, ID_X1600) && !is_soc_or_above(jzgc->jzpc, ID_X1830))
> + ingenic_gpio_set_bit(jzgc, X2000_GPIO_EDG, offset, val3);
> } else {
> ingenic_gpio_set_bit(jzgc, reg2, offset, val1);
> ingenic_gpio_set_bit(jzgc, reg1, offset, val2);
[Severity: Low]
This isn't a bug, but irq_set_type() is only called from
ingenic_gpio_irq_ack() (with IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_LEVEL_HIGH) and
ingenic_gpio_irq_set_type(), which converts IRQ_TYPE_EDGE_BOTH into a level
trigger on SoCs without hardware dual-edge support before calling
irq_set_type(). Because case IRQ_TYPE_EDGE_BOTH in irq_set_type() is only
reached on SoCs with hardware dual-edge support, val2 can be set to true
directly in the switch statement without re-checking the SoC version.
Also, the ID_X2000 and ID_X1000 branches in irq_set_type() now run the same
shadow register sequence, and the compound SoC check for hardware dual-edge
support is repeated across irq_set_type(), ingenic_gpio_irq_ack(), and
ingenic_gpio_irq_set_type(), which could be factored into a small helper
and a single ID_X1000 branch.
[ ... ]
> @@ -3724,7 +3746,9 @@ static void ingenic_gpio_irq_ack(struct irq_data *irqd)
> irq_set_type(jzgc, irq, IRQ_TYPE_LEVEL_HIGH);
> }
>
> - if (is_soc_or_above(jzgc->jzpc, ID_JZ4770))
> + if (is_soc_or_above(jzgc->jzpc, ID_X2600))
> + regmap_write(jzgc->jzpc->map, jzgc->reg_base + X2600_GPIO_FLAG_CLR, BIT(irq));
> + else if (is_soc_or_above(jzgc->jzpc, ID_JZ4770))
> ingenic_gpio_set_bit(jzgc, JZ4770_GPIO_FLAG, irq, false);
> else if (is_soc_or_above(jzgc->jzpc, ID_JZ4740))
> ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_DATA, irq, true);
[Severity: Low]
This isn't a bug, but is the separate ID_X2600 branch and X2600_GPIO_FLAG_CLR
definition needed here?
JZ4770_GPIO_FLAG is 0x50 and REG_CLEAR(x) is ((x) + 0x8), so calling
ingenic_gpio_set_bit(jzgc, JZ4770_GPIO_FLAG, irq, false) in the existing
ID_JZ4770 branch already writes BIT(irq) to jzgc->reg_base + 0x58, which is
identical to X2600_GPIO_FLAG_CLR.
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1794557697.git.hns@goldelico.com?part=2
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 3/3] pinctrl: ingenic: Add X2600 pin groups and functions
2026-11-13 8:14 ` [PATCH 3/3] pinctrl: ingenic: Add X2600 pin groups and functions H. Nikolaus Schaller
@ 2026-11-13 8:37 ` sashiko-bot
0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-11-13 8:37 UTC (permalink / raw)
To: H. Nikolaus Schaller; +Cc: linux-gpio, devicetree, robh, conor+dt
Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [Medium] pinctrl: ingenic: x2600 pin groups omitted from
x2600_functions table
- [Medium] pinctrl: ingenic: truncated pull bitmasks in x2600_pull_ups
and pull_downs
- [Low] pinctrl: ingenic: empty x2600_lcd_none_pins breaks
ingenic_pinconf_group_get()
--
commit faeb190e107ce4d769c2094c52cf1675b346a6a9
Author: H. Nikolaus Schaller <hns@goldelico.com>
pinctrl: ingenic: Add X2600 pin groups and functions
This commit adds pin groups, pinmux functions, pull-up/pull-down masks, and
register access ranges for the Lumissil X2600 SoC to the Ingenic pinctrl
driver.
> diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c
> index 6794c662d2afe..557cd652ecc00 100644
> --- a/drivers/pinctrl/pinctrl-ingenic.c
> +++ b/drivers/pinctrl/pinctrl-ingenic.c
> @@ -3515,6 +3515,503 @@ static const struct ingenic_chip_info x2100_chip_info = {
> .access_table = &x2000_access_table,
> };
>
> +static const u32 x2600_pull_ups[5] = {
> + 0x000007ff, 0xffffffff, 0x7ffbfff, 0x0000ffff, 0x000ffffe,
> +};
> +
> +static const u32 x2600_pull_downs[5] = {
> + 0x000007ff, 0xffffffff, 0x01ffff1, 0x0001e000, 0x000fffff,
> +};
> +
> +static int x2600_can0_pins[] = { 0x47, 0x48, };
> +static int x2600_can1_pins[] = { 0x49, 0x4a, };
> +
> +static int x2600_cim_pins[] = {
> + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
> + 0x08, 0x09, 0x0a, 0x0b,
> +};
[Severity: Medium]
Are the Port C and Port A masks in x2600_pull_ups and x2600_pull_downs
truncated?
The Port C entries (0x7ffbfff and 0x01ffff1) have only 7 hex digits instead
of 8, leaving bits 27..30 clear so ingenic_pinconf_set() rejects pull
configuration with -EINVAL on PC27..PC30 (0x5b..0x5e, used by
x2600_msc1_1bit_c_pins, x2600_msc1_4bit_c_pins, and the ssi1-*-c25 groups).
Similarly, the Port A mask 0x000007ff only covers 11 pins (0x00..0x0a),
which causes group pull configuration on cim-data to fail with -EINVAL on
PA11 (0x0b).
[ ... ]
> +static int x2600_lcd_sync_pins[] = { 0x3c, 0x3d, 0x3e, 0x3f, };
> +
> +static int x2600_lcd_none_pins[] = { };
[Severity: Low]
Does defining x2600_lcd_none_pins as an empty array break
ingenic_pinconf_group_get() for the "lcd-none" group?
When npins is 0, the loop in ingenic_pinconf_group_get() does not execute
and the function returns 0 without updating *config:
drivers/pinctrl/pinctrl-ingenic.c:ingenic_pinconf_group_get() {
...
for (i = 0; i < npins; i++) {
if (ingenic_pinconf_get(pctldev, pins[i], config))
return -ENOTSUPP;
...
return 0;
}
Reading debugfs pinconf-groups then reports every generic pin_config_param
as active on "lcd-none", and selecting "lcd-none" in
ingenic_pinmux_set_mux() is a no-op that configures no pins.
[ ... ]
> + /* I2S (Audio) & PCM */
> + INGENIC_PIN_GROUP("i2s-clk-rx", x2600_i2s_clk_rx, 1),
> + INGENIC_PIN_GROUP("i2s-sysclk", x2600_i2s_sysclk, 1),
> + INGENIC_PIN_GROUP("i2s-clk-tx", x2600_i2s_clk_tx, 1),
> + INGENIC_PIN_GROUP("i2s-data", x2600_i2s_data, 1),
> + INGENIC_PIN_GROUP("pcm", x2600_pcm, 3),
[ ... ]
> + INGENIC_PIN_GROUP("pwm10-c", x2600_pwm10_c, 0),
> + INGENIC_PIN_GROUP("pwm10-e", x2600_pwm10_e, 2),
> + INGENIC_PIN_GROUP("pwm11", x2600_pwm11, 0),
> + INGENIC_PIN_GROUP("pwm12", x2600_pwm12, 0),
> + INGENIC_PIN_GROUP("pwm13", x2600_pwm13, 0),
> + INGENIC_PIN_GROUP("pwm14", x2600_pwm14, 0),
> + INGENIC_PIN_GROUP("pwm15", x2600_pwm15, 0),
> + INGENIC_PIN_GROUP("pwm-trig-c", x2600_pwm_trig_c, 1),
> + INGENIC_PIN_GROUP("pwm-trig-d", x2600_pwm_trig_d, 1),
[ ... ]
> + /* WAIT */
> + INGENIC_PIN_GROUP("wait", x2600_wait, 3),
> +};
[ ... ]
> +static const struct pinfunction x2600_functions[] = {
> + INGENIC_PIN_FUNCTION("can0", x2600_can0),
> + INGENIC_PIN_FUNCTION("can1", x2600_can1),
> + INGENIC_PIN_FUNCTION("cim", x2600_cim),
> + INGENIC_PIN_FUNCTION("exclk", x2600_clk),
> + INGENIC_PIN_FUNCTION("dmic", x2600_dmic),
> + INGENIC_PIN_FUNCTION("i2c0", x2600_i2c0),
> + INGENIC_PIN_FUNCTION("i2c1", x2600_i2c1),
> + INGENIC_PIN_FUNCTION("i2c2", x2600_i2c2),
> + INGENIC_PIN_FUNCTION("i2c3", x2600_i2c3),
> + INGENIC_PIN_FUNCTION("i2s", x2600_i2s),
> + INGENIC_PIN_FUNCTION("lcd", x2600_lcd),
> + INGENIC_PIN_FUNCTION("mac", x2600_mac),
> + INGENIC_PIN_FUNCTION("mmc0", x2600_msc0),
> + INGENIC_PIN_FUNCTION("mmc1", x2600_msc1),
> + INGENIC_PIN_FUNCTION("otg", x2600_otg),
> + INGENIC_PIN_FUNCTION("pwm0", x2600_pwm0),
> + INGENIC_PIN_FUNCTION("pwm1", x2600_pwm1),
> + INGENIC_PIN_FUNCTION("pwm2", x2600_pwm2),
> + INGENIC_PIN_FUNCTION("pwm3", x2600_pwm3),
> + INGENIC_PIN_FUNCTION("pwm4", x2600_pwm4),
> + INGENIC_PIN_FUNCTION("pwm5", x2600_pwm5),
> + INGENIC_PIN_FUNCTION("pwm6", x2600_pwm6),
> + INGENIC_PIN_FUNCTION("pwm7", x2600_pwm7),
> + INGENIC_PIN_FUNCTION("pwm8", x2600_pwm8),
> + INGENIC_PIN_FUNCTION("pwm9", x2600_pwm9),
> + INGENIC_PIN_FUNCTION("pwm10", x2600_pwm10),
> + INGENIC_PIN_FUNCTION("sfc", x2600_sfc),
> + INGENIC_PIN_FUNCTION("slcd", x2600_slcd),
> + INGENIC_PIN_FUNCTION("ssi0", x2600_ssi0),
> + INGENIC_PIN_FUNCTION("ssi1", x2600_ssi1),
> + INGENIC_PIN_FUNCTION("ssi-slv", x2600_ssi_slv),
> + INGENIC_PIN_FUNCTION("uart0", x2600_uart0),
> + INGENIC_PIN_FUNCTION("uart1", x2600_uart1),
> + INGENIC_PIN_FUNCTION("uart2", x2600_uart2),
> + INGENIC_PIN_FUNCTION("uart3", x2600_uart3),
> + INGENIC_PIN_FUNCTION("uart4", x2600_uart4),
> + INGENIC_PIN_FUNCTION("uart5", x2600_uart5),
> + INGENIC_PIN_FUNCTION("uart6", x2600_uart6),
> + INGENIC_PIN_FUNCTION("uart7", x2600_uart7),
> + INGENIC_PIN_FUNCTION("tcu", x2600_tcu),
> +};
[Severity: Medium]
Were the "pcm", "pwm11" through "pwm15", "pwm-trig-c", "pwm-trig-d", and
"wait" pin groups left out of x2600_functions?
These nine groups are defined in x2600_groups, but they have no
corresponding group arrays or INGENIC_PIN_FUNCTION() entries in
x2600_functions, so pinmux_map_to_setting() will reject any pinctrl mapping
trying to mux them with -EINVAL.
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1794557697.git.hns@goldelico.com?part=3
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-11-13 8:37 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-13 8:14 [PATCH 0/3] pinctrl: ingenic: Add X2600 support H. Nikolaus Schaller
2026-11-13 8:14 ` [PATCH 1/3] dt-bindings: " H. Nikolaus Schaller
2026-11-13 8:14 ` [PATCH 2/3] pinctrl: ingenic: Add X2600 register and GPIO IRQ support H. Nikolaus Schaller
2026-11-13 8:26 ` sashiko-bot
2026-11-13 8:14 ` [PATCH 3/3] pinctrl: ingenic: Add X2600 pin groups and functions H. Nikolaus Schaller
2026-11-13 8:37 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.