Commit a1df7efe authored by Linus Torvalds's avatar Linus Torvalds

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

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

  GPIOLIB core changes:
   - Create and use of_mm_gpiochip_remove() for removing memory-mapped
     OF GPIO chips
   - GPIO MMIO library suppports bgpio_set_multiple for switching
     several lines at once, a feature merged in the last cycle.

  New drivers:
   - New driver for the APM X-gene standby GPIO controller
   - New driver for the Fujitsu MB86S7x GPIO controller

  Cleanups:
   - Moved rcar driver to use gpiolib irqchip
   - Moxart converted to the GPIO MMIO library
   - GE driver converted to GPIO MMIO library
   - Move sx150x to irqdomain
   - Move max732x to irqdomain
   - Move vx855 to use managed resources
   - Move dwapb to use managed resources
   - Clean tc3589x from platform data
   - Clean stmpe driver to use device tree only probe

  New subtypes:
   - sx1506 support in the sx150x driver
   - Quark 1000 SoC support in the SCH driver
   - Support X86 in the Xilinx driver
   - Support PXA1928 in the PXA driver

  Extended drivers:
   - max732x supports device tree probe
   - sx150x supports device tree probe

  Various minor cleanups and bug fixes"

* tag 'gpio-v3.20-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (61 commits)
  gpio: kconfig: replace PPC_OF with PPC
  gpio: pxa: add PXA1928 gpio type support
  dt/bindings: gpio: add compatible string for marvell,pxa1928-gpio
  gpio: pxa: remove mach IRQ includes
  gpio: max732x: use an inline function for container cast
  gpio: use sizeof() instead of hardcoded values
  gpio: max732x: add set_multiple function
  gpio: sch: Consolidate similar algorithms
  gpio: tz1090-pdc: Use resource_size to fix off-by-one resource size calculation
  gpio: ge: Convert to use devm_kstrdup
  gpio: correctly use const char * const
  gpio: sx150x: fixup OF support
  gpio: mpc8xxx: Use of_mm_gpiochip_remove
  gpio: Add Fujitsu MB86S7x GPIO driver
  gpio: mpc8xxx: Convert to platform device interface.
  gpio: zevio: Use of_mm_gpiochip_remove
  gpio: gpio-mm-lantiq: Use of_mm_gpiochip_remove
  gpio: gpio-mm-lantiq: Use of_property_read_u32
  gpio: gpio-mm-lantiq: Do not replicate code
  gpio :gpio-mm-lantiq: Use devm_kzalloc
  ...
parents aa7ed01f 0a4a3529
Fujitsu MB86S7x GPIO Controller
-------------------------------
Required properties:
- compatible: Should be "fujitsu,mb86s70-gpio"
- reg: Base address and length of register space
- clocks: Specify the clock
- gpio-controller: Marks the device node as a gpio controller.
- #gpio-cells: Should be <2>. The first cell is the pin number and the
second cell is used to specify optional parameters:
- bit 0 specifies polarity (0 for normal, 1 for inverted).
Examples:
gpio0: gpio@31000000 {
compatible = "fujitsu,mb86s70-gpio";
reg = <0 0x31000000 0x10000>;
gpio-controller;
#gpio-cells = <2>;
clocks = <&clk 0 2 1>;
};
* MAX732x-compatible I/O expanders
Required properties:
- compatible: Should be one of the following:
- "maxim,max7319": For the Maxim MAX7319
- "maxim,max7320": For the Maxim MAX7320
- "maxim,max7321": For the Maxim MAX7321
- "maxim,max7322": For the Maxim MAX7322
- "maxim,max7323": For the Maxim MAX7323
- "maxim,max7324": For the Maxim MAX7324
- "maxim,max7325": For the Maxim MAX7325
- "maxim,max7326": For the Maxim MAX7326
- "maxim,max7327": For the Maxim MAX7327
- reg: I2C slave address for this device.
- gpio-controller: Marks the device node as a GPIO controller.
- #gpio-cells: Should be 2.
- first cell is the GPIO number
- second cell specifies GPIO flags, as defined in <dt-bindings/gpio/gpio.h>.
Only the GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported.
Optional properties:
The I/O expander can detect input state changes, and thus optionally act as
an interrupt controller. When the expander interrupt line is connected all the
following properties must be set. For more information please see the
interrupt controller device tree bindings documentation available at
Documentation/devicetree/bindings/interrupt-controller/interrupts.txt.
- interrupt-controller: Identifies the node as an interrupt controller.
- #interrupt-cells: Number of cells to encode an interrupt source, shall be 2.
- first cell is the pin number
- second cell is used to specify flags
- interrupt-parent: phandle of the parent interrupt controller.
- interrupts: Interrupt specifier for the controllers interrupt.
Please refer to gpio.txt in this directory for details of the common GPIO
bindings used by client devices.
Example 1. MAX7325 with interrupt support enabled (CONFIG_GPIO_MAX732X_IRQ=y):
expander: max7325@6d {
compatible = "maxim,max7325";
reg = <0x6d>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&gpio4>;
interrupts = <29 IRQ_TYPE_EDGE_FALLING>;
};
Example 2. MAX7325 with interrupt support disabled (CONFIG_GPIO_MAX732X_IRQ=n):
expander: max7325@6d {
compatible = "maxim,max7325";
reg = <0x6d>;
gpio-controller;
#gpio-cells = <2>;
};
SEMTECH SX150x GPIO expander bindings
Required properties:
- compatible: should be "semtech,sx1506q",
"semtech,sx1508q",
"semtech,sx1509q".
- reg: The I2C slave address for this device.
- interrupt-parent: phandle of the parent interrupt controller.
- interrupts: Interrupt specifier for the controllers interrupt.
- #gpio-cells: Should be 2. The first cell is the GPIO number and the
second cell is used to specify optional parameters:
bit 0: polarity (0: normal, 1: inverted)
- gpio-controller: Marks the device as a GPIO controller.
- interrupt-controller: Marks the device as a interrupt controller.
The GPIO expander can optionally be used as an interrupt controller, in
which case it uses the default two cell specifier as described in
Documentation/devicetree/bindings/interrupt-controller/interrupts.txt.
Example:
i2c_gpio_expander@20{
#gpio-cells = <2>;
#interrupt-cells = <2>;
compatible = "semtech,sx1506q";
reg = <0x20>;
interrupt-parent = <&gpio_1>;
interrupts = <16 0>;
gpio-controller;
interrupt-controller;
};
APM X-Gene Standby GPIO controller bindings
This is a gpio controller in the standby domain.
There are 20 GPIO pins from 0..21. There is no GPIO_DS14 or GPIO_DS15,
only GPIO_DS8..GPIO_DS13 support interrupts. The IRQ mapping
is currently 1-to-1 on interrupts 0x28 thru 0x2d.
Required properties:
- compatible: "apm,xgene-gpio-sb" for the X-Gene Standby GPIO controller
- reg: Physical base address and size of the controller's registers
- #gpio-cells: Should be two.
- first cell is the 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.
- interrupts: Shall contain exactly 6 interrupts.
Example:
sbgpio: sbgpio@17001000 {
compatible = "apm,xgene-gpio-sb";
reg = <0x0 0x17001000 0x0 0x400>;
#gpio-cells = <2>;
gpio-controller;
interrupts = <0x0 0x28 0x1>,
<0x0 0x29 0x1>,
<0x0 0x2a 0x1>,
<0x0 0x2b 0x1>,
<0x0 0x2c 0x1>,
<0x0 0x2d 0x1>;
};
...@@ -69,7 +69,8 @@ GPIO pin number, and GPIO flags as accepted by the "qe_pio_e" gpio-controller. ...@@ -69,7 +69,8 @@ GPIO pin number, and GPIO flags as accepted by the "qe_pio_e" gpio-controller.
---------------------------------- ----------------------------------
A gpio-specifier should contain a flag indicating the GPIO polarity; active- A gpio-specifier should contain a flag indicating the GPIO polarity; active-
high or active-low. If it does, the follow best practices should be followed: high or active-low. If it does, the following best practices should be
followed:
The gpio-specifier's polarity flag should represent the physical level at the The gpio-specifier's polarity flag should represent the physical level at the
GPIO controller that achieves (or represents, for inputs) a logically asserted GPIO controller that achieves (or represents, for inputs) a logically asserted
...@@ -147,7 +148,7 @@ contains information structures as follows: ...@@ -147,7 +148,7 @@ contains information structures as follows:
numeric-gpio-range ::= numeric-gpio-range ::=
<pinctrl-phandle> <gpio-base> <pinctrl-base> <count> <pinctrl-phandle> <gpio-base> <pinctrl-base> <count>
named-gpio-range ::= <pinctrl-phandle> <gpio-base> '<0 0>' named-gpio-range ::= <pinctrl-phandle> <gpio-base> '<0 0>'
gpio-phandle : phandle to pin controller node. pinctrl-phandle : phandle to pin controller node
gpio-base : Base GPIO ID in the GPIO controller gpio-base : Base GPIO ID in the GPIO controller
pinctrl-base : Base pinctrl pin ID in the pin controller pinctrl-base : Base pinctrl pin ID in the pin controller
count : The number of GPIOs/pins in this range count : The number of GPIOs/pins in this range
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
Required properties: Required properties:
- compatible : Should be "intel,pxa25x-gpio", "intel,pxa26x-gpio", - compatible : Should be "intel,pxa25x-gpio", "intel,pxa26x-gpio",
"intel,pxa27x-gpio", "intel,pxa3xx-gpio", "intel,pxa27x-gpio", "intel,pxa3xx-gpio",
"marvell,pxa93x-gpio", "marvell,mmp-gpio" or "marvell,pxa93x-gpio", "marvell,mmp-gpio",
"marvell,mmp2-gpio". "marvell,mmp2-gpio" or marvell,pxa1928-gpio.
- reg : Address and length of the register set for the device - reg : Address and length of the register set for the device
- interrupts : Should be the port interrupt shared by all gpio pins. - interrupts : Should be the port interrupt shared by all gpio pins.
There're three gpio interrupts in arch-pxa, and they're gpio0, There're three gpio interrupts in arch-pxa, and they're gpio0,
......
...@@ -143,6 +143,7 @@ sandisk Sandisk Corporation ...@@ -143,6 +143,7 @@ sandisk Sandisk Corporation
sbs Smart Battery System sbs Smart Battery System
schindler Schindler schindler Schindler
seagate Seagate Technology PLC seagate Seagate Technology PLC
semtech Semtech Corporation
sil Silicon Image sil Silicon Image
silabs Silicon Laboratories silabs Silicon Laboratories
simtek simtek
......
...@@ -197,9 +197,16 @@ config GPIO_F7188X ...@@ -197,9 +197,16 @@ config GPIO_F7188X
To compile this driver as a module, choose M here: the module will To compile this driver as a module, choose M here: the module will
be called f7188x-gpio. be called f7188x-gpio.
config GPIO_MB86S7X
bool "GPIO support for Fujitsu MB86S7x Platforms"
depends on ARCH_MB86S7X
help
Say yes here to support the GPIO controller in Fujitsu MB86S70 SoCs.
config GPIO_MOXART config GPIO_MOXART
bool "MOXART GPIO support" bool "MOXART GPIO support"
depends on ARCH_MOXART depends on ARCH_MOXART
select GPIO_GENERIC
help help
Select this option to enable GPIO driver for Select this option to enable GPIO driver for
MOXA ART SoC devices. MOXA ART SoC devices.
...@@ -285,6 +292,7 @@ config GPIO_PXA ...@@ -285,6 +292,7 @@ config GPIO_PXA
config GPIO_RCAR config GPIO_RCAR
tristate "Renesas R-Car GPIO" tristate "Renesas R-Car GPIO"
depends on ARM && (ARCH_SHMOBILE || COMPILE_TEST) depends on ARM && (ARCH_SHMOBILE || COMPILE_TEST)
select GPIOLIB_IRQCHIP
help help
Say yes here to support GPIO on Renesas R-Car SoCs. Say yes here to support GPIO on Renesas R-Car SoCs.
...@@ -365,9 +373,17 @@ config GPIO_XGENE ...@@ -365,9 +373,17 @@ config GPIO_XGENE
the generic flash controller's address and data pins. Say yes the generic flash controller's address and data pins. Say yes
here to enable the GFC GPIO functionality. here to enable the GFC GPIO functionality.
config GPIO_XGENE_SB
tristate "APM X-Gene GPIO standby controller support"
depends on ARCH_XGENE && OF_GPIO
select GPIO_GENERIC
help
This driver supports the GPIO block within the APM X-Gene
Standby Domain. Say yes here to enable the GPIO functionality.
config GPIO_XILINX config GPIO_XILINX
bool "Xilinx GPIO support" tristate "Xilinx GPIO support"
depends on PPC_OF || MICROBLAZE || ARCH_ZYNQ depends on OF_GPIO && (PPC || MICROBLAZE || ARCH_ZYNQ || X86)
help help
Say yes here to support the Xilinx FPGA GPIO device Say yes here to support the Xilinx FPGA GPIO device
...@@ -394,25 +410,32 @@ config GPIO_VR41XX ...@@ -394,25 +410,32 @@ config GPIO_VR41XX
Say yes here to support the NEC VR4100 series General-purpose I/O Uint Say yes here to support the NEC VR4100 series General-purpose I/O Uint
config GPIO_SCH config GPIO_SCH
tristate "Intel SCH/TunnelCreek/Centerton GPIO" tristate "Intel SCH/TunnelCreek/Centerton/Quark X1000 GPIO"
depends on PCI && X86 depends on PCI && X86
select MFD_CORE select MFD_CORE
select LPC_SCH select LPC_SCH
help help
Say yes here to support GPIO interface on Intel Poulsbo SCH, Say yes here to support GPIO interface on Intel Poulsbo SCH,
Intel Tunnel Creek processor or Intel Centerton processor. Intel Tunnel Creek processor, Intel Centerton processor or
Intel Quark X1000 SoC.
The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are
powered by the core power rail and are turned off during sleep powered by the core power rail and are turned off during sleep
modes (S3 and higher). The remaining four GPIOs are powered by modes (S3 and higher). The remaining four GPIOs are powered by
the Intel SCH suspend power supply. These GPIOs remain the Intel SCH suspend power supply. These GPIOs remain
active during S3. The suspend powered GPIOs can be used to wake the active during S3. The suspend powered GPIOs can be used to wake the
system from the Suspend-to-RAM state. system from the Suspend-to-RAM state.
The Intel Tunnel Creek processor has 5 GPIOs powered by the The Intel Tunnel Creek processor has 5 GPIOs powered by the
core power rail and 9 from suspend power supply. core power rail and 9 from suspend power supply.
The Intel Centerton processor has a total of 30 GPIO pins. The Intel Centerton processor has a total of 30 GPIO pins.
Twenty-one are powered by the core power rail and 9 from the Twenty-one are powered by the core power rail and 9 from the
suspend power supply. suspend power supply.
The Intel Quark X1000 SoC has 2 GPIOs powered by the core
power well and 6 from the suspend power well.
config GPIO_ICH config GPIO_ICH
tristate "Intel ICH GPIO" tristate "Intel ICH GPIO"
depends on PCI && X86 depends on PCI && X86
...@@ -450,6 +473,7 @@ config GPIO_VX855 ...@@ -450,6 +473,7 @@ config GPIO_VX855
config GPIO_GE_FPGA config GPIO_GE_FPGA
bool "GE FPGA based GPIO" bool "GE FPGA based GPIO"
depends on GE_FPGA depends on GE_FPGA
select GPIO_GENERIC
help help
Support for common GPIO functionality provided on some GE Single Board Support for common GPIO functionality provided on some GE Single Board
Computers. Computers.
...@@ -519,6 +543,7 @@ config GPIO_MAX7300 ...@@ -519,6 +543,7 @@ config GPIO_MAX7300
config GPIO_MAX732X config GPIO_MAX732X
tristate "MAX7319, MAX7320-7327 I2C Port Expanders" tristate "MAX7319, MAX7320-7327 I2C Port Expanders"
depends on I2C depends on I2C
select IRQ_DOMAIN
help help
Say yes here to support the MAX7319, MAX7320-7327 series of I2C Say yes here to support the MAX7319, MAX7320-7327 series of I2C
Port Expanders. Each IO port on these chips has a fixed role of Port Expanders. Each IO port on these chips has a fixed role of
...@@ -613,6 +638,7 @@ config GPIO_RC5T583 ...@@ -613,6 +638,7 @@ config GPIO_RC5T583
config GPIO_SX150X config GPIO_SX150X
bool "Semtech SX150x I2C GPIO expander" bool "Semtech SX150x I2C GPIO expander"
depends on I2C=y depends on I2C=y
select GPIOLIB_IRQCHIP
default n default n
help help
Say yes here to provide support for Semtech SX150-series I2C Say yes here to provide support for Semtech SX150-series I2C
...@@ -624,6 +650,7 @@ config GPIO_SX150X ...@@ -624,6 +650,7 @@ config GPIO_SX150X
config GPIO_STMPE config GPIO_STMPE
bool "STMPE GPIOs" bool "STMPE GPIOs"
depends on MFD_STMPE depends on MFD_STMPE
depends on OF_GPIO
select GPIOLIB_IRQCHIP select GPIOLIB_IRQCHIP
help help
This enables support for the GPIOs found on the STMPE I/O This enables support for the GPIOs found on the STMPE I/O
......
...@@ -48,6 +48,7 @@ obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o ...@@ -48,6 +48,7 @@ obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o
obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o
obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o
obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o
obj-$(CONFIG_GPIO_MB86S7X) += gpio-mb86s7x.o
obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o
obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o
obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o
...@@ -105,6 +106,7 @@ obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o ...@@ -105,6 +106,7 @@ obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o
obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o
obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o
obj-$(CONFIG_GPIO_XGENE) += gpio-xgene.o obj-$(CONFIG_GPIO_XGENE) += gpio-xgene.o
obj-$(CONFIG_GPIO_XGENE_SB) += gpio-xgene-sb.o
obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o
obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o
obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o
......
...@@ -213,6 +213,12 @@ static int __init amd_gpio_init(void) ...@@ -213,6 +213,12 @@ static int __init amd_gpio_init(void)
goto out; goto out;
} }
gp.pm = ioport_map(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE); gp.pm = ioport_map(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE);
if (!gp.pm) {
dev_err(&pdev->dev, "Couldn't map io port into io memory\n");
release_region(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE);
err = -ENOMEM;
goto out;
}
gp.pdev = pdev; gp.pdev = pdev;
gp.chip.dev = &pdev->dev; gp.chip.dev = &pdev->dev;
......
...@@ -396,6 +396,7 @@ static void dln2_gpio_event(struct platform_device *pdev, u16 echo, ...@@ -396,6 +396,7 @@ static void dln2_gpio_event(struct platform_device *pdev, u16 echo,
const void *data, int len) const void *data, int len)
{ {
int pin, irq; int pin, irq;
const struct { const struct {
__le16 count; __le16 count;
__u8 type; __u8 type;
......
...@@ -469,15 +469,13 @@ dwapb_gpio_get_pdata_of(struct device *dev) ...@@ -469,15 +469,13 @@ dwapb_gpio_get_pdata_of(struct device *dev)
if (nports == 0) if (nports == 0)
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) if (!pdata)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
pdata->properties = kcalloc(nports, sizeof(*pp), GFP_KERNEL); pdata->properties = devm_kcalloc(dev, nports, sizeof(*pp), GFP_KERNEL);
if (!pdata->properties) { if (!pdata->properties)
kfree(pdata);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
pdata->nports = nports; pdata->nports = nports;
...@@ -490,8 +488,6 @@ dwapb_gpio_get_pdata_of(struct device *dev) ...@@ -490,8 +488,6 @@ dwapb_gpio_get_pdata_of(struct device *dev)
pp->idx >= DWAPB_MAX_PORTS) { pp->idx >= DWAPB_MAX_PORTS) {
dev_err(dev, "missing/invalid port index for %s\n", dev_err(dev, "missing/invalid port index for %s\n",
port_np->full_name); port_np->full_name);
kfree(pdata->properties);
kfree(pdata);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
...@@ -523,15 +519,6 @@ dwapb_gpio_get_pdata_of(struct device *dev) ...@@ -523,15 +519,6 @@ dwapb_gpio_get_pdata_of(struct device *dev)
return pdata; return pdata;
} }
static inline void dwapb_free_pdata_of(struct dwapb_platform_data *pdata)
{
if (!IS_ENABLED(CONFIG_OF_GPIO) || !pdata)
return;
kfree(pdata->properties);
kfree(pdata);
}
static int dwapb_gpio_probe(struct platform_device *pdev) static int dwapb_gpio_probe(struct platform_device *pdev)
{ {
unsigned int i; unsigned int i;
...@@ -540,40 +527,32 @@ static int dwapb_gpio_probe(struct platform_device *pdev) ...@@ -540,40 +527,32 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
int err; int err;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct dwapb_platform_data *pdata = dev_get_platdata(dev); struct dwapb_platform_data *pdata = dev_get_platdata(dev);
bool is_pdata_alloc = !pdata;
if (is_pdata_alloc) { if (!pdata) {
pdata = dwapb_gpio_get_pdata_of(dev); pdata = dwapb_gpio_get_pdata_of(dev);
if (IS_ERR(pdata)) if (IS_ERR(pdata))
return PTR_ERR(pdata); return PTR_ERR(pdata);
} }
if (!pdata->nports) { if (!pdata->nports)
err = -ENODEV; return -ENODEV;
goto out_err;
}
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio) { if (!gpio)
err = -ENOMEM; return -ENOMEM;
goto out_err;
}
gpio->dev = &pdev->dev; gpio->dev = &pdev->dev;
gpio->nr_ports = pdata->nports; gpio->nr_ports = pdata->nports;
gpio->ports = devm_kcalloc(&pdev->dev, gpio->nr_ports, gpio->ports = devm_kcalloc(&pdev->dev, gpio->nr_ports,
sizeof(*gpio->ports), GFP_KERNEL); sizeof(*gpio->ports), GFP_KERNEL);
if (!gpio->ports) { if (!gpio->ports)
err = -ENOMEM; return -ENOMEM;
goto out_err;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
gpio->regs = devm_ioremap_resource(&pdev->dev, res); gpio->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(gpio->regs)) { if (IS_ERR(gpio->regs))
err = PTR_ERR(gpio->regs); return PTR_ERR(gpio->regs);
goto out_err;
}
for (i = 0; i < gpio->nr_ports; i++) { for (i = 0; i < gpio->nr_ports; i++) {
err = dwapb_gpio_add_port(gpio, &pdata->properties[i], i); err = dwapb_gpio_add_port(gpio, &pdata->properties[i], i);
...@@ -582,16 +561,12 @@ static int dwapb_gpio_probe(struct platform_device *pdev) ...@@ -582,16 +561,12 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
} }
platform_set_drvdata(pdev, gpio); platform_set_drvdata(pdev, gpio);
goto out_err; return 0;
out_unregister: out_unregister:
dwapb_gpio_unregister(gpio); dwapb_gpio_unregister(gpio);
dwapb_irq_teardown(gpio); dwapb_irq_teardown(gpio);
out_err:
if (is_pdata_alloc)
dwapb_free_pdata_of(pdata);
return err; return err;
} }
......
...@@ -19,9 +19,12 @@ ...@@ -19,9 +19,12 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/slab.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/of_address.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/basic_mmio_gpio.h>
#define GEF_GPIO_DIRECT 0x00 #define GEF_GPIO_DIRECT 0x00
#define GEF_GPIO_IN 0x04 #define GEF_GPIO_IN 0x04
...@@ -33,53 +36,6 @@ ...@@ -33,53 +36,6 @@
#define GEF_GPIO_OVERRUN 0x1C #define GEF_GPIO_OVERRUN 0x1C
#define GEF_GPIO_MODE 0x20 #define GEF_GPIO_MODE 0x20
static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
unsigned int data;
data = ioread32be(mmchip->regs + GEF_GPIO_OUT);
if (value)
data = data | BIT(offset);
else
data = data & ~BIT(offset);
iowrite32be(data, mmchip->regs + GEF_GPIO_OUT);
}
static int gef_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
{
unsigned int data;
struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
data = data | BIT(offset);
iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
return 0;
}
static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
{
unsigned int data;
struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
/* Set value before switching to output */
gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
data = data & ~BIT(offset);
iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
return 0;
}
static int gef_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
return !!(ioread32be(mmchip->regs + GEF_GPIO_IN) & BIT(offset));
}
static const struct of_device_id gef_gpio_ids[] = { static const struct of_device_id gef_gpio_ids[] = {
{ {
.compatible = "gef,sbc610-gpio", .compatible = "gef,sbc610-gpio",
...@@ -99,22 +55,50 @@ static int __init gef_gpio_probe(struct platform_device *pdev) ...@@ -99,22 +55,50 @@ static int __init gef_gpio_probe(struct platform_device *pdev)
{ {
const struct of_device_id *of_id = const struct of_device_id *of_id =
of_match_device(gef_gpio_ids, &pdev->dev); of_match_device(gef_gpio_ids, &pdev->dev);
struct of_mm_gpio_chip *mmchip; struct bgpio_chip *bgc;
void __iomem *regs;
int ret;
mmchip = devm_kzalloc(&pdev->dev, sizeof(*mmchip), GFP_KERNEL); bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL);
if (!mmchip) if (!bgc)
return -ENOMEM; return -ENOMEM;
regs = of_iomap(pdev->dev.of_node, 0);
if (!regs)
return -ENOMEM;
ret = bgpio_init(bgc, &pdev->dev, 4, regs + GEF_GPIO_IN,
regs + GEF_GPIO_OUT, NULL, NULL,
regs + GEF_GPIO_DIRECT, BGPIOF_BIG_ENDIAN_BYTE_ORDER);
if (ret) {
dev_err(&pdev->dev, "bgpio_init failed\n");
goto err0;
}
/* Setup pointers to chip functions */ /* Setup pointers to chip functions */
mmchip->gc.ngpio = (u16)(uintptr_t)of_id->data; bgc->gc.label = devm_kstrdup(&pdev->dev, pdev->dev.of_node->full_name,
mmchip->gc.of_gpio_n_cells = 2; GFP_KERNEL);
mmchip->gc.direction_input = gef_gpio_dir_in; if (!bgc->gc.label) {
mmchip->gc.direction_output = gef_gpio_dir_out; ret = -ENOMEM;
mmchip->gc.get = gef_gpio_get; goto err0;
mmchip->gc.set = gef_gpio_set; }
bgc->gc.base = -1;
bgc->gc.ngpio = (u16)(uintptr_t)of_id->data;
bgc->gc.of_gpio_n_cells = 2;
bgc->gc.of_node = pdev->dev.of_node;
/* This function adds a memory mapped GPIO chip */ /* This function adds a memory mapped GPIO chip */
return of_mm_gpiochip_add(pdev->dev.of_node, mmchip); ret = gpiochip_add(&bgc->gc);
if (ret)
goto err0;
return 0;
err0:
iounmap(regs);
pr_err("%s: GPIO chip registration failed\n",
pdev->dev.of_node->full_name);
return ret;
}; };
static struct platform_driver gef_gpio_driver = { static struct platform_driver gef_gpio_driver = {
......
...@@ -190,6 +190,79 @@ static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) ...@@ -190,6 +190,79 @@ static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
spin_unlock_irqrestore(&bgc->lock, flags); spin_unlock_irqrestore(&bgc->lock, flags);
} }
static void bgpio_multiple_get_masks(struct bgpio_chip *bgc,
unsigned long *mask, unsigned long *bits,
unsigned long *set_mask,
unsigned long *clear_mask)
{
int i;
*set_mask = 0;
*clear_mask = 0;
for (i = 0; i < bgc->bits; i++) {
if (*mask == 0)
break;
if (__test_and_clear_bit(i, mask)) {
if (test_bit(i, bits))
*set_mask |= bgc->pin2mask(bgc, i);
else
*clear_mask |= bgc->pin2mask(bgc, i);
}
}
}
static void bgpio_set_multiple_single_reg(struct bgpio_chip *bgc,
unsigned long *mask,
unsigned long *bits,
void __iomem *reg)
{
unsigned long flags;
unsigned long set_mask, clear_mask;
spin_lock_irqsave(&bgc->lock, flags);
bgpio_multiple_get_masks(bgc, mask, bits, &set_mask, &clear_mask);
bgc->data |= set_mask;
bgc->data &= ~clear_mask;
bgc->write_reg(reg, bgc->data);
spin_unlock_irqrestore(&bgc->lock, flags);
}
static void bgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask,
unsigned long *bits)
{
struct bgpio_chip *bgc = to_bgpio_chip(gc);
bgpio_set_multiple_single_reg(bgc, mask, bits, bgc->reg_dat);
}
static void bgpio_set_multiple_set(struct gpio_chip *gc, unsigned long *mask,
unsigned long *bits)
{
struct bgpio_chip *bgc = to_bgpio_chip(gc);
bgpio_set_multiple_single_reg(bgc, mask, bits, bgc->reg_set);
}
static void bgpio_set_multiple_with_clear(struct gpio_chip *gc,
unsigned long *mask,
unsigned long *bits)
{
struct bgpio_chip *bgc = to_bgpio_chip(gc);
unsigned long set_mask, clear_mask;
bgpio_multiple_get_masks(bgc, mask, bits, &set_mask, &clear_mask);
if (set_mask)
bgc->write_reg(bgc->reg_set, set_mask);
if (clear_mask)
bgc->write_reg(bgc->reg_clr, clear_mask);
}
static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio) static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio)
{ {
return 0; return 0;
...@@ -354,11 +427,14 @@ static int bgpio_setup_io(struct bgpio_chip *bgc, ...@@ -354,11 +427,14 @@ static int bgpio_setup_io(struct bgpio_chip *bgc,
bgc->reg_set = set; bgc->reg_set = set;
bgc->reg_clr = clr; bgc->reg_clr = clr;
bgc->gc.set = bgpio_set_with_clear; bgc->gc.set = bgpio_set_with_clear;
bgc->gc.set_multiple = bgpio_set_multiple_with_clear;
} else if (set && !clr) { } else if (set && !clr) {
bgc->reg_set = set; bgc->reg_set = set;
bgc->gc.set = bgpio_set_set; bgc->gc.set = bgpio_set_set;
bgc->gc.set_multiple = bgpio_set_multiple_set;
} else { } else {
bgc->gc.set = bgpio_set; bgc->gc.set = bgpio_set;
bgc->gc.set_multiple = bgpio_set_multiple;
} }
bgc->gc.get = bgpio_get; bgc->gc.get = bgpio_get;
......
...@@ -121,7 +121,7 @@ static int grgpio_to_irq(struct gpio_chip *gc, unsigned offset) ...@@ -121,7 +121,7 @@ static int grgpio_to_irq(struct gpio_chip *gc, unsigned offset)
{ {
struct grgpio_priv *priv = grgpio_gc_to_priv(gc); struct grgpio_priv *priv = grgpio_gc_to_priv(gc);
if (offset > gc->ngpio) if (offset >= gc->ngpio)
return -ENXIO; return -ENXIO;
if (priv->lirqs[offset].index < 0) if (priv->lirqs[offset].index < 0)
......
...@@ -19,8 +19,10 @@ ...@@ -19,8 +19,10 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/max732x.h> #include <linux/i2c/max732x.h>
#include <linux/of.h>
/* /*
...@@ -116,6 +118,22 @@ static const struct i2c_device_id max732x_id[] = { ...@@ -116,6 +118,22 @@ static const struct i2c_device_id max732x_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, max732x_id); MODULE_DEVICE_TABLE(i2c, max732x_id);
#ifdef CONFIG_OF
static const struct of_device_id max732x_of_table[] = {
{ .compatible = "maxim,max7319" },
{ .compatible = "maxim,max7320" },
{ .compatible = "maxim,max7321" },
{ .compatible = "maxim,max7322" },
{ .compatible = "maxim,max7323" },
{ .compatible = "maxim,max7324" },
{ .compatible = "maxim,max7325" },
{ .compatible = "maxim,max7326" },
{ .compatible = "maxim,max7327" },
{ }
};
MODULE_DEVICE_TABLE(of, max732x_of_table);
#endif
struct max732x_chip { struct max732x_chip {
struct gpio_chip gpio_chip; struct gpio_chip gpio_chip;
...@@ -132,16 +150,22 @@ struct max732x_chip { ...@@ -132,16 +150,22 @@ struct max732x_chip {
uint8_t reg_out[2]; uint8_t reg_out[2];
#ifdef CONFIG_GPIO_MAX732X_IRQ #ifdef CONFIG_GPIO_MAX732X_IRQ
struct mutex irq_lock; struct irq_domain *irq_domain;
int irq_base; struct mutex irq_lock;
uint8_t irq_mask; int irq_base;
uint8_t irq_mask_cur; uint8_t irq_mask;
uint8_t irq_trig_raise; uint8_t irq_mask_cur;
uint8_t irq_trig_fall; uint8_t irq_trig_raise;
uint8_t irq_features; uint8_t irq_trig_fall;
uint8_t irq_features;
#endif #endif
}; };
static inline struct max732x_chip *to_max732x(struct gpio_chip *gc)
{
return container_of(gc, struct max732x_chip, gpio_chip);
}
static int max732x_writeb(struct max732x_chip *chip, int group_a, uint8_t val) static int max732x_writeb(struct max732x_chip *chip, int group_a, uint8_t val)
{ {
struct i2c_client *client; struct i2c_client *client;
...@@ -180,12 +204,10 @@ static inline int is_group_a(struct max732x_chip *chip, unsigned off) ...@@ -180,12 +204,10 @@ static inline int is_group_a(struct max732x_chip *chip, unsigned off)
static int max732x_gpio_get_value(struct gpio_chip *gc, unsigned off) static int max732x_gpio_get_value(struct gpio_chip *gc, unsigned off)
{ {
struct max732x_chip *chip; struct max732x_chip *chip = to_max732x(gc);
uint8_t reg_val; uint8_t reg_val;
int ret; int ret;
chip = container_of(gc, struct max732x_chip, gpio_chip);
ret = max732x_readb(chip, is_group_a(chip, off), &reg_val); ret = max732x_readb(chip, is_group_a(chip, off), &reg_val);
if (ret < 0) if (ret < 0)
return 0; return 0;
...@@ -193,18 +215,17 @@ static int max732x_gpio_get_value(struct gpio_chip *gc, unsigned off) ...@@ -193,18 +215,17 @@ static int max732x_gpio_get_value(struct gpio_chip *gc, unsigned off)
return reg_val & (1u << (off & 0x7)); return reg_val & (1u << (off & 0x7));
} }
static void max732x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) static void max732x_gpio_set_mask(struct gpio_chip *gc, unsigned off, int mask,
int val)
{ {
struct max732x_chip *chip; struct max732x_chip *chip = to_max732x(gc);
uint8_t reg_out, mask = 1u << (off & 0x7); uint8_t reg_out;
int ret; int ret;
chip = container_of(gc, struct max732x_chip, gpio_chip);
mutex_lock(&chip->lock); mutex_lock(&chip->lock);
reg_out = (off > 7) ? chip->reg_out[1] : chip->reg_out[0]; reg_out = (off > 7) ? chip->reg_out[1] : chip->reg_out[0];
reg_out = (val) ? reg_out | mask : reg_out & ~mask; reg_out = (reg_out & ~mask) | (val & mask);
ret = max732x_writeb(chip, is_group_a(chip, off), reg_out); ret = max732x_writeb(chip, is_group_a(chip, off), reg_out);
if (ret < 0) if (ret < 0)
...@@ -219,13 +240,31 @@ static void max732x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) ...@@ -219,13 +240,31 @@ static void max732x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
mutex_unlock(&chip->lock); mutex_unlock(&chip->lock);
} }
static void max732x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
{
unsigned base = off & ~0x7;
uint8_t mask = 1u << (off & 0x7);
max732x_gpio_set_mask(gc, base, mask, val << (off & 0x7));
}
static void max732x_gpio_set_multiple(struct gpio_chip *gc,
unsigned long *mask, unsigned long *bits)
{
unsigned mask_lo = mask[0] & 0xff;
unsigned mask_hi = (mask[0] >> 8) & 0xff;
if (mask_lo)
max732x_gpio_set_mask(gc, 0, mask_lo, bits[0] & 0xff);
if (mask_hi)
max732x_gpio_set_mask(gc, 8, mask_hi, (bits[0] >> 8) & 0xff);
}
static int max732x_gpio_direction_input(struct gpio_chip *gc, unsigned off) static int max732x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
{ {
struct max732x_chip *chip; struct max732x_chip *chip = to_max732x(gc);
unsigned int mask = 1u << off; unsigned int mask = 1u << off;
chip = container_of(gc, struct max732x_chip, gpio_chip);
if ((mask & chip->dir_input) == 0) { if ((mask & chip->dir_input) == 0) {
dev_dbg(&chip->client->dev, "%s port %d is output only\n", dev_dbg(&chip->client->dev, "%s port %d is output only\n",
chip->client->name, off); chip->client->name, off);
...@@ -245,11 +284,9 @@ static int max732x_gpio_direction_input(struct gpio_chip *gc, unsigned off) ...@@ -245,11 +284,9 @@ static int max732x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
static int max732x_gpio_direction_output(struct gpio_chip *gc, static int max732x_gpio_direction_output(struct gpio_chip *gc,
unsigned off, int val) unsigned off, int val)
{ {
struct max732x_chip *chip; struct max732x_chip *chip = to_max732x(gc);
unsigned int mask = 1u << off; unsigned int mask = 1u << off;
chip = container_of(gc, struct max732x_chip, gpio_chip);
if ((mask & chip->dir_output) == 0) { if ((mask & chip->dir_output) == 0) {
dev_dbg(&chip->client->dev, "%s port %d is input only\n", dev_dbg(&chip->client->dev, "%s port %d is input only\n",
chip->client->name, off); chip->client->name, off);
...@@ -321,24 +358,28 @@ static void max732x_irq_update_mask(struct max732x_chip *chip) ...@@ -321,24 +358,28 @@ static void max732x_irq_update_mask(struct max732x_chip *chip)
static int max732x_gpio_to_irq(struct gpio_chip *gc, unsigned off) static int max732x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
{ {
struct max732x_chip *chip; struct max732x_chip *chip = to_max732x(gc);
chip = container_of(gc, struct max732x_chip, gpio_chip); if (chip->irq_domain) {
return chip->irq_base + off; return irq_create_mapping(chip->irq_domain,
chip->irq_base + off);
} else {
return -ENXIO;
}
} }
static void max732x_irq_mask(struct irq_data *d) static void max732x_irq_mask(struct irq_data *d)
{ {
struct max732x_chip *chip = irq_data_get_irq_chip_data(d); struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
chip->irq_mask_cur &= ~(1 << (d->irq - chip->irq_base)); chip->irq_mask_cur &= ~(1 << d->hwirq);
} }
static void max732x_irq_unmask(struct irq_data *d) static void max732x_irq_unmask(struct irq_data *d)
{ {
struct max732x_chip *chip = irq_data_get_irq_chip_data(d); struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
chip->irq_mask_cur |= 1 << (d->irq - chip->irq_base); chip->irq_mask_cur |= 1 << d->hwirq;
} }
static void max732x_irq_bus_lock(struct irq_data *d) static void max732x_irq_bus_lock(struct irq_data *d)
...@@ -352,15 +393,25 @@ static void max732x_irq_bus_lock(struct irq_data *d) ...@@ -352,15 +393,25 @@ static void max732x_irq_bus_lock(struct irq_data *d)
static void max732x_irq_bus_sync_unlock(struct irq_data *d) static void max732x_irq_bus_sync_unlock(struct irq_data *d)
{ {
struct max732x_chip *chip = irq_data_get_irq_chip_data(d); struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
uint16_t new_irqs;
uint16_t level;
max732x_irq_update_mask(chip); max732x_irq_update_mask(chip);
new_irqs = chip->irq_trig_fall | chip->irq_trig_raise;
while (new_irqs) {
level = __ffs(new_irqs);
max732x_gpio_direction_input(&chip->gpio_chip, level);
new_irqs &= ~(1 << level);
}
mutex_unlock(&chip->irq_lock); mutex_unlock(&chip->irq_lock);
} }
static int max732x_irq_set_type(struct irq_data *d, unsigned int type) static int max732x_irq_set_type(struct irq_data *d, unsigned int type)
{ {
struct max732x_chip *chip = irq_data_get_irq_chip_data(d); struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
uint16_t off = d->irq - chip->irq_base; uint16_t off = d->hwirq;
uint16_t mask = 1 << off; uint16_t mask = 1 << off;
if (!(mask & chip->dir_input)) { if (!(mask & chip->dir_input)) {
...@@ -385,7 +436,7 @@ static int max732x_irq_set_type(struct irq_data *d, unsigned int type) ...@@ -385,7 +436,7 @@ static int max732x_irq_set_type(struct irq_data *d, unsigned int type)
else else
chip->irq_trig_raise &= ~mask; chip->irq_trig_raise &= ~mask;
return max732x_gpio_direction_input(&chip->gpio_chip, off); return 0;
} }
static struct irq_chip max732x_irq_chip = { static struct irq_chip max732x_irq_chip = {
...@@ -441,7 +492,7 @@ static irqreturn_t max732x_irq_handler(int irq, void *devid) ...@@ -441,7 +492,7 @@ static irqreturn_t max732x_irq_handler(int irq, void *devid)
do { do {
level = __ffs(pending); level = __ffs(pending);
handle_nested_irq(level + chip->irq_base); handle_nested_irq(irq_find_mapping(chip->irq_domain, level));
pending &= ~(1 << level); pending &= ~(1 << level);
} while (pending); } while (pending);
...@@ -449,6 +500,44 @@ static irqreturn_t max732x_irq_handler(int irq, void *devid) ...@@ -449,6 +500,44 @@ static irqreturn_t max732x_irq_handler(int irq, void *devid)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int max732x_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
struct max732x_chip *chip = h->host_data;
if (!(chip->dir_input & (1 << hw))) {
dev_err(&chip->client->dev,
"Attempt to map output line as IRQ line: %lu\n",
hw);
return -EPERM;
}
irq_set_chip_data(virq, chip);
irq_set_chip_and_handler(virq, &max732x_irq_chip,
handle_edge_irq);
irq_set_nested_thread(virq, 1);
#ifdef CONFIG_ARM
/* ARM needs us to explicitly flag the IRQ as valid
* and will set them noprobe when we do so. */
set_irq_flags(virq, IRQF_VALID);
#else
irq_set_noprobe(virq);
#endif
return 0;
}
static struct irq_domain_ops max732x_irq_domain_ops = {
.map = max732x_irq_map,
.xlate = irq_domain_xlate_twocell,
};
static void max732x_irq_teardown(struct max732x_chip *chip)
{
if (chip->client->irq && chip->irq_domain)
irq_domain_remove(chip->irq_domain);
}
static int max732x_irq_setup(struct max732x_chip *chip, static int max732x_irq_setup(struct max732x_chip *chip,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -457,28 +546,19 @@ static int max732x_irq_setup(struct max732x_chip *chip, ...@@ -457,28 +546,19 @@ static int max732x_irq_setup(struct max732x_chip *chip,
int has_irq = max732x_features[id->driver_data] >> 32; int has_irq = max732x_features[id->driver_data] >> 32;
int ret; int ret;
if (pdata->irq_base && has_irq != INT_NONE) { if (((pdata && pdata->irq_base) || client->irq)
int lvl; && has_irq != INT_NONE) {
if (pdata)
chip->irq_base = pdata->irq_base; chip->irq_base = pdata->irq_base;
chip->irq_features = has_irq; chip->irq_features = has_irq;
mutex_init(&chip->irq_lock); mutex_init(&chip->irq_lock);
for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) { chip->irq_domain = irq_domain_add_simple(client->dev.of_node,
int irq = lvl + chip->irq_base; chip->gpio_chip.ngpio, chip->irq_base,
&max732x_irq_domain_ops, chip);
if (!(chip->dir_input & (1 << lvl))) if (!chip->irq_domain) {
continue; dev_err(&client->dev, "Failed to create IRQ domain\n");
return -ENOMEM;
irq_set_chip_data(irq, chip);
irq_set_chip_and_handler(irq, &max732x_irq_chip,
handle_edge_irq);
irq_set_nested_thread(irq, 1);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(irq);
#endif
} }
ret = request_threaded_irq(client->irq, ret = request_threaded_irq(client->irq,
...@@ -498,15 +578,10 @@ static int max732x_irq_setup(struct max732x_chip *chip, ...@@ -498,15 +578,10 @@ static int max732x_irq_setup(struct max732x_chip *chip,
return 0; return 0;
out_failed: out_failed:
chip->irq_base = 0; max732x_irq_teardown(chip);
return ret; return ret;
} }
static void max732x_irq_teardown(struct max732x_chip *chip)
{
if (chip->irq_base)
free_irq(chip->client->irq, chip);
}
#else /* CONFIG_GPIO_MAX732X_IRQ */ #else /* CONFIG_GPIO_MAX732X_IRQ */
static int max732x_irq_setup(struct max732x_chip *chip, static int max732x_irq_setup(struct max732x_chip *chip,
const struct i2c_device_id *id) const struct i2c_device_id *id)
...@@ -515,7 +590,7 @@ static int max732x_irq_setup(struct max732x_chip *chip, ...@@ -515,7 +590,7 @@ static int max732x_irq_setup(struct max732x_chip *chip,
struct max732x_platform_data *pdata = dev_get_platdata(&client->dev); struct max732x_platform_data *pdata = dev_get_platdata(&client->dev);
int has_irq = max732x_features[id->driver_data] >> 32; int has_irq = max732x_features[id->driver_data] >> 32;
if (pdata->irq_base && has_irq != INT_NONE) if (((pdata && pdata->irq_base) || client->irq) && has_irq != INT_NONE)
dev_warn(&client->dev, "interrupt support not compiled in\n"); dev_warn(&client->dev, "interrupt support not compiled in\n");
return 0; return 0;
...@@ -562,6 +637,7 @@ static int max732x_setup_gpio(struct max732x_chip *chip, ...@@ -562,6 +637,7 @@ static int max732x_setup_gpio(struct max732x_chip *chip,
if (chip->dir_output) { if (chip->dir_output) {
gc->direction_output = max732x_gpio_direction_output; gc->direction_output = max732x_gpio_direction_output;
gc->set = max732x_gpio_set_value; gc->set = max732x_gpio_set_value;
gc->set_multiple = max732x_gpio_set_multiple;
} }
gc->get = max732x_gpio_get_value; gc->get = max732x_gpio_get_value;
gc->can_sleep = true; gc->can_sleep = true;
...@@ -574,28 +650,47 @@ static int max732x_setup_gpio(struct max732x_chip *chip, ...@@ -574,28 +650,47 @@ static int max732x_setup_gpio(struct max732x_chip *chip,
return port; return port;
} }
static struct max732x_platform_data *of_gpio_max732x(struct device *dev)
{
struct max732x_platform_data *pdata;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return NULL;
pdata->gpio_base = -1;
return pdata;
}
static int max732x_probe(struct i2c_client *client, static int max732x_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct max732x_platform_data *pdata; struct max732x_platform_data *pdata;
struct device_node *node;
struct max732x_chip *chip; struct max732x_chip *chip;
struct i2c_client *c; struct i2c_client *c;
uint16_t addr_a, addr_b; uint16_t addr_a, addr_b;
int ret, nr_port; int ret, nr_port;
pdata = dev_get_platdata(&client->dev); pdata = dev_get_platdata(&client->dev);
if (pdata == NULL) { node = client->dev.of_node;
if (!pdata && node)
pdata = of_gpio_max732x(&client->dev);
if (!pdata) {
dev_dbg(&client->dev, "no platform data\n"); dev_dbg(&client->dev, "no platform data\n");
return -EINVAL; return -EINVAL;
} }
chip = devm_kzalloc(&client->dev, sizeof(struct max732x_chip), chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
GFP_KERNEL);
if (chip == NULL) if (chip == NULL)
return -ENOMEM; return -ENOMEM;
chip->client = client; chip->client = client;
nr_port = max732x_setup_gpio(chip, id, pdata->gpio_base); nr_port = max732x_setup_gpio(chip, id, pdata->gpio_base);
chip->gpio_chip.dev = &client->dev;
addr_a = (client->addr & 0x0f) | 0x60; addr_a = (client->addr & 0x0f) | 0x60;
addr_b = (client->addr & 0x0f) | 0x50; addr_b = (client->addr & 0x0f) | 0x50;
...@@ -643,7 +738,7 @@ static int max732x_probe(struct i2c_client *client, ...@@ -643,7 +738,7 @@ static int max732x_probe(struct i2c_client *client,
if (ret) if (ret)
goto out_failed; goto out_failed;
if (pdata->setup) { if (pdata && pdata->setup) {
ret = pdata->setup(client, chip->gpio_chip.base, ret = pdata->setup(client, chip->gpio_chip.base,
chip->gpio_chip.ngpio, pdata->context); chip->gpio_chip.ngpio, pdata->context);
if (ret < 0) if (ret < 0)
...@@ -664,9 +759,10 @@ static int max732x_remove(struct i2c_client *client) ...@@ -664,9 +759,10 @@ static int max732x_remove(struct i2c_client *client)
{ {
struct max732x_platform_data *pdata = dev_get_platdata(&client->dev); struct max732x_platform_data *pdata = dev_get_platdata(&client->dev);
struct max732x_chip *chip = i2c_get_clientdata(client); struct max732x_chip *chip = i2c_get_clientdata(client);
int ret;
if (pdata->teardown) { if (pdata && pdata->teardown) {
int ret;
ret = pdata->teardown(client, chip->gpio_chip.base, ret = pdata->teardown(client, chip->gpio_chip.base,
chip->gpio_chip.ngpio, pdata->context); chip->gpio_chip.ngpio, pdata->context);
if (ret < 0) { if (ret < 0) {
...@@ -689,8 +785,9 @@ static int max732x_remove(struct i2c_client *client) ...@@ -689,8 +785,9 @@ static int max732x_remove(struct i2c_client *client)
static struct i2c_driver max732x_driver = { static struct i2c_driver max732x_driver = {
.driver = { .driver = {
.name = "max732x", .name = "max732x",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = of_match_ptr(max732x_of_table),
}, },
.probe = max732x_probe, .probe = max732x_probe,
.remove = max732x_remove, .remove = max732x_remove,
......
/*
* linux/drivers/gpio/gpio-mb86s7x.c
*
* Copyright (C) 2015 Fujitsu Semiconductor Limited
* Copyright (C) 2015 Linaro Ltd.
*
* 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, version 2 of the License.
*
* 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/io.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/of_device.h>
#include <linux/gpio/driver.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
/*
* Only first 8bits of a register correspond to each pin,
* so there are 4 registers for 32 pins.
*/
#define PDR(x) (0x0 + x / 8 * 4)
#define DDR(x) (0x10 + x / 8 * 4)
#define PFR(x) (0x20 + x / 8 * 4)
#define OFFSET(x) BIT((x) % 8)
struct mb86s70_gpio_chip {
struct gpio_chip gc;
void __iomem *base;
struct clk *clk;
spinlock_t lock;
};
static inline struct mb86s70_gpio_chip *chip_to_mb86s70(struct gpio_chip *gc)
{
return container_of(gc, struct mb86s70_gpio_chip, gc);
}
static int mb86s70_gpio_request(struct gpio_chip *gc, unsigned gpio)
{
struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
unsigned long flags;
u32 val;
spin_lock_irqsave(&gchip->lock, flags);
val = readl(gchip->base + PFR(gpio));
val &= ~OFFSET(gpio);
writel(val, gchip->base + PFR(gpio));
spin_unlock_irqrestore(&gchip->lock, flags);
return 0;
}
static void mb86s70_gpio_free(struct gpio_chip *gc, unsigned gpio)
{
struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
unsigned long flags;
u32 val;
spin_lock_irqsave(&gchip->lock, flags);
val = readl(gchip->base + PFR(gpio));
val |= OFFSET(gpio);
writel(val, gchip->base + PFR(gpio));
spin_unlock_irqrestore(&gchip->lock, flags);
}
static int mb86s70_gpio_direction_input(struct gpio_chip *gc, unsigned gpio)
{
struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
unsigned long flags;
unsigned char val;
spin_lock_irqsave(&gchip->lock, flags);
val = readl(gchip->base + DDR(gpio));
val &= ~OFFSET(gpio);
writel(val, gchip->base + DDR(gpio));
spin_unlock_irqrestore(&gchip->lock, flags);
return 0;
}
static int mb86s70_gpio_direction_output(struct gpio_chip *gc,
unsigned gpio, int value)
{
struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
unsigned long flags;
unsigned char val;
spin_lock_irqsave(&gchip->lock, flags);
val = readl(gchip->base + PDR(gpio));
if (value)
val |= OFFSET(gpio);
else
val &= ~OFFSET(gpio);
writel(val, gchip->base + PDR(gpio));
val = readl(gchip->base + DDR(gpio));
val |= OFFSET(gpio);
writel(val, gchip->base + DDR(gpio));
spin_unlock_irqrestore(&gchip->lock, flags);
return 0;
}
static int mb86s70_gpio_get(struct gpio_chip *gc, unsigned gpio)
{
struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
return !!(readl(gchip->base + PDR(gpio)) & OFFSET(gpio));
}
static void mb86s70_gpio_set(struct gpio_chip *gc, unsigned gpio, int value)
{
struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
unsigned long flags;
unsigned char val;
spin_lock_irqsave(&gchip->lock, flags);
val = readl(gchip->base + PDR(gpio));
if (value)
val |= OFFSET(gpio);
else
val &= ~OFFSET(gpio);
writel(val, gchip->base + PDR(gpio));
spin_unlock_irqrestore(&gchip->lock, flags);
}
static int mb86s70_gpio_probe(struct platform_device *pdev)
{
struct mb86s70_gpio_chip *gchip;
struct resource *res;
int ret;
gchip = devm_kzalloc(&pdev->dev, sizeof(*gchip), GFP_KERNEL);
if (gchip == NULL)
return -ENOMEM;
platform_set_drvdata(pdev, gchip);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
gchip->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(gchip->base))
return PTR_ERR(gchip->base);
gchip->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(gchip->clk))
return PTR_ERR(gchip->clk);
clk_prepare_enable(gchip->clk);
spin_lock_init(&gchip->lock);
gchip->gc.direction_output = mb86s70_gpio_direction_output;
gchip->gc.direction_input = mb86s70_gpio_direction_input;
gchip->gc.request = mb86s70_gpio_request;
gchip->gc.free = mb86s70_gpio_free;
gchip->gc.get = mb86s70_gpio_get;
gchip->gc.set = mb86s70_gpio_set;
gchip->gc.label = dev_name(&pdev->dev);
gchip->gc.ngpio = 32;
gchip->gc.owner = THIS_MODULE;
gchip->gc.dev = &pdev->dev;
gchip->gc.base = -1;
platform_set_drvdata(pdev, gchip);
ret = gpiochip_add(&gchip->gc);
if (ret) {
dev_err(&pdev->dev, "couldn't register gpio driver\n");
clk_disable_unprepare(gchip->clk);
}
return ret;
}
static int mb86s70_gpio_remove(struct platform_device *pdev)
{
struct mb86s70_gpio_chip *gchip = platform_get_drvdata(pdev);
gpiochip_remove(&gchip->gc);
clk_disable_unprepare(gchip->clk);
return 0;
}
static const struct of_device_id mb86s70_gpio_dt_ids[] = {
{ .compatible = "fujitsu,mb86s70-gpio" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mb86s70_gpio_dt_ids);
static struct platform_driver mb86s70_gpio_driver = {
.driver = {
.name = "mb86s70-gpio",
.of_match_table = mb86s70_gpio_dt_ids,
},
.probe = mb86s70_gpio_probe,
.remove = mb86s70_gpio_remove,
};
static int __init mb86s70_gpio_init(void)
{
return platform_driver_register(&mb86s70_gpio_driver);
}
module_init(mb86s70_gpio_init);
MODULE_DESCRIPTION("MB86S7x GPIO Driver");
MODULE_ALIAS("platform:mb86s70-gpio");
MODULE_LICENSE("GPL");
...@@ -104,35 +104,34 @@ static void ltq_mm_save_regs(struct of_mm_gpio_chip *mm_gc) ...@@ -104,35 +104,34 @@ static void ltq_mm_save_regs(struct of_mm_gpio_chip *mm_gc)
static int ltq_mm_probe(struct platform_device *pdev) static int ltq_mm_probe(struct platform_device *pdev)
{ {
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct ltq_mm *chip; struct ltq_mm *chip;
const __be32 *shadow; u32 shadow;
int ret = 0;
if (!res) { chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
dev_err(&pdev->dev, "failed to get memory resource\n");
return -ENOENT;
}
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (!chip) if (!chip)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(pdev, chip);
chip->mmchip.gc.ngpio = 16; chip->mmchip.gc.ngpio = 16;
chip->mmchip.gc.label = "gpio-mm-ltq";
chip->mmchip.gc.direction_output = ltq_mm_dir_out; chip->mmchip.gc.direction_output = ltq_mm_dir_out;
chip->mmchip.gc.set = ltq_mm_set; chip->mmchip.gc.set = ltq_mm_set;
chip->mmchip.save_regs = ltq_mm_save_regs; chip->mmchip.save_regs = ltq_mm_save_regs;
/* store the shadow value if one was passed by the devicetree */ /* store the shadow value if one was passed by the devicetree */
shadow = of_get_property(pdev->dev.of_node, "lantiq,shadow", NULL); if (!of_property_read_u32(pdev->dev.of_node, "lantiq,shadow", &shadow))
if (shadow) chip->shadow = shadow;
chip->shadow = be32_to_cpu(*shadow);
return of_mm_gpiochip_add(pdev->dev.of_node, &chip->mmchip);
ret = of_mm_gpiochip_add(pdev->dev.of_node, &chip->mmchip); }
if (ret)
kfree(chip); static int ltq_mm_remove(struct platform_device *pdev)
return ret; {
struct ltq_mm *chip = platform_get_drvdata(pdev);
of_mm_gpiochip_remove(&chip->mmchip);
return 0;
} }
static const struct of_device_id ltq_mm_match[] = { static const struct of_device_id ltq_mm_match[] = {
...@@ -143,6 +142,7 @@ MODULE_DEVICE_TABLE(of, ltq_mm_match); ...@@ -143,6 +142,7 @@ MODULE_DEVICE_TABLE(of, ltq_mm_match);
static struct platform_driver ltq_mm_driver = { static struct platform_driver ltq_mm_driver = {
.probe = ltq_mm_probe, .probe = ltq_mm_probe,
.remove = ltq_mm_remove,
.driver = { .driver = {
.name = "gpio-mm-ltq", .name = "gpio-mm-ltq",
.of_match_table = ltq_mm_match, .of_match_table = ltq_mm_match,
...@@ -155,3 +155,9 @@ static int __init ltq_mm_init(void) ...@@ -155,3 +155,9 @@ static int __init ltq_mm_init(void)
} }
subsys_initcall(ltq_mm_init); subsys_initcall(ltq_mm_init);
static void __exit ltq_mm_exit(void)
{
platform_driver_unregister(&ltq_mm_driver);
}
module_exit(ltq_mm_exit);
...@@ -23,21 +23,12 @@ ...@@ -23,21 +23,12 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/basic_mmio_gpio.h>
#define GPIO_DATA_OUT 0x00 #define GPIO_DATA_OUT 0x00
#define GPIO_DATA_IN 0x04 #define GPIO_DATA_IN 0x04
#define GPIO_PIN_DIRECTION 0x08 #define GPIO_PIN_DIRECTION 0x08
struct moxart_gpio_chip {
struct gpio_chip gpio;
void __iomem *base;
};
static inline struct moxart_gpio_chip *to_moxart_gpio(struct gpio_chip *chip)
{
return container_of(chip, struct moxart_gpio_chip, gpio);
}
static int moxart_gpio_request(struct gpio_chip *chip, unsigned offset) static int moxart_gpio_request(struct gpio_chip *chip, unsigned offset)
{ {
return pinctrl_request_gpio(offset); return pinctrl_request_gpio(offset);
...@@ -48,90 +39,60 @@ static void moxart_gpio_free(struct gpio_chip *chip, unsigned offset) ...@@ -48,90 +39,60 @@ static void moxart_gpio_free(struct gpio_chip *chip, unsigned offset)
pinctrl_free_gpio(offset); pinctrl_free_gpio(offset);
} }
static void moxart_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct moxart_gpio_chip *gc = to_moxart_gpio(chip);
void __iomem *ioaddr = gc->base + GPIO_DATA_OUT;
u32 reg = readl(ioaddr);
if (value)
reg = reg | BIT(offset);
else
reg = reg & ~BIT(offset);
writel(reg, ioaddr);
}
static int moxart_gpio_get(struct gpio_chip *chip, unsigned offset) static int moxart_gpio_get(struct gpio_chip *chip, unsigned offset)
{ {
struct moxart_gpio_chip *gc = to_moxart_gpio(chip); struct bgpio_chip *bgc = to_bgpio_chip(chip);
u32 ret = readl(gc->base + GPIO_PIN_DIRECTION); u32 ret = bgc->read_reg(bgc->reg_dir);
if (ret & BIT(offset)) if (ret & BIT(offset))
return !!(readl(gc->base + GPIO_DATA_OUT) & BIT(offset)); return !!(bgc->read_reg(bgc->reg_set) & BIT(offset));
else else
return !!(readl(gc->base + GPIO_DATA_IN) & BIT(offset)); return !!(bgc->read_reg(bgc->reg_dat) & BIT(offset));
}
static int moxart_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
struct moxart_gpio_chip *gc = to_moxart_gpio(chip);
void __iomem *ioaddr = gc->base + GPIO_PIN_DIRECTION;
writel(readl(ioaddr) & ~BIT(offset), ioaddr);
return 0;
}
static int moxart_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value)
{
struct moxart_gpio_chip *gc = to_moxart_gpio(chip);
void __iomem *ioaddr = gc->base + GPIO_PIN_DIRECTION;
moxart_gpio_set(chip, offset, value);
writel(readl(ioaddr) | BIT(offset), ioaddr);
return 0;
} }
static struct gpio_chip moxart_template_chip = {
.label = "moxart-gpio",
.request = moxart_gpio_request,
.free = moxart_gpio_free,
.direction_input = moxart_gpio_direction_input,
.direction_output = moxart_gpio_direction_output,
.set = moxart_gpio_set,
.get = moxart_gpio_get,
.ngpio = 32,
.owner = THIS_MODULE,
};
static int moxart_gpio_probe(struct platform_device *pdev) static int moxart_gpio_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct resource *res; struct resource *res;
struct moxart_gpio_chip *mgc; struct bgpio_chip *bgc;
void __iomem *base;
int ret; int ret;
mgc = devm_kzalloc(dev, sizeof(*mgc), GFP_KERNEL); bgc = devm_kzalloc(dev, sizeof(*bgc), GFP_KERNEL);
if (!mgc) if (!bgc)
return -ENOMEM; return -ENOMEM;
mgc->gpio = moxart_template_chip;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mgc->base = devm_ioremap_resource(dev, res); base = devm_ioremap_resource(dev, res);
if (IS_ERR(mgc->base)) if (IS_ERR(base))
return PTR_ERR(mgc->base); return PTR_ERR(base);
mgc->gpio.dev = dev; ret = bgpio_init(bgc, dev, 4, base + GPIO_DATA_IN,
base + GPIO_DATA_OUT, NULL,
base + GPIO_PIN_DIRECTION, NULL, 0);
if (ret) {
dev_err(&pdev->dev, "bgpio_init failed\n");
return ret;
}
ret = gpiochip_add(&mgc->gpio); bgc->gc.label = "moxart-gpio";
bgc->gc.request = moxart_gpio_request;
bgc->gc.free = moxart_gpio_free;
bgc->gc.get = moxart_gpio_get;
bgc->data = bgc->read_reg(bgc->reg_set);
bgc->gc.base = 0;
bgc->gc.ngpio = 32;
bgc->gc.dev = dev;
bgc->gc.owner = THIS_MODULE;
ret = gpiochip_add(&bgc->gc);
if (ret) { if (ret) {
dev_err(dev, "%s: gpiochip_add failed\n", dev_err(dev, "%s: gpiochip_add failed\n",
dev->of_node->full_name); dev->of_node->full_name);
return ret; return ret;
} }
return 0; return ret;
} }
static const struct of_device_id moxart_gpio_match[] = { static const struct of_device_id moxart_gpio_match[] = {
......
...@@ -155,10 +155,12 @@ static int mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev) ...@@ -155,10 +155,12 @@ static int mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
struct gpio_chip *gc; struct gpio_chip *gc;
int ret; int ret;
chip = kzalloc(sizeof(*chip), GFP_KERNEL); chip = devm_kzalloc(&ofdev->dev, sizeof(*chip), GFP_KERNEL);
if (!chip) if (!chip)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(ofdev, chip);
gc = &chip->mmchip.gc; gc = &chip->mmchip.gc;
gc->ngpio = 8; gc->ngpio = 8;
...@@ -181,7 +183,11 @@ static int mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev) ...@@ -181,7 +183,11 @@ static int mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
static int mpc52xx_gpiochip_remove(struct platform_device *ofdev) static int mpc52xx_gpiochip_remove(struct platform_device *ofdev)
{ {
return -EBUSY; struct mpc52xx_gpiochip *chip = platform_get_drvdata(ofdev);
of_mm_gpiochip_remove(&chip->mmchip);
return 0;
} }
static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = { static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = {
...@@ -314,10 +320,12 @@ static int mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev) ...@@ -314,10 +320,12 @@ static int mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)
struct mpc52xx_gpio __iomem *regs; struct mpc52xx_gpio __iomem *regs;
int ret; int ret;
chip = kzalloc(sizeof(*chip), GFP_KERNEL); chip = devm_kzalloc(&ofdev->dev, sizeof(*chip), GFP_KERNEL);
if (!chip) if (!chip)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(ofdev, chip);
gc = &chip->mmchip.gc; gc = &chip->mmchip.gc;
gc->ngpio = 32; gc->ngpio = 32;
...@@ -363,11 +371,16 @@ static int __init mpc52xx_gpio_init(void) ...@@ -363,11 +371,16 @@ static int __init mpc52xx_gpio_init(void)
return 0; return 0;
} }
/* Make sure we get initialised before anyone else tries to use us */ /* Make sure we get initialised before anyone else tries to use us */
subsys_initcall(mpc52xx_gpio_init); subsys_initcall(mpc52xx_gpio_init);
/* No exit call at the moment as we cannot unregister of gpio chips */ static void __exit mpc52xx_gpio_exit(void)
{
platform_driver_unregister(&mpc52xx_wkup_gpiochip_driver);
platform_driver_unregister(&mpc52xx_simple_gpiochip_driver);
}
module_exit(mpc52xx_gpio_exit);
MODULE_DESCRIPTION("Freescale MPC52xx gpio driver"); MODULE_DESCRIPTION("Freescale MPC52xx gpio driver");
MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de"); MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de");
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/irq.h> #include <linux/irq.h>
...@@ -39,6 +40,7 @@ struct mpc8xxx_gpio_chip { ...@@ -39,6 +40,7 @@ struct mpc8xxx_gpio_chip {
*/ */
u32 data; u32 data;
struct irq_domain *irq; struct irq_domain *irq;
unsigned int irqn;
const void *of_dev_id_data; const void *of_dev_id_data;
}; };
...@@ -342,20 +344,20 @@ static struct of_device_id mpc8xxx_gpio_ids[] __initdata = { ...@@ -342,20 +344,20 @@ static struct of_device_id mpc8xxx_gpio_ids[] __initdata = {
{} {}
}; };
static void __init mpc8xxx_add_controller(struct device_node *np) static int mpc8xxx_probe(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node;
struct mpc8xxx_gpio_chip *mpc8xxx_gc; struct mpc8xxx_gpio_chip *mpc8xxx_gc;
struct of_mm_gpio_chip *mm_gc; struct of_mm_gpio_chip *mm_gc;
struct gpio_chip *gc; struct gpio_chip *gc;
const struct of_device_id *id; const struct of_device_id *id;
unsigned hwirq;
int ret; int ret;
mpc8xxx_gc = kzalloc(sizeof(*mpc8xxx_gc), GFP_KERNEL); mpc8xxx_gc = devm_kzalloc(&pdev->dev, sizeof(*mpc8xxx_gc), GFP_KERNEL);
if (!mpc8xxx_gc) { if (!mpc8xxx_gc)
ret = -ENOMEM; return -ENOMEM;
goto err;
} platform_set_drvdata(pdev, mpc8xxx_gc);
spin_lock_init(&mpc8xxx_gc->lock); spin_lock_init(&mpc8xxx_gc->lock);
...@@ -375,16 +377,16 @@ static void __init mpc8xxx_add_controller(struct device_node *np) ...@@ -375,16 +377,16 @@ static void __init mpc8xxx_add_controller(struct device_node *np)
ret = of_mm_gpiochip_add(np, mm_gc); ret = of_mm_gpiochip_add(np, mm_gc);
if (ret) if (ret)
goto err; return ret;
hwirq = irq_of_parse_and_map(np, 0); mpc8xxx_gc->irqn = irq_of_parse_and_map(np, 0);
if (hwirq == NO_IRQ) if (mpc8xxx_gc->irqn == NO_IRQ)
goto skip_irq; return 0;
mpc8xxx_gc->irq = irq_domain_add_linear(np, MPC8XXX_GPIO_PINS, mpc8xxx_gc->irq = irq_domain_add_linear(np, MPC8XXX_GPIO_PINS,
&mpc8xxx_gpio_irq_ops, mpc8xxx_gc); &mpc8xxx_gpio_irq_ops, mpc8xxx_gc);
if (!mpc8xxx_gc->irq) if (!mpc8xxx_gc->irq)
goto skip_irq; return 0;
id = of_match_node(mpc8xxx_gpio_ids, np); id = of_match_node(mpc8xxx_gpio_ids, np);
if (id) if (id)
...@@ -394,27 +396,39 @@ static void __init mpc8xxx_add_controller(struct device_node *np) ...@@ -394,27 +396,39 @@ static void __init mpc8xxx_add_controller(struct device_node *np)
out_be32(mm_gc->regs + GPIO_IER, 0xffffffff); out_be32(mm_gc->regs + GPIO_IER, 0xffffffff);
out_be32(mm_gc->regs + GPIO_IMR, 0); out_be32(mm_gc->regs + GPIO_IMR, 0);
irq_set_handler_data(hwirq, mpc8xxx_gc); irq_set_handler_data(mpc8xxx_gc->irqn, mpc8xxx_gc);
irq_set_chained_handler(hwirq, mpc8xxx_gpio_irq_cascade); irq_set_chained_handler(mpc8xxx_gc->irqn, mpc8xxx_gpio_irq_cascade);
skip_irq:
return;
err:
pr_err("%s: registration failed with status %d\n",
np->full_name, ret);
kfree(mpc8xxx_gc);
return; return 0;
} }
static int __init mpc8xxx_add_gpiochips(void) static int mpc8xxx_remove(struct platform_device *pdev)
{ {
struct device_node *np; struct mpc8xxx_gpio_chip *mpc8xxx_gc = platform_get_drvdata(pdev);
if (mpc8xxx_gc->irq) {
irq_set_handler_data(mpc8xxx_gc->irqn, NULL);
irq_set_chained_handler(mpc8xxx_gc->irqn, NULL);
irq_domain_remove(mpc8xxx_gc->irq);
}
for_each_matching_node(np, mpc8xxx_gpio_ids) of_mm_gpiochip_remove(&mpc8xxx_gc->mm_gc);
mpc8xxx_add_controller(np);
return 0; return 0;
} }
arch_initcall(mpc8xxx_add_gpiochips);
static struct platform_driver mpc8xxx_plat_driver = {
.probe = mpc8xxx_probe,
.remove = mpc8xxx_remove,
.driver = {
.name = "gpio-mpc8xxx",
.of_match_table = mpc8xxx_gpio_ids,
},
};
static int __init mpc8xxx_init(void)
{
return platform_driver_register(&mpc8xxx_plat_driver);
}
arch_initcall(mpc8xxx_init);
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
#define GPIO_LEVEL_MASK_OFF 0x001c #define GPIO_LEVEL_MASK_OFF 0x001c
/* The MV78200 has per-CPU registers for edge mask and level mask */ /* The MV78200 has per-CPU registers for edge mask and level mask */
#define GPIO_EDGE_MASK_MV78200_OFF(cpu) ((cpu) ? 0x30 : 0x18) #define GPIO_EDGE_MASK_MV78200_OFF(cpu) ((cpu) ? 0x30 : 0x18)
#define GPIO_LEVEL_MASK_MV78200_OFF(cpu) ((cpu) ? 0x34 : 0x1C) #define GPIO_LEVEL_MASK_MV78200_OFF(cpu) ((cpu) ? 0x34 : 0x1C)
/* The Armada XP has per-CPU registers for interrupt cause, interrupt /* The Armada XP has per-CPU registers for interrupt cause, interrupt
...@@ -69,11 +69,11 @@ ...@@ -69,11 +69,11 @@
#define GPIO_EDGE_MASK_ARMADAXP_OFF(cpu) (0x10 + (cpu) * 0x4) #define GPIO_EDGE_MASK_ARMADAXP_OFF(cpu) (0x10 + (cpu) * 0x4)
#define GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu) (0x20 + (cpu) * 0x4) #define GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu) (0x20 + (cpu) * 0x4)
#define MVEBU_GPIO_SOC_VARIANT_ORION 0x1 #define MVEBU_GPIO_SOC_VARIANT_ORION 0x1
#define MVEBU_GPIO_SOC_VARIANT_MV78200 0x2 #define MVEBU_GPIO_SOC_VARIANT_MV78200 0x2
#define MVEBU_GPIO_SOC_VARIANT_ARMADAXP 0x3 #define MVEBU_GPIO_SOC_VARIANT_ARMADAXP 0x3
#define MVEBU_MAX_GPIO_PER_BANK 32 #define MVEBU_MAX_GPIO_PER_BANK 32
struct mvebu_gpio_chip { struct mvebu_gpio_chip {
struct gpio_chip chip; struct gpio_chip chip;
...@@ -82,9 +82,9 @@ struct mvebu_gpio_chip { ...@@ -82,9 +82,9 @@ struct mvebu_gpio_chip {
void __iomem *percpu_membase; void __iomem *percpu_membase;
int irqbase; int irqbase;
struct irq_domain *domain; struct irq_domain *domain;
int soc_variant; int soc_variant;
/* Used to preserve GPIO registers accross suspend/resume */ /* Used to preserve GPIO registers across suspend/resume */
u32 out_reg; u32 out_reg;
u32 io_conf_reg; u32 io_conf_reg;
u32 blink_en_reg; u32 blink_en_reg;
...@@ -107,7 +107,8 @@ static inline void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip) ...@@ -107,7 +107,8 @@ static inline void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip)
return mvchip->membase + GPIO_BLINK_EN_OFF; return mvchip->membase + GPIO_BLINK_EN_OFF;
} }
static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip) static inline void __iomem *
mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip)
{ {
return mvchip->membase + GPIO_IO_CONF_OFF; return mvchip->membase + GPIO_IO_CONF_OFF;
} }
...@@ -117,12 +118,14 @@ static inline void __iomem *mvebu_gpioreg_in_pol(struct mvebu_gpio_chip *mvchip) ...@@ -117,12 +118,14 @@ static inline void __iomem *mvebu_gpioreg_in_pol(struct mvebu_gpio_chip *mvchip)
return mvchip->membase + GPIO_IN_POL_OFF; return mvchip->membase + GPIO_IN_POL_OFF;
} }
static inline void __iomem *mvebu_gpioreg_data_in(struct mvebu_gpio_chip *mvchip) static inline void __iomem *
mvebu_gpioreg_data_in(struct mvebu_gpio_chip *mvchip)
{ {
return mvchip->membase + GPIO_DATA_IN_OFF; return mvchip->membase + GPIO_DATA_IN_OFF;
} }
static inline void __iomem *mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip) static inline void __iomem *
mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip)
{ {
int cpu; int cpu;
...@@ -132,13 +135,15 @@ static inline void __iomem *mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvc ...@@ -132,13 +135,15 @@ static inline void __iomem *mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvc
return mvchip->membase + GPIO_EDGE_CAUSE_OFF; return mvchip->membase + GPIO_EDGE_CAUSE_OFF;
case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
cpu = smp_processor_id(); cpu = smp_processor_id();
return mvchip->percpu_membase + GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu); return mvchip->percpu_membase +
GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu);
default: default:
BUG(); BUG();
} }
} }
static inline void __iomem *mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvchip) static inline void __iomem *
mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvchip)
{ {
int cpu; int cpu;
...@@ -150,7 +155,8 @@ static inline void __iomem *mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvch ...@@ -150,7 +155,8 @@ static inline void __iomem *mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvch
return mvchip->membase + GPIO_EDGE_MASK_MV78200_OFF(cpu); return mvchip->membase + GPIO_EDGE_MASK_MV78200_OFF(cpu);
case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
cpu = smp_processor_id(); cpu = smp_processor_id();
return mvchip->percpu_membase + GPIO_EDGE_MASK_ARMADAXP_OFF(cpu); return mvchip->percpu_membase +
GPIO_EDGE_MASK_ARMADAXP_OFF(cpu);
default: default:
BUG(); BUG();
} }
...@@ -168,7 +174,8 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip) ...@@ -168,7 +174,8 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip)
return mvchip->membase + GPIO_LEVEL_MASK_MV78200_OFF(cpu); return mvchip->membase + GPIO_LEVEL_MASK_MV78200_OFF(cpu);
case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
cpu = smp_processor_id(); cpu = smp_processor_id();
return mvchip->percpu_membase + GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu); return mvchip->percpu_membase +
GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu);
default: default:
BUG(); BUG();
} }
...@@ -364,22 +371,22 @@ static void mvebu_gpio_level_irq_unmask(struct irq_data *d) ...@@ -364,22 +371,22 @@ static void mvebu_gpio_level_irq_unmask(struct irq_data *d)
* value of the line or the opposite value. * value of the line or the opposite value.
* *
* Level IRQ handlers: DATA_IN is used directly as cause register. * Level IRQ handlers: DATA_IN is used directly as cause register.
* Interrupt are masked by LEVEL_MASK registers. * Interrupt are masked by LEVEL_MASK registers.
* Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE. * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE.
* Interrupt are masked by EDGE_MASK registers. * Interrupt are masked by EDGE_MASK registers.
* Both-edge handlers: Similar to regular Edge handlers, but also swaps * Both-edge handlers: Similar to regular Edge handlers, but also swaps
* the polarity to catch the next line transaction. * the polarity to catch the next line transaction.
* This is a race condition that might not perfectly * This is a race condition that might not perfectly
* work on some use cases. * work on some use cases.
* *
* Every eight GPIO lines are grouped (OR'ed) before going up to main * Every eight GPIO lines are grouped (OR'ed) before going up to main
* cause register. * cause register.
* *
* EDGE cause mask * EDGE cause mask
* data-in /--------| |-----| |----\ * data-in /--------| |-----| |----\
* -----| |----- ---- to main cause reg * -----| |----- ---- to main cause reg
* X \----------------| |----/ * X \----------------| |----/
* polarity LEVEL mask * polarity LEVEL mask
* *
****************************************************************************/ ****************************************************************************/
...@@ -394,9 +401,8 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type) ...@@ -394,9 +401,8 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
pin = d->hwirq; pin = d->hwirq;
u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin); u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin);
if (!u) { if (!u)
return -EINVAL; return -EINVAL;
}
type &= IRQ_TYPE_SENSE_MASK; type &= IRQ_TYPE_SENSE_MASK;
if (type == IRQ_TYPE_NONE) if (type == IRQ_TYPE_NONE)
...@@ -529,13 +535,13 @@ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) ...@@ -529,13 +535,13 @@ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
(data_in ^ in_pol) & msk ? "hi" : "lo", (data_in ^ in_pol) & msk ? "hi" : "lo",
in_pol & msk ? "lo" : "hi"); in_pol & msk ? "lo" : "hi");
if (!((edg_msk | lvl_msk) & msk)) { if (!((edg_msk | lvl_msk) & msk)) {
seq_printf(s, " disabled\n"); seq_puts(s, " disabled\n");
continue; continue;
} }
if (edg_msk & msk) if (edg_msk & msk)
seq_printf(s, " edge "); seq_puts(s, " edge ");
if (lvl_msk & msk) if (lvl_msk & msk)
seq_printf(s, " level"); seq_puts(s, " level");
seq_printf(s, " (%s)\n", cause & msk ? "pending" : "clear "); seq_printf(s, " (%s)\n", cause & msk ? "pending" : "clear ");
} }
} }
...@@ -546,15 +552,15 @@ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) ...@@ -546,15 +552,15 @@ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
static const struct of_device_id mvebu_gpio_of_match[] = { static const struct of_device_id mvebu_gpio_of_match[] = {
{ {
.compatible = "marvell,orion-gpio", .compatible = "marvell,orion-gpio",
.data = (void *) MVEBU_GPIO_SOC_VARIANT_ORION, .data = (void *) MVEBU_GPIO_SOC_VARIANT_ORION,
}, },
{ {
.compatible = "marvell,mv78200-gpio", .compatible = "marvell,mv78200-gpio",
.data = (void *) MVEBU_GPIO_SOC_VARIANT_MV78200, .data = (void *) MVEBU_GPIO_SOC_VARIANT_MV78200,
}, },
{ {
.compatible = "marvell,armadaxp-gpio", .compatible = "marvell,armadaxp-gpio",
.data = (void *) MVEBU_GPIO_SOC_VARIANT_ARMADAXP, .data = (void *) MVEBU_GPIO_SOC_VARIANT_ARMADAXP,
}, },
{ {
/* sentinel */ /* sentinel */
...@@ -661,6 +667,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) ...@@ -661,6 +667,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
unsigned int ngpios; unsigned int ngpios;
int soc_variant; int soc_variant;
int i, cpu, id; int i, cpu, id;
int err;
match = of_match_device(mvebu_gpio_of_match, &pdev->dev); match = of_match_device(mvebu_gpio_of_match, &pdev->dev);
if (match) if (match)
...@@ -668,7 +675,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev) ...@@ -668,7 +675,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
else else
soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION; soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION;
mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), GFP_KERNEL); mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip),
GFP_KERNEL);
if (!mvchip) if (!mvchip)
return -ENOMEM; return -ENOMEM;
...@@ -767,8 +775,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev) ...@@ -767,8 +775,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
* interrupt handlers, with each handler dealing with 8 GPIO * interrupt handlers, with each handler dealing with 8 GPIO
* pins. */ * pins. */
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
int irq; int irq = platform_get_irq(pdev, i);
irq = platform_get_irq(pdev, i);
if (irq < 0) if (irq < 0)
continue; continue;
irq_set_handler_data(irq, mvchip); irq_set_handler_data(irq, mvchip);
...@@ -778,14 +786,16 @@ static int mvebu_gpio_probe(struct platform_device *pdev) ...@@ -778,14 +786,16 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1); mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1);
if (mvchip->irqbase < 0) { if (mvchip->irqbase < 0) {
dev_err(&pdev->dev, "no irqs\n"); dev_err(&pdev->dev, "no irqs\n");
return mvchip->irqbase; err = mvchip->irqbase;
goto err_gpiochip_add;
} }
gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase, gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase,
mvchip->membase, handle_level_irq); mvchip->membase, handle_level_irq);
if (!gc) { if (!gc) {
dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n"); dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n");
return -ENOMEM; err = -ENOMEM;
goto err_gpiochip_add;
} }
gc->private = mvchip; gc->private = mvchip;
...@@ -816,18 +826,26 @@ static int mvebu_gpio_probe(struct platform_device *pdev) ...@@ -816,18 +826,26 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
if (!mvchip->domain) { if (!mvchip->domain) {
dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n", dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n",
mvchip->chip.label); mvchip->chip.label);
irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST, err = -ENODEV;
IRQ_LEVEL | IRQ_NOPROBE); goto err_generic_chip;
kfree(gc);
return -ENODEV;
} }
return 0; return 0;
err_generic_chip:
irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST,
IRQ_LEVEL | IRQ_NOPROBE);
kfree(gc);
err_gpiochip_add:
gpiochip_remove(&mvchip->chip);
return err;
} }
static struct platform_driver mvebu_gpio_driver = { static struct platform_driver mvebu_gpio_driver = {
.driver = { .driver = {
.name = "mvebu-gpio", .name = "mvebu-gpio",
.of_match_table = mvebu_gpio_of_match, .of_match_table = mvebu_gpio_of_match,
}, },
.probe = mvebu_gpio_probe, .probe = mvebu_gpio_probe,
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio-pxa.h> #include <linux/gpio-pxa.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
#include <linux/irqchip/chained_irq.h> #include <linux/irqchip/chained_irq.h>
...@@ -27,8 +28,6 @@ ...@@ -27,8 +28,6 @@
#include <linux/syscore_ops.h> #include <linux/syscore_ops.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <mach/irqs.h>
/* /*
* We handle the GPIOs by banks, each bank covers up to 32 GPIOs with * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
* one set of registers. The register offsets are organized below: * one set of registers. The register offsets are organized below:
...@@ -42,9 +41,12 @@ ...@@ -42,9 +41,12 @@
* BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C
* BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150 * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150
* *
* BANK 6 - 0x0200 0x020C 0x0218 0x0224 0x0230 0x023C 0x0248
*
* NOTE: * NOTE:
* BANK 3 is only available on PXA27x and later processors. * BANK 3 is only available on PXA27x and later processors.
* BANK 4 and 5 are only available on PXA935 * BANK 4 and 5 are only available on PXA935, PXA1928
* BANK 6 is only available on PXA1928
*/ */
#define GPLR_OFFSET 0x00 #define GPLR_OFFSET 0x00
...@@ -57,7 +59,8 @@ ...@@ -57,7 +59,8 @@
#define GAFR_OFFSET 0x54 #define GAFR_OFFSET 0x54
#define ED_MASK_OFFSET 0x9C /* GPIO edge detection for AP side */ #define ED_MASK_OFFSET 0x9C /* GPIO edge detection for AP side */
#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) #define BANK_OFF(n) (((n) < 3) ? (n) << 2 : ((n) > 5 ? 0x200 : 0x100) \
+ (((n) % 3) << 2))
int pxa_last_gpio; int pxa_last_gpio;
static int irq_base; static int irq_base;
...@@ -93,6 +96,7 @@ enum pxa_gpio_type { ...@@ -93,6 +96,7 @@ enum pxa_gpio_type {
PXA93X_GPIO, PXA93X_GPIO,
MMP_GPIO = 0x10, MMP_GPIO = 0x10,
MMP2_GPIO, MMP2_GPIO,
PXA1928_GPIO,
}; };
struct pxa_gpio_id { struct pxa_gpio_id {
...@@ -140,6 +144,11 @@ static struct pxa_gpio_id mmp2_id = { ...@@ -140,6 +144,11 @@ static struct pxa_gpio_id mmp2_id = {
.gpio_nums = 192, .gpio_nums = 192,
}; };
static struct pxa_gpio_id pxa1928_id = {
.type = PXA1928_GPIO,
.gpio_nums = 224,
};
#define for_each_gpio_chip(i, c) \ #define for_each_gpio_chip(i, c) \
for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++) for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++)
...@@ -487,6 +496,7 @@ static int pxa_gpio_nums(struct platform_device *pdev) ...@@ -487,6 +496,7 @@ static int pxa_gpio_nums(struct platform_device *pdev)
case PXA93X_GPIO: case PXA93X_GPIO:
case MMP_GPIO: case MMP_GPIO:
case MMP2_GPIO: case MMP2_GPIO:
case PXA1928_GPIO:
gpio_type = pxa_id->type; gpio_type = pxa_id->type;
count = pxa_id->gpio_nums - 1; count = pxa_id->gpio_nums - 1;
break; break;
...@@ -506,6 +516,7 @@ static const struct of_device_id pxa_gpio_dt_ids[] = { ...@@ -506,6 +516,7 @@ static const struct of_device_id pxa_gpio_dt_ids[] = {
{ .compatible = "marvell,pxa93x-gpio", .data = &pxa93x_id, }, { .compatible = "marvell,pxa93x-gpio", .data = &pxa93x_id, },
{ .compatible = "marvell,mmp-gpio", .data = &mmp_id, }, { .compatible = "marvell,mmp-gpio", .data = &mmp_id, },
{ .compatible = "marvell,mmp2-gpio", .data = &mmp2_id, }, { .compatible = "marvell,mmp2-gpio", .data = &mmp2_id, },
{ .compatible = "marvell,pxa1928-gpio", .data = &pxa1928_id, },
{} {}
}; };
...@@ -629,19 +640,18 @@ static int pxa_gpio_probe(struct platform_device *pdev) ...@@ -629,19 +640,18 @@ static int pxa_gpio_probe(struct platform_device *pdev)
} }
if (!use_of) { if (!use_of) {
#ifdef CONFIG_ARCH_PXA if (irq0 > 0) {
irq = gpio_to_irq(0); irq = gpio_to_irq(0);
irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
handle_edge_irq); handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler); }
if (irq1 > 0) {
irq = gpio_to_irq(1); irq = gpio_to_irq(1);
irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
handle_edge_irq); handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler); }
#endif
for (irq = gpio_to_irq(gpio_offset); for (irq = gpio_to_irq(gpio_offset);
irq <= gpio_to_irq(pxa_last_gpio); irq++) { irq <= gpio_to_irq(pxa_last_gpio); irq++) {
...@@ -649,13 +659,13 @@ static int pxa_gpio_probe(struct platform_device *pdev) ...@@ -649,13 +659,13 @@ static int pxa_gpio_probe(struct platform_device *pdev)
handle_edge_irq); handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
} }
} else {
if (irq0 > 0)
irq_set_chained_handler(irq0, pxa_gpio_demux_handler);
if (irq1 > 0)
irq_set_chained_handler(irq1, pxa_gpio_demux_handler);
} }
if (irq0 > 0)
irq_set_chained_handler(irq0, pxa_gpio_demux_handler);
if (irq1 > 0)
irq_set_chained_handler(irq1, pxa_gpio_demux_handler);
irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler); irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler);
return 0; return 0;
} }
...@@ -668,6 +678,7 @@ static const struct platform_device_id gpio_id_table[] = { ...@@ -668,6 +678,7 @@ static const struct platform_device_id gpio_id_table[] = {
{ "pxa93x-gpio", (unsigned long)&pxa93x_id }, { "pxa93x-gpio", (unsigned long)&pxa93x_id },
{ "mmp-gpio", (unsigned long)&mmp_id }, { "mmp-gpio", (unsigned long)&mmp_id },
{ "mmp2-gpio", (unsigned long)&mmp2_id }, { "mmp2-gpio", (unsigned long)&mmp2_id },
{ "pxa1928-gpio", (unsigned long)&pxa1928_id },
{ }, { },
}; };
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
...@@ -38,7 +37,6 @@ struct gpio_rcar_priv { ...@@ -38,7 +37,6 @@ struct gpio_rcar_priv {
struct platform_device *pdev; struct platform_device *pdev;
struct gpio_chip gpio_chip; struct gpio_chip gpio_chip;
struct irq_chip irq_chip; struct irq_chip irq_chip;
struct irq_domain *irq_domain;
}; };
#define IOINTSEL 0x00 #define IOINTSEL 0x00
...@@ -82,14 +80,18 @@ static void gpio_rcar_modify_bit(struct gpio_rcar_priv *p, int offs, ...@@ -82,14 +80,18 @@ static void gpio_rcar_modify_bit(struct gpio_rcar_priv *p, int offs,
static void gpio_rcar_irq_disable(struct irq_data *d) static void gpio_rcar_irq_disable(struct irq_data *d)
{ {
struct gpio_rcar_priv *p = irq_data_get_irq_chip_data(d); struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv,
gpio_chip);
gpio_rcar_write(p, INTMSK, ~BIT(irqd_to_hwirq(d))); gpio_rcar_write(p, INTMSK, ~BIT(irqd_to_hwirq(d)));
} }
static void gpio_rcar_irq_enable(struct irq_data *d) static void gpio_rcar_irq_enable(struct irq_data *d)
{ {
struct gpio_rcar_priv *p = irq_data_get_irq_chip_data(d); struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv,
gpio_chip);
gpio_rcar_write(p, MSKCLR, BIT(irqd_to_hwirq(d))); gpio_rcar_write(p, MSKCLR, BIT(irqd_to_hwirq(d)));
} }
...@@ -131,7 +133,9 @@ static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p, ...@@ -131,7 +133,9 @@ static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p,
static int gpio_rcar_irq_set_type(struct irq_data *d, unsigned int type) static int gpio_rcar_irq_set_type(struct irq_data *d, unsigned int type)
{ {
struct gpio_rcar_priv *p = irq_data_get_irq_chip_data(d); struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv,
gpio_chip);
unsigned int hwirq = irqd_to_hwirq(d); unsigned int hwirq = irqd_to_hwirq(d);
dev_dbg(&p->pdev->dev, "sense irq = %d, type = %d\n", hwirq, type); dev_dbg(&p->pdev->dev, "sense irq = %d, type = %d\n", hwirq, type);
...@@ -175,7 +179,8 @@ static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id) ...@@ -175,7 +179,8 @@ static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
gpio_rcar_read(p, INTMSK))) { gpio_rcar_read(p, INTMSK))) {
offset = __ffs(pending); offset = __ffs(pending);
gpio_rcar_write(p, INTCLR, BIT(offset)); gpio_rcar_write(p, INTCLR, BIT(offset));
generic_handle_irq(irq_find_mapping(p->irq_domain, offset)); generic_handle_irq(irq_find_mapping(p->gpio_chip.irqdomain,
offset));
irqs_handled++; irqs_handled++;
} }
...@@ -265,29 +270,6 @@ static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset, ...@@ -265,29 +270,6 @@ static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset,
return 0; return 0;
} }
static int gpio_rcar_to_irq(struct gpio_chip *chip, unsigned offset)
{
return irq_create_mapping(gpio_to_priv(chip)->irq_domain, offset);
}
static int gpio_rcar_irq_domain_map(struct irq_domain *h, unsigned int irq,
irq_hw_number_t hwirq)
{
struct gpio_rcar_priv *p = h->host_data;
dev_dbg(&p->pdev->dev, "map hw irq = %d, irq = %d\n", (int)hwirq, irq);
irq_set_chip_data(irq, h->host_data);
irq_set_chip_and_handler(irq, &p->irq_chip, handle_level_irq);
set_irq_flags(irq, IRQF_VALID); /* kill me now */
return 0;
}
static struct irq_domain_ops gpio_rcar_irq_domain_ops = {
.map = gpio_rcar_irq_domain_map,
.xlate = irq_domain_xlate_twocell,
};
struct gpio_rcar_info { struct gpio_rcar_info {
bool has_both_edge_trigger; bool has_both_edge_trigger;
}; };
...@@ -372,10 +354,8 @@ static int gpio_rcar_probe(struct platform_device *pdev) ...@@ -372,10 +354,8 @@ static int gpio_rcar_probe(struct platform_device *pdev)
int ret; int ret;
p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL); p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);
if (!p) { if (!p)
ret = -ENOMEM; return -ENOMEM;
goto err0;
}
p->pdev = pdev; p->pdev = pdev;
spin_lock_init(&p->lock); spin_lock_init(&p->lock);
...@@ -413,7 +393,6 @@ static int gpio_rcar_probe(struct platform_device *pdev) ...@@ -413,7 +393,6 @@ static int gpio_rcar_probe(struct platform_device *pdev)
gpio_chip->get = gpio_rcar_get; gpio_chip->get = gpio_rcar_get;
gpio_chip->direction_output = gpio_rcar_direction_output; gpio_chip->direction_output = gpio_rcar_direction_output;
gpio_chip->set = gpio_rcar_set; gpio_chip->set = gpio_rcar_set;
gpio_chip->to_irq = gpio_rcar_to_irq;
gpio_chip->label = name; gpio_chip->label = name;
gpio_chip->dev = dev; gpio_chip->dev = dev;
gpio_chip->owner = THIS_MODULE; gpio_chip->owner = THIS_MODULE;
...@@ -428,16 +407,19 @@ static int gpio_rcar_probe(struct platform_device *pdev) ...@@ -428,16 +407,19 @@ static int gpio_rcar_probe(struct platform_device *pdev)
irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED
| IRQCHIP_MASK_ON_SUSPEND; | IRQCHIP_MASK_ON_SUSPEND;
p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, ret = gpiochip_add(gpio_chip);
p->config.number_of_pins, if (ret) {
p->config.irq_base, dev_err(dev, "failed to add GPIO controller\n");
&gpio_rcar_irq_domain_ops, p);
if (!p->irq_domain) {
ret = -ENXIO;
dev_err(dev, "cannot initialize irq domain\n");
goto err0; goto err0;
} }
ret = gpiochip_irqchip_add(&p->gpio_chip, irq_chip, p->config.irq_base,
handle_level_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(dev, "cannot add irqchip\n");
goto err1;
}
if (devm_request_irq(dev, irq->start, gpio_rcar_irq_handler, if (devm_request_irq(dev, irq->start, gpio_rcar_irq_handler,
IRQF_SHARED, name, p)) { IRQF_SHARED, name, p)) {
dev_err(dev, "failed to request IRQ\n"); dev_err(dev, "failed to request IRQ\n");
...@@ -445,17 +427,11 @@ static int gpio_rcar_probe(struct platform_device *pdev) ...@@ -445,17 +427,11 @@ static int gpio_rcar_probe(struct platform_device *pdev)
goto err1; goto err1;
} }
ret = gpiochip_add(gpio_chip);
if (ret) {
dev_err(dev, "failed to add GPIO controller\n");
goto err1;
}
dev_info(dev, "driving %d GPIOs\n", p->config.number_of_pins); dev_info(dev, "driving %d GPIOs\n", p->config.number_of_pins);
/* warn in case of mismatch if irq base is specified */ /* warn in case of mismatch if irq base is specified */
if (p->config.irq_base) { if (p->config.irq_base) {
ret = irq_find_mapping(p->irq_domain, 0); ret = irq_find_mapping(p->gpio_chip.irqdomain, 0);
if (p->config.irq_base != ret) if (p->config.irq_base != ret)
dev_warn(dev, "irq base mismatch (%u/%u)\n", dev_warn(dev, "irq base mismatch (%u/%u)\n",
p->config.irq_base, ret); p->config.irq_base, ret);
...@@ -471,7 +447,7 @@ static int gpio_rcar_probe(struct platform_device *pdev) ...@@ -471,7 +447,7 @@ static int gpio_rcar_probe(struct platform_device *pdev)
return 0; return 0;
err1: err1:
irq_domain_remove(p->irq_domain); gpiochip_remove(&p->gpio_chip);
err0: err0:
pm_runtime_put(dev); pm_runtime_put(dev);
pm_runtime_disable(dev); pm_runtime_disable(dev);
...@@ -484,7 +460,6 @@ static int gpio_rcar_remove(struct platform_device *pdev) ...@@ -484,7 +460,6 @@ static int gpio_rcar_remove(struct platform_device *pdev)
gpiochip_remove(&p->gpio_chip); gpiochip_remove(&p->gpio_chip);
irq_domain_remove(p->irq_domain);
pm_runtime_put(&pdev->dev); pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
return 0; return 0;
......
...@@ -41,7 +41,7 @@ struct sch_gpio { ...@@ -41,7 +41,7 @@ struct sch_gpio {
unsigned short resume_base; unsigned short resume_base;
}; };
#define to_sch_gpio(c) container_of(c, struct sch_gpio, chip) #define to_sch_gpio(gc) container_of(gc, struct sch_gpio, chip)
static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio, static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio,
unsigned reg) unsigned reg)
...@@ -63,75 +63,59 @@ static unsigned sch_gpio_bit(struct sch_gpio *sch, unsigned gpio) ...@@ -63,75 +63,59 @@ static unsigned sch_gpio_bit(struct sch_gpio *sch, unsigned gpio)
return gpio % 8; return gpio % 8;
} }
static void sch_gpio_enable(struct sch_gpio *sch, unsigned gpio) static int sch_gpio_reg_get(struct gpio_chip *gc, unsigned gpio, unsigned reg)
{ {
struct sch_gpio *sch = to_sch_gpio(gc);
unsigned short offset, bit; unsigned short offset, bit;
u8 enable; u8 reg_val;
spin_lock(&sch->lock);
offset = sch_gpio_offset(sch, gpio, GEN); offset = sch_gpio_offset(sch, gpio, reg);
bit = sch_gpio_bit(sch, gpio); bit = sch_gpio_bit(sch, gpio);
enable = inb(sch->iobase + offset); reg_val = !!(inb(sch->iobase + offset) & BIT(bit));
if (!(enable & (1 << bit)))
outb(enable | (1 << bit), sch->iobase + offset);
spin_unlock(&sch->lock); return reg_val;
} }
static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num) static void sch_gpio_reg_set(struct gpio_chip *gc, unsigned gpio, unsigned reg,
int val)
{ {
struct sch_gpio *sch = to_sch_gpio(gc); struct sch_gpio *sch = to_sch_gpio(gc);
u8 curr_dirs;
unsigned short offset, bit; unsigned short offset, bit;
u8 reg_val;
spin_lock(&sch->lock); offset = sch_gpio_offset(sch, gpio, reg);
bit = sch_gpio_bit(sch, gpio);
offset = sch_gpio_offset(sch, gpio_num, GIO); reg_val = inb(sch->iobase + offset);
bit = sch_gpio_bit(sch, gpio_num);
curr_dirs = inb(sch->iobase + offset); if (val)
outb(reg_val | BIT(bit), sch->iobase + offset);
else
outb((reg_val & ~BIT(bit)), sch->iobase + offset);
}
if (!(curr_dirs & (1 << bit))) static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)
outb(curr_dirs | (1 << bit), sch->iobase + offset); {
struct sch_gpio *sch = to_sch_gpio(gc);
spin_lock(&sch->lock);
sch_gpio_reg_set(gc, gpio_num, GIO, 1);
spin_unlock(&sch->lock); spin_unlock(&sch->lock);
return 0; return 0;
} }
static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num) static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
{ {
struct sch_gpio *sch = to_sch_gpio(gc); return sch_gpio_reg_get(gc, gpio_num, GLV);
int res;
unsigned short offset, bit;
offset = sch_gpio_offset(sch, gpio_num, GLV);
bit = sch_gpio_bit(sch, gpio_num);
res = !!(inb(sch->iobase + offset) & (1 << bit));
return res;
} }
static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val) static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
{ {
struct sch_gpio *sch = to_sch_gpio(gc); struct sch_gpio *sch = to_sch_gpio(gc);
u8 curr_vals;
unsigned short offset, bit;
spin_lock(&sch->lock); spin_lock(&sch->lock);
sch_gpio_reg_set(gc, gpio_num, GLV, val);
offset = sch_gpio_offset(sch, gpio_num, GLV);
bit = sch_gpio_bit(sch, gpio_num);
curr_vals = inb(sch->iobase + offset);
if (val)
outb(curr_vals | (1 << bit), sch->iobase + offset);
else
outb((curr_vals & ~(1 << bit)), sch->iobase + offset);
spin_unlock(&sch->lock); spin_unlock(&sch->lock);
} }
...@@ -139,18 +123,9 @@ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num, ...@@ -139,18 +123,9 @@ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
int val) int val)
{ {
struct sch_gpio *sch = to_sch_gpio(gc); struct sch_gpio *sch = to_sch_gpio(gc);
u8 curr_dirs;
unsigned short offset, bit;
spin_lock(&sch->lock); spin_lock(&sch->lock);
sch_gpio_reg_set(gc, gpio_num, GIO, 0);
offset = sch_gpio_offset(sch, gpio_num, GIO);
bit = sch_gpio_bit(sch, gpio_num);
curr_dirs = inb(sch->iobase + offset);
if (curr_dirs & (1 << bit))
outb(curr_dirs & ~(1 << bit), sch->iobase + offset);
spin_unlock(&sch->lock); spin_unlock(&sch->lock);
/* /*
...@@ -209,13 +184,13 @@ static int sch_gpio_probe(struct platform_device *pdev) ...@@ -209,13 +184,13 @@ static int sch_gpio_probe(struct platform_device *pdev)
* GPIO7 is configured by the CMC as SLPIOVR * GPIO7 is configured by the CMC as SLPIOVR
* Enable GPIO[9:8] core powered gpios explicitly * Enable GPIO[9:8] core powered gpios explicitly
*/ */
sch_gpio_enable(sch, 8); sch_gpio_reg_set(&sch->chip, 8, GEN, 1);
sch_gpio_enable(sch, 9); sch_gpio_reg_set(&sch->chip, 9, GEN, 1);
/* /*
* SUS_GPIO[2:0] enabled by default * SUS_GPIO[2:0] enabled by default
* Enable SUS_GPIO3 resume powered gpio explicitly * Enable SUS_GPIO3 resume powered gpio explicitly
*/ */
sch_gpio_enable(sch, 13); sch_gpio_reg_set(&sch->chip, 13, GEN, 1);
break; break;
case PCI_DEVICE_ID_INTEL_ITC_LPC: case PCI_DEVICE_ID_INTEL_ITC_LPC:
...@@ -230,6 +205,12 @@ static int sch_gpio_probe(struct platform_device *pdev) ...@@ -230,6 +205,12 @@ static int sch_gpio_probe(struct platform_device *pdev)
sch->chip.ngpio = 30; sch->chip.ngpio = 30;
break; break;
case PCI_DEVICE_ID_INTEL_QUARK_X1000_ILB:
sch->core_base = 0;
sch->resume_base = 2;
sch->chip.ngpio = 8;
break;
default: default:
return -ENODEV; return -ENODEV;
} }
......
...@@ -30,7 +30,7 @@ struct stmpe_gpio { ...@@ -30,7 +30,7 @@ struct stmpe_gpio {
struct stmpe *stmpe; struct stmpe *stmpe;
struct device *dev; struct device *dev;
struct mutex irq_lock; struct mutex irq_lock;
unsigned norequest_mask; u32 norequest_mask;
/* Caches of interrupt control registers for bus_lock */ /* Caches of interrupt control registers for bus_lock */
u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS]; u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS]; u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
...@@ -340,13 +340,10 @@ static int stmpe_gpio_probe(struct platform_device *pdev) ...@@ -340,13 +340,10 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
{ {
struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct stmpe_gpio_platform_data *pdata;
struct stmpe_gpio *stmpe_gpio; struct stmpe_gpio *stmpe_gpio;
int ret; int ret;
int irq = 0; int irq = 0;
pdata = stmpe->pdata->gpio;
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
stmpe_gpio = kzalloc(sizeof(struct stmpe_gpio), GFP_KERNEL); stmpe_gpio = kzalloc(sizeof(struct stmpe_gpio), GFP_KERNEL);
...@@ -360,19 +357,14 @@ static int stmpe_gpio_probe(struct platform_device *pdev) ...@@ -360,19 +357,14 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
stmpe_gpio->chip = template_chip; stmpe_gpio->chip = template_chip;
stmpe_gpio->chip.ngpio = stmpe->num_gpios; stmpe_gpio->chip.ngpio = stmpe->num_gpios;
stmpe_gpio->chip.dev = &pdev->dev; stmpe_gpio->chip.dev = &pdev->dev;
#ifdef CONFIG_OF
stmpe_gpio->chip.of_node = np; stmpe_gpio->chip.of_node = np;
#endif
stmpe_gpio->chip.base = -1; stmpe_gpio->chip.base = -1;
if (IS_ENABLED(CONFIG_DEBUG_FS)) if (IS_ENABLED(CONFIG_DEBUG_FS))
stmpe_gpio->chip.dbg_show = stmpe_dbg_show; stmpe_gpio->chip.dbg_show = stmpe_dbg_show;
if (pdata) of_property_read_u32(np, "st,norequest-mask",
stmpe_gpio->norequest_mask = pdata->norequest_mask; &stmpe_gpio->norequest_mask);
else if (np)
of_property_read_u32(np, "st,norequest-mask",
&stmpe_gpio->norequest_mask);
if (irq < 0) if (irq < 0)
dev_info(&pdev->dev, dev_info(&pdev->dev,
...@@ -414,9 +406,6 @@ static int stmpe_gpio_probe(struct platform_device *pdev) ...@@ -414,9 +406,6 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
NULL); NULL);
} }
if (pdata && pdata->setup)
pdata->setup(stmpe, stmpe_gpio->chip.base);
platform_set_drvdata(pdev, stmpe_gpio); platform_set_drvdata(pdev, stmpe_gpio);
return 0; return 0;
...@@ -433,15 +422,9 @@ static int stmpe_gpio_remove(struct platform_device *pdev) ...@@ -433,15 +422,9 @@ static int stmpe_gpio_remove(struct platform_device *pdev)
{ {
struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev); struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev);
struct stmpe *stmpe = stmpe_gpio->stmpe; struct stmpe *stmpe = stmpe_gpio->stmpe;
struct stmpe_gpio_platform_data *pdata = stmpe->pdata->gpio;
if (pdata && pdata->remove)
pdata->remove(stmpe, stmpe_gpio->chip.base);
gpiochip_remove(&stmpe_gpio->chip); gpiochip_remove(&stmpe_gpio->chip);
stmpe_disable(stmpe, STMPE_BLOCK_GPIO); stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
kfree(stmpe_gpio); kfree(stmpe_gpio);
return 0; return 0;
......
...@@ -23,23 +23,51 @@ ...@@ -23,23 +23,51 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c/sx150x.h> #include <linux/i2c/sx150x.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/of_device.h>
#define NO_UPDATE_PENDING -1 #define NO_UPDATE_PENDING -1
/* The chip models of sx150x */
#define SX150X_456 0
#define SX150X_789 1
struct sx150x_456_pri {
u8 reg_pld_mode;
u8 reg_pld_table0;
u8 reg_pld_table1;
u8 reg_pld_table2;
u8 reg_pld_table3;
u8 reg_pld_table4;
u8 reg_advance;
};
struct sx150x_789_pri {
u8 reg_drain;
u8 reg_polarity;
u8 reg_clock;
u8 reg_misc;
u8 reg_reset;
u8 ngpios;
};
struct sx150x_device_data { struct sx150x_device_data {
u8 model;
u8 reg_pullup; u8 reg_pullup;
u8 reg_pulldn; u8 reg_pulldn;
u8 reg_drain;
u8 reg_polarity;
u8 reg_dir; u8 reg_dir;
u8 reg_data; u8 reg_data;
u8 reg_irq_mask; u8 reg_irq_mask;
u8 reg_irq_src; u8 reg_irq_src;
u8 reg_sense; u8 reg_sense;
u8 reg_clock;
u8 reg_misc;
u8 reg_reset;
u8 ngpios; u8 ngpios;
union {
struct sx150x_456_pri x456;
struct sx150x_789_pri x789;
} pri;
}; };
struct sx150x_chip { struct sx150x_chip {
...@@ -59,44 +87,79 @@ struct sx150x_chip { ...@@ -59,44 +87,79 @@ struct sx150x_chip {
static const struct sx150x_device_data sx150x_devices[] = { static const struct sx150x_device_data sx150x_devices[] = {
[0] = { /* sx1508q */ [0] = { /* sx1508q */
.reg_pullup = 0x03, .model = SX150X_789,
.reg_pulldn = 0x04, .reg_pullup = 0x03,
.reg_drain = 0x05, .reg_pulldn = 0x04,
.reg_polarity = 0x06, .reg_dir = 0x07,
.reg_dir = 0x07, .reg_data = 0x08,
.reg_data = 0x08, .reg_irq_mask = 0x09,
.reg_irq_mask = 0x09, .reg_irq_src = 0x0c,
.reg_irq_src = 0x0c, .reg_sense = 0x0b,
.reg_sense = 0x0b, .pri.x789 = {
.reg_clock = 0x0f, .reg_drain = 0x05,
.reg_misc = 0x10, .reg_polarity = 0x06,
.reg_reset = 0x7d, .reg_clock = 0x0f,
.ngpios = 8 .reg_misc = 0x10,
.reg_reset = 0x7d,
},
.ngpios = 8,
}, },
[1] = { /* sx1509q */ [1] = { /* sx1509q */
.reg_pullup = 0x07, .model = SX150X_789,
.reg_pulldn = 0x09, .reg_pullup = 0x07,
.reg_drain = 0x0b, .reg_pulldn = 0x09,
.reg_polarity = 0x0d, .reg_dir = 0x0f,
.reg_dir = 0x0f, .reg_data = 0x11,
.reg_data = 0x11, .reg_irq_mask = 0x13,
.reg_irq_mask = 0x13, .reg_irq_src = 0x19,
.reg_irq_src = 0x19, .reg_sense = 0x17,
.reg_sense = 0x17, .pri.x789 = {
.reg_clock = 0x1e, .reg_drain = 0x0b,
.reg_misc = 0x1f, .reg_polarity = 0x0d,
.reg_reset = 0x7d, .reg_clock = 0x1e,
.ngpios = 16 .reg_misc = 0x1f,
.reg_reset = 0x7d,
},
.ngpios = 16
},
[2] = { /* sx1506q */
.model = SX150X_456,
.reg_pullup = 0x05,
.reg_pulldn = 0x07,
.reg_dir = 0x03,
.reg_data = 0x01,
.reg_irq_mask = 0x09,
.reg_irq_src = 0x0f,
.reg_sense = 0x0d,
.pri.x456 = {
.reg_pld_mode = 0x21,
.reg_pld_table0 = 0x23,
.reg_pld_table1 = 0x25,
.reg_pld_table2 = 0x27,
.reg_pld_table3 = 0x29,
.reg_pld_table4 = 0x2b,
.reg_advance = 0xad,
},
.ngpios = 16
}, },
}; };
static const struct i2c_device_id sx150x_id[] = { static const struct i2c_device_id sx150x_id[] = {
{"sx1508q", 0}, {"sx1508q", 0},
{"sx1509q", 1}, {"sx1509q", 1},
{"sx1506q", 2},
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, sx150x_id); MODULE_DEVICE_TABLE(i2c, sx150x_id);
static const struct of_device_id sx150x_of_match[] = {
{ .compatible = "semtech,sx1508q" },
{ .compatible = "semtech,sx1509q" },
{ .compatible = "semtech,sx1506q" },
{},
};
MODULE_DEVICE_TABLE(of, sx150x_of_match);
static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val) static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val)
{ {
s32 err = i2c_smbus_write_byte_data(client, reg, val); s32 err = i2c_smbus_write_byte_data(client, reg, val);
...@@ -191,7 +254,7 @@ static int sx150x_get_io(struct sx150x_chip *chip, unsigned offset) ...@@ -191,7 +254,7 @@ static int sx150x_get_io(struct sx150x_chip *chip, unsigned offset)
static void sx150x_set_oscio(struct sx150x_chip *chip, int val) static void sx150x_set_oscio(struct sx150x_chip *chip, int val)
{ {
sx150x_i2c_write(chip->client, sx150x_i2c_write(chip->client,
chip->dev_cfg->reg_clock, chip->dev_cfg->pri.x789.reg_clock,
(val ? 0x1f : 0x10)); (val ? 0x1f : 0x10));
} }
...@@ -293,27 +356,11 @@ static int sx150x_gpio_direction_output(struct gpio_chip *gc, ...@@ -293,27 +356,11 @@ static int sx150x_gpio_direction_output(struct gpio_chip *gc,
return status; return status;
} }
static int sx150x_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
{
struct sx150x_chip *chip;
chip = container_of(gc, struct sx150x_chip, gpio_chip);
if (offset >= chip->dev_cfg->ngpios)
return -EINVAL;
if (chip->irq_base < 0)
return -EINVAL;
return chip->irq_base + offset;
}
static void sx150x_irq_mask(struct irq_data *d) static void sx150x_irq_mask(struct irq_data *d)
{ {
struct sx150x_chip *chip = irq_data_get_irq_chip_data(d); struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
unsigned n; unsigned n = d->hwirq;
n = d->irq - chip->irq_base;
chip->irq_masked |= (1 << n); chip->irq_masked |= (1 << n);
chip->irq_update = n; chip->irq_update = n;
} }
...@@ -321,9 +368,8 @@ static void sx150x_irq_mask(struct irq_data *d) ...@@ -321,9 +368,8 @@ static void sx150x_irq_mask(struct irq_data *d)
static void sx150x_irq_unmask(struct irq_data *d) static void sx150x_irq_unmask(struct irq_data *d)
{ {
struct sx150x_chip *chip = irq_data_get_irq_chip_data(d); struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
unsigned n; unsigned n = d->hwirq;
n = d->irq - chip->irq_base;
chip->irq_masked &= ~(1 << n); chip->irq_masked &= ~(1 << n);
chip->irq_update = n; chip->irq_update = n;
} }
...@@ -336,7 +382,7 @@ static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type) ...@@ -336,7 +382,7 @@ static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type)
if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
return -EINVAL; return -EINVAL;
n = d->irq - chip->irq_base; n = d->hwirq;
if (flow_type & IRQ_TYPE_EDGE_RISING) if (flow_type & IRQ_TYPE_EDGE_RISING)
val |= 0x1; val |= 0x1;
...@@ -371,7 +417,9 @@ static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id) ...@@ -371,7 +417,9 @@ static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id)
val); val);
for (n = 0; n < 8; ++n) { for (n = 0; n < 8; ++n) {
if (val & (1 << n)) { if (val & (1 << n)) {
sub_irq = chip->irq_base + (i * 8) + n; sub_irq = irq_find_mapping(
chip->gpio_chip.irqdomain,
(i * 8) + n);
handle_nested_irq(sub_irq); handle_nested_irq(sub_irq);
++nhandled; ++nhandled;
} }
...@@ -401,7 +449,7 @@ static void sx150x_irq_bus_sync_unlock(struct irq_data *d) ...@@ -401,7 +449,7 @@ static void sx150x_irq_bus_sync_unlock(struct irq_data *d)
/* Avoid updates if nothing changed */ /* Avoid updates if nothing changed */
if (chip->dev_sense == chip->irq_sense && if (chip->dev_sense == chip->irq_sense &&
chip->dev_sense == chip->irq_masked) chip->dev_masked == chip->irq_masked)
goto out; goto out;
chip->dev_sense = chip->irq_sense; chip->dev_sense = chip->irq_sense;
...@@ -428,15 +476,19 @@ static void sx150x_init_chip(struct sx150x_chip *chip, ...@@ -428,15 +476,19 @@ static void sx150x_init_chip(struct sx150x_chip *chip,
chip->client = client; chip->client = client;
chip->dev_cfg = &sx150x_devices[driver_data]; chip->dev_cfg = &sx150x_devices[driver_data];
chip->gpio_chip.dev = &client->dev;
chip->gpio_chip.label = client->name; chip->gpio_chip.label = client->name;
chip->gpio_chip.direction_input = sx150x_gpio_direction_input; chip->gpio_chip.direction_input = sx150x_gpio_direction_input;
chip->gpio_chip.direction_output = sx150x_gpio_direction_output; chip->gpio_chip.direction_output = sx150x_gpio_direction_output;
chip->gpio_chip.get = sx150x_gpio_get; chip->gpio_chip.get = sx150x_gpio_get;
chip->gpio_chip.set = sx150x_gpio_set; chip->gpio_chip.set = sx150x_gpio_set;
chip->gpio_chip.to_irq = sx150x_gpio_to_irq;
chip->gpio_chip.base = pdata->gpio_base; chip->gpio_chip.base = pdata->gpio_base;
chip->gpio_chip.can_sleep = true; chip->gpio_chip.can_sleep = true;
chip->gpio_chip.ngpio = chip->dev_cfg->ngpios; chip->gpio_chip.ngpio = chip->dev_cfg->ngpios;
#ifdef CONFIG_OF_GPIO
chip->gpio_chip.of_node = client->dev.of_node;
chip->gpio_chip.of_gpio_n_cells = 2;
#endif
if (pdata->oscio_is_gpo) if (pdata->oscio_is_gpo)
++chip->gpio_chip.ngpio; ++chip->gpio_chip.ngpio;
...@@ -470,13 +522,13 @@ static int sx150x_reset(struct sx150x_chip *chip) ...@@ -470,13 +522,13 @@ static int sx150x_reset(struct sx150x_chip *chip)
int err; int err;
err = i2c_smbus_write_byte_data(chip->client, err = i2c_smbus_write_byte_data(chip->client,
chip->dev_cfg->reg_reset, chip->dev_cfg->pri.x789.reg_reset,
0x12); 0x12);
if (err < 0) if (err < 0)
return err; return err;
err = i2c_smbus_write_byte_data(chip->client, err = i2c_smbus_write_byte_data(chip->client,
chip->dev_cfg->reg_reset, chip->dev_cfg->pri.x789.reg_reset,
0x34); 0x34);
return err; return err;
} }
...@@ -492,9 +544,14 @@ static int sx150x_init_hw(struct sx150x_chip *chip, ...@@ -492,9 +544,14 @@ static int sx150x_init_hw(struct sx150x_chip *chip,
return err; return err;
} }
err = sx150x_i2c_write(chip->client, if (chip->dev_cfg->model == SX150X_789)
chip->dev_cfg->reg_misc, err = sx150x_i2c_write(chip->client,
0x01); chip->dev_cfg->pri.x789.reg_misc,
0x01);
else
err = sx150x_i2c_write(chip->client,
chip->dev_cfg->pri.x456.reg_advance,
0x04);
if (err < 0) if (err < 0)
return err; return err;
...@@ -508,15 +565,27 @@ static int sx150x_init_hw(struct sx150x_chip *chip, ...@@ -508,15 +565,27 @@ static int sx150x_init_hw(struct sx150x_chip *chip,
if (err < 0) if (err < 0)
return err; return err;
err = sx150x_init_io(chip, chip->dev_cfg->reg_drain, if (chip->dev_cfg->model == SX150X_789) {
pdata->io_open_drain_ena); err = sx150x_init_io(chip,
if (err < 0) chip->dev_cfg->pri.x789.reg_drain,
return err; pdata->io_open_drain_ena);
if (err < 0)
return err;
err = sx150x_init_io(chip,
chip->dev_cfg->pri.x789.reg_polarity,
pdata->io_polarity);
if (err < 0)
return err;
} else {
/* Set all pins to work in normal mode */
err = sx150x_init_io(chip,
chip->dev_cfg->pri.x456.reg_pld_mode,
0);
if (err < 0)
return err;
}
err = sx150x_init_io(chip, chip->dev_cfg->reg_polarity,
pdata->io_polarity);
if (err < 0)
return err;
if (pdata->oscio_is_gpo) if (pdata->oscio_is_gpo)
sx150x_set_oscio(chip, 0); sx150x_set_oscio(chip, 0);
...@@ -529,31 +598,24 @@ static int sx150x_install_irq_chip(struct sx150x_chip *chip, ...@@ -529,31 +598,24 @@ static int sx150x_install_irq_chip(struct sx150x_chip *chip,
int irq_base) int irq_base)
{ {
int err; int err;
unsigned n;
unsigned irq;
chip->irq_summary = irq_summary; chip->irq_summary = irq_summary;
chip->irq_base = irq_base; chip->irq_base = irq_base;
for (n = 0; n < chip->dev_cfg->ngpios; ++n) { /* Add gpio chip to irq subsystem */
irq = irq_base + n; err = gpiochip_irqchip_add(&chip->gpio_chip,
irq_set_chip_data(irq, chip); &chip->irq_chip, chip->irq_base,
irq_set_chip_and_handler(irq, &chip->irq_chip, handle_edge_irq); handle_edge_irq, IRQ_TYPE_EDGE_BOTH);
irq_set_nested_thread(irq, 1); if (err) {
#ifdef CONFIG_ARM dev_err(&chip->client->dev,
set_irq_flags(irq, IRQF_VALID); "could not connect irqchip to gpiochip\n");
#else return err;
irq_set_noprobe(irq);
#endif
} }
err = devm_request_threaded_irq(&chip->client->dev, err = devm_request_threaded_irq(&chip->client->dev,
irq_summary, irq_summary, NULL, sx150x_irq_thread_fn,
NULL, IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_FALLING,
sx150x_irq_thread_fn, chip->irq_chip.name, chip);
IRQF_SHARED | IRQF_TRIGGER_FALLING,
chip->irq_chip.name,
chip);
if (err < 0) { if (err < 0) {
chip->irq_summary = -1; chip->irq_summary = -1;
chip->irq_base = -1; chip->irq_base = -1;
...@@ -562,17 +624,6 @@ static int sx150x_install_irq_chip(struct sx150x_chip *chip, ...@@ -562,17 +624,6 @@ static int sx150x_install_irq_chip(struct sx150x_chip *chip,
return err; return err;
} }
static void sx150x_remove_irq_chip(struct sx150x_chip *chip)
{
unsigned n;
unsigned irq;
for (n = 0; n < chip->dev_cfg->ngpios; ++n) {
irq = chip->irq_base + n;
irq_set_chip_and_handler(irq, NULL, NULL);
}
}
static int sx150x_probe(struct i2c_client *client, static int sx150x_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -626,16 +677,14 @@ static int sx150x_remove(struct i2c_client *client) ...@@ -626,16 +677,14 @@ static int sx150x_remove(struct i2c_client *client)
chip = i2c_get_clientdata(client); chip = i2c_get_clientdata(client);
gpiochip_remove(&chip->gpio_chip); gpiochip_remove(&chip->gpio_chip);
if (chip->irq_summary >= 0)
sx150x_remove_irq_chip(chip);
return 0; return 0;
} }
static struct i2c_driver sx150x_driver = { static struct i2c_driver sx150x_driver = {
.driver = { .driver = {
.name = "sx150x", .name = "sx150x",
.owner = THIS_MODULE .owner = THIS_MODULE,
.of_match_table = of_match_ptr(sx150x_of_match),
}, },
.probe = sx150x_probe, .probe = sx150x_probe,
.remove = sx150x_remove, .remove = sx150x_remove,
......
...@@ -232,16 +232,13 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev) ...@@ -232,16 +232,13 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
static int tc3589x_gpio_probe(struct platform_device *pdev) static int tc3589x_gpio_probe(struct platform_device *pdev)
{ {
struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent); struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
struct tc3589x_gpio_platform_data *pdata;
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct tc3589x_gpio *tc3589x_gpio; struct tc3589x_gpio *tc3589x_gpio;
int ret; int ret;
int irq; int irq;
pdata = tc3589x->pdata->gpio; if (!np) {
dev_err(&pdev->dev, "No Device Tree node found\n");
if (!(pdata || np)) {
dev_err(&pdev->dev, "No platform data or Device Tree found\n");
return -EINVAL; return -EINVAL;
} }
...@@ -305,9 +302,6 @@ static int tc3589x_gpio_probe(struct platform_device *pdev) ...@@ -305,9 +302,6 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
irq, irq,
NULL); NULL);
if (pdata && pdata->setup)
pdata->setup(tc3589x, tc3589x_gpio->chip.base);
platform_set_drvdata(pdev, tc3589x_gpio); platform_set_drvdata(pdev, tc3589x_gpio);
return 0; return 0;
...@@ -316,11 +310,6 @@ static int tc3589x_gpio_probe(struct platform_device *pdev) ...@@ -316,11 +310,6 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
static int tc3589x_gpio_remove(struct platform_device *pdev) static int tc3589x_gpio_remove(struct platform_device *pdev)
{ {
struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev); struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio;
if (pdata && pdata->remove)
pdata->remove(tc3589x, tc3589x_gpio->chip.base);
gpiochip_remove(&tc3589x_gpio->chip); gpiochip_remove(&tc3589x_gpio->chip);
......
...@@ -190,7 +190,7 @@ static int tz1090_pdc_gpio_probe(struct platform_device *pdev) ...@@ -190,7 +190,7 @@ static int tz1090_pdc_gpio_probe(struct platform_device *pdev)
/* Ioremap the registers */ /* Ioremap the registers */
priv->reg = devm_ioremap(&pdev->dev, res_regs->start, priv->reg = devm_ioremap(&pdev->dev, res_regs->start,
res_regs->end - res_regs->start); resource_size(res_regs));
if (!priv->reg) { if (!priv->reg) {
dev_err(&pdev->dev, "unable to ioremap registers\n"); dev_err(&pdev->dev, "unable to ioremap registers\n");
return -ENOMEM; return -ENOMEM;
......
...@@ -573,7 +573,7 @@ static int tz1090_gpio_probe(struct platform_device *pdev) ...@@ -573,7 +573,7 @@ static int tz1090_gpio_probe(struct platform_device *pdev)
/* Ioremap the registers */ /* Ioremap the registers */
priv.reg = devm_ioremap(&pdev->dev, res_regs->start, priv.reg = devm_ioremap(&pdev->dev, res_regs->start,
res_regs->end - res_regs->start); resource_size(res_regs));
if (!priv.reg) { if (!priv.reg) {
dev_err(&pdev->dev, "unable to ioremap registers\n"); dev_err(&pdev->dev, "unable to ioremap registers\n");
return -ENOMEM; return -ENOMEM;
......
...@@ -278,7 +278,6 @@ static int vf610_gpio_probe(struct platform_device *pdev) ...@@ -278,7 +278,6 @@ static int vf610_gpio_probe(struct platform_device *pdev)
static struct platform_driver vf610_gpio_driver = { static struct platform_driver vf610_gpio_driver = {
.driver = { .driver = {
.name = "gpio-vf610", .name = "gpio-vf610",
.owner = THIS_MODULE,
.of_match_table = vf610_gpio_dt_ids, .of_match_table = vf610_gpio_dt_ids,
}, },
.probe = vf610_gpio_probe, .probe = vf610_gpio_probe,
......
...@@ -52,8 +52,6 @@ struct vx855_gpio { ...@@ -52,8 +52,6 @@ struct vx855_gpio {
spinlock_t lock; spinlock_t lock;
u32 io_gpi; u32 io_gpi;
u32 io_gpo; u32 io_gpo;
bool gpi_reserved;
bool gpo_reserved;
}; };
/* resolve a GPIx into the corresponding bit position */ /* resolve a GPIx into the corresponding bit position */
...@@ -224,14 +222,13 @@ static int vx855gpio_probe(struct platform_device *pdev) ...@@ -224,14 +222,13 @@ static int vx855gpio_probe(struct platform_device *pdev)
struct resource *res_gpi; struct resource *res_gpi;
struct resource *res_gpo; struct resource *res_gpo;
struct vx855_gpio *vg; struct vx855_gpio *vg;
int ret;
res_gpi = platform_get_resource(pdev, IORESOURCE_IO, 0); res_gpi = platform_get_resource(pdev, IORESOURCE_IO, 0);
res_gpo = platform_get_resource(pdev, IORESOURCE_IO, 1); res_gpo = platform_get_resource(pdev, IORESOURCE_IO, 1);
if (!res_gpi || !res_gpo) if (!res_gpi || !res_gpo)
return -EBUSY; return -EBUSY;
vg = kzalloc(sizeof(*vg), GFP_KERNEL); vg = devm_kzalloc(&pdev->dev, sizeof(*vg), GFP_KERNEL);
if (!vg) if (!vg)
return -ENOMEM; return -ENOMEM;
...@@ -250,56 +247,27 @@ static int vx855gpio_probe(struct platform_device *pdev) ...@@ -250,56 +247,27 @@ static int vx855gpio_probe(struct platform_device *pdev)
* succeed. Ignore and continue. * succeed. Ignore and continue.
*/ */
if (!request_region(res_gpi->start, resource_size(res_gpi), if (!devm_request_region(&pdev->dev, res_gpi->start,
MODULE_NAME "_gpi")) resource_size(res_gpi), MODULE_NAME "_gpi"))
dev_warn(&pdev->dev, dev_warn(&pdev->dev,
"GPI I/O resource busy, probably claimed by ACPI\n"); "GPI I/O resource busy, probably claimed by ACPI\n");
else
vg->gpi_reserved = true;
if (!request_region(res_gpo->start, resource_size(res_gpo), if (!devm_request_region(&pdev->dev, res_gpo->start,
MODULE_NAME "_gpo")) resource_size(res_gpo), MODULE_NAME "_gpo"))
dev_warn(&pdev->dev, dev_warn(&pdev->dev,
"GPO I/O resource busy, probably claimed by ACPI\n"); "GPO I/O resource busy, probably claimed by ACPI\n");
else
vg->gpo_reserved = true;
vx855gpio_gpio_setup(vg); vx855gpio_gpio_setup(vg);
ret = gpiochip_add(&vg->gpio); return gpiochip_add(&vg->gpio);
if (ret) {
dev_err(&pdev->dev, "failed to register GPIOs\n");
goto out_release;
}
return 0;
out_release:
if (vg->gpi_reserved)
release_region(res_gpi->start, resource_size(res_gpi));
if (vg->gpo_reserved)
release_region(res_gpi->start, resource_size(res_gpo));
kfree(vg);
return ret;
} }
static int vx855gpio_remove(struct platform_device *pdev) static int vx855gpio_remove(struct platform_device *pdev)
{ {
struct vx855_gpio *vg = platform_get_drvdata(pdev); struct vx855_gpio *vg = platform_get_drvdata(pdev);
struct resource *res;
gpiochip_remove(&vg->gpio); gpiochip_remove(&vg->gpio);
if (vg->gpi_reserved) {
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
release_region(res->start, resource_size(res));
}
if (vg->gpo_reserved) {
res = platform_get_resource(pdev, IORESOURCE_IO, 1);
release_region(res->start, resource_size(res));
}
kfree(vg);
return 0; return 0;
} }
......
/*
* AppliedMicro X-Gene SoC GPIO-Standby Driver
*
* Copyright (c) 2014, Applied Micro Circuits Corporation
* Author: Tin Huynh <tnhuynh@apm.com>.
* Y Vo <yvo@apm.com>.
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/module.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/gpio/driver.h>
#include <linux/basic_mmio_gpio.h>
#define XGENE_MAX_GPIO_DS 22
#define XGENE_MAX_GPIO_DS_IRQ 6
#define GPIO_MASK(x) (1U << ((x) % 32))
#define MPA_GPIO_INT_LVL 0x0290
#define MPA_GPIO_OE_ADDR 0x029c
#define MPA_GPIO_OUT_ADDR 0x02a0
#define MPA_GPIO_IN_ADDR 0x02a4
#define MPA_GPIO_SEL_LO 0x0294
/**
* struct xgene_gpio_sb - GPIO-Standby private data structure.
* @bgc: memory-mapped GPIO controllers.
* @irq: Mapping GPIO pins and interrupt number
* nirq: Number of GPIO pins that supports interrupt
*/
struct xgene_gpio_sb {
struct bgpio_chip bgc;
u32 *irq;
u32 nirq;
};
static inline struct xgene_gpio_sb *to_xgene_gpio_sb(struct gpio_chip *gc)
{
struct bgpio_chip *bgc = to_bgpio_chip(gc);
return container_of(bgc, struct xgene_gpio_sb, bgc);
}
static void xgene_gpio_set_bit(struct bgpio_chip *bgc, void __iomem *reg, u32 gpio, int val)
{
u32 data;
data = bgc->read_reg(reg);
if (val)
data |= GPIO_MASK(gpio);
else
data &= ~GPIO_MASK(gpio);
bgc->write_reg(reg, data);
}
static int apm_gpio_sb_to_irq(struct gpio_chip *gc, u32 gpio)
{
struct xgene_gpio_sb *priv = to_xgene_gpio_sb(gc);
if (priv->irq[gpio])
return priv->irq[gpio];
return -ENXIO;
}
static int xgene_gpio_sb_probe(struct platform_device *pdev)
{
struct xgene_gpio_sb *priv;
u32 ret, i;
u32 default_lines[] = {0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D};
struct resource *res;
void __iomem *regs;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(&pdev->dev, res);
if (!regs)
return PTR_ERR(regs);
ret = bgpio_init(&priv->bgc, &pdev->dev, 4,
regs + MPA_GPIO_IN_ADDR,
regs + MPA_GPIO_OUT_ADDR, NULL,
regs + MPA_GPIO_OE_ADDR, NULL, 0);
if (ret)
return ret;
priv->bgc.gc.to_irq = apm_gpio_sb_to_irq;
priv->bgc.gc.ngpio = XGENE_MAX_GPIO_DS;
priv->nirq = XGENE_MAX_GPIO_DS_IRQ;
priv->irq = devm_kzalloc(&pdev->dev, sizeof(u32) * XGENE_MAX_GPIO_DS,
GFP_KERNEL);
if (!priv->irq)
return -ENOMEM;
memset(priv->irq, 0, sizeof(u32) * XGENE_MAX_GPIO_DS);
for (i = 0; i < priv->nirq; i++) {
priv->irq[default_lines[i]] = platform_get_irq(pdev, i);
xgene_gpio_set_bit(&priv->bgc, regs + MPA_GPIO_SEL_LO,
default_lines[i] * 2, 1);
xgene_gpio_set_bit(&priv->bgc, regs + MPA_GPIO_INT_LVL, i, 1);
}
platform_set_drvdata(pdev, priv);
ret = gpiochip_add(&priv->bgc.gc);
if (ret)
dev_err(&pdev->dev, "failed to register X-Gene GPIO Standby driver\n");
else
dev_info(&pdev->dev, "X-Gene GPIO Standby driver registered\n");
return ret;
}
static int xgene_gpio_sb_remove(struct platform_device *pdev)
{
struct xgene_gpio_sb *priv = platform_get_drvdata(pdev);
return bgpio_remove(&priv->bgc);
}
static const struct of_device_id xgene_gpio_sb_of_match[] = {
{.compatible = "apm,xgene-gpio-sb", },
{},
};
MODULE_DEVICE_TABLE(of, xgene_gpio_sb_of_match);
static struct platform_driver xgene_gpio_sb_driver = {
.driver = {
.name = "xgene-gpio-sb",
.of_match_table = xgene_gpio_sb_of_match,
},
.probe = xgene_gpio_sb_probe,
.remove = xgene_gpio_sb_remove,
};
module_platform_driver(xgene_gpio_sb_driver);
MODULE_AUTHOR("AppliedMicro");
MODULE_DESCRIPTION("APM X-Gene GPIO Standby driver");
MODULE_LICENSE("GPL");
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#define XGPIO_CHANNEL_OFFSET 0x8 #define XGPIO_CHANNEL_OFFSET 0x8
/* Read/Write access to the GPIO registers */ /* Read/Write access to the GPIO registers */
#ifdef CONFIG_ARCH_ZYNQ #if defined(CONFIG_ARCH_ZYNQ) || defined(CONFIG_X86)
# define xgpio_readreg(offset) readl(offset) # define xgpio_readreg(offset) readl(offset)
# define xgpio_writereg(offset, val) writel(val, offset) # define xgpio_writereg(offset, val) writel(val, offset)
#else #else
...@@ -40,37 +40,66 @@ ...@@ -40,37 +40,66 @@
/** /**
* struct xgpio_instance - Stores information about GPIO device * struct xgpio_instance - Stores information about GPIO device
* struct of_mm_gpio_chip mmchip: OF GPIO chip for memory mapped banks * @mmchip: OF GPIO chip for memory mapped banks
* gpio_state: GPIO state shadow register * @gpio_state: GPIO state shadow register
* gpio_dir: GPIO direction shadow register * @gpio_dir: GPIO direction shadow register
* offset: GPIO channel offset * @gpio_lock: Lock used for synchronization
* gpio_lock: Lock used for synchronization * @inited: True if the port has been inited
*/ */
struct xgpio_instance { struct xgpio_instance {
struct of_mm_gpio_chip mmchip; struct of_mm_gpio_chip mmchip;
u32 gpio_state; unsigned int gpio_width[2];
u32 gpio_dir; u32 gpio_state[2];
u32 offset; u32 gpio_dir[2];
spinlock_t gpio_lock; spinlock_t gpio_lock[2];
}; };
static inline int xgpio_index(struct xgpio_instance *chip, int gpio)
{
if (gpio >= chip->gpio_width[0])
return 1;
return 0;
}
static inline int xgpio_regoffset(struct xgpio_instance *chip, int gpio)
{
if (xgpio_index(chip, gpio))
return XGPIO_CHANNEL_OFFSET;
return 0;
}
static inline int xgpio_offset(struct xgpio_instance *chip, int gpio)
{
if (xgpio_index(chip, gpio))
return gpio - chip->gpio_width[0];
return gpio;
}
/** /**
* xgpio_get - Read the specified signal of the GPIO device. * xgpio_get - Read the specified signal of the GPIO device.
* @gc: Pointer to gpio_chip device structure. * @gc: Pointer to gpio_chip device structure.
* @gpio: GPIO signal number. * @gpio: GPIO signal number.
* *
* This function reads the specified signal of the GPIO device. It returns 0 if * This function reads the specified signal of the GPIO device.
* the signal clear, 1 if signal is set or negative value on error. *
* Return:
* 0 if direction of GPIO signals is set as input otherwise it
* returns negative error value.
*/ */
static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) static int xgpio_get(struct gpio_chip *gc, unsigned int gpio)
{ {
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
struct xgpio_instance *chip = struct xgpio_instance *chip =
container_of(mm_gc, struct xgpio_instance, mmchip); container_of(mm_gc, struct xgpio_instance, mmchip);
u32 val;
void __iomem *regs = mm_gc->regs + chip->offset; val = xgpio_readreg(mm_gc->regs + XGPIO_DATA_OFFSET +
xgpio_regoffset(chip, gpio));
return !!(xgpio_readreg(regs + XGPIO_DATA_OFFSET) & BIT(gpio)); return !!(val & BIT(xgpio_offset(chip, gpio)));
} }
/** /**
...@@ -88,20 +117,21 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) ...@@ -88,20 +117,21 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
struct xgpio_instance *chip = struct xgpio_instance *chip =
container_of(mm_gc, struct xgpio_instance, mmchip); container_of(mm_gc, struct xgpio_instance, mmchip);
void __iomem *regs = mm_gc->regs; int index = xgpio_index(chip, gpio);
int offset = xgpio_offset(chip, gpio);
spin_lock_irqsave(&chip->gpio_lock, flags); spin_lock_irqsave(&chip->gpio_lock[index], flags);
/* Write to GPIO signal and set its direction to output */ /* Write to GPIO signal and set its direction to output */
if (val) if (val)
chip->gpio_state |= BIT(gpio); chip->gpio_state[index] |= BIT(offset);
else else
chip->gpio_state &= ~BIT(gpio); chip->gpio_state[index] &= ~BIT(offset);
xgpio_writereg(regs + chip->offset + XGPIO_DATA_OFFSET, xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET +
chip->gpio_state); xgpio_regoffset(chip, gpio), chip->gpio_state[index]);
spin_unlock_irqrestore(&chip->gpio_lock, flags); spin_unlock_irqrestore(&chip->gpio_lock[index], flags);
} }
/** /**
...@@ -109,9 +139,9 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) ...@@ -109,9 +139,9 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
* @gc: Pointer to gpio_chip device structure. * @gc: Pointer to gpio_chip device structure.
* @gpio: GPIO signal number. * @gpio: GPIO signal number.
* *
* This function sets the direction of specified GPIO signal as input. * Return:
* It returns 0 if direction of GPIO signals is set as input otherwise it * 0 - if direction of GPIO signals is set as input
* returns negative error value. * otherwise it returns negative error value.
*/ */
static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
{ {
...@@ -119,15 +149,17 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) ...@@ -119,15 +149,17 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
struct xgpio_instance *chip = struct xgpio_instance *chip =
container_of(mm_gc, struct xgpio_instance, mmchip); container_of(mm_gc, struct xgpio_instance, mmchip);
void __iomem *regs = mm_gc->regs; int index = xgpio_index(chip, gpio);
int offset = xgpio_offset(chip, gpio);
spin_lock_irqsave(&chip->gpio_lock, flags); spin_lock_irqsave(&chip->gpio_lock[index], flags);
/* Set the GPIO bit in shadow register and set direction as input */ /* Set the GPIO bit in shadow register and set direction as input */
chip->gpio_dir |= BIT(gpio); chip->gpio_dir[index] |= BIT(offset);
xgpio_writereg(regs + chip->offset + XGPIO_TRI_OFFSET, chip->gpio_dir); xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET +
xgpio_regoffset(chip, gpio), chip->gpio_dir[index]);
spin_unlock_irqrestore(&chip->gpio_lock, flags); spin_unlock_irqrestore(&chip->gpio_lock[index], flags);
return 0; return 0;
} }
...@@ -138,8 +170,10 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) ...@@ -138,8 +170,10 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
* @gpio: GPIO signal number. * @gpio: GPIO signal number.
* @val: Value to be written to specified signal. * @val: Value to be written to specified signal.
* *
* This function sets the direction of specified GPIO signal as output. If all * This function sets the direction of specified GPIO signal as output.
* GPIO signals of GPIO chip is configured as input then it returns *
* Return:
* If all GPIO signals of GPIO chip is configured as input then it returns
* error otherwise it returns 0. * error otherwise it returns 0.
*/ */
static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
...@@ -148,80 +182,128 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) ...@@ -148,80 +182,128 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
struct xgpio_instance *chip = struct xgpio_instance *chip =
container_of(mm_gc, struct xgpio_instance, mmchip); container_of(mm_gc, struct xgpio_instance, mmchip);
void __iomem *regs = mm_gc->regs; int index = xgpio_index(chip, gpio);
int offset = xgpio_offset(chip, gpio);
spin_lock_irqsave(&chip->gpio_lock, flags); spin_lock_irqsave(&chip->gpio_lock[index], flags);
/* Write state of GPIO signal */ /* Write state of GPIO signal */
if (val) if (val)
chip->gpio_state |= BIT(gpio); chip->gpio_state[index] |= BIT(offset);
else else
chip->gpio_state &= ~BIT(gpio); chip->gpio_state[index] &= ~BIT(offset);
xgpio_writereg(regs + chip->offset + XGPIO_DATA_OFFSET, xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET +
chip->gpio_state); xgpio_regoffset(chip, gpio), chip->gpio_state[index]);
/* Clear the GPIO bit in shadow register and set direction as output */ /* Clear the GPIO bit in shadow register and set direction as output */
chip->gpio_dir &= ~BIT(gpio); chip->gpio_dir[index] &= ~BIT(offset);
xgpio_writereg(regs + chip->offset + XGPIO_TRI_OFFSET, chip->gpio_dir); xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET +
xgpio_regoffset(chip, gpio), chip->gpio_dir[index]);
spin_unlock_irqrestore(&chip->gpio_lock, flags); spin_unlock_irqrestore(&chip->gpio_lock[index], flags);
return 0; return 0;
} }
/** /**
* xgpio_save_regs - Set initial values of GPIO pins * xgpio_save_regs - Set initial values of GPIO pins
* @mm_gc: pointer to memory mapped GPIO chip structure * @mm_gc: Pointer to memory mapped GPIO chip structure
*/ */
static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc) static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc)
{ {
struct xgpio_instance *chip = struct xgpio_instance *chip =
container_of(mm_gc, struct xgpio_instance, mmchip); container_of(mm_gc, struct xgpio_instance, mmchip);
xgpio_writereg(mm_gc->regs + chip->offset + XGPIO_DATA_OFFSET, xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state[0]);
chip->gpio_state); xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir[0]);
xgpio_writereg(mm_gc->regs + chip->offset + XGPIO_TRI_OFFSET,
chip->gpio_dir); if (!chip->gpio_width[1])
return;
xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + XGPIO_TRI_OFFSET,
chip->gpio_state[1]);
xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET + XGPIO_TRI_OFFSET,
chip->gpio_dir[1]);
}
/**
* xgpio_remove - Remove method for the GPIO device.
* @pdev: pointer to the platform device
*
* This function remove gpiochips and frees all the allocated resources.
*/
static int xgpio_remove(struct platform_device *pdev)
{
struct xgpio_instance *chip = platform_get_drvdata(pdev);
of_mm_gpiochip_remove(&chip->mmchip);
return 0;
} }
/** /**
* xgpio_of_probe - Probe method for the GPIO device. * xgpio_of_probe - Probe method for the GPIO device.
* @np: pointer to device tree node * @pdev: pointer to the platform device
* *
* This function probes the GPIO device in the device tree. It initializes the * Return:
* driver data structure. It returns 0, if the driver is bound to the GPIO * It returns 0, if the driver is bound to the GPIO device, or
* device, or a negative value if there is an error. * a negative value if there is an error.
*/ */
static int xgpio_of_probe(struct device_node *np) static int xgpio_probe(struct platform_device *pdev)
{ {
struct xgpio_instance *chip; struct xgpio_instance *chip;
int status = 0; int status = 0;
const u32 *tree_info; struct device_node *np = pdev->dev.of_node;
u32 ngpio; u32 is_dual;
chip = kzalloc(sizeof(*chip), GFP_KERNEL); chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
if (!chip) if (!chip)
return -ENOMEM; return -ENOMEM;
/* Update GPIO state shadow register with default value */ platform_set_drvdata(pdev, chip);
of_property_read_u32(np, "xlnx,dout-default", &chip->gpio_state);
/* By default, all pins are inputs */ /* Update GPIO state shadow register with default value */
chip->gpio_dir = 0xFFFFFFFF; of_property_read_u32(np, "xlnx,dout-default", &chip->gpio_state[0]);
/* Update GPIO direction shadow register with default value */ /* Update GPIO direction shadow register with default value */
of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir); if (of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir[0]))
chip->gpio_dir[0] = 0xFFFFFFFF;
/* /*
* Check device node and parent device node for device width * Check device node and parent device node for device width
* and assume default width of 32 * and assume default width of 32
*/ */
if (of_property_read_u32(np, "xlnx,gpio-width", &ngpio)) if (of_property_read_u32(np, "xlnx,gpio-width", &chip->gpio_width[0]))
ngpio = 32; chip->gpio_width[0] = 32;
chip->mmchip.gc.ngpio = (u16)ngpio;
spin_lock_init(&chip->gpio_lock[0]);
if (of_property_read_u32(np, "xlnx,is-dual", &is_dual))
is_dual = 0;
if (is_dual) {
/* Update GPIO state shadow register with default value */
of_property_read_u32(np, "xlnx,dout-default-2",
&chip->gpio_state[1]);
spin_lock_init(&chip->gpio_lock); /* Update GPIO direction shadow register with default value */
if (of_property_read_u32(np, "xlnx,tri-default-2",
&chip->gpio_dir[1]))
chip->gpio_dir[1] = 0xFFFFFFFF;
/*
* Check device node and parent device node for device width
* and assume default width of 32
*/
if (of_property_read_u32(np, "xlnx,gpio2-width",
&chip->gpio_width[1]))
chip->gpio_width[1] = 32;
spin_lock_init(&chip->gpio_lock[1]);
}
chip->mmchip.gc.ngpio = chip->gpio_width[0] + chip->gpio_width[1];
chip->mmchip.gc.dev = &pdev->dev;
chip->mmchip.gc.direction_input = xgpio_dir_in; chip->mmchip.gc.direction_input = xgpio_dir_in;
chip->mmchip.gc.direction_output = xgpio_dir_out; chip->mmchip.gc.direction_output = xgpio_dir_out;
chip->mmchip.gc.get = xgpio_get; chip->mmchip.gc.get = xgpio_get;
...@@ -232,63 +314,11 @@ static int xgpio_of_probe(struct device_node *np) ...@@ -232,63 +314,11 @@ static int xgpio_of_probe(struct device_node *np)
/* Call the OF gpio helper to setup and register the GPIO device */ /* Call the OF gpio helper to setup and register the GPIO device */
status = of_mm_gpiochip_add(np, &chip->mmchip); status = of_mm_gpiochip_add(np, &chip->mmchip);
if (status) { if (status) {
kfree(chip);
pr_err("%s: error in probe function with status %d\n", pr_err("%s: error in probe function with status %d\n",
np->full_name, status); np->full_name, status);
return status; return status;
} }
pr_info("XGpio: %s: registered, base is %d\n", np->full_name,
chip->mmchip.gc.base);
tree_info = of_get_property(np, "xlnx,is-dual", NULL);
if (tree_info && be32_to_cpup(tree_info)) {
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
/* Add dual channel offset */
chip->offset = XGPIO_CHANNEL_OFFSET;
/* Update GPIO state shadow register with default value */
of_property_read_u32(np, "xlnx,dout-default-2",
&chip->gpio_state);
/* By default, all pins are inputs */
chip->gpio_dir = 0xFFFFFFFF;
/* Update GPIO direction shadow register with default value */
of_property_read_u32(np, "xlnx,tri-default-2", &chip->gpio_dir);
/*
* Check device node and parent device node for device width
* and assume default width of 32
*/
if (of_property_read_u32(np, "xlnx,gpio2-width", &ngpio))
ngpio = 32;
chip->mmchip.gc.ngpio = (u16)ngpio;
spin_lock_init(&chip->gpio_lock);
chip->mmchip.gc.direction_input = xgpio_dir_in;
chip->mmchip.gc.direction_output = xgpio_dir_out;
chip->mmchip.gc.get = xgpio_get;
chip->mmchip.gc.set = xgpio_set;
chip->mmchip.save_regs = xgpio_save_regs;
/* Call the OF gpio helper to setup and register the GPIO dev */
status = of_mm_gpiochip_add(np, &chip->mmchip);
if (status) {
kfree(chip);
pr_err("%s: error in probe function with status %d\n",
np->full_name, status);
return status;
}
pr_info("XGpio: %s: dual channel registered, base is %d\n",
np->full_name, chip->mmchip.gc.base);
}
return 0; return 0;
} }
...@@ -297,19 +327,29 @@ static const struct of_device_id xgpio_of_match[] = { ...@@ -297,19 +327,29 @@ static const struct of_device_id xgpio_of_match[] = {
{ /* end of list */ }, { /* end of list */ },
}; };
static int __init xgpio_init(void) MODULE_DEVICE_TABLE(of, xgpio_of_match);
{
struct device_node *np;
for_each_matching_node(np, xgpio_of_match) static struct platform_driver xgpio_plat_driver = {
xgpio_of_probe(np); .probe = xgpio_probe,
.remove = xgpio_remove,
.driver = {
.name = "gpio-xilinx",
.of_match_table = xgpio_of_match,
},
};
return 0; static int __init xgpio_init(void)
{
return platform_driver_register(&xgpio_plat_driver);
} }
/* Make sure we get initialized before anyone else tries to use us */
subsys_initcall(xgpio_init); subsys_initcall(xgpio_init);
/* No exit call at the moment as we cannot unregister of GPIO chips */
static void __exit xgpio_exit(void)
{
platform_driver_unregister(&xgpio_plat_driver);
}
module_exit(xgpio_exit);
MODULE_AUTHOR("Xilinx, Inc."); MODULE_AUTHOR("Xilinx, Inc.");
MODULE_DESCRIPTION("Xilinx GPIO driver"); MODULE_DESCRIPTION("Xilinx GPIO driver");
......
...@@ -181,6 +181,8 @@ static int zevio_gpio_probe(struct platform_device *pdev) ...@@ -181,6 +181,8 @@ static int zevio_gpio_probe(struct platform_device *pdev)
if (!controller) if (!controller)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(pdev, controller);
/* Copy our reference */ /* Copy our reference */
controller->chip.gc = zevio_gpio_chip; controller->chip.gc = zevio_gpio_chip;
controller->chip.gc.dev = &pdev->dev; controller->chip.gc.dev = &pdev->dev;
...@@ -202,6 +204,15 @@ static int zevio_gpio_probe(struct platform_device *pdev) ...@@ -202,6 +204,15 @@ static int zevio_gpio_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int zevio_gpio_remove(struct platform_device *pdev)
{
struct zevio_gpio *controller = platform_get_drvdata(pdev);
of_mm_gpiochip_remove(&controller->chip);
return 0;
}
static const struct of_device_id zevio_gpio_of_match[] = { static const struct of_device_id zevio_gpio_of_match[] = {
{ .compatible = "lsi,zevio-gpio", }, { .compatible = "lsi,zevio-gpio", },
{ }, { },
...@@ -215,6 +226,7 @@ static struct platform_driver zevio_gpio_driver = { ...@@ -215,6 +226,7 @@ static struct platform_driver zevio_gpio_driver = {
.of_match_table = zevio_gpio_of_match, .of_match_table = zevio_gpio_of_match,
}, },
.probe = zevio_gpio_probe, .probe = zevio_gpio_probe,
.remove = zevio_gpio_remove,
}; };
module_platform_driver(zevio_gpio_driver); module_platform_driver(zevio_gpio_driver);
......
...@@ -210,6 +210,23 @@ int of_mm_gpiochip_add(struct device_node *np, ...@@ -210,6 +210,23 @@ int of_mm_gpiochip_add(struct device_node *np,
} }
EXPORT_SYMBOL(of_mm_gpiochip_add); EXPORT_SYMBOL(of_mm_gpiochip_add);
/**
* of_mm_gpiochip_remove - Remove memory mapped GPIO chip (bank)
* @mm_gc: pointer to the of_mm_gpio_chip allocated structure
*/
void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc)
{
struct gpio_chip *gc = &mm_gc->gc;
if (!mm_gc)
return;
gpiochip_remove(gc);
iounmap(mm_gc->regs);
kfree(gc->label);
}
EXPORT_SYMBOL(of_mm_gpiochip_remove);
#ifdef CONFIG_PINCTRL #ifdef CONFIG_PINCTRL
static void of_gpiochip_add_pin_range(struct gpio_chip *chip) static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
{ {
......
...@@ -1659,7 +1659,7 @@ static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, ...@@ -1659,7 +1659,7 @@ static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
unsigned int idx, unsigned int idx,
enum gpio_lookup_flags *flags) enum gpio_lookup_flags *flags)
{ {
static const char *suffixes[] = { "gpios", "gpio" }; static const char * const suffixes[] = { "gpios", "gpio" };
char prop_name[32]; /* 32 is max size of property name */ char prop_name[32]; /* 32 is max size of property name */
enum of_gpio_flags of_flags; enum of_gpio_flags of_flags;
struct gpio_desc *desc; struct gpio_desc *desc;
...@@ -1667,9 +1667,11 @@ static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, ...@@ -1667,9 +1667,11 @@ static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
for (i = 0; i < ARRAY_SIZE(suffixes); i++) { for (i = 0; i < ARRAY_SIZE(suffixes); i++) {
if (con_id) if (con_id)
snprintf(prop_name, 32, "%s-%s", con_id, suffixes[i]); snprintf(prop_name, sizeof(prop_name), "%s-%s", con_id,
suffixes[i]);
else else
snprintf(prop_name, 32, "%s", suffixes[i]); snprintf(prop_name, sizeof(prop_name), "%s",
suffixes[i]);
desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx, desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx,
&of_flags); &of_flags);
......
...@@ -340,31 +340,32 @@ static inline int desc_to_gpio(const struct gpio_desc *desc) ...@@ -340,31 +340,32 @@ static inline int desc_to_gpio(const struct gpio_desc *desc)
* etc. * etc.
*/ */
#define __gpiod_get(dev, con_id, flags, ...) __gpiod_get(dev, con_id, flags) #define __gpiod_get(dev, con_id, flags, ...) __gpiod_get(dev, con_id, flags)
#define gpiod_get(varargs...) __gpiod_get(varargs, 0) #define gpiod_get(varargs...) __gpiod_get(varargs, GPIOD_ASIS)
#define __gpiod_get_index(dev, con_id, index, flags, ...) \ #define __gpiod_get_index(dev, con_id, index, flags, ...) \
__gpiod_get_index(dev, con_id, index, flags) __gpiod_get_index(dev, con_id, index, flags)
#define gpiod_get_index(varargs...) __gpiod_get_index(varargs, 0) #define gpiod_get_index(varargs...) __gpiod_get_index(varargs, GPIOD_ASIS)
#define __gpiod_get_optional(dev, con_id, flags, ...) \ #define __gpiod_get_optional(dev, con_id, flags, ...) \
__gpiod_get_optional(dev, con_id, flags) __gpiod_get_optional(dev, con_id, flags)
#define gpiod_get_optional(varargs...) __gpiod_get_optional(varargs, 0) #define gpiod_get_optional(varargs...) __gpiod_get_optional(varargs, GPIOD_ASIS)
#define __gpiod_get_index_optional(dev, con_id, index, flags, ...) \ #define __gpiod_get_index_optional(dev, con_id, index, flags, ...) \
__gpiod_get_index_optional(dev, con_id, index, flags) __gpiod_get_index_optional(dev, con_id, index, flags)
#define gpiod_get_index_optional(varargs...) \ #define gpiod_get_index_optional(varargs...) \
__gpiod_get_index_optional(varargs, 0) __gpiod_get_index_optional(varargs, GPIOD_ASIS)
#define __devm_gpiod_get(dev, con_id, flags, ...) \ #define __devm_gpiod_get(dev, con_id, flags, ...) \
__devm_gpiod_get(dev, con_id, flags) __devm_gpiod_get(dev, con_id, flags)
#define devm_gpiod_get(varargs...) __devm_gpiod_get(varargs, 0) #define devm_gpiod_get(varargs...) __devm_gpiod_get(varargs, GPIOD_ASIS)
#define __devm_gpiod_get_index(dev, con_id, index, flags, ...) \ #define __devm_gpiod_get_index(dev, con_id, index, flags, ...) \
__devm_gpiod_get_index(dev, con_id, index, flags) __devm_gpiod_get_index(dev, con_id, index, flags)
#define devm_gpiod_get_index(varargs...) __devm_gpiod_get_index(varargs, 0) #define devm_gpiod_get_index(varargs...) \
__devm_gpiod_get_index(varargs, GPIOD_ASIS)
#define __devm_gpiod_get_optional(dev, con_id, flags, ...) \ #define __devm_gpiod_get_optional(dev, con_id, flags, ...) \
__devm_gpiod_get_optional(dev, con_id, flags) __devm_gpiod_get_optional(dev, con_id, flags)
#define devm_gpiod_get_optional(varargs...) \ #define devm_gpiod_get_optional(varargs...) \
__devm_gpiod_get_optional(varargs, 0) __devm_gpiod_get_optional(varargs, GPIOD_ASIS)
#define __devm_gpiod_get_index_optional(dev, con_id, index, flags, ...) \ #define __devm_gpiod_get_index_optional(dev, con_id, index, flags, ...) \
__devm_gpiod_get_index_optional(dev, con_id, index, flags) __devm_gpiod_get_index_optional(dev, con_id, index, flags)
#define devm_gpiod_get_index_optional(varargs...) \ #define devm_gpiod_get_index_optional(varargs...) \
__devm_gpiod_get_index_optional(varargs, 0) __devm_gpiod_get_index_optional(varargs, GPIOD_ASIS)
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS)
......
...@@ -117,20 +117,6 @@ extern int stmpe_disable(struct stmpe *stmpe, unsigned int blocks); ...@@ -117,20 +117,6 @@ extern int stmpe_disable(struct stmpe *stmpe, unsigned int blocks);
#define STMPE_GPIO_NOREQ_811_TOUCH (0xf0) #define STMPE_GPIO_NOREQ_811_TOUCH (0xf0)
/**
* struct stmpe_gpio_platform_data - STMPE GPIO platform data
* @norequest_mask: bitmask specifying which GPIOs should _not_ be
* requestable due to different usage (e.g. touch, keypad)
* STMPE_GPIO_NOREQ_* macros can be used here.
* @setup: board specific setup callback.
* @remove: board specific remove callback
*/
struct stmpe_gpio_platform_data {
unsigned norequest_mask;
void (*setup)(struct stmpe *stmpe, unsigned gpio_base);
void (*remove)(struct stmpe *stmpe, unsigned gpio_base);
};
/** /**
* struct stmpe_ts_platform_data - stmpe811 touch screen controller platform * struct stmpe_ts_platform_data - stmpe811 touch screen controller platform
* data * data
...@@ -182,7 +168,6 @@ struct stmpe_ts_platform_data { ...@@ -182,7 +168,6 @@ struct stmpe_ts_platform_data {
* @irq_over_gpio: true if gpio is used to get irq * @irq_over_gpio: true if gpio is used to get irq
* @irq_gpio: gpio number over which irq will be requested (significant only if * @irq_gpio: gpio number over which irq will be requested (significant only if
* irq_over_gpio is true) * irq_over_gpio is true)
* @gpio: GPIO-specific platform data
* @ts: touchscreen-specific platform data * @ts: touchscreen-specific platform data
*/ */
struct stmpe_platform_data { struct stmpe_platform_data {
...@@ -194,7 +179,6 @@ struct stmpe_platform_data { ...@@ -194,7 +179,6 @@ struct stmpe_platform_data {
int irq_gpio; int irq_gpio;
int autosleep_timeout; int autosleep_timeout;
struct stmpe_gpio_platform_data *gpio;
struct stmpe_ts_platform_data *ts; struct stmpe_ts_platform_data *ts;
}; };
......
...@@ -162,25 +162,13 @@ struct tc3589x_keypad_platform_data { ...@@ -162,25 +162,13 @@ struct tc3589x_keypad_platform_data {
bool no_autorepeat; bool no_autorepeat;
}; };
/**
* struct tc3589x_gpio_platform_data - TC3589x GPIO platform data
* @setup: callback for board-specific initialization
* @remove: callback for board-specific teardown
*/
struct tc3589x_gpio_platform_data {
void (*setup)(struct tc3589x *tc3589x, unsigned gpio_base);
void (*remove)(struct tc3589x *tc3589x, unsigned gpio_base);
};
/** /**
* struct tc3589x_platform_data - TC3589x platform data * struct tc3589x_platform_data - TC3589x platform data
* @block: bitmask of blocks to enable (use TC3589x_BLOCK_*) * @block: bitmask of blocks to enable (use TC3589x_BLOCK_*)
* @gpio: GPIO-specific platform data
* @keypad: keypad-specific platform data * @keypad: keypad-specific platform data
*/ */
struct tc3589x_platform_data { struct tc3589x_platform_data {
unsigned int block; unsigned int block;
struct tc3589x_gpio_platform_data *gpio;
const struct tc3589x_keypad_platform_data *keypad; const struct tc3589x_keypad_platform_data *keypad;
}; };
......
...@@ -52,6 +52,7 @@ extern int of_get_named_gpio_flags(struct device_node *np, ...@@ -52,6 +52,7 @@ extern int of_get_named_gpio_flags(struct device_node *np,
extern int of_mm_gpiochip_add(struct device_node *np, extern int of_mm_gpiochip_add(struct device_node *np,
struct of_mm_gpio_chip *mm_gc); struct of_mm_gpio_chip *mm_gc);
extern void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc);
extern void of_gpiochip_add(struct gpio_chip *gc); extern void of_gpiochip_add(struct gpio_chip *gc);
extern void of_gpiochip_remove(struct gpio_chip *gc); extern void of_gpiochip_remove(struct gpio_chip *gc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment