[PATCH linux dev-4.13 v2 2/2] pinctrl: npcm: add NPCM7xx pin controller driver

Andrew Jeffery andrew at aj.id.au
Thu Jan 11 11:30:02 AEDT 2018


On Thu, 2017-12-28 at 12:43 +0200, Tomer Maimon wrote:
> Add Nuvoton BMC NPCM7xx pin controller driver.
> 
> The NPCM7XX Pin Controller multi-function routed
> through the multiplexing block, Each pin supports
> GPIO functionality (GPIOx) and multiple functions
> that directly connect the pin to different hardware
> blocks.
> 
> Signed-off-by: Tomer Maimon <tmaimon77 at gmail.com>
> ---
>  drivers/pinctrl/Kconfig                   |    1 +
>  drivers/pinctrl/Makefile                  |    2 +
>  drivers/pinctrl/nuvoton/Kconfig           |    8 +
>  drivers/pinctrl/nuvoton/Makefile          |    1 +
>  drivers/pinctrl/nuvoton/npcmreg.h         |  249 ++++
>  drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c | 2157 +++++++++++++++++++++++++++++
>  6 files changed, 2418 insertions(+)
>  create mode 100644 drivers/pinctrl/nuvoton/Kconfig
>  create mode 100644 drivers/pinctrl/nuvoton/Makefile
>  create mode 100644 drivers/pinctrl/nuvoton/npcmreg.h
>  create mode 100644 drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
> 
> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
> index e14b46c7b37f..25b7c1383631 100644
> --- a/drivers/pinctrl/Kconfig
> +++ b/drivers/pinctrl/Kconfig
> @@ -351,6 +351,7 @@ source "drivers/pinctrl/uniphier/Kconfig"
>  source "drivers/pinctrl/vt8500/Kconfig"
>  source "drivers/pinctrl/mediatek/Kconfig"
>  source "drivers/pinctrl/zte/Kconfig"
> +source "drivers/pinctrl/nuvoton/Kconfig"
>  
>  config PINCTRL_XWAY
>  	bool
> diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
> index 2bc641d62400..925d99b05e47 100644
> --- a/drivers/pinctrl/Makefile
> +++ b/drivers/pinctrl/Makefile
> @@ -62,3 +62,5 @@ obj-$(CONFIG_PINCTRL_UNIPHIER)	+= uniphier/
>  obj-$(CONFIG_ARCH_VT8500)	+= vt8500/
>  obj-$(CONFIG_PINCTRL_MTK)	+= mediatek/
>  obj-$(CONFIG_PINCTRL_ZX)	+= zte/
> +obj-$(CONFIG_ARCH_NPCM7XX)	+= nuvoton/
> +
> diff --git a/drivers/pinctrl/nuvoton/Kconfig b/drivers/pinctrl/nuvoton/Kconfig
> new file mode 100644
> index 000000000000..9217be2f489e
> --- /dev/null
> +++ b/drivers/pinctrl/nuvoton/Kconfig
> @@ -0,0 +1,8 @@
> +config PINCTRL_NPCM7XX
> +	bool "Pinctrl driver for Nuvoton NPCM7XX"
> +	select GPIOLIB
> +	select GPIOLIB_IRQCHIP
> +	select PINMUX
> +	select PINCONF
> +	select GENERIC_PINCONF
> +	default ARCH_NPCM7XX
> diff --git a/drivers/pinctrl/nuvoton/Makefile b/drivers/pinctrl/nuvoton/Makefile
> new file mode 100644
> index 000000000000..977b4ab28794
> --- /dev/null
> +++ b/drivers/pinctrl/nuvoton/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_PINCTRL_NPCMX50)	+= pinctrl-npcm7xx.o
> diff --git a/drivers/pinctrl/nuvoton/npcmreg.h b/drivers/pinctrl/nuvoton/npcmreg.h
> new file mode 100644
> index 000000000000..3aa2d1c21885
> --- /dev/null
> +++ b/drivers/pinctrl/nuvoton/npcmreg.h
> @@ -0,0 +1,249 @@
> +#ifndef __NPCM_REG_H__
> +#define __NPCM_REG_H__
> +
> +#define DRV_MSG2(x...)

Lets drop this. At the call sites, use dev_dbg().

> +
> +#define regdef(flags, offset)	 offset
> +#define regbitdef(flags, bitpos) BIT(bitpos)

I don't think it's useful to have the flags argument to these macros.
In the case of regdef(), it would be eliminated completed.

> +
> +#define gcrreg(reg, shift, bits) ((GCR_ ## reg) << 8 | (bits << 5) | (shift))
> +
> +/*
> + * GCR module
> + */
> +#define GCR_BA		0xF0800000
> +#define GCR_BANKSIZE	0x1000
> +
> +#define GCR_PDID	regdef(ro, 0x00)
> +
> +#define GCR_MFSEL1	regdef(rw, 0x0c)
> +#define GCR_MFSEL2	regdef(rw, 0x10)
> +#define GCR_MFSEL3	regdef(rw, 0x64)
> +#define GCR_MFSEL4	regdef(rw, 0xb0)
> +
> +#define GCR_CPCTL	regdef(xx,   0xD0)
> +#define GCR_CP2BST	regdef(rw1c, 0xD4)
> +#define GCR_B2CPNT	regdef(rw1s, 0xD8)
> +
> +#define GCR_I2CSEGSEL	regdef(rw, 0xE0)
> +
> +#define GCR_I2CSEGCTL	regdef(rw, 0xE4)
> +#define	  SMBXX_BITS	2
> +#define	  SMB0SS_SHIFT	0
> +#define	  SMB1SS_SHIFT	2
> +#define	  SMB2SS_SHIFT	4
> +#define	  SMB3SS_SHIFT	6
> +#define	  SMB4SS_SHIFT	8
> +#define	  SMB5SS_SHIFT	10
> +#define	  WEN0_SS	BIT(12)
> +#define	  WEN1_SS	BIT(13)
> +#define	  WEN2_SS	BIT(14)
> +#define	  WEN3_SS	BIT(15)
> +#define	  WEN4_SS	BIT(16)
> +#define	  WEN5_SS	BIT(17)
> +
> +#define GCR_SRCNT	regdef(rw, 0x68)
> +#define SRCNT_ESPI	   BIT(3)
> +/* SPI0D = 1:1
> + * SPI0C = 2:1
> + * ESPI	 = 3:1
> + * TDO	 = 4:1
> + */
> +#define GCR_FLOCKR1	regdef(xx, 0x74)
> +
> +#define GCR_DSCNT	regdef(rw, 0x78)
> +/* SPI0D = 1:1 (8,12)
> + * SPI0C = 2:1 (8,12)
> + * SYNC1 = 3:1 (4,8)
> + * ESPI	 = 6:2 (8,12,16,24)
> + * SPLD	 = 9:1 (2,4)
> + */
> +
> +/*
> + * GPIO module
> + */
> +#define GPIO_BA		0xF0010000
> +#define GPIO_BANKSIZE	0x1000
> +#define GPIO_PER_BANK	32
> +#define GPIO_NBANKS	8
> +
> +#define GPnTLOCK1	regdef(rw, 0x00)
> +#define GPnDIN		regdef(ro, 0x04) /* Data IN */
> +#define GPnPOL		regdef(rw, 0x08) /* Polarity */
> +#define GPnDOUT		regdef(rw, 0x0c) /* Data OUT */
> +
> +#define GPnOE		regdef(rw, 0x10) /* Output Enable */
> +#define GPnOTYP		regdef(rw, 0x14)
> +#define GPnMP		regdef(rw, 0x18)
> +#define GPnPU		regdef(rw, 0x1c) /* Pull-up */
> +
> +#define GPnPD		regdef(rw, 0x20) /* Pull-down */
> +#define GPnDBNC		regdef(rw, 0x24) /* Debounce */
> +#define GPnEVTYP	regdef(rw, 0x28) /* Event Type */
> +#define GPnEVBE		regdef(rw, 0x2c) /* Event Both Edge */
> +
> +#define GPnOBL0		regdef(rw, 0x30)
> +#define GPnOBL1		regdef(rw, 0x34)
> +#define GPnOBL2		regdef(rw, 0x38)
> +#define GPnOBL3		regdef(rw, 0x3c)
> +
> +#define GPnEVEN		regdef(rw, 0x40) /* Event Enable */
> +#define GPnEVENS	regdef(wo, 0x44) /* Event Set (enable) */
> +#define GPnEVENC	regdef(wo, 0x48) /* Event Clear (disable) */
> +#define GPnEVST		regdef(rc, 0x4c) /* Event Status */
> +
> +#define GPnSPLCK	regdef(rs, 0x50)
> +#define GPnMPLCK	regdef(rs, 0x54)
> +#define GPnIEM		regdef(rw, 0x58) /* Input Enable */
> +#define GPnOSRC		regdef(rw, 0x5c)
> +
> +#define GPnODSC		regdef(rw, 0x60)
> +#define GPnDOS		regdef(wo, 0x68) /* Data OUT Set */
> +#define GPnDOC		regdef(wo, 0x6c) /* Data OUT Clear */
> +
> +#define GPnOES		regdef(wo, 0x70) /* Output Enable Set */
> +#define GPnOEC		regdef(wo, 0x74) /* Output Enable Clear */
> +#define GPnTLOCK2	regdef(w,  0x7c)

It's a bit jarring visually to have the lowercase 'n' in the macro
name, but that's a pretty nit-picky review comment :)

> +
> +/*
> + * I2C module
> + */

Why are these necessary in the gpio/pinctrl driver?

> +#define SMB_INTERRUPT  (64+32)
> +#define SMB_BA		0xF0080000
> +#define SMB_BANKSIZE	0x1000
> +#define SMB_NBANKS	16
> +
> +#define SMBnSDA		regdef(rw, 0x00)
> +#define SMBnST		regdef(xx, 0x02)
> +#define	 ST_SLVSTP	   regbitdef(rw1c, 7)
> +#define	 ST_SDAST	   regbitdef(ro,   6)
> +#define	 ST_BER		   regbitdef(rw1c, 5)
> +#define	 ST_NEGACK	   regbitdef(rw1c, 4)
> +#define	 ST_STASTR	   regbitdef(rw1c, 3)
> +#define	 ST_NMATCH	   regbitdef(rw1c, 2)
> +#define	 ST_MASTER	   regbitdef(ro,   1)
> +#define	 ST_XMIT	   regbitdef(ro,   0)
> +#define SMBnCST		regdef(xx, 0x04)
> +#define	 CST_ARPMATCH	   regbitdef(ro,   7)
> +#define	 CST_MATCHAF	   regbitdef(ro,   6)
> +#define	 CST_TGSCL	   regbitdef(rw1s, 5)
> +#define	 CST_TDSDA	   regbitdef(ro,   4)
> +#define	 CST_GCMATCH	   regbitdef(ro,   3)
> +#define	 CST_MATCH	   regbitdef(ro,   2)
> +#define	 CST_BB		   regbitdef(rw1c, 1)
> +#define	 CST_BUSY	   regbitdef(ro,   0)
> +#define SMBnCTL1	regdef(xx, 0x06)
> +#define	 CTL_STASTRE	   regbitdef(rw,   7)
> +#define	 CTL_NMINTE	   regbitdef(rw,   6)
> +#define	 CTL_GCMEN	   regbitdef(rw,   5)
> +#define	 CTL_ACK	   regbitdef(rw,   4)
> +#define	 CTL_EOBINTE	   regbitdef(rw,   3)
> +#define	 CTL_INTEN	   regbitdef(rw,   2)
> +#define	 CTL_STOP	   regbitdef(rw1s, 1)
> +#define	 CTL_START	   regbitdef(rw1s, 0)
> +#define SMBnADDR1	regdef(rw, 0x08)
> +#define SMBnCTL2	regdef(rw, 0x0a)
> +#define	 CTL_SCLFREQ06	   regbitdef(rw,   1)
> +#define	 CTL_ENABLE	   regbitdef(rw,   0)
> +#define SMBnADDR2	regdef(rw, 0x0c)
> +#define SMBnCTL3	regdef(xx, 0x0e)
> +#define SMBnADDR3	regdef(rw, 0x10)
> +#define SMBnADDR7	regdef(rw, 0x11)
> +#define SMBnADDR4	regdef(rw, 0x12)
> +#define SMBnADDR8	regdef(rw, 0x13)
> +#define SMBnADDR5	regdef(rw, 0x14)
> +#define SMBnADDR6	regdef(rw, 0x16)
> +#define SMBnCST2	regdef(ro, 0x18)
> +#define SMBnCST3	regdef(xx, 0x19)
> +#define SMBnCTL4	regdef(rw, 0x1a)
> +#define SMBnCTL5	regdef(rw, 0x1b)
> +#define SMBnSCLLT	regdef(rw, 0x1c)
> +#define SMBnFIF_CTL	regdef(xx, 0x1d)
> +#define SMBnSCLHT	regdef(rw, 0x1e)
> +
> +/* Structure for register banks */
> +struct npcm_reg {
> +	u8		*base;
> +	int		irqbase;
> +	int		irq;
> +	spinlock_t	lock;
> +	void		*priv;
> +};
> +
> +static inline u8 npcm_read8(const void __iomem *addr)
> +{
> +	return *(const u8 *)addr;
> +}
> +
> +static inline void npcm_write8(void __iomem *addr, u8 val)
> +{
> +	*(u8 *)addr = val;
> +}
> +
> +static inline void npcm_setbit8(void __iomem *addr, u8 mask)
> +{
> +	*(u8 *)addr |= mask;
> +}
> +
> +static inline void npcm_clrbit8(void __iomem *addr, u8 mask)
> +{
> +	*(u8 *)addr &= ~mask;
> +}
> +
> +static inline u16 npcm_read16(const void __iomem *addr)
> +{
> +	return *(const u16 *)addr;
> +}
> +
> +static inline void npcm_write16(void __iomem *addr, u16 val)
> +{
> +	*(u16 *)addr = val;
> +}
> +
> +static inline void npcm_setbit16(void __iomem *addr, u16 mask)
> +{
> +	*(u16 *)addr |= mask;
> +}
> +
> +static inline void npcm_clrbit16(void __iomem *addr, u16 mask)
> +{
> +	*(u16 *)addr &= ~mask;
> +}
> +
> +static inline u32 npcm_read32(const void __iomem *addr)
> +{
> +	return *(const u32 *)addr;
> +}
> +
> +static inline void npcm_write32(void __iomem *addr, u32 val)
> +{
> +	*(u32 *)addr = val;
> +}
> +
> +static inline void npcm_setbit32(void __iomem *addr, u32 mask)
> +{
> +	*(u32 *)addr |= mask;
> +}
> +
> +static inline void npcm_clrbit32(void __iomem *addr, u32 mask)
> +{
> +	*(u32 *)addr &= ~mask;
> +}
> +
> +/* Read-modify-Write register */
> +static inline void npcm_rmw32(void __iomem *addr, int shift, int bits, u32 nv)
> +{
> +	u32 v, mask = (1L << bits)-1;
> +
> +	v = npcm_read32(addr) & ~(mask << shift);
> +	npcm_write32(addr, v | ((nv & mask) << shift));
> +}
> +
> +static inline void npcm_rmw8(void __iomem *addr, int shift, int bits, u8 nv)
> +{
> +	u8 v, mask = (1L << bits)-1;
> +
> +	v = npcm_read32(addr) & ~(mask << shift);
> +	npcm_write32(addr, v | ((nv & mask) << shift));
> +}

All of the above should be removed. Instead, use the kernel's existing
accessor functions like {read,write}{b,w,l}(), and open-code the
bitops.

