Skip to content

Commit

Permalink
Merge tag 'gpio-for-v3.7' of git://git.kernel.org/pub/scm/linux/kerne…
Browse files Browse the repository at this point in the history
…l/git/linusw/linux-gpio

Pull GPIO changes from Linus Walleij:
 "So this is the LW GPIO patch stack for v3.7:
   - refactoring from Thierry Redding at Arnd Bergmann's request to use
     the seq_file iterator interface in gpiolib.
   - A new driver for Avionic Design's N-bit GPIO expander.
   - Two instances of mutexes replaced by spinlocks from Axel Lin to
     code that is supposed to be fastpath compliant.
   - IRQ demuxer and gpio_to_irq() support for pcf857x by Kuninori
     Morimoto.
   - Dynamic GPIO numbers, device tree support, daisy chaining and some
     other fixes for the 74x164 driver by Maxime Ripard.
   - IRQ domain and device tree support for the tc3589x driver by Lee
     Jones.
   - Some conversion to use managed resources devm_* code.
   - Some instances of clk_prepare() or clk_prepare_enable() added to
     support the new, stricter common clock framework.
   - Some for_each_set_bit() simplifications.
   - Then a lot of fixes as we fixed up all of the above tripping over
     our own shoelaces and that kind of thing."

* tag 'gpio-for-v3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (34 commits)
  gpio: pcf857x: select IRQ_DOMAIN
  gpio: Document device_node's det_debounce
  gpio-lpc32xx: Add GPI_28
  gpio: adnp: dt: Reference generic interrupt binding
  gpio: Add Avionic Design N-bit GPIO expander support
  gpio: pxa: using for_each_set_bit to simplify the code
  gpio_msm: using for_each_set_bit to simplify the code
  gpio: Enable the tc3298x GPIO expander driver for Device Tree
  gpio: Provide the tc3589x GPIO expander driver with an IRQ domain
  ARM: shmobile: kzm9g: use gpio-keys instead of gpio-keys-polled
  gpio: pcf857x: fixup smatch WARNING
  gpio: 74x164: Add support for the daisy-chaining
  gpio: 74x164: dts: Add documentation for the dt binding
  dt: Fix incorrect reference in gpio-led documentation
  gpio: 74x164: Add device tree support
  gpio: 74x164: Use dynamic gpio number assignment if no pdata is present
  gpio: 74x164: Use devm_kzalloc
  gpio: 74x164: Use module_spi_driver boiler plate function
  gpio: sx150x: Use irq_data_get_irq_chip_data() at appropriate places
  gpio: em: Use irq_data_get_irq_chip_data() at appropriate places
  ...
  • Loading branch information
Linus Torvalds committed Oct 2, 2012
2 parents 916082b + 901acf5 commit dff8360
Show file tree
Hide file tree
Showing 30 changed files with 1,104 additions and 248 deletions.
22 changes: 22 additions & 0 deletions Documentation/devicetree/bindings/gpio/gpio-74x164.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
* Generic 8-bits shift register GPIO driver

Required properties:
- compatible : Should be "fairchild,74hc595"
- reg : chip select number
- gpio-controller : Marks the device node as a gpio controller.
- #gpio-cells : Should be two. The first cell is the pin number and
the second cell is used to specify the gpio polarity:
0 = active high
1 = active low
- registers-number: Number of daisy-chained shift registers

Example:

gpio5: gpio5@0 {
compatible = "fairchild,74hc595";
reg = <0>;
gpio-controller;
#gpio-cells = <2>;
registers-number = <4>;
spi-max-frequency = <100000>;
};
34 changes: 34 additions & 0 deletions Documentation/devicetree/bindings/gpio/gpio-adnp.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Avionic Design N-bit GPIO expander bindings

Required properties:
- compatible: should be "ad,gpio-adnp"
- reg: The I2C slave address for this device.
- interrupt-parent: phandle of the parent interrupt controller.
- interrupts: Interrupt specifier for the controllers interrupt.
- #gpio-cells: Should be 2. The first cell is the GPIO number and the
second cell is used to specify optional parameters:
- bit 0: polarity (0: normal, 1: inverted)
- gpio-controller: Marks the device as a GPIO controller
- nr-gpios: The number of pins supported by the controller.

The GPIO expander can optionally be used as an interrupt controller, in
which case it uses the default two cell specifier as described in
Documentation/devicetree/bindings/interrupt-controller/interrupts.txt.

Example:

gpioext: gpio-controller@41 {
compatible = "ad,gpio-adnp";
reg = <0x41>;

interrupt-parent = <&gpio>;
interrupts = <160 1>;

gpio-controller;
#gpio-cells = <2>;

interrupt-controller;
#interrupt-cells = <2>;

nr-gpios = <64>;
};
2 changes: 1 addition & 1 deletion Documentation/devicetree/bindings/gpio/led.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ node's name represents the name of the corresponding LED.

