Commit 41684f67 authored by Linus Torvalds's avatar Linus Torvalds

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
parents ec7ae517 d92ef29a
...@@ -67,6 +67,9 @@ extern int nmk_gpio_get_mode(int gpio); ...@@ -67,6 +67,9 @@ extern int nmk_gpio_get_mode(int gpio);
extern void nmk_gpio_wakeups_suspend(void); extern void nmk_gpio_wakeups_suspend(void);
extern void nmk_gpio_wakeups_resume(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); extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
/* /*
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include <asm/traps.h> #include <asm/traps.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/gpio.h> #include <asm/gpio-internal.h>
#include <asm/regs306x.h> #include <asm/regs306x.h>
const int __initdata h8300_saved_vectors[] = { const int __initdata h8300_saved_vectors[] = {
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#include <asm/traps.h> #include <asm/traps.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/gpio.h> #include <asm/gpio-internal.h>
#include <asm/regs267x.h> #include <asm/regs267x.h>
/* saved vector list */ /* saved vector list */
......
...@@ -397,6 +397,7 @@ config GPIO_LANGWELL ...@@ -397,6 +397,7 @@ config GPIO_LANGWELL
config GPIO_PCH config GPIO_PCH
tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GPIO" tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GPIO"
depends on PCI && X86 depends on PCI && X86
select GENERIC_IRQ_CHIP
help help
This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
which is an IOH(Input/Output Hub) for x86 embedded processor. which is an IOH(Input/Output Hub) for x86 embedded processor.
...@@ -411,6 +412,7 @@ config GPIO_PCH ...@@ -411,6 +412,7 @@ config GPIO_PCH
config GPIO_ML_IOH config GPIO_ML_IOH
tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support" tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"
depends on PCI depends on PCI
select GENERIC_IRQ_CHIP
help help
ML7213 is companion chip for Intel Atom E6xx series. ML7213 is companion chip for Intel Atom E6xx series.
This driver can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/Output This driver can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/Output
......
...@@ -59,6 +59,7 @@ enum GPIO_REG { ...@@ -59,6 +59,7 @@ enum GPIO_REG {
GRER, /* rising edge detect */ GRER, /* rising edge detect */
GFER, /* falling edge detect */ GFER, /* falling edge detect */
GEDR, /* edge detect result */ GEDR, /* edge detect result */
GAFR, /* alt function */
}; };
struct lnw_gpio { struct lnw_gpio {
...@@ -81,6 +82,31 @@ static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset, ...@@ -81,6 +82,31 @@ static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
return ptr; 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) static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset)
{ {
void __iomem *gplr = gpio_reg(chip, offset, GPLR); void __iomem *gplr = gpio_reg(chip, offset, GPLR);
...@@ -321,6 +347,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, ...@@ -321,6 +347,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
lnw->reg_base = base; lnw->reg_base = base;
lnw->irq_base = irq_base; lnw->irq_base = irq_base;
lnw->chip.label = dev_name(&pdev->dev); lnw->chip.label = dev_name(&pdev->dev);
lnw->chip.request = lnw_gpio_request;
lnw->chip.direction_input = lnw_gpio_direction_input; lnw->chip.direction_input = lnw_gpio_direction_input;
lnw->chip.direction_output = lnw_gpio_direction_output; lnw->chip.direction_output = lnw_gpio_direction_output;
lnw->chip.get = lnw_gpio_get; lnw->chip.get = lnw_gpio_get;
......
...@@ -18,6 +18,17 @@ ...@@ -18,6 +18,17 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/gpio.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 #define PCI_VENDOR_ID_ROHM 0x10DB
...@@ -46,12 +57,22 @@ struct ioh_regs { ...@@ -46,12 +57,22 @@ struct ioh_regs {
/** /**
* struct ioh_gpio_reg_data - The register store data. * 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. * @po_reg: To store contents of PO register.
* @pm_reg: To store contents of PM 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 { struct ioh_gpio_reg_data {
u32 ien_reg;
u32 imask_reg;
u32 po_reg; u32 po_reg;
u32 pm_reg; u32 pm_reg;
u32 im0_reg;
u32 im1_reg;
u32 use_sel_reg;
}; };
/** /**
...@@ -62,7 +83,11 @@ struct ioh_gpio_reg_data { ...@@ -62,7 +83,11 @@ struct ioh_gpio_reg_data {
* @gpio: Data for GPIO infrastructure. * @gpio: Data for GPIO infrastructure.
* @ioh_gpio_reg: Memory mapped Register data is saved here * @ioh_gpio_reg: Memory mapped Register data is saved here
* when suspend. * when suspend.
* @gpio_use_sel: Save GPIO_USE_SEL1~4 register for PM
* @ch: Indicate GPIO channel * @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 { struct ioh_gpio {
void __iomem *base; void __iomem *base;
...@@ -70,8 +95,11 @@ struct ioh_gpio { ...@@ -70,8 +95,11 @@ struct ioh_gpio {
struct device *dev; struct device *dev;
struct gpio_chip gpio; struct gpio_chip gpio;
struct ioh_gpio_reg_data ioh_gpio_reg; struct ioh_gpio_reg_data ioh_gpio_reg;
u32 gpio_use_sel;
struct mutex lock; struct mutex lock;
int ch; int ch;
int irq_base;
spinlock_t spinlock;
}; };
static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12}; 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) ...@@ -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) static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
{ {
chip->ioh_gpio_reg.po_reg = ioread32(&chip->reg->regs[chip->ch].po); int i;
chip->ioh_gpio_reg.pm_reg = ioread32(&chip->reg->regs[chip->ch].pm);
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) ...@@ -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) static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
{ {
/* to store contents of PO register */ int i;
iowrite32(chip->ioh_gpio_reg.po_reg, &chip->reg->regs[chip->ch].po);
/* to store contents of PM register */ for (i = 0; i < 8; i ++, chip++) {
iowrite32(chip->ioh_gpio_reg.pm_reg, &chip->reg->regs[chip->ch].pm); 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 #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) static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
{ {
struct gpio_chip *gpio = &chip->gpio; struct gpio_chip *gpio = &chip->gpio;
...@@ -175,16 +241,148 @@ static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port) ...@@ -175,16 +241,148 @@ static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
gpio->base = -1; gpio->base = -1;
gpio->ngpio = num_port; gpio->ngpio = num_port;
gpio->can_sleep = 0; 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, static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
const struct pci_device_id *id) const struct pci_device_id *id)
{ {
int ret; int ret;
int i; int i, j;
struct ioh_gpio *chip; struct ioh_gpio *chip;
void __iomem *base; void __iomem *base;
void __iomem *chip_save; void __iomem *chip_save;
int irq_base;
ret = pci_enable_device(pdev); ret = pci_enable_device(pdev);
if (ret) { if (ret) {
...@@ -228,10 +426,41 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev, ...@@ -228,10 +426,41 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
} }
chip = chip_save; 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); pci_set_drvdata(pdev, chip);
return 0; 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: err_gpiochip_add:
while (--i >= 0) { while (--i >= 0) {
chip--; chip--;
...@@ -264,7 +493,11 @@ static void __devexit ioh_gpio_remove(struct pci_dev *pdev) ...@@ -264,7 +493,11 @@ static void __devexit ioh_gpio_remove(struct pci_dev *pdev)
void __iomem *chip_save; void __iomem *chip_save;
chip_save = chip; chip_save = chip;
free_irq(pdev->irq, chip);
for (i = 0; i < 8; i++, chip++) { for (i = 0; i < 8; i++, chip++) {
irq_free_descs(chip->irq_base, num_ports[i]);
err = gpiochip_remove(&chip->gpio); err = gpiochip_remove(&chip->gpio);
if (err) if (err)
dev_err(&pdev->dev, "Failed gpiochip_remove\n"); 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) ...@@ -282,9 +515,11 @@ static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
{ {
s32 ret; s32 ret;
struct ioh_gpio *chip = pci_get_drvdata(pdev); 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_save_reg_conf(chip);
ioh_gpio_restore_reg_conf(chip); spin_unlock_irqrestore(&chip->spinlock, flags);
ret = pci_save_state(pdev); ret = pci_save_state(pdev);
if (ret) { if (ret) {
...@@ -304,6 +539,7 @@ static int ioh_gpio_resume(struct pci_dev *pdev) ...@@ -304,6 +539,7 @@ static int ioh_gpio_resume(struct pci_dev *pdev)
{ {
s32 ret; s32 ret;
struct ioh_gpio *chip = pci_get_drvdata(pdev); struct ioh_gpio *chip = pci_get_drvdata(pdev);
unsigned long flags;
ret = pci_enable_wake(pdev, PCI_D0, 0); ret = pci_enable_wake(pdev, PCI_D0, 0);
...@@ -315,9 +551,11 @@ static int ioh_gpio_resume(struct pci_dev *pdev) ...@@ -315,9 +551,11 @@ static int ioh_gpio_resume(struct pci_dev *pdev)
} }
pci_restore_state(pdev); pci_restore_state(pdev);
spin_lock_irqsave(&chip->spinlock, flags);
iowrite32(0x01, &chip->reg->srst); iowrite32(0x01, &chip->reg->srst);
iowrite32(0x00, &chip->reg->srst); iowrite32(0x00, &chip->reg->srst);
ioh_gpio_restore_reg_conf(chip); ioh_gpio_restore_reg_conf(chip);
spin_unlock_irqrestore(&chip->spinlock, flags);
return 0; return 0;
} }
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <asm-generic/bug.h> #include <asm-generic/bug.h>
#include <asm/mach/irq.h>
enum mxc_gpio_hwtype { enum mxc_gpio_hwtype {
IMX1_GPIO, /* runs on i.mx1 */ IMX1_GPIO, /* runs on i.mx1 */
...@@ -232,10 +233,15 @@ static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc) ...@@ -232,10 +233,15 @@ static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
{ {
u32 irq_stat; u32 irq_stat;
struct mxc_gpio_port *port = irq_get_handler_data(irq); 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); irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR);
mxc_gpio_irq_handler(port, irq_stat); mxc_gpio_irq_handler(port, irq_stat);
chained_irq_exit(chip, desc);
} }
/* MX2 has one interrupt *for all* gpio ports */ /* MX2 has one interrupt *for all* gpio ports */
......
...@@ -59,7 +59,6 @@ struct nmk_gpio_chip { ...@@ -59,7 +59,6 @@ struct nmk_gpio_chip {
u32 rwimsc; u32 rwimsc;
u32 fwimsc; u32 fwimsc;
u32 slpm; u32 slpm;
u32 enabled;
u32 pull_up; u32 pull_up;
}; };
...@@ -277,6 +276,8 @@ static void nmk_gpio_glitch_slpm_init(unsigned int *slpm) ...@@ -277,6 +276,8 @@ static void nmk_gpio_glitch_slpm_init(unsigned int *slpm)
if (!chip) if (!chip)
break; break;
clk_enable(chip->clk);
slpm[i] = readl(chip->addr + NMK_GPIO_SLPC); slpm[i] = readl(chip->addr + NMK_GPIO_SLPC);
writel(temp, 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) ...@@ -293,6 +294,8 @@ static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm)
break; break;
writel(slpm[i], chip->addr + NMK_GPIO_SLPC); 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) ...@@ -337,10 +340,12 @@ static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep)
break; break;
} }
clk_enable(nmk_chip->clk);
spin_lock(&nmk_chip->lock); spin_lock(&nmk_chip->lock);
__nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base, __nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base,
cfgs[i], sleep, glitch ? slpm : NULL); cfgs[i], sleep, glitch ? slpm : NULL);
spin_unlock(&nmk_chip->lock); spin_unlock(&nmk_chip->lock);
clk_disable(nmk_chip->clk);
} }
if (glitch) if (glitch)
...@@ -425,6 +430,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode) ...@@ -425,6 +430,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
if (!nmk_chip) if (!nmk_chip)
return -EINVAL; return -EINVAL;
clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
spin_lock(&nmk_chip->lock); spin_lock(&nmk_chip->lock);
...@@ -432,6 +438,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode) ...@@ -432,6 +438,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
spin_unlock(&nmk_chip->lock); spin_unlock(&nmk_chip->lock);
spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
clk_disable(nmk_chip->clk);
return 0; return 0;
} }
...@@ -458,9 +465,11 @@ int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull) ...@@ -458,9 +465,11 @@ int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull)
if (!nmk_chip) if (!nmk_chip)
return -EINVAL; return -EINVAL;
clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_chip->lock, flags); spin_lock_irqsave(&nmk_chip->lock, flags);
__nmk_gpio_set_pull(nmk_chip, gpio - nmk_chip->chip.base, pull); __nmk_gpio_set_pull(nmk_chip, gpio - nmk_chip->chip.base, pull);
spin_unlock_irqrestore(&nmk_chip->lock, flags); spin_unlock_irqrestore(&nmk_chip->lock, flags);
clk_disable(nmk_chip->clk);
return 0; return 0;
} }
...@@ -484,9 +493,11 @@ int nmk_gpio_set_mode(int gpio, int gpio_mode) ...@@ -484,9 +493,11 @@ int nmk_gpio_set_mode(int gpio, int gpio_mode)
if (!nmk_chip) if (!nmk_chip)
return -EINVAL; return -EINVAL;
clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_chip->lock, flags); spin_lock_irqsave(&nmk_chip->lock, flags);
__nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode); __nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode);
spin_unlock_irqrestore(&nmk_chip->lock, flags); spin_unlock_irqrestore(&nmk_chip->lock, flags);
clk_disable(nmk_chip->clk);
return 0; return 0;
} }
...@@ -503,9 +514,13 @@ int nmk_gpio_get_mode(int gpio) ...@@ -503,9 +514,13 @@ int nmk_gpio_get_mode(int gpio)
bit = 1 << (gpio - nmk_chip->chip.base); bit = 1 << (gpio - nmk_chip->chip.base);
clk_enable(nmk_chip->clk);
afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit; afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit;
bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & 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); return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
} }
EXPORT_SYMBOL(nmk_gpio_get_mode); EXPORT_SYMBOL(nmk_gpio_get_mode);
...@@ -526,7 +541,10 @@ static void nmk_gpio_irq_ack(struct irq_data *d) ...@@ -526,7 +541,10 @@ static void nmk_gpio_irq_ack(struct irq_data *d)
nmk_chip = irq_data_get_irq_chip_data(d); nmk_chip = irq_data_get_irq_chip_data(d);
if (!nmk_chip) if (!nmk_chip)
return; return;
clk_enable(nmk_chip->clk);
writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC); writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC);
clk_disable(nmk_chip->clk);
} }
enum nmk_gpio_irq_type { enum nmk_gpio_irq_type {
...@@ -587,11 +605,7 @@ static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable) ...@@ -587,11 +605,7 @@ static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
if (!nmk_chip) if (!nmk_chip)
return -EINVAL; return -EINVAL;
if (enable) clk_enable(nmk_chip->clk);
nmk_chip->enabled |= bitmask;
else
nmk_chip->enabled &= ~bitmask;
spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
spin_lock(&nmk_chip->lock); spin_lock(&nmk_chip->lock);
...@@ -602,6 +616,7 @@ static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable) ...@@ -602,6 +616,7 @@ static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
spin_unlock(&nmk_chip->lock); spin_unlock(&nmk_chip->lock);
spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
clk_disable(nmk_chip->clk);
return 0; return 0;
} }
...@@ -629,10 +644,11 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on) ...@@ -629,10 +644,11 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
return -EINVAL; return -EINVAL;
bitmask = nmk_gpio_get_bitmask(gpio); bitmask = nmk_gpio_get_bitmask(gpio);
clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
spin_lock(&nmk_chip->lock); spin_lock(&nmk_chip->lock);
if (!(nmk_chip->enabled & bitmask)) if (irqd_irq_disabled(d))
__nmk_gpio_set_wake(nmk_chip, gpio, on); __nmk_gpio_set_wake(nmk_chip, gpio, on);
if (on) if (on)
...@@ -642,13 +658,15 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int 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(&nmk_chip->lock);
spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
clk_disable(nmk_chip->clk);
return 0; return 0;
} }
static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) 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; int gpio;
struct nmk_gpio_chip *nmk_chip; struct nmk_gpio_chip *nmk_chip;
unsigned long flags; unsigned long flags;
...@@ -665,8 +683,7 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) ...@@ -665,8 +683,7 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
if (type & IRQ_TYPE_LEVEL_LOW) if (type & IRQ_TYPE_LEVEL_LOW)
return -EINVAL; return -EINVAL;
enabled = nmk_chip->enabled & bitmask; clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_chip->lock, flags); spin_lock_irqsave(&nmk_chip->lock, flags);
if (enabled) if (enabled)
...@@ -690,10 +707,28 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) ...@@ -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); __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true);
spin_unlock_irqrestore(&nmk_chip->lock, flags); spin_unlock_irqrestore(&nmk_chip->lock, flags);
clk_disable(nmk_chip->clk);
return 0; 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 = { static struct irq_chip nmk_gpio_irq_chip = {
.name = "Nomadik-GPIO", .name = "Nomadik-GPIO",
.irq_ack = nmk_gpio_irq_ack, .irq_ack = nmk_gpio_irq_ack,
...@@ -701,6 +736,8 @@ static struct irq_chip nmk_gpio_irq_chip = { ...@@ -701,6 +736,8 @@ static struct irq_chip nmk_gpio_irq_chip = {
.irq_unmask = nmk_gpio_irq_unmask, .irq_unmask = nmk_gpio_irq_unmask,
.irq_set_type = nmk_gpio_irq_set_type, .irq_set_type = nmk_gpio_irq_set_type,
.irq_set_wake = nmk_gpio_irq_set_wake, .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, 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, ...@@ -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) static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
{ {
struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq); 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); __nmk_gpio_irq_handler(irq, desc, status);
} }
...@@ -773,7 +814,12 @@ static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset) ...@@ -773,7 +814,12 @@ static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset)
struct nmk_gpio_chip *nmk_chip = struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip); container_of(chip, struct nmk_gpio_chip, chip);
clk_enable(nmk_chip->clk);
writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC); writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
clk_disable(nmk_chip->clk);
return 0; return 0;
} }
...@@ -782,8 +828,15 @@ static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset) ...@@ -782,8 +828,15 @@ static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset)
struct nmk_gpio_chip *nmk_chip = struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip); container_of(chip, struct nmk_gpio_chip, chip);
u32 bit = 1 << offset; u32 bit = 1 << offset;
int value;
clk_enable(nmk_chip->clk);
return (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0; 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, 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, ...@@ -792,7 +845,11 @@ static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset,
struct nmk_gpio_chip *nmk_chip = struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip); container_of(chip, struct nmk_gpio_chip, chip);
clk_enable(nmk_chip->clk);
__nmk_gpio_set_output(nmk_chip, offset, val); __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, 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, ...@@ -801,8 +858,12 @@ static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
struct nmk_gpio_chip *nmk_chip = struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip); container_of(chip, struct nmk_gpio_chip, chip);
clk_enable(nmk_chip->clk);
__nmk_gpio_make_output(nmk_chip, offset, val); __nmk_gpio_make_output(nmk_chip, offset, val);
clk_disable(nmk_chip->clk);
return 0; return 0;
} }
...@@ -833,6 +894,8 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) ...@@ -833,6 +894,8 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
[NMK_GPIO_ALT_C] = "altC", [NMK_GPIO_ALT_C] = "altC",
}; };
clk_enable(nmk_chip->clk);
for (i = 0; i < chip->ngpio; i++, gpio++) { for (i = 0; i < chip->ngpio; i++, gpio++) {
const char *label = gpiochip_is_requested(chip, i); const char *label = gpiochip_is_requested(chip, i);
bool pull; bool pull;
...@@ -877,6 +940,8 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) ...@@ -877,6 +940,8 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
seq_printf(s, "\n"); seq_printf(s, "\n");
} }
clk_disable(nmk_chip->clk);
} }
#else #else
...@@ -894,6 +959,34 @@ static struct gpio_chip nmk_gpio_template = { ...@@ -894,6 +959,34 @@ static struct gpio_chip nmk_gpio_template = {
.can_sleep = 0, .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 * 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, * (those that have had set_irq_wake() called on them) as wakeup interrupts,
...@@ -913,6 +1006,8 @@ void nmk_gpio_wakeups_suspend(void) ...@@ -913,6 +1006,8 @@ void nmk_gpio_wakeups_suspend(void)
if (!chip) if (!chip)
break; break;
clk_enable(chip->clk);
chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC); chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC);
chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC); chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC);
...@@ -927,6 +1022,8 @@ void nmk_gpio_wakeups_suspend(void) ...@@ -927,6 +1022,8 @@ void nmk_gpio_wakeups_suspend(void)
/* 0 -> wakeup enable */ /* 0 -> wakeup enable */
writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC); writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC);
} }
clk_disable(chip->clk);
} }
} }
...@@ -940,11 +1037,15 @@ void nmk_gpio_wakeups_resume(void) ...@@ -940,11 +1037,15 @@ void nmk_gpio_wakeups_resume(void)
if (!chip) if (!chip)
break; break;
clk_enable(chip->clk);
writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC); writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC);
writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC); writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC);
if (chip->sleepmode) if (chip->sleepmode)
writel(chip->slpm, chip->addr + NMK_GPIO_SLPC); 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) ...@@ -1011,8 +1112,6 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
goto out_release; goto out_release;
} }
clk_enable(clk);
nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL); nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL);
if (!nmk_chip) { if (!nmk_chip) {
ret = -ENOMEM; ret = -ENOMEM;
......
This diff is collapsed.
...@@ -118,7 +118,7 @@ static int pl061_to_irq(struct gpio_chip *gc, unsigned offset) ...@@ -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); 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 -EINVAL;
return chip->irq_base + offset; return chip->irq_base + offset;
...@@ -246,6 +246,18 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) ...@@ -246,6 +246,18 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
if (chip == NULL) if (chip == NULL)
return -ENOMEM; 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, if (!request_mem_region(dev->res.start,
resource_size(&dev->res), "pl061")) { resource_size(&dev->res), "pl061")) {
ret = -EBUSY; ret = -EBUSY;
...@@ -267,14 +279,11 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) ...@@ -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.get = pl061_get_value;
chip->gc.set = pl061_set_value; chip->gc.set = pl061_set_value;
chip->gc.to_irq = pl061_to_irq; chip->gc.to_irq = pl061_to_irq;
chip->gc.base = pdata->gpio_base;
chip->gc.ngpio = PL061_GPIO_NR; chip->gc.ngpio = PL061_GPIO_NR;
chip->gc.label = dev_name(&dev->dev); chip->gc.label = dev_name(&dev->dev);
chip->gc.dev = &dev->dev; chip->gc.dev = &dev->dev;
chip->gc.owner = THIS_MODULE; chip->gc.owner = THIS_MODULE;
chip->irq_base = pdata->irq_base;
ret = gpiochip_add(&chip->gc); ret = gpiochip_add(&chip->gc);
if (ret) if (ret)
goto iounmap; goto iounmap;
...@@ -283,7 +292,7 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) ...@@ -283,7 +292,7 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
* irq_chip support * irq_chip support
*/ */
if (chip->irq_base == (unsigned) -1) if (chip->irq_base == NO_IRQ)
return 0; return 0;
writeb(0, chip->base + GPIOIE); /* disable irqs */ writeb(0, chip->base + GPIOIE); /* disable irqs */
...@@ -307,11 +316,13 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) ...@@ -307,11 +316,13 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
list_add(&chip->list, chip_list); list_add(&chip->list, chip_list);
for (i = 0; i < PL061_GPIO_NR; i++) { for (i = 0; i < PL061_GPIO_NR; i++) {
if (pdata->directions & (1 << i)) if (pdata) {
pl061_direction_output(&chip->gc, i, if (pdata->directions & (1 << i))
pdata->values & (1 << i)); pl061_direction_output(&chip->gc, i,
else pdata->values & (1 << i));
pl061_direction_input(&chip->gc, i); else
pl061_direction_input(&chip->gc, i);
}
irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip, irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip,
handle_simple_irq); handle_simple_irq);
......
...@@ -41,6 +41,7 @@ static inline bool gpio_is_valid(int number) ...@@ -41,6 +41,7 @@ static inline bool gpio_is_valid(int number)
} }
struct device; struct device;
struct gpio;
struct seq_file; struct seq_file;
struct module; struct module;
struct device_node; struct device_node;
...@@ -170,18 +171,6 @@ extern int __gpio_cansleep(unsigned gpio); ...@@ -170,18 +171,6 @@ extern int __gpio_cansleep(unsigned gpio);
extern int __gpio_to_irq(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_one(unsigned gpio, unsigned long flags, const char *label);
extern int gpio_request_array(const struct gpio *array, size_t num); extern int gpio_request_array(const struct gpio *array, size_t num);
extern void gpio_free_array(const struct gpio *array, size_t num); extern void gpio_free_array(const struct gpio *array, size_t num);
...@@ -220,13 +209,13 @@ static inline int gpio_cansleep(unsigned gpio) ...@@ -220,13 +209,13 @@ static inline int gpio_cansleep(unsigned gpio)
static inline int gpio_get_value_cansleep(unsigned gpio) static inline int gpio_get_value_cansleep(unsigned gpio)
{ {
might_sleep(); might_sleep();
return gpio_get_value(gpio); return __gpio_get_value(gpio);
} }
static inline void gpio_set_value_cansleep(unsigned gpio, int value) static inline void gpio_set_value_cansleep(unsigned gpio, int value)
{ {
might_sleep(); might_sleep();
gpio_set_value(gpio, value); __gpio_set_value(gpio, value);
} }
#endif /* !CONFIG_GPIOLIB */ #endif /* !CONFIG_GPIOLIB */
......
...@@ -7,8 +7,7 @@ struct pl061_platform_data { ...@@ -7,8 +7,7 @@ struct pl061_platform_data {
unsigned gpio_base; unsigned gpio_base;
/* number of the first IRQ. /* number of the first IRQ.
* If the IRQ functionality in not desired this must be set to * If the IRQ functionality in not desired this must be set to NO_IRQ.
* (unsigned) -1.
*/ */
unsigned irq_base; unsigned irq_base;
......
...@@ -14,6 +14,18 @@ ...@@ -14,6 +14,18 @@
#define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW) #define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW)
#define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH) #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 #ifdef CONFIG_GENERIC_GPIO
#include <asm/gpio.h> #include <asm/gpio.h>
...@@ -24,18 +36,8 @@ ...@@ -24,18 +36,8 @@
#include <linux/errno.h> #include <linux/errno.h>
struct device; struct device;
struct gpio;
struct gpio_chip; 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) static inline bool gpio_is_valid(int number)
{ {
return false; return false;
......
...@@ -211,6 +211,7 @@ irq_alloc_generic_chip(const char *name, int num_ct, unsigned int irq_base, ...@@ -211,6 +211,7 @@ irq_alloc_generic_chip(const char *name, int num_ct, unsigned int irq_base,
} }
return gc; return gc;
} }
EXPORT_SYMBOL_GPL(irq_alloc_generic_chip);
/* /*
* Separate lockdep class for interrupt chip which can nest irq_desc * 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, ...@@ -258,6 +259,7 @@ void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk,
} }
gc->irq_cnt = i - gc->irq_base; gc->irq_cnt = i - gc->irq_base;
} }
EXPORT_SYMBOL_GPL(irq_setup_generic_chip);
/** /**
* irq_setup_alt_chip - Switch to alternative 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) ...@@ -281,6 +283,7 @@ int irq_setup_alt_chip(struct irq_data *d, unsigned int type)
} }
return -EINVAL; return -EINVAL;
} }
EXPORT_SYMBOL_GPL(irq_setup_alt_chip);
/** /**
* irq_remove_generic_chip - Remove a chip * irq_remove_generic_chip - Remove a chip
...@@ -311,6 +314,7 @@ void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk, ...@@ -311,6 +314,7 @@ void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,
irq_modify_status(i, clr, set); irq_modify_status(i, clr, set);
} }
} }
EXPORT_SYMBOL_GPL(irq_remove_generic_chip);
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int irq_gc_suspend(void) static int irq_gc_suspend(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment