summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-08 10:31:52 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-08 10:31:52 -0700
commitea125dedbc14b305307889c40d74d564c4419851 (patch)
tree0f11a7256b5fa0871ff323521f00f3a55a7ccb65 /drivers
parentfdea70d26a471e002f2afc3a48821323b699f1e6 (diff)
parent6310b930ccbba55168f30b610fae681d73bd7bd2 (diff)
Merge tag 'gpio-v4.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO updates from Linus Walleij: "This is the bulk of GPIO changes for the v4.18 development cycle. Core changes: - We have killed off VLA from the core library and all drivers. The background should be clear for everyone at this point: https://lwn.net/Articles/749064/ Also I just don't like VLA's, kernel developers hate it when compilers do things behind their back. It's as simple as that. I'm sorry that they even slipped in to begin with. Kudos to Laura Abbott for exorcising them. - Support GPIO hogs in machines/board files. New drivers and chip support: - R-Car r8a77470 (RZ/G1C) - R-Car r8a77965 (M3-N) - R-Car r8a77990 (E3) - PCA953x driver improvements to accomodate more variants. Improvements and new features: - Support one interrupt per line on port A in the DesignWare dwapb driver. Misc: - Random cleanups, right header files in the drivers, some size optimizations etc" * tag 'gpio-v4.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (73 commits) gpio: davinci: fix build warning when !CONFIG_OF gpio: dwapb: Fix rework support for 1 interrupt per port A GPIO gpio: pxa: Include the right header gpio: pl061: Include the right header gpio: pch: Include the right header gpio: pcf857x: Include the right header gpio: pca953x: Include the right header gpio: palmas: Include the right header gpio: omap: Include the right header gpio: octeon: Include the right header gpio: mxs: Switch to SPDX identifier gpio: Remove VLA from stmpe driver gpio: mxc: Switch to SPDX identifier gpio: mxc: add clock operation gpio: Remove VLA from gpiolib gpio: aspeed: Use a cache of output data registers gpio: aspeed: Set output latch before changing direction gpio: pca953x: fix address calculation for pcal6524 gpio: pca953x: define masks for addressing common and extended registers gpio: pca953x: set the PCA_PCAL flag also when matching by DT ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/Kconfig12
-rw-r--r--drivers/gpio/gpio-104-dio-48e.c2
-rw-r--r--drivers/gpio/gpio-104-idi-48.c2
-rw-r--r--drivers/gpio/gpio-74xx-mmio.c9
-rw-r--r--drivers/gpio/gpio-aspeed.c24
-rw-r--r--drivers/gpio/gpio-davinci.c2
-rw-r--r--drivers/gpio/gpio-dwapb.c57
-rw-r--r--drivers/gpio/gpio-eic-sprd.c73
-rw-r--r--drivers/gpio/gpio-ge.c4
-rw-r--r--drivers/gpio/gpio-gpio-mm.c2
-rw-r--r--drivers/gpio/gpio-ingenic.c4
-rw-r--r--drivers/gpio/gpio-loongson.c116
-rw-r--r--drivers/gpio/gpio-lp3943.c2
-rw-r--r--drivers/gpio/gpio-lp873x.c2
-rw-r--r--drivers/gpio/gpio-lpc32xx.c3
-rw-r--r--drivers/gpio/gpio-lynxpoint.c2
-rw-r--r--drivers/gpio/gpio-max730x.c2
-rw-r--r--drivers/gpio/gpio-mc33880.c2
-rw-r--r--drivers/gpio/gpio-mc9s08dz60.c2
-rw-r--r--drivers/gpio/gpio-ml-ioh.c2
-rw-r--r--drivers/gpio/gpio-mm-lantiq.c2
-rw-r--r--drivers/gpio/gpio-mockup.c7
-rw-r--r--drivers/gpio/gpio-msic.c2
-rw-r--r--drivers/gpio/gpio-mvebu.c20
-rw-r--r--drivers/gpio/gpio-mxc.c54
-rw-r--r--drivers/gpio/gpio-mxs.c32
-rw-r--r--drivers/gpio/gpio-octeon.c2
-rw-r--r--drivers/gpio/gpio-omap.c2
-rw-r--r--drivers/gpio/gpio-palmas.c8
-rw-r--r--drivers/gpio/gpio-pca953x.c81
-rw-r--r--drivers/gpio/gpio-pcf857x.c2
-rw-r--r--drivers/gpio/gpio-pch.c2
-rw-r--r--drivers/gpio/gpio-pl061.c2
-rw-r--r--drivers/gpio/gpio-pmic-eic-sprd.c58
-rw-r--r--drivers/gpio/gpio-pxa.c10
-rw-r--r--drivers/gpio/gpio-stmpe.c9
-rw-r--r--drivers/gpio/gpio-syscon.c9
-rw-r--r--drivers/gpio/gpio-ts4900.c7
-rw-r--r--drivers/gpio/gpio-vf610.c4
-rw-r--r--drivers/gpio/gpio-xlp.c9
-rw-r--r--drivers/gpio/gpio-xra1403.c15
-rw-r--r--drivers/gpio/gpio-zynq.c14
-rw-r--r--drivers/gpio/gpiolib-of.c7
-rw-r--r--drivers/gpio/gpiolib.c143
-rw-r--r--drivers/gpio/gpiolib.h2
-rw-r--r--drivers/mfd/intel_quark_i2c_gpio.c3
46 files changed, 544 insertions, 286 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index b960f6f35abd..71c0ab46f216 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -22,6 +22,18 @@ menuconfig GPIOLIB
if GPIOLIB
+config GPIOLIB_FASTPATH_LIMIT
+ int "Maximum number of GPIOs for fast path"
+ range 32 512
+ default 512
+ help
+ This adjusts the point at which certain APIs will switch from
+ using a stack allocated buffer to a dynamically allocated buffer.
+
+ You shouldn't need to change this unless you really need to
+ optimize either stack space or performance. Change this carefully
+ since setting an incorrect value could cause stack corruption.
+
config OF_GPIO
def_bool y
depends on OF
diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c
index 31e22c93e844..9c4e07fcb74b 100644
--- a/drivers/gpio/gpio-104-dio-48e.c
+++ b/drivers/gpio/gpio-104-dio-48e.c
@@ -188,7 +188,7 @@ static int dio48e_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
{
struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
size_t i;
- const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
+ static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
const unsigned int gpio_reg_size = 8;
unsigned int bits_offset;
size_t word_index;
diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c
index f35632609379..2c9738adb3a6 100644
--- a/drivers/gpio/gpio-104-idi-48.c
+++ b/drivers/gpio/gpio-104-idi-48.c
@@ -94,7 +94,7 @@ static int idi_48_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
{
struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
size_t i;
- const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
+ static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
const unsigned int gpio_reg_size = 8;
unsigned int bits_offset;
size_t word_index;
diff --git a/drivers/gpio/gpio-74xx-mmio.c b/drivers/gpio/gpio-74xx-mmio.c
index 0475e8ec96d0..49616ec815ee 100644
--- a/drivers/gpio/gpio-74xx-mmio.c
+++ b/drivers/gpio/gpio-74xx-mmio.c
@@ -105,27 +105,22 @@ static int mmio_74xx_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
static int mmio_74xx_gpio_probe(struct platform_device *pdev)
{
- const struct of_device_id *of_id;
struct mmio_74xx_gpio_priv *priv;
struct resource *res;
void __iomem *dat;
int err;
- of_id = of_match_device(mmio_74xx_gpio_ids, &pdev->dev);
- if (!of_id)
- return -ENODEV;
-
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
+ priv->flags = (uintptr_t)of_device_get_match_data(&pdev->dev);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dat = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(dat))
return PTR_ERR(dat);
- priv->flags = (uintptr_t) of_id->data;
-
err = bgpio_init(&priv->gc, &pdev->dev,
DIV_ROUND_UP(MMIO_74XX_BIT_CNT(priv->flags), 8),
dat, NULL, NULL, NULL, NULL, 0);
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
index 6f693b7d5220..5e89f1c74a33 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -54,6 +54,8 @@ struct aspeed_gpio {
u8 *offset_timer;
unsigned int timer_users[4];
struct clk *clk;
+
+ u32 *dcache;
};
struct aspeed_gpio_bank {
@@ -231,12 +233,13 @@ static void __aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
u32 reg;
addr = bank_val_reg(gpio, bank, GPIO_DATA);
- reg = ioread32(addr);
+ reg = gpio->dcache[GPIO_BANK(offset)];
if (val)
reg |= GPIO_BIT(offset);
else
reg &= ~GPIO_BIT(offset);
+ gpio->dcache[GPIO_BANK(offset)] = reg;
iowrite32(reg, addr);
}
@@ -287,11 +290,10 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,
spin_lock_irqsave(&gpio->lock, flags);
+ __aspeed_gpio_set(gc, offset, val);
reg = ioread32(bank_val_reg(gpio, bank, GPIO_DIR));
iowrite32(reg | GPIO_BIT(offset), bank_val_reg(gpio, bank, GPIO_DIR));
- __aspeed_gpio_set(gc, offset, val);
-
spin_unlock_irqrestore(&gpio->lock, flags);
return 0;
@@ -852,7 +854,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
const struct of_device_id *gpio_id;
struct aspeed_gpio *gpio;
struct resource *res;
- int rc;
+ int rc, i, banks;
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio)
@@ -893,6 +895,20 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
gpio->chip.base = -1;
gpio->chip.irq.need_valid_mask = true;
+ /* Allocate a cache of the output registers */
+ banks = gpio->config->nr_gpios >> 5;
+ gpio->dcache = devm_kzalloc(&pdev->dev,
+ sizeof(u32) * banks, GFP_KERNEL);
+ if (!gpio->dcache)
+ return -ENOMEM;
+
+ /* Populate it with initial values read from the HW */
+ for (i = 0; i < banks; i++) {
+ const struct aspeed_gpio_bank *bank = &aspeed_gpio_banks[i];
+ gpio->dcache[i] = ioread32(gpio->base + bank->val_regs +
+ GPIO_DATA);
+ }
+
rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
if (rc < 0)
return rc;
diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c
index 987126c4c6f6..b574ecff7761 100644
--- a/drivers/gpio/gpio-davinci.c
+++ b/drivers/gpio/gpio-davinci.c
@@ -610,14 +610,12 @@ done:
return 0;
}
-#if IS_ENABLED(CONFIG_OF)
static const struct of_device_id davinci_gpio_ids[] = {
{ .compatible = "ti,keystone-gpio", keystone_gpio_get_irq_chip},
{ .compatible = "ti,dm6441-gpio", davinci_gpio_get_irq_chip},
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, davinci_gpio_ids);
-#endif
static struct platform_driver davinci_gpio_driver = {
.probe = davinci_gpio_probe,
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 226977f78482..7a2de3de6571 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -441,14 +441,19 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
irq_gc->chip_types[1].handler = handle_edge_irq;
if (!pp->irq_shared) {
- irq_set_chained_handler_and_data(pp->irq, dwapb_irq_handler,
- gpio);
+ int i;
+
+ for (i = 0; i < pp->ngpio; i++) {
+ if (pp->irq[i] >= 0)
+ irq_set_chained_handler_and_data(pp->irq[i],
+ dwapb_irq_handler, gpio);
+ }
} else {
/*
* Request a shared IRQ since where MFD would have devices
* using the same irq pin
*/
- err = devm_request_irq(gpio->dev, pp->irq,
+ err = devm_request_irq(gpio->dev, pp->irq[0],
dwapb_irq_handler_mfd,
IRQF_SHARED, "gpio-dwapb-mfd", gpio);
if (err) {
@@ -524,7 +529,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
if (pp->idx == 0)
port->gc.set_config = dwapb_gpio_set_config;
- if (pp->irq)
+ if (pp->has_irq)
dwapb_configure_irqs(gpio, port, pp);
err = gpiochip_add_data(&port->gc, port);
@@ -535,7 +540,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
port->is_registered = true;
/* Add GPIO-signaled ACPI event support */
- if (pp->irq)
+ if (pp->has_irq)
acpi_gpiochip_request_interrupts(&port->gc);
return err;
@@ -557,7 +562,7 @@ dwapb_gpio_get_pdata(struct device *dev)
struct dwapb_platform_data *pdata;
struct dwapb_port_property *pp;
int nports;
- int i;
+ int i, j;
nports = device_get_child_node_count(dev);
if (nports == 0)
@@ -575,6 +580,8 @@ dwapb_gpio_get_pdata(struct device *dev)
i = 0;
device_for_each_child_node(dev, fwnode) {
+ struct device_node *np = NULL;
+
pp = &pdata->properties[i++];
pp->fwnode = fwnode;
@@ -594,23 +601,35 @@ dwapb_gpio_get_pdata(struct device *dev)
pp->ngpio = 32;
}
+ pp->irq_shared = false;
+ pp->gpio_base = -1;
+
/*
* Only port A can provide interrupts in all configurations of
* the IP.
*/
- if (dev->of_node && pp->idx == 0 &&
- fwnode_property_read_bool(fwnode,
+ if (pp->idx != 0)
+ continue;
+
+ if (dev->of_node && fwnode_property_read_bool(fwnode,
"interrupt-controller")) {
- pp->irq = irq_of_parse_and_map(to_of_node(fwnode), 0);
- if (!pp->irq)
- dev_warn(dev, "no irq for port%d\n", pp->idx);
+ np = to_of_node(fwnode);
}
- if (has_acpi_companion(dev) && pp->idx == 0)
- pp->irq = platform_get_irq(to_platform_device(dev), 0);
+ for (j = 0; j < pp->ngpio; j++) {
+ pp->irq[j] = -ENXIO;
- pp->irq_shared = false;
- pp->gpio_base = -1;
+ if (np)
+ pp->irq[j] = of_irq_get(np, j);
+ else if (has_acpi_companion(dev))
+ pp->irq[j] = platform_get_irq(to_platform_device(dev), j);
+
+ if (pp->irq[j] >= 0)
+ pp->has_irq = true;
+ }
+
+ if (!pp->has_irq)
+ dev_warn(dev, "no irq for port%d\n", pp->idx);
}
return pdata;
@@ -684,13 +703,7 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
gpio->flags = 0;
if (dev->of_node) {
- const struct of_device_id *of_devid;
-
- of_devid = of_match_device(dwapb_of_match, dev);
- if (of_devid) {
- if (of_devid->data)
- gpio->flags = (uintptr_t)of_devid->data;
- }
+ gpio->flags = (uintptr_t)of_device_get_match_data(dev);
} else if (has_acpi_companion(dev)) {
const struct acpi_device_id *acpi_id;
diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c
index de7dd939c043..e0d6a0a7bc69 100644
--- a/drivers/gpio/gpio-eic-sprd.c
+++ b/drivers/gpio/gpio-eic-sprd.c
@@ -300,6 +300,7 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
struct sprd_eic *sprd_eic = gpiochip_get_data(chip);
u32 offset = irqd_to_hwirq(data);
+ int state;
switch (sprd_eic->type) {
case SPRD_EIC_DEBOUNCE:
@@ -310,6 +311,17 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
case IRQ_TYPE_LEVEL_LOW:
sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 0);
break;
+ case IRQ_TYPE_EDGE_RISING:
+ case IRQ_TYPE_EDGE_FALLING:
+ case IRQ_TYPE_EDGE_BOTH:
+ state = sprd_eic_get(chip, offset);
+ if (state)
+ sprd_eic_update(chip, offset,
+ SPRD_EIC_DBNC_IEV, 0);
+ else
+ sprd_eic_update(chip, offset,
+ SPRD_EIC_DBNC_IEV, 1);
+ break;
default:
return -ENOTSUPP;
}
@@ -324,6 +336,17 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
case IRQ_TYPE_LEVEL_LOW:
sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 1);
break;
+ case IRQ_TYPE_EDGE_RISING:
+ case IRQ_TYPE_EDGE_FALLING:
+ case IRQ_TYPE_EDGE_BOTH:
+ state = sprd_eic_get(chip, offset);
+ if (state)
+ sprd_eic_update(chip, offset,
+ SPRD_EIC_LATCH_INTPOL, 0);
+ else
+ sprd_eic_update(chip, offset,
+ SPRD_EIC_LATCH_INTPOL, 1);
+ break;
default:
return -ENOTSUPP;
}
@@ -405,6 +428,55 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
return 0;
}
+static void sprd_eic_toggle_trigger(struct gpio_chip *chip, unsigned int irq,
+ unsigned int offset)
+{
+ struct sprd_eic *sprd_eic = gpiochip_get_data(chip);
+ struct irq_data *data = irq_get_irq_data(irq);
+ u32 trigger = irqd_get_trigger_type(data);
+ int state, post_state;
+
+ /*
+ * The debounce EIC and latch EIC can only support level trigger, so we
+ * can toggle the level trigger to emulate the edge trigger.
+ */
+ if ((sprd_eic->type != SPRD_EIC_DEBOUNCE &&
+ sprd_eic->type != SPRD_EIC_LATCH) ||
+ !(trigger & IRQ_TYPE_EDGE_BOTH))
+ return;
+
+ sprd_eic_irq_mask(data);
+ state = sprd_eic_get(chip, offset);
+
+retry:
+ switch (sprd_eic->type) {
+ case SPRD_EIC_DEBOUNCE:
+ if (state)
+ sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 0);
+ else
+ sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 1);
+ break;
+ case SPRD_EIC_LATCH:
+ if (state)
+ sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 0);
+ else
+ sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 1);
+ break;
+ default:
+ sprd_eic_irq_unmask(data);
+ return;
+ }
+
+ post_state = sprd_eic_get(chip, offset);
+ if (state != post_state) {
+ dev_warn(chip->parent, "EIC level was changed.\n");
+ state = post_state;
+ goto retry;
+ }
+
+ sprd_eic_irq_unmask(data);
+}
+
static int sprd_eic_match_chip_by_type(struct gpio_chip *chip, void *data)
{
enum sprd_eic_type type = *(enum sprd_eic_type *)data;
@@ -448,6 +520,7 @@ static void sprd_eic_handle_one_type(struct gpio_chip *chip)
bank * SPRD_EIC_PER_BANK_NR + n);
generic_handle_irq(girq);
+ sprd_eic_toggle_trigger(chip, girq, n);
}
}
}
diff --git a/drivers/gpio/gpio-ge.c b/drivers/gpio/gpio-ge.c
index 1fe2d3418f2f..636952769bc8 100644
--- a/drivers/gpio/gpio-ge.c
+++ b/drivers/gpio/gpio-ge.c
@@ -52,8 +52,6 @@ MODULE_DEVICE_TABLE(of, gef_gpio_ids);
static int __init gef_gpio_probe(struct platform_device *pdev)
{
- const struct of_device_id *of_id =
- of_match_device(gef_gpio_ids, &pdev->dev);
struct gpio_chip *gc;
void __iomem *regs;
int ret;
@@ -82,7 +80,7 @@ static int __init gef_gpio_probe(struct platform_device *pdev)
}
gc->base = -1;
- gc->ngpio = (u16)(uintptr_t)of_id->data;
+ gc->ngpio = (u16)(uintptr_t)of_device_get_match_data(&pdev->dev);
gc->of_gpio_n_cells = 2;
gc->of_node = pdev->dev.of_node;
diff --git a/drivers/gpio/gpio-gpio-mm.c b/drivers/gpio/gpio-gpio-mm.c
index d496cc56c2a2..b56ff2efbf36 100644
--- a/drivers/gpio/gpio-gpio-mm.c
+++ b/drivers/gpio/gpio-gpio-mm.c
@@ -177,7 +177,7 @@ static int gpiomm_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
{
struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
size_t i;
- const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
+ static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
const unsigned int gpio_reg_size = 8;
unsigned int bits_offset;
size_t word_index;
diff --git a/drivers/gpio/gpio-ingenic.c b/drivers/gpio/gpio-ingenic.c
index 15fb2bc796a8..e738e384a5ca 100644
--- a/drivers/gpio/gpio-ingenic.c
+++ b/drivers/gpio/gpio-ingenic.c
@@ -285,8 +285,6 @@ MODULE_DEVICE_TABLE(of, ingenic_gpio_of_match);
static int ingenic_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- const struct of_device_id *of_id = of_match_device(
- ingenic_gpio_of_match, dev);
struct ingenic_gpio_chip *jzgc;
u32 bank;
int err;
@@ -323,7 +321,7 @@ static int ingenic_gpio_probe(struct platform_device *pdev)
jzgc->gc.parent = dev;
jzgc->gc.of_node = dev->of_node;
jzgc->gc.owner = THIS_MODULE;
- jzgc->version = (enum jz_version)of_id->data;
+ jzgc->version = (enum jz_version)of_device_get_match_data(dev);
jzgc->gc.set = ingenic_gpio_set;
jzgc->gc.get = ingenic_gpio_get;
diff --git a/drivers/gpio/gpio-loongson.c b/drivers/gpio/gpio-loongson.c
index 92c4fe7b2677..16cfbe9e72fe 100644
--- a/drivers/gpio/gpio-loongson.c
+++ b/drivers/gpio/gpio-loongson.c
@@ -17,9 +17,11 @@
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/err.h>
+#include <linux/gpio/driver.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
#include <asm/types.h>
#include <loongson.h>
-#include <linux/gpio.h>
#define STLS2F_N_GPIO 4
#define STLS3A_N_GPIO 16
@@ -30,86 +32,108 @@
#define LOONGSON_N_GPIO STLS2F_N_GPIO
#endif
+/*
+ * Offset into the register where we read lines, we write them from offset 0.
+ * This offset is the only thing that stand between us and using
+ * GPIO_GENERIC.
+ */
#define LOONGSON_GPIO_IN_OFFSET 16
static DEFINE_SPINLOCK(gpio_lock);
-static int loongson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+static int loongson_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
{
- u32 temp;
- u32 mask;
+ u32 val;
spin_lock(&gpio_lock);
- mask = 1 << gpio;
- temp = LOONGSON_GPIOIE;
- temp |= mask;
- LOONGSON_GPIOIE = temp;
+ val = LOONGSON_GPIODATA;
spin_unlock(&gpio_lock);
- return 0;
+ return !!(val & BIT(gpio + LOONGSON_GPIO_IN_OFFSET));
}
-static int loongson_gpio_direction_output(struct gpio_chip *chip,
- unsigned gpio, int level)
+static void loongson_gpio_set_value(struct gpio_chip *chip,
+ unsigned gpio, int value)
+{
+ u32 val;
+
+ spin_lock(&gpio_lock);
+ val = LOONGSON_GPIODATA;
+ if (value)
+ val |= BIT(gpio);
+ else
+ val &= ~BIT(gpio);
+ LOONGSON_GPIODATA = val;
+ spin_unlock(&gpio_lock);
+}
+
+static int loongson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
u32 temp;
- u32 mask;
- gpio_set_value(gpio, level);
spin_lock(&gpio_lock);
- mask = 1 << gpio;
temp = LOONGSON_GPIOIE;
- temp &= (~mask);
+ temp |= BIT(gpio);
LOONGSON_GPIOIE = temp;
spin_unlock(&gpio_lock);
return 0;
}
-static int loongson_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+static int loongson_gpio_direction_output(struct gpio_chip *chip,
+ unsigned gpio, int level)
{
- u32 val;
- u32 mask;
+ u32 temp;
- mask = 1 << (gpio + LOONGSON_GPIO_IN_OFFSET);
+ loongson_gpio_set_value(chip, gpio, level);
spin_lock(&gpio_lock);
- val = LOONGSON_GPIODATA;
+ temp = LOONGSON_GPIOIE;
+ temp &= ~BIT(gpio);
+ LOONGSON_GPIOIE = temp;
spin_unlock(&gpio_lock);
- return (val & mask) != 0;
+ return 0;
}
-static void loongson_gpio_set_value(struct gpio_chip *chip,
- unsigned gpio, int value)
+static int loongson_gpio_probe(struct platform_device *pdev)
{
- u32 val;
- u32 mask;
-
- mask = 1 << gpio;
-
- spin_lock(&gpio_lock);
- val = LOONGSON_GPIODATA;
- if (value)
- val |= mask;
- else
- val &= (~mask);
- LOONGSON_GPIODATA = val;
- spin_unlock(&gpio_lock);
+ struct gpio_chip *gc;
+ struct device *dev = &pdev->dev;
+
+ gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
+ if (!gc)
+ return -ENOMEM;
+
+ gc->label = "loongson-gpio-chip";
+ gc->base = 0;
+ gc->ngpio = LOONGSON_N_GPIO;
+ gc->get = loongson_gpio_get_value;
+ gc->set = loongson_gpio_set_value;
+ gc->direction_input = loongson_gpio_direction_input;
+ gc->direction_output = loongson_gpio_direction_output;
+
+ return gpiochip_add_data(gc, NULL);
}
-static struct gpio_chip loongson_chip = {
- .label = "Loongson-gpio-chip",
- .direction_input = loongson_gpio_direction_input,
- .get = loongson_gpio_get_value,
- .direction_output = loongson_gpio_direction_output,
- .set = loongson_gpio_set_value,
- .base = 0,
- .ngpio = LOONGSON_N_GPIO,
- .can_sleep = false,
+static struct platform_driver loongson_gpio_driver = {
+ .driver = {
+ .name = "loongson-gpio",
+ },
+ .probe = loongson_gpio_probe,
};
static int __init loongson_gpio_setup(void)
{
- return gpiochip_add_data(&loongson_chip, NULL);
+ struct platform_device *pdev;
+ int ret;
+
+ ret = platform_driver_register(&loongson_gpio_driver);
+ if (ret) {
+ pr_err("error registering loongson GPIO driver\n");
+ return ret;
+ }
+
+ pdev = platform_device_register_simple("loongson-gpio", -1, NULL, 0);
+ return PTR_ERR_OR_ZERO(pdev);
}
postcore_initcall(loongson_gpio_setup);
diff --git a/drivers/gpio/gpio-lp3943.c b/drivers/gpio/gpio-lp3943.c
index 6dc6725403ec..c3a3b9b7b553 100644
--- a/drivers/gpio/gpio-lp3943.c
+++ b/drivers/gpio/gpio-lp3943.c
@@ -12,7 +12,7 @@
#include <linux/bitops.h>
#include <linux/err.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
#include <linux/i2c.h>
#include <linux/mfd/lp3943.h>
#include <linux/module.h>
diff --git a/drivers/gpio/gpio-lp873x.c b/drivers/gpio/gpio-lp873x.c
index df0ad2cef0d2..801995dd9b26 100644
--- a/drivers/gpio/gpio-lp873x.c
+++ b/drivers/gpio/gpio-lp873x.c
@@ -14,7 +14,7 @@
* Based on the TPS65218 driver
*/
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c
index 92b3ae2a6735..aa74cc4d8b14 100644
--- a/drivers/gpio/gpio-lpc32xx.c
+++ b/drivers/gpio/gpio-lpc32xx.c
@@ -20,9 +20,8 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/errno.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
#include <linux/of.h>
-#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/module.h>
diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c
index 1e557b10d73e..b5b5e500e72c 100644
--- a/drivers/gpio/gpio-lynxpoint.c
+++ b/drivers/gpio/gpio-lynxpoint.c
@@ -25,7 +25,7 @@
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/interrupt.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
#include <linux/slab.h>