Commit 8b29336f 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:
  gpio/via: rename VIA local config struct
  basic_mmio_gpio: split into a gpio library and platform device
  gpio: remove some legacy comments in build files
  gpio: add trace events for setting direction and value
  gpio/pca953x: Use handle_simple_irq instead of handle_edge_irq
  gpiolib: export gpiochip_find
  gpio: remove redundant Kconfig depends on GPIOLIB
  basic_mmio_gpio: convert to non-__raw* accessors
  basic_mmio_gpio: support direction registers
  basic_mmio_gpio: support different input/output registers
  basic_mmio_gpio: detect output method at probe time
  basic_mmio_gpio: request register regions
  basic_mmio_gpio: allow overriding number of gpio
  basic_mmio_gpio: convert to platform_{get,set}_drvdata()
  basic_mmio_gpio: remove runtime width/endianness evaluation
parents 9f1912c4 1adb656e
# #
# platform-neutral GPIO infrastructure and expanders # GPIO infrastructure and drivers
# #
config ARCH_WANT_OPTIONAL_GPIOLIB config ARCH_WANT_OPTIONAL_GPIOLIB
...@@ -31,7 +31,7 @@ menuconfig GPIOLIB ...@@ -31,7 +31,7 @@ menuconfig GPIOLIB
help help
This enables GPIO support through the generic GPIO library. This enables GPIO support through the generic GPIO library.
You only need to enable this, if you also want to enable You only need to enable this, if you also want to enable
one or more of the GPIO expansion card drivers below. one or more of the GPIO drivers below.
If unsure, say N. If unsure, say N.
...@@ -63,21 +63,26 @@ config GPIO_SYSFS ...@@ -63,21 +63,26 @@ config GPIO_SYSFS
Kernel drivers may also request that a particular GPIO be Kernel drivers may also request that a particular GPIO be
exported to userspace; this can be useful when debugging. exported to userspace; this can be useful when debugging.
# put expanders in the right section, in alphabetical order # put drivers in the right section, in alphabetical order
config GPIO_MAX730X config GPIO_MAX730X
tristate tristate
comment "Memory mapped GPIO expanders:" comment "Memory mapped GPIO drivers:"
config GPIO_BASIC_MMIO_CORE
tristate
help
Provides core functionality for basic memory-mapped GPIO controllers.
config GPIO_BASIC_MMIO config GPIO_BASIC_MMIO
tristate "Basic memory-mapped GPIO controllers support" tristate "Basic memory-mapped GPIO controllers support"
select GPIO_BASIC_MMIO_CORE
help help
Say yes here to support basic memory-mapped GPIO controllers. Say yes here to support basic memory-mapped GPIO controllers.
config GPIO_IT8761E config GPIO_IT8761E
tristate "IT8761E GPIO support" tristate "IT8761E GPIO support"
depends on GPIOLIB
help help
Say yes here to support GPIO functionality of IT8761E super I/O chip. Say yes here to support GPIO functionality of IT8761E super I/O chip.
...@@ -101,7 +106,7 @@ config GPIO_VR41XX ...@@ -101,7 +106,7 @@ config GPIO_VR41XX
config GPIO_SCH config GPIO_SCH
tristate "Intel SCH/TunnelCreek GPIO" tristate "Intel SCH/TunnelCreek GPIO"
depends on GPIOLIB && PCI && X86 depends on PCI && X86
select MFD_CORE select MFD_CORE
select LPC_SCH select LPC_SCH
help help
...@@ -121,7 +126,7 @@ config GPIO_SCH ...@@ -121,7 +126,7 @@ config GPIO_SCH
config GPIO_VX855 config GPIO_VX855
tristate "VIA VX855/VX875 GPIO" tristate "VIA VX855/VX875 GPIO"
depends on GPIOLIB && MFD_SUPPORT && PCI depends on MFD_SUPPORT && PCI
select MFD_CORE select MFD_CORE
select MFD_VX855 select MFD_VX855
help help
...@@ -347,13 +352,13 @@ config GPIO_ML_IOH ...@@ -347,13 +352,13 @@ config GPIO_ML_IOH
config GPIO_TIMBERDALE config GPIO_TIMBERDALE
bool "Support for timberdale GPIO IP" bool "Support for timberdale GPIO IP"
depends on MFD_TIMBERDALE && GPIOLIB && HAS_IOMEM depends on MFD_TIMBERDALE && HAS_IOMEM
---help--- ---help---
Add support for the GPIO IP in the timberdale FPGA. Add support for the GPIO IP in the timberdale FPGA.
config GPIO_RDC321X config GPIO_RDC321X
tristate "RDC R-321x GPIO support" tristate "RDC R-321x GPIO support"
depends on PCI && GPIOLIB depends on PCI
select MFD_SUPPORT select MFD_SUPPORT
select MFD_CORE select MFD_CORE
select MFD_RDC321X select MFD_RDC321X
......
# generic gpio support: dedicated expander chips, etc # generic gpio support: platform drivers, dedicated expander chips, etc
#
# NOTE: platform-specific GPIO drivers don't belong in the
# drivers/gpio directory; put them with other platform setup
# code, IRQ controllers, board init, etc.
ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
...@@ -10,6 +6,7 @@ obj-$(CONFIG_GPIOLIB) += gpiolib.o ...@@ -10,6 +6,7 @@ obj-$(CONFIG_GPIOLIB) += gpiolib.o
obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o
obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o
obj-$(CONFIG_GPIO_BASIC_MMIO_CORE) += basic_mmio_gpio.o
obj-$(CONFIG_GPIO_BASIC_MMIO) += basic_mmio_gpio.o obj-$(CONFIG_GPIO_BASIC_MMIO) += basic_mmio_gpio.o
obj-$(CONFIG_GPIO_LANGWELL) += langwell_gpio.o obj-$(CONFIG_GPIO_LANGWELL) += langwell_gpio.o
obj-$(CONFIG_GPIO_MAX730X) += max730x.o obj-$(CONFIG_GPIO_MAX730X) += max730x.o
......
This diff is collapsed.
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/slab.h> #include <linux/slab.h>
#define CREATE_TRACE_POINTS
#include <trace/events/gpio.h>
/* Optional implementation infrastructure for GPIO interfaces. /* Optional implementation infrastructure for GPIO interfaces.
* *
...@@ -1165,6 +1167,7 @@ struct gpio_chip *gpiochip_find(void *data, ...@@ -1165,6 +1167,7 @@ struct gpio_chip *gpiochip_find(void *data,
return chip; return chip;
} }
EXPORT_SYMBOL_GPL(gpiochip_find);
/* These "optional" allocation calls help prevent drivers from stomping /* These "optional" allocation calls help prevent drivers from stomping
* on each other, and help provide better diagnostics in debugfs. * on each other, and help provide better diagnostics in debugfs.
...@@ -1404,6 +1407,8 @@ int gpio_direction_input(unsigned gpio) ...@@ -1404,6 +1407,8 @@ int gpio_direction_input(unsigned gpio)
status = chip->direction_input(chip, gpio); status = chip->direction_input(chip, gpio);
if (status == 0) if (status == 0)
clear_bit(FLAG_IS_OUT, &desc->flags); clear_bit(FLAG_IS_OUT, &desc->flags);
trace_gpio_direction(chip->base + gpio, 1, status);
lose: lose:
return status; return status;
fail: fail:
...@@ -1457,6 +1462,8 @@ int gpio_direction_output(unsigned gpio, int value) ...@@ -1457,6 +1462,8 @@ int gpio_direction_output(unsigned gpio, int value)
status = chip->direction_output(chip, gpio, value); status = chip->direction_output(chip, gpio, value);
if (status == 0) if (status == 0)
set_bit(FLAG_IS_OUT, &desc->flags); set_bit(FLAG_IS_OUT, &desc->flags);
trace_gpio_value(chip->base + gpio, 0, value);
trace_gpio_direction(chip->base + gpio, 0, status);
lose: lose:
return status; return status;
fail: fail:
...@@ -1546,10 +1553,13 @@ EXPORT_SYMBOL_GPL(gpio_set_debounce); ...@@ -1546,10 +1553,13 @@ EXPORT_SYMBOL_GPL(gpio_set_debounce);
int __gpio_get_value(unsigned gpio) int __gpio_get_value(unsigned gpio)
{ {
struct gpio_chip *chip; struct gpio_chip *chip;
int value;
chip = gpio_to_chip(gpio); chip = gpio_to_chip(gpio);
WARN_ON(chip->can_sleep); WARN_ON(chip->can_sleep);
return chip->get ? chip->get(chip, gpio - chip->base) : 0; value = chip->get ? chip->get(chip, gpio - chip->base) : 0;
trace_gpio_value(gpio, 1, value);
return value;
} }
EXPORT_SYMBOL_GPL(__gpio_get_value); EXPORT_SYMBOL_GPL(__gpio_get_value);
...@@ -1568,6 +1578,7 @@ void __gpio_set_value(unsigned gpio, int value) ...@@ -1568,6 +1578,7 @@ void __gpio_set_value(unsigned gpio, int value)
chip = gpio_to_chip(gpio); chip = gpio_to_chip(gpio);
WARN_ON(chip->can_sleep); WARN_ON(chip->can_sleep);
trace_gpio_value(gpio, 0, value);
chip->set(chip, gpio - chip->base, value); chip->set(chip, gpio - chip->base, value);
} }
EXPORT_SYMBOL_GPL(__gpio_set_value); EXPORT_SYMBOL_GPL(__gpio_set_value);
...@@ -1618,10 +1629,13 @@ EXPORT_SYMBOL_GPL(__gpio_to_irq); ...@@ -1618,10 +1629,13 @@ EXPORT_SYMBOL_GPL(__gpio_to_irq);
int gpio_get_value_cansleep(unsigned gpio) int gpio_get_value_cansleep(unsigned gpio)
{ {
struct gpio_chip *chip; struct gpio_chip *chip;
int value;
might_sleep_if(extra_checks); might_sleep_if(extra_checks);
chip = gpio_to_chip(gpio); chip = gpio_to_chip(gpio);
return chip->get ? chip->get(chip, gpio - chip->base) : 0; value = chip->get ? chip->get(chip, gpio - chip->base) : 0;
trace_gpio_value(gpio, 1, value);
return value;
} }
EXPORT_SYMBOL_GPL(gpio_get_value_cansleep); EXPORT_SYMBOL_GPL(gpio_get_value_cansleep);
...@@ -1631,6 +1645,7 @@ void gpio_set_value_cansleep(unsigned gpio, int value) ...@@ -1631,6 +1645,7 @@ void gpio_set_value_cansleep(unsigned gpio, int value)
might_sleep_if(extra_checks); might_sleep_if(extra_checks);
chip = gpio_to_chip(gpio); chip = gpio_to_chip(gpio);
trace_gpio_value(gpio, 0, value);
chip->set(chip, gpio - chip->base, value); chip->set(chip, gpio - chip->base, value);
} }
EXPORT_SYMBOL_GPL(gpio_set_value_cansleep); EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);
......
...@@ -397,7 +397,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, ...@@ -397,7 +397,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
irq_set_chip_data(irq, chip); irq_set_chip_data(irq, chip);
irq_set_chip_and_handler(irq, &pca953x_irq_chip, irq_set_chip_and_handler(irq, &pca953x_irq_chip,
handle_edge_irq); handle_simple_irq);
#ifdef CONFIG_ARM #ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID); set_irq_flags(irq, IRQF_VALID);
#else #else
......
...@@ -145,7 +145,7 @@ static int via_gpio_get(struct gpio_chip *chip, unsigned int nr) ...@@ -145,7 +145,7 @@ static int via_gpio_get(struct gpio_chip *chip, unsigned int nr)
} }
static struct viafb_gpio_cfg gpio_config = { static struct viafb_gpio_cfg viafb_gpio_config = {
.gpio_chip = { .gpio_chip = {
.label = "VIAFB onboard GPIO", .label = "VIAFB onboard GPIO",
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -183,8 +183,8 @@ static int viafb_gpio_resume(void *private) ...@@ -183,8 +183,8 @@ static int viafb_gpio_resume(void *private)
{ {
int i; int i;
for (i = 0; i < gpio_config.gpio_chip.ngpio; i += 2) for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i += 2)
viafb_gpio_enable(gpio_config.active_gpios[i]); viafb_gpio_enable(viafb_gpio_config.active_gpios[i]);
return 0; return 0;
} }
...@@ -201,9 +201,9 @@ int viafb_gpio_lookup(const char *name) ...@@ -201,9 +201,9 @@ int viafb_gpio_lookup(const char *name)
{ {
int i; int i;
for (i = 0; i < gpio_config.gpio_chip.ngpio; i++) for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i++)
if (!strcmp(name, gpio_config.active_gpios[i]->vg_name)) if (!strcmp(name, viafb_gpio_config.active_gpios[i]->vg_name))
return gpio_config.gpio_chip.base + i; return viafb_gpio_config.gpio_chip.base + i;
return -1; return -1;
} }
EXPORT_SYMBOL_GPL(viafb_gpio_lookup); EXPORT_SYMBOL_GPL(viafb_gpio_lookup);
...@@ -229,14 +229,15 @@ static __devinit int viafb_gpio_probe(struct platform_device *platdev) ...@@ -229,14 +229,15 @@ static __devinit int viafb_gpio_probe(struct platform_device *platdev)
for (gpio = viafb_all_gpios; for (gpio = viafb_all_gpios;
gpio < viafb_all_gpios + VIAFB_NUM_GPIOS; gpio++) gpio < viafb_all_gpios + VIAFB_NUM_GPIOS; gpio++)
if (gpio->vg_port_index == port_cfg[i].ioport_index) { if (gpio->vg_port_index == port_cfg[i].ioport_index) {
gpio_config.active_gpios[ngpio] = gpio; viafb_gpio_config.active_gpios[ngpio] = gpio;
gpio_config.gpio_names[ngpio] = gpio->vg_name; viafb_gpio_config.gpio_names[ngpio] =
gpio->vg_name;
ngpio++; ngpio++;
} }
} }
gpio_config.gpio_chip.ngpio = ngpio; viafb_gpio_config.gpio_chip.ngpio = ngpio;
gpio_config.gpio_chip.names = gpio_config.gpio_names; viafb_gpio_config.gpio_chip.names = viafb_gpio_config.gpio_names;
gpio_config.vdev = vdev; viafb_gpio_config.vdev = vdev;
if (ngpio == 0) { if (ngpio == 0) {
printk(KERN_INFO "viafb: no GPIOs configured\n"); printk(KERN_INFO "viafb: no GPIOs configured\n");
return 0; return 0;
...@@ -245,18 +246,18 @@ static __devinit int viafb_gpio_probe(struct platform_device *platdev) ...@@ -245,18 +246,18 @@ static __devinit int viafb_gpio_probe(struct platform_device *platdev)
* Enable the ports. They come in pairs, with a single * Enable the ports. They come in pairs, with a single
* enable bit for both. * enable bit for both.
*/ */
spin_lock_irqsave(&gpio_config.vdev->reg_lock, flags); spin_lock_irqsave(&viafb_gpio_config.vdev->reg_lock, flags);
for (i = 0; i < ngpio; i += 2) for (i = 0; i < ngpio; i += 2)
viafb_gpio_enable(gpio_config.active_gpios[i]); viafb_gpio_enable(viafb_gpio_config.active_gpios[i]);
spin_unlock_irqrestore(&gpio_config.vdev->reg_lock, flags); spin_unlock_irqrestore(&viafb_gpio_config.vdev->reg_lock, flags);
/* /*
* Get registered. * Get registered.
*/ */
gpio_config.gpio_chip.base = -1; /* Dynamic */ viafb_gpio_config.gpio_chip.base = -1; /* Dynamic */
ret = gpiochip_add(&gpio_config.gpio_chip); ret = gpiochip_add(&viafb_gpio_config.gpio_chip);
if (ret) { if (ret) {
printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret); printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret);
gpio_config.gpio_chip.ngpio = 0; viafb_gpio_config.gpio_chip.ngpio = 0;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
viafb_pm_register(&viafb_gpio_pm_hooks); viafb_pm_register(&viafb_gpio_pm_hooks);
...@@ -277,8 +278,8 @@ static int viafb_gpio_remove(struct platform_device *platdev) ...@@ -277,8 +278,8 @@ static int viafb_gpio_remove(struct platform_device *platdev)
/* /*
* Get unregistered. * Get unregistered.
*/ */
if (gpio_config.gpio_chip.ngpio > 0) { if (viafb_gpio_config.gpio_chip.ngpio > 0) {
ret = gpiochip_remove(&gpio_config.gpio_chip); ret = gpiochip_remove(&viafb_gpio_config.gpio_chip);
if (ret) { /* Somebody still using it? */ if (ret) { /* Somebody still using it? */
printk(KERN_ERR "Viafb: GPIO remove failed\n"); printk(KERN_ERR "Viafb: GPIO remove failed\n");
return ret; return ret;
...@@ -287,11 +288,11 @@ static int viafb_gpio_remove(struct platform_device *platdev) ...@@ -287,11 +288,11 @@ static int viafb_gpio_remove(struct platform_device *platdev)
/* /*
* Disable the ports. * Disable the ports.
*/ */
spin_lock_irqsave(&gpio_config.vdev->reg_lock, flags); spin_lock_irqsave(&viafb_gpio_config.vdev->reg_lock, flags);
for (i = 0; i < gpio_config.gpio_chip.ngpio; i += 2) for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i += 2)
viafb_gpio_disable(gpio_config.active_gpios[i]); viafb_gpio_disable(viafb_gpio_config.active_gpios[i]);
gpio_config.gpio_chip.ngpio = 0; viafb_gpio_config.gpio_chip.ngpio = 0;
spin_unlock_irqrestore(&gpio_config.vdev->reg_lock, flags); spin_unlock_irqrestore(&viafb_gpio_config.vdev->reg_lock, flags);
return ret; return ret;
} }
......
...@@ -13,8 +13,64 @@ ...@@ -13,8 +13,64 @@
#ifndef __BASIC_MMIO_GPIO_H #ifndef __BASIC_MMIO_GPIO_H
#define __BASIC_MMIO_GPIO_H #define __BASIC_MMIO_GPIO_H
#include <linux/gpio.h>
#include <linux/types.h>
#include <linux/compiler.h>
struct bgpio_pdata { struct bgpio_pdata {
int base; int base;
int ngpio;
}; };
struct device;
struct bgpio_chip {
struct gpio_chip gc;
unsigned long (*read_reg)(void __iomem *reg);
void (*write_reg)(void __iomem *reg, unsigned long data);
void __iomem *reg_dat;
void __iomem *reg_set;
void __iomem *reg_clr;
void __iomem *reg_dir;
/* Number of bits (GPIOs): <register width> * 8. */
int bits;
/*
* Some GPIO controllers work with the big-endian bits notation,
* e.g. in a 8-bits register, GPIO7 is the least significant bit.
*/
unsigned long (*pin2mask)(struct bgpio_chip *bgc, unsigned int pin);
/*
* Used to lock bgpio_chip->data. Also, this is needed to keep
* shadowed and real data registers writes together.
*/
spinlock_t lock;
/* Shadowed data register to clear/set bits safely. */
unsigned long data;
/* Shadowed direction registers to clear/set direction safely. */
unsigned long dir;
};
static inline struct bgpio_chip *to_bgpio_chip(struct gpio_chip *gc)
{
return container_of(gc, struct bgpio_chip, gc);
}
int __devexit bgpio_remove(struct bgpio_chip *bgc);
int __devinit bgpio_init(struct bgpio_chip *bgc,
struct device *dev,
unsigned long sz,
void __iomem *dat,
void __iomem *set,
void __iomem *clr,
void __iomem *dirout,
void __iomem *dirin,
bool big_endian);
#endif /* __BASIC_MMIO_GPIO_H */ #endif /* __BASIC_MMIO_GPIO_H */
#undef TRACE_SYSTEM
#define TRACE_SYSTEM gpio
#if !defined(_TRACE_GPIO_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_GPIO_H
#include <linux/tracepoint.h>
TRACE_EVENT(gpio_direction,
TP_PROTO(unsigned gpio, int in, int err),
TP_ARGS(gpio, in, err),
TP_STRUCT__entry(
__field(unsigned, gpio)
__field(int, in)
__field(int, err)
),
TP_fast_assign(
__entry->gpio = gpio;
__entry->in = in;
__entry->err = err;
),
TP_printk("%u %3s (%d)", __entry->gpio,
__entry->in ? "in" : "out", __entry->err)
);
TRACE_EVENT(gpio_value,
TP_PROTO(unsigned gpio, int get, int value),
TP_ARGS(gpio, get, value),
TP_STRUCT__entry(
__field(unsigned, gpio)
__field(int, get)
__field(int, value)
),
TP_fast_assign(
__entry->gpio = gpio;
__entry->get = get;
__entry->value = value;
),
TP_printk("%u %3s %d", __entry->gpio,
__entry->get ? "get" : "set", __entry->value)
);
#endif /* if !defined(_TRACE_GPIO_H) || defined(TRACE_HEADER_MULTI_READ) */
/* This part must be outside protection */
#include <trace/define_trace.h>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment