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
  ...
This commit is contained in:
Linus Torvalds
2015-02-11 11:17:34 -08:00
41 changed files with 1534 additions and 809 deletions

View File

@@ -0,0 +1,20 @@
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>;
};

View File

@@ -0,0 +1,59 @@
* 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>;
};

View File

@@ -0,0 +1,40 @@
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;
};

View File

@@ -0,0 +1,32 @@
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>;
};

View File

@@ -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-
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
GPIO controller that achieves (or represents, for inputs) a logically asserted
@@ -147,7 +148,7 @@ contains information structures as follows:
numeric-gpio-range ::=
<pinctrl-phandle> <gpio-base> <pinctrl-base> <count>
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
pinctrl-base : Base pinctrl pin ID in the pin controller
count : The number of GPIOs/pins in this range

View File

@@ -3,8 +3,8 @@
Required properties:
- compatible : Should be "intel,pxa25x-gpio", "intel,pxa26x-gpio",
"intel,pxa27x-gpio", "intel,pxa3xx-gpio",
"marvell,pxa93x-gpio", "marvell,mmp-gpio" or
"marvell,mmp2-gpio".
"marvell,pxa93x-gpio", "marvell,mmp-gpio",
"marvell,mmp2-gpio" or marvell,pxa1928-gpio.
- reg : Address and length of the register set for the device
- interrupts : Should be the port interrupt shared by all gpio pins.
There're three gpio interrupts in arch-pxa, and they're gpio0,

View File

@@ -143,6 +143,7 @@ sandisk Sandisk Corporation
sbs Smart Battery System
schindler Schindler
seagate Seagate Technology PLC
semtech Semtech Corporation
sil Silicon Image
silabs Silicon Laboratories
simtek

View File

@@ -197,9 +197,16 @@ config GPIO_F7188X
To compile this driver as a module, choose M here: the module will
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
bool "MOXART GPIO support"
depends on ARCH_MOXART
select GPIO_GENERIC
help
Select this option to enable GPIO driver for
MOXA ART SoC devices.
@@ -285,6 +292,7 @@ config GPIO_PXA
config GPIO_RCAR
tristate "Renesas R-Car GPIO"
depends on ARM && (ARCH_SHMOBILE || COMPILE_TEST)
select GPIOLIB_IRQCHIP
help
Say yes here to support GPIO on Renesas R-Car SoCs.
@@ -365,9 +373,17 @@ config GPIO_XGENE
the generic flash controller's address and data pins. Say yes
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
bool "Xilinx GPIO support"
depends on PPC_OF || MICROBLAZE || ARCH_ZYNQ
tristate "Xilinx GPIO support"
depends on OF_GPIO && (PPC || MICROBLAZE || ARCH_ZYNQ || X86)
help
Say yes here to support the Xilinx FPGA GPIO device
@@ -394,25 +410,32 @@ config GPIO_VR41XX
Say yes here to support the NEC VR4100 series General-purpose I/O Uint
config GPIO_SCH
tristate "Intel SCH/TunnelCreek/Centerton GPIO"
tristate "Intel SCH/TunnelCreek/Centerton/Quark X1000 GPIO"
depends on PCI && X86
select MFD_CORE
select LPC_SCH
help
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
powered by the core power rail and are turned off during sleep
modes (S3 and higher). The remaining four GPIOs are powered by
the Intel SCH suspend power supply. These GPIOs remain
active during S3. The suspend powered GPIOs can be used to wake the
system from the Suspend-to-RAM state.
The Intel Tunnel Creek processor has 5 GPIOs powered by the
core power rail and 9 from suspend power supply.
The Intel Centerton processor has a total of 30 GPIO pins.
Twenty-one are powered by the core power rail and 9 from the
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
tristate "Intel ICH GPIO"
depends on PCI && X86
@@ -450,6 +473,7 @@ config GPIO_VX855
config GPIO_GE_FPGA
bool "GE FPGA based GPIO"
depends on GE_FPGA
select GPIO_GENERIC
help
Support for common GPIO functionality provided on some GE Single Board
Computers.
@@ -519,6 +543,7 @@ config GPIO_MAX7300
config GPIO_MAX732X
tristate "MAX7319, MAX7320-7327 I2C Port Expanders"
depends on I2C
select IRQ_DOMAIN
help
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
@@ -613,6 +638,7 @@ config GPIO_RC5T583
config GPIO_SX150X
bool "Semtech SX150x I2C GPIO expander"
depends on I2C=y
select GPIOLIB_IRQCHIP
default n
help
Say yes here to provide support for Semtech SX150-series I2C
@@ -624,6 +650,7 @@ config GPIO_SX150X
config GPIO_STMPE
bool "STMPE GPIOs"
depends on MFD_STMPE
depends on OF_GPIO
select GPIOLIB_IRQCHIP
help
This enables support for the GPIOs found on the STMPE I/O

View File

@@ -48,6 +48,7 @@ obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o
obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o
obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.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_MC9S08DZ60) += gpio-mc9s08dz60.o
obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o
@@ -105,6 +106,7 @@ obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o
obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o
obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.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_XTENSA) += gpio-xtensa.o
obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o

View File

@@ -213,6 +213,12 @@ found:
goto out;
}
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.chip.dev = &pdev->dev;

View File

@@ -396,6 +396,7 @@ static void dln2_gpio_event(struct platform_device *pdev, u16 echo,
const void *data, int len)
{
int pin, irq;
const struct {
__le16 count;
__u8 type;

View File

@@ -469,15 +469,13 @@ dwapb_gpio_get_pdata_of(struct device *dev)
if (nports == 0)
return ERR_PTR(-ENODEV);
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return ERR_PTR(-ENOMEM);
pdata->properties = kcalloc(nports, sizeof(*pp), GFP_KERNEL);
if (!pdata->properties) {
kfree(pdata);
pdata->properties = devm_kcalloc(dev, nports, sizeof(*pp), GFP_KERNEL);
if (!pdata->properties)
return ERR_PTR(-ENOMEM);
}
pdata->nports = nports;
@@ -490,8 +488,6 @@ dwapb_gpio_get_pdata_of(struct device *dev)
pp->idx >= DWAPB_MAX_PORTS) {
dev_err(dev, "missing/invalid port index for %s\n",
port_np->full_name);
kfree(pdata->properties);
kfree(pdata);
return ERR_PTR(-EINVAL);
}
@@ -523,15 +519,6 @@ dwapb_gpio_get_pdata_of(struct device *dev)
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)
{
unsigned int i;
@@ -540,40 +527,32 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
int err;
struct device *dev = &pdev->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);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
}
if (!pdata->nports) {
err = -ENODEV;
goto out_err;
}
if (!pdata->nports)
return -ENODEV;
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio) {
err = -ENOMEM;
goto out_err;
}
if (!gpio)
return -ENOMEM;
gpio->dev = &pdev->dev;
gpio->nr_ports = pdata->nports;
gpio->ports = devm_kcalloc(&pdev->dev, gpio->nr_ports,
sizeof(*gpio->ports), GFP_KERNEL);
if (!gpio->ports) {
err = -ENOMEM;
goto out_err;
}
if (!gpio->ports)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
gpio->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(gpio->regs)) {
err = PTR_ERR(gpio->regs);
goto out_err;
}
if (IS_ERR(gpio->regs))
return PTR_ERR(gpio->regs);
for (i = 0; i < gpio->nr_ports; i++) {
err = dwapb_gpio_add_port(gpio, &pdata->properties[i], i);
@@ -582,16 +561,12 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, gpio);
goto out_err;
return 0;
out_unregister:
dwapb_gpio_unregister(gpio);
dwapb_irq_teardown(gpio);
out_err:
if (is_pdata_alloc)
dwapb_free_pdata_of(pdata);
return err;
}

View File

