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)
static void __init tosa_init(void)
{
int dummy;
pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_config));
pxa_set_ffuart_info(NULL);
......@@ -947,10 +945,6 @@ static void __init tosa_init(void)
/* enable batt_fault */
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_ficp_info(&tosa_ficp_platform_data);
pxa_set_i2c_info(NULL);
......
config ARM64
def_bool y
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
select ARCH_WANT_OPTIONAL_GPIOLIB
select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
select ARCH_WANT_FRAME_POINTERS
select ARM_AMBA
......@@ -93,7 +94,7 @@ config IOMMU_HELPER
def_bool SWIOTLB
config GENERIC_GPIO
def_bool y
bool
source "init/Kconfig"
......
......@@ -30,6 +30,9 @@ config ARCH_REQUIRE_GPIOLIB
Selecting this from the architecture code will cause the gpiolib
code to always get built in.
config GPIO_DEVRES
def_bool y
depends on HAS_IOMEM
menuconfig GPIOLIB
......@@ -298,6 +301,14 @@ config GPIO_GE_FPGA
and write pin state) for GPIO implemented in a number of GE single
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:"
config GPIO_ARIZONA
......
......@@ -2,7 +2,8 @@
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_GPIO_ACPI) += gpiolib-acpi.o
......@@ -30,6 +31,7 @@ obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o
obj-$(CONFIG_GPIO_LANGWELL) += gpio-langwell.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_MAX7300) += gpio-max7300.o
obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o
......
......@@ -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->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->irq_base,
&em_gio_irq_domain_ops, p);
if (!p->irq_domain) {
ret = -ENXIO;
......
......@@ -71,10 +71,12 @@ struct lnw_gpio {
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,
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;
u8 reg = offset / 32;
void __iomem *ptr;
......@@ -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,
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;
u8 reg = offset / 16;
void __iomem *ptr;
......@@ -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)
{
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);
u32 value;
unsigned long flags;
......@@ -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,
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);
unsigned long flags;
......@@ -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)
{
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);
}
......@@ -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, 0x081f), .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, }
};
MODULE_DEVICE_TABLE(pci, lnw_gpio_ids);
......@@ -299,17 +303,6 @@ static const struct irq_domain_ops lnw_gpio_irq_ops = {
.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)
{
int err = pm_schedule_suspend(dev, 500);
......@@ -320,16 +313,8 @@ static int lnw_gpio_runtime_idle(struct device *dev)
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 = {
.runtime_suspend = lnw_gpio_runtime_suspend,
.runtime_resume = lnw_gpio_runtime_resume,
.runtime_idle = lnw_gpio_runtime_idle,
SET_RUNTIME_PM_OPS(NULL, NULL, lnw_gpio_runtime_idle)
};
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");
if (retval) {
dev_err(&pdev->dev, "error requesting resources\n");
goto err2;
goto err_pci_req_region;
}
/* get the gpio_base from bar1 */
start = pci_resource_start(pdev, 1);
......@@ -358,7 +343,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
if (!base) {
dev_err(&pdev->dev, "error mapping bar1\n");
retval = -EFAULT;
goto err3;
goto err_ioremap;
}
gpio_base = *((u32 *)base + 1);
/* 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,
if (!base) {
dev_err(&pdev->dev, "error mapping bar0\n");
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) {
dev_err(&pdev->dev, "can't allocate langwell_gpio chip data\n");
retval = -ENOMEM;
goto err3;
goto err_ioremap;
}
lnw->domain = irq_domain_add_linear(pdev->dev.of_node, ngpio,
&lnw_gpio_irq_ops, lnw);
if (!lnw->domain) {
retval = -ENOMEM;
goto err3;
goto err_ioremap;
}
lnw->reg_base = base;
......@@ -403,7 +388,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
retval = gpiochip_add(&lnw->chip);
if (retval) {
dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval);
goto err3;
goto err_ioremap;
}
lnw_irq_init_hw(lnw);
......@@ -418,9 +403,9 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
return 0;
err3:
err_ioremap:
pci_release_regions(pdev);
err2:
err_pci_req_region:
pci_disable_device(pdev);
return retval;
}
......
/*
* GPIO controller driver for Intel Lynxpoint PCH chipset>
* Copyright (c) 2012, Intel Corporation.
*
* Author: Mathias Nyman <mathias.nyman@linux.intel.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/irqdomain.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
/* LynxPoint chipset has support for 94 gpio pins */
#define LP_NUM_GPIO 94
/* Bitmapped register offsets */
#define LP_ACPI_OWNED 0x00 /* Bitmap, set by bios, 0: pin reserved for ACPI */
#define LP_GC 0x7C /* set APIC IRQ to IRQ14 or IRQ15 for all pins */
#define LP_INT_STAT 0x80
#define LP_INT_ENABLE 0x90
/* Each pin has two 32 bit config registers, starting at 0x100 */
#define LP_CONFIG1 0x100
#define LP_CONFIG2 0x104
/* LP_CONFIG1 reg bits */
#define OUT_LVL_BIT BIT(31)
#define IN_LVL_BIT BIT(30)
#define TRIG_SEL_BIT BIT(4) /* 0: Edge, 1: Level */
#define INT_INV_BIT BIT(3) /* Invert interrupt triggering */
#define DIR_BIT BIT(2) /* 0: Output, 1: Input */
#define USE_SEL_BIT BIT(0) /* 0: Native, 1: GPIO */
/* LP_CONFIG2 reg bits */
#define GPINDIS_BIT BIT(2) /* disable input sensing */
#define GPIWP_BIT (BIT(0) | BIT(1)) /* weak pull options */
struct lp_gpio {
struct gpio_chip chip;
struct irq_domain *domain;
struct platform_device *pdev;
spinlock_t lock;
unsigned long reg_base;
};
/*
* Lynxpoint gpios are controlled through both bitmapped registers and
* per gpio specific registers. The bitmapped registers are in chunks of
* 3 x 32bit registers to cover all 94 gpios
*
* per gpio specific registers consist of two 32bit registers per gpio
* (LP_CONFIG1 and LP_CONFIG2), with 94 gpios there's a total of
* 188 config registes.
*
* A simplified view of the register layout look like this:
*
* LP_ACPI_OWNED[31:0] gpio ownerships for gpios 0-31 (bitmapped registers)
* LP_ACPI_OWNED[63:32] gpio ownerships for gpios 32-63
* LP_ACPI_OWNED[94:64] gpio ownerships for gpios 63-94
* ...
* LP_INT_ENABLE[31:0] ...
* LP_INT_ENABLE[63:31] ...
* LP_INT_ENABLE[94:64] ...
* LP0_CONFIG1 (gpio 0) config1 reg for gpio 0 (per gpio registers)
* LP0_CONFIG2 (gpio 0) config2 reg for gpio 0
* LP1_CONFIG1 (gpio 1) config1 reg for gpio 1
* LP1_CONFIG2 (gpio 1) config2 reg for gpio 1
* LP2_CONFIG1 (gpio 2) ...
* LP2_CONFIG2 (gpio 2) ...
* ...
* LP94_CONFIG1 (gpio 94) ...
* LP94_CONFIG2 (gpio 94) ...
*/
static unsigned long lp_gpio_reg(struct gpio_chip *chip, unsigned offset,
int reg)
{
struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip);
int reg_offset;
if (reg == LP_CONFIG1 || reg == LP_CONFIG2)
/* per gpio specific config registers */
reg_offset = offset * 8;
else
/* bitmapped registers */
reg_offset = (offset / 32) * 4;
return lg->reg_base + reg + reg_offset;
}
static int lp_gpio_request(struct gpio_chip *chip, unsigned offset)
{
struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip);
unsigned long reg = lp_gpio_reg(chip, offset, LP_CONFIG1);
unsigned long conf2 = lp_gpio_reg(chip, offset, LP_CONFIG2);
unsigned long acpi_use = lp_gpio_reg(chip, offset, LP_ACPI_OWNED);
pm_runtime_get(&lg->pdev->dev); /* should we put if failed */
/* Fail if BIOS reserved pin for ACPI use */
if (!(inl(acpi_use) & BIT(offset % 32))) {
dev_err(&lg->pdev->dev, "gpio %d reserved for ACPI\n", offset);
return -EBUSY;
}
/* Fail if pin is in alternate function mode (not GPIO mode) */
if (!(inl(reg) & USE_SEL_BIT))
return -ENODEV;
/* enable input sensing */
outl(inl(conf2) & ~GPINDIS_BIT, conf2);
return 0;
}
static void lp_gpio_free(struct gpio_chip *chip, unsigned offset)
{
struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip);
unsigned long conf2 = lp_gpio_reg(chip, offset, LP_CONFIG2);
/* disable input sensing */
outl(inl(conf2) | GPINDIS_BIT, conf2);
pm_runtime_put(&lg->pdev->dev);
}
static int lp_irq_type(struct irq_data *d, unsigned type)
{
struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
u32 hwirq = irqd_to_hwirq(d);
unsigned long flags;
u32 value;
unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_CONFIG1);
if (hwirq >= lg->chip.ngpio)
return -EINVAL;
spin_lock_irqsave(&lg->lock, flags);
value = inl(reg);
/* set both TRIG_SEL and INV bits to 0 for rising edge */
if (type & IRQ_TYPE_EDGE_RISING)
value &= ~(TRIG_SEL_BIT | INT_INV_BIT);
/* TRIG_SEL bit 0, INV bit 1 for falling edge */
if (type & IRQ_TYPE_EDGE_FALLING)
value = (value | INT_INV_BIT) & ~TRIG_SEL_BIT;
/* TRIG_SEL bit 1, INV bit 0 for level low */
if (type & IRQ_TYPE_LEVEL_LOW)
value = (value | TRIG_SEL_BIT) & ~INT_INV_BIT;
/* TRIG_SEL bit 1, INV bit 1 for level high */
if (type & IRQ_TYPE_LEVEL_HIGH)
value |= TRIG_SEL_BIT | INT_INV_BIT;
outl(value, reg);
spin_unlock_irqrestore(&lg->lock, flags);
return 0;
}
static int lp_gpio_get(struct gpio_chip *chip, unsigned offset)
{
unsigned long reg = lp_gpio_reg(chip, offset, LP_CONFIG1);
return inl(reg) & IN_LVL_BIT;
}
static void lp_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip);
unsigned long reg = lp_gpio_reg(chip, offset, LP_CONFIG1);
unsigned long flags;
spin_lock_irqsave(&lg->lock, flags);
if (value)
outl(inl(reg) | OUT_LVL_BIT, reg);
else
outl(inl(reg) & ~OUT_LVL_BIT, reg);
spin_unlock_irqrestore(&lg->lock, flags);
}
static int lp_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip);
unsigned long reg = lp_gpio_reg(chip, offset, LP_CONFIG1);
unsigned long flags;
spin_lock_irqsave(&lg->lock, flags);
outl(inl(reg) | DIR_BIT, reg);
spin_unlock_irqrestore(&lg->lock, flags);
return 0;
}
static int lp_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value)
{
struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip);
unsigned long reg = lp_gpio_reg(chip, offset, LP_CONFIG1);
unsigned long flags;
lp_gpio_set(chip, offset, value);
spin_lock_irqsave(&lg->lock, flags);
outl(inl(reg) & ~DIR_BIT, reg);
spin_unlock_irqrestore(&lg->lock, flags);
return 0;
}
static int lp_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip);
return irq_create_mapping(lg->domain, offset);
}
static void lp_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
{
struct irq_data *data = irq_desc_get_irq_data(desc);
struct lp_gpio *lg = irq_data_get_irq_handler_data(data);
struct irq_chip *chip = irq_data_get_irq_chip(data);
u32 base, pin, mask;
unsigned long reg, pending;
unsigned virq;
/* check from GPIO controller which pin triggered the interrupt */
for (base = 0; base < lg->chip.ngpio; base += 32) {
reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT);
while ((pending = inl(reg))) {
pin = __ffs(pending);
mask = BIT(pin);
/* Clear before handling so we don't lose an edge */
outl(mask, reg);
virq = irq_find_mapping(lg->domain, base + pin);
generic_handle_irq(virq);
}
}
chip->irq_eoi(data);
}
static void lp_irq_unmask(struct irq_data *d)
{
}
static void lp_irq_mask(struct irq_data *d)
{
}
static void lp_irq_enable(struct irq_data *d)
{
struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
u32 hwirq = irqd_to_hwirq(d);
unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE);
unsigned long flags;
spin_lock_irqsave(&lg->lock, flags);
outl(inl(reg) | BIT(hwirq % 32), reg);
spin_unlock_irqrestore(&lg->lock, flags);
}
static void lp_irq_disable(struct irq_data *d)
{
struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
u32 hwirq = irqd_to_hwirq(d);
unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE);
unsigned long flags;
spin_lock_irqsave(&lg->lock, flags);
outl(inl(reg) & ~BIT(hwirq % 32), reg);
spin_unlock_irqrestore(&lg->lock, flags);
}
static struct irq_chip lp_irqchip = {
.name = "LP-GPIO",
.irq_mask = lp_irq_mask,
.irq_unmask = lp_irq_unmask,
.irq_enable = lp_irq_enable,
.irq_disable = lp_irq_disable,
.irq_set_type = lp_irq_type,
.flags = IRQCHIP_SKIP_SET_WAKE,
};
static void lp_gpio_irq_init_hw(struct lp_gpio *lg)
{
unsigned long reg;
unsigned base;
for (base = 0; base < lg->chip.ngpio; base += 32) {
/* disable gpio pin interrupts */
reg = lp_gpio_reg(&lg->chip, base, LP_INT_ENABLE);
outl(0, reg);
/* Clear interrupt status register */
reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT);
outl(0xffffffff, reg);
}
}
static int lp_gpio_irq_map(struct irq_domain *d, unsigned int virq,
irq_hw_number_t hw)
{
struct lp_gpio *lg = d->host_data;
irq_set_chip_and_handler_name(virq, &lp_irqchip, handle_simple_irq,
"demux");
irq_set_chip_data(virq, lg);
irq_set_irq_type(virq, IRQ_TYPE_NONE);
return 0;
}
static const struct irq_domain_ops lp_gpio_irq_ops = {
.map = lp_gpio_irq_map,
};
static int lp_gpio_probe(struct platform_device *pdev)
{
struct lp_gpio *lg;
struct gpio_chip *gc;
struct resource *io_rc, *irq_rc;
struct device *dev = &pdev->dev;
unsigned long reg_len;
unsigned hwirq;
int ret = -ENODEV;
lg = devm_kzalloc(dev, sizeof(struct lp_gpio), GFP_KERNEL);
if (!lg) {
dev_err(dev, "can't allocate lp_gpio chip data\n");
return -ENOMEM;
}
lg->pdev = pdev;
platform_set_drvdata(pdev, lg);
io_rc = platform_get_resource(pdev, IORESOURCE_IO, 0);
irq_rc = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!io_rc) {
dev_err(dev, "missing IO resources\n");
return -EINVAL;
}
lg->reg_base = io_rc->start;
reg_len = resource_size(io_rc);
if (!devm_request_region(dev, lg->reg_base, reg_len, "lp-gpio")) {
dev_err(dev, "failed requesting IO region 0x%x\n",
(unsigned int)lg->reg_base);
return -EBUSY;
}
spin_lock_init(&lg->lock);
gc = &lg->chip;
gc->label = dev_name(dev);
gc->owner = THIS_MODULE;
gc->request = lp_gpio_request;
gc->free = lp_gpio_free;
gc->direction_input = lp_gpio_direction_input;
gc->direction_output = lp_gpio_direction_output;
gc->get = lp_gpio_get;
gc->set = lp_gpio_set;
gc->base = -1;
gc->ngpio = LP_NUM_GPIO;
gc->can_sleep = 0;
gc->dev = dev;
/* set up interrupts */
if (irq_rc && irq_rc->start) {
hwirq = irq_rc->start;
gc->to_irq = lp_gpio_to_irq;
lg->domain = irq_domain_add_linear(NULL, LP_NUM_GPIO,
&lp_gpio_irq_ops, lg);
if (!lg->domain)
return -ENXIO;
lp_gpio_irq_init_hw(lg);
irq_set_handler_data(hwirq, lg);
irq_set_chained_handler(hwirq, lp_gpio_irq_handler);
}
ret = gpiochip_add(gc);
if (ret) {
dev_err(dev, "failed adding lp-gpio chip\n");
return ret;
}
pm_runtime_enable(dev);
return 0;
}
static int lp_gpio_runtime_suspend(struct device *dev)
{
return 0;
}
static int lp_gpio_runtime_resume(struct device *dev)
{
return 0;
}
static const struct dev_pm_ops lp_gpio_pm_ops = {
.runtime_suspend = lp_gpio_runtime_suspend,
.runtime_resume = lp_gpio_runtime_resume,
};
static const struct acpi_device_id lynxpoint_gpio_acpi_match[] = {
{ "INT33C7", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, lynxpoint_gpio_acpi_match);
static int lp_gpio_remove(struct platform_device *pdev)
{
struct lp_gpio *lg = platform_get_drvdata(pdev);
int err;
err = gpiochip_remove(&lg->chip);
if (err)
dev_warn(&pdev->dev, "failed to remove gpio_chip.\n");
platform_set_drvdata(pdev, NULL);
return 0;
}
static struct platform_driver lp_gpio_driver = {
.probe = lp_gpio_probe,
.remove = lp_gpio_remove,
.driver = {
.name = "lp_gpio",
.owner = THIS_MODULE,
.pm = &lp_gpio_pm_ops,
.acpi_match_table = ACPI_PTR(lynxpoint_gpio_acpi_match),
},
};
static int __init lp_gpio_init(void)
{
return platform_driver_register(&lp_gpio_driver);
}
subsys_initcall(lp_gpio_init);
......@@ -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_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq);
irq_set_irq_type(virq, IRQ_TYPE_NONE);
return 0;
}
......
......@@ -66,6 +66,7 @@ struct mxs_gpio_port {
struct irq_domain *domain;
struct bgpio_chip bgc;
enum mxs_gpio_id devid;
u32 both_edges;
};
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)
static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
{
u32 val;
u32 pin_mask = 1 << d->hwirq;
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct mxs_gpio_port *port = gc->private;
void __iomem *pin_addr;
int edge;
port->both_edges &= ~pin_mask;
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:
edge = GPIO_INT_RISE_EDGE;
break;
......@@ -125,6 +136,23 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
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 */
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) {
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));
irq_stat &= ~(1 << irqoffset);
}
......
......@@ -1476,19 +1476,19 @@ static struct omap_gpio_reg_offs omap4_gpio_regs = {
.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,
.bank_width = 32,
.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,
.bank_width = 32,
.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,
.bank_width = 32,
.dbck_flag = true,
......
......@@ -46,6 +46,7 @@
#define PCA957X_TYPE 0x2000
static const struct i2c_device_id pca953x_id[] = {
{ "pca9505", 40 | PCA953X_TYPE | PCA_INT, },
{ "pca9534", 8 | PCA953X_TYPE | PCA_INT, },
{ "pca9535", 16 | PCA953X_TYPE | PCA_INT, },
{ "pca9536", 4 | PCA953X_TYPE, },
......@@ -71,19 +72,23 @@ static const struct i2c_device_id pca953x_id[] = {
};
MODULE_DEVICE_TABLE(i2c, pca953x_id);
#define MAX_BANK 5
#define BANK_SZ 8
#define NBANK(chip) (chip->gpio_chip.ngpio / BANK_SZ)
struct pca953x_chip {
unsigned gpio_start;
u32 reg_output;
u32 reg_direction;
u8 reg_output[MAX_BANK];
u8 reg_direction[MAX_BANK];
struct mutex i2c_lock;
#ifdef CONFIG_GPIO_PCA953X_IRQ
struct mutex irq_lock;
u32 irq_mask;
u32 irq_stat;
u32 irq_trig_raise;
u32 irq_trig_fall;
int irq_base;
u8 irq_mask[MAX_BANK];
u8 irq_stat[MAX_BANK];
u8 irq_trig_raise[MAX_BANK];
u8 irq_trig_fall[MAX_BANK];
struct irq_domain *domain;
#endif
......@@ -93,33 +98,69 @@ struct pca953x_chip {
int chip_type;
};
static int pca953x_write_reg(struct pca953x_chip *chip, int reg, u32 val)
static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val,
int off)
{
int ret;
int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ);
int offset = off / BANK_SZ;
ret = i2c_smbus_read_byte_data(chip->client,
(reg << bank_shift) + offset);
*val = ret;
if (ret < 0) {
dev_err(&chip->client->dev, "failed reading register\n");
return ret;
}
return 0;
}
static int pca953x_write_single(struct pca953x_chip *chip, int reg, u32 val,
int off)
{
int ret = 0;
int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ);
int offset = off / BANK_SZ;
ret = i2c_smbus_write_byte_data(chip->client,
(reg << bank_shift) + offset, val);
if (ret < 0) {
dev_err(&chip->client->dev, "failed writing register\n");
return ret;
}
return 0;
}
static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val)
{
int ret = 0;
if (chip->gpio_chip.ngpio <= 8)
ret = i2c_smbus_write_byte_data(chip->client, reg, val);
else if (chip->gpio_chip.ngpio == 24) {
cpu_to_le32s(&val);
ret = i2c_smbus_write_byte_data(chip->client, reg, *val);
else if (chip->gpio_chip.ngpio >= 24) {
int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ);
ret = i2c_smbus_write_i2c_block_data(chip->client,
(reg << 2) | REG_ADDR_AI,
3,
(u8 *) &val);
(reg << bank_shift) | REG_ADDR_AI,
NBANK(chip), val);
}
else {
switch (chip->chip_type) {
case PCA953X_TYPE:
ret = i2c_smbus_write_word_data(chip->client,
reg << 1, val);
reg << 1, (u16) *val);
break;
case PCA957X_TYPE:
ret = i2c_smbus_write_byte_data(chip->client, reg << 1,
val & 0xff);
val[0]);
if (ret < 0)
break;
ret = i2c_smbus_write_byte_data(chip->client,
(reg << 1) + 1,
(val & 0xff00) >> 8);
val[1]);
break;
}
}
......@@ -132,26 +173,24 @@ static int pca953x_write_reg(struct pca953x_chip *chip, int reg, u32 val)
return 0;
}
static int pca953x_read_reg(struct pca953x_chip *chip, int reg, u32 *val)
static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val)
{
int ret;
if (chip->gpio_chip.ngpio <= 8) {
ret = i2c_smbus_read_byte_data(chip->client, reg);
*val = ret;
}
else if (chip->gpio_chip.ngpio == 24) {
*val = 0;
} else if (chip->gpio_chip.ngpio >= 24) {
int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ);
ret = i2c_smbus_read_i2c_block_data(chip->client,
(reg << 2) | REG_ADDR_AI,
3,
(u8 *) val);
le32_to_cpus(val);
(reg << bank_shift) | REG_ADDR_AI,
NBANK(chip), val);
} else {
ret = i2c_smbus_read_word_data(chip->client, reg << 1);
*val = ret;
val[0] = (u16)ret & 0xFF;
val[1] = (u16)ret >> 8;
}
if (ret < 0) {
dev_err(&chip->client->dev, "failed reading register\n");
return ret;
......@@ -163,13 +202,13 @@ static int pca953x_read_reg(struct pca953x_chip *chip, int reg, u32 *val)
static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
{
struct pca953x_chip *chip;
uint reg_val;
u8 reg_val;
int ret, offset = 0;
chip = container_of(gc, struct pca953x_chip, gpio_chip);
mutex_lock(&chip->i2c_lock);
reg_val = chip->reg_direction | (1u << off);
reg_val = chip->reg_direction[off / BANK_SZ] | (1u << (off % BANK_SZ));
switch (chip->chip_type) {
case PCA953X_TYPE:
......@@ -179,11 +218,11 @@ static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
offset = PCA957X_CFG;
break;
}
ret = pca953x_write_reg(chip, offset, reg_val);
ret = pca953x_write_single(chip, offset, reg_val, off);
if (ret)
goto exit;
chip->reg_direction = reg_val;
chip->reg_direction[off / BANK_SZ] = reg_val;
ret = 0;
exit:
mutex_unlock(&chip->i2c_lock);
......@@ -194,7 +233,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
unsigned off, int val)
{
struct pca953x_chip *chip;
uint reg_val;
u8 reg_val;
int ret, offset = 0;
chip = container_of(gc, struct pca953x_chip, gpio_chip);
......@@ -202,9 +241,11 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
mutex_lock(&chip->i2c_lock);
/* set output level */
if (val)
reg_val = chip->reg_output | (1u << off);
reg_val = chip->reg_output[off / BANK_SZ]
| (1u << (off % BANK_SZ));
else
reg_val = chip->reg_output & ~(1u << off);
reg_val = chip->reg_output[off / BANK_SZ]
& ~(1u << (off % BANK_SZ));
switch (chip->chip_type) {
case PCA953X_TYPE:
......@@ -214,14 +255,14 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
offset = PCA957X_OUT;
break;
}
ret = pca953x_write_reg(chip, offset, reg_val);
ret = pca953x_write_single(chip, offset, reg_val, off);
if (ret)
goto exit;
chip->reg_output = reg_val;
chip->reg_output[off / BANK_SZ] = reg_val;
/* then direction */
reg_val = chip->reg_direction & ~(1u << off);
reg_val = chip->reg_direction[off / BANK_SZ] & ~(1u << (off % BANK_SZ));
switch (chip->chip_type) {
case PCA953X_TYPE:
offset = PCA953X_DIRECTION;
......@@ -230,11 +271,11 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
offset = PCA957X_CFG;
break;
}
ret = pca953x_write_reg(chip, offset, reg_val);
ret = pca953x_write_single(chip, offset, reg_val, off);
if (ret)
goto exit;
chip->reg_direction = reg_val;
chip->reg_direction[off / BANK_SZ] = reg_val;
ret = 0;
exit:
mutex_unlock(&chip->i2c_lock);
......@@ -258,7 +299,7 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
offset = PCA957X_IN;
break;
}
ret = pca953x_read_reg(chip, offset, &reg_val);
ret = pca953x_read_single(chip, offset, &reg_val, off);
mutex_unlock(&chip->i2c_lock);
if (ret < 0) {
/* NOTE: diagnostic already emitted; that's all we should
......@@ -274,16 +315,18 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
{
struct pca953x_chip *chip;
u32 reg_val;
u8 reg_val;
int ret, offset = 0;
chip = container_of(gc, struct pca953x_chip, gpio_chip);
mutex_lock(&chip->i2c_lock);
if (val)
reg_val = chip->reg_output | (1u << off);
reg_val = chip->reg_output[off / BANK_SZ]
| (1u << (off % BANK_SZ));
else
reg_val = chip->reg_output & ~(1u << off);
reg_val = chip->reg_output[off / BANK_SZ]
& ~(1u << (off % BANK_SZ));
switch (chip->chip_type) {
case PCA953X_TYPE:
......@@ -293,11 +336,11 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
offset = PCA957X_OUT;
break;
}
ret = pca953x_write_reg(chip, offset, reg_val);
ret = pca953x_write_single(chip, offset, reg_val, off);
if (ret)
goto exit;
chip->reg_output = reg_val;
chip->reg_output[off / BANK_SZ] = reg_val;
exit:
mutex_unlock(&chip->i2c_lock);
}
......@@ -328,21 +371,21 @@ static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
struct pca953x_chip *chip;
chip = container_of(gc, struct pca953x_chip, gpio_chip);
return chip->irq_base + off;
return irq_create_mapping(chip->domain, off);
}
static void pca953x_irq_mask(struct irq_data *d)
{
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
chip->irq_mask &= ~(1 << d->hwirq);
chip->irq_mask[d->hwirq / BANK_SZ] &= ~(1 << (d->hwirq % BANK_SZ));
}
static void pca953x_irq_unmask(struct irq_data *d)
{
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
chip->irq_mask |= 1 << d->hwirq;
chip->irq_mask[d->hwirq / BANK_SZ] |= 1 << (d->hwirq % BANK_SZ);
}
static void pca953x_irq_bus_lock(struct irq_data *d)
......@@ -355,18 +398,21 @@ static void pca953x_irq_bus_lock(struct irq_data *d)
static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
{
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
u32 new_irqs;
u32 level;
u8 new_irqs;
int level, i;
/* Look for any newly setup interrupt */
new_irqs = chip->irq_trig_fall | chip->irq_trig_raise;
new_irqs &= ~chip->reg_direction;
for (i = 0; i < NBANK(chip); i++) {
new_irqs = chip->irq_trig_fall[i] | chip->irq_trig_raise[i];
new_irqs &= ~chip->reg_direction[i];
while (new_irqs) {
level = __ffs(new_irqs);
pca953x_gpio_direction_input(&chip->gpio_chip, level);
pca953x_gpio_direction_input(&chip->gpio_chip,
level + (BANK_SZ * i));
new_irqs &= ~(1 << level);
}
}
mutex_unlock(&chip->irq_lock);
}
......@@ -374,7 +420,8 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
{
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
u32 mask = 1 << d->hwirq;
int bank_nb = d->hwirq / BANK_SZ;
u8 mask = 1 << (d->hwirq % BANK_SZ);
if (!(type & IRQ_TYPE_EDGE_BOTH)) {
dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
......@@ -383,14 +430,14 @@ static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
}
if (type & IRQ_TYPE_EDGE_FALLING)
chip->irq_trig_fall |= mask;
chip->irq_trig_fall[bank_nb] |= mask;
else
chip->irq_trig_fall &= ~mask;
chip->irq_trig_fall[bank_nb] &= ~mask;
if (type & IRQ_TYPE_EDGE_RISING)
chip->irq_trig_raise |= mask;
chip->irq_trig_raise[bank_nb] |= mask;
else
chip->irq_trig_raise &= ~mask;
chip->irq_trig_raise[bank_nb] &= ~mask;
return 0;
}
......@@ -404,13 +451,13 @@ static struct irq_chip pca953x_irq_chip = {
.irq_set_type = pca953x_irq_set_type,
};
static u32 pca953x_irq_pending(struct pca953x_chip *chip)
static u8 pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending)
{
u32 cur_stat;
u32 old_stat;
u32 pending;
u32 trigger;
int ret, offset = 0;
u8 cur_stat[MAX_BANK];
u8 old_stat[MAX_BANK];
u8 pendings = 0;
u8 trigger[MAX_BANK], triggers = 0;
int ret, i, offset = 0;
switch (chip->chip_type) {
case PCA953X_TYPE:
......@@ -420,60 +467,88 @@ static u32 pca953x_irq_pending(struct pca953x_chip *chip)
offset = PCA957X_IN;
break;
}
ret = pca953x_read_reg(chip, offset, &cur_stat);
ret = pca953x_read_regs(chip, offset, cur_stat);
if (ret)
return 0;
/* Remove output pins from the equation */
cur_stat &= chip->reg_direction;
for (i = 0; i < NBANK(chip); i++)
cur_stat[i] &= chip->reg_direction[i];
memcpy(old_stat, chip->irq_stat, NBANK(chip));
old_stat = chip->irq_stat;
trigger = (cur_stat ^ old_stat) & chip->irq_mask;
for (i = 0; i < NBANK(chip); i++) {
trigger[i] = (cur_stat[i] ^ old_stat[i]) & chip->irq_mask[i];
triggers += trigger[i];
}
if (!trigger)
if (!triggers)
return 0;
chip->irq_stat = cur_stat;
memcpy(chip->irq_stat, cur_stat, NBANK(chip));
pending = (old_stat & chip->irq_trig_fall) |
(cur_stat & chip->irq_trig_raise);
pending &= trigger;
for (i = 0; i < NBANK(chip); i++) {
pending[i] = (old_stat[i] & chip->irq_trig_fall[i]) |
(cur_stat[i] & chip->irq_trig_raise[i]);
pending[i] &= trigger[i];
pendings += pending[i];
}
return pending;
return pendings;
}
static irqreturn_t pca953x_irq_handler(int irq, void *devid)
{
struct pca953x_chip *chip = devid;
u32 pending;
u32 level;
pending = pca953x_irq_pending(chip);
u8 pending[MAX_BANK];
u8 level;
int i;
if (!pending)
if (!pca953x_irq_pending(chip, pending))
return IRQ_HANDLED;
do {
level = __ffs(pending);
handle_nested_irq(irq_find_mapping(chip->domain, level));
pending &= ~(1 << level);
} while (pending);
for (i = 0; i < NBANK(chip); i++) {
while (pending[i]) {
level = __ffs(pending[i]);
handle_nested_irq(irq_find_mapping(chip->domain,
level + (BANK_SZ * i)));
pending[i] &= ~(1 << level);
}
}
return IRQ_HANDLED;
}
static int pca953x_gpio_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{
irq_clear_status_flags(irq, IRQ_NOREQUEST);
irq_set_chip_data(irq, d->host_data);
irq_set_chip(irq, &pca953x_irq_chip);
irq_set_nested_thread(irq, true);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(irq);
#endif
return 0;
}
static const struct irq_domain_ops pca953x_irq_simple_ops = {
.map = pca953x_gpio_irq_map,
.xlate = irq_domain_xlate_twocell,
};
static int pca953x_irq_setup(struct pca953x_chip *chip,
const struct i2c_device_id *id,
int irq_base)
{
struct i2c_client *client = chip->client;
int ret, offset = 0;
u32 temporary;
int ret, i, offset = 0;
if (irq_base != -1
&& (id->driver_data & PCA_INT)) {
int lvl;
switch (chip->chip_type) {
case PCA953X_TYPE:
......@@ -483,49 +558,29 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
offset = PCA957X_IN;
break;
}
ret = pca953x_read_reg(chip, offset, &temporary);
chip->irq_stat = temporary;
ret = pca953x_read_regs(chip, offset, chip->irq_stat);
if (ret)
goto out_failed;
return ret;
/*
* There is no way to know which GPIO line generated the
* interrupt. We have to rely on the previous read for
* this purpose.
*/
chip->irq_stat &= chip->reg_direction;
for (i = 0; i < NBANK(chip); i++)
chip->irq_stat[i] &= chip->reg_direction[i];
mutex_init(&chip->irq_lock);
chip->irq_base = irq_alloc_descs(-1, irq_base, chip->gpio_chip.ngpio, -1);
if (chip->irq_base < 0)
goto out_failed;
chip->domain = irq_domain_add_legacy(client->dev.of_node,
chip->domain = irq_domain_add_simple(client->dev.of_node,
chip->gpio_chip.ngpio,
chip->irq_base,
0,
&irq_domain_simple_ops,
irq_base,
&pca953x_irq_simple_ops,
NULL);
if (!chip->domain) {
ret = -ENODEV;
goto out_irqdesc_free;
}
for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
int irq = lvl + chip->irq_base;
if (!chip->domain)
return -ENODEV;
irq_clear_status_flags(irq, IRQ_NOREQUEST);
irq_set_chip_data(irq, chip);
irq_set_chip(irq, &pca953x_irq_chip);
irq_set_nested_thread(irq, true);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(irq);
#endif
}
ret = request_threaded_irq(client->irq,
ret = devm_request_threaded_irq(&client->dev,
client->irq,
NULL,
pca953x_irq_handler,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
......@@ -533,28 +588,15 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
if (ret) {
dev_err(&client->dev, "failed to request irq %d\n",
client->irq);
goto out_irqdesc_free;
return ret;
}
chip->gpio_chip.to_irq = pca953x_gpio_to_irq;
}
return 0;
out_irqdesc_free:
irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio);
out_failed:
chip->irq_base = -1;
return ret;
}
static void pca953x_irq_teardown(struct pca953x_chip *chip)
{
if (chip->irq_base != -1) {
irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio);
free_irq(chip->client->irq, chip);
}
}
#else /* CONFIG_GPIO_PCA953X_IRQ */
static int pca953x_irq_setup(struct pca953x_chip *chip,
const struct i2c_device_id *id,
......@@ -567,10 +609,6 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
return 0;
}
static void pca953x_irq_teardown(struct pca953x_chip *chip)
{
}
#endif
/*
......@@ -619,18 +657,24 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert)
static int device_pca953x_init(struct pca953x_chip *chip, u32 invert)
{
int ret;
u8 val[MAX_BANK];
ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
ret = pca953x_read_regs(chip, PCA953X_OUTPUT, chip->reg_output);
if (ret)
goto out;
ret = pca953x_read_reg(chip, PCA953X_DIRECTION,
&chip->reg_direction);
ret = pca953x_read_regs(chip, PCA953X_DIRECTION,
chip->reg_direction);
if (ret)
goto out;
/* set platform specific polarity inversion */
ret = pca953x_write_reg(chip, PCA953X_INVERT, invert);
if (invert)
memset(val, 0xFF, NBANK(chip));
else
memset(val, 0, NBANK(chip));
ret = pca953x_write_regs(chip, PCA953X_INVERT, val);
out:
return ret;
}
......@@ -638,28 +682,36 @@ static int device_pca953x_init(struct pca953x_chip *chip, u32 invert)
static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
{
int ret;
u32 val = 0;
u8 val[MAX_BANK];
/* Let every port in proper state, that could save power */
pca953x_write_reg(chip, PCA957X_PUPD, 0x0);
pca953x_write_reg(chip, PCA957X_CFG, 0xffff);
pca953x_write_reg(chip, PCA957X_OUT, 0x0);
ret = pca953x_read_reg(chip, PCA957X_IN, &val);
memset(val, 0, NBANK(chip));
pca953x_write_regs(chip, PCA957X_PUPD, val);
memset(val, 0xFF, NBANK(chip));
pca953x_write_regs(chip, PCA957X_CFG, val);
memset(val, 0, NBANK(chip));
pca953x_write_regs(chip, PCA957X_OUT, val);
ret = pca953x_read_regs(chip, PCA957X_IN, val);
if (ret)
goto out;
ret = pca953x_read_reg(chip, PCA957X_OUT, &chip->reg_output);
ret = pca953x_read_regs(chip, PCA957X_OUT, chip->reg_output);
if (ret)
goto out;
ret = pca953x_read_reg(chip, PCA957X_CFG, &chip->reg_direction);
ret = pca953x_read_regs(chip, PCA957X_CFG, chip->reg_direction);
if (ret)
goto out;
/* set platform specific polarity inversion */
pca953x_write_reg(chip, PCA957X_INVRT, invert);
if (invert)
memset(val, 0xFF, NBANK(chip));
else
memset(val, 0, NBANK(chip));
pca953x_write_regs(chip, PCA957X_INVRT, val);
/* To enable register 6, 7 to controll pull up and pull down */
pca953x_write_reg(chip, PCA957X_BKEN, 0x202);
memset(val, 0x02, NBANK(chip));
pca953x_write_regs(chip, PCA957X_BKEN, val);
return 0;
out:
......@@ -675,7 +727,8 @@ static int pca953x_probe(struct i2c_client *client,
int ret;
u32 invert = 0;
chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
chip = devm_kzalloc(&client->dev,
sizeof(struct pca953x_chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
......@@ -710,15 +763,15 @@ static int pca953x_probe(struct i2c_client *client,
else
ret = device_pca957x_init(chip, invert);
if (ret)
goto out_failed;
return ret;
ret = pca953x_irq_setup(chip, id, irq_base);
if (ret)
goto out_failed;
return ret;
ret = gpiochip_add(&chip->gpio_chip);
if (ret)
goto out_failed_irq;
return ret;
if (pdata && pdata->setup) {
ret = pdata->setup(client, chip->gpio_chip.base,
......@@ -729,12 +782,6 @@ static int pca953x_probe(struct i2c_client *client,
i2c_set_clientdata(client, chip);
return 0;
out_failed_irq:
pca953x_irq_teardown(chip);
out_failed:
kfree(chip);
return ret;
}
static int pca953x_remove(struct i2c_client *client)
......@@ -760,12 +807,11 @@ static int pca953x_remove(struct i2c_client *client)
return ret;
}
pca953x_irq_teardown(chip);
kfree(chip);
return 0;
}
static const struct of_device_id pca953x_dt_ids[] = {
{ .compatible = "nxp,pca9505", },
{ .compatible = "nxp,pca9534", },
{ .compatible = "nxp,pca9535", },
{ .compatible = "nxp,pca9536", },
......
......@@ -365,7 +365,7 @@ static int __init pl061_gpio_init(void)
{
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_DESCRIPTION("PL061 GPIO driver");
......
......@@ -642,12 +642,7 @@ static struct platform_driver pxa_gpio_driver = {
.of_match_table = of_match_ptr(pxa_gpio_dt_ids),
},
};
static int __init pxa_gpio_init(void)
{
return platform_driver_register(&pxa_gpio_driver);
}
postcore_initcall(pxa_gpio_init);
module_platform_driver(pxa_gpio_driver);
#ifdef CONFIG_PM
static int pxa_gpio_suspend(void)
......
......@@ -37,7 +37,6 @@
#include <linux/i2c/twl.h>
/*
* The GPIO "subchip" supports 18 GPIOs which can be configured as
* inputs or outputs, with pullups or pulldowns on each pin. Each
......@@ -49,11 +48,6 @@
* 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 */
#ifdef MODULE
#define is_module() true
......@@ -69,14 +63,24 @@ static int twl4030_gpio_irq_base;
/* Mask for GPIO registers when aggregated into a 32-bit integer */
#define GPIO_32_MASK 0x0003ffff
/* Data structures */
static DEFINE_MUTEX(gpio_lock);
struct gpio_twl4030_priv {
struct gpio_chip gpio_chip;
struct mutex mutex;
int irq_base;
/* store usage of each GPIO. - each bit represents one GPIO */
static unsigned int gpio_usage_count;
/* Bitfields for state caching */
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
*/
......@@ -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
* 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)
if (led)
mask <<= 1;
mutex_lock(&gpio_lock);
if (value)
cached_leden &= ~mask;
else
cached_leden |= mask;
status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden,
TWL4030_LED_LEDEN_REG);
mutex_unlock(&gpio_lock);
}
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;
int ret = 0;
mutex_lock(&gpio_lock);
ret = gpio_twl4030_read(base);
if (ret >= 0) {
if (is_input)
......@@ -168,7 +169,6 @@ static int twl4030_set_gpio_direction(int gpio, int is_input)
ret = gpio_twl4030_write(base, reg);
}
mutex_unlock(&gpio_lock);
return ret;
}
......@@ -193,10 +193,6 @@ static int twl4030_get_gpio_datain(int gpio)
u8 base = 0;
int ret = 0;
if (unlikely((gpio >= TWL4030_GPIO_MAX)
|| !(gpio_usage_count & BIT(gpio))))
return -EPERM;
base = REG_GPIODATAIN1 + d_bnk;
ret = gpio_twl4030_read(base);
if (ret > 0)
......@@ -209,9 +205,10 @@ static int twl4030_get_gpio_datain(int gpio)
static int twl_request(struct gpio_chip *chip, unsigned offset)
{
struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip);
int status = 0;
mutex_lock(&gpio_lock);
mutex_lock(&priv->mutex);
/* Support the two LED outputs as output-only GPIOs. */
if (offset >= TWL4030_GPIO_MAX) {
......@@ -252,7 +249,7 @@ static int twl_request(struct gpio_chip *chip, unsigned offset)
}
/* on first use, turn GPIO module "on" */
if (!gpio_usage_count) {
if (!priv->usage_count) {
struct twl4030_gpio_platform_data *pdata;
u8 value = MASK_GPIO_CTRL_GPIO_ON;
......@@ -266,79 +263,120 @@ static int twl_request(struct gpio_chip *chip, unsigned offset)
status = gpio_twl4030_write(REG_GPIO_CTRL, value);
}
done:
if (!status)
gpio_usage_count |= (0x1 << offset);
priv->usage_count |= BIT(offset);
done:
mutex_unlock(&gpio_lock);
mutex_unlock(&priv->mutex);
return status;
}
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) {
twl4030_led_set_value(offset - TWL4030_GPIO_MAX, 1);
return;
goto out;
}
mutex_lock(&gpio_lock);
gpio_usage_count &= ~BIT(offset);
priv->usage_count &= ~BIT(offset);
/* on last use, switch off GPIO module */
if (!gpio_usage_count)
if (!priv->usage_count)
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)
{
return (offset < TWL4030_GPIO_MAX)
? twl4030_set_gpio_direction(offset, 1)
: -EINVAL;
struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip);
int ret;
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)
{
struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip);
int ret;
int status = 0;
if (offset < TWL4030_GPIO_MAX)
status = twl4030_get_gpio_datain(offset);
else if (offset == TWL4030_GPIO_MAX)
status = cached_leden & LEDEN_LEDAON;
mutex_lock(&priv->mutex);
if (!(priv->usage_count & BIT(offset))) {
ret = -EPERM;
goto out;
}
if (priv->direction & BIT(offset))
status = priv->out_state & BIT(offset);
else
status = cached_leden & LEDEN_LEDBON;
return (status < 0) ? 0 : status;
status = twl4030_get_gpio_datain(offset);
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);
return twl4030_set_gpio_direction(offset, 0);
} else {
else
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)
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)
{
return (twl4030_gpio_irq_base && (offset < TWL4030_GPIO_MAX))
? (twl4030_gpio_irq_base + offset)
struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip);
return (priv->irq_base && (offset < TWL4030_GPIO_MAX))
? (priv->irq_base + offset)
: -EINVAL;
}
static struct gpio_chip twl_gpiochip = {
static struct gpio_chip template_chip = {
.label = "twl4030",
.owner = THIS_MODULE,
.request = twl_request,
......@@ -424,8 +462,14 @@ static int gpio_twl4030_probe(struct platform_device *pdev)
{
struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
struct device_node *node = pdev->dev.of_node;
struct gpio_twl4030_priv *priv;
int ret, irq_base;
priv = devm_kzalloc(&pdev->dev, sizeof(struct gpio_twl4030_priv),
GFP_KERNEL);
if (!priv)
return -ENOMEM;
/* maybe setup IRQs */
if (is_module()) {
dev_err(&pdev->dev, "can't dispatch IRQs from modules\n");
......@@ -445,12 +489,15 @@ static int gpio_twl4030_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
twl4030_gpio_irq_base = irq_base;
priv->irq_base = irq_base;
no_irqs:
twl_gpiochip.base = -1;
twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
twl_gpiochip.dev = &pdev->dev;
priv->gpio_chip = template_chip;
priv->gpio_chip.base = -1;
priv->gpio_chip.ngpio = TWL4030_GPIO_MAX;
priv->gpio_chip.dev = &pdev->dev;
mutex_init(&priv->mutex);
if (node)
pdata = of_gpio_twl4030(&pdev->dev);
......@@ -481,23 +528,23 @@ static int gpio_twl4030_probe(struct platform_device *pdev)
* is (still) clear if use_leds is set.
*/
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) {
dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret);
twl_gpiochip.ngpio = 0;
priv->gpio_chip.ngpio = 0;
gpio_twl4030_remove(pdev);
goto out;
}
twl4030_gpio_base = twl_gpiochip.base;
platform_set_drvdata(pdev, priv);
if (pdata && pdata->setup) {
int status;
status = pdata->setup(&pdev->dev,
twl4030_gpio_base, TWL4030_GPIO_MAX);
status = pdata->setup(&pdev->dev, priv->gpio_chip.base,
TWL4030_GPIO_MAX);
if (status)
dev_dbg(&pdev->dev, "setup --> %d\n", status);
}
......@@ -510,18 +557,19 @@ static int gpio_twl4030_probe(struct platform_device *pdev)
static int gpio_twl4030_remove(struct platform_device *pdev)
{
struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
struct gpio_twl4030_priv *priv = platform_get_drvdata(pdev);
int status;
if (pdata && pdata->teardown) {
status = pdata->teardown(&pdev->dev,
twl4030_gpio_base, TWL4030_GPIO_MAX);
status = pdata->teardown(&pdev->dev, priv->gpio_chip.base,
TWL4030_GPIO_MAX);
if (status) {
dev_dbg(&pdev->dev, "teardown --> %d\n", status);
return status;
}
}
status = gpiochip_remove(&twl_gpiochip);
status = gpiochip_remove(&priv->gpio_chip);
if (status < 0)
return status;
......
......@@ -73,19 +73,20 @@ struct vt8500_gpio_data {
static struct vt8500_gpio_data vt8500_data = {
.num_banks = 7,
.banks = {
VT8500_BANK(NO_REG, 0x3C, 0x5C, 0x7C, 9),
VT8500_BANK(0x00, 0x20, 0x40, 0x60, 26),
VT8500_BANK(0x04, 0x24, 0x44, 0x64, 28),
VT8500_BANK(0x08, 0x28, 0x48, 0x68, 31),
VT8500_BANK(0x0C, 0x2C, 0x4C, 0x6C, 19),
VT8500_BANK(0x10, 0x30, 0x50, 0x70, 19),
VT8500_BANK(0x14, 0x34, 0x54, 0x74, 23),
VT8500_BANK(NO_REG, 0x3C, 0x5C, 0x7C, 9),
},
};
static struct vt8500_gpio_data wm8505_data = {
.num_banks = 10,
.banks = {
VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22),
VT8500_BANK(0x40, 0x68, 0x90, 0xB8, 8),
VT8500_BANK(0x44, 0x6C, 0x94, 0xBC, 32),
VT8500_BANK(0x48, 0x70, 0x98, 0xC0, 6),
......@@ -95,7 +96,6 @@ static struct vt8500_gpio_data wm8505_data = {
VT8500_BANK(0x58, 0x80, 0xA8, 0xD0, 5),
VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12),
VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16),
VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22),
VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6),
},
};
......@@ -127,6 +127,12 @@ struct vt8500_gpio_chip {
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)
......@@ -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,
const struct vt8500_gpio_data *data)
{
struct vt8500_data *priv;
struct vt8500_gpio_chip *vtchip;
struct gpio_chip *chip;
int i;
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,
GFP_KERNEL);
if (!vtchip) {
pr_err("%s: failed to allocate chip memory\n", __func__);
if (!priv->chip) {
dev_err(&pdev->dev, "failed to allocate chip memory\n");
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++) {
vtchip[i].base = base;
vtchip[i].regs = &data->banks[i];
......@@ -273,36 +292,54 @@ static struct of_device_id vt8500_gpio_dt_ids[] = {
static int vt8500_gpio_probe(struct platform_device *pdev)
{
int ret;
void __iomem *gpio_base;
struct device_node *np;
struct resource *res;
const struct of_device_id *of_id =
of_match_device(vt8500_gpio_dt_ids, &pdev->dev);
if (!of_id) {
dev_err(&pdev->dev, "Failed to find gpio controller\n");
dev_err(&pdev->dev, "No matching driver data\n");
return -ENODEV;
}
np = pdev->dev.of_node;
if (!np) {
dev_err(&pdev->dev, "Missing GPIO description in devicetree\n");
return -EFAULT;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "Unable to get IO resource\n");
return -ENODEV;
}
gpio_base = of_iomap(np, 0);
gpio_base = devm_request_and_ioremap(&pdev->dev, res);
if (!gpio_base) {
dev_err(&pdev->dev, "Unable to map GPIO registers\n");
of_node_put(np);
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;
}
static struct platform_driver vt8500_gpio_driver = {
.probe = vt8500_gpio_probe,
.remove = vt8500_gpio_remove,
.driver = {
.name = "vt8500-gpio",
.owner = THIS_MODULE,
......
......@@ -15,6 +15,7 @@
#include <linux/export.h>
#include <linux/acpi_gpio.h>
#include <linux/acpi.h>
#include <linux/interrupt.h>
static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
{
......@@ -52,3 +53,89 @@ int acpi_get_gpio(char *path, int pin)
return chip->base + pin;
}
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);
......@@ -3,6 +3,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/debugfs.h>
......@@ -52,14 +53,13 @@ struct gpio_desc {
/* flag symbols are bit numbers */
#define FLAG_REQUESTED 0
#define FLAG_IS_OUT 1
#define FLAG_RESERVED 2
#define FLAG_EXPORT 3 /* protected by sysfs_lock */
#define FLAG_SYSFS 4 /* exported via /sys/class/gpio/control */
#define FLAG_TRIG_FALL 5 /* trigger on falling edge */
#define FLAG_TRIG_RISE 6 /* trigger on rising edge */
#define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */
#define FLAG_OPEN_DRAIN 8 /* Gpio is open drain type */
#define FLAG_OPEN_SOURCE 9 /* Gpio is open source type */
#define FLAG_EXPORT 2 /* protected by sysfs_lock */
#define FLAG_SYSFS 3 /* exported via /sys/class/gpio/control */
#define FLAG_TRIG_FALL 4 /* trigger on falling edge */
#define FLAG_TRIG_RISE 5 /* trigger on rising edge */
#define FLAG_ACTIVE_LOW 6 /* sysfs value has active low */
#define FLAG_OPEN_DRAIN 7 /* Gpio is open drain type */
#define FLAG_OPEN_SOURCE 8 /* Gpio is open source type */
#define ID_SHIFT 16 /* add new flags before this one */
......@@ -72,10 +72,36 @@ struct gpio_desc {
};
static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];
#define GPIO_OFFSET_VALID(chip, offset) (offset >= 0 && offset < chip->ngpio)
static LIST_HEAD(gpio_chips);
#ifdef CONFIG_GPIO_SYSFS
static DEFINE_IDR(dirent_idr);
#endif
/*
* Internal gpiod_* API using descriptors instead of the integer namespace.
* Most of this should eventually go public.
*/
static int gpiod_request(struct gpio_desc *desc, const char *label);
static void gpiod_free(struct gpio_desc *desc);
static int gpiod_direction_input(struct gpio_desc *desc);
static int gpiod_direction_output(struct gpio_desc *desc, int value);
static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce);
static int gpiod_get_value_cansleep(struct gpio_desc *desc);
static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value);
static int gpiod_get_value(struct gpio_desc *desc);
static void gpiod_set_value(struct gpio_desc *desc, int value);
static int gpiod_cansleep(struct gpio_desc *desc);
static int gpiod_to_irq(struct gpio_desc *desc);
static int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
static int gpiod_export_link(struct device *dev, const char *name,
struct gpio_desc *desc);
static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value);
static void gpiod_unexport(struct gpio_desc *desc);
static inline void desc_set_label(struct gpio_desc *d, const char *label)
{
#ifdef CONFIG_DEBUG_FS
......@@ -83,6 +109,36 @@ static inline void desc_set_label(struct gpio_desc *d, const char *label)
#endif
}
/*
* Return the GPIO number of the passed descriptor relative to its chip
*/
static int gpio_chip_hwgpio(const struct gpio_desc *desc)
{
return desc - &desc->chip->desc[0];
}
/**
* Convert a GPIO number to its descriptor
*/
static struct gpio_desc *gpio_to_desc(unsigned gpio)
{
if (WARN(!gpio_is_valid(gpio), "invalid GPIO %d\n", gpio))
return NULL;
else
return &gpio_desc[gpio];
}
/**
* Convert a GPIO descriptor to the integer namespace.
* This should disappear in the future but is needed since we still
* use GPIO numbers for error messages and sysfs nodes
*/
static int desc_to_gpio(const struct gpio_desc *desc)
{
return desc->chip->base + gpio_chip_hwgpio(desc);
}
/* Warn when drivers omit gpio_request() calls -- legal but ill-advised
* when setting direction, and otherwise illegal. Until board setup code
* and drivers use explicit requests everywhere (which won't happen when
......@@ -94,10 +150,10 @@ static inline void desc_set_label(struct gpio_desc *d, const char *label)
* only "legal" in the sense that (old) code using it won't break yet,
* but instead only triggers a WARN() stack dump.
*/
static int gpio_ensure_requested(struct gpio_desc *desc, unsigned offset)
static int gpio_ensure_requested(struct gpio_desc *desc)
{
const struct gpio_chip *chip = desc->chip;
const int gpio = chip->base + offset;
const int gpio = desc_to_gpio(desc);
if (WARN(test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0,
"autorequest GPIO-%d\n", gpio)) {
......@@ -116,95 +172,54 @@ static int gpio_ensure_requested(struct gpio_desc *desc, unsigned offset)
}
/* caller holds gpio_lock *OR* gpio is marked as requested */
static struct gpio_chip *gpiod_to_chip(struct gpio_desc *desc)
{
return desc->chip;
}
struct gpio_chip *gpio_to_chip(unsigned gpio)
{
return gpio_desc[gpio].chip;
return gpiod_to_chip(gpio_to_desc(gpio));
}
/* dynamic allocation of GPIOs, e.g. on a hotplugged device */
static int gpiochip_find_base(int ngpio)
{
int i;
int spare = 0;
int base = -ENOSPC;
for (i = ARCH_NR_GPIOS - 1; i >= 0 ; i--) {
struct gpio_desc *desc = &gpio_desc[i];
struct gpio_chip *chip = desc->chip;
struct gpio_chip *chip;
int base = ARCH_NR_GPIOS - ngpio;
if (!chip && !test_bit(FLAG_RESERVED, &desc->flags)) {
spare++;
if (spare == ngpio) {
base = i;
list_for_each_entry_reverse(chip, &gpio_chips, list) {
/* found a free space? */
if (chip->base + chip->ngpio <= base)
break;
}
} else {
spare = 0;
if (chip)
i -= chip->ngpio - 1;
}
else
/* nope, check the space right before the chip */
base = chip->base - ngpio;
}
if (gpio_is_valid(base))
if (gpio_is_valid(base)) {
pr_debug("%s: found new base at %d\n", __func__, base);
return base;
}
/**
* gpiochip_reserve() - reserve range of gpios to use with platform code only
* @start: starting gpio number
* @ngpio: number of gpios to reserve
* Context: platform init, potentially before irqs or kmalloc will work
*
* Returns a negative errno if any gpio within the range is already reserved
* or registered, else returns zero as a success code. Use this function
* to mark a range of gpios as unavailable for dynamic gpio number allocation,
* for example because its driver support is not yet loaded.
*/
int __init gpiochip_reserve(int start, int ngpio)
{
int ret = 0;
unsigned long flags;
int i;
if (!gpio_is_valid(start) || !gpio_is_valid(start + ngpio - 1))
return -EINVAL;
spin_lock_irqsave(&gpio_lock, flags);
for (i = start; i < start + ngpio; i++) {
struct gpio_desc *desc = &gpio_desc[i];
if (desc->chip || test_bit(FLAG_RESERVED, &desc->flags)) {
ret = -EBUSY;
goto err;
}
set_bit(FLAG_RESERVED, &desc->flags);
} else {
pr_err("%s: cannot find free range\n", __func__);
return -ENOSPC;
}
pr_debug("%s: reserved gpios from %d to %d\n",
__func__, start, start + ngpio - 1);
err:
spin_unlock_irqrestore(&gpio_lock, flags);
return ret;
}
/* caller ensures gpio is valid and requested, chip->get_direction may sleep */
static int gpio_get_direction(unsigned gpio)
static int gpiod_get_direction(struct gpio_desc *desc)
{
struct gpio_chip *chip;
struct gpio_desc *desc = &gpio_desc[gpio];
unsigned offset;
int status = -EINVAL;
chip = gpio_to_chip(gpio);
gpio -= chip->base;
chip = gpiod_to_chip(desc);
offset = gpio_chip_hwgpio(desc);
if (!chip->get_direction)
return status;
status = chip->get_direction(chip, gpio);
status = chip->get_direction(chip, offset);
if (status > 0) {
/* GPIOF_DIR_IN, or other positive */
status = 1;
......@@ -248,19 +263,19 @@ static DEFINE_MUTEX(sysfs_lock);
static ssize_t gpio_direction_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
const struct gpio_desc *desc = dev_get_drvdata(dev);
unsigned gpio = desc - gpio_desc;
struct gpio_desc *desc = dev_get_drvdata(dev);
ssize_t status;
mutex_lock(&sysfs_lock);
if (!test_bit(FLAG_EXPORT, &desc->flags))
if (!test_bit(FLAG_EXPORT, &desc->flags)) {
status = -EIO;
else
gpio_get_direction(gpio);
} else {
gpiod_get_direction(desc);
status = sprintf(buf, "%s\n",
test_bit(FLAG_IS_OUT, &desc->flags)
? "out" : "in");
}
mutex_unlock(&sysfs_lock);
return status;
......@@ -269,8 +284,7 @@ static ssize_t gpio_direction_show(struct device *dev,
static ssize_t gpio_direction_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
const struct gpio_desc *desc = dev_get_drvdata(dev);
unsigned gpio = desc - gpio_desc;
struct gpio_desc *desc = dev_get_drvdata(dev);
ssize_t status;
mutex_lock(&sysfs_lock);
......@@ -278,11 +292,11 @@ static ssize_t gpio_direction_store(struct device *dev,
if (!test_bit(FLAG_EXPORT, &desc->flags))
status = -EIO;
else if (sysfs_streq(buf, "high"))
status = gpio_direction_output(gpio, 1);
status = gpiod_direction_output(desc, 1);
else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low"))
status = gpio_direction_output(gpio, 0);
status = gpiod_direction_output(desc, 0);
else if (sysfs_streq(buf, "in"))
status = gpio_direction_input(gpio);
status = gpiod_direction_input(desc);
else
status = -EINVAL;
......@@ -296,8 +310,7 @@ static /* const */ DEVICE_ATTR(direction, 0644,
static ssize_t gpio_value_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
const struct gpio_desc *desc = dev_get_drvdata(dev);
unsigned gpio = desc - gpio_desc;
struct gpio_desc *desc = dev_get_drvdata(dev);
ssize_t status;
mutex_lock(&sysfs_lock);
......@@ -307,7 +320,7 @@ static ssize_t gpio_value_show(struct device *dev,
} else {
int value;
value = !!gpio_get_value_cansleep(gpio);
value = !!gpiod_get_value_cansleep(desc);
if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
value = !value;
......@@ -321,8 +334,7 @@ static ssize_t gpio_value_show(struct device *dev,
static ssize_t gpio_value_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
const struct gpio_desc *desc = dev_get_drvdata(dev);
unsigned gpio = desc - gpio_desc;
struct gpio_desc *desc = dev_get_drvdata(dev);
ssize_t status;
mutex_lock(&sysfs_lock);
......@@ -338,7 +350,7 @@ static ssize_t gpio_value_store(struct device *dev,
if (status == 0) {
if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
value = !value;
gpio_set_value_cansleep(gpio, value != 0);
gpiod_set_value_cansleep(desc, value != 0);
status = size;
}
}
......@@ -368,7 +380,7 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,
if ((desc->flags & GPIO_TRIGGER_MASK) == gpio_flags)
return 0;
irq = gpio_to_irq(desc - gpio_desc);
irq = gpiod_to_irq(desc);
if (irq < 0)
return -EIO;
......@@ -639,28 +651,31 @@ static ssize_t export_store(struct class *class,
const char *buf, size_t len)
{
long gpio;
struct gpio_desc *desc;
int status;
status = strict_strtol(buf, 0, &gpio);
if (status < 0)
goto done;
desc = gpio_to_desc(gpio);
/* No extra locking here; FLAG_SYSFS just signifies that the
* request and export were done by on behalf of userspace, so
* they may be undone on its behalf too.
*/
status = gpio_request(gpio, "sysfs");
status = gpiod_request(desc, "sysfs");
if (status < 0) {
if (status == -EPROBE_DEFER)
status = -ENODEV;
goto done;
}
status = gpio_export(gpio, true);
status = gpiod_export(desc, true);
if (status < 0)
gpio_free(gpio);
gpiod_free(desc);
else
set_bit(FLAG_SYSFS, &gpio_desc[gpio].flags);
set_bit(FLAG_SYSFS, &desc->flags);
done:
if (status)
......@@ -673,6 +688,7 @@ static ssize_t unexport_store(struct class *class,
const char *buf, size_t len)
{
long gpio;
struct gpio_desc *desc;
int status;
status = strict_strtol(buf, 0, &gpio);
......@@ -681,17 +697,18 @@ static ssize_t unexport_store(struct class *class,
status = -EINVAL;
desc = gpio_to_desc(gpio);
/* reject bogus commands (gpio_unexport ignores them) */
if (!gpio_is_valid(gpio))
if (!desc)
goto done;
/* No extra locking here; FLAG_SYSFS just signifies that the
* request and export were done by on behalf of userspace, so
* they may be undone on its behalf too.
*/
if (test_and_clear_bit(FLAG_SYSFS, &gpio_desc[gpio].flags)) {
if (test_and_clear_bit(FLAG_SYSFS, &desc->flags)) {
status = 0;
gpio_free(gpio);
gpiod_free(desc);
}
done:
if (status)
......@@ -728,13 +745,13 @@ static struct class gpio_class = {
*
* Returns zero on success, else an error.
*/
int gpio_export(unsigned gpio, bool direction_may_change)
static int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
{
unsigned long flags;
struct gpio_desc *desc;
int status;
const char *ioname = NULL;
struct device *dev;
int offset;
/* can't export until sysfs is available ... */
if (!gpio_class.p) {
......@@ -742,20 +759,19 @@ int gpio_export(unsigned gpio, bool direction_may_change)
return -ENOENT;
}
if (!gpio_is_valid(gpio)) {
pr_debug("%s: gpio %d is not valid\n", __func__, gpio);
if (!desc) {
pr_debug("%s: invalid gpio descriptor\n", __func__);
return -EINVAL;
}
mutex_lock(&sysfs_lock);
spin_lock_irqsave(&gpio_lock, flags);
desc = &gpio_desc[gpio];
if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
test_bit(FLAG_EXPORT, &desc->flags)) {
spin_unlock_irqrestore(&gpio_lock, flags);
pr_debug("%s: gpio %d unavailable (requested=%d, exported=%d)\n",
__func__, gpio,
__func__, desc_to_gpio(desc),
test_bit(FLAG_REQUESTED, &desc->flags),
test_bit(FLAG_EXPORT, &desc->flags));
status = -EPERM;
......@@ -766,11 +782,13 @@ int gpio_export(unsigned gpio, bool direction_may_change)
direction_may_change = false;
spin_unlock_irqrestore(&gpio_lock, flags);
if (desc->chip->names && desc->chip->names[gpio - desc->chip->base])
ioname = desc->chip->names[gpio - desc->chip->base];
offset = gpio_chip_hwgpio(desc);
if (desc->chip->names && desc->chip->names[offset])
ioname = desc->chip->names[offset];
dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
desc, ioname ? ioname : "gpio%u", gpio);
desc, ioname ? ioname : "gpio%u",
desc_to_gpio(desc));
if (IS_ERR(dev)) {
status = PTR_ERR(dev);
goto fail_unlock;
......@@ -786,7 +804,7 @@ int gpio_export(unsigned gpio, bool direction_may_change)
goto fail_unregister_device;
}
if (gpio_to_irq(gpio) >= 0 && (direction_may_change ||
if (gpiod_to_irq(desc) >= 0 && (direction_may_change ||
!test_bit(FLAG_IS_OUT, &desc->flags))) {
status = device_create_file(dev, &dev_attr_edge);
if (status)
......@@ -801,9 +819,15 @@ int gpio_export(unsigned gpio, bool direction_may_change)
device_unregister(dev);
fail_unlock:
mutex_unlock(&sysfs_lock);
pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),
status);
return status;
}
int gpio_export(unsigned gpio, bool direction_may_change)
{
return gpiod_export(gpio_to_desc(gpio), direction_may_change);
}
EXPORT_SYMBOL_GPL(gpio_export);
static int match_export(struct device *dev, const void *data)
......@@ -822,18 +846,16 @@ static int match_export(struct device *dev, const void *data)
*
* Returns zero on success, else an error.
*/
int gpio_export_link(struct device *dev, const char *name, unsigned gpio)
static int gpiod_export_link(struct device *dev, const char *name,
struct gpio_desc *desc)
{
struct gpio_desc *desc;
int status = -EINVAL;
if (!gpio_is_valid(gpio))
if (!desc)
goto done;
mutex_lock(&sysfs_lock);
desc = &gpio_desc[gpio];
if (test_bit(FLAG_EXPORT, &desc->flags)) {
struct device *tdev;
......@@ -850,12 +872,17 @@ int gpio_export_link(struct device *dev, const char *name, unsigned gpio)
done:
if (status)
pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),
status);
return status;
}
EXPORT_SYMBOL_GPL(gpio_export_link);
int gpio_export_link(struct device *dev, const char *name, unsigned gpio)
{
return gpiod_export_link(dev, name, gpio_to_desc(gpio));
}
EXPORT_SYMBOL_GPL(gpio_export_link);
/**
* gpio_sysfs_set_active_low - set the polarity of gpio sysfs value
......@@ -869,19 +896,16 @@ EXPORT_SYMBOL_GPL(gpio_export_link);
*
* Returns zero on success, else an error.
*/
int gpio_sysfs_set_active_low(unsigned gpio, int value)
static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
{
struct gpio_desc *desc;
struct device *dev = NULL;
int status = -EINVAL;
if (!gpio_is_valid(gpio))
if (!desc)
goto done;
mutex_lock(&sysfs_lock);
desc = &gpio_desc[gpio];
if (test_bit(FLAG_EXPORT, &desc->flags)) {
dev = class_find_device(&gpio_class, NULL, desc, match_export);
if (dev == NULL) {
......@@ -897,10 +921,16 @@ int gpio_sysfs_set_active_low(unsigned gpio, int value)
done:
if (status)
pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),
status);
return status;
}
int gpio_sysfs_set_active_low(unsigned gpio, int value)
{
return gpiod_sysfs_set_active_low(gpio_to_desc(gpio), value);
}
EXPORT_SYMBOL_GPL(gpio_sysfs_set_active_low);
/**
......@@ -909,21 +939,18 @@ EXPORT_SYMBOL_GPL(gpio_sysfs_set_active_low);
*
* This is implicit on gpio_free().
*/
void gpio_unexport(unsigned gpio)
static void gpiod_unexport(struct gpio_desc *desc)
{
struct gpio_desc *desc;
int status = 0;
struct device *dev = NULL;
if (!gpio_is_valid(gpio)) {
if (!desc) {
status = -EINVAL;
goto done;
}
mutex_lock(&sysfs_lock);
desc = &gpio_desc[gpio];
if (test_bit(FLAG_EXPORT, &desc->flags)) {
dev = class_find_device(&gpio_class, NULL, desc, match_export);
......@@ -935,13 +962,20 @@ void gpio_unexport(unsigned gpio)
}
mutex_unlock(&sysfs_lock);
if (dev) {
device_unregister(dev);
put_device(dev);
}
done:
if (status)
pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),
status);
}
void gpio_unexport(unsigned gpio)
{
gpiod_unexport(gpio_to_desc(gpio));
}
EXPORT_SYMBOL_GPL(gpio_unexport);
......@@ -975,9 +1009,9 @@ static int gpiochip_export(struct gpio_chip *chip)
unsigned gpio;
spin_lock_irqsave(&gpio_lock, flags);
gpio = chip->base;
while (gpio_desc[gpio].chip == chip)
gpio_desc[gpio++].chip = NULL;
gpio = 0;
while (gpio < chip->ngpio)
chip->desc[gpio++].chip = NULL;
spin_unlock_irqrestore(&gpio_lock, flags);
pr_debug("%s: chip %s status %d\n", __func__,
......@@ -1012,7 +1046,7 @@ static int __init gpiolib_sysfs_init(void)
{
int status;
unsigned long flags;
unsigned gpio;
struct gpio_chip *chip;
status = class_register(&gpio_class);
if (status < 0)
......@@ -1025,10 +1059,7 @@ static int __init gpiolib_sysfs_init(void)
* registered, and so arch_initcall() can always gpio_export().
*/
spin_lock_irqsave(&gpio_lock, flags);
for (gpio = 0; gpio < ARCH_NR_GPIOS; gpio++) {
struct gpio_chip *chip;
chip = gpio_desc[gpio].chip;
list_for_each_entry(chip, &gpio_chips, list) {
if (!chip || chip->exported)
continue;
......@@ -1053,8 +1084,66 @@ static inline void gpiochip_unexport(struct gpio_chip *chip)
{
}
static inline int gpiod_export(struct gpio_desc *desc,
bool direction_may_change)
{
return -ENOSYS;
}
static inline int gpiod_export_link(struct device *dev, const char *name,
struct gpio_desc *desc)
{
return -ENOSYS;
}
static inline int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
{
return -ENOSYS;
}
static inline void gpiod_unexport(struct gpio_desc *desc)
{
}
#endif /* CONFIG_GPIO_SYSFS */
/*
* Add a new chip to the global chips list, keeping the list of chips sorted
* by base order.
*
* Return -EBUSY if the new chip overlaps with some other chip's integer
* space.
*/
static int gpiochip_add_to_list(struct gpio_chip *chip)
{
struct list_head *pos = &gpio_chips;
struct gpio_chip *_chip;
int err = 0;
/* find where to insert our chip */
list_for_each(pos, &gpio_chips) {
_chip = list_entry(pos, struct gpio_chip, list);
/* shall we insert before _chip? */
if (_chip->base >= chip->base + chip->ngpio)
break;
}
/* are we stepping on the chip right before? */
if (pos != &gpio_chips && pos->prev != &gpio_chips) {
_chip = list_entry(pos->prev, struct gpio_chip, list);
if (_chip->base + _chip->ngpio > chip->base) {
dev_err(chip->dev,
"GPIO integer space overlap, cannot add chip\n");
err = -EBUSY;
}
}
if (!err)
list_add_tail(&chip->list, pos);
return err;
}
/**
* gpiochip_add() - register a gpio_chip
* @chip: the chip to register, with chip->base initialized
......@@ -1096,16 +1185,14 @@ int gpiochip_add(struct gpio_chip *chip)
chip->base = base;
}
/* these GPIO numbers must not be managed by another gpio_chip */
for (id = base; id < base + chip->ngpio; id++) {
if (gpio_desc[id].chip != NULL) {
status = -EBUSY;
break;
}
}
status = gpiochip_add_to_list(chip);
if (status == 0) {
for (id = base; id < base + chip->ngpio; id++) {
gpio_desc[id].chip = chip;
chip->desc = &gpio_desc[chip->base];
for (id = 0; id < chip->ngpio; id++) {
struct gpio_desc *desc = &chip->desc[id];
desc->chip = chip;
/* REVISIT: most hardware initializes GPIOs as
* inputs (often with pullups enabled) so power
......@@ -1114,7 +1201,7 @@ int gpiochip_add(struct gpio_chip *chip)
* and in case chip->get_direction is not set,
* we may expose the wrong direction in sysfs.
*/
gpio_desc[id].flags = !chip->direction_input
desc->flags = !chip->direction_input
? (1 << FLAG_IS_OUT)
: 0;
}
......@@ -1167,15 +1254,17 @@ int gpiochip_remove(struct gpio_chip *chip)
gpiochip_remove_pin_ranges(chip);
of_gpiochip_remove(chip);
for (id = chip->base; id < chip->base + chip->ngpio; id++) {
if (test_bit(FLAG_REQUESTED, &gpio_desc[id].flags)) {
for (id = 0; id < chip->ngpio; id++) {
if (test_bit(FLAG_REQUESTED, &chip->desc[id].flags)) {
status = -EBUSY;
break;
}
}
if (status == 0) {
for (id = chip->base; id < chip->base + chip->ngpio; id++)
gpio_desc[id].chip = NULL;
for (id = 0; id < chip->ngpio; id++)
chip->desc[id].chip = NULL;
list_del(&chip->list);
}
spin_unlock_irqrestore(&gpio_lock, flags);
......@@ -1202,20 +1291,17 @@ struct gpio_chip *gpiochip_find(void *data,
int (*match)(struct gpio_chip *chip,
void *data))
{
struct gpio_chip *chip = NULL;
struct gpio_chip *chip;
unsigned long flags;
int i;
spin_lock_irqsave(&gpio_lock, flags);
for (i = 0; i < ARCH_NR_GPIOS; i++) {
if (!gpio_desc[i].chip)
continue;
if (match(gpio_desc[i].chip, data)) {
chip = gpio_desc[i].chip;
list_for_each_entry(chip, &gpio_chips, list)
if (match(chip, data))
break;
}
}
/* No match? */
if (&chip->list == &gpio_chips)
chip = NULL;
spin_unlock_irqrestore(&gpio_lock, flags);
return chip;
......@@ -1297,20 +1383,18 @@ EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges);
* on each other, and help provide better diagnostics in debugfs.
* They're called even less than the "set direction" calls.
*/
int gpio_request(unsigned gpio, const char *label)
static int gpiod_request(struct gpio_desc *desc, const char *label)
{
struct gpio_desc *desc;
struct gpio_chip *chip;
int status = -EPROBE_DEFER;
unsigned long flags;
spin_lock_irqsave(&gpio_lock, flags);
if (!gpio_is_valid(gpio)) {
if (!desc) {
status = -EINVAL;
goto done;
}
desc = &gpio_desc[gpio];
chip = desc->chip;
if (chip == NULL)
goto done;
......@@ -1334,7 +1418,7 @@ int gpio_request(unsigned gpio, const char *label)
if (chip->request) {
/* chip->request may sleep */
spin_unlock_irqrestore(&gpio_lock, flags);
status = chip->request(chip, gpio - chip->base);
status = chip->request(chip, gpio_chip_hwgpio(desc));
spin_lock_irqsave(&gpio_lock, flags);
if (status < 0) {
......@@ -1347,42 +1431,46 @@ int gpio_request(unsigned gpio, const char *label)
if (chip->get_direction) {
/* chip->get_direction may sleep */
spin_unlock_irqrestore(&gpio_lock, flags);
gpio_get_direction(gpio);
gpiod_get_direction(desc);
spin_lock_irqsave(&gpio_lock, flags);
}
done:
if (status)
pr_debug("gpio_request: gpio-%d (%s) status %d\n",
gpio, label ? : "?", status);
pr_debug("_gpio_request: gpio-%d (%s) status %d\n",
desc ? desc_to_gpio(desc) : -1,
label ? : "?", status);
spin_unlock_irqrestore(&gpio_lock, flags);
return status;
}
int gpio_request(unsigned gpio, const char *label)
{
return gpiod_request(gpio_to_desc(gpio), label);
}
EXPORT_SYMBOL_GPL(gpio_request);
void gpio_free(unsigned gpio)
static void gpiod_free(struct gpio_desc *desc)
{
unsigned long flags;
struct gpio_desc *desc;
struct gpio_chip *chip;
might_sleep();
if (!gpio_is_valid(gpio)) {
if (!desc) {
WARN_ON(extra_checks);
return;
}
gpio_unexport(gpio);
gpiod_unexport(desc);
spin_lock_irqsave(&gpio_lock, flags);
desc = &gpio_desc[gpio];
chip = desc->chip;
if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) {
if (chip->free) {
spin_unlock_irqrestore(&gpio_lock, flags);
might_sleep_if(chip->can_sleep);
chip->free(chip, gpio - chip->base);
chip->free(chip, gpio_chip_hwgpio(desc));
spin_lock_irqsave(&gpio_lock, flags);
}
desc_set_label(desc, NULL);
......@@ -1396,6 +1484,11 @@ void gpio_free(unsigned gpio)
spin_unlock_irqrestore(&gpio_lock, flags);
}
void gpio_free(unsigned gpio)
{
gpiod_free(gpio_to_desc(gpio));
}
EXPORT_SYMBOL_GPL(gpio_free);
/**
......@@ -1406,29 +1499,32 @@ EXPORT_SYMBOL_GPL(gpio_free);
*/
int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
{
struct gpio_desc *desc;
int err;
err = gpio_request(gpio, label);
desc = gpio_to_desc(gpio);
err = gpiod_request(desc, label);
if (err)
return err;
if (flags & GPIOF_OPEN_DRAIN)
set_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags);
set_bit(FLAG_OPEN_DRAIN, &desc->flags);
if (flags & GPIOF_OPEN_SOURCE)
set_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags);
set_bit(FLAG_OPEN_SOURCE, &desc->flags);
if (flags & GPIOF_DIR_IN)
err = gpio_direction_input(gpio);
err = gpiod_direction_input(desc);
else
err = gpio_direction_output(gpio,
err = gpiod_direction_output(desc,
(flags & GPIOF_INIT_HIGH) ? 1 : 0);
if (err)
goto free_gpio;
if (flags & GPIOF_EXPORT) {
err = gpio_export(gpio, flags & GPIOF_EXPORT_CHANGEABLE);
err = gpiod_export(desc, flags & GPIOF_EXPORT_CHANGEABLE);
if (err)
goto free_gpio;
}
......@@ -1436,7 +1532,7 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
return 0;
free_gpio:
gpio_free(gpio);
gpiod_free(desc);
return err;
}
EXPORT_SYMBOL_GPL(gpio_request_one);
......@@ -1491,14 +1587,17 @@ EXPORT_SYMBOL_GPL(gpio_free_array);
*/
const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset)
{
unsigned gpio = chip->base + offset;
struct gpio_desc *desc;
if (!gpio_is_valid(gpio) || gpio_desc[gpio].chip != chip)
if (!GPIO_OFFSET_VALID(chip, offset))
return NULL;
if (test_bit(FLAG_REQUESTED, &gpio_desc[gpio].flags) == 0)
desc = &chip->desc[offset];
if (test_bit(FLAG_REQUESTED, &desc->flags) == 0)
return NULL;
#ifdef CONFIG_DEBUG_FS
return gpio_desc[gpio].label;
return desc->label;
#else
return "?";
#endif
......@@ -1515,24 +1614,21 @@ EXPORT_SYMBOL_GPL(gpiochip_is_requested);
* rely on gpio_request() having been called beforehand.
*/
int gpio_direction_input(unsigned gpio)
static int gpiod_direction_input(struct gpio_desc *desc)
{
unsigned long flags;
struct gpio_chip *chip;
struct gpio_desc *desc = &gpio_desc[gpio];
int status = -EINVAL;
int offset;
spin_lock_irqsave(&gpio_lock, flags);
if (!gpio_is_valid(gpio))
if (!desc)
goto fail;
chip = desc->chip;
if (!chip || !chip->get || !chip->direction_input)
goto fail;
gpio -= chip->base;
if (gpio >= chip->ngpio)
goto fail;
status = gpio_ensure_requested(desc, gpio);
status = gpio_ensure_requested(desc);
if (status < 0)
goto fail;
......@@ -1542,11 +1638,12 @@ int gpio_direction_input(unsigned gpio)
might_sleep_if(chip->can_sleep);
offset = gpio_chip_hwgpio(desc);
if (status) {
status = chip->request(chip, gpio);
status = chip->request(chip, offset);
if (status < 0) {
pr_debug("GPIO-%d: chip request fail, %d\n",
chip->base + gpio, status);
desc_to_gpio(desc), status);
/* and it's not available to anyone else ...
* gpio_request() is the fully clean solution.
*/
......@@ -1554,48 +1651,54 @@ int gpio_direction_input(unsigned gpio)
}
}
status = chip->direction_input(chip, gpio);
status = chip->direction_input(chip, offset);
if (status == 0)
clear_bit(FLAG_IS_OUT, &desc->flags);
trace_gpio_direction(chip->base + gpio, 1, status);
trace_gpio_direction(desc_to_gpio(desc), 1, status);
lose:
return status;
fail:
spin_unlock_irqrestore(&gpio_lock, flags);
if (status)
if (status) {
int gpio = -1;
if (desc)
gpio = desc_to_gpio(desc);
pr_debug("%s: gpio-%d status %d\n",
__func__, gpio, status);
}
return status;
}
int gpio_direction_input(unsigned gpio)
{
return gpiod_direction_input(gpio_to_desc(gpio));
}
EXPORT_SYMBOL_GPL(gpio_direction_input);
int gpio_direction_output(unsigned gpio, int value)
static int gpiod_direction_output(struct gpio_desc *desc, int value)
{
unsigned long flags;
struct gpio_chip *chip;
struct gpio_desc *desc = &gpio_desc[gpio];
int status = -EINVAL;
int offset;
/* Open drain pin should not be driven to 1 */
if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags))
return gpio_direction_input(gpio);
return gpiod_direction_input(desc);
/* Open source pin should not be driven to 0 */
if (!value && test_bit(FLAG_OPEN_SOURCE, &desc->flags))
return gpio_direction_input(gpio);
return gpiod_direction_input(desc);
spin_lock_irqsave(&gpio_lock, flags);
if (!gpio_is_valid(gpio))
if (!desc)
goto fail;
chip = desc->chip;
if (!chip || !chip->set || !chip->direction_output)
goto fail;
gpio -= chip->base;
if (gpio >= chip->ngpio)
goto fail;
status = gpio_ensure_requested(desc, gpio);
status = gpio_ensure_requested(desc);
if (status < 0)
goto fail;
......@@ -1605,11 +1708,12 @@ int gpio_direction_output(unsigned gpio, int value)
might_sleep_if(chip->can_sleep);
offset = gpio_chip_hwgpio(desc);
if (status) {
status = chip->request(chip, gpio);
status = chip->request(chip, offset);
if (status < 0) {
pr_debug("GPIO-%d: chip request fail, %d\n",
chip->base + gpio, status);
desc_to_gpio(desc), status);
/* and it's not available to anyone else ...
* gpio_request() is the fully clean solution.
*/
......@@ -1617,20 +1721,29 @@ int gpio_direction_output(unsigned gpio, int value)
}
}
status = chip->direction_output(chip, gpio, value);
status = chip->direction_output(chip, offset, value);
if (status == 0)
set_bit(FLAG_IS_OUT, &desc->flags);
trace_gpio_value(chip->base + gpio, 0, value);
trace_gpio_direction(chip->base + gpio, 0, status);
trace_gpio_value(desc_to_gpio(desc), 0, value);
trace_gpio_direction(desc_to_gpio(desc), 0, status);
lose:
return status;
fail:
spin_unlock_irqrestore(&gpio_lock, flags);
if (status)
if (status) {
int gpio = -1;
if (desc)
gpio = desc_to_gpio(desc);
pr_debug("%s: gpio-%d status %d\n",
__func__, gpio, status);
}
return status;
}
int gpio_direction_output(unsigned gpio, int value)
{
return gpiod_direction_output(gpio_to_desc(gpio), value);
}
EXPORT_SYMBOL_GPL(gpio_direction_output);
/**
......@@ -1638,24 +1751,22 @@ EXPORT_SYMBOL_GPL(gpio_direction_output);
* @gpio: the gpio to set debounce time
* @debounce: debounce time is microseconds
*/
int gpio_set_debounce(unsigned gpio, unsigned debounce)
static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
{
unsigned long flags;
struct gpio_chip *chip;
struct gpio_desc *desc = &gpio_desc[gpio];
int status = -EINVAL;
int offset;
spin_lock_irqsave(&gpio_lock, flags);
if (!gpio_is_valid(gpio))
if (!desc)
goto fail;
chip = desc->chip;
if (!chip || !chip->set || !chip->set_debounce)
goto fail;
gpio -= chip->base;
if (gpio >= chip->ngpio)
goto fail;
status = gpio_ensure_requested(desc, gpio);
status = gpio_ensure_requested(desc);
if (status < 0)
goto fail;
......@@ -1665,16 +1776,26 @@ int gpio_set_debounce(unsigned gpio, unsigned debounce)
might_sleep_if(chip->can_sleep);
return chip->set_debounce(chip, gpio, debounce);
offset = gpio_chip_hwgpio(desc);
return chip->set_debounce(chip, offset, debounce);
fail:
spin_unlock_irqrestore(&gpio_lock, flags);
if (status)
if (status) {
int gpio = -1;
if (desc)
gpio = desc_to_gpio(desc);
pr_debug("%s: gpio-%d status %d\n",
__func__, gpio, status);
}
return status;
}
int gpio_set_debounce(unsigned gpio, unsigned debounce)
{
return gpiod_set_debounce(gpio_to_desc(gpio), debounce);
}
EXPORT_SYMBOL_GPL(gpio_set_debounce);
/* I/O calls are only valid after configuration completed; the relevant
......@@ -1708,18 +1829,25 @@ EXPORT_SYMBOL_GPL(gpio_set_debounce);
* It returns the zero or nonzero value provided by the associated
* gpio_chip.get() method; or zero if no such method is provided.
*/
int __gpio_get_value(unsigned gpio)
static int gpiod_get_value(struct gpio_desc *desc)
{
struct gpio_chip *chip;
int value;
int offset;
chip = gpio_to_chip(gpio);
chip = desc->chip;
offset = gpio_chip_hwgpio(desc);
/* Should be using gpio_get_value_cansleep() */
WARN_ON(chip->can_sleep);
value = chip->get ? chip->get(chip, gpio - chip->base) : 0;
trace_gpio_value(gpio, 1, value);
value = chip->get ? chip->get(chip, offset) : 0;
trace_gpio_value(desc_to_gpio(desc), 1, value);
return value;
}
int __gpio_get_value(unsigned gpio)
{
return gpiod_get_value(gpio_to_desc(gpio));
}
EXPORT_SYMBOL_GPL(__gpio_get_value);
/*
......@@ -1728,23 +1856,25 @@ EXPORT_SYMBOL_GPL(__gpio_get_value);
* @chip: Gpio chip.
* @value: Non-zero for setting it HIGH otherise it will set to LOW.
*/
static void _gpio_set_open_drain_value(unsigned gpio,
struct gpio_chip *chip, int value)
static void _gpio_set_open_drain_value(struct gpio_desc *desc, int value)
{
int err = 0;
struct gpio_chip *chip = desc->chip;
int offset = gpio_chip_hwgpio(desc);
if (value) {
err = chip->direction_input(chip, gpio - chip->base);
err = chip->direction_input(chip, offset);
if (!err)
clear_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags);
clear_bit(FLAG_IS_OUT, &desc->flags);
} else {
err = chip->direction_output(chip, gpio - chip->base, 0);
err = chip->direction_output(chip, offset, 0);
if (!err)
set_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags);
set_bit(FLAG_IS_OUT, &desc->flags);
}
trace_gpio_direction(gpio, value, err);
trace_gpio_direction(desc_to_gpio(desc), value, err);
if (err < 0)
pr_err("%s: Error in set_value for open drain gpio%d err %d\n",
__func__, gpio, err);
__func__, desc_to_gpio(desc), err);
}
/*
......@@ -1753,26 +1883,27 @@ static void _gpio_set_open_drain_value(unsigned gpio,
* @chip: Gpio chip.
* @value: Non-zero for setting it HIGH otherise it will set to LOW.
*/
static void _gpio_set_open_source_value(unsigned gpio,
struct gpio_chip *chip, int value)
static void _gpio_set_open_source_value(struct gpio_desc *desc, int value)
{
int err = 0;
struct gpio_chip *chip = desc->chip;
int offset = gpio_chip_hwgpio(desc);
if (value) {
err = chip->direction_output(chip, gpio - chip->base, 1);
err = chip->direction_output(chip, offset, 1);
if (!err)
set_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags);
set_bit(FLAG_IS_OUT, &desc->flags);
} else {
err = chip->direction_input(chip, gpio - chip->base);
err = chip->direction_input(chip, offset);
if (!err)
clear_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags);
clear_bit(FLAG_IS_OUT, &desc->flags);
}
trace_gpio_direction(gpio, !value, err);
trace_gpio_direction(desc_to_gpio(desc), !value, err);
if (err < 0)
pr_err("%s: Error in set_value for open source gpio%d err %d\n",
__func__, gpio, err);
__func__, desc_to_gpio(desc), err);
}
/**
* __gpio_set_value() - assign a gpio's value
* @gpio: gpio whose value will be assigned
......@@ -1782,20 +1913,25 @@ static void _gpio_set_open_source_value(unsigned gpio,
* This is used directly or indirectly to implement gpio_set_value().
* It invokes the associated gpio_chip.set() method.
*/
void __gpio_set_value(unsigned gpio, int value)
static void gpiod_set_value(struct gpio_desc *desc, int value)
{
struct gpio_chip *chip;
chip = gpio_to_chip(gpio);
chip = desc->chip;
/* Should be using gpio_set_value_cansleep() */
WARN_ON(chip->can_sleep);
trace_gpio_value(gpio, 0, value);
if (test_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags))
_gpio_set_open_drain_value(gpio, chip, value);
else if (test_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags))
_gpio_set_open_source_value(gpio, chip, value);
trace_gpio_value(desc_to_gpio(desc), 0, value);
if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
_gpio_set_open_drain_value(desc, value);
else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags))
_gpio_set_open_source_value(desc, value);
else
chip->set(chip, gpio - chip->base, value);
chip->set(chip, gpio_chip_hwgpio(desc), value);
}
void __gpio_set_value(unsigned gpio, int value)
{
return gpiod_set_value(gpio_to_desc(gpio), value);
}
EXPORT_SYMBOL_GPL(__gpio_set_value);
......@@ -1807,14 +1943,15 @@ EXPORT_SYMBOL_GPL(__gpio_set_value);
* This is used directly or indirectly to implement gpio_cansleep(). It
* returns nonzero if access reading or writing the GPIO value can sleep.
*/
int __gpio_cansleep(unsigned gpio)
static int gpiod_cansleep(struct gpio_desc *desc)
{
struct gpio_chip *chip;
/* only call this on GPIOs that are valid! */
chip = gpio_to_chip(gpio);
return desc->chip->can_sleep;
}
return chip->can_sleep;
int __gpio_cansleep(unsigned gpio)
{
return gpiod_cansleep(gpio_to_desc(gpio));
}
EXPORT_SYMBOL_GPL(__gpio_cansleep);
......@@ -1827,50 +1964,67 @@ EXPORT_SYMBOL_GPL(__gpio_cansleep);
* It returns the number of the IRQ signaled by this (input) GPIO,
* or a negative errno.
*/
int __gpio_to_irq(unsigned gpio)
static int gpiod_to_irq(struct gpio_desc *desc)
{
struct gpio_chip *chip;
int offset;
chip = gpio_to_chip(gpio);
return chip->to_irq ? chip->to_irq(chip, gpio - chip->base) : -ENXIO;
chip = desc->chip;
offset = gpio_chip_hwgpio(desc);
return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO;
}
EXPORT_SYMBOL_GPL(__gpio_to_irq);
int __gpio_to_irq(unsigned gpio)
{
return gpiod_to_irq(gpio_to_desc(gpio));
}
EXPORT_SYMBOL_GPL(__gpio_to_irq);
/* There's no value in making it easy to inline GPIO calls that may sleep.
* Common examples include ones connected to I2C or SPI chips.
*/
int gpio_get_value_cansleep(unsigned gpio)
static int gpiod_get_value_cansleep(struct gpio_desc *desc)
{
struct gpio_chip *chip;
int value;
int offset;
might_sleep_if(extra_checks);
chip = gpio_to_chip(gpio);
value = chip->get ? chip->get(chip, gpio - chip->base) : 0;
trace_gpio_value(gpio, 1, value);
chip = desc->chip;
offset = gpio_chip_hwgpio(desc);
value = chip->get ? chip->get(chip, offset) : 0;
trace_gpio_value(desc_to_gpio(desc), 1, value);
return value;
}
int gpio_get_value_cansleep(unsigned gpio)
{
return gpiod_get_value_cansleep(gpio_to_desc(gpio));
}
EXPORT_SYMBOL_GPL(gpio_get_value_cansleep);
void gpio_set_value_cansleep(unsigned gpio, int value)
static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
{
struct gpio_chip *chip;
might_sleep_if(extra_checks);
chip = gpio_to_chip(gpio);
trace_gpio_value(gpio, 0, value);
if (test_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags))
_gpio_set_open_drain_value(gpio, chip, value);
else if (test_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags))
_gpio_set_open_source_value(gpio, chip, value);
chip = desc->chip;
trace_gpio_value(desc_to_gpio(desc), 0, value);
if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
_gpio_set_open_drain_value(desc, value);
else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags))
_gpio_set_open_source_value(desc, value);
else
chip->set(chip, gpio - chip->base, value);
chip->set(chip, gpio_chip_hwgpio(desc), value);
}
EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);
void gpio_set_value_cansleep(unsigned gpio, int value)
{
return gpiod_set_value_cansleep(gpio_to_desc(gpio), value);
}
EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);
#ifdef CONFIG_DEBUG_FS
......@@ -1878,14 +2032,14 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{
unsigned i;
unsigned gpio = chip->base;
struct gpio_desc *gdesc = &gpio_desc[gpio];
struct gpio_desc *gdesc = &chip->desc[0];
int is_out;
for (i = 0; i < chip->ngpio; i++, gpio++, gdesc++) {
if (!test_bit(FLAG_REQUESTED, &gdesc->flags))
continue;
gpio_get_direction(gpio);
gpiod_get_direction(gdesc);
is_out = test_bit(FLAG_IS_OUT, &gdesc->flags);
seq_printf(s, " gpio-%-3d (%-20.20s) %s %s",
gpio, gdesc->label,
......@@ -1899,46 +2053,35 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
static void *gpiolib_seq_start(struct seq_file *s, loff_t *pos)
{
unsigned long flags;
struct gpio_chip *chip = NULL;
unsigned int gpio;
void *ret = NULL;
loff_t index = 0;
/* REVISIT this isn't locked against gpio_chip removal ... */
for (gpio = 0; gpio_is_valid(gpio); gpio++) {
if (gpio_desc[gpio].chip == chip)
continue;
loff_t index = *pos;
chip = gpio_desc[gpio].chip;
if (!chip)
continue;
s->private = "";
if (index++ >= *pos) {
ret = chip;
break;
}
spin_lock_irqsave(&gpio_lock, flags);
list_for_each_entry(chip, &gpio_chips, list)
if (index-- == 0) {
spin_unlock_irqrestore(&gpio_lock, flags);
return chip;
}
spin_unlock_irqrestore(&gpio_lock, flags);
s->private = "";
return ret;
return NULL;
}
static void *gpiolib_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
unsigned long flags;
struct gpio_chip *chip = v;
unsigned int gpio;
void *ret = NULL;
/* skip GPIOs provided by the current chip */
for (gpio = chip->base + chip->ngpio; gpio_is_valid(gpio); gpio++) {
chip = gpio_desc[gpio].chip;
if (chip) {
ret = chip;
break;
}
}
spin_lock_irqsave(&gpio_lock, flags);
if (list_is_last(&chip->list, &gpio_chips))
ret = NULL;
else
ret = list_entry(chip->list.next, struct gpio_chip, list);
spin_unlock_irqrestore(&gpio_lock, flags);
s->private = "\n";
++*pos;
......
......@@ -47,12 +47,14 @@ struct gpio;
struct seq_file;
struct module;
struct device_node;
struct gpio_desc;
/**
* struct gpio_chip - abstract a GPIO controller
* @label: for diagnostics
* @dev: optional device providing the 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
* enabling module power and clock; may sleep
* @free: optional hook for chip-specific deactivation, such as
......@@ -75,6 +77,7 @@ struct device_node;
* negative during registration, requests dynamic ID allocation.
* @ngpio: the number of GPIOs handled by this controller; the last GPIO
* handled is (base + ngpio - 1).
* @desc: array of ngpio descriptors. Private.
* @can_sleep: flag must be set iff get()/set() methods sleep, as they
* must while accessing GPIO expander chips over I2C or SPI
* @names: if set, must be an array of strings to use as alternative
......@@ -98,6 +101,7 @@ struct gpio_chip {
const char *label;
struct device *dev;
struct module *owner;
struct list_head list;
int (*request)(struct gpio_chip *chip,
unsigned offset);
......@@ -124,6 +128,7 @@ struct gpio_chip {
struct gpio_chip *chip);
int base;
u16 ngpio;
struct gpio_desc *desc;
const char *const *names;
unsigned can_sleep:1;
unsigned exported:1;
......@@ -152,7 +157,6 @@ struct gpio_chip {
extern const char *gpiochip_is_requested(struct gpio_chip *chip,
unsigned offset);
extern struct gpio_chip *gpio_to_chip(unsigned gpio);
extern int __must_check gpiochip_reserve(int start, int ngpio);
/* add/remove chips */
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
extern int gpio_request_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
/*
......@@ -212,6 +210,43 @@ extern void gpio_unexport(unsigned gpio);
#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 */
static inline bool gpio_is_valid(int number)
......@@ -270,41 +305,4 @@ static inline void gpio_unexport(unsigned gpio)
}
#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 */
......@@ -2,10 +2,12 @@
#define _LINUX_ACPI_GPIO_H_
#include <linux/errno.h>
#include <linux/gpio.h>
#ifdef CONFIG_GPIO_ACPI
int acpi_get_gpio(char *path, int pin);
void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
#else /* CONFIG_GPIO_ACPI */
......@@ -14,6 +16,8 @@ static inline int acpi_get_gpio(char *path, int pin)
return -ENODEV;
}
static inline void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { }
#endif /* CONFIG_GPIO_ACPI */
#endif /* _LINUX_ACPI_GPIO_H_ */
......@@ -94,24 +94,12 @@ static inline int gpio_request(unsigned gpio, const char *label)
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,
unsigned long flags, const char *label)
{
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)
{
return -ENOSYS;
......@@ -125,14 +113,6 @@ static inline void gpio_free(unsigned gpio)
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)
{
might_sleep();
......@@ -248,4 +228,12 @@ gpiochip_remove_pin_ranges(struct gpio_chip *chip)
#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 */
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