summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpio-dwapb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpio-dwapb.c')
-rw-r--r--drivers/gpio/gpio-dwapb.c311
1 files changed, 170 insertions, 141 deletions
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 3eb13d6d31ef..4986c465c9a8 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -8,6 +8,7 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/generic.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -15,15 +16,12 @@
#include <linux/irq.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_data/gpio-dwapb.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/reset.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
-#include "gpiolib.h"
#include "gpiolib-acpi.h"
#define GPIO_SWPORTA_DR 0x00
@@ -48,12 +46,15 @@
#define DWAPB_DRIVER_NAME "gpio-dwapb"
#define DWAPB_MAX_PORTS 4
+#define DWAPB_MAX_GPIOS 32
#define GPIO_EXT_PORT_STRIDE 0x04 /* register stride 32 bits */
#define GPIO_SWPORT_DR_STRIDE 0x0c /* register stride 3*32 bits */
#define GPIO_SWPORT_DDR_STRIDE 0x0c /* register stride 3*32 bits */
+#define GPIO_REG_OFFSET_V1 0
#define GPIO_REG_OFFSET_V2 1
+#define GPIO_REG_OFFSET_MASK BIT(0)
#define GPIO_INTMASK_V2 0x44
#define GPIO_INTTYPE_LEVEL_V2 0x34
@@ -65,7 +66,19 @@
struct dwapb_gpio;
-#ifdef CONFIG_PM_SLEEP
+struct dwapb_port_property {
+ struct fwnode_handle *fwnode;
+ unsigned int idx;
+ unsigned int ngpio;
+ unsigned int gpio_base;
+ int irq[DWAPB_MAX_GPIOS];
+};
+
+struct dwapb_platform_data {
+ struct dwapb_port_property *properties;
+ unsigned int nports;
+};
+
/* Store GPIO context across system-wide suspend/resume transitions */
struct dwapb_context {
u32 data;
@@ -78,25 +91,25 @@ struct dwapb_context {
u32 int_deb;
u32 wake_en;
};
-#endif
struct dwapb_gpio_port_irqchip {
- struct irq_chip irqchip;
unsigned int nr_irqs;
unsigned int irq[DWAPB_MAX_GPIOS];
};
struct dwapb_gpio_port {
- struct gpio_chip gc;
+ struct gpio_generic_chip chip;
struct dwapb_gpio_port_irqchip *pirq;
struct dwapb_gpio *gpio;
-#ifdef CONFIG_PM_SLEEP
struct dwapb_context *ctx;
-#endif
unsigned int idx;
};
-#define to_dwapb_gpio(_gc) \
- (container_of(_gc, struct dwapb_gpio_port, gc)->gpio)
+
+static inline struct dwapb_gpio *to_dwapb_gpio(struct gpio_chip *gc)
+{
+ return container_of(to_gpio_generic_chip(gc),
+ struct dwapb_gpio_port, chip)->gpio;
+}
struct dwapb_gpio {
struct device *dev;
@@ -128,7 +141,7 @@ static inline u32 gpio_reg_v2_convert(unsigned int offset)
static inline u32 gpio_reg_convert(struct dwapb_gpio *gpio, unsigned int offset)
{
- if (gpio->flags & GPIO_REG_OFFSET_V2)
+ if ((gpio->flags & GPIO_REG_OFFSET_MASK) == GPIO_REG_OFFSET_V2)
return gpio_reg_v2_convert(offset);
return offset;
@@ -136,19 +149,19 @@ static inline u32 gpio_reg_convert(struct dwapb_gpio *gpio, unsigned int offset)
static inline u32 dwapb_read(struct dwapb_gpio *gpio, unsigned int offset)
{
- struct gpio_chip *gc = &gpio->ports[0].gc;
- void __iomem *reg_base = gpio->regs;
+ struct gpio_generic_chip *chip = &gpio->ports[0].chip;
+ void __iomem *reg_base = gpio->regs;
- return gc->read_reg(reg_base + gpio_reg_convert(gpio, offset));
+ return gpio_generic_read_reg(chip, reg_base + gpio_reg_convert(gpio, offset));
}
static inline void dwapb_write(struct dwapb_gpio *gpio, unsigned int offset,
u32 val)
{
- struct gpio_chip *gc = &gpio->ports[0].gc;
- void __iomem *reg_base = gpio->regs;
+ struct gpio_generic_chip *chip = &gpio->ports[0].chip;
+ void __iomem *reg_base = gpio->regs;
- gc->write_reg(reg_base + gpio_reg_convert(gpio, offset), val);
+ gpio_generic_write_reg(chip, reg_base + gpio_reg_convert(gpio, offset), val);
}
static struct dwapb_gpio_port *dwapb_offs_to_port(struct dwapb_gpio *gpio, unsigned int offs)
@@ -174,7 +187,7 @@ static void dwapb_toggle_trigger(struct dwapb_gpio *gpio, unsigned int offs)
if (!port)
return;
- gc = &port->gc;
+ gc = &port->chip.gc;
pol = dwapb_read(gpio, GPIO_INT_POLARITY);
/* Just read the current value right out of the data register */
@@ -189,13 +202,13 @@ static void dwapb_toggle_trigger(struct dwapb_gpio *gpio, unsigned int offs)
static u32 dwapb_do_irq(struct dwapb_gpio *gpio)
{
- struct gpio_chip *gc = &gpio->ports[0].gc;
+ struct gpio_generic_chip *gen_gc = &gpio->ports[0].chip;
unsigned long irq_status;
irq_hw_number_t hwirq;
irq_status = dwapb_read(gpio, GPIO_INTSTATUS);
for_each_set_bit(hwirq, &irq_status, DWAPB_MAX_GPIOS) {
- int gpio_irq = irq_find_mapping(gc->irq.domain, hwirq);
+ int gpio_irq = irq_find_mapping(gen_gc->gc.irq.domain, hwirq);
u32 irq_type = irq_get_trigger_type(gpio_irq);
generic_handle_irq(gpio_irq);
@@ -225,77 +238,89 @@ static irqreturn_t dwapb_irq_handler_mfd(int irq, void *dev_id)
static void dwapb_irq_ack(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(gc);
struct dwapb_gpio *gpio = to_dwapb_gpio(gc);
u32 val = BIT(irqd_to_hwirq(d));
- unsigned long flags;
- spin_lock_irqsave(&gc->bgpio_lock, flags);
+ guard(gpio_generic_lock_irqsave)(gen_gc);
+
dwapb_write(gpio, GPIO_PORTA_EOI, val);
- spin_unlock_irqrestore(&gc->bgpio_lock, flags);
}
static void dwapb_irq_mask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(gc);
struct dwapb_gpio *gpio = to_dwapb_gpio(gc);
- unsigned long flags;
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
u32 val;
- spin_lock_irqsave(&gc->bgpio_lock, flags);
- val = dwapb_read(gpio, GPIO_INTMASK) | BIT(irqd_to_hwirq(d));
- dwapb_write(gpio, GPIO_INTMASK, val);
- spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+ scoped_guard(gpio_generic_lock_irqsave, gen_gc) {
+ val = dwapb_read(gpio, GPIO_INTMASK) | BIT(hwirq);
+ dwapb_write(gpio, GPIO_INTMASK, val);
+ }
+
+ gpiochip_disable_irq(gc, hwirq);
}
static void dwapb_irq_unmask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(gc);
struct dwapb_gpio *gpio = to_dwapb_gpio(gc);
- unsigned long flags;
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
u32 val;
- spin_lock_irqsave(&gc->bgpio_lock, flags);
- val = dwapb_read(gpio, GPIO_INTMASK) & ~BIT(irqd_to_hwirq(d));
+ gpiochip_enable_irq(gc, hwirq);
+
+ guard(gpio_generic_lock_irqsave)(gen_gc);
+
+ val = dwapb_read(gpio, GPIO_INTMASK) & ~BIT(hwirq);
dwapb_write(gpio, GPIO_INTMASK, val);
- spin_unlock_irqrestore(&gc->bgpio_lock, flags);
}
static void dwapb_irq_enable(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(gc);
struct dwapb_gpio *gpio = to_dwapb_gpio(gc);
- unsigned long flags;
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
u32 val;
- spin_lock_irqsave(&gc->bgpio_lock, flags);
- val = dwapb_read(gpio, GPIO_INTEN);
- val |= BIT(irqd_to_hwirq(d));
+ guard(gpio_generic_lock_irqsave)(gen_gc);
+
+ val = dwapb_read(gpio, GPIO_INTEN) | BIT(hwirq);
dwapb_write(gpio, GPIO_INTEN, val);
- spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+ val = dwapb_read(gpio, GPIO_INTMASK) & ~BIT(hwirq);
+ dwapb_write(gpio, GPIO_INTMASK, val);
}
static void dwapb_irq_disable(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(gc);
struct dwapb_gpio *gpio = to_dwapb_gpio(gc);
- unsigned long flags;
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
u32 val;
- spin_lock_irqsave(&gc->bgpio_lock, flags);
- val = dwapb_read(gpio, GPIO_INTEN);
- val &= ~BIT(irqd_to_hwirq(d));
+ guard(gpio_generic_lock_irqsave)(gen_gc);
+
+ val = dwapb_read(gpio, GPIO_INTMASK) | BIT(hwirq);
+ dwapb_write(gpio, GPIO_INTMASK, val);
+ val = dwapb_read(gpio, GPIO_INTEN) & ~BIT(hwirq);
dwapb_write(gpio, GPIO_INTEN, val);
- spin_unlock_irqrestore(&gc->bgpio_lock, flags);
}
static int dwapb_irq_set_type(struct irq_data *d, u32 type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(gc);
struct dwapb_gpio *gpio = to_dwapb_gpio(gc);
irq_hw_number_t bit = irqd_to_hwirq(d);
- unsigned long level, polarity, flags;
+ unsigned long level, polarity;
+
+ guard(gpio_generic_lock_irqsave)(gen_gc);
- spin_lock_irqsave(&gc->bgpio_lock, flags);
level = dwapb_read(gpio, GPIO_INTTYPE_LEVEL);
polarity = dwapb_read(gpio, GPIO_INT_POLARITY);
@@ -330,12 +355,10 @@ static int dwapb_irq_set_type(struct irq_data *d, u32 type)
dwapb_write(gpio, GPIO_INTTYPE_LEVEL, level);
if (type != IRQ_TYPE_EDGE_BOTH)
dwapb_write(gpio, GPIO_INT_POLARITY, polarity);
- spin_unlock_irqrestore(&gc->bgpio_lock, flags);
return 0;
}
-#ifdef CONFIG_PM_SLEEP
static int dwapb_irq_set_wake(struct irq_data *d, unsigned int enable)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
@@ -350,17 +373,30 @@ static int dwapb_irq_set_wake(struct irq_data *d, unsigned int enable)
return 0;
}
-#endif
+
+static const struct irq_chip dwapb_irq_chip = {
+ .name = DWAPB_DRIVER_NAME,
+ .irq_ack = dwapb_irq_ack,
+ .irq_mask = dwapb_irq_mask,
+ .irq_unmask = dwapb_irq_unmask,
+ .irq_set_type = dwapb_irq_set_type,
+ .irq_enable = dwapb_irq_enable,
+ .irq_disable = dwapb_irq_disable,
+ .irq_set_wake = pm_sleep_ptr(dwapb_irq_set_wake),
+ .flags = IRQCHIP_IMMUTABLE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
static int dwapb_gpio_set_debounce(struct gpio_chip *gc,
unsigned offset, unsigned debounce)
{
struct dwapb_gpio_port *port = gpiochip_get_data(gc);
+ struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(gc);
struct dwapb_gpio *gpio = port->gpio;
- unsigned long flags, val_deb;
+ unsigned long val_deb;
unsigned long mask = BIT(offset);
- spin_lock_irqsave(&gc->bgpio_lock, flags);
+ guard(gpio_generic_lock_irqsave)(gen_gc);
val_deb = dwapb_read(gpio, GPIO_PORTA_DEBOUNCE);
if (debounce)
@@ -369,8 +405,6 @@ static int dwapb_gpio_set_debounce(struct gpio_chip *gc,
val_deb &= ~mask;
dwapb_write(gpio, GPIO_PORTA_DEBOUNCE, val_deb);
- spin_unlock_irqrestore(&gc->bgpio_lock, flags);
-
return 0;
}
@@ -379,11 +413,12 @@ static int dwapb_gpio_set_config(struct gpio_chip *gc, unsigned offset,
{
u32 debounce;
- if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
- return -ENOTSUPP;
+ if (pinconf_to_config_param(config) == PIN_CONFIG_INPUT_DEBOUNCE) {
+ debounce = pinconf_to_config_argument(config);
+ return dwapb_gpio_set_debounce(gc, offset, debounce);
+ }
- debounce = pinconf_to_config_argument(config);
- return dwapb_gpio_set_debounce(gc, offset, debounce);
+ return gpiochip_generic_config(gc, offset, config);
}
static int dwapb_convert_irqs(struct dwapb_gpio_port_irqchip *pirq,
@@ -407,7 +442,7 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
struct dwapb_port_property *pp)
{
struct dwapb_gpio_port_irqchip *pirq;
- struct gpio_chip *gc = &port->gc;
+ struct gpio_chip *gc = &port->chip.gc;
struct gpio_irq_chip *girq;
int err;
@@ -425,32 +460,18 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
girq->default_type = IRQ_TYPE_NONE;
port->pirq = pirq;
- pirq->irqchip.name = DWAPB_DRIVER_NAME;
- pirq->irqchip.irq_ack = dwapb_irq_ack;
- pirq->irqchip.irq_mask = dwapb_irq_mask;
- pirq->irqchip.irq_unmask = dwapb_irq_unmask;
- pirq->irqchip.irq_set_type = dwapb_irq_set_type;
- pirq->irqchip.irq_enable = dwapb_irq_enable;
- pirq->irqchip.irq_disable = dwapb_irq_disable;
-#ifdef CONFIG_PM_SLEEP
- pirq->irqchip.irq_set_wake = dwapb_irq_set_wake;
-#endif
- if (!pp->irq_shared) {
- girq->num_parents = pirq->nr_irqs;
- girq->parents = pirq->irq;
- girq->parent_handler_data = gpio;
- girq->parent_handler = dwapb_irq_handler;
- } else {
- /* This will let us handle the parent IRQ in the driver */
+ /*
+ * Intel ACPI-based platforms mostly have the DesignWare APB GPIO
+ * IRQ lane shared between several devices. In that case the parental
+ * IRQ has to be handled in the shared way so to be properly delivered
+ * to all the connected devices.
+ */
+ if (has_acpi_companion(gpio->dev)) {
girq->num_parents = 0;
girq->parents = NULL;
girq->parent_handler = NULL;
- /*
- * Request a shared IRQ since where MFD would have devices
- * using the same irq pin
- */
err = devm_request_irq(gpio->dev, pp->irq[0],
dwapb_irq_handler_mfd,
IRQF_SHARED, DWAPB_DRIVER_NAME, gpio);
@@ -458,9 +479,14 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
dev_err(gpio->dev, "error requesting IRQ\n");
goto err_kfree_pirq;
}
+ } else {
+ girq->num_parents = pirq->nr_irqs;
+ girq->parents = pirq->irq;
+ girq->parent_handler_data = gpio;
+ girq->parent_handler = dwapb_irq_handler;
}
- girq->chip = &pirq->irqchip;
+ gpio_irq_chip_set_chip(girq, &dwapb_irq_chip);
return;
@@ -472,6 +498,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
struct dwapb_port_property *pp,
unsigned int offs)
{
+ struct gpio_generic_chip_config config;
struct dwapb_gpio_port *port;
void __iomem *dat, *set, *dirout;
int err;
@@ -490,30 +517,39 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
set = gpio->regs + GPIO_SWPORTA_DR + pp->idx * GPIO_SWPORT_DR_STRIDE;
dirout = gpio->regs + GPIO_SWPORTA_DDR + pp->idx * GPIO_SWPORT_DDR_STRIDE;
+ config = (struct gpio_generic_chip_config) {
+ .dev = gpio->dev,
+ .sz = 4,
+ .dat = dat,
+ .set = set,
+ .dirout = dirout,
+ };
+
/* This registers 32 GPIO lines per port */
- err = bgpio_init(&port->gc, gpio->dev, 4, dat, set, NULL, dirout,
- NULL, 0);
+ err = gpio_generic_chip_init(&port->chip, &config);
if (err) {
dev_err(gpio->dev, "failed to init gpio chip for port%d\n",
port->idx);
return err;
}
-#ifdef CONFIG_OF_GPIO
- port->gc.of_node = to_of_node(pp->fwnode);
-#endif
- port->gc.ngpio = pp->ngpio;
- port->gc.base = pp->gpio_base;
+ port->chip.gc.fwnode = pp->fwnode;
+ port->chip.gc.ngpio = pp->ngpio;
+ port->chip.gc.base = pp->gpio_base;
+ port->chip.gc.request = gpiochip_generic_request;
+ port->chip.gc.free = gpiochip_generic_free;
/* Only port A support debounce */
if (pp->idx == 0)
- port->gc.set_config = dwapb_gpio_set_config;
+ port->chip.gc.set_config = dwapb_gpio_set_config;
+ else
+ port->chip.gc.set_config = gpiochip_generic_config;
/* Only port A can provide interrupts in all configurations of the IP */
if (pp->idx == 0)
dwapb_configure_irqs(gpio, port, pp);
- err = devm_gpiochip_add_data(gpio->dev, &port->gc, port);
+ err = devm_gpiochip_add_data(gpio->dev, &port->chip.gc, port);
if (err) {
dev_err(gpio->dev, "failed to register gpiochip for port%d\n",
port->idx);
@@ -540,7 +576,6 @@ static void dwapb_get_irq(struct device *dev, struct fwnode_handle *fwnode,
static struct dwapb_platform_data *dwapb_gpio_get_pdata(struct device *dev)
{
- struct fwnode_handle *fwnode;
struct dwapb_platform_data *pdata;
struct dwapb_port_property *pp;
int nports;
@@ -561,7 +596,7 @@ static struct dwapb_platform_data *dwapb_gpio_get_pdata(struct device *dev)
pdata->nports = nports;
i = 0;
- device_for_each_child_node(dev, fwnode) {
+ device_for_each_child_node_scoped(dev, fwnode) {
pp = &pdata->properties[i++];
pp->fwnode = fwnode;
@@ -569,7 +604,6 @@ static struct dwapb_platform_data *dwapb_gpio_get_pdata(struct device *dev)
pp->idx >= DWAPB_MAX_PORTS) {
dev_err(dev,
"missing/invalid port index for port%d\n", i);
- fwnode_handle_put(fwnode);
return ERR_PTR(-EINVAL);
}
@@ -581,9 +615,12 @@ static struct dwapb_platform_data *dwapb_gpio_get_pdata(struct device *dev)
pp->ngpio = DWAPB_MAX_GPIOS;
}
- pp->irq_shared = false;
pp->gpio_base = -1;
+ /* For internal use only, new platforms mustn't exercise this */
+ if (is_software_node(fwnode))
+ fwnode_property_read_u32(fwnode, "gpio-base", &pp->gpio_base);
+
/*
* Only port A can provide interrupts in all configurations of
* the IP.
@@ -636,10 +673,9 @@ static int dwapb_get_clks(struct dwapb_gpio *gpio)
gpio->clks[1].id = "db";
err = devm_clk_bulk_get_optional(gpio->dev, DWAPB_NR_CLOCKS,
gpio->clks);
- if (err) {
- dev_err(gpio->dev, "Cannot get APB/Debounce clocks\n");
- return err;
- }
+ if (err)
+ return dev_err_probe(gpio->dev, err,
+ "Cannot get APB/Debounce clocks\n");
err = clk_bulk_prepare_enable(DWAPB_NR_CLOCKS, gpio->clks);
if (err) {
@@ -651,16 +687,17 @@ static int dwapb_get_clks(struct dwapb_gpio *gpio)
}
static const struct of_device_id dwapb_of_match[] = {
- { .compatible = "snps,dw-apb-gpio", .data = (void *)0},
+ { .compatible = "snps,dw-apb-gpio", .data = (void *)GPIO_REG_OFFSET_V1},
{ .compatible = "apm,xgene-gpio-v2", .data = (void *)GPIO_REG_OFFSET_V2},
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, dwapb_of_match);
static const struct acpi_device_id dwapb_acpi_match[] = {
- {"HISI0181", 0},
- {"APMC0D07", 0},
+ {"HISI0181", GPIO_REG_OFFSET_V1},
+ {"APMC0D07", GPIO_REG_OFFSET_V1},
{"APMC0D81", GPIO_REG_OFFSET_V2},
+ {"FUJI200A", GPIO_REG_OFFSET_V1},
{ }
};
MODULE_DEVICE_TABLE(acpi, dwapb_acpi_match);
@@ -670,17 +707,12 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
unsigned int i;
struct dwapb_gpio *gpio;
int err;
+ struct dwapb_platform_data *pdata;
struct device *dev = &pdev->dev;
- struct dwapb_platform_data *pdata = dev_get_platdata(dev);
- if (!pdata) {
- pdata = dwapb_gpio_get_pdata(dev);
- if (IS_ERR(pdata))
- return PTR_ERR(pdata);
- }
-
- if (!pdata->nports)
- return -ENODEV;
+ pdata = dwapb_gpio_get_pdata(dev);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio)
@@ -719,42 +751,40 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM_SLEEP
static int dwapb_gpio_suspend(struct device *dev)
{
struct dwapb_gpio *gpio = dev_get_drvdata(dev);
- struct gpio_chip *gc = &gpio->ports[0].gc;
- unsigned long flags;
+ struct gpio_generic_chip *gen_gc = &gpio->ports[0].chip;
int i;
- spin_lock_irqsave(&gc->bgpio_lock, flags);
- for (i = 0; i < gpio->nr_ports; i++) {
- unsigned int offset;
- unsigned int idx = gpio->ports[i].idx;
- struct dwapb_context *ctx = gpio->ports[i].ctx;
+ scoped_guard(gpio_generic_lock_irqsave, gen_gc) {
+ for (i = 0; i < gpio->nr_ports; i++) {
+ unsigned int offset;
+ unsigned int idx = gpio->ports[i].idx;
+ struct dwapb_context *ctx = gpio->ports[i].ctx;
- offset = GPIO_SWPORTA_DDR + idx * GPIO_SWPORT_DDR_STRIDE;
- ctx->dir = dwapb_read(gpio, offset);
+ offset = GPIO_SWPORTA_DDR + idx * GPIO_SWPORT_DDR_STRIDE;
+ ctx->dir = dwapb_read(gpio, offset);
- offset = GPIO_SWPORTA_DR + idx * GPIO_SWPORT_DR_STRIDE;
- ctx->data = dwapb_read(gpio, offset);
+ offset = GPIO_SWPORTA_DR + idx * GPIO_SWPORT_DR_STRIDE;
+ ctx->data = dwapb_read(gpio, offset);
- offset = GPIO_EXT_PORTA + idx * GPIO_EXT_PORT_STRIDE;
- ctx->ext = dwapb_read(gpio, offset);
+ offset = GPIO_EXT_PORTA + idx * GPIO_EXT_PORT_STRIDE;
+ ctx->ext = dwapb_read(gpio, offset);
- /* Only port A can provide interrupts */
- if (idx == 0) {
- ctx->int_mask = dwapb_read(gpio, GPIO_INTMASK);
- ctx->int_en = dwapb_read(gpio, GPIO_INTEN);
- ctx->int_pol = dwapb_read(gpio, GPIO_INT_POLARITY);
- ctx->int_type = dwapb_read(gpio, GPIO_INTTYPE_LEVEL);
- ctx->int_deb = dwapb_read(gpio, GPIO_PORTA_DEBOUNCE);
-
- /* Mask out interrupts */
- dwapb_write(gpio, GPIO_INTMASK, ~ctx->wake_en);
+ /* Only port A can provide interrupts */
+ if (idx == 0) {
+ ctx->int_mask = dwapb_read(gpio, GPIO_INTMASK);
+ ctx->int_en = dwapb_read(gpio, GPIO_INTEN);
+ ctx->int_pol = dwapb_read(gpio, GPIO_INT_POLARITY);
+ ctx->int_type = dwapb_read(gpio, GPIO_INTTYPE_LEVEL);
+ ctx->int_deb = dwapb_read(gpio, GPIO_PORTA_DEBOUNCE);
+
+ /* Mask out interrupts */
+ dwapb_write(gpio, GPIO_INTMASK, ~ctx->wake_en);
+ }
}
}
- spin_unlock_irqrestore(&gc->bgpio_lock, flags);
clk_bulk_disable_unprepare(DWAPB_NR_CLOCKS, gpio->clks);
@@ -764,8 +794,8 @@ static int dwapb_gpio_suspend(struct device *dev)
static int dwapb_gpio_resume(struct device *dev)
{
struct dwapb_gpio *gpio = dev_get_drvdata(dev);
- struct gpio_chip *gc = &gpio->ports[0].gc;
- unsigned long flags;
+ struct gpio_chip *gc = &gpio->ports[0].chip.gc;
+ struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(gc);
int i, err;
err = clk_bulk_prepare_enable(DWAPB_NR_CLOCKS, gpio->clks);
@@ -774,7 +804,8 @@ static int dwapb_gpio_resume(struct device *dev)
return err;
}
- spin_lock_irqsave(&gc->bgpio_lock, flags);
+ guard(gpio_generic_lock_irqsave)(gen_gc);
+
for (i = 0; i < gpio->nr_ports; i++) {
unsigned int offset;
unsigned int idx = gpio->ports[i].idx;
@@ -801,19 +832,17 @@ static int dwapb_gpio_resume(struct device *dev)
dwapb_write(gpio, GPIO_PORTA_EOI, 0xffffffff);
}
}
- spin_unlock_irqrestore(&gc->bgpio_lock, flags);
return 0;
}
-#endif
-static SIMPLE_DEV_PM_OPS(dwapb_gpio_pm_ops, dwapb_gpio_suspend,
- dwapb_gpio_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(dwapb_gpio_pm_ops,
+ dwapb_gpio_suspend, dwapb_gpio_resume);
static struct platform_driver dwapb_gpio_driver = {
.driver = {
.name = DWAPB_DRIVER_NAME,
- .pm = &dwapb_gpio_pm_ops,
+ .pm = pm_sleep_ptr(&dwapb_gpio_pm_ops),
.of_match_table = dwapb_of_match,
.acpi_match_table = dwapb_acpi_match,
},