Commit 4c8c225a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux

Pull GPIO changes from Grant Likely:
 "This branch contains the usual set of individual driver improvements
  and bug fixes, as well as updates to the core code.  The more notable
  changes include:

   - Internally add new API for referencing GPIOs by gpio_desc instead
     of number.  Eventually this will become a public API

   - ACPI GPIO binding support"

* tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux: (33 commits)
  arm64: select ARCH_WANT_OPTIONAL_GPIOLIB
  gpio: em: Use irq_domain_add_simple() to fix runtime error
  gpio: using common order: let 'static const' instead of 'const static'
  gpio/vt8500: memory cleanup missing
  gpiolib: Fix locking on gpio debugfs files
  gpiolib: let gpio_chip reference its descriptors
  gpiolib: use descriptors internally
  gpiolib: use gpio_chips list in gpiochip_find_base
  gpiolib: use gpio_chips list in sysfs ops
  gpiolib: use gpio_chips list in gpiochip_find
  gpiolib: use gpio_chips list in gpiolib_sysfs_init
  gpiolib: link all gpio_chips using a list
  gpio/langwell: cleanup driver
  gpio/langwell: Add Cloverview ids to pci device table
  gpio/lynxpoint: add chipset gpio driver.
  gpiolib: add missing braces in gpio_direction_show
  gpiolib-acpi: Fix error checks in interrupt requesting
  gpio: mpc8xxx: don't set IRQ_TYPE_NONE when creating irq mapping
  gpiolib: remove gpiochip_reserve()
  arm: pxa: tosa: do not use gpiochip_reserve()
  ...
