summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpio-xgene-sb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpio-xgene-sb.c')
-rw-r--r--drivers/gpio/gpio-xgene-sb.c122
1 files changed, 73 insertions, 49 deletions
diff --git a/drivers/gpio/gpio-xgene-sb.c b/drivers/gpio/gpio-xgene-sb.c
index a809609ee957..661259f026e1 100644
--- a/drivers/gpio/gpio-xgene-sb.c
+++ b/drivers/gpio/gpio-xgene-sb.c
@@ -8,21 +8,23 @@
* Quan Nguyen <qnguyen@apm.com>.
*/
-#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/err.h>
#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/types.h>
+
#include <linux/gpio/driver.h>
-#include <linux/acpi.h>
+#include <linux/gpio/generic.h>
-#include "gpiolib.h"
#include "gpiolib-acpi.h"
-/* Common property names */
-#define XGENE_NIRQ_PROPERTY "apm,nr-irqs"
-#define XGENE_NGPIO_PROPERTY "apm,nr-gpios"
-#define XGENE_IRQ_START_PROPERTY "apm,irq-start"
-
#define XGENE_DFLT_MAX_NGPIO 22
#define XGENE_DFLT_MAX_NIRQ 6
#define XGENE_DFLT_IRQ_START_PIN 8
@@ -39,7 +41,7 @@
/**
* struct xgene_gpio_sb - GPIO-Standby private data structure.
- * @gc: memory-mapped GPIO controllers.
+ * @chip: Generic GPIO chip data
* @regs: GPIO register base offset
* @irq_domain: GPIO interrupt domain
* @irq_start: GPIO pin that start support interrupt
@@ -47,7 +49,7 @@
* @parent_irq_base: Start parent HWIRQ
*/
struct xgene_gpio_sb {
- struct gpio_chip gc;
+ struct gpio_generic_chip chip;
void __iomem *regs;
struct irq_domain *irq_domain;
u16 irq_start;
@@ -61,14 +63,15 @@ struct xgene_gpio_sb {
static void xgene_gpio_set_bit(struct gpio_chip *gc,
void __iomem *reg, u32 gpio, int val)
{
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
u32 data;
- data = gc->read_reg(reg);
+ data = gpio_generic_read_reg(chip, reg);
if (val)
data |= GPIO_MASK(gpio);
else
data &= ~GPIO_MASK(gpio);
- gc->write_reg(reg, data);
+ gpio_generic_write_reg(chip, reg, data);
}
static int xgene_gpio_sb_irq_set_type(struct irq_data *d, unsigned int type)
@@ -90,9 +93,9 @@ static int xgene_gpio_sb_irq_set_type(struct irq_data *d, unsigned int type)
break;
}
- xgene_gpio_set_bit(&priv->gc, priv->regs + MPA_GPIO_SEL_LO,
+ xgene_gpio_set_bit(&priv->chip.gc, priv->regs + MPA_GPIO_SEL_LO,
gpio * 2, 1);
- xgene_gpio_set_bit(&priv->gc, priv->regs + MPA_GPIO_INT_LVL,
+ xgene_gpio_set_bit(&priv->chip.gc, priv->regs + MPA_GPIO_INT_LVL,
d->hwirq, lvl_type);
/* Propagate IRQ type setting to parent */
@@ -102,12 +105,32 @@ static int xgene_gpio_sb_irq_set_type(struct irq_data *d, unsigned int type)
return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
}
-static struct irq_chip xgene_gpio_sb_irq_chip = {
+static void xgene_gpio_sb_irq_mask(struct irq_data *d)
+{
+ struct xgene_gpio_sb *priv = irq_data_get_irq_chip_data(d);
+
+ irq_chip_mask_parent(d);
+
+ gpiochip_disable_irq(&priv->chip.gc, d->hwirq);
+}
+
+static void xgene_gpio_sb_irq_unmask(struct irq_data *d)
+{
+ struct xgene_gpio_sb *priv = irq_data_get_irq_chip_data(d);
+
+ gpiochip_enable_irq(&priv->chip.gc, d->hwirq);
+
+ irq_chip_unmask_parent(d);
+}
+
+static const struct irq_chip xgene_gpio_sb_irq_chip = {
.name = "sbgpio",
.irq_eoi = irq_chip_eoi_parent,
- .irq_mask = irq_chip_mask_parent,
- .irq_unmask = irq_chip_unmask_parent,
+ .irq_mask = xgene_gpio_sb_irq_mask,
+ .irq_unmask = xgene_gpio_sb_irq_unmask,
.irq_set_type = xgene_gpio_sb_irq_set_type,
+ .flags = IRQCHIP_IMMUTABLE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
};
static int xgene_gpio_sb_to_irq(struct gpio_chip *gc, u32 gpio)
@@ -134,15 +157,15 @@ static int xgene_gpio_sb_domain_activate(struct irq_domain *d,
u32 gpio = HWIRQ_TO_GPIO(priv, irq_data->hwirq);
int ret;
- ret = gpiochip_lock_as_irq(&priv->gc, gpio);
+ ret = gpiochip_lock_as_irq(&priv->chip.gc, gpio);
if (ret) {
- dev_err(priv->gc.parent,
+ dev_err(priv->chip.gc.parent,
"Unable to configure XGene GPIO standby pin %d as IRQ\n",
gpio);
return ret;
}
- xgene_gpio_set_bit(&priv->gc, priv->regs + MPA_GPIO_SEL_LO,
+ xgene_gpio_set_bit(&priv->chip.gc, priv->regs + MPA_GPIO_SEL_LO,
gpio * 2, 1);
return 0;
}
@@ -153,8 +176,8 @@ static void xgene_gpio_sb_domain_deactivate(struct irq_domain *d,
struct xgene_gpio_sb *priv = d->host_data;
u32 gpio = HWIRQ_TO_GPIO(priv, irq_data->hwirq);
- gpiochip_unlock_as_irq(&priv->gc, gpio);
- xgene_gpio_set_bit(&priv->gc, priv->regs + MPA_GPIO_SEL_LO,
+ gpiochip_unlock_as_irq(&priv->chip.gc, gpio);
+ xgene_gpio_set_bit(&priv->chip.gc, priv->regs + MPA_GPIO_SEL_LO,
gpio * 2, 0);
}
@@ -216,6 +239,7 @@ static const struct irq_domain_ops xgene_gpio_sb_domain_ops = {
static int xgene_gpio_sb_probe(struct platform_device *pdev)
{
+ struct gpio_generic_chip_config config;
struct xgene_gpio_sb *priv;
int ret;
void __iomem *regs;
@@ -242,33 +266,37 @@ static int xgene_gpio_sb_probe(struct platform_device *pdev)
return -ENODEV;
}
- ret = bgpio_init(&priv->gc, &pdev->dev, 4,
- regs + MPA_GPIO_IN_ADDR,
- regs + MPA_GPIO_OUT_ADDR, NULL,
- regs + MPA_GPIO_OE_ADDR, NULL, 0);
+ config = (struct gpio_generic_chip_config) {
+ .dev = &pdev->dev,
+ .sz = 4,
+ .dat = regs + MPA_GPIO_IN_ADDR,
+ .set = regs + MPA_GPIO_OUT_ADDR,
+ .dirout = regs + MPA_GPIO_OE_ADDR,
+ };
+
+ ret = gpio_generic_chip_init(&priv->chip, &config);
if (ret)
return ret;
- priv->gc.to_irq = xgene_gpio_sb_to_irq;
+ priv->chip.gc.to_irq = xgene_gpio_sb_to_irq;
/* Retrieve start irq pin, use default if property not found */
priv->irq_start = XGENE_DFLT_IRQ_START_PIN;
- if (!device_property_read_u32(&pdev->dev,
- XGENE_IRQ_START_PROPERTY, &val32))
+ if (!device_property_read_u32(&pdev->dev, "apm,irq-start", &val32))
priv->irq_start = val32;
/* Retrieve number irqs, use default if property not found */
priv->nirq = XGENE_DFLT_MAX_NIRQ;
- if (!device_property_read_u32(&pdev->dev, XGENE_NIRQ_PROPERTY, &val32))
+ if (!device_property_read_u32(&pdev->dev, "apm,nr-irqs", &val32))
priv->nirq = val32;
/* Retrieve number gpio, use default if property not found */
- priv->gc.ngpio = XGENE_DFLT_MAX_NGPIO;
- if (!device_property_read_u32(&pdev->dev, XGENE_NGPIO_PROPERTY, &val32))
- priv->gc.ngpio = val32;
+ priv->chip.gc.ngpio = XGENE_DFLT_MAX_NGPIO;
+ if (!device_property_read_u32(&pdev->dev, "apm,nr-gpios", &val32))
+ priv->chip.gc.ngpio = val32;
dev_info(&pdev->dev, "Support %d gpios, %d irqs start from pin %d\n",
- priv->gc.ngpio, priv->nirq, priv->irq_start);
+ priv->chip.gc.ngpio, priv->nirq, priv->irq_start);
platform_set_drvdata(pdev, priv);
@@ -278,9 +306,9 @@ static int xgene_gpio_sb_probe(struct platform_device *pdev)
if (!priv->irq_domain)
return -ENODEV;
- priv->gc.irq.domain = priv->irq_domain;
+ priv->chip.gc.irq.domain = priv->irq_domain;
- ret = devm_gpiochip_add_data(&pdev->dev, &priv->gc, priv);
+ ret = devm_gpiochip_add_data(&pdev->dev, &priv->chip.gc, priv);
if (ret) {
dev_err(&pdev->dev,
"failed to register X-Gene GPIO Standby driver\n");
@@ -291,42 +319,38 @@ static int xgene_gpio_sb_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "X-Gene GPIO Standby driver registered\n");
/* Register interrupt handlers for GPIO signaled ACPI Events */
- acpi_gpiochip_request_interrupts(&priv->gc);
+ acpi_gpiochip_request_interrupts(&priv->chip.gc);
return ret;
}
-static int xgene_gpio_sb_remove(struct platform_device *pdev)
+static void xgene_gpio_sb_remove(struct platform_device *pdev)
{
struct xgene_gpio_sb *priv = platform_get_drvdata(pdev);
- acpi_gpiochip_free_interrupts(&priv->gc);
+ acpi_gpiochip_free_interrupts(&priv->chip.gc);
irq_domain_remove(priv->irq_domain);
-
- return 0;
}
static const struct of_device_id xgene_gpio_sb_of_match[] = {
- {.compatible = "apm,xgene-gpio-sb", },
- {},
+ { .compatible = "apm,xgene-gpio-sb" },
+ {}
};
MODULE_DEVICE_TABLE(of, xgene_gpio_sb_of_match);
-#ifdef CONFIG_ACPI
static const struct acpi_device_id xgene_gpio_sb_acpi_match[] = {
- {"APMC0D15", 0},
- {},
+ { "APMC0D15" },
+ {}
};
MODULE_DEVICE_TABLE(acpi, xgene_gpio_sb_acpi_match);
-#endif
static struct platform_driver xgene_gpio_sb_driver = {
.driver = {
.name = "xgene-gpio-sb",
.of_match_table = xgene_gpio_sb_of_match,
- .acpi_match_table = ACPI_PTR(xgene_gpio_sb_acpi_match),
- },
+ .acpi_match_table = xgene_gpio_sb_acpi_match,
+ },
.probe = xgene_gpio_sb_probe,
.remove = xgene_gpio_sb_remove,
};