> +#endif
> diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
> new file mode 100644
> index 000000000000..7b2a92deba70
> --- /dev/null
> +++ b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
> @@ -0,0 +1,2157 @@
> +/*
> + * Copyright (c) 2016, Dell Inc
> + * Copyright (c) 2016-2017 Nuvoton Technology corporation.
> + *
> + * Released under the GPLv2 only.
> + * SPDX-License-Identifier: GPL-2.0
> + */
> +
> +#include <linux/module.h>
> +#include <linux/version.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/pinctrl/pinctrl.h>
> +#include <linux/pinctrl/pinmux.h>
> +#include <linux/pinctrl/pinconf.h>
> +#include <linux/pinctrl/pinconf-generic.h>
> +#include <linux/pinctrl/machine.h>
> +#include <linux/interrupt.h>
> +#include <linux/gpio.h>
> +#include <linux/sysfs.h>
> +#include <linux/irq.h>
> +
> +#include <linux/slab.h>
> +
> +#ifdef CONFIG_OF
> +#include <linux/of.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_address.h>
> +#endif
> +#include <linux/device.h>
> +
> +#include "npcmreg.h"
> +
> +#define DRV_DATE    "2016-10-15"
> +#define DRV_VERSION "1.0.0"
> +
> +#undef DRV_MSG2
> +#define DRV_MSG2(x...)
> +#define GPIO_DRIVER
> +
> +
> +//#define irq_set_handler_locked(x, y) __irq_set_handler_locked(x->irq, y)
> +
> +#define GCR_BANK  8
> +static struct npcm_reg npcm_bank[9];
> +
> +struct npcm_dev {
> +	struct pinctrl_dev *pctl;
> +	struct platform_device *pdev;
> +	struct gpio_chip gc;
> +	struct irq_domain *domain;

IRQs should be handled through the gpiochip_irqchip_*() abstraction.

> +};
> +
> +static struct npcm_dev npcm;

This should go away with some suggestions below.

> +
> +#define gpiochip_to_data(_gc) container_of(_gc, struct npcm_dev, gc)
> +
> +#define gcrreg(reg, shift, bits) ((GCR_ ## reg) << 8 | (bits << 5) | (shift))
> +enum {
> +	opSET,
> +	opGETBIT,
> +	opSETBIT,
> +	opCLRBIT,
> +};

Anonymous enum?