@@ -19,9 +19,12 @@
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/of_address.h>
#include <linux/module.h>
#include <linux/basic_mmio_gpio.h>
#define GEF_GPIO_DIRECT 0x00
#define GEF_GPIO_IN 0x04
@@ -33,53 +36,6 @@
#define GEF_GPIO_OVERRUN 0x1C
#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[] = {
{
.compatible = "gef,sbc610-gpio",
@@ -99,22 +55,50 @@ static int __init gef_gpio_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id =
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);
if (!mmchip)
bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL);
if (!bgc)
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 */
mmchip->gc.ngpio = (u16)(uintptr_t)of_id->data;
mmchip->gc.of_gpio_n_cells = 2;
mmchip->gc.direction_input = gef_gpio_dir_in;
mmchip->gc.direction_output = gef_gpio_dir_out;
mmchip->gc.get = gef_gpio_get;
mmchip->gc.set = gef_gpio_set;
bgc->gc.label = devm_kstrdup(&pdev->dev, pdev->dev.of_node->full_name,
GFP_KERNEL);
if (!bgc->gc.label) {
ret = -ENOMEM;
goto err0;
}
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 */
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 = {

View File

@@ -190,6 +190,79 @@ static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
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)
{
return 0;
@@ -354,11 +427,14 @@ static int bgpio_setup_io(struct bgpio_chip *bgc,
bgc->reg_set = set;
bgc->reg_clr = clr;
bgc->gc.set = bgpio_set_with_clear;
bgc->gc.set_multiple = bgpio_set_multiple_with_clear;
} else if (set && !clr) {
bgc->reg_set = set;
bgc->gc.set = bgpio_set_set;
bgc->gc.set_multiple = bgpio_set_multiple_set;
} else {
bgc->gc.set = bgpio_set;
bgc->gc.set_multiple = bgpio_set_multiple;
}
bgc->gc.get = bgpio_get;

View File

@@ -121,7 +121,7 @@ static int grgpio_to_irq(struct gpio_chip *gc, unsigned offset)
{
struct grgpio_priv *priv = grgpio_gc_to_priv(gc);
if (offset > gc->ngpio)
if (offset >= gc->ngpio)
return -ENXIO;
if (priv->lirqs[offset].index < 0)

View File

@@ -19,8 +19,10 @@
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/i2c.h>
#include <linux/i2c/max732x.h>
#include <linux/of.h>
/*
@@ -116,6 +118,22 @@ static const struct i2c_device_id 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 gpio_chip gpio_chip;
@@ -132,16 +150,22 @@ struct max732x_chip {
uint8_t reg_out[2];
#ifdef CONFIG_GPIO_MAX732X_IRQ
struct mutex irq_lock;
int irq_base;
uint8_t irq_mask;
uint8_t irq_mask_cur;
uint8_t irq_trig_raise;
uint8_t irq_trig_fall;
uint8_t irq_features;
struct irq_domain *irq_domain;
struct mutex irq_lock;
int irq_base;
uint8_t irq_mask;
uint8_t irq_mask_cur;
uint8_t irq_trig_raise;
uint8_t irq_trig_fall;
uint8_t irq_features;
#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)
{
struct i2c_client *client;
@@ -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)
{
struct max732x_chip *chip;
struct max732x_chip *chip = to_max732x(gc);
uint8_t reg_val;
int ret;
chip = container_of(gc, struct max732x_chip, gpio_chip);
ret = max732x_readb(chip, is_group_a(chip, off), &reg_val);
if (ret < 0)
return 0;
@@ -193,18 +215,17 @@ static int max732x_gpio_get_value(struct gpio_chip *gc, unsigned off)
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;
uint8_t reg_out, mask = 1u << (off & 0x7);
struct max732x_chip *chip = to_max732x(gc);
uint8_t reg_out;
int ret;
chip = container_of(gc, struct max732x_chip, gpio_chip);
mutex_lock(&chip->lock);
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);
if (ret < 0)
@@ -219,13 +240,31 @@ out:
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)
{
struct max732x_chip *chip;
struct max732x_chip *chip = to_max732x(gc);
unsigned int mask = 1u << off;
chip = container_of(gc, struct max732x_chip, gpio_chip);
if ((mask & chip->dir_input) == 0) {
dev_dbg(&chip->client->dev, "%s port %d is output only\n",
chip->client->name, 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,
unsigned off, int val)
{
struct max732x_chip *chip;
struct max732x_chip *chip = to_max732x(gc);
unsigned int mask = 1u << off;
chip = container_of(gc, struct max732x_chip, gpio_chip);
if ((mask & chip->dir_output) == 0) {
dev_dbg(&chip->client->dev, "%s port %d is input only\n",
chip->client->name, off);
@@ -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)
{
struct max732x_chip *chip;
struct max732x_chip *chip = to_max732x(gc);
chip = container_of(gc, struct max732x_chip, gpio_chip);
return chip->irq_base + off;
if (chip->irq_domain) {
return irq_create_mapping(chip->irq_domain,
chip->irq_base + off);
} else {
return -ENXIO;
}
}
static void max732x_irq_mask(struct irq_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)
{
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)
@@ -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)
{
struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
uint16_t new_irqs;
uint16_t level;
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);
}
static int max732x_irq_set_type(struct irq_data *d, unsigned int type)
{
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;
if (!(mask & chip->dir_input)) {
@@ -385,7 +436,7 @@ static int max732x_irq_set_type(struct irq_data *d, unsigned int type)
else
chip->irq_trig_raise &= ~mask;
return max732x_gpio_direction_input(&chip->gpio_chip, off);
return 0;
}
static struct irq_chip max732x_irq_chip = {
@@ -441,7 +492,7 @@ static irqreturn_t max732x_irq_handler(int irq, void *devid)
do {
level = __ffs(pending);
handle_nested_irq(level + chip->irq_base);
handle_nested_irq(irq_find_mapping(chip->irq_domain, level));
pending &= ~(1 << level);
} while (pending);
@@ -449,6 +500,44 @@ static irqreturn_t max732x_irq_handler(int irq, void *devid)
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,
const struct i2c_device_id *id)
{
@@ -457,28 +546,19 @@ static int max732x_irq_setup(struct max732x_chip *chip,
int has_irq = max732x_features[id->driver_data] >> 32;
int ret;
if (pdata->irq_base && has_irq != INT_NONE) {
int lvl;
chip->irq_base = pdata->irq_base;
if (((pdata && pdata->irq_base) || client->irq)
&& has_irq != INT_NONE) {
if (pdata)
chip->irq_base = pdata->irq_base;
chip->irq_features = has_irq;
mutex_init(&chip->irq_lock);
for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
int irq = lvl + chip->irq_base;
if (!(chip->dir_input & (1 << lvl)))
continue;
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
chip->irq_domain = irq_domain_add_simple(client->dev.of_node,
chip->gpio_chip.ngpio, chip->irq_base,
&max732x_irq_domain_ops, chip);
if (!chip->irq_domain) {
dev_err(&client->dev, "Failed to create IRQ domain\n");
return -ENOMEM;
}
ret = request_threaded_irq(client->irq,
@@ -498,15 +578,10 @@ static int max732x_irq_setup(struct max732x_chip *chip,
return 0;
out_failed:
chip->irq_base = 0;
max732x_irq_teardown(chip);
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 */
static int max732x_irq_setup(struct max732x_chip *chip,
const struct i2c_device_id *id)
@@ -515,7 +590,7 @@ static int max732x_irq_setup(struct max732x_chip *chip,
struct max732x_platform_data *pdata = dev_get_platdata(&client->dev);
int has_irq = max732x_features[id->driver_data] >> 32;
if (pdata->irq_base && has_irq != INT_NONE)
if (((pdata && pdata->irq_base) || client->irq) && has_irq != INT_NONE)
dev_warn(&client->dev, "interrupt support not compiled in\n");
return 0;
@@ -562,6 +637,7 @@ static int max732x_setup_gpio(struct max732x_chip *chip,
if (chip->dir_output) {
gc->direction_output = max732x_gpio_direction_output;
gc->set = max732x_gpio_set_value;
gc->set_multiple = max732x_gpio_set_multiple;
}
gc->get = max732x_gpio_get_value;
gc->can_sleep = true;
@@ -574,28 +650,47 @@ static int max732x_setup_gpio(struct max732x_chip *chip,
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,
const struct i2c_device_id *id)
{
struct max732x_platform_data *pdata;
struct device_node *node;
struct max732x_chip *chip;
struct i2c_client *c;
uint16_t addr_a, addr_b;
int ret, nr_port;
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");
return -EINVAL;
}
chip = devm_kzalloc(&client->dev, sizeof(struct max732x_chip),
GFP_KERNEL);
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
chip->client = client;
nr_port = max732x_setup_gpio(chip, id, pdata->gpio_base);
chip->gpio_chip.dev = &client->dev;
addr_a = (client->addr & 0x0f) | 0x60;
addr_b = (client->addr & 0x0f) | 0x50;
@@ -643,7 +738,7 @@ static int max732x_probe(struct i2c_client *client,
if (ret)
goto out_failed;
if (pdata->setup) {
if (pdata && pdata->setup) {
ret = pdata->setup(client, chip->gpio_chip.base,
chip->gpio_chip.ngpio, pdata->context);
if (ret < 0)
@@ -664,9 +759,10 @@ static int max732x_remove(struct i2c_client *client)
{
struct max732x_platform_data *pdata = dev_get_platdata(&client->dev);
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,
chip->gpio_chip.ngpio, pdata->context);
if (ret < 0) {
@@ -689,8 +785,9 @@ static int max732x_remove(struct i2c_client *client)
static struct i2c_driver max732x_driver = {
.driver = {
.name = "max732x",
.owner = THIS_MODULE,
.name = "max732x",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(max732x_of_table),
},
.probe = max732x_probe,
.remove = max732x_remove,

232
drivers/gpio/gpio-mb86s7x.c Normal file
View File

@@ -0,0 +1,232 @@
/*
* 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");

View File

@@ -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)
{
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct ltq_mm *chip;
const __be32 *shadow;
int ret = 0;
u32 shadow;
if (!res) {
dev_err(&pdev->dev, "failed to get memory resource\n");
return -ENOENT;
}
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
platform_set_drvdata(pdev, chip);
chip->mmchip.gc.ngpio = 16;
chip->mmchip.gc.label = "gpio-mm-ltq";
chip->mmchip.gc.direction_output = ltq_mm_dir_out;
chip->mmchip.gc.set = ltq_mm_set;
chip->mmchip.save_regs = ltq_mm_save_regs;
/* store the shadow value if one was passed by the devicetree */
shadow = of_get_property(pdev->dev.of_node, "lantiq,shadow", NULL);
if (shadow)
chip->shadow = be32_to_cpu(*shadow);
if (!of_property_read_u32(pdev->dev.of_node, "lantiq,shadow", &shadow))
chip->shadow = shadow;
ret = of_mm_gpiochip_add(pdev->dev.of_node, &chip->mmchip);
if (ret)
kfree(chip);
return ret;
return of_mm_gpiochip_add(pdev->dev.of_node, &chip->mmchip);
}
static int ltq_mm_remove(struct platform_device *pdev)
{
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[] = {
@@ -143,6 +142,7 @@ MODULE_DEVICE_TABLE(of, ltq_mm_match);
static struct platform_driver ltq_mm_driver = {
.probe = ltq_mm_probe,
.remove = ltq_mm_remove,
.driver = {
.name = "gpio-mm-ltq",
.of_match_table = ltq_mm_match,
@@ -155,3 +155,9 @@ static int __init ltq_mm_init(void)
}
subsys_initcall(ltq_mm_init);
static void __exit ltq_mm_exit(void)
{
platform_driver_unregister(&ltq_mm_driver);
}
module_exit(ltq_mm_exit);

View File

@@ -23,21 +23,12 @@
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/bitops.h>
#include <linux/basic_mmio_gpio.h>
#define GPIO_DATA_OUT 0x00
#define GPIO_DATA_IN 0x04
#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)
{
return pinctrl_request_gpio(offset);
@@ -48,90 +39,60 @@ static void moxart_gpio_free(struct gpio_chip *chip, unsigned 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)
{
struct moxart_gpio_chip *gc = to_moxart_gpio(chip);
u32 ret = readl(gc->base + GPIO_PIN_DIRECTION);
struct bgpio_chip *bgc = to_bgpio_chip(chip);
u32 ret = bgc->read_reg(bgc->reg_dir);
if (ret & BIT(offset))
return !!(readl(gc->base + GPIO_DATA_OUT) & BIT(offset));
return !!(bgc->read_reg(bgc->reg_set) & BIT(offset));
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)
{
struct device *dev = &pdev->dev;
struct resource *res;
struct moxart_gpio_chip *mgc;
struct bgpio_chip *bgc;
void __iomem *base;
int ret;
mgc = devm_kzalloc(dev, sizeof(*mgc), GFP_KERNEL);
if (!mgc)
bgc = devm_kzalloc(dev, sizeof(*bgc), GFP_KERNEL);
if (!bgc)
return -ENOMEM;
mgc->gpio = moxart_template_chip;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mgc->base = devm_ioremap_resource(dev, res);
if (IS_ERR(mgc->base))
return PTR_ERR(mgc->base);
base = devm_ioremap_resource(dev, res);
if (IS_ERR(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) {
dev_err(dev, "%s: gpiochip_add failed\n",
dev->of_node->full_name);
return ret;
}
return 0;
return ret;
}
static const struct of_device_id moxart_gpio_match[] = {

View File

@@ -155,10 +155,12 @@ static int mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
struct gpio_chip *gc;
int ret;
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
chip = devm_kzalloc(&ofdev->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
platform_set_drvdata(ofdev, chip);
gc = &chip->mmchip.gc;
gc->ngpio = 8;
@@ -181,7 +183,11 @@ static int mpc52xx_wkup_gpiochip_probe(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[] = {
@@ -314,10 +320,12 @@ static int mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)
struct mpc52xx_gpio __iomem *regs;
int ret;
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
chip = devm_kzalloc(&ofdev->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
platform_set_drvdata(ofdev, chip);
gc = &chip->mmchip.gc;
gc->ngpio = 32;
@@ -363,11 +371,16 @@ static int __init mpc52xx_gpio_init(void)
return 0;
}
/* Make sure we get initialised before anyone else tries to use us */
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_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de");

Some files were not shown because too many files have changed in this diff Show More