parents 3eb05225 9170100e
...@@ -927,8 +927,6 @@ static void tosa_restart(char mode, const char *cmd) ...@@ -927,8 +927,6 @@ static void tosa_restart(char mode, const char *cmd)
static void __init tosa_init(void) static void __init tosa_init(void)
{ {
int dummy;
pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_config)); pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_config));
pxa_set_ffuart_info(NULL); pxa_set_ffuart_info(NULL);
...@@ -947,10 +945,6 @@ static void __init tosa_init(void) ...@@ -947,10 +945,6 @@ static void __init tosa_init(void)
/* enable batt_fault */ /* enable batt_fault */
PMCR = 0x01; PMCR = 0x01;
dummy = gpiochip_reserve(TOSA_SCOOP_GPIO_BASE, 12);
dummy = gpiochip_reserve(TOSA_SCOOP_JC_GPIO_BASE, 12);
dummy = gpiochip_reserve(TOSA_TC6393XB_GPIO_BASE, 16);
pxa_set_mci_info(&tosa_mci_platform_data); pxa_set_mci_info(&tosa_mci_platform_data);
pxa_set_ficp_info(&tosa_ficp_platform_data); pxa_set_ficp_info(&tosa_ficp_platform_data);
pxa_set_i2c_info(NULL); pxa_set_i2c_info(NULL);
......
config ARM64 config ARM64
def_bool y def_bool y
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
select ARCH_WANT_OPTIONAL_GPIOLIB
select ARCH_WANT_COMPAT_IPC_PARSE_VERSION select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
select ARCH_WANT_FRAME_POINTERS select ARCH_WANT_FRAME_POINTERS
select ARM_AMBA select ARM_AMBA
...@@ -93,7 +94,7 @@ config IOMMU_HELPER ...@@ -93,7 +94,7 @@ config IOMMU_HELPER
def_bool SWIOTLB def_bool SWIOTLB
config GENERIC_GPIO config GENERIC_GPIO
def_bool y bool
source "init/Kconfig" source "init/Kconfig"
......
...@@ -30,6 +30,9 @@ config ARCH_REQUIRE_GPIOLIB ...@@ -30,6 +30,9 @@ config ARCH_REQUIRE_GPIOLIB
Selecting this from the architecture code will cause the gpiolib Selecting this from the architecture code will cause the gpiolib
code to always get built in. code to always get built in.
config GPIO_DEVRES
def_bool y
depends on HAS_IOMEM
menuconfig GPIOLIB menuconfig GPIOLIB
...@@ -298,6 +301,14 @@ config GPIO_GE_FPGA ...@@ -298,6 +301,14 @@ config GPIO_GE_FPGA
and write pin state) for GPIO implemented in a number of GE single and write pin state) for GPIO implemented in a number of GE single
board computers. board computers.
config GPIO_LYNXPOINT
bool "Intel Lynxpoint GPIO support"
depends on ACPI
select IRQ_DOMAIN
help
driver for GPIO functionality on Intel Lynxpoint PCH chipset
Requires ACPI device enumeration code to set up a platform device.
comment "I2C GPIO expanders:" comment "I2C GPIO expanders:"
config GPIO_ARIZONA config GPIO_ARIZONA
......
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
obj-$(CONFIG_GPIOLIB) += gpiolib.o devres.o obj-$(CONFIG_GPIO_DEVRES) += devres.o
obj-$(CONFIG_GPIOLIB) += gpiolib.o
obj-$(CONFIG_OF_GPIO) += gpiolib-of.o obj-$(CONFIG_OF_GPIO) += gpiolib-of.o
obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o
...@@ -30,6 +31,7 @@ obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o ...@@ -30,6 +31,7 @@ obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o
obj-$(CONFIG_GPIO_LANGWELL) += gpio-langwell.o obj-$(CONFIG_GPIO_LANGWELL) += gpio-langwell.o
obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o
obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o
obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o
obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o
obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o
......
...@@ -299,8 +299,9 @@ static int em_gio_probe(struct platform_device *pdev) ...@@ -299,8 +299,9 @@ static int em_gio_probe(struct platform_device *pdev)
irq_chip->irq_set_type = em_gio_irq_set_type; irq_chip->irq_set_type = em_gio_irq_set_type;
irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; irq_chip->flags = IRQCHIP_SKIP_SET_WAKE;
p->irq_domain = irq_domain_add_linear(pdev->dev.of_node, p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
pdata->number_of_pins, pdata->number_of_pins,
pdata->irq_base,
&em_gio_irq_domain_ops, p); &em_gio_irq_domain_ops, p);
if (!p->irq_domain) { if (!p->irq_domain) {
ret = -ENXIO; ret = -ENXIO;
......
...@@ -71,10 +71,12 @@ struct lnw_gpio { ...@@ -71,10 +71,12 @@ struct lnw_gpio {
struct irq_domain *domain; struct irq_domain *domain;
}; };
#define to_lnw_priv(chip) container_of(chip, struct lnw_gpio, chip)
static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset, static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
enum GPIO_REG reg_type) enum GPIO_REG reg_type)
{ {
struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); struct lnw_gpio *lnw = to_lnw_priv(chip);
unsigned nreg = chip->ngpio / 32; unsigned nreg = chip->ngpio / 32;
u8 reg = offset / 32; u8 reg = offset / 32;
void __iomem *ptr; void __iomem *ptr;
...@@ -86,7 +88,7 @@ static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset, ...@@ -86,7 +88,7 @@ static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset, static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset,
enum GPIO_REG reg_type) enum GPIO_REG reg_type)
{ {
struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); struct lnw_gpio *lnw = to_lnw_priv(chip);
unsigned nreg = chip->ngpio / 32; unsigned nreg = chip->ngpio / 32;
u8 reg = offset / 16; u8 reg = offset / 16;
void __iomem *ptr; void __iomem *ptr;
...@@ -130,7 +132,7 @@ static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ...@@ -130,7 +132,7 @@ static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset) static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{ {
struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); struct lnw_gpio *lnw = to_lnw_priv(chip);
void __iomem *gpdr = gpio_reg(chip, offset, GPDR); void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
u32 value; u32 value;
unsigned long flags; unsigned long flags;
...@@ -153,7 +155,7 @@ static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ...@@ -153,7 +155,7 @@ static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
static int lnw_gpio_direction_output(struct gpio_chip *chip, static int lnw_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value) unsigned offset, int value)
{ {
struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); struct lnw_gpio *lnw = to_lnw_priv(chip);
void __iomem *gpdr = gpio_reg(chip, offset, GPDR); void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
unsigned long flags; unsigned long flags;
...@@ -176,7 +178,7 @@ static int lnw_gpio_direction_output(struct gpio_chip *chip, ...@@ -176,7 +178,7 @@ static int lnw_gpio_direction_output(struct gpio_chip *chip,
static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset) static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{ {
struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); struct lnw_gpio *lnw = to_lnw_priv(chip);
return irq_create_mapping(lnw->domain, offset); return irq_create_mapping(lnw->domain, offset);
} }
...@@ -234,6 +236,8 @@ static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = { /* pin number */ ...@@ -234,6 +236,8 @@ static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = { /* pin number */
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), .driver_data = 64 }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), .driver_data = 64 },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f), .driver_data = 96 }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f), .driver_data = 96 },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a), .driver_data = 96 }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a), .driver_data = 96 },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08eb), .driver_data = 96 },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7), .driver_data = 96 },
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE(pci, lnw_gpio_ids); MODULE_DEVICE_TABLE(pci, lnw_gpio_ids);
...@@ -299,17 +303,6 @@ static const struct irq_domain_ops lnw_gpio_irq_ops = { ...@@ -299,17 +303,6 @@ static const struct irq_domain_ops lnw_gpio_irq_ops = {
.xlate = irq_domain_xlate_twocell, .xlate = irq_domain_xlate_twocell,
}; };
#ifdef CONFIG_PM
static int lnw_gpio_runtime_resume(struct device *dev)
{
return 0;
}
static int lnw_gpio_runtime_suspend(struct device *dev)
{
return 0;
}
static int lnw_gpio_runtime_idle(struct device *dev) static int lnw_gpio_runtime_idle(struct device *dev)
{ {
int err = pm_schedule_suspend(dev, 500); int err = pm_schedule_suspend(dev, 500);
...@@ -320,16 +313,8 @@ static int lnw_gpio_runtime_idle(struct device *dev) ...@@ -320,16 +313,8 @@ static int lnw_gpio_runtime_idle(struct device *dev)
return -EBUSY; return -EBUSY;
} }
#else
#define lnw_gpio_runtime_suspend NULL
#define lnw_gpio_runtime_resume NULL
#define lnw_gpio_runtime_idle NULL
#endif
static const struct dev_pm_ops lnw_gpio_pm_ops = { static const struct dev_pm_ops lnw_gpio_pm_ops = {
.runtime_suspend = lnw_gpio_runtime_suspend, SET_RUNTIME_PM_OPS(NULL, NULL, lnw_gpio_runtime_idle)
.runtime_resume = lnw_gpio_runtime_resume,
.runtime_idle = lnw_gpio_runtime_idle,
}; };
static int lnw_gpio_probe(struct pci_dev *pdev, static int lnw_gpio_probe(struct pci_dev *pdev,
...@@ -349,7 +334,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev, ...@@ -349,7 +334,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
retval = pci_request_regions(pdev, "langwell_gpio"); retval = pci_request_regions(pdev, "langwell_gpio");
if (retval) { if (retval) {
dev_err(&pdev->dev, "error requesting resources\n"); dev_err(&pdev->dev, "error requesting resources\n");
goto err2; goto err_pci_req_region;
} }
/* get the gpio_base from bar1 */ /* get the gpio_base from bar1 */
start = pci_resource_start(pdev, 1); start = pci_resource_start(pdev, 1);
...@@ -358,7 +343,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev, ...@@ -358,7 +343,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
if (!base) { if (!base) {
dev_err(&pdev->dev, "error mapping bar1\n"); dev_err(&pdev->dev, "error mapping bar1\n");
retval = -EFAULT; retval = -EFAULT;
goto err3; goto err_ioremap;
} }
gpio_base = *((u32 *)base + 1); gpio_base = *((u32 *)base + 1);
/* release the IO mapping, since we already get the info from bar1 */ /* release the IO mapping, since we already get the info from bar1 */
...@@ -370,21 +355,21 @@ static int lnw_gpio_probe(struct pci_dev *pdev, ...@@ -370,21 +355,21 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
if (!base) { if (!base) {
dev_err(&pdev->dev, "error mapping bar0\n"); dev_err(&pdev->dev, "error mapping bar0\n");
retval = -EFAULT; retval = -EFAULT;
goto err3; goto err_ioremap;
} }
lnw = devm_kzalloc(&pdev->dev, sizeof(struct lnw_gpio), GFP_KERNEL); lnw = devm_kzalloc(&pdev->dev, sizeof(*lnw), GFP_KERNEL);
if (!lnw) { if (!lnw) {
dev_err(&pdev->dev, "can't allocate langwell_gpio chip data\n"); dev_err(&pdev->dev, "can't allocate langwell_gpio chip data\n");
retval = -ENOMEM; retval = -ENOMEM;
goto err3; goto err_ioremap;
} }
lnw->domain = irq_domain_add_linear(pdev->dev.of_node, ngpio, lnw->domain = irq_domain_add_linear(pdev->dev.of_node, ngpio,
&lnw_gpio_irq_ops, lnw); &lnw_gpio_irq_ops, lnw);
if (!lnw->domain) { if (!lnw->domain) {
retval = -ENOMEM; retval = -ENOMEM;
goto err3; goto err_ioremap;
} }
lnw->reg_base = base; lnw->reg_base = base;
...@@ -403,7 +388,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev, ...@@ -403,7 +388,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
retval = gpiochip_add(&lnw->chip); retval = gpiochip_add(&lnw->chip);
if (retval) { if (retval) {
dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval); dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval);
goto err3; goto err_ioremap;
} }
lnw_irq_init_hw(lnw); lnw_irq_init_hw(lnw);
...@@ -418,9 +403,9 @@ static int lnw_gpio_probe(struct pci_dev *pdev, ...@@ -418,9 +403,9 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
return 0; return 0;
err3: err_ioremap:
pci_release_regions(pdev); pci_release_regions(pdev);
err2: err_pci_req_region:
pci_disable_device(pdev); pci_disable_device(pdev);
return retval; return retval;
} }
......
This diff is collapsed.
...@@ -292,7 +292,6 @@ static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int virq, ...@@ -292,7 +292,6 @@ static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int virq,
irq_set_chip_data(virq, h->host_data); irq_set_chip_data(virq, h->host_data);
irq_set_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq); irq_set_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq);
irq_set_irq_type(virq, IRQ_TYPE_NONE);
return 0; return 0;
} }
......
...@@ -66,6 +66,7 @@ struct mxs_gpio_port { ...@@ -66,6 +66,7 @@ struct mxs_gpio_port {
struct irq_domain *domain; struct irq_domain *domain;
struct bgpio_chip bgc; struct bgpio_chip bgc;
enum mxs_gpio_id devid; enum mxs_gpio_id devid;
u32 both_edges;
}; };
static inline int is_imx23_gpio(struct mxs_gpio_port *port) static inline int is_imx23_gpio(struct mxs_gpio_port *port)
...@@ -82,13 +83,23 @@ static inline int is_imx28_gpio(struct mxs_gpio_port *port) ...@@ -82,13 +83,23 @@ static inline int is_imx28_gpio(struct mxs_gpio_port *port)
static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
{ {
u32 val;
u32 pin_mask = 1 << d->hwirq; u32 pin_mask = 1 << d->hwirq;
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct mxs_gpio_port *port = gc->private; struct mxs_gpio_port *port = gc->private;
void __iomem *pin_addr; void __iomem *pin_addr;
int edge; int edge;
port->both_edges &= ~pin_mask;
switch (type) { switch (type) {
case IRQ_TYPE_EDGE_BOTH:
val = gpio_get_value(port->bgc.gc.base + d->hwirq);
if (val)
edge = GPIO_INT_FALL_EDGE;
else
edge = GPIO_INT_RISE_EDGE;
port->both_edges |= pin_mask;
break;
case IRQ_TYPE_EDGE_RISING: case IRQ_TYPE_EDGE_RISING:
edge = GPIO_INT_RISE_EDGE; edge = GPIO_INT_RISE_EDGE;
break; break;
...@@ -125,6 +136,23 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) ...@@ -125,6 +136,23 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
return 0; return 0;
} }
static void mxs_flip_edge(struct mxs_gpio_port *port, u32 gpio)
{
u32 bit, val, edge;
void __iomem *pin_addr;
bit = 1 << gpio;
pin_addr = port->base + PINCTRL_IRQPOL(port);
val = readl(pin_addr);
edge = val & bit;
if (edge)
writel(bit, pin_addr + MXS_CLR);
else
writel(bit, pin_addr + MXS_SET);
}
/* MXS has one interrupt *per* gpio port */ /* MXS has one interrupt *per* gpio port */
static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
{ {
...@@ -138,6 +166,9 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) ...@@ -138,6 +166,9 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
while (irq_stat != 0) { while (irq_stat != 0) {
int irqoffset = fls(irq_stat) - 1; int irqoffset = fls(irq_stat) - 1;
if (port->both_edges & (1 << irqoffset))
mxs_flip_edge(port, irqoffset);
generic_handle_irq(irq_find_mapping(port->domain, irqoffset)); generic_handle_irq(irq_find_mapping(port->domain, irqoffset));
irq_stat &= ~(1 << irqoffset); irq_stat &= ~(1 << irqoffset);
} }
......
...@@ -1476,19 +1476,19 @@ static struct omap_gpio_reg_offs omap4_gpio_regs = { ...@@ -1476,19 +1476,19 @@ static struct omap_gpio_reg_offs omap4_gpio_regs = {
.fallingdetect = OMAP4_GPIO_FALLINGDETECT, .fallingdetect = OMAP4_GPIO_FALLINGDETECT,
}; };
const static struct omap_gpio_platform_data omap2_pdata = { static const struct omap_gpio_platform_data omap2_pdata = {
.regs = &omap2_gpio_regs, .regs = &omap2_gpio_regs,
.bank_width = 32, .bank_width = 32,
.dbck_flag = false, .dbck_flag = false,
}; };
const static struct omap_gpio_platform_data omap3_pdata = { static const struct omap_gpio_platform_data omap3_pdata = {
.regs = &omap2_gpio_regs, .regs = &omap2_gpio_regs,
.bank_width = 32, .bank_width = 32,
.dbck_flag = true, .dbck_flag = true,
}; };
const static struct omap_gpio_platform_data omap4_pdata = { static const struct omap_gpio_platform_data omap4_pdata = {
.regs = &omap4_gpio_regs, .regs = &omap4_gpio_regs,
.bank_width = 32, .bank_width = 32,
.dbck_flag = true, .dbck_flag = true,
......
This diff is collapsed.
...@@ -365,7 +365,7 @@ static int __init pl061_gpio_init(void) ...@@ -365,7 +365,7 @@ static int __init pl061_gpio_init(void)
{ {
return amba_driver_register(&pl061_gpio_driver); return amba_driver_register(&pl061_gpio_driver);
} }
subsys_initcall(pl061_gpio_init); module_init(pl061_gpio_init);
MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
MODULE_DESCRIPTION("PL061 GPIO driver"); MODULE_DESCRIPTION("PL061 GPIO driver");
......
...@@ -642,12 +642,7 @@ static struct platform_driver pxa_gpio_driver = { ...@@ -642,12 +642,7 @@ static struct platform_driver pxa_gpio_driver = {
.of_match_table = of_match_ptr(pxa_gpio_dt_ids), .of_match_table = of_match_ptr(pxa_gpio_dt_ids),
}, },
}; };
module_platform_driver(pxa_gpio_driver);
static int __init pxa_gpio_init(void)
{
return platform_driver_register(&pxa_gpio_driver);
}
postcore_initcall(pxa_gpio_init);
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int pxa_gpio_suspend(void) static int pxa_gpio_suspend(void)
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include <linux/i2c/twl.h> #include <linux/i2c/twl.h>
/* /*
* The GPIO "subchip" supports 18 GPIOs which can be configured as * The GPIO "subchip" supports 18 GPIOs which can be configured as
* inputs or outputs, with pullups or pulldowns on each pin. Each * inputs or outputs, with pullups or pulldowns on each pin. Each
...@@ -49,11 +48,6 @@ ...@@ -49,11 +48,6 @@
* There are also two LED pins used sometimes as output-only GPIOs. * There are also two LED pins used sometimes as output-only GPIOs.
*/ */
static struct gpio_chip twl_gpiochip;
static int twl4030_gpio_base;
static int twl4030_gpio_irq_base;
/* genirq interfaces are not available to modules */ /* genirq interfaces are not available to modules */
#ifdef MODULE #ifdef MODULE
#define is_module() true #define is_module() true
...@@ -69,14 +63,24 @@ static int twl4030_gpio_irq_base; ...@@ -69,14 +63,24 @@ static int twl4030_gpio_irq_base;
/* Mask for GPIO registers when aggregated into a 32-bit integer */ /* Mask for GPIO registers when aggregated into a 32-bit integer */
#define GPIO_32_MASK 0x0003ffff #define GPIO_32_MASK 0x0003ffff
/* Data structures */ struct gpio_twl4030_priv {
static DEFINE_MUTEX(gpio_lock); struct gpio_chip gpio_chip;
struct mutex mutex;
int irq_base;
/* store usage of each GPIO. - each bit represents one GPIO */ /* Bitfields for state caching */
static unsigned int gpio_usage_count; unsigned int usage_count;
unsigned int direction;
unsigned int out_state;
};
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
static inline struct gpio_twl4030_priv *to_gpio_twl4030(struct gpio_chip *chip)
{
return container_of(chip, struct gpio_twl4030_priv, gpio_chip);
}
/* /*
* To configure TWL4030 GPIO module registers * To configure TWL4030 GPIO module registers
*/ */
...@@ -126,7 +130,7 @@ static inline int gpio_twl4030_read(u8 address) ...@@ -126,7 +130,7 @@ static inline int gpio_twl4030_read(u8 address)
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
static u8 cached_leden; /* protected by gpio_lock */ static u8 cached_leden;
/* The LED lines are open drain outputs ... a FET pulls to GND, so an /* The LED lines are open drain outputs ... a FET pulls to GND, so an
* external pullup is needed. We could also expose the integrated PWM * external pullup is needed. We could also expose the integrated PWM
...@@ -140,14 +144,12 @@ static void twl4030_led_set_value(int led, int value) ...@@ -140,14 +144,12 @@ static void twl4030_led_set_value(int led, int value)
if (led) if (led)
mask <<= 1; mask <<= 1;
mutex_lock(&gpio_lock);
if (value) if (value)
cached_leden &= ~mask; cached_leden &= ~mask;
else else
cached_leden |= mask; cached_leden |= mask;
status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden, status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden,
TWL4030_LED_LEDEN_REG); TWL4030_LED_LEDEN_REG);
mutex_unlock(&gpio_lock);
} }
static int twl4030_set_gpio_direction(int gpio, int is_input) static int twl4030_set_gpio_direction(int gpio, int is_input)
...@@ -158,7 +160,6 @@ static int twl4030_set_gpio_direction(int gpio, int is_input) ...@@ -158,7 +160,6 @@ static int twl4030_set_gpio_direction(int gpio, int is_input)
u8 base = REG_GPIODATADIR1 + d_bnk; u8 base = REG_GPIODATADIR1 + d_bnk;
int ret = 0; int ret = 0;
mutex_lock(&gpio_lock);
ret = gpio_twl4030_read(base); ret = gpio_twl4030_read(base);
if (ret >= 0) { if (ret >= 0) {
if (is_input) if (is_input)
...@@ -168,7 +169,6 @@ static int twl4030_set_gpio_direction(int gpio, int is_input) ...@@ -168,7 +169,6 @@ static int twl4030_set_gpio_direction(int gpio, int is_input)
ret = gpio_twl4030_write(base, reg); ret = gpio_twl4030_write(base, reg);
} }
mutex_unlock(&gpio_lock);
return ret; return ret;
} }
...@@ -193,10 +193,6 @@ static int twl4030_get_gpio_datain(int gpio) ...@@ -193,10 +193,6 @@ static int twl4030_get_gpio_datain(int gpio)
u8 base = 0; u8 base = 0;
int ret = 0; int ret = 0;
if (unlikely((gpio >= TWL4030_GPIO_MAX)
|| !(gpio_usage_count & BIT(gpio))))
return -EPERM;
base = REG_GPIODATAIN1 + d_bnk; base = REG_GPIODATAIN1 + d_bnk;
ret = gpio_twl4030_read(base); ret = gpio_twl4030_read(base);
if (ret > 0) if (ret > 0)
...@@ -209,9 +205,10 @@ static int twl4030_get_gpio_datain(int gpio) ...@@ -209,9 +205,10 @@ static int twl4030_get_gpio_datain(int gpio)
static int twl_request(struct gpio_chip *chip, unsigned offset) static int twl_request(struct gpio_chip *chip, unsigned offset)
{ {
struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip);
int status = 0; int status = 0;
mutex_lock(&gpio_lock); mutex_lock(&priv->mutex);
/* Support the two LED outputs as output-only GPIOs. */ /* Support the two LED outputs as output-only GPIOs. */
if (offset >= TWL4030_GPIO_MAX) { if (offset >= TWL4030_GPIO_MAX) {
...@@ -252,7 +249,7 @@ static int twl_request(struct gpio_chip *chip, unsigned offset) ...@@ -252,7 +249,7 @@ static int twl_request(struct gpio_chip *chip, unsigned offset)
} }
/* on first use, turn GPIO module "on" */ /* on first use, turn GPIO module "on" */
if (!gpio_usage_count) { if (!priv->usage_count) {
struct twl4030_gpio_platform_data *pdata; struct twl4030_gpio_platform_data *pdata;
u8 value = MASK_GPIO_CTRL_GPIO_ON; u8 value = MASK_GPIO_CTRL_GPIO_ON;
...@@ -266,79 +263,120 @@ static int twl_request(struct gpio_chip *chip, unsigned offset) ...@@ -266,79 +263,120 @@ static int twl_request(struct gpio_chip *chip, unsigned offset)
status = gpio_twl4030_write(REG_GPIO_CTRL, value); status = gpio_twl4030_write(REG_GPIO_CTRL, value);
} }
done:
if (!status) if (!status)
gpio_usage_count |= (0x1 << offset); priv->usage_count |= BIT(offset);
done: mutex_unlock(&priv->mutex);
mutex_unlock(&gpio_lock);
return status; return status;
} }
static void twl_free(struct gpio_chip *chip, unsigned offset) static void twl_free(struct gpio_chip *chip, unsigned offset)
{ {
struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip);
mutex_lock(&priv->mutex);
if (offset >= TWL4030_GPIO_MAX) { if (offset >= TWL4030_GPIO_MAX) {
twl4030_led_set_value(offset - TWL4030_GPIO_MAX, 1); twl4030_led_set_value(offset - TWL4030_GPIO_MAX, 1);
return; goto out;
} }
mutex_lock(&gpio_lock); priv->usage_count &= ~BIT(offset);
gpio_usage_count &= ~BIT(offset);
/* on last use, switch off GPIO module */ /* on last use, switch off GPIO module */
if (!gpio_usage_count) if (!priv->usage_count)
gpio_twl4030_write(REG_GPIO_CTRL, 0x0); gpio_twl4030_write(REG_GPIO_CTRL, 0x0);
mutex_unlock(&gpio_lock); out:
mutex_unlock(&priv->mutex);
} }
static int twl_direction_in(struct gpio_chip *chip, unsigned offset) static int twl_direction_in(struct gpio_chip *chip, unsigned offset)
{ {
return (offset < TWL4030_GPIO_MAX) struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip);
? twl4030_set_gpio_direction(offset, 1) int ret;
: -EINVAL;
mutex_lock(&priv->mutex);
if (offset < TWL4030_GPIO_MAX)
ret = twl4030_set_gpio_direction(offset, 1);
else
ret = -EINVAL;
if (!ret)
priv->direction &= ~BIT(offset);
mutex_unlock(&priv->mutex);
return ret;
} }
static int twl_get(struct gpio_chip *chip, unsigned offset) static int twl_get(struct gpio_chip *chip, unsigned offset)
{ {
struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip);
int ret;
int status = 0; int status = 0;
if (offset < TWL4030_GPIO_MAX) mutex_lock(&priv->mutex);
status = twl4030_get_gpio_datain(offset); if (!(priv->usage_count & BIT(offset))) {
else if (offset == TWL4030_GPIO_MAX) ret = -EPERM;
status = cached_leden & LEDEN_LEDAON; goto out;
}
if (priv->direction & BIT(offset))
status = priv->out_state & BIT(offset);
else else
status = cached_leden & LEDEN_LEDBON; status = twl4030_get_gpio_datain(offset);
return (status < 0) ? 0 : status;
ret = (status <= 0) ? 0 : 1;
out:
mutex_unlock(&priv->mutex);
return ret;
} }
static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value) static void twl_set(struct gpio_chip *chip, unsigned offset, int value)
{ {
if (offset < TWL4030_GPIO_MAX) { struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip);
mutex_lock(&priv->mutex);
if (offset < TWL4030_GPIO_MAX)
twl4030_set_gpio_dataout(offset, value); twl4030_set_gpio_dataout(offset, value);
return twl4030_set_gpio_direction(offset, 0); else
} else {
twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value); twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value);
return 0;
} if (value)
priv->out_state |= BIT(offset);
else
priv->out_state &= ~BIT(offset);
mutex_unlock(&priv->mutex);
} }
static void twl_set(struct gpio_chip *chip, unsigned offset, int value) static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value)
{ {
struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip);
mutex_lock(&priv->mutex);
if (offset < TWL4030_GPIO_MAX) if (offset < TWL4030_GPIO_MAX)
twl4030_set_gpio_dataout(offset, value); twl4030_set_gpio_dataout(offset, value);
else
twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value); priv->direction |= BIT(offset);
mutex_unlock(&priv->mutex);
twl_set(chip, offset, value);
return 0;
} }
static int twl_to_irq(struct gpio_chip *chip, unsigned offset) static int twl_to_irq(struct gpio_chip *chip, unsigned offset)
{ {
return (twl4030_gpio_irq_base && (offset < TWL4030_GPIO_MAX)) struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip);
? (twl4030_gpio_irq_base + offset)
return (priv->irq_base && (offset < TWL4030_GPIO_MAX))
? (priv->irq_base + offset)
: -EINVAL; : -EINVAL;
} }
static struct gpio_chip twl_gpiochip = { static struct gpio_chip template_chip = {
.label = "twl4030", .label = "twl4030",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.request = twl_request, .request = twl_request,
...@@ -424,8 +462,14 @@ static int gpio_twl4030_probe(struct platform_device *pdev) ...@@ -424,8 +462,14 @@ static int gpio_twl4030_probe(struct platform_device *pdev)
{ {
struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data; struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
struct device_node *node = pdev->dev.of_node; struct device_node *node = pdev->dev.of_node;
struct gpio_twl4030_priv *priv;
int ret, irq_base; int ret, irq_base;
priv = devm_kzalloc(&pdev->dev, sizeof(struct gpio_twl4030_priv),
GFP_KERNEL);
if (!priv)
return -ENOMEM;
/* maybe setup IRQs */ /* maybe setup IRQs */
if (is_module()) { if (is_module()) {
dev_err(&pdev->dev, "can't dispatch IRQs from modules\n"); dev_err(&pdev->dev, "can't dispatch IRQs from modules\n");
...@@ -445,12 +489,15 @@ static int gpio_twl4030_probe(struct platform_device *pdev) ...@@ -445,12 +489,15 @@ static int gpio_twl4030_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
return ret; return ret;
twl4030_gpio_irq_base = irq_base; priv->irq_base = irq_base;
no_irqs: no_irqs:
twl_gpiochip.base = -1; priv->gpio_chip = template_chip;
twl_gpiochip.ngpio = TWL4030_GPIO_MAX; priv->gpio_chip.base = -1;
twl_gpiochip.dev = &pdev->dev; priv->gpio_chip.ngpio = TWL4030_GPIO_MAX;
priv->gpio_chip.dev = &pdev->dev;
mutex_init(&priv->mutex);
if (node) if (node)
pdata = of_gpio_twl4030(&pdev->dev); pdata = of_gpio_twl4030(&pdev->dev);
...@@ -481,23 +528,23 @@ static int gpio_twl4030_probe(struct platform_device *pdev) ...@@ -481,23 +528,23 @@ static int gpio_twl4030_probe(struct platform_device *pdev)
* is (still) clear if use_leds is set. * is (still) clear if use_leds is set.
*/ */
if (pdata->use_leds) if (pdata->use_leds)
twl_gpiochip.ngpio += 2; priv->gpio_chip.ngpio += 2;
ret = gpiochip_add(&twl_gpiochip); ret = gpiochip_add(&priv->gpio_chip);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret); dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret);
twl_gpiochip.ngpio = 0; priv->gpio_chip.ngpio = 0;
gpio_twl4030_remove(pdev); gpio_twl4030_remove(pdev);
goto out; goto out;
} }
twl4030_gpio_base = twl_gpiochip.base; platform_set_drvdata(pdev, priv);
if (pdata && pdata->setup) { if (pdata && pdata->setup) {
int status; int status;
status = pdata->setup(&pdev->dev, status = pdata->setup(&pdev->dev, priv->gpio_chip.base,
twl4030_gpio_base, TWL4030_GPIO_MAX); TWL4030_GPIO_MAX);
if (status) if (status)
dev_dbg(&pdev->dev, "setup --> %d\n", status); dev_dbg(&pdev->dev, "setup --> %d\n", status);
} }
...@@ -510,18 +557,19 @@ static int gpio_twl4030_probe(struct platform_device *pdev) ...@@ -510,18 +557,19 @@ static int gpio_twl4030_probe(struct platform_device *pdev)
static int gpio_twl4030_remove(struct platform_device *pdev) static int gpio_twl4030_remove(struct platform_device *pdev)
{ {
struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data; struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
struct gpio_twl4030_priv *priv = platform_get_drvdata(pdev);
int status; int status;
if (pdata && pdata->teardown) { if (pdata && pdata->teardown) {
status = pdata->teardown(&pdev->dev, status = pdata->teardown(&pdev->dev, priv->gpio_chip.base,
twl4030_gpio_base, TWL4030_GPIO_MAX); TWL4030_GPIO_MAX);
if (status) { if (status) {
dev_dbg(&pdev->dev, "teardown --> %d\n", status); dev_dbg(&pdev->dev, "teardown --> %d\n", status);
return status; return status;
} }
} }
status = gpiochip_remove(&twl_gpiochip); status = gpiochip_remove(&priv->gpio_chip);
if (status < 0) if (status < 0)
return status; return status;
......
...@@ -73,19 +73,20 @@ struct vt8500_gpio_data { ...@@ -73,19 +73,20 @@ struct vt8500_gpio_data {
static struct vt8500_gpio_data vt8500_data = { static struct vt8500_gpio_data vt8500_data = {
.num_banks = 7, .num_banks = 7,
.banks = { .banks = {
VT8500_BANK(NO_REG, 0x3C, 0x5C, 0x7C, 9),
VT8500_BANK(0x00, 0x20, 0x40, 0x60, 26), VT8500_BANK(0x00, 0x20, 0x40, 0x60, 26),
VT8500_BANK(0x04, 0x24, 0x44, 0x64, 28), VT8500_BANK(0x04, 0x24, 0x44, 0x64, 28),
VT8500_BANK(0x08, 0x28, 0x48, 0x68, 31), VT8500_BANK(0x08, 0x28, 0x48, 0x68, 31),
VT8500_BANK(0x0C, 0x2C, 0x4C, 0x6C, 19), VT8500_BANK(0x0C, 0x2C, 0x4C, 0x6C, 19),
VT8500_BANK(0x10, 0x30, 0x50, 0x70, 19), VT8500_BANK(0x10, 0x30, 0x50, 0x70, 19),
VT8500_BANK(0x14, 0x34, 0x54, 0x74, 23), VT8500_BANK(0x14, 0x34, 0x54, 0x74, 23),
VT8500_BANK(NO_REG, 0x3C, 0x5C, 0x7C, 9),
}, },
}; };
static struct vt8500_gpio_data wm8505_data = { static struct vt8500_gpio_data wm8505_data = {
.num_banks = 10, .num_banks = 10,
.banks = { .banks = {
VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22),
VT8500_BANK(0x40, 0x68, 0x90, 0xB8, 8), VT8500_BANK(0x40, 0x68, 0x90, 0xB8, 8),
VT8500_BANK(0x44, 0x6C, 0x94, 0xBC, 32), VT8500_BANK(0x44, 0x6C, 0x94, 0xBC, 32),
VT8500_BANK(0x48, 0x70, 0x98, 0xC0, 6), VT8500_BANK(0x48, 0x70, 0x98, 0xC0, 6),
...@@ -95,7 +96,6 @@ static struct vt8500_gpio_data wm8505_data = { ...@@ -95,7 +96,6 @@ static struct vt8500_gpio_data wm8505_data = {
VT8500_BANK(0x58, 0x80, 0xA8, 0xD0, 5), VT8500_BANK(0x58, 0x80, 0xA8, 0xD0, 5),
VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12), VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12),
VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16), VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16),
VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22),
VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6), VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6),
}, },
}; };
...@@ -127,6 +127,12 @@ struct vt8500_gpio_chip { ...@@ -127,6 +127,12 @@ struct vt8500_gpio_chip {
void __iomem *base; void __iomem *base;
}; };
struct vt8500_data {
struct vt8500_gpio_chip *chip;
void __iomem *iobase;
int num_banks;
};
#define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip) #define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip)
...@@ -224,19 +230,32 @@ static int vt8500_of_xlate(struct gpio_chip *gc, ...@@ -224,19 +230,32 @@ static int vt8500_of_xlate(struct gpio_chip *gc,
static int vt8500_add_chips(struct platform_device *pdev, void __iomem *base, static int vt8500_add_chips(struct platform_device *pdev, void __iomem *base,
const struct vt8500_gpio_data *data) const struct vt8500_gpio_data *data)
{ {
struct vt8500_data *priv;
struct vt8500_gpio_chip *vtchip; struct vt8500_gpio_chip *vtchip;
struct gpio_chip *chip; struct gpio_chip *chip;
int i; int i;
int pin_cnt = 0; int pin_cnt = 0;
vtchip = devm_kzalloc(&pdev->dev, priv = devm_kzalloc(&pdev->dev, sizeof(struct vt8500_data), GFP_KERNEL);
if (!priv) {
dev_err(&pdev->dev, "failed to allocate memory\n");
return -ENOMEM;
}
priv->chip = devm_kzalloc(&pdev->dev,
sizeof(struct vt8500_gpio_chip) * data->num_banks, sizeof(struct vt8500_gpio_chip) * data->num_banks,
GFP_KERNEL); GFP_KERNEL);
if (!vtchip) { if (!priv->chip) {
pr_err("%s: failed to allocate chip memory\n", __func__); dev_err(&pdev->dev, "failed to allocate chip memory\n");
return -ENOMEM; return -ENOMEM;
} }
priv->iobase = base;
priv->num_banks = data->num_banks;
platform_set_drvdata(pdev, priv);
vtchip = priv->chip;
for (i = 0; i < data->num_banks; i++) { for (i = 0; i < data->num_banks; i++) {
vtchip[i].base = base; vtchip[i].base = base;
vtchip[i].regs = &data->banks[i]; vtchip[i].regs = &data->banks[i];
...@@ -273,36 +292,54 @@ static struct of_device_id vt8500_gpio_dt_ids[] = { ...@@ -273,36 +292,54 @@ static struct of_device_id vt8500_gpio_dt_ids[] = {
static int vt8500_gpio_probe(struct platform_device *pdev) static int vt8500_gpio_probe(struct platform_device *pdev)
{ {
int ret;
void __iomem *gpio_base; void __iomem *gpio_base;
struct device_node *np; struct resource *res;
const struct of_device_id *of_id = const struct of_device_id *of_id =
of_match_device(vt8500_gpio_dt_ids, &pdev->dev); of_match_device(vt8500_gpio_dt_ids, &pdev->dev);
if (!of_id) { if (!of_id) {
dev_err(&pdev->dev, "Failed to find gpio controller\n"); dev_err(&pdev->dev, "No matching driver data\n");
return -ENODEV; return -ENODEV;
} }
np = pdev->dev.of_node; res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!np) { if (!res) {
dev_err(&pdev->dev, "Missing GPIO description in devicetree\n"); dev_err(&pdev->dev, "Unable to get IO resource\n");
return -EFAULT; return -ENODEV;
} }
gpio_base = of_iomap(np, 0); gpio_base = devm_request_and_ioremap(&pdev->dev, res);
if (!gpio_base) { if (!gpio_base) {
dev_err(&pdev->dev, "Unable to map GPIO registers\n"); dev_err(&pdev->dev, "Unable to map GPIO registers\n");
of_node_put(np);
return -ENOMEM; return -ENOMEM;
} }
vt8500_add_chips(pdev, gpio_base, of_id->data); ret = vt8500_add_chips(pdev, gpio_base, of_id->data);
return ret;
}
static int vt8500_gpio_remove(struct platform_device *pdev)
{
int i;
int ret;
struct vt8500_data *priv = platform_get_drvdata(pdev);
struct vt8500_gpio_chip *vtchip = priv->chip;
for (i = 0; i < priv->num_banks; i++) {
ret = gpiochip_remove(&vtchip[i].chip);
if (ret)
dev_warn(&pdev->dev, "gpiochip_remove returned %d\n",
ret);
}
return 0; return 0;
} }
static struct platform_driver vt8500_gpio_driver = { static struct platform_driver vt8500_gpio_driver = {
.probe = vt8500_gpio_probe, .probe = vt8500_gpio_probe,
.remove = vt8500_gpio_remove,
.driver = { .driver = {
.name = "vt8500-gpio", .name = "vt8500-gpio",
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/acpi_gpio.h> #include <linux/acpi_gpio.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/interrupt.h>
static int acpi_gpiochip_find(struct gpio_chip *gc, void *data) static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
{ {
...@@ -52,3 +53,89 @@ int acpi_get_gpio(char *path, int pin) ...@@ -52,3 +53,89 @@ int acpi_get_gpio(char *path, int pin)
return chip->base + pin; return chip->base + pin;
} }
EXPORT_SYMBOL_GPL(acpi_get_gpio); EXPORT_SYMBOL_GPL(acpi_get_gpio);
static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)
{
acpi_handle handle = data;
acpi_evaluate_object(handle, NULL, NULL, NULL);
return IRQ_HANDLED;
}
/**
* acpi_gpiochip_request_interrupts() - Register isr for gpio chip ACPI events
* @chip: gpio chip
*
* ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are
* handled by ACPI event methods which need to be called from the GPIO
* chip's interrupt handler. acpi_gpiochip_request_interrupts finds out which
* gpio pins have acpi event methods and assigns interrupt handlers that calls
* the acpi event methods for those pins.
*
* Interrupts are automatically freed on driver detach
*/
void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
{
struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
struct acpi_resource *res;
acpi_handle handle, ev_handle;
acpi_status status;
unsigned int pin;
int irq, ret;
char ev_name[5];
if (!chip->dev || !chip->to_irq)
return;
handle = ACPI_HANDLE(chip->dev);
if (!handle)
return;
status = acpi_get_event_resources(handle, &buf);
if (ACPI_FAILURE(status))
return;
/* If a gpio interrupt has an acpi event handler method, then
* set up an interrupt handler that calls the acpi event handler
*/
for (res = buf.pointer;
res && (res->type != ACPI_RESOURCE_TYPE_END_TAG);
res = ACPI_NEXT_RESOURCE(res)) {
if (res->type != ACPI_RESOURCE_TYPE_GPIO ||
res->data.gpio.connection_type !=
ACPI_RESOURCE_GPIO_TYPE_INT)
continue;
pin = res->data.gpio.pin_table[0];
if (pin > chip->ngpio)
continue;
sprintf(ev_name, "_%c%02X",
res->data.gpio.triggering ? 'E' : 'L', pin);
status = acpi_get_handle(handle, ev_name, &ev_handle);
if (ACPI_FAILURE(status))
continue;
irq = chip->to_irq(chip, pin);
if (irq < 0)
continue;
/* Assume BIOS sets the triggering, so no flags */
ret = devm_request_threaded_irq(chip->dev, irq, NULL,
acpi_gpio_irq_handler,
0,
"GPIO-signaled-ACPI-event",
ev_handle);
if (ret)
dev_err(chip->dev,
"Failed to request IRQ %d ACPI event handler\n",
irq);
}
}
EXPORT_SYMBOL(acpi_gpiochip_request_interrupts);
This diff is collapsed.
...@@ -47,12 +47,14 @@ struct gpio; ...@@ -47,12 +47,14 @@ struct gpio;
struct seq_file; struct seq_file;
struct module; struct module;
struct device_node; struct device_node;
struct gpio_desc;
/** /**
* struct gpio_chip - abstract a GPIO controller * struct gpio_chip - abstract a GPIO controller
* @label: for diagnostics * @label: for diagnostics
* @dev: optional device providing the GPIOs * @dev: optional device providing the GPIOs
* @owner: helps prevent removal of modules exporting active GPIOs * @owner: helps prevent removal of modules exporting active GPIOs
* @list: links gpio_chips together for traversal
* @request: optional hook for chip-specific activation, such as * @request: optional hook for chip-specific activation, such as
* enabling module power and clock; may sleep * enabling module power and clock; may sleep
* @free: optional hook for chip-specific deactivation, such as * @free: optional hook for chip-specific deactivation, such as
...@@ -75,6 +77,7 @@ struct device_node; ...@@ -75,6 +77,7 @@ struct device_node;
* negative during registration, requests dynamic ID allocation. * negative during registration, requests dynamic ID allocation.
* @ngpio: the number of GPIOs handled by this controller; the last GPIO * @ngpio: the number of GPIOs handled by this controller; the last GPIO
* handled is (base + ngpio - 1). * handled is (base + ngpio - 1).
* @desc: array of ngpio descriptors. Private.
* @can_sleep: flag must be set iff get()/set() methods sleep, as they * @can_sleep: flag must be set iff get()/set() methods sleep, as they
* must while accessing GPIO expander chips over I2C or SPI * must while accessing GPIO expander chips over I2C or SPI
* @names: if set, must be an array of strings to use as alternative * @names: if set, must be an array of strings to use as alternative
...@@ -98,6 +101,7 @@ struct gpio_chip { ...@@ -98,6 +101,7 @@ struct gpio_chip {
const char *label; const char *label;
struct device *dev; struct device *dev;
struct module *owner; struct module *owner;
struct list_head list;
int (*request)(struct gpio_chip *chip, int (*request)(struct gpio_chip *chip,
unsigned offset); unsigned offset);
...@@ -124,6 +128,7 @@ struct gpio_chip { ...@@ -124,6 +128,7 @@ struct gpio_chip {
struct gpio_chip *chip); struct gpio_chip *chip);
int base; int base;
u16 ngpio; u16 ngpio;
struct gpio_desc *desc;
const char *const *names; const char *const *names;
unsigned can_sleep:1; unsigned can_sleep:1;
unsigned exported:1; unsigned exported:1;
...@@ -152,7 +157,6 @@ struct gpio_chip { ...@@ -152,7 +157,6 @@ struct gpio_chip {
extern const char *gpiochip_is_requested(struct gpio_chip *chip, extern const char *gpiochip_is_requested(struct gpio_chip *chip,
unsigned offset); unsigned offset);
extern struct gpio_chip *gpio_to_chip(unsigned gpio); extern struct gpio_chip *gpio_to_chip(unsigned gpio);
extern int __must_check gpiochip_reserve(int start, int ngpio);
/* add/remove chips */ /* add/remove chips */
extern int gpiochip_add(struct gpio_chip *chip); extern int gpiochip_add(struct gpio_chip *chip);
...@@ -192,12 +196,6 @@ extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *labe ...@@ -192,12 +196,6 @@ extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *labe
extern int gpio_request_array(const struct gpio *array, size_t num); extern int gpio_request_array(const struct gpio *array, size_t num);
extern void gpio_free_array(const struct gpio *array, size_t num); extern void gpio_free_array(const struct gpio *array, size_t num);
/* bindings for managed devices that want to request gpios */
int devm_gpio_request(struct device *dev, unsigned gpio, const char *label);
int devm_gpio_request_one(struct device *dev, unsigned gpio,
unsigned long flags, const char *label);
void devm_gpio_free(struct device *dev, unsigned int gpio);
#ifdef CONFIG_GPIO_SYSFS #ifdef CONFIG_GPIO_SYSFS
/* /*
...@@ -212,6 +210,43 @@ extern void gpio_unexport(unsigned gpio); ...@@ -212,6 +210,43 @@ extern void gpio_unexport(unsigned gpio);
#endif /* CONFIG_GPIO_SYSFS */ #endif /* CONFIG_GPIO_SYSFS */
#ifdef CONFIG_PINCTRL
/**
* struct gpio_pin_range - pin range controlled by a gpio chip
* @head: list for maintaining set of pin ranges, used internally
* @pctldev: pinctrl device which handles corresponding pins
* @range: actual range of pins controlled by a gpio controller
*/
struct gpio_pin_range {
struct list_head node;
struct pinctrl_dev *pctldev;
struct pinctrl_gpio_range range;
};
int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
unsigned int gpio_offset, unsigned int pin_offset,
unsigned int npins);
void gpiochip_remove_pin_ranges(struct gpio_chip *chip);
#else
static inline int
gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
unsigned int gpio_offset, unsigned int pin_offset,
unsigned int npins)
{
return 0;
}
static inline void
gpiochip_remove_pin_ranges(struct gpio_chip *chip)
{
}
#endif /* CONFIG_PINCTRL */
#else /* !CONFIG_GPIOLIB */ #else /* !CONFIG_GPIOLIB */
static inline bool gpio_is_valid(int number) static inline bool gpio_is_valid(int number)
...@@ -270,41 +305,4 @@ static inline void gpio_unexport(unsigned gpio) ...@@ -270,41 +305,4 @@ static inline void gpio_unexport(unsigned gpio)
} }
#endif /* CONFIG_GPIO_SYSFS */ #endif /* CONFIG_GPIO_SYSFS */
#ifdef CONFIG_PINCTRL
/**
* struct gpio_pin_range - pin range controlled by a gpio chip
* @head: list for maintaining set of pin ranges, used internally
* @pctldev: pinctrl device which handles corresponding pins
* @range: actual range of pins controlled by a gpio controller
*/
struct gpio_pin_range {
struct list_head node;
struct pinctrl_dev *pctldev;
struct pinctrl_gpio_range range;
};
int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
unsigned int gpio_offset, unsigned int pin_offset,
unsigned int npins);
void gpiochip_remove_pin_ranges(struct gpio_chip *chip);
#else
static inline int
gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
unsigned int gpio_offset, unsigned int pin_offset,
unsigned int npins)
{
return 0;
}
static inline void
gpiochip_remove_pin_ranges(struct gpio_chip *chip)
{
}
#endif /* CONFIG_PINCTRL */
#endif /* _ASM_GENERIC_GPIO_H */ #endif /* _ASM_GENERIC_GPIO_H */
...@@ -2,10 +2,12 @@ ...@@ -2,10 +2,12 @@
#define _LINUX_ACPI_GPIO_H_ #define _LINUX_ACPI_GPIO_H_
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/gpio.h>
#ifdef CONFIG_GPIO_ACPI #ifdef CONFIG_GPIO_ACPI
int acpi_get_gpio(char *path, int pin); int acpi_get_gpio(char *path, int pin);
void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
#else /* CONFIG_GPIO_ACPI */ #else /* CONFIG_GPIO_ACPI */
...@@ -14,6 +16,8 @@ static inline int acpi_get_gpio(char *path, int pin) ...@@ -14,6 +16,8 @@ static inline int acpi_get_gpio(char *path, int pin)
return -ENODEV; return -ENODEV;
} }
static inline void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { }
#endif /* CONFIG_GPIO_ACPI */ #endif /* CONFIG_GPIO_ACPI */
#endif /* _LINUX_ACPI_GPIO_H_ */ #endif /* _LINUX_ACPI_GPIO_H_ */
...@@ -94,24 +94,12 @@ static inline int gpio_request(unsigned gpio, const char *label) ...@@ -94,24 +94,12 @@ static inline int gpio_request(unsigned gpio, const char *label)
return -ENOSYS; return -ENOSYS;
} }
static inline int devm_gpio_request(struct device *dev, unsigned gpio,
const char *label)
{
return -ENOSYS;
}
static inline int gpio_request_one(unsigned gpio, static inline int gpio_request_one(unsigned gpio,
unsigned long flags, const char *label) unsigned long flags, const char *label)
{ {
return -ENOSYS; return -ENOSYS;
} }
static inline int devm_gpio_request_one(struct device *dev, unsigned gpio,
unsigned long flags, const char *label)
{
return -ENOSYS;
}
static inline int gpio_request_array(const struct gpio *array, size_t num) static inline int gpio_request_array(const struct gpio *array, size_t num)
{ {
return -ENOSYS; return -ENOSYS;
...@@ -125,14 +113,6 @@ static inline void gpio_free(unsigned gpio) ...@@ -125,14 +113,6 @@ static inline void gpio_free(unsigned gpio)
WARN_ON(1); WARN_ON(1);
} }
static inline void devm_gpio_free(struct device *dev, unsigned gpio)
{
might_sleep();
/* GPIO can never have been requested */
WARN_ON(1);
}
static inline void gpio_free_array(const struct gpio *array, size_t num) static inline void gpio_free_array(const struct gpio *array, size_t num)
{ {
might_sleep(); might_sleep();
...@@ -248,4 +228,12 @@ gpiochip_remove_pin_ranges(struct gpio_chip *chip) ...@@ -248,4 +228,12 @@ gpiochip_remove_pin_ranges(struct gpio_chip *chip)
#endif /* ! CONFIG_GENERIC_GPIO */ #endif /* ! CONFIG_GENERIC_GPIO */
struct device;
/* bindings for managed devices that want to request gpios */
int devm_gpio_request(struct device *dev, unsigned gpio, const char *label);
int devm_gpio_request_one(struct device *dev, unsigned gpio,
unsigned long flags, const char *label);
void devm_gpio_free(struct device *dev, unsigned int gpio);
#endif /* __LINUX_GPIO_H */ #endif /* __LINUX_GPIO_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment