162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci// Copyright (c) 2016-2018 Nuvoton Technology corporation.
362306a36Sopenharmony_ci// Copyright (c) 2016, Dell Inc
462306a36Sopenharmony_ci// Copyright (c) 2021-2022 Jonathan Neuschäfer
562306a36Sopenharmony_ci//
662306a36Sopenharmony_ci// This driver uses the following registers:
762306a36Sopenharmony_ci// - Pin mux registers, in the GCR (general control registers) block
862306a36Sopenharmony_ci// - GPIO registers, specific to each GPIO bank
962306a36Sopenharmony_ci// - GPIO event (interrupt) registers, located centrally in the GPIO register
1062306a36Sopenharmony_ci//   block, shared between all GPIO banks
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/device.h>
1362306a36Sopenharmony_ci#include <linux/fwnode.h>
1462306a36Sopenharmony_ci#include <linux/gpio/driver.h>
1562306a36Sopenharmony_ci#include <linux/interrupt.h>
1662306a36Sopenharmony_ci#include <linux/irq.h>
1762306a36Sopenharmony_ci#include <linux/mfd/syscon.h>
1862306a36Sopenharmony_ci#include <linux/module.h>
1962306a36Sopenharmony_ci#include <linux/mod_devicetable.h>
2062306a36Sopenharmony_ci#include <linux/platform_device.h>
2162306a36Sopenharmony_ci#include <linux/regmap.h>
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#include <linux/pinctrl/pinconf.h>
2462306a36Sopenharmony_ci#include <linux/pinctrl/pinconf-generic.h>
2562306a36Sopenharmony_ci#include <linux/pinctrl/pinctrl.h>
2662306a36Sopenharmony_ci#include <linux/pinctrl/pinmux.h>
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#include "../core.h"
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/* GCR registers */
3162306a36Sopenharmony_ci#define WPCM450_GCR_MFSEL1	0x0c
3262306a36Sopenharmony_ci#define WPCM450_GCR_MFSEL2	0x10
3362306a36Sopenharmony_ci#define WPCM450_GCR_NONE	0
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci/* GPIO event (interrupt) registers */
3662306a36Sopenharmony_ci#define WPCM450_GPEVTYPE	0x00
3762306a36Sopenharmony_ci#define WPCM450_GPEVPOL		0x04
3862306a36Sopenharmony_ci#define WPCM450_GPEVDBNC	0x08
3962306a36Sopenharmony_ci#define WPCM450_GPEVEN		0x0c
4062306a36Sopenharmony_ci#define WPCM450_GPEVST		0x10
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define WPCM450_NUM_BANKS	8
4362306a36Sopenharmony_ci#define WPCM450_NUM_GPIOS	128
4462306a36Sopenharmony_ci#define WPCM450_NUM_GPIO_IRQS	4
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistruct wpcm450_pinctrl;
4762306a36Sopenharmony_cistruct wpcm450_bank;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistruct wpcm450_gpio {
5062306a36Sopenharmony_ci	struct gpio_chip	gc;
5162306a36Sopenharmony_ci	struct wpcm450_pinctrl	*pctrl;
5262306a36Sopenharmony_ci	const struct wpcm450_bank *bank;
5362306a36Sopenharmony_ci};
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistruct wpcm450_pinctrl {
5662306a36Sopenharmony_ci	struct pinctrl_dev	*pctldev;
5762306a36Sopenharmony_ci	struct device		*dev;
5862306a36Sopenharmony_ci	struct irq_domain	*domain;
5962306a36Sopenharmony_ci	struct regmap		*gcr_regmap;
6062306a36Sopenharmony_ci	void __iomem		*gpio_base;
6162306a36Sopenharmony_ci	struct wpcm450_gpio	gpio_bank[WPCM450_NUM_BANKS];
6262306a36Sopenharmony_ci	unsigned long		both_edges;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	/*
6562306a36Sopenharmony_ci	 * This spin lock protects registers and struct wpcm450_pinctrl fields
6662306a36Sopenharmony_ci	 * against concurrent access.
6762306a36Sopenharmony_ci	 */
6862306a36Sopenharmony_ci	raw_spinlock_t		lock;
6962306a36Sopenharmony_ci};
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cistruct wpcm450_bank {
7262306a36Sopenharmony_ci	/* Range of GPIOs in this port */
7362306a36Sopenharmony_ci	u8 base;
7462306a36Sopenharmony_ci	u8 length;
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	/* Register offsets (0 = register doesn't exist in this port) */
7762306a36Sopenharmony_ci	u8 cfg0, cfg1, cfg2;
7862306a36Sopenharmony_ci	u8 blink;
7962306a36Sopenharmony_ci	u8 dataout, datain;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	/* Interrupt bit mapping */
8262306a36Sopenharmony_ci	u8 first_irq_bit;   /* First bit in GPEVST that belongs to this bank */
8362306a36Sopenharmony_ci	u8 num_irqs;        /* Number of IRQ-capable GPIOs in this bank */
8462306a36Sopenharmony_ci	u8 first_irq_gpio;  /* First IRQ-capable GPIO in this bank */
8562306a36Sopenharmony_ci};
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cistatic const struct wpcm450_bank wpcm450_banks[WPCM450_NUM_BANKS] = {
8862306a36Sopenharmony_ci	/*  range   cfg0  cfg1  cfg2 blink  out   in     IRQ map */
8962306a36Sopenharmony_ci	{   0, 16,  0x14, 0x18,    0,    0, 0x1c, 0x20,  0, 16, 0 },
9062306a36Sopenharmony_ci	{  16, 16,  0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 16,  2, 8 },
9162306a36Sopenharmony_ci	{  32, 16,  0x3c, 0x40, 0x44,    0, 0x48, 0x4c,  0,  0, 0 },
9262306a36Sopenharmony_ci	{  48, 16,  0x50, 0x54, 0x58,    0, 0x5c, 0x60,  0,  0, 0 },
9362306a36Sopenharmony_ci	{  64, 16,  0x64, 0x68, 0x6c,    0, 0x70, 0x74,  0,  0, 0 },
9462306a36Sopenharmony_ci	{  80, 16,  0x78, 0x7c, 0x80,    0, 0x84, 0x88,  0,  0, 0 },
9562306a36Sopenharmony_ci	{  96, 18,     0,    0,    0,    0,    0, 0x8c,  0,  0, 0 },
9662306a36Sopenharmony_ci	{ 114, 14,  0x90, 0x94, 0x98,    0, 0x9c, 0xa0,  0,  0, 0 },
9762306a36Sopenharmony_ci};
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic int wpcm450_gpio_irq_bitnum(struct wpcm450_gpio *gpio, struct irq_data *d)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	const struct wpcm450_bank *bank = gpio->bank;
10262306a36Sopenharmony_ci	int hwirq = irqd_to_hwirq(d);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	if (hwirq < bank->first_irq_gpio)
10562306a36Sopenharmony_ci		return -EINVAL;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	if (hwirq - bank->first_irq_gpio >= bank->num_irqs)
10862306a36Sopenharmony_ci		return -EINVAL;
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	return hwirq - bank->first_irq_gpio + bank->first_irq_bit;
11162306a36Sopenharmony_ci}
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_cistatic int wpcm450_irq_bitnum_to_gpio(struct wpcm450_gpio *gpio, int bitnum)
11462306a36Sopenharmony_ci{
11562306a36Sopenharmony_ci	const struct wpcm450_bank *bank = gpio->bank;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	if (bitnum < bank->first_irq_bit)
11862306a36Sopenharmony_ci		return -EINVAL;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	if (bitnum - bank->first_irq_bit > bank->num_irqs)
12162306a36Sopenharmony_ci		return -EINVAL;
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	return bitnum - bank->first_irq_bit + bank->first_irq_gpio;
12462306a36Sopenharmony_ci}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cistatic void wpcm450_gpio_irq_ack(struct irq_data *d)
12762306a36Sopenharmony_ci{
12862306a36Sopenharmony_ci	struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(d));
12962306a36Sopenharmony_ci	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
13062306a36Sopenharmony_ci	unsigned long flags;
13162306a36Sopenharmony_ci	int bit;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	bit = wpcm450_gpio_irq_bitnum(gpio, d);
13462306a36Sopenharmony_ci	if (bit < 0)
13562306a36Sopenharmony_ci		return;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	raw_spin_lock_irqsave(&pctrl->lock, flags);
13862306a36Sopenharmony_ci	iowrite32(BIT(bit), pctrl->gpio_base + WPCM450_GPEVST);
13962306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
14062306a36Sopenharmony_ci}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistatic void wpcm450_gpio_irq_mask(struct irq_data *d)
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
14562306a36Sopenharmony_ci	struct wpcm450_gpio *gpio = gpiochip_get_data(gc);
14662306a36Sopenharmony_ci	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
14762306a36Sopenharmony_ci	unsigned long flags;
14862306a36Sopenharmony_ci	unsigned long even;
14962306a36Sopenharmony_ci	int bit;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	bit = wpcm450_gpio_irq_bitnum(gpio, d);
15262306a36Sopenharmony_ci	if (bit < 0)
15362306a36Sopenharmony_ci		return;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	raw_spin_lock_irqsave(&pctrl->lock, flags);
15662306a36Sopenharmony_ci	even = ioread32(pctrl->gpio_base + WPCM450_GPEVEN);
15762306a36Sopenharmony_ci	__assign_bit(bit, &even, 0);
15862306a36Sopenharmony_ci	iowrite32(even, pctrl->gpio_base + WPCM450_GPEVEN);
15962306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	gpiochip_disable_irq(gc, irqd_to_hwirq(d));
16262306a36Sopenharmony_ci}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_cistatic void wpcm450_gpio_irq_unmask(struct irq_data *d)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
16762306a36Sopenharmony_ci	struct wpcm450_gpio *gpio = gpiochip_get_data(gc);
16862306a36Sopenharmony_ci	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
16962306a36Sopenharmony_ci	unsigned long flags;
17062306a36Sopenharmony_ci	unsigned long even;
17162306a36Sopenharmony_ci	int bit;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	bit = wpcm450_gpio_irq_bitnum(gpio, d);
17462306a36Sopenharmony_ci	if (bit < 0)
17562306a36Sopenharmony_ci		return;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	gpiochip_enable_irq(gc, irqd_to_hwirq(d));
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	raw_spin_lock_irqsave(&pctrl->lock, flags);
18062306a36Sopenharmony_ci	even = ioread32(pctrl->gpio_base + WPCM450_GPEVEN);
18162306a36Sopenharmony_ci	__assign_bit(bit, &even, 1);
18262306a36Sopenharmony_ci	iowrite32(even, pctrl->gpio_base + WPCM450_GPEVEN);
18362306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
18462306a36Sopenharmony_ci}
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci/*
18762306a36Sopenharmony_ci * This is an implementation of the gpio_chip->get() function, for use in
18862306a36Sopenharmony_ci * wpcm450_gpio_fix_evpol. Unfortunately, we can't use the bgpio-provided
18962306a36Sopenharmony_ci * implementation there, because it would require taking gpio_chip->bgpio_lock,
19062306a36Sopenharmony_ci * which is a spin lock, but wpcm450_gpio_fix_evpol must work in contexts where
19162306a36Sopenharmony_ci * a raw spin lock is held.
19262306a36Sopenharmony_ci */
19362306a36Sopenharmony_cistatic int wpcm450_gpio_get(struct wpcm450_gpio *gpio, int offset)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	void __iomem *reg = gpio->pctrl->gpio_base + gpio->bank->datain;
19662306a36Sopenharmony_ci	unsigned long flags;
19762306a36Sopenharmony_ci	u32 level;
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	raw_spin_lock_irqsave(&gpio->pctrl->lock, flags);
20062306a36Sopenharmony_ci	level = !!(ioread32(reg) & BIT(offset));
20162306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&gpio->pctrl->lock, flags);
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	return level;
20462306a36Sopenharmony_ci}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci/*
20762306a36Sopenharmony_ci * Since the GPIO controller does not support dual-edge triggered interrupts
20862306a36Sopenharmony_ci * (IRQ_TYPE_EDGE_BOTH), they are emulated using rising/falling edge triggered
20962306a36Sopenharmony_ci * interrupts. wpcm450_gpio_fix_evpol sets the interrupt polarity for the
21062306a36Sopenharmony_ci * specified emulated dual-edge triggered interrupts, so that the next edge can
21162306a36Sopenharmony_ci * be detected.
21262306a36Sopenharmony_ci */
21362306a36Sopenharmony_cistatic void wpcm450_gpio_fix_evpol(struct wpcm450_gpio *gpio, unsigned long all)
21462306a36Sopenharmony_ci{
21562306a36Sopenharmony_ci	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
21662306a36Sopenharmony_ci	unsigned int bit;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	for_each_set_bit(bit, &all, 32) {
21962306a36Sopenharmony_ci		int offset = wpcm450_irq_bitnum_to_gpio(gpio, bit);
22062306a36Sopenharmony_ci		unsigned long evpol;
22162306a36Sopenharmony_ci		unsigned long flags;
22262306a36Sopenharmony_ci		int level;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci		do {
22562306a36Sopenharmony_ci			level = wpcm450_gpio_get(gpio, offset);
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci			/* Switch event polarity to the opposite of the current level */
22862306a36Sopenharmony_ci			raw_spin_lock_irqsave(&pctrl->lock, flags);
22962306a36Sopenharmony_ci			evpol = ioread32(pctrl->gpio_base + WPCM450_GPEVPOL);
23062306a36Sopenharmony_ci			__assign_bit(bit, &evpol, !level);
23162306a36Sopenharmony_ci			iowrite32(evpol, pctrl->gpio_base + WPCM450_GPEVPOL);
23262306a36Sopenharmony_ci			raw_spin_unlock_irqrestore(&pctrl->lock, flags);
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci		} while (wpcm450_gpio_get(gpio, offset) != level);
23562306a36Sopenharmony_ci	}
23662306a36Sopenharmony_ci}
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cistatic int wpcm450_gpio_set_irq_type(struct irq_data *d, unsigned int flow_type)
23962306a36Sopenharmony_ci{
24062306a36Sopenharmony_ci	struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(d));
24162306a36Sopenharmony_ci	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
24262306a36Sopenharmony_ci	unsigned long evtype, evpol;
24362306a36Sopenharmony_ci	unsigned long flags;
24462306a36Sopenharmony_ci	int ret = 0;
24562306a36Sopenharmony_ci	int bit;
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	bit = wpcm450_gpio_irq_bitnum(gpio, d);
24862306a36Sopenharmony_ci	if (bit < 0)
24962306a36Sopenharmony_ci		return bit;
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	irq_set_handler_locked(d, handle_level_irq);
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	raw_spin_lock_irqsave(&pctrl->lock, flags);
25462306a36Sopenharmony_ci	evtype = ioread32(pctrl->gpio_base + WPCM450_GPEVTYPE);
25562306a36Sopenharmony_ci	evpol = ioread32(pctrl->gpio_base + WPCM450_GPEVPOL);
25662306a36Sopenharmony_ci	__assign_bit(bit, &pctrl->both_edges, 0);
25762306a36Sopenharmony_ci	switch (flow_type) {
25862306a36Sopenharmony_ci	case IRQ_TYPE_LEVEL_LOW:
25962306a36Sopenharmony_ci		__assign_bit(bit, &evtype, 1);
26062306a36Sopenharmony_ci		__assign_bit(bit, &evpol, 0);
26162306a36Sopenharmony_ci		break;
26262306a36Sopenharmony_ci	case IRQ_TYPE_LEVEL_HIGH:
26362306a36Sopenharmony_ci		__assign_bit(bit, &evtype, 1);
26462306a36Sopenharmony_ci		__assign_bit(bit, &evpol, 1);
26562306a36Sopenharmony_ci		break;
26662306a36Sopenharmony_ci	case IRQ_TYPE_EDGE_FALLING:
26762306a36Sopenharmony_ci		__assign_bit(bit, &evtype, 0);
26862306a36Sopenharmony_ci		__assign_bit(bit, &evpol, 0);
26962306a36Sopenharmony_ci		break;
27062306a36Sopenharmony_ci	case IRQ_TYPE_EDGE_RISING:
27162306a36Sopenharmony_ci		__assign_bit(bit, &evtype, 0);
27262306a36Sopenharmony_ci		__assign_bit(bit, &evpol, 1);
27362306a36Sopenharmony_ci		break;
27462306a36Sopenharmony_ci	case IRQ_TYPE_EDGE_BOTH:
27562306a36Sopenharmony_ci		__assign_bit(bit, &evtype, 0);
27662306a36Sopenharmony_ci		__assign_bit(bit, &pctrl->both_edges, 1);
27762306a36Sopenharmony_ci		break;
27862306a36Sopenharmony_ci	default:
27962306a36Sopenharmony_ci		ret = -EINVAL;
28062306a36Sopenharmony_ci	}
28162306a36Sopenharmony_ci	iowrite32(evtype, pctrl->gpio_base + WPCM450_GPEVTYPE);
28262306a36Sopenharmony_ci	iowrite32(evpol, pctrl->gpio_base + WPCM450_GPEVPOL);
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	/* clear the event status for good measure */
28562306a36Sopenharmony_ci	iowrite32(BIT(bit), pctrl->gpio_base + WPCM450_GPEVST);
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	/* fix event polarity after clearing event status */
29062306a36Sopenharmony_ci	wpcm450_gpio_fix_evpol(gpio, BIT(bit));
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	return ret;
29362306a36Sopenharmony_ci}
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_cistatic const struct irq_chip wpcm450_gpio_irqchip = {
29662306a36Sopenharmony_ci	.name = "WPCM450-GPIO-IRQ",
29762306a36Sopenharmony_ci	.irq_ack = wpcm450_gpio_irq_ack,
29862306a36Sopenharmony_ci	.irq_unmask = wpcm450_gpio_irq_unmask,
29962306a36Sopenharmony_ci	.irq_mask = wpcm450_gpio_irq_mask,
30062306a36Sopenharmony_ci	.irq_set_type = wpcm450_gpio_set_irq_type,
30162306a36Sopenharmony_ci	.flags = IRQCHIP_IMMUTABLE,
30262306a36Sopenharmony_ci	GPIOCHIP_IRQ_RESOURCE_HELPERS,
30362306a36Sopenharmony_ci};
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_cistatic void wpcm450_gpio_irqhandler(struct irq_desc *desc)
30662306a36Sopenharmony_ci{
30762306a36Sopenharmony_ci	struct wpcm450_gpio *gpio = gpiochip_get_data(irq_desc_get_handler_data(desc));
30862306a36Sopenharmony_ci	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
30962306a36Sopenharmony_ci	struct irq_chip *chip = irq_desc_get_chip(desc);
31062306a36Sopenharmony_ci	unsigned long pending;
31162306a36Sopenharmony_ci	unsigned long flags;
31262306a36Sopenharmony_ci	unsigned long ours;
31362306a36Sopenharmony_ci	unsigned int bit;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	ours = GENMASK(gpio->bank->num_irqs - 1, 0) << gpio->bank->first_irq_bit;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	raw_spin_lock_irqsave(&pctrl->lock, flags);
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	pending = ioread32(pctrl->gpio_base + WPCM450_GPEVST);
32062306a36Sopenharmony_ci	pending &= ioread32(pctrl->gpio_base + WPCM450_GPEVEN);
32162306a36Sopenharmony_ci	pending &= ours;
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	if (pending & pctrl->both_edges)
32662306a36Sopenharmony_ci		wpcm450_gpio_fix_evpol(gpio, pending & pctrl->both_edges);
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	chained_irq_enter(chip, desc);
32962306a36Sopenharmony_ci	for_each_set_bit(bit, &pending, 32) {
33062306a36Sopenharmony_ci		int offset = wpcm450_irq_bitnum_to_gpio(gpio, bit);
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci		generic_handle_domain_irq(gpio->gc.irq.domain, offset);
33362306a36Sopenharmony_ci	}
33462306a36Sopenharmony_ci	chained_irq_exit(chip, desc);
33562306a36Sopenharmony_ci}
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_cistatic int smb0_pins[]  = { 115, 114 };
33862306a36Sopenharmony_cistatic int smb1_pins[]  = { 117, 116 };
33962306a36Sopenharmony_cistatic int smb2_pins[]  = { 119, 118 };
34062306a36Sopenharmony_cistatic int smb3_pins[]  = { 30, 31 };
34162306a36Sopenharmony_cistatic int smb4_pins[]  = { 28, 29 };
34262306a36Sopenharmony_cistatic int smb5_pins[]  = { 26, 27 };
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_cistatic int scs1_pins[] = { 32 };
34562306a36Sopenharmony_cistatic int scs2_pins[] = { 33 };
34662306a36Sopenharmony_cistatic int scs3_pins[] = { 34 };
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_cistatic int bsp_pins[] = { 41, 42 };
34962306a36Sopenharmony_cistatic int hsp1_pins[] = { 43, 44, 45, 46, 47, 61, 62, 63 };
35062306a36Sopenharmony_cistatic int hsp2_pins[] = { 48, 49, 50, 51, 52, 53, 54, 55 };
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_cistatic int r1err_pins[] = { 56 };
35362306a36Sopenharmony_cistatic int r1md_pins[] = { 57, 58 };
35462306a36Sopenharmony_cistatic int rmii2_pins[] = { 84, 85, 86, 87, 88, 89 };
35562306a36Sopenharmony_cistatic int r2err_pins[] = { 90 };
35662306a36Sopenharmony_cistatic int r2md_pins[] = { 91, 92 };
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_cistatic int kbcc_pins[] = { 94, 93 };
35962306a36Sopenharmony_cistatic int clko_pins[] = { 96 };
36062306a36Sopenharmony_cistatic int smi_pins[] = { 97 };
36162306a36Sopenharmony_cistatic int uinc_pins[] = { 19 };
36262306a36Sopenharmony_cistatic int mben_pins[] = {};
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_cistatic int gspi_pins[] = { 12, 13, 14, 15 };
36562306a36Sopenharmony_cistatic int sspi_pins[] = { 12, 13, 14, 15 };
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_cistatic int xcs1_pins[] = { 35 };
36862306a36Sopenharmony_cistatic int xcs2_pins[] = { 36 };
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_cistatic int sdio_pins[] = { 7, 22, 43, 44, 45, 46, 47, 60 };
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_cistatic int fi0_pins[] = { 64 };
37362306a36Sopenharmony_cistatic int fi1_pins[] = { 65 };
37462306a36Sopenharmony_cistatic int fi2_pins[] = { 66 };
37562306a36Sopenharmony_cistatic int fi3_pins[] = { 67 };
37662306a36Sopenharmony_cistatic int fi4_pins[] = { 68 };
37762306a36Sopenharmony_cistatic int fi5_pins[] = { 69 };
37862306a36Sopenharmony_cistatic int fi6_pins[] = { 70 };
37962306a36Sopenharmony_cistatic int fi7_pins[] = { 71 };
38062306a36Sopenharmony_cistatic int fi8_pins[] = { 72 };
38162306a36Sopenharmony_cistatic int fi9_pins[] = { 73 };
38262306a36Sopenharmony_cistatic int fi10_pins[] = { 74 };
38362306a36Sopenharmony_cistatic int fi11_pins[] = { 75 };
38462306a36Sopenharmony_cistatic int fi12_pins[] = { 76 };
38562306a36Sopenharmony_cistatic int fi13_pins[] = { 77 };
38662306a36Sopenharmony_cistatic int fi14_pins[] = { 78 };
38762306a36Sopenharmony_cistatic int fi15_pins[] = { 79 };
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_cistatic int pwm0_pins[] = { 80 };
39062306a36Sopenharmony_cistatic int pwm1_pins[] = { 81 };
39162306a36Sopenharmony_cistatic int pwm2_pins[] = { 82 };
39262306a36Sopenharmony_cistatic int pwm3_pins[] = { 83 };
39362306a36Sopenharmony_cistatic int pwm4_pins[] = { 20 };
39462306a36Sopenharmony_cistatic int pwm5_pins[] = { 21 };
39562306a36Sopenharmony_cistatic int pwm6_pins[] = { 16 };
39662306a36Sopenharmony_cistatic int pwm7_pins[] = { 17 };
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_cistatic int hg0_pins[] = { 20 };
39962306a36Sopenharmony_cistatic int hg1_pins[] = { 21 };
40062306a36Sopenharmony_cistatic int hg2_pins[] = { 22 };
40162306a36Sopenharmony_cistatic int hg3_pins[] = { 23 };
40262306a36Sopenharmony_cistatic int hg4_pins[] = { 24 };
40362306a36Sopenharmony_cistatic int hg5_pins[] = { 25 };
40462306a36Sopenharmony_cistatic int hg6_pins[] = { 59 };
40562306a36Sopenharmony_cistatic int hg7_pins[] = { 60 };
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci#define WPCM450_GRPS \
40862306a36Sopenharmony_ci	WPCM450_GRP(smb3), \
40962306a36Sopenharmony_ci	WPCM450_GRP(smb4), \
41062306a36Sopenharmony_ci	WPCM450_GRP(smb5), \
41162306a36Sopenharmony_ci	WPCM450_GRP(scs1), \
41262306a36Sopenharmony_ci	WPCM450_GRP(scs2), \
41362306a36Sopenharmony_ci	WPCM450_GRP(scs3), \
41462306a36Sopenharmony_ci	WPCM450_GRP(smb0), \
41562306a36Sopenharmony_ci	WPCM450_GRP(smb1), \
41662306a36Sopenharmony_ci	WPCM450_GRP(smb2), \
41762306a36Sopenharmony_ci	WPCM450_GRP(bsp), \
41862306a36Sopenharmony_ci	WPCM450_GRP(hsp1), \
41962306a36Sopenharmony_ci	WPCM450_GRP(hsp2), \
42062306a36Sopenharmony_ci	WPCM450_GRP(r1err), \
42162306a36Sopenharmony_ci	WPCM450_GRP(r1md), \
42262306a36Sopenharmony_ci	WPCM450_GRP(rmii2), \
42362306a36Sopenharmony_ci	WPCM450_GRP(r2err), \
42462306a36Sopenharmony_ci	WPCM450_GRP(r2md), \
42562306a36Sopenharmony_ci	WPCM450_GRP(kbcc), \
42662306a36Sopenharmony_ci	WPCM450_GRP(clko), \
42762306a36Sopenharmony_ci	WPCM450_GRP(smi), \
42862306a36Sopenharmony_ci	WPCM450_GRP(uinc), \
42962306a36Sopenharmony_ci	WPCM450_GRP(gspi), \
43062306a36Sopenharmony_ci	WPCM450_GRP(mben), \
43162306a36Sopenharmony_ci	WPCM450_GRP(xcs2), \
43262306a36Sopenharmony_ci	WPCM450_GRP(xcs1), \
43362306a36Sopenharmony_ci	WPCM450_GRP(sdio), \
43462306a36Sopenharmony_ci	WPCM450_GRP(sspi), \
43562306a36Sopenharmony_ci	WPCM450_GRP(fi0), \
43662306a36Sopenharmony_ci	WPCM450_GRP(fi1), \
43762306a36Sopenharmony_ci	WPCM450_GRP(fi2), \
43862306a36Sopenharmony_ci	WPCM450_GRP(fi3), \
43962306a36Sopenharmony_ci	WPCM450_GRP(fi4), \
44062306a36Sopenharmony_ci	WPCM450_GRP(fi5), \
44162306a36Sopenharmony_ci	WPCM450_GRP(fi6), \
44262306a36Sopenharmony_ci	WPCM450_GRP(fi7), \
44362306a36Sopenharmony_ci	WPCM450_GRP(fi8), \
44462306a36Sopenharmony_ci	WPCM450_GRP(fi9), \
44562306a36Sopenharmony_ci	WPCM450_GRP(fi10), \
44662306a36Sopenharmony_ci	WPCM450_GRP(fi11), \
44762306a36Sopenharmony_ci	WPCM450_GRP(fi12), \
44862306a36Sopenharmony_ci	WPCM450_GRP(fi13), \
44962306a36Sopenharmony_ci	WPCM450_GRP(fi14), \
45062306a36Sopenharmony_ci	WPCM450_GRP(fi15), \
45162306a36Sopenharmony_ci	WPCM450_GRP(pwm0), \
45262306a36Sopenharmony_ci	WPCM450_GRP(pwm1), \
45362306a36Sopenharmony_ci	WPCM450_GRP(pwm2), \
45462306a36Sopenharmony_ci	WPCM450_GRP(pwm3), \
45562306a36Sopenharmony_ci	WPCM450_GRP(pwm4), \
45662306a36Sopenharmony_ci	WPCM450_GRP(pwm5), \
45762306a36Sopenharmony_ci	WPCM450_GRP(pwm6), \
45862306a36Sopenharmony_ci	WPCM450_GRP(pwm7), \
45962306a36Sopenharmony_ci	WPCM450_GRP(hg0), \
46062306a36Sopenharmony_ci	WPCM450_GRP(hg1), \
46162306a36Sopenharmony_ci	WPCM450_GRP(hg2), \
46262306a36Sopenharmony_ci	WPCM450_GRP(hg3), \
46362306a36Sopenharmony_ci	WPCM450_GRP(hg4), \
46462306a36Sopenharmony_ci	WPCM450_GRP(hg5), \
46562306a36Sopenharmony_ci	WPCM450_GRP(hg6), \
46662306a36Sopenharmony_ci	WPCM450_GRP(hg7), \
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_cienum {
46962306a36Sopenharmony_ci#define WPCM450_GRP(x) fn_ ## x
47062306a36Sopenharmony_ci	WPCM450_GRPS
47162306a36Sopenharmony_ci	/* add placeholder for none/gpio */
47262306a36Sopenharmony_ci	WPCM450_GRP(gpio),
47362306a36Sopenharmony_ci	WPCM450_GRP(none),
47462306a36Sopenharmony_ci#undef WPCM450_GRP
47562306a36Sopenharmony_ci};
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_cistatic struct group_desc wpcm450_groups[] = {
47862306a36Sopenharmony_ci#define WPCM450_GRP(x) { .name = #x, .pins = x ## _pins, \
47962306a36Sopenharmony_ci			.num_pins = ARRAY_SIZE(x ## _pins) }
48062306a36Sopenharmony_ci	WPCM450_GRPS
48162306a36Sopenharmony_ci#undef WPCM450_GRP
48262306a36Sopenharmony_ci};
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci#define WPCM450_SFUNC(a) WPCM450_FUNC(a, #a)
48562306a36Sopenharmony_ci#define WPCM450_FUNC(a, b...) static const char *a ## _grp[] = { b }
48662306a36Sopenharmony_ci#define WPCM450_MKFUNC(nm) { .name = #nm, .ngroups = ARRAY_SIZE(nm ## _grp), \
48762306a36Sopenharmony_ci			.groups = nm ## _grp }
48862306a36Sopenharmony_cistruct wpcm450_func {
48962306a36Sopenharmony_ci	const char *name;
49062306a36Sopenharmony_ci	const unsigned int ngroups;
49162306a36Sopenharmony_ci	const char *const *groups;
49262306a36Sopenharmony_ci};
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ciWPCM450_SFUNC(smb3);
49562306a36Sopenharmony_ciWPCM450_SFUNC(smb4);
49662306a36Sopenharmony_ciWPCM450_SFUNC(smb5);
49762306a36Sopenharmony_ciWPCM450_SFUNC(scs1);
49862306a36Sopenharmony_ciWPCM450_SFUNC(scs2);
49962306a36Sopenharmony_ciWPCM450_SFUNC(scs3);
50062306a36Sopenharmony_ciWPCM450_SFUNC(smb0);
50162306a36Sopenharmony_ciWPCM450_SFUNC(smb1);
50262306a36Sopenharmony_ciWPCM450_SFUNC(smb2);
50362306a36Sopenharmony_ciWPCM450_SFUNC(bsp);
50462306a36Sopenharmony_ciWPCM450_SFUNC(hsp1);
50562306a36Sopenharmony_ciWPCM450_SFUNC(hsp2);
50662306a36Sopenharmony_ciWPCM450_SFUNC(r1err);
50762306a36Sopenharmony_ciWPCM450_SFUNC(r1md);
50862306a36Sopenharmony_ciWPCM450_SFUNC(rmii2);
50962306a36Sopenharmony_ciWPCM450_SFUNC(r2err);
51062306a36Sopenharmony_ciWPCM450_SFUNC(r2md);
51162306a36Sopenharmony_ciWPCM450_SFUNC(kbcc);
51262306a36Sopenharmony_ciWPCM450_SFUNC(clko);
51362306a36Sopenharmony_ciWPCM450_SFUNC(smi);
51462306a36Sopenharmony_ciWPCM450_SFUNC(uinc);
51562306a36Sopenharmony_ciWPCM450_SFUNC(gspi);
51662306a36Sopenharmony_ciWPCM450_SFUNC(mben);
51762306a36Sopenharmony_ciWPCM450_SFUNC(xcs2);
51862306a36Sopenharmony_ciWPCM450_SFUNC(xcs1);
51962306a36Sopenharmony_ciWPCM450_SFUNC(sdio);
52062306a36Sopenharmony_ciWPCM450_SFUNC(sspi);
52162306a36Sopenharmony_ciWPCM450_SFUNC(fi0);
52262306a36Sopenharmony_ciWPCM450_SFUNC(fi1);
52362306a36Sopenharmony_ciWPCM450_SFUNC(fi2);
52462306a36Sopenharmony_ciWPCM450_SFUNC(fi3);
52562306a36Sopenharmony_ciWPCM450_SFUNC(fi4);
52662306a36Sopenharmony_ciWPCM450_SFUNC(fi5);
52762306a36Sopenharmony_ciWPCM450_SFUNC(fi6);
52862306a36Sopenharmony_ciWPCM450_SFUNC(fi7);
52962306a36Sopenharmony_ciWPCM450_SFUNC(fi8);
53062306a36Sopenharmony_ciWPCM450_SFUNC(fi9);
53162306a36Sopenharmony_ciWPCM450_SFUNC(fi10);
53262306a36Sopenharmony_ciWPCM450_SFUNC(fi11);
53362306a36Sopenharmony_ciWPCM450_SFUNC(fi12);
53462306a36Sopenharmony_ciWPCM450_SFUNC(fi13);
53562306a36Sopenharmony_ciWPCM450_SFUNC(fi14);
53662306a36Sopenharmony_ciWPCM450_SFUNC(fi15);
53762306a36Sopenharmony_ciWPCM450_SFUNC(pwm0);
53862306a36Sopenharmony_ciWPCM450_SFUNC(pwm1);
53962306a36Sopenharmony_ciWPCM450_SFUNC(pwm2);
54062306a36Sopenharmony_ciWPCM450_SFUNC(pwm3);
54162306a36Sopenharmony_ciWPCM450_SFUNC(pwm4);
54262306a36Sopenharmony_ciWPCM450_SFUNC(pwm5);
54362306a36Sopenharmony_ciWPCM450_SFUNC(pwm6);
54462306a36Sopenharmony_ciWPCM450_SFUNC(pwm7);
54562306a36Sopenharmony_ciWPCM450_SFUNC(hg0);
54662306a36Sopenharmony_ciWPCM450_SFUNC(hg1);
54762306a36Sopenharmony_ciWPCM450_SFUNC(hg2);
54862306a36Sopenharmony_ciWPCM450_SFUNC(hg3);
54962306a36Sopenharmony_ciWPCM450_SFUNC(hg4);
55062306a36Sopenharmony_ciWPCM450_SFUNC(hg5);
55162306a36Sopenharmony_ciWPCM450_SFUNC(hg6);
55262306a36Sopenharmony_ciWPCM450_SFUNC(hg7);
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci#define WPCM450_GRP(x) #x
55562306a36Sopenharmony_ciWPCM450_FUNC(gpio, WPCM450_GRPS);
55662306a36Sopenharmony_ci#undef WPCM450_GRP
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci/* Function names */
55962306a36Sopenharmony_cistatic struct wpcm450_func wpcm450_funcs[] = {
56062306a36Sopenharmony_ci	WPCM450_MKFUNC(smb3),
56162306a36Sopenharmony_ci	WPCM450_MKFUNC(smb4),
56262306a36Sopenharmony_ci	WPCM450_MKFUNC(smb5),
56362306a36Sopenharmony_ci	WPCM450_MKFUNC(scs1),
56462306a36Sopenharmony_ci	WPCM450_MKFUNC(scs2),
56562306a36Sopenharmony_ci	WPCM450_MKFUNC(scs3),
56662306a36Sopenharmony_ci	WPCM450_MKFUNC(smb0),
56762306a36Sopenharmony_ci	WPCM450_MKFUNC(smb1),
56862306a36Sopenharmony_ci	WPCM450_MKFUNC(smb2),
56962306a36Sopenharmony_ci	WPCM450_MKFUNC(bsp),
57062306a36Sopenharmony_ci	WPCM450_MKFUNC(hsp1),
57162306a36Sopenharmony_ci	WPCM450_MKFUNC(hsp2),
57262306a36Sopenharmony_ci	WPCM450_MKFUNC(r1err),
57362306a36Sopenharmony_ci	WPCM450_MKFUNC(r1md),
57462306a36Sopenharmony_ci	WPCM450_MKFUNC(rmii2),
57562306a36Sopenharmony_ci	WPCM450_MKFUNC(r2err),
57662306a36Sopenharmony_ci	WPCM450_MKFUNC(r2md),
57762306a36Sopenharmony_ci	WPCM450_MKFUNC(kbcc),
57862306a36Sopenharmony_ci	WPCM450_MKFUNC(clko),
57962306a36Sopenharmony_ci	WPCM450_MKFUNC(smi),
58062306a36Sopenharmony_ci	WPCM450_MKFUNC(uinc),
58162306a36Sopenharmony_ci	WPCM450_MKFUNC(gspi),
58262306a36Sopenharmony_ci	WPCM450_MKFUNC(mben),
58362306a36Sopenharmony_ci	WPCM450_MKFUNC(xcs2),
58462306a36Sopenharmony_ci	WPCM450_MKFUNC(xcs1),
58562306a36Sopenharmony_ci	WPCM450_MKFUNC(sdio),
58662306a36Sopenharmony_ci	WPCM450_MKFUNC(sspi),
58762306a36Sopenharmony_ci	WPCM450_MKFUNC(fi0),
58862306a36Sopenharmony_ci	WPCM450_MKFUNC(fi1),
58962306a36Sopenharmony_ci	WPCM450_MKFUNC(fi2),
59062306a36Sopenharmony_ci	WPCM450_MKFUNC(fi3),
59162306a36Sopenharmony_ci	WPCM450_MKFUNC(fi4),
59262306a36Sopenharmony_ci	WPCM450_MKFUNC(fi5),
59362306a36Sopenharmony_ci	WPCM450_MKFUNC(fi6),
59462306a36Sopenharmony_ci	WPCM450_MKFUNC(fi7),
59562306a36Sopenharmony_ci	WPCM450_MKFUNC(fi8),
59662306a36Sopenharmony_ci	WPCM450_MKFUNC(fi9),
59762306a36Sopenharmony_ci	WPCM450_MKFUNC(fi10),
59862306a36Sopenharmony_ci	WPCM450_MKFUNC(fi11),
59962306a36Sopenharmony_ci	WPCM450_MKFUNC(fi12),
60062306a36Sopenharmony_ci	WPCM450_MKFUNC(fi13),
60162306a36Sopenharmony_ci	WPCM450_MKFUNC(fi14),
60262306a36Sopenharmony_ci	WPCM450_MKFUNC(fi15),
60362306a36Sopenharmony_ci	WPCM450_MKFUNC(pwm0),
60462306a36Sopenharmony_ci	WPCM450_MKFUNC(pwm1),
60562306a36Sopenharmony_ci	WPCM450_MKFUNC(pwm2),
60662306a36Sopenharmony_ci	WPCM450_MKFUNC(pwm3),
60762306a36Sopenharmony_ci	WPCM450_MKFUNC(pwm4),
60862306a36Sopenharmony_ci	WPCM450_MKFUNC(pwm5),
60962306a36Sopenharmony_ci	WPCM450_MKFUNC(pwm6),
61062306a36Sopenharmony_ci	WPCM450_MKFUNC(pwm7),
61162306a36Sopenharmony_ci	WPCM450_MKFUNC(hg0),
61262306a36Sopenharmony_ci	WPCM450_MKFUNC(hg1),
61362306a36Sopenharmony_ci	WPCM450_MKFUNC(hg2),
61462306a36Sopenharmony_ci	WPCM450_MKFUNC(hg3),
61562306a36Sopenharmony_ci	WPCM450_MKFUNC(hg4),
61662306a36Sopenharmony_ci	WPCM450_MKFUNC(hg5),
61762306a36Sopenharmony_ci	WPCM450_MKFUNC(hg6),
61862306a36Sopenharmony_ci	WPCM450_MKFUNC(hg7),
61962306a36Sopenharmony_ci	WPCM450_MKFUNC(gpio),
62062306a36Sopenharmony_ci};
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci#define WPCM450_PINCFG(a, b, c, d, e, f, g) \
62362306a36Sopenharmony_ci	[a] = { .fn0 = fn_ ## b, .reg0 = WPCM450_GCR_ ## c, .bit0 = d, \
62462306a36Sopenharmony_ci	        .fn1 = fn_ ## e, .reg1 = WPCM450_GCR_ ## f, .bit1 = g }
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_cistruct wpcm450_pincfg {
62762306a36Sopenharmony_ci	int fn0, reg0, bit0;
62862306a36Sopenharmony_ci	int fn1, reg1, bit1;
62962306a36Sopenharmony_ci};
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci/* Add this value to bit0 or bit1 to indicate that the MFSEL bit is inverted */
63262306a36Sopenharmony_ci#define INV	BIT(5)
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_cistatic const struct wpcm450_pincfg pincfg[] = {
63562306a36Sopenharmony_ci	/*		PIN	  FUNCTION 1		   FUNCTION 2 */
63662306a36Sopenharmony_ci	WPCM450_PINCFG(0,	 none, NONE, 0,		  none, NONE, 0),
63762306a36Sopenharmony_ci	WPCM450_PINCFG(1,	 none, NONE, 0,		  none, NONE, 0),
63862306a36Sopenharmony_ci	WPCM450_PINCFG(2,	 none, NONE, 0,		  none, NONE, 0),
63962306a36Sopenharmony_ci	WPCM450_PINCFG(3,	 none, NONE, 0,		  none, NONE, 0),
64062306a36Sopenharmony_ci	WPCM450_PINCFG(4,	 none, NONE, 0,		  none, NONE, 0),
64162306a36Sopenharmony_ci	WPCM450_PINCFG(5,	 none, NONE, 0,		  none, NONE, 0),
64262306a36Sopenharmony_ci	WPCM450_PINCFG(6,	 none, NONE, 0,		  none, NONE, 0),
64362306a36Sopenharmony_ci	WPCM450_PINCFG(7,	 none, NONE, 0,		  sdio, MFSEL1, 30),
64462306a36Sopenharmony_ci	WPCM450_PINCFG(8,	 none, NONE, 0,		  none, NONE, 0),
64562306a36Sopenharmony_ci	WPCM450_PINCFG(9,	 none, NONE, 0,		  none, NONE, 0),
64662306a36Sopenharmony_ci	WPCM450_PINCFG(10,	 none, NONE, 0,		  none, NONE, 0),
64762306a36Sopenharmony_ci	WPCM450_PINCFG(11,	 none, NONE, 0,		  none, NONE, 0),
64862306a36Sopenharmony_ci	WPCM450_PINCFG(12,	 gspi, MFSEL1, 24,	  sspi, MFSEL1, 31),
64962306a36Sopenharmony_ci	WPCM450_PINCFG(13,	 gspi, MFSEL1, 24,	  sspi, MFSEL1, 31),
65062306a36Sopenharmony_ci	WPCM450_PINCFG(14,	 gspi, MFSEL1, 24,	  sspi, MFSEL1, 31),
65162306a36Sopenharmony_ci	WPCM450_PINCFG(15,	 gspi, MFSEL1, 24,	  sspi, MFSEL1, 31),
65262306a36Sopenharmony_ci	WPCM450_PINCFG(16,	 none, NONE, 0,		  pwm6, MFSEL2, 22),
65362306a36Sopenharmony_ci	WPCM450_PINCFG(17,	 none, NONE, 0,		  pwm7, MFSEL2, 23),
65462306a36Sopenharmony_ci	WPCM450_PINCFG(18,	 none, NONE, 0,		  none, NONE, 0),
65562306a36Sopenharmony_ci	WPCM450_PINCFG(19,	 uinc, MFSEL1, 23,	  none, NONE, 0),
65662306a36Sopenharmony_ci	WPCM450_PINCFG(20,	  hg0, MFSEL2, 24,	  pwm4, MFSEL2, 20),
65762306a36Sopenharmony_ci	WPCM450_PINCFG(21,	  hg1, MFSEL2, 25,	  pwm5, MFSEL2, 21),
65862306a36Sopenharmony_ci	WPCM450_PINCFG(22,	  hg2, MFSEL2, 26,	  none, NONE, 0),
65962306a36Sopenharmony_ci	WPCM450_PINCFG(23,	  hg3, MFSEL2, 27,	  none, NONE, 0),
66062306a36Sopenharmony_ci	WPCM450_PINCFG(24,	  hg4, MFSEL2, 28,	  none, NONE, 0),
66162306a36Sopenharmony_ci	WPCM450_PINCFG(25,	  hg5, MFSEL2, 29,	  none, NONE, 0),
66262306a36Sopenharmony_ci	WPCM450_PINCFG(26,	 smb5, MFSEL1, 2,	  none, NONE, 0),
66362306a36Sopenharmony_ci	WPCM450_PINCFG(27,	 smb5, MFSEL1, 2,	  none, NONE, 0),
66462306a36Sopenharmony_ci	WPCM450_PINCFG(28,	 smb4, MFSEL1, 1,	  none, NONE, 0),
66562306a36Sopenharmony_ci	WPCM450_PINCFG(29,	 smb4, MFSEL1, 1,	  none, NONE, 0),
66662306a36Sopenharmony_ci	WPCM450_PINCFG(30,	 smb3, MFSEL1, 0,	  none, NONE, 0),
66762306a36Sopenharmony_ci	WPCM450_PINCFG(31,	 smb3, MFSEL1, 0,	  none, NONE, 0),
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	WPCM450_PINCFG(32,	 scs1, MFSEL1, 3,	  none, NONE, 0),
67062306a36Sopenharmony_ci	WPCM450_PINCFG(33,	 scs2, MFSEL1, 4,	  none, NONE, 0),
67162306a36Sopenharmony_ci	WPCM450_PINCFG(34,	 scs3, MFSEL1, 5 | INV,	  none, NONE, 0),
67262306a36Sopenharmony_ci	WPCM450_PINCFG(35,	 xcs1, MFSEL1, 29,	  none, NONE, 0),
67362306a36Sopenharmony_ci	WPCM450_PINCFG(36,	 xcs2, MFSEL1, 28,	  none, NONE, 0),
67462306a36Sopenharmony_ci	WPCM450_PINCFG(37,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
67562306a36Sopenharmony_ci	WPCM450_PINCFG(38,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
67662306a36Sopenharmony_ci	WPCM450_PINCFG(39,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
67762306a36Sopenharmony_ci	WPCM450_PINCFG(40,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
67862306a36Sopenharmony_ci	WPCM450_PINCFG(41,	  bsp, MFSEL1, 9,	  none, NONE, 0),
67962306a36Sopenharmony_ci	WPCM450_PINCFG(42,	  bsp, MFSEL1, 9,	  none, NONE, 0),
68062306a36Sopenharmony_ci	WPCM450_PINCFG(43,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
68162306a36Sopenharmony_ci	WPCM450_PINCFG(44,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
68262306a36Sopenharmony_ci	WPCM450_PINCFG(45,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
68362306a36Sopenharmony_ci	WPCM450_PINCFG(46,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
68462306a36Sopenharmony_ci	WPCM450_PINCFG(47,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
68562306a36Sopenharmony_ci	WPCM450_PINCFG(48,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
68662306a36Sopenharmony_ci	WPCM450_PINCFG(49,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
68762306a36Sopenharmony_ci	WPCM450_PINCFG(50,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
68862306a36Sopenharmony_ci	WPCM450_PINCFG(51,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
68962306a36Sopenharmony_ci	WPCM450_PINCFG(52,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
69062306a36Sopenharmony_ci	WPCM450_PINCFG(53,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
69162306a36Sopenharmony_ci	WPCM450_PINCFG(54,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
69262306a36Sopenharmony_ci	WPCM450_PINCFG(55,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
69362306a36Sopenharmony_ci	WPCM450_PINCFG(56,	r1err, MFSEL1, 12,	  none, NONE, 0),
69462306a36Sopenharmony_ci	WPCM450_PINCFG(57,	 r1md, MFSEL1, 13,	  none, NONE, 0),
69562306a36Sopenharmony_ci	WPCM450_PINCFG(58,	 r1md, MFSEL1, 13,	  none, NONE, 0),
69662306a36Sopenharmony_ci	WPCM450_PINCFG(59,	  hg6, MFSEL2, 30,	  none, NONE, 0),
69762306a36Sopenharmony_ci	WPCM450_PINCFG(60,	  hg7, MFSEL2, 31,	  sdio, MFSEL1, 30),
69862306a36Sopenharmony_ci	WPCM450_PINCFG(61,	 hsp1, MFSEL1, 10,	  none, NONE, 0),
69962306a36Sopenharmony_ci	WPCM450_PINCFG(62,	 hsp1, MFSEL1, 10,	  none, NONE, 0),
70062306a36Sopenharmony_ci	WPCM450_PINCFG(63,	 hsp1, MFSEL1, 10,	  none, NONE, 0),
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci	WPCM450_PINCFG(64,	  fi0, MFSEL2, 0,	  none, NONE, 0),
70362306a36Sopenharmony_ci	WPCM450_PINCFG(65,	  fi1, MFSEL2, 1,	  none, NONE, 0),
70462306a36Sopenharmony_ci	WPCM450_PINCFG(66,	  fi2, MFSEL2, 2,	  none, NONE, 0),
70562306a36Sopenharmony_ci	WPCM450_PINCFG(67,	  fi3, MFSEL2, 3,	  none, NONE, 0),
70662306a36Sopenharmony_ci	WPCM450_PINCFG(68,	  fi4, MFSEL2, 4,	  none, NONE, 0),
70762306a36Sopenharmony_ci	WPCM450_PINCFG(69,	  fi5, MFSEL2, 5,	  none, NONE, 0),
70862306a36Sopenharmony_ci	WPCM450_PINCFG(70,	  fi6, MFSEL2, 6,	  none, NONE, 0),
70962306a36Sopenharmony_ci	WPCM450_PINCFG(71,	  fi7, MFSEL2, 7,	  none, NONE, 0),
71062306a36Sopenharmony_ci	WPCM450_PINCFG(72,	  fi8, MFSEL2, 8,	  none, NONE, 0),
71162306a36Sopenharmony_ci	WPCM450_PINCFG(73,	  fi9, MFSEL2, 9,	  none, NONE, 0),
71262306a36Sopenharmony_ci	WPCM450_PINCFG(74,	 fi10, MFSEL2, 10,	  none, NONE, 0),
71362306a36Sopenharmony_ci	WPCM450_PINCFG(75,	 fi11, MFSEL2, 11,	  none, NONE, 0),
71462306a36Sopenharmony_ci	WPCM450_PINCFG(76,	 fi12, MFSEL2, 12,	  none, NONE, 0),
71562306a36Sopenharmony_ci	WPCM450_PINCFG(77,	 fi13, MFSEL2, 13,	  none, NONE, 0),
71662306a36Sopenharmony_ci	WPCM450_PINCFG(78,	 fi14, MFSEL2, 14,	  none, NONE, 0),
71762306a36Sopenharmony_ci	WPCM450_PINCFG(79,	 fi15, MFSEL2, 15,	  none, NONE, 0),
71862306a36Sopenharmony_ci	WPCM450_PINCFG(80,	 pwm0, MFSEL2, 16,	  none, NONE, 0),
71962306a36Sopenharmony_ci	WPCM450_PINCFG(81,	 pwm1, MFSEL2, 17,	  none, NONE, 0),
72062306a36Sopenharmony_ci	WPCM450_PINCFG(82,	 pwm2, MFSEL2, 18,	  none, NONE, 0),
72162306a36Sopenharmony_ci	WPCM450_PINCFG(83,	 pwm3, MFSEL2, 19,	  none, NONE, 0),
72262306a36Sopenharmony_ci	WPCM450_PINCFG(84,	rmii2, MFSEL1, 14,	  none, NONE, 0),
72362306a36Sopenharmony_ci	WPCM450_PINCFG(85,	rmii2, MFSEL1, 14,	  none, NONE, 0),
72462306a36Sopenharmony_ci	WPCM450_PINCFG(86,	rmii2, MFSEL1, 14,	  none, NONE, 0),
72562306a36Sopenharmony_ci	WPCM450_PINCFG(87,	rmii2, MFSEL1, 14,	  none, NONE, 0),
72662306a36Sopenharmony_ci	WPCM450_PINCFG(88,	rmii2, MFSEL1, 14,	  none, NONE, 0),
72762306a36Sopenharmony_ci	WPCM450_PINCFG(89,	rmii2, MFSEL1, 14,	  none, NONE, 0),
72862306a36Sopenharmony_ci	WPCM450_PINCFG(90,	r2err, MFSEL1, 15,	  none, NONE, 0),
72962306a36Sopenharmony_ci	WPCM450_PINCFG(91,	 r2md, MFSEL1, 16,	  none, NONE, 0),
73062306a36Sopenharmony_ci	WPCM450_PINCFG(92,	 r2md, MFSEL1, 16,	  none, NONE, 0),
73162306a36Sopenharmony_ci	WPCM450_PINCFG(93,	 kbcc, MFSEL1, 17 | INV,  none, NONE, 0),
73262306a36Sopenharmony_ci	WPCM450_PINCFG(94,	 kbcc, MFSEL1, 17 | INV,  none, NONE, 0),
73362306a36Sopenharmony_ci	WPCM450_PINCFG(95,	 none, NONE, 0,		  none, NONE, 0),
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci	WPCM450_PINCFG(96,	 none, NONE, 0,		  none, NONE, 0),
73662306a36Sopenharmony_ci	WPCM450_PINCFG(97,	 none, NONE, 0,		  none, NONE, 0),
73762306a36Sopenharmony_ci	WPCM450_PINCFG(98,	 none, NONE, 0,		  none, NONE, 0),
73862306a36Sopenharmony_ci	WPCM450_PINCFG(99,	 none, NONE, 0,		  none, NONE, 0),
73962306a36Sopenharmony_ci	WPCM450_PINCFG(100,	 none, NONE, 0,		  none, NONE, 0),
74062306a36Sopenharmony_ci	WPCM450_PINCFG(101,	 none, NONE, 0,		  none, NONE, 0),
74162306a36Sopenharmony_ci	WPCM450_PINCFG(102,	 none, NONE, 0,		  none, NONE, 0),
74262306a36Sopenharmony_ci	WPCM450_PINCFG(103,	 none, NONE, 0,		  none, NONE, 0),
74362306a36Sopenharmony_ci	WPCM450_PINCFG(104,	 none, NONE, 0,		  none, NONE, 0),
74462306a36Sopenharmony_ci	WPCM450_PINCFG(105,	 none, NONE, 0,		  none, NONE, 0),
74562306a36Sopenharmony_ci	WPCM450_PINCFG(106,	 none, NONE, 0,		  none, NONE, 0),
74662306a36Sopenharmony_ci	WPCM450_PINCFG(107,	 none, NONE, 0,		  none, NONE, 0),
74762306a36Sopenharmony_ci	WPCM450_PINCFG(108,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
74862306a36Sopenharmony_ci	WPCM450_PINCFG(109,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
74962306a36Sopenharmony_ci	WPCM450_PINCFG(110,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
75062306a36Sopenharmony_ci	WPCM450_PINCFG(111,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
75162306a36Sopenharmony_ci	WPCM450_PINCFG(112,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
75262306a36Sopenharmony_ci	WPCM450_PINCFG(113,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
75362306a36Sopenharmony_ci	WPCM450_PINCFG(114,	 smb0, MFSEL1, 6,	  none, NONE, 0),
75462306a36Sopenharmony_ci	WPCM450_PINCFG(115,	 smb0, MFSEL1, 6,	  none, NONE, 0),
75562306a36Sopenharmony_ci	WPCM450_PINCFG(116,	 smb1, MFSEL1, 7,	  none, NONE, 0),
75662306a36Sopenharmony_ci	WPCM450_PINCFG(117,	 smb1, MFSEL1, 7,	  none, NONE, 0),
75762306a36Sopenharmony_ci	WPCM450_PINCFG(118,	 smb2, MFSEL1, 8,	  none, NONE, 0),
75862306a36Sopenharmony_ci	WPCM450_PINCFG(119,	 smb2, MFSEL1, 8,	  none, NONE, 0),
75962306a36Sopenharmony_ci	WPCM450_PINCFG(120,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
76062306a36Sopenharmony_ci	WPCM450_PINCFG(121,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
76162306a36Sopenharmony_ci	WPCM450_PINCFG(122,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
76262306a36Sopenharmony_ci	WPCM450_PINCFG(123,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
76362306a36Sopenharmony_ci	WPCM450_PINCFG(124,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
76462306a36Sopenharmony_ci	WPCM450_PINCFG(125,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
76562306a36Sopenharmony_ci	WPCM450_PINCFG(126,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
76662306a36Sopenharmony_ci	WPCM450_PINCFG(127,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
76762306a36Sopenharmony_ci};
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_ci#define WPCM450_PIN(n)		PINCTRL_PIN(n, "gpio" #n)
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_cistatic const struct pinctrl_pin_desc wpcm450_pins[] = {
77262306a36Sopenharmony_ci	WPCM450_PIN(0),   WPCM450_PIN(1),   WPCM450_PIN(2),   WPCM450_PIN(3),
77362306a36Sopenharmony_ci	WPCM450_PIN(4),   WPCM450_PIN(5),   WPCM450_PIN(6),   WPCM450_PIN(7),
77462306a36Sopenharmony_ci	WPCM450_PIN(8),   WPCM450_PIN(9),   WPCM450_PIN(10),  WPCM450_PIN(11),
77562306a36Sopenharmony_ci	WPCM450_PIN(12),  WPCM450_PIN(13),  WPCM450_PIN(14),  WPCM450_PIN(15),
77662306a36Sopenharmony_ci	WPCM450_PIN(16),  WPCM450_PIN(17),  WPCM450_PIN(18),  WPCM450_PIN(19),
77762306a36Sopenharmony_ci	WPCM450_PIN(20),  WPCM450_PIN(21),  WPCM450_PIN(22),  WPCM450_PIN(23),
77862306a36Sopenharmony_ci	WPCM450_PIN(24),  WPCM450_PIN(25),  WPCM450_PIN(26),  WPCM450_PIN(27),
77962306a36Sopenharmony_ci	WPCM450_PIN(28),  WPCM450_PIN(29),  WPCM450_PIN(30),  WPCM450_PIN(31),
78062306a36Sopenharmony_ci	WPCM450_PIN(32),  WPCM450_PIN(33),  WPCM450_PIN(34),  WPCM450_PIN(35),
78162306a36Sopenharmony_ci	WPCM450_PIN(36),  WPCM450_PIN(37),  WPCM450_PIN(38),  WPCM450_PIN(39),
78262306a36Sopenharmony_ci	WPCM450_PIN(40),  WPCM450_PIN(41),  WPCM450_PIN(42),  WPCM450_PIN(43),
78362306a36Sopenharmony_ci	WPCM450_PIN(44),  WPCM450_PIN(45),  WPCM450_PIN(46),  WPCM450_PIN(47),
78462306a36Sopenharmony_ci	WPCM450_PIN(48),  WPCM450_PIN(49),  WPCM450_PIN(50),  WPCM450_PIN(51),
78562306a36Sopenharmony_ci	WPCM450_PIN(52),  WPCM450_PIN(53),  WPCM450_PIN(54),  WPCM450_PIN(55),
78662306a36Sopenharmony_ci	WPCM450_PIN(56),  WPCM450_PIN(57),  WPCM450_PIN(58),  WPCM450_PIN(59),
78762306a36Sopenharmony_ci	WPCM450_PIN(60),  WPCM450_PIN(61),  WPCM450_PIN(62),  WPCM450_PIN(63),
78862306a36Sopenharmony_ci	WPCM450_PIN(64),  WPCM450_PIN(65),  WPCM450_PIN(66),  WPCM450_PIN(67),
78962306a36Sopenharmony_ci	WPCM450_PIN(68),  WPCM450_PIN(69),  WPCM450_PIN(70),  WPCM450_PIN(71),
79062306a36Sopenharmony_ci	WPCM450_PIN(72),  WPCM450_PIN(73),  WPCM450_PIN(74),  WPCM450_PIN(75),
79162306a36Sopenharmony_ci	WPCM450_PIN(76),  WPCM450_PIN(77),  WPCM450_PIN(78),  WPCM450_PIN(79),
79262306a36Sopenharmony_ci	WPCM450_PIN(80),  WPCM450_PIN(81),  WPCM450_PIN(82),  WPCM450_PIN(83),
79362306a36Sopenharmony_ci	WPCM450_PIN(84),  WPCM450_PIN(85),  WPCM450_PIN(86),  WPCM450_PIN(87),
79462306a36Sopenharmony_ci	WPCM450_PIN(88),  WPCM450_PIN(89),  WPCM450_PIN(90),  WPCM450_PIN(91),
79562306a36Sopenharmony_ci	WPCM450_PIN(92),  WPCM450_PIN(93),  WPCM450_PIN(94),  WPCM450_PIN(95),
79662306a36Sopenharmony_ci	WPCM450_PIN(96),  WPCM450_PIN(97),  WPCM450_PIN(98),  WPCM450_PIN(99),
79762306a36Sopenharmony_ci	WPCM450_PIN(100), WPCM450_PIN(101), WPCM450_PIN(102), WPCM450_PIN(103),
79862306a36Sopenharmony_ci	WPCM450_PIN(104), WPCM450_PIN(105), WPCM450_PIN(106), WPCM450_PIN(107),
79962306a36Sopenharmony_ci	WPCM450_PIN(108), WPCM450_PIN(109), WPCM450_PIN(110), WPCM450_PIN(111),
80062306a36Sopenharmony_ci	WPCM450_PIN(112), WPCM450_PIN(113), WPCM450_PIN(114), WPCM450_PIN(115),
80162306a36Sopenharmony_ci	WPCM450_PIN(116), WPCM450_PIN(117), WPCM450_PIN(118), WPCM450_PIN(119),
80262306a36Sopenharmony_ci	WPCM450_PIN(120), WPCM450_PIN(121), WPCM450_PIN(122), WPCM450_PIN(123),
80362306a36Sopenharmony_ci	WPCM450_PIN(124), WPCM450_PIN(125), WPCM450_PIN(126), WPCM450_PIN(127),
80462306a36Sopenharmony_ci};
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci/* Helper function to update MFSEL field according to the selected function */
80762306a36Sopenharmony_cistatic void wpcm450_update_mfsel(struct regmap *gcr_regmap, int reg, int bit, int fn, int fn_selected)
80862306a36Sopenharmony_ci{
80962306a36Sopenharmony_ci	bool value = (fn == fn_selected);
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci	if (bit & INV) {
81262306a36Sopenharmony_ci		value = !value;
81362306a36Sopenharmony_ci		bit &= ~INV;
81462306a36Sopenharmony_ci	}
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci	regmap_update_bits(gcr_regmap, reg, BIT(bit), value ? BIT(bit) : 0);
81762306a36Sopenharmony_ci}
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ci/* Enable mode in pin group */
82062306a36Sopenharmony_cistatic void wpcm450_setfunc(struct regmap *gcr_regmap, const unsigned int *pin,
82162306a36Sopenharmony_ci			    int npins, int func)
82262306a36Sopenharmony_ci{
82362306a36Sopenharmony_ci	const struct wpcm450_pincfg *cfg;
82462306a36Sopenharmony_ci	int i;
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	for (i = 0; i < npins; i++) {
82762306a36Sopenharmony_ci		cfg = &pincfg[pin[i]];
82862306a36Sopenharmony_ci		if (func == fn_gpio || cfg->fn0 == func || cfg->fn1 == func) {
82962306a36Sopenharmony_ci			if (cfg->reg0)
83062306a36Sopenharmony_ci				wpcm450_update_mfsel(gcr_regmap, cfg->reg0,
83162306a36Sopenharmony_ci						     cfg->bit0, cfg->fn0, func);
83262306a36Sopenharmony_ci			if (cfg->reg1)
83362306a36Sopenharmony_ci				wpcm450_update_mfsel(gcr_regmap, cfg->reg1,
83462306a36Sopenharmony_ci						     cfg->bit1, cfg->fn1, func);
83562306a36Sopenharmony_ci		}
83662306a36Sopenharmony_ci	}
83762306a36Sopenharmony_ci}
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_cistatic int wpcm450_get_groups_count(struct pinctrl_dev *pctldev)
84062306a36Sopenharmony_ci{
84162306a36Sopenharmony_ci	return ARRAY_SIZE(wpcm450_groups);
84262306a36Sopenharmony_ci}
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_cistatic const char *wpcm450_get_group_name(struct pinctrl_dev *pctldev,
84562306a36Sopenharmony_ci					  unsigned int selector)
84662306a36Sopenharmony_ci{
84762306a36Sopenharmony_ci	return wpcm450_groups[selector].name;
84862306a36Sopenharmony_ci}
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_cistatic int wpcm450_get_group_pins(struct pinctrl_dev *pctldev,
85162306a36Sopenharmony_ci				  unsigned int selector,
85262306a36Sopenharmony_ci				  const unsigned int **pins,
85362306a36Sopenharmony_ci				  unsigned int *npins)
85462306a36Sopenharmony_ci{
85562306a36Sopenharmony_ci	*npins = wpcm450_groups[selector].num_pins;
85662306a36Sopenharmony_ci	*pins  = wpcm450_groups[selector].pins;
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	return 0;
85962306a36Sopenharmony_ci}
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_cistatic int wpcm450_dt_node_to_map(struct pinctrl_dev *pctldev,
86262306a36Sopenharmony_ci				  struct device_node *np_config,
86362306a36Sopenharmony_ci				  struct pinctrl_map **map,
86462306a36Sopenharmony_ci				  u32 *num_maps)
86562306a36Sopenharmony_ci{
86662306a36Sopenharmony_ci	return pinconf_generic_dt_node_to_map(pctldev, np_config,
86762306a36Sopenharmony_ci					      map, num_maps,
86862306a36Sopenharmony_ci					      PIN_MAP_TYPE_INVALID);
86962306a36Sopenharmony_ci}
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_cistatic void wpcm450_dt_free_map(struct pinctrl_dev *pctldev,
87262306a36Sopenharmony_ci				struct pinctrl_map *map, u32 num_maps)
87362306a36Sopenharmony_ci{
87462306a36Sopenharmony_ci	kfree(map);
87562306a36Sopenharmony_ci}
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_cistatic const struct pinctrl_ops wpcm450_pinctrl_ops = {
87862306a36Sopenharmony_ci	.get_groups_count = wpcm450_get_groups_count,
87962306a36Sopenharmony_ci	.get_group_name = wpcm450_get_group_name,
88062306a36Sopenharmony_ci	.get_group_pins = wpcm450_get_group_pins,
88162306a36Sopenharmony_ci	.dt_node_to_map = wpcm450_dt_node_to_map,
88262306a36Sopenharmony_ci	.dt_free_map = wpcm450_dt_free_map,
88362306a36Sopenharmony_ci};
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_cistatic int wpcm450_get_functions_count(struct pinctrl_dev *pctldev)
88662306a36Sopenharmony_ci{
88762306a36Sopenharmony_ci	return ARRAY_SIZE(wpcm450_funcs);
88862306a36Sopenharmony_ci}
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_cistatic const char *wpcm450_get_function_name(struct pinctrl_dev *pctldev,
89162306a36Sopenharmony_ci					     unsigned int function)
89262306a36Sopenharmony_ci{
89362306a36Sopenharmony_ci	return wpcm450_funcs[function].name;
89462306a36Sopenharmony_ci}
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_cistatic int wpcm450_get_function_groups(struct pinctrl_dev *pctldev,
89762306a36Sopenharmony_ci				       unsigned int function,
89862306a36Sopenharmony_ci				       const char * const **groups,
89962306a36Sopenharmony_ci				       unsigned int * const ngroups)
90062306a36Sopenharmony_ci{
90162306a36Sopenharmony_ci	*ngroups = wpcm450_funcs[function].ngroups;
90262306a36Sopenharmony_ci	*groups	 = wpcm450_funcs[function].groups;
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci	return 0;
90562306a36Sopenharmony_ci}
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_cistatic int wpcm450_pinmux_set_mux(struct pinctrl_dev *pctldev,
90862306a36Sopenharmony_ci				  unsigned int function,
90962306a36Sopenharmony_ci				  unsigned int group)
91062306a36Sopenharmony_ci{
91162306a36Sopenharmony_ci	struct wpcm450_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci	wpcm450_setfunc(pctrl->gcr_regmap, wpcm450_groups[group].pins,
91462306a36Sopenharmony_ci			wpcm450_groups[group].num_pins, function);
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci	return 0;
91762306a36Sopenharmony_ci}
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_cistatic const struct pinmux_ops wpcm450_pinmux_ops = {
92062306a36Sopenharmony_ci	.get_functions_count = wpcm450_get_functions_count,
92162306a36Sopenharmony_ci	.get_function_name = wpcm450_get_function_name,
92262306a36Sopenharmony_ci	.get_function_groups = wpcm450_get_function_groups,
92362306a36Sopenharmony_ci	.set_mux = wpcm450_pinmux_set_mux,
92462306a36Sopenharmony_ci};
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_cistatic int debounce_bitnum(int gpio)
92762306a36Sopenharmony_ci{
92862306a36Sopenharmony_ci	if (gpio >= 0 && gpio < 16)
92962306a36Sopenharmony_ci		return gpio;
93062306a36Sopenharmony_ci	return -EINVAL;
93162306a36Sopenharmony_ci}
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_cistatic int wpcm450_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
93462306a36Sopenharmony_ci			      unsigned long *config)
93562306a36Sopenharmony_ci{
93662306a36Sopenharmony_ci	struct wpcm450_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
93762306a36Sopenharmony_ci	enum pin_config_param param = pinconf_to_config_param(*config);
93862306a36Sopenharmony_ci	unsigned long flags;
93962306a36Sopenharmony_ci	int bit;
94062306a36Sopenharmony_ci	u32 reg;
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	switch (param) {
94362306a36Sopenharmony_ci	case PIN_CONFIG_INPUT_DEBOUNCE:
94462306a36Sopenharmony_ci		bit = debounce_bitnum(pin);
94562306a36Sopenharmony_ci		if (bit < 0)
94662306a36Sopenharmony_ci			return bit;
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_ci		raw_spin_lock_irqsave(&pctrl->lock, flags);
94962306a36Sopenharmony_ci		reg = ioread32(pctrl->gpio_base + WPCM450_GPEVDBNC);
95062306a36Sopenharmony_ci		raw_spin_unlock_irqrestore(&pctrl->lock, flags);
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci		*config = pinconf_to_config_packed(param, !!(reg & BIT(bit)));
95362306a36Sopenharmony_ci		return 0;
95462306a36Sopenharmony_ci	default:
95562306a36Sopenharmony_ci		return -ENOTSUPP;
95662306a36Sopenharmony_ci	}
95762306a36Sopenharmony_ci}
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_cistatic int wpcm450_config_set_one(struct wpcm450_pinctrl *pctrl,
96062306a36Sopenharmony_ci				  unsigned int pin, unsigned long config)
96162306a36Sopenharmony_ci{
96262306a36Sopenharmony_ci	enum pin_config_param param = pinconf_to_config_param(config);
96362306a36Sopenharmony_ci	unsigned long flags;
96462306a36Sopenharmony_ci	unsigned long reg;
96562306a36Sopenharmony_ci	int bit;
96662306a36Sopenharmony_ci	int arg;
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci	switch (param) {
96962306a36Sopenharmony_ci	case PIN_CONFIG_INPUT_DEBOUNCE:
97062306a36Sopenharmony_ci		bit = debounce_bitnum(pin);
97162306a36Sopenharmony_ci		if (bit < 0)
97262306a36Sopenharmony_ci			return bit;
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_ci		arg = pinconf_to_config_argument(config);
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci		raw_spin_lock_irqsave(&pctrl->lock, flags);
97762306a36Sopenharmony_ci		reg = ioread32(pctrl->gpio_base + WPCM450_GPEVDBNC);
97862306a36Sopenharmony_ci		__assign_bit(bit, &reg, arg);
97962306a36Sopenharmony_ci		iowrite32(reg, pctrl->gpio_base + WPCM450_GPEVDBNC);
98062306a36Sopenharmony_ci		raw_spin_unlock_irqrestore(&pctrl->lock, flags);
98162306a36Sopenharmony_ci		return 0;
98262306a36Sopenharmony_ci	default:
98362306a36Sopenharmony_ci		return -ENOTSUPP;
98462306a36Sopenharmony_ci	}
98562306a36Sopenharmony_ci}
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_cistatic int wpcm450_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
98862306a36Sopenharmony_ci			      unsigned long *configs, unsigned int num_configs)
98962306a36Sopenharmony_ci{
99062306a36Sopenharmony_ci	struct wpcm450_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
99162306a36Sopenharmony_ci	int ret;
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_ci	while (num_configs--) {
99462306a36Sopenharmony_ci		ret = wpcm450_config_set_one(pctrl, pin, *configs++);
99562306a36Sopenharmony_ci		if (ret)
99662306a36Sopenharmony_ci			return ret;
99762306a36Sopenharmony_ci	}
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_ci	return 0;
100062306a36Sopenharmony_ci}
100162306a36Sopenharmony_ci
100262306a36Sopenharmony_cistatic const struct pinconf_ops wpcm450_pinconf_ops = {
100362306a36Sopenharmony_ci	.is_generic = true,
100462306a36Sopenharmony_ci	.pin_config_get = wpcm450_config_get,
100562306a36Sopenharmony_ci	.pin_config_set = wpcm450_config_set,
100662306a36Sopenharmony_ci};
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_cistatic struct pinctrl_desc wpcm450_pinctrl_desc = {
100962306a36Sopenharmony_ci	.name = "wpcm450-pinctrl",
101062306a36Sopenharmony_ci	.pins = wpcm450_pins,
101162306a36Sopenharmony_ci	.npins = ARRAY_SIZE(wpcm450_pins),
101262306a36Sopenharmony_ci	.pctlops = &wpcm450_pinctrl_ops,
101362306a36Sopenharmony_ci	.pmxops = &wpcm450_pinmux_ops,
101462306a36Sopenharmony_ci	.confops = &wpcm450_pinconf_ops,
101562306a36Sopenharmony_ci	.owner = THIS_MODULE,
101662306a36Sopenharmony_ci};
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_cistatic int wpcm450_gpio_set_config(struct gpio_chip *chip,
101962306a36Sopenharmony_ci				   unsigned int offset, unsigned long config)
102062306a36Sopenharmony_ci{
102162306a36Sopenharmony_ci	struct wpcm450_gpio *gpio = gpiochip_get_data(chip);
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_ci	return wpcm450_config_set_one(gpio->pctrl, offset, config);
102462306a36Sopenharmony_ci}
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_cistatic int wpcm450_gpio_add_pin_ranges(struct gpio_chip *chip)
102762306a36Sopenharmony_ci{
102862306a36Sopenharmony_ci	struct wpcm450_gpio *gpio = gpiochip_get_data(chip);
102962306a36Sopenharmony_ci	const struct wpcm450_bank *bank = gpio->bank;
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_ci	return gpiochip_add_pin_range(&gpio->gc, dev_name(gpio->pctrl->dev),
103262306a36Sopenharmony_ci				      0, bank->base, bank->length);
103362306a36Sopenharmony_ci}
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_cistatic int wpcm450_gpio_register(struct platform_device *pdev,
103662306a36Sopenharmony_ci				 struct wpcm450_pinctrl *pctrl)
103762306a36Sopenharmony_ci{
103862306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
103962306a36Sopenharmony_ci	struct fwnode_handle *child;
104062306a36Sopenharmony_ci	int ret;
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci	pctrl->gpio_base = devm_platform_ioremap_resource(pdev, 0);
104362306a36Sopenharmony_ci	if (IS_ERR(pctrl->gpio_base))
104462306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(pctrl->gpio_base),
104562306a36Sopenharmony_ci				     "Resource fail for GPIO controller\n");
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	device_for_each_child_node(dev, child)  {
104862306a36Sopenharmony_ci		void __iomem *dat = NULL;
104962306a36Sopenharmony_ci		void __iomem *set = NULL;
105062306a36Sopenharmony_ci		void __iomem *dirout = NULL;
105162306a36Sopenharmony_ci		unsigned long flags = 0;
105262306a36Sopenharmony_ci		const struct wpcm450_bank *bank;
105362306a36Sopenharmony_ci		struct wpcm450_gpio *gpio;
105462306a36Sopenharmony_ci		struct gpio_irq_chip *girq;
105562306a36Sopenharmony_ci		u32 reg;
105662306a36Sopenharmony_ci		int i;
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci		if (!fwnode_property_read_bool(child, "gpio-controller"))
105962306a36Sopenharmony_ci			continue;
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci		ret = fwnode_property_read_u32(child, "reg", &reg);
106262306a36Sopenharmony_ci		if (ret < 0)
106362306a36Sopenharmony_ci			return ret;
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci		if (reg >= WPCM450_NUM_BANKS)
106662306a36Sopenharmony_ci			return dev_err_probe(dev, -EINVAL,
106762306a36Sopenharmony_ci					     "GPIO index %d out of range!\n", reg);
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci		gpio = &pctrl->gpio_bank[reg];
107062306a36Sopenharmony_ci		gpio->pctrl = pctrl;
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_ci		bank = &wpcm450_banks[reg];
107362306a36Sopenharmony_ci		gpio->bank = bank;
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci		dat = pctrl->gpio_base + bank->datain;
107662306a36Sopenharmony_ci		if (bank->dataout) {
107762306a36Sopenharmony_ci			set = pctrl->gpio_base + bank->dataout;
107862306a36Sopenharmony_ci			dirout = pctrl->gpio_base + bank->cfg0;
107962306a36Sopenharmony_ci		} else {
108062306a36Sopenharmony_ci			flags = BGPIOF_NO_OUTPUT;
108162306a36Sopenharmony_ci		}
108262306a36Sopenharmony_ci		ret = bgpio_init(&gpio->gc, dev, 4,
108362306a36Sopenharmony_ci				 dat, set, NULL, dirout, NULL, flags);
108462306a36Sopenharmony_ci		if (ret < 0)
108562306a36Sopenharmony_ci			return dev_err_probe(dev, ret, "GPIO initialization failed\n");
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_ci		gpio->gc.ngpio = bank->length;
108862306a36Sopenharmony_ci		gpio->gc.set_config = wpcm450_gpio_set_config;
108962306a36Sopenharmony_ci		gpio->gc.fwnode = child;
109062306a36Sopenharmony_ci		gpio->gc.add_pin_ranges = wpcm450_gpio_add_pin_ranges;
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci		girq = &gpio->gc.irq;
109362306a36Sopenharmony_ci		gpio_irq_chip_set_chip(girq, &wpcm450_gpio_irqchip);
109462306a36Sopenharmony_ci		girq->parent_handler = wpcm450_gpio_irqhandler;
109562306a36Sopenharmony_ci		girq->parents = devm_kcalloc(dev, WPCM450_NUM_GPIO_IRQS,
109662306a36Sopenharmony_ci					     sizeof(*girq->parents), GFP_KERNEL);
109762306a36Sopenharmony_ci		if (!girq->parents)
109862306a36Sopenharmony_ci			return -ENOMEM;
109962306a36Sopenharmony_ci		girq->default_type = IRQ_TYPE_NONE;
110062306a36Sopenharmony_ci		girq->handler = handle_bad_irq;
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci		girq->num_parents = 0;
110362306a36Sopenharmony_ci		for (i = 0; i < WPCM450_NUM_GPIO_IRQS; i++) {
110462306a36Sopenharmony_ci			int irq;
110562306a36Sopenharmony_ci
110662306a36Sopenharmony_ci			irq = fwnode_irq_get(child, i);
110762306a36Sopenharmony_ci			if (irq < 0)
110862306a36Sopenharmony_ci				break;
110962306a36Sopenharmony_ci			if (!irq)
111062306a36Sopenharmony_ci				continue;
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci			girq->parents[i] = irq;
111362306a36Sopenharmony_ci			girq->num_parents++;
111462306a36Sopenharmony_ci		}
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_ci		ret = devm_gpiochip_add_data(dev, &gpio->gc, gpio);
111762306a36Sopenharmony_ci		if (ret)
111862306a36Sopenharmony_ci			return dev_err_probe(dev, ret, "Failed to add GPIO chip\n");
111962306a36Sopenharmony_ci	}
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	return 0;
112262306a36Sopenharmony_ci}
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_cistatic int wpcm450_pinctrl_probe(struct platform_device *pdev)
112562306a36Sopenharmony_ci{
112662306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
112762306a36Sopenharmony_ci	struct wpcm450_pinctrl *pctrl;
112862306a36Sopenharmony_ci	int ret;
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci	pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
113162306a36Sopenharmony_ci	if (!pctrl)
113262306a36Sopenharmony_ci		return -ENOMEM;
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	pctrl->dev = &pdev->dev;
113562306a36Sopenharmony_ci	raw_spin_lock_init(&pctrl->lock);
113662306a36Sopenharmony_ci	dev_set_drvdata(dev, pctrl);
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_ci	pctrl->gcr_regmap =
113962306a36Sopenharmony_ci		syscon_regmap_lookup_by_compatible("nuvoton,wpcm450-gcr");
114062306a36Sopenharmony_ci	if (IS_ERR(pctrl->gcr_regmap))
114162306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(pctrl->gcr_regmap),
114262306a36Sopenharmony_ci				     "Failed to find nuvoton,wpcm450-gcr\n");
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_ci	pctrl->pctldev = devm_pinctrl_register(dev,
114562306a36Sopenharmony_ci					       &wpcm450_pinctrl_desc, pctrl);
114662306a36Sopenharmony_ci	if (IS_ERR(pctrl->pctldev))
114762306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(pctrl->pctldev),
114862306a36Sopenharmony_ci				     "Failed to register pinctrl device\n");
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci	ret = wpcm450_gpio_register(pdev, pctrl);
115162306a36Sopenharmony_ci	if (ret < 0)
115262306a36Sopenharmony_ci		return ret;
115362306a36Sopenharmony_ci
115462306a36Sopenharmony_ci	return 0;
115562306a36Sopenharmony_ci}
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_cistatic const struct of_device_id wpcm450_pinctrl_match[] = {
115862306a36Sopenharmony_ci	{ .compatible = "nuvoton,wpcm450-pinctrl" },
115962306a36Sopenharmony_ci	{ }
116062306a36Sopenharmony_ci};
116162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, wpcm450_pinctrl_match);
116262306a36Sopenharmony_ci
116362306a36Sopenharmony_cistatic struct platform_driver wpcm450_pinctrl_driver = {
116462306a36Sopenharmony_ci	.probe = wpcm450_pinctrl_probe,
116562306a36Sopenharmony_ci	.driver = {
116662306a36Sopenharmony_ci		.name = "wpcm450-pinctrl",
116762306a36Sopenharmony_ci		.of_match_table = wpcm450_pinctrl_match,
116862306a36Sopenharmony_ci	},
116962306a36Sopenharmony_ci};
117062306a36Sopenharmony_cimodule_platform_driver(wpcm450_pinctrl_driver);
117162306a36Sopenharmony_ci
117262306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
117362306a36Sopenharmony_ciMODULE_AUTHOR("Jonathan Neuschäfer <j.neuschaefer@gmx.net>");
117462306a36Sopenharmony_ciMODULE_DESCRIPTION("Nuvoton WPCM450 Pinctrl and GPIO driver");
1175