mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 18:51:56 -04:00
Merge branch 'gpio-for-grant' of git://sources.calxeda.com/kernel/linux into gpio/next
Conflicts: drivers/gpio/gpio-pl061.c
This commit is contained in:
commit
fda87903f4
353 changed files with 5031 additions and 2524 deletions
|
|
@ -138,6 +138,7 @@ config GPIO_MXS
|
|||
config GPIO_PL061
|
||||
bool "PrimeCell PL061 GPIO support"
|
||||
depends on ARM_AMBA
|
||||
select GENERIC_IRQ_CHIP
|
||||
help
|
||||
Say yes here to support the PrimeCell PL061 GPIO device
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
#include <linux/mfd/da9052/da9052.h>
|
||||
#include <linux/mfd/da9052/reg.h>
|
||||
#include <linux/mfd/da9052/pdata.h>
|
||||
#include <linux/mfd/da9052/gpio.h>
|
||||
|
||||
#define DA9052_INPUT 1
|
||||
#define DA9052_OUTPUT_OPENDRAIN 2
|
||||
|
|
@ -43,6 +42,9 @@
|
|||
#define DA9052_GPIO_MASK_UPPER_NIBBLE 0xF0
|
||||
#define DA9052_GPIO_MASK_LOWER_NIBBLE 0x0F
|
||||
#define DA9052_GPIO_NIBBLE_SHIFT 4
|
||||
#define DA9052_IRQ_GPI0 16
|
||||
#define DA9052_GPIO_ODD_SHIFT 7
|
||||
#define DA9052_GPIO_EVEN_SHIFT 3
|
||||
|
||||
struct da9052_gpio {
|
||||
struct da9052 *da9052;
|
||||
|
|
@ -104,33 +106,26 @@ static int da9052_gpio_get(struct gpio_chip *gc, unsigned offset)
|
|||
static void da9052_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
|
||||
{
|
||||
struct da9052_gpio *gpio = to_da9052_gpio(gc);
|
||||
unsigned char register_value = 0;
|
||||
int ret;
|
||||
|
||||
if (da9052_gpio_port_odd(offset)) {
|
||||
if (value) {
|
||||
register_value = DA9052_GPIO_ODD_PORT_MODE;
|
||||
ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
|
||||
DA9052_GPIO_0_1_REG,
|
||||
DA9052_GPIO_ODD_PORT_MODE,
|
||||
register_value);
|
||||
value << DA9052_GPIO_ODD_SHIFT);
|
||||
if (ret != 0)
|
||||
dev_err(gpio->da9052->dev,
|
||||
"Failed to updated gpio odd reg,%d",
|
||||
ret);
|
||||
}
|
||||
} else {
|
||||
if (value) {
|
||||
register_value = DA9052_GPIO_EVEN_PORT_MODE;
|
||||
ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
|
||||
DA9052_GPIO_0_1_REG,
|
||||
DA9052_GPIO_EVEN_PORT_MODE,
|
||||
register_value);
|
||||
value << DA9052_GPIO_EVEN_SHIFT);
|
||||
if (ret != 0)
|
||||
dev_err(gpio->da9052->dev,
|
||||
"Failed to updated gpio even reg,%d",
|
||||
ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -201,9 +196,9 @@ static struct gpio_chip reference_gp __devinitdata = {
|
|||
.direction_input = da9052_gpio_direction_input,
|
||||
.direction_output = da9052_gpio_direction_output,
|
||||
.to_irq = da9052_gpio_to_irq,
|
||||
.can_sleep = 1;
|
||||
.ngpio = 16;
|
||||
.base = -1;
|
||||
.can_sleep = 1,
|
||||
.ngpio = 16,
|
||||
.base = -1,
|
||||
};
|
||||
|
||||
static int __devinit da9052_gpio_probe(struct platform_device *pdev)
|
||||
|
|
|
|||
|
|
@ -332,6 +332,34 @@ static void ioh_irq_mask(struct irq_data *d)
|
|||
&chip->reg->regs[chip->ch].imask);
|
||||
}
|
||||
|
||||
static void ioh_irq_disable(struct irq_data *d)
|
||||
{
|
||||
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
|
||||
struct ioh_gpio *chip = gc->private;
|
||||
unsigned long flags;
|
||||
u32 ien;
|
||||
|
||||
spin_lock_irqsave(&chip->spinlock, flags);
|
||||
ien = ioread32(&chip->reg->regs[chip->ch].ien);
|
||||
ien &= ~(1 << (d->irq - chip->irq_base));
|
||||
iowrite32(ien, &chip->reg->regs[chip->ch].ien);
|
||||
spin_unlock_irqrestore(&chip->spinlock, flags);
|
||||
}
|
||||
|
||||
static void ioh_irq_enable(struct irq_data *d)
|
||||
{
|
||||
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
|
||||
struct ioh_gpio *chip = gc->private;
|
||||
unsigned long flags;
|
||||
u32 ien;
|
||||
|
||||
spin_lock_irqsave(&chip->spinlock, flags);
|
||||
ien = ioread32(&chip->reg->regs[chip->ch].ien);
|
||||
ien |= 1 << (d->irq - chip->irq_base);
|
||||
iowrite32(ien, &chip->reg->regs[chip->ch].ien);
|
||||
spin_unlock_irqrestore(&chip->spinlock, flags);
|
||||
}
|
||||
|
||||
static irqreturn_t ioh_gpio_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct ioh_gpio *chip = dev_id;
|
||||
|
|
@ -339,7 +367,7 @@ static irqreturn_t ioh_gpio_handler(int irq, void *dev_id)
|
|||
int i, j;
|
||||
int ret = IRQ_NONE;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
for (i = 0; i < 8; i++, chip++) {
|
||||
reg_val = ioread32(&chip->reg->regs[i].istatus);
|
||||
for (j = 0; j < num_ports[i]; j++) {
|
||||
if (reg_val & BIT(j)) {
|
||||
|
|
@ -370,6 +398,8 @@ static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
|
|||
ct->chip.irq_mask = ioh_irq_mask;
|
||||
ct->chip.irq_unmask = ioh_irq_unmask;
|
||||
ct->chip.irq_set_type = ioh_irq_type;
|
||||
ct->chip.irq_disable = ioh_irq_disable;
|
||||
ct->chip.irq_enable = ioh_irq_enable;
|
||||
|
||||
irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
|
||||
IRQ_NOREQUEST | IRQ_NOPROBE, 0);
|
||||
|
|
|
|||
|
|
@ -132,6 +132,15 @@ static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mpc5121_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
{
|
||||
/* GPIO 28..31 are input only on MPC5121 */
|
||||
if (gpio >= 28)
|
||||
return -EINVAL;
|
||||
|
||||
return mpc8xxx_gpio_dir_out(gc, gpio, val);
|
||||
}
|
||||
|
||||
static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
|
||||
|
|
@ -340,11 +349,10 @@ static void __init mpc8xxx_add_controller(struct device_node *np)
|
|||
mm_gc->save_regs = mpc8xxx_gpio_save_regs;
|
||||
gc->ngpio = MPC8XXX_GPIO_PINS;
|
||||
gc->direction_input = mpc8xxx_gpio_dir_in;
|
||||
gc->direction_output = mpc8xxx_gpio_dir_out;
|
||||
if (of_device_is_compatible(np, "fsl,mpc8572-gpio"))
|
||||
gc->get = mpc8572_gpio_get;
|
||||
else
|
||||
gc->get = mpc8xxx_gpio_get;
|
||||
gc->direction_output = of_device_is_compatible(np, "fsl,mpc5121-gpio") ?
|
||||
mpc5121_gpio_dir_out : mpc8xxx_gpio_dir_out;
|
||||
gc->get = of_device_is_compatible(np, "fsl,mpc8572-gpio") ?
|
||||
mpc8572_gpio_get : mpc8xxx_gpio_get;
|
||||
gc->set = mpc8xxx_gpio_set;
|
||||
gc->to_irq = mpc8xxx_gpio_to_irq;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/irq.h>
|
||||
|
|
@ -24,6 +23,7 @@
|
|||
#include <linux/amba/pl061.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pm.h>
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
#define GPIODIR 0x400
|
||||
#define GPIOIS 0x404
|
||||
|
|
@ -48,23 +48,16 @@ struct pl061_context_save_regs {
|
|||
#endif
|
||||
|
||||
struct pl061_gpio {
|
||||
/* We use a list of pl061_gpio structs for each trigger IRQ in the main
|
||||
* interrupts controller of the system. We need this to support systems
|
||||
* in which more that one PL061s are connected to the same IRQ. The ISR
|
||||
* interates through this list to find the source of the interrupt.
|
||||
*/
|
||||
struct list_head list;
|
||||
|
||||
/* Each of the two spinlocks protects a different set of hardware
|
||||
* regiters and data structurs. This decouples the code of the IRQ from
|
||||
* the GPIO code. This also makes the case of a GPIO routine call from
|
||||
* the IRQ code simpler.
|
||||
*/
|
||||
spinlock_t lock; /* GPIO registers */
|
||||
spinlock_t irq_lock; /* IRQ registers */
|
||||
|
||||
void __iomem *base;
|
||||
unsigned irq_base;
|
||||
int irq_base;
|
||||
struct irq_chip_generic *irq_gc;
|
||||
struct gpio_chip gc;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
|
@ -134,46 +127,16 @@ 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 == NO_IRQ)
|
||||
if (chip->irq_base <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
return chip->irq_base + offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* PL061 GPIO IRQ
|
||||
*/
|
||||
static void pl061_irq_disable(struct irq_data *d)
|
||||
{
|
||||
struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
|
||||
int offset = d->irq - chip->irq_base;
|
||||
unsigned long flags;
|
||||
u8 gpioie;
|
||||
|
||||
spin_lock_irqsave(&chip->irq_lock, flags);
|
||||
gpioie = readb(chip->base + GPIOIE);
|
||||
gpioie &= ~(1 << offset);
|
||||
writeb(gpioie, chip->base + GPIOIE);
|
||||
spin_unlock_irqrestore(&chip->irq_lock, flags);
|
||||
}
|
||||
|
||||
static void pl061_irq_enable(struct irq_data *d)
|
||||
{
|
||||
struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
|
||||
int offset = d->irq - chip->irq_base;
|
||||
unsigned long flags;
|
||||
u8 gpioie;
|
||||
|
||||
spin_lock_irqsave(&chip->irq_lock, flags);
|
||||
gpioie = readb(chip->base + GPIOIE);
|
||||
gpioie |= 1 << offset;
|
||||
writeb(gpioie, chip->base + GPIOIE);
|
||||
spin_unlock_irqrestore(&chip->irq_lock, flags);
|
||||
}
|
||||
|
||||
static int pl061_irq_type(struct irq_data *d, unsigned trigger)
|
||||
{
|
||||
struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
|
||||
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
|
||||
struct pl061_gpio *chip = gc->private;
|
||||
int offset = d->irq - chip->irq_base;
|
||||
unsigned long flags;
|
||||
u8 gpiois, gpioibe, gpioiev;
|
||||
|
|
@ -181,7 +144,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
|
|||
if (offset < 0 || offset >= PL061_GPIO_NR)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&chip->irq_lock, flags);
|
||||
raw_spin_lock_irqsave(&gc->lock, flags);
|
||||
|
||||
gpioiev = readb(chip->base + GPIOIEV);
|
||||
|
||||
|
|
@ -210,53 +173,54 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
|
|||
|
||||
writeb(gpioiev, chip->base + GPIOIEV);
|
||||
|
||||
spin_unlock_irqrestore(&chip->irq_lock, flags);
|
||||
raw_spin_unlock_irqrestore(&gc->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip pl061_irqchip = {
|
||||
.name = "GPIO",
|
||||
.irq_enable = pl061_irq_enable,
|
||||
.irq_disable = pl061_irq_disable,
|
||||
.irq_set_type = pl061_irq_type,
|
||||
};
|
||||
|
||||
static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
|
||||
{
|
||||
struct list_head *chip_list = irq_get_handler_data(irq);
|
||||
struct list_head *ptr;
|
||||
struct pl061_gpio *chip;
|
||||
unsigned long pending;
|
||||
int offset;
|
||||
struct pl061_gpio *chip = irq_desc_get_handler_data(desc);
|
||||
struct irq_chip *irqchip = irq_desc_get_chip(desc);
|
||||
|
||||
desc->irq_data.chip->irq_ack(&desc->irq_data);
|
||||
list_for_each(ptr, chip_list) {
|
||||
unsigned long pending;
|
||||
int offset;
|
||||
|
||||
chip = list_entry(ptr, struct pl061_gpio, list);
|
||||
pending = readb(chip->base + GPIOMIS);
|
||||
writeb(pending, chip->base + GPIOIC);
|
||||
|
||||
if (pending == 0)
|
||||
continue;
|
||||
chained_irq_enter(irqchip, desc);
|
||||
|
||||
pending = readb(chip->base + GPIOMIS);
|
||||
writeb(pending, chip->base + GPIOIC);
|
||||
if (pending) {
|
||||
for_each_set_bit(offset, &pending, PL061_GPIO_NR)
|
||||
generic_handle_irq(pl061_to_irq(&chip->gc, offset));
|
||||
}
|
||||
desc->irq_data.chip->irq_unmask(&desc->irq_data);
|
||||
|
||||
chained_irq_exit(irqchip, desc);
|
||||
}
|
||||
|
||||
static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base)
|
||||
{
|
||||
struct irq_chip_type *ct;
|
||||
|
||||
chip->irq_gc = irq_alloc_generic_chip("gpio-pl061", 1, irq_base,
|
||||
chip->base, handle_simple_irq);
|
||||
chip->irq_gc->private = chip;
|
||||
|
||||
ct = chip->irq_gc->chip_types;
|
||||
ct->chip.irq_mask = irq_gc_mask_clr_bit;
|
||||
ct->chip.irq_unmask = irq_gc_mask_set_bit;
|
||||
ct->chip.irq_set_type = pl061_irq_type;
|
||||
ct->chip.irq_set_wake = irq_gc_set_wake;
|
||||
ct->regs.mask = GPIOIE;
|
||||
|
||||
irq_setup_generic_chip(chip->irq_gc, IRQ_MSK(PL061_GPIO_NR),
|
||||
IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
|
||||
}
|
||||
|
||||
static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
|
||||
{
|
||||
struct pl061_platform_data *pdata;
|
||||
struct pl061_gpio *chip;
|
||||
struct list_head *chip_list;
|
||||
int ret, irq, i;
|
||||
static DECLARE_BITMAP(init_irq, NR_IRQS);
|
||||
|
||||
pdata = dev->dev.platform_data;
|
||||
if (pdata == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
|
||||
if (chip == NULL)
|
||||
|
|
@ -268,7 +232,7 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
|
|||
chip->irq_base = pdata->irq_base;
|
||||
} else if (dev->dev.of_node) {
|
||||
chip->gc.base = -1;
|
||||
chip->irq_base = NO_IRQ;
|
||||
chip->irq_base = 0;
|
||||
} else {
|
||||
ret = -ENODEV;
|
||||
goto free_mem;
|
||||
|
|
@ -287,8 +251,6 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
|
|||
}
|
||||
|
||||
spin_lock_init(&chip->lock);
|
||||
spin_lock_init(&chip->irq_lock);
|
||||
INIT_LIST_HEAD(&chip->list);
|
||||
|
||||
chip->gc.direction_input = pl061_direction_input;
|
||||
chip->gc.direction_output = pl061_direction_output;
|
||||
|
|
@ -308,9 +270,11 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
|
|||
* irq_chip support
|
||||
*/
|
||||
|
||||
if (chip->irq_base == NO_IRQ)
|
||||
if (chip->irq_base <= 0)
|
||||
return 0;
|
||||
|
||||
pl061_init_gc(chip, chip->irq_base);
|
||||
|
||||
writeb(0, chip->base + GPIOIE); /* disable irqs */
|
||||
irq = dev->irq[0];
|
||||
if (irq < 0) {
|
||||
|
|
@ -318,18 +282,7 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
|
|||
goto iounmap;
|
||||
}
|
||||
irq_set_chained_handler(irq, pl061_irq_handler);
|
||||
if (!test_and_set_bit(irq, init_irq)) { /* list initialized? */
|
||||
chip_list = kmalloc(sizeof(*chip_list), GFP_KERNEL);
|
||||
if (chip_list == NULL) {
|
||||
clear_bit(irq, init_irq);
|
||||
ret = -ENOMEM;
|
||||
goto iounmap;
|
||||
}
|
||||
INIT_LIST_HEAD(chip_list);
|
||||
irq_set_handler_data(irq, chip_list);
|
||||
} else
|
||||
chip_list = irq_get_handler_data(irq);
|
||||
list_add(&chip->list, chip_list);
|
||||
irq_set_handler_data(irq, chip);
|
||||
|
||||
for (i = 0; i < PL061_GPIO_NR; i++) {
|
||||
if (pdata) {
|
||||
|
|
@ -339,11 +292,6 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
|
|||
else
|
||||
pl061_direction_input(&chip->gc, i);
|
||||
}
|
||||
|
||||
irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip,
|
||||
handle_simple_irq);
|
||||
set_irq_flags(i+chip->irq_base, IRQF_VALID);
|
||||
irq_set_chip_data(i + chip->irq_base, chip);
|
||||
}
|
||||
|
||||
amba_set_drvdata(dev, chip);
|
||||
|
|
|
|||
Loading…
Reference in a new issue