> +
> +/* Helper function to setup IRQ, ioremap, spinlocks per register block */
> +static int npcm_init_bank(int id, u32 base, size_t sz, int irqid,
> +			  const char *dts)
> +{
> +	int irq = 0;
> +
> +#ifdef CONFIG_OF

I don't think the ifdef is necessary - won't dts be NULL if CONFIG_OF
is undefined?

> +	struct device_node *np;
> +	struct of_device_id dt_id[2] = { };
> +	struct resource res;
> +	int ret;
> +
> +	if (dts != NULL) {
> +		snprintf(dt_id[0].compatible, sizeof(dt_id[0].compatible),
> +			 "%s", dts);
> +		np = of_find_matching_node(NULL, dt_id);
> +		if (np != NULL) {
> +			ret = of_address_to_resource(np, 0, &res);
> +			if (ret) {
> +				pr_err("of_address_to_resource pinctrl failed\n");
> +				return -1;
> +			}
> +			base = res.start+(id*sz);
> +			irq = irq_of_parse_and_map(np, irqid);
> +		}

This looks strange. I'll keep reading to better understand what you're
trying to do here, but I suspect there are better ways of mapping the
banks.

> +	}
> +#endif
> +	if (id >= ARRAY_SIZE(npcm_bank))
> +		return -1;
> +	npcm_bank[id].base = ioremap(base, sz);
> +	pr_debug("[%d] iomap: %.8x, %.8x = %p irq:%d\n",
> +		id, base, sz, npcm_bank[id].base, irq);
> +	if (!npcm_bank[id].base)
> +		return -1;
> +	spin_lock_init(&npcm_bank[id].lock);
> +	npcm_bank[id].irq = irq;
> +	return 0;
> +}
> +
> +/* Perform locked bit operations on GPIO registers */
> +static int gpio_bitop(int op, int offset, int reg)
> +{
> +	struct npcm_reg *bank;
> +	unsigned long flags;
> +	u32 mask;
> +
> +	bank = &npcm_bank[offset / GPIO_PER_BANK];
> +	mask = (1L << (offset % GPIO_PER_BANK));
> +	spin_lock_irqsave(&bank->lock, flags);
> +	switch (op) {
> +	case opSET:
> +		npcm_write32(bank->base + reg, mask);
> +		break;
> +	case opGETBIT:
> +		mask &= npcm_read32(bank->base + reg);
> +		break;
> +	case opSETBIT:
> +		npcm_setbit32(bank->base + reg, mask);
> +		break;
> +	case opCLRBIT:
> +		npcm_clrbit32(bank->base + reg, mask);
> +		break;
> +	}
> +	spin_unlock_irqrestore(&bank->lock, flags);
> +	return !!mask;

This helper should go away; I suspect at some point you'll want to
modify multple registers in concert, in which case you'll want to lock
across the group of operations and not for each individual operation.
Otherwise it's racy in that multiple processes changing the state of
the controller can see inconsistent state.

Taking this helper away also eliminates the need for the
op{SET,GETBIT,SETBIT,CLRBIT} enum. We can just open code these
operations.

> +}
> +
> +/*
> + * GPIO code
> + */
> +
> +/* Helper function to get GPIO direction */
> +static int _npcmgpio_get_direction(unsigned int gpio)
> +{
> +	u32 oe, ie;
> +
> +	/* Get Input & Output state */
> +	ie = gpio_bitop(opGETBIT, gpio, GPnIEM);
> +	oe = gpio_bitop(opGETBIT, gpio, GPnOE);

For example here, you should probably just lock once and read both of
these offsets under the one lock acquisition.

> +	if (ie && !oe)
> +		return GPIOF_DIR_IN;
> +	else if (oe && !ie)
> +		return GPIOF_DIR_OUT;
> +	return -EINVAL;
> +}
> +
> +/* Dump GPIO and GCR registers */
> +static void npcmgpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
> +{
> +	int module;
> +	void *base;
> +
> +	for (module = 0; module < 8; module++) {
> +		base = npcm_bank[module].base;
> +		seq_printf(s, "-- module %d [gpio%d - %d]\n", module,
> +			   module * GPIO_PER_BANK,
> +			   (module * GPIO_PER_BANK) + GPIO_PER_BANK - 1);
> +		seq_printf(s, "DIN :%.8x DOUT:%.8x IE  :%.8x OE	 :%.8x\n",
> +			   npcm_read32(base + GPnDIN),
> +			   npcm_read32(base + GPnDOUT),
> +			   npcm_read32(base + GPnIEM),
> +			   npcm_read32(base + GPnOE));
> +		seq_printf(s, "PU  :%.8x PD  :%.8x DB  :%.8x POL :%.8x\n",
> +			   npcm_read32(base + GPnPU),
> +			   npcm_read32(base + GPnPD),
> +			   npcm_read32(base + GPnDBNC),
> +			   npcm_read32(base + GPnPOL));
> +		seq_printf(s, "ETYP:%.8x EVBE:%.8x EVEN:%.8x EVST:%.8x\n",
> +			   npcm_read32(base + GPnEVTYP),
> +			   npcm_read32(base + GPnEVBE),
> +			   npcm_read32(base + GPnEVEN),
> +			   npcm_read32(base + GPnEVST));
> +		seq_printf(s, "OTYP:%.8x OSRC:%.8x ODSC:%.8x\n",
> +			   npcm_read32(base + GPnOTYP),
> +			   npcm_read32(base + GPnOSRC),
> +			   npcm_read32(base + GPnODSC));
> +		seq_printf(s, "OBL0:%.8x OBL1:%.8x OBL2:%.8x OBL3:%.8x\n",
> +			   npcm_read32(base + GPnOBL0),
> +			   npcm_read32(base + GPnOBL1),
> +			   npcm_read32(base + GPnOBL2),
> +			   npcm_read32(base + GPnOBL3));
> +		seq_printf(s, "SLCK:%.8x MLCK:%.8x\n",
> +			   npcm_read32(base + GPnSPLCK),
> +			   npcm_read32(base + GPnMPLCK));
> +	}
> +	seq_puts(s, "-- GCR\n");
> +	base = npcm_bank[GCR_BANK].base;
> +	seq_printf(s, "MFSEL1:%.8x MFSEL2:%.8x MFSEL3:%.8x MFSEL4:%.8x I2C:%.8x FLOCKR1:%.8x\n",
> +		   npcm_read32(base + GCR_MFSEL1),
> +		   npcm_read32(base + GCR_MFSEL2),
> +		   npcm_read32(base + GCR_MFSEL3),
> +		   npcm_read32(base + GCR_MFSEL4),
> +		   npcm_read32(base + GCR_I2CSEGSEL),
> +		   npcm_read32(base + GCR_FLOCKR1));
> +}
> +
> +/* Get direction of GPIO pin */
> +static int npcmgpio_get_direction(struct gpio_chip *chip, unsigned int offset)
> +{
> +	unsigned int gpio = chip->base + offset;
> +
> +	DRV_MSG2("gpio_get_direction: gpio%d\n", gpio);
> +	return _npcmgpio_get_direction(gpio);
> +}
> +
> +/* Set GPIO to Input */
> +static int npcmgpio_direction_input(struct gpio_chip *chip, unsigned int offset)
> +{
> +	unsigned int gpio = chip->base + offset;
> +
> +	DRV_MSG2("%s: %d\n", __func__, gpio);
> +	return pinctrl_gpio_direction_input(gpio);
> +}
> +
> +/* Set GPIO to Output with initial value */
> +static int npcmgpio_direction_output(struct gpio_chip *chip,
> +				     unsigned int offset, int value)
> +{
> +	unsigned int gpio = chip->base + offset;
> +
> +	DRV_MSG2("gpio_direction_output: gpio%d = %x\n", gpio, value);
> +	/* Check if we're enabled as an interrupt.. */
> +	if (gpio_bitop(opGETBIT, gpio, GPnEVEN) &&
> +	    gpio_bitop(opGETBIT, gpio, GPnIEM)) {
> +		pr_info("gpio_direction_output: IRQ enabled on gpio%d\n",
> +			gpio);
> +		return -EINVAL;

Why not disable it and switch the output?

> +	}
> +	gpio_bitop(opSETBIT, gpio, value ? GPnDOS : GPnDOC);
> +	return pinctrl_gpio_direction_output(gpio);
> +}
> +
> +/* Retrieve value of GPIO */
> +static int npcmgpio_get_value(struct gpio_chip *chip, unsigned int offset)
> +{
> +	unsigned int gpio = chip->base + offset;
> +	int dir;
> +
> +	DRV_MSG2("gpio_get: gpio%d\n", gpio);
> +	dir = _npcmgpio_get_direction(gpio);
> +	return gpio_bitop(opGETBIT, gpio, dir == GPIOF_DIR_OUT ?
> +			  GPnDOUT : GPnDIN);
> +}
> +
> +/* Set value of Output GPIO */
> +static void npcmgpio_set_value(struct gpio_chip *chip, unsigned int offset,
> +			       int value)
> +{
> +	unsigned int gpio = chip->base + offset;
> +
> +	DRV_MSG2("gpio_set: gpio%d = %x\n", gpio, value);
> +	if (_npcmgpio_get_direction(gpio) == GPIOF_DIR_OUT)
> +		gpio_bitop(opSETBIT, gpio, value ? GPnDOS : GPnDOC);
> +}
> +
> +#if (KERNEL_VERSION(4, 10, 17) >= LINUX_VERSION_CODE)
> +/* Set GPIO Debounce mode */
> +static int npcmgpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
> +				 unsigned int debounce)
> +{
> +	unsigned int gpio = chip->base + offset;
> +
> +	DRV_MSG2("gpio_set_debounce: gpio%d = %d\n", gpio, debounce);
> +	gpio_bitop(debounce ? opSETBIT : opCLRBIT, gpio, GPnDBNC);
> +	return 0;
> +}
> +#endif
> +
> +#if ((KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE) && (KERNEL_VERSION(4, 10, 17) >= LINUX_VERSION_CODE))
> +/* Set open-drain or push-pull mode */
> +static int npcmgpio_set_single_ended(struct gpio_chip *chip,
> +				     unsigned int offset,
> +				     enum single_ended_mode mode)
> +{
> +	unsigned int gpio = chip->base + offset;
> +
> +	DRV_MSG2("gpio_set_single_ended: gpio%d mode:%d\n", gpio, mode);
> +	if (mode == LINE_MODE_PUSH_PULL)
> +		gpio_bitop(opCLRBIT, gpio, GPnOTYP);
> +	else if (mode == LINE_MODE_OPEN_DRAIN)
> +		gpio_bitop(opSETBIT, gpio, GPnOTYP);
> +	else
> +		return -EINVAL;
> +	return 0;
> +}
> +#endif
> +
> +/* Dynamically allocate IRQ for GPIO */
> +static int npcmgpio_to_irq(struct gpio_chip *chip, unsigned int offset)
> +{
> +	struct npcm_dev *npcm = gpiochip_to_data(chip);
> +	unsigned int gpio = chip->base + offset;
> +	int irq;
> +
> +	/* Allocate interrupt on demand */
> +	irq = irq_create_mapping(npcm->domain, gpio);
> +	DRV_MSG2("gpio_to_irq: gpio%d = %d\n", gpio, irq);
> +	if (!irq)
> +		return -EINVAL;
> +	return irq;
> +}
> +
> +/* Request GPIO */
> +static int npcmgpio_gpio_request(struct gpio_chip *chip, unsigned int offset)
> +{
> +	unsigned int gpio = chip->base + offset;
> +
> +	DRV_MSG2("gpio_request: gpio%d\n", gpio);
> +	return pinctrl_request_gpio(gpio);
> +}
> +
> +/* Release GPIO */
> +static void npcmgpio_gpio_free(struct gpio_chip *chip, unsigned int offset)
> +{
> +	unsigned int gpio = chip->base + offset;
> +
> +	DRV_MSG2("gpio_free: gpio%d\n", gpio);
> +	pinctrl_free_gpio(gpio);
> +}
> +
> +/*
> + * IRQ code
> + */
> +#ifdef GPIO_DRIVER
> +static void npcmgpio_irq_handler(struct irq_desc *desc)
> +{
> +	struct irq_chip *chip;
> +	struct npcm_reg *bank;
> +	u32 sts, en, bit, virq;
> +
> +	chip = irq_desc_get_chip(desc);
> +	bank = irq_desc_get_handler_data(desc);
> +
> +	chained_irq_enter(chip, desc);
> +	sts = npcm_read32(bank->base + GPnEVST);
> +	en  = npcm_read32(bank->base + GPnEVEN);
> +	DRV_MSG2("==> got irq sts %.8x %.8x\n", sts, en);
> +
> +	sts &= en;
> +	for_each_set_bit(bit, (const void *)&sts, GPIO_PER_BANK) {
> +		virq = irq_find_mapping(npcm.domain, bank->irqbase + bit);
> +		pr_info(" gpio:%u irq:%u\n", bank->irqbase + bit, virq);
> +		if (virq) {
> +			/* Pass off to virtual interrupt handler */
> +			generic_handle_irq(virq);
> +		} else {
> +			DRV_MSG2("gpio_irq_handler: spurious interrupt...\n");
> +			gpio_bitop(opCLRBIT, bank->irqbase + bit, GPnEVEN);
> +			gpio_bitop(opSETBIT, bank->irqbase + bit, GPnEVST);
> +		}
> +	}
> +	chained_irq_exit(chip, desc);
> +}
> +#endif
> +
> +/* Set trigger type of GPIO interrupt */
> +static int npcmgpio_set_irq_type(struct irq_data *d, unsigned int type)
> +{
> +	unsigned int gpio = d->hwirq;
> +	struct npcm_reg *bank;
> +
> +	DRV_MSG2("setirqtype: %u.%u = %u\n", gpio, d->irq, type);
> +	bank = irq_get_handler_data(d->irq);
> +	switch (type) {
> +	case IRQ_TYPE_EDGE_RISING:
> +		/* EVTYP=1, POL=0, EVBE=0 */
> +		DRV_MSG2("	edge.rising\n");
> +		gpio_bitop(opCLRBIT, gpio, GPnEVBE);
> +		gpio_bitop(opCLRBIT, gpio, GPnPOL);
> +		break;
> +	case IRQ_TYPE_EDGE_FALLING:
> +		/* EVTYP=1, POL=1, EVBE=1 */
> +		DRV_MSG2("	edge.falling\n");
> +		gpio_bitop(opCLRBIT, gpio, GPnEVBE);
> +		gpio_bitop(opSETBIT, gpio, GPnPOL);
> +		break;
> +	case IRQ_TYPE_EDGE_BOTH:
> +		/* EVTYP=1, POL=0, EVBE=1 */
> +		DRV_MSG2("	edge.both\n");
> +		gpio_bitop(opSETBIT, gpio, GPnEVBE);
> +		break;
> +	case IRQ_TYPE_LEVEL_LOW:
> +		/* EVTYP=0, POL=1 */
> +		DRV_MSG2("	level.low\n");
> +		gpio_bitop(opSETBIT, gpio, GPnPOL);
> +		break;
> +	case IRQ_TYPE_LEVEL_HIGH:
> +		/* EVTYP=0, POL=0 */
> +		DRV_MSG2("	level.high\n");
> +		gpio_bitop(opCLRBIT, gpio, GPnPOL);
> +		break;
> +	default:
> +		DRV_MSG2("	invalid irq type\n");
> +		return -EINVAL;
> +	}
> +	if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
> +		gpio_bitop(opCLRBIT, gpio, GPnEVTYP);
> +		irq_set_handler_locked(d, handle_level_irq);
> +	} else if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
> +		gpio_bitop(opSETBIT, gpio, GPnEVTYP);
> +		irq_set_handler_locked(d, handle_edge_irq);
> +	}
> +	return 0;
> +}
> +
> +/* ACK GPIO interrupt */
> +static void npcmgpio_irq_ack(struct irq_data *d)
> +{
> +	unsigned int gpio = d->hwirq;
> +
> +	DRV_MSG2("irq_ack: %u.%u\n", gpio, d->irq);
> +	gpio_bitop(opSET, gpio, GPnEVST);
> +}
> +
> +/* Disable GPIO interrupt */
> +static void npcmgpio_irq_mask(struct irq_data *d)
> +{
> +	unsigned int gpio = d->hwirq;
> +
> +	/* Clear events */
> +	DRV_MSG2("irq_mask: %u.%u\n", gpio, d->irq);
> +	gpio_bitop(opSET, gpio, GPnEVENC);
> +}
> +
> +/* Enable GPIO interrupt */
> +static void npcmgpio_irq_unmask(struct irq_data *d)
> +{
> +	unsigned int gpio = d->hwirq;
> +
> +	/* Enable events */
> +	DRV_MSG2("irq_unmask: %u.%u\n", gpio, d->irq);
> +	gpio_bitop(opSET, gpio, GPnEVENS);
> +}
> +
> +/* Initialize GPIO interrupt */
> +static unsigned int npcmgpio_irq_startup(struct irq_data *d)
> +{
> +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
> +	unsigned int gpio = d->hwirq;
> +
> +	/* active-high, input, clear interrupt, enable interrupt */
> +	DRV_MSG2("startup: %u.%u\n", gpio, d->irq);
> +	npcmgpio_direction_output(gc, gpio, 1);
> +	npcmgpio_direction_input(gc, gpio);
> +	npcmgpio_irq_ack(d);
> +	npcmgpio_irq_unmask(d);
> +	return 0;
> +}
> +
> +static struct irq_chip npcmgpio_irqchip = {
> +	.name = "npcm",
> +	.irq_ack = npcmgpio_irq_ack,
> +	.irq_unmask = npcmgpio_irq_unmask,
> +	.irq_mask = npcmgpio_irq_mask,
> +	.irq_set_type = npcmgpio_set_irq_type,
> +	.irq_startup = npcmgpio_irq_startup,
> +};
> +
> +static int npcmgpio_irqdomain_map(struct irq_domain *dom,
> +				  unsigned int irq,
> +				  irq_hw_number_t hwirq)
> +{
> +	DRV_MSG2("irqdomainmap: %lu -> %u %p %p\n", hwirq, irq, &npcm,
> +		 dom->host_data);
> +	irq_set_chip_and_handler(irq, &npcmgpio_irqchip,
> +				 handle_simple_irq);
> +	irq_set_chip_data(irq, dom->host_data);
> +	return 0;
> +}
> +
> +static const struct irq_domain_ops npcmgpio_domain_ops = {
> +	.map = npcmgpio_irqdomain_map,
> +};
> +
> +/*
> + * PINCTRL code
> + */
> +
> +static const int smb0_pins[]  = { 115, 114 };
> +static const int smb0b_pins[] = { 195, 194 };
> +static const int smb0c_pins[] = { 202, 196 };
> +static const int smb0d_pins[] = { 198, 199 };
> +static const int smb0den_pins[] = { 197 };
> +
> +static const int smb1_pins[]  = { 117, 116 };
> +static const int smb1b_pins[] = { 126, 127 };
> +static const int smb1c_pins[] = { 124, 125 };
> +static const int smb1d_pins[] = { 4, 5 };
> +
> +static const int smb2_pins[]  = { 119, 118 };
> +static const int smb2b_pins[] = { 122, 123 };
> +static const int smb2c_pins[] = { 120, 121 };
> +static const int smb2d_pins[] = { 6, 7 };
> +
> +static const int smb3_pins[]  = { 30, 31 };
> +static const int smb3b_pins[] = { 39, 40 };
> +static const int smb3c_pins[] = { 37, 38 };
> +static const int smb3d_pins[] = { 59, 60 };
> +
> +static const int smb4_pins[]  = { 28, 29 };
> +static const int smb4b_pins[] = { 18, 19 };
> +static const int smb4c_pins[] = { 20, 21 };
> +static const int smb4d_pins[] = { 22, 23 };
> +static const int smb4den_pins[] = { 17 };
> +
> +static const int smb5_pins[]  = { 26, 27 };
> +static const int smb5b_pins[] = { 13, 12 };
> +static const int smb5c_pins[] = { 15, 14 };
> +static const int smb5d_pins[] = { 94, 93 };
> +static const int ga20kbc_pins[] = { 94, 93 };
> +
> +static const int smb6_pins[]  = { 172, 171 };
> +static const int smb7_pins[]  = { 174, 173 };
> +static const int smb8_pins[]  = { 129, 128 };
> +static const int smb9_pins[]  = { 131, 130 };
> +static const int smb10_pins[] = { 133, 132 };
> +static const int smb11_pins[] = { 135, 134 };
> +static const int smb12_pins[] = { 221, 220 };
> +static const int smb13_pins[] = { 223, 222 };
> +static const int smb14_pins[] = { 22, 23 };
> +static const int smb15_pins[] = { 20, 21 };
> +
> +static const int fanin0_pins[] = { 64 };
> +static const int fanin1_pins[] = { 65 };
> +static const int fanin2_pins[] = { 66 };
> +static const int fanin3_pins[] = { 67 };
> +static const int fanin4_pins[] = { 68 };
> +static const int fanin5_pins[] = { 69 };
> +static const int fanin6_pins[] = { 70 };
> +static const int fanin7_pins[] = { 71 };
> +static const int fanin8_pins[] = { 72 };
> +static const int fanin9_pins[] = { 73 };
> +static const int fanin10_pins[] = { 74 };
> +static const int fanin11_pins[] = { 75 };
> +static const int fanin12_pins[] = { 76 };
> +static const int fanin13_pins[] = { 77 };
> +static const int fanin14_pins[] = { 78 };
> +static const int fanin15_pins[] = { 79 };
> +static const int faninx_pins[] = { 175, 176, 177, 203 };
> +
> +static const int pwm0_pins[] = { 80 };
> +static const int pwm1_pins[] = { 81 };
> +static const int pwm2_pins[] = { 82 };
> +static const int pwm3_pins[] = { 83 };
> +static const int pwm4_pins[] = { 144 };
> +static const int pwm5_pins[] = { 145 };
> +static const int pwm6_pins[] = { 146 };
> +static const int pwm7_pins[] = { 147 };
> +
> +static const int uart1_pins[] = { 43, 44, 45, 46, 47, 61, 62, 63 };
> +static const int uart2_pins[] = { 48, 49, 50, 51, 52, 53, 54, 55 };
> +
> +static const int rg1_pins[] = { 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
> +	106, 107 };
> +static const int rg1mdio_pins[] = { 108, 109 };
> +
> +static const int rg2_pins[] = { 110, 111, 112, 113, 208, 209, 210, 211, 212,
> +	213, 214, 215 };
> +static const int rg2mdio_pins[] = { 216, 217 };
> +static const int ddr_pins[] = { 110, 111, 112, 113, 208, 209, 210, 211, 212,
> +	213, 214, 215, 216, 217 };
> +
> +static const int iox1_pins[] = { 0, 1, 2, 3 };
> +static const int iox2_pins[] = { 4, 5, 6, 7 };
> +static const int ioxh_pins[] = { 10, 11, 24, 25 };
> +
> +static const int mmc_pins[] = { 152, 154, 156, 157, 158, 159 };
> +static const int mmcwp_pins[] = { 153 };
> +static const int mmccd_pins[] = { 155 };
> +static const int mmcrst_pins[] = { 155 };
> +static const int mmc8_pins[] = { 148, 149, 150, 151 };
> +
> +static const int r1_pins[] = { 178, 179, 180, 181, 182, 193, 201 };
> +static const int r1err_pins[] = { 56 };
> +static const int r1md_pins[] = { 57, 58 };
> +
> +static const int r2_pins[] = { 84, 85, 86, 87, 88, 89, 200 };
> +static const int r2err_pins[] = { 90 };
> +static const int r2md_pins[] = { 91, 92 };
> +
> +static const int sd1_pins[] = { 136, 137, 138, 139, 140, 141, 142, 143 };
> +static const int sd1pwr_pins[] = { 143 };
> +
> +static const int wdog1_pins[] = { 218 };
> +static const int wdog2_pins[] = { 219 };
> +
> +static const int bmcuart0a_pins[] = { 41, 42 };
> +static const int bmcuart0b_pins[] = { 48, 49 };
> +
> +static const int bmcuart1_pins[] = { 43, 44, 62, 63 };
> +
> +static const int scipme_pins[] = { 169 };
> +static const int sci_pins[] = { 170 };
> +static const int serirq_pins[] = { 162 };
> +
> +static const int clkout_pins[] = { 160 };
> +static const int clkreq_pins[] = { 231 };
> +
> +static const int jtag2_pins[] = { 43, 44, 45, 46, 47 };
> +
> +static const int gspi_pins[] = { 12, 13, 14, 15 };
> +
> +static const int spix_pins[] = { 224, 225, 226, 227, 229, 230 };
> +static const int spixcs1_pins[] = { 228 };
> +
> +static const int pspi1_pins[] = { 175, 176, 177 };
> +static const int pspi2_pins[] = { 17, 18, 19 };
> +
> +static const int spi0quad_pins[] = { 33, 34 };
> +static const int spi0cs1_pins[] = { 32 };
> +static const int spi0cs2_pins[] = { 33 };
> +static const int spi0cs3_pins[] = { 34 };
> +
> +static const int spi3_pins[] = { 183, 184, 185, 186 };
> +static const int spi3cs1_pins[] = { 187 };
> +static const int spi3quad_pins[] = { 188, 189 };
> +static const int spi3cs2_pins[] = { 188 };
> +static const int spi3cs3_pins[] = { 189 };
> +
> +static const int ddc_pins[] = { 204, 205, 206, 207 };
> +
> +static const int lpc_pins[] = { 95, 161, 163, 164, 165, 166, 167 };
> +static const int espi_pins[] = { 95, 161, 163, 164, 165, 166, 167, 168 };
> +
> +static const int lkgpo0_pins[] = { 16 };
> +static const int lkgpo1_pins[] = { 8 };
> +static const int lkgpo2_pins[] = { 9 };
> +
> +static const int nprd_smi_pins[] = { 190 };
> +
> +/*
> + * pin:	     name, number
> + * group:    name, npins,   pins
> + * function: name, ngroups, groups
> + */
> +struct npcm_group {
> +	const char *name;
> +	const unsigned int *pins;
> +	int npins;
> +};
> +
> +#define NPCM_GRPS (\
> +	GRP(smb0), \
> +	GRP(smb0b), \
> +	GRP(smb0c), \
> +	GRP(smb0d), \
> +	GRP(smb0den), \
> +	GRP(smb1), \
> +	GRP(smb1b), \
> +	GRP(smb1c), \
> +	GRP(smb1d), \
> +	GRP(smb2), \
> +	GRP(smb2b), \
> +	GRP(smb2c), \
> +	GRP(smb2d), \
> +	GRP(smb3), \
> +	GRP(smb3b), \
> +	GRP(smb3c), \
> +	GRP(smb3d), \
> +	GRP(smb4), \
> +	GRP(smb4b), \
> +	GRP(smb4c), \
> +	GRP(smb4d), \
> +	GRP(smb4den), \
> +	GRP(smb5), \
> +	GRP(smb5b), \
> +	GRP(smb5c), \
> +	GRP(smb5d), \
> +	GRP(ga20kbc), \
> +	GRP(smb6), \
> +	GRP(smb7), \
> +	GRP(smb8), \
> +	GRP(smb9), \
> +	GRP(smb10), \
> +	GRP(smb11), \
> +	GRP(smb12), \
> +	GRP(smb13), \
> +	GRP(smb14), \
> +	GRP(smb15), \
> +	GRP(fanin0), \
> +	GRP(fanin1), \
> +	GRP(fanin2), \
> +	GRP(fanin3), \
> +	GRP(fanin4), \
> +	GRP(fanin5), \
> +	GRP(fanin6), \
> +	GRP(fanin7), \
> +	GRP(fanin8), \
> +	GRP(fanin9), \
> +	GRP(fanin10), \
> +	GRP(fanin11), \
> +	GRP(fanin12), \
> +	GRP(fanin13), \
> +	GRP(fanin14), \
> +	GRP(fanin15), \
> +	GRP(faninx), \
> +	GRP(pwm0), \
> +	GRP(pwm1), \
> +	GRP(pwm2), \
> +	GRP(pwm3), \
> +	GRP(pwm4), \
> +	GRP(pwm5), \
> +	GRP(pwm6), \
> +	GRP(pwm7), \
> +	GRP(rg1), \
> +	GRP(rg1mdio), \
> +	GRP(rg2), \
> +	GRP(rg2mdio), \
> +	GRP(ddr), \
> +	GRP(uart1), \
> +	GRP(uart2), \
> +	GRP(bmcuart0a), \
> +	GRP(bmcuart0b), \
> +	GRP(bmcuart1), \
> +	GRP(iox1), \
> +	GRP(iox2), \
> +	GRP(ioxh), \
> +	GRP(gspi), \
> +	GRP(mmc), \
> +	GRP(mmcwp), \
> +	GRP(mmccd), \
> +	GRP(mmcrst), \
> +	GRP(mmc8), \
> +	GRP(r1), \
> +	GRP(r1err), \
> +	GRP(r1md), \
> +	GRP(r2), \
> +	GRP(r2err), \
> +	GRP(r2md), \
> +	GRP(sd1), \
> +	GRP(sd1pwr), \
> +	GRP(wdog1), \
> +	GRP(wdog2), \
> +	GRP(scipme), \
> +	GRP(sci), \
> +	GRP(serirq), \
> +	GRP(jtag2), \
> +	GRP(spix), \
> +	GRP(spixcs1), \
> +	GRP(pspi1), \
> +	GRP(pspi2), \
> +	GRP(ddc), \
> +	GRP(clkreq), \
> +	GRP(clkout), \
> +	GRP(spi3), \
> +	GRP(spi3cs1), \
> +	GRP(spi3quad), \
> +	GRP(spi3cs2), \
> +	GRP(spi3cs3), \
> +	GRP(spi0cs1), \
> +	GRP(spi0cs2), \
> +	GRP(spi0cs3), \
> +	GRP(spi0quad), \
> +	GRP(lpc), \
> +	GRP(espi), \
> +	GRP(lkgpo0), \
> +	GRP(lkgpo1), \
> +	GRP(lkgpo2), \
> +	GRP(nprd_smi), \
> +	) \
> +
> +/* Group enums */
> +enum {
> +#define GRP(x) fn_ ## x
> +	NPCM_GRPS
> +	/* add placeholder for none/gpio */
> +	GRP(none),
> +	GRP(gpio),
> +#undef GRP
> +};
> +
> +/* Group names/pins */
> +static struct npcm_group npcm_groups[] = {
> +#define GRP(x) { .name = #x, .pins = x ## _pins, .npins = ARRAY_SIZE(x ## _pins) }
> +	NPCM_GRPS
> +#undef GRP
> +};
> +
> +#define NPCM_SFUNC(a) NPCM_FUNC(a, #a)
> +#define NPCM_FUNC(a, b...) static const char *a ## _grp[] = { b }
> +#define NPCM_MKFUNC(nm) { .name = #nm, .ngroups = ARRAY_SIZE(nm ## _grp), .groups = nm ## _grp }
> +struct npcm_func {
> +	const char *name;
> +	const unsigned int ngroups;
> +	const char *const *groups;
> +};
> +
> +NPCM_SFUNC(smb0);
> +NPCM_SFUNC(smb0b);
> +NPCM_SFUNC(smb0c);
> +NPCM_SFUNC(smb0d);
> +NPCM_SFUNC(smb0den);
> +NPCM_SFUNC(smb1);
> +NPCM_SFUNC(smb1b);
> +NPCM_SFUNC(smb1c);
> +NPCM_SFUNC(smb1d);
> +NPCM_SFUNC(smb2);
> +NPCM_SFUNC(smb2b);
> +NPCM_SFUNC(smb2c);
> +NPCM_SFUNC(smb2d);
> +NPCM_SFUNC(smb3);
> +NPCM_SFUNC(smb3b);
> +NPCM_SFUNC(smb3c);
> +NPCM_SFUNC(smb3d);
> +NPCM_SFUNC(smb4);
> +NPCM_SFUNC(smb4b);
> +NPCM_SFUNC(smb4c);
> +NPCM_SFUNC(smb4d);
> +NPCM_SFUNC(smb4den);
> +NPCM_SFUNC(smb5);
> +NPCM_SFUNC(smb5b);
> +NPCM_SFUNC(smb5c);
> +NPCM_SFUNC(smb5d);
> +NPCM_SFUNC(ga20kbc);
> +NPCM_SFUNC(smb6);
> +NPCM_SFUNC(smb7);
> +NPCM_SFUNC(smb8);
> +NPCM_SFUNC(smb9);
> +NPCM_SFUNC(smb10);
> +NPCM_SFUNC(smb11);
> +NPCM_SFUNC(smb12);
> +NPCM_SFUNC(smb13);
> +NPCM_SFUNC(smb14);
> +NPCM_SFUNC(smb15);
> +NPCM_SFUNC(fanin0);
> +NPCM_SFUNC(fanin1);
> +NPCM_SFUNC(fanin2);
> +NPCM_SFUNC(fanin3);
> +NPCM_SFUNC(fanin4);
> +NPCM_SFUNC(fanin5);
> +NPCM_SFUNC(fanin6);
> +NPCM_SFUNC(fanin7);
> +NPCM_SFUNC(fanin8);
> +NPCM_SFUNC(fanin9);
> +NPCM_SFUNC(fanin10);
> +NPCM_SFUNC(fanin11);
> +NPCM_SFUNC(fanin12);
> +NPCM_SFUNC(fanin13);
> +NPCM_SFUNC(fanin14);
> +NPCM_SFUNC(fanin15);
> +NPCM_SFUNC(faninx);
> +NPCM_SFUNC(pwm0);
> +NPCM_SFUNC(pwm1);
> +NPCM_SFUNC(pwm2);
> +NPCM_SFUNC(pwm3);
> +NPCM_SFUNC(pwm4);
> +NPCM_SFUNC(pwm5);
> +NPCM_SFUNC(pwm6);
> +NPCM_SFUNC(pwm7);
> +NPCM_SFUNC(rg1);
> +NPCM_SFUNC(rg1mdio);
> +NPCM_SFUNC(rg2);
> +NPCM_SFUNC(rg2mdio);
> +NPCM_SFUNC(ddr);
> +NPCM_SFUNC(uart1);
> +NPCM_SFUNC(uart2);
> +NPCM_SFUNC(bmcuart0a);
> +NPCM_SFUNC(bmcuart0b);
> +NPCM_SFUNC(bmcuart1);
> +NPCM_SFUNC(iox1);
> +NPCM_SFUNC(iox2);
> +NPCM_SFUNC(ioxh);
> +NPCM_SFUNC(gspi);
> +NPCM_SFUNC(mmc);
> +NPCM_SFUNC(mmcwp);
> +NPCM_SFUNC(mmccd);
> +NPCM_SFUNC(mmcrst);
> +NPCM_SFUNC(mmc8);
> +NPCM_SFUNC(r1);
> +NPCM_SFUNC(r1err);
> +NPCM_SFUNC(r1md);
> +NPCM_SFUNC(r2);
> +NPCM_SFUNC(r2err);
> +NPCM_SFUNC(r2md);
> +NPCM_SFUNC(sd1);
> +NPCM_SFUNC(sd1pwr);
> +NPCM_SFUNC(wdog1);
> +NPCM_SFUNC(wdog2);
> +NPCM_SFUNC(scipme);
> +NPCM_SFUNC(sci);
> +NPCM_SFUNC(serirq);
> +NPCM_SFUNC(jtag2);
> +NPCM_SFUNC(spix);
> +NPCM_SFUNC(spixcs1);
> +NPCM_SFUNC(pspi1);
> +NPCM_SFUNC(pspi2);
> +NPCM_SFUNC(ddc);
> +NPCM_SFUNC(clkreq);
> +NPCM_SFUNC(clkout);
> +NPCM_SFUNC(spi3);
> +NPCM_SFUNC(spi3cs1);
> +NPCM_SFUNC(spi3quad);
> +NPCM_SFUNC(spi3cs2);
> +NPCM_SFUNC(spi3cs3);
> +NPCM_SFUNC(spi0cs1);
> +NPCM_SFUNC(spi0cs2);
> +NPCM_SFUNC(spi0cs3);
> +NPCM_SFUNC(spi0quad);
> +NPCM_SFUNC(lpc);
> +NPCM_SFUNC(espi);
> +NPCM_SFUNC(lkgpo0);
> +NPCM_SFUNC(lkgpo1);
> +NPCM_SFUNC(lkgpo2);
> +NPCM_SFUNC(nprd_smi);
> +
> +/* Function names */
> +static struct npcm_func npcm_funcs[] = {
> +	NPCM_MKFUNC(smb0),
> +	NPCM_MKFUNC(smb0b),
> +	NPCM_MKFUNC(smb0c),
> +	NPCM_MKFUNC(smb0d),
> +	NPCM_MKFUNC(smb0den),
> +	NPCM_MKFUNC(smb1),
> +	NPCM_MKFUNC(smb1b),
> +	NPCM_MKFUNC(smb1c),
> +	NPCM_MKFUNC(smb1d),
> +	NPCM_MKFUNC(smb2),
> +	NPCM_MKFUNC(smb2b),
> +	NPCM_MKFUNC(smb2c),
> +	NPCM_MKFUNC(smb2d),
> +	NPCM_MKFUNC(smb3),
> +	NPCM_MKFUNC(smb3b),
> +	NPCM_MKFUNC(smb3c),
> +	NPCM_MKFUNC(smb3d),
> +	NPCM_MKFUNC(smb4),
> +	NPCM_MKFUNC(smb4b),
> +	NPCM_MKFUNC(smb4c),
> +	NPCM_MKFUNC(smb4d),
> +	NPCM_MKFUNC(smb4den),
> +	NPCM_MKFUNC(smb5),
> +	NPCM_MKFUNC(smb5b),
> +	NPCM_MKFUNC(smb5c),
> +	NPCM_MKFUNC(smb5d),
> +	NPCM_MKFUNC(ga20kbc),
> +	NPCM_MKFUNC(smb6),
> +	NPCM_MKFUNC(smb7),
> +	NPCM_MKFUNC(smb8),
> +	NPCM_MKFUNC(smb9),
> +	NPCM_MKFUNC(smb10),
> +	NPCM_MKFUNC(smb11),
> +	NPCM_MKFUNC(smb12),
> +	NPCM_MKFUNC(smb13),
> +	NPCM_MKFUNC(smb14),
> +	NPCM_MKFUNC(smb15),
> +	NPCM_MKFUNC(fanin0),
> +	NPCM_MKFUNC(fanin1),
> +	NPCM_MKFUNC(fanin2),
> +	NPCM_MKFUNC(fanin3),
> +	NPCM_MKFUNC(fanin4),
> +	NPCM_MKFUNC(fanin5),
> +	NPCM_MKFUNC(fanin6),
> +	NPCM_MKFUNC(fanin7),
> +	NPCM_MKFUNC(fanin8),
> +	NPCM_MKFUNC(fanin9),
> +	NPCM_MKFUNC(fanin10),
> +	NPCM_MKFUNC(fanin11),
> +	NPCM_MKFUNC(fanin12),
> +	NPCM_MKFUNC(fanin13),
> +	NPCM_MKFUNC(fanin14),
> +	NPCM_MKFUNC(fanin15),
> +	NPCM_MKFUNC(faninx),
> +	NPCM_MKFUNC(pwm0),
> +	NPCM_MKFUNC(pwm1),
> +	NPCM_MKFUNC(pwm2),
> +	NPCM_MKFUNC(pwm3),
> +	NPCM_MKFUNC(pwm4),
> +	NPCM_MKFUNC(pwm5),
> +	NPCM_MKFUNC(pwm6),
> +	NPCM_MKFUNC(pwm7),
> +	NPCM_MKFUNC(rg1),
> +	NPCM_MKFUNC(rg1mdio),
> +	NPCM_MKFUNC(rg2),
> +	NPCM_MKFUNC(rg2mdio),
> +	NPCM_MKFUNC(ddr),
> +	NPCM_MKFUNC(uart1),
> +	NPCM_MKFUNC(uart2),
> +	NPCM_MKFUNC(bmcuart0a),
> +	NPCM_MKFUNC(bmcuart0b),
> +	NPCM_MKFUNC(bmcuart1),
> +	NPCM_MKFUNC(iox1),
> +	NPCM_MKFUNC(iox2),
> +	NPCM_MKFUNC(ioxh),
> +	NPCM_MKFUNC(gspi),
> +	NPCM_MKFUNC(mmc),
> +	NPCM_MKFUNC(mmcwp),
> +	NPCM_MKFUNC(mmccd),
> +	NPCM_MKFUNC(mmcrst),
> +	NPCM_MKFUNC(mmc8),
> +	NPCM_MKFUNC(r1),
> +	NPCM_MKFUNC(r1err),
> +	NPCM_MKFUNC(r1md),
> +	NPCM_MKFUNC(r2),
> +	NPCM_MKFUNC(r2err),
> +	NPCM_MKFUNC(r2md),
> +	NPCM_MKFUNC(sd1),
> +	NPCM_MKFUNC(sd1pwr),
> +	NPCM_MKFUNC(wdog1),
> +	NPCM_MKFUNC(wdog2),
> +	NPCM_MKFUNC(scipme),
> +	NPCM_MKFUNC(sci),
> +	NPCM_MKFUNC(serirq),
> +	NPCM_MKFUNC(jtag2),
> +	NPCM_MKFUNC(spix),
> +	NPCM_MKFUNC(spixcs1),
> +	NPCM_MKFUNC(pspi1),
> +	NPCM_MKFUNC(pspi2),
> +	NPCM_MKFUNC(ddc),
> +	NPCM_MKFUNC(clkreq),
> +	NPCM_MKFUNC(clkout),
> +	NPCM_MKFUNC(spi3),
> +	NPCM_MKFUNC(spi3cs1),
> +	NPCM_MKFUNC(spi3quad),
> +	NPCM_MKFUNC(spi3cs2),
> +	NPCM_MKFUNC(spi3cs3),
> +	NPCM_MKFUNC(spi0cs1),
> +	NPCM_MKFUNC(spi0cs2),
> +	NPCM_MKFUNC(spi0cs3),
> +	NPCM_MKFUNC(spi0quad),
> +	NPCM_MKFUNC(lpc),
> +	NPCM_MKFUNC(espi),
> +	NPCM_MKFUNC(lkgpo0),
> +	NPCM_MKFUNC(lkgpo1),
> +	NPCM_MKFUNC(lkgpo2),
> +	NPCM_MKFUNC(nprd_smi),
> +};
> +
> +#define GCR_NONE 0
> +
> +#define PINCFG(a, b, c, d, e, f, g, h, i, j, k) \
> +	[a] { .fn0 = fn_ ## b, .reg0 = GCR_ ## c, .bit0 = d, \
> +			.fn1 = fn_ ## e, .reg1 = GCR_ ## f, .bit1 = g, \
> +			.fn2 = fn_ ## h, .reg2 = GCR_ ## i, .bit2 = j, \
> +			.flag = k }
> +
> +/* Drive strength controlled by GPnODSC */
> +#define DRIVE_STRENGTH_LO_SHIFT		8
> +#define DRIVE_STRENGTH_HI_SHIFT		12
> +#define DRIVE_STRENGTH_MASK		0x0000FF00
> +
> +#define DS(lo, hi)	(((lo) << DRIVE_STRENGTH_LO_SHIFT) | \
> +			 ((hi) << DRIVE_STRENGTH_HI_SHIFT))
> +#define DSLO(x)		(((x) >> DRIVE_STRENGTH_LO_SHIFT) & 0xF)
> +#define DSHI(x)		(((x) >> DRIVE_STRENGTH_HI_SHIFT) & 0xF)

These macro names seem a bit terse.

> +
> +#define GPI		0x1 /* Not GPO */
> +#define GPO		0x2 /* Not GPI */
> +#define SLEW		0x4 /* Has Slew Control, GPnOSRC */
> +#define SLEWLPC		0x8 /* Has Slew Control, SRCNT.3 */
> +
> +struct npcm_pincfg {
> +	int flag;
> +	int fn0, reg0, bit0;
> +	int fn1, reg1, bit1;
> +	int fn2, reg2, bit2;
> +};
> +
> +static const struct npcm_pincfg pincfg[] = {
> +	/*	PIN	  FUNCTION 1		   FUNCTION 2		  FUNCTION 3	    FLAGS */
> +	PINCFG(0,	 iox1, MFSEL1, 30,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(1,	 iox1, MFSEL1, 30,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(2,	 iox1, MFSEL1, 30,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(3,	 iox1, MFSEL1, 30,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(4,	 iox2, MFSEL3, 14,	 smb1d, I2CSEGSEL, 7,	none, NONE, 0,	     SLEW),
> +	PINCFG(5,	 iox2, MFSEL3, 14,	 smb1d, I2CSEGSEL, 7,	none, NONE, 0,	     SLEW),
> +	PINCFG(6,	 iox2, MFSEL3, 14,	 smb2d, I2CSEGSEL, 10,  none, NONE, 0,       SLEW),
> +	PINCFG(7,	 iox2, MFSEL3, 14,	 smb2d, I2CSEGSEL, 10,  none, NONE, 0,       SLEW),
> +	PINCFG(8,      lkgpo1, FLOCKR1, 4,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(9,      lkgpo2, FLOCKR1, 8,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(10,	 ioxh, MFSEL3, 18,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(11,	 ioxh, MFSEL3, 18,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(12,	 gspi, MFSEL1, 24,	 smb5b, I2CSEGSEL, 19,  none, NONE, 0,	     SLEW),
> +	PINCFG(13,	 gspi, MFSEL1, 24,	 smb5b, I2CSEGSEL, 19,  none, NONE, 0,	     SLEW),
> +	PINCFG(14,	 gspi, MFSEL1, 24,	 smb5c, I2CSEGSEL, 20,	none, NONE, 0,	     SLEW),
> +	PINCFG(15,	 gspi, MFSEL1, 24,	 smb5c, I2CSEGSEL, 20,	none, NONE, 0,	     SLEW),
> +	PINCFG(16,     lkgpo0, FLOCKR1, 0,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(17,      pspi2, MFSEL3, 13,     smb4den, I2CSEGSEL, 23,  none, NONE, 0,       DS(8, 12)),
> +	PINCFG(18,      pspi2, MFSEL3, 13,	 smb4b, I2CSEGSEL, 14,  none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(19,      pspi2, MFSEL3, 13,	 smb4b, I2CSEGSEL, 14,  none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(20,	smb4c, I2CSEGSEL, 15,    smb15, MFSEL3, 8,      none, NONE, 0,	     0),
> +	PINCFG(21,	smb4c, I2CSEGSEL, 15,    smb15, MFSEL3, 8,      none, NONE, 0,	     0),
> +	PINCFG(22,      smb4d, I2CSEGSEL, 16,	 smb14, MFSEL3, 7,      none, NONE, 0,	     0),
> +	PINCFG(23,      smb4d, I2CSEGSEL, 16,	 smb14, MFSEL3, 7,      none, NONE, 0,	     0),
> +	PINCFG(24,	 ioxh, MFSEL3, 18,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(25,	 ioxh, MFSEL3, 18,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(26,	 smb5, MFSEL1, 2,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(27,	 smb5, MFSEL1, 2,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(28,	 smb4, MFSEL1, 1,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(29,	 smb4, MFSEL1, 1,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(30,	 smb3, MFSEL1, 0,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(31,	 smb3, MFSEL1, 0,	  none, NONE, 0,	none, NONE, 0,	     0),
> +
> +	PINCFG(32,    spi0cs1, MFSEL1, 3,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(33,   spi0quad, MFSEL4, 15,     spi0cs2, MFSEL1, 4,	none, NONE, 0,	     SLEW),  /* cs2=Z1 */
> +	PINCFG(34,   spi0quad, MFSEL4, 15,     spi0cs3, MFSEL1, 5,	none, NONE, 0,	     SLEW),  /* cs3=Z1 */
> +	PINCFG(37,	smb3c, I2CSEGSEL, 12,	  none, NONE, 0,	none, NONE, 0,	     SLEW),
> +	PINCFG(38,	smb3c, I2CSEGSEL, 12,	  none, NONE, 0,	none, NONE, 0,	     SLEW),
> +	PINCFG(39,	smb3b, I2CSEGSEL, 11,	  none, NONE, 0,	none, NONE, 0,	     SLEW),
> +	PINCFG(40,	smb3b, I2CSEGSEL, 11,	  none, NONE, 0,	none, NONE, 0,	     SLEW),
> +	PINCFG(41,  bmcuart0a, MFSEL1, 9,         none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(42,  bmcuart0a, MFSEL1, 9,         none, NONE, 0,	none, NONE, 0,	     DS(2, 4) | GPO),
> +	PINCFG(43,      uart1, MFSEL1, 10,	 jtag2, MFSEL4, 0,  bmcuart1, MFSEL3, 24,    0),
> +	PINCFG(44,      uart1, MFSEL1, 10,	 jtag2, MFSEL4, 0,  bmcuart1, MFSEL3, 24,    0),
> +	PINCFG(45,      uart1, MFSEL1, 10,	 jtag2, MFSEL4, 0,	none, NONE, 0,	     0),
> +	PINCFG(46,      uart1, MFSEL1, 10,	 jtag2, MFSEL4, 0,	none, NONE, 0,	     DS(2, 8)),
> +	PINCFG(47,      uart1, MFSEL1, 10,	 jtag2, MFSEL4, 0,	none, NONE, 0,	     DS(2, 8)),
> +	PINCFG(48,	uart2, MFSEL1, 11,   bmcuart0b, MFSEL4, 1,      none, NONE, 0,	     GPO),
> +	PINCFG(49,	uart2, MFSEL1, 11,   bmcuart0b, MFSEL4, 1,      none, NONE, 0,	     0),
> +	PINCFG(50,	uart2, MFSEL1, 11,	  none, NONE, 0,        none, NONE, 0,	     0),
> +	PINCFG(51,	uart2, MFSEL1, 11,	  none, NONE, 0,        none, NONE, 0,	     GPO),
> +	PINCFG(52,	uart2, MFSEL1, 11,	  none, NONE, 0,        none, NONE, 0,	     0),
> +	PINCFG(53,	uart2, MFSEL1, 11,	  none, NONE, 0,        none, NONE, 0,	     GPO),
> +	PINCFG(54,	uart2, MFSEL1, 11,	  none, NONE, 0,        none, NONE, 0,	     0),
> +	PINCFG(55,	uart2, MFSEL1, 11,	  none, NONE, 0,        none, NONE, 0,	     0),
> +	PINCFG(56,	r1err, MFSEL1, 12,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(57,       r1md, MFSEL1, 13,        none, NONE, 0,        none, NONE, 0,       DS(2, 4)),
> +	PINCFG(58,       r1md, MFSEL1, 13,        none, NONE, 0,	none, NONE, 0,	     DS(2, 4)),
> +	PINCFG(59,	smb3d, I2CSEGSEL, 13,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(60,	smb3d, I2CSEGSEL, 13,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(61,      uart1, MFSEL1, 10,	  none, NONE, 0,	none, NONE, 0,     GPO),
> +	PINCFG(62,      uart1, MFSEL1, 10,    bmcuart1, MFSEL3, 24,	none, NONE, 0,     GPO),
> +	PINCFG(63,      uart1, MFSEL1, 10,    bmcuart1, MFSEL3, 24,	none, NONE, 0,     GPO),
> +
> +	PINCFG(64,    fanin0, MFSEL2, 0,          none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(65,    fanin1, MFSEL2, 1,          none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(66,    fanin2, MFSEL2, 2,          none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(67,    fanin3, MFSEL2, 3,          none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(68,    fanin4, MFSEL2, 4,          none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(69,    fanin5, MFSEL2, 5,          none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(70,    fanin6, MFSEL2, 6,          none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(71,    fanin7, MFSEL2, 7,          none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(72,    fanin8, MFSEL2, 8,          none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(73,    fanin9, MFSEL2, 9,          none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(74,    fanin10, MFSEL2, 10,        none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(75,    fanin11, MFSEL2, 11,        none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(76,    fanin12, MFSEL2, 12,        none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(77,    fanin13, MFSEL2, 13,        none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(78,    fanin14, MFSEL2, 14,        none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(79,    fanin15, MFSEL2, 15,        none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(80,	 pwm0, MFSEL2, 16,        none, NONE, 0,	none, NONE, 0,	     DS(4, 8)),
> +	PINCFG(81,	 pwm1, MFSEL2, 17,        none, NONE, 0,	none, NONE, 0,	     DS(4, 8)),
> +	PINCFG(82,	 pwm2, MFSEL2, 18,        none, NONE, 0,	none, NONE, 0,	     DS(4, 8)),
> +	PINCFG(83,	 pwm3, MFSEL2, 19,        none, NONE, 0,	none, NONE, 0,	     DS(4, 8)),
> +	PINCFG(84,         r2, MFSEL1, 14,        none, NONE, 0,        none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(85,         r2, MFSEL1, 14,        none, NONE, 0,        none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(86,         r2, MFSEL1, 14,        none, NONE, 0,        none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(87,         r2, MFSEL1, 14,        none, NONE, 0,        none, NONE, 0,	     0),
> +	PINCFG(88,         r2, MFSEL1, 14,        none, NONE, 0,        none, NONE, 0,	     0),
> +	PINCFG(89,         r2, MFSEL1, 14,        none, NONE, 0,        none, NONE, 0,	     0),
> +	PINCFG(90,      r2err, MFSEL1, 15,        none, NONE, 0,        none, NONE, 0,       0),
> +	PINCFG(91,       r2md, MFSEL1, 16,	  none, NONE, 0,        none, NONE, 0,	     DS(2, 4)),
> +	PINCFG(92,       r2md, MFSEL1, 16,	  none, NONE, 0,        none, NONE, 0,	     DS(2, 4)),
> +	PINCFG(93,    ga20kbc, MFSEL1, 17,	 smb5d, I2CSEGSEL, 21,  none, NONE, 0,	     0),
> +	PINCFG(94,    ga20kbc, MFSEL1, 17,	 smb5d, I2CSEGSEL, 21,  none, NONE, 0,	     0),
> +	PINCFG(95,	  lpc, NONE, 0,		  espi, MFSEL4, 8,      gpio, MFSEL1, 26,    0),
> +
> +	PINCFG(96,	  rg1, MFSEL4, 22,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(97,	  rg1, MFSEL4, 22,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(98,	  rg1, MFSEL4, 22,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(99,	  rg1, MFSEL4, 22,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(100,	  rg1, MFSEL4, 22,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(101,	  rg1, MFSEL4, 22,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(102,	  rg1, MFSEL4, 22,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(103,	  rg1, MFSEL4, 22,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(104,	  rg1, MFSEL4, 22,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(105,	  rg1, MFSEL4, 22,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(106,	  rg1, MFSEL4, 22,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(107,	  rg1, MFSEL4, 22,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(108,   rg1mdio, MFSEL4, 21,        none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(109,   rg1mdio, MFSEL4, 21,        none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(110,       rg2, MFSEL4, 24,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
> +	PINCFG(111,       rg2, MFSEL4, 24,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
> +	PINCFG(112,       rg2, MFSEL4, 24,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
> +	PINCFG(113,       rg2, MFSEL4, 24,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
> +	PINCFG(114,	 smb0, MFSEL1, 6,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(115,	 smb0, MFSEL1, 6,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(116,	 smb1, MFSEL1, 7,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(117,	 smb1, MFSEL1, 7,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(118,	 smb2, MFSEL1, 8,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(119,	 smb2, MFSEL1, 8,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(120,	smb2c, I2CSEGSEL, 9,	  none, NONE, 0,	none, NONE, 0,	     SLEW),
> +	PINCFG(121,	smb2c, I2CSEGSEL, 9,      none, NONE, 0,	none, NONE, 0,	     SLEW),
> +	PINCFG(122,	smb2b, I2CSEGSEL, 8,	  none, NONE, 0,	none, NONE, 0,	     SLEW),
> +	PINCFG(123,	smb2b, I2CSEGSEL, 8,	  none, NONE, 0,	none, NONE, 0,	     SLEW),
> +	PINCFG(124,	smb1c, I2CSEGSEL, 6,	  none, NONE, 0,	none, NONE, 0,	     SLEW),
> +	PINCFG(125,	smb1c, I2CSEGSEL, 6,	  none, NONE, 0,	none, NONE, 0,	     SLEW),
> +	PINCFG(126,	smb1b, I2CSEGSEL, 5,	  none, NONE, 0,	none, NONE, 0,	     SLEW),
> +	PINCFG(127,	smb1b, I2CSEGSEL, 5,	  none, NONE, 0,	none, NONE, 0,	     SLEW),
> +
> +	PINCFG(128,	 smb8, MFSEL4, 11,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(129,	 smb8, MFSEL4, 11,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(130,	 smb9, MFSEL4, 12,        none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(131,	 smb9, MFSEL4, 12,        none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(132,	smb10, MFSEL4, 13,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(133,	smb10, MFSEL4, 13,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(134,	smb11, MFSEL4, 14,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(135,	smb11, MFSEL4, 14,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(136,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(137,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(138,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(139,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(140,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(141,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(142,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(143,       sd1, MFSEL3, 12,      sd1pwr, MFSEL4, 5,      none, NONE, 0,       0),
> +	PINCFG(144,	 pwm4, MFSEL2, 20,	  none, NONE, 0,	none, NONE, 0,	     DS(4, 8)),
> +	PINCFG(145,	 pwm5, MFSEL2, 21,	  none, NONE, 0,	none, NONE, 0,	     DS(4, 8)),
> +	PINCFG(146,	 pwm6, MFSEL2, 22,	  none, NONE, 0,	none, NONE, 0,	     DS(4, 8)),
> +	PINCFG(147,	 pwm7, MFSEL2, 23,	  none, NONE, 0,	none, NONE, 0,	     DS(4, 8)),
> +	PINCFG(148,	 mmc8, MFSEL3, 11,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(149,	 mmc8, MFSEL3, 11,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(150,	 mmc8, MFSEL3, 11,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(151,	 mmc8, MFSEL3, 11,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(152,	  mmc, MFSEL3, 10,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(153,     mmcwp, FLOCKR1, 24,       none, NONE, 0,	none, NONE, 0,	     0),  /* Z1/A1 */
> +	PINCFG(154,	  mmc, MFSEL3, 10,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(155,     mmccd, MFSEL3, 25,      mmcrst, MFSEL4, 6,      none, NONE, 0,       0),  /* Z1/A1 */
> +	PINCFG(156,	  mmc, MFSEL3, 10,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(157,	  mmc, MFSEL3, 10,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(158,	  mmc, MFSEL3, 10,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(159,	  mmc, MFSEL3, 10,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +
> +	PINCFG(160,    clkout, MFSEL1, 21,        none, NONE, 0,        none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(161,	  lpc, NONE, 0,		  espi, MFSEL4, 8,      gpio, MFSEL1, 26,    DS(8, 12)),
> +	PINCFG(162,    serirq, NONE, 0,           gpio, MFSEL1, 31,	none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(163,	  lpc, NONE, 0,		  espi, MFSEL4, 8,      gpio, MFSEL1, 26,    0),
> +	PINCFG(164,	  lpc, NONE, 0,		  espi, MFSEL4, 8,      gpio, MFSEL1, 26,    SLEWLPC),
> +	PINCFG(165,	  lpc, NONE, 0,		  espi, MFSEL4, 8,      gpio, MFSEL1, 26,    SLEWLPC),
> +	PINCFG(166,	  lpc, NONE, 0,		  espi, MFSEL4, 8,      gpio, MFSEL1, 26,    SLEWLPC),
> +	PINCFG(167,	  lpc, NONE, 0,		  espi, MFSEL4, 8,      gpio, MFSEL1, 26,    SLEWLPC),
> +	PINCFG(168,	  lpc, NONE, 0,           espi, MFSEL4, 8,      gpio, MFSEL3, 16,    0),
> +	PINCFG(169,    scipme, MFSEL3, 0,         none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(170,	  sci, MFSEL1, 22,        none, NONE, 0,        none, NONE, 0,	     0),
> +	PINCFG(171,	 smb6, MFSEL3, 1,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(172,	 smb6, MFSEL3, 1,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(173,	 smb7, MFSEL3, 2,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(174,	 smb7, MFSEL3, 2,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(175,	pspi1, MFSEL3, 4,       faninx, MFSEL3, 3,      none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(176,     pspi1, MFSEL3, 4,       faninx, MFSEL3, 3,      none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(177,     pspi1, MFSEL3, 4,       faninx, MFSEL3, 3,      none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(178,	   r1, MFSEL3, 9,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(179,	   r1, MFSEL3, 9,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(180,	   r1, MFSEL3, 9,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(181,	   r1, MFSEL3, 9,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(182,	   r1, MFSEL3, 9,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(183,     spi3, MFSEL4, 16,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(184,     spi3, MFSEL4, 16,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW | GPO),
> +	PINCFG(185,     spi3, MFSEL4, 16,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW | GPO),
> +	PINCFG(186,     spi3, MFSEL4, 16,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(187,   spi3cs1, MFSEL4, 17,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(188,  spi3quad, MFSEL4, 20,     spi3cs2, MFSEL4, 18,     none, NONE, 0,    DS(8, 12) | SLEW),
> +	PINCFG(189,  spi3quad, MFSEL4, 20,     spi3cs3, MFSEL4, 19,     none, NONE, 0,    DS(8, 12) | SLEW),
> +	PINCFG(190,      gpio, FLOCKR1, 20,   nprd_smi, NONE, 0,	none, NONE, 0,	     DS(2, 4)),
> +	PINCFG(191,	 none, NONE, 0,		  none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),  /* XX */
> +
> +	PINCFG(192,	 none, NONE, 0,		  none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),  /* XX */
> +	PINCFG(193,	   r1, MFSEL3, 9,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(194,	smb0b, I2CSEGSEL, 0,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(195,	smb0b, I2CSEGSEL, 0,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(196,	smb0c, I2CSEGSEL, 1,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(197,   smb0den, I2CSEGSEL, 22,     none, NONE, 0,	none, NONE, 0,	     SLEW),
> +	PINCFG(198,	smb0d, I2CSEGSEL, 2,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(199,	smb0d, I2CSEGSEL, 2,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(200,        r2, MFSEL1, 14,        none, NONE, 0,        none, NONE, 0,       0),
> +	PINCFG(201,	   r1, MFSEL3, 9,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(202,	smb0c, I2CSEGSEL, 1,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(203,    faninx, MFSEL3, 3,         none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(204,	  ddc, NONE, 0,           gpio, MFSEL3, 22,	none, NONE, 0,	     SLEW),
> +	PINCFG(205,	  ddc, NONE, 0,           gpio, MFSEL3, 22,	none, NONE, 0,	     SLEW),
> +	PINCFG(206,	  ddc, NONE, 0,           gpio, MFSEL3, 22,	none, NONE, 0,	     DS(4, 8)),
> +	PINCFG(207,	  ddc, NONE, 0,           gpio, MFSEL3, 22,	none, NONE, 0,	     DS(4, 8)),
> +	PINCFG(208,       rg2, MFSEL4, 24,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
> +	PINCFG(209,       rg2, MFSEL4, 24,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
> +	PINCFG(210,       rg2, MFSEL4, 24,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
> +	PINCFG(211,       rg2, MFSEL4, 24,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
> +	PINCFG(212,       rg2, MFSEL4, 24,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
> +	PINCFG(213,       rg2, MFSEL4, 24,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
> +	PINCFG(214,       rg2, MFSEL4, 24,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
> +	PINCFG(215,       rg2, MFSEL4, 24,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
> +	PINCFG(216,   rg2mdio, MFSEL4, 23,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
> +	PINCFG(217,   rg2mdio, MFSEL4, 23,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
> +	PINCFG(218,     wdog1, MFSEL3, 19,        none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(219,     wdog2, MFSEL3, 20,        none, NONE, 0,	none, NONE, 0,	     DS(4, 8)),
> +	PINCFG(220,	smb12, MFSEL3, 5,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(221,	smb12, MFSEL3, 5,	  none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(222,     smb13, MFSEL3, 6,         none, NONE, 0,	none, NONE, 0,	     0),
> +	PINCFG(223,     smb13, MFSEL3, 6,         none, NONE, 0,	none, NONE, 0,	     0),
> +
> +	PINCFG(224,	 spix, MFSEL4, 27,        none, NONE, 0,	none, NONE, 0,	     SLEW),
> +	PINCFG(225,	 spix, MFSEL4, 27,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW | GPO),
> +	PINCFG(226,	 spix, MFSEL4, 27,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW | GPO),
> +	PINCFG(227,	 spix, MFSEL4, 27,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(228,   spixcs1, MFSEL4, 28,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(229,	 spix, MFSEL4, 27,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(230,	 spix, MFSEL4, 27,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
> +	PINCFG(231,    clkreq, MFSEL4, 9,         none, NONE, 0,        none, NONE, 0,	     DS(8, 12)),
> +	PINCFG(253,	 none, NONE, 0,		  none, NONE, 0,	none, NONE, 0,	     GPI), /* SDHC1 power */
> +	PINCFG(254,	 none, NONE, 0,		  none, NONE, 0,	none, NONE, 0,	     GPI), /* SDHC2 power */
> +	PINCFG(255,	 none, NONE, 0,		  none, NONE, 0,	none, NONE, 0,	     GPI), /* DACOSEL */
> +};
> +
> +/* number, name, drv_data */
> +static const struct pinctrl_pin_desc npcm_pins[] = {
> +	PINCTRL_PIN(0,	"GPIO0/IOX1DI"),
> +	PINCTRL_PIN(1,	"GPIO1/IOX1LD"),
> +	PINCTRL_PIN(2,	"GPIO2/IOX1CK"),
> +	PINCTRL_PIN(3,	"GPIO3/IOX1D0"),
> +	PINCTRL_PIN(4,	"GPIO4/IOX2DI/SMB1DSDA"),
> +	PINCTRL_PIN(5,	"GPIO5/IOX2LD/SMB1DSCL"),
> +	PINCTRL_PIN(6,	"GPIO6/IOX2CK/SMB2DSDA"),
> +	PINCTRL_PIN(7,	"GPIO7/IOX2D0/SMB2DSCL"),
> +	PINCTRL_PIN(8,	"GPIO8/LKGPO1"),
> +	PINCTRL_PIN(9,	"GPIO9/LKGPO2"),
> +	PINCTRL_PIN(10, "GPIO10/IOXHLD"),
> +	PINCTRL_PIN(11, "GPIO11/IOXHCK"),
> +	PINCTRL_PIN(12, "GPIO12/GSPICK/SMB5BSCL"),
> +	PINCTRL_PIN(13, "GPIO13/GSPIDO/SMB5BSDA"),
> +	PINCTRL_PIN(14, "GPIO14/GSPIDI/SMB5CSCL"),
> +	PINCTRL_PIN(15, "GPIO15/GSPICS/SMB5CSDA"),
> +	PINCTRL_PIN(16, "GPIO16/LKGPO0"),
> +	PINCTRL_PIN(17, "GPIO17/PSPI2DI/SMB4DEN"),
> +	PINCTRL_PIN(18, "GPIO18/PSPI2D0/SMB4BSDA"),
> +	PINCTRL_PIN(19, "GPIO19/PSPI2CK/SMB4BSCL"),
> +	PINCTRL_PIN(20, "GPIO20/SMB4CSDA/SMB15SDA"),
> +	PINCTRL_PIN(21, "GPIO21/SMB4CSCL/SMB15SCL"),
> +	PINCTRL_PIN(22, "GPIO22/SMB4DSDA/SMB14SDA"),
> +	PINCTRL_PIN(23, "GPIO23/SMB4DSCL/SMB14SCL"),
> +	PINCTRL_PIN(24, "GPIO24/IOXHDO"),
> +	PINCTRL_PIN(25, "GPIO25/IOXHDI"),
> +	PINCTRL_PIN(26, "GPIO26/SMB5SDA"),
> +	PINCTRL_PIN(27, "GPIO27/SMB5SCL"),
> +	PINCTRL_PIN(28, "GPIO28/SMB4SDA"),
> +	PINCTRL_PIN(29, "GPIO29/SMB4SCL"),
> +	PINCTRL_PIN(30, "GPIO30/SMB3SDA"),
> +	PINCTRL_PIN(31, "GPIO31/SMB3SCL"),
> +
> +	PINCTRL_PIN(32, "GPIO32/nSPI0CS1"),
> +	PINCTRL_PIN(33, "GPIO33/SPI0D2/nSPI0CS2"),
> +	PINCTRL_PIN(34, "GPIO34/SPI0D3/nSPI0CS3"),
> +	PINCTRL_PIN(37, "GPIO37/SMB3CSDA"),
> +	PINCTRL_PIN(38, "GPIO38/SMB3CSCL"),
> +	PINCTRL_PIN(39, "GPIO39/SMB3BSDA"),
> +	PINCTRL_PIN(40, "GPIO40/SMB3BSCL"),
> +	PINCTRL_PIN(41, "GPIO41/BSPRXD"),
> +	PINCTRL_PIN(42, "GPO42/BSPTXD/STRAP11"),
> +	PINCTRL_PIN(43, "GPIO43/RXD1/JTMS2/BU1RXD"),
> +	PINCTRL_PIN(44, "GPIO44/nCTS1/JTDI2/BU1CTS"),
> +	PINCTRL_PIN(45, "GPIO45/nDCD1/JTDO2"),
> +	PINCTRL_PIN(46, "GPIO46/nDSR1/JTCK2"),
> +	PINCTRL_PIN(47, "GPIO47/nRI1/JCP_RDY2"),
> +	PINCTRL_PIN(48, "GPIO48/TXD2/BSPTXD"),
> +	PINCTRL_PIN(49, "GPIO49/RXD2/BSPRXD"),
> +	PINCTRL_PIN(50, "GPIO50/nCTS2"),
> +	PINCTRL_PIN(51, "GPO51/nRTS2/STRAP2"),
> +	PINCTRL_PIN(52, "GPIO52/nDCD2"),
> +	PINCTRL_PIN(53, "GPIO53/nDTR2_BOUT2/STRAP1"),
> +	PINCTRL_PIN(54, "GPIO54/nDSR2"),
> +	PINCTRL_PIN(55, "GPIO55/nRI2"),
> +	PINCTRL_PIN(56, "GPIO56/R1RXERR"),
> +	PINCTRL_PIN(57, "GPIO57/R1MDC"),
> +	PINCTRL_PIN(58, "GPIO58/R1MDIO"),
> +	PINCTRL_PIN(59, "GPIO59/SMB3DSDA"),
> +	PINCTRL_PIN(60, "GPIO60/SMB3DSCL"),
> +	PINCTRL_PIN(61, "GPO61/nDTR1_BOUT1/STRAP6"),
> +	PINCTRL_PIN(62, "GPO62/nRTST1/STRAP5"),
> +	PINCTRL_PIN(63, "GPO63/TXD1/STRAP4"),
> +
> +	PINCTRL_PIN(64, "GPIO64/FANIN0"),
> +	PINCTRL_PIN(65, "GPIO65/FANIN1"),
> +	PINCTRL_PIN(66, "GPIO66/FANIN2"),
> +	PINCTRL_PIN(67, "GPIO67/FANIN3"),
> +	PINCTRL_PIN(68, "GPIO68/FANIN4"),
> +	PINCTRL_PIN(69, "GPIO69/FANIN5"),
> +	PINCTRL_PIN(70, "GPIO70/FANIN6"),
> +	PINCTRL_PIN(71, "GPIO71/FANIN7"),
> +	PINCTRL_PIN(72, "GPIO72/FANIN8"),
> +	PINCTRL_PIN(73, "GPIO73/FANIN9"),
> +	PINCTRL_PIN(74, "GPIO74/FANIN10"),
> +	PINCTRL_PIN(75, "GPIO75/FANIN11"),
> +	PINCTRL_PIN(76, "GPIO76/FANIN12"),
> +	PINCTRL_PIN(77, "GPIO77/FANIN13"),
> +	PINCTRL_PIN(78, "GPIO78/FANIN14"),
> +	PINCTRL_PIN(79, "GPIO79/FANIN15"),
> +	PINCTRL_PIN(80, "GPIO80/PWM0"),
> +	PINCTRL_PIN(81, "GPIO81/PWM1"),
> +	PINCTRL_PIN(82, "GPIO82/PWM2"),
> +	PINCTRL_PIN(83, "GPIO83/PWM3"),
> +	PINCTRL_PIN(84, "GPIO84/R2TXD0"),
> +	PINCTRL_PIN(85, "GPIO85/R2TXD1"),
> +	PINCTRL_PIN(86, "GPIO86/R2TXEN"),
> +	PINCTRL_PIN(87, "GPIO87/R2RXD0"),
> +	PINCTRL_PIN(88, "GPIO88/R2RXD1"),
> +	PINCTRL_PIN(89, "GPIO89/R2CRSDV"),
> +	PINCTRL_PIN(90, "GPIO90/R2RXERR"),
> +	PINCTRL_PIN(91, "GPIO91/R2MDC"),
> +	PINCTRL_PIN(92, "GPIO92/R2MDIO"),
> +	PINCTRL_PIN(93, "GPIO93/GA20/SMB5DSCL"),
> +	PINCTRL_PIN(94, "GPIO94/nKBRST/SMB5DSDA"),
> +	PINCTRL_PIN(95, "GPIO95/nLRESET/nESPIRST"),
> +
> +	PINCTRL_PIN(96, "GPIO96/RG1TXD0"),
> +	PINCTRL_PIN(97, "GPIO97/RG1TXD1"),
> +	PINCTRL_PIN(98, "GPIO98/RG1TXD2"),
> +	PINCTRL_PIN(99, "GPIO99/RG1TXD3"),
> +	PINCTRL_PIN(100, "GPIO100/RG1TXC"),
> +	PINCTRL_PIN(101, "GPIO101/RG1TXCTL"),
> +	PINCTRL_PIN(102, "GPIO102/RG1RXD0"),
> +	PINCTRL_PIN(103, "GPIO103/RG1RXD1"),
> +	PINCTRL_PIN(104, "GPIO104/RG1RXD2"),
> +	PINCTRL_PIN(105, "GPIO105/RG1RXD3"),
> +	PINCTRL_PIN(106, "GPIO106/RG1RXC"),
> +	PINCTRL_PIN(107, "GPIO107/RG1RXCTL"),
> +	PINCTRL_PIN(108, "GPIO108/RG1MDC"),
> +	PINCTRL_PIN(109, "GPIO109/RG1MDIO"),
> +	PINCTRL_PIN(110, "GPIO110/RG2TXD0/DDRV0"),
> +	PINCTRL_PIN(111, "GPIO111/RG2TXD1/DDRV1"),
> +	PINCTRL_PIN(112, "GPIO112/RG2TXD2/DDRV2"),
> +	PINCTRL_PIN(113, "GPIO113/RG2TXD3/DDRV3"),
> +	PINCTRL_PIN(114, "GPIO114/SMB0SCL"),
> +	PINCTRL_PIN(115, "GPIO115/SMB0SDA"),
> +	PINCTRL_PIN(116, "GPIO116/SMB1SCL"),
> +	PINCTRL_PIN(117, "GPIO117/SMB1SDA"),
> +	PINCTRL_PIN(118, "GPIO118/SMB2SCL"),
> +	PINCTRL_PIN(119, "GPIO119/SMB2SDA"),
> +	PINCTRL_PIN(120, "GPIO120/SMB2CSDA"),
> +	PINCTRL_PIN(121, "GPIO121/SMB2CSCL"),
> +	PINCTRL_PIN(122, "GPIO122/SMB2BSDA"),
> +	PINCTRL_PIN(123, "GPIO123/SMB2BSCL"),
> +	PINCTRL_PIN(124, "GPIO124/SMB1CSDA"),
> +	PINCTRL_PIN(125, "GPIO125/SMB1CSCL"),
> +	PINCTRL_PIN(126, "GPIO126/SMB1BSDA"),
> +	PINCTRL_PIN(127, "GPIO127/SMB1BSCL"),
> +
> +	PINCTRL_PIN(128, "GPIO128/SMB8SCL"),
> +	PINCTRL_PIN(129, "GPIO129/SMB8SDA"),
> +	PINCTRL_PIN(130, "GPIO130/SMB9SCL"),
> +	PINCTRL_PIN(131, "GPIO131/SMB9SDA"),
> +	PINCTRL_PIN(132, "GPIO132/SMB10SCL"),
> +	PINCTRL_PIN(133, "GPIO133/SMB10SDA"),
> +	PINCTRL_PIN(134, "GPIO134/SMB11SCL"),
> +	PINCTRL_PIN(135, "GPIO135/SMB11SDA"),
> +	PINCTRL_PIN(136, "GPIO136/SD1DT0"),
> +	PINCTRL_PIN(137, "GPIO137/SD1DT1"),
> +	PINCTRL_PIN(138, "GPIO138/SD1DT2"),
> +	PINCTRL_PIN(139, "GPIO139/SD1DT3"),
> +	PINCTRL_PIN(140, "GPIO140/SD1CLK"),
> +	PINCTRL_PIN(141, "GPIO141/SD1WP"),
> +	PINCTRL_PIN(142, "GPIO142/SD1CMD"),
> +	PINCTRL_PIN(143, "GPIO143/SD1CD/SD1PWR"),
> +	PINCTRL_PIN(144, "GPIO144/PWM4"),
> +	PINCTRL_PIN(145, "GPIO145/PWM5"),
> +	PINCTRL_PIN(146, "GPIO146/PWM6"),
> +	PINCTRL_PIN(147, "GPIO147/PWM7"),
> +	PINCTRL_PIN(148, "GPIO148/MMCDT4"),
> +	PINCTRL_PIN(149, "GPIO149/MMCDT5"),
> +	PINCTRL_PIN(150, "GPIO150/MMCDT6"),
> +	PINCTRL_PIN(151, "GPIO151/MMCDT7"),
> +	PINCTRL_PIN(152, "GPIO152/MMCCLK"),
> +	PINCTRL_PIN(153, "GPIO153/MMCWP"),
> +	PINCTRL_PIN(154, "GPIO154/MMCCMD"),
> +	PINCTRL_PIN(155, "GPIO155/nMMCCD/nMMCRST"),
> +	PINCTRL_PIN(156, "GPIO156/MMCDT0"),
> +	PINCTRL_PIN(157, "GPIO157/MMCDT1"),
> +	PINCTRL_PIN(158, "GPIO158/MMCDT2"),
> +	PINCTRL_PIN(159, "GPIO159/MMCDT3"),
> +
> +	PINCTRL_PIN(160, "GPIO160/CLKOUT/RNGOSCOUT"),
> +	PINCTRL_PIN(161, "GPIO161/nLFRAME/nESPICS"),
> +	PINCTRL_PIN(162, "GPIO162/SERIRQ"),
> +	PINCTRL_PIN(163, "GPIO163/LCLK/ESPICLK"),
> +	PINCTRL_PIN(164, "GPIO164/LAD0/ESPI_IO0"/*dscnt6*/),
> +	PINCTRL_PIN(165, "GPIO165/LAD1/ESPI_IO1"/*dscnt6*/),
> +	PINCTRL_PIN(166, "GPIO166/LAD2/ESPI_IO2"/*dscnt6*/),
> +	PINCTRL_PIN(167, "GPIO167/LAD3/ESPI_IO3"/*dscnt6*/),
> +	PINCTRL_PIN(168, "GPIO168/nCLKRUN/nESPIALERT"),
> +	PINCTRL_PIN(169, "GPIO169/nSCIPME"),
> +	PINCTRL_PIN(170, "GPIO170/nSMI"),
> +	PINCTRL_PIN(171, "GPIO171/SMB6SCL"),
> +	PINCTRL_PIN(172, "GPIO172/SMB6SDA"),
> +	PINCTRL_PIN(173, "GPIO173/SMB7SCL"),
> +	PINCTRL_PIN(174, "GPIO174/SMB7SDA"),
> +	PINCTRL_PIN(175, "GPIO175/PSPI1CK/FANIN19"),
> +	PINCTRL_PIN(176, "GPIO176/PSPI1DO/FANIN18"),
> +	PINCTRL_PIN(177, "GPIO177/PSPI1DI/FANIN17"),
> +	PINCTRL_PIN(178, "GPIO178/R1TXD0"),
> +	PINCTRL_PIN(179, "GPIO179/R1TXD1"),
> +	PINCTRL_PIN(180, "GPIO180/R1TXEN"),
> +	PINCTRL_PIN(181, "GPIO181/R1RXD0"),
> +	PINCTRL_PIN(182, "GPIO182/R1RXD1"),
> +	PINCTRL_PIN(183, "GPIO183/SPI3CK"),
> +	PINCTRL_PIN(184, "GPO184/SPI3D0/STRAP9"),
> +	PINCTRL_PIN(185, "GPO185/SPI3D1/STRAP10"),
> +	PINCTRL_PIN(186, "GPIO186/nSPI3CS0"),
> +	PINCTRL_PIN(187, "GPIO187/nSPI3CS1"),
> +	PINCTRL_PIN(188, "GPIO188/SPI3D2/nSPI3CS2"),
> +	PINCTRL_PIN(189, "GPIO189/SPI3D3/nSPI3CS3"),
> +	PINCTRL_PIN(190, "GPIO190/nPRD_SMI"),
> +	PINCTRL_PIN(191, "GPIO191"),
> +
> +	PINCTRL_PIN(192, "GPIO192/PSPI1CS2"),
> +	PINCTRL_PIN(193, "GPIO193/R1CRSDV"),
> +	PINCTRL_PIN(194, "GPIO194/SMB0BSCL"),
> +	PINCTRL_PIN(195, "GPIO195/SMB0BSDA"),
> +	PINCTRL_PIN(196, "GPIO196/SMB0CSCL"),
> +	PINCTRL_PIN(197, "GPIO197/SMB0DEN"),
> +	PINCTRL_PIN(198, "GPIO198/SMB0DSDA"),
> +	PINCTRL_PIN(199, "GPIO199/SMB0DSCL"),
> +	PINCTRL_PIN(200, "GPIO200/R2CK"),
> +	PINCTRL_PIN(201, "GPIO201/R1CK"),
> +	PINCTRL_PIN(202, "GPIO202/SMB0CSDA"),
> +	PINCTRL_PIN(203, "GPIO203/FANIN16"),
> +	PINCTRL_PIN(204, "GPIO204/DDC2SCL"),
> +	PINCTRL_PIN(205, "GPIO205/DDC2SDA"),
> +	PINCTRL_PIN(206, "GPIO206/HSYNC2"),
> +	PINCTRL_PIN(207, "GPIO207/VSYNC2"),
> +	PINCTRL_PIN(208, "GPIO208/RG2TXC/DVCK"),
> +	PINCTRL_PIN(209, "GPIO209/RG2TXCTL/DDRV4"),
> +	PINCTRL_PIN(210, "GPIO210/RG2RXD0/DDRV5"),
> +	PINCTRL_PIN(211, "GPIO211/RG2RXD1/DDRV6"),
> +	PINCTRL_PIN(212, "GPIO212/RG2RXD2/DDRV7"),
> +	PINCTRL_PIN(213, "GPIO213/RG2RXD3/DDRV8"),
> +	PINCTRL_PIN(214, "GPIO214/RG2RXC/DDRV9"),
> +	PINCTRL_PIN(215, "GPIO215/RG2RXCTL/DDRV10"),
> +	PINCTRL_PIN(216, "GPIO216/RG2MDC/DDRV11"),
> +	PINCTRL_PIN(217, "GPIO217/RG2MDIO/DVHSYNC"),
> +	PINCTRL_PIN(218, "GPIO218/nWDO1"),
> +	PINCTRL_PIN(219, "GPIO219/nWDO2"),
> +	PINCTRL_PIN(220, "GPIO220/SMB12SCL"),
> +	PINCTRL_PIN(221, "GPIO221/SMB12SDA"),
> +	PINCTRL_PIN(222, "GPIO222/SMB13SCL"),
> +	PINCTRL_PIN(223, "GPIO223/SMB13SDA"),
> +
> +	PINCTRL_PIN(224, "GPIO224/SPIXCK"),
> +	PINCTRL_PIN(225, "GPO225/SPIXD0/STRAP12"),
> +	PINCTRL_PIN(226, "GPO226/SPIXD1/STRAP13"),
> +	PINCTRL_PIN(227, "GPIO227/nSPIXCS0"),
> +	PINCTRL_PIN(228, "GPIO228/nSPIXCS1"),
> +	PINCTRL_PIN(229, "GPIO229/SPIXD2/STRAP3"),
> +	PINCTRL_PIN(230, "GPIO230/SPIXD3"),
> +	PINCTRL_PIN(231, "GPIO231/nCLKREQ"),
> +	PINCTRL_PIN(255, "GPI255/DACOSEL"),
> +};

I'm assuming all the above is a good reflection of the hardware.

> +
> +static const char *gcr_regname(int reg)
> +{
> +	switch (reg) {
> +	case GCR_MFSEL1: return "MFSEL1";
> +	case GCR_MFSEL2: return "MFSEL2";
> +	case GCR_MFSEL3: return "MFSEL3";
> +	case GCR_MFSEL4: return "MFSEL4";
> +	case GCR_I2CSEGSEL: return "I2CSEGSEL";
> +	case GCR_FLOCKR1: return "FLOCKR1";

Any chance this can just be an array lookup?

> +	}
> +	return "xx";
> +}
> +
> +#ifdef DEBUG
> +static void showmfsel(void)
> +{
> +	int module;
> +	void *base;
> +
> +	for (module = 0; module < 8; module++) {
> +		base = npcm_bank[module].base;
> +		pr_info("-- module %d [gpio%d - %d]\n", module,
> +			   module * GPIO_PER_BANK,
> +			   (module * GPIO_PER_BANK) + GPIO_PER_BANK - 1);
> +		pr_info("DIN :%.8x DOUT:%.8x IE  :%.8x OE	 :%.8x\n",
> +			   npcm_read32(base + GPnDIN),
> +			   npcm_read32(base + GPnDOUT),
> +			   npcm_read32(base + GPnIEM),
> +			   npcm_read32(base + GPnOE));
> +		pr_info("PU  :%.8x PD  :%.8x DB  :%.8x POL :%.8x\n",
> +			   npcm_read32(base + GPnPU),
> +			   npcm_read32(base + GPnPD),
> +			   npcm_read32(base + GPnDBNC),
> +			   npcm_read32(base + GPnPOL));
> +		pr_info("ETYP:%.8x EVBE:%.8x EVEN:%.8x EVST:%.8x\n",
> +			   npcm_read32(base + GPnEVTYP),
> +			   npcm_read32(base + GPnEVBE),
> +			   npcm_read32(base + GPnEVEN),
> +			   npcm_read32(base + GPnEVST));
> +		pr_info("OTYP:%.8x OSRC:%.8x ODSC:%.8x\n",
> +			   npcm_read32(base + GPnOTYP),
> +			   npcm_read32(base + GPnOSRC),
> +			   npcm_read32(base + GPnODSC));
> +		pr_info("OBL0:%.8x OBL1:%.8x OBL2:%.8x OBL3:%.8x\n",
> +			   npcm_read32(base + GPnOBL0),
> +			   npcm_read32(base + GPnOBL1),
> +			   npcm_read32(base + GPnOBL2),
> +			   npcm_read32(base + GPnOBL3));
> +		pr_info("SLCK:%.8x MLCK:%.8x\n",
> +			   npcm_read32(base + GPnSPLCK),
> +			   npcm_read32(base + GPnMPLCK));
> +	}
> +	pr_info("-- GCR\n");
> +	base = npcm_bank[GCR_BANK].base;
> +	pr_info("MFSEL1:%.8x MFSEL2:%.8x MFSEL3:%.8x MFSEL4:%.8x I2C:%.8x FLOCKR1:%.8x\n",
> +		npcm_read32(base + GCR_MFSEL1),
> +		npcm_read32(base + GCR_MFSEL2),
> +		npcm_read32(base + GCR_MFSEL3),
> +		npcm_read32(base + GCR_MFSEL4),
> +		npcm_read32(base + GCR_I2CSEGSEL),
> +		npcm_read32(base + GCR_FLOCKR1));
> +}
> +#endif

Can we drop this?

> +
> +static void npcm_setmode(struct npcm_reg *bank, int reg, int bit, int mode, int pin)
> +{
> +	if (reg) {
> +		pr_debug("Pin %d: setting reg:%x[%s.%d] = %d\n", pin,
> +		       reg, gcr_regname(reg), bit, mode);
> +		npcm_rmw32(bank->base + reg, bit, 1, mode);
> +	}
> +}
> +
> +/* Enable mode in pin group */
> +static void npcm_setfunc(int pin, int n, int mode)
> +{
> +	struct npcm_reg *bank = &npcm_bank[GCR_BANK];
> +	const struct npcm_pincfg *cfg;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&bank->lock, flags);
> +	while (n--) {
> +		cfg = &pincfg[pin++];
> +		if (mode == fn_gpio || cfg->fn0 == mode || cfg->fn1 == mode || cfg->fn2 == mode) {
> +			npcm_setmode(bank, cfg->reg0, cfg->bit0, !!(cfg->fn0 == mode), pin-1);
> +			npcm_setmode(bank, cfg->reg1, cfg->bit1, !!(cfg->fn1 == mode), pin-1);
> +			npcm_setmode(bank, cfg->reg2, cfg->bit2, !!(cfg->fn2 == mode), pin-1);
> +		}
> +	}
> +	spin_unlock_irqrestore(&bank->lock, flags);
> +}
> +
> +/* Get slew rate of pin (high/low) */
> +static int npcm_get_slew_rate(unsigned int pin)
> +{
> +	if (pincfg[pin].flag & SLEW)
> +		return gpio_bitop(opGETBIT, pin, GPnOSRC);
> +	/* LPC Slew rate in SRCNT register */
> +	if (pincfg[pin].flag & SLEWLPC)
> +		return !!(npcm_read32(npcm_bank[GCR_BANK].base + GCR_SRCNT) & SRCNT_ESPI);

Is this meant to return a binary value?

> +	return -EINVAL;
> +}
> +
> +/* Get drive strength for a pin, if supported */
> +static int npcm_get_drive_strength(unsigned int pin)
> +{
> +	u32 val, ds = 0;
> +	int flg;
> +
> +	flg = pincfg[pin].flag;
> +	if (flg & DRIVE_STRENGTH_MASK) {
> +		/* Get standard reading */
> +		val = gpio_bitop(opGETBIT, pin, GPnODSC);
> +		ds = val ? DSHI(flg) : DSLO(flg);
> +	}
> +	DRV_MSG2(" pin %d strength %d = %d\n", pin, val, ds);
> +	return ds;
> +}
> +
> +/* Set drive strength for a pin, if supported */
> +static int npcm_set_drive_strength(unsigned int pin, int nval)
> +{
> +	int v;
> +
> +	v = (pincfg[pin].flag & DRIVE_STRENGTH_MASK);
> +	if (!nval || !v)
> +		return 0;
> +	if (DSLO(v) == nval) {
> +		DRV_MSG2(" setting pin %d to low strength [%d]\n", pin, nval);
> +		gpio_bitop(opCLRBIT, pin, GPnODSC);
> +		return 1;
> +	} else if (DSHI(v) == nval) {
> +		DRV_MSG2(" setting pin %d to high strength [%d]\n", pin, nval);
> +		gpio_bitop(opSETBIT, pin, GPnODSC);
> +		return 1;
> +	}
> +	return 0;
> +}
> +
> +/* ================= pinctrl_ops ========================= */

Lets remove the ASCII art here and in the cases below.

> +static void npcm_pin_dbg_show(struct pinctrl_dev *pctldev,
> +			      struct seq_file *s, unsigned int offset)
> +{
> +	seq_printf(s, "pinctrl_ops.dbg: %d", offset);
> +}
> +
> +static int npcm_get_groups_count(struct pinctrl_dev *pctldev)
> +{
> +	DRV_MSG2("group size: %d\n", ARRAY_SIZE(npcm_groups));

I think this debug message is useful in the grand scheme of things.

> +	return ARRAY_SIZE(npcm_groups);
> +}
> +
> +static const char *npcm_get_group_name(struct pinctrl_dev *pctldev,
> +				       unsigned int selector)
> +{
> +	return npcm_groups[selector].name;
> +}
> +
> +static int npcm_get_group_pins(struct pinctrl_dev *pctldev,
> +			       unsigned int selector,
> +			       const unsigned int **pins,
> +			       unsigned int *npins)
> +{
> +	*npins = npcm_groups[selector].npins;
> +	*pins  = npcm_groups[selector].pins;
> +	return 0;
> +}
> +
> +static int npcm_dt_node_to_map(struct pinctrl_dev *pctldev,
> +			       struct device_node *np_config,
> +			       struct pinctrl_map **map,
> +			       u32 *num_maps)
> +{
> +	pr_debug("dt_node_to_map: %s\n", np_config->name);
> +	return pinconf_generic_dt_node_to_map(pctldev, np_config,
> +					      map, num_maps,
> +					      PIN_MAP_TYPE_INVALID);
> +}
> +
> +static void npcm_dt_free_map(struct pinctrl_dev *pctldev,
> +			     struct pinctrl_map *map, u32 num_maps)
> +{
> +	kfree(map);
> +}
> +
> +static struct pinctrl_ops npcm_pinctrl_ops = {
> +	.get_groups_count = npcm_get_groups_count,
> +	.get_group_name = npcm_get_group_name,
> +	.get_group_pins = npcm_get_group_pins,
> +	.pin_dbg_show = npcm_pin_dbg_show,
> +	.dt_node_to_map = npcm_dt_node_to_map,
> +	.dt_free_map = npcm_dt_free_map,
> +};
> +
> +/* ================= pinmux_ops ========================= */
> +static int npcm_get_functions_count(struct pinctrl_dev *pctldev)
> +{
> +	return ARRAY_SIZE(npcm_funcs);
> +}
> +
> +static const char *npcm_get_function_name(struct pinctrl_dev *pctldev,
> +					  unsigned int function)
> +{
> +	return npcm_funcs[function].name;
> +}
> +
> +static int npcm_get_function_groups(struct pinctrl_dev *pctldev,
> +				    unsigned int function,
> +				    const char * const **groups,
> +				    unsigned int * const ngroups)
> +{
> +	*ngroups = npcm_funcs[function].ngroups;
> +	*groups	 = npcm_funcs[function].groups;
> +	return 0;
> +}
> +
> +static int npcm_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
> +			       unsigned int group)
> +{
> +	struct npcm_dev *npcm = pinctrl_dev_get_drvdata(pctldev);
> +
> +	dev_dbg(npcm->gc.parent, "set_mux: %d, %d[%s]\n", function, group, npcm_groups[group].name);
> +	npcm_setfunc(0, ARRAY_SIZE(pincfg), group);
> +	return 0;
> +}
> +
> +static int npcm_gpio_request_enable(struct pinctrl_dev *pctldev,
> +				    struct pinctrl_gpio_range *range,
> +				    unsigned int offset)
> +{
> +	struct npcm_dev *npcm = pinctrl_dev_get_drvdata(pctldev);
> +
> +	if (!range) {
> +		dev_err(npcm->gc.parent, "invalid range\n");
> +		return -EINVAL;
> +	}
> +	if (!range->gc) {
> +		dev_err(npcm->gc.parent, "invalid gpiochip\n");
> +		return -EINVAL;
> +	}
> +	dev_dbg(npcm->gc.parent, "Enable GPIO %d\n", offset);
> +	npcm_setfunc(offset, 1, fn_gpio);
> +	return 0;
> +}
> +
> +/* Release GPIO back to pinctrl mode */
> +static void npcm_gpio_request_free(struct pinctrl_dev *pctldev,
> +				   struct pinctrl_gpio_range *range,
> +				   unsigned int offset)
> +{
> +	struct npcm_dev *npcm = pinctrl_dev_get_drvdata(pctldev);
> +	int virq;
> +
> +	virq = irq_find_mapping(npcm->domain, offset);
> +	DRV_MSG2("Free GPIO %d, irq=%d\n", offset, virq);
> +	if (virq)
> +		irq_dispose_mapping(virq);
> +}
> +
> +/* Set GPIO direction */
> +static int npcm_gpio_set_direction(struct pinctrl_dev *pctldev,
> +				   struct pinctrl_gpio_range *range,
> +				   unsigned int offset, bool input)
> +{
> +	DRV_MSG2("GPIO Set Direction: %d = %d\n", offset, input);
> +	if (input) {
> +		gpio_bitop(opCLRBIT, offset, GPnOE);
> +		gpio_bitop(opSETBIT, offset, GPnIEM);
> +	} else {
> +		gpio_bitop(opCLRBIT, offset, GPnIEM);
> +		gpio_bitop(opSETBIT, offset, GPnOE);
> +	}
> +	return 0;
> +}
> +
> +static struct pinmux_ops npcm_pinmux_ops = {
> +#if 0
> +	.request(struct pinctrl_dev *, unsigned int);
> +	.free(struct pinctrl_dev *, unsigned int);
> +#endif

Delete the above.

> +	.get_functions_count = npcm_get_functions_count,
> +	.get_function_name = npcm_get_function_name,
> +	.get_function_groups = npcm_get_function_groups,
> +
> +	.set_mux = npcm_pinmux_set_mux,
> +
> +	.gpio_request_enable = npcm_gpio_request_enable,
> +	.gpio_disable_free = npcm_gpio_request_free,
> +	.gpio_set_direction = npcm_gpio_set_direction,
> +};
> +
> +/* ================= pinconf_ops ========================= */
> +
> +/* Get configuration setting for a pin */
> +static int npcm_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
> +			   unsigned long *config)
> +{
> +	enum pin_config_param param = pinconf_to_config_param(*config);
> +	u32 ie, oe, pu, pd;
> +	int rc;
> +
> +	rc = 0;
> +	switch (param) {
> +	case PIN_CONFIG_BIAS_DISABLE:
> +	case PIN_CONFIG_BIAS_PULL_UP:
> +	case PIN_CONFIG_BIAS_PULL_DOWN:
> +		pu = gpio_bitop(opGETBIT, pin, GPnPU);
> +		pd = gpio_bitop(opGETBIT, pin, GPnPD);
> +		if (param == PIN_CONFIG_BIAS_DISABLE)
> +			rc = (!pu && !pd);
> +		else if (param == PIN_CONFIG_BIAS_PULL_UP)
> +			rc = (pu && !pd);
> +		else if (param == PIN_CONFIG_BIAS_PULL_DOWN)
> +			rc = (!pu && pd);
> +		break;
> +	case PIN_CONFIG_OUTPUT:
> +	case PIN_CONFIG_INPUT_ENABLE:
> +		ie = gpio_bitop(opGETBIT, pin, GPnIEM);
> +		oe = gpio_bitop(opGETBIT, pin, GPnOE);
> +		if (param == PIN_CONFIG_INPUT_ENABLE)
> +			rc = (ie && !oe);
> +		else if (param == PIN_CONFIG_OUTPUT)
> +			rc = (!ie && oe);
> +		break;
> +	case PIN_CONFIG_DRIVE_PUSH_PULL:
> +		rc = !gpio_bitop(opGETBIT, pin, GPnOTYP);
> +		break;
> +	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
> +		rc = gpio_bitop(opGETBIT, pin, GPnOTYP);
> +		break;
> +	case PIN_CONFIG_INPUT_DEBOUNCE:
> +		rc = gpio_bitop(opGETBIT, pin, GPnDBNC);
> +		break;
> +	case PIN_CONFIG_DRIVE_STRENGTH:
> +		rc = npcm_get_drive_strength(pin);
> +		if (rc)
> +			*config = pinconf_to_config_packed(param, rc * 1000);
> +		break;
> +	case PIN_CONFIG_SLEW_RATE:
> +		rc = npcm_get_slew_rate(pin);
> +		if (rc >= 0)
> +			*config = pinconf_to_config_packed(param, rc);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	if (!rc)
> +		return -EINVAL;
> +	return 0;
> +}
> +
> +/* Set configuration setting for a pin */
> +static int npcm_config_set_one(struct npcm_dev *npcm, unsigned int pin,
> +			       unsigned long config)
> +{
> +	enum pin_config_param param = pinconf_to_config_param(config);
> +	u16 arg = pinconf_to_config_argument(config);
> +	int rc;
> +
> +	dev_dbg(npcm->gc.parent, "param=%d %d[GPIO]\n", param, pin);
> +	switch (param) {
> +	case PIN_CONFIG_BIAS_DISABLE:
> +		npcm_setfunc(pin, 1, fn_gpio);
> +		gpio_bitop(opCLRBIT, pin, GPnPU);
> +		gpio_bitop(opCLRBIT, pin, GPnPD);
> +		break;
> +	case PIN_CONFIG_BIAS_PULL_DOWN:
> +		/* arg: 0=GND, !0=enabled */
> +		npcm_setfunc(pin, 1, fn_gpio);
> +		gpio_bitop(opCLRBIT, pin, GPnPU);
> +		gpio_bitop(opSETBIT, pin, GPnPD);
> +		break;
> +	case PIN_CONFIG_BIAS_PULL_UP:
> +		/* arg: 0=VDD, !0=enabled */
> +		npcm_setfunc(pin, 1, fn_gpio);
> +		gpio_bitop(opCLRBIT, pin, GPnPD);
> +		gpio_bitop(opSETBIT, pin, GPnPU);
> +		break;
> +	case PIN_CONFIG_INPUT_ENABLE:
> +		/* arg: 0=disable, 1=enable */
> +		npcm_setfunc(pin, 1, fn_gpio);
> +		gpio_bitop(opCLRBIT, pin, GPnOE);
> +		gpio_bitop(opSETBIT, pin, GPnIEM);
> +		break;
> +	case PIN_CONFIG_OUTPUT:
> +		/* arg: 0=low, 1=high */
> +		npcm_setfunc(pin, 1, fn_gpio);
> +		gpio_bitop(opCLRBIT, pin, GPnIEM);
> +		gpio_bitop(opSETBIT, pin, GPnOE);
> +		gpio_bitop(opSET, pin, arg ? GPnDOS : GPnDOC);
> +		break;
> +	case PIN_CONFIG_DRIVE_PUSH_PULL:
> +		npcm_setfunc(pin, 1, fn_gpio);
> +		gpio_bitop(opCLRBIT, pin, GPnOTYP);
> +		break;
> +	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
> +		npcm_setfunc(pin, 1, fn_gpio);
> +		gpio_bitop(opSETBIT, pin, GPnOTYP);
> +		break;
> +	case PIN_CONFIG_INPUT_DEBOUNCE:
> +		npcm_setfunc(pin, 1, fn_gpio);
> +		gpio_bitop(opSETBIT, pin, GPnDBNC);
> +		break;
> +	case PIN_CONFIG_DRIVE_STRENGTH:
> +		/* arg is mA */
> +		npcm_setfunc(pin, 1, fn_gpio);
> +		rc = npcm_set_drive_strength(pin, arg / 1000);
> +		if (!rc)
> +			return -EINVAL;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	return 0;
> +}
> +
> +/* Set multiple configuration settings for a pin */
> +static int npcm_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
> +			   unsigned long *configs,
> +			   unsigned int num_configs)
> +{
> +	struct npcm_dev *npcm = pinctrl_dev_get_drvdata(pctldev);
> +	int rc;
> +
> +	while (num_configs--) {
> +		rc = npcm_config_set_one(npcm, pin, *configs++);
> +		if (rc)
> +			return rc;
> +	}
> +	return 0;
> +}
> +
> +static void npcm_config_dbg_show(struct pinctrl_dev *pctldev,
> +				 struct seq_file *s,
> +				 unsigned int offset)
> +{
> +}
> +
> +static void npcm_config_group_dbg_show(struct pinctrl_dev *pctldev,
> +				       struct seq_file *s,
> +				       unsigned int selector)
> +{
> +}
> +
> +static void npcm_config_config_dbg_show(struct pinctrl_dev *pctldev,
> +					struct seq_file *s,
> +					unsigned long config)
> +{
> +}
> +
> +static struct pinconf_ops npcm_pinconf_ops = {
> +	.is_generic = true,
> +	.pin_config_get = npcm_config_get,
> +	.pin_config_set = npcm_config_set,
> +	.pin_config_dbg_show = npcm_config_dbg_show,
> +	.pin_config_group_dbg_show = npcm_config_group_dbg_show,
> +	.pin_config_config_dbg_show = npcm_config_config_dbg_show,

The dbg_show() functions are all optional. Given the implementations
are empty, you should just delete them and remove the assignments here.

> +};
> +
> +/* ================= pinctrl_desc ========================= */
> +static struct pinctrl_desc npcm_desc = {
> +	.name = "npcm",
> +	.pins = npcm_pins,
> +	.npins = ARRAY_SIZE(npcm_pins),
> +	.pctlops = &npcm_pinctrl_ops,
> +	.pmxops = &npcm_pinmux_ops,
> +	.confops = &npcm_pinconf_ops,
> +	.owner = THIS_MODULE,
> +};
> +
> +static struct gpio_chip npcm_gc = {
> +	.owner		= THIS_MODULE,
> +	.label		= "npcmgpio",
> +	.request	= npcmgpio_gpio_request,
> +	.free		= npcmgpio_gpio_free,
> +	.get_direction	= npcmgpio_get_direction,
> +	.direction_input = npcmgpio_direction_input,
> +	.direction_output = npcmgpio_direction_output,
> +#if (KERNEL_VERSION(4, 10, 17) >= LINUX_VERSION_CODE)

I think we should just assume this now - this is the current stable
version of OpenBMC.

> +	.set_debounce	= npcmgpio_set_debounce,
> +#endif
> +	.get		= npcmgpio_get_value,
> +	.set		= npcmgpio_set_value,
> +	.dbg_show	= npcmgpio_dbg_show,
> +	.to_irq		= npcmgpio_to_irq,
> +#if ((KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE) && (KERNEL_VERSION(4, 10, 17) >= LINUX_VERSION_CODE))
> +	.set_single_ended = npcmgpio_set_single_ended,
> +#endif
> +	.ngpio		= 256,
> +};
> +
> +static int __init npcm_pin_init(void)
> +{
> +	int rc, i;
> +
> +	if (!npcm.pdev) {
> +		npcm.pdev = platform_device_alloc("npcm", 0);
> +		if (!npcm.pdev)
> +			return -ENOMEM;
> +		rc = platform_device_add(npcm.pdev);
> +		if (rc) {
> +			platform_device_put(npcm.pdev);
> +			return -ENODEV;
> +		}
> +	}
> +	npcm.gc = npcm_gc;
> +	npcm.gc.parent = &npcm.pdev->dev;
> +
> +	if (npcm_init_bank(GCR_BANK, GCR_BA, GCR_BANKSIZE, 0, NULL))
> +		return -EINVAL;
> +	/* Setup bank registers */
> +	for (i = 0; i < GPIO_NBANKS; i++) {
> +		if (npcm_init_bank(i, GPIO_BA + (i * GPIO_BANKSIZE),
> +				   GPIO_BANKSIZE, i,
> +				   "nuvoton,npcm750-gpio"))
> +			return -EINVAL;
> +		npcm_bank[i].irqbase = i * GPIO_PER_BANK;
> +#ifdef GPIO_DRIVER
> +		irq_set_irq_type(npcm_bank[i].irq, IRQ_TYPE_LEVEL_HIGH);
> +		irq_set_handler_data(npcm_bank[i].irq, &npcm_bank[i]);
> +		irq_set_chained_handler(npcm_bank[i].irq, npcmgpio_irq_handler);
> +#endif
> +	}
> +	npcm.pctl = pinctrl_register(&npcm_desc, npcm.gc.parent, &npcm);
> +	if (!npcm.pctl) {
> +		platform_device_del(npcm.pdev);
> +		platform_device_put(npcm.pdev);

Both of these steps can be done in one with
platform_device_unregister(). I found this because the _del() / _put()
sequence seems odd, but that's what platform_device_unregister() does
as well.

> +		DRV_MSG2("could not register foo pin driver\n");
> +		return -EINVAL;
> +	}
> +#ifdef GPIO_DRIVER
> +	rc = gpiochip_add(&npcm.gc);
> +	if (rc) {
> +		DRV_MSG2("gpiochip_add fails\n");
> +		return rc;
> +	}
> +	rc = gpiochip_add_pin_range(&npcm.gc, dev_name(npcm.gc.parent),
> +				    0, 0, npcm.gc.ngpio);
> +	if (rc) {
> +		DRV_MSG2("gpiochip_add_pin_range fails\n");
> +		return rc;
> +	}
> +	npcm.domain = irq_domain_add_linear(NULL, npcm.gc.ngpio,
> +					    &npcmgpio_domain_ops,
> +					    &npcmgpio_irqchip);

This should be using the gpiochip_irqchip_*() abstractions

> +	if (!npcm.domain) {
> +		DRV_MSG2("irqdomain_add fails\n");
> +		return -ENOMEM;
> +	}
> +#endif
> +	/* pinctrl_select_state(..., state); */
> +	pr_info("Nuvoton Pinctrl driver version %s [%s]\n", DRV_VERSION, DRV_DATE);
> +	return 0;
> +}
> +
> +static void npcm_pin_exit(void)
> +{
> +	int i;
> +
> +#ifdef GPIO_DRIVER
> +	irq_domain_remove(npcm.domain);

Instead of ifdef'ing this we could test if the pointer is NULL.

> +	gpiochip_remove(&npcm.gc);
> +#endif
> +	for (i = 0; i < GPIO_NBANKS; i++) {
> +#ifdef GPIO_DRIVER

Similarly here.

> +		irq_set_chained_handler(npcm_bank[i].irq, NULL);
> +#endif
> +		iounmap(npcm_bank[i].base);
> +	}
> +	iounmap(npcm_bank[GCR_BANK].base);
> +	pinctrl_unregister(npcm.pctl);
> +	platform_device_unregister(npcm.pdev);
> +}
> +
> +static int npcm_pinctrl_probe(struct platform_device *pdev)
> +{
> +	npcm.pdev = pdev;
> +	npcm_pin_init();

Calling npcm_pin_init() from probe() feels backwards. I rather think
the implementation should be the other way around: Move all of the code
in init() into probe, then let the driver model take care of calling
your probe().

Doing that we can avoid the npcm global. Instead, allocate one
dynamically and stuff it's pointer into the platform device with
platform_set_drvdata().

> +	return 0;
> +}
> +
> +static int npcm_pinctrl_remove(struct platform_device *pdev)
> +{
> +	npcm_pin_exit();

As above for probe(), put the exit() code in remove() and let the
driver model do it all for you.

> +	return 0;
> +}
> +
> +static const struct of_device_id npcm_pinctrl_match[] = {
> +	{ .compatible = "nuvoton,npcmx50-pinctrl" },
> +	{ },
> +};
> +
> +MODULE_DEVICE_TABLE(of, npcm_pinctrl_match);
> +
> +static struct platform_driver npcm_pinctrl_driver = {
> +	.probe = npcm_pinctrl_probe,
> +	.remove = npcm_pinctrl_remove,
> +	.driver = {
> +		.name = "npcm-pinctrl",
> +		.owner = THIS_MODULE,
> +		.of_match_table = of_match_ptr(npcm_pinctrl_match),
> +	},
> +};
> +
> +module_platform_driver(npcm_pinctrl_driver);

This implements init() and exit() for you, so with the the suggestions
regarding moving the code for probe() and remove() we can delete the
current init() and exit() implementations.

Hope that helps!

Andrew

> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("jordan_hargrave at dell.com");
> +MODULE_VERSION(DRV_VERSION);
> +MODULE_DESCRIPTION("Provide Pinctrl/GPIO methods for NPCM7XX");
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: This is a digitally signed message part
URL: <http://lists.ozlabs.org/pipermail/openbmc/attachments/20180110/2edc77a2/attachment-0001.sig>


More information about the openbmc mailing list