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, ®, 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", ®); 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