pinctrl: npcm8xx: use new generic GPIO chip API

Convert the driver to using the new generic GPIO chip interfaces from
linux/gpio/generic.h.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Link: https://lore.kernel.org/20250811-gpio-mmio-pinctrl-conv-v1-3-a84c5da2be20@linaro.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
Bartosz Golaszewski 2025-08-11 17:02:02 +02:00 committed by Linus Walleij
parent 658cd189d7
commit d2e9afca3a

View File

@ -4,6 +4,7 @@
#include <linux/bits.h>
#include <linux/device.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/generic.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/mfd/syscon.h>
@ -90,7 +91,7 @@ struct debounce_time {
};
struct npcm8xx_gpio {
struct gpio_chip gc;
struct gpio_generic_chip chip;
void __iomem *base;
struct debounce_time debounce;
int irqbase;
@ -115,24 +116,20 @@ struct npcm8xx_pinctrl {
};
/* GPIO handling in the pinctrl driver */
static void npcm_gpio_set(struct gpio_chip *gc, void __iomem *reg,
static void npcm_gpio_set(struct gpio_generic_chip *chip, void __iomem *reg,
unsigned int pinmask)
{
unsigned long flags;
guard(gpio_generic_lock_irqsave)(chip);
raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
iowrite32(ioread32(reg) | pinmask, reg);
raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
}
static void npcm_gpio_clr(struct gpio_chip *gc, void __iomem *reg,
static void npcm_gpio_clr(struct gpio_generic_chip *chip, void __iomem *reg,
unsigned int pinmask)
{
unsigned long flags;
guard(gpio_generic_lock_irqsave)(chip);
raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
iowrite32(ioread32(reg) & ~pinmask, reg);
raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
}
static void npcmgpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
@ -233,32 +230,32 @@ static int npcmgpio_set_irq_type(struct irq_data *d, unsigned int type)
switch (type) {
case IRQ_TYPE_EDGE_RISING:
npcm_gpio_clr(&bank->gc, bank->base + NPCM8XX_GP_N_EVBE, gpio);
npcm_gpio_clr(&bank->gc, bank->base + NPCM8XX_GP_N_POL, gpio);
npcm_gpio_clr(&bank->chip, bank->base + NPCM8XX_GP_N_EVBE, gpio);
npcm_gpio_clr(&bank->chip, bank->base + NPCM8XX_GP_N_POL, gpio);
break;
case IRQ_TYPE_EDGE_FALLING:
npcm_gpio_clr(&bank->gc, bank->base + NPCM8XX_GP_N_EVBE, gpio);
npcm_gpio_set(&bank->gc, bank->base + NPCM8XX_GP_N_POL, gpio);
npcm_gpio_clr(&bank->chip, bank->base + NPCM8XX_GP_N_EVBE, gpio);
npcm_gpio_set(&bank->chip, bank->base + NPCM8XX_GP_N_POL, gpio);
break;
case IRQ_TYPE_EDGE_BOTH:
npcm_gpio_clr(&bank->gc, bank->base + NPCM8XX_GP_N_POL, gpio);
npcm_gpio_set(&bank->gc, bank->base + NPCM8XX_GP_N_EVBE, gpio);
npcm_gpio_clr(&bank->chip, bank->base + NPCM8XX_GP_N_POL, gpio);
npcm_gpio_set(&bank->chip, bank->base + NPCM8XX_GP_N_EVBE, gpio);
break;
case IRQ_TYPE_LEVEL_LOW:
npcm_gpio_set(&bank->gc, bank->base + NPCM8XX_GP_N_POL, gpio);
npcm_gpio_set(&bank->chip, bank->base + NPCM8XX_GP_N_POL, gpio);
break;
case IRQ_TYPE_LEVEL_HIGH:
npcm_gpio_clr(&bank->gc, bank->base + NPCM8XX_GP_N_POL, gpio);
npcm_gpio_clr(&bank->chip, bank->base + NPCM8XX_GP_N_POL, gpio);
break;
default:
return -EINVAL;
}
if (type & IRQ_TYPE_LEVEL_MASK) {
npcm_gpio_clr(&bank->gc, bank->base + NPCM8XX_GP_N_EVTYP, gpio);
npcm_gpio_clr(&bank->chip, bank->base + NPCM8XX_GP_N_EVTYP, gpio);
irq_set_handler_locked(d, handle_level_irq);
} else if (type & IRQ_TYPE_EDGE_BOTH) {
npcm_gpio_set(&bank->gc, bank->base + NPCM8XX_GP_N_EVTYP, gpio);
npcm_gpio_set(&bank->chip, bank->base + NPCM8XX_GP_N_EVTYP, gpio);
irq_set_handler_locked(d, handle_edge_irq);
}
@ -1842,7 +1839,7 @@ static void npcm8xx_setfunc(struct regmap *gcr_regmap, const unsigned int *pin,
static int npcm8xx_get_slew_rate(struct npcm8xx_gpio *bank,
struct regmap *gcr_regmap, unsigned int pin)
{
int gpio = pin % bank->gc.ngpio;
int gpio = pin % bank->chip.gc.ngpio;
unsigned long pinmask = BIT(gpio);
u32 val;
@ -1862,15 +1859,15 @@ static int npcm8xx_set_slew_rate(struct npcm8xx_gpio *bank,
int arg)
{
void __iomem *OSRC_Offset = bank->base + NPCM8XX_GP_N_OSRC;
int gpio = BIT(pin % bank->gc.ngpio);
int gpio = BIT(pin % bank->chip.gc.ngpio);
if (pincfg[pin].flag & SLEW) {
switch (arg) {
case 0:
npcm_gpio_clr(&bank->gc, OSRC_Offset, gpio);
npcm_gpio_clr(&bank->chip, OSRC_Offset, gpio);
return 0;
case 1:
npcm_gpio_set(&bank->gc, OSRC_Offset, gpio);
npcm_gpio_set(&bank->chip, OSRC_Offset, gpio);
return 0;
default:
return -EINVAL;
@ -1902,7 +1899,7 @@ static int npcm8xx_get_drive_strength(struct pinctrl_dev *pctldev,
struct npcm8xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
struct npcm8xx_gpio *bank =
&npcm->gpio_bank[pin / NPCM8XX_GPIO_PER_BANK];
int gpio = pin % bank->gc.ngpio;
int gpio = pin % bank->chip.gc.ngpio;
unsigned long pinmask = BIT(gpio);
int flg, val;
u32 ds = 0;
@ -1913,7 +1910,7 @@ static int npcm8xx_get_drive_strength(struct pinctrl_dev *pctldev,
val = ioread32(bank->base + NPCM8XX_GP_N_ODSC) & pinmask;
ds = val ? DSHI(flg) : DSLO(flg);
dev_dbg(bank->gc.parent, "pin %d strength %d = %d\n", pin, val, ds);
dev_dbg(bank->chip.gc.parent, "pin %d strength %d = %d\n", pin, val, ds);
return ds;
}
@ -1923,15 +1920,15 @@ static int npcm8xx_set_drive_strength(struct npcm8xx_pinctrl *npcm,
{
struct npcm8xx_gpio *bank =
&npcm->gpio_bank[pin / NPCM8XX_GPIO_PER_BANK];
int gpio = BIT(pin % bank->gc.ngpio);
int gpio = BIT(pin % bank->chip.gc.ngpio);
int v;
v = pincfg[pin].flag & DRIVE_STRENGTH_MASK;
if (DSLO(v) == nval)
npcm_gpio_clr(&bank->gc, bank->base + NPCM8XX_GP_N_ODSC, gpio);
npcm_gpio_clr(&bank->chip, bank->base + NPCM8XX_GP_N_ODSC, gpio);
else if (DSHI(v) == nval)
npcm_gpio_set(&bank->gc, bank->base + NPCM8XX_GP_N_ODSC, gpio);
npcm_gpio_set(&bank->chip, bank->base + NPCM8XX_GP_N_ODSC, gpio);
else
return -ENOTSUPP;
@ -2054,7 +2051,7 @@ static int npcm_gpio_set_direction(struct pinctrl_dev *pctldev,
struct npcm8xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
struct npcm8xx_gpio *bank =
&npcm->gpio_bank[offset / NPCM8XX_GPIO_PER_BANK];
int gpio = BIT(offset % bank->gc.ngpio);
int gpio = BIT(offset % bank->chip.gc.ngpio);
if (input)
iowrite32(gpio, bank->base + NPCM8XX_GP_N_OEC);
@ -2085,7 +2082,7 @@ static int debounce_timing_setting(struct npcm8xx_gpio *bank, u32 gpio,
if (bank->debounce.set_val[i]) {
if (bank->debounce.nanosec_val[i] == nanosecs) {
debounce_select = i << gpio_debounce;
npcm_gpio_set(&bank->gc, DBNCS_offset,
npcm_gpio_set(&bank->chip, DBNCS_offset,
debounce_select);
break;
}
@ -2093,7 +2090,7 @@ static int debounce_timing_setting(struct npcm8xx_gpio *bank, u32 gpio,
bank->debounce.set_val[i] = true;
bank->debounce.nanosec_val[i] = nanosecs;
debounce_select = i << gpio_debounce;
npcm_gpio_set(&bank->gc, DBNCS_offset, debounce_select);
npcm_gpio_set(&bank->chip, DBNCS_offset, debounce_select);
switch (nanosecs) {
case 1 ... 1040:
iowrite32(0, bank->base + NPCM8XX_GP_N_DBNCP0 + (i * 4));
@ -2145,21 +2142,21 @@ static int npcm_set_debounce(struct npcm8xx_pinctrl *npcm, unsigned int pin,
{
struct npcm8xx_gpio *bank =
&npcm->gpio_bank[pin / NPCM8XX_GPIO_PER_BANK];
int gpio = BIT(pin % bank->gc.ngpio);
int gpio = BIT(pin % bank->chip.gc.ngpio);
int ret;
if (nanosecs) {
ret = debounce_timing_setting(bank, pin % bank->gc.ngpio,
ret = debounce_timing_setting(bank, pin % bank->chip.gc.ngpio,
nanosecs);
if (ret)
dev_err(npcm->dev, "Pin %d, All four debounce timing values are used, please use one of exist debounce values\n", pin);
else
npcm_gpio_set(&bank->gc, bank->base + NPCM8XX_GP_N_DBNC,
npcm_gpio_set(&bank->chip, bank->base + NPCM8XX_GP_N_DBNC,
gpio);
return ret;
}
npcm_gpio_clr(&bank->gc, bank->base + NPCM8XX_GP_N_DBNC, gpio);
npcm_gpio_clr(&bank->chip, bank->base + NPCM8XX_GP_N_DBNC, gpio);
return 0;
}
@ -2172,7 +2169,7 @@ static int npcm8xx_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
struct npcm8xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
struct npcm8xx_gpio *bank =
&npcm->gpio_bank[pin / NPCM8XX_GPIO_PER_BANK];
int gpio = pin % bank->gc.ngpio;
int gpio = pin % bank->chip.gc.ngpio;
unsigned long pinmask = BIT(gpio);
u32 ie, oe, pu, pd;
int rc = 0;
@ -2235,34 +2232,34 @@ static int npcm8xx_config_set_one(struct npcm8xx_pinctrl *npcm,
struct npcm8xx_gpio *bank =
&npcm->gpio_bank[pin / NPCM8XX_GPIO_PER_BANK];
u32 arg = pinconf_to_config_argument(config);
int gpio = BIT(pin % bank->gc.ngpio);
int gpio = BIT(pin % bank->chip.gc.ngpio);
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
npcm_gpio_clr(&bank->gc, bank->base + NPCM8XX_GP_N_PU, gpio);
npcm_gpio_clr(&bank->gc, bank->base + NPCM8XX_GP_N_PD, gpio);
npcm_gpio_clr(&bank->chip, bank->base + NPCM8XX_GP_N_PU, gpio);
npcm_gpio_clr(&bank->chip, bank->base + NPCM8XX_GP_N_PD, gpio);
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
npcm_gpio_clr(&bank->gc, bank->base + NPCM8XX_GP_N_PU, gpio);
npcm_gpio_set(&bank->gc, bank->base + NPCM8XX_GP_N_PD, gpio);
npcm_gpio_clr(&bank->chip, bank->base + NPCM8XX_GP_N_PU, gpio);
npcm_gpio_set(&bank->chip, bank->base + NPCM8XX_GP_N_PD, gpio);
break;
case PIN_CONFIG_BIAS_PULL_UP:
npcm_gpio_clr(&bank->gc, bank->base + NPCM8XX_GP_N_PD, gpio);
npcm_gpio_set(&bank->gc, bank->base + NPCM8XX_GP_N_PU, gpio);
npcm_gpio_clr(&bank->chip, bank->base + NPCM8XX_GP_N_PD, gpio);
npcm_gpio_set(&bank->chip, bank->base + NPCM8XX_GP_N_PU, gpio);
break;
case PIN_CONFIG_INPUT_ENABLE:
iowrite32(gpio, bank->base + NPCM8XX_GP_N_OEC);
bank->direction_input(&bank->gc, pin % bank->gc.ngpio);
bank->direction_input(&bank->chip.gc, pin % bank->chip.gc.ngpio);
break;
case PIN_CONFIG_OUTPUT:
bank->direction_output(&bank->gc, pin % bank->gc.ngpio, arg);
bank->direction_output(&bank->chip.gc, pin % bank->chip.gc.ngpio, arg);
iowrite32(gpio, bank->base + NPCM8XX_GP_N_OES);
break;
case PIN_CONFIG_DRIVE_PUSH_PULL:
npcm_gpio_clr(&bank->gc, bank->base + NPCM8XX_GP_N_OTYP, gpio);
npcm_gpio_clr(&bank->chip, bank->base + NPCM8XX_GP_N_OTYP, gpio);
break;
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
npcm_gpio_set(&bank->gc, bank->base + NPCM8XX_GP_N_OTYP, gpio);
npcm_gpio_set(&bank->chip, bank->base + NPCM8XX_GP_N_OTYP, gpio);
break;
case PIN_CONFIG_INPUT_DEBOUNCE:
return npcm_set_debounce(npcm, pin, arg * 1000);
@ -2313,13 +2310,14 @@ static int npcmgpio_add_pin_ranges(struct gpio_chip *chip)
{
struct npcm8xx_gpio *bank = gpiochip_get_data(chip);
return gpiochip_add_pin_range(&bank->gc, dev_name(chip->parent),
bank->pinctrl_id, bank->gc.base,
bank->gc.ngpio);
return gpiochip_add_pin_range(&bank->chip.gc, dev_name(chip->parent),
bank->pinctrl_id, bank->chip.gc.base,
bank->chip.gc.ngpio);
}
static int npcm8xx_gpio_fw(struct npcm8xx_pinctrl *pctrl)
{
struct gpio_generic_chip_config config;
struct fwnode_reference_args args;
struct device *dev = pctrl->dev;
struct fwnode_handle *child;
@ -2331,15 +2329,19 @@ static int npcm8xx_gpio_fw(struct npcm8xx_pinctrl *pctrl)
if (!pctrl->gpio_bank[id].base)
return dev_err_probe(dev, -ENXIO, "fwnode_iomap id %d failed\n", id);
ret = bgpio_init(&pctrl->gpio_bank[id].gc, dev, 4,
pctrl->gpio_bank[id].base + NPCM8XX_GP_N_DIN,
pctrl->gpio_bank[id].base + NPCM8XX_GP_N_DOUT,
NULL,
NULL,
pctrl->gpio_bank[id].base + NPCM8XX_GP_N_IEM,
BGPIOF_READ_OUTPUT_REG_SET);
config = (typeof(config)){
.dev = dev,
.sz = 4,
.dat = pctrl->gpio_bank[id].base + NPCM8XX_GP_N_DIN,
.set = pctrl->gpio_bank[id].base + NPCM8XX_GP_N_DOUT,
.dirin = pctrl->gpio_bank[id].base + NPCM8XX_GP_N_IEM,
.flags = BGPIOF_READ_OUTPUT_REG_SET,
};
ret = gpio_generic_chip_init(&pctrl->gpio_bank[id].chip, &config);
if (ret)
return dev_err_probe(dev, ret, "bgpio_init() failed\n");
return dev_err_probe(dev, ret,
"failed to initialize the generic GPIO chip\n");
ret = fwnode_property_get_reference_args(child, "gpio-ranges", NULL, 3, 0, &args);
if (ret < 0)
@ -2353,26 +2355,26 @@ static int npcm8xx_gpio_fw(struct npcm8xx_pinctrl *pctrl)
pctrl->gpio_bank[id].irq_chip = npcmgpio_irqchip;
pctrl->gpio_bank[id].irqbase = id * NPCM8XX_GPIO_PER_BANK;
pctrl->gpio_bank[id].pinctrl_id = args.args[0];
pctrl->gpio_bank[id].gc.base = -1;
pctrl->gpio_bank[id].gc.ngpio = args.args[2];
pctrl->gpio_bank[id].gc.owner = THIS_MODULE;
pctrl->gpio_bank[id].gc.parent = dev;
pctrl->gpio_bank[id].gc.fwnode = child;
pctrl->gpio_bank[id].gc.label = devm_kasprintf(dev, GFP_KERNEL, "%pfw", child);
if (pctrl->gpio_bank[id].gc.label == NULL)
pctrl->gpio_bank[id].chip.gc.base = -1;
pctrl->gpio_bank[id].chip.gc.ngpio = args.args[2];
pctrl->gpio_bank[id].chip.gc.owner = THIS_MODULE;
pctrl->gpio_bank[id].chip.gc.parent = dev;
pctrl->gpio_bank[id].chip.gc.fwnode = child;
pctrl->gpio_bank[id].chip.gc.label = devm_kasprintf(dev, GFP_KERNEL, "%pfw", child);
if (pctrl->gpio_bank[id].chip.gc.label == NULL)
return -ENOMEM;
pctrl->gpio_bank[id].gc.dbg_show = npcmgpio_dbg_show;
pctrl->gpio_bank[id].direction_input = pctrl->gpio_bank[id].gc.direction_input;
pctrl->gpio_bank[id].gc.direction_input = npcmgpio_direction_input;
pctrl->gpio_bank[id].direction_output = pctrl->gpio_bank[id].gc.direction_output;
pctrl->gpio_bank[id].gc.direction_output = npcmgpio_direction_output;
pctrl->gpio_bank[id].request = pctrl->gpio_bank[id].gc.request;
pctrl->gpio_bank[id].gc.request = npcmgpio_gpio_request;
pctrl->gpio_bank[id].gc.free = pinctrl_gpio_free;
pctrl->gpio_bank[id].chip.gc.dbg_show = npcmgpio_dbg_show;
pctrl->gpio_bank[id].direction_input = pctrl->gpio_bank[id].chip.gc.direction_input;
pctrl->gpio_bank[id].chip.gc.direction_input = npcmgpio_direction_input;
pctrl->gpio_bank[id].direction_output = pctrl->gpio_bank[id].chip.gc.direction_output;
pctrl->gpio_bank[id].chip.gc.direction_output = npcmgpio_direction_output;
pctrl->gpio_bank[id].request = pctrl->gpio_bank[id].chip.gc.request;
pctrl->gpio_bank[id].chip.gc.request = npcmgpio_gpio_request;
pctrl->gpio_bank[id].chip.gc.free = pinctrl_gpio_free;
for (i = 0 ; i < NPCM8XX_DEBOUNCE_MAX ; i++)
pctrl->gpio_bank[id].debounce.set_val[i] = false;
pctrl->gpio_bank[id].gc.add_pin_ranges = npcmgpio_add_pin_ranges;
pctrl->gpio_bank[id].chip.gc.add_pin_ranges = npcmgpio_add_pin_ranges;
id++;
}
@ -2387,7 +2389,7 @@ static int npcm8xx_gpio_register(struct npcm8xx_pinctrl *pctrl)
for (id = 0 ; id < pctrl->bank_num ; id++) {
struct gpio_irq_chip *girq;
girq = &pctrl->gpio_bank[id].gc.irq;
girq = &pctrl->gpio_bank[id].chip.gc.irq;
girq->chip = &pctrl->gpio_bank[id].irq_chip;
girq->parent_handler = npcmgpio_irq_handler;
girq->num_parents = 1;
@ -2401,7 +2403,7 @@ static int npcm8xx_gpio_register(struct npcm8xx_pinctrl *pctrl)
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_level_irq;
ret = devm_gpiochip_add_data(pctrl->dev,
&pctrl->gpio_bank[id].gc,
&pctrl->gpio_bank[id].chip.gc,
&pctrl->gpio_bank[id]);
if (ret)
return dev_err_probe(pctrl->dev, ret, "Failed to add GPIO chip %u\n", id);