mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 02:53:36 +02:00
gpio: mpc8xxx: use new generic GPIO chip API
Convert the driver to using the new generic GPIO chip interfaces from linux/gpio/generic.h. Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Link: https://lore.kernel.org/r/20250825-gpio-mmio-gpio-conv-v1-13-356b4b1d5110@linaro.org Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
This commit is contained in:
parent
67e4be48f4
commit
90ab705035
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/acpi.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/gpio/generic.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
|
|
@ -34,7 +35,7 @@
|
|||
#define GPIO_IBE 0x18
|
||||
|
||||
struct mpc8xxx_gpio_chip {
|
||||
struct gpio_chip gc;
|
||||
struct gpio_generic_chip chip;
|
||||
void __iomem *regs;
|
||||
raw_spinlock_t lock;
|
||||
|
||||
|
|
@ -66,8 +67,10 @@ static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio)
|
|||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = gpiochip_get_data(gc);
|
||||
u32 out_mask, out_shadow;
|
||||
|
||||
out_mask = gc->read_reg(mpc8xxx_gc->regs + GPIO_DIR);
|
||||
val = gc->read_reg(mpc8xxx_gc->regs + GPIO_DAT) & ~out_mask;
|
||||
out_mask = gpio_generic_read_reg(&mpc8xxx_gc->chip,
|
||||
mpc8xxx_gc->regs + GPIO_DIR);
|
||||
val = gpio_generic_read_reg(&mpc8xxx_gc->chip,
|
||||
mpc8xxx_gc->regs + GPIO_DAT) & ~out_mask;
|
||||
out_shadow = gc->bgpio_data & out_mask;
|
||||
|
||||
return !!((val | out_shadow) & mpc_pin2mask(gpio));
|
||||
|
|
@ -108,12 +111,13 @@ static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
|
|||
static irqreturn_t mpc8xxx_gpio_irq_cascade(int irq, void *data)
|
||||
{
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = data;
|
||||
struct gpio_chip *gc = &mpc8xxx_gc->gc;
|
||||
unsigned long mask;
|
||||
int i;
|
||||
|
||||
mask = gc->read_reg(mpc8xxx_gc->regs + GPIO_IER)
|
||||
& gc->read_reg(mpc8xxx_gc->regs + GPIO_IMR);
|
||||
mask = gpio_generic_read_reg(&mpc8xxx_gc->chip,
|
||||
mpc8xxx_gc->regs + GPIO_IER) &
|
||||
gpio_generic_read_reg(&mpc8xxx_gc->chip,
|
||||
mpc8xxx_gc->regs + GPIO_IMR);
|
||||
for_each_set_bit(i, &mask, 32)
|
||||
generic_handle_domain_irq(mpc8xxx_gc->irq, 31 - i);
|
||||
|
||||
|
|
@ -124,15 +128,17 @@ static void mpc8xxx_irq_unmask(struct irq_data *d)
|
|||
{
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
|
||||
irq_hw_number_t hwirq = irqd_to_hwirq(d);
|
||||
struct gpio_chip *gc = &mpc8xxx_gc->gc;
|
||||
struct gpio_chip *gc = &mpc8xxx_gc->chip.gc;
|
||||
unsigned long flags;
|
||||
|
||||
gpiochip_enable_irq(gc, hwirq);
|
||||
|
||||
raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
||||
|
||||
gc->write_reg(mpc8xxx_gc->regs + GPIO_IMR,
|
||||
gc->read_reg(mpc8xxx_gc->regs + GPIO_IMR)
|
||||
gpio_generic_write_reg(&mpc8xxx_gc->chip,
|
||||
mpc8xxx_gc->regs + GPIO_IMR,
|
||||
gpio_generic_read_reg(&mpc8xxx_gc->chip,
|
||||
mpc8xxx_gc->regs + GPIO_IMR)
|
||||
| mpc_pin2mask(irqd_to_hwirq(d)));
|
||||
|
||||
raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||
|
|
@ -142,13 +148,14 @@ static void mpc8xxx_irq_mask(struct irq_data *d)
|
|||
{
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
|
||||
irq_hw_number_t hwirq = irqd_to_hwirq(d);
|
||||
struct gpio_chip *gc = &mpc8xxx_gc->gc;
|
||||
struct gpio_chip *gc = &mpc8xxx_gc->chip.gc;
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
||||
|
||||
gc->write_reg(mpc8xxx_gc->regs + GPIO_IMR,
|
||||
gc->read_reg(mpc8xxx_gc->regs + GPIO_IMR)
|
||||
gpio_generic_write_reg(&mpc8xxx_gc->chip, mpc8xxx_gc->regs + GPIO_IMR,
|
||||
gpio_generic_read_reg(&mpc8xxx_gc->chip,
|
||||
mpc8xxx_gc->regs + GPIO_IMR)
|
||||
& ~mpc_pin2mask(irqd_to_hwirq(d)));
|
||||
|
||||
raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||
|
|
@ -159,32 +166,34 @@ static void mpc8xxx_irq_mask(struct irq_data *d)
|
|||
static void mpc8xxx_irq_ack(struct irq_data *d)
|
||||
{
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_chip *gc = &mpc8xxx_gc->gc;
|
||||
|
||||
gc->write_reg(mpc8xxx_gc->regs + GPIO_IER,
|
||||
gpio_generic_write_reg(&mpc8xxx_gc->chip, mpc8xxx_gc->regs + GPIO_IER,
|
||||
mpc_pin2mask(irqd_to_hwirq(d)));
|
||||
}
|
||||
|
||||
static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
||||
{
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_chip *gc = &mpc8xxx_gc->gc;
|
||||
unsigned long flags;
|
||||
|
||||
switch (flow_type) {
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
||||
gc->write_reg(mpc8xxx_gc->regs + GPIO_ICR,
|
||||
gc->read_reg(mpc8xxx_gc->regs + GPIO_ICR)
|
||||
gpio_generic_write_reg(&mpc8xxx_gc->chip,
|
||||
mpc8xxx_gc->regs + GPIO_ICR,
|
||||
gpio_generic_read_reg(&mpc8xxx_gc->chip,
|
||||
mpc8xxx_gc->regs + GPIO_ICR)
|
||||
| mpc_pin2mask(irqd_to_hwirq(d)));
|
||||
raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
||||
gc->write_reg(mpc8xxx_gc->regs + GPIO_ICR,
|
||||
gc->read_reg(mpc8xxx_gc->regs + GPIO_ICR)
|
||||
gpio_generic_write_reg(&mpc8xxx_gc->chip,
|
||||
mpc8xxx_gc->regs + GPIO_ICR,
|
||||
gpio_generic_read_reg(&mpc8xxx_gc->chip,
|
||||
mpc8xxx_gc->regs + GPIO_ICR)
|
||||
& ~mpc_pin2mask(irqd_to_hwirq(d)));
|
||||
raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||
break;
|
||||
|
|
@ -199,7 +208,6 @@ static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
|||
static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
||||
{
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_chip *gc = &mpc8xxx_gc->gc;
|
||||
unsigned long gpio = irqd_to_hwirq(d);
|
||||
void __iomem *reg;
|
||||
unsigned int shift;
|
||||
|
|
@ -217,7 +225,9 @@ static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
|||
case IRQ_TYPE_EDGE_FALLING:
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
||||
gc->write_reg(reg, (gc->read_reg(reg) & ~(3 << shift))
|
||||
gpio_generic_write_reg(&mpc8xxx_gc->chip, reg,
|
||||
(gpio_generic_read_reg(&mpc8xxx_gc->chip,
|
||||
reg) & ~(3 << shift))
|
||||
| (2 << shift));
|
||||
raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||
break;
|
||||
|
|
@ -225,14 +235,18 @@ static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
|||
case IRQ_TYPE_EDGE_RISING:
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
||||
gc->write_reg(reg, (gc->read_reg(reg) & ~(3 << shift))
|
||||
gpio_generic_write_reg(&mpc8xxx_gc->chip, reg,
|
||||
(gpio_generic_read_reg(&mpc8xxx_gc->chip,
|
||||
reg) & ~(3 << shift))
|
||||
| (1 << shift));
|
||||
raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
||||
gc->write_reg(reg, (gc->read_reg(reg) & ~(3 << shift)));
|
||||
gpio_generic_write_reg(&mpc8xxx_gc->chip, reg,
|
||||
(gpio_generic_read_reg(&mpc8xxx_gc->chip,
|
||||
reg) & ~(3 << shift)));
|
||||
raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||
break;
|
||||
|
||||
|
|
@ -309,6 +323,7 @@ static const struct of_device_id mpc8xxx_gpio_ids[] = {
|
|||
static int mpc8xxx_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct mpc8xxx_gpio_devtype *devtype = NULL;
|
||||
struct gpio_generic_chip_config config;
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct fwnode_handle *fwnode;
|
||||
|
|
@ -327,26 +342,28 @@ static int mpc8xxx_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(mpc8xxx_gc->regs))
|
||||
return PTR_ERR(mpc8xxx_gc->regs);
|
||||
|
||||
gc = &mpc8xxx_gc->gc;
|
||||
gc = &mpc8xxx_gc->chip.gc;
|
||||
gc->parent = dev;
|
||||
|
||||
config = (typeof(config)){
|
||||
.dev = dev,
|
||||
.sz = 4,
|
||||
.dat = mpc8xxx_gc->regs + GPIO_DAT,
|
||||
.dirout = mpc8xxx_gc->regs + GPIO_DIR,
|
||||
.flags = BGPIOF_BIG_ENDIAN
|
||||
};
|
||||
|
||||
if (device_property_read_bool(dev, "little-endian")) {
|
||||
ret = bgpio_init(gc, dev, 4, mpc8xxx_gc->regs + GPIO_DAT,
|
||||
NULL, NULL, mpc8xxx_gc->regs + GPIO_DIR,
|
||||
NULL, BGPIOF_BIG_ENDIAN);
|
||||
if (ret)
|
||||
return ret;
|
||||
dev_dbg(dev, "GPIO registers are LITTLE endian\n");
|
||||
} else {
|
||||
ret = bgpio_init(gc, dev, 4, mpc8xxx_gc->regs + GPIO_DAT,
|
||||
NULL, NULL, mpc8xxx_gc->regs + GPIO_DIR,
|
||||
NULL, BGPIOF_BIG_ENDIAN
|
||||
| BGPIOF_BIG_ENDIAN_BYTE_ORDER);
|
||||
if (ret)
|
||||
return ret;
|
||||
config.flags |= BGPIOF_BIG_ENDIAN_BYTE_ORDER;
|
||||
dev_dbg(dev, "GPIO registers are BIG endian\n");
|
||||
}
|
||||
|
||||
ret = gpio_generic_chip_init(&mpc8xxx_gc->chip, &config);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mpc8xxx_gc->direction_output = gc->direction_output;
|
||||
|
||||
devtype = device_get_match_data(dev);
|
||||
|
|
@ -379,10 +396,13 @@ static int mpc8xxx_probe(struct platform_device *pdev)
|
|||
device_is_compatible(dev, "fsl,ls1028a-gpio") ||
|
||||
device_is_compatible(dev, "fsl,ls1088a-gpio") ||
|
||||
is_acpi_node(fwnode)) {
|
||||
gc->write_reg(mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff);
|
||||
gpio_generic_write_reg(&mpc8xxx_gc->chip,
|
||||
mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff);
|
||||
/* Also, latch state of GPIOs configured as output by bootloader. */
|
||||
gc->bgpio_data = gc->read_reg(mpc8xxx_gc->regs + GPIO_DAT) &
|
||||
gc->read_reg(mpc8xxx_gc->regs + GPIO_DIR);
|
||||
gc->bgpio_data = gpio_generic_read_reg(&mpc8xxx_gc->chip,
|
||||
mpc8xxx_gc->regs + GPIO_DAT) &
|
||||
gpio_generic_read_reg(&mpc8xxx_gc->chip,
|
||||
mpc8xxx_gc->regs + GPIO_DIR);
|
||||
}
|
||||
|
||||
ret = devm_gpiochip_add_data(dev, gc, mpc8xxx_gc);
|
||||
|
|
@ -405,8 +425,10 @@ static int mpc8xxx_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
/* ack and mask all irqs */
|
||||
gc->write_reg(mpc8xxx_gc->regs + GPIO_IER, 0xffffffff);
|
||||
gc->write_reg(mpc8xxx_gc->regs + GPIO_IMR, 0);
|
||||
gpio_generic_write_reg(&mpc8xxx_gc->chip,
|
||||
mpc8xxx_gc->regs + GPIO_IER, 0xffffffff);
|
||||
gpio_generic_write_reg(&mpc8xxx_gc->chip,
|
||||
mpc8xxx_gc->regs + GPIO_IMR, 0);
|
||||
|
||||
ret = devm_request_irq(dev, mpc8xxx_gc->irqn,
|
||||
mpc8xxx_gpio_irq_cascade,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user