linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] pinctrl: meson-a1: add pinctrl driver
@ 2019-09-17  6:07 Qianggui Song
  2019-09-17  6:07 ` [PATCH 1/3] pinctrl: add compatible for Amlogic Meson A1 pin controller Qianggui Song
                   ` (2 more replies)
  0 siblings, 3 replies; 15+ messages in thread
From: Qianggui Song @ 2019-09-17  6:07 UTC (permalink / raw)
  To: Linus Walleij, linux-gpio
  Cc: Qianggui Song, Neil Armstrong, Jerome Brunet, Kevin Hilman,
	Martin Blumenstingl, Carlo Caione, Rob Herring, Xingyu Chen,
	Jianxin Pan, Hanjie Lin, Mark Rutland, linux-arm-kernel,
	linux-amlogic, linux-kernel, devicetree

This patchset adds Pin controller driver support for Meson-A1 Soc
which shares the same register layout of pinmux with previous
Meson-G12A, however there is difference for gpio and pin config
registers in A1.

This patchset is based on A1 DTBv4[1].

[1] https://lore.kernel.org/linux-amlogic/1568276370-54181-1-git-send-email-jianxin.pan@amlogic.com

Qianggui Song (3):
  pinctrl: add compatible for Amlogic Meson A1 pin controller
  pinctrl: meson-a1: add pinctrl driver for Meson A1 Soc
  arm64: dts: meson: a1: add pinctrl controller support

 .../devicetree/bindings/pinctrl/meson,pinctrl.txt  |   1 +
 arch/arm64/boot/dts/amlogic/meson-a1.dtsi          |  18 +
 drivers/pinctrl/meson/Kconfig                      |   6 +
 drivers/pinctrl/meson/Makefile                     |   1 +
 drivers/pinctrl/meson/pinctrl-meson-a1.c           | 942 +++++++++++++++++++++
 drivers/pinctrl/meson/pinctrl-meson.c              |   8 +-
 drivers/pinctrl/meson/pinctrl-meson.h              |   9 +
 include/dt-bindings/gpio/meson-a1-gpio.h           |  73 ++
 8 files changed, 1056 insertions(+), 2 deletions(-)
 create mode 100644 drivers/pinctrl/meson/pinctrl-meson-a1.c
 create mode 100644 include/dt-bindings/gpio/meson-a1-gpio.h

-- 
1.9.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/3] pinctrl: add compatible for Amlogic Meson A1 pin controller
  2019-09-17  6:07 [PATCH 0/3] pinctrl: meson-a1: add pinctrl driver Qianggui Song
@ 2019-09-17  6:07 ` Qianggui Song
  2019-09-17  7:18   ` Neil Armstrong
  2019-09-30 22:47   ` Rob Herring
  2019-09-17  6:07 ` [PATCH 2/3] pinctrl: meson-a1: add pinctrl driver for Meson A1 Soc Qianggui Song
  2019-09-17  6:07 ` [PATCH 3/3] arm64: dts: meson: a1: add pinctrl controller support Qianggui Song
  2 siblings, 2 replies; 15+ messages in thread
From: Qianggui Song @ 2019-09-17  6:07 UTC (permalink / raw)
  To: Linus Walleij, linux-gpio
  Cc: Qianggui Song, Xingyu Chen, Jianxin Pan, Neil Armstrong,
	Jerome Brunet, Kevin Hilman, Martin Blumenstingl, Carlo Caione,
	Rob Herring, Hanjie Lin, Mark Rutland, linux-arm-kernel,
	linux-amlogic, linux-kernel, devicetree

Add new compatible name for Amlogic's Meson-A1 pin controller
add a dt-binding header file which document the detail pin names.

Signed-off-by: Qianggui Song <qianggui.song@amlogic.com>
Signed-off-by: Xingyu Chen <xingyu.chen@amlogic.com>
Signed-off-by: Jianxin Pan <jianxin.pan@amlogic.com>
---
 .../devicetree/bindings/pinctrl/meson,pinctrl.txt  |  1 +
 include/dt-bindings/gpio/meson-a1-gpio.h           | 73 ++++++++++++++++++++++
 2 files changed, 74 insertions(+)
 create mode 100644 include/dt-bindings/gpio/meson-a1-gpio.h

diff --git a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
index 10dc4f7..0aff1f2 100644
--- a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
@@ -15,6 +15,7 @@ Required properties for the root node:
 		      "amlogic,meson-axg-aobus-pinctrl"
 		      "amlogic,meson-g12a-periphs-pinctrl"
 		      "amlogic,meson-g12a-aobus-pinctrl"
+		      "amlogic,meson-a1-periphs-pinctrl"
  - reg: address and size of registers controlling irq functionality
 
 === GPIO sub-nodes ===
diff --git a/include/dt-bindings/gpio/meson-a1-gpio.h b/include/dt-bindings/gpio/meson-a1-gpio.h
new file mode 100644
index 0000000..40e57a5
--- /dev/null
+++ b/include/dt-bindings/gpio/meson-a1-gpio.h
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ * Author: Qianggui Song <qianggui.song@amlogic.com>
+ */
+
+#ifndef _DT_BINDINGS_MESON_A1_GPIO_H
+#define _DT_BINDINGS_MESON_A1_GPIO_H
+
+#define GPIOP_0		0
+#define GPIOP_1		1
+#define GPIOP_2		2
+#define GPIOP_3		3
+#define GPIOP_4		4
+#define GPIOP_5		5
+#define GPIOP_6		6
+#define GPIOP_7		7
+#define GPIOP_8		8
+#define GPIOP_9		9
+#define GPIOP_10	10
+#define GPIOP_11	11
+#define GPIOP_12	12
+#define GPIOB_0		13
+#define GPIOB_1		14
+#define GPIOB_2		15
+#define GPIOB_3		16
+#define GPIOB_4		17
+#define GPIOB_5		18
+#define GPIOB_6		19
+#define GPIOX_0		20
+#define GPIOX_1		21
+#define GPIOX_2		22
+#define GPIOX_3		23
+#define GPIOX_4		24
+#define GPIOX_5		25
+#define GPIOX_6		26
+#define GPIOX_7		27
+#define GPIOX_8		28
+#define GPIOX_9		29
+#define GPIOX_10	30
+#define GPIOX_11	31
+#define GPIOX_12	32
+#define GPIOX_13	33
+#define GPIOX_14	34
+#define GPIOX_15	35
+#define GPIOX_16	36
+#define GPIOF_0		37
+#define GPIOF_1		38
+#define GPIOF_2		39
+#define GPIOF_3		40
+#define GPIOF_4		41
+#define GPIOF_5		42
+#define GPIOF_6		43
+#define GPIOF_7		44
+#define GPIOF_8		45
+#define GPIOF_9		46
+#define GPIOF_10	47
+#define GPIOF_11	48
+#define GPIOF_12	49
+#define GPIOA_0		50
+#define GPIOA_1		51
+#define GPIOA_2		52
+#define GPIOA_3		53
+#define GPIOA_4		54
+#define GPIOA_5		55
+#define GPIOA_6		56
+#define GPIOA_7		57
+#define GPIOA_8		58
+#define GPIOA_9		59
+#define GPIOA_10	60
+#define GPIOA_11	61
+
+#endif /* _DT_BINDINGS_MESON_A1_GPIO_H */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/3] pinctrl: meson-a1: add pinctrl driver for Meson A1 Soc
  2019-09-17  6:07 [PATCH 0/3] pinctrl: meson-a1: add pinctrl driver Qianggui Song
  2019-09-17  6:07 ` [PATCH 1/3] pinctrl: add compatible for Amlogic Meson A1 pin controller Qianggui Song
@ 2019-09-17  6:07 ` Qianggui Song
  2019-09-17  7:15   ` Neil Armstrong
  2019-09-17  9:29   ` Jerome Brunet
  2019-09-17  6:07 ` [PATCH 3/3] arm64: dts: meson: a1: add pinctrl controller support Qianggui Song
  2 siblings, 2 replies; 15+ messages in thread
From: Qianggui Song @ 2019-09-17  6:07 UTC (permalink / raw)
  To: Linus Walleij, linux-gpio
  Cc: Qianggui Song, Xingyu Chen, Jianxin Pan, Neil Armstrong,
	Jerome Brunet, Kevin Hilman, Martin Blumenstingl, Carlo Caione,
	Rob Herring, Hanjie Lin, Mark Rutland, linux-arm-kernel,
	linux-amlogic, linux-kernel

Add pinctrl driver for Meson A1 Soc which share the same register layout of
pinmux with previous Meson-G12A, however there is difference for gpio
and pin config register in A1. The register layout is as below:

/* first bank */	      /* addr */
- P_PADCTRL_GPIOP_I         base + 0x00 << 2
- P_PADCTRL_GPIOP_O         base + 0x01 << 2
- P_PADCTRL_GPIOP_OEN       base + 0x02 << 2
- P_PADCTRL_GPIOP_PULL_EN   base + 0x03 << 2
- P_PADCTRL_GPIOP_PULL_UP   base + 0x04 << 2
- P_PADCTRL_GPIOP_DS        base + 0x05 << 2

/* second bank */
- P_PADCTRL_GPIOB_I         base + 0x10 << 2
- P_PADCTRL_GPIOB_O         base + 0x11 << 2
- P_PADCTRL_GPIOB_OEN       base + 0x12 << 2
- P_PADCTRL_GPIOB_PULL_EN   base + 0x13 << 2
- P_PADCTRL_GPIOB_PULL_UP   base + 0x14 << 2
- P_PADCTRL_GPIOB_DS        base + 0x15 << 2

Each bank contains at least 6 registers to be configured, if one bank has
more than 16 gpios, an extra P_PADCTRL_GPIO[X]_DS_EXT is included. Between
two adjacent P_PADCTRL_GPIO[X]_I, there is an offset 0x10, that is to say,
for third bank, the offsets will be 0x20,0x21,0x22,0x23,0x24,0x25 according
to above register layout.

Current Meson pinctrl driver can cover such change by using base address of
GPIO as that of drive-strength. While simply giving reg_ds = reg_pullen
make wrong value to reg_ds for Soc that not support drive-strength like AXG
. Here a private data used to identify register layout is introduced.

Signed-off-by: Qianggui Song <qianggui.song@amlogic.com>
Signed-off-by: Xingyu Chen <xingyu.chen@amlogic.com>
Signed-off-by: Jianxin Pan <jianxin.pan@amlogic.com>
---
 drivers/pinctrl/meson/Kconfig            |   6 +
 drivers/pinctrl/meson/Makefile           |   1 +
 drivers/pinctrl/meson/pinctrl-meson-a1.c | 942 +++++++++++++++++++++++++++++++
 drivers/pinctrl/meson/pinctrl-meson.c    |   8 +-
 drivers/pinctrl/meson/pinctrl-meson.h    |   9 +
 5 files changed, 964 insertions(+), 2 deletions(-)
 create mode 100644 drivers/pinctrl/meson/pinctrl-meson-a1.c

diff --git a/drivers/pinctrl/meson/Kconfig b/drivers/pinctrl/meson/Kconfig
index df55f61..3cb1191 100644
--- a/drivers/pinctrl/meson/Kconfig
+++ b/drivers/pinctrl/meson/Kconfig
@@ -54,4 +54,10 @@ config PINCTRL_MESON_G12A
 	select PINCTRL_MESON_AXG_PMX
 	default y
 
+config PINCTRL_MESON_A1
+	bool "Meson a1 Soc pinctrl driver"
+	depends on ARM64
+	select PINCTRL_MESON_AXG_PMX
+	default y
+
 endif
diff --git a/drivers/pinctrl/meson/Makefile b/drivers/pinctrl/meson/Makefile
index a69c565..1a5bffe 100644
--- a/drivers/pinctrl/meson/Makefile
+++ b/drivers/pinctrl/meson/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_PINCTRL_MESON_GXL) += pinctrl-meson-gxl.o
 obj-$(CONFIG_PINCTRL_MESON_AXG_PMX) += pinctrl-meson-axg-pmx.o
 obj-$(CONFIG_PINCTRL_MESON_AXG) += pinctrl-meson-axg.o
 obj-$(CONFIG_PINCTRL_MESON_G12A) += pinctrl-meson-g12a.o
+obj-$(CONFIG_PINCTRL_MESON_A1) += pinctrl-meson-a1.o
diff --git a/drivers/pinctrl/meson/pinctrl-meson-a1.c b/drivers/pinctrl/meson/pinctrl-meson-a1.c
new file mode 100644
index 0000000..f3a88f1
--- /dev/null
+++ b/drivers/pinctrl/meson/pinctrl-meson-a1.c
@@ -0,0 +1,942 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Pin controller and GPIO driver for Amlogic Meson A1 SoC.
+ *
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ * Author: Qianggui Song <qianggui.song@amlogic.com>
+ */
+
+#include <dt-bindings/gpio/meson-a1-gpio.h>
+#include "pinctrl-meson.h"
+#include "pinctrl-meson-axg-pmx.h"
+
+static const struct pinctrl_pin_desc meson_a1_periphs_pins[] = {
+	MESON_PIN(GPIOP_0),
+	MESON_PIN(GPIOP_1),
+	MESON_PIN(GPIOP_2),
+	MESON_PIN(GPIOP_3),
+	MESON_PIN(GPIOP_4),
+	MESON_PIN(GPIOP_5),
+	MESON_PIN(GPIOP_6),
+	MESON_PIN(GPIOP_7),
+	MESON_PIN(GPIOP_8),
+	MESON_PIN(GPIOP_9),
+	MESON_PIN(GPIOP_10),
+	MESON_PIN(GPIOP_11),
+	MESON_PIN(GPIOP_12),
+	MESON_PIN(GPIOB_0),
+	MESON_PIN(GPIOB_1),
+	MESON_PIN(GPIOB_2),
+	MESON_PIN(GPIOB_3),
+	MESON_PIN(GPIOB_4),
+	MESON_PIN(GPIOB_5),
+	MESON_PIN(GPIOB_6),
+	MESON_PIN(GPIOX_0),
+	MESON_PIN(GPIOX_1),
+	MESON_PIN(GPIOX_2),
+	MESON_PIN(GPIOX_3),
+	MESON_PIN(GPIOX_4),
+	MESON_PIN(GPIOX_5),
+	MESON_PIN(GPIOX_6),
+	MESON_PIN(GPIOX_7),
+	MESON_PIN(GPIOX_8),
+	MESON_PIN(GPIOX_9),
+	MESON_PIN(GPIOX_10),
+	MESON_PIN(GPIOX_11),
+	MESON_PIN(GPIOX_12),
+	MESON_PIN(GPIOX_13),
+	MESON_PIN(GPIOX_14),
+	MESON_PIN(GPIOX_15),
+	MESON_PIN(GPIOX_16),
+	MESON_PIN(GPIOF_0),
+	MESON_PIN(GPIOF_1),
+	MESON_PIN(GPIOF_2),
+	MESON_PIN(GPIOF_3),
+	MESON_PIN(GPIOF_4),
+	MESON_PIN(GPIOF_5),
+	MESON_PIN(GPIOF_6),
+	MESON_PIN(GPIOF_7),
+	MESON_PIN(GPIOF_8),
+	MESON_PIN(GPIOF_9),
+	MESON_PIN(GPIOF_10),
+	MESON_PIN(GPIOF_11),
+	MESON_PIN(GPIOF_12),
+	MESON_PIN(GPIOA_0),
+	MESON_PIN(GPIOA_1),
+	MESON_PIN(GPIOA_2),
+	MESON_PIN(GPIOA_3),
+	MESON_PIN(GPIOA_4),
+	MESON_PIN(GPIOA_5),
+	MESON_PIN(GPIOA_6),
+	MESON_PIN(GPIOA_7),
+	MESON_PIN(GPIOA_8),
+	MESON_PIN(GPIOA_9),
+	MESON_PIN(GPIOA_10),
+	MESON_PIN(GPIOA_11),
+};
+
+/* psram */
+static const unsigned int psram_clkn_pins[]		= { GPIOP_0 };
+static const unsigned int psram_clkp_pins[]		= { GPIOP_1 };
+static const unsigned int psram_ce_n_pins[]		= { GPIOP_2 };
+static const unsigned int psram_rst_n_pins[]		= { GPIOP_3 };
+static const unsigned int psram_adq0_pins[]		= { GPIOP_4 };
+static const unsigned int psram_adq1_pins[]		= { GPIOP_5 };
+static const unsigned int psram_adq2_pins[]		= { GPIOP_6 };
+static const unsigned int psram_adq3_pins[]		= { GPIOP_7 };
+static const unsigned int psram_adq4_pins[]		= { GPIOP_8 };
+static const unsigned int psram_adq5_pins[]		= { GPIOP_9 };
+static const unsigned int psram_adq6_pins[]		= { GPIOP_10 };
+static const unsigned int psram_adq7_pins[]		= { GPIOP_11 };
+static const unsigned int psram_dqs_dm_pins[]		= { GPIOP_12 };
+
+/* sdcard */
+static const unsigned int sdcard_d0_b_pins[]		= { GPIOB_0 };
+static const unsigned int sdcard_d1_b_pins[]		= { GPIOB_1 };
+static const unsigned int sdcard_d2_b_pins[]		= { GPIOB_2 };
+static const unsigned int sdcard_d3_b_pins[]		= { GPIOB_3 };
+static const unsigned int sdcard_clk_b_pins[]		= { GPIOB_4 };
+static const unsigned int sdcard_cmd_b_pins[]		= { GPIOB_5 };
+
+static const unsigned int sdcard_d0_x_pins[]		= { GPIOX_0 };
+static const unsigned int sdcard_d1_x_pins[]		= { GPIOX_1 };
+static const unsigned int sdcard_d2_x_pins[]		= { GPIOX_2 };
+static const unsigned int sdcard_d3_x_pins[]		= { GPIOX_3 };
+static const unsigned int sdcard_clk_x_pins[]		= { GPIOX_4 };
+static const unsigned int sdcard_cmd_x_pins[]		= { GPIOX_5 };
+
+/* spif */
+static const unsigned int spif_mo_pins[]		= { GPIOB_0 };
+static const unsigned int spif_mi_pins[]		= { GPIOB_1 };
+static const unsigned int spif_wp_n_pins[]		= { GPIOB_2 };
+static const unsigned int spif_hold_n_pins[]		= { GPIOB_3 };
+static const unsigned int spif_clk_pins[]		= { GPIOB_4 };
+static const unsigned int spif_cs_pins[]		= { GPIOB_5 };
+
+/* i2c0 */
+static const unsigned int i2c0_sck_f9_pins[]		= { GPIOF_9 };
+static const unsigned int i2c0_sda_f10_pins[]		= { GPIOF_10 };
+static const unsigned int i2c0_sck_f11_pins[]		= { GPIOF_11 };
+static const unsigned int i2c0_sda_f12_pins[]		= { GPIOF_12 };
+
+/* i2c1 */
+static const unsigned int i2c1_sda_x_pins[]		= { GPIOX_9 };
+static const unsigned int i2c1_sck_x_pins[]		= { GPIOX_10 };
+static const unsigned int i2c1_sda_a_pins[]		= { GPIOA_10 };
+static const unsigned int i2c1_sck_a_pins[]		= { GPIOA_11 };
+
+/* i2c2 */
+static const unsigned int i2c2_sck_x0_pins[]		= { GPIOX_0 };
+static const unsigned int i2c2_sda_x1_pins[]		= { GPIOX_1 };
+static const unsigned int i2c2_sck_x15_pins[]		= { GPIOX_15 };
+static const unsigned int i2c2_sda_x16_pins[]		= { GPIOX_16 };
+static const unsigned int i2c2_sck_a4_pins[]		= { GPIOA_4 };
+static const unsigned int i2c2_sda_a5_pins[]		= { GPIOA_5 };
+static const unsigned int i2c2_sck_a8_pins[]		= { GPIOA_8 };
+static const unsigned int i2c2_sda_a9_pins[]		= { GPIOA_9 };
+
+/* i2c3 */
+static const unsigned int i2c3_sck_f_pins[]		= { GPIOF_4 };
+static const unsigned int i2c3_sda_f_pins[]		= { GPIOF_5 };
+static const unsigned int i2c3_sck_x_pins[]		= { GPIOX_11 };
+static const unsigned int i2c3_sda_x_pins[]		= { GPIOX_12 };
+
+/* i2c slave */
+static const unsigned int i2c_slave_sck_a_pins[]	= { GPIOA_10 };
+static const unsigned int i2c_slave_sda_a_pins[]	= { GPIOA_11 };
+static const unsigned int i2c_slave_sck_f_pins[]	= { GPIOF_11 };
+static const unsigned int i2c_slave_sda_f_pins[]	= { GPIOF_12 };
+
+/* uart_a */
+static const unsigned int uart_a_tx_pins[]		= { GPIOX_11 };
+static const unsigned int uart_a_rx_pins[]		= { GPIOX_12 };
+static const unsigned int uart_a_cts_pins[]		= { GPIOX_13 };
+static const unsigned int uart_a_rts_pins[]		= { GPIOX_14 };
+
+/* uart_b */
+static const unsigned int uart_b_tx_x_pins[]		= { GPIOX_7 };
+static const unsigned int uart_b_rx_x_pins[]		= { GPIOX_8 };
+static const unsigned int uart_b_tx_f_pins[]		= { GPIOF_0 };
+static const unsigned int uart_b_rx_f_pins[]		= { GPIOF_1 };
+
+/* uart_c */
+static const unsigned int uart_c_tx_x0_pins[]		= { GPIOX_0 };
+static const unsigned int uart_c_rx_x1_pins[]		= { GPIOX_1 };
+static const unsigned int uart_c_cts_pins[]		= { GPIOX_2 };
+static const unsigned int uart_c_rts_pins[]		= { GPIOX_3 };
+static const unsigned int uart_c_tx_x15_pins[]		= { GPIOX_15 };
+static const unsigned int uart_c_rx_x16_pins[]		= { GPIOX_16 };
+
+/* pmw_a */
+static const unsigned int pwm_a_x6_pins[]		= { GPIOX_6 };
+static const unsigned int pwm_a_x7_pins[]		= { GPIOX_7 };
+static const unsigned int pwm_a_f6_pins[]		= { GPIOF_6 };
+static const unsigned int pwm_a_f10_pins[]		= { GPIOF_10 };
+static const unsigned int pwm_a_a_pins[]		= { GPIOA_5 };
+
+/* pmw_b */
+static const unsigned int pwm_b_x_pins[]		= { GPIOX_8 };
+static const unsigned int pwm_b_f_pins[]		= { GPIOF_7 };
+static const unsigned int pwm_b_a_pins[]		= { GPIOA_11 };
+
+/* pmw_c */
+static const unsigned int pwm_c_x_pins[]		= { GPIOX_9 };
+static const unsigned int pwm_c_f3_pins[]		= { GPIOF_3 };
+static const unsigned int pwm_c_f8_pins[]		= { GPIOF_8 };
+static const unsigned int pwm_c_a_pins[]		= { GPIOA_10 };
+
+/* pwm_d */
+static const unsigned int pwm_d_x10_pins[]		= { GPIOX_10 };
+static const unsigned int pwm_d_x13_pins[]		= { GPIOX_13 };
+static const unsigned int pwm_d_x15_pins[]		= { GPIOX_15 };
+static const unsigned int pwm_d_f_pins[]		= { GPIOF_11 };
+
+/* pwm_e */
+static const unsigned int pwm_e_p_pins[]		= { GPIOP_3 };
+static const unsigned int pwm_e_x2_pins[]		= { GPIOX_2 };
+static const unsigned int pwm_e_x14_pins[]		= { GPIOX_14 };
+static const unsigned int pwm_e_x16_pins[]		= { GPIOX_16 };
+static const unsigned int pwm_e_f_pins[]		= { GPIOF_3 };
+static const unsigned int pwm_e_a_pins[]		= { GPIOA_0 };
+
+/* pwm_f */
+static const unsigned int pwm_f_b_pins[]		= { GPIOB_6 };
+static const unsigned int pwm_f_x_pins[]		= { GPIOX_3 };
+static const unsigned int pwm_f_f4_pins[]		= { GPIOF_4 };
+static const unsigned int pwm_f_f12_pins[]		= { GPIOF_12 };
+
+/* pwm_a_hiz */
+static const unsigned int pwm_a_hiz_f8_pins[]		= { GPIOF_8 };
+static const unsigned int pwm_a_hiz_f10_pins[]		= { GPIOF_10 };
+static const unsigned int pmw_a_hiz_f6_pins[]		= { GPIOF_6 };
+
+/* pwm_b_hiz */
+static const unsigned int pwm_b_hiz_pins[]		= { GPIOF_7 };
+
+/* pmw_c_hiz */
+static const unsigned int pwm_c_hiz_pins[]		= { GPIOF_8 };
+
+/* tdm_a */
+static const unsigned int tdm_a_dout1_pins[]		= { GPIOX_7 };
+static const unsigned int tdm_a_dout0_pins[]		= { GPIOX_8 };
+static const unsigned int tdm_a_fs_pins[]		= { GPIOX_9 };
+static const unsigned int tdm_a_sclk_pins[]		= { GPIOX_10 };
+static const unsigned int tdm_a_din1_pins[]		= { GPIOX_7 };
+static const unsigned int tdm_a_din0_pins[]		= { GPIOX_8 };
+static const unsigned int tdm_a_slv_fs_pins[]		= { GPIOX_9 };
+static const unsigned int tdm_a_slv_sclk_pins[]		= { GPIOX_10 };
+
+/* spi_a */
+static const unsigned int spi_a_mosi_x2_pins[]		= { GPIOX_2 };
+static const unsigned int spi_a_ss0_x3_pins[]		= { GPIOX_3 };
+static const unsigned int spi_a_sclk_x4_pins[]		= { GPIOX_4 };
+static const unsigned int spi_a_miso_x5_pins[]		= { GPIOX_5 };
+static const unsigned int spi_a_mosi_x7_pins[]		= { GPIOX_7 };
+static const unsigned int spi_a_miso_x8_pins[]		= { GPIOX_8 };
+static const unsigned int spi_a_ss0_x9_pins[]		= { GPIOX_9 };
+static const unsigned int spi_a_sclk_x10_pins[]		= { GPIOX_10 };
+
+static const unsigned int spi_a_mosi_a_pins[]		= { GPIOA_6 };
+static const unsigned int spi_a_miso_a_pins[]		= { GPIOA_7 };
+static const unsigned int spi_a_ss0_a_pins[]		= { GPIOA_8 };
+static const unsigned int spi_a_sclk_a_pins[]		= { GPIOA_9 };
+
+/* pdm */
+static const unsigned int pdm_din0_x_pins[]		= { GPIOX_7 };
+static const unsigned int pdm_din1_x_pins[]		= { GPIOX_8 };
+static const unsigned int pdm_din2_x_pins[]		= { GPIOX_9 };
+static const unsigned int pdm_dclk_x_pins[]		= { GPIOX_10 };
+
+static const unsigned int pdm_din2_a_pins[]		= { GPIOA_6 };
+static const unsigned int pdm_din1_a_pins[]		= { GPIOA_7 };
+static const unsigned int pdm_din0_a_pins[]		= { GPIOA_8 };
+static const unsigned int pdm_dclk_pins[]		= { GPIOA_9 };
+
+/* gen_clk */
+static const unsigned int gen_clk_x_pins[]		= { GPIOX_7 };
+static const unsigned int gen_clk_f8_pins[]		= { GPIOF_8 };
+static const unsigned int gen_clk_f10_pins[]		= { GPIOF_10 };
+static const unsigned int gen_clk_a_pins[]		= { GPIOA_11 };
+
+/* jtag_a */
+static const unsigned int jtag_a_clk_pins[]		= { GPIOF_4 };
+static const unsigned int jtag_a_tms_pins[]		= { GPIOF_5 };
+static const unsigned int jtag_a_tdi_pins[]		= { GPIOF_6 };
+static const unsigned int jtag_a_tdo_pins[]		= { GPIOF_7 };
+
+/* clk_32_in */
+static const unsigned int clk_32k_in_pins[]		= { GPIOF_2 };
+
+/* ir in */
+static const unsigned int remote_input_f_pins[]		= { GPIOF_3 };
+static const unsigned int remote_input_a_pins[]		= { GPIOA_11 };
+
+/* ir out */
+static const unsigned int remote_out_pins[]		= { GPIOF_5 };
+
+/* spdif */
+static const unsigned int spdif_in_f6_pins[]		= { GPIOF_6 };
+static const unsigned int spdif_in_f7_pins[]		= { GPIOF_7 };
+
+/* sw */
+static const unsigned int swclk_pins[]			= { GPIOF_4 };
+static const unsigned int swdio_pins[]			= { GPIOF_5 };
+
+/* clk_25 */
+static const unsigned int clk25_pins[]			= { GPIOF_10 };
+
+/* cec_a */
+static const unsigned int cec_a_pins[]			= { GPIOF_2 };
+
+/* cec_b */
+static const unsigned int cec_b_pins[]			= { GPIOF_2 };
+
+/* clk12_24 */
+static const unsigned int clk12_24_pins[]		= { GPIOF_10 };
+
+/* mclk_0 */
+static const unsigned int mclk_0_pins[]			= { GPIOA_0 };
+
+/* tdm_b */
+static const unsigned int tdm_b_sclk_pins[]		= { GPIOA_1 };
+static const unsigned int tdm_b_fs_pins[]		= { GPIOA_2 };
+static const unsigned int tdm_b_dout0_pins[]		= { GPIOA_3 };
+static const unsigned int tdm_b_dout1_pins[]		= { GPIOA_4 };
+static const unsigned int tdm_b_dout2_pins[]		= { GPIOA_5 };
+static const unsigned int tdm_b_dout3_pins[]		= { GPIOA_6 };
+static const unsigned int tdm_b_dout4_pins[]		= { GPIOA_7 };
+static const unsigned int tdm_b_dout5_pins[]		= { GPIOA_8 };
+static const unsigned int tdm_b_slv_sclk_pins[]		= { GPIOA_5 };
+static const unsigned int tdm_b_slv_fs_pins[]		= { GPIOA_6 };
+static const unsigned int tdm_b_din0_pins[]		= { GPIOA_7 };
+static const unsigned int tdm_b_din1_pins[]		= { GPIOA_8 };
+static const unsigned int tdm_b_din2_pins[]		= { GPIOA_9 };
+
+/* mclk_vad */
+static const unsigned int mclk_vad_pins[]		= { GPIOA_0 };
+
+/* tdm_vad */
+static const unsigned int tdm_vad_sclk_a1_pins[]	= { GPIOA_1 };
+static const unsigned int tdm_vad_fs_a2_pins[]		= { GPIOA_2 };
+static const unsigned int tdm_vad_sclk_a5_pins[]	= { GPIOA_5 };
+static const unsigned int tdm_vad_fs_a6_pins[]		= { GPIOA_6 };
+
+/* tst_out */
+static const unsigned int tst_out0_pins[]		= { GPIOA_0 };
+static const unsigned int tst_out1_pins[]		= { GPIOA_1 };
+static const unsigned int tst_out2_pins[]		= { GPIOA_2 };
+static const unsigned int tst_out3_pins[]		= { GPIOA_3 };
+static const unsigned int tst_out4_pins[]		= { GPIOA_4 };
+static const unsigned int tst_out5_pins[]		= { GPIOA_5 };
+static const unsigned int tst_out6_pins[]		= { GPIOA_6 };
+static const unsigned int tst_out7_pins[]		= { GPIOA_7 };
+static const unsigned int tst_out8_pins[]		= { GPIOA_8 };
+static const unsigned int tst_out9_pins[]		= { GPIOA_9 };
+static const unsigned int tst_out10_pins[]		= { GPIOA_10 };
+static const unsigned int tst_out11_pins[]		= { GPIOA_11 };
+
+/* mute */
+static const unsigned int mute_key_pins[]		= { GPIOA_4 };
+static const unsigned int mute_en_pins[]		= { GPIOA_5 };
+
+static struct meson_pmx_group meson_a1_periphs_groups[] = {
+	GPIO_GROUP(GPIOP_0),
+	GPIO_GROUP(GPIOP_1),
+	GPIO_GROUP(GPIOP_2),
+	GPIO_GROUP(GPIOP_3),
+	GPIO_GROUP(GPIOP_4),
+	GPIO_GROUP(GPIOP_5),
+	GPIO_GROUP(GPIOP_6),
+	GPIO_GROUP(GPIOP_7),
+	GPIO_GROUP(GPIOP_8),
+	GPIO_GROUP(GPIOP_9),
+	GPIO_GROUP(GPIOP_10),
+	GPIO_GROUP(GPIOP_11),
+	GPIO_GROUP(GPIOP_12),
+	GPIO_GROUP(GPIOB_0),
+	GPIO_GROUP(GPIOB_1),
+	GPIO_GROUP(GPIOB_2),
+	GPIO_GROUP(GPIOB_3),
+	GPIO_GROUP(GPIOB_4),
+	GPIO_GROUP(GPIOB_5),
+	GPIO_GROUP(GPIOB_6),
+	GPIO_GROUP(GPIOX_0),
+	GPIO_GROUP(GPIOX_1),
+	GPIO_GROUP(GPIOX_2),
+	GPIO_GROUP(GPIOX_3),
+	GPIO_GROUP(GPIOX_4),
+	GPIO_GROUP(GPIOX_5),
+	GPIO_GROUP(GPIOX_6),
+	GPIO_GROUP(GPIOX_7),
+	GPIO_GROUP(GPIOX_8),
+	GPIO_GROUP(GPIOX_9),
+	GPIO_GROUP(GPIOX_10),
+	GPIO_GROUP(GPIOX_11),
+	GPIO_GROUP(GPIOX_12),
+	GPIO_GROUP(GPIOX_13),
+	GPIO_GROUP(GPIOX_14),
+	GPIO_GROUP(GPIOX_15),
+	GPIO_GROUP(GPIOX_16),
+	GPIO_GROUP(GPIOF_0),
+	GPIO_GROUP(GPIOF_1),
+	GPIO_GROUP(GPIOF_2),
+	GPIO_GROUP(GPIOF_3),
+	GPIO_GROUP(GPIOF_4),
+	GPIO_GROUP(GPIOF_5),
+	GPIO_GROUP(GPIOF_6),
+	GPIO_GROUP(GPIOF_7),
+	GPIO_GROUP(GPIOF_8),
+	GPIO_GROUP(GPIOF_9),
+	GPIO_GROUP(GPIOF_10),
+	GPIO_GROUP(GPIOF_11),
+	GPIO_GROUP(GPIOF_12),
+	GPIO_GROUP(GPIOA_0),
+	GPIO_GROUP(GPIOA_1),
+	GPIO_GROUP(GPIOA_2),
+	GPIO_GROUP(GPIOA_3),
+	GPIO_GROUP(GPIOA_4),
+	GPIO_GROUP(GPIOA_5),
+	GPIO_GROUP(GPIOA_6),
+	GPIO_GROUP(GPIOA_7),
+	GPIO_GROUP(GPIOA_8),
+	GPIO_GROUP(GPIOA_9),
+	GPIO_GROUP(GPIOA_10),
+	GPIO_GROUP(GPIOA_11),
+
+	/* bank P func1 */
+	GROUP(psram_clkn,		1),
+	GROUP(psram_clkp,		1),
+	GROUP(psram_ce_n,		1),
+	GROUP(psram_rst_n,		1),
+	GROUP(psram_adq0,		1),
+	GROUP(psram_adq1,		1),
+	GROUP(psram_adq2,		1),
+	GROUP(psram_adq3,		1),
+	GROUP(psram_adq4,		1),
+	GROUP(psram_adq5,		1),
+	GROUP(psram_adq6,		1),
+	GROUP(psram_adq7,		1),
+	GROUP(psram_dqs_dm,		1),
+
+	/*bank P func2 */
+	GROUP(pwm_e_p,			2),
+
+	/*bank B func1 */
+	GROUP(spif_mo,			1),
+	GROUP(spif_mi,			1),
+	GROUP(spif_wp_n,		1),
+	GROUP(spif_hold_n,		1),
+	GROUP(spif_clk,			1),
+	GROUP(spif_cs,			1),
+	GROUP(pwm_f_b,			1),
+
+	/*bank B func2 */
+	GROUP(sdcard_d0_b,		2),
+	GROUP(sdcard_d1_b,		2),
+	GROUP(sdcard_d2_b,		2),
+	GROUP(sdcard_d3_b,		2),
+	GROUP(sdcard_clk_b,		2),
+	GROUP(sdcard_cmd_b,		2),
+
+	/*bank X func1 */
+	GROUP(sdcard_d0_x,		1),
+	GROUP(sdcard_d1_x,		1),
+	GROUP(sdcard_d2_x,		1),
+	GROUP(sdcard_d3_x,		1),
+	GROUP(sdcard_clk_x,		1),
+	GROUP(sdcard_cmd_x,		1),
+	GROUP(pwm_a_x6,			1),
+	GROUP(tdm_a_dout1,		1),
+	GROUP(tdm_a_dout0,		1),
+	GROUP(tdm_a_fs,			1),
+	GROUP(tdm_a_sclk,		1),
+	GROUP(uart_a_tx,		1),
+	GROUP(uart_a_rx,		1),
+	GROUP(uart_a_cts,		1),
+	GROUP(uart_a_rts,		1),
+	GROUP(pwm_d_x15,		1),
+	GROUP(pwm_e_x16,		1),
+
+	/*bank X func2 */
+	GROUP(i2c2_sck_x0,		2),
+	GROUP(i2c2_sda_x1,		2),
+	GROUP(spi_a_mosi_x2,		2),
+	GROUP(spi_a_ss0_x3,		2),
+	GROUP(spi_a_sclk_x4,		2),
+	GROUP(spi_a_miso_x5,		2),
+	GROUP(tdm_a_din1,		2),
+	GROUP(tdm_a_din0,		2),
+	GROUP(tdm_a_slv_fs,		2),
+	GROUP(tdm_a_slv_sclk,		2),
+	GROUP(i2c3_sck_x,		2),
+	GROUP(i2c3_sda_x,		2),
+	GROUP(pwm_d_x13,		2),
+	GROUP(pwm_e_x14,		2),
+	GROUP(i2c2_sck_x15,		2),
+	GROUP(i2c2_sda_x16,		2),
+
+	/*bank X func3 */
+	GROUP(uart_c_tx_x0,		3),
+	GROUP(uart_c_rx_x1,		3),
+	GROUP(uart_c_cts,		3),
+	GROUP(uart_c_rts,		3),
+	GROUP(pdm_din0_x,		3),
+	GROUP(pdm_din1_x,		3),
+	GROUP(pdm_din2_x,		3),
+	GROUP(pdm_dclk_x,		3),
+	GROUP(uart_c_tx_x15,		3),
+	GROUP(uart_c_rx_x16,		3),
+
+	/*bank X func4 */
+	GROUP(pwm_e_x2,			4),
+	GROUP(pwm_f_x,			4),
+	GROUP(spi_a_mosi_x7,		4),
+	GROUP(spi_a_miso_x8,		4),
+	GROUP(spi_a_ss0_x9,		4),
+	GROUP(spi_a_sclk_x10,		4),
+
+	/*bank X func5 */
+	GROUP(uart_b_tx_x,		5),
+	GROUP(uart_b_rx_x,		5),
+	GROUP(i2c1_sda_x,		5),
+	GROUP(i2c1_sck_x,		5),
+
+	/*bank X func6 */
+	GROUP(pwm_a_x7,			6),
+	GROUP(pwm_b_x,			6),
+	GROUP(pwm_c_x,			6),
+	GROUP(pwm_d_x10,		6),
+
+	/*bank X func7 */
+	GROUP(gen_clk_x,		7),
+
+	/*bank F func1 */
+	GROUP(uart_b_tx_f,		1),
+	GROUP(uart_b_rx_f,		1),
+	GROUP(remote_input_f,		1),
+	GROUP(jtag_a_clk,		1),
+	GROUP(jtag_a_tms,		1),
+	GROUP(jtag_a_tdi,		1),
+	GROUP(jtag_a_tdo,		1),
+	GROUP(gen_clk_f8,		1),
+	GROUP(pwm_a_f10,		1),
+	GROUP(i2c0_sck_f11,		1),
+	GROUP(i2c0_sda_f12,		1),
+
+	/*bank F func2 */
+	GROUP(clk_32k_in,		2),
+	GROUP(pwm_e_f,			2),
+	GROUP(pwm_f_f4,			2),
+	GROUP(remote_out,		2),
+	GROUP(spdif_in_f6,		2),
+	GROUP(spdif_in_f7,		2),
+	GROUP(pwm_a_hiz_f8,		2),
+	GROUP(pwm_a_hiz_f10,		2),
+	GROUP(pwm_d_f,			2),
+	GROUP(pwm_f_f12,		2),
+
+	/*bank F func3 */
+	GROUP(pwm_c_f3,			3),
+	GROUP(swclk,			3),
+	GROUP(swdio,			3),
+	GROUP(pwm_a_f6,			3),
+	GROUP(pwm_b_f,			3),
+	GROUP(pwm_c_f8,			3),
+	GROUP(clk25,			3),
+	GROUP(i2c_slave_sck_f,		3),
+	GROUP(i2c_slave_sda_f,		3),
+
+	/*bank F func4 */
+	GROUP(cec_a,			4),
+	GROUP(i2c3_sck_f,		4),
+	GROUP(i2c3_sda_f,		4),
+	GROUP(pmw_a_hiz_f6,		4),
+	GROUP(pwm_b_hiz,		4),
+	GROUP(pwm_c_hiz,		4),
+	GROUP(i2c0_sck_f9,		4),
+	GROUP(i2c0_sda_f10,		4),
+
+	/*bank F func5 */
+	GROUP(cec_b,			5),
+	GROUP(clk12_24,			5),
+
+	/*bank F func7 */
+	GROUP(gen_clk_f10,		7),
+
+	/*bank A func1 */
+	GROUP(mclk_0,			1),
+	GROUP(tdm_b_sclk,		1),
+	GROUP(tdm_b_fs,			1),
+	GROUP(tdm_b_dout0,		1),
+	GROUP(tdm_b_dout1,		1),
+	GROUP(tdm_b_dout2,		1),
+	GROUP(tdm_b_dout3,		1),
+	GROUP(tdm_b_dout4,		1),
+	GROUP(tdm_b_dout5,		1),
+	GROUP(remote_input_a,		1),
+
+	/*bank A func2 */
+	GROUP(pwm_e_a,			2),
+	GROUP(tdm_b_slv_sclk,		2),
+	GROUP(tdm_b_slv_fs,		2),
+	GROUP(tdm_b_din0,		2),
+	GROUP(tdm_b_din1,		2),
+	GROUP(tdm_b_din2,		2),
+	GROUP(i2c1_sda_a,		2),
+	GROUP(i2c1_sck_a,		2),
+
+	/*bank A func3 */
+	GROUP(i2c2_sck_a4,		3),
+	GROUP(i2c2_sda_a5,		3),
+	GROUP(pdm_din2_a,		3),
+	GROUP(pdm_din1_a,		3),
+	GROUP(pdm_din0_a,		3),
+	GROUP(pdm_dclk,			3),
+	GROUP(pwm_c_a,			3),
+	GROUP(pwm_b_a,			3),
+
+	/*bank A func4 */
+	GROUP(pwm_a_a,			4),
+	GROUP(spi_a_mosi_a,		4),
+	GROUP(spi_a_miso_a,		4),
+	GROUP(spi_a_ss0_a,		4),
+	GROUP(spi_a_sclk_a,		4),
+	GROUP(i2c_slave_sck_a,		4),
+	GROUP(i2c_slave_sda_a,		4),
+
+	/*bank A func5 */
+	GROUP(mclk_vad,			5),
+	GROUP(tdm_vad_sclk_a1,		5),
+	GROUP(tdm_vad_fs_a2,		5),
+	GROUP(tdm_vad_sclk_a5,		5),
+	GROUP(tdm_vad_fs_a6,		5),
+	GROUP(i2c2_sck_a8,		5),
+	GROUP(i2c2_sda_a9,		5),
+
+	/*bank A func6 */
+	GROUP(tst_out0,			6),
+	GROUP(tst_out1,			6),
+	GROUP(tst_out2,			6),
+	GROUP(tst_out3,			6),
+	GROUP(tst_out4,			6),
+	GROUP(tst_out5,			6),
+	GROUP(tst_out6,			6),
+	GROUP(tst_out7,			6),
+	GROUP(tst_out8,			6),
+	GROUP(tst_out9,			6),
+	GROUP(tst_out10,		6),
+	GROUP(tst_out11,		6),
+
+	/*bank A func7 */
+	GROUP(mute_key,			7),
+	GROUP(mute_en,			7),
+	GROUP(gen_clk_a,		7),
+};
+
+static const char * const gpio_periphs_groups[] = {
+	"GPIOP_0", "GPIOP_1", "GPIOP_2", "GPIOP_3", "GPIOP_4",
+	"GPIOP_5", "GPIOP_6", "GPIOP_7", "GPIOP_8", "GPIOP_9",
+	"GPIOP_10", "GPIOP_11", "GPIOP_12",
+
+	"GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4",
+	"GPIOB_5", "GPIOB_6",
+
+	"GPIOX_0", "GPIOX_1", "GPIOX_2", "GPIOX_3", "GPIOX_4",
+	"GPIOX_5", "GPIOX_6", "GPIOX_7", "GPIOX_8", "GPIOX_9",
+	"GPIOX_10", "GPIOX_11", "GPIOX_12", "GPIOX_13", "GPIOX_14",
+	"GPIOX_15", "GPIOX_16",
+
+	"GPIOF_0", "GPIOF_1", "GPIOF_2", "GPIOF_3", "GPIOF_4",
+	"GPIOF_5", "GPIOF_6", "GPIOF_7", "GPIOF_8", "GPIOF_9",
+	"GPIOF_10", "GPIOF_11", "GPIOF_12",
+
+	"GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4",
+	"GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9",
+	"GPIOA_10", "GPIOA_11",
+};
+
+static const char * const psram_groups[] = {
+	"psram_clkn", "psram_clkp", "psram_ce_n", "psram_rst_n", "psram_adq0",
+	"psram_adq1", "psram_adq2", "psram_adq3", "psram_adq4", "psram_adq5",
+	"psram_adq6", "psram_adq7", "psram_dqs_dm",
+};
+
+static const char * const pwm_a_groups[] = {
+	"pwm_a_x6", "pwm_a_x7", "pwm_a_f10", "pwm_a_f6", "pwm_a_a",
+};
+
+static const char * const pwm_b_groups[] = {
+	"pwm_b_x", "pwm_b_f", "pwm_b_a",
+};
+
+static const char * const pwm_c_groups[] = {
+	"pwm_c_x", "pwm_c_f3", "pwm_c_f8", "pwm_c_a",
+};
+
+static const char * const pwm_d_groups[] = {
+	"pwm_d_x15", "pwm_d_x13", "pwm_d_x10", "pwm_d_f",
+};
+
+static const char * const pwm_e_groups[] = {
+	"pwm_e_p", "pwm_e_x16", "pwm_e_x14", "pwm_e_x2", "pwm_e_f",
+	"pwm_e_a",
+};
+
+static const char * const pwm_f_groups[] = {
+	"pwm_f_b", "pwm_f_x", "pwm_f_f4", "pwm_f_f12",
+};
+
+static const char * const pwm_a_hiz_groups[] = {
+	"pwm_a_hiz_f8", "pwm_a_hiz_f10", "pwm_a_hiz_f6",
+};
+
+static const char * const pwm_b_hiz_groups[] = {
+	"pwm_b_hiz",
+};
+
+static const char * const pwm_c_hiz_groups[] = {
+	"pwm_c_hiz",
+};
+
+static const char * const spif_groups[] = {
+	"spif_mo", "spif_mi", "spif_wp_n", "spif_hold_n", "spif_clk",
+	"spif_cs",
+};
+
+static const char * const sdcard_groups[] = {
+	"sdcard_d0_b", "sdcard_d1_b", "sdcard_d2_b", "sdcard_d3_b",
+	"sdcard_clk_b", "sdcard_cmd_b",
+
+	"sdcard_d0_x", "sdcard_d1_x", "sdcard_d2_x", "sdcard_d3_x",
+	"sdcard_clk_x", "sdcard_cmd_x",
+};
+
+static const char * const tdm_a_groups[] = {
+	"tdm_a_din0", "tdm_a_din1",  "tdm_a_fs", "tdm_a_sclk",
+	"tdm_a_slv_fs", "tdm_a_slv_sclk", "tdm_a_dout0", "tdm_a_dout1",
+};
+
+static const char * const uart_a_groups[] = {
+	"uart_a_tx", "uart_a_rx", "uart_a_cts", "uart_a_rts",
+};
+
+static const char * const uart_b_groups[] = {
+	"uart_b_tx_x", "uart_b_rx_x", "uart_b_tx_f", "uart_b_rx_f",
+};
+
+static const char * const uart_c_groups[] = {
+	"uart_c_tx_x0", "uart_c_rx_x1", "uart_c_cts", "uart_c_rts",
+	"uart_c_tx_x15", "uart_c_rx_x16",
+};
+
+static const char * const i2c0_groups[] = {
+	"i2c0_sck_f11", "i2c0_sda_f12", "i2c0_sck_f9", "i2c0_sda_f10",
+};
+
+static const char * const i2c1_groups[] = {
+	"i2c1_sda_x", "i2c1_sck_x", "i2c1_sda_a", "i2c1_sck_a",
+};
+
+static const char * const i2c2_groups[] = {
+	"i2c2_sck_x0", "i2c2_sda_x1", "i2c2_sck_x15", "i2c2_sda_x16",
+	"i2c2_sck_a4", "i2c2_sda_a5", "i2c2_sck_a8", "i2c2_sda_a9",
+};
+
+static const char * const i2c3_groups[] = {
+	"i2c3_sck_x", "i2c3_sda_x", "i2c3_sck_f", "i2c3_sda_f",
+};
+
+static const char * const i2c_slave_groups[] = {
+	"i2c_slave_sda_a", "i2c_slave_sck_a",
+	"i2c_slave_sda_f", "i2c_slave_sck_f",
+};
+
+static const char * const spi_a_groups[] = {
+	"spi_a_mosi_x2", "spi_a_ss0_x3", "spi_a_sclk_x4", "spi_a_miso_x5",
+	"spi_a_mosi_x7", "spi_a_miso_x8", "spi_a_ss0_x9", "spi_a_sclk_x10",
+
+	"spi_a_mosi_a", "spi_a_miso_a", "spi_a_ss0_a", "spi_a_sclk_a",
+};
+
+static const char * const pdm_groups[] = {
+	"pdm_din0_x", "pdm_din1_x", "pdm_din2_x", "pdm_dclk_x", "pdm_din2_a",
+	"pdm_din1_a", "pdm_din0_a", "pdm_dclk",
+};
+
+static const char * const gen_clk_groups[] = {
+	"gen_clk_x", "gen_clk_f8", "gen_clk_f10", "gen_clk_a",
+};
+
+static const char * const remote_input_groups[] = {
+	"remote_input_f",
+	"remote_input_a",
+};
+
+static const char * const jtag_a_groups[] = {
+	"jtag_a_clk", "jtag_a_tms", "jtag_a_tdi", "jtag_a_tdo",
+};
+
+static const char * const clk_32k_in_groups[] = {
+	"clk_32k_in",
+};
+
+static const char * const remote_out_groups[] = {
+	"remote_out",
+};
+
+static const char * const spdif_in_groups[] = {
+	"spdif_in_f6", "spdif_in_f7",
+};
+
+static const char * const sw_groups[] = {
+	"swclk", "swdio",
+};
+
+static const char * const clk25_groups[] = {
+	"clk_25",
+};
+
+static const char * const cec_a_groups[] = {
+	"cec_a",
+};
+
+static const char * const cec_b_groups[] = {
+	"cec_b",
+};
+
+static const char * const clk12_24_groups[] = {
+	"clk12_24",
+};
+
+static const char * const mclk_0_groups[] = {
+	"mclk_0",
+};
+
+static const char * const tdm_b_groups[] = {
+	"tdm_b_din0", "tdm_b_din1", "tdm_b_din2",
+	"tdm_b_sclk", "tdm_b_fs", "tdm_b_dout0", "tdm_b_dout1",
+	"tdm_b_dout2", "tdm_b_dout3", "tdm_b_dout4", "tdm_b_dout5",
+	"tdm_b_slv_sclk", "tdm_b_slv_fs",
+};
+
+static const char * const mclk_vad_groups[] = {
+	"mclk_vad",
+};
+
+static const char * const tdm_vad_groups[] = {
+	"tdm_vad_sclk_a1", "tdm_vad_fs_a2", "tdm_vad_sclk_a5", "tdm_vad_fs_a6",
+};
+
+static const char * const tst_out_groups[] = {
+	"tst_out0", "tst_out1", "tst_out2", "tst_out3",
+	"tst_out4", "tst_out5", "tst_out6", "tst_out7",
+	"tst_out8", "tst_out9", "tst_out10", "tst_out11",
+};
+
+static const char * const mute_groups[] = {
+	"mute_key", "mute_en",
+};
+
+static struct meson_pmx_func meson_a1_periphs_functions[] = {
+	FUNCTION(gpio_periphs),
+	FUNCTION(psram),
+	FUNCTION(pwm_a),
+	FUNCTION(pwm_b),
+	FUNCTION(pwm_c),
+	FUNCTION(pwm_d),
+	FUNCTION(pwm_e),
+	FUNCTION(pwm_f),
+	FUNCTION(pwm_a_hiz),
+	FUNCTION(pwm_b_hiz),
+	FUNCTION(pwm_c_hiz),
+	FUNCTION(spif),
+	FUNCTION(sdcard),
+	FUNCTION(tdm_a),
+	FUNCTION(uart_a),
+	FUNCTION(uart_b),
+	FUNCTION(uart_c),
+	FUNCTION(i2c0),
+	FUNCTION(i2c1),
+	FUNCTION(i2c2),
+	FUNCTION(i2c3),
+	FUNCTION(spi_a),
+	FUNCTION(pdm),
+	FUNCTION(gen_clk),
+	FUNCTION(remote_input),
+	FUNCTION(jtag_a),
+	FUNCTION(clk_32k_in),
+	FUNCTION(remote_out),
+	FUNCTION(spdif_in),
+	FUNCTION(sw),
+	FUNCTION(clk25),
+	FUNCTION(cec_a),
+	FUNCTION(cec_b),
+	FUNCTION(clk12_24),
+	FUNCTION(mclk_0),
+	FUNCTION(tdm_b),
+	FUNCTION(mclk_vad),
+	FUNCTION(tdm_vad),
+	FUNCTION(tst_out),
+	FUNCTION(mute),
+};
+
+static struct meson_bank meson_a1_periphs_banks[] = {
+	/* name  first  last  irq  pullen  pull  dir  out  in  ds*/
+	BANK_DS("P",  GPIOP_0,  GPIOP_12,  0,  12, 0x3,  0,  0x4,  0,
+		0x2,  0,  0x1,  0,  0x0,  0,  0x5,  0),
+	BANK_DS("B",  GPIOB_0,    GPIOB_6,   13,  19,  0x13,  0,  0x14,  0,
+		0x12,  0,  0x11,  0,  0x10,  0,  0x15,  0),
+	BANK_DS("X",  GPIOX_0,    GPIOX_16,  20,  36,  0x23,  0,  0x24,  0,
+		0x22,  0,  0x21,  0,  0x20,  0,  0x25,  0),
+	BANK_DS("F",  GPIOF_0,    GPIOF_12,  37,  49,  0x33,  0,  0x34,  0,
+		0x32,  0,  0x31,  0,  0x30,  0,  0x35,  0),
+	BANK_DS("A",  GPIOA_0,    GPIOA_11,  50,  61,  0x43,  0,  0x44,  0,
+		0x42,  0,  0x41,  0,  0x40,  0,  0x45,  0),
+};
+
+static struct meson_pmx_bank meson_a1_periphs_pmx_banks[] = {
+	/*  name	 first	    lask    reg	offset  */
+	BANK_PMX("P",    GPIOP_0, GPIOP_12, 0x0, 0),
+	BANK_PMX("B",    GPIOB_0, GPIOB_6,  0x2, 0),
+	BANK_PMX("X",    GPIOX_0, GPIOX_16, 0x3, 0),
+	BANK_PMX("F",    GPIOF_0, GPIOF_12, 0x6, 0),
+	BANK_PMX("A",    GPIOA_0, GPIOA_11, 0x8, 0),
+};
+
+static struct meson_axg_pmx_data meson_a1_periphs_pmx_banks_data = {
+	.pmx_banks	= meson_a1_periphs_pmx_banks,
+	.num_pmx_banks	= ARRAY_SIZE(meson_a1_periphs_pmx_banks),
+};
+
+static struct meson_pinctrl_data meson_a1_periphs_pinctrl_data = {
+	.name		= "periphs-banks",
+	.pins		= meson_a1_periphs_pins,
+	.groups		= meson_a1_periphs_groups,
+	.funcs		= meson_a1_periphs_functions,
+	.banks		= meson_a1_periphs_banks,
+	.num_pins	= ARRAY_SIZE(meson_a1_periphs_pins),
+	.num_groups	= ARRAY_SIZE(meson_a1_periphs_groups),
+	.num_funcs	= ARRAY_SIZE(meson_a1_periphs_functions),
+	.num_banks	= ARRAY_SIZE(meson_a1_periphs_banks),
+	.pmx_ops	= &meson_axg_pmx_ops,
+	.pmx_data	= &meson_a1_periphs_pmx_banks_data,
+	.reg_layout	= A1_LAYOUT,
+};
+
+static const struct of_device_id meson_a1_pinctrl_dt_match[] = {
+	{
+		.compatible = "amlogic,meson-a1-periphs-pinctrl",
+		.data = &meson_a1_periphs_pinctrl_data,
+	},
+	{ },
+};
+
+static struct platform_driver meson_a1_pinctrl_driver = {
+	.probe  = meson_pinctrl_probe,
+	.driver = {
+		.name	= "meson-a1-pinctrl",
+		.of_match_table = meson_a1_pinctrl_dt_match,
+	},
+};
+
+builtin_platform_driver(meson_a1_pinctrl_driver);
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
index 8bba9d0..885b89d 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.c
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -688,8 +688,12 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
 
 	pc->reg_ds = meson_map_resource(pc, gpio_np, "ds");
 	if (IS_ERR(pc->reg_ds)) {
-		dev_dbg(pc->dev, "ds registers not found - skipping\n");
-		pc->reg_ds = NULL;
+		if (pc->data->reg_layout == A1_LAYOUT) {
+			pc->reg_ds = pc->reg_pullen;
+		} else {
+			dev_dbg(pc->dev, "ds registers not found - skipping\n");
+			pc->reg_ds = NULL;
+		}
 	}
 
 	return 0;
diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
index c696f32..3d0c58d 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.h
+++ b/drivers/pinctrl/meson/pinctrl-meson.h
@@ -80,6 +80,14 @@ enum meson_pinconf_drv {
 };
 
 /**
+ * enum meson_reg_layout - identify two types of reg layout
+ */
+enum meson_reg_layout {
+	LEGACY_LAYOUT,
+	A1_LAYOUT,
+};
+
+/**
  * struct meson bank
  *
  * @name:	bank name
@@ -114,6 +122,7 @@ struct meson_pinctrl_data {
 	unsigned int num_banks;
 	const struct pinmux_ops *pmx_ops;
 	void *pmx_data;
+	unsigned int reg_layout;
 };
 
 struct meson_pinctrl {
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/3] arm64: dts: meson: a1: add pinctrl controller support
  2019-09-17  6:07 [PATCH 0/3] pinctrl: meson-a1: add pinctrl driver Qianggui Song
  2019-09-17  6:07 ` [PATCH 1/3] pinctrl: add compatible for Amlogic Meson A1 pin controller Qianggui Song
  2019-09-17  6:07 ` [PATCH 2/3] pinctrl: meson-a1: add pinctrl driver for Meson A1 Soc Qianggui Song
@ 2019-09-17  6:07 ` Qianggui Song
  2 siblings, 0 replies; 15+ messages in thread
From: Qianggui Song @ 2019-09-17  6:07 UTC (permalink / raw)
  To: Linus Walleij, linux-gpio
  Cc: Qianggui Song, Xingyu Chen, Jianxin Pan, Neil Armstrong,
	Jerome Brunet, Kevin Hilman, Martin Blumenstingl, Carlo Caione,
	Rob Herring, Hanjie Lin, Mark Rutland, linux-arm-kernel,
	linux-amlogic, linux-kernel, devicetree

add peripheral pinctrl controller to a1 soc

Signed-off-by: Qianggui Song <qianggui.song@amlogic.com>
Signed-off-by: Xingyu Chen <xingyu.chen@amlogic.com>
Signed-off-by: Jianxin Pan <jianxin.pan@amlogic.com>
---
 arch/arm64/boot/dts/amlogic/meson-a1.dtsi | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
index 7210ad0..0965259 100644
--- a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
@@ -5,6 +5,7 @@
 
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/gpio/meson-a1-gpio.h>
 
 / {
 	compatible = "amlogic,a1";
@@ -74,6 +75,23 @@
 			#size-cells = <2>;
 			ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x1000000>;
 
+			periphs_pinctrl: pinctrl@0400 {
+				compatible = "amlogic,meson-a1-periphs-pinctrl";
+				#address-cells = <2>;
+				#size-cells = <2>;
+				ranges;
+
+				gpio: bank@0400 {
+					reg = <0x0 0x0400 0x0 0x003c>,
+					      <0x0 0x0480 0x0 0x0118>;
+					reg-names = "mux", "gpio";
+					gpio-controller;
+					#gpio-cells = <2>;
+					gpio-ranges = <&periphs_pinctrl 0 0 62>;
+				};
+
+			};
+
 			uart_AO: serial@1c00 {
 				compatible = "amlogic,meson-gx-uart",
 					     "amlogic,meson-ao-uart";
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/3] pinctrl: meson-a1: add pinctrl driver for Meson A1 Soc
  2019-09-17  6:07 ` [PATCH 2/3] pinctrl: meson-a1: add pinctrl driver for Meson A1 Soc Qianggui Song
@ 2019-09-17  7:15   ` Neil Armstrong
  2019-09-17 10:59     ` Qianggui Song
  2019-09-17  9:29   ` Jerome Brunet
  1 sibling, 1 reply; 15+ messages in thread
From: Neil Armstrong @ 2019-09-17  7:15 UTC (permalink / raw)
  To: Qianggui Song, Linus Walleij, linux-gpio
  Cc: Xingyu Chen, Jianxin Pan, Jerome Brunet, Kevin Hilman,
	Martin Blumenstingl, Carlo Caione, Rob Herring, Hanjie Lin,
	Mark Rutland, linux-arm-kernel, linux-amlogic, linux-kernel

Hi,

On 17/09/2019 08:07, Qianggui Song wrote:
> Add pinctrl driver for Meson A1 Soc which share the same register layout of
> pinmux with previous Meson-G12A, however there is difference for gpio
> and pin config register in A1. The register layout is as below:
> 
> /* first bank */	      /* addr */
> - P_PADCTRL_GPIOP_I         base + 0x00 << 2
> - P_PADCTRL_GPIOP_O         base + 0x01 << 2
> - P_PADCTRL_GPIOP_OEN       base + 0x02 << 2
> - P_PADCTRL_GPIOP_PULL_EN   base + 0x03 << 2
> - P_PADCTRL_GPIOP_PULL_UP   base + 0x04 << 2
> - P_PADCTRL_GPIOP_DS        base + 0x05 << 2
> 
> /* second bank */
> - P_PADCTRL_GPIOB_I         base + 0x10 << 2
> - P_PADCTRL_GPIOB_O         base + 0x11 << 2
> - P_PADCTRL_GPIOB_OEN       base + 0x12 << 2
> - P_PADCTRL_GPIOB_PULL_EN   base + 0x13 << 2
> - P_PADCTRL_GPIOB_PULL_UP   base + 0x14 << 2
> - P_PADCTRL_GPIOB_DS        base + 0x15 << 2
> 
> Each bank contains at least 6 registers to be configured, if one bank has
> more than 16 gpios, an extra P_PADCTRL_GPIO[X]_DS_EXT is included. Between
> two adjacent P_PADCTRL_GPIO[X]_I, there is an offset 0x10, that is to say,
> for third bank, the offsets will be 0x20,0x21,0x22,0x23,0x24,0x25 according
> to above register layout.

Sorry but the explanation is not very clear, could you show the G12A mapping
in comparison to explain your point and how reg_ds = reg_pullen solves the issue
here ?

> 
> Current Meson pinctrl driver can cover such change by using base address of
> GPIO as that of drive-strength. While simply giving reg_ds = reg_pullen
> make wrong value to reg_ds for Soc that not support drive-strength like AXG
> . Here a private data used to identify register layout is introduced.

Could you also precise there is no AO pinctrl bank on A1.

> 
> Signed-off-by: Qianggui Song <qianggui.song@amlogic.com>
> Signed-off-by: Xingyu Chen <xingyu.chen@amlogic.com>
> Signed-off-by: Jianxin Pan <jianxin.pan@amlogic.com>
> ---
>  drivers/pinctrl/meson/Kconfig            |   6 +
>  drivers/pinctrl/meson/Makefile           |   1 +
>  drivers/pinctrl/meson/pinctrl-meson-a1.c | 942 +++++++++++++++++++++++++++++++
>  drivers/pinctrl/meson/pinctrl-meson.c    |   8 +-
>  drivers/pinctrl/meson/pinctrl-meson.h    |   9 +
>  5 files changed, 964 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/pinctrl/meson/pinctrl-meson-a1.c
> 
> diff --git a/drivers/pinctrl/meson/Kconfig b/drivers/pinctrl/meson/Kconfig
> index df55f61..3cb1191 100644
> --- a/drivers/pinctrl/meson/Kconfig
> +++ b/drivers/pinctrl/meson/Kconfig
> @@ -54,4 +54,10 @@ config PINCTRL_MESON_G12A
>  	select PINCTRL_MESON_AXG_PMX
>  	default y
>  
> +config PINCTRL_MESON_A1
> +	bool "Meson a1 Soc pinctrl driver"
> +	depends on ARM64
> +	select PINCTRL_MESON_AXG_PMX
> +	default y
> +
>  endif
> diff --git a/drivers/pinctrl/meson/Makefile b/drivers/pinctrl/meson/Makefile
> index a69c565..1a5bffe 100644
> --- a/drivers/pinctrl/meson/Makefile
> +++ b/drivers/pinctrl/meson/Makefile
> @@ -8,3 +8,4 @@ obj-$(CONFIG_PINCTRL_MESON_GXL) += pinctrl-meson-gxl.o
>  obj-$(CONFIG_PINCTRL_MESON_AXG_PMX) += pinctrl-meson-axg-pmx.o
>  obj-$(CONFIG_PINCTRL_MESON_AXG) += pinctrl-meson-axg.o
>  obj-$(CONFIG_PINCTRL_MESON_G12A) += pinctrl-meson-g12a.o
> +obj-$(CONFIG_PINCTRL_MESON_A1) += pinctrl-meson-a1.o
> diff --git a/drivers/pinctrl/meson/pinctrl-meson-a1.c b/drivers/pinctrl/meson/pinctrl-meson-a1.c
> new file mode 100644
> index 0000000..f3a88f1
> --- /dev/null
> +++ b/drivers/pinctrl/meson/pinctrl-meson-a1.c
> @@ -0,0 +1,942 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Pin controller and GPIO driver for Amlogic Meson A1 SoC.
> + *
> + * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
> + * Author: Qianggui Song <qianggui.song@amlogic.com>
> + */
> +
> +#include <dt-bindings/gpio/meson-a1-gpio.h>
> +#include "pinctrl-meson.h"
> +#include "pinctrl-meson-axg-pmx.h"
> +
> +static const struct pinctrl_pin_desc meson_a1_periphs_pins[] = {
> +	MESON_PIN(GPIOP_0),
> +	MESON_PIN(GPIOP_1),
> +	MESON_PIN(GPIOP_2),
> +	MESON_PIN(GPIOP_3),
> +	MESON_PIN(GPIOP_4),
> +	MESON_PIN(GPIOP_5),
> +	MESON_PIN(GPIOP_6),
> +	MESON_PIN(GPIOP_7),
> +	MESON_PIN(GPIOP_8),
> +	MESON_PIN(GPIOP_9),
> +	MESON_PIN(GPIOP_10),
> +	MESON_PIN(GPIOP_11),
> +	MESON_PIN(GPIOP_12),
> +	MESON_PIN(GPIOB_0),
> +	MESON_PIN(GPIOB_1),
> +	MESON_PIN(GPIOB_2),
> +	MESON_PIN(GPIOB_3),
> +	MESON_PIN(GPIOB_4),
> +	MESON_PIN(GPIOB_5),
> +	MESON_PIN(GPIOB_6),
> +	MESON_PIN(GPIOX_0),
> +	MESON_PIN(GPIOX_1),
> +	MESON_PIN(GPIOX_2),
> +	MESON_PIN(GPIOX_3),
> +	MESON_PIN(GPIOX_4),
> +	MESON_PIN(GPIOX_5),
> +	MESON_PIN(GPIOX_6),
> +	MESON_PIN(GPIOX_7),
> +	MESON_PIN(GPIOX_8),
> +	MESON_PIN(GPIOX_9),
> +	MESON_PIN(GPIOX_10),
> +	MESON_PIN(GPIOX_11),
> +	MESON_PIN(GPIOX_12),
> +	MESON_PIN(GPIOX_13),
> +	MESON_PIN(GPIOX_14),
> +	MESON_PIN(GPIOX_15),
> +	MESON_PIN(GPIOX_16),
> +	MESON_PIN(GPIOF_0),
> +	MESON_PIN(GPIOF_1),
> +	MESON_PIN(GPIOF_2),
> +	MESON_PIN(GPIOF_3),
> +	MESON_PIN(GPIOF_4),
> +	MESON_PIN(GPIOF_5),
> +	MESON_PIN(GPIOF_6),
> +	MESON_PIN(GPIOF_7),
> +	MESON_PIN(GPIOF_8),
> +	MESON_PIN(GPIOF_9),
> +	MESON_PIN(GPIOF_10),
> +	MESON_PIN(GPIOF_11),
> +	MESON_PIN(GPIOF_12),
> +	MESON_PIN(GPIOA_0),
> +	MESON_PIN(GPIOA_1),
> +	MESON_PIN(GPIOA_2),
> +	MESON_PIN(GPIOA_3),
> +	MESON_PIN(GPIOA_4),
> +	MESON_PIN(GPIOA_5),
> +	MESON_PIN(GPIOA_6),
> +	MESON_PIN(GPIOA_7),
> +	MESON_PIN(GPIOA_8),
> +	MESON_PIN(GPIOA_9),
> +	MESON_PIN(GPIOA_10),
> +	MESON_PIN(GPIOA_11),
> +};
> +
> +/* psram */
> +static const unsigned int psram_clkn_pins[]		= { GPIOP_0 };
> +static const unsigned int psram_clkp_pins[]		= { GPIOP_1 };
> +static const unsigned int psram_ce_n_pins[]		= { GPIOP_2 };
> +static const unsigned int psram_rst_n_pins[]		= { GPIOP_3 };
> +static const unsigned int psram_adq0_pins[]		= { GPIOP_4 };
> +static const unsigned int psram_adq1_pins[]		= { GPIOP_5 };
> +static const unsigned int psram_adq2_pins[]		= { GPIOP_6 };
> +static const unsigned int psram_adq3_pins[]		= { GPIOP_7 };
> +static const unsigned int psram_adq4_pins[]		= { GPIOP_8 };
> +static const unsigned int psram_adq5_pins[]		= { GPIOP_9 };
> +static const unsigned int psram_adq6_pins[]		= { GPIOP_10 };
> +static const unsigned int psram_adq7_pins[]		= { GPIOP_11 };
> +static const unsigned int psram_dqs_dm_pins[]		= { GPIOP_12 };
> +
> +/* sdcard */
> +static const unsigned int sdcard_d0_b_pins[]		= { GPIOB_0 };
> +static const unsigned int sdcard_d1_b_pins[]		= { GPIOB_1 };
> +static const unsigned int sdcard_d2_b_pins[]		= { GPIOB_2 };
> +static const unsigned int sdcard_d3_b_pins[]		= { GPIOB_3 };
> +static const unsigned int sdcard_clk_b_pins[]		= { GPIOB_4 };
> +static const unsigned int sdcard_cmd_b_pins[]		= { GPIOB_5 };
> +
> +static const unsigned int sdcard_d0_x_pins[]		= { GPIOX_0 };
> +static const unsigned int sdcard_d1_x_pins[]		= { GPIOX_1 };
> +static const unsigned int sdcard_d2_x_pins[]		= { GPIOX_2 };
> +static const unsigned int sdcard_d3_x_pins[]		= { GPIOX_3 };
> +static const unsigned int sdcard_clk_x_pins[]		= { GPIOX_4 };
> +static const unsigned int sdcard_cmd_x_pins[]		= { GPIOX_5 };
> +
> +/* spif */
> +static const unsigned int spif_mo_pins[]		= { GPIOB_0 };
> +static const unsigned int spif_mi_pins[]		= { GPIOB_1 };
> +static const unsigned int spif_wp_n_pins[]		= { GPIOB_2 };
> +static const unsigned int spif_hold_n_pins[]		= { GPIOB_3 };
> +static const unsigned int spif_clk_pins[]		= { GPIOB_4 };
> +static const unsigned int spif_cs_pins[]		= { GPIOB_5 };
> +
> +/* i2c0 */
> +static const unsigned int i2c0_sck_f9_pins[]		= { GPIOF_9 };
> +static const unsigned int i2c0_sda_f10_pins[]		= { GPIOF_10 };
> +static const unsigned int i2c0_sck_f11_pins[]		= { GPIOF_11 };
> +static const unsigned int i2c0_sda_f12_pins[]		= { GPIOF_12 };
> +
> +/* i2c1 */
> +static const unsigned int i2c1_sda_x_pins[]		= { GPIOX_9 };
> +static const unsigned int i2c1_sck_x_pins[]		= { GPIOX_10 };
> +static const unsigned int i2c1_sda_a_pins[]		= { GPIOA_10 };
> +static const unsigned int i2c1_sck_a_pins[]		= { GPIOA_11 };
> +
> +/* i2c2 */
> +static const unsigned int i2c2_sck_x0_pins[]		= { GPIOX_0 };
> +static const unsigned int i2c2_sda_x1_pins[]		= { GPIOX_1 };
> +static const unsigned int i2c2_sck_x15_pins[]		= { GPIOX_15 };
> +static const unsigned int i2c2_sda_x16_pins[]		= { GPIOX_16 };
> +static const unsigned int i2c2_sck_a4_pins[]		= { GPIOA_4 };
> +static const unsigned int i2c2_sda_a5_pins[]		= { GPIOA_5 };
> +static const unsigned int i2c2_sck_a8_pins[]		= { GPIOA_8 };
> +static const unsigned int i2c2_sda_a9_pins[]		= { GPIOA_9 };
> +
> +/* i2c3 */
> +static const unsigned int i2c3_sck_f_pins[]		= { GPIOF_4 };
> +static const unsigned int i2c3_sda_f_pins[]		= { GPIOF_5 };
> +static const unsigned int i2c3_sck_x_pins[]		= { GPIOX_11 };
> +static const unsigned int i2c3_sda_x_pins[]		= { GPIOX_12 };
> +
> +/* i2c slave */
> +static const unsigned int i2c_slave_sck_a_pins[]	= { GPIOA_10 };
> +static const unsigned int i2c_slave_sda_a_pins[]	= { GPIOA_11 };
> +static const unsigned int i2c_slave_sck_f_pins[]	= { GPIOF_11 };
> +static const unsigned int i2c_slave_sda_f_pins[]	= { GPIOF_12 };
> +
> +/* uart_a */
> +static const unsigned int uart_a_tx_pins[]		= { GPIOX_11 };
> +static const unsigned int uart_a_rx_pins[]		= { GPIOX_12 };
> +static const unsigned int uart_a_cts_pins[]		= { GPIOX_13 };
> +static const unsigned int uart_a_rts_pins[]		= { GPIOX_14 };
> +
> +/* uart_b */
> +static const unsigned int uart_b_tx_x_pins[]		= { GPIOX_7 };
> +static const unsigned int uart_b_rx_x_pins[]		= { GPIOX_8 };
> +static const unsigned int uart_b_tx_f_pins[]		= { GPIOF_0 };
> +static const unsigned int uart_b_rx_f_pins[]		= { GPIOF_1 };
> +
> +/* uart_c */
> +static const unsigned int uart_c_tx_x0_pins[]		= { GPIOX_0 };
> +static const unsigned int uart_c_rx_x1_pins[]		= { GPIOX_1 };
> +static const unsigned int uart_c_cts_pins[]		= { GPIOX_2 };
> +static const unsigned int uart_c_rts_pins[]		= { GPIOX_3 };
> +static const unsigned int uart_c_tx_x15_pins[]		= { GPIOX_15 };
> +static const unsigned int uart_c_rx_x16_pins[]		= { GPIOX_16 };
> +
> +/* pmw_a */
> +static const unsigned int pwm_a_x6_pins[]		= { GPIOX_6 };
> +static const unsigned int pwm_a_x7_pins[]		= { GPIOX_7 };
> +static const unsigned int pwm_a_f6_pins[]		= { GPIOF_6 };
> +static const unsigned int pwm_a_f10_pins[]		= { GPIOF_10 };
> +static const unsigned int pwm_a_a_pins[]		= { GPIOA_5 };
> +
> +/* pmw_b */
> +static const unsigned int pwm_b_x_pins[]		= { GPIOX_8 };
> +static const unsigned int pwm_b_f_pins[]		= { GPIOF_7 };
> +static const unsigned int pwm_b_a_pins[]		= { GPIOA_11 };
> +
> +/* pmw_c */
> +static const unsigned int pwm_c_x_pins[]		= { GPIOX_9 };
> +static const unsigned int pwm_c_f3_pins[]		= { GPIOF_3 };
> +static const unsigned int pwm_c_f8_pins[]		= { GPIOF_8 };
> +static const unsigned int pwm_c_a_pins[]		= { GPIOA_10 };
> +
> +/* pwm_d */
> +static const unsigned int pwm_d_x10_pins[]		= { GPIOX_10 };
> +static const unsigned int pwm_d_x13_pins[]		= { GPIOX_13 };
> +static const unsigned int pwm_d_x15_pins[]		= { GPIOX_15 };
> +static const unsigned int pwm_d_f_pins[]		= { GPIOF_11 };
> +
> +/* pwm_e */
> +static const unsigned int pwm_e_p_pins[]		= { GPIOP_3 };
> +static const unsigned int pwm_e_x2_pins[]		= { GPIOX_2 };
> +static const unsigned int pwm_e_x14_pins[]		= { GPIOX_14 };
> +static const unsigned int pwm_e_x16_pins[]		= { GPIOX_16 };
> +static const unsigned int pwm_e_f_pins[]		= { GPIOF_3 };
> +static const unsigned int pwm_e_a_pins[]		= { GPIOA_0 };
> +
> +/* pwm_f */
> +static const unsigned int pwm_f_b_pins[]		= { GPIOB_6 };
> +static const unsigned int pwm_f_x_pins[]		= { GPIOX_3 };
> +static const unsigned int pwm_f_f4_pins[]		= { GPIOF_4 };
> +static const unsigned int pwm_f_f12_pins[]		= { GPIOF_12 };
> +
> +/* pwm_a_hiz */
> +static const unsigned int pwm_a_hiz_f8_pins[]		= { GPIOF_8 };
> +static const unsigned int pwm_a_hiz_f10_pins[]		= { GPIOF_10 };
> +static const unsigned int pmw_a_hiz_f6_pins[]		= { GPIOF_6 };
> +
> +/* pwm_b_hiz */
> +static const unsigned int pwm_b_hiz_pins[]		= { GPIOF_7 };
> +
> +/* pmw_c_hiz */
> +static const unsigned int pwm_c_hiz_pins[]		= { GPIOF_8 };
> +
> +/* tdm_a */
> +static const unsigned int tdm_a_dout1_pins[]		= { GPIOX_7 };
> +static const unsigned int tdm_a_dout0_pins[]		= { GPIOX_8 };
> +static const unsigned int tdm_a_fs_pins[]		= { GPIOX_9 };
> +static const unsigned int tdm_a_sclk_pins[]		= { GPIOX_10 };
> +static const unsigned int tdm_a_din1_pins[]		= { GPIOX_7 };
> +static const unsigned int tdm_a_din0_pins[]		= { GPIOX_8 };
> +static const unsigned int tdm_a_slv_fs_pins[]		= { GPIOX_9 };
> +static const unsigned int tdm_a_slv_sclk_pins[]		= { GPIOX_10 };
> +
> +/* spi_a */
> +static const unsigned int spi_a_mosi_x2_pins[]		= { GPIOX_2 };
> +static const unsigned int spi_a_ss0_x3_pins[]		= { GPIOX_3 };
> +static const unsigned int spi_a_sclk_x4_pins[]		= { GPIOX_4 };
> +static const unsigned int spi_a_miso_x5_pins[]		= { GPIOX_5 };
> +static const unsigned int spi_a_mosi_x7_pins[]		= { GPIOX_7 };
> +static const unsigned int spi_a_miso_x8_pins[]		= { GPIOX_8 };
> +static const unsigned int spi_a_ss0_x9_pins[]		= { GPIOX_9 };
> +static const unsigned int spi_a_sclk_x10_pins[]		= { GPIOX_10 };
> +
> +static const unsigned int spi_a_mosi_a_pins[]		= { GPIOA_6 };
> +static const unsigned int spi_a_miso_a_pins[]		= { GPIOA_7 };
> +static const unsigned int spi_a_ss0_a_pins[]		= { GPIOA_8 };
> +static const unsigned int spi_a_sclk_a_pins[]		= { GPIOA_9 };
> +
> +/* pdm */
> +static const unsigned int pdm_din0_x_pins[]		= { GPIOX_7 };
> +static const unsigned int pdm_din1_x_pins[]		= { GPIOX_8 };
> +static const unsigned int pdm_din2_x_pins[]		= { GPIOX_9 };
> +static const unsigned int pdm_dclk_x_pins[]		= { GPIOX_10 };
> +
> +static const unsigned int pdm_din2_a_pins[]		= { GPIOA_6 };
> +static const unsigned int pdm_din1_a_pins[]		= { GPIOA_7 };
> +static const unsigned int pdm_din0_a_pins[]		= { GPIOA_8 };
> +static const unsigned int pdm_dclk_pins[]		= { GPIOA_9 };
> +
> +/* gen_clk */
> +static const unsigned int gen_clk_x_pins[]		= { GPIOX_7 };
> +static const unsigned int gen_clk_f8_pins[]		= { GPIOF_8 };
> +static const unsigned int gen_clk_f10_pins[]		= { GPIOF_10 };
> +static const unsigned int gen_clk_a_pins[]		= { GPIOA_11 };
> +
> +/* jtag_a */
> +static const unsigned int jtag_a_clk_pins[]		= { GPIOF_4 };
> +static const unsigned int jtag_a_tms_pins[]		= { GPIOF_5 };
> +static const unsigned int jtag_a_tdi_pins[]		= { GPIOF_6 };
> +static const unsigned int jtag_a_tdo_pins[]		= { GPIOF_7 };
> +
> +/* clk_32_in */
> +static const unsigned int clk_32k_in_pins[]		= { GPIOF_2 };
> +
> +/* ir in */
> +static const unsigned int remote_input_f_pins[]		= { GPIOF_3 };
> +static const unsigned int remote_input_a_pins[]		= { GPIOA_11 };
> +
> +/* ir out */
> +static const unsigned int remote_out_pins[]		= { GPIOF_5 };
> +
> +/* spdif */
> +static const unsigned int spdif_in_f6_pins[]		= { GPIOF_6 };
> +static const unsigned int spdif_in_f7_pins[]		= { GPIOF_7 };
> +
> +/* sw */
> +static const unsigned int swclk_pins[]			= { GPIOF_4 };
> +static const unsigned int swdio_pins[]			= { GPIOF_5 };
> +
> +/* clk_25 */
> +static const unsigned int clk25_pins[]			= { GPIOF_10 };
> +
> +/* cec_a */
> +static const unsigned int cec_a_pins[]			= { GPIOF_2 };
> +
> +/* cec_b */
> +static const unsigned int cec_b_pins[]			= { GPIOF_2 };
> +
> +/* clk12_24 */
> +static const unsigned int clk12_24_pins[]		= { GPIOF_10 };
> +
> +/* mclk_0 */
> +static const unsigned int mclk_0_pins[]			= { GPIOA_0 };
> +
> +/* tdm_b */
> +static const unsigned int tdm_b_sclk_pins[]		= { GPIOA_1 };
> +static const unsigned int tdm_b_fs_pins[]		= { GPIOA_2 };
> +static const unsigned int tdm_b_dout0_pins[]		= { GPIOA_3 };
> +static const unsigned int tdm_b_dout1_pins[]		= { GPIOA_4 };
> +static const unsigned int tdm_b_dout2_pins[]		= { GPIOA_5 };
> +static const unsigned int tdm_b_dout3_pins[]		= { GPIOA_6 };
> +static const unsigned int tdm_b_dout4_pins[]		= { GPIOA_7 };
> +static const unsigned int tdm_b_dout5_pins[]		= { GPIOA_8 };
> +static const unsigned int tdm_b_slv_sclk_pins[]		= { GPIOA_5 };
> +static const unsigned int tdm_b_slv_fs_pins[]		= { GPIOA_6 };
> +static const unsigned int tdm_b_din0_pins[]		= { GPIOA_7 };
> +static const unsigned int tdm_b_din1_pins[]		= { GPIOA_8 };
> +static const unsigned int tdm_b_din2_pins[]		= { GPIOA_9 };
> +
> +/* mclk_vad */
> +static const unsigned int mclk_vad_pins[]		= { GPIOA_0 };
> +
> +/* tdm_vad */
> +static const unsigned int tdm_vad_sclk_a1_pins[]	= { GPIOA_1 };
> +static const unsigned int tdm_vad_fs_a2_pins[]		= { GPIOA_2 };
> +static const unsigned int tdm_vad_sclk_a5_pins[]	= { GPIOA_5 };
> +static const unsigned int tdm_vad_fs_a6_pins[]		= { GPIOA_6 };
> +
> +/* tst_out */
> +static const unsigned int tst_out0_pins[]		= { GPIOA_0 };
> +static const unsigned int tst_out1_pins[]		= { GPIOA_1 };
> +static const unsigned int tst_out2_pins[]		= { GPIOA_2 };
> +static const unsigned int tst_out3_pins[]		= { GPIOA_3 };
> +static const unsigned int tst_out4_pins[]		= { GPIOA_4 };
> +static const unsigned int tst_out5_pins[]		= { GPIOA_5 };
> +static const unsigned int tst_out6_pins[]		= { GPIOA_6 };
> +static const unsigned int tst_out7_pins[]		= { GPIOA_7 };
> +static const unsigned int tst_out8_pins[]		= { GPIOA_8 };
> +static const unsigned int tst_out9_pins[]		= { GPIOA_9 };
> +static const unsigned int tst_out10_pins[]		= { GPIOA_10 };
> +static const unsigned int tst_out11_pins[]		= { GPIOA_11 };
> +
> +/* mute */
> +static const unsigned int mute_key_pins[]		= { GPIOA_4 };
> +static const unsigned int mute_en_pins[]		= { GPIOA_5 };
> +
> +static struct meson_pmx_group meson_a1_periphs_groups[] = {
> +	GPIO_GROUP(GPIOP_0),
> +	GPIO_GROUP(GPIOP_1),
> +	GPIO_GROUP(GPIOP_2),
> +	GPIO_GROUP(GPIOP_3),
> +	GPIO_GROUP(GPIOP_4),
> +	GPIO_GROUP(GPIOP_5),
> +	GPIO_GROUP(GPIOP_6),
> +	GPIO_GROUP(GPIOP_7),
> +	GPIO_GROUP(GPIOP_8),
> +	GPIO_GROUP(GPIOP_9),
> +	GPIO_GROUP(GPIOP_10),
> +	GPIO_GROUP(GPIOP_11),
> +	GPIO_GROUP(GPIOP_12),
> +	GPIO_GROUP(GPIOB_0),
> +	GPIO_GROUP(GPIOB_1),
> +	GPIO_GROUP(GPIOB_2),
> +	GPIO_GROUP(GPIOB_3),
> +	GPIO_GROUP(GPIOB_4),
> +	GPIO_GROUP(GPIOB_5),
> +	GPIO_GROUP(GPIOB_6),
> +	GPIO_GROUP(GPIOX_0),
> +	GPIO_GROUP(GPIOX_1),
> +	GPIO_GROUP(GPIOX_2),
> +	GPIO_GROUP(GPIOX_3),
> +	GPIO_GROUP(GPIOX_4),
> +	GPIO_GROUP(GPIOX_5),
> +	GPIO_GROUP(GPIOX_6),
> +	GPIO_GROUP(GPIOX_7),
> +	GPIO_GROUP(GPIOX_8),
> +	GPIO_GROUP(GPIOX_9),
> +	GPIO_GROUP(GPIOX_10),
> +	GPIO_GROUP(GPIOX_11),
> +	GPIO_GROUP(GPIOX_12),
> +	GPIO_GROUP(GPIOX_13),
> +	GPIO_GROUP(GPIOX_14),
> +	GPIO_GROUP(GPIOX_15),
> +	GPIO_GROUP(GPIOX_16),
> +	GPIO_GROUP(GPIOF_0),
> +	GPIO_GROUP(GPIOF_1),
> +	GPIO_GROUP(GPIOF_2),
> +	GPIO_GROUP(GPIOF_3),
> +	GPIO_GROUP(GPIOF_4),
> +	GPIO_GROUP(GPIOF_5),
> +	GPIO_GROUP(GPIOF_6),
> +	GPIO_GROUP(GPIOF_7),
> +	GPIO_GROUP(GPIOF_8),
> +	GPIO_GROUP(GPIOF_9),
> +	GPIO_GROUP(GPIOF_10),
> +	GPIO_GROUP(GPIOF_11),
> +	GPIO_GROUP(GPIOF_12),
> +	GPIO_GROUP(GPIOA_0),
> +	GPIO_GROUP(GPIOA_1),
> +	GPIO_GROUP(GPIOA_2),
> +	GPIO_GROUP(GPIOA_3),
> +	GPIO_GROUP(GPIOA_4),
> +	GPIO_GROUP(GPIOA_5),
> +	GPIO_GROUP(GPIOA_6),
> +	GPIO_GROUP(GPIOA_7),
> +	GPIO_GROUP(GPIOA_8),
> +	GPIO_GROUP(GPIOA_9),
> +	GPIO_GROUP(GPIOA_10),
> +	GPIO_GROUP(GPIOA_11),
> +
> +	/* bank P func1 */
> +	GROUP(psram_clkn,		1),
> +	GROUP(psram_clkp,		1),
> +	GROUP(psram_ce_n,		1),
> +	GROUP(psram_rst_n,		1),
> +	GROUP(psram_adq0,		1),
> +	GROUP(psram_adq1,		1),
> +	GROUP(psram_adq2,		1),
> +	GROUP(psram_adq3,		1),
> +	GROUP(psram_adq4,		1),
> +	GROUP(psram_adq5,		1),
> +	GROUP(psram_adq6,		1),
> +	GROUP(psram_adq7,		1),
> +	GROUP(psram_dqs_dm,		1),
> +
> +	/*bank P func2 */
> +	GROUP(pwm_e_p,			2),
> +
> +	/*bank B func1 */
> +	GROUP(spif_mo,			1),
> +	GROUP(spif_mi,			1),
> +	GROUP(spif_wp_n,		1),
> +	GROUP(spif_hold_n,		1),
> +	GROUP(spif_clk,			1),
> +	GROUP(spif_cs,			1),
> +	GROUP(pwm_f_b,			1),
> +
> +	/*bank B func2 */
> +	GROUP(sdcard_d0_b,		2),
> +	GROUP(sdcard_d1_b,		2),
> +	GROUP(sdcard_d2_b,		2),
> +	GROUP(sdcard_d3_b,		2),
> +	GROUP(sdcard_clk_b,		2),
> +	GROUP(sdcard_cmd_b,		2),
> +
> +	/*bank X func1 */
> +	GROUP(sdcard_d0_x,		1),
> +	GROUP(sdcard_d1_x,		1),
> +	GROUP(sdcard_d2_x,		1),
> +	GROUP(sdcard_d3_x,		1),
> +	GROUP(sdcard_clk_x,		1),
> +	GROUP(sdcard_cmd_x,		1),
> +	GROUP(pwm_a_x6,			1),
> +	GROUP(tdm_a_dout1,		1),
> +	GROUP(tdm_a_dout0,		1),
> +	GROUP(tdm_a_fs,			1),
> +	GROUP(tdm_a_sclk,		1),
> +	GROUP(uart_a_tx,		1),
> +	GROUP(uart_a_rx,		1),
> +	GROUP(uart_a_cts,		1),
> +	GROUP(uart_a_rts,		1),
> +	GROUP(pwm_d_x15,		1),
> +	GROUP(pwm_e_x16,		1),
> +
> +	/*bank X func2 */
> +	GROUP(i2c2_sck_x0,		2),
> +	GROUP(i2c2_sda_x1,		2),
> +	GROUP(spi_a_mosi_x2,		2),
> +	GROUP(spi_a_ss0_x3,		2),
> +	GROUP(spi_a_sclk_x4,		2),
> +	GROUP(spi_a_miso_x5,		2),
> +	GROUP(tdm_a_din1,		2),
> +	GROUP(tdm_a_din0,		2),
> +	GROUP(tdm_a_slv_fs,		2),
> +	GROUP(tdm_a_slv_sclk,		2),
> +	GROUP(i2c3_sck_x,		2),
> +	GROUP(i2c3_sda_x,		2),
> +	GROUP(pwm_d_x13,		2),
> +	GROUP(pwm_e_x14,		2),
> +	GROUP(i2c2_sck_x15,		2),
> +	GROUP(i2c2_sda_x16,		2),
> +
> +	/*bank X func3 */
> +	GROUP(uart_c_tx_x0,		3),
> +	GROUP(uart_c_rx_x1,		3),
> +	GROUP(uart_c_cts,		3),
> +	GROUP(uart_c_rts,		3),
> +	GROUP(pdm_din0_x,		3),
> +	GROUP(pdm_din1_x,		3),
> +	GROUP(pdm_din2_x,		3),
> +	GROUP(pdm_dclk_x,		3),
> +	GROUP(uart_c_tx_x15,		3),
> +	GROUP(uart_c_rx_x16,		3),
> +
> +	/*bank X func4 */
> +	GROUP(pwm_e_x2,			4),
> +	GROUP(pwm_f_x,			4),
> +	GROUP(spi_a_mosi_x7,		4),
> +	GROUP(spi_a_miso_x8,		4),
> +	GROUP(spi_a_ss0_x9,		4),
> +	GROUP(spi_a_sclk_x10,		4),
> +
> +	/*bank X func5 */
> +	GROUP(uart_b_tx_x,		5),
> +	GROUP(uart_b_rx_x,		5),
> +	GROUP(i2c1_sda_x,		5),
> +	GROUP(i2c1_sck_x,		5),
> +
> +	/*bank X func6 */
> +	GROUP(pwm_a_x7,			6),
> +	GROUP(pwm_b_x,			6),
> +	GROUP(pwm_c_x,			6),
> +	GROUP(pwm_d_x10,		6),
> +
> +	/*bank X func7 */
> +	GROUP(gen_clk_x,		7),
> +
> +	/*bank F func1 */
> +	GROUP(uart_b_tx_f,		1),
> +	GROUP(uart_b_rx_f,		1),
> +	GROUP(remote_input_f,		1),
> +	GROUP(jtag_a_clk,		1),
> +	GROUP(jtag_a_tms,		1),
> +	GROUP(jtag_a_tdi,		1),
> +	GROUP(jtag_a_tdo,		1),
> +	GROUP(gen_clk_f8,		1),
> +	GROUP(pwm_a_f10,		1),
> +	GROUP(i2c0_sck_f11,		1),
> +	GROUP(i2c0_sda_f12,		1),
> +
> +	/*bank F func2 */
> +	GROUP(clk_32k_in,		2),
> +	GROUP(pwm_e_f,			2),
> +	GROUP(pwm_f_f4,			2),
> +	GROUP(remote_out,		2),
> +	GROUP(spdif_in_f6,		2),
> +	GROUP(spdif_in_f7,		2),
> +	GROUP(pwm_a_hiz_f8,		2),
> +	GROUP(pwm_a_hiz_f10,		2),
> +	GROUP(pwm_d_f,			2),
> +	GROUP(pwm_f_f12,		2),
> +
> +	/*bank F func3 */
> +	GROUP(pwm_c_f3,			3),
> +	GROUP(swclk,			3),
> +	GROUP(swdio,			3),
> +	GROUP(pwm_a_f6,			3),
> +	GROUP(pwm_b_f,			3),
> +	GROUP(pwm_c_f8,			3),
> +	GROUP(clk25,			3),
> +	GROUP(i2c_slave_sck_f,		3),
> +	GROUP(i2c_slave_sda_f,		3),
> +
> +	/*bank F func4 */
> +	GROUP(cec_a,			4),
> +	GROUP(i2c3_sck_f,		4),
> +	GROUP(i2c3_sda_f,		4),
> +	GROUP(pmw_a_hiz_f6,		4),
> +	GROUP(pwm_b_hiz,		4),
> +	GROUP(pwm_c_hiz,		4),
> +	GROUP(i2c0_sck_f9,		4),
> +	GROUP(i2c0_sda_f10,		4),
> +
> +	/*bank F func5 */
> +	GROUP(cec_b,			5),
> +	GROUP(clk12_24,			5),
> +
> +	/*bank F func7 */
> +	GROUP(gen_clk_f10,		7),
> +
> +	/*bank A func1 */
> +	GROUP(mclk_0,			1),
> +	GROUP(tdm_b_sclk,		1),
> +	GROUP(tdm_b_fs,			1),
> +	GROUP(tdm_b_dout0,		1),
> +	GROUP(tdm_b_dout1,		1),
> +	GROUP(tdm_b_dout2,		1),
> +	GROUP(tdm_b_dout3,		1),
> +	GROUP(tdm_b_dout4,		1),
> +	GROUP(tdm_b_dout5,		1),
> +	GROUP(remote_input_a,		1),
> +
> +	/*bank A func2 */
> +	GROUP(pwm_e_a,			2),
> +	GROUP(tdm_b_slv_sclk,		2),
> +	GROUP(tdm_b_slv_fs,		2),
> +	GROUP(tdm_b_din0,		2),
> +	GROUP(tdm_b_din1,		2),
> +	GROUP(tdm_b_din2,		2),
> +	GROUP(i2c1_sda_a,		2),
> +	GROUP(i2c1_sck_a,		2),
> +
> +	/*bank A func3 */
> +	GROUP(i2c2_sck_a4,		3),
> +	GROUP(i2c2_sda_a5,		3),
> +	GROUP(pdm_din2_a,		3),
> +	GROUP(pdm_din1_a,		3),
> +	GROUP(pdm_din0_a,		3),
> +	GROUP(pdm_dclk,			3),
> +	GROUP(pwm_c_a,			3),
> +	GROUP(pwm_b_a,			3),
> +
> +	/*bank A func4 */
> +	GROUP(pwm_a_a,			4),
> +	GROUP(spi_a_mosi_a,		4),
> +	GROUP(spi_a_miso_a,		4),
> +	GROUP(spi_a_ss0_a,		4),
> +	GROUP(spi_a_sclk_a,		4),
> +	GROUP(i2c_slave_sck_a,		4),
> +	GROUP(i2c_slave_sda_a,		4),
> +
> +	/*bank A func5 */
> +	GROUP(mclk_vad,			5),
> +	GROUP(tdm_vad_sclk_a1,		5),
> +	GROUP(tdm_vad_fs_a2,		5),
> +	GROUP(tdm_vad_sclk_a5,		5),
> +	GROUP(tdm_vad_fs_a6,		5),
> +	GROUP(i2c2_sck_a8,		5),
> +	GROUP(i2c2_sda_a9,		5),
> +
> +	/*bank A func6 */
> +	GROUP(tst_out0,			6),
> +	GROUP(tst_out1,			6),
> +	GROUP(tst_out2,			6),
> +	GROUP(tst_out3,			6),
> +	GROUP(tst_out4,			6),
> +	GROUP(tst_out5,			6),
> +	GROUP(tst_out6,			6),
> +	GROUP(tst_out7,			6),
> +	GROUP(tst_out8,			6),
> +	GROUP(tst_out9,			6),
> +	GROUP(tst_out10,		6),
> +	GROUP(tst_out11,		6),
> +
> +	/*bank A func7 */
> +	GROUP(mute_key,			7),
> +	GROUP(mute_en,			7),
> +	GROUP(gen_clk_a,		7),
> +};
> +
> +static const char * const gpio_periphs_groups[] = {
> +	"GPIOP_0", "GPIOP_1", "GPIOP_2", "GPIOP_3", "GPIOP_4",
> +	"GPIOP_5", "GPIOP_6", "GPIOP_7", "GPIOP_8", "GPIOP_9",
> +	"GPIOP_10", "GPIOP_11", "GPIOP_12",
> +
> +	"GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4",
> +	"GPIOB_5", "GPIOB_6",
> +
> +	"GPIOX_0", "GPIOX_1", "GPIOX_2", "GPIOX_3", "GPIOX_4",
> +	"GPIOX_5", "GPIOX_6", "GPIOX_7", "GPIOX_8", "GPIOX_9",
> +	"GPIOX_10", "GPIOX_11", "GPIOX_12", "GPIOX_13", "GPIOX_14",
> +	"GPIOX_15", "GPIOX_16",
> +
> +	"GPIOF_0", "GPIOF_1", "GPIOF_2", "GPIOF_3", "GPIOF_4",
> +	"GPIOF_5", "GPIOF_6", "GPIOF_7", "GPIOF_8", "GPIOF_9",
> +	"GPIOF_10", "GPIOF_11", "GPIOF_12",
> +
> +	"GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4",
> +	"GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9",
> +	"GPIOA_10", "GPIOA_11",
> +};
> +
> +static const char * const psram_groups[] = {
> +	"psram_clkn", "psram_clkp", "psram_ce_n", "psram_rst_n", "psram_adq0",
> +	"psram_adq1", "psram_adq2", "psram_adq3", "psram_adq4", "psram_adq5",
> +	"psram_adq6", "psram_adq7", "psram_dqs_dm",
> +};
> +
> +static const char * const pwm_a_groups[] = {
> +	"pwm_a_x6", "pwm_a_x7", "pwm_a_f10", "pwm_a_f6", "pwm_a_a",
> +};
> +
> +static const char * const pwm_b_groups[] = {
> +	"pwm_b_x", "pwm_b_f", "pwm_b_a",
> +};
> +
> +static const char * const pwm_c_groups[] = {
> +	"pwm_c_x", "pwm_c_f3", "pwm_c_f8", "pwm_c_a",
> +};
> +
> +static const char * const pwm_d_groups[] = {
> +	"pwm_d_x15", "pwm_d_x13", "pwm_d_x10", "pwm_d_f",
> +};
> +
> +static const char * const pwm_e_groups[] = {
> +	"pwm_e_p", "pwm_e_x16", "pwm_e_x14", "pwm_e_x2", "pwm_e_f",
> +	"pwm_e_a",
> +};
> +
> +static const char * const pwm_f_groups[] = {
> +	"pwm_f_b", "pwm_f_x", "pwm_f_f4", "pwm_f_f12",
> +};
> +
> +static const char * const pwm_a_hiz_groups[] = {
> +	"pwm_a_hiz_f8", "pwm_a_hiz_f10", "pwm_a_hiz_f6",
> +};
> +
> +static const char * const pwm_b_hiz_groups[] = {
> +	"pwm_b_hiz",
> +};
> +
> +static const char * const pwm_c_hiz_groups[] = {
> +	"pwm_c_hiz",
> +};
> +
> +static const char * const spif_groups[] = {
> +	"spif_mo", "spif_mi", "spif_wp_n", "spif_hold_n", "spif_clk",
> +	"spif_cs",
> +};
> +
> +static const char * const sdcard_groups[] = {
> +	"sdcard_d0_b", "sdcard_d1_b", "sdcard_d2_b", "sdcard_d3_b",
> +	"sdcard_clk_b", "sdcard_cmd_b",
> +
> +	"sdcard_d0_x", "sdcard_d1_x", "sdcard_d2_x", "sdcard_d3_x",
> +	"sdcard_clk_x", "sdcard_cmd_x",
> +};
> +
> +static const char * const tdm_a_groups[] = {
> +	"tdm_a_din0", "tdm_a_din1",  "tdm_a_fs", "tdm_a_sclk",
> +	"tdm_a_slv_fs", "tdm_a_slv_sclk", "tdm_a_dout0", "tdm_a_dout1",
> +};
> +
> +static const char * const uart_a_groups[] = {
> +	"uart_a_tx", "uart_a_rx", "uart_a_cts", "uart_a_rts",
> +};
> +
> +static const char * const uart_b_groups[] = {
> +	"uart_b_tx_x", "uart_b_rx_x", "uart_b_tx_f", "uart_b_rx_f",
> +};
> +
> +static const char * const uart_c_groups[] = {
> +	"uart_c_tx_x0", "uart_c_rx_x1", "uart_c_cts", "uart_c_rts",
> +	"uart_c_tx_x15", "uart_c_rx_x16",
> +};
> +
> +static const char * const i2c0_groups[] = {
> +	"i2c0_sck_f11", "i2c0_sda_f12", "i2c0_sck_f9", "i2c0_sda_f10",
> +};
> +
> +static const char * const i2c1_groups[] = {
> +	"i2c1_sda_x", "i2c1_sck_x", "i2c1_sda_a", "i2c1_sck_a",
> +};
> +
> +static const char * const i2c2_groups[] = {
> +	"i2c2_sck_x0", "i2c2_sda_x1", "i2c2_sck_x15", "i2c2_sda_x16",
> +	"i2c2_sck_a4", "i2c2_sda_a5", "i2c2_sck_a8", "i2c2_sda_a9",
> +};
> +
> +static const char * const i2c3_groups[] = {
> +	"i2c3_sck_x", "i2c3_sda_x", "i2c3_sck_f", "i2c3_sda_f",
> +};
> +
> +static const char * const i2c_slave_groups[] = {
> +	"i2c_slave_sda_a", "i2c_slave_sck_a",
> +	"i2c_slave_sda_f", "i2c_slave_sck_f",
> +};
> +
> +static const char * const spi_a_groups[] = {
> +	"spi_a_mosi_x2", "spi_a_ss0_x3", "spi_a_sclk_x4", "spi_a_miso_x5",
> +	"spi_a_mosi_x7", "spi_a_miso_x8", "spi_a_ss0_x9", "spi_a_sclk_x10",
> +
> +	"spi_a_mosi_a", "spi_a_miso_a", "spi_a_ss0_a", "spi_a_sclk_a",
> +};
> +
> +static const char * const pdm_groups[] = {
> +	"pdm_din0_x", "pdm_din1_x", "pdm_din2_x", "pdm_dclk_x", "pdm_din2_a",
> +	"pdm_din1_a", "pdm_din0_a", "pdm_dclk",
> +};
> +
> +static const char * const gen_clk_groups[] = {
> +	"gen_clk_x", "gen_clk_f8", "gen_clk_f10", "gen_clk_a",
> +};
> +
> +static const char * const remote_input_groups[] = {
> +	"remote_input_f",
> +	"remote_input_a",
> +};
> +
> +static const char * const jtag_a_groups[] = {
> +	"jtag_a_clk", "jtag_a_tms", "jtag_a_tdi", "jtag_a_tdo",
> +};
> +
> +static const char * const clk_32k_in_groups[] = {
> +	"clk_32k_in",
> +};
> +
> +static const char * const remote_out_groups[] = {
> +	"remote_out",
> +};
> +
> +static const char * const spdif_in_groups[] = {
> +	"spdif_in_f6", "spdif_in_f7",
> +};
> +
> +static const char * const sw_groups[] = {
> +	"swclk", "swdio",
> +};
> +
> +static const char * const clk25_groups[] = {
> +	"clk_25",
> +};
> +
> +static const char * const cec_a_groups[] = {
> +	"cec_a",
> +};
> +
> +static const char * const cec_b_groups[] = {
> +	"cec_b",
> +};
> +
> +static const char * const clk12_24_groups[] = {
> +	"clk12_24",
> +};
> +
> +static const char * const mclk_0_groups[] = {
> +	"mclk_0",
> +};
> +
> +static const char * const tdm_b_groups[] = {
> +	"tdm_b_din0", "tdm_b_din1", "tdm_b_din2",
> +	"tdm_b_sclk", "tdm_b_fs", "tdm_b_dout0", "tdm_b_dout1",
> +	"tdm_b_dout2", "tdm_b_dout3", "tdm_b_dout4", "tdm_b_dout5",
> +	"tdm_b_slv_sclk", "tdm_b_slv_fs",
> +};
> +
> +static const char * const mclk_vad_groups[] = {
> +	"mclk_vad",
> +};
> +
> +static const char * const tdm_vad_groups[] = {
> +	"tdm_vad_sclk_a1", "tdm_vad_fs_a2", "tdm_vad_sclk_a5", "tdm_vad_fs_a6",
> +};
> +
> +static const char * const tst_out_groups[] = {
> +	"tst_out0", "tst_out1", "tst_out2", "tst_out3",
> +	"tst_out4", "tst_out5", "tst_out6", "tst_out7",
> +	"tst_out8", "tst_out9", "tst_out10", "tst_out11",
> +};
> +
> +static const char * const mute_groups[] = {
> +	"mute_key", "mute_en",
> +};
> +
> +static struct meson_pmx_func meson_a1_periphs_functions[] = {
> +	FUNCTION(gpio_periphs),
> +	FUNCTION(psram),
> +	FUNCTION(pwm_a),
> +	FUNCTION(pwm_b),
> +	FUNCTION(pwm_c),
> +	FUNCTION(pwm_d),
> +	FUNCTION(pwm_e),
> +	FUNCTION(pwm_f),
> +	FUNCTION(pwm_a_hiz),
> +	FUNCTION(pwm_b_hiz),
> +	FUNCTION(pwm_c_hiz),
> +	FUNCTION(spif),
> +	FUNCTION(sdcard),
> +	FUNCTION(tdm_a),
> +	FUNCTION(uart_a),
> +	FUNCTION(uart_b),
> +	FUNCTION(uart_c),
> +	FUNCTION(i2c0),
> +	FUNCTION(i2c1),
> +	FUNCTION(i2c2),
> +	FUNCTION(i2c3),
> +	FUNCTION(spi_a),
> +	FUNCTION(pdm),
> +	FUNCTION(gen_clk),
> +	FUNCTION(remote_input),
> +	FUNCTION(jtag_a),
> +	FUNCTION(clk_32k_in),
> +	FUNCTION(remote_out),
> +	FUNCTION(spdif_in),
> +	FUNCTION(sw),
> +	FUNCTION(clk25),
> +	FUNCTION(cec_a),
> +	FUNCTION(cec_b),
> +	FUNCTION(clk12_24),
> +	FUNCTION(mclk_0),
> +	FUNCTION(tdm_b),
> +	FUNCTION(mclk_vad),
> +	FUNCTION(tdm_vad),
> +	FUNCTION(tst_out),
> +	FUNCTION(mute),
> +};
> +
> +static struct meson_bank meson_a1_periphs_banks[] = {
> +	/* name  first  last  irq  pullen  pull  dir  out  in  ds*/
> +	BANK_DS("P",  GPIOP_0,  GPIOP_12,  0,  12, 0x3,  0,  0x4,  0,
> +		0x2,  0,  0x1,  0,  0x0,  0,  0x5,  0),
> +	BANK_DS("B",  GPIOB_0,    GPIOB_6,   13,  19,  0x13,  0,  0x14,  0,
> +		0x12,  0,  0x11,  0,  0x10,  0,  0x15,  0),
> +	BANK_DS("X",  GPIOX_0,    GPIOX_16,  20,  36,  0x23,  0,  0x24,  0,
> +		0x22,  0,  0x21,  0,  0x20,  0,  0x25,  0),
> +	BANK_DS("F",  GPIOF_0,    GPIOF_12,  37,  49,  0x33,  0,  0x34,  0,
> +		0x32,  0,  0x31,  0,  0x30,  0,  0x35,  0),
> +	BANK_DS("A",  GPIOA_0,    GPIOA_11,  50,  61,  0x43,  0,  0x44,  0,
> +		0x42,  0,  0x41,  0,  0x40,  0,  0x45,  0),
> +};
> +
> +static struct meson_pmx_bank meson_a1_periphs_pmx_banks[] = {
> +	/*  name	 first	    lask    reg	offset  */
> +	BANK_PMX("P",    GPIOP_0, GPIOP_12, 0x0, 0),
> +	BANK_PMX("B",    GPIOB_0, GPIOB_6,  0x2, 0),
> +	BANK_PMX("X",    GPIOX_0, GPIOX_16, 0x3, 0),
> +	BANK_PMX("F",    GPIOF_0, GPIOF_12, 0x6, 0),
> +	BANK_PMX("A",    GPIOA_0, GPIOA_11, 0x8, 0),
> +};
> +
> +static struct meson_axg_pmx_data meson_a1_periphs_pmx_banks_data = {
> +	.pmx_banks	= meson_a1_periphs_pmx_banks,
> +	.num_pmx_banks	= ARRAY_SIZE(meson_a1_periphs_pmx_banks),
> +};
> +
> +static struct meson_pinctrl_data meson_a1_periphs_pinctrl_data = {
> +	.name		= "periphs-banks",
> +	.pins		= meson_a1_periphs_pins,
> +	.groups		= meson_a1_periphs_groups,
> +	.funcs		= meson_a1_periphs_functions,
> +	.banks		= meson_a1_periphs_banks,
> +	.num_pins	= ARRAY_SIZE(meson_a1_periphs_pins),
> +	.num_groups	= ARRAY_SIZE(meson_a1_periphs_groups),
> +	.num_funcs	= ARRAY_SIZE(meson_a1_periphs_functions),
> +	.num_banks	= ARRAY_SIZE(meson_a1_periphs_banks),
> +	.pmx_ops	= &meson_axg_pmx_ops,
> +	.pmx_data	= &meson_a1_periphs_pmx_banks_data,
> +	.reg_layout	= A1_LAYOUT,
> +};
> +
> +static const struct of_device_id meson_a1_pinctrl_dt_match[] = {
> +	{
> +		.compatible = "amlogic,meson-a1-periphs-pinctrl",
> +		.data = &meson_a1_periphs_pinctrl_data,
> +	},
> +	{ },
> +};
> +
> +static struct platform_driver meson_a1_pinctrl_driver = {
> +	.probe  = meson_pinctrl_probe,
> +	.driver = {
> +		.name	= "meson-a1-pinctrl",
> +		.of_match_table = meson_a1_pinctrl_dt_match,
> +	},
> +};
> +
> +builtin_platform_driver(meson_a1_pinctrl_driver);
> diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
> index 8bba9d0..885b89d 100644
> --- a/drivers/pinctrl/meson/pinctrl-meson.c
> +++ b/drivers/pinctrl/meson/pinctrl-meson.c
> @@ -688,8 +688,12 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
>  
>  	pc->reg_ds = meson_map_resource(pc, gpio_np, "ds");
>  	if (IS_ERR(pc->reg_ds)) {
> -		dev_dbg(pc->dev, "ds registers not found - skipping\n");
> -		pc->reg_ds = NULL;
> +		if (pc->data->reg_layout == A1_LAYOUT) {

If the ds_reg is not used in A1_LAYOUT, simply avoid mapping it and mark
it unneeded for A1 SoCs in the bindings instead.

> +			pc->reg_ds = pc->reg_pullen;
> +		} else {
> +			dev_dbg(pc->dev, "ds registers not found - skipping\n");
> +			pc->reg_ds = NULL;
> +		}
>  	}
>  
>  	return 0;
> diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
> index c696f32..3d0c58d 100644
> --- a/drivers/pinctrl/meson/pinctrl-meson.h
> +++ b/drivers/pinctrl/meson/pinctrl-meson.h
> @@ -80,6 +80,14 @@ enum meson_pinconf_drv {
>  };
>  
>  /**
> + * enum meson_reg_layout - identify two types of reg layout
> + */
> +enum meson_reg_layout {
> +	LEGACY_LAYOUT,
> +	A1_LAYOUT,
> +};
> +
> +/**
>   * struct meson bank
>   *
>   * @name:	bank name
> @@ -114,6 +122,7 @@ struct meson_pinctrl_data {
>  	unsigned int num_banks;
>  	const struct pinmux_ops *pmx_ops;
>  	void *pmx_data;
> +	unsigned int reg_layout;
>  };
>  
>  struct meson_pinctrl {
> 

Apart that look good to me,

Neil

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/3] pinctrl: add compatible for Amlogic Meson A1 pin controller
  2019-09-17  6:07 ` [PATCH 1/3] pinctrl: add compatible for Amlogic Meson A1 pin controller Qianggui Song
@ 2019-09-17  7:18   ` Neil Armstrong
  2019-09-17 10:29     ` Qianggui Song
  2019-09-30 22:47   ` Rob Herring
  1 sibling, 1 reply; 15+ messages in thread
From: Neil Armstrong @ 2019-09-17  7:18 UTC (permalink / raw)
  To: Qianggui Song, Linus Walleij, linux-gpio
  Cc: Xingyu Chen, Jianxin Pan, Jerome Brunet, Kevin Hilman,
	Martin Blumenstingl, Carlo Caione, Rob Herring, Hanjie Lin,
	Mark Rutland, linux-arm-kernel, linux-amlogic, linux-kernel,
	devicetree

Hi,

On 17/09/2019 08:07, Qianggui Song wrote:
> Add new compatible name for Amlogic's Meson-A1 pin controller
> add a dt-binding header file which document the detail pin names.

Please add in the commit log that A1 doesn't need the DS bank reg,
so when we will convert these bindings to yaml we will be aware of it.

> 
> Signed-off-by: Qianggui Song <qianggui.song@amlogic.com>
> Signed-off-by: Xingyu Chen <xingyu.chen@amlogic.com>
> Signed-off-by: Jianxin Pan <jianxin.pan@amlogic.com>
> ---
>  .../devicetree/bindings/pinctrl/meson,pinctrl.txt  |  1 +
>  include/dt-bindings/gpio/meson-a1-gpio.h           | 73 ++++++++++++++++++++++
>  2 files changed, 74 insertions(+)
>  create mode 100644 include/dt-bindings/gpio/meson-a1-gpio.h
> 
> diff --git a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
> index 10dc4f7..0aff1f2 100644
> --- a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
> +++ b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
> @@ -15,6 +15,7 @@ Required properties for the root node:
>  		      "amlogic,meson-axg-aobus-pinctrl"
>  		      "amlogic,meson-g12a-periphs-pinctrl"
>  		      "amlogic,meson-g12a-aobus-pinctrl"
> +		      "amlogic,meson-a1-periphs-pinctrl"
>   - reg: address and size of registers controlling irq functionality
>  
>  === GPIO sub-nodes ===
> diff --git a/include/dt-bindings/gpio/meson-a1-gpio.h b/include/dt-bindings/gpio/meson-a1-gpio.h
> new file mode 100644
> index 0000000..40e57a5
> --- /dev/null
> +++ b/include/dt-bindings/gpio/meson-a1-gpio.h
> @@ -0,0 +1,73 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> +/*
> + * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
> + * Author: Qianggui Song <qianggui.song@amlogic.com>
> + */
> +
> +#ifndef _DT_BINDINGS_MESON_A1_GPIO_H
> +#define _DT_BINDINGS_MESON_A1_GPIO_H
> +
> +#define GPIOP_0		0
> +#define GPIOP_1		1
> +#define GPIOP_2		2
> +#define GPIOP_3		3
> +#define GPIOP_4		4
> +#define GPIOP_5		5
> +#define GPIOP_6		6
> +#define GPIOP_7		7
> +#define GPIOP_8		8
> +#define GPIOP_9		9
> +#define GPIOP_10	10
> +#define GPIOP_11	11
> +#define GPIOP_12	12
> +#define GPIOB_0		13
> +#define GPIOB_1		14
> +#define GPIOB_2		15
> +#define GPIOB_3		16
> +#define GPIOB_4		17
> +#define GPIOB_5		18
> +#define GPIOB_6		19
> +#define GPIOX_0		20
> +#define GPIOX_1		21
> +#define GPIOX_2		22
> +#define GPIOX_3		23
> +#define GPIOX_4		24
> +#define GPIOX_5		25
> +#define GPIOX_6		26
> +#define GPIOX_7		27
> +#define GPIOX_8		28
> +#define GPIOX_9		29
> +#define GPIOX_10	30
> +#define GPIOX_11	31
> +#define GPIOX_12	32
> +#define GPIOX_13	33
> +#define GPIOX_14	34
> +#define GPIOX_15	35
> +#define GPIOX_16	36
> +#define GPIOF_0		37
> +#define GPIOF_1		38
> +#define GPIOF_2		39
> +#define GPIOF_3		40
> +#define GPIOF_4		41
> +#define GPIOF_5		42
> +#define GPIOF_6		43
> +#define GPIOF_7		44
> +#define GPIOF_8		45
> +#define GPIOF_9		46
> +#define GPIOF_10	47
> +#define GPIOF_11	48
> +#define GPIOF_12	49
> +#define GPIOA_0		50
> +#define GPIOA_1		51
> +#define GPIOA_2		52
> +#define GPIOA_3		53
> +#define GPIOA_4		54
> +#define GPIOA_5		55
> +#define GPIOA_6		56
> +#define GPIOA_7		57
> +#define GPIOA_8		58
> +#define GPIOA_9		59
> +#define GPIOA_10	60
> +#define GPIOA_11	61
> +
> +#endif /* _DT_BINDINGS_MESON_A1_GPIO_H */
> 


With that fixed,

Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>

Neil

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/3] pinctrl: meson-a1: add pinctrl driver for Meson A1 Soc
  2019-09-17  6:07 ` [PATCH 2/3] pinctrl: meson-a1: add pinctrl driver for Meson A1 Soc Qianggui Song
  2019-09-17  7:15   ` Neil Armstrong
@ 2019-09-17  9:29   ` Jerome Brunet
  2019-09-17 11:51     ` Qianggui Song
  1 sibling, 1 reply; 15+ messages in thread
From: Jerome Brunet @ 2019-09-17  9:29 UTC (permalink / raw)
  To: Qianggui Song
  Cc: Linus Walleij, linux-gpio, Xingyu Chen, Jianxin Pan,
	Neil Armstrong, Jerome Brunet, Kevin Hilman, Martin Blumenstingl,
	Carlo Caione, Rob Herring, Hanjie Lin, Mark Rutland,
	linux-arm-kernel, linux-amlogic, linux-kernel


On Tue 17 Sep 2019 at 08:07, Qianggui Song <qianggui.song@amlogic.com> wrote:

> Add pinctrl driver for Meson A1 Soc which share the same register layout of
> pinmux with previous Meson-G12A, however there is difference for gpio
> and pin config register in A1. The register layout is as below:
>
> /* first bank */	      /* addr */
> - P_PADCTRL_GPIOP_I         base + 0x00 << 2
> - P_PADCTRL_GPIOP_O         base + 0x01 << 2
> - P_PADCTRL_GPIOP_OEN       base + 0x02 << 2
> - P_PADCTRL_GPIOP_PULL_EN   base + 0x03 << 2
> - P_PADCTRL_GPIOP_PULL_UP   base + 0x04 << 2
> - P_PADCTRL_GPIOP_DS        base + 0x05 << 2
>
> /* second bank */
> - P_PADCTRL_GPIOB_I         base + 0x10 << 2
> - P_PADCTRL_GPIOB_O         base + 0x11 << 2
> - P_PADCTRL_GPIOB_OEN       base + 0x12 << 2
> - P_PADCTRL_GPIOB_PULL_EN   base + 0x13 << 2
> - P_PADCTRL_GPIOB_PULL_UP   base + 0x14 << 2
> - P_PADCTRL_GPIOB_DS        base + 0x15 << 2
>
> Each bank contains at least 6 registers to be configured, if one bank has
> more than 16 gpios, an extra P_PADCTRL_GPIO[X]_DS_EXT is included. Between
> two adjacent P_PADCTRL_GPIO[X]_I, there is an offset 0x10, that is to say,
> for third bank, the offsets will be 0x20,0x21,0x22,0x23,0x24,0x25 according
> to above register layout.
>
> Current Meson pinctrl driver can cover such change by using base address of
> GPIO as that of drive-strength. While simply giving reg_ds = reg_pullen
> make wrong value to reg_ds for Soc that not support drive-strength like AXG
> . Here a private data used to identify register layout is introduced.
>
> Signed-off-by: Qianggui Song <qianggui.song@amlogic.com>
> Signed-off-by: Xingyu Chen <xingyu.chen@amlogic.com>
> Signed-off-by: Jianxin Pan <jianxin.pan@amlogic.com>
> ---
>  drivers/pinctrl/meson/Kconfig            |   6 +
>  drivers/pinctrl/meson/Makefile           |   1 +
>  drivers/pinctrl/meson/pinctrl-meson-a1.c | 942 +++++++++++++++++++++++++++++++
>  drivers/pinctrl/meson/pinctrl-meson.c    |   8 +-
>  drivers/pinctrl/meson/pinctrl-meson.h    |   9 +
>  5 files changed, 964 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/pinctrl/meson/pinctrl-meson-a1.c
>
> diff --git a/drivers/pinctrl/meson/Kconfig b/drivers/pinctrl/meson/Kconfig
> index df55f61..3cb1191 100644
> --- a/drivers/pinctrl/meson/Kconfig
> +++ b/drivers/pinctrl/meson/Kconfig
> @@ -54,4 +54,10 @@ config PINCTRL_MESON_G12A
>  	select PINCTRL_MESON_AXG_PMX
>  	default y
>  
> +config PINCTRL_MESON_A1
> +	bool "Meson a1 Soc pinctrl driver"
> +	depends on ARM64
> +	select PINCTRL_MESON_AXG_PMX
> +	default y
> +
>  endif
> diff --git a/drivers/pinctrl/meson/Makefile b/drivers/pinctrl/meson/Makefile
> index a69c565..1a5bffe 100644
> --- a/drivers/pinctrl/meson/Makefile
> +++ b/drivers/pinctrl/meson/Makefile
> @@ -8,3 +8,4 @@ obj-$(CONFIG_PINCTRL_MESON_GXL) += pinctrl-meson-gxl.o
>  obj-$(CONFIG_PINCTRL_MESON_AXG_PMX) += pinctrl-meson-axg-pmx.o
>  obj-$(CONFIG_PINCTRL_MESON_AXG) += pinctrl-meson-axg.o
>  obj-$(CONFIG_PINCTRL_MESON_G12A) += pinctrl-meson-g12a.o
> +obj-$(CONFIG_PINCTRL_MESON_A1) += pinctrl-meson-a1.o
> diff --git a/drivers/pinctrl/meson/pinctrl-meson-a1.c b/drivers/pinctrl/meson/pinctrl-meson-a1.c
> new file mode 100644
> index 0000000..f3a88f1
> --- /dev/null
> +++ b/drivers/pinctrl/meson/pinctrl-meson-a1.c
> @@ -0,0 +1,942 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Pin controller and GPIO driver for Amlogic Meson A1 SoC.
> + *
> + * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
> + * Author: Qianggui Song <qianggui.song@amlogic.com>
> + */
> +
> +#include <dt-bindings/gpio/meson-a1-gpio.h>
> +#include "pinctrl-meson.h"
> +#include "pinctrl-meson-axg-pmx.h"
> +
> +static const struct pinctrl_pin_desc meson_a1_periphs_pins[] = {
> +	MESON_PIN(GPIOP_0),
> +	MESON_PIN(GPIOP_1),
> +	MESON_PIN(GPIOP_2),
> +	MESON_PIN(GPIOP_3),
> +	MESON_PIN(GPIOP_4),
> +	MESON_PIN(GPIOP_5),
> +	MESON_PIN(GPIOP_6),
> +	MESON_PIN(GPIOP_7),
> +	MESON_PIN(GPIOP_8),
> +	MESON_PIN(GPIOP_9),
> +	MESON_PIN(GPIOP_10),
> +	MESON_PIN(GPIOP_11),
> +	MESON_PIN(GPIOP_12),
> +	MESON_PIN(GPIOB_0),
> +	MESON_PIN(GPIOB_1),
> +	MESON_PIN(GPIOB_2),
> +	MESON_PIN(GPIOB_3),
> +	MESON_PIN(GPIOB_4),
> +	MESON_PIN(GPIOB_5),
> +	MESON_PIN(GPIOB_6),
> +	MESON_PIN(GPIOX_0),
> +	MESON_PIN(GPIOX_1),
> +	MESON_PIN(GPIOX_2),
> +	MESON_PIN(GPIOX_3),
> +	MESON_PIN(GPIOX_4),
> +	MESON_PIN(GPIOX_5),
> +	MESON_PIN(GPIOX_6),
> +	MESON_PIN(GPIOX_7),
> +	MESON_PIN(GPIOX_8),
> +	MESON_PIN(GPIOX_9),
> +	MESON_PIN(GPIOX_10),
> +	MESON_PIN(GPIOX_11),
> +	MESON_PIN(GPIOX_12),
> +	MESON_PIN(GPIOX_13),
> +	MESON_PIN(GPIOX_14),
> +	MESON_PIN(GPIOX_15),
> +	MESON_PIN(GPIOX_16),
> +	MESON_PIN(GPIOF_0),
> +	MESON_PIN(GPIOF_1),
> +	MESON_PIN(GPIOF_2),
> +	MESON_PIN(GPIOF_3),
> +	MESON_PIN(GPIOF_4),
> +	MESON_PIN(GPIOF_5),
> +	MESON_PIN(GPIOF_6),
> +	MESON_PIN(GPIOF_7),
> +	MESON_PIN(GPIOF_8),
> +	MESON_PIN(GPIOF_9),
> +	MESON_PIN(GPIOF_10),
> +	MESON_PIN(GPIOF_11),
> +	MESON_PIN(GPIOF_12),
> +	MESON_PIN(GPIOA_0),
> +	MESON_PIN(GPIOA_1),
> +	MESON_PIN(GPIOA_2),
> +	MESON_PIN(GPIOA_3),
> +	MESON_PIN(GPIOA_4),
> +	MESON_PIN(GPIOA_5),
> +	MESON_PIN(GPIOA_6),
> +	MESON_PIN(GPIOA_7),
> +	MESON_PIN(GPIOA_8),
> +	MESON_PIN(GPIOA_9),
> +	MESON_PIN(GPIOA_10),
> +	MESON_PIN(GPIOA_11),
> +};
> +
> +/* psram */
> +static const unsigned int psram_clkn_pins[]		= { GPIOP_0 };
> +static const unsigned int psram_clkp_pins[]		= { GPIOP_1 };
> +static const unsigned int psram_ce_n_pins[]		= { GPIOP_2 };
> +static const unsigned int psram_rst_n_pins[]		= { GPIOP_3 };
> +static const unsigned int psram_adq0_pins[]		= { GPIOP_4 };
> +static const unsigned int psram_adq1_pins[]		= { GPIOP_5 };
> +static const unsigned int psram_adq2_pins[]		= { GPIOP_6 };
> +static const unsigned int psram_adq3_pins[]		= { GPIOP_7 };
> +static const unsigned int psram_adq4_pins[]		= { GPIOP_8 };
> +static const unsigned int psram_adq5_pins[]		= { GPIOP_9 };
> +static const unsigned int psram_adq6_pins[]		= { GPIOP_10 };
> +static const unsigned int psram_adq7_pins[]		= { GPIOP_11 };
> +static const unsigned int psram_dqs_dm_pins[]		= { GPIOP_12 };
> +
> +/* sdcard */
> +static const unsigned int sdcard_d0_b_pins[]		= { GPIOB_0 };
> +static const unsigned int sdcard_d1_b_pins[]		= { GPIOB_1 };
> +static const unsigned int sdcard_d2_b_pins[]		= { GPIOB_2 };
> +static const unsigned int sdcard_d3_b_pins[]		= { GPIOB_3 };
> +static const unsigned int sdcard_clk_b_pins[]		= { GPIOB_4 };
> +static const unsigned int sdcard_cmd_b_pins[]		= { GPIOB_5 };
> +
> +static const unsigned int sdcard_d0_x_pins[]		= { GPIOX_0 };
> +static const unsigned int sdcard_d1_x_pins[]		= { GPIOX_1 };
> +static const unsigned int sdcard_d2_x_pins[]		= { GPIOX_2 };
> +static const unsigned int sdcard_d3_x_pins[]		= { GPIOX_3 };
> +static const unsigned int sdcard_clk_x_pins[]		= { GPIOX_4 };
> +static const unsigned int sdcard_cmd_x_pins[]		= { GPIOX_5 };
> +
> +/* spif */
> +static const unsigned int spif_mo_pins[]		= { GPIOB_0 };
> +static const unsigned int spif_mi_pins[]		= { GPIOB_1 };
> +static const unsigned int spif_wp_n_pins[]		= { GPIOB_2 };
> +static const unsigned int spif_hold_n_pins[]		= { GPIOB_3 };
> +static const unsigned int spif_clk_pins[]		= { GPIOB_4 };
> +static const unsigned int spif_cs_pins[]		= { GPIOB_5 };
> +
> +/* i2c0 */
> +static const unsigned int i2c0_sck_f9_pins[]		= { GPIOF_9 };
> +static const unsigned int i2c0_sda_f10_pins[]		= { GPIOF_10 };
> +static const unsigned int i2c0_sck_f11_pins[]		= { GPIOF_11 };
> +static const unsigned int i2c0_sda_f12_pins[]		= { GPIOF_12 };
> +
> +/* i2c1 */
> +static const unsigned int i2c1_sda_x_pins[]		= { GPIOX_9 };
> +static const unsigned int i2c1_sck_x_pins[]		= { GPIOX_10 };
> +static const unsigned int i2c1_sda_a_pins[]		= { GPIOA_10 };
> +static const unsigned int i2c1_sck_a_pins[]		= { GPIOA_11 };
> +
> +/* i2c2 */
> +static const unsigned int i2c2_sck_x0_pins[]		= { GPIOX_0 };
> +static const unsigned int i2c2_sda_x1_pins[]		= { GPIOX_1 };
> +static const unsigned int i2c2_sck_x15_pins[]		= { GPIOX_15 };
> +static const unsigned int i2c2_sda_x16_pins[]		= { GPIOX_16 };
> +static const unsigned int i2c2_sck_a4_pins[]		= { GPIOA_4 };
> +static const unsigned int i2c2_sda_a5_pins[]		= { GPIOA_5 };
> +static const unsigned int i2c2_sck_a8_pins[]		= { GPIOA_8 };
> +static const unsigned int i2c2_sda_a9_pins[]		= { GPIOA_9 };
> +
> +/* i2c3 */
> +static const unsigned int i2c3_sck_f_pins[]		= { GPIOF_4 };
> +static const unsigned int i2c3_sda_f_pins[]		= { GPIOF_5 };
> +static const unsigned int i2c3_sck_x_pins[]		= { GPIOX_11 };
> +static const unsigned int i2c3_sda_x_pins[]		= { GPIOX_12 };
> +
> +/* i2c slave */
> +static const unsigned int i2c_slave_sck_a_pins[]	= { GPIOA_10 };
> +static const unsigned int i2c_slave_sda_a_pins[]	= { GPIOA_11 };
> +static const unsigned int i2c_slave_sck_f_pins[]	= { GPIOF_11 };
> +static const unsigned int i2c_slave_sda_f_pins[]	= { GPIOF_12 };
> +
> +/* uart_a */
> +static const unsigned int uart_a_tx_pins[]		= { GPIOX_11 };
> +static const unsigned int uart_a_rx_pins[]		= { GPIOX_12 };
> +static const unsigned int uart_a_cts_pins[]		= { GPIOX_13 };
> +static const unsigned int uart_a_rts_pins[]		= { GPIOX_14 };
> +
> +/* uart_b */
> +static const unsigned int uart_b_tx_x_pins[]		= { GPIOX_7 };
> +static const unsigned int uart_b_rx_x_pins[]		= { GPIOX_8 };
> +static const unsigned int uart_b_tx_f_pins[]		= { GPIOF_0 };
> +static const unsigned int uart_b_rx_f_pins[]		= { GPIOF_1 };
> +
> +/* uart_c */
> +static const unsigned int uart_c_tx_x0_pins[]		= { GPIOX_0 };
> +static const unsigned int uart_c_rx_x1_pins[]		= { GPIOX_1 };
> +static const unsigned int uart_c_cts_pins[]		= { GPIOX_2 };
> +static const unsigned int uart_c_rts_pins[]		= { GPIOX_3 };
> +static const unsigned int uart_c_tx_x15_pins[]		= { GPIOX_15 };
> +static const unsigned int uart_c_rx_x16_pins[]		= { GPIOX_16 };
> +
> +/* pmw_a */
> +static const unsigned int pwm_a_x6_pins[]		= { GPIOX_6 };
> +static const unsigned int pwm_a_x7_pins[]		= { GPIOX_7 };
> +static const unsigned int pwm_a_f6_pins[]		= { GPIOF_6 };
> +static const unsigned int pwm_a_f10_pins[]		= { GPIOF_10 };
> +static const unsigned int pwm_a_a_pins[]		= { GPIOA_5 };
> +
> +/* pmw_b */
> +static const unsigned int pwm_b_x_pins[]		= { GPIOX_8 };
> +static const unsigned int pwm_b_f_pins[]		= { GPIOF_7 };
> +static const unsigned int pwm_b_a_pins[]		= { GPIOA_11 };
> +
> +/* pmw_c */
> +static const unsigned int pwm_c_x_pins[]		= { GPIOX_9 };
> +static const unsigned int pwm_c_f3_pins[]		= { GPIOF_3 };
> +static const unsigned int pwm_c_f8_pins[]		= { GPIOF_8 };
> +static const unsigned int pwm_c_a_pins[]		= { GPIOA_10 };
> +
> +/* pwm_d */
> +static const unsigned int pwm_d_x10_pins[]		= { GPIOX_10 };
> +static const unsigned int pwm_d_x13_pins[]		= { GPIOX_13 };
> +static const unsigned int pwm_d_x15_pins[]		= { GPIOX_15 };
> +static const unsigned int pwm_d_f_pins[]		= { GPIOF_11 };
> +
> +/* pwm_e */
> +static const unsigned int pwm_e_p_pins[]		= { GPIOP_3 };
> +static const unsigned int pwm_e_x2_pins[]		= { GPIOX_2 };
> +static const unsigned int pwm_e_x14_pins[]		= { GPIOX_14 };
> +static const unsigned int pwm_e_x16_pins[]		= { GPIOX_16 };
> +static const unsigned int pwm_e_f_pins[]		= { GPIOF_3 };
> +static const unsigned int pwm_e_a_pins[]		= { GPIOA_0 };
> +
> +/* pwm_f */
> +static const unsigned int pwm_f_b_pins[]		= { GPIOB_6 };
> +static const unsigned int pwm_f_x_pins[]		= { GPIOX_3 };
> +static const unsigned int pwm_f_f4_pins[]		= { GPIOF_4 };
> +static const unsigned int pwm_f_f12_pins[]		= { GPIOF_12 };
> +
> +/* pwm_a_hiz */
> +static const unsigned int pwm_a_hiz_f8_pins[]		= { GPIOF_8 };
> +static const unsigned int pwm_a_hiz_f10_pins[]		= { GPIOF_10 };
> +static const unsigned int pmw_a_hiz_f6_pins[]		= { GPIOF_6 };
> +
> +/* pwm_b_hiz */
> +static const unsigned int pwm_b_hiz_pins[]		= { GPIOF_7 };
> +
> +/* pmw_c_hiz */
> +static const unsigned int pwm_c_hiz_pins[]		= { GPIOF_8 };
> +
> +/* tdm_a */
> +static const unsigned int tdm_a_dout1_pins[]		= { GPIOX_7 };
> +static const unsigned int tdm_a_dout0_pins[]		= { GPIOX_8 };
> +static const unsigned int tdm_a_fs_pins[]		= { GPIOX_9 };
> +static const unsigned int tdm_a_sclk_pins[]		= { GPIOX_10 };
> +static const unsigned int tdm_a_din1_pins[]		= { GPIOX_7 };
> +static const unsigned int tdm_a_din0_pins[]		= { GPIOX_8 };
> +static const unsigned int tdm_a_slv_fs_pins[]		= { GPIOX_9 };
> +static const unsigned int tdm_a_slv_sclk_pins[]		= { GPIOX_10 };
> +
> +/* spi_a */
> +static const unsigned int spi_a_mosi_x2_pins[]		= { GPIOX_2 };
> +static const unsigned int spi_a_ss0_x3_pins[]		= { GPIOX_3 };
> +static const unsigned int spi_a_sclk_x4_pins[]		= { GPIOX_4 };
> +static const unsigned int spi_a_miso_x5_pins[]		= { GPIOX_5 };
> +static const unsigned int spi_a_mosi_x7_pins[]		= { GPIOX_7 };
> +static const unsigned int spi_a_miso_x8_pins[]		= { GPIOX_8 };
> +static const unsigned int spi_a_ss0_x9_pins[]		= { GPIOX_9 };
> +static const unsigned int spi_a_sclk_x10_pins[]		= { GPIOX_10 };
> +
> +static const unsigned int spi_a_mosi_a_pins[]		= { GPIOA_6 };
> +static const unsigned int spi_a_miso_a_pins[]		= { GPIOA_7 };
> +static const unsigned int spi_a_ss0_a_pins[]		= { GPIOA_8 };
> +static const unsigned int spi_a_sclk_a_pins[]		= { GPIOA_9 };
> +
> +/* pdm */
> +static const unsigned int pdm_din0_x_pins[]		= { GPIOX_7 };
> +static const unsigned int pdm_din1_x_pins[]		= { GPIOX_8 };
> +static const unsigned int pdm_din2_x_pins[]		= { GPIOX_9 };
> +static const unsigned int pdm_dclk_x_pins[]		= { GPIOX_10 };
> +
> +static const unsigned int pdm_din2_a_pins[]		= { GPIOA_6 };
> +static const unsigned int pdm_din1_a_pins[]		= { GPIOA_7 };
> +static const unsigned int pdm_din0_a_pins[]		= { GPIOA_8 };
> +static const unsigned int pdm_dclk_pins[]		= { GPIOA_9 };
> +
> +/* gen_clk */
> +static const unsigned int gen_clk_x_pins[]		= { GPIOX_7 };
> +static const unsigned int gen_clk_f8_pins[]		= { GPIOF_8 };
> +static const unsigned int gen_clk_f10_pins[]		= { GPIOF_10 };
> +static const unsigned int gen_clk_a_pins[]		= { GPIOA_11 };
> +
> +/* jtag_a */
> +static const unsigned int jtag_a_clk_pins[]		= { GPIOF_4 };
> +static const unsigned int jtag_a_tms_pins[]		= { GPIOF_5 };
> +static const unsigned int jtag_a_tdi_pins[]		= { GPIOF_6 };
> +static const unsigned int jtag_a_tdo_pins[]		= { GPIOF_7 };
> +
> +/* clk_32_in */
> +static const unsigned int clk_32k_in_pins[]		= { GPIOF_2 };
> +
> +/* ir in */
> +static const unsigned int remote_input_f_pins[]		= { GPIOF_3 };
> +static const unsigned int remote_input_a_pins[]		= { GPIOA_11 };
> +
> +/* ir out */
> +static const unsigned int remote_out_pins[]		= { GPIOF_5 };
> +
> +/* spdif */
> +static const unsigned int spdif_in_f6_pins[]		= { GPIOF_6 };
> +static const unsigned int spdif_in_f7_pins[]		= { GPIOF_7 };
> +
> +/* sw */
> +static const unsigned int swclk_pins[]			= { GPIOF_4 };
> +static const unsigned int swdio_pins[]			= { GPIOF_5 };
> +
> +/* clk_25 */
> +static const unsigned int clk25_pins[]			= { GPIOF_10 };
> +
> +/* cec_a */
> +static const unsigned int cec_a_pins[]			= { GPIOF_2 };
> +
> +/* cec_b */
> +static const unsigned int cec_b_pins[]			= { GPIOF_2 };
> +
> +/* clk12_24 */
> +static const unsigned int clk12_24_pins[]		= { GPIOF_10 };
> +
> +/* mclk_0 */
> +static const unsigned int mclk_0_pins[]			= { GPIOA_0 };
> +
> +/* tdm_b */
> +static const unsigned int tdm_b_sclk_pins[]		= { GPIOA_1 };
> +static const unsigned int tdm_b_fs_pins[]		= { GPIOA_2 };
> +static const unsigned int tdm_b_dout0_pins[]		= { GPIOA_3 };
> +static const unsigned int tdm_b_dout1_pins[]		= { GPIOA_4 };
> +static const unsigned int tdm_b_dout2_pins[]		= { GPIOA_5 };
> +static const unsigned int tdm_b_dout3_pins[]		= { GPIOA_6 };
> +static const unsigned int tdm_b_dout4_pins[]		= { GPIOA_7 };
> +static const unsigned int tdm_b_dout5_pins[]		= { GPIOA_8 };
> +static const unsigned int tdm_b_slv_sclk_pins[]		= { GPIOA_5 };
> +static const unsigned int tdm_b_slv_fs_pins[]		= { GPIOA_6 };
> +static const unsigned int tdm_b_din0_pins[]		= { GPIOA_7 };
> +static const unsigned int tdm_b_din1_pins[]		= { GPIOA_8 };
> +static const unsigned int tdm_b_din2_pins[]		= { GPIOA_9 };
> +
> +/* mclk_vad */
> +static const unsigned int mclk_vad_pins[]		= { GPIOA_0 };
> +
> +/* tdm_vad */
> +static const unsigned int tdm_vad_sclk_a1_pins[]	= { GPIOA_1 };
> +static const unsigned int tdm_vad_fs_a2_pins[]		= { GPIOA_2 };
> +static const unsigned int tdm_vad_sclk_a5_pins[]	= { GPIOA_5 };
> +static const unsigned int tdm_vad_fs_a6_pins[]		= { GPIOA_6 };
> +
> +/* tst_out */
> +static const unsigned int tst_out0_pins[]		= { GPIOA_0 };
> +static const unsigned int tst_out1_pins[]		= { GPIOA_1 };
> +static const unsigned int tst_out2_pins[]		= { GPIOA_2 };
> +static const unsigned int tst_out3_pins[]		= { GPIOA_3 };
> +static const unsigned int tst_out4_pins[]		= { GPIOA_4 };
> +static const unsigned int tst_out5_pins[]		= { GPIOA_5 };
> +static const unsigned int tst_out6_pins[]		= { GPIOA_6 };
> +static const unsigned int tst_out7_pins[]		= { GPIOA_7 };
> +static const unsigned int tst_out8_pins[]		= { GPIOA_8 };
> +static const unsigned int tst_out9_pins[]		= { GPIOA_9 };
> +static const unsigned int tst_out10_pins[]		= { GPIOA_10 };
> +static const unsigned int tst_out11_pins[]		= { GPIOA_11 };
> +
> +/* mute */
> +static const unsigned int mute_key_pins[]		= { GPIOA_4 };
> +static const unsigned int mute_en_pins[]		= { GPIOA_5 };
> +
> +static struct meson_pmx_group meson_a1_periphs_groups[] = {
> +	GPIO_GROUP(GPIOP_0),
> +	GPIO_GROUP(GPIOP_1),
> +	GPIO_GROUP(GPIOP_2),
> +	GPIO_GROUP(GPIOP_3),
> +	GPIO_GROUP(GPIOP_4),
> +	GPIO_GROUP(GPIOP_5),
> +	GPIO_GROUP(GPIOP_6),
> +	GPIO_GROUP(GPIOP_7),
> +	GPIO_GROUP(GPIOP_8),
> +	GPIO_GROUP(GPIOP_9),
> +	GPIO_GROUP(GPIOP_10),
> +	GPIO_GROUP(GPIOP_11),
> +	GPIO_GROUP(GPIOP_12),
> +	GPIO_GROUP(GPIOB_0),
> +	GPIO_GROUP(GPIOB_1),
> +	GPIO_GROUP(GPIOB_2),
> +	GPIO_GROUP(GPIOB_3),
> +	GPIO_GROUP(GPIOB_4),
> +	GPIO_GROUP(GPIOB_5),
> +	GPIO_GROUP(GPIOB_6),
> +	GPIO_GROUP(GPIOX_0),
> +	GPIO_GROUP(GPIOX_1),
> +	GPIO_GROUP(GPIOX_2),
> +	GPIO_GROUP(GPIOX_3),
> +	GPIO_GROUP(GPIOX_4),
> +	GPIO_GROUP(GPIOX_5),
> +	GPIO_GROUP(GPIOX_6),
> +	GPIO_GROUP(GPIOX_7),
> +	GPIO_GROUP(GPIOX_8),
> +	GPIO_GROUP(GPIOX_9),
> +	GPIO_GROUP(GPIOX_10),
> +	GPIO_GROUP(GPIOX_11),
> +	GPIO_GROUP(GPIOX_12),
> +	GPIO_GROUP(GPIOX_13),
> +	GPIO_GROUP(GPIOX_14),
> +	GPIO_GROUP(GPIOX_15),
> +	GPIO_GROUP(GPIOX_16),
> +	GPIO_GROUP(GPIOF_0),
> +	GPIO_GROUP(GPIOF_1),
> +	GPIO_GROUP(GPIOF_2),
> +	GPIO_GROUP(GPIOF_3),
> +	GPIO_GROUP(GPIOF_4),
> +	GPIO_GROUP(GPIOF_5),
> +	GPIO_GROUP(GPIOF_6),
> +	GPIO_GROUP(GPIOF_7),
> +	GPIO_GROUP(GPIOF_8),
> +	GPIO_GROUP(GPIOF_9),
> +	GPIO_GROUP(GPIOF_10),
> +	GPIO_GROUP(GPIOF_11),
> +	GPIO_GROUP(GPIOF_12),
> +	GPIO_GROUP(GPIOA_0),
> +	GPIO_GROUP(GPIOA_1),
> +	GPIO_GROUP(GPIOA_2),
> +	GPIO_GROUP(GPIOA_3),
> +	GPIO_GROUP(GPIOA_4),
> +	GPIO_GROUP(GPIOA_5),
> +	GPIO_GROUP(GPIOA_6),
> +	GPIO_GROUP(GPIOA_7),
> +	GPIO_GROUP(GPIOA_8),
> +	GPIO_GROUP(GPIOA_9),
> +	GPIO_GROUP(GPIOA_10),
> +	GPIO_GROUP(GPIOA_11),
> +
> +	/* bank P func1 */
> +	GROUP(psram_clkn,		1),
> +	GROUP(psram_clkp,		1),
> +	GROUP(psram_ce_n,		1),
> +	GROUP(psram_rst_n,		1),
> +	GROUP(psram_adq0,		1),
> +	GROUP(psram_adq1,		1),
> +	GROUP(psram_adq2,		1),
> +	GROUP(psram_adq3,		1),
> +	GROUP(psram_adq4,		1),
> +	GROUP(psram_adq5,		1),
> +	GROUP(psram_adq6,		1),
> +	GROUP(psram_adq7,		1),
> +	GROUP(psram_dqs_dm,		1),
> +
> +	/*bank P func2 */
> +	GROUP(pwm_e_p,			2),
> +
> +	/*bank B func1 */
> +	GROUP(spif_mo,			1),
> +	GROUP(spif_mi,			1),
> +	GROUP(spif_wp_n,		1),
> +	GROUP(spif_hold_n,		1),
> +	GROUP(spif_clk,			1),
> +	GROUP(spif_cs,			1),
> +	GROUP(pwm_f_b,			1),
> +
> +	/*bank B func2 */
> +	GROUP(sdcard_d0_b,		2),
> +	GROUP(sdcard_d1_b,		2),
> +	GROUP(sdcard_d2_b,		2),
> +	GROUP(sdcard_d3_b,		2),
> +	GROUP(sdcard_clk_b,		2),
> +	GROUP(sdcard_cmd_b,		2),
> +
> +	/*bank X func1 */
> +	GROUP(sdcard_d0_x,		1),
> +	GROUP(sdcard_d1_x,		1),
> +	GROUP(sdcard_d2_x,		1),
> +	GROUP(sdcard_d3_x,		1),
> +	GROUP(sdcard_clk_x,		1),
> +	GROUP(sdcard_cmd_x,		1),
> +	GROUP(pwm_a_x6,			1),
> +	GROUP(tdm_a_dout1,		1),
> +	GROUP(tdm_a_dout0,		1),
> +	GROUP(tdm_a_fs,			1),
> +	GROUP(tdm_a_sclk,		1),
> +	GROUP(uart_a_tx,		1),
> +	GROUP(uart_a_rx,		1),
> +	GROUP(uart_a_cts,		1),
> +	GROUP(uart_a_rts,		1),
> +	GROUP(pwm_d_x15,		1),
> +	GROUP(pwm_e_x16,		1),
> +
> +	/*bank X func2 */
> +	GROUP(i2c2_sck_x0,		2),
> +	GROUP(i2c2_sda_x1,		2),
> +	GROUP(spi_a_mosi_x2,		2),
> +	GROUP(spi_a_ss0_x3,		2),
> +	GROUP(spi_a_sclk_x4,		2),
> +	GROUP(spi_a_miso_x5,		2),
> +	GROUP(tdm_a_din1,		2),
> +	GROUP(tdm_a_din0,		2),
> +	GROUP(tdm_a_slv_fs,		2),
> +	GROUP(tdm_a_slv_sclk,		2),
> +	GROUP(i2c3_sck_x,		2),
> +	GROUP(i2c3_sda_x,		2),
> +	GROUP(pwm_d_x13,		2),
> +	GROUP(pwm_e_x14,		2),
> +	GROUP(i2c2_sck_x15,		2),
> +	GROUP(i2c2_sda_x16,		2),
> +
> +	/*bank X func3 */
> +	GROUP(uart_c_tx_x0,		3),
> +	GROUP(uart_c_rx_x1,		3),
> +	GROUP(uart_c_cts,		3),
> +	GROUP(uart_c_rts,		3),
> +	GROUP(pdm_din0_x,		3),
> +	GROUP(pdm_din1_x,		3),
> +	GROUP(pdm_din2_x,		3),
> +	GROUP(pdm_dclk_x,		3),
> +	GROUP(uart_c_tx_x15,		3),
> +	GROUP(uart_c_rx_x16,		3),
> +
> +	/*bank X func4 */
> +	GROUP(pwm_e_x2,			4),
> +	GROUP(pwm_f_x,			4),
> +	GROUP(spi_a_mosi_x7,		4),
> +	GROUP(spi_a_miso_x8,		4),
> +	GROUP(spi_a_ss0_x9,		4),
> +	GROUP(spi_a_sclk_x10,		4),
> +
> +	/*bank X func5 */
> +	GROUP(uart_b_tx_x,		5),
> +	GROUP(uart_b_rx_x,		5),
> +	GROUP(i2c1_sda_x,		5),
> +	GROUP(i2c1_sck_x,		5),
> +
> +	/*bank X func6 */
> +	GROUP(pwm_a_x7,			6),
> +	GROUP(pwm_b_x,			6),
> +	GROUP(pwm_c_x,			6),
> +	GROUP(pwm_d_x10,		6),
> +
> +	/*bank X func7 */
> +	GROUP(gen_clk_x,		7),
> +
> +	/*bank F func1 */
> +	GROUP(uart_b_tx_f,		1),
> +	GROUP(uart_b_rx_f,		1),
> +	GROUP(remote_input_f,		1),
> +	GROUP(jtag_a_clk,		1),
> +	GROUP(jtag_a_tms,		1),
> +	GROUP(jtag_a_tdi,		1),
> +	GROUP(jtag_a_tdo,		1),
> +	GROUP(gen_clk_f8,		1),
> +	GROUP(pwm_a_f10,		1),
> +	GROUP(i2c0_sck_f11,		1),
> +	GROUP(i2c0_sda_f12,		1),
> +
> +	/*bank F func2 */
> +	GROUP(clk_32k_in,		2),
> +	GROUP(pwm_e_f,			2),
> +	GROUP(pwm_f_f4,			2),
> +	GROUP(remote_out,		2),
> +	GROUP(spdif_in_f6,		2),
> +	GROUP(spdif_in_f7,		2),
> +	GROUP(pwm_a_hiz_f8,		2),
> +	GROUP(pwm_a_hiz_f10,		2),
> +	GROUP(pwm_d_f,			2),
> +	GROUP(pwm_f_f12,		2),
> +
> +	/*bank F func3 */
> +	GROUP(pwm_c_f3,			3),
> +	GROUP(swclk,			3),
> +	GROUP(swdio,			3),
> +	GROUP(pwm_a_f6,			3),
> +	GROUP(pwm_b_f,			3),
> +	GROUP(pwm_c_f8,			3),
> +	GROUP(clk25,			3),
> +	GROUP(i2c_slave_sck_f,		3),
> +	GROUP(i2c_slave_sda_f,		3),
> +
> +	/*bank F func4 */
> +	GROUP(cec_a,			4),
> +	GROUP(i2c3_sck_f,		4),
> +	GROUP(i2c3_sda_f,		4),
> +	GROUP(pmw_a_hiz_f6,		4),
> +	GROUP(pwm_b_hiz,		4),
> +	GROUP(pwm_c_hiz,		4),
> +	GROUP(i2c0_sck_f9,		4),
> +	GROUP(i2c0_sda_f10,		4),
> +
> +	/*bank F func5 */
> +	GROUP(cec_b,			5),
> +	GROUP(clk12_24,			5),
> +
> +	/*bank F func7 */
> +	GROUP(gen_clk_f10,		7),
> +
> +	/*bank A func1 */
> +	GROUP(mclk_0,			1),
> +	GROUP(tdm_b_sclk,		1),
> +	GROUP(tdm_b_fs,			1),
> +	GROUP(tdm_b_dout0,		1),
> +	GROUP(tdm_b_dout1,		1),
> +	GROUP(tdm_b_dout2,		1),
> +	GROUP(tdm_b_dout3,		1),
> +	GROUP(tdm_b_dout4,		1),
> +	GROUP(tdm_b_dout5,		1),
> +	GROUP(remote_input_a,		1),
> +
> +	/*bank A func2 */
> +	GROUP(pwm_e_a,			2),
> +	GROUP(tdm_b_slv_sclk,		2),
> +	GROUP(tdm_b_slv_fs,		2),
> +	GROUP(tdm_b_din0,		2),
> +	GROUP(tdm_b_din1,		2),
> +	GROUP(tdm_b_din2,		2),
> +	GROUP(i2c1_sda_a,		2),
> +	GROUP(i2c1_sck_a,		2),
> +
> +	/*bank A func3 */
> +	GROUP(i2c2_sck_a4,		3),
> +	GROUP(i2c2_sda_a5,		3),
> +	GROUP(pdm_din2_a,		3),
> +	GROUP(pdm_din1_a,		3),
> +	GROUP(pdm_din0_a,		3),
> +	GROUP(pdm_dclk,			3),
> +	GROUP(pwm_c_a,			3),
> +	GROUP(pwm_b_a,			3),
> +
> +	/*bank A func4 */
> +	GROUP(pwm_a_a,			4),
> +	GROUP(spi_a_mosi_a,		4),
> +	GROUP(spi_a_miso_a,		4),
> +	GROUP(spi_a_ss0_a,		4),
> +	GROUP(spi_a_sclk_a,		4),
> +	GROUP(i2c_slave_sck_a,		4),
> +	GROUP(i2c_slave_sda_a,		4),
> +
> +	/*bank A func5 */
> +	GROUP(mclk_vad,			5),
> +	GROUP(tdm_vad_sclk_a1,		5),
> +	GROUP(tdm_vad_fs_a2,		5),
> +	GROUP(tdm_vad_sclk_a5,		5),
> +	GROUP(tdm_vad_fs_a6,		5),
> +	GROUP(i2c2_sck_a8,		5),
> +	GROUP(i2c2_sda_a9,		5),
> +
> +	/*bank A func6 */
> +	GROUP(tst_out0,			6),
> +	GROUP(tst_out1,			6),
> +	GROUP(tst_out2,			6),
> +	GROUP(tst_out3,			6),
> +	GROUP(tst_out4,			6),
> +	GROUP(tst_out5,			6),
> +	GROUP(tst_out6,			6),
> +	GROUP(tst_out7,			6),
> +	GROUP(tst_out8,			6),
> +	GROUP(tst_out9,			6),
> +	GROUP(tst_out10,		6),
> +	GROUP(tst_out11,		6),
> +
> +	/*bank A func7 */
> +	GROUP(mute_key,			7),
> +	GROUP(mute_en,			7),
> +	GROUP(gen_clk_a,		7),
> +};
> +
> +static const char * const gpio_periphs_groups[] = {
> +	"GPIOP_0", "GPIOP_1", "GPIOP_2", "GPIOP_3", "GPIOP_4",
> +	"GPIOP_5", "GPIOP_6", "GPIOP_7", "GPIOP_8", "GPIOP_9",
> +	"GPIOP_10", "GPIOP_11", "GPIOP_12",
> +
> +	"GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4",
> +	"GPIOB_5", "GPIOB_6",
> +
> +	"GPIOX_0", "GPIOX_1", "GPIOX_2", "GPIOX_3", "GPIOX_4",
> +	"GPIOX_5", "GPIOX_6", "GPIOX_7", "GPIOX_8", "GPIOX_9",
> +	"GPIOX_10", "GPIOX_11", "GPIOX_12", "GPIOX_13", "GPIOX_14",
> +	"GPIOX_15", "GPIOX_16",
> +
> +	"GPIOF_0", "GPIOF_1", "GPIOF_2", "GPIOF_3", "GPIOF_4",
> +	"GPIOF_5", "GPIOF_6", "GPIOF_7", "GPIOF_8", "GPIOF_9",
> +	"GPIOF_10", "GPIOF_11", "GPIOF_12",
> +
> +	"GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4",
> +	"GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9",
> +	"GPIOA_10", "GPIOA_11",
> +};
> +
> +static const char * const psram_groups[] = {
> +	"psram_clkn", "psram_clkp", "psram_ce_n", "psram_rst_n", "psram_adq0",
> +	"psram_adq1", "psram_adq2", "psram_adq3", "psram_adq4", "psram_adq5",
> +	"psram_adq6", "psram_adq7", "psram_dqs_dm",
> +};
> +
> +static const char * const pwm_a_groups[] = {
> +	"pwm_a_x6", "pwm_a_x7", "pwm_a_f10", "pwm_a_f6", "pwm_a_a",
> +};
> +
> +static const char * const pwm_b_groups[] = {
> +	"pwm_b_x", "pwm_b_f", "pwm_b_a",
> +};
> +
> +static const char * const pwm_c_groups[] = {
> +	"pwm_c_x", "pwm_c_f3", "pwm_c_f8", "pwm_c_a",
> +};
> +
> +static const char * const pwm_d_groups[] = {
> +	"pwm_d_x15", "pwm_d_x13", "pwm_d_x10", "pwm_d_f",
> +};
> +
> +static const char * const pwm_e_groups[] = {
> +	"pwm_e_p", "pwm_e_x16", "pwm_e_x14", "pwm_e_x2", "pwm_e_f",
> +	"pwm_e_a",
> +};
> +
> +static const char * const pwm_f_groups[] = {
> +	"pwm_f_b", "pwm_f_x", "pwm_f_f4", "pwm_f_f12",
> +};
> +
> +static const char * const pwm_a_hiz_groups[] = {
> +	"pwm_a_hiz_f8", "pwm_a_hiz_f10", "pwm_a_hiz_f6",
> +};
> +
> +static const char * const pwm_b_hiz_groups[] = {
> +	"pwm_b_hiz",
> +};
> +
> +static const char * const pwm_c_hiz_groups[] = {
> +	"pwm_c_hiz",
> +};
> +
> +static const char * const spif_groups[] = {
> +	"spif_mo", "spif_mi", "spif_wp_n", "spif_hold_n", "spif_clk",
> +	"spif_cs",
> +};
> +
> +static const char * const sdcard_groups[] = {
> +	"sdcard_d0_b", "sdcard_d1_b", "sdcard_d2_b", "sdcard_d3_b",
> +	"sdcard_clk_b", "sdcard_cmd_b",
> +
> +	"sdcard_d0_x", "sdcard_d1_x", "sdcard_d2_x", "sdcard_d3_x",
> +	"sdcard_clk_x", "sdcard_cmd_x",
> +};
> +
> +static const char * const tdm_a_groups[] = {
> +	"tdm_a_din0", "tdm_a_din1",  "tdm_a_fs", "tdm_a_sclk",
> +	"tdm_a_slv_fs", "tdm_a_slv_sclk", "tdm_a_dout0", "tdm_a_dout1",
> +};
> +
> +static const char * const uart_a_groups[] = {
> +	"uart_a_tx", "uart_a_rx", "uart_a_cts", "uart_a_rts",
> +};
> +
> +static const char * const uart_b_groups[] = {
> +	"uart_b_tx_x", "uart_b_rx_x", "uart_b_tx_f", "uart_b_rx_f",
> +};
> +
> +static const char * const uart_c_groups[] = {
> +	"uart_c_tx_x0", "uart_c_rx_x1", "uart_c_cts", "uart_c_rts",
> +	"uart_c_tx_x15", "uart_c_rx_x16",
> +};
> +
> +static const char * const i2c0_groups[] = {
> +	"i2c0_sck_f11", "i2c0_sda_f12", "i2c0_sck_f9", "i2c0_sda_f10",
> +};
> +
> +static const char * const i2c1_groups[] = {
> +	"i2c1_sda_x", "i2c1_sck_x", "i2c1_sda_a", "i2c1_sck_a",
> +};
> +
> +static const char * const i2c2_groups[] = {
> +	"i2c2_sck_x0", "i2c2_sda_x1", "i2c2_sck_x15", "i2c2_sda_x16",
> +	"i2c2_sck_a4", "i2c2_sda_a5", "i2c2_sck_a8", "i2c2_sda_a9",
> +};
> +
> +static const char * const i2c3_groups[] = {
> +	"i2c3_sck_x", "i2c3_sda_x", "i2c3_sck_f", "i2c3_sda_f",
> +};
> +
> +static const char * const i2c_slave_groups[] = {
> +	"i2c_slave_sda_a", "i2c_slave_sck_a",
> +	"i2c_slave_sda_f", "i2c_slave_sck_f",
> +};
> +
> +static const char * const spi_a_groups[] = {
> +	"spi_a_mosi_x2", "spi_a_ss0_x3", "spi_a_sclk_x4", "spi_a_miso_x5",
> +	"spi_a_mosi_x7", "spi_a_miso_x8", "spi_a_ss0_x9", "spi_a_sclk_x10",
> +
> +	"spi_a_mosi_a", "spi_a_miso_a", "spi_a_ss0_a", "spi_a_sclk_a",
> +};
> +
> +static const char * const pdm_groups[] = {
> +	"pdm_din0_x", "pdm_din1_x", "pdm_din2_x", "pdm_dclk_x", "pdm_din2_a",
> +	"pdm_din1_a", "pdm_din0_a", "pdm_dclk",
> +};
> +
> +static const char * const gen_clk_groups[] = {
> +	"gen_clk_x", "gen_clk_f8", "gen_clk_f10", "gen_clk_a",
> +};
> +
> +static const char * const remote_input_groups[] = {
> +	"remote_input_f",
> +	"remote_input_a",
> +};
> +
> +static const char * const jtag_a_groups[] = {
> +	"jtag_a_clk", "jtag_a_tms", "jtag_a_tdi", "jtag_a_tdo",
> +};
> +
> +static const char * const clk_32k_in_groups[] = {
> +	"clk_32k_in",
> +};
> +
> +static const char * const remote_out_groups[] = {
> +	"remote_out",
> +};
> +
> +static const char * const spdif_in_groups[] = {
> +	"spdif_in_f6", "spdif_in_f7",
> +};
> +
> +static const char * const sw_groups[] = {
> +	"swclk", "swdio",
> +};
> +
> +static const char * const clk25_groups[] = {
> +	"clk_25",
> +};
> +
> +static const char * const cec_a_groups[] = {
> +	"cec_a",
> +};
> +
> +static const char * const cec_b_groups[] = {
> +	"cec_b",
> +};
> +
> +static const char * const clk12_24_groups[] = {
> +	"clk12_24",
> +};
> +
> +static const char * const mclk_0_groups[] = {
> +	"mclk_0",
> +};
> +
> +static const char * const tdm_b_groups[] = {
> +	"tdm_b_din0", "tdm_b_din1", "tdm_b_din2",
> +	"tdm_b_sclk", "tdm_b_fs", "tdm_b_dout0", "tdm_b_dout1",
> +	"tdm_b_dout2", "tdm_b_dout3", "tdm_b_dout4", "tdm_b_dout5",
> +	"tdm_b_slv_sclk", "tdm_b_slv_fs",
> +};
> +
> +static const char * const mclk_vad_groups[] = {
> +	"mclk_vad",
> +};
> +
> +static const char * const tdm_vad_groups[] = {
> +	"tdm_vad_sclk_a1", "tdm_vad_fs_a2", "tdm_vad_sclk_a5", "tdm_vad_fs_a6",
> +};
> +
> +static const char * const tst_out_groups[] = {
> +	"tst_out0", "tst_out1", "tst_out2", "tst_out3",
> +	"tst_out4", "tst_out5", "tst_out6", "tst_out7",
> +	"tst_out8", "tst_out9", "tst_out10", "tst_out11",
> +};
> +
> +static const char * const mute_groups[] = {
> +	"mute_key", "mute_en",
> +};
> +
> +static struct meson_pmx_func meson_a1_periphs_functions[] = {
> +	FUNCTION(gpio_periphs),
> +	FUNCTION(psram),
> +	FUNCTION(pwm_a),
> +	FUNCTION(pwm_b),
> +	FUNCTION(pwm_c),
> +	FUNCTION(pwm_d),
> +	FUNCTION(pwm_e),
> +	FUNCTION(pwm_f),
> +	FUNCTION(pwm_a_hiz),
> +	FUNCTION(pwm_b_hiz),
> +	FUNCTION(pwm_c_hiz),
> +	FUNCTION(spif),
> +	FUNCTION(sdcard),
> +	FUNCTION(tdm_a),
> +	FUNCTION(uart_a),
> +	FUNCTION(uart_b),
> +	FUNCTION(uart_c),
> +	FUNCTION(i2c0),
> +	FUNCTION(i2c1),
> +	FUNCTION(i2c2),
> +	FUNCTION(i2c3),
> +	FUNCTION(spi_a),
> +	FUNCTION(pdm),
> +	FUNCTION(gen_clk),
> +	FUNCTION(remote_input),
> +	FUNCTION(jtag_a),
> +	FUNCTION(clk_32k_in),
> +	FUNCTION(remote_out),
> +	FUNCTION(spdif_in),
> +	FUNCTION(sw),
> +	FUNCTION(clk25),
> +	FUNCTION(cec_a),
> +	FUNCTION(cec_b),
> +	FUNCTION(clk12_24),
> +	FUNCTION(mclk_0),
> +	FUNCTION(tdm_b),
> +	FUNCTION(mclk_vad),
> +	FUNCTION(tdm_vad),
> +	FUNCTION(tst_out),
> +	FUNCTION(mute),
> +};
> +
> +static struct meson_bank meson_a1_periphs_banks[] = {
> +	/* name  first  last  irq  pullen  pull  dir  out  in  ds*/
> +	BANK_DS("P",  GPIOP_0,  GPIOP_12,  0,  12, 0x3,  0,  0x4,  0,
> +		0x2,  0,  0x1,  0,  0x0,  0,  0x5,  0),
> +	BANK_DS("B",  GPIOB_0,    GPIOB_6,   13,  19,  0x13,  0,  0x14,  0,
> +		0x12,  0,  0x11,  0,  0x10,  0,  0x15,  0),
> +	BANK_DS("X",  GPIOX_0,    GPIOX_16,  20,  36,  0x23,  0,  0x24,  0,
> +		0x22,  0,  0x21,  0,  0x20,  0,  0x25,  0),
> +	BANK_DS("F",  GPIOF_0,    GPIOF_12,  37,  49,  0x33,  0,  0x34,  0,
> +		0x32,  0,  0x31,  0,  0x30,  0,  0x35,  0),
> +	BANK_DS("A",  GPIOA_0,    GPIOA_11,  50,  61,  0x43,  0,  0x44,  0,
> +		0x42,  0,  0x41,  0,  0x40,  0,  0x45,  0),
> +};
> +
> +static struct meson_pmx_bank meson_a1_periphs_pmx_banks[] = {
> +	/*  name	 first	    lask    reg	offset  */
> +	BANK_PMX("P",    GPIOP_0, GPIOP_12, 0x0, 0),
> +	BANK_PMX("B",    GPIOB_0, GPIOB_6,  0x2, 0),
> +	BANK_PMX("X",    GPIOX_0, GPIOX_16, 0x3, 0),
> +	BANK_PMX("F",    GPIOF_0, GPIOF_12, 0x6, 0),
> +	BANK_PMX("A",    GPIOA_0, GPIOA_11, 0x8, 0),
> +};
> +
> +static struct meson_axg_pmx_data meson_a1_periphs_pmx_banks_data = {
> +	.pmx_banks	= meson_a1_periphs_pmx_banks,
> +	.num_pmx_banks	= ARRAY_SIZE(meson_a1_periphs_pmx_banks),
> +};
> +
> +static struct meson_pinctrl_data meson_a1_periphs_pinctrl_data = {
> +	.name		= "periphs-banks",
> +	.pins		= meson_a1_periphs_pins,
> +	.groups		= meson_a1_periphs_groups,
> +	.funcs		= meson_a1_periphs_functions,
> +	.banks		= meson_a1_periphs_banks,
> +	.num_pins	= ARRAY_SIZE(meson_a1_periphs_pins),
> +	.num_groups	= ARRAY_SIZE(meson_a1_periphs_groups),
> +	.num_funcs	= ARRAY_SIZE(meson_a1_periphs_functions),
> +	.num_banks	= ARRAY_SIZE(meson_a1_periphs_banks),
> +	.pmx_ops	= &meson_axg_pmx_ops,
> +	.pmx_data	= &meson_a1_periphs_pmx_banks_data,
> +	.reg_layout	= A1_LAYOUT,
> +};
> +
> +static const struct of_device_id meson_a1_pinctrl_dt_match[] = {
> +	{
> +		.compatible = "amlogic,meson-a1-periphs-pinctrl",
> +		.data = &meson_a1_periphs_pinctrl_data,
> +	},
> +	{ },
> +};
> +
> +static struct platform_driver meson_a1_pinctrl_driver = {
> +	.probe  = meson_pinctrl_probe,
> +	.driver = {
> +		.name	= "meson-a1-pinctrl",
> +		.of_match_table = meson_a1_pinctrl_dt_match,
> +	},
> +};
> +
> +builtin_platform_driver(meson_a1_pinctrl_driver);
> diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
> index 8bba9d0..885b89d 100644
> --- a/drivers/pinctrl/meson/pinctrl-meson.c
> +++ b/drivers/pinctrl/meson/pinctrl-meson.c
> @@ -688,8 +688,12 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
>  
>  	pc->reg_ds = meson_map_resource(pc, gpio_np, "ds");
>  	if (IS_ERR(pc->reg_ds)) {
> -		dev_dbg(pc->dev, "ds registers not found - skipping\n");
> -		pc->reg_ds = NULL;
> +		if (pc->data->reg_layout == A1_LAYOUT) {
> +			pc->reg_ds = pc->reg_pullen;

IMO, this kind of ID based init fixup is not going to scale and will
lead to something difficult to maintain in the end.

The way the different register sets interract with each other is already
pretty complex to follow.

You could rework this in 2 different ways:
#1 - Have the generic function parse all the register sets and have all
drivers provide a specific (as in gxbb, gxl, axg, etc ...)  function to :
 - Verify the expected sets have been provided
 - Make assignement fixup as above if necessary

#2 - Rework the driver to have only one single register region
 I think one of your colleague previously mentionned this was not
 possible. It is still unclear to me why ...

> +		} else {
> +			dev_dbg(pc->dev, "ds registers not found - skipping\n");
> +			pc->reg_ds = NULL;
> +		}
>  	}
>  
>  	return 0;
> diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
> index c696f32..3d0c58d 100644
> --- a/drivers/pinctrl/meson/pinctrl-meson.h
> +++ b/drivers/pinctrl/meson/pinctrl-meson.h
> @@ -80,6 +80,14 @@ enum meson_pinconf_drv {
>  };
>  
>  /**
> + * enum meson_reg_layout - identify two types of reg layout
> + */
> +enum meson_reg_layout {
> +	LEGACY_LAYOUT,
> +	A1_LAYOUT,
> +};
> +
> +/**
>   * struct meson bank
>   *
>   * @name:	bank name
> @@ -114,6 +122,7 @@ struct meson_pinctrl_data {
>  	unsigned int num_banks;
>  	const struct pinmux_ops *pmx_ops;
>  	void *pmx_data;
> +	unsigned int reg_layout;
>  };
>  
>  struct meson_pinctrl {


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/3] pinctrl: add compatible for Amlogic Meson A1 pin controller
  2019-09-17  7:18   ` Neil Armstrong
@ 2019-09-17 10:29     ` Qianggui Song
  0 siblings, 0 replies; 15+ messages in thread
From: Qianggui Song @ 2019-09-17 10:29 UTC (permalink / raw)
  To: Neil Armstrong, Linus Walleij, linux-gpio
  Cc: Xingyu Chen, Jianxin Pan, Jerome Brunet, Kevin Hilman,
	Martin Blumenstingl, Carlo Caione, Rob Herring, Hanjie Lin,
	Mark Rutland, linux-arm-kernel, linux-amlogic, linux-kernel,
	devicetree

Hi, Neil
	Thanks for your review

On 2019/9/17 15:18, Neil Armstrong wrote:
> Hi,
> 
> On 17/09/2019 08:07, Qianggui Song wrote:
>> Add new compatible name for Amlogic's Meson-A1 pin controller
>> add a dt-binding header file which document the detail pin names.
> 
> Please add in the commit log that A1 doesn't need the DS bank reg,
> so when we will convert these bindings to yaml we will be aware of it.
> 
OK, will add it in the next patch
>>
>> Signed-off-by: Qianggui Song <qianggui.song@amlogic.com>
>> Signed-off-by: Xingyu Chen <xingyu.chen@amlogic.com>
>> Signed-off-by: Jianxin Pan <jianxin.pan@amlogic.com>
>> ---
>>  .../devicetree/bindings/pinctrl/meson,pinctrl.txt  |  1 +
>>  include/dt-bindings/gpio/meson-a1-gpio.h           | 73 ++++++++++++++++++++++
>>  2 files changed, 74 insertions(+)
>>  create mode 100644 include/dt-bindings/gpio/meson-a1-gpio.h
>>
>> diff --git a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
>> index 10dc4f7..0aff1f2 100644
>> --- a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
>> +++ b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
>> @@ -15,6 +15,7 @@ Required properties for the root node:
>>  		      "amlogic,meson-axg-aobus-pinctrl"
>>  		      "amlogic,meson-g12a-periphs-pinctrl"
>>  		      "amlogic,meson-g12a-aobus-pinctrl"
>> +		      "amlogic,meson-a1-periphs-pinctrl"
>>   - reg: address and size of registers controlling irq functionality
>>  
>>  === GPIO sub-nodes ===
>> diff --git a/include/dt-bindings/gpio/meson-a1-gpio.h b/include/dt-bindings/gpio/meson-a1-gpio.h
>> new file mode 100644
>> index 0000000..40e57a5
>> --- /dev/null
>> +++ b/include/dt-bindings/gpio/meson-a1-gpio.h
>> @@ -0,0 +1,73 @@
>> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
>> +/*
>> + * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
>> + * Author: Qianggui Song <qianggui.song@amlogic.com>
>> + */
>> +
>> +#ifndef _DT_BINDINGS_MESON_A1_GPIO_H
>> +#define _DT_BINDINGS_MESON_A1_GPIO_H
>> +
>> +#define GPIOP_0		0
>> +#define GPIOP_1		1
>> +#define GPIOP_2		2
>> +#define GPIOP_3		3
>> +#define GPIOP_4		4
>> +#define GPIOP_5		5
>> +#define GPIOP_6		6
>> +#define GPIOP_7		7
>> +#define GPIOP_8		8
>> +#define GPIOP_9		9
>> +#define GPIOP_10	10
>> +#define GPIOP_11	11
>> +#define GPIOP_12	12
>> +#define GPIOB_0		13
>> +#define GPIOB_1		14
>> +#define GPIOB_2		15
>> +#define GPIOB_3		16
>> +#define GPIOB_4		17
>> +#define GPIOB_5		18
>> +#define GPIOB_6		19
>> +#define GPIOX_0		20
>> +#define GPIOX_1		21
>> +#define GPIOX_2		22
>> +#define GPIOX_3		23
>> +#define GPIOX_4		24
>> +#define GPIOX_5		25
>> +#define GPIOX_6		26
>> +#define GPIOX_7		27
>> +#define GPIOX_8		28
>> +#define GPIOX_9		29
>> +#define GPIOX_10	30
>> +#define GPIOX_11	31
>> +#define GPIOX_12	32
>> +#define GPIOX_13	33
>> +#define GPIOX_14	34
>> +#define GPIOX_15	35
>> +#define GPIOX_16	36
>> +#define GPIOF_0		37
>> +#define GPIOF_1		38
>> +#define GPIOF_2		39
>> +#define GPIOF_3		40
>> +#define GPIOF_4		41
>> +#define GPIOF_5		42
>> +#define GPIOF_6		43
>> +#define GPIOF_7		44
>> +#define GPIOF_8		45
>> +#define GPIOF_9		46
>> +#define GPIOF_10	47
>> +#define GPIOF_11	48
>> +#define GPIOF_12	49
>> +#define GPIOA_0		50
>> +#define GPIOA_1		51
>> +#define GPIOA_2		52
>> +#define GPIOA_3		53
>> +#define GPIOA_4		54
>> +#define GPIOA_5		55
>> +#define GPIOA_6		56
>> +#define GPIOA_7		57
>> +#define GPIOA_8		58
>> +#define GPIOA_9		59
>> +#define GPIOA_10	60
>> +#define GPIOA_11	61
>> +
>> +#endif /* _DT_BINDINGS_MESON_A1_GPIO_H */
>>
> 
> 
> With that fixed,
> 
> Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
> 
> Neil
> 
> .
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/3] pinctrl: meson-a1: add pinctrl driver for Meson A1 Soc
  2019-09-17  7:15   ` Neil Armstrong
@ 2019-09-17 10:59     ` Qianggui Song
  0 siblings, 0 replies; 15+ messages in thread
From: Qianggui Song @ 2019-09-17 10:59 UTC (permalink / raw)
  To: Neil Armstrong, Linus Walleij, linux-gpio
  Cc: Xingyu Chen, Jianxin Pan, Jerome Brunet, Kevin Hilman,
	Martin Blumenstingl, Carlo Caione, Rob Herring, Hanjie Lin,
	Mark Rutland, linux-arm-kernel, linux-amlogic, linux-kernel


On 2019/9/17 15:15, Neil Armstrong wrote:
> Hi,
> 
> On 17/09/2019 08:07, Qianggui Song wrote:
>> Add pinctrl driver for Meson A1 Soc which share the same register layout of
>> pinmux with previous Meson-G12A, however there is difference for gpio
>> and pin config register in A1. The register layout is as below:
>>
>> /* first bank */	      /* addr */
>> - P_PADCTRL_GPIOP_I         base + 0x00 << 2
>> - P_PADCTRL_GPIOP_O         base + 0x01 << 2
>> - P_PADCTRL_GPIOP_OEN       base + 0x02 << 2
>> - P_PADCTRL_GPIOP_PULL_EN   base + 0x03 << 2
>> - P_PADCTRL_GPIOP_PULL_UP   base + 0x04 << 2
>> - P_PADCTRL_GPIOP_DS        base + 0x05 << 2
>>
>> /* second bank */
>> - P_PADCTRL_GPIOB_I         base + 0x10 << 2
>> - P_PADCTRL_GPIOB_O         base + 0x11 << 2
>> - P_PADCTRL_GPIOB_OEN       base + 0x12 << 2
>> - P_PADCTRL_GPIOB_PULL_EN   base + 0x13 << 2
>> - P_PADCTRL_GPIOB_PULL_UP   base + 0x14 << 2
>> - P_PADCTRL_GPIOB_DS        base + 0x15 << 2
>>
>> Each bank contains at least 6 registers to be configured, if one bank has
>> more than 16 gpios, an extra P_PADCTRL_GPIO[X]_DS_EXT is included. Between
>> two adjacent P_PADCTRL_GPIO[X]_I, there is an offset 0x10, that is to say,
>> for third bank, the offsets will be 0x20,0x21,0x22,0x23,0x24,0x25 according
>> to above register layout.
> 
> Sorry but the explanation is not very clear, could you show the G12A mapping
> in comparison to explain your point and how reg_ds = reg_pullen solves the issue
> here ?
> 
For G12A EE groups, register layout is like:
- PREG_PAD_GPIO[N]_EN_N
- PREG_PAD_GPIO[N]_O
- PREG_PAD_GPIO[N]_I
 ------address not continue----
- PAD_PULL_UP_REG[N]
		...
 ------address not continue----
- PAD_PULL_UP_EN_REG[N]
		...
 ------address not continue----
- PAD_DS_REG[N][M]

where N=0~5, M=A or B

So for G12A EE groups , to calculate other register, we have five
register bases in dts:
"gpio"(reg_gpio), "mux"(reg_mux), "pull(reg_pull)",
"pull_enable(reg_pull)", "ds(reg_ds)",

For G12A AO groups
- AO_PAD_DS_A
- AO_PAD_DS_B
- AO_GPIO_O_EN_N
- AO_GPIO_I
- AO_RTI_PULL_UP_REG
- AO_RTI_PULL_UP_EN_REG
- AO_GPIO_O

we only need three register bases in dts: "mux"(reg_mux), "ds"(reg_ds),
"gpio"(reg_gpio).
To do that "reg_pull = reg_gpio",  "reg_pullen = reg_pull" have done by
previous work.

In A1, there are no EE and AO groups, register layout depicted in commit
log shows that we just use one register base (for A1 here is
P_PADCTRL_GPIOP_I), other register bases can be easily calculated for
simple rule. Since we just use one register base,reg_ds should be
equaled to reg_pullen.

G12A gpio and pin config registers is grouped according to function,
while A1 is according to bank.

>>
>> Current Meson pinctrl driver can cover such change by using base address of
>> GPIO as that of drive-strength. While simply giving reg_ds = reg_pullen
>> make wrong value to reg_ds for Soc that not support drive-strength like AXG
>> . Here a private data used to identify register layout is introduced.
> 
> Could you also precise there is no AO pinctrl bank on A1.
> 
will add description in the next patch
>>
>> Signed-off-by: Qianggui Song <qianggui.song@amlogic.com>
>> Signed-off-by: Xingyu Chen <xingyu.chen@amlogic.com>
>> Signed-off-by: Jianxin Pan <jianxin.pan@amlogic.com>
>> ---
>>  drivers/pinctrl/meson/Kconfig            |   6 +
>>  drivers/pinctrl/meson/Makefile           |   1 +
>>  drivers/pinctrl/meson/pinctrl-meson-a1.c | 942 +++++++++++++++++++++++++++++++
>>  drivers/pinctrl/meson/pinctrl-meson.c    |   8 +-
>>  drivers/pinctrl/meson/pinctrl-meson.h    |   9 +
>>  5 files changed, 964 insertions(+), 2 deletions(-)
>>  create mode 100644 drivers/pinctrl/meson/pinctrl-meson-a1.c
>>
>> diff --git a/drivers/pinctrl/meson/Kconfig b/drivers/pinctrl/meson/Kconfig
>> index df55f61..3cb1191 100644
>> --- a/drivers/pinctrl/meson/Kconfig
>> +++ b/drivers/pinctrl/meson/Kconfig
>> @@ -54,4 +54,10 @@ config PINCTRL_MESON_G12A
>>  	select PINCTRL_MESON_AXG_PMX
>>  	default y
>>  
>> +config PINCTRL_MESON_A1
>> +	bool "Meson a1 Soc pinctrl driver"
>> +	depends on ARM64
>> +	select PINCTRL_MESON_AXG_PMX
>> +	default y
>> +
>>  endif
>> diff --git a/drivers/pinctrl/meson/Makefile b/drivers/pinctrl/meson/Makefile
>> index a69c565..1a5bffe 100644
>> --- a/drivers/pinctrl/meson/Makefile
>> +++ b/drivers/pinctrl/meson/Makefile
>> @@ -8,3 +8,4 @@ obj-$(CONFIG_PINCTRL_MESON_GXL) += pinctrl-meson-gxl.o
>>  obj-$(CONFIG_PINCTRL_MESON_AXG_PMX) += pinctrl-meson-axg-pmx.o
>>  obj-$(CONFIG_PINCTRL_MESON_AXG) += pinctrl-meson-axg.o
>>  obj-$(CONFIG_PINCTRL_MESON_G12A) += pinctrl-meson-g12a.o
>> +obj-$(CONFIG_PINCTRL_MESON_A1) += pinctrl-meson-a1.o
>> diff --git a/drivers/pinctrl/meson/pinctrl-meson-a1.c b/drivers/pinctrl/meson/pinctrl-meson-a1.c
>> new file mode 100644
>> index 0000000..f3a88f1
>> --- /dev/null
>> +++ b/drivers/pinctrl/meson/pinctrl-meson-a1.c
>> @@ -0,0 +1,942 @@
>> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>> +/*
>> + * Pin controller and GPIO driver for Amlogic Meson A1 SoC.
>> + *
>> + * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
>> + * Author: Qianggui Song <qianggui.song@amlogic.com>
>> + */
>> +
>> +#include <dt-bindings/gpio/meson-a1-gpio.h>
>> +#include "pinctrl-meson.h"
>> +#include "pinctrl-meson-axg-pmx.h"
>> +
>> +static const struct pinctrl_pin_desc meson_a1_periphs_pins[] = {
>> +	MESON_PIN(GPIOP_0),
>> +	MESON_PIN(GPIOP_1),
>> +	MESON_PIN(GPIOP_2),
>> +	MESON_PIN(GPIOP_3),
>> +	MESON_PIN(GPIOP_4),
>> +	MESON_PIN(GPIOP_5),
>> +	MESON_PIN(GPIOP_6),
>> +	MESON_PIN(GPIOP_7),
>> +	MESON_PIN(GPIOP_8),
>> +	MESON_PIN(GPIOP_9),
>> +	MESON_PIN(GPIOP_10),
>> +	MESON_PIN(GPIOP_11),
>> +	MESON_PIN(GPIOP_12),
>> +	MESON_PIN(GPIOB_0),
>> +	MESON_PIN(GPIOB_1),
>> +	MESON_PIN(GPIOB_2),
>> +	MESON_PIN(GPIOB_3),
>> +	MESON_PIN(GPIOB_4),
>> +	MESON_PIN(GPIOB_5),
>> +	MESON_PIN(GPIOB_6),
>> +	MESON_PIN(GPIOX_0),
>> +	MESON_PIN(GPIOX_1),
>> +	MESON_PIN(GPIOX_2),
>> +	MESON_PIN(GPIOX_3),
>> +	MESON_PIN(GPIOX_4),
>> +	MESON_PIN(GPIOX_5),
>> +	MESON_PIN(GPIOX_6),
>> +	MESON_PIN(GPIOX_7),
>> +	MESON_PIN(GPIOX_8),
>> +	MESON_PIN(GPIOX_9),
>> +	MESON_PIN(GPIOX_10),
>> +	MESON_PIN(GPIOX_11),
>> +	MESON_PIN(GPIOX_12),
>> +	MESON_PIN(GPIOX_13),
>> +	MESON_PIN(GPIOX_14),
>> +	MESON_PIN(GPIOX_15),
>> +	MESON_PIN(GPIOX_16),
>> +	MESON_PIN(GPIOF_0),
>> +	MESON_PIN(GPIOF_1),
>> +	MESON_PIN(GPIOF_2),
>> +	MESON_PIN(GPIOF_3),
>> +	MESON_PIN(GPIOF_4),
>> +	MESON_PIN(GPIOF_5),
>> +	MESON_PIN(GPIOF_6),
>> +	MESON_PIN(GPIOF_7),
>> +	MESON_PIN(GPIOF_8),
>> +	MESON_PIN(GPIOF_9),
>> +	MESON_PIN(GPIOF_10),
>> +	MESON_PIN(GPIOF_11),
>> +	MESON_PIN(GPIOF_12),
>> +	MESON_PIN(GPIOA_0),
>> +	MESON_PIN(GPIOA_1),
>> +	MESON_PIN(GPIOA_2),
>> +	MESON_PIN(GPIOA_3),
>> +	MESON_PIN(GPIOA_4),
>> +	MESON_PIN(GPIOA_5),
>> +	MESON_PIN(GPIOA_6),
>> +	MESON_PIN(GPIOA_7),
>> +	MESON_PIN(GPIOA_8),
>> +	MESON_PIN(GPIOA_9),
>> +	MESON_PIN(GPIOA_10),
>> +	MESON_PIN(GPIOA_11),
>> +};
>> +
>> +/* psram */
>> +static const unsigned int psram_clkn_pins[]		= { GPIOP_0 };
>> +static const unsigned int psram_clkp_pins[]		= { GPIOP_1 };
>> +static const unsigned int psram_ce_n_pins[]		= { GPIOP_2 };
>> +static const unsigned int psram_rst_n_pins[]		= { GPIOP_3 };
>> +static const unsigned int psram_adq0_pins[]		= { GPIOP_4 };
>> +static const unsigned int psram_adq1_pins[]		= { GPIOP_5 };
>> +static const unsigned int psram_adq2_pins[]		= { GPIOP_6 };
>> +static const unsigned int psram_adq3_pins[]		= { GPIOP_7 };
>> +static const unsigned int psram_adq4_pins[]		= { GPIOP_8 };
>> +static const unsigned int psram_adq5_pins[]		= { GPIOP_9 };
>> +static const unsigned int psram_adq6_pins[]		= { GPIOP_10 };
>> +static const unsigned int psram_adq7_pins[]		= { GPIOP_11 };
>> +static const unsigned int psram_dqs_dm_pins[]		= { GPIOP_12 };
>> +
>> +/* sdcard */
>> +static const unsigned int sdcard_d0_b_pins[]		= { GPIOB_0 };
>> +static const unsigned int sdcard_d1_b_pins[]		= { GPIOB_1 };
>> +static const unsigned int sdcard_d2_b_pins[]		= { GPIOB_2 };
>> +static const unsigned int sdcard_d3_b_pins[]		= { GPIOB_3 };
>> +static const unsigned int sdcard_clk_b_pins[]		= { GPIOB_4 };
>> +static const unsigned int sdcard_cmd_b_pins[]		= { GPIOB_5 };
>> +
>> +static const unsigned int sdcard_d0_x_pins[]		= { GPIOX_0 };
>> +static const unsigned int sdcard_d1_x_pins[]		= { GPIOX_1 };
>> +static const unsigned int sdcard_d2_x_pins[]		= { GPIOX_2 };
>> +static const unsigned int sdcard_d3_x_pins[]		= { GPIOX_3 };
>> +static const unsigned int sdcard_clk_x_pins[]		= { GPIOX_4 };
>> +static const unsigned int sdcard_cmd_x_pins[]		= { GPIOX_5 };
>> +
>> +/* spif */
>> +static const unsigned int spif_mo_pins[]		= { GPIOB_0 };
>> +static const unsigned int spif_mi_pins[]		= { GPIOB_1 };
>> +static const unsigned int spif_wp_n_pins[]		= { GPIOB_2 };
>> +static const unsigned int spif_hold_n_pins[]		= { GPIOB_3 };
>> +static const unsigned int spif_clk_pins[]		= { GPIOB_4 };
>> +static const unsigned int spif_cs_pins[]		= { GPIOB_5 };
>> +
>> +/* i2c0 */
>> +static const unsigned int i2c0_sck_f9_pins[]		= { GPIOF_9 };
>> +static const unsigned int i2c0_sda_f10_pins[]		= { GPIOF_10 };
>> +static const unsigned int i2c0_sck_f11_pins[]		= { GPIOF_11 };
>> +static const unsigned int i2c0_sda_f12_pins[]		= { GPIOF_12 };
>> +
>> +/* i2c1 */
>> +static const unsigned int i2c1_sda_x_pins[]		= { GPIOX_9 };
>> +static const unsigned int i2c1_sck_x_pins[]		= { GPIOX_10 };
>> +static const unsigned int i2c1_sda_a_pins[]		= { GPIOA_10 };
>> +static const unsigned int i2c1_sck_a_pins[]		= { GPIOA_11 };
>> +
>> +/* i2c2 */
>> +static const unsigned int i2c2_sck_x0_pins[]		= { GPIOX_0 };
>> +static const unsigned int i2c2_sda_x1_pins[]		= { GPIOX_1 };
>> +static const unsigned int i2c2_sck_x15_pins[]		= { GPIOX_15 };
>> +static const unsigned int i2c2_sda_x16_pins[]		= { GPIOX_16 };
>> +static const unsigned int i2c2_sck_a4_pins[]		= { GPIOA_4 };
>> +static const unsigned int i2c2_sda_a5_pins[]		= { GPIOA_5 };
>> +static const unsigned int i2c2_sck_a8_pins[]		= { GPIOA_8 };
>> +static const unsigned int i2c2_sda_a9_pins[]		= { GPIOA_9 };
>> +
>> +/* i2c3 */
>> +static const unsigned int i2c3_sck_f_pins[]		= { GPIOF_4 };
>> +static const unsigned int i2c3_sda_f_pins[]		= { GPIOF_5 };
>> +static const unsigned int i2c3_sck_x_pins[]		= { GPIOX_11 };
>> +static const unsigned int i2c3_sda_x_pins[]		= { GPIOX_12 };
>> +
>> +/* i2c slave */
>> +static const unsigned int i2c_slave_sck_a_pins[]	= { GPIOA_10 };
>> +static const unsigned int i2c_slave_sda_a_pins[]	= { GPIOA_11 };
>> +static const unsigned int i2c_slave_sck_f_pins[]	= { GPIOF_11 };
>> +static const unsigned int i2c_slave_sda_f_pins[]	= { GPIOF_12 };
>> +
>> +/* uart_a */
>> +static const unsigned int uart_a_tx_pins[]		= { GPIOX_11 };
>> +static const unsigned int uart_a_rx_pins[]		= { GPIOX_12 };
>> +static const unsigned int uart_a_cts_pins[]		= { GPIOX_13 };
>> +static const unsigned int uart_a_rts_pins[]		= { GPIOX_14 };
>> +
>> +/* uart_b */
>> +static const unsigned int uart_b_tx_x_pins[]		= { GPIOX_7 };
>> +static const unsigned int uart_b_rx_x_pins[]		= { GPIOX_8 };
>> +static const unsigned int uart_b_tx_f_pins[]		= { GPIOF_0 };
>> +static const unsigned int uart_b_rx_f_pins[]		= { GPIOF_1 };
>> +
>> +/* uart_c */
>> +static const unsigned int uart_c_tx_x0_pins[]		= { GPIOX_0 };
>> +static const unsigned int uart_c_rx_x1_pins[]		= { GPIOX_1 };
>> +static const unsigned int uart_c_cts_pins[]		= { GPIOX_2 };
>> +static const unsigned int uart_c_rts_pins[]		= { GPIOX_3 };
>> +static const unsigned int uart_c_tx_x15_pins[]		= { GPIOX_15 };
>> +static const unsigned int uart_c_rx_x16_pins[]		= { GPIOX_16 };
>> +
>> +/* pmw_a */
>> +static const unsigned int pwm_a_x6_pins[]		= { GPIOX_6 };
>> +static const unsigned int pwm_a_x7_pins[]		= { GPIOX_7 };
>> +static const unsigned int pwm_a_f6_pins[]		= { GPIOF_6 };
>> +static const unsigned int pwm_a_f10_pins[]		= { GPIOF_10 };
>> +static const unsigned int pwm_a_a_pins[]		= { GPIOA_5 };
>> +
>> +/* pmw_b */
>> +static const unsigned int pwm_b_x_pins[]		= { GPIOX_8 };
>> +static const unsigned int pwm_b_f_pins[]		= { GPIOF_7 };
>> +static const unsigned int pwm_b_a_pins[]		= { GPIOA_11 };
>> +
>> +/* pmw_c */
>> +static const unsigned int pwm_c_x_pins[]		= { GPIOX_9 };
>> +static const unsigned int pwm_c_f3_pins[]		= { GPIOF_3 };
>> +static const unsigned int pwm_c_f8_pins[]		= { GPIOF_8 };
>> +static const unsigned int pwm_c_a_pins[]		= { GPIOA_10 };
>> +
>> +/* pwm_d */
>> +static const unsigned int pwm_d_x10_pins[]		= { GPIOX_10 };
>> +static const unsigned int pwm_d_x13_pins[]		= { GPIOX_13 };
>> +static const unsigned int pwm_d_x15_pins[]		= { GPIOX_15 };
>> +static const unsigned int pwm_d_f_pins[]		= { GPIOF_11 };
>> +
>> +/* pwm_e */
>> +static const unsigned int pwm_e_p_pins[]		= { GPIOP_3 };
>> +static const unsigned int pwm_e_x2_pins[]		= { GPIOX_2 };
>> +static const unsigned int pwm_e_x14_pins[]		= { GPIOX_14 };
>> +static const unsigned int pwm_e_x16_pins[]		= { GPIOX_16 };
>> +static const unsigned int pwm_e_f_pins[]		= { GPIOF_3 };
>> +static const unsigned int pwm_e_a_pins[]		= { GPIOA_0 };
>> +
>> +/* pwm_f */
>> +static const unsigned int pwm_f_b_pins[]		= { GPIOB_6 };
>> +static const unsigned int pwm_f_x_pins[]		= { GPIOX_3 };
>> +static const unsigned int pwm_f_f4_pins[]		= { GPIOF_4 };
>> +static const unsigned int pwm_f_f12_pins[]		= { GPIOF_12 };
>> +
>> +/* pwm_a_hiz */
>> +static const unsigned int pwm_a_hiz_f8_pins[]		= { GPIOF_8 };
>> +static const unsigned int pwm_a_hiz_f10_pins[]		= { GPIOF_10 };
>> +static const unsigned int pmw_a_hiz_f6_pins[]		= { GPIOF_6 };
>> +
>> +/* pwm_b_hiz */
>> +static const unsigned int pwm_b_hiz_pins[]		= { GPIOF_7 };
>> +
>> +/* pmw_c_hiz */
>> +static const unsigned int pwm_c_hiz_pins[]		= { GPIOF_8 };
>> +
>> +/* tdm_a */
>> +static const unsigned int tdm_a_dout1_pins[]		= { GPIOX_7 };
>> +static const unsigned int tdm_a_dout0_pins[]		= { GPIOX_8 };
>> +static const unsigned int tdm_a_fs_pins[]		= { GPIOX_9 };
>> +static const unsigned int tdm_a_sclk_pins[]		= { GPIOX_10 };
>> +static const unsigned int tdm_a_din1_pins[]		= { GPIOX_7 };
>> +static const unsigned int tdm_a_din0_pins[]		= { GPIOX_8 };
>> +static const unsigned int tdm_a_slv_fs_pins[]		= { GPIOX_9 };
>> +static const unsigned int tdm_a_slv_sclk_pins[]		= { GPIOX_10 };
>> +
>> +/* spi_a */
>> +static const unsigned int spi_a_mosi_x2_pins[]		= { GPIOX_2 };
>> +static const unsigned int spi_a_ss0_x3_pins[]		= { GPIOX_3 };
>> +static const unsigned int spi_a_sclk_x4_pins[]		= { GPIOX_4 };
>> +static const unsigned int spi_a_miso_x5_pins[]		= { GPIOX_5 };
>> +static const unsigned int spi_a_mosi_x7_pins[]		= { GPIOX_7 };
>> +static const unsigned int spi_a_miso_x8_pins[]		= { GPIOX_8 };
>> +static const unsigned int spi_a_ss0_x9_pins[]		= { GPIOX_9 };
>> +static const unsigned int spi_a_sclk_x10_pins[]		= { GPIOX_10 };
>> +
>> +static const unsigned int spi_a_mosi_a_pins[]		= { GPIOA_6 };
>> +static const unsigned int spi_a_miso_a_pins[]		= { GPIOA_7 };
>> +static const unsigned int spi_a_ss0_a_pins[]		= { GPIOA_8 };
>> +static const unsigned int spi_a_sclk_a_pins[]		= { GPIOA_9 };
>> +
>> +/* pdm */
>> +static const unsigned int pdm_din0_x_pins[]		= { GPIOX_7 };
>> +static const unsigned int pdm_din1_x_pins[]		= { GPIOX_8 };
>> +static const unsigned int pdm_din2_x_pins[]		= { GPIOX_9 };
>> +static const unsigned int pdm_dclk_x_pins[]		= { GPIOX_10 };
>> +
>> +static const unsigned int pdm_din2_a_pins[]		= { GPIOA_6 };
>> +static const unsigned int pdm_din1_a_pins[]		= { GPIOA_7 };
>> +static const unsigned int pdm_din0_a_pins[]		= { GPIOA_8 };
>> +static const unsigned int pdm_dclk_pins[]		= { GPIOA_9 };
>> +
>> +/* gen_clk */
>> +static const unsigned int gen_clk_x_pins[]		= { GPIOX_7 };
>> +static const unsigned int gen_clk_f8_pins[]		= { GPIOF_8 };
>> +static const unsigned int gen_clk_f10_pins[]		= { GPIOF_10 };
>> +static const unsigned int gen_clk_a_pins[]		= { GPIOA_11 };
>> +
>> +/* jtag_a */
>> +static const unsigned int jtag_a_clk_pins[]		= { GPIOF_4 };
>> +static const unsigned int jtag_a_tms_pins[]		= { GPIOF_5 };
>> +static const unsigned int jtag_a_tdi_pins[]		= { GPIOF_6 };
>> +static const unsigned int jtag_a_tdo_pins[]		= { GPIOF_7 };
>> +
>> +/* clk_32_in */
>> +static const unsigned int clk_32k_in_pins[]		= { GPIOF_2 };
>> +
>> +/* ir in */
>> +static const unsigned int remote_input_f_pins[]		= { GPIOF_3 };
>> +static const unsigned int remote_input_a_pins[]		= { GPIOA_11 };
>> +
>> +/* ir out */
>> +static const unsigned int remote_out_pins[]		= { GPIOF_5 };
>> +
>> +/* spdif */
>> +static const unsigned int spdif_in_f6_pins[]		= { GPIOF_6 };
>> +static const unsigned int spdif_in_f7_pins[]		= { GPIOF_7 };
>> +
>> +/* sw */
>> +static const unsigned int swclk_pins[]			= { GPIOF_4 };
>> +static const unsigned int swdio_pins[]			= { GPIOF_5 };
>> +
>> +/* clk_25 */
>> +static const unsigned int clk25_pins[]			= { GPIOF_10 };
>> +
>> +/* cec_a */
>> +static const unsigned int cec_a_pins[]			= { GPIOF_2 };
>> +
>> +/* cec_b */
>> +static const unsigned int cec_b_pins[]			= { GPIOF_2 };
>> +
>> +/* clk12_24 */
>> +static const unsigned int clk12_24_pins[]		= { GPIOF_10 };
>> +
>> +/* mclk_0 */
>> +static const unsigned int mclk_0_pins[]			= { GPIOA_0 };
>> +
>> +/* tdm_b */
>> +static const unsigned int tdm_b_sclk_pins[]		= { GPIOA_1 };
>> +static const unsigned int tdm_b_fs_pins[]		= { GPIOA_2 };
>> +static const unsigned int tdm_b_dout0_pins[]		= { GPIOA_3 };
>> +static const unsigned int tdm_b_dout1_pins[]		= { GPIOA_4 };
>> +static const unsigned int tdm_b_dout2_pins[]		= { GPIOA_5 };
>> +static const unsigned int tdm_b_dout3_pins[]		= { GPIOA_6 };
>> +static const unsigned int tdm_b_dout4_pins[]		= { GPIOA_7 };
>> +static const unsigned int tdm_b_dout5_pins[]		= { GPIOA_8 };
>> +static const unsigned int tdm_b_slv_sclk_pins[]		= { GPIOA_5 };
>> +static const unsigned int tdm_b_slv_fs_pins[]		= { GPIOA_6 };
>> +static const unsigned int tdm_b_din0_pins[]		= { GPIOA_7 };
>> +static const unsigned int tdm_b_din1_pins[]		= { GPIOA_8 };
>> +static const unsigned int tdm_b_din2_pins[]		= { GPIOA_9 };
>> +
>> +/* mclk_vad */
>> +static const unsigned int mclk_vad_pins[]		= { GPIOA_0 };
>> +
>> +/* tdm_vad */
>> +static const unsigned int tdm_vad_sclk_a1_pins[]	= { GPIOA_1 };
>> +static const unsigned int tdm_vad_fs_a2_pins[]		= { GPIOA_2 };
>> +static const unsigned int tdm_vad_sclk_a5_pins[]	= { GPIOA_5 };
>> +static const unsigned int tdm_vad_fs_a6_pins[]		= { GPIOA_6 };
>> +
>> +/* tst_out */
>> +static const unsigned int tst_out0_pins[]		= { GPIOA_0 };
>> +static const unsigned int tst_out1_pins[]		= { GPIOA_1 };
>> +static const unsigned int tst_out2_pins[]		= { GPIOA_2 };
>> +static const unsigned int tst_out3_pins[]		= { GPIOA_3 };
>> +static const unsigned int tst_out4_pins[]		= { GPIOA_4 };
>> +static const unsigned int tst_out5_pins[]		= { GPIOA_5 };
>> +static const unsigned int tst_out6_pins[]		= { GPIOA_6 };
>> +static const unsigned int tst_out7_pins[]		= { GPIOA_7 };
>> +static const unsigned int tst_out8_pins[]		= { GPIOA_8 };
>> +static const unsigned int tst_out9_pins[]		= { GPIOA_9 };
>> +static const unsigned int tst_out10_pins[]		= { GPIOA_10 };
>> +static const unsigned int tst_out11_pins[]		= { GPIOA_11 };
>> +
>> +/* mute */
>> +static const unsigned int mute_key_pins[]		= { GPIOA_4 };
>> +static const unsigned int mute_en_pins[]		= { GPIOA_5 };
>> +
>> +static struct meson_pmx_group meson_a1_periphs_groups[] = {
>> +	GPIO_GROUP(GPIOP_0),
>> +	GPIO_GROUP(GPIOP_1),
>> +	GPIO_GROUP(GPIOP_2),
>> +	GPIO_GROUP(GPIOP_3),
>> +	GPIO_GROUP(GPIOP_4),
>> +	GPIO_GROUP(GPIOP_5),
>> +	GPIO_GROUP(GPIOP_6),
>> +	GPIO_GROUP(GPIOP_7),
>> +	GPIO_GROUP(GPIOP_8),
>> +	GPIO_GROUP(GPIOP_9),
>> +	GPIO_GROUP(GPIOP_10),
>> +	GPIO_GROUP(GPIOP_11),
>> +	GPIO_GROUP(GPIOP_12),
>> +	GPIO_GROUP(GPIOB_0),
>> +	GPIO_GROUP(GPIOB_1),
>> +	GPIO_GROUP(GPIOB_2),
>> +	GPIO_GROUP(GPIOB_3),
>> +	GPIO_GROUP(GPIOB_4),
>> +	GPIO_GROUP(GPIOB_5),
>> +	GPIO_GROUP(GPIOB_6),
>> +	GPIO_GROUP(GPIOX_0),
>> +	GPIO_GROUP(GPIOX_1),
>> +	GPIO_GROUP(GPIOX_2),
>> +	GPIO_GROUP(GPIOX_3),
>> +	GPIO_GROUP(GPIOX_4),
>> +	GPIO_GROUP(GPIOX_5),
>> +	GPIO_GROUP(GPIOX_6),
>> +	GPIO_GROUP(GPIOX_7),
>> +	GPIO_GROUP(GPIOX_8),
>> +	GPIO_GROUP(GPIOX_9),
>> +	GPIO_GROUP(GPIOX_10),
>> +	GPIO_GROUP(GPIOX_11),
>> +	GPIO_GROUP(GPIOX_12),
>> +	GPIO_GROUP(GPIOX_13),
>> +	GPIO_GROUP(GPIOX_14),
>> +	GPIO_GROUP(GPIOX_15),
>> +	GPIO_GROUP(GPIOX_16),
>> +	GPIO_GROUP(GPIOF_0),
>> +	GPIO_GROUP(GPIOF_1),
>> +	GPIO_GROUP(GPIOF_2),
>> +	GPIO_GROUP(GPIOF_3),
>> +	GPIO_GROUP(GPIOF_4),
>> +	GPIO_GROUP(GPIOF_5),
>> +	GPIO_GROUP(GPIOF_6),
>> +	GPIO_GROUP(GPIOF_7),
>> +	GPIO_GROUP(GPIOF_8),
>> +	GPIO_GROUP(GPIOF_9),
>> +	GPIO_GROUP(GPIOF_10),
>> +	GPIO_GROUP(GPIOF_11),
>> +	GPIO_GROUP(GPIOF_12),
>> +	GPIO_GROUP(GPIOA_0),
>> +	GPIO_GROUP(GPIOA_1),
>> +	GPIO_GROUP(GPIOA_2),
>> +	GPIO_GROUP(GPIOA_3),
>> +	GPIO_GROUP(GPIOA_4),
>> +	GPIO_GROUP(GPIOA_5),
>> +	GPIO_GROUP(GPIOA_6),
>> +	GPIO_GROUP(GPIOA_7),
>> +	GPIO_GROUP(GPIOA_8),
>> +	GPIO_GROUP(GPIOA_9),
>> +	GPIO_GROUP(GPIOA_10),
>> +	GPIO_GROUP(GPIOA_11),
>> +
>> +	/* bank P func1 */
>> +	GROUP(psram_clkn,		1),
>> +	GROUP(psram_clkp,		1),
>> +	GROUP(psram_ce_n,		1),
>> +	GROUP(psram_rst_n,		1),
>> +	GROUP(psram_adq0,		1),
>> +	GROUP(psram_adq1,		1),
>> +	GROUP(psram_adq2,		1),
>> +	GROUP(psram_adq3,		1),
>> +	GROUP(psram_adq4,		1),
>> +	GROUP(psram_adq5,		1),
>> +	GROUP(psram_adq6,		1),
>> +	GROUP(psram_adq7,		1),
>> +	GROUP(psram_dqs_dm,		1),
>> +
>> +	/*bank P func2 */
>> +	GROUP(pwm_e_p,			2),
>> +
>> +	/*bank B func1 */
>> +	GROUP(spif_mo,			1),
>> +	GROUP(spif_mi,			1),
>> +	GROUP(spif_wp_n,		1),
>> +	GROUP(spif_hold_n,		1),
>> +	GROUP(spif_clk,			1),
>> +	GROUP(spif_cs,			1),
>> +	GROUP(pwm_f_b,			1),
>> +
>> +	/*bank B func2 */
>> +	GROUP(sdcard_d0_b,		2),
>> +	GROUP(sdcard_d1_b,		2),
>> +	GROUP(sdcard_d2_b,		2),
>> +	GROUP(sdcard_d3_b,		2),
>> +	GROUP(sdcard_clk_b,		2),
>> +	GROUP(sdcard_cmd_b,		2),
>> +
>> +	/*bank X func1 */
>> +	GROUP(sdcard_d0_x,		1),
>> +	GROUP(sdcard_d1_x,		1),
>> +	GROUP(sdcard_d2_x,		1),
>> +	GROUP(sdcard_d3_x,		1),
>> +	GROUP(sdcard_clk_x,		1),
>> +	GROUP(sdcard_cmd_x,		1),
>> +	GROUP(pwm_a_x6,			1),
>> +	GROUP(tdm_a_dout1,		1),
>> +	GROUP(tdm_a_dout0,		1),
>> +	GROUP(tdm_a_fs,			1),
>> +	GROUP(tdm_a_sclk,		1),
>> +	GROUP(uart_a_tx,		1),
>> +	GROUP(uart_a_rx,		1),
>> +	GROUP(uart_a_cts,		1),
>> +	GROUP(uart_a_rts,		1),
>> +	GROUP(pwm_d_x15,		1),
>> +	GROUP(pwm_e_x16,		1),
>> +
>> +	/*bank X func2 */
>> +	GROUP(i2c2_sck_x0,		2),
>> +	GROUP(i2c2_sda_x1,		2),
>> +	GROUP(spi_a_mosi_x2,		2),
>> +	GROUP(spi_a_ss0_x3,		2),
>> +	GROUP(spi_a_sclk_x4,		2),
>> +	GROUP(spi_a_miso_x5,		2),
>> +	GROUP(tdm_a_din1,		2),
>> +	GROUP(tdm_a_din0,		2),
>> +	GROUP(tdm_a_slv_fs,		2),
>> +	GROUP(tdm_a_slv_sclk,		2),
>> +	GROUP(i2c3_sck_x,		2),
>> +	GROUP(i2c3_sda_x,		2),
>> +	GROUP(pwm_d_x13,		2),
>> +	GROUP(pwm_e_x14,		2),
>> +	GROUP(i2c2_sck_x15,		2),
>> +	GROUP(i2c2_sda_x16,		2),
>> +
>> +	/*bank X func3 */
>> +	GROUP(uart_c_tx_x0,		3),
>> +	GROUP(uart_c_rx_x1,		3),
>> +	GROUP(uart_c_cts,		3),
>> +	GROUP(uart_c_rts,		3),
>> +	GROUP(pdm_din0_x,		3),
>> +	GROUP(pdm_din1_x,		3),
>> +	GROUP(pdm_din2_x,		3),
>> +	GROUP(pdm_dclk_x,		3),
>> +	GROUP(uart_c_tx_x15,		3),
>> +	GROUP(uart_c_rx_x16,		3),
>> +
>> +	/*bank X func4 */
>> +	GROUP(pwm_e_x2,			4),
>> +	GROUP(pwm_f_x,			4),
>> +	GROUP(spi_a_mosi_x7,		4),
>> +	GROUP(spi_a_miso_x8,		4),
>> +	GROUP(spi_a_ss0_x9,		4),
>> +	GROUP(spi_a_sclk_x10,		4),
>> +
>> +	/*bank X func5 */
>> +	GROUP(uart_b_tx_x,		5),
>> +	GROUP(uart_b_rx_x,		5),
>> +	GROUP(i2c1_sda_x,		5),
>> +	GROUP(i2c1_sck_x,		5),
>> +
>> +	/*bank X func6 */
>> +	GROUP(pwm_a_x7,			6),
>> +	GROUP(pwm_b_x,			6),
>> +	GROUP(pwm_c_x,			6),
>> +	GROUP(pwm_d_x10,		6),
>> +
>> +	/*bank X func7 */
>> +	GROUP(gen_clk_x,		7),
>> +
>> +	/*bank F func1 */
>> +	GROUP(uart_b_tx_f,		1),
>> +	GROUP(uart_b_rx_f,		1),
>> +	GROUP(remote_input_f,		1),
>> +	GROUP(jtag_a_clk,		1),
>> +	GROUP(jtag_a_tms,		1),
>> +	GROUP(jtag_a_tdi,		1),
>> +	GROUP(jtag_a_tdo,		1),
>> +	GROUP(gen_clk_f8,		1),
>> +	GROUP(pwm_a_f10,		1),
>> +	GROUP(i2c0_sck_f11,		1),
>> +	GROUP(i2c0_sda_f12,		1),
>> +
>> +	/*bank F func2 */
>> +	GROUP(clk_32k_in,		2),
>> +	GROUP(pwm_e_f,			2),
>> +	GROUP(pwm_f_f4,			2),
>> +	GROUP(remote_out,		2),
>> +	GROUP(spdif_in_f6,		2),
>> +	GROUP(spdif_in_f7,		2),
>> +	GROUP(pwm_a_hiz_f8,		2),
>> +	GROUP(pwm_a_hiz_f10,		2),
>> +	GROUP(pwm_d_f,			2),
>> +	GROUP(pwm_f_f12,		2),
>> +
>> +	/*bank F func3 */
>> +	GROUP(pwm_c_f3,			3),
>> +	GROUP(swclk,			3),
>> +	GROUP(swdio,			3),
>> +	GROUP(pwm_a_f6,			3),
>> +	GROUP(pwm_b_f,			3),
>> +	GROUP(pwm_c_f8,			3),
>> +	GROUP(clk25,			3),
>> +	GROUP(i2c_slave_sck_f,		3),
>> +	GROUP(i2c_slave_sda_f,		3),
>> +
>> +	/*bank F func4 */
>> +	GROUP(cec_a,			4),
>> +	GROUP(i2c3_sck_f,		4),
>> +	GROUP(i2c3_sda_f,		4),
>> +	GROUP(pmw_a_hiz_f6,		4),
>> +	GROUP(pwm_b_hiz,		4),
>> +	GROUP(pwm_c_hiz,		4),
>> +	GROUP(i2c0_sck_f9,		4),
>> +	GROUP(i2c0_sda_f10,		4),
>> +
>> +	/*bank F func5 */
>> +	GROUP(cec_b,			5),
>> +	GROUP(clk12_24,			5),
>> +
>> +	/*bank F func7 */
>> +	GROUP(gen_clk_f10,		7),
>> +
>> +	/*bank A func1 */
>> +	GROUP(mclk_0,			1),
>> +	GROUP(tdm_b_sclk,		1),
>> +	GROUP(tdm_b_fs,			1),
>> +	GROUP(tdm_b_dout0,		1),
>> +	GROUP(tdm_b_dout1,		1),
>> +	GROUP(tdm_b_dout2,		1),
>> +	GROUP(tdm_b_dout3,		1),
>> +	GROUP(tdm_b_dout4,		1),
>> +	GROUP(tdm_b_dout5,		1),
>> +	GROUP(remote_input_a,		1),
>> +
>> +	/*bank A func2 */
>> +	GROUP(pwm_e_a,			2),
>> +	GROUP(tdm_b_slv_sclk,		2),
>> +	GROUP(tdm_b_slv_fs,		2),
>> +	GROUP(tdm_b_din0,		2),
>> +	GROUP(tdm_b_din1,		2),
>> +	GROUP(tdm_b_din2,		2),
>> +	GROUP(i2c1_sda_a,		2),
>> +	GROUP(i2c1_sck_a,		2),
>> +
>> +	/*bank A func3 */
>> +	GROUP(i2c2_sck_a4,		3),
>> +	GROUP(i2c2_sda_a5,		3),
>> +	GROUP(pdm_din2_a,		3),
>> +	GROUP(pdm_din1_a,		3),
>> +	GROUP(pdm_din0_a,		3),
>> +	GROUP(pdm_dclk,			3),
>> +	GROUP(pwm_c_a,			3),
>> +	GROUP(pwm_b_a,			3),
>> +
>> +	/*bank A func4 */
>> +	GROUP(pwm_a_a,			4),
>> +	GROUP(spi_a_mosi_a,		4),
>> +	GROUP(spi_a_miso_a,		4),
>> +	GROUP(spi_a_ss0_a,		4),
>> +	GROUP(spi_a_sclk_a,		4),
>> +	GROUP(i2c_slave_sck_a,		4),
>> +	GROUP(i2c_slave_sda_a,		4),
>> +
>> +	/*bank A func5 */
>> +	GROUP(mclk_vad,			5),
>> +	GROUP(tdm_vad_sclk_a1,		5),
>> +	GROUP(tdm_vad_fs_a2,		5),
>> +	GROUP(tdm_vad_sclk_a5,		5),
>> +	GROUP(tdm_vad_fs_a6,		5),
>> +	GROUP(i2c2_sck_a8,		5),
>> +	GROUP(i2c2_sda_a9,		5),
>> +
>> +	/*bank A func6 */
>> +	GROUP(tst_out0,			6),
>> +	GROUP(tst_out1,			6),
>> +	GROUP(tst_out2,			6),
>> +	GROUP(tst_out3,			6),
>> +	GROUP(tst_out4,			6),
>> +	GROUP(tst_out5,			6),
>> +	GROUP(tst_out6,			6),
>> +	GROUP(tst_out7,			6),
>> +	GROUP(tst_out8,			6),
>> +	GROUP(tst_out9,			6),
>> +	GROUP(tst_out10,		6),
>> +	GROUP(tst_out11,		6),
>> +
>> +	/*bank A func7 */
>> +	GROUP(mute_key,			7),
>> +	GROUP(mute_en,			7),
>> +	GROUP(gen_clk_a,		7),
>> +};
>> +
>> +static const char * const gpio_periphs_groups[] = {
>> +	"GPIOP_0", "GPIOP_1", "GPIOP_2", "GPIOP_3", "GPIOP_4",
>> +	"GPIOP_5", "GPIOP_6", "GPIOP_7", "GPIOP_8", "GPIOP_9",
>> +	"GPIOP_10", "GPIOP_11", "GPIOP_12",
>> +
>> +	"GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4",
>> +	"GPIOB_5", "GPIOB_6",
>> +
>> +	"GPIOX_0", "GPIOX_1", "GPIOX_2", "GPIOX_3", "GPIOX_4",
>> +	"GPIOX_5", "GPIOX_6", "GPIOX_7", "GPIOX_8", "GPIOX_9",
>> +	"GPIOX_10", "GPIOX_11", "GPIOX_12", "GPIOX_13", "GPIOX_14",
>> +	"GPIOX_15", "GPIOX_16",
>> +
>> +	"GPIOF_0", "GPIOF_1", "GPIOF_2", "GPIOF_3", "GPIOF_4",
>> +	"GPIOF_5", "GPIOF_6", "GPIOF_7", "GPIOF_8", "GPIOF_9",
>> +	"GPIOF_10", "GPIOF_11", "GPIOF_12",
>> +
>> +	"GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4",
>> +	"GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9",
>> +	"GPIOA_10", "GPIOA_11",
>> +};
>> +
>> +static const char * const psram_groups[] = {
>> +	"psram_clkn", "psram_clkp", "psram_ce_n", "psram_rst_n", "psram_adq0",
>> +	"psram_adq1", "psram_adq2", "psram_adq3", "psram_adq4", "psram_adq5",
>> +	"psram_adq6", "psram_adq7", "psram_dqs_dm",
>> +};
>> +
>> +static const char * const pwm_a_groups[] = {
>> +	"pwm_a_x6", "pwm_a_x7", "pwm_a_f10", "pwm_a_f6", "pwm_a_a",
>> +};
>> +
>> +static const char * const pwm_b_groups[] = {
>> +	"pwm_b_x", "pwm_b_f", "pwm_b_a",
>> +};
>> +
>> +static const char * const pwm_c_groups[] = {
>> +	"pwm_c_x", "pwm_c_f3", "pwm_c_f8", "pwm_c_a",
>> +};
>> +
>> +static const char * const pwm_d_groups[] = {
>> +	"pwm_d_x15", "pwm_d_x13", "pwm_d_x10", "pwm_d_f",
>> +};
>> +
>> +static const char * const pwm_e_groups[] = {
>> +	"pwm_e_p", "pwm_e_x16", "pwm_e_x14", "pwm_e_x2", "pwm_e_f",
>> +	"pwm_e_a",
>> +};
>> +
>> +static const char * const pwm_f_groups[] = {
>> +	"pwm_f_b", "pwm_f_x", "pwm_f_f4", "pwm_f_f12",
>> +};
>> +
>> +static const char * const pwm_a_hiz_groups[] = {
>> +	"pwm_a_hiz_f8", "pwm_a_hiz_f10", "pwm_a_hiz_f6",
>> +};
>> +
>> +static const char * const pwm_b_hiz_groups[] = {
>> +	"pwm_b_hiz",
>> +};
>> +
>> +static const char * const pwm_c_hiz_groups[] = {
>> +	"pwm_c_hiz",
>> +};
>> +
>> +static const char * const spif_groups[] = {
>> +	"spif_mo", "spif_mi", "spif_wp_n", "spif_hold_n", "spif_clk",
>> +	"spif_cs",
>> +};
>> +
>> +static const char * const sdcard_groups[] = {
>> +	"sdcard_d0_b", "sdcard_d1_b", "sdcard_d2_b", "sdcard_d3_b",
>> +	"sdcard_clk_b", "sdcard_cmd_b",
>> +
>> +	"sdcard_d0_x", "sdcard_d1_x", "sdcard_d2_x", "sdcard_d3_x",
>> +	"sdcard_clk_x", "sdcard_cmd_x",
>> +};
>> +
>> +static const char * const tdm_a_groups[] = {
>> +	"tdm_a_din0", "tdm_a_din1",  "tdm_a_fs", "tdm_a_sclk",
>> +	"tdm_a_slv_fs", "tdm_a_slv_sclk", "tdm_a_dout0", "tdm_a_dout1",
>> +};
>> +
>> +static const char * const uart_a_groups[] = {
>> +	"uart_a_tx", "uart_a_rx", "uart_a_cts", "uart_a_rts",
>> +};
>> +
>> +static const char * const uart_b_groups[] = {
>> +	"uart_b_tx_x", "uart_b_rx_x", "uart_b_tx_f", "uart_b_rx_f",
>> +};
>> +
>> +static const char * const uart_c_groups[] = {
>> +	"uart_c_tx_x0", "uart_c_rx_x1", "uart_c_cts", "uart_c_rts",
>> +	"uart_c_tx_x15", "uart_c_rx_x16",
>> +};
>> +
>> +static const char * const i2c0_groups[] = {
>> +	"i2c0_sck_f11", "i2c0_sda_f12", "i2c0_sck_f9", "i2c0_sda_f10",
>> +};
>> +
>> +static const char * const i2c1_groups[] = {
>> +	"i2c1_sda_x", "i2c1_sck_x", "i2c1_sda_a", "i2c1_sck_a",
>> +};
>> +
>> +static const char * const i2c2_groups[] = {
>> +	"i2c2_sck_x0", "i2c2_sda_x1", "i2c2_sck_x15", "i2c2_sda_x16",
>> +	"i2c2_sck_a4", "i2c2_sda_a5", "i2c2_sck_a8", "i2c2_sda_a9",
>> +};
>> +
>> +static const char * const i2c3_groups[] = {
>> +	"i2c3_sck_x", "i2c3_sda_x", "i2c3_sck_f", "i2c3_sda_f",
>> +};
>> +
>> +static const char * const i2c_slave_groups[] = {
>> +	"i2c_slave_sda_a", "i2c_slave_sck_a",
>> +	"i2c_slave_sda_f", "i2c_slave_sck_f",
>> +};
>> +
>> +static const char * const spi_a_groups[] = {
>> +	"spi_a_mosi_x2", "spi_a_ss0_x3", "spi_a_sclk_x4", "spi_a_miso_x5",
>> +	"spi_a_mosi_x7", "spi_a_miso_x8", "spi_a_ss0_x9", "spi_a_sclk_x10",
>> +
>> +	"spi_a_mosi_a", "spi_a_miso_a", "spi_a_ss0_a", "spi_a_sclk_a",
>> +};
>> +
>> +static const char * const pdm_groups[] = {
>> +	"pdm_din0_x", "pdm_din1_x", "pdm_din2_x", "pdm_dclk_x", "pdm_din2_a",
>> +	"pdm_din1_a", "pdm_din0_a", "pdm_dclk",
>> +};
>> +
>> +static const char * const gen_clk_groups[] = {
>> +	"gen_clk_x", "gen_clk_f8", "gen_clk_f10", "gen_clk_a",
>> +};
>> +
>> +static const char * const remote_input_groups[] = {
>> +	"remote_input_f",
>> +	"remote_input_a",
>> +};
>> +
>> +static const char * const jtag_a_groups[] = {
>> +	"jtag_a_clk", "jtag_a_tms", "jtag_a_tdi", "jtag_a_tdo",
>> +};
>> +
>> +static const char * const clk_32k_in_groups[] = {
>> +	"clk_32k_in",
>> +};
>> +
>> +static const char * const remote_out_groups[] = {
>> +	"remote_out",
>> +};
>> +
>> +static const char * const spdif_in_groups[] = {
>> +	"spdif_in_f6", "spdif_in_f7",
>> +};
>> +
>> +static const char * const sw_groups[] = {
>> +	"swclk", "swdio",
>> +};
>> +
>> +static const char * const clk25_groups[] = {
>> +	"clk_25",
>> +};
>> +
>> +static const char * const cec_a_groups[] = {
>> +	"cec_a",
>> +};
>> +
>> +static const char * const cec_b_groups[] = {
>> +	"cec_b",
>> +};
>> +
>> +static const char * const clk12_24_groups[] = {
>> +	"clk12_24",
>> +};
>> +
>> +static const char * const mclk_0_groups[] = {
>> +	"mclk_0",
>> +};
>> +
>> +static const char * const tdm_b_groups[] = {
>> +	"tdm_b_din0", "tdm_b_din1", "tdm_b_din2",
>> +	"tdm_b_sclk", "tdm_b_fs", "tdm_b_dout0", "tdm_b_dout1",
>> +	"tdm_b_dout2", "tdm_b_dout3", "tdm_b_dout4", "tdm_b_dout5",
>> +	"tdm_b_slv_sclk", "tdm_b_slv_fs",
>> +};
>> +
>> +static const char * const mclk_vad_groups[] = {
>> +	"mclk_vad",
>> +};
>> +
>> +static const char * const tdm_vad_groups[] = {
>> +	"tdm_vad_sclk_a1", "tdm_vad_fs_a2", "tdm_vad_sclk_a5", "tdm_vad_fs_a6",
>> +};
>> +
>> +static const char * const tst_out_groups[] = {
>> +	"tst_out0", "tst_out1", "tst_out2", "tst_out3",
>> +	"tst_out4", "tst_out5", "tst_out6", "tst_out7",
>> +	"tst_out8", "tst_out9", "tst_out10", "tst_out11",
>> +};
>> +
>> +static const char * const mute_groups[] = {
>> +	"mute_key", "mute_en",
>> +};
>> +
>> +static struct meson_pmx_func meson_a1_periphs_functions[] = {
>> +	FUNCTION(gpio_periphs),
>> +	FUNCTION(psram),
>> +	FUNCTION(pwm_a),
>> +	FUNCTION(pwm_b),
>> +	FUNCTION(pwm_c),
>> +	FUNCTION(pwm_d),
>> +	FUNCTION(pwm_e),
>> +	FUNCTION(pwm_f),
>> +	FUNCTION(pwm_a_hiz),
>> +	FUNCTION(pwm_b_hiz),
>> +	FUNCTION(pwm_c_hiz),
>> +	FUNCTION(spif),
>> +	FUNCTION(sdcard),
>> +	FUNCTION(tdm_a),
>> +	FUNCTION(uart_a),
>> +	FUNCTION(uart_b),
>> +	FUNCTION(uart_c),
>> +	FUNCTION(i2c0),
>> +	FUNCTION(i2c1),
>> +	FUNCTION(i2c2),
>> +	FUNCTION(i2c3),
>> +	FUNCTION(spi_a),
>> +	FUNCTION(pdm),
>> +	FUNCTION(gen_clk),
>> +	FUNCTION(remote_input),
>> +	FUNCTION(jtag_a),
>> +	FUNCTION(clk_32k_in),
>> +	FUNCTION(remote_out),
>> +	FUNCTION(spdif_in),
>> +	FUNCTION(sw),
>> +	FUNCTION(clk25),
>> +	FUNCTION(cec_a),
>> +	FUNCTION(cec_b),
>> +	FUNCTION(clk12_24),
>> +	FUNCTION(mclk_0),
>> +	FUNCTION(tdm_b),
>> +	FUNCTION(mclk_vad),
>> +	FUNCTION(tdm_vad),
>> +	FUNCTION(tst_out),
>> +	FUNCTION(mute),
>> +};
>> +
>> +static struct meson_bank meson_a1_periphs_banks[] = {
>> +	/* name  first  last  irq  pullen  pull  dir  out  in  ds*/
>> +	BANK_DS("P",  GPIOP_0,  GPIOP_12,  0,  12, 0x3,  0,  0x4,  0,
>> +		0x2,  0,  0x1,  0,  0x0,  0,  0x5,  0),
>> +	BANK_DS("B",  GPIOB_0,    GPIOB_6,   13,  19,  0x13,  0,  0x14,  0,
>> +		0x12,  0,  0x11,  0,  0x10,  0,  0x15,  0),
>> +	BANK_DS("X",  GPIOX_0,    GPIOX_16,  20,  36,  0x23,  0,  0x24,  0,
>> +		0x22,  0,  0x21,  0,  0x20,  0,  0x25,  0),
>> +	BANK_DS("F",  GPIOF_0,    GPIOF_12,  37,  49,  0x33,  0,  0x34,  0,
>> +		0x32,  0,  0x31,  0,  0x30,  0,  0x35,  0),
>> +	BANK_DS("A",  GPIOA_0,    GPIOA_11,  50,  61,  0x43,  0,  0x44,  0,
>> +		0x42,  0,  0x41,  0,  0x40,  0,  0x45,  0),
>> +};
>> +
>> +static struct meson_pmx_bank meson_a1_periphs_pmx_banks[] = {
>> +	/*  name	 first	    lask    reg	offset  */
>> +	BANK_PMX("P",    GPIOP_0, GPIOP_12, 0x0, 0),
>> +	BANK_PMX("B",    GPIOB_0, GPIOB_6,  0x2, 0),
>> +	BANK_PMX("X",    GPIOX_0, GPIOX_16, 0x3, 0),
>> +	BANK_PMX("F",    GPIOF_0, GPIOF_12, 0x6, 0),
>> +	BANK_PMX("A",    GPIOA_0, GPIOA_11, 0x8, 0),
>> +};
>> +
>> +static struct meson_axg_pmx_data meson_a1_periphs_pmx_banks_data = {
>> +	.pmx_banks	= meson_a1_periphs_pmx_banks,
>> +	.num_pmx_banks	= ARRAY_SIZE(meson_a1_periphs_pmx_banks),
>> +};
>> +
>> +static struct meson_pinctrl_data meson_a1_periphs_pinctrl_data = {
>> +	.name		= "periphs-banks",
>> +	.pins		= meson_a1_periphs_pins,
>> +	.groups		= meson_a1_periphs_groups,
>> +	.funcs		= meson_a1_periphs_functions,
>> +	.banks		= meson_a1_periphs_banks,
>> +	.num_pins	= ARRAY_SIZE(meson_a1_periphs_pins),
>> +	.num_groups	= ARRAY_SIZE(meson_a1_periphs_groups),
>> +	.num_funcs	= ARRAY_SIZE(meson_a1_periphs_functions),
>> +	.num_banks	= ARRAY_SIZE(meson_a1_periphs_banks),
>> +	.pmx_ops	= &meson_axg_pmx_ops,
>> +	.pmx_data	= &meson_a1_periphs_pmx_banks_data,
>> +	.reg_layout	= A1_LAYOUT,
>> +};
>> +
>> +static const struct of_device_id meson_a1_pinctrl_dt_match[] = {
>> +	{
>> +		.compatible = "amlogic,meson-a1-periphs-pinctrl",
>> +		.data = &meson_a1_periphs_pinctrl_data,
>> +	},
>> +	{ },
>> +};
>> +
>> +static struct platform_driver meson_a1_pinctrl_driver = {
>> +	.probe  = meson_pinctrl_probe,
>> +	.driver = {
>> +		.name	= "meson-a1-pinctrl",
>> +		.of_match_table = meson_a1_pinctrl_dt_match,
>> +	},
>> +};
>> +
>> +builtin_platform_driver(meson_a1_pinctrl_driver);
>> diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
>> index 8bba9d0..885b89d 100644
>> --- a/drivers/pinctrl/meson/pinctrl-meson.c
>> +++ b/drivers/pinctrl/meson/pinctrl-meson.c
>> @@ -688,8 +688,12 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
>>  
>>  	pc->reg_ds = meson_map_resource(pc, gpio_np, "ds");
>>  	if (IS_ERR(pc->reg_ds)) {
>> -		dev_dbg(pc->dev, "ds registers not found - skipping\n");
>> -		pc->reg_ds = NULL;
>> +		if (pc->data->reg_layout == A1_LAYOUT) {
> 
> If the ds_reg is not used in A1_LAYOUT, simply avoid mapping it and mark
> it unneeded for A1 SoCs in the bindings instead.
> 
>> +			pc->reg_ds = pc->reg_pullen;
>> +		} else {
>> +			dev_dbg(pc->dev, "ds registers not found - skipping\n");
>> +			pc->reg_ds = NULL;
>> +		}
>>  	}
>>  
>>  	return 0;
>> diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
>> index c696f32..3d0c58d 100644
>> --- a/drivers/pinctrl/meson/pinctrl-meson.h
>> +++ b/drivers/pinctrl/meson/pinctrl-meson.h
>> @@ -80,6 +80,14 @@ enum meson_pinconf_drv {
>>  };
>>  
>>  /**
>> + * enum meson_reg_layout - identify two types of reg layout
>> + */
>> +enum meson_reg_layout {
>> +	LEGACY_LAYOUT,
>> +	A1_LAYOUT,
>> +};
>> +
>> +/**
>>   * struct meson bank
>>   *
>>   * @name:	bank name
>> @@ -114,6 +122,7 @@ struct meson_pinctrl_data {
>>  	unsigned int num_banks;
>>  	const struct pinmux_ops *pmx_ops;
>>  	void *pmx_data;
>> +	unsigned int reg_layout;
>>  };
>>  
>>  struct meson_pinctrl {
>>
> 
> Apart that look good to me,
> 
> Neil
> 
> .
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/3] pinctrl: meson-a1: add pinctrl driver for Meson A1 Soc
  2019-09-17  9:29   ` Jerome Brunet
@ 2019-09-17 11:51     ` Qianggui Song
  2019-09-17 14:07       ` Jerome Brunet
  0 siblings, 1 reply; 15+ messages in thread
From: Qianggui Song @ 2019-09-17 11:51 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Linus Walleij, linux-gpio, Xingyu Chen, Jianxin Pan,
	Neil Armstrong, Kevin Hilman, Martin Blumenstingl, Carlo Caione,
	Rob Herring, Hanjie Lin, Mark Rutland, linux-arm-kernel,
	linux-amlogic, linux-kernel

Hi, Jerome
    Thanks for your review

On 2019/9/17 17:29, Jerome Brunet wrote:
> 
> On Tue 17 Sep 2019 at 08:07, Qianggui Song <qianggui.song@amlogic.com> wrote:
> 
>> Add pinctrl driver for Meson A1 Soc which share the same register layout of
>> pinmux with previous Meson-G12A, however there is difference for gpio
>> and pin config register in A1. The register layout is as below:
>>
>> /* first bank */	      /* addr */
>> - P_PADCTRL_GPIOP_I         base + 0x00 << 2
>> - P_PADCTRL_GPIOP_O         base + 0x01 << 2
>> - P_PADCTRL_GPIOP_OEN       base + 0x02 << 2
>> - P_PADCTRL_GPIOP_PULL_EN   base + 0x03 << 2
>> - P_PADCTRL_GPIOP_PULL_UP   base + 0x04 << 2
>> - P_PADCTRL_GPIOP_DS        base + 0x05 << 2
>>
>> /* second bank */
>> - P_PADCTRL_GPIOB_I         base + 0x10 << 2
>> - P_PADCTRL_GPIOB_O         base + 0x11 << 2
>> - P_PADCTRL_GPIOB_OEN       base + 0x12 << 2
>> - P_PADCTRL_GPIOB_PULL_EN   base + 0x13 << 2
>> - P_PADCTRL_GPIOB_PULL_UP   base + 0x14 << 2
>> - P_PADCTRL_GPIOB_DS        base + 0x15 << 2
>>
>> Each bank contains at least 6 registers to be configured, if one bank has
>> more than 16 gpios, an extra P_PADCTRL_GPIO[X]_DS_EXT is included. Between
>> two adjacent P_PADCTRL_GPIO[X]_I, there is an offset 0x10, that is to say,
>> for third bank, the offsets will be 0x20,0x21,0x22,0x23,0x24,0x25 according
>> to above register layout.
>>
>> Current Meson pinctrl driver can cover such change by using base address of
>> GPIO as that of drive-strength. While simply giving reg_ds = reg_pullen
>> make wrong value to reg_ds for Soc that not support drive-strength like AXG
>> . Here a private data used to identify register layout is introduced.
>>
>> Signed-off-by: Qianggui Song <qianggui.song@amlogic.com>
>> Signed-off-by: Xingyu Chen <xingyu.chen@amlogic.com>
>> Signed-off-by: Jianxin Pan <jianxin.pan@amlogic.com>
>> ---
>>  drivers/pinctrl/meson/Kconfig            |   6 +
>>  drivers/pinctrl/meson/Makefile           |   1 +
>>  drivers/pinctrl/meson/pinctrl-meson-a1.c | 942 +++++++++++++++++++++++++++++++
>>  drivers/pinctrl/meson/pinctrl-meson.c    |   8 +-
>>  drivers/pinctrl/meson/pinctrl-meson.h    |   9 +
>>  5 files changed, 964 insertions(+), 2 deletions(-)
>>  create mode 100644 drivers/pinctrl/meson/pinctrl-meson-a1.c
>>
>> diff --git a/drivers/pinctrl/meson/Kconfig b/drivers/pinctrl/meson/Kconfig
>> index df55f61..3cb1191 100644
>> --- a/drivers/pinctrl/meson/Kconfig
>> +++ b/drivers/pinctrl/meson/Kconfig
>> @@ -54,4 +54,10 @@ config PINCTRL_MESON_G12A
>>  	select PINCTRL_MESON_AXG_PMX
>>  	default y
>>  
>> +config PINCTRL_MESON_A1
>> +	bool "Meson a1 Soc pinctrl driver"
>> +	depends on ARM64
>> +	select PINCTRL_MESON_AXG_PMX
>> +	default y
>> +
>>  endif
>> diff --git a/drivers/pinctrl/meson/Makefile b/drivers/pinctrl/meson/Makefile
>> index a69c565..1a5bffe 100644
>> --- a/drivers/pinctrl/meson/Makefile
>> +++ b/drivers/pinctrl/meson/Makefile
>> @@ -8,3 +8,4 @@ obj-$(CONFIG_PINCTRL_MESON_GXL) += pinctrl-meson-gxl.o
>>  obj-$(CONFIG_PINCTRL_MESON_AXG_PMX) += pinctrl-meson-axg-pmx.o
>>  obj-$(CONFIG_PINCTRL_MESON_AXG) += pinctrl-meson-axg.o
>>  obj-$(CONFIG_PINCTRL_MESON_G12A) += pinctrl-meson-g12a.o
>> +obj-$(CONFIG_PINCTRL_MESON_A1) += pinctrl-meson-a1.o
>> diff --git a/drivers/pinctrl/meson/pinctrl-meson-a1.c b/drivers/pinctrl/meson/pinctrl-meson-a1.c
>> new file mode 100644
>> index 0000000..f3a88f1
>> --- /dev/null
>> +++ b/drivers/pinctrl/meson/pinctrl-meson-a1.c
>> @@ -0,0 +1,942 @@
>> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>> +/*
>> + * Pin controller and GPIO driver for Amlogic Meson A1 SoC.
>> + *
>> + * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
>> + * Author: Qianggui Song <qianggui.song@amlogic.com>
>> + */
>> +
>> +#include <dt-bindings/gpio/meson-a1-gpio.h>
>> +#include "pinctrl-meson.h"
>> +#include "pinctrl-meson-axg-pmx.h"
>> +
>> +static const struct pinctrl_pin_desc meson_a1_periphs_pins[] = {
>> +	MESON_PIN(GPIOP_0),
>> +	MESON_PIN(GPIOP_1),
>> +	MESON_PIN(GPIOP_2),
>> +	MESON_PIN(GPIOP_3),
>> +	MESON_PIN(GPIOP_4),
>> +	MESON_PIN(GPIOP_5),
>> +	MESON_PIN(GPIOP_6),
>> +	MESON_PIN(GPIOP_7),
>> +	MESON_PIN(GPIOP_8),
>> +	MESON_PIN(GPIOP_9),
>> +	MESON_PIN(GPIOP_10),
>> +	MESON_PIN(GPIOP_11),
>> +	MESON_PIN(GPIOP_12),
>> +	MESON_PIN(GPIOB_0),
>> +	MESON_PIN(GPIOB_1),
>> +	MESON_PIN(GPIOB_2),
>> +	MESON_PIN(GPIOB_3),
>> +	MESON_PIN(GPIOB_4),
>> +	MESON_PIN(GPIOB_5),
>> +	MESON_PIN(GPIOB_6),
>> +	MESON_PIN(GPIOX_0),
>> +	MESON_PIN(GPIOX_1),
>> +	MESON_PIN(GPIOX_2),
>> +	MESON_PIN(GPIOX_3),
>> +	MESON_PIN(GPIOX_4),
>> +	MESON_PIN(GPIOX_5),
>> +	MESON_PIN(GPIOX_6),
>> +	MESON_PIN(GPIOX_7),
>> +	MESON_PIN(GPIOX_8),
>> +	MESON_PIN(GPIOX_9),
>> +	MESON_PIN(GPIOX_10),
>> +	MESON_PIN(GPIOX_11),
>> +	MESON_PIN(GPIOX_12),
>> +	MESON_PIN(GPIOX_13),
>> +	MESON_PIN(GPIOX_14),
>> +	MESON_PIN(GPIOX_15),
>> +	MESON_PIN(GPIOX_16),
>> +	MESON_PIN(GPIOF_0),
>> +	MESON_PIN(GPIOF_1),
>> +	MESON_PIN(GPIOF_2),
>> +	MESON_PIN(GPIOF_3),
>> +	MESON_PIN(GPIOF_4),
>> +	MESON_PIN(GPIOF_5),
>> +	MESON_PIN(GPIOF_6),
>> +	MESON_PIN(GPIOF_7),
>> +	MESON_PIN(GPIOF_8),
>> +	MESON_PIN(GPIOF_9),
>> +	MESON_PIN(GPIOF_10),
>> +	MESON_PIN(GPIOF_11),
>> +	MESON_PIN(GPIOF_12),
>> +	MESON_PIN(GPIOA_0),
>> +	MESON_PIN(GPIOA_1),
>> +	MESON_PIN(GPIOA_2),
>> +	MESON_PIN(GPIOA_3),
>> +	MESON_PIN(GPIOA_4),
>> +	MESON_PIN(GPIOA_5),
>> +	MESON_PIN(GPIOA_6),
>> +	MESON_PIN(GPIOA_7),
>> +	MESON_PIN(GPIOA_8),
>> +	MESON_PIN(GPIOA_9),
>> +	MESON_PIN(GPIOA_10),
>> +	MESON_PIN(GPIOA_11),
>> +};
>> +
>> +/* psram */
>> +static const unsigned int psram_clkn_pins[]		= { GPIOP_0 };
>> +static const unsigned int psram_clkp_pins[]		= { GPIOP_1 };
>> +static const unsigned int psram_ce_n_pins[]		= { GPIOP_2 };
>> +static const unsigned int psram_rst_n_pins[]		= { GPIOP_3 };
>> +static const unsigned int psram_adq0_pins[]		= { GPIOP_4 };
>> +static const unsigned int psram_adq1_pins[]		= { GPIOP_5 };
>> +static const unsigned int psram_adq2_pins[]		= { GPIOP_6 };
>> +static const unsigned int psram_adq3_pins[]		= { GPIOP_7 };
>> +static const unsigned int psram_adq4_pins[]		= { GPIOP_8 };
>> +static const unsigned int psram_adq5_pins[]		= { GPIOP_9 };
>> +static const unsigned int psram_adq6_pins[]		= { GPIOP_10 };
>> +static const unsigned int psram_adq7_pins[]		= { GPIOP_11 };
>> +static const unsigned int psram_dqs_dm_pins[]		= { GPIOP_12 };
>> +
>> +/* sdcard */
>> +static const unsigned int sdcard_d0_b_pins[]		= { GPIOB_0 };
>> +static const unsigned int sdcard_d1_b_pins[]		= { GPIOB_1 };
>> +static const unsigned int sdcard_d2_b_pins[]		= { GPIOB_2 };
>> +static const unsigned int sdcard_d3_b_pins[]		= { GPIOB_3 };
>> +static const unsigned int sdcard_clk_b_pins[]		= { GPIOB_4 };
>> +static const unsigned int sdcard_cmd_b_pins[]		= { GPIOB_5 };
>> +
>> +static const unsigned int sdcard_d0_x_pins[]		= { GPIOX_0 };
>> +static const unsigned int sdcard_d1_x_pins[]		= { GPIOX_1 };
>> +static const unsigned int sdcard_d2_x_pins[]		= { GPIOX_2 };
>> +static const unsigned int sdcard_d3_x_pins[]		= { GPIOX_3 };
>> +static const unsigned int sdcard_clk_x_pins[]		= { GPIOX_4 };
>> +static const unsigned int sdcard_cmd_x_pins[]		= { GPIOX_5 };
>> +
>> +/* spif */
>> +static const unsigned int spif_mo_pins[]		= { GPIOB_0 };
>> +static const unsigned int spif_mi_pins[]		= { GPIOB_1 };
>> +static const unsigned int spif_wp_n_pins[]		= { GPIOB_2 };
>> +static const unsigned int spif_hold_n_pins[]		= { GPIOB_3 };
>> +static const unsigned int spif_clk_pins[]		= { GPIOB_4 };
>> +static const unsigned int spif_cs_pins[]		= { GPIOB_5 };
>> +
>> +/* i2c0 */
>> +static const unsigned int i2c0_sck_f9_pins[]		= { GPIOF_9 };
>> +static const unsigned int i2c0_sda_f10_pins[]		= { GPIOF_10 };
>> +static const unsigned int i2c0_sck_f11_pins[]		= { GPIOF_11 };
>> +static const unsigned int i2c0_sda_f12_pins[]		= { GPIOF_12 };
>> +
>> +/* i2c1 */
>> +static const unsigned int i2c1_sda_x_pins[]		= { GPIOX_9 };
>> +static const unsigned int i2c1_sck_x_pins[]		= { GPIOX_10 };
>> +static const unsigned int i2c1_sda_a_pins[]		= { GPIOA_10 };
>> +static const unsigned int i2c1_sck_a_pins[]		= { GPIOA_11 };
>> +
>> +/* i2c2 */
>> +static const unsigned int i2c2_sck_x0_pins[]		= { GPIOX_0 };
>> +static const unsigned int i2c2_sda_x1_pins[]		= { GPIOX_1 };
>> +static const unsigned int i2c2_sck_x15_pins[]		= { GPIOX_15 };
>> +static const unsigned int i2c2_sda_x16_pins[]		= { GPIOX_16 };
>> +static const unsigned int i2c2_sck_a4_pins[]		= { GPIOA_4 };
>> +static const unsigned int i2c2_sda_a5_pins[]		= { GPIOA_5 };
>> +static const unsigned int i2c2_sck_a8_pins[]		= { GPIOA_8 };
>> +static const unsigned int i2c2_sda_a9_pins[]		= { GPIOA_9 };
>> +
>> +/* i2c3 */
>> +static const unsigned int i2c3_sck_f_pins[]		= { GPIOF_4 };
>> +static const unsigned int i2c3_sda_f_pins[]		= { GPIOF_5 };
>> +static const unsigned int i2c3_sck_x_pins[]		= { GPIOX_11 };
>> +static const unsigned int i2c3_sda_x_pins[]		= { GPIOX_12 };
>> +
>> +/* i2c slave */
>> +static const unsigned int i2c_slave_sck_a_pins[]	= { GPIOA_10 };
>> +static const unsigned int i2c_slave_sda_a_pins[]	= { GPIOA_11 };
>> +static const unsigned int i2c_slave_sck_f_pins[]	= { GPIOF_11 };
>> +static const unsigned int i2c_slave_sda_f_pins[]	= { GPIOF_12 };
>> +
>> +/* uart_a */
>> +static const unsigned int uart_a_tx_pins[]		= { GPIOX_11 };
>> +static const unsigned int uart_a_rx_pins[]		= { GPIOX_12 };
>> +static const unsigned int uart_a_cts_pins[]		= { GPIOX_13 };
>> +static const unsigned int uart_a_rts_pins[]		= { GPIOX_14 };
>> +
>> +/* uart_b */
>> +static const unsigned int uart_b_tx_x_pins[]		= { GPIOX_7 };
>> +static const unsigned int uart_b_rx_x_pins[]		= { GPIOX_8 };
>> +static const unsigned int uart_b_tx_f_pins[]		= { GPIOF_0 };
>> +static const unsigned int uart_b_rx_f_pins[]		= { GPIOF_1 };
>> +
>> +/* uart_c */
>> +static const unsigned int uart_c_tx_x0_pins[]		= { GPIOX_0 };
>> +static const unsigned int uart_c_rx_x1_pins[]		= { GPIOX_1 };
>> +static const unsigned int uart_c_cts_pins[]		= { GPIOX_2 };
>> +static const unsigned int uart_c_rts_pins[]		= { GPIOX_3 };
>> +static const unsigned int uart_c_tx_x15_pins[]		= { GPIOX_15 };
>> +static const unsigned int uart_c_rx_x16_pins[]		= { GPIOX_16 };
>> +
>> +/* pmw_a */
>> +static const unsigned int pwm_a_x6_pins[]		= { GPIOX_6 };
>> +static const unsigned int pwm_a_x7_pins[]		= { GPIOX_7 };
>> +static const unsigned int pwm_a_f6_pins[]		= { GPIOF_6 };
>> +static const unsigned int pwm_a_f10_pins[]		= { GPIOF_10 };
>> +static const unsigned int pwm_a_a_pins[]		= { GPIOA_5 };
>> +
>> +/* pmw_b */
>> +static const unsigned int pwm_b_x_pins[]		= { GPIOX_8 };
>> +static const unsigned int pwm_b_f_pins[]		= { GPIOF_7 };
>> +static const unsigned int pwm_b_a_pins[]		= { GPIOA_11 };
>> +
>> +/* pmw_c */
>> +static const unsigned int pwm_c_x_pins[]		= { GPIOX_9 };
>> +static const unsigned int pwm_c_f3_pins[]		= { GPIOF_3 };
>> +static const unsigned int pwm_c_f8_pins[]		= { GPIOF_8 };
>> +static const unsigned int pwm_c_a_pins[]		= { GPIOA_10 };
>> +
>> +/* pwm_d */
>> +static const unsigned int pwm_d_x10_pins[]		= { GPIOX_10 };
>> +static const unsigned int pwm_d_x13_pins[]		= { GPIOX_13 };
>> +static const unsigned int pwm_d_x15_pins[]		= { GPIOX_15 };
>> +static const unsigned int pwm_d_f_pins[]		= { GPIOF_11 };
>> +
>> +/* pwm_e */
>> +static const unsigned int pwm_e_p_pins[]		= { GPIOP_3 };
>> +static const unsigned int pwm_e_x2_pins[]		= { GPIOX_2 };
>> +static const unsigned int pwm_e_x14_pins[]		= { GPIOX_14 };
>> +static const unsigned int pwm_e_x16_pins[]		= { GPIOX_16 };
>> +static const unsigned int pwm_e_f_pins[]		= { GPIOF_3 };
>> +static const unsigned int pwm_e_a_pins[]		= { GPIOA_0 };
>> +
>> +/* pwm_f */
>> +static const unsigned int pwm_f_b_pins[]		= { GPIOB_6 };
>> +static const unsigned int pwm_f_x_pins[]		= { GPIOX_3 };
>> +static const unsigned int pwm_f_f4_pins[]		= { GPIOF_4 };
>> +static const unsigned int pwm_f_f12_pins[]		= { GPIOF_12 };
>> +
>> +/* pwm_a_hiz */
>> +static const unsigned int pwm_a_hiz_f8_pins[]		= { GPIOF_8 };
>> +static const unsigned int pwm_a_hiz_f10_pins[]		= { GPIOF_10 };
>> +static const unsigned int pmw_a_hiz_f6_pins[]		= { GPIOF_6 };
>> +
>> +/* pwm_b_hiz */
>> +static const unsigned int pwm_b_hiz_pins[]		= { GPIOF_7 };
>> +
>> +/* pmw_c_hiz */
>> +static const unsigned int pwm_c_hiz_pins[]		= { GPIOF_8 };
>> +
>> +/* tdm_a */
>> +static const unsigned int tdm_a_dout1_pins[]		= { GPIOX_7 };
>> +static const unsigned int tdm_a_dout0_pins[]		= { GPIOX_8 };
>> +static const unsigned int tdm_a_fs_pins[]		= { GPIOX_9 };
>> +static const unsigned int tdm_a_sclk_pins[]		= { GPIOX_10 };
>> +static const unsigned int tdm_a_din1_pins[]		= { GPIOX_7 };
>> +static const unsigned int tdm_a_din0_pins[]		= { GPIOX_8 };
>> +static const unsigned int tdm_a_slv_fs_pins[]		= { GPIOX_9 };
>> +static const unsigned int tdm_a_slv_sclk_pins[]		= { GPIOX_10 };
>> +
>> +/* spi_a */
>> +static const unsigned int spi_a_mosi_x2_pins[]		= { GPIOX_2 };
>> +static const unsigned int spi_a_ss0_x3_pins[]		= { GPIOX_3 };
>> +static const unsigned int spi_a_sclk_x4_pins[]		= { GPIOX_4 };
>> +static const unsigned int spi_a_miso_x5_pins[]		= { GPIOX_5 };
>> +static const unsigned int spi_a_mosi_x7_pins[]		= { GPIOX_7 };
>> +static const unsigned int spi_a_miso_x8_pins[]		= { GPIOX_8 };
>> +static const unsigned int spi_a_ss0_x9_pins[]		= { GPIOX_9 };
>> +static const unsigned int spi_a_sclk_x10_pins[]		= { GPIOX_10 };
>> +
>> +static const unsigned int spi_a_mosi_a_pins[]		= { GPIOA_6 };
>> +static const unsigned int spi_a_miso_a_pins[]		= { GPIOA_7 };
>> +static const unsigned int spi_a_ss0_a_pins[]		= { GPIOA_8 };
>> +static const unsigned int spi_a_sclk_a_pins[]		= { GPIOA_9 };
>> +
>> +/* pdm */
>> +static const unsigned int pdm_din0_x_pins[]		= { GPIOX_7 };
>> +static const unsigned int pdm_din1_x_pins[]		= { GPIOX_8 };
>> +static const unsigned int pdm_din2_x_pins[]		= { GPIOX_9 };
>> +static const unsigned int pdm_dclk_x_pins[]		= { GPIOX_10 };
>> +
>> +static const unsigned int pdm_din2_a_pins[]		= { GPIOA_6 };
>> +static const unsigned int pdm_din1_a_pins[]		= { GPIOA_7 };
>> +static const unsigned int pdm_din0_a_pins[]		= { GPIOA_8 };
>> +static const unsigned int pdm_dclk_pins[]		= { GPIOA_9 };
>> +
>> +/* gen_clk */
>> +static const unsigned int gen_clk_x_pins[]		= { GPIOX_7 };
>> +static const unsigned int gen_clk_f8_pins[]		= { GPIOF_8 };
>> +static const unsigned int gen_clk_f10_pins[]		= { GPIOF_10 };
>> +static const unsigned int gen_clk_a_pins[]		= { GPIOA_11 };
>> +
>> +/* jtag_a */
>> +static const unsigned int jtag_a_clk_pins[]		= { GPIOF_4 };
>> +static const unsigned int jtag_a_tms_pins[]		= { GPIOF_5 };
>> +static const unsigned int jtag_a_tdi_pins[]		= { GPIOF_6 };
>> +static const unsigned int jtag_a_tdo_pins[]		= { GPIOF_7 };
>> +
>> +/* clk_32_in */
>> +static const unsigned int clk_32k_in_pins[]		= { GPIOF_2 };
>> +
>> +/* ir in */
>> +static const unsigned int remote_input_f_pins[]		= { GPIOF_3 };
>> +static const unsigned int remote_input_a_pins[]		= { GPIOA_11 };
>> +
>> +/* ir out */
>> +static const unsigned int remote_out_pins[]		= { GPIOF_5 };
>> +
>> +/* spdif */
>> +static const unsigned int spdif_in_f6_pins[]		= { GPIOF_6 };
>> +static const unsigned int spdif_in_f7_pins[]		= { GPIOF_7 };
>> +
>> +/* sw */
>> +static const unsigned int swclk_pins[]			= { GPIOF_4 };
>> +static const unsigned int swdio_pins[]			= { GPIOF_5 };
>> +
>> +/* clk_25 */
>> +static const unsigned int clk25_pins[]			= { GPIOF_10 };
>> +
>> +/* cec_a */
>> +static const unsigned int cec_a_pins[]			= { GPIOF_2 };
>> +
>> +/* cec_b */
>> +static const unsigned int cec_b_pins[]			= { GPIOF_2 };
>> +
>> +/* clk12_24 */
>> +static const unsigned int clk12_24_pins[]		= { GPIOF_10 };
>> +
>> +/* mclk_0 */
>> +static const unsigned int mclk_0_pins[]			= { GPIOA_0 };
>> +
>> +/* tdm_b */
>> +static const unsigned int tdm_b_sclk_pins[]		= { GPIOA_1 };
>> +static const unsigned int tdm_b_fs_pins[]		= { GPIOA_2 };
>> +static const unsigned int tdm_b_dout0_pins[]		= { GPIOA_3 };
>> +static const unsigned int tdm_b_dout1_pins[]		= { GPIOA_4 };
>> +static const unsigned int tdm_b_dout2_pins[]		= { GPIOA_5 };
>> +static const unsigned int tdm_b_dout3_pins[]		= { GPIOA_6 };
>> +static const unsigned int tdm_b_dout4_pins[]		= { GPIOA_7 };
>> +static const unsigned int tdm_b_dout5_pins[]		= { GPIOA_8 };
>> +static const unsigned int tdm_b_slv_sclk_pins[]		= { GPIOA_5 };
>> +static const unsigned int tdm_b_slv_fs_pins[]		= { GPIOA_6 };
>> +static const unsigned int tdm_b_din0_pins[]		= { GPIOA_7 };
>> +static const unsigned int tdm_b_din1_pins[]		= { GPIOA_8 };
>> +static const unsigned int tdm_b_din2_pins[]		= { GPIOA_9 };
>> +
>> +/* mclk_vad */
>> +static const unsigned int mclk_vad_pins[]		= { GPIOA_0 };
>> +
>> +/* tdm_vad */
>> +static const unsigned int tdm_vad_sclk_a1_pins[]	= { GPIOA_1 };
>> +static const unsigned int tdm_vad_fs_a2_pins[]		= { GPIOA_2 };
>> +static const unsigned int tdm_vad_sclk_a5_pins[]	= { GPIOA_5 };
>> +static const unsigned int tdm_vad_fs_a6_pins[]		= { GPIOA_6 };
>> +
>> +/* tst_out */
>> +static const unsigned int tst_out0_pins[]		= { GPIOA_0 };
>> +static const unsigned int tst_out1_pins[]		= { GPIOA_1 };
>> +static const unsigned int tst_out2_pins[]		= { GPIOA_2 };
>> +static const unsigned int tst_out3_pins[]		= { GPIOA_3 };
>> +static const unsigned int tst_out4_pins[]		= { GPIOA_4 };
>> +static const unsigned int tst_out5_pins[]		= { GPIOA_5 };
>> +static const unsigned int tst_out6_pins[]		= { GPIOA_6 };
>> +static const unsigned int tst_out7_pins[]		= { GPIOA_7 };
>> +static const unsigned int tst_out8_pins[]		= { GPIOA_8 };
>> +static const unsigned int tst_out9_pins[]		= { GPIOA_9 };
>> +static const unsigned int tst_out10_pins[]		= { GPIOA_10 };
>> +static const unsigned int tst_out11_pins[]		= { GPIOA_11 };
>> +
>> +/* mute */
>> +static const unsigned int mute_key_pins[]		= { GPIOA_4 };
>> +static const unsigned int mute_en_pins[]		= { GPIOA_5 };
>> +
>> +static struct meson_pmx_group meson_a1_periphs_groups[] = {
>> +	GPIO_GROUP(GPIOP_0),
>> +	GPIO_GROUP(GPIOP_1),
>> +	GPIO_GROUP(GPIOP_2),
>> +	GPIO_GROUP(GPIOP_3),
>> +	GPIO_GROUP(GPIOP_4),
>> +	GPIO_GROUP(GPIOP_5),
>> +	GPIO_GROUP(GPIOP_6),
>> +	GPIO_GROUP(GPIOP_7),
>> +	GPIO_GROUP(GPIOP_8),
>> +	GPIO_GROUP(GPIOP_9),
>> +	GPIO_GROUP(GPIOP_10),
>> +	GPIO_GROUP(GPIOP_11),
>> +	GPIO_GROUP(GPIOP_12),
>> +	GPIO_GROUP(GPIOB_0),
>> +	GPIO_GROUP(GPIOB_1),
>> +	GPIO_GROUP(GPIOB_2),
>> +	GPIO_GROUP(GPIOB_3),
>> +	GPIO_GROUP(GPIOB_4),
>> +	GPIO_GROUP(GPIOB_5),
>> +	GPIO_GROUP(GPIOB_6),
>> +	GPIO_GROUP(GPIOX_0),
>> +	GPIO_GROUP(GPIOX_1),
>> +	GPIO_GROUP(GPIOX_2),
>> +	GPIO_GROUP(GPIOX_3),
>> +	GPIO_GROUP(GPIOX_4),
>> +	GPIO_GROUP(GPIOX_5),
>> +	GPIO_GROUP(GPIOX_6),
>> +	GPIO_GROUP(GPIOX_7),
>> +	GPIO_GROUP(GPIOX_8),
>> +	GPIO_GROUP(GPIOX_9),
>> +	GPIO_GROUP(GPIOX_10),
>> +	GPIO_GROUP(GPIOX_11),
>> +	GPIO_GROUP(GPIOX_12),
>> +	GPIO_GROUP(GPIOX_13),
>> +	GPIO_GROUP(GPIOX_14),
>> +	GPIO_GROUP(GPIOX_15),
>> +	GPIO_GROUP(GPIOX_16),
>> +	GPIO_GROUP(GPIOF_0),
>> +	GPIO_GROUP(GPIOF_1),
>> +	GPIO_GROUP(GPIOF_2),
>> +	GPIO_GROUP(GPIOF_3),
>> +	GPIO_GROUP(GPIOF_4),
>> +	GPIO_GROUP(GPIOF_5),
>> +	GPIO_GROUP(GPIOF_6),
>> +	GPIO_GROUP(GPIOF_7),
>> +	GPIO_GROUP(GPIOF_8),
>> +	GPIO_GROUP(GPIOF_9),
>> +	GPIO_GROUP(GPIOF_10),
>> +	GPIO_GROUP(GPIOF_11),
>> +	GPIO_GROUP(GPIOF_12),
>> +	GPIO_GROUP(GPIOA_0),
>> +	GPIO_GROUP(GPIOA_1),
>> +	GPIO_GROUP(GPIOA_2),
>> +	GPIO_GROUP(GPIOA_3),
>> +	GPIO_GROUP(GPIOA_4),
>> +	GPIO_GROUP(GPIOA_5),
>> +	GPIO_GROUP(GPIOA_6),
>> +	GPIO_GROUP(GPIOA_7),
>> +	GPIO_GROUP(GPIOA_8),
>> +	GPIO_GROUP(GPIOA_9),
>> +	GPIO_GROUP(GPIOA_10),
>> +	GPIO_GROUP(GPIOA_11),
>> +
>> +	/* bank P func1 */
>> +	GROUP(psram_clkn,		1),
>> +	GROUP(psram_clkp,		1),
>> +	GROUP(psram_ce_n,		1),
>> +	GROUP(psram_rst_n,		1),
>> +	GROUP(psram_adq0,		1),
>> +	GROUP(psram_adq1,		1),
>> +	GROUP(psram_adq2,		1),
>> +	GROUP(psram_adq3,		1),
>> +	GROUP(psram_adq4,		1),
>> +	GROUP(psram_adq5,		1),
>> +	GROUP(psram_adq6,		1),
>> +	GROUP(psram_adq7,		1),
>> +	GROUP(psram_dqs_dm,		1),
>> +
>> +	/*bank P func2 */
>> +	GROUP(pwm_e_p,			2),
>> +
>> +	/*bank B func1 */
>> +	GROUP(spif_mo,			1),
>> +	GROUP(spif_mi,			1),
>> +	GROUP(spif_wp_n,		1),
>> +	GROUP(spif_hold_n,		1),
>> +	GROUP(spif_clk,			1),
>> +	GROUP(spif_cs,			1),
>> +	GROUP(pwm_f_b,			1),
>> +
>> +	/*bank B func2 */
>> +	GROUP(sdcard_d0_b,		2),
>> +	GROUP(sdcard_d1_b,		2),
>> +	GROUP(sdcard_d2_b,		2),
>> +	GROUP(sdcard_d3_b,		2),
>> +	GROUP(sdcard_clk_b,		2),
>> +	GROUP(sdcard_cmd_b,		2),
>> +
>> +	/*bank X func1 */
>> +	GROUP(sdcard_d0_x,		1),
>> +	GROUP(sdcard_d1_x,		1),
>> +	GROUP(sdcard_d2_x,		1),
>> +	GROUP(sdcard_d3_x,		1),
>> +	GROUP(sdcard_clk_x,		1),
>> +	GROUP(sdcard_cmd_x,		1),
>> +	GROUP(pwm_a_x6,			1),
>> +	GROUP(tdm_a_dout1,		1),
>> +	GROUP(tdm_a_dout0,		1),
>> +	GROUP(tdm_a_fs,			1),
>> +	GROUP(tdm_a_sclk,		1),
>> +	GROUP(uart_a_tx,		1),
>> +	GROUP(uart_a_rx,		1),
>> +	GROUP(uart_a_cts,		1),
>> +	GROUP(uart_a_rts,		1),
>> +	GROUP(pwm_d_x15,		1),
>> +	GROUP(pwm_e_x16,		1),
>> +
>> +	/*bank X func2 */
>> +	GROUP(i2c2_sck_x0,		2),
>> +	GROUP(i2c2_sda_x1,		2),
>> +	GROUP(spi_a_mosi_x2,		2),
>> +	GROUP(spi_a_ss0_x3,		2),
>> +	GROUP(spi_a_sclk_x4,		2),
>> +	GROUP(spi_a_miso_x5,		2),
>> +	GROUP(tdm_a_din1,		2),
>> +	GROUP(tdm_a_din0,		2),
>> +	GROUP(tdm_a_slv_fs,		2),
>> +	GROUP(tdm_a_slv_sclk,		2),
>> +	GROUP(i2c3_sck_x,		2),
>> +	GROUP(i2c3_sda_x,		2),
>> +	GROUP(pwm_d_x13,		2),
>> +	GROUP(pwm_e_x14,		2),
>> +	GROUP(i2c2_sck_x15,		2),
>> +	GROUP(i2c2_sda_x16,		2),
>> +
>> +	/*bank X func3 */
>> +	GROUP(uart_c_tx_x0,		3),
>> +	GROUP(uart_c_rx_x1,		3),
>> +	GROUP(uart_c_cts,		3),
>> +	GROUP(uart_c_rts,		3),
>> +	GROUP(pdm_din0_x,		3),
>> +	GROUP(pdm_din1_x,		3),
>> +	GROUP(pdm_din2_x,		3),
>> +	GROUP(pdm_dclk_x,		3),
>> +	GROUP(uart_c_tx_x15,		3),
>> +	GROUP(uart_c_rx_x16,		3),
>> +
>> +	/*bank X func4 */
>> +	GROUP(pwm_e_x2,			4),
>> +	GROUP(pwm_f_x,			4),
>> +	GROUP(spi_a_mosi_x7,		4),
>> +	GROUP(spi_a_miso_x8,		4),
>> +	GROUP(spi_a_ss0_x9,		4),
>> +	GROUP(spi_a_sclk_x10,		4),
>> +
>> +	/*bank X func5 */
>> +	GROUP(uart_b_tx_x,		5),
>> +	GROUP(uart_b_rx_x,		5),
>> +	GROUP(i2c1_sda_x,		5),
>> +	GROUP(i2c1_sck_x,		5),
>> +
>> +	/*bank X func6 */
>> +	GROUP(pwm_a_x7,			6),
>> +	GROUP(pwm_b_x,			6),
>> +	GROUP(pwm_c_x,			6),
>> +	GROUP(pwm_d_x10,		6),
>> +
>> +	/*bank X func7 */
>> +	GROUP(gen_clk_x,		7),
>> +
>> +	/*bank F func1 */
>> +	GROUP(uart_b_tx_f,		1),
>> +	GROUP(uart_b_rx_f,		1),
>> +	GROUP(remote_input_f,		1),
>> +	GROUP(jtag_a_clk,		1),
>> +	GROUP(jtag_a_tms,		1),
>> +	GROUP(jtag_a_tdi,		1),
>> +	GROUP(jtag_a_tdo,		1),
>> +	GROUP(gen_clk_f8,		1),
>> +	GROUP(pwm_a_f10,		1),
>> +	GROUP(i2c0_sck_f11,		1),
>> +	GROUP(i2c0_sda_f12,		1),
>> +
>> +	/*bank F func2 */
>> +	GROUP(clk_32k_in,		2),
>> +	GROUP(pwm_e_f,			2),
>> +	GROUP(pwm_f_f4,			2),
>> +	GROUP(remote_out,		2),
>> +	GROUP(spdif_in_f6,		2),
>> +	GROUP(spdif_in_f7,		2),
>> +	GROUP(pwm_a_hiz_f8,		2),
>> +	GROUP(pwm_a_hiz_f10,		2),
>> +	GROUP(pwm_d_f,			2),
>> +	GROUP(pwm_f_f12,		2),
>> +
>> +	/*bank F func3 */
>> +	GROUP(pwm_c_f3,			3),
>> +	GROUP(swclk,			3),
>> +	GROUP(swdio,			3),
>> +	GROUP(pwm_a_f6,			3),
>> +	GROUP(pwm_b_f,			3),
>> +	GROUP(pwm_c_f8,			3),
>> +	GROUP(clk25,			3),
>> +	GROUP(i2c_slave_sck_f,		3),
>> +	GROUP(i2c_slave_sda_f,		3),
>> +
>> +	/*bank F func4 */
>> +	GROUP(cec_a,			4),
>> +	GROUP(i2c3_sck_f,		4),
>> +	GROUP(i2c3_sda_f,		4),
>> +	GROUP(pmw_a_hiz_f6,		4),
>> +	GROUP(pwm_b_hiz,		4),
>> +	GROUP(pwm_c_hiz,		4),
>> +	GROUP(i2c0_sck_f9,		4),
>> +	GROUP(i2c0_sda_f10,		4),
>> +
>> +	/*bank F func5 */
>> +	GROUP(cec_b,			5),
>> +	GROUP(clk12_24,			5),
>> +
>> +	/*bank F func7 */
>> +	GROUP(gen_clk_f10,		7),
>> +
>> +	/*bank A func1 */
>> +	GROUP(mclk_0,			1),
>> +	GROUP(tdm_b_sclk,		1),
>> +	GROUP(tdm_b_fs,			1),
>> +	GROUP(tdm_b_dout0,		1),
>> +	GROUP(tdm_b_dout1,		1),
>> +	GROUP(tdm_b_dout2,		1),
>> +	GROUP(tdm_b_dout3,		1),
>> +	GROUP(tdm_b_dout4,		1),
>> +	GROUP(tdm_b_dout5,		1),
>> +	GROUP(remote_input_a,		1),
>> +
>> +	/*bank A func2 */
>> +	GROUP(pwm_e_a,			2),
>> +	GROUP(tdm_b_slv_sclk,		2),
>> +	GROUP(tdm_b_slv_fs,		2),
>> +	GROUP(tdm_b_din0,		2),
>> +	GROUP(tdm_b_din1,		2),
>> +	GROUP(tdm_b_din2,		2),
>> +	GROUP(i2c1_sda_a,		2),
>> +	GROUP(i2c1_sck_a,		2),
>> +
>> +	/*bank A func3 */
>> +	GROUP(i2c2_sck_a4,		3),
>> +	GROUP(i2c2_sda_a5,		3),
>> +	GROUP(pdm_din2_a,		3),
>> +	GROUP(pdm_din1_a,		3),
>> +	GROUP(pdm_din0_a,		3),
>> +	GROUP(pdm_dclk,			3),
>> +	GROUP(pwm_c_a,			3),
>> +	GROUP(pwm_b_a,			3),
>> +
>> +	/*bank A func4 */
>> +	GROUP(pwm_a_a,			4),
>> +	GROUP(spi_a_mosi_a,		4),
>> +	GROUP(spi_a_miso_a,		4),
>> +	GROUP(spi_a_ss0_a,		4),
>> +	GROUP(spi_a_sclk_a,		4),
>> +	GROUP(i2c_slave_sck_a,		4),
>> +	GROUP(i2c_slave_sda_a,		4),
>> +
>> +	/*bank A func5 */
>> +	GROUP(mclk_vad,			5),
>> +	GROUP(tdm_vad_sclk_a1,		5),
>> +	GROUP(tdm_vad_fs_a2,		5),
>> +	GROUP(tdm_vad_sclk_a5,		5),
>> +	GROUP(tdm_vad_fs_a6,		5),
>> +	GROUP(i2c2_sck_a8,		5),
>> +	GROUP(i2c2_sda_a9,		5),
>> +
>> +	/*bank A func6 */
>> +	GROUP(tst_out0,			6),
>> +	GROUP(tst_out1,			6),
>> +	GROUP(tst_out2,			6),
>> +	GROUP(tst_out3,			6),
>> +	GROUP(tst_out4,			6),
>> +	GROUP(tst_out5,			6),
>> +	GROUP(tst_out6,			6),
>> +	GROUP(tst_out7,			6),
>> +	GROUP(tst_out8,			6),
>> +	GROUP(tst_out9,			6),
>> +	GROUP(tst_out10,		6),
>> +	GROUP(tst_out11,		6),
>> +
>> +	/*bank A func7 */
>> +	GROUP(mute_key,			7),
>> +	GROUP(mute_en,			7),
>> +	GROUP(gen_clk_a,		7),
>> +};
>> +
>> +static const char * const gpio_periphs_groups[] = {
>> +	"GPIOP_0", "GPIOP_1", "GPIOP_2", "GPIOP_3", "GPIOP_4",
>> +	"GPIOP_5", "GPIOP_6", "GPIOP_7", "GPIOP_8", "GPIOP_9",
>> +	"GPIOP_10", "GPIOP_11", "GPIOP_12",
>> +
>> +	"GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4",
>> +	"GPIOB_5", "GPIOB_6",
>> +
>> +	"GPIOX_0", "GPIOX_1", "GPIOX_2", "GPIOX_3", "GPIOX_4",
>> +	"GPIOX_5", "GPIOX_6", "GPIOX_7", "GPIOX_8", "GPIOX_9",
>> +	"GPIOX_10", "GPIOX_11", "GPIOX_12", "GPIOX_13", "GPIOX_14",
>> +	"GPIOX_15", "GPIOX_16",
>> +
>> +	"GPIOF_0", "GPIOF_1", "GPIOF_2", "GPIOF_3", "GPIOF_4",
>> +	"GPIOF_5", "GPIOF_6", "GPIOF_7", "GPIOF_8", "GPIOF_9",
>> +	"GPIOF_10", "GPIOF_11", "GPIOF_12",
>> +
>> +	"GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4",
>> +	"GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9",
>> +	"GPIOA_10", "GPIOA_11",
>> +};
>> +
>> +static const char * const psram_groups[] = {
>> +	"psram_clkn", "psram_clkp", "psram_ce_n", "psram_rst_n", "psram_adq0",
>> +	"psram_adq1", "psram_adq2", "psram_adq3", "psram_adq4", "psram_adq5",
>> +	"psram_adq6", "psram_adq7", "psram_dqs_dm",
>> +};
>> +
>> +static const char * const pwm_a_groups[] = {
>> +	"pwm_a_x6", "pwm_a_x7", "pwm_a_f10", "pwm_a_f6", "pwm_a_a",
>> +};
>> +
>> +static const char * const pwm_b_groups[] = {
>> +	"pwm_b_x", "pwm_b_f", "pwm_b_a",
>> +};
>> +
>> +static const char * const pwm_c_groups[] = {
>> +	"pwm_c_x", "pwm_c_f3", "pwm_c_f8", "pwm_c_a",
>> +};
>> +
>> +static const char * const pwm_d_groups[] = {
>> +	"pwm_d_x15", "pwm_d_x13", "pwm_d_x10", "pwm_d_f",
>> +};
>> +
>> +static const char * const pwm_e_groups[] = {
>> +	"pwm_e_p", "pwm_e_x16", "pwm_e_x14", "pwm_e_x2", "pwm_e_f",
>> +	"pwm_e_a",
>> +};
>> +
>> +static const char * const pwm_f_groups[] = {
>> +	"pwm_f_b", "pwm_f_x", "pwm_f_f4", "pwm_f_f12",
>> +};
>> +
>> +static const char * const pwm_a_hiz_groups[] = {
>> +	"pwm_a_hiz_f8", "pwm_a_hiz_f10", "pwm_a_hiz_f6",
>> +};
>> +
>> +static const char * const pwm_b_hiz_groups[] = {
>> +	"pwm_b_hiz",
>> +};
>> +
>> +static const char * const pwm_c_hiz_groups[] = {
>> +	"pwm_c_hiz",
>> +};
>> +
>> +static const char * const spif_groups[] = {
>> +	"spif_mo", "spif_mi", "spif_wp_n", "spif_hold_n", "spif_clk",
>> +	"spif_cs",
>> +};
>> +
>> +static const char * const sdcard_groups[] = {
>> +	"sdcard_d0_b", "sdcard_d1_b", "sdcard_d2_b", "sdcard_d3_b",
>> +	"sdcard_clk_b", "sdcard_cmd_b",
>> +
>> +	"sdcard_d0_x", "sdcard_d1_x", "sdcard_d2_x", "sdcard_d3_x",
>> +	"sdcard_clk_x", "sdcard_cmd_x",
>> +};
>> +
>> +static const char * const tdm_a_groups[] = {
>> +	"tdm_a_din0", "tdm_a_din1",  "tdm_a_fs", "tdm_a_sclk",
>> +	"tdm_a_slv_fs", "tdm_a_slv_sclk", "tdm_a_dout0", "tdm_a_dout1",
>> +};
>> +
>> +static const char * const uart_a_groups[] = {
>> +	"uart_a_tx", "uart_a_rx", "uart_a_cts", "uart_a_rts",
>> +};
>> +
>> +static const char * const uart_b_groups[] = {
>> +	"uart_b_tx_x", "uart_b_rx_x", "uart_b_tx_f", "uart_b_rx_f",
>> +};
>> +
>> +static const char * const uart_c_groups[] = {
>> +	"uart_c_tx_x0", "uart_c_rx_x1", "uart_c_cts", "uart_c_rts",
>> +	"uart_c_tx_x15", "uart_c_rx_x16",
>> +};
>> +
>> +static const char * const i2c0_groups[] = {
>> +	"i2c0_sck_f11", "i2c0_sda_f12", "i2c0_sck_f9", "i2c0_sda_f10",
>> +};
>> +
>> +static const char * const i2c1_groups[] = {
>> +	"i2c1_sda_x", "i2c1_sck_x", "i2c1_sda_a", "i2c1_sck_a",
>> +};
>> +
>> +static const char * const i2c2_groups[] = {
>> +	"i2c2_sck_x0", "i2c2_sda_x1", "i2c2_sck_x15", "i2c2_sda_x16",
>> +	"i2c2_sck_a4", "i2c2_sda_a5", "i2c2_sck_a8", "i2c2_sda_a9",
>> +};
>> +
>> +static const char * const i2c3_groups[] = {
>> +	"i2c3_sck_x", "i2c3_sda_x", "i2c3_sck_f", "i2c3_sda_f",
>> +};
>> +
>> +static const char * const i2c_slave_groups[] = {
>> +	"i2c_slave_sda_a", "i2c_slave_sck_a",
>> +	"i2c_slave_sda_f", "i2c_slave_sck_f",
>> +};
>> +
>> +static const char * const spi_a_groups[] = {
>> +	"spi_a_mosi_x2", "spi_a_ss0_x3", "spi_a_sclk_x4", "spi_a_miso_x5",
>> +	"spi_a_mosi_x7", "spi_a_miso_x8", "spi_a_ss0_x9", "spi_a_sclk_x10",
>> +
>> +	"spi_a_mosi_a", "spi_a_miso_a", "spi_a_ss0_a", "spi_a_sclk_a",
>> +};
>> +
>> +static const char * const pdm_groups[] = {
>> +	"pdm_din0_x", "pdm_din1_x", "pdm_din2_x", "pdm_dclk_x", "pdm_din2_a",
>> +	"pdm_din1_a", "pdm_din0_a", "pdm_dclk",
>> +};
>> +
>> +static const char * const gen_clk_groups[] = {
>> +	"gen_clk_x", "gen_clk_f8", "gen_clk_f10", "gen_clk_a",
>> +};
>> +
>> +static const char * const remote_input_groups[] = {
>> +	"remote_input_f",
>> +	"remote_input_a",
>> +};
>> +
>> +static const char * const jtag_a_groups[] = {
>> +	"jtag_a_clk", "jtag_a_tms", "jtag_a_tdi", "jtag_a_tdo",
>> +};
>> +
>> +static const char * const clk_32k_in_groups[] = {
>> +	"clk_32k_in",
>> +};
>> +
>> +static const char * const remote_out_groups[] = {
>> +	"remote_out",
>> +};
>> +
>> +static const char * const spdif_in_groups[] = {
>> +	"spdif_in_f6", "spdif_in_f7",
>> +};
>> +
>> +static const char * const sw_groups[] = {
>> +	"swclk", "swdio",
>> +};
>> +
>> +static const char * const clk25_groups[] = {
>> +	"clk_25",
>> +};
>> +
>> +static const char * const cec_a_groups[] = {
>> +	"cec_a",
>> +};
>> +
>> +static const char * const cec_b_groups[] = {
>> +	"cec_b",
>> +};
>> +
>> +static const char * const clk12_24_groups[] = {
>> +	"clk12_24",
>> +};
>> +
>> +static const char * const mclk_0_groups[] = {
>> +	"mclk_0",
>> +};
>> +
>> +static const char * const tdm_b_groups[] = {
>> +	"tdm_b_din0", "tdm_b_din1", "tdm_b_din2",
>> +	"tdm_b_sclk", "tdm_b_fs", "tdm_b_dout0", "tdm_b_dout1",
>> +	"tdm_b_dout2", "tdm_b_dout3", "tdm_b_dout4", "tdm_b_dout5",
>> +	"tdm_b_slv_sclk", "tdm_b_slv_fs",
>> +};
>> +
>> +static const char * const mclk_vad_groups[] = {
>> +	"mclk_vad",
>> +};
>> +
>> +static const char * const tdm_vad_groups[] = {
>> +	"tdm_vad_sclk_a1", "tdm_vad_fs_a2", "tdm_vad_sclk_a5", "tdm_vad_fs_a6",
>> +};
>> +
>> +static const char * const tst_out_groups[] = {
>> +	"tst_out0", "tst_out1", "tst_out2", "tst_out3",
>> +	"tst_out4", "tst_out5", "tst_out6", "tst_out7",
>> +	"tst_out8", "tst_out9", "tst_out10", "tst_out11",
>> +};
>> +
>> +static const char * const mute_groups[] = {
>> +	"mute_key", "mute_en",
>> +};
>> +
>> +static struct meson_pmx_func meson_a1_periphs_functions[] = {
>> +	FUNCTION(gpio_periphs),
>> +	FUNCTION(psram),
>> +	FUNCTION(pwm_a),
>> +	FUNCTION(pwm_b),
>> +	FUNCTION(pwm_c),
>> +	FUNCTION(pwm_d),
>> +	FUNCTION(pwm_e),
>> +	FUNCTION(pwm_f),
>> +	FUNCTION(pwm_a_hiz),
>> +	FUNCTION(pwm_b_hiz),
>> +	FUNCTION(pwm_c_hiz),
>> +	FUNCTION(spif),
>> +	FUNCTION(sdcard),
>> +	FUNCTION(tdm_a),
>> +	FUNCTION(uart_a),
>> +	FUNCTION(uart_b),
>> +	FUNCTION(uart_c),
>> +	FUNCTION(i2c0),
>> +	FUNCTION(i2c1),
>> +	FUNCTION(i2c2),
>> +	FUNCTION(i2c3),
>> +	FUNCTION(spi_a),
>> +	FUNCTION(pdm),
>> +	FUNCTION(gen_clk),
>> +	FUNCTION(remote_input),
>> +	FUNCTION(jtag_a),
>> +	FUNCTION(clk_32k_in),
>> +	FUNCTION(remote_out),
>> +	FUNCTION(spdif_in),
>> +	FUNCTION(sw),
>> +	FUNCTION(clk25),
>> +	FUNCTION(cec_a),
>> +	FUNCTION(cec_b),
>> +	FUNCTION(clk12_24),
>> +	FUNCTION(mclk_0),
>> +	FUNCTION(tdm_b),
>> +	FUNCTION(mclk_vad),
>> +	FUNCTION(tdm_vad),
>> +	FUNCTION(tst_out),
>> +	FUNCTION(mute),
>> +};
>> +
>> +static struct meson_bank meson_a1_periphs_banks[] = {
>> +	/* name  first  last  irq  pullen  pull  dir  out  in  ds*/
>> +	BANK_DS("P",  GPIOP_0,  GPIOP_12,  0,  12, 0x3,  0,  0x4,  0,
>> +		0x2,  0,  0x1,  0,  0x0,  0,  0x5,  0),
>> +	BANK_DS("B",  GPIOB_0,    GPIOB_6,   13,  19,  0x13,  0,  0x14,  0,
>> +		0x12,  0,  0x11,  0,  0x10,  0,  0x15,  0),
>> +	BANK_DS("X",  GPIOX_0,    GPIOX_16,  20,  36,  0x23,  0,  0x24,  0,
>> +		0x22,  0,  0x21,  0,  0x20,  0,  0x25,  0),
>> +	BANK_DS("F",  GPIOF_0,    GPIOF_12,  37,  49,  0x33,  0,  0x34,  0,
>> +		0x32,  0,  0x31,  0,  0x30,  0,  0x35,  0),
>> +	BANK_DS("A",  GPIOA_0,    GPIOA_11,  50,  61,  0x43,  0,  0x44,  0,
>> +		0x42,  0,  0x41,  0,  0x40,  0,  0x45,  0),
>> +};
>> +
>> +static struct meson_pmx_bank meson_a1_periphs_pmx_banks[] = {
>> +	/*  name	 first	    lask    reg	offset  */
>> +	BANK_PMX("P",    GPIOP_0, GPIOP_12, 0x0, 0),
>> +	BANK_PMX("B",    GPIOB_0, GPIOB_6,  0x2, 0),
>> +	BANK_PMX("X",    GPIOX_0, GPIOX_16, 0x3, 0),
>> +	BANK_PMX("F",    GPIOF_0, GPIOF_12, 0x6, 0),
>> +	BANK_PMX("A",    GPIOA_0, GPIOA_11, 0x8, 0),
>> +};
>> +
>> +static struct meson_axg_pmx_data meson_a1_periphs_pmx_banks_data = {
>> +	.pmx_banks	= meson_a1_periphs_pmx_banks,
>> +	.num_pmx_banks	= ARRAY_SIZE(meson_a1_periphs_pmx_banks),
>> +};
>> +
>> +static struct meson_pinctrl_data meson_a1_periphs_pinctrl_data = {
>> +	.name		= "periphs-banks",
>> +	.pins		= meson_a1_periphs_pins,
>> +	.groups		= meson_a1_periphs_groups,
>> +	.funcs		= meson_a1_periphs_functions,
>> +	.banks		= meson_a1_periphs_banks,
>> +	.num_pins	= ARRAY_SIZE(meson_a1_periphs_pins),
>> +	.num_groups	= ARRAY_SIZE(meson_a1_periphs_groups),
>> +	.num_funcs	= ARRAY_SIZE(meson_a1_periphs_functions),
>> +	.num_banks	= ARRAY_SIZE(meson_a1_periphs_banks),
>> +	.pmx_ops	= &meson_axg_pmx_ops,
>> +	.pmx_data	= &meson_a1_periphs_pmx_banks_data,
>> +	.reg_layout	= A1_LAYOUT,
>> +};
>> +
>> +static const struct of_device_id meson_a1_pinctrl_dt_match[] = {
>> +	{
>> +		.compatible = "amlogic,meson-a1-periphs-pinctrl",
>> +		.data = &meson_a1_periphs_pinctrl_data,
>> +	},
>> +	{ },
>> +};
>> +
>> +static struct platform_driver meson_a1_pinctrl_driver = {
>> +	.probe  = meson_pinctrl_probe,
>> +	.driver = {
>> +		.name	= "meson-a1-pinctrl",
>> +		.of_match_table = meson_a1_pinctrl_dt_match,
>> +	},
>> +};
>> +
>> +builtin_platform_driver(meson_a1_pinctrl_driver);
>> diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
>> index 8bba9d0..885b89d 100644
>> --- a/drivers/pinctrl/meson/pinctrl-meson.c
>> +++ b/drivers/pinctrl/meson/pinctrl-meson.c
>> @@ -688,8 +688,12 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
>>  
>>  	pc->reg_ds = meson_map_resource(pc, gpio_np, "ds");
>>  	if (IS_ERR(pc->reg_ds)) {
>> -		dev_dbg(pc->dev, "ds registers not found - skipping\n");
>> -		pc->reg_ds = NULL;
>> +		if (pc->data->reg_layout == A1_LAYOUT) {
>> +			pc->reg_ds = pc->reg_pullen;
> 
> IMO, this kind of ID based init fixup is not going to scale and will
> lead to something difficult to maintain in the end.
> 
> The way the different register sets interract with each other is already
> pretty complex to follow.
> 
> You could rework this in 2 different ways:
> #1 - Have the generic function parse all the register sets and have all
> drivers provide a specific (as in gxbb, gxl, axg, etc ...)  function to :
>  - Verify the expected sets have been provided
>  - Make assignement fixup as above if necessary
> 
> #2 - Rework the driver to have only one single register region
>  I think one of your colleague previously mentionned this was not
>  possible. It is still unclear to me why ...
> 
Appreciate your advice.  I have an idea based on #1, how about providing
only two dt parse function, one is for chips before A1(the old one),
another is for A1 and later chips that share the same layout. Assign
these two functions to their own driver.
>> +		} else {
>> +			dev_dbg(pc->dev, "ds registers not found - skipping\n");
>> +			pc->reg_ds = NULL;
>> +		}
>>  	}
>>  
>>  	return 0;
>> diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
>> index c696f32..3d0c58d 100644
>> --- a/drivers/pinctrl/meson/pinctrl-meson.h
>> +++ b/drivers/pinctrl/meson/pinctrl-meson.h
>> @@ -80,6 +80,14 @@ enum meson_pinconf_drv {
>>  };
>>  
>>  /**
>> + * enum meson_reg_layout - identify two types of reg layout
>> + */
>> +enum meson_reg_layout {
>> +	LEGACY_LAYOUT,
>> +	A1_LAYOUT,
>> +};
>> +
>> +/**
>>   * struct meson bank
>>   *
>>   * @name:	bank name
>> @@ -114,6 +122,7 @@ struct meson_pinctrl_data {
>>  	unsigned int num_banks;
>>  	const struct pinmux_ops *pmx_ops;
>>  	void *pmx_data;
>> +	unsigned int reg_layout;
>>  };
>>  
>>  struct meson_pinctrl {
> 
> .
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/3] pinctrl: meson-a1: add pinctrl driver for Meson A1 Soc
  2019-09-17 11:51     ` Qianggui Song
@ 2019-09-17 14:07       ` Jerome Brunet
  2019-09-18  6:36         ` Qianggui Song
  0 siblings, 1 reply; 15+ messages in thread
From: Jerome Brunet @ 2019-09-17 14:07 UTC (permalink / raw)
  To: Qianggui Song
  Cc: Linus Walleij, linux-gpio, Xingyu Chen, Jianxin Pan,
	Neil Armstrong, Kevin Hilman, Martin Blumenstingl, Carlo Caione,
	Rob Herring, Hanjie Lin, Mark Rutland, linux-arm-kernel,
	linux-amlogic, linux-kernel


On Tue 17 Sep 2019 at 13:51, Qianggui Song <qianggui.song@amlogic.com> wrote:
>>> diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
>>> index 8bba9d0..885b89d 100644
>>> --- a/drivers/pinctrl/meson/pinctrl-meson.c
>>> +++ b/drivers/pinctrl/meson/pinctrl-meson.c
>>> @@ -688,8 +688,12 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
>>>  
>>>  	pc->reg_ds = meson_map_resource(pc, gpio_np, "ds");
>>>  	if (IS_ERR(pc->reg_ds)) {
>>> -		dev_dbg(pc->dev, "ds registers not found - skipping\n");
>>> -		pc->reg_ds = NULL;
>>> +		if (pc->data->reg_layout == A1_LAYOUT) {
>>> +			pc->reg_ds = pc->reg_pullen;
>> 
>> IMO, this kind of ID based init fixup is not going to scale and will
>> lead to something difficult to maintain in the end.
>> 
>> The way the different register sets interract with each other is already
>> pretty complex to follow.
>> 
>> You could rework this in 2 different ways:
>> #1 - Have the generic function parse all the register sets and have all
>> drivers provide a specific (as in gxbb, gxl, axg, etc ...)  function to :
>>  - Verify the expected sets have been provided
>>  - Make assignement fixup as above if necessary
>> 
>> #2 - Rework the driver to have only one single register region
>>  I think one of your colleague previously mentionned this was not
>>  possible. It is still unclear to me why ...
>> 
> Appreciate your advice.  I have an idea based on #1, how about providing
> only two dt parse function, one is for chips before A1(the old one),
> another is for A1 and later chips that share the same layout. Assign
> these two functions to their own driver.

That's roughly the same thing as your initial proposition with function
pointer instead of IDs ... IMO, this would still be a quick fix to
address your immediate topic instead of dealing with the driver as
whole, which is my concern here.

>>> +		} else {
>>> +			dev_dbg(pc->dev, "ds registers not found - skipping\n");
>>> +			pc->reg_ds = NULL;
>>> +		}
>>>  	}
>>>  
>>>  	return 0;
>>> diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
>>> index c696f32..3d0c58d 100644
>>> --- a/drivers/pinctrl/meson/pinctrl-meson.h
>>> +++ b/drivers/pinctrl/meson/pinctrl-meson.h
>>> @@ -80,6 +80,14 @@ enum meson_pinconf_drv {
>>>  };
>>>  
>>>  /**
>>> + * enum meson_reg_layout - identify two types of reg layout
>>> + */
>>> +enum meson_reg_layout {
>>> +	LEGACY_LAYOUT,
>>> +	A1_LAYOUT,
>>> +};
>>> +
>>> +/**
>>>   * struct meson bank
>>>   *
>>>   * @name:	bank name
>>> @@ -114,6 +122,7 @@ struct meson_pinctrl_data {
>>>  	unsigned int num_banks;
>>>  	const struct pinmux_ops *pmx_ops;
>>>  	void *pmx_data;
>>> +	unsigned int reg_layout;
>>>  };
>>>  
>>>  struct meson_pinctrl {
>> 
>> .
>> 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/3] pinctrl: meson-a1: add pinctrl driver for Meson A1 Soc
  2019-09-17 14:07       ` Jerome Brunet
@ 2019-09-18  6:36         ` Qianggui Song
  2019-09-19 16:26           ` Jerome Brunet
  0 siblings, 1 reply; 15+ messages in thread
From: Qianggui Song @ 2019-09-18  6:36 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Linus Walleij, linux-gpio, Xingyu Chen, Jianxin Pan,
	Neil Armstrong, Kevin Hilman, Martin Blumenstingl, Carlo Caione,
	Rob Herring, Hanjie Lin, Mark Rutland, linux-arm-kernel,
	linux-amlogic, linux-kernel


On 2019/9/17 22:07, Jerome Brunet wrote:
> 
> On Tue 17 Sep 2019 at 13:51, Qianggui Song <qianggui.song@amlogic.com> wrote:
>>>> diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
>>>> index 8bba9d0..885b89d 100644
>>>> --- a/drivers/pinctrl/meson/pinctrl-meson.c
>>>> +++ b/drivers/pinctrl/meson/pinctrl-meson.c
>>>> @@ -688,8 +688,12 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
>>>>  
>>>>  	pc->reg_ds = meson_map_resource(pc, gpio_np, "ds");
>>>>  	if (IS_ERR(pc->reg_ds)) {
>>>> -		dev_dbg(pc->dev, "ds registers not found - skipping\n");
>>>> -		pc->reg_ds = NULL;
>>>> +		if (pc->data->reg_layout == A1_LAYOUT) {
>>>> +			pc->reg_ds = pc->reg_pullen;
>>>
>>> IMO, this kind of ID based init fixup is not going to scale and will
>>> lead to something difficult to maintain in the end.
>>>
>>> The way the different register sets interract with each other is already
>>> pretty complex to follow.
>>>
>>> You could rework this in 2 different ways:
>>> #1 - Have the generic function parse all the register sets and have all
>>> drivers provide a specific (as in gxbb, gxl, axg, etc ...)  function to :
>>>  - Verify the expected sets have been provided
>>>  - Make assignement fixup as above if necessary
>>>
>>> #2 - Rework the driver to have only one single register region
>>>  I think one of your colleague previously mentionned this was not
>>>  possible. It is still unclear to me why ...
>>>
>> Appreciate your advice.  I have an idea based on #1, how about providing
>> only two dt parse function, one is for chips before A1(the old one),
>> another is for A1 and later chips that share the same layout. Assign
>> these two functions to their own driver.
> 
> That's roughly the same thing as your initial proposition with function
> pointer instead of IDs ... IMO, this would still be a quick fix to
> address your immediate topic instead of dealing with the driver as
> whole, which is my concern here.
> 
For #1. It would be like
generic_parse_dt()
{
	1. parse all register regions (mux gpio pull pull_en ds)
	
	2. call  specific function through function pointer in
 	   meson_pinctrl_data.(each platform should have AO and EE two
           specific functions for they are not the same)
	{
		do work you mentioned above
	}
}
right ?
If that so, maybe there are a lot of duplicated codes for most Socs
share the same reg layout. So I guess five specific functions are
enough: AXG and before(ao,ee), G12A(ao,ee) and A1(will place them in
pinctrl_meson.c). Since m8 to AXG are the same register layout for both
ee and ao, G12A with new feature ds and new ao register layout.

Or I misunderstood the #1 ?
>>>> +		} else {
>>>> +			dev_dbg(pc->dev, "ds registers not found - skipping\n");
>>>> +			pc->reg_ds = NULL;
>>>> +		}
>>>>  	}
>>>>  
>>>>  	return 0;
>>>> diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
>>>> index c696f32..3d0c58d 100644
>>>> --- a/drivers/pinctrl/meson/pinctrl-meson.h
>>>> +++ b/drivers/pinctrl/meson/pinctrl-meson.h
>>>> @@ -80,6 +80,14 @@ enum meson_pinconf_drv {
>>>>  };
>>>>  
>>>>  /**
>>>> + * enum meson_reg_layout - identify two types of reg layout
>>>> + */
>>>> +enum meson_reg_layout {
>>>> +	LEGACY_LAYOUT,
>>>> +	A1_LAYOUT,
>>>> +};
>>>> +
>>>> +/**
>>>>   * struct meson bank
>>>>   *
>>>>   * @name:	bank name
>>>> @@ -114,6 +122,7 @@ struct meson_pinctrl_data {
>>>>  	unsigned int num_banks;
>>>>  	const struct pinmux_ops *pmx_ops;
>>>>  	void *pmx_data;
>>>> +	unsigned int reg_layout;
>>>>  };
>>>>  
>>>>  struct meson_pinctrl {
>>>
>>> .
>>>
> 
> .
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/3] pinctrl: meson-a1: add pinctrl driver for Meson A1 Soc
  2019-09-18  6:36         ` Qianggui Song
@ 2019-09-19 16:26           ` Jerome Brunet
  2019-09-23  7:29             ` Qianggui Song
  0 siblings, 1 reply; 15+ messages in thread
From: Jerome Brunet @ 2019-09-19 16:26 UTC (permalink / raw)
  To: Qianggui Song
  Cc: Linus Walleij, linux-gpio, Xingyu Chen, Jianxin Pan,
	Neil Armstrong, Kevin Hilman, Martin Blumenstingl, Carlo Caione,
	Rob Herring, Hanjie Lin, Mark Rutland, linux-arm-kernel,
	linux-amlogic, linux-kernel

On Wed 18 Sep 2019 at 14:36, Qianggui Song <qianggui.song@amlogic.com> wrote:

> On 2019/9/17 22:07, Jerome Brunet wrote:
>> 
>> On Tue 17 Sep 2019 at 13:51, Qianggui Song <qianggui.song@amlogic.com> wrote:
>>>>> diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
>>>>> index 8bba9d0..885b89d 100644
>>>>> --- a/drivers/pinctrl/meson/pinctrl-meson.c
>>>>> +++ b/drivers/pinctrl/meson/pinctrl-meson.c
>>>>> @@ -688,8 +688,12 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
>>>>>  
>>>>>  	pc->reg_ds = meson_map_resource(pc, gpio_np, "ds");
>>>>>  	if (IS_ERR(pc->reg_ds)) {
>>>>> -		dev_dbg(pc->dev, "ds registers not found - skipping\n");
>>>>> -		pc->reg_ds = NULL;
>>>>> +		if (pc->data->reg_layout == A1_LAYOUT) {
>>>>> +			pc->reg_ds = pc->reg_pullen;
>>>>
>>>> IMO, this kind of ID based init fixup is not going to scale and will
>>>> lead to something difficult to maintain in the end.
>>>>
>>>> The way the different register sets interract with each other is already
>>>> pretty complex to follow.
>>>>
>>>> You could rework this in 2 different ways:
>>>> #1 - Have the generic function parse all the register sets and have all
>>>> drivers provide a specific (as in gxbb, gxl, axg, etc ...)  function to :
>>>>  - Verify the expected sets have been provided
>>>>  - Make assignement fixup as above if necessary
>>>>
>>>> #2 - Rework the driver to have only one single register region
>>>>  I think one of your colleague previously mentionned this was not
>>>>  possible. It is still unclear to me why ...
>>>>
>>> Appreciate your advice.  I have an idea based on #1, how about providing
>>> only two dt parse function, one is for chips before A1(the old one),
>>> another is for A1 and later chips that share the same layout. Assign
>>> these two functions to their own driver.
>> 
>> That's roughly the same thing as your initial proposition with function
>> pointer instead of IDs ... IMO, this would still be a quick fix to
>> address your immediate topic instead of dealing with the driver as
>> whole, which is my concern here.
>> 
> For #1. It would be like
> generic_parse_dt()
> {
> 	1. parse all register regions (mux gpio pull pull_en ds)
> 	
> 	2. call  specific function through function pointer in
>  	   meson_pinctrl_data.(each platform should have AO and EE two
>            specific functions for they are not the same)
> 	{
> 		do work you mentioned above
> 	}
> }
> right ?
> If that so, maybe there are a lot of duplicated codes

Only if you make it so. Providing a callback and duplicating code are
not the same thing

> for most Socs share the same reg layout.

That's not really accurate:

So far they all have the "mux" and "gpio" region but

gxbb, gxl, axg, meson8 EE:
 has: pull, pull-en
 remap: non
 unsupported: ds

gxbb, gxl, axg, meson8 AO:
 has: pull
 remap: pull-en -> pull
 unsupported: ds

g12 and sm1 EE:
 has: pull, pull-en, ds
 remap: none

g12 and sm1 AO:
 has: ds
 remap: pull->gpio, pull_en->gpio

And now a1 chip remaps "ds" to "pull_en" ...

As said previouly all this is getting pretty difficult to follow and
maintain. Adding a proper callback for each meson pinctrl would make the
above explicit in the code ... which helps maintain thing, at least for
a while ...

Judging by the offsets between those regions, I still think one single
region would make things a whole lot simpler. If it is not possible to
map it with one single region, could you tell us why ? What non-pinctrl
related device do we have there ?

> So I guess five specific functions are
> enough: AXG and before(ao,ee), G12A(ao,ee) and A1(will place them in
> pinctrl_meson.c). Since m8 to AXG are the same register layout for both
> ee and ao, G12A with new feature ds and new ao register layout.
>
> Or I misunderstood the #1 ?
>>>>> +		} else {
>>>>> +			dev_dbg(pc->dev, "ds registers not found - skipping\n");
>>>>> +			pc->reg_ds = NULL;
>>>>> +		}
>>>>>  	}
>>>>>  
>>>>>  	return 0;
>>>>> diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
>>>>> index c696f32..3d0c58d 100644
>>>>> --- a/drivers/pinctrl/meson/pinctrl-meson.h
>>>>> +++ b/drivers/pinctrl/meson/pinctrl-meson.h
>>>>> @@ -80,6 +80,14 @@ enum meson_pinconf_drv {
>>>>>  };
>>>>>  
>>>>>  /**
>>>>> + * enum meson_reg_layout - identify two types of reg layout
>>>>> + */
>>>>> +enum meson_reg_layout {
>>>>> +	LEGACY_LAYOUT,
>>>>> +	A1_LAYOUT,
>>>>> +};
>>>>> +
>>>>> +/**
>>>>>   * struct meson bank
>>>>>   *
>>>>>   * @name:	bank name
>>>>> @@ -114,6 +122,7 @@ struct meson_pinctrl_data {
>>>>>  	unsigned int num_banks;
>>>>>  	const struct pinmux_ops *pmx_ops;
>>>>>  	void *pmx_data;
>>>>> +	unsigned int reg_layout;
>>>>>  };
>>>>>  
>>>>>  struct meson_pinctrl {
>>>>
>>>> .
>>>>
>> 
>> .
>> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/3] pinctrl: meson-a1: add pinctrl driver for Meson A1 Soc
  2019-09-19 16:26           ` Jerome Brunet
@ 2019-09-23  7:29             ` Qianggui Song
  0 siblings, 0 replies; 15+ messages in thread
From: Qianggui Song @ 2019-09-23  7:29 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Linus Walleij, linux-gpio, Xingyu Chen, Jianxin Pan,
	Neil Armstrong, Kevin Hilman, Martin Blumenstingl, Carlo Caione,
	Rob Herring, Hanjie Lin, Mark Rutland, linux-arm-kernel,
	linux-amlogic, linux-kernel



On 2019/9/20 0:26, Jerome Brunet wrote:
> On Wed 18 Sep 2019 at 14:36, Qianggui Song <qianggui.song@amlogic.com> wrote:
> 
>> On 2019/9/17 22:07, Jerome Brunet wrote:
>>>
>>> On Tue 17 Sep 2019 at 13:51, Qianggui Song <qianggui.song@amlogic.com> wrote:
>>>>>> diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
>>>>>> index 8bba9d0..885b89d 100644
>>>>>> --- a/drivers/pinctrl/meson/pinctrl-meson.c
>>>>>> +++ b/drivers/pinctrl/meson/pinctrl-meson.c
>>>>>> @@ -688,8 +688,12 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
>>>>>>  
>>>>>>  	pc->reg_ds = meson_map_resource(pc, gpio_np, "ds");
>>>>>>  	if (IS_ERR(pc->reg_ds)) {
>>>>>> -		dev_dbg(pc->dev, "ds registers not found - skipping\n");
>>>>>> -		pc->reg_ds = NULL;
>>>>>> +		if (pc->data->reg_layout == A1_LAYOUT) {
>>>>>> +			pc->reg_ds = pc->reg_pullen;
>>>>>
>>>>> IMO, this kind of ID based init fixup is not going to scale and will
>>>>> lead to something difficult to maintain in the end.
>>>>>
>>>>> The way the different register sets interract with each other is already
>>>>> pretty complex to follow.
>>>>>
>>>>> You could rework this in 2 different ways:
>>>>> #1 - Have the generic function parse all the register sets and have all
>>>>> drivers provide a specific (as in gxbb, gxl, axg, etc ...)  function to :
>>>>>  - Verify the expected sets have been provided
>>>>>  - Make assignement fixup as above if necessary
>>>>>
>>>>> #2 - Rework the driver to have only one single register region
>>>>>  I think one of your colleague previously mentionned this was not
>>>>>  possible. It is still unclear to me why ...
>>>>>
>>>> Appreciate your advice.  I have an idea based on #1, how about providing
>>>> only two dt parse function, one is for chips before A1(the old one),
>>>> another is for A1 and later chips that share the same layout. Assign
>>>> these two functions to their own driver.
>>>
>>> That's roughly the same thing as your initial proposition with function
>>> pointer instead of IDs ... IMO, this would still be a quick fix to
>>> address your immediate topic instead of dealing with the driver as
>>> whole, which is my concern here.
>>>
>> For #1. It would be like
>> generic_parse_dt()
>> {
>> 	1. parse all register regions (mux gpio pull pull_en ds)
>> 	
>> 	2. call  specific function through function pointer in
>>  	   meson_pinctrl_data.(each platform should have AO and EE two
>>            specific functions for they are not the same)
>> 	{
>> 		do work you mentioned above
>> 	}
>> }
>> right ?
>> If that so, maybe there are a lot of duplicated codes
> 
> Only if you make it so. Providing a callback and duplicating code are
> not the same thing
> 
>> for most Socs share the same reg layout.
> 
> That's not really accurate:
> 
> So far they all have the "mux" and "gpio" region but
> 
> gxbb, gxl, axg, meson8 EE:
>  has: pull, pull-en
>  remap: non
>  unsupported: ds
> 
> gxbb, gxl, axg, meson8 AO:
>  has: pull
>  remap: pull-en -> pull
>  unsupported: ds
> 
> g12 and sm1 EE:
>  has: pull, pull-en, ds
>  remap: none
> 
> g12 and sm1 AO:
>  has: ds
>  remap: pull->gpio, pull_en->gpio
> 
> And now a1 chip remaps "ds" to "pull_en" ...
> 
> As said previouly all this is getting pretty difficult to follow and
> maintain. Adding a proper callback for each meson pinctrl would make the
> above explicit in the code ... which helps maintain thing, at least for
> a while ...
> 
> Judging by the offsets between those regions, I still think one single
> region would make things a whole lot simpler. If it is not possible to
> map it with one single region, could you tell us why ? What non-pinctrl
> related device do we have there ?
>Here I mean duplicated is that m8/m8b/gxl/gxbb/axg use the same layout,
while g12a/b/sm1 are the same, so don't need to implement every Socs
parser functions just as I said below AXG type for m8/m8b/gxl/gxbb/axg,
g12a type for g12a/b/sm1, the last one is for a1. three types functions
(with ao and ee) can cover all platform. But I still consider that
providing an extra meson_a1_pasert_dt like function for a1 or later is
more simpler.

The reason why we can not use one single region for previous Socs, it'
that there is non-pinctrl related device for some Socs region.
Take an example for g12a:

#define	PREG_PAD_GPIO0_EN_N	(0xff634400 + (0x010 << 2))
#define	PREG_PAD_GPIO0_O	(0xff634400 + (0x011 << 2))
#define	PREG_PAD_GPIO0_I	(0xff634400 + (0x012 << 2))

	...continue region...

#define	PAD_PULL_UP_EN_REG5	(0xff634400 + (0x04d << 2))

	... ETH/NAND/VPU/TIMER...  a lot of no-pinctrl registers

#define	PERIPHS_PIN_MUX_0	(0xff634400 + (0x0b0 << 2))

	...continue region...

#define	PERIPHS_PIN_MUX_F	(0xff634400 + (0x0bf << 2))

	...no use region...

#define	EFUSE_CFG_LOCK		(0xff634400 + (0x0c0 << 2))

	...other EFUSE relative registers...
	...no use region...

#define	PAD_DS_REG0A		(0xff634400 + (0x0d0 << 2))

	...continue region for all ds...

#define	PAD_DS_REG5A		(0xff634400 + (0x0d6 << 2))

So from the above we can see there are lots of other registers between
gpio and ds register.When map gpio to ds region, they will bury a lot of
other registers.

>> So I guess five specific functions are
>> enough: AXG and before(ao,ee), G12A(ao,ee) and A1(will place them in
>> pinctrl_meson.c). Since m8 to AXG are the same register layout for both
>> ee and ao, G12A with new feature ds and new ao register layout.
>>
>> Or I misunderstood the #1 ?
>>>>>> +		} else {
>>>>>> +			dev_dbg(pc->dev, "ds registers not found - skipping\n");
>>>>>> +			pc->reg_ds = NULL;
>>>>>> +		}
>>>>>>  	}
>>>>>>  
>>>>>>  	return 0;
>>>>>> diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
>>>>>> index c696f32..3d0c58d 100644
>>>>>> --- a/drivers/pinctrl/meson/pinctrl-meson.h
>>>>>> +++ b/drivers/pinctrl/meson/pinctrl-meson.h
>>>>>> @@ -80,6 +80,14 @@ enum meson_pinconf_drv {
>>>>>>  };
>>>>>>  
>>>>>>  /**
>>>>>> + * enum meson_reg_layout - identify two types of reg layout
>>>>>> + */
>>>>>> +enum meson_reg_layout {
>>>>>> +	LEGACY_LAYOUT,
>>>>>> +	A1_LAYOUT,
>>>>>> +};
>>>>>> +
>>>>>> +/**
>>>>>>   * struct meson bank
>>>>>>   *
>>>>>>   * @name:	bank name
>>>>>> @@ -114,6 +122,7 @@ struct meson_pinctrl_data {
>>>>>>  	unsigned int num_banks;
>>>>>>  	const struct pinmux_ops *pmx_ops;
>>>>>>  	void *pmx_data;
>>>>>> +	unsigned int reg_layout;
>>>>>>  };
>>>>>>  
>>>>>>  struct meson_pinctrl {
>>>>>
>>>>> .
>>>>>
>>>
>>> .
>>>
> 
> .
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/3] pinctrl: add compatible for Amlogic Meson A1 pin controller
  2019-09-17  6:07 ` [PATCH 1/3] pinctrl: add compatible for Amlogic Meson A1 pin controller Qianggui Song
  2019-09-17  7:18   ` Neil Armstrong
@ 2019-09-30 22:47   ` Rob Herring
  1 sibling, 0 replies; 15+ messages in thread
From: Rob Herring @ 2019-09-30 22:47 UTC (permalink / raw)
  To: Qianggui Song
  Cc: Linus Walleij, linux-gpio, Qianggui Song, Mark Rutland,
	Hanjie Lin, Jianxin Pan, Neil Armstrong, Martin Blumenstingl,
	Kevin Hilman, linux-kernel, devicetree, linux-arm-kernel,
	Carlo Caione, linux-amlogic, Xingyu Chen, Jerome Brunet

On Tue, 17 Sep 2019 14:07:20 +0800, Qianggui Song wrote:
> Add new compatible name for Amlogic's Meson-A1 pin controller
> add a dt-binding header file which document the detail pin names.
> 
> Signed-off-by: Qianggui Song <qianggui.song@amlogic.com>
> Signed-off-by: Xingyu Chen <xingyu.chen@amlogic.com>
> Signed-off-by: Jianxin Pan <jianxin.pan@amlogic.com>
> ---
>  .../devicetree/bindings/pinctrl/meson,pinctrl.txt  |  1 +
>  include/dt-bindings/gpio/meson-a1-gpio.h           | 73 ++++++++++++++++++++++
>  2 files changed, 74 insertions(+)
>  create mode 100644 include/dt-bindings/gpio/meson-a1-gpio.h
> 

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2019-09-30 22:47 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-17  6:07 [PATCH 0/3] pinctrl: meson-a1: add pinctrl driver Qianggui Song
2019-09-17  6:07 ` [PATCH 1/3] pinctrl: add compatible for Amlogic Meson A1 pin controller Qianggui Song
2019-09-17  7:18   ` Neil Armstrong
2019-09-17 10:29     ` Qianggui Song
2019-09-30 22:47   ` Rob Herring
2019-09-17  6:07 ` [PATCH 2/3] pinctrl: meson-a1: add pinctrl driver for Meson A1 Soc Qianggui Song
2019-09-17  7:15   ` Neil Armstrong
2019-09-17 10:59     ` Qianggui Song
2019-09-17  9:29   ` Jerome Brunet
2019-09-17 11:51     ` Qianggui Song
2019-09-17 14:07       ` Jerome Brunet
2019-09-18  6:36         ` Qianggui Song
2019-09-19 16:26           ` Jerome Brunet
2019-09-23  7:29             ` Qianggui Song
2019-09-17  6:07 ` [PATCH 3/3] arm64: dts: meson: a1: add pinctrl controller support Qianggui Song

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).