mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 08:33:17 +02:00
Merge branch 'ib-gpio_generic_chip_init' into devel
This commit is contained in:
commit
4b4dbf0f26
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#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>
|
||||
|
|
@ -77,7 +78,7 @@
|
|||
/* Structure for register banks */
|
||||
struct npcm7xx_gpio {
|
||||
void __iomem *base;
|
||||
struct gpio_chip gc;
|
||||
struct gpio_generic_chip chip;
|
||||
int irqbase;
|
||||
int irq;
|
||||
u32 pinctrl_id;
|
||||
|
|
@ -99,32 +100,26 @@ struct npcm7xx_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;
|
||||
unsigned long val;
|
||||
|
||||
raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
|
||||
guard(gpio_generic_lock_irqsave)(chip);
|
||||
|
||||
val = ioread32(reg) | pinmask;
|
||||
iowrite32(val, 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;
|
||||
unsigned long val;
|
||||
|
||||
raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
|
||||
guard(gpio_generic_lock_irqsave)(chip);
|
||||
|
||||
val = ioread32(reg) & ~pinmask;
|
||||
iowrite32(val, reg);
|
||||
|
||||
raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
|
||||
}
|
||||
|
||||
static void npcmgpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
|
|
@ -132,9 +127,9 @@ static void npcmgpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
|||
struct npcm7xx_gpio *bank = gpiochip_get_data(chip);
|
||||
|
||||
seq_printf(s, "-- module %d [gpio%d - %d]\n",
|
||||
bank->gc.base / bank->gc.ngpio,
|
||||
bank->gc.base,
|
||||
bank->gc.base + bank->gc.ngpio);
|
||||
bank->chip.gc.base / bank->chip.gc.ngpio,
|
||||
bank->chip.gc.base,
|
||||
bank->chip.gc.base + bank->chip.gc.ngpio);
|
||||
seq_printf(s, "DIN :%.8x DOUT:%.8x IE :%.8x OE :%.8x\n",
|
||||
ioread32(bank->base + NPCM7XX_GP_N_DIN),
|
||||
ioread32(bank->base + NPCM7XX_GP_N_DOUT),
|
||||
|
|
@ -220,7 +215,7 @@ static void npcmgpio_irq_handler(struct irq_desc *desc)
|
|||
chained_irq_enter(chip, desc);
|
||||
sts = ioread32(bank->base + NPCM7XX_GP_N_EVST);
|
||||
en = ioread32(bank->base + NPCM7XX_GP_N_EVEN);
|
||||
dev_dbg(bank->gc.parent, "==> got irq sts %.8lx %.8lx\n", sts,
|
||||
dev_dbg(bank->chip.gc.parent, "==> got irq sts %.8lx %.8lx\n", sts,
|
||||
en);
|
||||
|
||||
sts &= en;
|
||||
|
|
@ -235,42 +230,42 @@ static int npcmgpio_set_irq_type(struct irq_data *d, unsigned int type)
|
|||
struct npcm7xx_gpio *bank = gpiochip_get_data(gc);
|
||||
unsigned int gpio = BIT(irqd_to_hwirq(d));
|
||||
|
||||
dev_dbg(bank->gc.parent, "setirqtype: %u.%u = %u\n", gpio,
|
||||
dev_dbg(bank->chip.gc.parent, "setirqtype: %u.%u = %u\n", gpio,
|
||||
d->irq, type);
|
||||
switch (type) {
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
dev_dbg(bank->gc.parent, "edge.rising\n");
|
||||
npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_EVBE, gpio);
|
||||
npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_POL, gpio);
|
||||
dev_dbg(bank->chip.gc.parent, "edge.rising\n");
|
||||
npcm_gpio_clr(&bank->chip, bank->base + NPCM7XX_GP_N_EVBE, gpio);
|
||||
npcm_gpio_clr(&bank->chip, bank->base + NPCM7XX_GP_N_POL, gpio);
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
dev_dbg(bank->gc.parent, "edge.falling\n");
|
||||
npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_EVBE, gpio);
|
||||
npcm_gpio_set(&bank->gc, bank->base + NPCM7XX_GP_N_POL, gpio);
|
||||
dev_dbg(bank->chip.gc.parent, "edge.falling\n");
|
||||
npcm_gpio_clr(&bank->chip, bank->base + NPCM7XX_GP_N_EVBE, gpio);
|
||||
npcm_gpio_set(&bank->chip, bank->base + NPCM7XX_GP_N_POL, gpio);
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
dev_dbg(bank->gc.parent, "edge.both\n");
|
||||
npcm_gpio_set(&bank->gc, bank->base + NPCM7XX_GP_N_EVBE, gpio);
|
||||
dev_dbg(bank->chip.gc.parent, "edge.both\n");
|
||||
npcm_gpio_set(&bank->chip, bank->base + NPCM7XX_GP_N_EVBE, gpio);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
dev_dbg(bank->gc.parent, "level.low\n");
|
||||
npcm_gpio_set(&bank->gc, bank->base + NPCM7XX_GP_N_POL, gpio);
|
||||
dev_dbg(bank->chip.gc.parent, "level.low\n");
|
||||
npcm_gpio_set(&bank->chip, bank->base + NPCM7XX_GP_N_POL, gpio);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
dev_dbg(bank->gc.parent, "level.high\n");
|
||||
npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_POL, gpio);
|
||||
dev_dbg(bank->chip.gc.parent, "level.high\n");
|
||||
npcm_gpio_clr(&bank->chip, bank->base + NPCM7XX_GP_N_POL, gpio);
|
||||
break;
|
||||
default:
|
||||
dev_dbg(bank->gc.parent, "invalid irq type\n");
|
||||
dev_dbg(bank->chip.gc.parent, "invalid irq type\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
|
||||
npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_EVTYP, gpio);
|
||||
npcm_gpio_clr(&bank->chip, bank->base + NPCM7XX_GP_N_EVTYP, gpio);
|
||||
irq_set_handler_locked(d, handle_level_irq);
|
||||
} else if (type & (IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_EDGE_RISING
|
||||
| IRQ_TYPE_EDGE_FALLING)) {
|
||||
npcm_gpio_set(&bank->gc, bank->base + NPCM7XX_GP_N_EVTYP, gpio);
|
||||
npcm_gpio_set(&bank->chip, bank->base + NPCM7XX_GP_N_EVTYP, gpio);
|
||||
irq_set_handler_locked(d, handle_edge_irq);
|
||||
}
|
||||
|
||||
|
|
@ -283,7 +278,7 @@ static void npcmgpio_irq_ack(struct irq_data *d)
|
|||
struct npcm7xx_gpio *bank = gpiochip_get_data(gc);
|
||||
unsigned int gpio = irqd_to_hwirq(d);
|
||||
|
||||
dev_dbg(bank->gc.parent, "irq_ack: %u.%u\n", gpio, d->irq);
|
||||
dev_dbg(bank->chip.gc.parent, "irq_ack: %u.%u\n", gpio, d->irq);
|
||||
iowrite32(BIT(gpio), bank->base + NPCM7XX_GP_N_EVST);
|
||||
}
|
||||
|
||||
|
|
@ -295,7 +290,7 @@ static void npcmgpio_irq_mask(struct irq_data *d)
|
|||
unsigned int gpio = irqd_to_hwirq(d);
|
||||
|
||||
/* Clear events */
|
||||
dev_dbg(bank->gc.parent, "irq_mask: %u.%u\n", gpio, d->irq);
|
||||
dev_dbg(bank->chip.gc.parent, "irq_mask: %u.%u\n", gpio, d->irq);
|
||||
iowrite32(BIT(gpio), bank->base + NPCM7XX_GP_N_EVENC);
|
||||
gpiochip_disable_irq(gc, gpio);
|
||||
}
|
||||
|
|
@ -309,7 +304,7 @@ static void npcmgpio_irq_unmask(struct irq_data *d)
|
|||
|
||||
/* Enable events */
|
||||
gpiochip_enable_irq(gc, gpio);
|
||||
dev_dbg(bank->gc.parent, "irq_unmask: %u.%u\n", gpio, d->irq);
|
||||
dev_dbg(bank->chip.gc.parent, "irq_unmask: %u.%u\n", gpio, d->irq);
|
||||
iowrite32(BIT(gpio), bank->base + NPCM7XX_GP_N_EVENS);
|
||||
}
|
||||
|
||||
|
|
@ -1423,7 +1418,7 @@ static int npcm7xx_get_slew_rate(struct npcm7xx_gpio *bank,
|
|||
struct regmap *gcr_regmap, unsigned int pin)
|
||||
{
|
||||
u32 val;
|
||||
int gpio = (pin % bank->gc.ngpio);
|
||||
int gpio = (pin % bank->chip.gc.ngpio);
|
||||
unsigned long pinmask = BIT(gpio);
|
||||
|
||||
if (pincfg[pin].flag & SLEW)
|
||||
|
|
@ -1443,16 +1438,16 @@ static int npcm7xx_set_slew_rate(struct npcm7xx_gpio *bank,
|
|||
struct regmap *gcr_regmap, unsigned int pin,
|
||||
int arg)
|
||||
{
|
||||
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, bank->base + NPCM7XX_GP_N_OSRC,
|
||||
npcm_gpio_clr(&bank->chip, bank->base + NPCM7XX_GP_N_OSRC,
|
||||
gpio);
|
||||
return 0;
|
||||
case 1:
|
||||
npcm_gpio_set(&bank->gc, bank->base + NPCM7XX_GP_N_OSRC,
|
||||
npcm_gpio_set(&bank->chip, bank->base + NPCM7XX_GP_N_OSRC,
|
||||
gpio);
|
||||
return 0;
|
||||
default:
|
||||
|
|
@ -1485,7 +1480,7 @@ static int npcm7xx_get_drive_strength(struct pinctrl_dev *pctldev,
|
|||
struct npcm7xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct npcm7xx_gpio *bank =
|
||||
&npcm->gpio_bank[pin / NPCM7XX_GPIO_PER_BANK];
|
||||
int gpio = (pin % bank->gc.ngpio);
|
||||
int gpio = (pin % bank->chip.gc.ngpio);
|
||||
unsigned long pinmask = BIT(gpio);
|
||||
u32 ds = 0;
|
||||
int flg, val;
|
||||
|
|
@ -1496,7 +1491,7 @@ static int npcm7xx_get_drive_strength(struct pinctrl_dev *pctldev,
|
|||
val = ioread32(bank->base + NPCM7XX_GP_N_ODSC)
|
||||
& pinmask;
|
||||
ds = val ? DSHI(flg) : DSLO(flg);
|
||||
dev_dbg(bank->gc.parent,
|
||||
dev_dbg(bank->chip.gc.parent,
|
||||
"pin %d strength %d = %d\n", pin, val, ds);
|
||||
return ds;
|
||||
}
|
||||
|
|
@ -1511,20 +1506,20 @@ static int npcm7xx_set_drive_strength(struct npcm7xx_pinctrl *npcm,
|
|||
int v;
|
||||
struct npcm7xx_gpio *bank =
|
||||
&npcm->gpio_bank[pin / NPCM7XX_GPIO_PER_BANK];
|
||||
int gpio = BIT(pin % bank->gc.ngpio);
|
||||
int gpio = BIT(pin % bank->chip.gc.ngpio);
|
||||
|
||||
v = (pincfg[pin].flag & DRIVE_STRENGTH_MASK);
|
||||
if (!nval || !v)
|
||||
return -ENOTSUPP;
|
||||
if (DSLO(v) == nval) {
|
||||
dev_dbg(bank->gc.parent,
|
||||
dev_dbg(bank->chip.gc.parent,
|
||||
"setting pin %d to low strength [%d]\n", pin, nval);
|
||||
npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_ODSC, gpio);
|
||||
npcm_gpio_clr(&bank->chip, bank->base + NPCM7XX_GP_N_ODSC, gpio);
|
||||
return 0;
|
||||
} else if (DSHI(v) == nval) {
|
||||
dev_dbg(bank->gc.parent,
|
||||
dev_dbg(bank->chip.gc.parent,
|
||||
"setting pin %d to high strength [%d]\n", pin, nval);
|
||||
npcm_gpio_set(&bank->gc, bank->base + NPCM7XX_GP_N_ODSC, gpio);
|
||||
npcm_gpio_set(&bank->chip, bank->base + NPCM7XX_GP_N_ODSC, gpio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1657,9 +1652,9 @@ static int npcm_gpio_set_direction(struct pinctrl_dev *pctldev,
|
|||
struct npcm7xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct npcm7xx_gpio *bank =
|
||||
&npcm->gpio_bank[offset / NPCM7XX_GPIO_PER_BANK];
|
||||
int gpio = BIT(offset % bank->gc.ngpio);
|
||||
int gpio = BIT(offset % bank->chip.gc.ngpio);
|
||||
|
||||
dev_dbg(bank->gc.parent, "GPIO Set Direction: %d = %d\n", offset,
|
||||
dev_dbg(bank->chip.gc.parent, "GPIO Set Direction: %d = %d\n", offset,
|
||||
input);
|
||||
if (input)
|
||||
iowrite32(gpio, bank->base + NPCM7XX_GP_N_OEC);
|
||||
|
|
@ -1687,7 +1682,7 @@ static int npcm7xx_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
|
|||
struct npcm7xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct npcm7xx_gpio *bank =
|
||||
&npcm->gpio_bank[pin / NPCM7XX_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;
|
||||
|
|
@ -1750,38 +1745,38 @@ static int npcm7xx_config_set_one(struct npcm7xx_pinctrl *npcm,
|
|||
u16 arg = pinconf_to_config_argument(config);
|
||||
struct npcm7xx_gpio *bank =
|
||||
&npcm->gpio_bank[pin / NPCM7XX_GPIO_PER_BANK];
|
||||
int gpio = BIT(pin % bank->gc.ngpio);
|
||||
int gpio = BIT(pin % bank->chip.gc.ngpio);
|
||||
|
||||
dev_dbg(bank->gc.parent, "param=%d %d[GPIO]\n", param, pin);
|
||||
dev_dbg(bank->chip.gc.parent, "param=%d %d[GPIO]\n", param, pin);
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_PU, gpio);
|
||||
npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_PD, gpio);
|
||||
npcm_gpio_clr(&bank->chip, bank->base + NPCM7XX_GP_N_PU, gpio);
|
||||
npcm_gpio_clr(&bank->chip, bank->base + NPCM7XX_GP_N_PD, gpio);
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_PU, gpio);
|
||||
npcm_gpio_set(&bank->gc, bank->base + NPCM7XX_GP_N_PD, gpio);
|
||||
npcm_gpio_clr(&bank->chip, bank->base + NPCM7XX_GP_N_PU, gpio);
|
||||
npcm_gpio_set(&bank->chip, bank->base + NPCM7XX_GP_N_PD, gpio);
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_PD, gpio);
|
||||
npcm_gpio_set(&bank->gc, bank->base + NPCM7XX_GP_N_PU, gpio);
|
||||
npcm_gpio_clr(&bank->chip, bank->base + NPCM7XX_GP_N_PD, gpio);
|
||||
npcm_gpio_set(&bank->chip, bank->base + NPCM7XX_GP_N_PU, gpio);
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
iowrite32(gpio, bank->base + NPCM7XX_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 + NPCM7XX_GP_N_OES);
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_PUSH_PULL:
|
||||
npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_OTYP, gpio);
|
||||
npcm_gpio_clr(&bank->chip, bank->base + NPCM7XX_GP_N_OTYP, gpio);
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
||||
npcm_gpio_set(&bank->gc, bank->base + NPCM7XX_GP_N_OTYP, gpio);
|
||||
npcm_gpio_set(&bank->chip, bank->base + NPCM7XX_GP_N_OTYP, gpio);
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_DEBOUNCE:
|
||||
npcm_gpio_set(&bank->gc, bank->base + NPCM7XX_GP_N_DBNC, gpio);
|
||||
npcm_gpio_set(&bank->chip, bank->base + NPCM7XX_GP_N_DBNC, gpio);
|
||||
break;
|
||||
case PIN_CONFIG_SLEW_RATE:
|
||||
return npcm7xx_set_slew_rate(bank, npcm->gcr_regmap, pin, arg);
|
||||
|
|
@ -1829,6 +1824,7 @@ static const struct pinctrl_desc npcm7xx_pinctrl_desc = {
|
|||
|
||||
static int npcm7xx_gpio_of(struct npcm7xx_pinctrl *pctrl)
|
||||
{
|
||||
struct gpio_generic_chip_config config;
|
||||
int ret = -ENXIO;
|
||||
struct device *dev = pctrl->dev;
|
||||
struct fwnode_reference_args args;
|
||||
|
|
@ -1840,15 +1836,18 @@ static int npcm7xx_gpio_of(struct npcm7xx_pinctrl *pctrl)
|
|||
if (!pctrl->gpio_bank[id].base)
|
||||
return -EINVAL;
|
||||
|
||||
ret = bgpio_init(&pctrl->gpio_bank[id].gc, dev, 4,
|
||||
pctrl->gpio_bank[id].base + NPCM7XX_GP_N_DIN,
|
||||
pctrl->gpio_bank[id].base + NPCM7XX_GP_N_DOUT,
|
||||
NULL,
|
||||
NULL,
|
||||
pctrl->gpio_bank[id].base + NPCM7XX_GP_N_IEM,
|
||||
BGPIOF_READ_OUTPUT_REG_SET);
|
||||
config = (typeof(config)){
|
||||
.dev = dev,
|
||||
.sz = 4,
|
||||
.dat = pctrl->gpio_bank[id].base + NPCM7XX_GP_N_DIN,
|
||||
.set = pctrl->gpio_bank[id].base + NPCM7XX_GP_N_DOUT,
|
||||
.dirin = pctrl->gpio_bank[id].base + NPCM7XX_GP_N_IEM,
|
||||
.flags = BGPIOF_READ_OUTPUT_REG_SET,
|
||||
};
|
||||
|
||||
ret = gpio_generic_chip_init(&pctrl->gpio_bank[id].chip, &config);
|
||||
if (ret) {
|
||||
dev_err(dev, "bgpio_init() failed\n");
|
||||
dev_err(dev, "failed to initialize the generic GPIO chip\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1866,23 +1865,23 @@ static int npcm7xx_gpio_of(struct npcm7xx_pinctrl *pctrl)
|
|||
pctrl->gpio_bank[id].irq = ret;
|
||||
pctrl->gpio_bank[id].irqbase = id * NPCM7XX_GPIO_PER_BANK;
|
||||
pctrl->gpio_bank[id].pinctrl_id = args.args[0];
|
||||
pctrl->gpio_bank[id].gc.base = args.args[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 = args.args[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;
|
||||
id++;
|
||||
}
|
||||
|
||||
|
|
@ -1897,7 +1896,7 @@ static int npcm7xx_gpio_register(struct npcm7xx_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;
|
||||
gpio_irq_chip_set_chip(girq, &npcmgpio_irqchip);
|
||||
girq->parent_handler = npcmgpio_irq_handler;
|
||||
girq->num_parents = 1;
|
||||
|
|
@ -1912,21 +1911,21 @@ static int npcm7xx_gpio_register(struct npcm7xx_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) {
|
||||
dev_err(pctrl->dev, "Failed to add GPIO chip %u\n", id);
|
||||
goto err_register;
|
||||
}
|
||||
|
||||
ret = gpiochip_add_pin_range(&pctrl->gpio_bank[id].gc,
|
||||
ret = gpiochip_add_pin_range(&pctrl->gpio_bank[id].chip.gc,
|
||||
dev_name(pctrl->dev),
|
||||
pctrl->gpio_bank[id].pinctrl_id,
|
||||
pctrl->gpio_bank[id].gc.base,
|
||||
pctrl->gpio_bank[id].gc.ngpio);
|
||||
pctrl->gpio_bank[id].chip.gc.base,
|
||||
pctrl->gpio_bank[id].chip.gc.ngpio);
|
||||
if (ret < 0) {
|
||||
dev_err(pctrl->dev, "Failed to add GPIO bank %u\n", id);
|
||||
gpiochip_remove(&pctrl->gpio_bank[id].gc);
|
||||
gpiochip_remove(&pctrl->gpio_bank[id].chip.gc);
|
||||
goto err_register;
|
||||
}
|
||||
}
|
||||
|
|
@ -1935,7 +1934,7 @@ static int npcm7xx_gpio_register(struct npcm7xx_pinctrl *pctrl)
|
|||
|
||||
err_register:
|
||||
for (; id > 0; id--)
|
||||
gpiochip_remove(&pctrl->gpio_bank[id - 1].gc);
|
||||
gpiochip_remove(&pctrl->gpio_bank[id - 1].chip.gc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#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>
|
||||
|
|
@ -47,7 +48,7 @@ struct wpcm450_pinctrl;
|
|||
struct wpcm450_bank;
|
||||
|
||||
struct wpcm450_gpio {
|
||||
struct gpio_chip gc;
|
||||
struct gpio_generic_chip chip;
|
||||
struct wpcm450_pinctrl *pctrl;
|
||||
const struct wpcm450_bank *bank;
|
||||
};
|
||||
|
|
@ -184,11 +185,12 @@ static void wpcm450_gpio_irq_unmask(struct irq_data *d)
|
|||
}
|
||||
|
||||
/*
|
||||
* This is an implementation of the gpio_chip->get() function, for use in
|
||||
* wpcm450_gpio_fix_evpol. Unfortunately, we can't use the bgpio-provided
|
||||
* implementation there, because it would require taking gpio_chip->bgpio_lock,
|
||||
* which is a spin lock, but wpcm450_gpio_fix_evpol must work in contexts where
|
||||
* a raw spin lock is held.
|
||||
* FIXME: This is an implementation of the gpio_chip->get() function, for use
|
||||
* in wpcm450_gpio_fix_evpol(). It was implemented back when gpio-mmio used a
|
||||
* regular spinlock internally, while wpcm450_gpio_fix_evpol() needed to work
|
||||
* in contexts with a raw spinlock held. Since then, the gpio generic chip has
|
||||
* been switched to using a raw spinlock so this should be converted to using
|
||||
* the locking interfaces provided in linux/gpio/gneneric.h.
|
||||
*/
|
||||
static int wpcm450_gpio_get(struct wpcm450_gpio *gpio, int offset)
|
||||
{
|
||||
|
|
@ -329,7 +331,7 @@ static void wpcm450_gpio_irqhandler(struct irq_desc *desc)
|
|||
for_each_set_bit(bit, &pending, 32) {
|
||||
int offset = wpcm450_irq_bitnum_to_gpio(gpio, bit);
|
||||
|
||||
generic_handle_domain_irq(gpio->gc.irq.domain, offset);
|
||||
generic_handle_domain_irq(gpio->chip.gc.irq.domain, offset);
|
||||
}
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
|
@ -1012,7 +1014,7 @@ static int wpcm450_gpio_add_pin_ranges(struct gpio_chip *chip)
|
|||
struct wpcm450_gpio *gpio = gpiochip_get_data(chip);
|
||||
const struct wpcm450_bank *bank = gpio->bank;
|
||||
|
||||
return gpiochip_add_pin_range(&gpio->gc, dev_name(gpio->pctrl->dev),
|
||||
return gpiochip_add_pin_range(&gpio->chip.gc, dev_name(gpio->pctrl->dev),
|
||||
0, bank->base, bank->length);
|
||||
}
|
||||
|
||||
|
|
@ -1029,6 +1031,7 @@ static int wpcm450_gpio_register(struct platform_device *pdev,
|
|||
"Resource fail for GPIO controller\n");
|
||||
|
||||
for_each_gpiochip_node(dev, child) {
|
||||
struct gpio_generic_chip_config config;
|
||||
void __iomem *dat = NULL;
|
||||
void __iomem *set = NULL;
|
||||
void __iomem *dirout = NULL;
|
||||
|
|
@ -1060,17 +1063,26 @@ static int wpcm450_gpio_register(struct platform_device *pdev,
|
|||
} else {
|
||||
flags = BGPIOF_NO_OUTPUT;
|
||||
}
|
||||
ret = bgpio_init(&gpio->gc, dev, 4,
|
||||
dat, set, NULL, dirout, NULL, flags);
|
||||
|
||||
config = (typeof(config)){
|
||||
.dev = dev,
|
||||
.sz = 4,
|
||||
.dat = dat,
|
||||
.set = set,
|
||||
.dirout = dirout,
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
ret = gpio_generic_chip_init(&gpio->chip, &config);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "GPIO initialization failed\n");
|
||||
|
||||
gpio->gc.ngpio = bank->length;
|
||||
gpio->gc.set_config = wpcm450_gpio_set_config;
|
||||
gpio->gc.fwnode = child;
|
||||
gpio->gc.add_pin_ranges = wpcm450_gpio_add_pin_ranges;
|
||||
gpio->chip.gc.ngpio = bank->length;
|
||||
gpio->chip.gc.set_config = wpcm450_gpio_set_config;
|
||||
gpio->chip.gc.fwnode = child;
|
||||
gpio->chip.gc.add_pin_ranges = wpcm450_gpio_add_pin_ranges;
|
||||
|
||||
girq = &gpio->gc.irq;
|
||||
girq = &gpio->chip.gc.irq;
|
||||
gpio_irq_chip_set_chip(girq, &wpcm450_gpio_irqchip);
|
||||
girq->parent_handler = wpcm450_gpio_irqhandler;
|
||||
girq->parents = devm_kcalloc(dev, WPCM450_NUM_GPIO_IRQS,
|
||||
|
|
@ -1094,7 +1106,7 @@ static int wpcm450_gpio_register(struct platform_device *pdev,
|
|||
girq->num_parents++;
|
||||
}
|
||||
|
||||
ret = devm_gpiochip_add_data(dev, &gpio->gc, gpio);
|
||||
ret = devm_gpiochip_add_data(dev, &gpio->chip.gc, gpio);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to add GPIO chip\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
/* Copyright (C) 2019 Intel Corporation */
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/gpio/generic.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
|
@ -179,7 +180,7 @@ static int gpiochip_setup(struct device *dev, struct eqbr_gpio_ctrl *gctrl)
|
|||
struct gpio_irq_chip *girq;
|
||||
struct gpio_chip *gc;
|
||||
|
||||
gc = &gctrl->chip;
|
||||
gc = &gctrl->chip.gc;
|
||||
gc->label = gctrl->name;
|
||||
gc->fwnode = gctrl->fwnode;
|
||||
gc->request = gpiochip_generic_request;
|
||||
|
|
@ -191,7 +192,7 @@ static int gpiochip_setup(struct device *dev, struct eqbr_gpio_ctrl *gctrl)
|
|||
return 0;
|
||||
}
|
||||
|
||||
girq = &gctrl->chip.irq;
|
||||
girq = &gctrl->chip.gc.irq;
|
||||
gpio_irq_chip_set_chip(girq, &eqbr_irq_chip);
|
||||
girq->parent_handler = eqbr_irq_handler;
|
||||
girq->num_parents = 1;
|
||||
|
|
@ -208,6 +209,7 @@ static int gpiochip_setup(struct device *dev, struct eqbr_gpio_ctrl *gctrl)
|
|||
|
||||
static int gpiolib_reg(struct eqbr_pinctrl_drv_data *drvdata)
|
||||
{
|
||||
struct gpio_generic_chip_config config;
|
||||
struct device *dev = drvdata->dev;
|
||||
struct eqbr_gpio_ctrl *gctrl;
|
||||
struct device_node *np;
|
||||
|
|
@ -239,12 +241,16 @@ static int gpiolib_reg(struct eqbr_pinctrl_drv_data *drvdata)
|
|||
}
|
||||
raw_spin_lock_init(&gctrl->lock);
|
||||
|
||||
ret = bgpio_init(&gctrl->chip, dev, gctrl->bank->nr_pins / 8,
|
||||
gctrl->membase + GPIO_IN,
|
||||
gctrl->membase + GPIO_OUTSET,
|
||||
gctrl->membase + GPIO_OUTCLR,
|
||||
gctrl->membase + GPIO_DIR,
|
||||
NULL, 0);
|
||||
config = (typeof(config)){
|
||||
.dev = dev,
|
||||
.sz = gctrl->bank->nr_pins / 8,
|
||||
.dat = gctrl->membase + GPIO_IN,
|
||||
.set = gctrl->membase + GPIO_OUTSET,
|
||||
.clr = gctrl->membase + GPIO_OUTCLR,
|
||||
.dirout = gctrl->membase + GPIO_DIR,
|
||||
};
|
||||
|
||||
ret = gpio_generic_chip_init(&gctrl->chip, &config);
|
||||
if (ret) {
|
||||
dev_err(dev, "unable to init generic GPIO\n");
|
||||
return ret;
|
||||
|
|
@ -254,7 +260,7 @@ static int gpiolib_reg(struct eqbr_pinctrl_drv_data *drvdata)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_gpiochip_add_data(dev, &gctrl->chip, gctrl);
|
||||
ret = devm_gpiochip_add_data(dev, &gctrl->chip.gc, gctrl);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -499,7 +505,7 @@ static int eqbr_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
|||
bank->pin_base, pin);
|
||||
return -ENODEV;
|
||||
}
|
||||
gc = &gctrl->chip;
|
||||
gc = &gctrl->chip.gc;
|
||||
gc->direction_output(gc, offset, 0);
|
||||
continue;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ struct fwnode_handle;
|
|||
* @lock: spin lock to protect gpio register write.
|
||||
*/
|
||||
struct eqbr_gpio_ctrl {
|
||||
struct gpio_chip chip;
|
||||
struct gpio_generic_chip chip;
|
||||
struct fwnode_handle *fwnode;
|
||||
struct eqbr_pin_bank *bank;
|
||||
void __iomem *membase;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <linux/bits.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/gpio/generic.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
|
@ -45,7 +46,7 @@ struct stm32_hdp {
|
|||
void __iomem *base;
|
||||
struct clk *clk;
|
||||
struct pinctrl_dev *pctl_dev;
|
||||
struct gpio_chip gpio_chip;
|
||||
struct gpio_generic_chip gpio_chip;
|
||||
u32 mux_conf;
|
||||
u32 gposet_conf;
|
||||
const char * const *func_name;
|
||||
|
|
@ -603,6 +604,7 @@ MODULE_DEVICE_TABLE(of, stm32_hdp_of_match);
|
|||
|
||||
static int stm32_hdp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct gpio_generic_chip_config config;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct stm32_hdp *hdp;
|
||||
u8 version;
|
||||
|
|
@ -635,21 +637,25 @@ static int stm32_hdp_probe(struct platform_device *pdev)
|
|||
if (err)
|
||||
return dev_err_probe(dev, err, "Failed to enable pinctrl\n");
|
||||
|
||||
hdp->gpio_chip.get_direction = stm32_hdp_gpio_get_direction;
|
||||
hdp->gpio_chip.ngpio = ARRAY_SIZE(stm32_hdp_pins);
|
||||
hdp->gpio_chip.can_sleep = true;
|
||||
hdp->gpio_chip.names = stm32_hdp_pins_group;
|
||||
hdp->gpio_chip.gc.get_direction = stm32_hdp_gpio_get_direction;
|
||||
hdp->gpio_chip.gc.ngpio = ARRAY_SIZE(stm32_hdp_pins);
|
||||
hdp->gpio_chip.gc.can_sleep = true;
|
||||
hdp->gpio_chip.gc.names = stm32_hdp_pins_group;
|
||||
|
||||
err = bgpio_init(&hdp->gpio_chip, dev, 4,
|
||||
hdp->base + HDP_GPOVAL,
|
||||
hdp->base + HDP_GPOSET,
|
||||
hdp->base + HDP_GPOCLR,
|
||||
NULL, NULL, BGPIOF_NO_INPUT);
|
||||
config = (typeof(config)){
|
||||
.dev = dev,
|
||||
.sz = 4,
|
||||
.dat = hdp->base + HDP_GPOVAL,
|
||||
.set = hdp->base + HDP_GPOSET,
|
||||
.clr = hdp->base + HDP_GPOCLR,
|
||||
.flags = BGPIOF_NO_INPUT,
|
||||
};
|
||||
|
||||
err = gpio_generic_chip_init(&hdp->gpio_chip, &config);
|
||||
if (err)
|
||||
return dev_err_probe(dev, err, "Failed to init bgpio\n");
|
||||
return dev_err_probe(dev, err, "Failed to init the generic GPIO chip\n");
|
||||
|
||||
|
||||
err = devm_gpiochip_add_data(dev, &hdp->gpio_chip, hdp);
|
||||
err = devm_gpiochip_add_data(dev, &hdp->gpio_chip.gc, hdp);
|
||||
if (err)
|
||||
return dev_err_probe(dev, err, "Failed to add gpiochip\n");
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user