LED sub-node properties:
- gpios : Should specify the LED's GPIO, see "gpios property" in
Documentation/devicetree/gpio.txt. Active low LEDs should be
Documentation/devicetree/bindings/gpio/gpio.txt. Active low LEDs should be
indicated using flags in the GPIO specifier.
- label : (optional) The label for this LED. If omitted, the label is
taken from the node name (excluding the unit address).
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/configs/kzm9g_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
CONFIG_ARCH_SHMOBILE=y
CONFIG_KEYBOARD_GPIO_POLLED=y
CONFIG_ARCH_SH73A0=y
CONFIG_MACH_KZM9G=y
CONFIG_MEMORY_START=0x41000000
Expand Down Expand Up @@ -71,6 +70,7 @@ CONFIG_INPUT_SPARSEKMAP=y
# CONFIG_INPUT_MOUSEDEV is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_GPIO=y
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ST1232=y
Expand Down
5 changes: 2 additions & 3 deletions arch/arm/mach-shmobile/board-kzm9g.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,12 +482,10 @@ static struct gpio_keys_button gpio_buttons[] = {
static struct gpio_keys_platform_data gpio_key_info = {
.buttons = gpio_buttons,
.nbuttons = ARRAY_SIZE(gpio_buttons),
.poll_interval = 250, /* poling at this point */
};

static struct platform_device gpio_keys_device = {
/* gpio-pcf857x.c driver doesn't support gpio_to_irq() */
.name = "gpio-keys-polled",
.name = "gpio-keys",
.dev = {
.platform_data = &gpio_key_info,
},
Expand Down Expand Up @@ -550,6 +548,7 @@ static struct platform_device fsi_ak4648_device = {
/* I2C */
static struct pcf857x_platform_data pcf8575_pdata = {
.gpio_base = GPIO_PCF8575_BASE,
.irq = intcs_evt2irq(0x3260), /* IRQ19 */
};

static struct i2c_board_info i2c0_devices[] = {
Expand Down
14 changes: 13 additions & 1 deletion drivers/gpio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ config GPIO_GENERIC

config GPIO_DA9052
tristate "Dialog DA9052 GPIO"
depends on PMIC_DA9052 && BROKEN
depends on PMIC_DA9052
help
Say yes here to enable the GPIO driver for the DA9052 chip.

Expand Down Expand Up @@ -330,6 +330,7 @@ config GPIO_PCA953X_IRQ
config GPIO_PCF857X
tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders"
depends on I2C
select IRQ_DOMAIN
help
Say yes here to provide access to most "quasi-bidirectional" I2C
GPIO expanders used for additional digital outputs or inputs.
Expand Down Expand Up @@ -450,6 +451,17 @@ config GPIO_ADP5588_IRQ
Say yes here to enable the adp5588 to be used as an interrupt
controller. It requires the driver to be built in the kernel.

config GPIO_ADNP
tristate "Avionic Design N-bit GPIO expander"
depends on I2C && OF
help
This option enables support for N GPIOs found on Avionic Design
I2C GPIO expanders. The register space will be extended by powers
of two, so the controller will need to accomodate for that. For
example: if a controller provides 48 pins, 6 registers will be
enough to represent all pins, but the driver will assume a
register layout for 64 pins (8 registers).

comment "PCI GPIO expanders:"

config GPIO_CS5535
Expand Down
1 change: 1 addition & 0 deletions drivers/gpio/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o

obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o
obj-$(CONFIG_GPIO_AB8500) += gpio-ab8500.o
obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o
obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
Expand Down
103 changes: 75 additions & 28 deletions drivers/gpio/gpio-74x164.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,18 @@
#include <linux/spi/spi.h>
#include <linux/spi/74x164.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
#include <linux/module.h>

#define GEN_74X164_NUMBER_GPIOS 8

struct gen_74x164_chip {
struct spi_device *spi;
u8 *buffer;
struct gpio_chip gpio_chip;
struct mutex lock;
u8 port_config;
u32 registers;
};

static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc)
Expand All @@ -31,17 +35,47 @@ static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc)

static int __gen_74x164_write_config(struct gen_74x164_chip *chip)
{
return spi_write(chip->spi,
&chip->port_config, sizeof(chip->port_config));
struct spi_message message;
struct spi_transfer *msg_buf;
int i, ret = 0;

msg_buf = kzalloc(chip->registers * sizeof(struct spi_transfer),
GFP_KERNEL);
if (!msg_buf)
return -ENOMEM;

spi_message_init(&message);

/*
* Since the registers are chained, every byte sent will make
* the previous byte shift to the next register in the
* chain. Thus, the first byte send will end up in the last
* register at the end of the transfer. So, to have a logical
* numbering, send the bytes in reverse order so that the last
* byte of the buffer will end up in the last register.
*/
for (i = chip->registers - 1; i >= 0; i--) {
msg_buf[i].tx_buf = chip->buffer +i;
msg_buf[i].len = sizeof(u8);
spi_message_add_tail(msg_buf + i, &message);
}

ret = spi_sync(chip->spi, &message);

kfree(msg_buf);

return ret;
}

static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
{
struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
u8 bank = offset / 8;
u8 pin = offset % 8;
int ret;

mutex_lock(&chip->lock);
ret = (chip->port_config >> offset) & 0x1;
ret = (chip->buffer[bank] >> pin) & 0x1;
mutex_unlock(&chip->lock);

return ret;
Expand All @@ -51,12 +85,14 @@ static void gen_74x164_set_value(struct gpio_chip *gc,
unsigned offset, int val)
{
struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
u8 bank = offset / 8;
u8 pin = offset % 8;

mutex_lock(&chip->lock);
if (val)
chip->port_config |= (1 << offset);
chip->buffer[bank] |= (1 << pin);
else
chip->port_config &= ~(1 << offset);
chip->buffer[bank] &= ~(1 << pin);

__gen_74x164_write_config(chip);
mutex_unlock(&chip->lock);
Expand All @@ -75,9 +111,8 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
struct gen_74x164_chip_platform_data *pdata;
int ret;

pdata = spi->dev.platform_data;
if (!pdata || !pdata->base) {
dev_dbg(&spi->dev, "incorrect or missing platform data\n");
if (!spi->dev.of_node) {
dev_err(&spi->dev, "No device tree data available.\n");
return -EINVAL;
}

Expand All @@ -90,10 +125,16 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
if (ret < 0)
return ret;

chip = kzalloc(sizeof(*chip), GFP_KERNEL);
chip = devm_kzalloc(&spi->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;

pdata = spi->dev.platform_data;
if (pdata && pdata->base)
chip->gpio_chip.base = pdata->base;
else
chip->gpio_chip.base = -1;

mutex_init(&chip->lock);

dev_set_drvdata(&spi->dev, chip);
Expand All @@ -104,8 +145,20 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
chip->gpio_chip.direction_output = gen_74x164_direction_output;
chip->gpio_chip.get = gen_74x164_get_value;
chip->gpio_chip.set = gen_74x164_set_value;
chip->gpio_chip.base = pdata->base;
chip->gpio_chip.ngpio = 8;

if (of_property_read_u32(spi->dev.of_node, "registers-number", &chip->registers)) {
dev_err(&spi->dev, "Missing registers-number property in the DT.\n");
ret = -EINVAL;
goto exit_destroy;
}

chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers;
chip->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL);
if (!chip->buffer) {
ret = -ENOMEM;
goto exit_destroy;
}

chip->gpio_chip.can_sleep = 1;
chip->gpio_chip.dev = &spi->dev;
chip->gpio_chip.owner = THIS_MODULE;
Expand All @@ -125,7 +178,6 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
exit_destroy:
dev_set_drvdata(&spi->dev, NULL);
mutex_destroy(&chip->lock);
kfree(chip);
return ret;
}

Expand All @@ -141,36 +193,31 @@ static int __devexit gen_74x164_remove(struct spi_device *spi)
dev_set_drvdata(&spi->dev, NULL);

ret = gpiochip_remove(&chip->gpio_chip);
if (!ret) {
if (!ret)
mutex_destroy(&chip->lock);
kfree(chip);
} else
else
dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
ret);

return ret;
}

static const struct of_device_id gen_74x164_dt_ids[] = {
{ .compatible = "fairchild,74hc595" },
{},
};
MODULE_DEVICE_TABLE(of, gen_74x164_dt_ids);

static struct spi_driver gen_74x164_driver = {
.driver = {
.name = "74x164",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(gen_74x164_dt_ids),
},
.probe = gen_74x164_probe,
.remove = __devexit_p(gen_74x164_remove),
};

static int __init gen_74x164_init(void)
{
return spi_register_driver(&gen_74x164_driver);
}
subsys_initcall(gen_74x164_init);

static void __exit gen_74x164_exit(void)
{
spi_unregister_driver(&gen_74x164_driver);
}
module_exit(gen_74x164_exit);
module_spi_driver(gen_74x164_driver);

MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>");
Expand Down
Loading

0 comments on commit dff8360

Please sign in to comment.