Merge branch 'gpio/next' of git://git.secretlab.ca/git/linux-2.6

* 'gpio/next' of git://git.secretlab.ca/git/linux-2.6:
  h8300: Move gpio.h to gpio-internal.h
  gpio: pl061: add DT binding support
  gpio: fix build error in include/asm-generic/gpio.h
  gpiolib: Ensure struct gpio is always defined
  irq: Add EXPORT_SYMBOL_GPL to function of irq generic-chip
  gpio-ml-ioh: Use NUMA_NO_NODE not GFP_KERNEL
  gpio-pch: Use NUMA_NO_NODE not GFP_KERNEL
  gpio: langwell: ensure alternate function is cleared
  gpio-pch: Support interrupt function
  gpio-pch: Save register value in suspend()
  gpio-pch: modify gpio_nums and mask
  gpio-pch: support ML7223 IOH n-Bus
  gpio-pch: add spinlock in suspend/resume processing
  gpio-pch: Delete invalid "restore" code in suspend()
  gpio-ml-ioh: Fix suspend/resume issue
  gpio-ml-ioh: Support interrupt function
  gpio-ml-ioh: Delete unnecessary code
  gpio/mxc: add chained_irq_enter/exit() to mx3_gpio_irq_handler()
  gpio/nomadik: use genirq core to track enablement
  gpio/nomadik: disable clocks when unused
This commit is contained in:
Linus Torvalds 2011-10-29 07:27:45 -07:00
Родитель ec7ae51753 d92ef29a6f
Коммит 41684f67af
15 изменённых файлов: 683 добавлений и 67 удалений

Просмотреть файл

@ -67,6 +67,9 @@ extern int nmk_gpio_get_mode(int gpio);
extern void nmk_gpio_wakeups_suspend(void);
extern void nmk_gpio_wakeups_resume(void);
extern void nmk_gpio_clocks_enable(void);
extern void nmk_gpio_clocks_disable(void);
extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
/*

Просмотреть файл

Просмотреть файл

@ -11,7 +11,7 @@
#include <asm/traps.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/gpio.h>
#include <asm/gpio-internal.h>
#include <asm/regs306x.h>
const int __initdata h8300_saved_vectors[] = {

Просмотреть файл

@ -14,7 +14,7 @@
#include <asm/traps.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/gpio.h>
#include <asm/gpio-internal.h>
#include <asm/regs267x.h>
/* saved vector list */

Просмотреть файл

@ -397,6 +397,7 @@ config GPIO_LANGWELL
config GPIO_PCH
tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GPIO"
depends on PCI && X86
select GENERIC_IRQ_CHIP
help
This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
which is an IOH(Input/Output Hub) for x86 embedded processor.
@ -411,6 +412,7 @@ config GPIO_PCH
config GPIO_ML_IOH
tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"
depends on PCI
select GENERIC_IRQ_CHIP
help
ML7213 is companion chip for Intel Atom E6xx series.
This driver can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/Output

Просмотреть файл

@ -59,6 +59,7 @@ enum GPIO_REG {
GRER, /* rising edge detect */
GFER, /* falling edge detect */
GEDR, /* edge detect result */
GAFR, /* alt function */
};
struct lnw_gpio {
@ -81,6 +82,31 @@ static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
return ptr;
}
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);
unsigned nreg = chip->ngpio / 32;
u8 reg = offset / 16;
void __iomem *ptr;
ptr = (void __iomem *)(lnw->reg_base + reg_type * nreg * 4 + reg * 4);
return ptr;
}
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);
@ -321,6 +347,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
lnw->reg_base = base;
lnw->irq_base = irq_base;
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;

Просмотреть файл

@ -18,6 +18,17 @@
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#define IOH_EDGE_FALLING 0
#define IOH_EDGE_RISING BIT(0)
#define IOH_LEVEL_L BIT(1)
#define IOH_LEVEL_H (BIT(0) | BIT(1))
#define IOH_EDGE_BOTH BIT(2)
#define IOH_IM_MASK (BIT(0) | BIT(1) | BIT(2))
#define IOH_IRQ_BASE 0
#define PCI_VENDOR_ID_ROHM 0x10DB
@ -46,12 +57,22 @@ struct ioh_regs {
/**
* struct ioh_gpio_reg_data - The register store data.
* @ien_reg To store contents of interrupt enable register.
* @imask_reg: To store contents of interrupt mask regist
* @po_reg: To store contents of PO register.
* @pm_reg: To store contents of PM register.
* @im0_reg: To store contents of interrupt mode regist0
* @im1_reg: To store contents of interrupt mode regist1
* @use_sel_reg: To store contents of GPIO_USE_SEL0~3
*/
struct ioh_gpio_reg_data {
u32 ien_reg;
u32 imask_reg;
u32 po_reg;
u32 pm_reg;
u32 im0_reg;
u32 im1_reg;
u32 use_sel_reg;
};
/**
@ -62,7 +83,11 @@ struct ioh_gpio_reg_data {
* @gpio: Data for GPIO infrastructure.
* @ioh_gpio_reg: Memory mapped Register data is saved here
* when suspend.
* @gpio_use_sel: Save GPIO_USE_SEL1~4 register for PM
* @ch: Indicate GPIO channel
* @irq_base: Save base of IRQ number for interrupt
* @spinlock: Used for register access protection in
* interrupt context ioh_irq_type and PM;
*/
struct ioh_gpio {
void __iomem *base;
@ -70,8 +95,11 @@ struct ioh_gpio {
struct device *dev;
struct gpio_chip gpio;
struct ioh_gpio_reg_data ioh_gpio_reg;
u32 gpio_use_sel;
struct mutex lock;
int ch;
int irq_base;
spinlock_t spinlock;
};
static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12};
@ -145,8 +173,25 @@ static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
*/
static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
{
chip->ioh_gpio_reg.po_reg = ioread32(&chip->reg->regs[chip->ch].po);
chip->ioh_gpio_reg.pm_reg = ioread32(&chip->reg->regs[chip->ch].pm);
int i;
for (i = 0; i < 8; i ++, chip++) {
chip->ioh_gpio_reg.po_reg =
ioread32(&chip->reg->regs[chip->ch].po);
chip->ioh_gpio_reg.pm_reg =
ioread32(&chip->reg->regs[chip->ch].pm);
chip->ioh_gpio_reg.ien_reg =
ioread32(&chip->reg->regs[chip->ch].ien);
chip->ioh_gpio_reg.imask_reg =
ioread32(&chip->reg->regs[chip->ch].imask);
chip->ioh_gpio_reg.im0_reg =
ioread32(&chip->reg->regs[chip->ch].im_0);
chip->ioh_gpio_reg.im1_reg =
ioread32(&chip->reg->regs[chip->ch].im_1);
if (i < 4)
chip->ioh_gpio_reg.use_sel_reg =
ioread32(&chip->reg->ioh_sel_reg[i]);
}
}
/*
@ -154,13 +199,34 @@ static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
*/
static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
{
/* to store contents of PO register */
iowrite32(chip->ioh_gpio_reg.po_reg, &chip->reg->regs[chip->ch].po);
/* to store contents of PM register */
iowrite32(chip->ioh_gpio_reg.pm_reg, &chip->reg->regs[chip->ch].pm);
int i;
for (i = 0; i < 8; i ++, chip++) {
iowrite32(chip->ioh_gpio_reg.po_reg,
&chip->reg->regs[chip->ch].po);
iowrite32(chip->ioh_gpio_reg.pm_reg,
&chip->reg->regs[chip->ch].pm);
iowrite32(chip->ioh_gpio_reg.ien_reg,
&chip->reg->regs[chip->ch].ien);
iowrite32(chip->ioh_gpio_reg.imask_reg,
&chip->reg->regs[chip->ch].imask);
iowrite32(chip->ioh_gpio_reg.im0_reg,
&chip->reg->regs[chip->ch].im_0);
iowrite32(chip->ioh_gpio_reg.im1_reg,
&chip->reg->regs[chip->ch].im_1);
if (i < 4)
iowrite32(chip->ioh_gpio_reg.use_sel_reg,
&chip->reg->ioh_sel_reg[i]);
}
}
#endif
static int ioh_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
{
struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio);
return chip->irq_base + offset;
}
static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
{
struct gpio_chip *gpio = &chip->gpio;
@ -175,16 +241,148 @@ static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
gpio->base = -1;
gpio->ngpio = num_port;
gpio->can_sleep = 0;
gpio->to_irq = ioh_gpio_to_irq;
}
static int ioh_irq_type(struct irq_data *d, unsigned int type)
{
u32 im;
u32 *im_reg;
u32 ien;
u32 im_pos;
int ch;
unsigned long flags;
u32 val;
int irq = d->irq;
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct ioh_gpio *chip = gc->private;
ch = irq - chip->irq_base;
if (irq <= chip->irq_base + 7) {
im_reg = &chip->reg->regs[chip->ch].im_0;
im_pos = ch;
} else {
im_reg = &chip->reg->regs[chip->ch].im_1;
im_pos = ch - 8;
}
dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d type=%d\n",
__func__, irq, type, ch, im_pos, type);
spin_lock_irqsave(&chip->spinlock, flags);
switch (type) {
case IRQ_TYPE_EDGE_RISING:
val = IOH_EDGE_RISING;
break;
case IRQ_TYPE_EDGE_FALLING:
val = IOH_EDGE_FALLING;
break;
case IRQ_TYPE_EDGE_BOTH:
val = IOH_EDGE_BOTH;
break;
case IRQ_TYPE_LEVEL_HIGH:
val = IOH_LEVEL_H;
break;
case IRQ_TYPE_LEVEL_LOW:
val = IOH_LEVEL_L;
break;
case IRQ_TYPE_PROBE:
goto end;
default:
dev_warn(chip->dev, "%s: unknown type(%dd)",
__func__, type);
goto end;
}
/* Set interrupt mode */
im = ioread32(im_reg) & ~(IOH_IM_MASK << (im_pos * 4));
iowrite32(im | (val << (im_pos * 4)), im_reg);
/* iclr */
iowrite32(BIT(ch), &chip->reg->regs[chip->ch].iclr);
/* IMASKCLR */
iowrite32(BIT(ch), &chip->reg->regs[chip->ch].imaskclr);
/* Enable interrupt */
ien = ioread32(&chip->reg->regs[chip->ch].ien);
iowrite32(ien | BIT(ch), &chip->reg->regs[chip->ch].ien);
end:
spin_unlock_irqrestore(&chip->spinlock, flags);
return 0;
}
static void ioh_irq_unmask(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct ioh_gpio *chip = gc->private;
iowrite32(1 << (d->irq - chip->irq_base),
&chip->reg->regs[chip->ch].imaskclr);
}
static void ioh_irq_mask(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct ioh_gpio *chip = gc->private;
iowrite32(1 << (d->irq - chip->irq_base),
&chip->reg->regs[chip->ch].imask);
}
static irqreturn_t ioh_gpio_handler(int irq, void *dev_id)
{
struct ioh_gpio *chip = dev_id;
u32 reg_val;
int i, j;
int ret = IRQ_NONE;
for (i = 0; i < 8; i++) {
reg_val = ioread32(&chip->reg->regs[i].istatus);
for (j = 0; j < num_ports[i]; j++) {
if (reg_val & BIT(j)) {
dev_dbg(chip->dev,
"%s:[%d]:irq=%d status=0x%x\n",
__func__, j, irq, reg_val);
iowrite32(BIT(j),
&chip->reg->regs[chip->ch].iclr);
generic_handle_irq(chip->irq_base + j);
ret = IRQ_HANDLED;
}
}
}
return ret;
}
static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
unsigned int irq_start, unsigned int num)
{
struct irq_chip_generic *gc;
struct irq_chip_type *ct;
gc = irq_alloc_generic_chip("ioh_gpio", 1, irq_start, chip->base,
handle_simple_irq);
gc->private = chip;
ct = gc->chip_types;
ct->chip.irq_mask = ioh_irq_mask;
ct->chip.irq_unmask = ioh_irq_unmask;
ct->chip.irq_set_type = ioh_irq_type;
irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
IRQ_NOREQUEST | IRQ_NOPROBE, 0);
}
static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
int ret;
int i;
int i, j;
struct ioh_gpio *chip;
void __iomem *base;
void __iomem *chip_save;
int irq_base;
ret = pci_enable_device(pdev);
if (ret) {
@ -228,10 +426,41 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
}
chip = chip_save;
for (j = 0; j < 8; j++, chip++) {
irq_base = irq_alloc_descs(-1, IOH_IRQ_BASE, num_ports[j],
NUMA_NO_NODE);
if (irq_base < 0) {
dev_warn(&pdev->dev,
"ml_ioh_gpio: Failed to get IRQ base num\n");
chip->irq_base = -1;
goto err_irq_alloc_descs;
}
chip->irq_base = irq_base;
ioh_gpio_alloc_generic_chip(chip, irq_base, num_ports[j]);
}
chip = chip_save;
ret = request_irq(pdev->irq, ioh_gpio_handler,
IRQF_SHARED, KBUILD_MODNAME, chip);
if (ret != 0) {
dev_err(&pdev->dev,
"%s request_irq failed\n", __func__);
goto err_request_irq;
}
pci_set_drvdata(pdev, chip);
return 0;
err_request_irq:
chip = chip_save;
err_irq_alloc_descs:
while (--j >= 0) {
chip--;
irq_free_descs(chip->irq_base, num_ports[j]);
}
chip = chip_save;
err_gpiochip_add:
while (--i >= 0) {
chip--;
@ -264,7 +493,11 @@ static void __devexit ioh_gpio_remove(struct pci_dev *pdev)
void __iomem *chip_save;
chip_save = chip;
free_irq(pdev->irq, chip);
for (i = 0; i < 8; i++, chip++) {
irq_free_descs(chip->irq_base, num_ports[i]);
err = gpiochip_remove(&chip->gpio);
if (err)
dev_err(&pdev->dev, "Failed gpiochip_remove\n");
@ -282,9 +515,11 @@ static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
{
s32 ret;
struct ioh_gpio *chip = pci_get_drvdata(pdev);
unsigned long flags;
spin_lock_irqsave(&chip->spinlock, flags);
ioh_gpio_save_reg_conf(chip);
ioh_gpio_restore_reg_conf(chip);
spin_unlock_irqrestore(&chip->spinlock, flags);
ret = pci_save_state(pdev);
if (ret) {
@ -304,6 +539,7 @@ static int ioh_gpio_resume(struct pci_dev *pdev)
{
s32 ret;
struct ioh_gpio *chip = pci_get_drvdata(pdev);
unsigned long flags;
ret = pci_enable_wake(pdev, PCI_D0, 0);
@ -315,9 +551,11 @@ static int ioh_gpio_resume(struct pci_dev *pdev)
}
pci_restore_state(pdev);
spin_lock_irqsave(&chip->spinlock, flags);
iowrite32(0x01, &chip->reg->srst);
iowrite32(0x00, &chip->reg->srst);
ioh_gpio_restore_reg_conf(chip);
spin_unlock_irqrestore(&chip->spinlock, flags);
return 0;
}

Просмотреть файл

@ -30,6 +30,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <asm-generic/bug.h>
#include <asm/mach/irq.h>
enum mxc_gpio_hwtype {
IMX1_GPIO, /* runs on i.mx1 */
@ -232,10 +233,15 @@ static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
{
u32 irq_stat;
struct mxc_gpio_port *port = irq_get_handler_data(irq);
struct irq_chip *chip = irq_get_chip(irq);
chained_irq_enter(chip, desc);
irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR);
mxc_gpio_irq_handler(port, irq_stat);
chained_irq_exit(chip, desc);
}
/* MX2 has one interrupt *for all* gpio ports */

Просмотреть файл

@ -59,7 +59,6 @@ struct nmk_gpio_chip {
u32 rwimsc;
u32 fwimsc;
u32 slpm;
u32 enabled;
u32 pull_up;
};
@ -277,6 +276,8 @@ static void nmk_gpio_glitch_slpm_init(unsigned int *slpm)
if (!chip)
break;
clk_enable(chip->clk);
slpm[i] = readl(chip->addr + NMK_GPIO_SLPC);
writel(temp, chip->addr + NMK_GPIO_SLPC);
}
@ -293,6 +294,8 @@ static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm)
break;
writel(slpm[i], chip->addr + NMK_GPIO_SLPC);
clk_disable(chip->clk);
}
}
@ -337,10 +340,12 @@ static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep)
break;
}
clk_enable(nmk_chip->clk);
spin_lock(&nmk_chip->lock);
__nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base,
cfgs[i], sleep, glitch ? slpm : NULL);
spin_unlock(&nmk_chip->lock);
clk_disable(nmk_chip->clk);
}
if (glitch)
@ -425,6 +430,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
if (!nmk_chip)
return -EINVAL;
clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
spin_lock(&nmk_chip->lock);
@ -432,6 +438,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
spin_unlock(&nmk_chip->lock);
spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
clk_disable(nmk_chip->clk);
return 0;
}
@ -458,9 +465,11 @@ int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull)
if (!nmk_chip)
return -EINVAL;
clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_chip->lock, flags);
__nmk_gpio_set_pull(nmk_chip, gpio - nmk_chip->chip.base, pull);
spin_unlock_irqrestore(&nmk_chip->lock, flags);
clk_disable(nmk_chip->clk);
return 0;
}
@ -484,9 +493,11 @@ int nmk_gpio_set_mode(int gpio, int gpio_mode)
if (!nmk_chip)
return -EINVAL;
clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_chip->lock, flags);
__nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode);
spin_unlock_irqrestore(&nmk_chip->lock, flags);
clk_disable(nmk_chip->clk);
return 0;
}
@ -503,9 +514,13 @@ int nmk_gpio_get_mode(int gpio)
bit = 1 << (gpio - nmk_chip->chip.base);
clk_enable(nmk_chip->clk);
afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit;
bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit;
clk_disable(nmk_chip->clk);
return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
}
EXPORT_SYMBOL(nmk_gpio_get_mode);
@ -526,7 +541,10 @@ static void nmk_gpio_irq_ack(struct irq_data *d)
nmk_chip = irq_data_get_irq_chip_data(d);
if (!nmk_chip)
return;
clk_enable(nmk_chip->clk);
writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC);
clk_disable(nmk_chip->clk);
}
enum nmk_gpio_irq_type {
@ -587,11 +605,7 @@ static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
if (!nmk_chip)
return -EINVAL;
if (enable)
nmk_chip->enabled |= bitmask;
else
nmk_chip->enabled &= ~bitmask;
clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
spin_lock(&nmk_chip->lock);
@ -602,6 +616,7 @@ static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
spin_unlock(&nmk_chip->lock);
spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
clk_disable(nmk_chip->clk);
return 0;
}
@ -629,10 +644,11 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
return -EINVAL;
bitmask = nmk_gpio_get_bitmask(gpio);
clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
spin_lock(&nmk_chip->lock);
if (!(nmk_chip->enabled & bitmask))
if (irqd_irq_disabled(d))
__nmk_gpio_set_wake(nmk_chip, gpio, on);
if (on)
@ -642,13 +658,15 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
spin_unlock(&nmk_chip->lock);
spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
clk_disable(nmk_chip->clk);
return 0;
}
static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
bool enabled, wake = irqd_is_wakeup_set(d);
bool enabled = !irqd_irq_disabled(d);
bool wake = irqd_is_wakeup_set(d);
int gpio;
struct nmk_gpio_chip *nmk_chip;
unsigned long flags;
@ -665,8 +683,7 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
if (type & IRQ_TYPE_LEVEL_LOW)
return -EINVAL;
enabled = nmk_chip->enabled & bitmask;
clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_chip->lock, flags);
if (enabled)
@ -690,10 +707,28 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true);
spin_unlock_irqrestore(&nmk_chip->lock, flags);
clk_disable(nmk_chip->clk);
return 0;
}
static unsigned int nmk_gpio_irq_startup(struct irq_data *d)
{
struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d);
clk_enable(nmk_chip->clk);
nmk_gpio_irq_unmask(d);
return 0;
}
static void nmk_gpio_irq_shutdown(struct irq_data *d)
{
struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d);
nmk_gpio_irq_mask(d);
clk_disable(nmk_chip->clk);
}
static struct irq_chip nmk_gpio_irq_chip = {
.name = "Nomadik-GPIO",
.irq_ack = nmk_gpio_irq_ack,
@ -701,6 +736,8 @@ static struct irq_chip nmk_gpio_irq_chip = {
.irq_unmask = nmk_gpio_irq_unmask,
.irq_set_type = nmk_gpio_irq_set_type,
.irq_set_wake = nmk_gpio_irq_set_wake,
.irq_startup = nmk_gpio_irq_startup,
.irq_shutdown = nmk_gpio_irq_shutdown,
};
static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
@ -727,7 +764,11 @@ static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
{
struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq);
u32 status = readl(nmk_chip->addr + NMK_GPIO_IS);
u32 status;
clk_enable(nmk_chip->clk);
status = readl(nmk_chip->addr + NMK_GPIO_IS);
clk_disable(nmk_chip->clk);
__nmk_gpio_irq_handler(irq, desc, status);
}
@ -773,7 +814,12 @@ static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset)
struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip);
clk_enable(nmk_chip->clk);
writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
clk_disable(nmk_chip->clk);
return 0;
}
@ -782,8 +828,15 @@ static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset)
struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip);
u32 bit = 1 << offset;
int value;
return (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0;
clk_enable(nmk_chip->clk);
value = (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0;
clk_disable(nmk_chip->clk);
return value;
}
static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset,
@ -792,7 +845,11 @@ static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset,
struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip);
clk_enable(nmk_chip->clk);
__nmk_gpio_set_output(nmk_chip, offset, val);
clk_disable(nmk_chip->clk);
}
static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
@ -801,8 +858,12 @@ static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip);
clk_enable(nmk_chip->clk);
__nmk_gpio_make_output(nmk_chip, offset, val);
clk_disable(nmk_chip->clk);
return 0;
}
@ -833,6 +894,8 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
[NMK_GPIO_ALT_C] = "altC",
};
clk_enable(nmk_chip->clk);
for (i = 0; i < chip->ngpio; i++, gpio++) {
const char *label = gpiochip_is_requested(chip, i);
bool pull;
@ -877,6 +940,8 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
seq_printf(s, "\n");
}
clk_disable(nmk_chip->clk);
}
#else
@ -894,6 +959,34 @@ static struct gpio_chip nmk_gpio_template = {
.can_sleep = 0,
};
void nmk_gpio_clocks_enable(void)
{
int i;
for (i = 0; i < NUM_BANKS; i++) {
struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
if (!chip)
continue;
clk_enable(chip->clk);
}
}
void nmk_gpio_clocks_disable(void)
{
int i;
for (i = 0; i < NUM_BANKS; i++) {
struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
if (!chip)
continue;
clk_disable(chip->clk);
}
}
/*
* Called from the suspend/resume path to only keep the real wakeup interrupts
* (those that have had set_irq_wake() called on them) as wakeup interrupts,
@ -913,6 +1006,8 @@ void nmk_gpio_wakeups_suspend(void)
if (!chip)
break;
clk_enable(chip->clk);
chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC);
chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC);
@ -927,6 +1022,8 @@ void nmk_gpio_wakeups_suspend(void)
/* 0 -> wakeup enable */
writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC);
}
clk_disable(chip->clk);
}
}
@ -940,11 +1037,15 @@ void nmk_gpio_wakeups_resume(void)
if (!chip)
break;
clk_enable(chip->clk);
writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC);
writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC);
if (chip->sleepmode)
writel(chip->slpm, chip->addr + NMK_GPIO_SLPC);
clk_disable(chip->clk);
}
}
@ -1011,8 +1112,6 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
goto out_release;
}
clk_enable(clk);
nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL);
if (!nmk_chip) {
ret = -ENOMEM;

Просмотреть файл

@ -17,9 +17,17 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#define PCH_GPIO_ALL_PINS 0xfff /* Mask for GPIO pins 0 to 11 */
#define GPIO_NUM_PINS 12 /* Specifies number of GPIO PINS GPIO0-GPIO11 */
#define PCH_EDGE_FALLING 0
#define PCH_EDGE_RISING BIT(0)
#define PCH_LEVEL_L BIT(1)
#define PCH_LEVEL_H (BIT(0) | BIT(1))
#define PCH_EDGE_BOTH BIT(2)
#define PCH_IM_MASK (BIT(0) | BIT(1) | BIT(2))
#define PCH_IRQ_BASE 24
struct pch_regs {
u32 ien;
@ -33,18 +41,43 @@ struct pch_regs {
u32 pm;
u32 im0;
u32 im1;
u32 reserved[4];
u32 reserved[3];
u32 gpio_use_sel;
u32 reset;
};
enum pch_type_t {
INTEL_EG20T_PCH,
OKISEMI_ML7223m_IOH, /* OKISEMI ML7223 IOH PCIe Bus-m */
OKISEMI_ML7223n_IOH /* OKISEMI ML7223 IOH PCIe Bus-n */
};
/* Specifies number of GPIO PINS */
static int gpio_pins[] = {
[INTEL_EG20T_PCH] = 12,
[OKISEMI_ML7223m_IOH] = 8,
[OKISEMI_ML7223n_IOH] = 8,
};
/**
* struct pch_gpio_reg_data - The register store data.
* @ien_reg: To store contents of IEN register.
* @imask_reg: To store contents of IMASK register.
* @po_reg: To store contents of PO register.
* @pm_reg: To store contents of PM register.
* @im0_reg: To store contents of IM0 register.
* @im1_reg: To store contents of IM1 register.
* @gpio_use_sel_reg : To store contents of GPIO_USE_SEL register.
* (Only ML7223 Bus-n)
*/
struct pch_gpio_reg_data {
u32 ien_reg;
u32 imask_reg;
u32 po_reg;
u32 pm_reg;
u32 im0_reg;
u32 im1_reg;
u32 gpio_use_sel_reg;
};
/**
@ -55,6 +88,12 @@ struct pch_gpio_reg_data {
* @gpio: Data for GPIO infrastructure.
* @pch_gpio_reg: Memory mapped Register data is saved here
* when suspend.
* @lock: Used for register access protection
* @irq_base: Save base of IRQ number for interrupt
* @ioh: IOH ID
* @spinlock: Used for register access protection in
* interrupt context pch_irq_mask,
* pch_irq_unmask and pch_irq_type;
*/
struct pch_gpio {
void __iomem *base;
@ -63,6 +102,9 @@ struct pch_gpio {
struct gpio_chip gpio;
struct pch_gpio_reg_data pch_gpio_reg;
struct mutex lock;
int irq_base;
enum pch_type_t ioh;
spinlock_t spinlock;
};
static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
@ -96,7 +138,7 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
u32 reg_val;
mutex_lock(&chip->lock);
pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS;
pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
pm |= (1 << nr);
iowrite32(pm, &chip->reg->pm);
@ -118,7 +160,7 @@ static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
u32 pm;
mutex_lock(&chip->lock);
pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS; /*bits 0-11*/
pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
pm &= ~(1 << nr);
iowrite32(pm, &chip->reg->pm);
mutex_unlock(&chip->lock);
@ -131,8 +173,16 @@ static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
*/
static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
{
chip->pch_gpio_reg.ien_reg = ioread32(&chip->reg->ien);
chip->pch_gpio_reg.imask_reg = ioread32(&chip->reg->imask);
chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po);
chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm);
chip->pch_gpio_reg.im0_reg = ioread32(&chip->reg->im0);
if (chip->ioh == INTEL_EG20T_PCH)
chip->pch_gpio_reg.im1_reg = ioread32(&chip->reg->im1);
if (chip->ioh == OKISEMI_ML7223n_IOH)
chip->pch_gpio_reg.gpio_use_sel_reg =\
ioread32(&chip->reg->gpio_use_sel);
}
/*
@ -140,10 +190,24 @@ static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
*/
static void pch_gpio_restore_reg_conf(struct pch_gpio *chip)
{
iowrite32(chip->pch_gpio_reg.ien_reg, &chip->reg->ien);
iowrite32(chip->pch_gpio_reg.imask_reg, &chip->reg->imask);
/* to store contents of PO register */
iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po);
/* to store contents of PM register */
iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm);
iowrite32(chip->pch_gpio_reg.im0_reg, &chip->reg->im0);
if (chip->ioh == INTEL_EG20T_PCH)
iowrite32(chip->pch_gpio_reg.im1_reg, &chip->reg->im1);
if (chip->ioh == OKISEMI_ML7223n_IOH)
iowrite32(chip->pch_gpio_reg.gpio_use_sel_reg,
&chip->reg->gpio_use_sel);
}
static int pch_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
{
struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
return chip->irq_base + offset;
}
static void pch_gpio_setup(struct pch_gpio *chip)
@ -158,8 +222,132 @@ static void pch_gpio_setup(struct pch_gpio *chip)
gpio->set = pch_gpio_set;
gpio->dbg_show = NULL;
gpio->base = -1;
gpio->ngpio = GPIO_NUM_PINS;
gpio->ngpio = gpio_pins[chip->ioh];
gpio->can_sleep = 0;
gpio->to_irq = pch_gpio_to_irq;
}
static int pch_irq_type(struct irq_data *d, unsigned int type)
{
u32 im;
u32 *im_reg;
u32 ien;
u32 im_pos;
int ch;
unsigned long flags;
u32 val;
int irq = d->irq;
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct pch_gpio *chip = gc->private;
ch = irq - chip->irq_base;
if (irq <= chip->irq_base + 7) {
im_reg = &chip->reg->im0;
im_pos = ch;
} else {
im_reg = &chip->reg->im1;
im_pos = ch - 8;
}
dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d\n",
__func__, irq, type, ch, im_pos);
spin_lock_irqsave(&chip->spinlock, flags);
switch (type) {
case IRQ_TYPE_EDGE_RISING:
val = PCH_EDGE_RISING;
break;
case IRQ_TYPE_EDGE_FALLING:
val = PCH_EDGE_FALLING;
break;
case IRQ_TYPE_EDGE_BOTH:
val = PCH_EDGE_BOTH;
break;
case IRQ_TYPE_LEVEL_HIGH:
val = PCH_LEVEL_H;
break;
case IRQ_TYPE_LEVEL_LOW:
val = PCH_LEVEL_L;
break;
case IRQ_TYPE_PROBE:
goto end;
default:
dev_warn(chip->dev, "%s: unknown type(%dd)",
__func__, type);
goto end;
}
/* Set interrupt mode */
im = ioread32(im_reg) & ~(PCH_IM_MASK << (im_pos * 4));
iowrite32(im | (val << (im_pos * 4)), im_reg);
/* iclr */
iowrite32(BIT(ch), &chip->reg->iclr);
/* IMASKCLR */
iowrite32(BIT(ch), &chip->reg->imaskclr);
/* Enable interrupt */
ien = ioread32(&chip->reg->ien);
iowrite32(ien | BIT(ch), &chip->reg->ien);
end:
spin_unlock_irqrestore(&chip->spinlock, flags);
return 0;
}
static void pch_irq_unmask(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct pch_gpio *chip = gc->private;
iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imaskclr);
}
static void pch_irq_mask(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct pch_gpio *chip = gc->private;
iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imask);
}
static irqreturn_t pch_gpio_handler(int irq, void *dev_id)
{
struct pch_gpio *chip = dev_id;
u32 reg_val = ioread32(&chip->reg->istatus);
int i;
int ret = IRQ_NONE;
for (i = 0; i < gpio_pins[chip->ioh]; i++) {
if (reg_val & BIT(i)) {
dev_dbg(chip->dev, "%s:[%d]:irq=%d status=0x%x\n",
__func__, i, irq, reg_val);
iowrite32(BIT(i), &chip->reg->iclr);
generic_handle_irq(chip->irq_base + i);
ret = IRQ_HANDLED;
}
}
return ret;
}
static __devinit void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
unsigned int irq_start, unsigned int num)
{
struct irq_chip_generic *gc;
struct irq_chip_type *ct;
gc = irq_alloc_generic_chip("pch_gpio", 1, irq_start, chip->base,
handle_simple_irq);
gc->private = chip;
ct = gc->chip_types;
ct->chip.irq_mask = pch_irq_mask;
ct->chip.irq_unmask = pch_irq_unmask;
ct->chip.irq_set_type = pch_irq_type;
irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
IRQ_NOREQUEST | IRQ_NOPROBE, 0);
}
static int __devinit pch_gpio_probe(struct pci_dev *pdev,
@ -167,6 +355,7 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
{
s32 ret;
struct pch_gpio *chip;
int irq_base;
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
@ -192,6 +381,13 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
goto err_iomap;
}
if (pdev->device == 0x8803)
chip->ioh = INTEL_EG20T_PCH;
else if (pdev->device == 0x8014)
chip->ioh = OKISEMI_ML7223m_IOH;
else if (pdev->device == 0x8043)
chip->ioh = OKISEMI_ML7223n_IOH;
chip->reg = chip->base;
pci_set_drvdata(pdev, chip);
mutex_init(&chip->lock);
@ -202,8 +398,36 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
goto err_gpiochip_add;
}
irq_base = irq_alloc_descs(-1, 0, gpio_pins[chip->ioh], NUMA_NO_NODE);
if (irq_base < 0) {
dev_warn(&pdev->dev, "PCH gpio: Failed to get IRQ base num\n");
chip->irq_base = -1;
goto end;
}
chip->irq_base = irq_base;
ret = request_irq(pdev->irq, pch_gpio_handler,
IRQF_SHARED, KBUILD_MODNAME, chip);
if (ret != 0) {
dev_err(&pdev->dev,
"%s request_irq failed\n", __func__);
goto err_request_irq;
}
pch_gpio_alloc_generic_chip(chip, irq_base, gpio_pins[chip->ioh]);
/* Initialize interrupt ien register */
iowrite32(0, &chip->reg->ien);
end:
return 0;
err_request_irq:
irq_free_descs(irq_base, gpio_pins[chip->ioh]);
ret = gpiochip_remove(&chip->gpio);
if (ret)
dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
err_gpiochip_add:
pci_iounmap(pdev, chip->base);
@ -224,6 +448,12 @@ static void __devexit pch_gpio_remove(struct pci_dev *pdev)
int err;
struct pch_gpio *chip = pci_get_drvdata(pdev);
if (chip->irq_base != -1) {
free_irq(pdev->irq, chip);
irq_free_descs(chip->irq_base, gpio_pins[chip->ioh]);
}
err = gpiochip_remove(&chip->gpio);
if (err)
dev_err(&pdev->dev, "Failed gpiochip_remove\n");
@ -239,9 +469,11 @@ static int pch_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
{
s32 ret;
struct pch_gpio *chip = pci_get_drvdata(pdev);
unsigned long flags;
spin_lock_irqsave(&chip->spinlock, flags);
pch_gpio_save_reg_conf(chip);
pch_gpio_restore_reg_conf(chip);
spin_unlock_irqrestore(&chip->spinlock, flags);
ret = pci_save_state(pdev);
if (ret) {
@ -261,6 +493,7 @@ static int pch_gpio_resume(struct pci_dev *pdev)
{
s32 ret;
struct pch_gpio *chip = pci_get_drvdata(pdev);
unsigned long flags;
ret = pci_enable_wake(pdev, PCI_D0, 0);
@ -272,9 +505,11 @@ static int pch_gpio_resume(struct pci_dev *pdev)
}
pci_restore_state(pdev);
spin_lock_irqsave(&chip->spinlock, flags);
iowrite32(0x01, &chip->reg->reset);
iowrite32(0x00, &chip->reg->reset);
pch_gpio_restore_reg_conf(chip);
spin_unlock_irqrestore(&chip->spinlock, flags);
return 0;
}
@ -287,6 +522,7 @@ static int pch_gpio_resume(struct pci_dev *pdev)
static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);

Просмотреть файл

@ -118,7 +118,7 @@ static int pl061_to_irq(struct gpio_chip *gc, unsigned offset)
{
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
if (chip->irq_base == (unsigned) -1)
if (chip->irq_base == NO_IRQ)
return -EINVAL;
return chip->irq_base + offset;
@ -246,6 +246,18 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
if (chip == NULL)
return -ENOMEM;
pdata = dev->dev.platform_data;
if (pdata) {
chip->gc.base = pdata->gpio_base;
chip->irq_base = pdata->irq_base;
} else if (dev->dev.of_node) {
chip->gc.base = -1;
chip->irq_base = NO_IRQ;
} else {
ret = -ENODEV;
goto free_mem;
}
if (!request_mem_region(dev->res.start,
resource_size(&dev->res), "pl061")) {
ret = -EBUSY;
@ -267,14 +279,11 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
chip->gc.get = pl061_get_value;
chip->gc.set = pl061_set_value;
chip->gc.to_irq = pl061_to_irq;
chip->gc.base = pdata->gpio_base;
chip->gc.ngpio = PL061_GPIO_NR;
chip->gc.label = dev_name(&dev->dev);
chip->gc.dev = &dev->dev;
chip->gc.owner = THIS_MODULE;
chip->irq_base = pdata->irq_base;
ret = gpiochip_add(&chip->gc);
if (ret)
goto iounmap;
@ -283,7 +292,7 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
* irq_chip support
*/
if (chip->irq_base == (unsigned) -1)
if (chip->irq_base == NO_IRQ)
return 0;
writeb(0, chip->base + GPIOIE); /* disable irqs */
@ -307,11 +316,13 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
list_add(&chip->list, chip_list);
for (i = 0; i < PL061_GPIO_NR; i++) {
if (pdata->directions & (1 << i))
pl061_direction_output(&chip->gc, i,
pdata->values & (1 << i));
else
pl061_direction_input(&chip->gc, i);
if (pdata) {
if (pdata->directions & (1 << i))
pl061_direction_output(&chip->gc, i,
pdata->values & (1 << i));
else
pl061_direction_input(&chip->gc, i);
}
irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip,
handle_simple_irq);

Просмотреть файл

@ -41,6 +41,7 @@ static inline bool gpio_is_valid(int number)
}
struct device;
struct gpio;
struct seq_file;
struct module;
struct device_node;
@ -170,18 +171,6 @@ extern int __gpio_cansleep(unsigned gpio);
extern int __gpio_to_irq(unsigned gpio);
/**
* struct gpio - a structure describing a GPIO with configuration
* @gpio: the GPIO number
* @flags: GPIO configuration as specified by GPIOF_*
* @label: a literal description string of this GPIO
*/
struct gpio {
unsigned gpio;
unsigned long flags;
const char *label;
};
extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
extern int gpio_request_array(const struct gpio *array, size_t num);
extern void gpio_free_array(const struct gpio *array, size_t num);
@ -220,13 +209,13 @@ static inline int gpio_cansleep(unsigned gpio)
static inline int gpio_get_value_cansleep(unsigned gpio)
{
might_sleep();
return gpio_get_value(gpio);
return __gpio_get_value(gpio);
}
static inline void gpio_set_value_cansleep(unsigned gpio, int value)
{
might_sleep();
gpio_set_value(gpio, value);
__gpio_set_value(gpio, value);
}
#endif /* !CONFIG_GPIOLIB */

Просмотреть файл

@ -7,8 +7,7 @@ struct pl061_platform_data {
unsigned gpio_base;
/* number of the first IRQ.
* If the IRQ functionality in not desired this must be set to
* (unsigned) -1.
* If the IRQ functionality in not desired this must be set to NO_IRQ.
*/
unsigned irq_base;

Просмотреть файл

@ -14,6 +14,18 @@
#define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW)
#define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH)
/**
* struct gpio - a structure describing a GPIO with configuration
* @gpio: the GPIO number
* @flags: GPIO configuration as specified by GPIOF_*
* @label: a literal description string of this GPIO
*/
struct gpio {
unsigned gpio;
unsigned long flags;
const char *label;
};
#ifdef CONFIG_GENERIC_GPIO
#include <asm/gpio.h>
@ -24,18 +36,8 @@
#include <linux/errno.h>
struct device;
struct gpio;
struct gpio_chip;
/*
* Some platforms don't support the GPIO programming interface.
*
* In case some driver uses it anyway (it should normally have
* depended on GENERIC_GPIO), these routines help the compiler
* optimize out much GPIO-related code ... or trigger a runtime
* warning when something is wrongly called.
*/
static inline bool gpio_is_valid(int number)
{
return false;

Просмотреть файл

@ -211,6 +211,7 @@ irq_alloc_generic_chip(const char *name, int num_ct, unsigned int irq_base,
}
return gc;
}
EXPORT_SYMBOL_GPL(irq_alloc_generic_chip);
/*
* Separate lockdep class for interrupt chip which can nest irq_desc
@ -258,6 +259,7 @@ void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk,
}
gc->irq_cnt = i - gc->irq_base;
}
EXPORT_SYMBOL_GPL(irq_setup_generic_chip);
/**
* irq_setup_alt_chip - Switch to alternative chip
@ -281,6 +283,7 @@ int irq_setup_alt_chip(struct irq_data *d, unsigned int type)
}
return -EINVAL;
}
EXPORT_SYMBOL_GPL(irq_setup_alt_chip);
/**
* irq_remove_generic_chip - Remove a chip
@ -311,6 +314,7 @@ void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,
irq_modify_status(i, clr, set);
}
}
EXPORT_SYMBOL_GPL(irq_remove_generic_chip);
#ifdef CONFIG_PM
static int irq_gc_suspend(void)