Merge tag 'gpio-v3.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

Pull GPIO changes from Linus Walleij:
 "Here is the bulk of GPIO changes for the v3.13 development cycle.

  I've got ACKs for the things that affect other subsystems (or it's my
  own subsystem, like pinctrl).  Most of that pertain to an attempt from
  my side to consolidate and get rid of custom GPIO implementations in
  the ARM tree.  I will continue doing this.

  The main change this time is the new GPIO descriptor API, background
  for this can be found in Corbet's summary from this january in LWN:

    http://lwn.net/Articles/533632/

  Summary:

   - Merged the GPIO descriptor API from Alexandre Courbot.  This is a
     first step toward trying to get rid of the global GPIO numberspace
     for the future.

   - Add an API so that driver can flag that a certain GPIO line is
     being used by a irqchip backend for generating IRQs, so that we can
     enforce checks, like not allowing users to switch that line to an
     output at runtime, since this makes no sense.  Implemented
     corresponding calls in a few select drivers.

   - ACPI GPIO cleanups, refactorings and switch to using the
     descriptor-based interface.

   - Support for the TPS80036 Palmas GPIO variant.

   - A new driver for the Broadcom Kona GPIO SoC IP block.

   - Device tree support for the PCF857x driver.

   - A set of ARM GPIO refactorings with the goal of getting rid of a
     bunch of custom GPIO implementations from the arch/arm/* tree:

     * Move the IOP GPIO driver to the GPIO subsystem and fix all users
       to use the gpiolib API for accessing GPIOs.  Delete the old
       custom GPIO implementation.

     * Delete the unused custom PXA GPIO implemention.

     * Convert all users of the IXP4 custom GPIO implementation to use
       gpiolib and delete the custom implementation.

     * Delete the custom Gemini GPIO implementation, also completely
       unused.

   - Various cleanups and renamings"

* tag 'gpio-v3.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (85 commits)
  gpio: gpio-mxs: Remove unneeded dt checks
  gpio: pl061: don't depend on CONFIG_ARM
  gpio: bcm-kona: add missing .owner to struct gpio_chip
  gpiolib: provide a declaration of seq_file in gpio/driver.h
  gpiolib: include gpio/consumer.h in of_gpio.h for desc_to_gpio()
  gpio: provide stubs for devres gpio functions
  gpiolib: devres: add missing headers
  gpiolib: make GPIO_DEVRES depend on GPIOLIB
  gpiolib: devres: fix devm_gpiod_get_index()
  gpiolib / ACPI: document the GPIO descriptor based interface
  gpiolib / ACPI: allow passing GPIOF_ACTIVE_LOW for GpioInt resources
  gpiolib / ACPI: add ACPI support for gpiod_get_index()
  gpiolib / ACPI: convert to gpiod interfaces
  gpiolib: add gpiod_get() and gpiod_put() functions
  gpiolib: port of_ functions to use gpiod
  gpiolib: export descriptor-based GPIO interface
  Fixup "MAINTAINERS: GPIO-INTEL-MID: add maintainer"
  gpio: bcm281xx: Don't print addresses of GPIO area in probe()
  gpio: tegra: use new gpio_lock_as_irq() API
  gpio: rcar: Include linux/of.h header
  ...
This commit is contained in:
Linus Torvalds
2013-11-12 15:50:46 +09:00
當前提交 c2d3306991
共有 74 個文件被更改,包括 3234 次插入1490 次删除

查看文件

@@ -30,10 +30,6 @@ 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
bool "GPIO Support"
@@ -47,6 +43,10 @@ menuconfig GPIOLIB
if GPIOLIB
config GPIO_DEVRES
def_bool y
depends on HAS_IOMEM
config OF_GPIO
def_bool y
depends on OF
@@ -129,7 +129,7 @@ config GPIO_IT8761E
config GPIO_EM
tristate "Emma Mobile GPIO"
depends on ARM
depends on ARM && OF_GPIO
help
Say yes here to support GPIO on Renesas Emma Mobile SoCs.
@@ -213,7 +213,7 @@ config GPIO_OCTEON
config GPIO_PL061
bool "PrimeCell PL061 GPIO support"
depends on ARM && ARM_AMBA
depends on ARM_AMBA
select GENERIC_IRQ_CHIP
help
Say yes here to support the PrimeCell PL061 GPIO device
@@ -320,6 +320,15 @@ config GPIO_ICH
If unsure, say N.
config GPIO_IOP
tristate "Intel IOP GPIO"
depends on ARM && (ARCH_IOP32X || ARCH_IOP33X)
help
Say yes here to support the GPIO functionality of a number of Intel
IOP32X or IOP33X.
If unsure, say N.
config GPIO_VX855
tristate "VIA VX855/VX875 GPIO"
depends on PCI
@@ -616,12 +625,12 @@ config GPIO_AMD8111
If unsure, say N
config GPIO_LANGWELL
bool "Intel Langwell/Penwell GPIO support"
config GPIO_INTEL_MID
bool "Intel Mid GPIO support"
depends on PCI && X86
select IRQ_DOMAIN
help
Say Y here to support Intel Langwell/Penwell GPIO.
Say Y here to support Intel Mid GPIO.
config GPIO_PCH
tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7223/ML7831) GPIO"
@@ -707,7 +716,7 @@ config GPIO_74X164
comment "AC97 GPIO expanders:"
config GPIO_UCB1400
bool "Philips UCB1400 GPIO"
tristate "Philips UCB1400 GPIO"
depends on UCB1400_CORE
help
This enables support for the Philips UCB1400 GPIO pins.
@@ -763,6 +772,12 @@ config GPIO_MSIC
Enable support for GPIO on intel MSIC controllers found in
intel MID devices
config GPIO_BCM_KONA
bool "Broadcom Kona GPIO"
depends on OF_GPIO
help
Turn on GPIO support for Broadcom "Kona" chips.
comment "USB GPIO expanders:"
config GPIO_VIPERBOARD

查看文件

@@ -16,6 +16,7 @@ obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
@@ -28,11 +29,12 @@ obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o
obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
obj-$(CONFIG_GPIO_IOP) += gpio-iop.o
obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o
obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o
obj-$(CONFIG_GPIO_LANGWELL) += gpio-langwell.o
obj-$(CONFIG_GPIO_INTEL_MID) += gpio-intel-mid.o
obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o
obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o
obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o

查看文件

@@ -15,10 +15,95 @@
*/
#include <linux/module.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/device.h>
#include <linux/gfp.h>
static void devm_gpiod_release(struct device *dev, void *res)
{
struct gpio_desc **desc = res;
gpiod_put(*desc);
}
static int devm_gpiod_match(struct device *dev, void *res, void *data)
{
struct gpio_desc **this = res, **gpio = data;
return *this == *gpio;
}
/**
* devm_gpiod_get - Resource-managed gpiod_get()
* @dev: GPIO consumer
* @con_id: function within the GPIO consumer
*
* Managed gpiod_get(). GPIO descriptors returned from this function are
* automatically disposed on driver detach. See gpiod_get() for detailed
* information about behavior and return values.
*/
struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
const char *con_id)
{
return devm_gpiod_get_index(dev, con_id, 0);
}
EXPORT_SYMBOL(devm_gpiod_get);
/**
* devm_gpiod_get_index - Resource-managed gpiod_get_index()
* @dev: GPIO consumer
* @con_id: function within the GPIO consumer
* @idx: index of the GPIO to obtain in the consumer
*
* Managed gpiod_get_index(). GPIO descriptors returned from this function are
* automatically disposed on driver detach. See gpiod_get_index() for detailed
* information about behavior and return values.
*/
struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
const char *con_id,
unsigned int idx)
{
struct gpio_desc **dr;
struct gpio_desc *desc;
dr = devres_alloc(devm_gpiod_release, sizeof(struct gpiod_desc *),
GFP_KERNEL);
if (!dr)
return ERR_PTR(-ENOMEM);
desc = gpiod_get_index(dev, con_id, idx);
if (IS_ERR(desc)) {
devres_free(dr);
return desc;
}
*dr = desc;
devres_add(dev, dr);
return desc;
}
EXPORT_SYMBOL(devm_gpiod_get_index);
/**
* devm_gpiod_put - Resource-managed gpiod_put()
* @desc: GPIO descriptor to dispose of
*
* Dispose of a GPIO descriptor obtained with devm_gpiod_get() or
* devm_gpiod_get_index(). Normally this function will not be called as the GPIO
* will be disposed of by the resource management code.
*/
void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
{
WARN_ON(devres_release(dev, devm_gpiod_release, devm_gpiod_match,
&desc));
}
EXPORT_SYMBOL(devm_gpiod_put);
static void devm_gpio_release(struct device *dev, void *res)
{
unsigned *gpio = res;

查看文件

@@ -176,7 +176,6 @@ static int gen_74x164_probe(struct spi_device *spi)
return ret;
exit_destroy:
spi_set_drvdata(spi, NULL);
mutex_destroy(&chip->lock);
return ret;
}
@@ -190,8 +189,6 @@ static int gen_74x164_remove(struct spi_device *spi)
if (chip == NULL)
return -ENODEV;
spi_set_drvdata(spi, NULL);
ret = gpiochip_remove(&chip->gpio_chip);
if (!ret)
mutex_destroy(&chip->lock);
@@ -212,7 +209,7 @@ static struct spi_driver gen_74x164_driver = {
.driver = {
.name = "74x164",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(gen_74x164_dt_ids),
.of_match_table = gen_74x164_dt_ids,
},
.probe = gen_74x164_probe,
.remove = gen_74x164_remove,

查看文件

@@ -325,9 +325,9 @@ static irqreturn_t adnp_irq(int irq, void *data)
pending &= isr & ier;
for_each_set_bit(bit, &pending, 8) {
unsigned int virq;
virq = irq_find_mapping(adnp->domain, base + bit);
handle_nested_irq(virq);
unsigned int child_irq;
child_irq = irq_find_mapping(adnp->domain, base + bit);
handle_nested_irq(child_irq);
}
}
@@ -594,7 +594,7 @@ static struct i2c_driver adnp_i2c_driver = {
.driver = {
.name = "gpio-adnp",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(adnp_of_match),
.of_match_table = adnp_of_match,
},
.probe = adnp_i2c_probe,
.remove = adnp_i2c_remove,

查看文件

@@ -109,10 +109,14 @@ static int arizona_gpio_probe(struct platform_device *pdev)
arizona_gpio->arizona = arizona;
arizona_gpio->gpio_chip = template_chip;
arizona_gpio->gpio_chip.dev = &pdev->dev;
#ifdef CONFIG_OF_GPIO
arizona_gpio->gpio_chip.of_node = arizona->dev->of_node;
#endif
switch (arizona->type) {
case WM5102:
case WM5110:
case WM8997:
arizona_gpio->gpio_chip.ngpio = 5;
break;
default:

查看文件

@@ -0,0 +1,640 @@
/*
* Copyright (C) 2012-2013 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/bitops.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/module.h>
#include <linux/irqdomain.h>
#include <linux/irqchip/chained_irq.h>
#define BCM_GPIO_PASSWD 0x00a5a501
#define GPIO_PER_BANK 32
#define GPIO_MAX_BANK_NUM 8
#define GPIO_BANK(gpio) ((gpio) >> 5)
#define GPIO_BIT(gpio) ((gpio) & (GPIO_PER_BANK - 1))
#define GPIO_OUT_STATUS(bank) (0x00000000 + ((bank) << 2))
#define GPIO_IN_STATUS(bank) (0x00000020 + ((bank) << 2))
#define GPIO_OUT_SET(bank) (0x00000040 + ((bank) << 2))
#define GPIO_OUT_CLEAR(bank) (0x00000060 + ((bank) << 2))
#define GPIO_INT_STATUS(bank) (0x00000080 + ((bank) << 2))
#define GPIO_INT_MASK(bank) (0x000000a0 + ((bank) << 2))
#define GPIO_INT_MSKCLR(bank) (0x000000c0 + ((bank) << 2))
#define GPIO_CONTROL(bank) (0x00000100 + ((bank) << 2))
#define GPIO_PWD_STATUS(bank) (0x00000500 + ((bank) << 2))
#define GPIO_GPPWR_OFFSET 0x00000520
#define GPIO_GPCTR0_DBR_SHIFT 5
#define GPIO_GPCTR0_DBR_MASK 0x000001e0
#define GPIO_GPCTR0_ITR_SHIFT 3
#define GPIO_GPCTR0_ITR_MASK 0x00000018
#define GPIO_GPCTR0_ITR_CMD_RISING_EDGE 0x00000001
#define GPIO_GPCTR0_ITR_CMD_FALLING_EDGE 0x00000002
#define GPIO_GPCTR0_ITR_CMD_BOTH_EDGE 0x00000003
#define GPIO_GPCTR0_IOTR_MASK 0x00000001
#define GPIO_GPCTR0_IOTR_CMD_0UTPUT 0x00000000
#define GPIO_GPCTR0_IOTR_CMD_INPUT 0x00000001
#define GPIO_GPCTR0_DB_ENABLE_MASK 0x00000100
#define LOCK_CODE 0xffffffff
#define UNLOCK_CODE 0x00000000
struct bcm_kona_gpio {
void __iomem *reg_base;
int num_bank;
spinlock_t lock;
struct gpio_chip gpio_chip;
struct irq_domain *irq_domain;
struct bcm_kona_gpio_bank *banks;
struct platform_device *pdev;
};
struct bcm_kona_gpio_bank {
int id;
int irq;
/* Used in the interrupt handler */
struct bcm_kona_gpio *kona_gpio;
};
static inline struct bcm_kona_gpio *to_kona_gpio(struct gpio_chip *chip)
{
return container_of(chip, struct bcm_kona_gpio, gpio_chip);
}
static void bcm_kona_gpio_set_lockcode_bank(void __iomem *reg_base,
int bank_id, int lockcode)
{
writel(BCM_GPIO_PASSWD, reg_base + GPIO_GPPWR_OFFSET);
writel(lockcode, reg_base + GPIO_PWD_STATUS(bank_id));
}
static inline void bcm_kona_gpio_lock_bank(void __iomem *reg_base, int bank_id)
{
bcm_kona_gpio_set_lockcode_bank(reg_base, bank_id, LOCK_CODE);
}
static inline void bcm_kona_gpio_unlock_bank(void __iomem *reg_base,
int bank_id)
{
bcm_kona_gpio_set_lockcode_bank(reg_base, bank_id, UNLOCK_CODE);
}
static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
{
struct bcm_kona_gpio *kona_gpio;
void __iomem *reg_base;
int bank_id = GPIO_BANK(gpio);
int bit = GPIO_BIT(gpio);
u32 val, reg_offset;
unsigned long flags;
kona_gpio = to_kona_gpio(chip);
reg_base = kona_gpio->reg_base;
spin_lock_irqsave(&kona_gpio->lock, flags);
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
/* determine the GPIO pin direction */
val = readl(reg_base + GPIO_CONTROL(gpio));
val &= GPIO_GPCTR0_IOTR_MASK;
/* this function only applies to output pin */
if (GPIO_GPCTR0_IOTR_CMD_INPUT == val)
goto out;
reg_offset = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
val = readl(reg_base + reg_offset);
val |= BIT(bit);
writel(val, reg_base + reg_offset);
out:
bcm_kona_gpio_lock_bank(reg_base, bank_id);
spin_unlock_irqrestore(&kona_gpio->lock, flags);
}
static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
{
struct bcm_kona_gpio *kona_gpio;
void __iomem *reg_base;
int bank_id = GPIO_BANK(gpio);
int bit = GPIO_BIT(gpio);
u32 val, reg_offset;
unsigned long flags;
kona_gpio = to_kona_gpio(chip);
reg_base = kona_gpio->reg_base;
spin_lock_irqsave(&kona_gpio->lock, flags);
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
/* determine the GPIO pin direction */
val = readl(reg_base + GPIO_CONTROL(gpio));
val &= GPIO_GPCTR0_IOTR_MASK;
/* read the GPIO bank status */
reg_offset = (GPIO_GPCTR0_IOTR_CMD_INPUT == val) ?
GPIO_IN_STATUS(bank_id) : GPIO_OUT_STATUS(bank_id);
val = readl(reg_base + reg_offset);
bcm_kona_gpio_lock_bank(reg_base, bank_id);
spin_unlock_irqrestore(&kona_gpio->lock, flags);
/* return the specified bit status */
return !!(val & bit);
}
static int bcm_kona_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
struct bcm_kona_gpio *kona_gpio;
void __iomem *reg_base;
u32 val;
unsigned long flags;
int bank_id = GPIO_BANK(gpio);
kona_gpio = to_kona_gpio(chip);
reg_base = kona_gpio->reg_base;
spin_lock_irqsave(&kona_gpio->lock, flags);
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
val = readl(reg_base + GPIO_CONTROL(gpio));
val &= ~GPIO_GPCTR0_IOTR_MASK;
val |= GPIO_GPCTR0_IOTR_CMD_INPUT;
writel(val, reg_base + GPIO_CONTROL(gpio));
bcm_kona_gpio_lock_bank(reg_base, bank_id);
spin_unlock_irqrestore(&kona_gpio->lock, flags);
return 0;
}
static int bcm_kona_gpio_direction_output(struct gpio_chip *chip,
unsigned gpio, int value)
{
struct bcm_kona_gpio *kona_gpio;
void __iomem *reg_base;
int bank_id = GPIO_BANK(gpio);
int bit = GPIO_BIT(gpio);
u32 val, reg_offset;
unsigned long flags;
kona_gpio = to_kona_gpio(chip);
reg_base = kona_gpio->reg_base;
spin_lock_irqsave(&kona_gpio->lock, flags);
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
val = readl(reg_base + GPIO_CONTROL(gpio));
val &= ~GPIO_GPCTR0_IOTR_MASK;
val |= GPIO_GPCTR0_IOTR_CMD_0UTPUT;
writel(val, reg_base + GPIO_CONTROL(gpio));
reg_offset = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
val = readl(reg_base + reg_offset);
val |= BIT(bit);
writel(val, reg_base + reg_offset);
bcm_kona_gpio_lock_bank(reg_base, bank_id);
spin_unlock_irqrestore(&kona_gpio->lock, flags);
return 0;
}
static int bcm_kona_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
{
struct bcm_kona_gpio *kona_gpio;
kona_gpio = to_kona_gpio(chip);
if (gpio >= kona_gpio->gpio_chip.ngpio)
return -ENXIO;
return irq_create_mapping(kona_gpio->irq_domain, gpio);
}
static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
unsigned debounce)
{
struct bcm_kona_gpio *kona_gpio;
void __iomem *reg_base;
u32 val, res;
unsigned long flags;
int bank_id = GPIO_BANK(gpio);
kona_gpio = to_kona_gpio(chip);
reg_base = kona_gpio->reg_base;
/* debounce must be 1-128ms (or 0) */
if ((debounce > 0 && debounce < 1000) || debounce > 128000) {
dev_err(chip->dev, "Debounce value %u not in range\n",
debounce);
return -EINVAL;
}
/* calculate debounce bit value */
if (debounce != 0) {
/* Convert to ms */
debounce /= 1000;
/* find the MSB */
res = fls(debounce) - 1;
/* Check if MSB-1 is set (round up or down) */
if (res > 0 && (debounce & BIT(res - 1)))
res++;
}
/* spin lock for read-modify-write of the GPIO register */
spin_lock_irqsave(&kona_gpio->lock, flags);
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
val = readl(reg_base + GPIO_CONTROL(gpio));
val &= ~GPIO_GPCTR0_DBR_MASK;
if (debounce == 0) {
/* disable debounce */
val &= ~GPIO_GPCTR0_DB_ENABLE_MASK;
} else {
val |= GPIO_GPCTR0_DB_ENABLE_MASK |
(res << GPIO_GPCTR0_DBR_SHIFT);
}
writel(val, reg_base + GPIO_CONTROL(gpio));
bcm_kona_gpio_lock_bank(reg_base, bank_id);
spin_unlock_irqrestore(&kona_gpio->lock, flags);
return 0;
}
static struct gpio_chip template_chip = {
.label = "bcm-kona-gpio",
.owner = THIS_MODULE,
.direction_input = bcm_kona_gpio_direction_input,
.get = bcm_kona_gpio_get,
.direction_output = bcm_kona_gpio_direction_output,
.set = bcm_kona_gpio_set,
.set_debounce = bcm_kona_gpio_set_debounce,
.to_irq = bcm_kona_gpio_to_irq,
.base = 0,
};
static void bcm_kona_gpio_irq_ack(struct irq_data *d)
{
struct bcm_kona_gpio *kona_gpio;
void __iomem *reg_base;
int gpio = d->hwirq;
int bank_id = GPIO_BANK(gpio);
int bit = GPIO_BIT(gpio);
u32 val;
unsigned long flags;
kona_gpio = irq_data_get_irq_chip_data(d);
reg_base = kona_gpio->reg_base;
spin_lock_irqsave(&kona_gpio->lock, flags);
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
val = readl(reg_base + GPIO_INT_STATUS(bank_id));
val |= BIT(bit);
writel(val, reg_base + GPIO_INT_STATUS(bank_id));
bcm_kona_gpio_lock_bank(reg_base, bank_id);
spin_unlock_irqrestore(&kona_gpio->lock, flags);
}
static void bcm_kona_gpio_irq_mask(struct irq_data *d)
{
struct bcm_kona_gpio *kona_gpio;
void __iomem *reg_base;
int gpio = d->hwirq;
int bank_id = GPIO_BANK(gpio);
int bit = GPIO_BIT(gpio);
u32 val;
unsigned long flags;
kona_gpio = irq_data_get_irq_chip_data(d);
reg_base = kona_gpio->reg_base;
spin_lock_irqsave(&kona_gpio->lock, flags);
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
val = readl(reg_base + GPIO_INT_MASK(bank_id));
val |= BIT(bit);
writel(val, reg_base + GPIO_INT_MASK(bank_id));
bcm_kona_gpio_lock_bank(reg_base, bank_id);
spin_unlock_irqrestore(&kona_gpio->lock, flags);
}
static void bcm_kona_gpio_irq_unmask(struct irq_data *d)
{
struct bcm_kona_gpio *kona_gpio;
void __iomem *reg_base;
int gpio = d->hwirq;
int bank_id = GPIO_BANK(gpio);
int bit = GPIO_BIT(gpio);
u32 val;
unsigned long flags;
kona_gpio = irq_data_get_irq_chip_data(d);
reg_base = kona_gpio->reg_base;
spin_lock_irqsave(&kona_gpio->lock, flags);
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
val = readl(reg_base + GPIO_INT_MSKCLR(bank_id));
val |= BIT(bit);
writel(val, reg_base + GPIO_INT_MSKCLR(bank_id));
bcm_kona_gpio_lock_bank(reg_base, bank_id);
spin_unlock_irqrestore(&kona_gpio->lock, flags);
}
static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
struct bcm_kona_gpio *kona_gpio;
void __iomem *reg_base;
int gpio = d->hwirq;
u32 lvl_type;
u32 val;
unsigned long flags;
int bank_id = GPIO_BANK(gpio);
kona_gpio = irq_data_get_irq_chip_data(d);
reg_base = kona_gpio->reg_base;
switch (type & IRQ_TYPE_SENSE_MASK) {
case IRQ_TYPE_EDGE_RISING:
lvl_type = GPIO_GPCTR0_ITR_CMD_RISING_EDGE;
break;
case IRQ_TYPE_EDGE_FALLING:
lvl_type = GPIO_GPCTR0_ITR_CMD_FALLING_EDGE;
break;
case IRQ_TYPE_EDGE_BOTH:
lvl_type = GPIO_GPCTR0_ITR_CMD_BOTH_EDGE;
break;
case IRQ_TYPE_LEVEL_HIGH:
case IRQ_TYPE_LEVEL_LOW:
/* BCM GPIO doesn't support level triggering */
default:
dev_err(kona_gpio->gpio_chip.dev,
"Invalid BCM GPIO irq type 0x%x\n", type);
return -EINVAL;
}
spin_lock_irqsave(&kona_gpio->lock, flags);
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
val = readl(reg_base + GPIO_CONTROL(gpio));
val &= ~GPIO_GPCTR0_ITR_MASK;
val |= lvl_type << GPIO_GPCTR0_ITR_SHIFT;
writel(val, reg_base + GPIO_CONTROL(gpio));
bcm_kona_gpio_lock_bank(reg_base, bank_id);
spin_unlock_irqrestore(&kona_gpio->lock, flags);
return 0;
}
static void bcm_kona_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
{
void __iomem *reg_base;
int bit, bank_id;
unsigned long sta;
struct bcm_kona_gpio_bank *bank = irq_get_handler_data(irq);
struct irq_chip *chip = irq_desc_get_chip(desc);
chained_irq_enter(chip, desc);
/*
* For bank interrupts, we can't use chip_data to store the kona_gpio
* pointer, since GIC needs it for its own purposes. Therefore, we get
* our pointer from the bank structure.
*/
reg_base = bank->kona_gpio->reg_base;
bank_id = bank->id;
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
while ((sta = readl(reg_base + GPIO_INT_STATUS(bank_id)) &
(~(readl(reg_base + GPIO_INT_MASK(bank_id)))))) {
for_each_set_bit(bit, &sta, 32) {
int hwirq = GPIO_PER_BANK * bank_id + bit;
int child_irq =
irq_find_mapping(bank->kona_gpio->irq_domain,
hwirq);
/*
* Clear interrupt before handler is called so we don't
* miss any interrupt occurred during executing them.
*/
writel(readl(reg_base + GPIO_INT_STATUS(bank_id)) |
BIT(bit), reg_base + GPIO_INT_STATUS(bank_id));
/* Invoke interrupt handler */
generic_handle_irq(child_irq);
}
}
bcm_kona_gpio_lock_bank(reg_base, bank_id);
chained_irq_exit(chip, desc);
}
static struct irq_chip bcm_gpio_irq_chip = {
.name = "bcm-kona-gpio",
.irq_ack = bcm_kona_gpio_irq_ack,
.irq_mask = bcm_kona_gpio_irq_mask,
.irq_unmask = bcm_kona_gpio_irq_unmask,
.irq_set_type = bcm_kona_gpio_irq_set_type,
};
static struct __initconst of_device_id bcm_kona_gpio_of_match[] = {
{ .compatible = "brcm,kona-gpio" },
{}
};
MODULE_DEVICE_TABLE(of, bcm_kona_gpio_of_match);
/*
* This lock class tells lockdep that GPIO irqs are in a different
* category than their parents, so it won't report false recursion.
*/
static struct lock_class_key gpio_lock_class;
static int bcm_kona_gpio_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{
int ret;
ret = irq_set_chip_data(irq, d->host_data);
if (ret < 0)
return ret;
irq_set_lockdep_class(irq, &gpio_lock_class);
irq_set_chip_and_handler(irq, &bcm_gpio_irq_chip, handle_simple_irq);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(irq);
#endif
return 0;
}
static void bcm_kona_gpio_irq_unmap(struct irq_domain *d, unsigned int irq)
{
irq_set_chip_and_handler(irq, NULL, NULL);
irq_set_chip_data(irq, NULL);
}
static struct irq_domain_ops bcm_kona_irq_ops = {
.map = bcm_kona_gpio_irq_map,
.unmap = bcm_kona_gpio_irq_unmap,
.xlate = irq_domain_xlate_twocell,
};
static void bcm_kona_gpio_reset(struct bcm_kona_gpio *kona_gpio)
{
void __iomem *reg_base;
int i;
reg_base = kona_gpio->reg_base;
/* disable interrupts and clear status */
for (i = 0; i < kona_gpio->num_bank; i++) {
bcm_kona_gpio_unlock_bank(reg_base, i);
writel(0xffffffff, reg_base + GPIO_INT_MASK(i));
writel(0xffffffff, reg_base + GPIO_INT_STATUS(i));
bcm_kona_gpio_lock_bank(reg_base, i);
}
}
static int bcm_kona_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct of_device_id *match;
struct resource *res;
struct bcm_kona_gpio_bank *bank;
struct bcm_kona_gpio *kona_gpio;
struct gpio_chip *chip;
int ret;
int i;
match = of_match_device(bcm_kona_gpio_of_match, dev);
if (!match) {
dev_err(dev, "Failed to find gpio controller\n");
return -ENODEV;
}
kona_gpio = devm_kzalloc(dev, sizeof(*kona_gpio), GFP_KERNEL);
if (!kona_gpio)
return -ENOMEM;
kona_gpio->gpio_chip = template_chip;
chip = &kona_gpio->gpio_chip;
kona_gpio->num_bank = of_irq_count(dev->of_node);
if (kona_gpio->num_bank == 0) {
dev_err(dev, "Couldn't determine # GPIO banks\n");
return -ENOENT;
}
if (kona_gpio->num_bank > GPIO_MAX_BANK_NUM) {
dev_err(dev, "Too many GPIO banks configured (max=%d)\n",
GPIO_MAX_BANK_NUM);
return -ENXIO;
}
kona_gpio->banks = devm_kzalloc(dev,
kona_gpio->num_bank *
sizeof(*kona_gpio->banks), GFP_KERNEL);
if (!kona_gpio->banks)
return -ENOMEM;
kona_gpio->pdev = pdev;
platform_set_drvdata(pdev, kona_gpio);
chip->of_node = dev->of_node;
chip->ngpio = kona_gpio->num_bank * GPIO_PER_BANK;
kona_gpio->irq_domain = irq_domain_add_linear(dev->of_node,
chip->ngpio,
&bcm_kona_irq_ops,
kona_gpio);
if (!kona_gpio->irq_domain) {
dev_err(dev, "Couldn't allocate IRQ domain\n");
return -ENXIO;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
kona_gpio->reg_base = devm_ioremap_resource(dev, res);
if (IS_ERR(kona_gpio->reg_base)) {
ret = -ENXIO;
goto err_irq_domain;
}
for (i = 0; i < kona_gpio->num_bank; i++) {
bank = &kona_gpio->banks[i];
bank->id = i;
bank->irq = platform_get_irq(pdev, i);
bank->kona_gpio = kona_gpio;
if (bank->irq < 0) {
dev_err(dev, "Couldn't get IRQ for bank %d", i);
ret = -ENOENT;
goto err_irq_domain;
}
}
dev_info(&pdev->dev, "Setting up Kona GPIO\n");
bcm_kona_gpio_reset(kona_gpio);
ret = gpiochip_add(chip);
if (ret < 0) {
dev_err(dev, "Couldn't add GPIO chip -- %d\n", ret);
goto err_irq_domain;
}
for (i = 0; i < chip->ngpio; i++) {
int irq = bcm_kona_gpio_to_irq(chip, i);
irq_set_lockdep_class(irq, &gpio_lock_class);
irq_set_chip_and_handler(irq, &bcm_gpio_irq_chip,
handle_simple_irq);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(irq);
#endif
}
for (i = 0; i < kona_gpio->num_bank; i++) {
bank = &kona_gpio->banks[i];
irq_set_chained_handler(bank->irq, bcm_kona_gpio_irq_handler);
irq_set_handler_data(bank->irq, bank);
}
spin_lock_init(&kona_gpio->lock);
return 0;
err_irq_domain:
irq_domain_remove(kona_gpio->irq_domain);
return ret;
}
static struct platform_driver bcm_kona_gpio_driver = {
.driver = {
.name = "bcm-kona-gpio",
.owner = THIS_MODULE,
.of_match_table = bcm_kona_gpio_of_match,
},
.probe = bcm_kona_gpio_probe,
};
module_platform_driver(bcm_kona_gpio_driver);
MODULE_AUTHOR("Broadcom");
MODULE_DESCRIPTION("Broadcom Kona GPIO Driver");
MODULE_LICENSE("GPL v2");

查看文件

@@ -228,7 +228,6 @@ static int bt8xxgpio_probe(struct pci_dev *dev,
err_release_mem:
release_mem_region(pci_resource_start(dev, 0),
pci_resource_len(dev, 0));
pci_set_drvdata(dev, NULL);
err_disable:
pci_disable_device(dev);
err_freebg:
@@ -252,7 +251,6 @@ static void bt8xxgpio_remove(struct pci_dev *pdev)
pci_resource_len(pdev, 0));
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
kfree(bg);
}

查看文件

@@ -87,7 +87,7 @@ static struct platform_driver clps711x_gpio_driver = {
.driver = {
.name = "clps711x-gpio",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(clps711x_gpio_ids),
.of_match_table = clps711x_gpio_ids,
},
.probe = clps711x_gpio_probe,
.remove = clps711x_gpio_remove,

查看文件

@@ -232,16 +232,16 @@ static void em_gio_free(struct gpio_chip *chip, unsigned offset)
em_gio_direction_input(chip, offset);
}
static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int irq,
irq_hw_number_t hwirq)
{
struct em_gio_priv *p = h->host_data;
pr_debug("gio: map hw irq = %d, virq = %d\n", (int)hw, virq);
pr_debug("gio: map hw irq = %d, irq = %d\n", (int)hwirq, irq);
irq_set_chip_data(virq, h->host_data);
irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
set_irq_flags(virq, IRQF_VALID); /* kill me now */
irq_set_chip_data(irq, h->host_data);
irq_set_chip_and_handler(irq, &p->irq_chip, handle_level_irq);
set_irq_flags(irq, IRQF_VALID); /* kill me now */
return 0;
}
@@ -319,6 +319,7 @@ static int em_gio_probe(struct platform_device *pdev)
}
gpio_chip = &p->gpio_chip;
gpio_chip->of_node = pdev->dev.of_node;
gpio_chip->direction_input = em_gio_direction_input;
gpio_chip->get = em_gio_get;
gpio_chip->direction_output = em_gio_direction_output;

查看文件

@@ -51,15 +51,15 @@ static void ep93xx_gpio_update_int_params(unsigned port)
{
BUG_ON(port > 2);
__raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port]));
writeb_relaxed(0, EP93XX_GPIO_REG(int_en_register_offset[port]));
__raw_writeb(gpio_int_type2[port],
writeb_relaxed(gpio_int_type2[port],
EP93XX_GPIO_REG(int_type2_register_offset[port]));
__raw_writeb(gpio_int_type1[port],
writeb_relaxed(gpio_int_type1[port],
EP93XX_GPIO_REG(int_type1_register_offset[port]));
__raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],
writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],
EP93XX_GPIO_REG(int_en_register_offset[port]));
}
@@ -74,7 +74,7 @@ static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable)
else
gpio_int_debounce[port] &= ~port_mask;
__raw_writeb(gpio_int_debounce[port],
writeb(gpio_int_debounce[port],
EP93XX_GPIO_REG(int_debounce_register_offset[port]));
}
@@ -83,7 +83,7 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
unsigned char status;
int i;
status = __raw_readb(EP93XX_GPIO_A_INT_STATUS);
status = readb(EP93XX_GPIO_A_INT_STATUS);
for (i = 0; i < 8; i++) {
if (status & (1 << i)) {
int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i;
@@ -91,7 +91,7 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
}
}
status = __raw_readb(EP93XX_GPIO_B_INT_STATUS);
status = readb(EP93XX_GPIO_B_INT_STATUS);
for (i = 0; i < 8; i++) {
if (status & (1 << i)) {
int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i;
@@ -124,7 +124,7 @@ static void ep93xx_gpio_irq_ack(struct irq_data *d)
ep93xx_gpio_update_int_params(port);
}
__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
}
static void ep93xx_gpio_irq_mask_ack(struct irq_data *d)
@@ -139,7 +139,7 @@ static void ep93xx_gpio_irq_mask_ack(struct irq_data *d)
gpio_int_unmasked[port] &= ~port_mask;
ep93xx_gpio_update_int_params(port);
__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
}
static void ep93xx_gpio_irq_mask(struct irq_data *d)

查看文件

@@ -0,0 +1,471 @@
/*
* Moorestown platform Langwell chip GPIO driver
*
* Copyright (c) 2008, 2009, 2013, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Supports:
* Moorestown platform Langwell chip.
* Medfield platform Penwell chip.
* Clovertrail platform Cloverview chip.
* Merrifield platform Tangier chip.
*/
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/stddef.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/irqdomain.h>
#define INTEL_MID_IRQ_TYPE_EDGE (1 << 0)
#define INTEL_MID_IRQ_TYPE_LEVEL (1 << 1)
/*
* Langwell chip has 64 pins and thus there are 2 32bit registers to control
* each feature, while Penwell chip has 96 pins for each block, and need 3 32bit
* registers to control them, so we only define the order here instead of a
* structure, to get a bit offset for a pin (use GPDR as an example):
*
* nreg = ngpio / 32;
* reg = offset / 32;
* bit = offset % 32;
* reg_addr = reg_base + GPDR * nreg * 4 + reg * 4;
*
* so the bit of reg_addr is to control pin offset's GPDR feature
*/
enum GPIO_REG {
GPLR = 0, /* pin level read-only */
GPDR, /* pin direction */
GPSR, /* pin set */
GPCR, /* pin clear */
GRER, /* rising edge detect */
GFER, /* falling edge detect */
GEDR, /* edge detect result */
GAFR, /* alt function */
};
/* intel_mid gpio driver data */
struct intel_mid_gpio_ddata {
u16 ngpio; /* number of gpio pins */
u32 gplr_offset; /* offset of first GPLR register from base */
u32 flis_base; /* base address of FLIS registers */
u32 flis_len; /* length of FLIS registers */
u32 (*get_flis_offset)(int gpio);
u32 chip_irq_type; /* chip interrupt type */
};
struct intel_mid_gpio {
struct gpio_chip chip;
void __iomem *reg_base;
spinlock_t lock;
struct pci_dev *pdev;
struct irq_domain *domain;
};
#define to_intel_gpio_priv(chip) container_of(chip, struct intel_mid_gpio, chip)
static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
enum GPIO_REG reg_type)
{
struct intel_mid_gpio *priv = to_intel_gpio_priv(chip);
unsigned nreg = chip->ngpio / 32;
u8 reg = offset / 32;
return priv->reg_base + reg_type * nreg * 4 + reg * 4;
}
static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset,
enum GPIO_REG reg_type)
{
struct intel_mid_gpio *priv = to_intel_gpio_priv(chip);
unsigned nreg = chip->ngpio / 32;
u8 reg = offset / 16;
return priv->reg_base + reg_type * nreg * 4 + reg * 4;
}
static int intel_gpio_request(struct gpio_chip *chip, unsigned offset)
{
void __iomem *gafr = gpio_reg_2bit(chip, offset, GAFR);
u32 value = readl(gafr);
int shift = (offset % 16) << 1, af = (value >> shift) & 3;
if (af) {
value &= ~(3 << shift);
writel(value, gafr);
}
return 0;
}
static int intel_gpio_get(struct gpio_chip *chip, unsigned offset)
{
void __iomem *gplr = gpio_reg(chip, offset, GPLR);
return readl(gplr) & BIT(offset % 32);
}
static void intel_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
void __iomem *gpsr, *gpcr;
if (value) {
gpsr = gpio_reg(chip, offset, GPSR);
writel(BIT(offset % 32), gpsr);
} else {
gpcr = gpio_reg(chip, offset, GPCR);
writel(BIT(offset % 32), gpcr);
}
}
static int intel_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
struct intel_mid_gpio *priv = to_intel_gpio_priv(chip);
void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
u32 value;
unsigned long flags;
if (priv->pdev)
pm_runtime_get(&priv->pdev->dev);
spin_lock_irqsave(&priv->lock, flags);
value = readl(gpdr);
value &= ~BIT(offset % 32);
writel(value, gpdr);
spin_unlock_irqrestore(&priv->lock, flags);
if (priv->pdev)
pm_runtime_put(&priv->pdev->dev);
return 0;
}
static int intel_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value)
{
struct intel_mid_gpio *priv = to_intel_gpio_priv(chip);
void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
unsigned long flags;
intel_gpio_set(chip, offset, value);
if (priv->pdev)
pm_runtime_get(&priv->pdev->dev);
spin_lock_irqsave(&priv->lock, flags);
value = readl(gpdr);
value |= BIT(offset % 32);
writel(value, gpdr);
spin_unlock_irqrestore(&priv->lock, flags);
if (priv->pdev)
pm_runtime_put(&priv->pdev->dev);
return 0;
}
static int intel_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct intel_mid_gpio *priv = to_intel_gpio_priv(chip);
return irq_create_mapping(priv->domain, offset);
}
static int intel_mid_irq_type(struct irq_data *d, unsigned type)
{
struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d);
u32 gpio = irqd_to_hwirq(d);
unsigned long flags;
u32 value;
void __iomem *grer = gpio_reg(&priv->chip, gpio, GRER);
void __iomem *gfer = gpio_reg(&priv->chip, gpio, GFER);
if (gpio >= priv->chip.ngpio)
return -EINVAL;
if (priv->pdev)
pm_runtime_get(&priv->pdev->dev);
spin_lock_irqsave(&priv->lock, flags);
if (type & IRQ_TYPE_EDGE_RISING)
value = readl(grer) | BIT(gpio % 32);
else
value = readl(grer) & (~BIT(gpio % 32));
writel(value, grer);
if (type & IRQ_TYPE_EDGE_FALLING)
value = readl(gfer) | BIT(gpio % 32);
else
value = readl(gfer) & (~BIT(gpio % 32));
writel(value, gfer);
spin_unlock_irqrestore(&priv->lock, flags);
if (priv->pdev)
pm_runtime_put(&priv->pdev->dev);
return 0;
}
static void intel_mid_irq_unmask(struct irq_data *d)
{
}
static void intel_mid_irq_mask(struct irq_data *d)
{
}
static struct irq_chip intel_mid_irqchip = {
.name = "INTEL_MID-GPIO",
.irq_mask = intel_mid_irq_mask,
.irq_unmask = intel_mid_irq_unmask,
.irq_set_type = intel_mid_irq_type,
};
static const struct intel_mid_gpio_ddata gpio_lincroft = {
.ngpio = 64,
};
static const struct intel_mid_gpio_ddata gpio_penwell_aon = {
.ngpio = 96,
.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
};
static const struct intel_mid_gpio_ddata gpio_penwell_core = {
.ngpio = 96,
.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
};
static const struct intel_mid_gpio_ddata gpio_cloverview_aon = {
.ngpio = 96,
.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE | INTEL_MID_IRQ_TYPE_LEVEL,
};
static const struct intel_mid_gpio_ddata gpio_cloverview_core = {
.ngpio = 96,
.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
};
static const struct intel_mid_gpio_ddata gpio_tangier = {
.ngpio = 192,
.gplr_offset = 4,
.flis_base = 0xff0c0000,
.flis_len = 0x8000,
.get_flis_offset = NULL,
.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
};
static DEFINE_PCI_DEVICE_TABLE(intel_gpio_ids) = {
{
/* Lincroft */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f),
.driver_data = (kernel_ulong_t)&gpio_lincroft,
},
{
/* Penwell AON */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f),
.driver_data = (kernel_ulong_t)&gpio_penwell_aon,
},
{
/* Penwell Core */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a),
.driver_data = (kernel_ulong_t)&gpio_penwell_core,
},
{
/* Cloverview Aon */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08eb),
.driver_data = (kernel_ulong_t)&gpio_cloverview_aon,
},
{
/* Cloverview Core */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7),
.driver_data = (kernel_ulong_t)&gpio_cloverview_core,
},
{
/* Tangier */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1199),
.driver_data = (kernel_ulong_t)&gpio_tangier,
},
{ 0 }
};
MODULE_DEVICE_TABLE(pci, intel_gpio_ids);
static void intel_mid_irq_handler(unsigned irq, struct irq_desc *desc)
{
struct irq_data *data = irq_desc_get_irq_data(desc);
struct intel_mid_gpio *priv = irq_data_get_irq_handler_data(data);
struct irq_chip *chip = irq_data_get_irq_chip(data);
u32 base, gpio, mask;
unsigned long pending;
void __iomem *gedr;
/* check GPIO controller to check which pin triggered the interrupt */
for (base = 0; base < priv->chip.ngpio; base += 32) {
gedr = gpio_reg(&priv->chip, base, GEDR);
while ((pending = readl(gedr))) {
gpio = __ffs(pending);
mask = BIT(gpio);
/* Clear before handling so we can't lose an edge */
writel(mask, gedr);
generic_handle_irq(irq_find_mapping(priv->domain,
base + gpio));
}
}
chip->irq_eoi(data);
}
static void intel_mid_irq_init_hw(struct intel_mid_gpio *priv)
{
void __iomem *reg;
unsigned base;
for (base = 0; base < priv->chip.ngpio; base += 32) {
/* Clear the rising-edge detect register */
reg = gpio_reg(&priv->chip, base, GRER);
writel(0, reg);
/* Clear the falling-edge detect register */
reg = gpio_reg(&priv->chip, base, GFER);
writel(0, reg);
/* Clear the edge detect status register */
reg = gpio_reg(&priv->chip, base, GEDR);
writel(~0, reg);
}
}
static int intel_gpio_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{
struct intel_mid_gpio *priv = d->host_data;
irq_set_chip_and_handler_name(irq, &intel_mid_irqchip,
handle_simple_irq, "demux");
irq_set_chip_data(irq, priv);
irq_set_irq_type(irq, IRQ_TYPE_NONE);
return 0;
}
static const struct irq_domain_ops intel_gpio_irq_ops = {
.map = intel_gpio_irq_map,
.xlate = irq_domain_xlate_twocell,
};
static int intel_gpio_runtime_idle(struct device *dev)
{
pm_schedule_suspend(dev, 500);
return -EBUSY;
}
static const struct dev_pm_ops intel_gpio_pm_ops = {
SET_RUNTIME_PM_OPS(NULL, NULL, intel_gpio_runtime_idle)
};
static int intel_gpio_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
void __iomem *base;
struct intel_mid_gpio *priv;
u32 gpio_base;
u32 irq_base;
int retval;
struct intel_mid_gpio_ddata *ddata =
(struct intel_mid_gpio_ddata *)id->driver_data;
retval = pcim_enable_device(pdev);
if (retval)
return retval;
retval = pcim_iomap_regions(pdev, 1 << 0 | 1 << 1, pci_name(pdev));
if (retval) {
dev_err(&pdev->dev, "I/O memory mapping error\n");
return retval;
}
base = pcim_iomap_table(pdev)[1];
irq_base = readl(base);
gpio_base = readl(sizeof(u32) + base);
/* release the IO mapping, since we already get the info from bar1 */
pcim_iounmap_regions(pdev, 1 << 1);
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) {
dev_err(&pdev->dev, "can't allocate chip data\n");
return -ENOMEM;
}
priv->reg_base = pcim_iomap_table(pdev)[0];
priv->chip.label = dev_name(&pdev->dev);
priv->chip.request = intel_gpio_request;
priv->chip.direction_input = intel_gpio_direction_input;
priv->chip.direction_output = intel_gpio_direction_output;
priv->chip.get = intel_gpio_get;
priv->chip.set = intel_gpio_set;
priv->chip.to_irq = intel_gpio_to_irq;
priv->chip.base = gpio_base;
priv->chip.ngpio = ddata->ngpio;
priv->chip.can_sleep = 0;
priv->pdev = pdev;
spin_lock_init(&priv->lock);
priv->domain = irq_domain_add_simple(pdev->dev.of_node, ddata->ngpio,
irq_base, &intel_gpio_irq_ops, priv);
if (!priv->domain)
return -ENOMEM;
pci_set_drvdata(pdev, priv);
retval = gpiochip_add(&priv->chip);
if (retval) {
dev_err(&pdev->dev, "gpiochip_add error %d\n", retval);
return retval;
}
intel_mid_irq_init_hw(priv);
irq_set_handler_data(pdev->irq, priv);
irq_set_chained_handler(pdev->irq, intel_mid_irq_handler);
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_allow(&pdev->dev);
return 0;
}
static struct pci_driver intel_gpio_driver = {
.name = "intel_mid_gpio",
.id_table = intel_gpio_ids,
.probe = intel_gpio_probe,
.driver = {
.pm = &intel_gpio_pm_ops,
},
};
static int __init intel_gpio_init(void)
{
return pci_register_driver(&intel_gpio_driver);
}
device_initcall(intel_gpio_init);

130
drivers/gpio/gpio-iop.c Normal file
查看文件

@@ -0,0 +1,130 @@
/*
* arch/arm/plat-iop/gpio.c
* GPIO handling for Intel IOP3xx processors.
*
* Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*/
#include <linux/device.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/export.h>
#include <linux/platform_device.h>
#include <linux/bitops.h>
#include <linux/io.h>
#define IOP3XX_N_GPIOS 8
#define GPIO_IN 0
#define GPIO_OUT 1
#define GPIO_LOW 0
#define GPIO_HIGH 1
/* Memory base offset */
static void __iomem *base;
#define IOP3XX_GPIO_REG(reg) (base + (reg))
#define IOP3XX_GPOE IOP3XX_GPIO_REG(0x0000)
#define IOP3XX_GPID IOP3XX_GPIO_REG(0x0004)
#define IOP3XX_GPOD IOP3XX_GPIO_REG(0x0008)
static void gpio_line_config(int line, int direction)
{
unsigned long flags;
u32 val;
local_irq_save(flags);
val = readl(IOP3XX_GPOE);
if (direction == GPIO_IN) {
val |= BIT(line);
} else if (direction == GPIO_OUT) {
val &= ~BIT(line);
}
writel(val, IOP3XX_GPOE);
local_irq_restore(flags);
}
static int gpio_line_get(int line)
{
return !!(readl(IOP3XX_GPID) & BIT(line));
}
static void gpio_line_set(int line, int value)
{
unsigned long flags;
u32 val;
local_irq_save(flags);
val = readl(IOP3XX_GPOD);
if (value == GPIO_LOW) {
val &= ~BIT(line);
} else if (value == GPIO_HIGH) {
val |= BIT(line);
}
writel(val, IOP3XX_GPOD);
local_irq_restore(flags);
}
static int iop3xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
gpio_line_config(gpio, GPIO_IN);
return 0;
}
static int iop3xx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int level)
{
gpio_line_set(gpio, level);
gpio_line_config(gpio, GPIO_OUT);
return 0;
}
static int iop3xx_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
{
return gpio_line_get(gpio);
}
static void iop3xx_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
{
gpio_line_set(gpio, value);
}
static struct gpio_chip iop3xx_chip = {
.label = "iop3xx",
.direction_input = iop3xx_gpio_direction_input,
.get = iop3xx_gpio_get_value,
.direction_output = iop3xx_gpio_direction_output,
.set = iop3xx_gpio_set_value,
.base = 0,
.ngpio = IOP3XX_N_GPIOS,
};
static int iop3xx_gpio_probe(struct platform_device *pdev)
{
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
return gpiochip_add(&iop3xx_chip);
}
static struct platform_driver iop3xx_gpio_driver = {
.driver = {
.name = "gpio-iop",
.owner = THIS_MODULE,
},
.probe = iop3xx_gpio_probe,
};
static int __init iop3xx_gpio_init(void)
{
return platform_driver_register(&iop3xx_gpio_driver);
}
arch_initcall(iop3xx_gpio_init);

查看文件

@@ -1,397 +0,0 @@
/*
* Moorestown platform Langwell chip GPIO driver
*
* Copyright (c) 2008, 2009, 2013, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Supports:
* Moorestown platform Langwell chip.
* Medfield platform Penwell chip.
*/
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/stddef.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/irqdomain.h>
/*
* Langwell chip has 64 pins and thus there are 2 32bit registers to control
* each feature, while Penwell chip has 96 pins for each block, and need 3 32bit
* registers to control them, so we only define the order here instead of a
* structure, to get a bit offset for a pin (use GPDR as an example):
*
* nreg = ngpio / 32;
* reg = offset / 32;
* bit = offset % 32;
* reg_addr = reg_base + GPDR * nreg * 4 + reg * 4;
*
* so the bit of reg_addr is to control pin offset's GPDR feature
*/
enum GPIO_REG {
GPLR = 0, /* pin level read-only */
GPDR, /* pin direction */
GPSR, /* pin set */
GPCR, /* pin clear */
GRER, /* rising edge detect */
GFER, /* falling edge detect */
GEDR, /* edge detect result */
GAFR, /* alt function */
};
struct lnw_gpio {
struct gpio_chip chip;
void __iomem *reg_base;
spinlock_t lock;
struct pci_dev *pdev;
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 = to_lnw_priv(chip);
unsigned nreg = chip->ngpio / 32;
u8 reg = offset / 32;
return lnw->reg_base + reg_type * nreg * 4 + reg * 4;
}
static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset,
enum GPIO_REG reg_type)
{
struct lnw_gpio *lnw = to_lnw_priv(chip);
unsigned nreg = chip->ngpio / 32;
u8 reg = offset / 16;
return lnw->reg_base + reg_type * nreg * 4 + reg * 4;
}
static int lnw_gpio_request(struct gpio_chip *chip, unsigned offset)
{
void __iomem *gafr = gpio_reg_2bit(chip, offset, GAFR);
u32 value = readl(gafr);
int shift = (offset % 16) << 1, af = (value >> shift) & 3;
if (af) {
value &= ~(3 << shift);
writel(value, gafr);
}
return 0;
}
static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset)
{
void __iomem *gplr = gpio_reg(chip, offset, GPLR);
return readl(gplr) & BIT(offset % 32);
}
static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
void __iomem *gpsr, *gpcr;
if (value) {
gpsr = gpio_reg(chip, offset, GPSR);
writel(BIT(offset % 32), gpsr);
} else {
gpcr = gpio_reg(chip, offset, GPCR);
writel(BIT(offset % 32), gpcr);
}
}
static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
struct lnw_gpio *lnw = to_lnw_priv(chip);
void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
u32 value;
unsigned long flags;
if (lnw->pdev)
pm_runtime_get(&lnw->pdev->dev);
spin_lock_irqsave(&lnw->lock, flags);
value = readl(gpdr);
value &= ~BIT(offset % 32);
writel(value, gpdr);
spin_unlock_irqrestore(&lnw->lock, flags);
if (lnw->pdev)
pm_runtime_put(&lnw->pdev->dev);
return 0;
}
static int lnw_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value)
{
struct lnw_gpio *lnw = to_lnw_priv(chip);
void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
unsigned long flags;
lnw_gpio_set(chip, offset, value);
if (lnw->pdev)
pm_runtime_get(&lnw->pdev->dev);
spin_lock_irqsave(&lnw->lock, flags);
value = readl(gpdr);
value |= BIT(offset % 32);
writel(value, gpdr);
spin_unlock_irqrestore(&lnw->lock, flags);
if (lnw->pdev)
pm_runtime_put(&lnw->pdev->dev);
return 0;
}
static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct lnw_gpio *lnw = to_lnw_priv(chip);
return irq_create_mapping(lnw->domain, offset);
}
static int lnw_irq_type(struct irq_data *d, unsigned type)
{
struct lnw_gpio *lnw = irq_data_get_irq_chip_data(d);
u32 gpio = irqd_to_hwirq(d);
unsigned long flags;
u32 value;
void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER);
void __iomem *gfer = gpio_reg(&lnw->chip, gpio, GFER);
if (gpio >= lnw->chip.ngpio)
return -EINVAL;
if (lnw->pdev)
pm_runtime_get(&lnw->pdev->dev);
spin_lock_irqsave(&lnw->lock, flags);
if (type & IRQ_TYPE_EDGE_RISING)
value = readl(grer) | BIT(gpio % 32);
else
value = readl(grer) & (~BIT(gpio % 32));
writel(value, grer);
if (type & IRQ_TYPE_EDGE_FALLING)
value = readl(gfer) | BIT(gpio % 32);
else
value = readl(gfer) & (~BIT(gpio % 32));
writel(value, gfer);
spin_unlock_irqrestore(&lnw->lock, flags);
if (lnw->pdev)
pm_runtime_put(&lnw->pdev->dev);
return 0;
}
static void lnw_irq_unmask(struct irq_data *d)
{
}
static void lnw_irq_mask(struct irq_data *d)
{
}
static struct irq_chip lnw_irqchip = {
.name = "LNW-GPIO",
.irq_mask = lnw_irq_mask,
.irq_unmask = lnw_irq_unmask,
.irq_set_type = lnw_irq_type,
};
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);
static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
{
struct irq_data *data = irq_desc_get_irq_data(desc);
struct lnw_gpio *lnw = irq_data_get_irq_handler_data(data);
struct irq_chip *chip = irq_data_get_irq_chip(data);
u32 base, gpio, mask;
unsigned long pending;
void __iomem *gedr;
/* check GPIO controller to check which pin triggered the interrupt */
for (base = 0; base < lnw->chip.ngpio; base += 32) {
gedr = gpio_reg(&lnw->chip, base, GEDR);
while ((pending = readl(gedr))) {
gpio = __ffs(pending);
mask = BIT(gpio);
/* Clear before handling so we can't lose an edge */
writel(mask, gedr);
generic_handle_irq(irq_find_mapping(lnw->domain,
base + gpio));
}
}
chip->irq_eoi(data);
}
static void lnw_irq_init_hw(struct lnw_gpio *lnw)
{
void __iomem *reg;
unsigned base;
for (base = 0; base < lnw->chip.ngpio; base += 32) {
/* Clear the rising-edge detect register */
reg = gpio_reg(&lnw->chip, base, GRER);
writel(0, reg);
/* Clear the falling-edge detect register */
reg = gpio_reg(&lnw->chip, base, GFER);
writel(0, reg);
/* Clear the edge detect status register */
reg = gpio_reg(&lnw->chip, base, GEDR);
writel(~0, reg);
}
}
static int lnw_gpio_irq_map(struct irq_domain *d, unsigned int virq,
irq_hw_number_t hw)
{
struct lnw_gpio *lnw = d->host_data;
irq_set_chip_and_handler_name(virq, &lnw_irqchip, handle_simple_irq,
"demux");
irq_set_chip_data(virq, lnw);
irq_set_irq_type(virq, IRQ_TYPE_NONE);
return 0;
}
static const struct irq_domain_ops lnw_gpio_irq_ops = {
.map = lnw_gpio_irq_map,
.xlate = irq_domain_xlate_twocell,
};
static int lnw_gpio_runtime_idle(struct device *dev)
{
pm_schedule_suspend(dev, 500);
return -EBUSY;
}
static const struct dev_pm_ops lnw_gpio_pm_ops = {
SET_RUNTIME_PM_OPS(NULL, NULL, lnw_gpio_runtime_idle)
};
static int lnw_gpio_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
void __iomem *base;
struct lnw_gpio *lnw;
u32 gpio_base;
u32 irq_base;
int retval;
int ngpio = id->driver_data;
retval = pcim_enable_device(pdev);
if (retval)
return retval;
retval = pcim_iomap_regions(pdev, 1 << 0 | 1 << 1, pci_name(pdev));
if (retval) {
dev_err(&pdev->dev, "I/O memory mapping error\n");
return retval;
}
base = pcim_iomap_table(pdev)[1];
irq_base = readl(base);
gpio_base = readl(sizeof(u32) + base);
/* release the IO mapping, since we already get the info from bar1 */
pcim_iounmap_regions(pdev, 1 << 1);
lnw = devm_kzalloc(&pdev->dev, sizeof(*lnw), GFP_KERNEL);
if (!lnw) {
dev_err(&pdev->dev, "can't allocate chip data\n");
return -ENOMEM;
}
lnw->reg_base = pcim_iomap_table(pdev)[0];
lnw->chip.label = dev_name(&pdev->dev);
lnw->chip.request = lnw_gpio_request;
lnw->chip.direction_input = lnw_gpio_direction_input;
lnw->chip.direction_output = lnw_gpio_direction_output;
lnw->chip.get = lnw_gpio_get;
lnw->chip.set = lnw_gpio_set;
lnw->chip.to_irq = lnw_gpio_to_irq;
lnw->chip.base = gpio_base;
lnw->chip.ngpio = ngpio;
lnw->chip.can_sleep = 0;
lnw->pdev = pdev;
spin_lock_init(&lnw->lock);
lnw->domain = irq_domain_add_simple(pdev->dev.of_node, ngpio, irq_base,
&lnw_gpio_irq_ops, lnw);
if (!lnw->domain)
return -ENOMEM;
pci_set_drvdata(pdev, lnw);
retval = gpiochip_add(&lnw->chip);
if (retval) {
dev_err(&pdev->dev, "gpiochip_add error %d\n", retval);
return retval;
}
lnw_irq_init_hw(lnw);
irq_set_handler_data(pdev->irq, lnw);
irq_set_chained_handler(pdev->irq, lnw_irq_handler);
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_allow(&pdev->dev);
return 0;
}
static struct pci_driver lnw_gpio_driver = {
.name = "langwell_gpio",
.id_table = lnw_gpio_ids,
.probe = lnw_gpio_probe,
.driver = {
.pm = &lnw_gpio_pm_ops,
},
};
static int __init lnw_gpio_init(void)
{
return pci_register_driver(&lnw_gpio_driver);
}
device_initcall(lnw_gpio_init);

查看文件

@@ -21,6 +21,7 @@
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/module.h>

查看文件

