lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250325141311.758787-3-emil.renner.berthing@canonical.com>
Date: Tue, 25 Mar 2025 15:13:04 +0100
From: Emil Renner Berthing <emil.renner.berthing@...onical.com>
To: Pinkesh Vaghela <pinkesh.vaghela@...fochips.com>,
	Pritesh Patel <pritesh.patel@...fochips.com>,
	Min Lin <linmin@...incomputing.com>
Cc: Samuel Holland <samuel.holland@...ive.com>,
	Linus Walleij <linus.walleij@...aro.org>,
	Rob Herring <robh@...nel.org>,
	Krzysztof Kozlowski <krzk+dt@...nel.org>,
	Conor Dooley <conor+dt@...nel.org>,
	Paul Walmsley <paul.walmsley@...ive.com>,
	Palmer Dabbelt <palmer@...belt.com>,
	Alexandre Ghiti <alex@...ti.fr>,
	Bartosz Golaszewski <brgl@...ev.pl>,
	linux-gpio@...r.kernel.org,
	devicetree@...r.kernel.org,
	linux-kernel@...r.kernel.org,
	linux-riscv@...ts.infradead.org
Subject: [RFC PATCH 2/4] pinctrl: Add driver for the ESWIN EIC7700 RISC-V SoC

Add pin control driver for the ESWIN EIC7700 RISC-V SoC.

Signed-off-by: Emil Renner Berthing <emil.renner.berthing@...onical.com>
---
 drivers/pinctrl/Kconfig           |  14 +
 drivers/pinctrl/Makefile          |   1 +
 drivers/pinctrl/pinctrl-eic7700.c | 802 ++++++++++++++++++++++++++++++
 3 files changed, 817 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-eic7700.c

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 95a8e2b9a614..3847dd3d0833 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -194,6 +194,20 @@ config PINCTRL_DIGICOLOR
 	select PINMUX
 	select GENERIC_PINCONF
 
+config PINCTRL_EIC7700
+	tristate "Pinctrl driver for the ESWIN EIC7700 SoC"
+	depends on ARCH_ESWIN || COMPILE_TEST
+	depends on OF
+	select GENERIC_PINMUX_FUNCTIONS
+	select GENERIC_PINCONF
+	select PINMUX
+	help
+	  This is the driver for the pin controller blocks on the
+	  ESWIN EIC7700 SoC.
+
+	  This driver is needed for RISC-V development boards like
+	  the HiFive Premier P550 and Milk-V Megrez.
+
 config PINCTRL_EP93XX
 	bool
 	depends on ARCH_EP93XX || COMPILE_TEST
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index fba1c56624c0..da5fb21c95a7 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_PINCTRL_CY8C95X0)	+= pinctrl-cy8c95x0.o
 obj-$(CONFIG_PINCTRL_DA850_PUPD) += pinctrl-da850-pupd.o
 obj-$(CONFIG_PINCTRL_DA9062)	+= pinctrl-da9062.o
 obj-$(CONFIG_PINCTRL_DIGICOLOR)	+= pinctrl-digicolor.o
+obj-$(CONFIG_PINCTRL_EIC7700)	+= pinctrl-eic7700.o
 obj-$(CONFIG_PINCTRL_EQUILIBRIUM)   += pinctrl-equilibrium.o
 obj-$(CONFIG_PINCTRL_EP93XX)	+= pinctrl-ep93xx.o
 obj-$(CONFIG_PINCTRL_EYEQ5)	+= pinctrl-eyeq5.o
diff --git a/drivers/pinctrl/pinctrl-eic7700.c b/drivers/pinctrl/pinctrl-eic7700.c
new file mode 100644
index 000000000000..955a862d7316
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-eic7700.c
@@ -0,0 +1,802 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl driver for the ESWIN EIC7700 SoC
+ *
+ * Copyright (C) 2025 Emil Renner Berthing <emil.renner.berthing@...onical.com>
+ */
+
+#include <linux/array_size.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/cleanup.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
+
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "core.h"
+#include "pinmux.h"
+#include "pinconf.h"
+
+#define EIC7700_PWDATA_FUNCSEL	GENMASK(18, 16)
+#define EIC7700_PWDATA_ST	BIT(7)
+#define EIC7700_PWDATA_DS	GENMASK(6, 3)
+#define EIC7700_PWDATA_PD	BIT(2)
+#define EIC7700_PWDATA_PU	BIT(1)
+#define EIC7700_PWDATA_IE	BIT(0)
+
+#define EIC7700_PULLDOWN_OHM	22000
+#define EIC7700_PULLUP_OHM	25000
+#define EIC7700_STRONGUP_OHM	3500
+
+struct eic7700_pinctrl {
+	struct pinctrl_desc desc;
+	struct mutex mutex;	/* serialize adding functions */
+	raw_spinlock_t lock;	/* serialize register access */
+	void __iomem *base;
+	struct pinctrl_dev *pctl;
+};
+
+static void __iomem *eic7700_pwdata(struct eic7700_pinctrl *ep,
+				    unsigned int pin)
+{
+	return ep->base + 4 * pin;
+}
+
+enum eic7700_muxtype {
+	EIC7700_MUX_____,
+	EIC7700_MUX_CSI,
+	EIC7700_MUX_DBG,
+	EIC7700_MUX_DDR,
+	EIC7700_MUX_FAN,
+	EIC7700_MUX_GPIO,
+	EIC7700_MUX_HDMI,
+	EIC7700_MUX_I2C,
+	EIC7700_MUX_I2S,
+	EIC7700_MUX_JTAG,
+	EIC7700_MUX_MIPI,
+	EIC7700_MUX_MODE,
+	EIC7700_MUX_OSC,
+	EIC7700_MUX_PCI,
+	EIC7700_MUX_PWM,
+	EIC7700_MUX_RGMI,
+	EIC7700_MUX_RST,
+	EIC7700_MUX_SATA,
+	EIC7700_MUX_SPI,
+	EIC7700_MUX_SDIO,
+	EIC7700_MUX_UART,
+	EIC7700_MUX_USB,
+};
+
+static const char *const eic7700_muxtype_string[] = {
+	[EIC7700_MUX_CSI]  = "csi",
+	[EIC7700_MUX_DBG]  = "debug",
+	[EIC7700_MUX_DDR]  = "ddr",
+	[EIC7700_MUX_FAN]  = "fan",
+	[EIC7700_MUX_GPIO] = "gpio",
+	[EIC7700_MUX_HDMI] = "hdmi",
+	[EIC7700_MUX_I2C]  = "i2c",
+	[EIC7700_MUX_I2S]  = "i2s",
+	[EIC7700_MUX_JTAG] = "jtag",
+	[EIC7700_MUX_MIPI] = "mipi",
+	[EIC7700_MUX_MODE] = "mode",
+	[EIC7700_MUX_OSC]  = "oscillator",
+	[EIC7700_MUX_PCI]  = "pci",
+	[EIC7700_MUX_PWM]  = "pwm",
+	[EIC7700_MUX_RGMI] = "rgmii",
+	[EIC7700_MUX_RST]  = "reset",
+	[EIC7700_MUX_SATA] = "sata",
+	[EIC7700_MUX_SPI]  = "spi",
+	[EIC7700_MUX_SDIO] = "sdio",
+	[EIC7700_MUX_UART] = "uart",
+	[EIC7700_MUX_USB]  = "usb",
+};
+
+static enum eic7700_muxtype eic7700_muxtype_get(const char *str)
+{
+	enum eic7700_muxtype mt;
+
+	for (mt = EIC7700_MUX_CSI; mt < ARRAY_SIZE(eic7700_muxtype_string); mt++) {
+		if (!strcmp(str, eic7700_muxtype_string[mt]))
+			return mt;
+	}
+	return EIC7700_MUX_____;
+}
+
+#define EIC7700_PAD(_nr, _name, m0, m1, m2, m3, m6, _flags) \
+	{ .number = _nr, .name = #_name, .drv_data = (void *)((_flags) | \
+		(EIC7700_MUX_##m0 <<  0) | (EIC7700_MUX_##m1 <<  5) | (EIC7700_MUX_##m2 << 10) | \
+		(EIC7700_MUX_##m3 << 15) | (EIC7700_MUX_##m6 << 20)) }
+
+static unsigned long eic7700_pad_muxdata(void *drv_data)
+{
+	return (uintptr_t)drv_data & GENMASK(24, 0);
+}
+
+static bool eic7700_pad_is_oscillator(void *drv_data)
+{
+	return ((uintptr_t)drv_data & GENMASK(4, 0)) == EIC7700_MUX_OSC;
+}
+
+static const struct pinctrl_pin_desc eic7700_pins[] = {
+	EIC7700_PAD(0,   CHIP_MODE,       MODE, ____, ____, ____, ____, 0),
+	EIC7700_PAD(1,   MODE_SET0,       SDIO, ____, GPIO, ____, ____, 0), /* GPIO13  */
+	EIC7700_PAD(2,   MODE_SET1,       SDIO, ____, GPIO, ____, ____, 0), /* GPIO14  */
+	EIC7700_PAD(3,   MODE_SET2,       SDIO, ____, GPIO, ____, ____, 0), /* GPIO15  */
+	EIC7700_PAD(4,   MODE_SET3,       SDIO, ____, GPIO, ____, ____, 0), /* GPIO16  */
+	EIC7700_PAD(5,   XIN,             OSC,  ____, ____, ____, ____, 0),
+	EIC7700_PAD(6,   RTC_XIN,         OSC,  ____, ____, ____, ____, 0),
+	EIC7700_PAD(7,   RST_OUT_N,       RST,  ____, ____, ____, ____, 0),
+	EIC7700_PAD(8,   KEY_RESET_N,     RST,  ____, ____, ____, ____, 0),
+	/* skip 9, 10 and 11 so we can calculate register offsets from the pin number */
+	EIC7700_PAD(12,  GPIO0,           GPIO, ____, ____, ____, ____, 0), /* GPIO0   */
+	EIC7700_PAD(13,  POR_SEL,         MODE, ____, ____, ____, ____, 0),
+	EIC7700_PAD(14,  JTAG0_TCK,       JTAG, SPI,  GPIO, ____, ____, 0), /* GPIO1   */
+	EIC7700_PAD(15,  JTAG0_TMS,       JTAG, SPI,  GPIO, ____, ____, 0), /* GPIO2   */
+	EIC7700_PAD(16,  JTAG0_TDI,       JTAG, SPI,  GPIO, ____, ____, 0), /* GPIO3   */
+	EIC7700_PAD(17,  JTAG0_TDO,       JTAG, SPI,  GPIO, ____, ____, 0), /* GPIO4   */
+	EIC7700_PAD(18,  GPIO5,           GPIO, SPI,  ____, ____, ____, 0), /* GPIO5   */
+	EIC7700_PAD(19,  SPI2_CS0_N,      SPI,  ____, GPIO, ____, ____, 0), /* GPIO6   */
+	EIC7700_PAD(20,  JTAG1_TCK,       JTAG, ____, GPIO, ____, ____, 0), /* GPIO7   */
+	EIC7700_PAD(21,  JTAG1_TMS,       JTAG, ____, GPIO, ____, ____, 0), /* GPIO8   */
+	EIC7700_PAD(22,  JTAG1_TDI,       JTAG, ____, GPIO, ____, ____, 0), /* GPIO9   */
+	EIC7700_PAD(23,  JTAG1_TDO,       JTAG, ____, GPIO, ____, ____, 0), /* GPIO10  */
+	EIC7700_PAD(24,  GPIO11,          GPIO, ____, ____, ____, ____, 0), /* GPIO11  */
+	EIC7700_PAD(25,  SPI2_CS1_N,      SPI,  ____, GPIO, ____, ____, 0), /* GPIO12  */
+	EIC7700_PAD(26,  PCIE_CLKREQ_N,   PCI,  ____, ____, ____, ____, 0),
+	EIC7700_PAD(27,  PCIE_WAKE_N,     PCI,  ____, ____, ____, ____, 0),
+	EIC7700_PAD(28,  PCIE_PERST_N,    PCI,  ____, ____, ____, ____, 0),
+	EIC7700_PAD(29,  HDMI_SCL,        HDMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(30,  HDMI_SDA,        HDMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(31,  HDMI_CEC,        HDMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(32,  JTAG2_TRST,      JTAG, ____, GPIO, ____, CSI,  0), /* GPIO17  */
+	EIC7700_PAD(33,  RGMII0_CLK_125,  RGMI, ____, ____, ____, CSI,  0),
+	EIC7700_PAD(34,  RGMII0_TXEN,     RGMI, ____, ____, ____, CSI,  0),
+	EIC7700_PAD(35,  RGMII0_TXCLK,    RGMI, ____, ____, ____, CSI,  0),
+	EIC7700_PAD(36,  RGMII0_TXD0,     RGMI, ____, ____, ____, CSI,  0),
+	EIC7700_PAD(37,  RGMII0_TXD1,     RGMI, ____, ____, ____, CSI,  0),
+	EIC7700_PAD(38,  RGMII0_TXD2,     RGMI, ____, ____, ____, CSI,  0),
+	EIC7700_PAD(39,  RGMII0_TXD3,     RGMI, ____, ____, ____, CSI,  0),
+	EIC7700_PAD(40,  I2S0_BCLK,       I2S,  ____, GPIO, ____, CSI,  0), /* GPIO18  */
+	EIC7700_PAD(41,  I2S0_WCLK,       I2S,  ____, GPIO, ____, CSI,  0), /* GPIO19  */
+	EIC7700_PAD(42,  I2S0_SDI,        I2S,  ____, GPIO, ____, CSI,  0), /* GPIO20  */
+	EIC7700_PAD(43,  I2S0_SDO,        I2S,  ____, GPIO, ____, CSI,  0), /* GPIO21  */
+	EIC7700_PAD(44,  I2S_MCLK,        I2S,  ____, GPIO, ____, CSI,  0), /* GPIO22  */
+	EIC7700_PAD(45,  RGMII0_RXCLK,    RGMI, ____, ____, ____, CSI,  0),
+	EIC7700_PAD(46,  RGMII0_RXDV,     RGMI, ____, ____, ____, CSI,  0),
+	EIC7700_PAD(47,  RGMII0_RXD0,     RGMI, ____, ____, ____, CSI,  0),
+	EIC7700_PAD(48,  RGMII0_RXD1,     RGMI, ____, ____, ____, CSI,  0),
+	EIC7700_PAD(49,  RGMII0_RXD2,     RGMI, ____, ____, ____, CSI,  0),
+	EIC7700_PAD(50,  RGMII0_RXD3,     RGMI, ____, ____, ____, CSI,  0),
+	EIC7700_PAD(51,  I2S2_BCLK,       I2S,  ____, GPIO, ____, CSI,  0), /* GPIO23  */
+	EIC7700_PAD(52,  I2S2_WCLK,       I2S,  ____, GPIO, ____, CSI,  0), /* GPIO24  */
+	EIC7700_PAD(53,  I2S2_SDI,        I2S,  ____, GPIO, ____, CSI,  0), /* GPIO25  */
+	EIC7700_PAD(54,  I2S2_SDO,        I2S,  ____, GPIO, ____, CSI,  0), /* GPIO26  */
+	EIC7700_PAD(55,  GPIO27,          GPIO, SATA, ____, ____, CSI,  0), /* GPIO27  */
+	EIC7700_PAD(56,  GPIO28,          GPIO, ____, ____, ____, ____, 0), /* GPIO28  */
+	EIC7700_PAD(57,  GPIO29,          MODE, SDIO, GPIO, ____, ____, 0), /* GPIO29  */
+	EIC7700_PAD(58,  RGMII0_MDC,      RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(59,  RGMII0_MDIO,     RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(60,  RGMII0_INTB,     RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(61,  RGMII1_CLK_125,  RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(62,  RGMII1_TXEN,     RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(63,  RGMII1_TXCLK,    RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(64,  RGMII1_TXD0,     RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(65,  RGMII1_TXD1,     RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(66,  RGMII1_TXD2,     RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(67,  RGMII1_TXD3,     RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(68,  I2S1_BCLK,       I2S,  ____, GPIO, ____, ____, 0), /* GPIO30  */
+	EIC7700_PAD(69,  I2S1_WCLK,       I2S,  ____, GPIO, ____, ____, 0), /* GPIO31  */
+	EIC7700_PAD(70,  I2S1_SDI,        I2S,  ____, GPIO, ____, ____, 0), /* GPIO32  */
+	EIC7700_PAD(71,  I2S1_SDO,        I2S,  ____, GPIO, ____, ____, 0), /* GPIO33  */
+	EIC7700_PAD(72,  GPIO34,          MODE, SDIO, GPIO, ____, ____, 0), /* GPIO34  */
+	EIC7700_PAD(73,  RGMII1_RXCLK,    RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(74,  RGMII2_RXDV,     RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(75,  RGMII2_RXD0,     RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(76,  RGMII2_RXD1,     RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(77,  RGMII2_RXD2,     RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(78,  RGMII2_RXD3,     RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(79,  SPI1_CS0_N,      SPI,  ____, GPIO, ____, ____, 0), /* GPIO35  */
+	EIC7700_PAD(80,  SPI1_CLK,        SPI,  ____, GPIO, ____, ____, 0), /* GPIO36  */
+	EIC7700_PAD(81,  SPI1_D0,         SPI,  I2C,  GPIO, UART, ____, 0), /* GPIO37  */
+	EIC7700_PAD(82,  SPI1_D1,         SPI,  I2C,  GPIO, UART, ____, 0), /* GPIO38  */
+	EIC7700_PAD(83,  SPI1_D2,         SPI,  SDIO, GPIO, ____, ____, 0), /* GPIO39  */
+	EIC7700_PAD(84,  SPI1_D3,         SPI,  PWM,  GPIO, ____, ____, 0), /* GPIO40  */
+	EIC7700_PAD(85,  SPI1_CS1_N,      SPI,  PWM,  GPIO, ____, ____, 0), /* GPIO41  */
+	EIC7700_PAD(86,  RGMII1_MDC,      RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(87,  RGMII1_MDIO,     RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(88,  RGMII1_INTB,     RGMI, ____, ____, ____, ____, 0),
+	EIC7700_PAD(89,  USB0_PWREN,      USB,  ____, GPIO, ____, ____, 0), /* GPIO42  */
+	EIC7700_PAD(90,  USB1_PWREN,      USB,  ____, GPIO, ____, ____, 0), /* GPIO43  */
+	EIC7700_PAD(91,  I2C0_SCL,        I2C,  ____, GPIO, ____, ____, 0), /* GPIO44  */
+	EIC7700_PAD(92,  I2C0_SDA,        I2C,  ____, GPIO, ____, ____, 0), /* GPIO45  */
+	EIC7700_PAD(93,  I2C1_SCL,        I2C,  ____, GPIO, ____, ____, 0), /* GPIO46  */
+	EIC7700_PAD(94,  I2C1_SDA,        I2C,  ____, GPIO, ____, ____, 0), /* GPIO47  */
+	EIC7700_PAD(95,  I2C2_SCL,        I2C,  ____, GPIO, ____, ____, 0), /* GPIO48  */
+	EIC7700_PAD(96,  I2C2_SDA,        I2C,  ____, GPIO, ____, CSI,  0), /* GPIO49  */
+	EIC7700_PAD(97,  I2C3_SCL,        I2C,  ____, GPIO, ____, CSI,  0), /* GPIO50  */
+	EIC7700_PAD(98,  I2C3_SDA,        I2C,  ____, GPIO, ____, CSI,  0), /* GPIO51  */
+	EIC7700_PAD(99,  I2C4_SCL,        I2C,  ____, GPIO, ____, CSI,  0), /* GPIO52  */
+	EIC7700_PAD(100, I2C4_SDA,        I2C,  ____, GPIO, ____, CSI,  0), /* GPIO53  */
+	EIC7700_PAD(101, I2C5_SCL,        I2C,  ____, GPIO, ____, CSI,  0), /* GPIO54  */
+	EIC7700_PAD(102, I2C5_SDA,        I2C,  ____, GPIO, ____, CSI,  0), /* GPIO55  */
+	EIC7700_PAD(103, UART0_TX,        UART, ____, GPIO, ____, ____, 0), /* GPIO56  */
+	EIC7700_PAD(104, UART0_RX,        UART, ____, GPIO, ____, ____, 0), /* GPIO57  */
+	EIC7700_PAD(105, UART1_TX,        UART, ____, GPIO, ____, ____, 0), /* GPIO58  */
+	EIC7700_PAD(106, UART1_RX,        UART, ____, GPIO, ____, ____, 0), /* GPIO59  */
+	EIC7700_PAD(107, UART1_CTS,       UART, I2C,  GPIO, ____, ____, 0), /* GPIO60  */
+	EIC7700_PAD(108, UART1_RTS,       UART, I2C,  GPIO, ____, ____, 0), /* GPIO61  */
+	EIC7700_PAD(109, UART2_TX,        UART, I2C,  GPIO, ____, CSI,  0), /* GPIO62  */
+	EIC7700_PAD(110, UART2_RX,        UART, I2C,  GPIO, ____, DBG,  0), /* GPIO63  */
+	EIC7700_PAD(111, JTAG2_TCK,       JTAG, ____, GPIO, ____, DBG,  0), /* GPIO64  */
+	EIC7700_PAD(112, JTAG2_TMS,       JTAG, ____, GPIO, ____, DBG,  0), /* GPIO65  */
+	EIC7700_PAD(113, JTAG2_TDI,       JTAG, ____, GPIO, ____, DBG,  0), /* GPIO66  */
+	EIC7700_PAD(114, JTAG2_TDO,       JTAG, ____, GPIO, ____, DBG,  0), /* GPIO67  */
+	EIC7700_PAD(115, FAN_PWM,         FAN,  ____, GPIO, ____, DBG,  0), /* GPIO68  */
+	EIC7700_PAD(116, FAN_TACH,        FAN,  ____, GPIO, ____, DBG,  0), /* GPIO69  */
+	EIC7700_PAD(117, MIPI_CSI0_XVS,   MIPI, ____, GPIO, ____, DBG,  0), /* GPIO70  */
+	EIC7700_PAD(118, MIPI_CSI0_XHS,   MIPI, ____, GPIO, ____, DBG,  0), /* GPIO71  */
+	EIC7700_PAD(119, MIPI_CSI0_MCLK,  MIPI, ____, GPIO, ____, DBG,  0), /* GPIO72  */
+	EIC7700_PAD(120, MIPI_CSI1_XVS,   MIPI, ____, GPIO, ____, DBG,  0), /* GPIO73  */
+	EIC7700_PAD(121, MIPI_CSI1_XHS,   MIPI, ____, GPIO, ____, DBG,  0), /* GPIO74  */
+	EIC7700_PAD(122, MIPI_CSI1_MCLK,  MIPI, ____, GPIO, ____, DBG,  0), /* GPIO75  */
+	EIC7700_PAD(123, MIPI_CSI2_XVS,   MIPI, ____, GPIO, ____, DBG,  0), /* GPIO76  */
+	EIC7700_PAD(124, MIPI_CSI2_XHS,   MIPI, ____, GPIO, ____, DBG,  0), /* GPIO77  */
+	EIC7700_PAD(125, MIPI_CSI2_MCLK,  MIPI, ____, GPIO, ____, DBG,  0), /* GPIO78  */
+	EIC7700_PAD(126, MIPI_CSI3_XVS,   MIPI, ____, GPIO, ____, SATA, 0), /* GPIO79  */
+	EIC7700_PAD(127, MIPI_CSI3_XHS,   MIPI, ____, GPIO, ____, SATA, 0), /* GPIO80  */
+	EIC7700_PAD(128, MIPI_CSI3_MCLK,  MIPI, ____, GPIO, ____, SATA, 0), /* GPIO81  */
+	EIC7700_PAD(129, MIPI_CSI4_XVS,   MIPI, ____, GPIO, ____, CSI,  0), /* GPIO82  */
+	EIC7700_PAD(130, MIPI_CSI4_XHS,   MIPI, ____, GPIO, ____, CSI,  0), /* GPIO83  */
+	EIC7700_PAD(131, MIPI_CSI4_MCLK,  MIPI, ____, GPIO, ____, CSI,  0), /* GPIO84  */
+	EIC7700_PAD(132, MIPI_CSI5_XVS,   MIPI, ____, GPIO, ____, CSI,  0), /* GPIO85  */
+	EIC7700_PAD(133, MIPI_CSI5_XHS,   MIPI, ____, GPIO, ____, CSI,  0), /* GPIO86  */
+	EIC7700_PAD(134, MIPI_CSI5_MCLK,  MIPI, ____, GPIO, ____, CSI,  0), /* GPIO87  */
+	EIC7700_PAD(135, SPI3_CS_N,       SPI,  ____, GPIO, ____, ____, 0), /* GPIO88  */
+	EIC7700_PAD(136, SPI3_CLK,        SPI,  ____, GPIO, ____, ____, 0), /* GPIO89  */
+	EIC7700_PAD(137, SPI3_DI,         SPI,  ____, GPIO, ____, ____, 0), /* GPIO90  */
+	EIC7700_PAD(138, SPI3_DO,         SPI,  ____, GPIO, ____, ____, 0), /* GPIO91  */
+	EIC7700_PAD(139, GPIO92,          I2C,  MIPI, GPIO, UART, ____, 0), /* GPIO92  */
+	EIC7700_PAD(140, GPIO93,          I2C,  MIPI, GPIO, UART, ____, 0), /* GPIO93  */
+	EIC7700_PAD(141, S_MODE,          MODE, ____, GPIO, ____, ____, 0), /* GPIO94  */
+	EIC7700_PAD(142, GPIO95,          MODE, ____, GPIO, ____, ____, 0), /* GPIO95  */
+	EIC7700_PAD(143, SPI0_CS_N,       SPI,  ____, GPIO, ____, ____, 0), /* GPIO96  */
+	EIC7700_PAD(144, SPI0_CLK,        SPI,  ____, GPIO, ____, ____, 0), /* GPIO97  */
+	EIC7700_PAD(145, SPI0_D0,         SPI,  ____, GPIO, ____, ____, 0), /* GPIO98  */
+	EIC7700_PAD(146, SPI0_D1,         SPI,  ____, GPIO, ____, ____, 0), /* GPIO99  */
+	EIC7700_PAD(147, SPI0_D2,         SPI,  ____, GPIO, ____, ____, 0), /* GPIO100 */
+	EIC7700_PAD(148, SPI0_D3,         SPI,  ____, GPIO, ____, ____, 0), /* GPIO101 */
+	EIC7700_PAD(149, I2C10_SCL,       I2C,  ____, GPIO, ____, ____, 0), /* GPIO102 */
+	EIC7700_PAD(150, I2C10_SDA,       I2C,  ____, GPIO, ____, ____, 0), /* GPIO103 */
+	EIC7700_PAD(151, I2C11_SCL,       I2C,  ____, GPIO, ____, ____, 0), /* GPIO104 */
+	EIC7700_PAD(152, I2C11_SDA,       I2C,  ____, GPIO, ____, ____, 0), /* GPIO105 */
+	EIC7700_PAD(153, GPIO106,         GPIO, ____, ____, ____, ____, 0), /* GPIO106 */
+	EIC7700_PAD(154, BOOT_SEL0,       MODE, ____, GPIO, ____, ____, 0), /* GPIO107 */
+	EIC7700_PAD(155, BOOT_SEL1,       MODE, ____, GPIO, ____, ____, 0), /* GPIO108 */
+	EIC7700_PAD(156, BOOT_SEL2,       MODE, ____, GPIO, ____, ____, 0), /* GPIO109 */
+	EIC7700_PAD(157, BOOT_SEL3,       MODE, ____, GPIO, ____, ____, 0), /* GPIO110 */
+	EIC7700_PAD(158, GPIO111,         GPIO, ____, ____, ____, ____, 0), /* GPIO111 */
+	/* skip 159, 160, 161 and 162 */
+	EIC7700_PAD(163, LPDDR_REF_CLK,   DDR,  ____, ____, ____, ____, 0),
+};
+
+static int eic7700_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct eic7700_pinctrl *ep = pinctrl_dev_get_drvdata(pctldev);
+
+	return ep->desc.npins;
+}
+
+static const char *eic7700_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+						  unsigned int gsel)
+{
+	struct eic7700_pinctrl *ep = pinctrl_dev_get_drvdata(pctldev);
+
+	return ep->desc.pins[gsel].name;
+}
+
+static int eic7700_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+					  unsigned int gsel,
+					  const unsigned int **pins,
+					  unsigned int *npins)
+{
+	struct eic7700_pinctrl *ep = pinctrl_dev_get_drvdata(pctldev);
+
+	*pins = &ep->desc.pins[gsel].number;
+	*npins = 1;
+	return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void eic7700_pin_dbg_show(struct pinctrl_dev *pctldev,
+				 struct seq_file *s, unsigned int pin)
+{
+	struct eic7700_pinctrl *ep = pinctrl_dev_get_drvdata(pctldev);
+	void __iomem *pwdata = eic7700_pwdata(ep, pin);
+	u32 value;
+
+	scoped_guard(raw_spinlock_irqsave, &ep->lock) {
+		value = readl_relaxed(pwdata);
+	}
+
+	seq_printf(s, "[pwdata:0x%x=0x%05x]", 0x80 + 4 * pin, value);
+}
+#else
+#define eic7700_pin_dbg_show NULL
+#endif
+
+static void eic7700_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+					struct pinctrl_map *map,
+					unsigned int nmaps)
+{
+	unsigned long *seen = NULL;
+	unsigned int i;
+
+	for (i = 0; i < nmaps; i++) {
+		if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN &&
+		    map[i].data.configs.configs != seen) {
+			seen = map[i].data.configs.configs;
+			kfree(seen);
+		}
+	}
+
+	kfree(map);
+}
+
+static int eic7700_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+					  struct device_node *np,
+					  struct pinctrl_map **maps,
+					  unsigned int *num_maps)
+{
+	struct eic7700_pinctrl *ep = pinctrl_dev_get_drvdata(pctldev);
+	struct pinctrl_map *map;
+	unsigned long *configs;
+	unsigned int nconfigs;
+	unsigned int nmaps;
+	int ret;
+
+	nmaps = 0;
+	for_each_available_child_of_node_scoped(np, child) {
+		int npins = of_property_count_strings(child, "pins");
+
+		if (npins <= 0) {
+			dev_err(ep->pctl->dev, "no pins selected for %pOFn.%pOFn\n",
+				np, child);
+			return -EINVAL;
+		}
+		nmaps += npins;
+		if (of_property_present(child, "function"))
+			nmaps += npins;
+	}
+
+	map = kcalloc(nmaps, sizeof(*map), GFP_KERNEL);
+	if (!map)
+		return -ENOMEM;
+
+	nmaps = 0;
+	guard(mutex)(&ep->mutex);
+	for_each_available_child_of_node_scoped(np, child) {
+		unsigned int rollback = nmaps;
+		enum eic7700_muxtype muxtype;
+		struct property *prop;
+		const char *funcname;
+		const char **pgnames;
+		const char *pinname;
+		int npins;
+
+		ret = pinconf_generic_parse_dt_config(child, pctldev, &configs, &nconfigs);
+		if (ret) {
+			dev_err(ep->pctl->dev, "%pOFn.%pOFn: error parsing pin config\n",
+				np, child);
+			goto free_map;
+		}
+
+		if (!of_property_read_string(child, "function", &funcname)) {
+			muxtype = eic7700_muxtype_get(funcname);
+			if (!muxtype) {
+				dev_err(ep->pctl->dev, "%pOFn.%pOFn: unknown function '%s'\n",
+					np, child, funcname);
+				ret = -EINVAL;
+				goto free_configs;
+			}
+
+			funcname = devm_kasprintf(ep->pctl->dev, GFP_KERNEL, "%pOFn.%pOFn",
+						  np, child);
+			if (!funcname) {
+				ret = -ENOMEM;
+				goto free_configs;
+			}
+
+			npins = of_property_count_strings(child, "pins");
+			pgnames = devm_kcalloc(ep->pctl->dev, npins, sizeof(*pgnames), GFP_KERNEL);
+			if (!pgnames) {
+				ret = -ENOMEM;
+				goto free_configs;
+			}
+		} else {
+			funcname = NULL;
+		}
+
+		npins = 0;
+		of_property_for_each_string(child, "pins", prop, pinname) {
+			unsigned int i;
+
+			for (i = 0; i < ep->desc.npins; i++) {
+				if (!strcmp(pinname, ep->desc.pins[i].name))
+					break;
+			}
+			if (i == ep->desc.npins) {
+				nmaps = rollback;
+				dev_err(ep->pctl->dev, "%pOFn.%pOFn: unknown pin '%s'\n",
+					np, child, pinname);
+				ret = -EINVAL;
+				goto free_configs;
+			}
+
+			if (nconfigs) {
+				map[nmaps].type = PIN_MAP_TYPE_CONFIGS_PIN;
+				map[nmaps].data.configs.group_or_pin = ep->desc.pins[i].name;
+				map[nmaps].data.configs.configs = configs;
+				map[nmaps].data.configs.num_configs = nconfigs;
+				nmaps += 1;
+			}
+			if (funcname) {
+				pgnames[npins++] = ep->desc.pins[i].name;
+				map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
+				map[nmaps].data.mux.function = funcname;
+				map[nmaps].data.mux.group = ep->desc.pins[i].name;
+				nmaps += 1;
+			}
+		}
+
+		if (funcname) {
+			ret = pinmux_generic_add_function(pctldev, funcname, pgnames,
+							  npins, (void *)muxtype);
+			if (ret < 0) {
+				dev_err(ep->pctl->dev, "error adding function %s\n", funcname);
+				goto free_map;
+			}
+		}
+	}
+
+	*maps = map;
+	*num_maps = nmaps;
+	return 0;
+
+free_configs:
+	kfree(configs);
+free_map:
+	eic7700_pinctrl_dt_free_map(pctldev, map, nmaps);
+	return ret;
+}
+
+static const struct pinctrl_ops eic7700_pinctrl_ops = {
+	.get_groups_count = eic7700_pinctrl_get_groups_count,
+	.get_group_name = eic7700_pinctrl_get_group_name,
+	.get_group_pins = eic7700_pinctrl_get_group_pins,
+	.pin_dbg_show = eic7700_pin_dbg_show,
+	.dt_node_to_map = eic7700_pinctrl_dt_node_to_map,
+	.dt_free_map = eic7700_pinctrl_dt_free_map,
+};
+
+static const u16 eic7700_drive_strength_in_uA[8] = {
+	3100, 6700, 9600, 12900, 18000, 20900, 23200, 25900,
+};
+
+static u32 eic7700_drive_strength_from_uA(u32 arg)
+{
+	u32 ds;
+
+	for (ds = 0; ds < ARRAY_SIZE(eic7700_drive_strength_in_uA); ds++) {
+		if (arg <= eic7700_drive_strength_in_uA[ds])
+			return ds;
+	}
+	return ARRAY_SIZE(eic7700_drive_strength_in_uA);
+}
+
+static int eic7700_pwdata_rmw(struct eic7700_pinctrl *ep, unsigned int pin,
+			      u32 mask, u32 value)
+{
+	void __iomem *pwdata = eic7700_pwdata(ep, pin);
+	u32 tmp;
+
+	scoped_guard(raw_spinlock_irqsave, &ep->lock) {
+		tmp = readl_relaxed(pwdata);
+		tmp = (tmp & ~mask) | value;
+		writel_relaxed(tmp, pwdata);
+	}
+	return 0;
+}
+
+static int eic7700_pinconf_get(struct pinctrl_dev *pctldev,
+			       unsigned int pin, unsigned long *config)
+{
+	struct eic7700_pinctrl *ep = pinctrl_dev_get_drvdata(pctldev);
+	const struct pin_desc *desc = pin_desc_get(pctldev, pin);
+	u32 value = readl_relaxed(eic7700_pwdata(ep, pin));
+	int param = pinconf_to_config_param(*config);
+	bool enabled;
+	u32 arg;
+
+	if (eic7700_pad_is_oscillator(desc->drv_data))
+		return -ENOTSUPP;
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		enabled = !(value & (EIC7700_PWDATA_PD | EIC7700_PWDATA_PU));
+		arg = 0;
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		enabled = value & EIC7700_PWDATA_PD;
+		arg = EIC7700_PULLDOWN_OHM;
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		enabled = value & EIC7700_PWDATA_PU;
+		arg = EIC7700_PULLUP_OHM;
+		break;
+	case PIN_CONFIG_DRIVE_STRENGTH_UA:
+		enabled = true;
+		arg = FIELD_GET(EIC7700_PWDATA_DS, value);
+		if (arg < ARRAY_SIZE(eic7700_drive_strength_in_uA))
+			arg = eic7700_drive_strength_in_uA[arg];
+		else
+			arg = 0;
+		break;
+	case PIN_CONFIG_INPUT_ENABLE:
+		enabled = value & EIC7700_PWDATA_IE;
+		arg = enabled ? 1 : 0;
+		break;
+	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+		enabled = value & EIC7700_PWDATA_ST;
+		arg = enabled ? 1 : 0;
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	*config = pinconf_to_config_packed(param, arg);
+	return enabled ? 0 : -EINVAL;
+}
+
+static int eic7700_pinconf_group_get(struct pinctrl_dev *pctldev,
+				     unsigned int gsel, unsigned long *config)
+{
+	struct eic7700_pinctrl *ep = pinctrl_dev_get_drvdata(pctldev);
+	unsigned int pin = ep->desc.pins[gsel].number;
+
+	return eic7700_pinconf_get(pctldev, pin, config);
+}
+
+static int eic7700_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+			       unsigned long *configs, unsigned int num_configs)
+{
+	struct eic7700_pinctrl *ep = pinctrl_dev_get_drvdata(pctldev);
+	const struct pin_desc *desc = pin_desc_get(pctldev, pin);
+	unsigned int i;
+	u32 value = 0;
+	u32 mask = 0;
+
+	if (eic7700_pad_is_oscillator(desc->drv_data))
+		return -ENOTSUPP;
+
+	for (i = 0; i < num_configs; i++) {
+		int param = pinconf_to_config_param(configs[i]);
+		u32 arg = pinconf_to_config_argument(configs[i]);
+
+		switch (param) {
+		case PIN_CONFIG_BIAS_DISABLE:
+			mask |= EIC7700_PWDATA_PU | EIC7700_PWDATA_PD;
+			value &= ~(EIC7700_PWDATA_PU | EIC7700_PWDATA_PD);
+			break;
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			if (arg == 0)
+				return -ENOTSUPP;
+			mask |= EIC7700_PWDATA_PU | EIC7700_PWDATA_PD;
+			value &= ~EIC7700_PWDATA_PU;
+			value |= EIC7700_PWDATA_PD;
+			break;
+		case PIN_CONFIG_BIAS_PULL_UP:
+			if (arg == 0)
+				return -ENOTSUPP;
+			mask |= EIC7700_PWDATA_PU | EIC7700_PWDATA_PD;
+			value &= ~EIC7700_PWDATA_PD;
+			value |= EIC7700_PWDATA_PU;
+			break;
+		case PIN_CONFIG_DRIVE_STRENGTH_UA:
+			mask |= EIC7700_PWDATA_DS;
+			value &= ~EIC7700_PWDATA_DS;
+			value |= FIELD_PREP(EIC7700_PWDATA_DS,
+					eic7700_drive_strength_from_uA(arg));
+			break;
+		case PIN_CONFIG_INPUT_ENABLE:
+			mask |= EIC7700_PWDATA_IE;
+			if (arg)
+				value |= EIC7700_PWDATA_IE;
+			else
+				value &= ~EIC7700_PWDATA_IE;
+			break;
+		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+			mask |= EIC7700_PWDATA_ST;
+			if (arg)
+				value |= EIC7700_PWDATA_ST;
+			else
+				value &= ~EIC7700_PWDATA_ST;
+			break;
+		default:
+			return -ENOTSUPP;
+		}
+	}
+
+	return eic7700_pwdata_rmw(ep, pin, mask, value);
+}
+
+static int eic7700_pinconf_group_set(struct pinctrl_dev *pctldev,
+				     unsigned int gsel,
+				     unsigned long *configs,
+				     unsigned int num_configs)
+{
+	struct eic7700_pinctrl *ep = pinctrl_dev_get_drvdata(pctldev);
+	unsigned int pin = ep->desc.pins[gsel].number;
+
+	return eic7700_pinconf_set(pctldev, pin, configs, num_configs);
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void eic7700_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+				     struct seq_file *s, unsigned int pin)
+{
+	struct eic7700_pinctrl *ep = pinctrl_dev_get_drvdata(pctldev);
+	u32 value = readl_relaxed(eic7700_pwdata(ep, pin));
+
+	seq_printf(s, " [0x%02lx]", value & GENMASK(7, 0));
+}
+#else
+#define eic7700_pinconf_dbg_show NULL
+#endif
+
+static const struct pinconf_ops eic7700_pinconf_ops = {
+	.pin_config_get = eic7700_pinconf_get,
+	.pin_config_group_get = eic7700_pinconf_group_get,
+	.pin_config_set = eic7700_pinconf_set,
+	.pin_config_group_set = eic7700_pinconf_group_set,
+	.pin_config_dbg_show = eic7700_pinconf_dbg_show,
+	.is_generic = true,
+};
+
+static int eic7700_pinmux_set(struct eic7700_pinctrl *ep, unsigned int pin,
+			      unsigned long muxdata, enum eic7700_muxtype muxtype)
+{
+	u32 value;
+
+	for (value = 0; muxdata; muxdata >>= 5, value++) {
+		if ((muxdata & GENMASK(4, 0)) == muxtype)
+			break;
+	}
+	if (!muxdata) {
+		dev_err(ep->pctl->dev, "invalid mux %s for pin %s\n",
+			eic7700_muxtype_string[muxtype], pin_get_name(ep->pctl, pin));
+		return -EINVAL;
+	}
+
+	/* only pwdata[18:16] = 0, 1, 2, 3 and 6 are used */
+	if (value == 4)
+		value = 6;
+
+	return eic7700_pwdata_rmw(ep, pin, EIC7700_PWDATA_FUNCSEL,
+				  FIELD_PREP(EIC7700_PWDATA_FUNCSEL, value));
+}
+
+static int eic7700_pinmux_set_mux(struct pinctrl_dev *pctldev,
+				  unsigned int fsel, unsigned int gsel)
+{
+	struct eic7700_pinctrl *ep = pinctrl_dev_get_drvdata(pctldev);
+	const struct function_desc *func = pinmux_generic_get_function(pctldev, fsel);
+	enum eic7700_muxtype muxtype;
+
+	if (!func)
+		return -EINVAL;
+
+	muxtype = (uintptr_t)func->data;
+	return eic7700_pinmux_set(ep, ep->desc.pins[gsel].number,
+				  eic7700_pad_muxdata(ep->desc.pins[gsel].drv_data),
+				  muxtype);
+}
+
+static int eic7700_gpio_request_enable(struct pinctrl_dev *pctldev,
+				       struct pinctrl_gpio_range *range,
+				       unsigned int offset)
+{
+	struct eic7700_pinctrl *ep = pinctrl_dev_get_drvdata(pctldev);
+	const struct pin_desc *desc = pin_desc_get(pctldev, offset);
+
+	return eic7700_pinmux_set(ep, offset,
+				  eic7700_pad_muxdata(desc->drv_data),
+				  EIC7700_MUX_GPIO);
+}
+
+static int eic7700_gpio_set_direction(struct pinctrl_dev *pctldev,
+				      struct pinctrl_gpio_range *range,
+				      unsigned int offset, bool input)
+{
+	struct eic7700_pinctrl *ep = pinctrl_dev_get_drvdata(pctldev);
+
+	return eic7700_pwdata_rmw(ep, offset, EIC7700_PWDATA_IE,
+				  input ? EIC7700_PWDATA_IE : 0);
+}
+
+static const struct pinmux_ops eic7700_pinmux_ops = {
+	.get_functions_count = pinmux_generic_get_function_count,
+	.get_function_name = pinmux_generic_get_function_name,
+	.get_function_groups = pinmux_generic_get_function_groups,
+	.set_mux = eic7700_pinmux_set_mux,
+	.gpio_request_enable = eic7700_gpio_request_enable,
+	.gpio_set_direction = eic7700_gpio_set_direction,
+	.strict = true,
+};
+
+static int eic7700_pinctrl_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct eic7700_pinctrl *ep;
+	int ret;
+
+	ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL);
+	if (!ep)
+		return -ENOMEM;
+
+	ep->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(ep->base))
+		return PTR_ERR(ep->base);
+
+	ep->desc.name = "eic7700";
+	ep->desc.pins = eic7700_pins;
+	ep->desc.npins = ARRAY_SIZE(eic7700_pins);
+	ep->desc.pctlops = &eic7700_pinctrl_ops;
+	ep->desc.pmxops = &eic7700_pinmux_ops;
+	ep->desc.confops = &eic7700_pinconf_ops;
+	ep->desc.owner = THIS_MODULE;
+	raw_spin_lock_init(&ep->lock);
+
+	ret = devm_mutex_init(dev, &ep->mutex);
+	if (ret)
+		return ret;
+
+	ret = devm_pinctrl_register_and_init(dev, &ep->desc, ep, &ep->pctl);
+	if (ret)
+		return dev_err_probe(dev, ret, "could not register pinctrl driver\n");
+
+	return pinctrl_enable(ep->pctl);
+}
+
+static const struct of_device_id eic7700_pinctrl_of_match[] = {
+	{ .compatible = "eswin,eic7700-pinctrl"},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, eic7700_pinctrl_of_match);
+
+static struct platform_driver eic7700_pinctrl_driver = {
+	.probe = eic7700_pinctrl_probe,
+	.driver = {
+		.name = "pinctrl-eic7700",
+		.of_match_table = eic7700_pinctrl_of_match,
+	},
+};
+module_platform_driver(eic7700_pinctrl_driver);
+
+MODULE_DESCRIPTION("Pinctrl driver for the ESWIN EIC7700 SoC");
+MODULE_AUTHOR("Emil Renner Berthing <emil.renner.berthing@...onical.com>");
+MODULE_LICENSE("GPL");
-- 
2.43.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