This is the bulk of GPIO changes for the v3.12 series:

- A new driver for the TZ1090 PDC which is used on the metag
   architecture.
 
 - A new driver for the Kontron ETX or COMexpress GPIO block.
   This is found on some ETX x86 devices.
 
 - A new driver for the Fintek Super-I/O chips, used on
   some x86 boards.
 
 - Added device tree probing on a few select GPIO blocks.
 
 - Drop the Exynos support from the Samsung GPIO driver.
   The Samsung maintainers have moved over to use the
   modernized pin control driver to provide GPIO for the
   modern platforms instead.
 
 - The usual bunch of non-critical fixes and cleanups.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.14 (GNU/Linux)
 
 iQIcBAABAgAGBQJSKZvzAAoJEEEQszewGV1zUg8QAMAqM90/U/0c73fxS28BbN6+
 5bO3a/l9JZYWHyk+739oFZqMUoPDKcq/IOSbirxdgpWE3zcF34ogNfIgSoAL77C5
 3yGa2Lclkxmngo8ZXXeu6DSTq82rlaVjCcHcXw/qd6lVAZT8YaS364vGYpcENPxI
 s1yfrCZy89kZQufX++ytcbIUj75KXHvd9MK9IRE4BVkQMgLXAX/oSbTdB5PhFb79
 J5ls0T1c8JRxI4sj32ZDh6dfeKGsRQF20z6OO5o0ZIyQ+ZGLJPlYatdivJelQz9J
 P67suwn86RXfABISYle2YbNmy3zX+wEyG2nHASDL7hSfWtGpZ5ANJTXqrKjwFITL
 sfqQhMtHDZ7fNbgA0kOyE25kgLybsJZNxR/PJGEHteT1+XZHi2nsP2NTNuxxEKjb
 6NyLXrYXb0VK/poG+ZYXH2tt0C02pg3MfN9y+nfh8reG2bfeLvL/cU7DiQgMUGEf
 DXwgXQdgow9dHus/ZuCuWz4xqAfqk5VRS8ba6Wg2F8uLaXY1qYM6mNeatzTfP3fg
 5jALMy038l7yMBMFnTp8GCb78/iIXWLtEejtgoowBuGbZtOjii8wEExHvl4tCabQ
 PbB9pG8+ojjiQPk2t1ZFFUqX6hCGBFrJbYnJj2vfftBHiFnz5bKrcSBOWVdTWgco
 YqURqegvZVin4aQNGFF2
 =oEK9
 -----END PGP SIGNATURE-----

Merge tag 'gpio-v3.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

Pull GPIO updates from Linus Walleij:
 "This is the bulk of GPIO changes for the v3.12 series:

   - A new driver for the TZ1090 PDC which is used on the metag
     architecture.

   - A new driver for the Kontron ETX or COMexpress GPIO block.  This is
     found on some ETX x86 devices.

   - A new driver for the Fintek Super-I/O chips, used on some x86
     boards.

   - Added device tree probing on a few select GPIO blocks.

   - Drop the Exynos support from the Samsung GPIO driver.

     The Samsung maintainers have moved over to use the modernized pin
     control driver to provide GPIO for the modern platforms instead.

   - The usual bunch of non-critical fixes and cleanups"

* tag 'gpio-v3.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (36 commits)
  gpio: return -ENOTSUPP if debounce cannot be set
  gpio: improve error path in gpiolib
  gpio: add GPIO support for F71882FG and F71889F
  of: add vendor prefix for Microchip Technology Inc
  gpio: mcp23s08: rename the device tree property
  gpio: samsung: Drop support for Exynos SoCs
  gpio: pcf857x: Remove pdata argument to pcf857x_irq_domain_init()
  gpio: pcf857x: Sort headers alphabetically
  gpio: max7301: Reverting "Do not force SPI speed when using OF Platform"
  gpio: Fix bit masking in Kontron PLD GPIO driver
  gpio: pca953x: fix gpio input on gpio offsets >= 8
  drivers/gpio: simplify use of devm_ioremap_resource
  drivers/gpio/gpio-omap.c: convert comma to semicolon
  gpio-lynxpoint: Fix warning about unbalanced pm_runtime_enable
  gpio: Fix platform driver name in Kontron PLD GPIO driver
  gpio: adnp: Fix segfault if request_threaded_irq fails
  gpio: msm: Staticize local variable 'msm_gpio'
  gpio: gpiolib-of.c: make error message more meaningful by adding the node name and index
  gpio: use dev_get_platdata()
  gpio/mxc: add chained_irq_enter/exit() to mx2_gpio_irq_handler
  ...
This commit is contained in:
Linus Torvalds 2013-09-07 10:53:00 -07:00
commit 27c7651a6a
58 changed files with 1967 additions and 1031 deletions

View File

@ -3,10 +3,17 @@ Microchip MCP2308/MCP23S08/MCP23017/MCP23S17 driver for
Required properties:
- compatible : Should be
- "mcp,mcp23s08" for 8 GPIO SPI version
- "mcp,mcp23s17" for 16 GPIO SPI version
- "mcp,mcp23008" for 8 GPIO I2C version or
- "mcp,mcp23017" for 16 GPIO I2C version of the chip
- "mcp,mcp23s08" (DEPRECATED) for 8 GPIO SPI version
- "mcp,mcp23s17" (DEPRECATED) for 16 GPIO SPI version
- "mcp,mcp23008" (DEPRECATED) for 8 GPIO I2C version or
- "mcp,mcp23017" (DEPRECATED) for 16 GPIO I2C version of the chip
- "microchip,mcp23s08" for 8 GPIO SPI version
- "microchip,mcp23s17" for 16 GPIO SPI version
- "microchip,mcp23008" for 8 GPIO I2C version or
- "microchip,mcp23017" for 16 GPIO I2C version of the chip
NOTE: Do not use the old mcp prefix any more. It is deprecated and will be
removed.
- #gpio-cells : Should be two.
- first cell is the pin number
- second cell is used to specify flags. Flags are currently unused.
@ -15,10 +22,11 @@ Required properties:
SPI uses this to specify the chipselect line which the chip is
connected to. The driver and the SPI variant of the chip support
multiple chips on the same chipselect. Have a look at
mcp,spi-present-mask below.
microchip,spi-present-mask below.
Required device specific properties (only for SPI chips):
- mcp,spi-present-mask : This is a present flag, that makes only sense for SPI
- mcp,spi-present-mask (DEPRECATED)
- microchip,spi-present-mask : This is a present flag, that makes only sense for SPI
chips - as the name suggests. Multiple SPI chips can share the same
SPI chipselect. Set a bit in bit0-7 in this mask to 1 if there is a
chip connected with the corresponding spi address set. For example if
@ -26,11 +34,13 @@ Required device specific properties (only for SPI chips):
which is 0x08. mcp23s08 chip variant only supports bits 0-3. It is not
possible to mix mcp23s08 and mcp23s17 on the same chipselect. Set at
least one bit to 1 for SPI chips.
NOTE: Do not use the old mcp prefix any more. It is deprecated and will be
removed.
- spi-max-frequency = The maximum frequency this chip is able to handle
Example I2C:
gpiom1: gpio@20 {
compatible = "mcp,mcp23017";
compatible = "microchip,mcp23017";
gpio-controller;
#gpio-cells = <2>;
reg = <0x20>;
@ -38,7 +48,7 @@ gpiom1: gpio@20 {
Example SPI:
gpiom1: gpio@0 {
compatible = "mcp,mcp23s17";
compatible = "microchip,mcp23s17";
gpio-controller;
#gpio-cells = <2>;
spi-present-mask = <0x01>;

View File

@ -0,0 +1,27 @@
Palmas GPIO controller bindings
Required properties:
- compatible:
- "ti,palams-gpio" for palma series of the GPIO controller
- "ti,tps80036-gpio" for Palma series device TPS80036.
- "ti,tps65913-gpio" for palma series device TPS65913.
- "ti,tps65914-gpio" for palma series device TPS65914.
- #gpio-cells : Should be two.
- first cell is the gpio pin number
- second cell is used to specify the gpio polarity:
0 = active high
1 = active low
- gpio-controller : Marks the device node as a GPIO controller.
Note: This gpio node will be sub node of palmas node.
Example:
palmas: tps65913@58 {
:::::::::::
palmas_gpio: palmas_gpio {
compatible = "ti,palmas-gpio";
gpio-controller;
#gpio-cells = <2>;
};
:::::::::::
};

View File

@ -0,0 +1,45 @@
ImgTec TZ1090 PDC GPIO Controller
Required properties:
- compatible: Compatible property value should be "img,tz1090-pdc-gpio".
- reg: Physical base address of the controller and length of memory mapped
region. This starts at and cover the SOC_GPIO_CONTROL registers.
- gpio-controller: Specifies that the node is a gpio controller.
- #gpio-cells: Should be 2. The syntax of the gpio specifier used by client
nodes should have the following values.
<[phandle of the gpio controller node]
[PDC gpio number]
[gpio flags]>
Values for gpio specifier:
- GPIO number: a value in the range 0 to 6.
- GPIO flags: bit field of flags, as defined in <dt-bindings/gpio/gpio.h>.
Only the following flags are supported:
GPIO_ACTIVE_HIGH
GPIO_ACTIVE_LOW
Optional properties:
- gpio-ranges: Mapping to pin controller pins (as described in
Documentation/devicetree/bindings/gpio/gpio.txt)
- interrupts: Individual syswake interrupts (other GPIOs cannot interrupt)
Example:
pdc_gpios: gpio-controller@02006500 {
gpio-controller;
#gpio-cells = <2>;
compatible = "img,tz1090-pdc-gpio";
reg = <0x02006500 0x100>;
interrupt-parent = <&pdc>;
interrupts = <8 IRQ_TYPE_NONE>, /* Syswake 0 */
<9 IRQ_TYPE_NONE>, /* Syswake 1 */
<10 IRQ_TYPE_NONE>; /* Syswake 2 */
gpio-ranges = <&pdc_pinctrl 0 0 7>;
};

View File

@ -0,0 +1,88 @@
ImgTec TZ1090 GPIO Controller
Required properties:
- compatible: Compatible property value should be "img,tz1090-gpio".
- reg: Physical base address of the controller and length of memory mapped
region.
- #address-cells: Should be 1 (for bank subnodes)
- #size-cells: Should be 0 (for bank subnodes)
- Each bank of GPIOs should have a subnode to represent it.
Bank subnode required properties:
- reg: Index of bank in the range 0 to 2.
- gpio-controller: Specifies that the node is a gpio controller.
- #gpio-cells: Should be 2. The syntax of the gpio specifier used by client
nodes should have the following values.
<[phandle of the gpio controller node]
[gpio number within the gpio bank]
[gpio flags]>
Values for gpio specifier:
- GPIO number: a value in the range 0 to 29.
- GPIO flags: bit field of flags, as defined in <dt-bindings/gpio/gpio.h>.
Only the following flags are supported:
GPIO_ACTIVE_HIGH
GPIO_ACTIVE_LOW
Bank subnode optional properties:
- gpio-ranges: Mapping to pin controller pins (as described in
Documentation/devicetree/bindings/gpio/gpio.txt)
- interrupts: Interrupt for the entire bank
- interrupt-controller: Specifies that the node is an interrupt controller
- #interrupt-cells: Should be 2. The syntax of the interrupt specifier used by
client nodes should have the following values.
<[phandle of the interurupt controller]
[gpio number within the gpio bank]
[irq flags]>
Values for irq specifier:
- GPIO number: a value in the range 0 to 29
- IRQ flags: value to describe edge and level triggering, as defined in
<dt-bindings/interrupt-controller/irq.h>. Only the following flags are
supported:
IRQ_TYPE_EDGE_RISING
IRQ_TYPE_EDGE_FALLING
IRQ_TYPE_EDGE_BOTH
IRQ_TYPE_LEVEL_HIGH
IRQ_TYPE_LEVEL_LOW
Example:
gpios: gpio-controller@02005800 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "img,tz1090-gpio";
reg = <0x02005800 0x90>;
/* bank 0 with an interrupt */
gpios0: bank@0 {
#gpio-cells = <2>;
#interrupt-cells = <2>;
reg = <0>;
interrupts = <13 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
gpio-ranges = <&pinctrl 0 0 30>;
interrupt-controller;
};
/* bank 2 without interrupt */
gpios2: bank@2 {
#gpio-cells = <2>;
reg = <2>;
gpio-controller;
gpio-ranges = <&pinctrl 0 60 30>;
};
};

View File

@ -10,8 +10,9 @@ Required properties:
There're three gpio interrupts in arch-pxa, and they're gpio0,
gpio1 and gpio_mux. There're only one gpio interrupt in arch-mmp,
gpio_mux.
- interrupt-name : Should be the name of irq resource. Each interrupt
binds its interrupt-name.
- interrupt-names : Should be the names of irq resources. Each interrupt
uses its own interrupt name, so there should be as many interrupt names
as referenced interrups.
- interrupt-controller : Identifies the node as an interrupt controller.
- #interrupt-cells: Specifies the number of cells needed to encode an
interrupt source.
@ -24,7 +25,7 @@ Example:
compatible = "marvell,mmp-gpio";
reg = <0xd4019000 0x1000>;
interrupts = <49>;
interrupt-name = "gpio_mux";
interrupt-names = "gpio_mux";
gpio-controller;
#gpio-cells = <1>;
interrupt-controller;

View File

@ -23,6 +23,10 @@ Required Properties:
Please refer to gpio.txt in this directory for details of gpio-ranges property
and the common GPIO bindings used by client devices.
The GPIO controller also acts as an interrupt controller. It uses the default
two cells specifier as described in Documentation/devicetree/bindings/
interrupt-controller/interrupts.txt.
Example: R8A7779 (R-Car H1) GPIO controller nodes
gpio0: gpio@ffc40000 {
@ -33,6 +37,8 @@ Example: R8A7779 (R-Car H1) GPIO controller nodes
#gpio-cells = <2>;
gpio-controller;
gpio-ranges = <&pfc 0 0 32>;
interrupt-controller;
#interrupt-cells = <2>;
};
...
gpio6: gpio@ffc46000 {
@ -43,4 +49,6 @@ Example: R8A7779 (R-Car H1) GPIO controller nodes
#gpio-cells = <2>;
gpio-controller;
gpio-ranges = <&pfc 0 192 9>;
interrupt-controller;
#interrupt-cells = <2>;
};

View File

@ -38,6 +38,7 @@ linux Linux-specific binding
lsi LSI Corp. (LSI Logic)
marvell Marvell Technology Group Ltd.
maxim Maxim Integrated Products
microchip Microchip Technology Inc.
mosaixtech Mosaix Technologies, Inc.
national National Semiconductor
nintendo Nintendo

View File

@ -1320,7 +1320,6 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-vt8500/
F: drivers/clocksource/vt8500_timer.c
F: drivers/gpio/gpio-vt8500.c
F: drivers/i2c/busses/i2c-wmt.c
F: drivers/mmc/host/wmt-sdmmc.c
F: drivers/pwm/pwm-vt8500.c

View File

@ -146,6 +146,16 @@ config GPIO_MM_LANTIQ
(EBU) found on Lantiq SoCs. The gpios are output only as they are
created by attaching a 16bit latch to the bus.
config GPIO_F7188X
tristate "F71882FG and F71889F GPIO support"
depends on X86
help
This option enables support for GPIOs found on Fintek Super-I/O
chips F71882FG and F71889F.
To compile this driver as a module, choose M here: the module will
be called f7188x-gpio.
config GPIO_MPC5200
def_bool y
depends on PPC_MPC52xx
@ -242,6 +252,21 @@ config GPIO_TS5500
blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600
LCD port.
config GPIO_TZ1090
bool "Toumaz Xenif TZ1090 GPIO support"
depends on SOC_TZ1090
select GENERIC_IRQ_CHIP
default y
help
Say yes here to support Toumaz Xenif TZ1090 GPIOs.
config GPIO_TZ1090_PDC
bool "Toumaz Xenif TZ1090 PDC GPIO support"
depends on SOC_TZ1090
default y
help
Say yes here to support Toumaz Xenif TZ1090 PDC GPIOs.
config GPIO_XILINX
bool "Xilinx GPIO support"
depends on PPC_OF || MICROBLAZE || ARCH_ZYNQ
@ -676,6 +701,18 @@ config GPIO_UCB1400
This enables support for the Philips UCB1400 GPIO pins.
The UCB1400 is an AC97 audio codec.
comment "LPC GPIO expanders:"
config GPIO_KEMPLD
tristate "Kontron ETX / COMexpress GPIO"
depends on MFD_KEMPLD
help
This enables support for the PLD GPIO interface on some Kontron ETX
and COMexpress (ETXexpress) modules.
This driver can also be built as a module. If so, the module will be
called gpio-kempld.
comment "MODULbus GPIO expanders:"
config GPIO_JANZ_TTL

View File

@ -24,11 +24,13 @@ obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o
obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o
obj-$(CONFIG_GPIO_EM) += gpio-em.o
obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o
obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o
obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o
obj-$(CONFIG_GPIO_LANGWELL) += gpio-langwell.o
obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o
@ -79,6 +81,8 @@ obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o
obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o
obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o
obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o
obj-$(CONFIG_GPIO_TZ1090) += gpio-tz1090.o
obj-$(CONFIG_GPIO_TZ1090_PDC) += gpio-tz1090-pdc.o
obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o
obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o
obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o

View File

@ -129,7 +129,7 @@ static int gen_74x164_probe(struct spi_device *spi)
if (!chip)
return -ENOMEM;
pdata = spi->dev.platform_data;
pdata = dev_get_platdata(&spi->dev);
if (pdata && pdata->base)
chip->gpio_chip.base = pdata->base;
else

View File

@ -490,15 +490,11 @@ static int adnp_irq_setup(struct adnp *adnp)
if (err != 0) {
dev_err(chip->dev, "can't request IRQ#%d: %d\n",
adnp->client->irq, err);
goto error;
return err;
}
chip->to_irq = adnp_gpio_to_irq;
return 0;
error:
irq_domain_remove(adnp->domain);
return err;
}
static void adnp_irq_teardown(struct adnp *adnp)

View File

@ -89,7 +89,7 @@ static int adp5520_gpio_direction_output(struct gpio_chip *chip,
static int adp5520_gpio_probe(struct platform_device *pdev)
{
struct adp5520_gpio_platform_data *pdata = pdev->dev.platform_data;
struct adp5520_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct adp5520_gpio *dev;
struct gpio_chip *gc;
int ret, i, gpios;

View File

@ -276,7 +276,8 @@ static irqreturn_t adp5588_irq_handler(int irq, void *devid)
static int adp5588_irq_setup(struct adp5588_gpio *dev)
{
struct i2c_client *client = dev->client;
struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
struct adp5588_gpio_platform_data *pdata =
dev_get_platdata(&client->dev);
unsigned gpio;
int ret;
@ -349,7 +350,8 @@ static void adp5588_irq_teardown(struct adp5588_gpio *dev)
static int adp5588_gpio_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
struct adp5588_gpio_platform_data *pdata =
dev_get_platdata(&client->dev);
struct adp5588_gpio *dev;
struct gpio_chip *gc;
int ret, i, revid;
@ -440,7 +442,8 @@ static int adp5588_gpio_probe(struct i2c_client *client,
static int adp5588_gpio_remove(struct i2c_client *client)
{
struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
struct adp5588_gpio_platform_data *pdata =
dev_get_platdata(&client->dev);
struct adp5588_gpio *dev = i2c_get_clientdata(client);
int ret;

View File

@ -97,7 +97,7 @@ static struct gpio_chip template_chip = {
static int arizona_gpio_probe(struct platform_device *pdev)
{
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
struct arizona_pdata *pdata = arizona->dev->platform_data;
struct arizona_pdata *pdata = dev_get_platdata(arizona->dev);
struct arizona_gpio *arizona_gpio;
int ret;

View File

@ -216,7 +216,7 @@ static int da9052_gpio_probe(struct platform_device *pdev)
return -ENOMEM;
gpio->da9052 = dev_get_drvdata(pdev->dev.parent);
pdata = gpio->da9052->dev->platform_data;
pdata = dev_get_platdata(gpio->da9052->dev);
gpio->gp = reference_gp;
if (pdata && pdata->gpio_base)

View File

@ -150,7 +150,7 @@ static int da9055_gpio_probe(struct platform_device *pdev)
return -ENOMEM;
gpio->da9055 = dev_get_drvdata(pdev->dev.parent);
pdata = gpio->da9055->dev->platform_data;
pdata = dev_get_platdata(gpio->da9055->dev);
gpio->gp = reference_gp;
if (pdata && pdata->gpio_base)

View File

@ -30,6 +30,7 @@
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_data/gpio-em.h>
struct em_gio_priv {
@ -216,6 +217,21 @@ static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset)
return irq_create_mapping(gpio_to_priv(chip)->irq_domain, offset);
}
static int em_gio_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void em_gio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(chip->base + offset);
/* Set the GPIO as an input to ensure that the next GPIO request won't
* drive the GPIO pin as an output.
*/
em_gio_direction_input(chip, offset);
}
static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
@ -237,7 +253,7 @@ static struct irq_domain_ops em_gio_irq_domain_ops = {
static int em_gio_probe(struct platform_device *pdev)
{
struct gpio_em_config pdata_dt;
struct gpio_em_config *pdata = pdev->dev.platform_data;
struct gpio_em_config *pdata = dev_get_platdata(&pdev->dev);
struct em_gio_priv *p;
struct resource *io[2], *irq[2];
struct gpio_chip *gpio_chip;
@ -308,6 +324,8 @@ static int em_gio_probe(struct platform_device *pdev)
gpio_chip->direction_output = em_gio_direction_output;
gpio_chip->set = em_gio_set;
gpio_chip->to_irq = em_gio_to_irq;
gpio_chip->request = em_gio_request;
gpio_chip->free = em_gio_free;
gpio_chip->label = name;
gpio_chip->owner = THIS_MODULE;
gpio_chip->base = pdata->gpio_base;
@ -351,6 +369,13 @@ static int em_gio_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to add GPIO controller\n");
goto err1;
}
if (pdata->pctl_name) {
ret = gpiochip_add_pin_range(gpio_chip, pdata->pctl_name, 0,
gpio_chip->base, gpio_chip->ngpio);
if (ret < 0)
dev_warn(&pdev->dev, "failed to add pin range\n");
}
return 0;
err1:

469
drivers/gpio/gpio-f7188x.c Normal file
View File

@ -0,0 +1,469 @@
/*
* GPIO driver for Fintek Super-I/O F71882 and F71889
*
* Copyright (C) 2010-2013 LaCie
*
* Author: Simon Guinot <simon.guinot@sequanux.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio.h>
#define DRVNAME "gpio-f7188x"
/*
* Super-I/O registers
*/
#define SIO_LDSEL 0x07 /* Logical device select */
#define SIO_DEVID 0x20 /* Device ID (2 bytes) */
#define SIO_DEVREV 0x22 /* Device revision */
#define SIO_MANID 0x23 /* Fintek ID (2 bytes) */
#define SIO_LD_GPIO 0x06 /* GPIO logical device */
#define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */
#define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */
#define SIO_FINTEK_ID 0x1934 /* Manufacturer ID */
#define SIO_F71882_ID 0x0541 /* F71882 chipset ID */
#define SIO_F71889_ID 0x0909 /* F71889 chipset ID */
enum chips { f71882fg, f71889f };
static const char * const f7188x_names[] = {
"f71882fg",
"f71889f",
};
struct f7188x_sio {
int addr;
enum chips type;
};
struct f7188x_gpio_bank {
struct gpio_chip chip;
unsigned int regbase;
struct f7188x_gpio_data *data;
};
struct f7188x_gpio_data {
struct f7188x_sio *sio;
int nr_bank;
struct f7188x_gpio_bank *bank;
};
/*
* Super-I/O functions.
*/
static inline int superio_inb(int base, int reg)
{
outb(reg, base);
return inb(base + 1);
}
static int superio_inw(int base, int reg)
{
int val;
outb(reg++, base);
val = inb(base + 1) << 8;
outb(reg, base);
val |= inb(base + 1);
return val;
}
static inline void superio_outb(int base, int reg, int val)
{
outb(reg, base);
outb(val, base + 1);
}
static inline int superio_enter(int base)
{
/* Don't step on other drivers' I/O space by accident. */
if (!request_muxed_region(base, 2, DRVNAME)) {
pr_err(DRVNAME "I/O address 0x%04x already in use\n", base);
return -EBUSY;
}
/* According to the datasheet the key must be send twice. */
outb(SIO_UNLOCK_KEY, base);
outb(SIO_UNLOCK_KEY, base);
return 0;
}
static inline void superio_select(int base, int ld)
{
outb(SIO_LDSEL, base);
outb(ld, base + 1);
}
static inline void superio_exit(int base)
{
outb(SIO_LOCK_KEY, base);
release_region(base, 2);
}
/*
* GPIO chip.
*/
static int f7188x_gpio_direction_in(struct gpio_chip *chip, unsigned offset);
static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset);
static int f7188x_gpio_direction_out(struct gpio_chip *chip,
unsigned offset, int value);
static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value);
#define F7188X_GPIO_BANK(_base, _ngpio, _regbase) \
{ \
.chip = { \
.label = DRVNAME, \
.owner = THIS_MODULE, \
.direction_input = f7188x_gpio_direction_in, \
.get = f7188x_gpio_get, \
.direction_output = f7188x_gpio_direction_out, \
.set = f7188x_gpio_set, \
.base = _base, \
.ngpio = _ngpio, \
}, \
.regbase = _regbase, \
}
#define gpio_dir(base) (base + 0)
#define gpio_data_out(base) (base + 1)
#define gpio_data_in(base) (base + 2)
/* Output mode register (0:open drain 1:push-pull). */
#define gpio_out_mode(base) (base + 3)
static struct f7188x_gpio_bank f71882_gpio_bank[] = {
F7188X_GPIO_BANK(0 , 8, 0xF0),
F7188X_GPIO_BANK(10, 8, 0xE0),
F7188X_GPIO_BANK(20, 8, 0xD0),
F7188X_GPIO_BANK(30, 4, 0xC0),
F7188X_GPIO_BANK(40, 4, 0xB0),
};
static struct f7188x_gpio_bank f71889_gpio_bank[] = {
F7188X_GPIO_BANK(0 , 7, 0xF0),
F7188X_GPIO_BANK(10, 7, 0xE0),
F7188X_GPIO_BANK(20, 8, 0xD0),
F7188X_GPIO_BANK(30, 8, 0xC0),
F7188X_GPIO_BANK(40, 8, 0xB0),
F7188X_GPIO_BANK(50, 5, 0xA0),
F7188X_GPIO_BANK(60, 8, 0x90),
F7188X_GPIO_BANK(70, 8, 0x80),
};
static int f7188x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
{
int err;
struct f7188x_gpio_bank *bank =
container_of(chip, struct f7188x_gpio_bank, chip);
struct f7188x_sio *sio = bank->data->sio;
u8 dir;
err = superio_enter(sio->addr);
if (err)
return err;
superio_select(sio->addr, SIO_LD_GPIO);
dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
dir &= ~(1 << offset);
superio_outb(sio->addr, gpio_dir(bank->regbase), dir);
superio_exit(sio->addr);
return 0;
}
static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset)
{
int err;
struct f7188x_gpio_bank *bank =
container_of(chip, struct f7188x_gpio_bank, chip);
struct f7188x_sio *sio = bank->data->sio;
u8 dir, data;
err = superio_enter(sio->addr);
if (err)
return err;
superio_select(sio->addr, SIO_LD_GPIO);
dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
dir = !!(dir & (1 << offset));
if (dir)
data = superio_inb(sio->addr, gpio_data_out(bank->regbase));
else
data = superio_inb(sio->addr, gpio_data_in(bank->regbase));
superio_exit(sio->addr);
return !!(data & 1 << offset);
}
static int f7188x_gpio_direction_out(struct gpio_chip *chip,
unsigned offset, int value)
{
int err;
struct f7188x_gpio_bank *bank =
container_of(chip, struct f7188x_gpio_bank, chip);
struct f7188x_sio *sio = bank->data->sio;
u8 dir, data_out;
err = superio_enter(sio->addr);
if (err)
return err;
superio_select(sio->addr, SIO_LD_GPIO);
data_out = superio_inb(sio->addr, gpio_data_out(bank->regbase));
if (value)
data_out |= (1 << offset);
else
data_out &= ~(1 << offset);
superio_outb(sio->addr, gpio_data_out(bank->regbase), data_out);
dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
dir |= (1 << offset);
superio_outb(sio->addr, gpio_dir(bank->regbase), dir);
superio_exit(sio->addr);
return 0;
}
static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
int err;
struct f7188x_gpio_bank *bank =
container_of(chip, struct f7188x_gpio_bank, chip);
struct f7188x_sio *sio = bank->data->sio;
u8 data_out;
err = superio_enter(sio->addr);
if (err)
return;
superio_select(sio->addr, SIO_LD_GPIO);
data_out = superio_inb(sio->addr, gpio_data_out(bank->regbase));
if (value)
data_out |= (1 << offset);
else
data_out &= ~(1 << offset);
superio_outb(sio->addr, gpio_data_out(bank->regbase), data_out);
superio_exit(sio->addr);
}
/*
* Platform device and driver.
*/
static int f7188x_gpio_probe(struct platform_device *pdev)
{
int err;
int i;
struct f7188x_sio *sio = pdev->dev.platform_data;
struct f7188x_gpio_data *data;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
switch (sio->type) {
case f71882fg:
data->nr_bank = ARRAY_SIZE(f71882_gpio_bank);
data->bank = f71882_gpio_bank;
break;
case f71889f:
data->nr_bank = ARRAY_SIZE(f71889_gpio_bank);
data->bank = f71889_gpio_bank;
break;
default:
return -ENODEV;
}
data->sio = sio;
platform_set_drvdata(pdev, data);
/* For each GPIO bank, register a GPIO chip. */
for (i = 0; i < data->nr_bank; i++) {
struct f7188x_gpio_bank *bank = &data->bank[i];
bank->chip.dev = &pdev->dev;
bank->data = data;
err = gpiochip_add(&bank->chip);
if (err) {
dev_err(&pdev->dev,
"Failed to register gpiochip %d: %d\n",
i, err);
goto err_gpiochip;
}
}
return 0;
err_gpiochip:
for (i = i - 1; i >= 0; i--) {
struct f7188x_gpio_bank *bank = &data->bank[i];
int tmp;
tmp = gpiochip_remove(&bank->chip);
if (tmp < 0)
dev_err(&pdev->dev,
"Failed to remove gpiochip %d: %d\n",
i, tmp);
}
return err;
}
static int f7188x_gpio_remove(struct platform_device *pdev)
{
int err;
int i;
struct f7188x_gpio_data *data = platform_get_drvdata(pdev);
for (i = 0; i < data->nr_bank; i++) {
struct f7188x_gpio_bank *bank = &data->bank[i];
err = gpiochip_remove(&bank->chip);
if (err) {
dev_err(&pdev->dev,
"Failed to remove GPIO gpiochip %d: %d\n",
i, err);
return err;
}
}
return 0;
}
static int __init f7188x_find(int addr, struct f7188x_sio *sio)
{
int err;
u16 devid;
err = superio_enter(addr);
if (err)
return err;
err = -ENODEV;
devid = superio_inw(addr, SIO_MANID);
if (devid != SIO_FINTEK_ID) {
pr_debug(DRVNAME ": Not a Fintek device at 0x%08x\n", addr);
goto err;
}
devid = superio_inw(addr, SIO_DEVID);
switch (devid) {
case SIO_F71882_ID:
sio->type = f71882fg;
break;
case SIO_F71889_ID:
sio->type = f71889f;
break;
default:
pr_info(DRVNAME ": Unsupported Fintek device 0x%04x\n", devid);
goto err;
}
sio->addr = addr;
err = 0;
pr_info(DRVNAME ": Found %s at %#x, revision %d\n",
f7188x_names[sio->type],
(unsigned int) addr,
(int) superio_inb(addr, SIO_DEVREV));
err:
superio_exit(addr);
return err;
}
static struct platform_device *f7188x_gpio_pdev;
static int __init
f7188x_gpio_device_add(const struct f7188x_sio *sio)
{
int err;
f7188x_gpio_pdev = platform_device_alloc(DRVNAME, -1);
if (!f7188x_gpio_pdev)
return -ENOMEM;
err = platform_device_add_data(f7188x_gpio_pdev,
sio, sizeof(*sio));
if (err) {
pr_err(DRVNAME "Platform data allocation failed\n");
goto err;
}
err = platform_device_add(f7188x_gpio_pdev);
if (err) {
pr_err(DRVNAME "Device addition failed\n");
goto err;
}
return 0;
err:
platform_device_put(f7188x_gpio_pdev);
return err;
}
/*
* Try to match a supported Fintech device by reading the (hard-wired)
* configuration I/O ports. If available, then register both the platform
* device and driver to support the GPIOs.
*/
static struct platform_driver f7188x_gpio_driver = {
.driver = {
.owner = THIS_MODULE,
.name = DRVNAME,
},
.probe = f7188x_gpio_probe,
.remove = f7188x_gpio_remove,
};
static int __init f7188x_gpio_init(void)
{
int err;
struct f7188x_sio sio;
if (f7188x_find(0x2e, &sio) &&
f7188x_find(0x4e, &sio))
return -ENODEV;
err = platform_driver_register(&f7188x_gpio_driver);
if (!err) {
err = f7188x_gpio_device_add(&sio);
if (err)
platform_driver_unregister(&f7188x_gpio_driver);
}
return err;
}
subsys_initcall(f7188x_gpio_init);
static void __exit f7188x_gpio_exit(void)
{
platform_device_unregister(f7188x_gpio_pdev);
platform_driver_unregister(&f7188x_gpio_driver);
}
module_exit(f7188x_gpio_exit);
MODULE_DESCRIPTION("GPIO driver for Super-I/O chips F71882FG and F71889F");
MODULE_AUTHOR("Simon Guinot <simon.guinot@sequanux.org>");
MODULE_LICENSE("GPL");

View File

@ -354,7 +354,7 @@ static int ichx_gpio_probe(struct platform_device *pdev)
{
struct resource *res_base, *res_pm;
int err;
struct lpc_ich_info *ich_info = pdev->dev.platform_data;
struct lpc_ich_info *ich_info = dev_get_platdata(&pdev->dev);
if (!ich_info)
return -ENODEV;

View File

@ -149,7 +149,7 @@ static int ttl_probe(struct platform_device *pdev)
struct resource *res;
int ret;
pdata = pdev->dev.platform_data;
pdata = dev_get_platdata(&pdev->dev);
if (!pdata) {
dev_err(dev, "no platform data\n");
ret = -ENXIO;

219
drivers/gpio/gpio-kempld.c Normal file
View File

@ -0,0 +1,219 @@
/*
* Kontron PLD GPIO driver
*
* Copyright (c) 2010-2013 Kontron Europe GmbH
* Author: Michael Brunner <michael.brunner@kontron.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 2 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/bitops.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/mfd/kempld.h>
#define KEMPLD_GPIO_MAX_NUM 16
#define KEMPLD_GPIO_MASK(x) (1 << ((x) % 8))
#define KEMPLD_GPIO_DIR_NUM(x) (0x40 + (x) / 8)
#define KEMPLD_GPIO_LVL_NUM(x) (0x42 + (x) / 8)
#define KEMPLD_GPIO_EVT_LVL_EDGE 0x46
#define KEMPLD_GPIO_IEN 0x4A
struct kempld_gpio_data {
struct gpio_chip chip;
struct kempld_device_data *pld;
};
/*
* Set or clear GPIO bit
* kempld_get_mutex must be called prior to calling this function.
*/
static void kempld_gpio_bitop(struct kempld_device_data *pld,
u8 reg, u8 bit, u8 val)
{
u8 status;
status = kempld_read8(pld, reg);
if (val)
status |= KEMPLD_GPIO_MASK(bit);
else
status &= ~KEMPLD_GPIO_MASK(bit);
kempld_write8(pld, reg, status);
}
static int kempld_gpio_get_bit(struct kempld_device_data *pld, u8 reg, u8 bit)
{
u8 status;
kempld_get_mutex(pld);
status = kempld_read8(pld, reg);
kempld_release_mutex(pld);
return !!(status & KEMPLD_GPIO_MASK(bit));
}
static int kempld_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct kempld_gpio_data *gpio
= container_of(chip, struct kempld_gpio_data, chip);
struct kempld_device_data *pld = gpio->pld;
return kempld_gpio_get_bit(pld, KEMPLD_GPIO_LVL_NUM(offset), offset);
}
static void kempld_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct kempld_gpio_data *gpio
= container_of(chip, struct kempld_gpio_data, chip);
struct kempld_device_data *pld = gpio->pld;
kempld_get_mutex(pld);
kempld_gpio_bitop(pld, KEMPLD_GPIO_LVL_NUM(offset), offset, value);
kempld_release_mutex(pld);
}
static int kempld_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
struct kempld_gpio_data *gpio
= container_of(chip, struct kempld_gpio_data, chip);
struct kempld_device_data *pld = gpio->pld;
kempld_get_mutex(pld);
kempld_gpio_bitop(pld, KEMPLD_GPIO_DIR_NUM(offset), offset, 0);
kempld_release_mutex(pld);
return 0;
}
static int kempld_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
int value)
{
struct kempld_gpio_data *gpio
= container_of(chip, struct kempld_gpio_data, chip);
struct kempld_device_data *pld = gpio->pld;
kempld_get_mutex(pld);
kempld_gpio_bitop(pld, KEMPLD_GPIO_LVL_NUM(offset), offset, value);
kempld_gpio_bitop(pld, KEMPLD_GPIO_DIR_NUM(offset), offset, 1);
kempld_release_mutex(pld);
return 0;
}
static int kempld_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
struct kempld_gpio_data *gpio
= container_of(chip, struct kempld_gpio_data, chip);
struct kempld_device_data *pld = gpio->pld;
return kempld_gpio_get_bit(pld, KEMPLD_GPIO_DIR_NUM(offset), offset);
}
static int kempld_gpio_pincount(struct kempld_device_data *pld)
{
u16 evt, evt_back;
kempld_get_mutex(pld);
/* Backup event register as it might be already initialized */
evt_back = kempld_read16(pld, KEMPLD_GPIO_EVT_LVL_EDGE);
/* Clear event register */
kempld_write16(pld, KEMPLD_GPIO_EVT_LVL_EDGE, 0x0000);
/* Read back event register */
evt = kempld_read16(pld, KEMPLD_GPIO_EVT_LVL_EDGE);
/* Restore event register */
kempld_write16(pld, KEMPLD_GPIO_EVT_LVL_EDGE, evt_back);
kempld_release_mutex(pld);
return evt ? __ffs(evt) : 16;
}
static int kempld_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct kempld_device_data *pld = dev_get_drvdata(dev->parent);
struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
struct kempld_gpio_data *gpio;
struct gpio_chip *chip;
int ret;
if (pld->info.spec_major < 2) {
dev_err(dev,
"Driver only supports GPIO devices compatible to PLD spec. rev. 2.0 or higher\n");
return -ENODEV;
}
gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL);
if (gpio == NULL)
return -ENOMEM;
gpio->pld = pld;
platform_set_drvdata(pdev, gpio);
chip = &gpio->chip;
chip->label = "gpio-kempld";
chip->owner = THIS_MODULE;
chip->dev = dev;
chip->can_sleep = 1;
if (pdata && pdata->gpio_base)
chip->base = pdata->gpio_base;
else
chip->base = -1;
chip->direction_input = kempld_gpio_direction_input;
chip->direction_output = kempld_gpio_direction_output;
chip->get_direction = kempld_gpio_get_direction;
chip->get = kempld_gpio_get;
chip->set = kempld_gpio_set;
chip->ngpio = kempld_gpio_pincount(pld);
if (chip->ngpio == 0) {
dev_err(dev, "No GPIO pins detected\n");
return -ENODEV;
}
ret = gpiochip_add(chip);
if (ret) {
dev_err(dev, "Could not register GPIO chip\n");
return ret;
}
dev_info(dev, "GPIO functionality initialized with %d pins\n",
chip->ngpio);
return 0;
}
static int kempld_gpio_remove(struct platform_device *pdev)
{
struct kempld_gpio_data *gpio = platform_get_drvdata(pdev);
return gpiochip_remove(&gpio->chip);
}
static struct platform_driver kempld_gpio_driver = {
.driver = {
.name = "kempld-gpio",
.owner = THIS_MODULE,
},
.probe = kempld_gpio_probe,
.remove = kempld_gpio_remove,
};
module_platform_driver(kempld_gpio_driver);
MODULE_DESCRIPTION("KEM PLD GPIO Driver");
MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:gpio-kempld");

View File

@ -444,6 +444,7 @@ static int lp_gpio_remove(struct platform_device *pdev)
{
struct lp_gpio *lg = platform_get_drvdata(pdev);
int err;
pm_runtime_disable(&pdev->dev);
err = gpiochip_remove(&lg->chip);
if (err)
dev_warn(&pdev->dev, "failed to remove gpio_chip.\n");

View File

@ -56,8 +56,7 @@ static int max7301_probe(struct spi_device *spi)
int ret;
/* bits_per_word cannot be configured in platform data */
if (spi->dev.platform_data)
spi->bits_per_word = 16;
spi->bits_per_word = 16;
ret = spi_setup(spi);
if (ret < 0)
return ret;

View File

@ -166,7 +166,7 @@ int __max730x_probe(struct max7301 *ts)
struct max7301_platform_data *pdata;
int i, ret;
pdata = dev->platform_data;
pdata = dev_get_platdata(dev);
mutex_init(&ts->lock);
dev_set_drvdata(dev, ts);

View File

@ -453,7 +453,7 @@ static int max732x_irq_setup(struct max732x_chip *chip,
const struct i2c_device_id *id)
{
struct i2c_client *client = chip->client;
struct max732x_platform_data *pdata = client->dev.platform_data;
struct max732x_platform_data *pdata = dev_get_platdata(&client->dev);
int has_irq = max732x_features[id->driver_data] >> 32;
int ret;
@ -512,7 +512,7 @@ static int max732x_irq_setup(struct max732x_chip *chip,
const struct i2c_device_id *id)
{
struct i2c_client *client = chip->client;
struct max732x_platform_data *pdata = client->dev.platform_data;
struct max732x_platform_data *pdata = dev_get_platdata(&client->dev);
int has_irq = max732x_features[id->driver_data] >> 32;
if (pdata->irq_base && has_irq != INT_NONE)
@ -583,7 +583,7 @@ static int max732x_probe(struct i2c_client *client,
uint16_t addr_a, addr_b;
int ret, nr_port;
pdata = client->dev.platform_data;
pdata = dev_get_platdata(&client->dev);
if (pdata == NULL) {
dev_dbg(&client->dev, "no platform data\n");
return -EINVAL;
@ -653,7 +653,7 @@ static int max732x_probe(struct i2c_client *client,
static int max732x_remove(struct i2c_client *client)
{
struct max732x_platform_data *pdata = client->dev.platform_data;
struct max732x_platform_data *pdata = dev_get_platdata(&client->dev);
struct max732x_chip *chip = i2c_get_clientdata(client);
int ret;

View File

@ -86,7 +86,7 @@ static int mc33880_probe(struct spi_device *spi)
struct mc33880_platform_data *pdata;
int ret;
pdata = spi->dev.platform_data;
pdata = dev_get_platdata(&spi->dev);
if (!pdata || !pdata->base) {
dev_dbg(&spi->dev, "incorrect or missing platform data\n");
return -EINVAL;

View File

@ -483,10 +483,21 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
#ifdef CONFIG_SPI_MASTER
static struct of_device_id mcp23s08_spi_of_match[] = {
{
.compatible = "mcp,mcp23s08", .data = (void *) MCP_TYPE_S08,
.compatible = "microchip,mcp23s08",
.data = (void *) MCP_TYPE_S08,
},
{
.compatible = "mcp,mcp23s17", .data = (void *) MCP_TYPE_S17,
.compatible = "microchip,mcp23s17",
.data = (void *) MCP_TYPE_S17,
},
/* NOTE: The use of the mcp prefix is deprecated and will be removed. */
{
.compatible = "mcp,mcp23s08",
.data = (void *) MCP_TYPE_S08,
},
{
.compatible = "mcp,mcp23s17",
.data = (void *) MCP_TYPE_S17,
},
{ },
};
@ -496,10 +507,21 @@ MODULE_DEVICE_TABLE(of, mcp23s08_spi_of_match);
#if IS_ENABLED(CONFIG_I2C)
static struct of_device_id mcp23s08_i2c_of_match[] = {
{
.compatible = "mcp,mcp23008", .data = (void *) MCP_TYPE_008,
.compatible = "microchip,mcp23008",
.data = (void *) MCP_TYPE_008,
},
{
.compatible = "mcp,mcp23017", .data = (void *) MCP_TYPE_017,
.compatible = "microchip,mcp23017",
.data = (void *) MCP_TYPE_017,
},
/* NOTE: The use of the mcp prefix is deprecated and will be removed. */
{
.compatible = "mcp,mcp23008",
.data = (void *) MCP_TYPE_008,
},
{
.compatible = "mcp,mcp23017",
.data = (void *) MCP_TYPE_017,
},
{ },
};
@ -520,14 +542,13 @@ static int mcp230xx_probe(struct i2c_client *client,
match = of_match_device(of_match_ptr(mcp23s08_i2c_of_match),
&client->dev);
if (match) {
pdata = dev_get_platdata(&client->dev);
if (match || !pdata) {
base = -1;
pullups = 0;
} else {
pdata = client->dev.platform_data;
if (!pdata || !gpio_is_valid(pdata->base)) {
dev_dbg(&client->dev,
"invalid or missing platform data\n");
if (!gpio_is_valid(pdata->base)) {
dev_dbg(&client->dev, "invalid platform data\n");
return -EINVAL;
}
base = pdata->base;
@ -621,10 +642,15 @@ static int mcp23s08_probe(struct spi_device *spi)
if (match) {
type = (int)match->data;
status = of_property_read_u32(spi->dev.of_node,
"mcp,spi-present-mask", &spi_present_mask);
"microchip,spi-present-mask", &spi_present_mask);
if (status) {
dev_err(&spi->dev, "DT has no spi-present-mask\n");
return -ENODEV;
status = of_property_read_u32(spi->dev.of_node,
"mcp,spi-present-mask", &spi_present_mask);
if (status) {
dev_err(&spi->dev,
"DT has no spi-present-mask\n");
return -ENODEV;
}
}
if ((spi_present_mask <= 0) || (spi_present_mask >= 256)) {
dev_err(&spi->dev, "invalid spi-present-mask\n");
@ -635,7 +661,7 @@ static int mcp23s08_probe(struct spi_device *spi)
pullups[addr] = 0;
} else {
type = spi_get_device_id(spi)->driver_data;
pdata = spi->dev.platform_data;
pdata = dev_get_platdata(&spi->dev);
if (!pdata || !gpio_is_valid(pdata->base)) {
dev_dbg(&spi->dev,
"invalid or missing platform data\n");

View File

@ -259,7 +259,7 @@ static void msic_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
static int platform_msic_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct intel_msic_gpio_pdata *pdata = dev->platform_data;
struct intel_msic_gpio_pdata *pdata = dev_get_platdata(dev);
struct msic_gpio *mg;
int irq = platform_get_irq(pdev, 0);
int retval;

View File

@ -106,7 +106,7 @@ struct msm_gpio_dev {
void __iomem *msm_tlmm_base;
};
struct msm_gpio_dev msm_gpio;
static struct msm_gpio_dev msm_gpio;
#define GPIO_INTR_CFG_SU(gpio) (msm_gpio.msm_tlmm_base + 0x0400 + \
(0x04 * (gpio)))

View File

@ -566,12 +566,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
else
soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "Cannot get memory resource\n");
return -ENODEV;
}
mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), GFP_KERNEL);
if (!mvchip) {
dev_err(&pdev->dev, "Cannot allocate memory\n");
@ -611,6 +605,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
mvchip->chip.dbg_show = mvebu_gpio_dbg_show;
spin_lock_init(&mvchip->lock);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mvchip->membase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mvchip->membase))
return PTR_ERR(mvchip->membase);

View File

@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <linux/err.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@ -291,6 +292,9 @@ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
{
u32 irq_msk, irq_stat;
struct mxc_gpio_port *port;
struct irq_chip *chip = irq_get_chip(irq);
chained_irq_enter(chip, desc);
/* walk through all interrupt status registers */
list_for_each_entry(port, &mxc_gpio_ports, node) {
@ -302,6 +306,7 @@ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
if (irq_stat)
mxc_gpio_irq_handler(port, irq_stat);
}
chained_irq_exit(chip, desc);
}
/*
@ -405,34 +410,19 @@ static int mxc_gpio_probe(struct platform_device *pdev)
mxc_gpio_get_hw(pdev);
port = kzalloc(sizeof(struct mxc_gpio_port), GFP_KERNEL);
port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
if (!port)
return -ENOMEM;
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!iores) {
err = -ENODEV;
goto out_kfree;
}
if (!request_mem_region(iores->start, resource_size(iores),
pdev->name)) {
err = -EBUSY;
goto out_kfree;
}
port->base = ioremap(iores->start, resource_size(iores));
if (!port->base) {
err = -ENOMEM;
goto out_release_mem;
}
port->base = devm_ioremap_resource(&pdev->dev, iores);
if (IS_ERR(port->base))
return PTR_ERR(port->base);
port->irq_high = platform_get_irq(pdev, 1);
port->irq = platform_get_irq(pdev, 0);
if (port->irq < 0) {
err = -EINVAL;
goto out_iounmap;
}
if (port->irq < 0)
return -EINVAL;
/* disable the interrupt and clear the status */
writel(0, port->base + GPIO_IMR);
@ -462,7 +452,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
port->base + GPIO_DR, NULL,
port->base + GPIO_GDIR, NULL, 0);
if (err)
goto out_iounmap;
goto out_bgio;
port->bgc.gc.to_irq = mxc_gpio_to_irq;
port->bgc.gc.base = (pdev->id < 0) ? of_alias_get_id(np, "gpio") * 32 :
@ -498,12 +488,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
WARN_ON(gpiochip_remove(&port->bgc.gc) < 0);
out_bgpio_remove:
bgpio_remove(&port->bgc);
out_iounmap:
iounmap(port->base);
out_release_mem:
release_mem_region(iores->start, resource_size(iores));
out_kfree:
kfree(port);
out_bgio:
dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
return err;
}

View File

@ -1030,7 +1030,7 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
ct->chip.irq_set_type = gpio_irq_type;
if (bank->regs->wkup_en)
ct->chip.irq_set_wake = gpio_wake_enable,
ct->chip.irq_set_wake = gpio_wake_enable;
ct->regs.mask = OMAP_MPUIO_GPIO_INT / bank->stride;
irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
@ -1100,7 +1100,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
match = of_match_device(of_match_ptr(omap_gpio_match), dev);
pdata = match ? match->data : dev->platform_data;
pdata = match ? match->data : dev_get_platdata(dev);
if (!pdata)
return -EINVAL;

View File

@ -43,9 +43,22 @@ static int palmas_gpio_get(struct gpio_chip *gc, unsigned offset)
unsigned int val;
int ret;
ret = palmas_read(palmas, PALMAS_GPIO_BASE, PALMAS_GPIO_DATA_IN, &val);
ret = palmas_read(palmas, PALMAS_GPIO_BASE, PALMAS_GPIO_DATA_DIR, &val);
if (ret < 0) {
dev_err(gc->dev, "GPIO_DATA_IN read failed, err = %d\n", ret);
dev_err(gc->dev, "GPIO_DATA_DIR read failed, err = %d\n", ret);
return ret;
}
if (val & (1 << offset)) {
ret = palmas_read(palmas, PALMAS_GPIO_BASE,
PALMAS_GPIO_DATA_OUT, &val);
} else {
ret = palmas_read(palmas, PALMAS_GPIO_BASE,
PALMAS_GPIO_DATA_IN, &val);
}
if (ret < 0) {
dev_err(gc->dev, "GPIO_DATA_IN/OUT read failed, err = %d\n",
ret);
return ret;
}
return !!(val & BIT(offset));
@ -134,7 +147,7 @@ static int palmas_gpio_probe(struct platform_device *pdev)
palmas_gpio->gpio_chip.get = palmas_gpio_get;
palmas_gpio->gpio_chip.dev = &pdev->dev;
#ifdef CONFIG_OF_GPIO
palmas_gpio->gpio_chip.of_node = palmas->dev->of_node;
palmas_gpio->gpio_chip.of_node = pdev->dev.of_node;
#endif
palmas_pdata = dev_get_platdata(palmas->dev);
if (palmas_pdata && palmas_pdata->gpio_base)
@ -159,9 +172,19 @@ static int palmas_gpio_remove(struct platform_device *pdev)
return gpiochip_remove(&palmas_gpio->gpio_chip);
}
static struct of_device_id of_palmas_gpio_match[] = {
{ .compatible = "ti,palmas-gpio"},
{ .compatible = "ti,tps65913-gpio"},
{ .compatible = "ti,tps65914-gpio"},
{ .compatible = "ti,tps80036-gpio"},
{ },
};
MODULE_DEVICE_TABLE(of, of_palmas_gpio_match);
static struct platform_driver palmas_gpio_driver = {
.driver.name = "palmas-gpio",
.driver.owner = THIS_MODULE,
.driver.of_match_table = of_palmas_gpio_match,
.probe = palmas_gpio_probe,
.remove = palmas_gpio_remove,
};

View File

@ -308,7 +308,7 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
return 0;
}
return (reg_val & (1u << off)) ? 1 : 0;
return (reg_val & (1u << (off % BANK_SZ))) ? 1 : 0;
}
static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
@ -731,7 +731,7 @@ static int pca953x_probe(struct i2c_client *client,
if (chip == NULL)
return -ENOMEM;
pdata = client->dev.platform_data;
pdata = dev_get_platdata(&client->dev);
if (pdata) {
irq_base = pdata->irq_base;
chip->gpio_start = pdata->gpio_base;
@ -785,7 +785,7 @@ static int pca953x_probe(struct i2c_client *client,
static int pca953x_remove(struct i2c_client *client)
{
struct pca953x_platform_data *pdata = client->dev.platform_data;
struct pca953x_platform_data *pdata = dev_get_platdata(&client->dev);
struct pca953x_chip *chip = i2c_get_clientdata(client);
int ret = 0;

View File

@ -18,15 +18,15 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/i2c/pcf857x.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
@ -223,7 +223,6 @@ static void pcf857x_irq_domain_cleanup(struct pcf857x *gpio)
}
static int pcf857x_irq_domain_init(struct pcf857x *gpio,
struct pcf857x_platform_data *pdata,
struct i2c_client *client)
{
int status;
@ -262,7 +261,7 @@ static int pcf857x_probe(struct i2c_client *client,
struct pcf857x *gpio;
int status;
pdata = client->dev.platform_data;
pdata = dev_get_platdata(&client->dev);
if (!pdata) {
dev_dbg(&client->dev, "no platform data\n");
}
@ -286,8 +285,8 @@ static int pcf857x_probe(struct i2c_client *client,
gpio->chip.ngpio = id->driver_data;
/* enable gpio_to_irq() if platform has settings */
if (pdata && client->irq) {
status = pcf857x_irq_domain_init(gpio, pdata, client);
if (client->irq) {
status = pcf857x_irq_domain_init(gpio, client);
if (status < 0) {
dev_err(&client->dev, "irq_domain init failed\n");
goto fail;
@ -388,7 +387,7 @@ static int pcf857x_probe(struct i2c_client *client,
dev_dbg(&client->dev, "probe error %d for '%s'\n",
status, client->name);
if (pdata && client->irq)
if (client->irq)
pcf857x_irq_domain_cleanup(gpio);
return status;
@ -396,7 +395,7 @@ static int pcf857x_probe(struct i2c_client *client,
static int pcf857x_remove(struct i2c_client *client)
{
struct pcf857x_platform_data *pdata = client->dev.platform_data;
struct pcf857x_platform_data *pdata = dev_get_platdata(&client->dev);
struct pcf857x *gpio = i2c_get_clientdata(client);
int status = 0;
@ -411,7 +410,7 @@ static int pcf857x_remove(struct i2c_client *client)
}
}
if (pdata && client->irq)
if (client->irq)
pcf857x_irq_domain_cleanup(gpio);
status = gpiochip_remove(&gpio->chip);

View File

@ -259,7 +259,7 @@ static const struct irq_domain_ops pl061_domain_ops = {
static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
{
struct device *dev = &adev->dev;
struct pl061_platform_data *pdata = dev->platform_data;
struct pl061_platform_data *pdata = dev_get_platdata(dev);
struct pl061_gpio *chip;
int ret, irq, i, irq_base;

View File

@ -524,8 +524,8 @@ const struct irq_domain_ops pxa_irq_domain_ops = {
static int pxa_gpio_probe_dt(struct platform_device *pdev)
{
int ret, nr_gpios;
struct device_node *prev, *next, *np = pdev->dev.of_node;
int ret = 0, nr_gpios;
struct device_node *np = pdev->dev.of_node;
const struct of_device_id *of_id =
of_match_device(pxa_gpio_dt_ids, &pdev->dev);
const struct pxa_gpio_id *gpio_id;
@ -537,20 +537,13 @@ static int pxa_gpio_probe_dt(struct platform_device *pdev)
gpio_id = of_id->data;
gpio_type = gpio_id->type;
next = of_get_next_child(np, NULL);
prev = next;
if (!next) {
dev_err(&pdev->dev, "Failed to find child gpio node\n");
ret = -EINVAL;
goto err;
}
of_node_put(prev);
nr_gpios = gpio_id->gpio_nums;
pxa_last_gpio = nr_gpios - 1;
irq_base = irq_alloc_descs(-1, 0, nr_gpios, 0);
if (irq_base < 0) {
dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
ret = irq_base;
goto err;
}
domain = irq_domain_add_legacy(np, nr_gpios, irq_base, 0,

View File

@ -285,7 +285,7 @@ static struct irq_domain_ops gpio_rcar_irq_domain_ops = {
static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p)
{
struct gpio_rcar_config *pdata = p->pdev->dev.platform_data;
struct gpio_rcar_config *pdata = dev_get_platdata(&p->pdev->dev);
struct device_node *np = p->pdev->dev.of_node;
struct of_phandle_args args;
int ret;

View File

@ -135,7 +135,7 @@ static int rdc321x_gpio_probe(struct platform_device *pdev)
struct rdc321x_gpio *rdc321x_gpio_dev;
struct rdc321x_gpio_pdata *pdata;
pdata = pdev->dev.platform_data;
pdata = dev_get_platdata(&pdev->dev);
if (!pdata) {
dev_err(&pdev->dev, "no platform data supplied\n");
return -ENODEV;

View File

@ -161,28 +161,6 @@ int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
}
static int exynos_gpio_setpull(struct samsung_gpio_chip *chip,
unsigned int off, samsung_gpio_pull_t pull)
{
if (pull == S3C_GPIO_PULL_UP)
pull = 3;
return samsung_gpio_setpull_updown(chip, off, pull);
}
static samsung_gpio_pull_t exynos_gpio_getpull(struct samsung_gpio_chip *chip,
unsigned int off)
{
samsung_gpio_pull_t pull;
pull = samsung_gpio_getpull_updown(chip, off);
if (pull == 3)
pull = S3C_GPIO_PULL_UP;
return pull;
}
/*
* samsung_gpio_setcfg_2bit - Samsung 2bit style GPIO configuration.
* @chip: The gpio chip that is being configured.
@ -444,15 +422,6 @@ static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
};
#endif
#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_SOC_EXYNOS5250)
static struct samsung_gpio_cfg exynos_gpio_cfg = {
.set_pull = exynos_gpio_setpull,
.get_pull = exynos_gpio_getpull,
.set_config = samsung_gpio_setcfg_4bit,
.get_config = samsung_gpio_getcfg_4bit,
};
#endif
#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = {
.cfg_eint = 0x3,
@ -495,15 +464,6 @@ static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
.set_config = samsung_gpio_setcfg_2bit,
.get_config = samsung_gpio_getcfg_2bit,
},
[8] = {
.set_pull = exynos_gpio_setpull,
.get_pull = exynos_gpio_getpull,
},
[9] = {
.cfg_eint = 0x3,
.set_pull = exynos_gpio_setpull,
.get_pull = exynos_gpio_getpull,
}
};
/*
@ -2115,833 +2075,6 @@ static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
#endif
};
/*
* Followings are the gpio banks in EXYNOS SoCs
*
* The 'config' member when left to NULL, is initialized to the default
* structure exynos_gpio_cfg in the init function below.
*
* The 'base' member is also initialized in the init function below.
* Note: The initialization of 'base' member of samsung_gpio_chip structure
* uses the above macro and depends on the banks being listed in order here.
*/
#ifdef CONFIG_ARCH_EXYNOS4
static struct samsung_gpio_chip exynos4_gpios_1[] = {
{
.chip = {
.base = EXYNOS4_GPA0(0),
.ngpio = EXYNOS4_GPIO_A0_NR,
.label = "GPA0",
},
}, {
.chip = {
.base = EXYNOS4_GPA1(0),
.ngpio = EXYNOS4_GPIO_A1_NR,
.label = "GPA1",
},
}, {
.chip = {
.base = EXYNOS4_GPB(0),
.ngpio = EXYNOS4_GPIO_B_NR,
.label = "GPB",
},
}, {
.chip = {
.base = EXYNOS4_GPC0(0),
.ngpio = EXYNOS4_GPIO_C0_NR,
.label = "GPC0",
},
}, {
.chip = {
.base = EXYNOS4_GPC1(0),
.ngpio = EXYNOS4_GPIO_C1_NR,
.label = "GPC1",
},
}, {
.chip = {
.base = EXYNOS4_GPD0(0),
.ngpio = EXYNOS4_GPIO_D0_NR,
.label = "GPD0",
},
}, {
.chip = {
.base = EXYNOS4_GPD1(0),
.ngpio = EXYNOS4_GPIO_D1_NR,
.label = "GPD1",
},
}, {
.chip = {
.base = EXYNOS4_GPE0(0),
.ngpio = EXYNOS4_GPIO_E0_NR,
.label = "GPE0",
},
}, {
.chip = {
.base = EXYNOS4_GPE1(0),
.ngpio = EXYNOS4_GPIO_E1_NR,
.label = "GPE1",
},
}, {
.chip = {
.base = EXYNOS4_GPE2(0),
.ngpio = EXYNOS4_GPIO_E2_NR,
.label = "GPE2",
},
}, {
.chip = {
.base = EXYNOS4_GPE3(0),
.ngpio = EXYNOS4_GPIO_E3_NR,
.label = "GPE3",
},
}, {
.chip = {
.base = EXYNOS4_GPE4(0),
.ngpio = EXYNOS4_GPIO_E4_NR,
.label = "GPE4",
},
}, {
.chip = {
.base = EXYNOS4_GPF0(0),
.ngpio = EXYNOS4_GPIO_F0_NR,
.label = "GPF0",
},
}, {
.chip = {
.base = EXYNOS4_GPF1(0),
.ngpio = EXYNOS4_GPIO_F1_NR,
.label = "GPF1",
},
}, {
.chip = {
.base = EXYNOS4_GPF2(0),
.ngpio = EXYNOS4_GPIO_F2_NR,
.label = "GPF2",
},
}, {
.chip = {
.base = EXYNOS4_GPF3(0),
.ngpio = EXYNOS4_GPIO_F3_NR,
.label = "GPF3",
},
},
};
#endif
#ifdef CONFIG_ARCH_EXYNOS4
static struct samsung_gpio_chip exynos4_gpios_2[] = {
{
.chip = {
.base = EXYNOS4_GPJ0(0),
.ngpio = EXYNOS4_GPIO_J0_NR,
.label = "GPJ0",
},
}, {
.chip = {
.base = EXYNOS4_GPJ1(0),
.ngpio = EXYNOS4_GPIO_J1_NR,
.label = "GPJ1",
},
}, {
.chip = {
.base = EXYNOS4_GPK0(0),
.ngpio = EXYNOS4_GPIO_K0_NR,
.label = "GPK0",
},
}, {
.chip = {
.base = EXYNOS4_GPK1(0),
.ngpio = EXYNOS4_GPIO_K1_NR,
.label = "GPK1",
},
}, {
.chip = {
.base = EXYNOS4_GPK2(0),
.ngpio = EXYNOS4_GPIO_K2_NR,
.label = "GPK2",
},
}, {
.chip = {
.base = EXYNOS4_GPK3(0),
.ngpio = EXYNOS4_GPIO_K3_NR,
.label = "GPK3",
},
}, {
.chip = {
.base = EXYNOS4_GPL0(0),
.ngpio = EXYNOS4_GPIO_L0_NR,
.label = "GPL0",
},
}, {
.chip = {
.base = EXYNOS4_GPL1(0),
.ngpio = EXYNOS4_GPIO_L1_NR,
.label = "GPL1",
},
}, {
.chip = {
.base = EXYNOS4_GPL2(0),
.ngpio = EXYNOS4_GPIO_L2_NR,
.label = "GPL2",
},
}, {
.config = &samsung_gpio_cfgs[8],
.chip = {
.base = EXYNOS4_GPY0(0),
.ngpio = EXYNOS4_GPIO_Y0_NR,
.label = "GPY0",
},
}, {
.config = &samsung_gpio_cfgs[8],
.chip = {
.base = EXYNOS4_GPY1(0),
.ngpio = EXYNOS4_GPIO_Y1_NR,
.label = "GPY1",
},
}, {
.config = &samsung_gpio_cfgs[8],
.chip = {
.base = EXYNOS4_GPY2(0),
.ngpio = EXYNOS4_GPIO_Y2_NR,
.label = "GPY2",
},
}, {
.config = &samsung_gpio_cfgs[8],
.chip = {
.base = EXYNOS4_GPY3(0),
.ngpio = EXYNOS4_GPIO_Y3_NR,
.label = "GPY3",
},
}, {
.config = &samsung_gpio_cfgs[8],
.chip = {
.base = EXYNOS4_GPY4(0),
.ngpio = EXYNOS4_GPIO_Y4_NR,
.label = "GPY4",
},
}, {
.config = &samsung_gpio_cfgs[8],
.chip = {
.base = EXYNOS4_GPY5(0),
.ngpio = EXYNOS4_GPIO_Y5_NR,
.label = "GPY5",
},
}, {
.config = &samsung_gpio_cfgs[8],
.chip = {
.base = EXYNOS4_GPY6(0),
.ngpio = EXYNOS4_GPIO_Y6_NR,
.label = "GPY6",
},
}, {
.config = &samsung_gpio_cfgs[9],
.irq_base = IRQ_EINT(0),
.chip = {
.base = EXYNOS4_GPX0(0),
.ngpio = EXYNOS4_GPIO_X0_NR,
.label = "GPX0",
.to_irq = samsung_gpiolib_to_irq,
},
}, {
.config = &samsung_gpio_cfgs[9],
.irq_base = IRQ_EINT(8),
.chip = {
.base = EXYNOS4_GPX1(0),
.ngpio = EXYNOS4_GPIO_X1_NR,
.label = "GPX1",
.to_irq = samsung_gpiolib_to_irq,
},
}, {
.config = &samsung_gpio_cfgs[9],
.irq_base = IRQ_EINT(16),
.chip = {
.base = EXYNOS4_GPX2(0),
.ngpio = EXYNOS4_GPIO_X2_NR,
.label = "GPX2",
.to_irq = samsung_gpiolib_to_irq,
},
}, {
.config = &samsung_gpio_cfgs[9],
.irq_base = IRQ_EINT(24),
.chip = {
.base = EXYNOS4_GPX3(0),
.ngpio = EXYNOS4_GPIO_X3_NR,
.label = "GPX3",
.to_irq = samsung_gpiolib_to_irq,
},
},
};
#endif
#ifdef CONFIG_ARCH_EXYNOS4
static struct samsung_gpio_chip exynos4_gpios_3[] = {
{
.chip = {
.base = EXYNOS4_GPZ(0),
.ngpio = EXYNOS4_GPIO_Z_NR,
.label = "GPZ",
},
},
};
#endif
#ifdef CONFIG_SOC_EXYNOS5250
static struct samsung_gpio_chip exynos5_gpios_1[] = {
{
.chip = {
.base = EXYNOS5_GPA0(0),
.ngpio = EXYNOS5_GPIO_A0_NR,
.label = "GPA0",
},
}, {
.chip = {
.base = EXYNOS5_GPA1(0),
.ngpio = EXYNOS5_GPIO_A1_NR,
.label = "GPA1",
},
}, {
.chip = {
.base = EXYNOS5_GPA2(0),
.ngpio = EXYNOS5_GPIO_A2_NR,
.label = "GPA2",
},
}, {
.chip = {
.base = EXYNOS5_GPB0(0),
.ngpio = EXYNOS5_GPIO_B0_NR,
.label = "GPB0",
},
}, {
.chip = {
.base = EXYNOS5_GPB1(0),
.ngpio = EXYNOS5_GPIO_B1_NR,
.label = "GPB1",
},
}, {
.chip = {
.base = EXYNOS5_GPB2(0),
.ngpio = EXYNOS5_GPIO_B2_NR,
.label = "GPB2",
},
}, {
.chip = {
.base = EXYNOS5_GPB3(0),
.ngpio = EXYNOS5_GPIO_B3_NR,
.label = "GPB3",
},
}, {
.chip = {
.base = EXYNOS5_GPC0(0),
.ngpio = EXYNOS5_GPIO_C0_NR,
.label = "GPC0",
},
}, {
.chip = {
.base = EXYNOS5_GPC1(0),
.ngpio = EXYNOS5_GPIO_C1_NR,
.label = "GPC1",
},
}, {
.chip = {
.base = EXYNOS5_GPC2(0),
.ngpio = EXYNOS5_GPIO_C2_NR,
.label = "GPC2",
},
}, {
.chip = {
.base = EXYNOS5_GPC3(0),
.ngpio = EXYNOS5_GPIO_C3_NR,
.label = "GPC3",
},
}, {
.chip = {
.base = EXYNOS5_GPD0(0),
.ngpio = EXYNOS5_GPIO_D0_NR,
.label = "GPD0",
},
}, {
.chip = {
.base = EXYNOS5_GPD1(0),
.ngpio = EXYNOS5_GPIO_D1_NR,
.label = "GPD1",
},
}, {
.chip = {
.base = EXYNOS5_GPY0(0),
.ngpio = EXYNOS5_GPIO_Y0_NR,
.label = "GPY0",
},
}, {
.chip = {
.base = EXYNOS5_GPY1(0),
.ngpio = EXYNOS5_GPIO_Y1_NR,
.label = "GPY1",
},
}, {
.chip = {
.base = EXYNOS5_GPY2(0),
.ngpio = EXYNOS5_GPIO_Y2_NR,
.label = "GPY2",
},
}, {
.chip = {
.base = EXYNOS5_GPY3(0),
.ngpio = EXYNOS5_GPIO_Y3_NR,
.label = "GPY3",
},
}, {
.chip = {
.base = EXYNOS5_GPY4(0),
.ngpio = EXYNOS5_GPIO_Y4_NR,
.label = "GPY4",
},
}, {
.chip = {
.base = EXYNOS5_GPY5(0),
.ngpio = EXYNOS5_GPIO_Y5_NR,
.label = "GPY5",
},
}, {
.chip = {
.base = EXYNOS5_GPY6(0),
.ngpio = EXYNOS5_GPIO_Y6_NR,
.label = "GPY6",
},
}, {
.chip = {
.base = EXYNOS5_GPC4(0),
.ngpio = EXYNOS5_GPIO_C4_NR,
.label = "GPC4",
},
}, {
.config = &samsung_gpio_cfgs[9],
.irq_base = IRQ_EINT(0),
.chip = {
.base = EXYNOS5_GPX0(0),
.ngpio = EXYNOS5_GPIO_X0_NR,
.label = "GPX0",
.to_irq = samsung_gpiolib_to_irq,
},
}, {
.config = &samsung_gpio_cfgs[9],
.irq_base = IRQ_EINT(8),
.chip = {
.base = EXYNOS5_GPX1(0),
.ngpio = EXYNOS5_GPIO_X1_NR,
.label = "GPX1",
.to_irq = samsung_gpiolib_to_irq,
},
}, {
.config = &samsung_gpio_cfgs[9],
.irq_base = IRQ_EINT(16),
.chip = {
.base = EXYNOS5_GPX2(0),
.ngpio = EXYNOS5_GPIO_X2_NR,
.label = "GPX2",
.to_irq = samsung_gpiolib_to_irq,
},
}, {
.config = &samsung_gpio_cfgs[9],
.irq_base = IRQ_EINT(24),
.chip = {
.base = EXYNOS5_GPX3(0),
.ngpio = EXYNOS5_GPIO_X3_NR,
.label = "GPX3",
.to_irq = samsung_gpiolib_to_irq,
},
},
};
#endif
#ifdef CONFIG_SOC_EXYNOS5250
static struct samsung_gpio_chip exynos5_gpios_2[] = {
{
.chip = {
.base = EXYNOS5_GPE0(0),
.ngpio = EXYNOS5_GPIO_E0_NR,
.label = "GPE0",
},
}, {
.chip = {
.base = EXYNOS5_GPE1(0),
.ngpio = EXYNOS5_GPIO_E1_NR,
.label = "GPE1",
},
}, {
.chip = {
.base = EXYNOS5_GPF0(0),
.ngpio = EXYNOS5_GPIO_F0_NR,
.label = "GPF0",
},
}, {
.chip = {
.base = EXYNOS5_GPF1(0),
.ngpio = EXYNOS5_GPIO_F1_NR,
.label = "GPF1",
},
}, {
.chip = {
.base = EXYNOS5_GPG0(0),
.ngpio = EXYNOS5_GPIO_G0_NR,
.label = "GPG0",
},
}, {
.chip = {
.base = EXYNOS5_GPG1(0),
.ngpio = EXYNOS5_GPIO_G1_NR,
.label = "GPG1",
},
}, {
.chip = {
.base = EXYNOS5_GPG2(0),
.ngpio = EXYNOS5_GPIO_G2_NR,
.label = "GPG2",
},
}, {
.chip = {
.base = EXYNOS5_GPH0(0),
.ngpio = EXYNOS5_GPIO_H0_NR,
.label = "GPH0",
},
}, {
.chip = {
.base = EXYNOS5_GPH1(0),
.ngpio = EXYNOS5_GPIO_H1_NR,
.label = "GPH1",
},
},
};
#endif
#ifdef CONFIG_SOC_EXYNOS5250
static struct samsung_gpio_chip exynos5_gpios_3[] = {
{
.chip = {
.base = EXYNOS5_GPV0(0),
.ngpio = EXYNOS5_GPIO_V0_NR,
.label = "GPV0",
},
}, {
.chip = {
.base = EXYNOS5_GPV1(0),
.ngpio = EXYNOS5_GPIO_V1_NR,
.label = "GPV1",
},
}, {
.chip = {
.base = EXYNOS5_GPV2(0),
.ngpio = EXYNOS5_GPIO_V2_NR,
.label = "GPV2",
},
}, {
.chip = {
.base = EXYNOS5_GPV3(0),
.ngpio = EXYNOS5_GPIO_V3_NR,
.label = "GPV3",
},
}, {
.chip = {
.base = EXYNOS5_GPV4(0),
.ngpio = EXYNOS5_GPIO_V4_NR,
.label = "GPV4",
},
},
};
#endif
#ifdef CONFIG_SOC_EXYNOS5250
static struct samsung_gpio_chip exynos5_gpios_4[] = {
{
.chip = {
.base = EXYNOS5_GPZ(0),
.ngpio = EXYNOS5_GPIO_Z_NR,
.label = "GPZ",
},
},
};
#endif
#if defined(CONFIG_ARCH_EXYNOS) && defined(CONFIG_OF)
static int exynos_gpio_xlate(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec, u32 *flags)
{
unsigned int pin;
if (WARN_ON(gc->of_gpio_n_cells < 4))
return -EINVAL;
if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
return -EINVAL;
if (gpiospec->args[0] > gc->ngpio)
return -EINVAL;
pin = gc->base + gpiospec->args[0];
if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1])))
pr_warn("gpio_xlate: failed to set pin function\n");
if (s3c_gpio_setpull(pin, gpiospec->args[2] & 0xffff))
pr_warn("gpio_xlate: failed to set pin pull up/down\n");
if (s5p_gpio_set_drvstr(pin, gpiospec->args[3]))
pr_warn("gpio_xlate: failed to set pin drive strength\n");
if (flags)
*flags = gpiospec->args[2] >> 16;
return gpiospec->args[0];
}
static const struct of_device_id exynos_gpio_dt_match[] __initdata = {
{ .compatible = "samsung,exynos4-gpio", },
{}
};
static __init void exynos_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
u64 base, u64 offset)
{
struct gpio_chip *gc = &chip->chip;
u64 address;
if (!of_have_populated_dt())
return;
address = chip->base ? base + ((u32)chip->base & 0xfff) : base + offset;
gc->of_node = of_find_matching_node_by_address(NULL,
exynos_gpio_dt_match, address);
if (!gc->of_node) {
pr_info("gpio: device tree node not found for gpio controller"
" with base address %08llx\n", address);
return;
}
gc->of_gpio_n_cells = 4;
gc->of_xlate = exynos_gpio_xlate;
}
#elif defined(CONFIG_ARCH_EXYNOS)
static __init void exynos_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
u64 base, u64 offset)
{
return;
}
#endif /* defined(CONFIG_ARCH_EXYNOS) && defined(CONFIG_OF) */
static __init void exynos4_gpiolib_init(void)
{
#ifdef CONFIG_CPU_EXYNOS4210
struct samsung_gpio_chip *chip;
int i, nr_chips;
void __iomem *gpio_base1, *gpio_base2, *gpio_base3;
int group = 0;
void __iomem *gpx_base;
/* gpio part1 */
gpio_base1 = ioremap(EXYNOS4_PA_GPIO1, SZ_4K);
if (gpio_base1 == NULL) {
pr_err("unable to ioremap for gpio_base1\n");
goto err_ioremap1;
}
chip = exynos4_gpios_1;
nr_chips = ARRAY_SIZE(exynos4_gpios_1);
for (i = 0; i < nr_chips; i++, chip++) {
if (!chip->config) {
chip->config = &exynos_gpio_cfg;
chip->group = group++;
}
exynos_gpiolib_attach_ofnode(chip,
EXYNOS4_PA_GPIO1, i * 0x20);
}
samsung_gpiolib_add_4bit_chips(exynos4_gpios_1,
nr_chips, gpio_base1);
/* gpio part2 */
gpio_base2 = ioremap(EXYNOS4_PA_GPIO2, SZ_4K);
if (gpio_base2 == NULL) {
pr_err("unable to ioremap for gpio_base2\n");
goto err_ioremap2;
}
/* need to set base address for gpx */
chip = &exynos4_gpios_2[16];
gpx_base = gpio_base2 + 0xC00;
for (i = 0; i < 4; i++, chip++, gpx_base += 0x20)
chip->base = gpx_base;
chip = exynos4_gpios_2;
nr_chips = ARRAY_SIZE(exynos4_gpios_2);
for (i = 0; i < nr_chips; i++, chip++) {
if (!chip->config) {
chip->config = &exynos_gpio_cfg;
chip->group = group++;
}
exynos_gpiolib_attach_ofnode(chip,
EXYNOS4_PA_GPIO2, i * 0x20);
}
samsung_gpiolib_add_4bit_chips(exynos4_gpios_2,
nr_chips, gpio_base2);
/* gpio part3 */
gpio_base3 = ioremap(EXYNOS4_PA_GPIO3, SZ_256);
if (gpio_base3 == NULL) {
pr_err("unable to ioremap for gpio_base3\n");
goto err_ioremap3;
}
chip = exynos4_gpios_3;
nr_chips = ARRAY_SIZE(exynos4_gpios_3);
for (i = 0; i < nr_chips; i++, chip++) {
if (!chip->config) {
chip->config = &exynos_gpio_cfg;
chip->group = group++;
}
exynos_gpiolib_attach_ofnode(chip,
EXYNOS4_PA_GPIO3, i * 0x20);
}
samsung_gpiolib_add_4bit_chips(exynos4_gpios_3,
nr_chips, gpio_base3);
#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_S5P_GPIO_INT)
s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
#endif
return;
err_ioremap3:
iounmap(gpio_base2);
err_ioremap2:
iounmap(gpio_base1);
err_ioremap1:
return;
#endif /* CONFIG_CPU_EXYNOS4210 */
}
static __init void exynos5_gpiolib_init(void)
{
#ifdef CONFIG_SOC_EXYNOS5250
struct samsung_gpio_chip *chip;
int i, nr_chips;
void __iomem *gpio_base1, *gpio_base2, *gpio_base3, *gpio_base4;
int group = 0;
void __iomem *gpx_base;
/* gpio part1 */
gpio_base1 = ioremap(EXYNOS5_PA_GPIO1, SZ_4K);
if (gpio_base1 == NULL) {
pr_err("unable to ioremap for gpio_base1\n");
goto err_ioremap1;
}
/* need to set base address for gpc4 */
exynos5_gpios_1[20].base = gpio_base1 + 0x2E0;
/* need to set base address for gpx */
chip = &exynos5_gpios_1[21];
gpx_base = gpio_base1 + 0xC00;
for (i = 0; i < 4; i++, chip++, gpx_base += 0x20)
chip->base = gpx_base;
chip = exynos5_gpios_1;
nr_chips = ARRAY_SIZE(exynos5_gpios_1);
for (i = 0; i < nr_chips; i++, chip++) {
if (!chip->config) {
chip->config = &exynos_gpio_cfg;
chip->group = group++;
}
exynos_gpiolib_attach_ofnode(chip,
EXYNOS5_PA_GPIO1, i * 0x20);
}
samsung_gpiolib_add_4bit_chips(exynos5_gpios_1,
nr_chips, gpio_base1);
/* gpio part2 */
gpio_base2 = ioremap(EXYNOS5_PA_GPIO2, SZ_4K);
if (gpio_base2 == NULL) {
pr_err("unable to ioremap for gpio_base2\n");
goto err_ioremap2;
}
chip = exynos5_gpios_2;
nr_chips = ARRAY_SIZE(exynos5_gpios_2);
for (i = 0; i < nr_chips; i++, chip++) {
if (!chip->config) {
chip->config = &exynos_gpio_cfg;
chip->group = group++;
}
exynos_gpiolib_attach_ofnode(chip,
EXYNOS5_PA_GPIO2, i * 0x20);
}
samsung_gpiolib_add_4bit_chips(exynos5_gpios_2,
nr_chips, gpio_base2);
/* gpio part3 */
gpio_base3 = ioremap(EXYNOS5_PA_GPIO3, SZ_4K);
if (gpio_base3 == NULL) {
pr_err("unable to ioremap for gpio_base3\n");
goto err_ioremap3;
}
/* need to set base address for gpv */
exynos5_gpios_3[0].base = gpio_base3;
exynos5_gpios_3[1].base = gpio_base3 + 0x20;
exynos5_gpios_3[2].base = gpio_base3 + 0x60;
exynos5_gpios_3[3].base = gpio_base3 + 0x80;
exynos5_gpios_3[4].base = gpio_base3 + 0xC0;
chip = exynos5_gpios_3;
nr_chips = ARRAY_SIZE(exynos5_gpios_3);
for (i = 0; i < nr_chips; i++, chip++) {
if (!chip->config) {
chip->config = &exynos_gpio_cfg;
chip->group = group++;
}
exynos_gpiolib_attach_ofnode(chip,
EXYNOS5_PA_GPIO3, i * 0x20);
}
samsung_gpiolib_add_4bit_chips(exynos5_gpios_3,
nr_chips, gpio_base3);
/* gpio part4 */
gpio_base4 = ioremap(EXYNOS5_PA_GPIO4, SZ_4K);
if (gpio_base4 == NULL) {
pr_err("unable to ioremap for gpio_base4\n");
goto err_ioremap4;
}
chip = exynos5_gpios_4;
nr_chips = ARRAY_SIZE(exynos5_gpios_4);
for (i = 0; i < nr_chips; i++, chip++) {
if (!chip->config) {
chip->config = &exynos_gpio_cfg;
chip->group = group++;
}
exynos_gpiolib_attach_ofnode(chip,
EXYNOS5_PA_GPIO4, i * 0x20);
}
samsung_gpiolib_add_4bit_chips(exynos5_gpios_4,
nr_chips, gpio_base4);
return;
err_ioremap4:
iounmap(gpio_base3);
err_ioremap3:
iounmap(gpio_base2);
err_ioremap2:
iounmap(gpio_base1);
err_ioremap1:
return;
#endif /* CONFIG_SOC_EXYNOS5250 */
}
/* TODO: cleanup soc_is_* */
static __init int samsung_gpiolib_init(void)
{
@ -3040,10 +2173,6 @@ static __init int samsung_gpiolib_init(void)
#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_S5P_GPIO_INT)
s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
#endif
} else if (soc_is_exynos4210()) {
exynos4_gpiolib_init();
} else if (soc_is_exynos5250()) {
exynos5_gpiolib_init();
} else {
WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n");
return -ENODEV;

View File

@ -128,18 +128,13 @@ static int spics_gpio_probe(struct platform_device *pdev)
struct resource *res;
int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "invalid IORESOURCE_MEM\n");
return -EBUSY;
}
spics = devm_kzalloc(&pdev->dev, sizeof(*spics), GFP_KERNEL);
if (!spics) {
dev_err(&pdev->dev, "memory allocation fail\n");
return -ENOMEM;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spics->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(spics->base))
return PTR_ERR(spics->base);

View File

@ -361,7 +361,7 @@ static int gsta_probe(struct platform_device *dev)
struct gsta_gpio *chip;
struct resource *res;
pdev = *(struct pci_dev **)(dev->dev.platform_data);
pdev = *(struct pci_dev **)dev_get_platdata(&dev->dev);
gpio_pdata = dev_get_platdata(&pdev->dev);
if (gpio_pdata == NULL)

View File

@ -583,7 +583,7 @@ static int sx150x_probe(struct i2c_client *client,
struct sx150x_chip *chip;
int rc;
pdata = client->dev.platform_data;
pdata = dev_get_platdata(&client->dev);
if (!pdata)
return -EINVAL;

View File

@ -227,7 +227,7 @@ static int timbgpio_probe(struct platform_device *pdev)
struct gpio_chip *gc;
struct timbgpio *tgpio;
struct resource *iomem;
struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
int irq = platform_get_irq(pdev, 0);
if (!pdata || pdata->nr_pins > 32) {
@ -318,7 +318,7 @@ static int timbgpio_probe(struct platform_device *pdev)
static int timbgpio_remove(struct platform_device *pdev)
{
int err;
struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct timbgpio *tgpio = platform_get_drvdata(pdev);
struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
int irq = platform_get_irq(pdev, 0);

View File

@ -87,7 +87,7 @@ static struct gpio_chip template_chip = {
static int tps65912_gpio_probe(struct platform_device *pdev)
{
struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
struct tps65912_board *pdata = tps65912->dev->platform_data;
struct tps65912_board *pdata = dev_get_platdata(tps65912->dev);
struct tps65912_gpio_data *tps65912_gpio;
int ret;

View File

@ -322,7 +322,7 @@ static void ts5500_disable_irq(struct ts5500_priv *priv)
static int ts5500_dio_probe(struct platform_device *pdev)
{
enum ts5500_blocks block = platform_get_device_id(pdev)->driver_data;
struct ts5500_dio_platform_data *pdata = pdev->dev.platform_data;
struct ts5500_dio_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct device *dev = &pdev->dev;
const char *name = dev_name(dev);
struct ts5500_priv *priv;

View File

@ -256,7 +256,7 @@ static int twl_request(struct gpio_chip *chip, unsigned offset)
/* optionally have the first two GPIOs switch vMMC1
* and vMMC2 power supplies based on card presence.
*/
pdata = chip->dev->platform_data;
pdata = dev_get_platdata(chip->dev);
if (pdata)
value |= pdata->mmc_cd & 0x03;
@ -460,7 +460,7 @@ static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev)
static int gpio_twl4030_probe(struct platform_device *pdev)
{
struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
struct twl4030_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct device_node *node = pdev->dev.of_node;
struct gpio_twl4030_priv *priv;
int ret, irq_base;
@ -556,7 +556,7 @@ static int gpio_twl4030_probe(struct platform_device *pdev)
/* Cannot use as gpio_twl4030_probe() calls us */
static int gpio_twl4030_remove(struct platform_device *pdev)
{
struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
struct twl4030_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct gpio_twl4030_priv *priv = platform_get_drvdata(pdev);
int status;

View File

@ -84,15 +84,11 @@ static struct gpio_chip twl6040gpo_chip = {
static int gpo_twl6040_probe(struct platform_device *pdev)
{
struct twl6040_gpo_data *pdata = pdev->dev.platform_data;
struct device *twl6040_core_dev = pdev->dev.parent;
struct twl6040 *twl6040 = dev_get_drvdata(twl6040_core_dev);
int ret;
if (pdata)
twl6040gpo_chip.base = pdata->gpio_base;
else
twl6040gpo_chip.base = -1;
twl6040gpo_chip.base = -1;
if (twl6040_get_revid(twl6040) < TWL6041_REV_ES2_0)
twl6040gpo_chip.ngpio = 3; /* twl6040 have 3 GPO */

View File

@ -0,0 +1,243 @@
/*
* Toumaz Xenif TZ1090 PDC GPIO handling.
*
* Copyright (C) 2012-2013 Imagination Technologies Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/bitops.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/syscore_ops.h>
#include <asm/global_lock.h>
/* Register offsets from SOC_GPIO_CONTROL0 */
#define REG_SOC_GPIO_CONTROL0 0x00
#define REG_SOC_GPIO_CONTROL1 0x04
#define REG_SOC_GPIO_CONTROL2 0x08
#define REG_SOC_GPIO_CONTROL3 0x0c
#define REG_SOC_GPIO_STATUS 0x80
/* PDC GPIOs go after normal GPIOs */
#define GPIO_PDC_BASE 90
#define GPIO_PDC_NGPIO 7
/* Out of PDC gpios, only syswakes have irqs */
#define GPIO_PDC_IRQ_FIRST 2
#define GPIO_PDC_NIRQ 3
/**
* struct tz1090_pdc_gpio - GPIO bank private data
* @chip: Generic GPIO chip for GPIO bank
* @reg: Base of registers, offset for this GPIO bank
* @irq: IRQ numbers for Syswake GPIOs
*
* This is the main private data for the PDC GPIO driver. It encapsulates a
* gpio_chip, and the callbacks for the gpio_chip can access the private data
* with the to_pdc() macro below.
*/
struct tz1090_pdc_gpio {
struct gpio_chip chip;
void __iomem *reg;
int irq[GPIO_PDC_NIRQ];
};
#define to_pdc(c) container_of(c, struct tz1090_pdc_gpio, chip)
/* Register accesses into the PDC MMIO area */
static inline void pdc_write(struct tz1090_pdc_gpio *priv, unsigned int reg_offs,
unsigned int data)
{
writel(data, priv->reg + reg_offs);
}
static inline unsigned int pdc_read(struct tz1090_pdc_gpio *priv,
unsigned int reg_offs)
{
return readl(priv->reg + reg_offs);
}
/* Generic GPIO interface */
static int tz1090_pdc_gpio_direction_input(struct gpio_chip *chip,
unsigned int offset)
{
struct tz1090_pdc_gpio *priv = to_pdc(chip);
u32 value;
int lstat;
__global_lock2(lstat);
value = pdc_read(priv, REG_SOC_GPIO_CONTROL1);
value |= BIT(offset);
pdc_write(priv, REG_SOC_GPIO_CONTROL1, value);
__global_unlock2(lstat);
return 0;
}
static int tz1090_pdc_gpio_direction_output(struct gpio_chip *chip,
unsigned int offset,
int output_value)
{
struct tz1090_pdc_gpio *priv = to_pdc(chip);
u32 value;
int lstat;
__global_lock2(lstat);
/* EXT_POWER doesn't seem to have an output value bit */
if (offset < 6) {
value = pdc_read(priv, REG_SOC_GPIO_CONTROL0);
if (output_value)
value |= BIT(offset);
else
value &= ~BIT(offset);
pdc_write(priv, REG_SOC_GPIO_CONTROL0, value);
}
value = pdc_read(priv, REG_SOC_GPIO_CONTROL1);
value &= ~BIT(offset);
pdc_write(priv, REG_SOC_GPIO_CONTROL1, value);
__global_unlock2(lstat);
return 0;
}
static int tz1090_pdc_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct tz1090_pdc_gpio *priv = to_pdc(chip);
return pdc_read(priv, REG_SOC_GPIO_STATUS) & BIT(offset);
}
static void tz1090_pdc_gpio_set(struct gpio_chip *chip, unsigned int offset,
int output_value)
{
struct tz1090_pdc_gpio *priv = to_pdc(chip);
u32 value;
int lstat;
/* EXT_POWER doesn't seem to have an output value bit */
if (offset >= 6)
return;
__global_lock2(lstat);
value = pdc_read(priv, REG_SOC_GPIO_CONTROL0);
if (output_value)
value |= BIT(offset);
else
value &= ~BIT(offset);
pdc_write(priv, REG_SOC_GPIO_CONTROL0, value);
__global_unlock2(lstat);
}
static int tz1090_pdc_gpio_request(struct gpio_chip *chip, unsigned int offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void tz1090_pdc_gpio_free(struct gpio_chip *chip, unsigned int offset)
{
pinctrl_free_gpio(chip->base + offset);
}
static int tz1090_pdc_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
{
struct tz1090_pdc_gpio *priv = to_pdc(chip);
unsigned int syswake = offset - GPIO_PDC_IRQ_FIRST;
int irq;
/* only syswakes have irqs */
if (syswake >= GPIO_PDC_NIRQ)
return -EINVAL;
irq = priv->irq[syswake];
if (!irq)
return -EINVAL;
return irq;
}
static int tz1090_pdc_gpio_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct resource *res_regs;
struct tz1090_pdc_gpio *priv;
unsigned int i;
if (!np) {
dev_err(&pdev->dev, "must be instantiated via devicetree\n");
return -ENOENT;
}
res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res_regs) {
dev_err(&pdev->dev, "cannot find registers resource\n");
return -ENOENT;
}
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) {
dev_err(&pdev->dev, "unable to allocate driver data\n");
return -ENOMEM;
}
/* Ioremap the registers */
priv->reg = devm_ioremap(&pdev->dev, res_regs->start,
res_regs->end - res_regs->start);
if (!priv->reg) {
dev_err(&pdev->dev, "unable to ioremap registers\n");
return -ENOMEM;
}
/* Set up GPIO chip */
priv->chip.label = "tz1090-pdc-gpio";
priv->chip.dev = &pdev->dev;
priv->chip.direction_input = tz1090_pdc_gpio_direction_input;
priv->chip.direction_output = tz1090_pdc_gpio_direction_output;
priv->chip.get = tz1090_pdc_gpio_get;
priv->chip.set = tz1090_pdc_gpio_set;
priv->chip.free = tz1090_pdc_gpio_free;
priv->chip.request = tz1090_pdc_gpio_request;
priv->chip.to_irq = tz1090_pdc_gpio_to_irq;
priv->chip.of_node = np;
/* GPIO numbering */
priv->chip.base = GPIO_PDC_BASE;
priv->chip.ngpio = GPIO_PDC_NGPIO;
/* Map the syswake irqs */
for (i = 0; i < GPIO_PDC_NIRQ; ++i)
priv->irq[i] = irq_of_parse_and_map(np, i);
/* Add the GPIO bank */
gpiochip_add(&priv->chip);
return 0;
}
static struct of_device_id tz1090_pdc_gpio_of_match[] = {
{ .compatible = "img,tz1090-pdc-gpio" },
{ },
};
static struct platform_driver tz1090_pdc_gpio_driver = {
.driver = {
.name = "tz1090-pdc-gpio",
.owner = THIS_MODULE,
.of_match_table = tz1090_pdc_gpio_of_match,
},
.probe = tz1090_pdc_gpio_probe,
};
static int __init tz1090_pdc_gpio_init(void)
{
return platform_driver_register(&tz1090_pdc_gpio_driver);
}
subsys_initcall(tz1090_pdc_gpio_init);

606
drivers/gpio/gpio-tz1090.c Normal file
View File

@ -0,0 +1,606 @@
/*
* Toumaz Xenif TZ1090 GPIO handling.
*
* Copyright (C) 2008-2013 Imagination Technologies Ltd.
*
* Based on ARM PXA code and others.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/bitops.h>
#include <linux/export.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/of_irq.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/syscore_ops.h>
#include <asm/global_lock.h>
/* Register offsets from bank base address */
#define REG_GPIO_DIR 0x00
#define REG_GPIO_IRQ_PLRT 0x20
#define REG_GPIO_IRQ_TYPE 0x30
#define REG_GPIO_IRQ_EN 0x40
#define REG_GPIO_IRQ_STS 0x50
#define REG_GPIO_BIT_EN 0x60
#define REG_GPIO_DIN 0x70
#define REG_GPIO_DOUT 0x80
/* REG_GPIO_IRQ_PLRT */
#define REG_GPIO_IRQ_PLRT_LOW 0
#define REG_GPIO_IRQ_PLRT_HIGH 1
/* REG_GPIO_IRQ_TYPE */
#define REG_GPIO_IRQ_TYPE_LEVEL 0
#define REG_GPIO_IRQ_TYPE_EDGE 1
/**
* struct tz1090_gpio_bank - GPIO bank private data
* @chip: Generic GPIO chip for GPIO bank
* @domain: IRQ domain for GPIO bank (may be NULL)
* @reg: Base of registers, offset for this GPIO bank
* @irq: IRQ number for GPIO bank
* @label: Debug GPIO bank label, used for storage of chip->label
*
* This is the main private data for a GPIO bank. It encapsulates a gpio_chip,
* and the callbacks for the gpio_chip can access the private data with the
* to_bank() macro below.
*/
struct tz1090_gpio_bank {
struct gpio_chip chip;
struct irq_domain *domain;
void __iomem *reg;
int irq;
char label[16];
};
#define to_bank(c) container_of(c, struct tz1090_gpio_bank, chip)
/**
* struct tz1090_gpio - Overall GPIO device private data
* @dev: Device (from platform device)
* @reg: Base of GPIO registers
*
* Represents the overall GPIO device. This structure is actually only
* temporary, and used during init.
*/
struct tz1090_gpio {
struct device *dev;
void __iomem *reg;
};
/**
* struct tz1090_gpio_bank_info - Temporary registration info for GPIO bank
* @priv: Overall GPIO device private data
* @node: Device tree node specific to this GPIO bank
* @index: Index of bank in range 0-2
*/
struct tz1090_gpio_bank_info {
struct tz1090_gpio *priv;
struct device_node *node;
unsigned int index;
};
/* Convenience register accessors */
static inline void tz1090_gpio_write(struct tz1090_gpio_bank *bank,
unsigned int reg_offs, u32 data)
{
iowrite32(data, bank->reg + reg_offs);
}
static inline u32 tz1090_gpio_read(struct tz1090_gpio_bank *bank,
unsigned int reg_offs)
{
return ioread32(bank->reg + reg_offs);
}
/* caller must hold LOCK2 */
static inline void _tz1090_gpio_clear_bit(struct tz1090_gpio_bank *bank,
unsigned int reg_offs,
unsigned int offset)
{
u32 value;
value = tz1090_gpio_read(bank, reg_offs);
value &= ~BIT(offset);
tz1090_gpio_write(bank, reg_offs, value);
}
static void tz1090_gpio_clear_bit(struct tz1090_gpio_bank *bank,
unsigned int reg_offs,
unsigned int offset)
{
int lstat;
__global_lock2(lstat);
_tz1090_gpio_clear_bit(bank, reg_offs, offset);
__global_unlock2(lstat);
}
/* caller must hold LOCK2 */
static inline void _tz1090_gpio_set_bit(struct tz1090_gpio_bank *bank,
unsigned int reg_offs,
unsigned int offset)
{
u32 value;
value = tz1090_gpio_read(bank, reg_offs);
value |= BIT(offset);
tz1090_gpio_write(bank, reg_offs, value);
}
static void tz1090_gpio_set_bit(struct tz1090_gpio_bank *bank,
unsigned int reg_offs,
unsigned int offset)
{
int lstat;
__global_lock2(lstat);
_tz1090_gpio_set_bit(bank, reg_offs, offset);
__global_unlock2(lstat);
}
/* caller must hold LOCK2 */
static inline void _tz1090_gpio_mod_bit(struct tz1090_gpio_bank *bank,
unsigned int reg_offs,
unsigned int offset,
bool val)
{
u32 value;
value = tz1090_gpio_read(bank, reg_offs);
value &= ~BIT(offset);
if (val)
value |= BIT(offset);
tz1090_gpio_write(bank, reg_offs, value);
}
static void tz1090_gpio_mod_bit(struct tz1090_gpio_bank *bank,
unsigned int reg_offs,
unsigned int offset,
bool val)
{
int lstat;
__global_lock2(lstat);
_tz1090_gpio_mod_bit(bank, reg_offs, offset, val);
__global_unlock2(lstat);
}
static inline int tz1090_gpio_read_bit(struct tz1090_gpio_bank *bank,
unsigned int reg_offs,
unsigned int offset)
{
return tz1090_gpio_read(bank, reg_offs) & BIT(offset);
}
/* GPIO chip callbacks */
static int tz1090_gpio_direction_input(struct gpio_chip *chip,
unsigned int offset)
{
struct tz1090_gpio_bank *bank = to_bank(chip);
tz1090_gpio_set_bit(bank, REG_GPIO_DIR, offset);
return 0;
}
static int tz1090_gpio_direction_output(struct gpio_chip *chip,
unsigned int offset, int output_value)
{
struct tz1090_gpio_bank *bank = to_bank(chip);
int lstat;
__global_lock2(lstat);
_tz1090_gpio_mod_bit(bank, REG_GPIO_DOUT, offset, output_value);
_tz1090_gpio_clear_bit(bank, REG_GPIO_DIR, offset);
__global_unlock2(lstat);
return 0;
}
/*
* Return GPIO level
*/
static int tz1090_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct tz1090_gpio_bank *bank = to_bank(chip);
return tz1090_gpio_read_bit(bank, REG_GPIO_DIN, offset);
}
/*
* Set output GPIO level
*/
static void tz1090_gpio_set(struct gpio_chip *chip, unsigned int offset,
int output_value)
{
struct tz1090_gpio_bank *bank = to_bank(chip);
tz1090_gpio_mod_bit(bank, REG_GPIO_DOUT, offset, output_value);
}
static int tz1090_gpio_request(struct gpio_chip *chip, unsigned int offset)
{
struct tz1090_gpio_bank *bank = to_bank(chip);
int ret;
ret = pinctrl_request_gpio(chip->base + offset);
if (ret)
return ret;
tz1090_gpio_set_bit(bank, REG_GPIO_DIR, offset);
tz1090_gpio_set_bit(bank, REG_GPIO_BIT_EN, offset);
return 0;
}
static void tz1090_gpio_free(struct gpio_chip *chip, unsigned int offset)
{
struct tz1090_gpio_bank *bank = to_bank(chip);
pinctrl_free_gpio(chip->base + offset);
tz1090_gpio_clear_bit(bank, REG_GPIO_BIT_EN, offset);
}
static int tz1090_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
{
struct tz1090_gpio_bank *bank = to_bank(chip);
if (!bank->domain)
return -EINVAL;
return irq_create_mapping(bank->domain, offset);
}
/* IRQ chip handlers */
/* Get TZ1090 GPIO chip from irq data provided to generic IRQ callbacks */
static inline struct tz1090_gpio_bank *irqd_to_gpio_bank(struct irq_data *data)
{
return (struct tz1090_gpio_bank *)data->domain->host_data;
}
static void tz1090_gpio_irq_polarity(struct tz1090_gpio_bank *bank,
unsigned int offset, unsigned int polarity)
{
tz1090_gpio_mod_bit(bank, REG_GPIO_IRQ_PLRT, offset, polarity);
}
static void tz1090_gpio_irq_type(struct tz1090_gpio_bank *bank,
unsigned int offset, unsigned int type)
{
tz1090_gpio_mod_bit(bank, REG_GPIO_IRQ_TYPE, offset, type);
}
/* set polarity to trigger on next edge, whether rising or falling */
static void tz1090_gpio_irq_next_edge(struct tz1090_gpio_bank *bank,
unsigned int offset)
{
unsigned int value_p, value_i;
int lstat;
/*
* Set the GPIO's interrupt polarity to the opposite of the current
* input value so that the next edge triggers an interrupt.
*/
__global_lock2(lstat);
value_i = ~tz1090_gpio_read(bank, REG_GPIO_DIN);
value_p = tz1090_gpio_read(bank, REG_GPIO_IRQ_PLRT);
value_p &= ~BIT(offset);
value_p |= value_i & BIT(offset);
tz1090_gpio_write(bank, REG_GPIO_IRQ_PLRT, value_p);
__global_unlock2(lstat);
}
static unsigned int gpio_startup_irq(struct irq_data *data)
{
/*
* This warning indicates that the type of the irq hasn't been set
* before enabling the irq. This would normally be done by passing some
* trigger flags to request_irq().
*/
WARN(irqd_get_trigger_type(data) == IRQ_TYPE_NONE,
"irq type not set before enabling gpio irq %d", data->irq);
irq_gc_ack_clr_bit(data);
irq_gc_mask_set_bit(data);
return 0;
}
static int gpio_set_irq_type(struct irq_data *data, unsigned int flow_type)
{
struct tz1090_gpio_bank *bank = irqd_to_gpio_bank(data);
unsigned int type;
unsigned int polarity;
switch (flow_type) {
case IRQ_TYPE_EDGE_BOTH:
type = REG_GPIO_IRQ_TYPE_EDGE;
polarity = REG_GPIO_IRQ_PLRT_LOW;
break;
case IRQ_TYPE_EDGE_RISING:
type = REG_GPIO_IRQ_TYPE_EDGE;
polarity = REG_GPIO_IRQ_PLRT_HIGH;
break;
case IRQ_TYPE_EDGE_FALLING:
type = REG_GPIO_IRQ_TYPE_EDGE;
polarity = REG_GPIO_IRQ_PLRT_LOW;
break;
case IRQ_TYPE_LEVEL_HIGH:
type = REG_GPIO_IRQ_TYPE_LEVEL;
polarity = REG_GPIO_IRQ_PLRT_HIGH;
break;
case IRQ_TYPE_LEVEL_LOW:
type = REG_GPIO_IRQ_TYPE_LEVEL;
polarity = REG_GPIO_IRQ_PLRT_LOW;
break;
default:
return -EINVAL;
}
tz1090_gpio_irq_type(bank, data->hwirq, type);
irq_setup_alt_chip(data, flow_type);
if (flow_type == IRQ_TYPE_EDGE_BOTH)
tz1090_gpio_irq_next_edge(bank, data->hwirq);
else
tz1090_gpio_irq_polarity(bank, data->hwirq, polarity);
return 0;
}
#ifdef CONFIG_SUSPEND
static int gpio_set_irq_wake(struct irq_data *data, unsigned int on)
{
struct tz1090_gpio_bank *bank = irqd_to_gpio_bank(data);
#ifdef CONFIG_PM_DEBUG
pr_info("irq_wake irq%d state:%d\n", data->irq, on);
#endif
/* wake on gpio block interrupt */
return irq_set_irq_wake(bank->irq, on);
}
#else
#define gpio_set_irq_wake NULL
#endif
static void tz1090_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
{
irq_hw_number_t hw;
unsigned int irq_stat, irq_no;
struct tz1090_gpio_bank *bank;
struct irq_desc *child_desc;
bank = (struct tz1090_gpio_bank *)irq_desc_get_handler_data(desc);
irq_stat = tz1090_gpio_read(bank, REG_GPIO_DIR) &
tz1090_gpio_read(bank, REG_GPIO_IRQ_STS) &
tz1090_gpio_read(bank, REG_GPIO_IRQ_EN) &
0x3FFFFFFF; /* 30 bits only */
for (hw = 0; irq_stat; irq_stat >>= 1, ++hw) {
if (!(irq_stat & 1))
continue;
irq_no = irq_linear_revmap(bank->domain, hw);
child_desc = irq_to_desc(irq_no);
/* Toggle edge for pin with both edges triggering enabled */
if (irqd_get_trigger_type(&child_desc->irq_data)
== IRQ_TYPE_EDGE_BOTH)
tz1090_gpio_irq_next_edge(bank, hw);
generic_handle_irq_desc(irq_no, child_desc);
}
}
static int tz1090_gpio_bank_probe(struct tz1090_gpio_bank_info *info)
{
struct device_node *np = info->node;
struct device *dev = info->priv->dev;
struct tz1090_gpio_bank *bank;
struct irq_chip_generic *gc;
int err;
bank = devm_kzalloc(dev, sizeof(*bank), GFP_KERNEL);
if (!bank) {
dev_err(dev, "unable to allocate driver data\n");
return -ENOMEM;
}
/* Offset the main registers to the first register in this bank */
bank->reg = info->priv->reg + info->index * 4;
/* Set up GPIO chip */
snprintf(bank->label, sizeof(bank->label), "tz1090-gpio-%u",
info->index);
bank->chip.label = bank->label;
bank->chip.dev = dev;
bank->chip.direction_input = tz1090_gpio_direction_input;
bank->chip.direction_output = tz1090_gpio_direction_output;
bank->chip.get = tz1090_gpio_get;
bank->chip.set = tz1090_gpio_set;
bank->chip.free = tz1090_gpio_free;
bank->chip.request = tz1090_gpio_request;
bank->chip.to_irq = tz1090_gpio_to_irq;
bank->chip.of_node = np;
/* GPIO numbering from 0 */
bank->chip.base = info->index * 30;
bank->chip.ngpio = 30;
/* Add the GPIO bank */
gpiochip_add(&bank->chip);
/* Get the GPIO bank IRQ if provided */
bank->irq = irq_of_parse_and_map(np, 0);
/* The interrupt is optional (it may be used by another core on chip) */
if (bank->irq < 0) {
dev_info(dev, "IRQ not provided for bank %u, IRQs disabled\n",
info->index);
return 0;
}
dev_info(dev, "Setting up IRQs for GPIO bank %u\n",
info->index);
/*
* Initialise all interrupts to disabled so we don't get
* spurious ones on a dirty boot and hit the BUG_ON in the
* handler.
*/
tz1090_gpio_write(bank, REG_GPIO_IRQ_EN, 0);
/* Add a virtual IRQ for each GPIO */
bank->domain = irq_domain_add_linear(np,
bank->chip.ngpio,
&irq_generic_chip_ops,
bank);
/* Set up a generic irq chip with 2 chip types (level and edge) */
err = irq_alloc_domain_generic_chips(bank->domain, bank->chip.ngpio, 2,
bank->label, handle_bad_irq, 0, 0,
IRQ_GC_INIT_NESTED_LOCK);
if (err) {
dev_info(dev,
"irq_alloc_domain_generic_chips failed for bank %u, IRQs disabled\n",
info->index);
irq_domain_remove(bank->domain);
return 0;
}
gc = irq_get_domain_generic_chip(bank->domain, 0);
gc->reg_base = bank->reg;
/* level chip type */
gc->chip_types[0].type = IRQ_TYPE_LEVEL_MASK;
gc->chip_types[0].handler = handle_level_irq;
gc->chip_types[0].regs.ack = REG_GPIO_IRQ_STS;
gc->chip_types[0].regs.mask = REG_GPIO_IRQ_EN;
gc->chip_types[0].chip.irq_startup = gpio_startup_irq,
gc->chip_types[0].chip.irq_ack = irq_gc_ack_clr_bit,
gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit,
gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit,
gc->chip_types[0].chip.irq_set_type = gpio_set_irq_type,
gc->chip_types[0].chip.irq_set_wake = gpio_set_irq_wake,
gc->chip_types[0].chip.flags = IRQCHIP_MASK_ON_SUSPEND,
/* edge chip type */
gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH;
gc->chip_types[1].handler = handle_edge_irq;
gc->chip_types[1].regs.ack = REG_GPIO_IRQ_STS;
gc->chip_types[1].regs.mask = REG_GPIO_IRQ_EN;
gc->chip_types[1].chip.irq_startup = gpio_startup_irq,
gc->chip_types[1].chip.irq_ack = irq_gc_ack_clr_bit,
gc->chip_types[1].chip.irq_mask = irq_gc_mask_clr_bit,
gc->chip_types[1].chip.irq_unmask = irq_gc_mask_set_bit,
gc->chip_types[1].chip.irq_set_type = gpio_set_irq_type,
gc->chip_types[1].chip.irq_set_wake = gpio_set_irq_wake,
gc->chip_types[1].chip.flags = IRQCHIP_MASK_ON_SUSPEND,
/* Setup chained handler for this GPIO bank */
irq_set_handler_data(bank->irq, bank);
irq_set_chained_handler(bank->irq, tz1090_gpio_irq_handler);
return 0;
}
static void tz1090_gpio_register_banks(struct tz1090_gpio *priv)
{
struct device_node *np = priv->dev->of_node;
struct device_node *node;
for_each_available_child_of_node(np, node) {
struct tz1090_gpio_bank_info info;
u32 addr;
int ret;
ret = of_property_read_u32(node, "reg", &addr);
if (ret) {
dev_err(priv->dev, "invalid reg on %s\n",
node->full_name);
continue;
}
if (addr >= 3) {
dev_err(priv->dev, "index %u in %s out of range\n",
addr, node->full_name);
continue;
}
info.index = addr;
info.node = of_node_get(node);
info.priv = priv;
ret = tz1090_gpio_bank_probe(&info);
if (ret) {
dev_err(priv->dev, "failure registering %s\n",
node->full_name);
of_node_put(node);
continue;
}
}
}
static int tz1090_gpio_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct resource *res_regs;
struct tz1090_gpio priv;
if (!np) {
dev_err(&pdev->dev, "must be instantiated via devicetree\n");
return -ENOENT;
}
res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res_regs) {
dev_err(&pdev->dev, "cannot find registers resource\n");
return -ENOENT;
}
priv.dev = &pdev->dev;
/* Ioremap the registers */
priv.reg = devm_ioremap(&pdev->dev, res_regs->start,
res_regs->end - res_regs->start);
if (!priv.reg) {
dev_err(&pdev->dev, "unable to ioremap registers\n");
return -ENOMEM;
}
/* Look for banks */
tz1090_gpio_register_banks(&priv);
return 0;
}
static struct of_device_id tz1090_gpio_of_match[] = {
{ .compatible = "img,tz1090-gpio" },
{ },
};
static struct platform_driver tz1090_gpio_driver = {
.driver = {
.name = "tz1090-gpio",
.owner = THIS_MODULE,
.of_match_table = tz1090_gpio_of_match,
},
.probe = tz1090_gpio_probe,
};
static int __init tz1090_gpio_init(void)
{
return platform_driver_register(&tz1090_gpio_driver);
}
subsys_initcall(tz1090_gpio_init);

View File

@ -45,7 +45,7 @@ static void ucb1400_gpio_set(struct gpio_chip *gc, unsigned off, int val)
static int ucb1400_gpio_probe(struct platform_device *dev)
{
struct ucb1400_gpio *ucb = dev->dev.platform_data;
struct ucb1400_gpio *ucb = dev_get_platdata(&dev->dev);
int err = 0;
if (!(ucb && ucb->gpio_offset)) {

View File

@ -246,7 +246,7 @@ static struct gpio_chip template_chip = {
static int wm831x_gpio_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
struct wm831x_gpio *wm831x_gpio;
int ret;

View File

@ -112,7 +112,7 @@ static struct gpio_chip template_chip = {
static int wm8350_gpio_probe(struct platform_device *pdev)
{
struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent);
struct wm8350_platform_data *pdata = wm8350->dev->platform_data;
struct wm8350_platform_data *pdata = dev_get_platdata(wm8350->dev);
struct wm8350_gpio_data *wm8350_gpio;
int ret;

View File

@ -248,7 +248,7 @@ static struct gpio_chip template_chip = {
static int wm8994_gpio_probe(struct platform_device *pdev)
{
struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
struct wm8994_pdata *pdata = wm8994->dev->platform_data;
struct wm8994_pdata *pdata = dev_get_platdata(wm8994->dev);
struct wm8994_gpio *wm8994_gpio;
int ret;

View File

@ -76,7 +76,8 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname,
ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index,
&gg_data.gpiospec);
if (ret) {
pr_debug("%s: can't parse gpios property\n", __func__);
pr_debug("%s: can't parse gpios property of node '%s[%d]'\n",
__func__, np->full_name, index);
return ret;
}

View File

@ -349,7 +349,7 @@ static ssize_t gpio_value_store(struct device *dev,
else {
long value;
status = strict_strtol(buf, 0, &value);
status = kstrtol(buf, 0, &value);
if (status == 0) {
if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
value = !value;
@ -570,7 +570,7 @@ static ssize_t gpio_active_low_store(struct device *dev,
} else {
long value;
status = strict_strtol(buf, 0, &value);
status = kstrtol(buf, 0, &value);
if (status == 0)
status = sysfs_set_active_low(desc, dev, value != 0);
}
@ -652,7 +652,7 @@ static ssize_t export_store(struct class *class,
struct gpio_desc *desc;
int status;
status = strict_strtol(buf, 0, &gpio);
status = kstrtol(buf, 0, &gpio);
if (status < 0)
goto done;
@ -694,7 +694,7 @@ static ssize_t unexport_store(struct class *class,
struct gpio_desc *desc;
int status;
status = strict_strtol(buf, 0, &gpio);
status = kstrtol(buf, 0, &gpio);
if (status < 0)
goto done;
@ -1398,7 +1398,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
int status = -EPROBE_DEFER;
unsigned long flags;
if (!desc) {
if (!desc || !desc->chip) {
pr_warn("%s: invalid GPIO\n", __func__);
return -EINVAL;
}
@ -1406,8 +1406,6 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
spin_lock_irqsave(&gpio_lock, flags);
chip = desc->chip;
if (chip == NULL)
goto done;
if (!try_module_get(chip->owner))
goto done;
@ -1630,16 +1628,20 @@ static int gpiod_direction_input(struct gpio_desc *desc)
int status = -EINVAL;
int offset;
if (!desc) {
if (!desc || !desc->chip) {
pr_warn("%s: invalid GPIO\n", __func__);
return -EINVAL;
}
chip = desc->chip;
if (!chip->get || !chip->direction_input) {
pr_warn("%s: missing get() or direction_input() operations\n",
__func__);
return -EIO;
}
spin_lock_irqsave(&gpio_lock, flags);
chip = desc->chip;
if (!chip || !chip->get || !chip->direction_input)
goto fail;
status = gpio_ensure_requested(desc);
if (status < 0)
goto fail;
@ -1691,7 +1693,7 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)
int status = -EINVAL;
int offset;
if (!desc) {
if (!desc || !desc->chip) {
pr_warn("%s: invalid GPIO\n", __func__);
return -EINVAL;
}
@ -1704,11 +1706,15 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)
if (!value && test_bit(FLAG_OPEN_SOURCE, &desc->flags))
return gpiod_direction_input(desc);
chip = desc->chip;
if (!chip->set || !chip->direction_output) {
pr_warn("%s: missing set() or direction_output() operations\n",
__func__);
return -EIO;
}
spin_lock_irqsave(&gpio_lock, flags);
chip = desc->chip;
if (!chip || !chip->set || !chip->direction_output)
goto fail;
status = gpio_ensure_requested(desc);
if (status < 0)
goto fail;
@ -1757,6 +1763,9 @@ EXPORT_SYMBOL_GPL(gpio_direction_output);
* gpio_set_debounce - sets @debounce time for a @gpio
* @gpio: the gpio to set debounce time
* @debounce: debounce time is microseconds
*
* returns -ENOTSUPP if the controller does not support setting
* debounce.
*/
static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
{
@ -1765,16 +1774,19 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
int status = -EINVAL;
int offset;
if (!desc) {
if (!desc || !desc->chip) {
pr_warn("%s: invalid GPIO\n", __func__);
return -EINVAL;
}
spin_lock_irqsave(&gpio_lock, flags);
chip = desc->chip;
if (!chip || !chip->set || !chip->set_debounce)
goto fail;
if (!chip->set || !chip->set_debounce) {
pr_debug("%s: missing set() or set_debounce() operations\n",
__func__);
return -ENOTSUPP;
}
spin_lock_irqsave(&gpio_lock, flags);
status = gpio_ensure_requested(desc);
if (status < 0)

View File

@ -5,6 +5,7 @@ struct gpio_em_config {
unsigned int gpio_base;
unsigned int irq_base;
unsigned int number_of_pins;
const char *pctl_name;
};
#endif /* __GPIO_EM_H__ */