@@ -242,14 +242,13 @@ static int lp_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
return irq_create_mapping(lg->domain, offset);
}
static void lp_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
static void lp_gpio_irq_handler(unsigned hwirq, 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, ena, pending;
unsigned virq;
/* check from GPIO controller which pin triggered the interrupt */
for (base = 0; base < lg->chip.ngpio; base += 32) {
@@ -257,12 +256,14 @@ static void lp_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
ena = lp_gpio_reg(&lg->chip, base, LP_INT_ENABLE);
while ((pending = (inl(reg) & inl(ena)))) {
unsigned irq;
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);
irq = irq_find_mapping(lg->domain, base + pin);
generic_handle_irq(irq);
}
}
chip->irq_eoi(data);
@@ -325,15 +326,15 @@ static void lp_gpio_irq_init_hw(struct lp_gpio *lg)
}
}
static int lp_gpio_irq_map(struct irq_domain *d, unsigned int virq,
irq_hw_number_t hw)
static int lp_gpio_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{
struct lp_gpio *lg = d->host_data;
irq_set_chip_and_handler_name(virq, &lp_irqchip, handle_simple_irq,
irq_set_chip_and_handler_name(irq, &lp_irqchip, handle_simple_irq,
"demux");
irq_set_chip_data(virq, lg);
irq_set_irq_type(virq, IRQ_TYPE_NONE);
irq_set_chip_data(irq, lg);
irq_set_irq_type(irq, IRQ_TYPE_NONE);
return 0;
}

查看文件

@@ -142,7 +142,6 @@ static int mc33880_probe(struct spi_device *spi)
return ret;
exit_destroy:
spi_set_drvdata(spi, NULL);
mutex_destroy(&mc->lock);
return ret;
}
@@ -156,8 +155,6 @@ static int mc33880_remove(struct spi_device *spi)
if (mc == NULL)
return -ENODEV;
spi_set_drvdata(spi, NULL);
ret = gpiochip_remove(&mc->chip);
if (!ret)
mutex_destroy(&mc->lock);

查看文件

@@ -282,16 +282,16 @@ static struct irq_chip mpc8xxx_irq_chip = {
.irq_set_type = mpc8xxx_irq_set_type,
};
static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int irq,
irq_hw_number_t hwirq)
{
struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data;
if (mpc8xxx_gc->of_dev_id_data)
mpc8xxx_irq_chip.irq_set_type = mpc8xxx_gc->of_dev_id_data;
irq_set_chip_data(virq, h->host_data);
irq_set_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq);
irq_set_chip_data(irq, h->host_data);
irq_set_chip_and_handler(irq, &mpc8xxx_irq_chip, handle_level_irq);
return 0;
}

查看文件

@@ -254,7 +254,6 @@ static int mxs_gpio_probe(struct platform_device *pdev)
struct device_node *parent;
static void __iomem *base;
struct mxs_gpio_port *port;
struct resource *iores = NULL;
int irq_base;
int err;
@@ -262,16 +261,10 @@ static int mxs_gpio_probe(struct platform_device *pdev)
if (!port)
return -ENOMEM;
if (np) {
port->id = of_alias_get_id(np, "gpio");
if (port->id < 0)
return port->id;
port->devid = (enum mxs_gpio_id) of_id->data;
} else {
port->id = pdev->id;
port->devid = pdev->id_entry->driver_data;
}
port->id = of_alias_get_id(np, "gpio");
if (port->id < 0)
return port->id;
port->devid = (enum mxs_gpio_id) of_id->data;
port->irq = platform_get_irq(pdev, 0);
if (port->irq < 0)
return port->irq;
@@ -281,18 +274,11 @@ static int mxs_gpio_probe(struct platform_device *pdev)
* share the same one
*/
if (!base) {
if (np) {
parent = of_get_parent(np);
base = of_iomap(parent, 0);
of_node_put(parent);
if (!base)
return -EADDRNOTAVAIL;
} else {
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, iores);
if (IS_ERR(base))
return PTR_ERR(base);
}
parent = of_get_parent(np);
base = of_iomap(parent, 0);
of_node_put(parent);
if (!base)
return -EADDRNOTAVAIL;
}
port->base = base;

查看文件

@@ -514,6 +514,14 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
return -EINVAL;
}
retval = gpio_lock_as_irq(&bank->chip, offset);
if (retval) {
dev_err(bank->dev, "unable to lock offset %d for IRQ\n",
offset);
spin_unlock_irqrestore(&bank->lock, flags);
return retval;
}
bank->irq_usage |= 1 << GPIO_INDEX(bank, gpio);
spin_unlock_irqrestore(&bank->lock, flags);
@@ -797,6 +805,7 @@ static void gpio_irq_shutdown(struct irq_data *d)
unsigned offset = GPIO_INDEX(bank, gpio);
spin_lock_irqsave(&bank->lock, flags);
gpio_unlock_as_irq(&bank->chip, offset);
bank->irq_usage &= ~(1 << offset);
_disable_gpio_module(bank, offset);
_reset_gpio(bank, gpio);
@@ -957,22 +966,13 @@ static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
{
struct gpio_bank *bank;
unsigned long flags;
int retval = 0;
bank = container_of(chip, struct gpio_bank, chip);
spin_lock_irqsave(&bank->lock, flags);
if (LINE_USED(bank->irq_usage, offset)) {
retval = -EINVAL;
goto exit;
}
bank->set_dataout(bank, offset, value);
_set_gpio_direction(bank, offset, 0);
exit:
spin_unlock_irqrestore(&bank->lock, flags);
return retval;
return 0;
}
static int gpio_debounce(struct gpio_chip *chip, unsigned offset,

查看文件

@@ -31,6 +31,10 @@ struct palmas_gpio {
struct palmas *palmas;
};
struct palmas_device_data {
int ngpio;
};
static inline struct palmas_gpio *to_palmas_gpio(struct gpio_chip *chip)
{
return container_of(chip, struct palmas_gpio, gpio_chip);
@@ -42,23 +46,26 @@ static int palmas_gpio_get(struct gpio_chip *gc, unsigned offset)
struct palmas *palmas = pg->palmas;
unsigned int val;
int ret;
unsigned int reg;
int gpio16 = (offset/8);
ret = palmas_read(palmas, PALMAS_GPIO_BASE, PALMAS_GPIO_DATA_DIR, &val);
offset %= 8;
reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);
if (ret < 0) {
dev_err(gc->dev, "GPIO_DATA_DIR read failed, err = %d\n", ret);
dev_err(gc->dev, "Reg 0x%02x read failed, %d\n", reg, ret);
return ret;
}
if (val & (1 << offset)) {
ret = palmas_read(palmas, PALMAS_GPIO_BASE,
PALMAS_GPIO_DATA_OUT, &val);
} else {
ret = palmas_read(palmas, PALMAS_GPIO_BASE,
PALMAS_GPIO_DATA_IN, &val);
}
if (val & BIT(offset))
reg = (gpio16) ? PALMAS_GPIO_DATA_OUT2 : PALMAS_GPIO_DATA_OUT;
else
reg = (gpio16) ? PALMAS_GPIO_DATA_IN2 : PALMAS_GPIO_DATA_IN;
ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);
if (ret < 0) {
dev_err(gc->dev, "GPIO_DATA_IN/OUT read failed, err = %d\n",
ret);
dev_err(gc->dev, "Reg 0x%02x read failed, %d\n", reg, ret);
return ret;
}
return !!(val & BIT(offset));
@@ -70,17 +77,20 @@ static void palmas_gpio_set(struct gpio_chip *gc, unsigned offset,
struct palmas_gpio *pg = to_palmas_gpio(gc);
struct palmas *palmas = pg->palmas;
int ret;
unsigned int reg;
int gpio16 = (offset/8);
if (value)
ret = palmas_write(palmas, PALMAS_GPIO_BASE,
PALMAS_GPIO_SET_DATA_OUT, BIT(offset));
offset %= 8;
if (gpio16)
reg = (value) ?
PALMAS_GPIO_SET_DATA_OUT2 : PALMAS_GPIO_CLEAR_DATA_OUT2;
else
ret = palmas_write(palmas, PALMAS_GPIO_BASE,
PALMAS_GPIO_CLEAR_DATA_OUT, BIT(offset));
reg = (value) ?
PALMAS_GPIO_SET_DATA_OUT : PALMAS_GPIO_CLEAR_DATA_OUT;
ret = palmas_write(palmas, PALMAS_GPIO_BASE, reg, BIT(offset));
if (ret < 0)
dev_err(gc->dev, "%s write failed, err = %d\n",
(value) ? "GPIO_SET_DATA_OUT" : "GPIO_CLEAR_DATA_OUT",
ret);
dev_err(gc->dev, "Reg 0x%02x write failed, %d\n", reg, ret);
}
static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset,
@@ -89,14 +99,19 @@ static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset,
struct palmas_gpio *pg = to_palmas_gpio(gc);
struct palmas *palmas = pg->palmas;
int ret;
unsigned int reg;
int gpio16 = (offset/8);
offset %= 8;
reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
/* Set the initial value */
palmas_gpio_set(gc, offset, value);
ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE,
PALMAS_GPIO_DATA_DIR, BIT(offset), BIT(offset));
ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg,
BIT(offset), BIT(offset));
if (ret < 0)
dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret);
dev_err(gc->dev, "Reg 0x%02x update failed, %d\n", reg, ret);
return ret;
}
@@ -105,11 +120,15 @@ static int palmas_gpio_input(struct gpio_chip *gc, unsigned offset)
struct palmas_gpio *pg = to_palmas_gpio(gc);
struct palmas *palmas = pg->palmas;
int ret;
unsigned int reg;
int gpio16 = (offset/8);
ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE,
PALMAS_GPIO_DATA_DIR, BIT(offset), 0);
offset %= 8;
reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, BIT(offset), 0);
if (ret < 0)
dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret);
dev_err(gc->dev, "Reg 0x%02x update failed, %d\n", reg, ret);
return ret;
}
@@ -121,12 +140,36 @@ static int palmas_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
return palmas_irq_get_virq(palmas, PALMAS_GPIO_0_IRQ + offset);
}
static const struct palmas_device_data palmas_dev_data = {
.ngpio = 8,
};
static const struct palmas_device_data tps80036_dev_data = {
.ngpio = 16,
};
static struct of_device_id of_palmas_gpio_match[] = {
{ .compatible = "ti,palmas-gpio", .data = &palmas_dev_data,},
{ .compatible = "ti,tps65913-gpio", .data = &palmas_dev_data,},
{ .compatible = "ti,tps65914-gpio", .data = &palmas_dev_data,},
{ .compatible = "ti,tps80036-gpio", .data = &tps80036_dev_data,},
{ },
};
MODULE_DEVICE_TABLE(of, of_palmas_gpio_match);
static int palmas_gpio_probe(struct platform_device *pdev)
{
struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
struct palmas_platform_data *palmas_pdata;
struct palmas_gpio *palmas_gpio;
int ret;
const struct of_device_id *match;
const struct palmas_device_data *dev_data;
match = of_match_device(of_palmas_gpio_match, &pdev->dev);
dev_data = match->data;
if (!dev_data)
dev_data = &palmas_dev_data;
palmas_gpio = devm_kzalloc(&pdev->dev,
sizeof(*palmas_gpio), GFP_KERNEL);
@@ -138,7 +181,7 @@ static int palmas_gpio_probe(struct platform_device *pdev)
palmas_gpio->palmas = palmas;
palmas_gpio->gpio_chip.owner = THIS_MODULE;
palmas_gpio->gpio_chip.label = dev_name(&pdev->dev);
palmas_gpio->gpio_chip.ngpio = 8;
palmas_gpio->gpio_chip.ngpio = dev_data->ngpio;
palmas_gpio->gpio_chip.can_sleep = 1;
palmas_gpio->gpio_chip.direction_input = palmas_gpio_input;
palmas_gpio->gpio_chip.direction_output = palmas_gpio_output;
@@ -172,15 +215,6 @@ static int palmas_gpio_remove(struct platform_device *pdev)
return gpiochip_remove(&palmas_gpio->gpio_chip);
}
static struct of_device_id of_palmas_gpio_match[] = {
{ .compatible = "ti,palmas-gpio"},
{ .compatible = "ti,tps65913-gpio"},
{ .compatible = "ti,tps65914-gpio"},
{ .compatible = "ti,tps80036-gpio"},
{ },
};
MODULE_DEVICE_TABLE(of, of_palmas_gpio_match);
static struct platform_driver palmas_gpio_driver = {
.driver.name = "palmas-gpio",
.driver.owner = THIS_MODULE,

查看文件

@@ -683,17 +683,6 @@ static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
int ret;
u8 val[MAX_BANK];
/* Let every port in proper state, that could save power */
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_regs(chip, PCA957X_OUT, chip->reg_output);
if (ret)
goto out;

查看文件

@@ -26,9 +26,10 @@
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
static const struct i2c_device_id pcf857x_id[] = {
@@ -50,6 +51,27 @@ static const struct i2c_device_id pcf857x_id[] = {
};
MODULE_DEVICE_TABLE(i2c, pcf857x_id);
#ifdef CONFIG_OF
static const struct of_device_id pcf857x_of_table[] = {
{ .compatible = "nxp,pcf8574" },
{ .compatible = "nxp,pcf8574a" },
{ .compatible = "nxp,pca8574" },
{ .compatible = "nxp,pca9670" },
{ .compatible = "nxp,pca9672" },
{ .compatible = "nxp,pca9674" },
{ .compatible = "nxp,pcf8575" },
{ .compatible = "nxp,pca8575" },
{ .compatible = "nxp,pca9671" },
{ .compatible = "nxp,pca9673" },
{ .compatible = "nxp,pca9675" },
{ .compatible = "maxim,max7328" },
{ .compatible = "maxim,max7329" },
{ .compatible = "ti,tca9554" },
{ }
};
MODULE_DEVICE_TABLE(of, pcf857x_of_table);
#endif
/*
* The pcf857x, pca857x, and pca967x chips only expose one read and one
* write register. Writing a "one" bit (to match the reset state) lets
@@ -66,12 +88,11 @@ struct pcf857x {
struct gpio_chip chip;
struct i2c_client *client;
struct mutex lock; /* protect 'out' */
struct work_struct work; /* irq demux work */
struct irq_domain *irq_domain; /* for irq demux */
spinlock_t slock; /* protect irq demux */
unsigned out; /* software latch */
unsigned status; /* current status */
int irq; /* real irq number */
unsigned irq_mapped; /* mapped gpio irqs */
int (*write)(struct i2c_client *client, unsigned data);
int (*read)(struct i2c_client *client);
@@ -164,48 +185,54 @@ static void pcf857x_set(struct gpio_chip *chip, unsigned offset, int value)
static int pcf857x_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
int ret;
return irq_create_mapping(gpio->irq_domain, offset);
ret = irq_create_mapping(gpio->irq_domain, offset);
if (ret > 0)
gpio->irq_mapped |= (1 << offset);
return ret;
}
static void pcf857x_irq_demux_work(struct work_struct *work)
static irqreturn_t pcf857x_irq(int irq, void *data)
{
struct pcf857x *gpio = container_of(work,
struct pcf857x,
work);
struct pcf857x *gpio = data;
unsigned long change, i, status, flags;
status = gpio->read(gpio->client);
spin_lock_irqsave(&gpio->slock, flags);
change = gpio->status ^ status;
/*
* call the interrupt handler iff gpio is used as
* interrupt source, just to avoid bad irqs
*/
change = ((gpio->status ^ status) & gpio->irq_mapped);
for_each_set_bit(i, &change, gpio->chip.ngpio)
generic_handle_irq(irq_find_mapping(gpio->irq_domain, i));
gpio->status = status;
spin_unlock_irqrestore(&gpio->slock, flags);
}
static irqreturn_t pcf857x_irq_demux(int irq, void *data)
{
struct pcf857x *gpio = data;
/*
* pcf857x can't read/write data here,
* since i2c data access might go to sleep.
*/
schedule_work(&gpio->work);
return IRQ_HANDLED;
}
static int pcf857x_irq_domain_map(struct irq_domain *domain, unsigned int virq,
static int pcf857x_irq_domain_map(struct irq_domain *domain, unsigned int irq,
irq_hw_number_t hw)
{
irq_set_chip_and_handler(virq,
struct pcf857x *gpio = domain->host_data;
irq_set_chip_and_handler(irq,
&dummy_irq_chip,
handle_level_irq);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(irq);
#endif
gpio->irq_mapped |= (1 << hw);
return 0;
}
@@ -218,8 +245,6 @@ static void pcf857x_irq_domain_cleanup(struct pcf857x *gpio)
if (gpio->irq_domain)
irq_domain_remove(gpio->irq_domain);
if (gpio->irq)
free_irq(gpio->irq, gpio);
}
static int pcf857x_irq_domain_init(struct pcf857x *gpio,
@@ -230,20 +255,21 @@ static int pcf857x_irq_domain_init(struct pcf857x *gpio,
gpio->irq_domain = irq_domain_add_linear(client->dev.of_node,
gpio->chip.ngpio,
&pcf857x_irq_domain_ops,
NULL);
gpio);
if (!gpio->irq_domain)
goto fail;
/* enable real irq */
status = request_irq(client->irq, pcf857x_irq_demux, 0,
dev_name(&client->dev), gpio);
status = devm_request_threaded_irq(&client->dev, client->irq,
NULL, pcf857x_irq, IRQF_ONESHOT |
IRQF_TRIGGER_FALLING,
dev_name(&client->dev), gpio);
if (status)
goto fail;
/* enable gpio_to_irq() */
INIT_WORK(&gpio->work, pcf857x_irq_demux_work);
gpio->chip.to_irq = pcf857x_to_irq;
gpio->irq = client->irq;
return 0;
@@ -257,14 +283,18 @@ fail:
static int pcf857x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pcf857x_platform_data *pdata;
struct pcf857x_platform_data *pdata = dev_get_platdata(&client->dev);
struct device_node *np = client->dev.of_node;
struct pcf857x *gpio;
unsigned int n_latch = 0;
int status;
pdata = dev_get_platdata(&client->dev);
if (!pdata) {
if (IS_ENABLED(CONFIG_OF) && np)
of_property_read_u32(np, "lines-initial-states", &n_latch);
else if (pdata)
n_latch = pdata->n_latch;
else
dev_dbg(&client->dev, "no platform data\n");
}
/* Allocate, initialize, and register this gpio_chip. */
gpio = devm_kzalloc(&client->dev, sizeof(*gpio), GFP_KERNEL);
@@ -357,11 +387,11 @@ static int pcf857x_probe(struct i2c_client *client,
* may cause transient glitching since it can't know the last value
* written (some pins may need to be driven low).
*
* Using pdata->n_latch avoids that trouble. When left initialized
* to zero, our software copy of the "latch" then matches the chip's
* all-ones reset state. Otherwise it flags pins to be driven low.
* Using n_latch avoids that trouble. When left initialized to zero,
* our software copy of the "latch" then matches the chip's all-ones
* reset state. Otherwise it flags pins to be driven low.
*/
gpio->out = pdata ? ~pdata->n_latch : ~0;
gpio->out = ~n_latch;
gpio->status = gpio->out;
status = gpiochip_add(&gpio->chip);
@@ -423,6 +453,7 @@ static struct i2c_driver pcf857x_driver = {
.driver = {
.name = "pcf857x",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(pcf857x_of_table),
},
.probe = pcf857x_probe,
.remove = pcf857x_remove,

查看文件

@@ -238,15 +238,15 @@ static struct irq_chip pl061_irqchip = {
.irq_set_type = pl061_irq_type,
};
static int pl061_irq_map(struct irq_domain *d, unsigned int virq,
irq_hw_number_t hw)
static int pl061_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{
struct pl061_gpio *chip = d->host_data;
irq_set_chip_and_handler_name(virq, &pl061_irqchip, handle_simple_irq,
irq_set_chip_and_handler_name(irq, &pl061_irqchip, handle_simple_irq,
"pl061");
irq_set_chip_data(virq, chip);
irq_set_irq_type(virq, IRQ_TYPE_NONE);
irq_set_chip_data(irq, chip);
irq_set_irq_type(irq, IRQ_TYPE_NONE);
return 0;
}

查看文件

@@ -22,6 +22,7 @@
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_data/gpio-rcar.h>
#include <linux/platform_device.h>
@@ -266,16 +267,16 @@ static int gpio_rcar_to_irq(struct gpio_chip *chip, unsigned offset)
return irq_create_mapping(gpio_to_priv(chip)->irq_domain, offset);
}
static int gpio_rcar_irq_domain_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
static int gpio_rcar_irq_domain_map(struct irq_domain *h, unsigned int irq,
irq_hw_number_t hwirq)
{
struct gpio_rcar_priv *p = h->host_data;
dev_dbg(&p->pdev->dev, "map hw irq = %d, virq = %d\n", (int)hw, virq);
dev_dbg(&p->pdev->dev, "map hw irq = %d, irq = %d\n", (int)hwirq, irq);
irq_set_chip_data(virq, h->host_data);
irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
set_irq_flags(virq, IRQF_VALID); /* kill me now */
irq_set_chip_data(irq, h->host_data);
irq_set_chip_and_handler(irq, &p->irq_chip, handle_level_irq);
set_irq_flags(irq, IRQF_VALID); /* kill me now */
return 0;
}

查看文件

@@ -254,9 +254,10 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
while (stat) {
int bit = __ffs(stat);
int line = bank * 8 + bit;
int virq = irq_find_mapping(stmpe_gpio->domain, line);
int child_irq = irq_find_mapping(stmpe_gpio->domain,
line);
handle_nested_irq(virq);
handle_nested_irq(child_irq);
stat &= ~(1 << bit);
}
@@ -271,7 +272,7 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
return IRQ_HANDLED;
}
static int stmpe_gpio_irq_map(struct irq_domain *d, unsigned int virq,
static int stmpe_gpio_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{
struct stmpe_gpio *stmpe_gpio = d->host_data;
@@ -279,26 +280,26 @@ static int stmpe_gpio_irq_map(struct irq_domain *d, unsigned int virq,
if (!stmpe_gpio)
return -EINVAL;
irq_set_chip_data(hwirq, stmpe_gpio);
irq_set_chip_and_handler(hwirq, &stmpe_gpio_irq_chip,
irq_set_chip_data(irq, stmpe_gpio);
irq_set_chip_and_handler(irq, &stmpe_gpio_irq_chip,
handle_simple_irq);
irq_set_nested_thread(hwirq, 1);
irq_set_nested_thread(irq, 1);
#ifdef CONFIG_ARM
set_irq_flags(hwirq, IRQF_VALID);
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(hwirq);
irq_set_noprobe(irq);
#endif
return 0;
}
static void stmpe_gpio_irq_unmap(struct irq_domain *d, unsigned int virq)
static void stmpe_gpio_irq_unmap(struct irq_domain *d, unsigned int irq)
{
#ifdef CONFIG_ARM
set_irq_flags(virq, 0);
set_irq_flags(irq, 0);
#endif
irq_set_chip_and_handler(virq, NULL, NULL);
irq_set_chip_data(virq, NULL);
irq_set_chip_and_handler(irq, NULL, NULL);
irq_set_chip_data(irq, NULL);
}
static const struct irq_domain_ops stmpe_gpio_irq_simple_ops = {

查看文件

@@ -96,27 +96,27 @@ static int tc3589x_gpio_direction_input(struct gpio_chip *chip,
}
/**
* tc3589x_gpio_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
* tc3589x_gpio_irq_get_irq(): Map a hardware IRQ on a chip to a Linux IRQ
*
* @tc3589x_gpio: tc3589x_gpio_irq controller to operate on.
* @irq: index of the interrupt requested in the chip IRQs
* @irq: index of the hardware interrupt requested in the chip IRQs
*
* Useful for drivers to request their own IRQs.
*/
static int tc3589x_gpio_irq_get_virq(struct tc3589x_gpio *tc3589x_gpio,
int irq)
static int tc3589x_gpio_irq_get_irq(struct tc3589x_gpio *tc3589x_gpio,
int hwirq)
{
if (!tc3589x_gpio)
return -EINVAL;
return irq_create_mapping(tc3589x_gpio->domain, irq);
return irq_create_mapping(tc3589x_gpio->domain, hwirq);
}
static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
return tc3589x_gpio_irq_get_virq(tc3589x_gpio, offset);
return tc3589x_gpio_irq_get_irq(tc3589x_gpio, offset);
}
static struct gpio_chip template_chip = {
@@ -242,9 +242,9 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
while (stat) {
int bit = __ffs(stat);
int line = i * 8 + bit;
int virq = tc3589x_gpio_irq_get_virq(tc3589x_gpio, line);
int irq = tc3589x_gpio_irq_get_irq(tc3589x_gpio, line);
handle_nested_irq(virq);
handle_nested_irq(irq);
stat &= ~(1 << bit);
}
@@ -254,31 +254,31 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
return IRQ_HANDLED;
}
static int tc3589x_gpio_irq_map(struct irq_domain *d, unsigned int virq,
static int tc3589x_gpio_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{
struct tc3589x *tc3589x_gpio = d->host_data;
irq_set_chip_data(virq, tc3589x_gpio);
irq_set_chip_and_handler(virq, &tc3589x_gpio_irq_chip,
irq_set_chip_data(irq, tc3589x_gpio);
irq_set_chip_and_handler(irq, &tc3589x_gpio_irq_chip,
handle_simple_irq);
irq_set_nested_thread(virq, 1);
irq_set_nested_thread(irq, 1);
#ifdef CONFIG_ARM
set_irq_flags(virq, IRQF_VALID);
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(virq);
irq_set_noprobe(irq);
#endif
return 0;
}
static void tc3589x_gpio_irq_unmap(struct irq_domain *d, unsigned int virq)
static void tc3589x_gpio_irq_unmap(struct irq_domain *d, unsigned int irq)
{
#ifdef CONFIG_ARM
set_irq_flags(virq, 0);
set_irq_flags(irq, 0);
#endif
irq_set_chip_and_handler(virq, NULL, NULL);
irq_set_chip_data(virq, NULL);
irq_set_chip_and_handler(irq, NULL, NULL);
irq_set_chip_data(irq, NULL);
}
static struct irq_domain_ops tc3589x_irq_ops = {

查看文件

@@ -75,6 +75,7 @@ struct tegra_gpio_bank {
#endif
};
static struct device *dev;
static struct irq_domain *irq_domain;
static void __iomem *regs;
static u32 tegra_gpio_bank_count;
@@ -205,6 +206,7 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
int lvl_type;
int val;
unsigned long flags;
int ret;
switch (type & IRQ_TYPE_SENSE_MASK) {
case IRQ_TYPE_EDGE_RISING:
@@ -231,6 +233,12 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
return -EINVAL;
}
ret = gpio_lock_as_irq(&tegra_gpio_chip, gpio);
if (ret) {
dev_err(dev, "unable to lock Tegra GPIO %d as IRQ\n", gpio);
return ret;
}
spin_lock_irqsave(&bank->lvl_lock[port], flags);
val = tegra_gpio_readl(GPIO_INT_LVL(gpio));
@@ -251,6 +259,13 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
return 0;
}
static void tegra_gpio_irq_shutdown(struct irq_data *d)
{
int gpio = d->hwirq;
gpio_unlock_as_irq(&tegra_gpio_chip, gpio);
}
static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
{
struct tegra_gpio_bank *bank;
@@ -368,6 +383,7 @@ static struct irq_chip tegra_gpio_irq_chip = {
.irq_mask = tegra_gpio_irq_mask,
.irq_unmask = tegra_gpio_irq_unmask,
.irq_set_type = tegra_gpio_irq_set_type,
.irq_shutdown = tegra_gpio_irq_shutdown,
#ifdef CONFIG_PM_SLEEP
.irq_set_wake = tegra_gpio_irq_set_wake,
#endif
@@ -413,6 +429,8 @@ static int tegra_gpio_probe(struct platform_device *pdev)
int i;
int j;
dev = &pdev->dev;
match = of_match_device(tegra_gpio_of_match, &pdev->dev);
if (!match) {
dev_err(&pdev->dev, "Error: No device match found\n");

查看文件

@@ -594,7 +594,7 @@ static struct platform_driver gpio_twl4030_driver = {
.driver = {
.name = "twl4030_gpio",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(twl_gpio_match),
.of_match_table = twl_gpio_match,
},
.probe = gpio_twl4030_probe,
.remove = gpio_twl4030_remove,

查看文件

@@ -11,7 +11,7 @@
*/
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/export.h>
#include <linux/acpi_gpio.h>
#include <linux/acpi.h>
@@ -33,14 +33,15 @@ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
}
/**
* acpi_get_gpio() - Translate ACPI GPIO pin to GPIO number usable with GPIO API
* acpi_get_gpiod() - Translate ACPI GPIO pin to GPIO descriptor usable with GPIO API
* @path: ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1")
* @pin: ACPI GPIO pin number (0-based, controller-relative)
*
* Returns GPIO number to use with Linux generic GPIO API, or errno error value
* Returns GPIO descriptor to use with Linux generic GPIO API, or ERR_PTR
* error value
*/
int acpi_get_gpio(char *path, int pin)
static struct gpio_desc *acpi_get_gpiod(char *path, int pin)
{
struct gpio_chip *chip;
acpi_handle handle;
@@ -48,18 +49,17 @@ int acpi_get_gpio(char *path, int pin)
status = acpi_get_handle(NULL, path, &handle);
if (ACPI_FAILURE(status))
return -ENODEV;
return ERR_PTR(-ENODEV);
chip = gpiochip_find(handle, acpi_gpiochip_find);
if (!chip)
return -ENODEV;
return ERR_PTR(-ENODEV);
if (!gpio_is_valid(chip->base + pin))
return -EINVAL;
if (pin < 0 || pin > chip->ngpio)
return ERR_PTR(-EINVAL);
return chip->base + pin;
return gpio_to_desc(chip->base + pin);
}
EXPORT_SYMBOL_GPL(acpi_get_gpio);
static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)
{
@@ -73,15 +73,8 @@ static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)
static irqreturn_t acpi_gpio_irq_handler_evt(int irq, void *data)
{
struct acpi_gpio_evt_pin *evt_pin = data;
struct acpi_object_list args;
union acpi_object arg;
arg.type = ACPI_TYPE_INTEGER;
arg.integer.value = evt_pin->pin;
args.count = 1;
args.pointer = &arg;
acpi_evaluate_object(evt_pin->evt_handle, NULL, &args, NULL);
acpi_execute_simple_method(evt_pin->evt_handle, NULL, evt_pin->pin);
return IRQ_HANDLED;
}
@@ -201,84 +194,6 @@ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
}
EXPORT_SYMBOL(acpi_gpiochip_request_interrupts);
struct acpi_gpio_lookup {
struct acpi_gpio_info info;
int index;
int gpio;
int n;
};
static int acpi_find_gpio(struct acpi_resource *ares, void *data)
{
struct acpi_gpio_lookup *lookup = data;
if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
return 1;
if (lookup->n++ == lookup->index && lookup->gpio < 0) {
const struct acpi_resource_gpio *agpio = &ares->data.gpio;
lookup->gpio = acpi_get_gpio(agpio->resource_source.string_ptr,
agpio->pin_table[0]);
lookup->info.gpioint =
agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
}
return 1;
}
/**
* acpi_get_gpio_by_index() - get a GPIO number from device resources
* @dev: pointer to a device to get GPIO from
* @index: index of GpioIo/GpioInt resource (starting from %0)
* @info: info pointer to fill in (optional)
*
* Function goes through ACPI resources for @dev and based on @index looks
* up a GpioIo/GpioInt resource, translates it to the Linux GPIO number,
* and returns it. @index matches GpioIo/GpioInt resources only so if there
* are total %3 GPIO resources, the index goes from %0 to %2.
*
* If the GPIO cannot be translated or there is an error, negative errno is
* returned.
*
* Note: if the GPIO resource has multiple entries in the pin list, this
* function only returns the first.
*/
int acpi_get_gpio_by_index(struct device *dev, int index,
struct acpi_gpio_info *info)
{
struct acpi_gpio_lookup lookup;
struct list_head resource_list;
struct acpi_device *adev;
acpi_handle handle;
int ret;
if (!dev)
return -EINVAL;
handle = ACPI_HANDLE(dev);
if (!handle || acpi_bus_get_device(handle, &adev))
return -ENODEV;
memset(&lookup, 0, sizeof(lookup));
lookup.index = index;
lookup.gpio = -ENODEV;
INIT_LIST_HEAD(&resource_list);
ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
&lookup);
if (ret < 0)
return ret;
acpi_dev_free_resource_list(&resource_list);
if (lookup.gpio >= 0 && info)
*info = lookup.info;
return lookup.gpio;
}
EXPORT_SYMBOL_GPL(acpi_get_gpio_by_index);
/**
* acpi_gpiochip_free_interrupts() - Free GPIO _EVT ACPI event interrupts.
* @chip: gpio chip
@@ -316,3 +231,82 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
kfree(evt_pins);
}
EXPORT_SYMBOL(acpi_gpiochip_free_interrupts);
struct acpi_gpio_lookup {
struct acpi_gpio_info info;
int index;
struct gpio_desc *desc;
int n;
};
static int acpi_find_gpio(struct acpi_resource *ares, void *data)
{
struct acpi_gpio_lookup *lookup = data;
if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
return 1;
if (lookup->n++ == lookup->index && !lookup->desc) {
const struct acpi_resource_gpio *agpio = &ares->data.gpio;
lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr,
agpio->pin_table[0]);
lookup->info.gpioint =
agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
lookup->info.active_low =
agpio->polarity == ACPI_ACTIVE_LOW;
}
return 1;
}
/**
* acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources
* @dev: pointer to a device to get GPIO from
* @index: index of GpioIo/GpioInt resource (starting from %0)
* @info: info pointer to fill in (optional)
*
* Function goes through ACPI resources for @dev and based on @index looks
* up a GpioIo/GpioInt resource, translates it to the Linux GPIO descriptor,
* and returns it. @index matches GpioIo/GpioInt resources only so if there
* are total %3 GPIO resources, the index goes from %0 to %2.
*
* If the GPIO cannot be translated or there is an error an ERR_PTR is
* returned.
*
* Note: if the GPIO resource has multiple entries in the pin list, this
* function only returns the first.
*/
struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
struct acpi_gpio_info *info)
{
struct acpi_gpio_lookup lookup;
struct list_head resource_list;
struct acpi_device *adev;
acpi_handle handle;
int ret;
if (!dev)
return ERR_PTR(-EINVAL);
handle = ACPI_HANDLE(dev);
if (!handle || acpi_bus_get_device(handle, &adev))
return ERR_PTR(-ENODEV);
memset(&lookup, 0, sizeof(lookup));
lookup.index = index;
INIT_LIST_HEAD(&resource_list);
ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
&lookup);
if (ret < 0)
return ERR_PTR(ret);
acpi_dev_free_resource_list(&resource_list);
if (lookup.desc && info)
*info = lookup.info;
return lookup.desc ? lookup.desc : ERR_PTR(-ENODEV);
}
EXPORT_SYMBOL_GPL(acpi_get_gpiod_by_index);

查看文件

@@ -15,19 +15,21 @@
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/slab.h>
struct gpio_desc;
/* Private data structure for of_gpiochip_find_and_xlate */
struct gg_data {
enum of_gpio_flags *flags;
struct of_phandle_args gpiospec;
int out_gpio;
struct gpio_desc *out_gpio;
};
/* Private function for resolving node pointer to gpio_chip */
@@ -45,28 +47,31 @@ static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data)
if (ret < 0)
return false;
gg_data->out_gpio = ret + gc->base;
gg_data->out_gpio = gpio_to_desc(ret + gc->base);
return true;
}
/**
* of_get_named_gpio_flags() - Get a GPIO number and flags to use with GPIO API
* of_get_named_gpiod_flags() - Get a GPIO descriptor and flags for GPIO API
* @np: device node to get GPIO from
* @propname: property name containing gpio specifier(s)
* @index: index of the GPIO
* @flags: a flags pointer to fill in
*
* Returns GPIO number to use with Linux generic GPIO API, or one of the errno
* Returns GPIO descriptor to use with Linux GPIO API, or one of the errno
* value on the error condition. If @flags is not NULL the function also fills
* in flags for the GPIO.
*/
int of_get_named_gpio_flags(struct device_node *np, const char *propname,
int index, enum of_gpio_flags *flags)
struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
const char *propname, int index, enum of_gpio_flags *flags)
{
/* Return -EPROBE_DEFER to support probe() functions to be called
* later when the GPIO actually becomes available
*/
struct gg_data gg_data = { .flags = flags, .out_gpio = -EPROBE_DEFER };
struct gg_data gg_data = {
.flags = flags,
.out_gpio = ERR_PTR(-EPROBE_DEFER)
};
int ret;
/* .of_xlate might decide to not fill in the flags, so clear it. */
@@ -78,16 +83,17 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname,
if (ret) {
pr_debug("%s: can't parse gpios property of node '%s[%d]'\n",
__func__, np->full_name, index);
return ret;
return ERR_PTR(ret);
}
gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);
of_node_put(gg_data.gpiospec.np);
pr_debug("%s exited with status %d\n", __func__, gg_data.out_gpio);
pr_debug("%s exited with status %d\n", __func__,
PTR_RET(gg_data.out_gpio));
return gg_data.out_gpio;
}
EXPORT_SYMBOL(of_get_named_gpio_flags);
EXPORT_SYMBOL(of_get_named_gpiod_flags);
/**
* of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags

文件差異過大導致無法顯示 Load Diff