Commit 6de4c691 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull GPIO updates from Linus Walleij:
 "This is the bulk of GPIO changes for the v4.19 kernel cycle.

  I don't know if anything in particular stands out. Maybe the Aspeed
  coprocessor thing from Benji: Aspeed is doing baseboard management
  chips (BMC's) for servers etc.

  These Aspeed's are ARM processors that exist inside (I guess) Intel
  servers, and they are moving forward to using mainline Linux in those.
  This is one of the pieces of the puzzle to achive that. They are doing
  OpenBMC, it's pretty cool: https://lwn.net/Articles/683320/

  Summary:

  Core changes:

   - Add a new API for explicitly naming GPIO consumers, when needed.

   - Don't let userspace set values on input lines. While we do not
     think anyone would do this crazy thing we better plug the hole
     before someone uses it and think it's a nifty feature.

   - Avoid calling chip->request() for unused GPIOs.

  New drivers/subdrivers:

   - The Mediatek MT7621 is supported which is a big win for OpenWRT and
     similar router distributions using this chip, as it seems every
     major router manufacturer on the planet has made products using
     this chip: https://wikidevi.com/wiki/MediaTek_MT7621

   - The Tegra 194 is now supported.

   - The IT87 driver now supports IT8786E and IT8718F super-IO chips.

   - Add support for Rockchip RK3328 in the syscon GPIO driver.

  Driver changes:

   - Handle the get/set_multiple() properly on MMIO chips with inverted
     direction registers. We didn't have this problem until a new chip
     appear that has get/set registers AND inverted direction bits, OK
     now we handle it.

   - A patch series making more error codes percolate upward properly
     for different errors on gpiochip_lock_as_irq().

   - Get/set multiple for the OMAP driver, accelerating these multiple
     line operations if possible.

   - A coprocessor interface for the Aspeed driver. Sometimes a few GPIO
     lines need to be grabbed by a co-processor for doing automated
     tasks, sometimes they are available as GPIO lines. By adding an
     explicit API in this driver we make it possible for the two line
     consumers to coexist. (This work was made available on the
     ib-aspeed branch, which may be appearing in other pull requests.)

   - Implemented .get_direction() and open drain in the SCH311x driver.

   - Continuing cleanup of included headers in GPIO drivers"

* tag 'gpio-v4.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (80 commits)
  gpio: it87: Add support for IT8613
  gpio: it87: add support for IT8718F Super I/O.
  gpiolib: Avoid calling chip->request() for unused gpios
  gpio: tegra: Include the right header
  gpio: mmio: Fix up inverted direction registers
  gpio: xilinx: Use the right include
  gpio: timberdale: Include the right header
  gpio: tb10x: Use the right include
  gpiolib: Fix of_node inconsistency
  gpio: vr41xx: Bail out on gpiochip_lock_as_irq() error
  gpio: uniphier: Bail out on gpiochip_lock_as_irq() error
  gpio: xgene-sb: Don't shadow error code of gpiochip_lock_as_irq()
  gpio: em: Don't shadow error code of gpiochip_lock_as_irq()
  gpio: dwapb: Don't shadow error code of gpiochip_lock_as_irq()
  gpio: bcm-kona: Don't shadow error code of gpiochip_lock_as_irq()
  gpiolib: Don't shadow error code of gpiochip_lock_as_irq()
  gpio: syscon: rockchip: add GRF GPIO support for rk3328
  gpio: omap: Add get/set_multiple() callbacks
  gpio: pxa: remove set but not used variable 'gpio_offset'
  gpio-it87: add support for IT8786E Super I/O
  ...
parents c1c2ad82 a5ec96dd
...@@ -19,6 +19,9 @@ Required properties: ...@@ -19,6 +19,9 @@ Required properties:
4 = active high level-sensitive. 4 = active high level-sensitive.
8 = active low level-sensitive. 8 = active low level-sensitive.
Optional properties:
- clocks: the clock for clocking the GPIO silicon
Example: Example:
gpio0: gpio@73f84000 { gpio0: gpio@73f84000 {
......
Mediatek MT7621 SoC GPIO controller bindings
The IP core used inside these SoCs has 3 banks of 32 GPIOs each.
The registers of all the banks are interwoven inside one single IO range.
We load one GPIO controller instance per bank. Also the GPIO controller can receive
interrupts on any of the GPIOs, either edge or level. It then interrupts the CPU
using GIC INT12.
Required properties for the top level node:
- #gpio-cells : Should be two. The first cell is the GPIO pin number and the
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.
- #interrupt-cells : Specifies the number of cells needed to encode an
interrupt. Should be 2. The first cell defines the interrupt number,
the second encodes the triger flags encoded as described in
Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
- compatible:
- "mediatek,mt7621-gpio" for Mediatek controllers
- reg : Physical base address and length of the controller's registers
- interrupt-parent : phandle of the parent interrupt controller.
- interrupts : Interrupt specifier for the controllers interrupt.
- interrupt-controller : Mark the device node as an interrupt controller.
- gpio-controller : Marks the device node as a GPIO controller.
Example:
gpio@600 {
#gpio-cells = <2>;
#interrupt-cells = <2>;
compatible = "mediatek,mt7621-gpio";
gpio-controller;
interrupt-controller;
reg = <0x600 0x100>;
interrupt-parent = <&gic>;
interrupts = <GIC_SHARED 12 IRQ_TYPE_LEVEL_HIGH>;
};
...@@ -68,6 +68,8 @@ Required properties: ...@@ -68,6 +68,8 @@ Required properties:
One of: One of:
- "nvidia,tegra186-gpio". - "nvidia,tegra186-gpio".
- "nvidia,tegra186-gpio-aon". - "nvidia,tegra186-gpio-aon".
- "nvidia,tegra194-gpio".
- "nvidia,tegra194-gpio-aon".
- reg-names - reg-names
Array of strings. Array of strings.
Contains a list of names for the register spaces described by the reg Contains a list of names for the register spaces described by the reg
...@@ -91,6 +93,8 @@ Required properties: ...@@ -91,6 +93,8 @@ Required properties:
depending on compatible value: depending on compatible value:
- "nvidia,tegra186-gpio": 6 entries. - "nvidia,tegra186-gpio": 6 entries.
- "nvidia,tegra186-gpio-aon": 1 entry. - "nvidia,tegra186-gpio-aon": 1 entry.
- "nvidia,tegra194-gpio": 6 entries.
- "nvidia,tegra194-gpio-aon": 1 entry.
- gpio-controller - gpio-controller
Boolean. Boolean.
Marks the device node as a GPIO controller/provider. Marks the device node as a GPIO controller/provider.
......
...@@ -17,6 +17,7 @@ Required Properties: ...@@ -17,6 +17,7 @@ Required Properties:
- "renesas,gpio-r8a7796": for R8A7796 (R-Car M3-W) compatible GPIO controller. - "renesas,gpio-r8a7796": for R8A7796 (R-Car M3-W) compatible GPIO controller.
- "renesas,gpio-r8a77965": for R8A77965 (R-Car M3-N) compatible GPIO controller. - "renesas,gpio-r8a77965": for R8A77965 (R-Car M3-N) compatible GPIO controller.
- "renesas,gpio-r8a77970": for R8A77970 (R-Car V3M) compatible GPIO controller. - "renesas,gpio-r8a77970": for R8A77970 (R-Car V3M) compatible GPIO controller.
- "renesas,gpio-r8a77980": for R8A77980 (R-Car V3H) compatible GPIO controller.
- "renesas,gpio-r8a77990": for R8A77990 (R-Car E3) compatible GPIO controller. - "renesas,gpio-r8a77990": for R8A77990 (R-Car E3) compatible GPIO controller.
- "renesas,gpio-r8a77995": for R8A77995 (R-Car D3) compatible GPIO controller. - "renesas,gpio-r8a77995": for R8A77995 (R-Car D3) compatible GPIO controller.
- "renesas,rcar-gen1-gpio": for a generic R-Car Gen1 GPIO controller. - "renesas,rcar-gen1-gpio": for a generic R-Car Gen1 GPIO controller.
......
Rockchip RK3328 GRF (General Register Files) GPIO controller.
In Rockchip RK3328, the output only GPIO_MUTE pin, originally for codec mute
control, can also be used for general purpose. It is manipulated by the
GRF_SOC_CON10 register in GRF. Aside from the GPIO_MUTE pin, the HDMI pins can
also be set in the same way.
Currently this GPIO controller only supports the mute pin. If needed in the
future, the HDMI pins support can also be added.
Required properties:
- compatible: Should contain "rockchip,rk3328-grf-gpio".
- 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 the gpio polarity:
0 = Active high,
1 = Active low.
Example:
grf: syscon@ff100000 {
compatible = "rockchip,rk3328-grf", "syscon", "simple-mfd";
grf_gpio: grf-gpio {
compatible = "rockchip,rk3328-grf-gpio";
gpio-controller;
#gpio-cells = <2>;
};
};
Note: The grf_gpio node should be declared as the child of the GRF (General
Register File) node. The GPIO_MUTE pin is referred to as <&grf_gpio 0>.
...@@ -359,6 +359,15 @@ config GPIO_MPC8XXX ...@@ -359,6 +359,15 @@ config GPIO_MPC8XXX
Say Y here if you're going to use hardware that connects to the Say Y here if you're going to use hardware that connects to the
MPC512x/831x/834x/837x/8572/8610/QorIQ GPIOs. MPC512x/831x/834x/837x/8572/8610/QorIQ GPIOs.
config GPIO_MT7621
bool "Mediatek MT7621 GPIO Support"
depends on SOC_MT7620 || SOC_MT7621 || COMPILE_TEST
depends on OF_GPIO
select GPIO_GENERIC
select GPIOLIB_IRQCHIP
help
Say yes here to support the Mediatek MT7621 SoC GPIO device
config GPIO_MVEBU config GPIO_MVEBU
def_bool y def_bool y
depends on PLAT_ORION || ARCH_MVEBU depends on PLAT_ORION || ARCH_MVEBU
...@@ -684,7 +693,8 @@ config GPIO_IT87 ...@@ -684,7 +693,8 @@ config GPIO_IT87
Say yes here to support GPIO functionality of IT87xx Super I/O chips. Say yes here to support GPIO functionality of IT87xx Super I/O chips.
This driver is tested with ITE IT8728 and IT8732 Super I/O chips, and This driver is tested with ITE IT8728 and IT8732 Super I/O chips, and
supports the IT8761E, IT8620E and IT8628E Super I/O chip as well. supports the IT8761E, IT8613, IT8620E, and IT8628E Super I/O chips as
well.
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 gpio_it87 be called gpio_it87
......
...@@ -88,6 +88,7 @@ obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o ...@@ -88,6 +88,7 @@ obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o
obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o
obj-$(CONFIG_GPIO_MT7621) += gpio-mt7621.o
obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o
obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o
obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o
......
This diff is collapsed.
...@@ -51,7 +51,7 @@ static u32 ath79_gpio_read(struct ath79_gpio_ctrl *ctrl, unsigned reg) ...@@ -51,7 +51,7 @@ static u32 ath79_gpio_read(struct ath79_gpio_ctrl *ctrl, unsigned reg)
static void ath79_gpio_write(struct ath79_gpio_ctrl *ctrl, static void ath79_gpio_write(struct ath79_gpio_ctrl *ctrl,
unsigned reg, u32 val) unsigned reg, u32 val)
{ {
return writel(val, ctrl->base + reg); writel(val, ctrl->base + reg);
} }
static bool ath79_gpio_update_bits( static bool ath79_gpio_update_bits(
......
...@@ -485,12 +485,14 @@ static void bcm_kona_gpio_irq_handler(struct irq_desc *desc) ...@@ -485,12 +485,14 @@ static void bcm_kona_gpio_irq_handler(struct irq_desc *desc)
static int bcm_kona_gpio_irq_reqres(struct irq_data *d) static int bcm_kona_gpio_irq_reqres(struct irq_data *d)
{ {
struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d); struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d);
int ret;
if (gpiochip_lock_as_irq(&kona_gpio->gpio_chip, d->hwirq)) { ret = gpiochip_lock_as_irq(&kona_gpio->gpio_chip, d->hwirq);
if (ret) {
dev_err(kona_gpio->gpio_chip.parent, dev_err(kona_gpio->gpio_chip.parent,
"unable to lock HW IRQ %lu for IRQ\n", "unable to lock HW IRQ %lu for IRQ\n",
d->hwirq); d->hwirq);
return -EINVAL; return ret;
} }
return 0; return 0;
} }
......
...@@ -167,8 +167,8 @@ davinci_gpio_get_pdata(struct platform_device *pdev) ...@@ -167,8 +167,8 @@ davinci_gpio_get_pdata(struct platform_device *pdev)
static int davinci_gpio_probe(struct platform_device *pdev) static int davinci_gpio_probe(struct platform_device *pdev)
{ {
static int ctrl_num, bank_base; static int ctrl_num, bank_base;
int gpio, bank, ret = 0; int gpio, bank, i, ret = 0;
unsigned ngpio, nbank; unsigned int ngpio, nbank, nirq;
struct davinci_gpio_controller *chips; struct davinci_gpio_controller *chips;
struct davinci_gpio_platform_data *pdata; struct davinci_gpio_platform_data *pdata;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
...@@ -197,6 +197,16 @@ static int davinci_gpio_probe(struct platform_device *pdev) ...@@ -197,6 +197,16 @@ static int davinci_gpio_probe(struct platform_device *pdev)
if (WARN_ON(ARCH_NR_GPIOS < ngpio)) if (WARN_ON(ARCH_NR_GPIOS < ngpio))
ngpio = ARCH_NR_GPIOS; ngpio = ARCH_NR_GPIOS;
/*
* If there are unbanked interrupts then the number of
* interrupts is equal to number of gpios else all are banked so
* number of interrupts is equal to number of banks(each with 16 gpios)
*/
if (pdata->gpio_unbanked)
nirq = pdata->gpio_unbanked;
else
nirq = DIV_ROUND_UP(ngpio, 16);
nbank = DIV_ROUND_UP(ngpio, 32); nbank = DIV_ROUND_UP(ngpio, 32);
chips = devm_kcalloc(dev, chips = devm_kcalloc(dev,
nbank, sizeof(struct davinci_gpio_controller), nbank, sizeof(struct davinci_gpio_controller),
...@@ -209,6 +219,15 @@ static int davinci_gpio_probe(struct platform_device *pdev) ...@@ -209,6 +219,15 @@ static int davinci_gpio_probe(struct platform_device *pdev)
if (IS_ERR(gpio_base)) if (IS_ERR(gpio_base))
return PTR_ERR(gpio_base); return PTR_ERR(gpio_base);
for (i = 0; i < nirq; i++) {
chips->irqs[i] = platform_get_irq(pdev, i);
if (chips->irqs[i] < 0) {
dev_info(dev, "IRQ not populated, err = %d\n",
chips->irqs[i]);
return chips->irqs[i];
}
}
snprintf(label, MAX_LABEL_SIZE, "davinci_gpio.%d", ctrl_num++); snprintf(label, MAX_LABEL_SIZE, "davinci_gpio.%d", ctrl_num++);
chips->chip.label = devm_kstrdup(dev, label, GFP_KERNEL); chips->chip.label = devm_kstrdup(dev, label, GFP_KERNEL);
if (!chips->chip.label) if (!chips->chip.label)
...@@ -377,7 +396,7 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset) ...@@ -377,7 +396,7 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset)
* can provide direct-mapped IRQs to AINTC (up to 32 GPIOs). * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs).
*/ */
if (offset < d->gpio_unbanked) if (offset < d->gpio_unbanked)
return d->base_irq + offset; return d->irqs[offset];
else else
return -ENODEV; return -ENODEV;
} }
...@@ -386,11 +405,18 @@ static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger) ...@@ -386,11 +405,18 @@ static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger)
{ {
struct davinci_gpio_controller *d; struct davinci_gpio_controller *d;
struct davinci_gpio_regs __iomem *g; struct davinci_gpio_regs __iomem *g;
u32 mask; u32 mask, i;
d = (struct davinci_gpio_controller *)irq_data_get_irq_handler_data(data); d = (struct davinci_gpio_controller *)irq_data_get_irq_handler_data(data);
g = (struct davinci_gpio_regs __iomem *)d->regs[0]; g = (struct davinci_gpio_regs __iomem *)d->regs[0];
mask = __gpio_mask(data->irq - d->base_irq); for (i = 0; i < MAX_INT_PER_BANK; i++)
if (data->irq == d->irqs[i])
break;
if (i == MAX_INT_PER_BANK)
return -EINVAL;
mask = __gpio_mask(i);
if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
return -EINVAL; return -EINVAL;
...@@ -459,9 +485,8 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) ...@@ -459,9 +485,8 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
int ret; int ret;
struct clk *clk; struct clk *clk;
u32 binten = 0; u32 binten = 0;
unsigned ngpio, bank_irq; unsigned ngpio;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct resource *res;
struct davinci_gpio_controller *chips = platform_get_drvdata(pdev); struct davinci_gpio_controller *chips = platform_get_drvdata(pdev);
struct davinci_gpio_platform_data *pdata = dev->platform_data; struct davinci_gpio_platform_data *pdata = dev->platform_data;
struct davinci_gpio_regs __iomem *g; struct davinci_gpio_regs __iomem *g;
...@@ -481,24 +506,13 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) ...@@ -481,24 +506,13 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
gpio_get_irq_chip = (gpio_get_irq_chip_cb_t)match->data; gpio_get_irq_chip = (gpio_get_irq_chip_cb_t)match->data;
ngpio = pdata->ngpio; ngpio = pdata->ngpio;
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
dev_err(dev, "Invalid IRQ resource\n");
return -EBUSY;
}
bank_irq = res->start;
if (!bank_irq) {
dev_err(dev, "Invalid IRQ resource\n");
return -ENODEV;
}
clk = devm_clk_get(dev, "gpio"); clk = devm_clk_get(dev, "gpio");
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(dev, "Error %ld getting gpio clock\n", PTR_ERR(clk)); dev_err(dev, "Error %ld getting gpio clock\n", PTR_ERR(clk));
return PTR_ERR(clk); return PTR_ERR(clk);
} }
ret = clk_prepare_enable(clk); ret = clk_prepare_enable(clk);
if (ret) if (ret)
return ret; return ret;
...@@ -538,12 +552,11 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) ...@@ -538,12 +552,11 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
if (pdata->gpio_unbanked) { if (pdata->gpio_unbanked) {
/* pass "bank 0" GPIO IRQs to AINTC */ /* pass "bank 0" GPIO IRQs to AINTC */
chips->chip.to_irq = gpio_to_irq_unbanked; chips->chip.to_irq = gpio_to_irq_unbanked;
chips->base_irq = bank_irq;
chips->gpio_unbanked = pdata->gpio_unbanked; chips->gpio_unbanked = pdata->gpio_unbanked;
binten = GENMASK(pdata->gpio_unbanked / 16, 0); binten = GENMASK(pdata->gpio_unbanked / 16, 0);
/* AINTC handles mask/unmask; GPIO handles triggering */ /* AINTC handles mask/unmask; GPIO handles triggering */
irq = bank_irq; irq = chips->irqs[0];
irq_chip = gpio_get_irq_chip(irq); irq_chip = gpio_get_irq_chip(irq);
irq_chip->name = "GPIO-AINTC"; irq_chip->name = "GPIO-AINTC";
irq_chip->irq_set_type = gpio_irq_type_unbanked; irq_chip->irq_set_type = gpio_irq_type_unbanked;
...@@ -554,10 +567,11 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) ...@@ -554,10 +567,11 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
writel_relaxed(~0, &g->set_rising); writel_relaxed(~0, &g->set_rising);
/* set the direct IRQs up to use that irqchip */ /* set the direct IRQs up to use that irqchip */
for (gpio = 0; gpio < pdata->gpio_unbanked; gpio++, irq++) { for (gpio = 0; gpio < pdata->gpio_unbanked; gpio++) {
irq_set_chip(irq, irq_chip); irq_set_chip(chips->irqs[gpio], irq_chip);
irq_set_handler_data(irq, chips); irq_set_handler_data(chips->irqs[gpio], chips);
irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH); irq_set_status_flags(chips->irqs[gpio],
IRQ_TYPE_EDGE_BOTH);
} }
goto done; goto done;
...@@ -567,7 +581,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) ...@@ -567,7 +581,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
* Or, AINTC can handle IRQs for banks of 16 GPIO IRQs, which we * Or, AINTC can handle IRQs for banks of 16 GPIO IRQs, which we
* then chain through our own handler. * then chain through our own handler.
*/ */
for (gpio = 0, bank = 0; gpio < ngpio; bank++, bank_irq++, gpio += 16) { for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 16) {
/* disabled by default, enabled only as needed /* disabled by default, enabled only as needed
* There are register sets for 32 GPIOs. 2 banks of 16 * There are register sets for 32 GPIOs. 2 banks of 16
* GPIOs are covered by each set of registers hence divide by 2 * GPIOs are covered by each set of registers hence divide by 2
...@@ -594,8 +608,8 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) ...@@ -594,8 +608,8 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
irqdata->bank_num = bank; irqdata->bank_num = bank;
irqdata->chip = chips; irqdata->chip = chips;
irq_set_chained_handler_and_data(bank_irq, gpio_irq_handler, irq_set_chained_handler_and_data(chips->irqs[bank],
irqdata); gpio_irq_handler, irqdata);
binten |= BIT(bank); binten |= BIT(bank);
} }
......
...@@ -255,11 +255,13 @@ static int dwapb_irq_reqres(struct irq_data *d) ...@@ -255,11 +255,13 @@ static int dwapb_irq_reqres(struct irq_data *d)
struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d); struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d);
struct dwapb_gpio *gpio = igc->private; struct dwapb_gpio *gpio = igc->private;
struct gpio_chip *gc = &gpio->ports[0].gc; struct gpio_chip *gc = &gpio->ports[0].gc;
int ret;
if (gpiochip_lock_as_irq(gc, irqd_to_hwirq(d))) { ret = gpiochip_lock_as_irq(gc, irqd_to_hwirq(d));
if (ret) {
dev_err(gpio->dev, "unable to lock HW IRQ %lu for IRQ\n", dev_err(gpio->dev, "unable to lock HW IRQ %lu for IRQ\n",
irqd_to_hwirq(d)); irqd_to_hwirq(d));
return -EINVAL; return ret;
} }
return 0; return 0;
} }
......
...@@ -101,12 +101,14 @@ static void em_gio_irq_enable(struct irq_data *d) ...@@ -101,12 +101,14 @@ static void em_gio_irq_enable(struct irq_data *d)
static int em_gio_irq_reqres(struct irq_data *d) static int em_gio_irq_reqres(struct irq_data *d)
{ {
struct em_gio_priv *p = irq_data_get_irq_chip_data(d); struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
int ret;
if (gpiochip_lock_as_irq(&p->gpio_chip, irqd_to_hwirq(d))) { ret = gpiochip_lock_as_irq(&p->gpio_chip, irqd_to_hwirq(d));
if (ret) {
dev_err(p->gpio_chip.parent, dev_err(p->gpio_chip.parent,
"unable to lock HW IRQ %lu for IRQ\n", "unable to lock HW IRQ %lu for IRQ\n",
irqd_to_hwirq(d)); irqd_to_hwirq(d));
return -EINVAL; return ret;
} }
return 0; return 0;
} }
......
...@@ -35,12 +35,15 @@ ...@@ -35,12 +35,15 @@
/* Chip Id numbers */ /* Chip Id numbers */
#define NO_DEV_ID 0xffff #define NO_DEV_ID 0xffff
#define IT8613_ID 0x8613
#define IT8620_ID 0x8620 #define IT8620_ID 0x8620
#define IT8628_ID 0x8628 #define IT8628_ID 0x8628
#define IT8718_ID 0x8718
#define IT8728_ID 0x8728 #define IT8728_ID 0x8728
#define IT8732_ID 0x8732 #define IT8732_ID 0x8732
#define IT8761_ID 0x8761 #define IT8761_ID 0x8761
#define IT8772_ID 0x8772 #define IT8772_ID 0x8772
#define IT8786_ID 0x8786
/* IO Ports */ /* IO Ports */
#define REG 0x2e #define REG 0x2e
...@@ -306,6 +309,14 @@ static int __init it87_gpio_init(void) ...@@ -306,6 +309,14 @@ static int __init it87_gpio_init(void)
it87_gpio->chip = it87_template_chip; it87_gpio->chip = it87_template_chip;
switch (chip_type) { switch (chip_type) {
case IT8613_ID:
gpio_ba_reg = 0x62;
it87_gpio->io_size = 8; /* it8613 only needs 6, use 8 for alignment */
it87_gpio->output_base = 0xc8;
it87_gpio->simple_base = 0xc0;
it87_gpio->simple_size = 6;
it87_gpio->chip.ngpio = 64; /* has 48, use 64 for convenient calc */
break;
case IT8620_ID: case IT8620_ID:
case IT8628_ID: case IT8628_ID:
gpio_ba_reg = 0x62; gpio_ba_reg = 0x62;
...@@ -314,9 +325,11 @@ static int __init it87_gpio_init(void) ...@@ -314,9 +325,11 @@ static int __init it87_gpio_init(void)
it87_gpio->simple_size = 0; it87_gpio->simple_size = 0;
it87_gpio->chip.ngpio = 64; it87_gpio->chip.ngpio = 64;
break; break;
case IT8718_ID:
case IT8728_ID: case IT8728_ID:
case IT8732_ID: case IT8732_ID:
case IT8772_ID: case IT8772_ID:
case IT8786_ID:
gpio_ba_reg = 0x62; gpio_ba_reg = 0x62;
it87_gpio->io_size = 8; it87_gpio->io_size = 8;
it87_gpio->output_base = 0xc8; it87_gpio->output_base = 0xc8;
......
...@@ -653,6 +653,12 @@ static int max732x_probe(struct i2c_client *client, ...@@ -653,6 +653,12 @@ static int max732x_probe(struct i2c_client *client,
chip->client_group_a = client; chip->client_group_a = client;
if (nr_port > 8) { if (nr_port > 8) {
c = i2c_new_dummy(client->adapter, addr_b); c = i2c_new_dummy(client->adapter, addr_b);
if (!c) {
dev_err(&client->dev,
"Failed to allocate I2C device\n");
ret = -ENODEV;
goto out_failed;
}
chip->client_group_b = chip->client_dummy = c; chip->client_group_b = chip->client_dummy = c;
} }
break; break;
...@@ -660,6 +666,12 @@ static int max732x_probe(struct i2c_client *client, ...@@ -660,6 +666,12 @@ static int max732x_probe(struct i2c_client *client,
chip->client_group_b = client; chip->client_group_b = client;
if (nr_port > 8) { if (nr_port > 8) {
c = i2c_new_dummy(client->adapter, addr_a); c = i2c_new_dummy(client->adapter, addr_a);
if (!c) {
dev_err(&client->dev,
"Failed to allocate I2C device\n");
ret = -ENODEV;
goto out_failed;
}
chip->client_group_a = chip->client_dummy = c; chip->client_group_a = chip->client_dummy = c;
} }
break; break;
......
...@@ -56,9 +56,9 @@ static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio, ...@@ -56,9 +56,9 @@ static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio,
rnd = fls(debounce) - 1; rnd = fls(debounce) - 1;
if (rnd && (debounce & BIT(rnd - 1))) if (rnd && (debounce & BIT(rnd - 1)))
debounce = round_up(debounce, MEN_Z127_DB_MIN_US); debounce = roundup(debounce, MEN_Z127_DB_MIN_US);
else else
debounce = round_down(debounce, MEN_Z127_DB_MIN_US); debounce = rounddown(debounce, MEN_Z127_DB_MIN_US);
if (debounce > MEN_Z127_DB_MAX_US) if (debounce > MEN_Z127_DB_MAX_US)
debounce = MEN_Z127_DB_MAX_US; debounce = MEN_Z127_DB_MAX_US;
......
...@@ -496,9 +496,10 @@ static int ioh_gpio_probe(struct pci_dev *pdev, ...@@ -496,9 +496,10 @@ static int ioh_gpio_probe(struct pci_dev *pdev,
return 0; return 0;
err_gpiochip_add: err_gpiochip_add:
chip = chip_save;
while (--i >= 0) { while (--i >= 0) {
chip--;
gpiochip_remove(&chip->gpio); gpiochip_remove(&chip->gpio);
chip++;
} }
kfree(chip_save); kfree(chip_save);
......
...@@ -136,8 +136,20 @@ static unsigned long bgpio_line2mask(struct gpio_chip *gc, unsigned int line) ...@@ -136,8 +136,20 @@ static unsigned long bgpio_line2mask(struct gpio_chip *gc, unsigned int line)
static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio) static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio)
{ {
unsigned long pinmask = bgpio_line2mask(gc, gpio); unsigned long pinmask = bgpio_line2mask(gc, gpio);
bool dir = !!(gc->bgpio_dir & pinmask);
if (gc->bgpio_dir & pinmask) /*
* If the direction is OUT we read the value from the SET
* register, and if the direction is IN we read the value
* from the DAT register.
*
* If the direction bits are inverted, naturally this gets
* inverted too.
*/
if (gc->bgpio_dir_inverted)
dir = !dir;
if (dir)
return !!(gc->read_reg(gc->reg_set) & pinmask); return !!(gc->read_reg(gc->reg_set) & pinmask);
else else
return !!(gc->read_reg(gc->reg_dat) & pinmask); return !!(gc->read_reg(gc->reg_dat) & pinmask);
...@@ -157,8 +169,13 @@ static int bgpio_get_set_multiple(struct gpio_chip *gc, unsigned long *mask, ...@@ -157,8 +169,13 @@ static int bgpio_get_set_multiple(struct gpio_chip *gc, unsigned long *mask,
*bits &= ~*mask; *bits &= ~*mask;
/* Exploit the fact that we know which directions are set */ /* Exploit the fact that we know which directions are set */
set_mask = *mask & gc->bgpio_dir; if (gc->bgpio_dir_inverted) {
get_mask = *mask & ~gc->bgpio_dir; set_mask = *mask & ~gc->bgpio_dir;
get_mask = *mask & gc->bgpio_dir;
} else {
set_mask = *mask & gc->bgpio_dir;
get_mask = *mask & ~gc->bgpio_dir;
}
if (set_mask) if (set_mask)
*bits |= gc->read_reg(gc->reg_set) & set_mask; *bits |= gc->read_reg(gc->reg_set) & set_mask;
...@@ -359,7 +376,10 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) ...@@ -359,7 +376,10 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
spin_lock_irqsave(&gc->bgpio_lock, flags); spin_lock_irqsave(&gc->bgpio_lock, flags);
gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio); if (gc->bgpio_dir_inverted)
gc->bgpio_dir |= bgpio_line2mask(gc, gpio);
else
gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio);
gc->write_reg(gc->reg_dir, gc->bgpio_dir); gc->write_reg(gc->reg_dir, gc->bgpio_dir);
spin_unlock_irqrestore(&gc->bgpio_lock, flags); spin_unlock_irqrestore(&gc->bgpio_lock, flags);
...@@ -370,7 +390,10 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) ...@@ -370,7 +390,10 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio) static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio)
{ {
/* Return 0 if output, 1 of input */ /* Return 0 if output, 1 of input */
return !(gc->read_reg(gc->reg_dir) & bgpio_line2mask(gc, gpio)); if (gc->bgpio_dir_inverted)
return !!(gc->read_reg(gc->reg_dir) & bgpio_line2mask(gc, gpio));
else
return !(gc->read_reg(gc->reg_dir) & bgpio_line2mask(gc, gpio));
} }
static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
...@@ -381,37 +404,10 @@ static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) ...@@ -381,37 +404,10 @@ static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
spin_lock_irqsave(&gc->bgpio_lock, flags); spin_lock_irqsave(&gc->bgpio_lock, flags);
gc->bgpio_dir |= bgpio_line2mask(gc, gpio); if (gc->bgpio_dir_inverted)
gc->write_reg(gc->reg_dir, gc->bgpio_dir); gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio);
else
spin_unlock_irqrestore(&gc->bgpio_lock, flags); gc->bgpio_dir |= bgpio_line2mask(gc, gpio);
return 0;
}
static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio)
{
unsigned long flags;
spin_lock_irqsave(&gc->bgpio_lock, flags);
gc->bgpio_dir |= bgpio_line2mask(gc, gpio);
gc->write_reg(gc->reg_dir, gc->bgpio_dir);
spin_unlock_irqrestore(&gc->bgpio_lock, flags);
return 0;
}
static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val)
{
unsigned long flags;
gc->set(gc, gpio, val);
spin_lock_irqsave(&gc->bgpio_lock, flags);
gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio);
gc->write_reg(gc->reg_dir, gc->bgpio_dir); gc->write_reg(gc->reg_dir, gc->bgpio_dir);
spin_unlock_irqrestore(&gc->bgpio_lock, flags); spin_unlock_irqrestore(&gc->bgpio_lock, flags);
...@@ -419,12 +415,6 @@ static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val) ...@@ -419,12 +415,6 @@ static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val)
return 0; return 0;
} }
static int bgpio_get_dir_inv(struct gpio_chip *gc, unsigned int gpio)
{
/* Return 0 if output, 1 if input */
return !!(gc->read_reg(gc->reg_dir) & bgpio_line2mask(gc, gpio));
}
static int bgpio_setup_accessors(struct device *dev, static int bgpio_setup_accessors(struct device *dev,
struct gpio_chip *gc, struct gpio_chip *gc,
bool byte_be) bool byte_be)
...@@ -560,9 +550,10 @@ static int bgpio_setup_direction(struct gpio_chip *gc, ...@@ -560,9 +550,10 @@ static int bgpio_setup_direction(struct gpio_chip *gc,
gc->get_direction = bgpio_get_dir; gc->get_direction = bgpio_get_dir;
} else if (dirin) { } else if (dirin) {
gc->reg_dir = dirin; gc->reg_dir = dirin;
gc->direction_output = bgpio_dir_out_inv; gc->direction_output = bgpio_dir_out;
gc->direction_input = bgpio_dir_in_inv; gc->direction_input = bgpio_dir_in;
gc->get_direction = bgpio_get_dir_inv; gc->get_direction = bgpio_get_dir;
gc->bgpio_dir_inverted = true;
} else { } else {
if (flags & BGPIOF_NO_OUTPUT) if (flags & BGPIOF_NO_OUTPUT)
gc->direction_output = bgpio_dir_out_err; gc->direction_output = bgpio_dir_out_err;
...@@ -582,6 +573,33 @@ static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin) ...@@ -582,6 +573,33 @@ static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin)
return -EINVAL; return -EINVAL;
} }
/**
* bgpio_init() - Initialize generic GPIO accessor functions
* @gc: the GPIO chip to set up
* @dev: the parent device of the new GPIO chip (compulsory)
* @sz: the size (width) of the MMIO registers in bytes, typically 1, 2 or 4
* @dat: MMIO address for the register to READ the value of the GPIO lines, it
* is expected that a 1 in the corresponding bit in this register means the
* line is asserted
* @set: MMIO address for the register to SET the value of the GPIO lines, it is
* expected that we write the line with 1 in this register to drive the GPIO line
* high.
* @clr: MMIO address for the register to CLEAR the value of the GPIO lines, it is
* expected that we write the line with 1 in this register to drive the GPIO line
* low. It is allowed to leave this address as NULL, in that case the SET register
* will be assumed to also clear the GPIO lines, by actively writing the line
* with 0.
* @dirout: MMIO address for the register to set the line as OUTPUT. It is assumed
* that setting a line to 1 in this register will turn that line into an
* output line. Conversely, setting the line to 0 will turn that line into
* an input. Either this or @dirin can be defined, but never both.
* @dirin: MMIO address for the register to set this line as INPUT. It is assumed
* that setting a line to 1 in this register will turn that line into an
* input line. Conversely, setting the line to 0 will turn that line into
* an output. Either this or @dirout can be defined, but never both.
* @flags: Different flags that will affect the behaviour of the device, such as
* endianness etc.
*/
int bgpio_init(struct gpio_chip *gc, struct device *dev, int bgpio_init(struct gpio_chip *gc, struct device *dev,
unsigned long sz, void __iomem *dat, void __iomem *set, unsigned long sz, void __iomem *dat, void __iomem *set,
void __iomem *clr, void __iomem *dirout, void __iomem *dirin, void __iomem *clr, void __iomem *dirout, void __iomem *dirin,
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2013 John Crispin <blogic@openwrt.org>
*/
#include <linux/err.h>
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#define MTK_BANK_CNT 3
#define MTK_BANK_WIDTH 32
#define GPIO_BANK_STRIDE 0x04
#define GPIO_REG_CTRL 0x00
#define GPIO_REG_POL 0x10
#define GPIO_REG_DATA 0x20
#define GPIO_REG_DSET 0x30
#define GPIO_REG_DCLR 0x40
#define GPIO_REG_REDGE 0x50
#define GPIO_REG_FEDGE 0x60
#define GPIO_REG_HLVL 0x70
#define GPIO_REG_LLVL 0x80
#define GPIO_REG_STAT 0x90
#define GPIO_REG_EDGE 0xA0
struct mtk_gc {
struct gpio_chip chip;
spinlock_t lock;
int bank;
u32 rising;
u32 falling;
u32 hlevel;
u32 llevel;
};
/**
* struct mtk - state container for
* data of the platform driver. It is 3
* separate gpio-chip each one with its
* own irq_chip.
* @dev: device instance
* @base: memory base address
* @gpio_irq: irq number from the device tree
* @gc_map: array of the gpio chips
*/
struct mtk {
struct device *dev;
void __iomem *base;
int gpio_irq;
struct mtk_gc gc_map[MTK_BANK_CNT];
};
static inline struct mtk_gc *
to_mediatek_gpio(struct gpio_chip *chip)
{
return container_of(chip, struct mtk_gc, chip);
}
static inline void
mtk_gpio_w32(struct mtk_gc *rg, u32 offset, u32 val)
{
struct gpio_chip *gc = &rg->chip;
struct mtk *mtk = gpiochip_get_data(gc);
offset = (rg->bank * GPIO_BANK_STRIDE) + offset;
gc->write_reg(mtk->base + offset, val);
}
static inline u32
mtk_gpio_r32(struct mtk_gc *rg, u32 offset)
{
struct gpio_chip *gc = &rg->chip;
struct mtk *mtk = gpiochip_get_data(gc);
offset = (rg->bank * GPIO_BANK_STRIDE) + offset;
return gc->read_reg(mtk->base + offset);
}
static irqreturn_t
mediatek_gpio_irq_handler(int irq, void *data)
{
struct gpio_chip *gc = data;
struct mtk_gc *rg = to_mediatek_gpio(gc);
irqreturn_t ret = IRQ_NONE;
unsigned long pending;
int bit;
pending = mtk_gpio_r32(rg, GPIO_REG_STAT);
for_each_set_bit(bit, &pending, MTK_BANK_WIDTH) {
u32 map = irq_find_mapping(gc->irq.domain, bit);
generic_handle_irq(map);
mtk_gpio_w32(rg, GPIO_REG_STAT, BIT(bit));
ret |= IRQ_HANDLED;
}
return ret;
}
static void
mediatek_gpio_irq_unmask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct mtk_gc *rg = to_mediatek_gpio(gc);
int pin = d->hwirq;
unsigned long flags;
u32 rise, fall, high, low;
spin_lock_irqsave(&rg->lock, flags);
rise = mtk_gpio_r32(rg, GPIO_REG_REDGE);
fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE);
high = mtk_gpio_r32(rg, GPIO_REG_HLVL);
low = mtk_gpio_r32(rg, GPIO_REG_LLVL);
mtk_gpio_w32(rg, GPIO_REG_REDGE, rise | (BIT(pin) & rg->rising));
mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall | (BIT(pin) & rg->falling));
mtk_gpio_w32(rg, GPIO_REG_HLVL, high | (BIT(pin) & rg->hlevel));
mtk_gpio_w32(rg, GPIO_REG_LLVL, low | (BIT(pin) & rg->llevel));
spin_unlock_irqrestore(&rg->lock, flags);
}
static void
mediatek_gpio_irq_mask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct mtk_gc *rg = to_mediatek_gpio(gc);
int pin = d->hwirq;
unsigned long flags;
u32 rise, fall, high, low;
spin_lock_irqsave(&rg->lock, flags);
rise = mtk_gpio_r32(rg, GPIO_REG_REDGE);
fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE);
high = mtk_gpio_r32(rg, GPIO_REG_HLVL);
low = mtk_gpio_r32(rg, GPIO_REG_LLVL);
mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall & ~BIT(pin));
mtk_gpio_w32(rg, GPIO_REG_REDGE, rise & ~BIT(pin));
mtk_gpio_w32(rg, GPIO_REG_HLVL, high & ~BIT(pin));
mtk_gpio_w32(rg, GPIO_REG_LLVL, low & ~BIT(pin));
spin_unlock_irqrestore(&rg->lock, flags);
}
static int
mediatek_gpio_irq_type(struct irq_data *d, unsigned int type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct mtk_gc *rg = to_mediatek_gpio(gc);
int pin = d->hwirq;
u32 mask = BIT(pin);
if (type == IRQ_TYPE_PROBE) {
if ((rg->rising | rg->falling |
rg->hlevel | rg->llevel) & mask)
return 0;
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
}
rg->rising &= ~mask;
rg->falling &= ~mask;
rg->hlevel &= ~mask;
rg->llevel &= ~mask;
switch (type & IRQ_TYPE_SENSE_MASK) {
case IRQ_TYPE_EDGE_BOTH:
rg->rising |= mask;
rg->falling |= mask;
break;
case IRQ_TYPE_EDGE_RISING:
rg->rising |= mask;
break;
case IRQ_TYPE_EDGE_FALLING:
rg->falling |= mask;
break;
case IRQ_TYPE_LEVEL_HIGH:
rg->hlevel |= mask;
break;
case IRQ_TYPE_LEVEL_LOW:
rg->llevel |= mask;
break;
}
return 0;
}
static struct irq_chip mediatek_gpio_irq_chip = {
.irq_unmask = mediatek_gpio_irq_unmask,
.irq_mask = mediatek_gpio_irq_mask,
.irq_mask_ack = mediatek_gpio_irq_mask,
.irq_set_type = mediatek_gpio_irq_type,
};
static int
mediatek_gpio_xlate(struct gpio_chip *chip,
const struct of_phandle_args *spec, u32 *flags)
{
int gpio = spec->args[0];
struct mtk_gc *rg = to_mediatek_gpio(chip);
if (rg->bank != gpio / MTK_BANK_WIDTH)
return -EINVAL;
if (flags)
*flags = spec->args[1];
return gpio % MTK_BANK_WIDTH;
}
static int
mediatek_gpio_bank_probe(struct device *dev,
struct device_node *node, int bank)
{
struct mtk *mtk = dev_get_drvdata(dev);
struct mtk_gc *rg;
void __iomem *dat, *set, *ctrl, *diro;
int ret;
rg = &mtk->gc_map[bank];
memset(rg, 0, sizeof(*rg));
spin_lock_init(&rg->lock);
rg->chip.of_node = node;
rg->bank = bank;
dat = mtk->base + GPIO_REG_DATA + (rg->bank * GPIO_BANK_STRIDE);
set = mtk->base + GPIO_REG_DSET + (rg->bank * GPIO_BANK_STRIDE);
ctrl = mtk->base + GPIO_REG_DCLR + (rg->bank * GPIO_BANK_STRIDE);
diro = mtk->base + GPIO_REG_CTRL + (rg->bank * GPIO_BANK_STRIDE);
ret = bgpio_init(&rg->chip, dev, 4,
dat, set, ctrl, diro, NULL, 0);
if (ret) {
dev_err(dev, "bgpio_init() failed\n");
return ret;
}
rg->chip.of_gpio_n_cells = 2;
rg->chip.of_xlate = mediatek_gpio_xlate;
rg->chip.label = devm_kasprintf(dev, GFP_KERNEL, "%s-bank%d",
dev_name(dev), bank);
ret = devm_gpiochip_add_data(dev, &rg->chip, mtk);
if (ret < 0) {
dev_err(dev, "Could not register gpio %d, ret=%d\n",
rg->chip.ngpio, ret);
return ret;
}
if (mtk->gpio_irq) {
/*
* Manually request the irq here instead of passing
* a flow-handler to gpiochip_set_chained_irqchip,
* because the irq is shared.
*/
ret = devm_request_irq(dev, mtk->gpio_irq,
mediatek_gpio_irq_handler, IRQF_SHARED,
rg->chip.label, &rg->chip);
if (ret) {
dev_err(dev, "Error requesting IRQ %d: %d\n",
mtk->gpio_irq, ret);
return ret;
}
ret = gpiochip_irqchip_add(&rg->chip, &mediatek_gpio_irq_chip,
0, handle_simple_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(dev, "failed to add gpiochip_irqchip\n");
return ret;
}
gpiochip_set_chained_irqchip(&rg->chip, &mediatek_gpio_irq_chip,
mtk->gpio_irq, NULL);
}
/* set polarity to low for all gpios */
mtk_gpio_w32(rg, GPIO_REG_POL, 0);
dev_info(dev, "registering %d gpios\n", rg->chip.ngpio);
return 0;
}
static int
mediatek_gpio_probe(struct platform_device *pdev)
{
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct mtk *mtk;
int i;
mtk = devm_kzalloc(dev, sizeof(*mtk), GFP_KERNEL);
if (!mtk)
return -ENOMEM;
mtk->base = devm_ioremap_resource(dev, res);
if (IS_ERR(mtk->base))
return PTR_ERR(mtk->base);
mtk->gpio_irq = irq_of_parse_and_map(np, 0);
mtk->dev = dev;
platform_set_drvdata(pdev, mtk);
mediatek_gpio_irq_chip.name = dev_name(dev);
for (i = 0; i < MTK_BANK_CNT; i++)
mediatek_gpio_bank_probe(dev, np, i);
return 0;
}
static const struct of_device_id mediatek_gpio_match[] = {
{ .compatible = "mediatek,mt7621-gpio" },
{},
};
MODULE_DEVICE_TABLE(of, mediatek_gpio_match);
static struct platform_driver mediatek_gpio_driver = {
.probe = mediatek_gpio_probe,
.driver = {
.name = "mt7621_gpio",
.of_match_table = mediatek_gpio_match,
},
};
builtin_platform_driver(mediatek_gpio_driver);
...@@ -45,6 +45,15 @@ struct mxc_gpio_hwdata { ...@@ -45,6 +45,15 @@ struct mxc_gpio_hwdata {
unsigned fall_edge; unsigned fall_edge;
}; };
struct mxc_gpio_reg_saved {
u32 icr1;
u32 icr2;
u32 imr;
u32 gdir;
u32 edge_sel;
u32 dr;
};
struct mxc_gpio_port { struct mxc_gpio_port {
struct list_head node; struct list_head node;
void __iomem *base; void __iomem *base;
...@@ -55,6 +64,8 @@ struct mxc_gpio_port { ...@@ -55,6 +64,8 @@ struct mxc_gpio_port {
struct gpio_chip gc; struct gpio_chip gc;
struct device *dev; struct device *dev;
u32 both_edges; u32 both_edges;
struct mxc_gpio_reg_saved gpio_saved_reg;
bool power_off;
}; };
static struct mxc_gpio_hwdata imx1_imx21_gpio_hwdata = { static struct mxc_gpio_hwdata imx1_imx21_gpio_hwdata = {
...@@ -143,6 +154,7 @@ static const struct of_device_id mxc_gpio_dt_ids[] = { ...@@ -143,6 +154,7 @@ static const struct of_device_id mxc_gpio_dt_ids[] = {
{ .compatible = "fsl,imx21-gpio", .data = &mxc_gpio_devtype[IMX21_GPIO], }, { .compatible = "fsl,imx21-gpio", .data = &mxc_gpio_devtype[IMX21_GPIO], },
{ .compatible = "fsl,imx31-gpio", .data = &mxc_gpio_devtype[IMX31_GPIO], }, { .compatible = "fsl,imx31-gpio", .data = &mxc_gpio_devtype[IMX31_GPIO], },
{ .compatible = "fsl,imx35-gpio", .data = &mxc_gpio_devtype[IMX35_GPIO], }, { .compatible = "fsl,imx35-gpio", .data = &mxc_gpio_devtype[IMX35_GPIO], },
{ .compatible = "fsl,imx7d-gpio", .data = &mxc_gpio_devtype[IMX35_GPIO], },
{ /* sentinel */ } { /* sentinel */ }
}; };
...@@ -434,6 +446,9 @@ static int mxc_gpio_probe(struct platform_device *pdev) ...@@ -434,6 +446,9 @@ static int mxc_gpio_probe(struct platform_device *pdev)
return err; return err;
} }
if (of_device_is_compatible(np, "fsl,imx7d-gpio"))
port->power_off = true;
/* disable the interrupt and clear the status */ /* disable the interrupt and clear the status */
writel(0, port->base + GPIO_IMR); writel(0, port->base + GPIO_IMR);
writel(~0, port->base + GPIO_ISR); writel(~0, port->base + GPIO_ISR);
...@@ -497,6 +512,8 @@ static int mxc_gpio_probe(struct platform_device *pdev) ...@@ -497,6 +512,8 @@ static int mxc_gpio_probe(struct platform_device *pdev)
list_add_tail(&port->node, &mxc_gpio_ports); list_add_tail(&port->node, &mxc_gpio_ports);
platform_set_drvdata(pdev, port);
return 0; return 0;
out_irqdomain_remove: out_irqdomain_remove:
...@@ -507,11 +524,67 @@ static int mxc_gpio_probe(struct platform_device *pdev) ...@@ -507,11 +524,67 @@ static int mxc_gpio_probe(struct platform_device *pdev)
return err; return err;
} }
static void mxc_gpio_save_regs(struct mxc_gpio_port *port)
{
if (!port->power_off)
return;
port->gpio_saved_reg.icr1 = readl(port->base + GPIO_ICR1);
port->gpio_saved_reg.icr2 = readl(port->base + GPIO_ICR2);
port->gpio_saved_reg.imr = readl(port->base + GPIO_IMR);
port->gpio_saved_reg.gdir = readl(port->base + GPIO_GDIR);
port->gpio_saved_reg.edge_sel = readl(port->base + GPIO_EDGE_SEL);
port->gpio_saved_reg.dr = readl(port->base + GPIO_DR);
}
static void mxc_gpio_restore_regs(struct mxc_gpio_port *port)
{
if (!port->power_off)
return;
writel(port->gpio_saved_reg.icr1, port->base + GPIO_ICR1);
writel(port->gpio_saved_reg.icr2, port->base + GPIO_ICR2);
writel(port->gpio_saved_reg.imr, port->base + GPIO_IMR);
writel(port->gpio_saved_reg.gdir, port->base + GPIO_GDIR);
writel(port->gpio_saved_reg.edge_sel, port->base + GPIO_EDGE_SEL);
writel(port->gpio_saved_reg.dr, port->base + GPIO_DR);
}
static int __maybe_unused mxc_gpio_noirq_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct mxc_gpio_port *port = platform_get_drvdata(pdev);
mxc_gpio_save_regs(port);
clk_disable_unprepare(port->clk);
return 0;
}
static int __maybe_unused mxc_gpio_noirq_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct mxc_gpio_port *port = platform_get_drvdata(pdev);
int ret;
ret = clk_prepare_enable(port->clk);
if (ret)
return ret;
mxc_gpio_restore_regs(port);
return 0;
}
static const struct dev_pm_ops mxc_gpio_dev_pm_ops = {
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mxc_gpio_noirq_suspend, mxc_gpio_noirq_resume)
};
static struct platform_driver mxc_gpio_driver = { static struct platform_driver mxc_gpio_driver = {
.driver = { .driver = {
.name = "gpio-mxc", .name = "gpio-mxc",
.of_match_table = mxc_gpio_dt_ids, .of_match_table = mxc_gpio_dt_ids,
.suppress_bind_attrs = true, .suppress_bind_attrs = true,
.pm = &mxc_gpio_dev_pm_ops,
}, },
.probe = mxc_gpio_probe, .probe = mxc_gpio_probe,
.id_table = mxc_gpio_devtype, .id_table = mxc_gpio_devtype,
......
...@@ -126,8 +126,7 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) ...@@ -126,8 +126,7 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
else else
writel(pin_mask, pin_addr + MXS_CLR); writel(pin_mask, pin_addr + MXS_CLR);
writel(pin_mask, writel(pin_mask, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR);
port->base + PINCTRL_IRQSTAT(port) + MXS_CLR);
return 0; return 0;
} }
......
...@@ -77,6 +77,8 @@ struct gpio_bank { ...@@ -77,6 +77,8 @@ struct gpio_bank {
bool workaround_enabled; bool workaround_enabled;
void (*set_dataout)(struct gpio_bank *bank, unsigned gpio, int enable); void (*set_dataout)(struct gpio_bank *bank, unsigned gpio, int enable);
void (*set_dataout_multiple)(struct gpio_bank *bank,
unsigned long *mask, unsigned long *bits);
int (*get_context_loss_count)(struct device *dev); int (*get_context_loss_count)(struct device *dev);
struct omap_gpio_reg_offs *regs; struct omap_gpio_reg_offs *regs;
...@@ -161,6 +163,51 @@ static int omap_get_gpio_dataout(struct gpio_bank *bank, int offset) ...@@ -161,6 +163,51 @@ static int omap_get_gpio_dataout(struct gpio_bank *bank, int offset)
return (readl_relaxed(reg) & (BIT(offset))) != 0; return (readl_relaxed(reg) & (BIT(offset))) != 0;
} }
/* set multiple data out values using dedicate set/clear register */
static void omap_set_gpio_dataout_reg_multiple(struct gpio_bank *bank,
unsigned long *mask,
unsigned long *bits)
{
void __iomem *reg = bank->base;
u32 l;
l = *bits & *mask;
writel_relaxed(l, reg + bank->regs->set_dataout);
bank->context.dataout |= l;
l = ~*bits & *mask;
writel_relaxed(l, reg + bank->regs->clr_dataout);
bank->context.dataout &= ~l;
}
/* set multiple data out values using mask register */
static void omap_set_gpio_dataout_mask_multiple(struct gpio_bank *bank,
unsigned long *mask,
unsigned long *bits)
{
void __iomem *reg = bank->base + bank->regs->dataout;
u32 l = (readl_relaxed(reg) & ~*mask) | (*bits & *mask);
writel_relaxed(l, reg);
bank->context.dataout = l;
}
static unsigned long omap_get_gpio_datain_multiple(struct gpio_bank *bank,
unsigned long *mask)
{
void __iomem *reg = bank->base + bank->regs->datain;
return readl_relaxed(reg) & *mask;
}
static unsigned long omap_get_gpio_dataout_multiple(struct gpio_bank *bank,
unsigned long *mask)
{
void __iomem *reg = bank->base + bank->regs->dataout;
return readl_relaxed(reg) & *mask;
}
static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set) static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
{ {
int l = readl_relaxed(base + reg); int l = readl_relaxed(base + reg);
...@@ -968,6 +1015,26 @@ static int omap_gpio_output(struct gpio_chip *chip, unsigned offset, int value) ...@@ -968,6 +1015,26 @@ static int omap_gpio_output(struct gpio_chip *chip, unsigned offset, int value)
return 0; return 0;
} }
static int omap_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
unsigned long *bits)
{
struct gpio_bank *bank = gpiochip_get_data(chip);
void __iomem *reg = bank->base + bank->regs->direction;
unsigned long in = readl_relaxed(reg), l;
*bits = 0;
l = in & *mask;
if (l)
*bits |= omap_get_gpio_datain_multiple(bank, &l);
l = ~in & *mask;
if (l)
*bits |= omap_get_gpio_dataout_multiple(bank, &l);
return 0;
}
static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset, static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,
unsigned debounce) unsigned debounce)
{ {
...@@ -1012,6 +1079,17 @@ static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ...@@ -1012,6 +1079,17 @@ static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
raw_spin_unlock_irqrestore(&bank->lock, flags); raw_spin_unlock_irqrestore(&bank->lock, flags);
} }
static void omap_gpio_set_multiple(struct gpio_chip *chip, unsigned long *mask,
unsigned long *bits)
{
struct gpio_bank *bank = gpiochip_get_data(chip);
unsigned long flags;
raw_spin_lock_irqsave(&bank->lock, flags);
bank->set_dataout_multiple(bank, mask, bits);
raw_spin_unlock_irqrestore(&bank->lock, flags);
}
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
static void omap_gpio_show_rev(struct gpio_bank *bank) static void omap_gpio_show_rev(struct gpio_bank *bank)
...@@ -1073,9 +1151,11 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) ...@@ -1073,9 +1151,11 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
bank->chip.get_direction = omap_gpio_get_direction; bank->chip.get_direction = omap_gpio_get_direction;
bank->chip.direction_input = omap_gpio_input; bank->chip.direction_input = omap_gpio_input;
bank->chip.get = omap_gpio_get; bank->chip.get = omap_gpio_get;
bank->chip.get_multiple = omap_gpio_get_multiple;
bank->chip.direction_output = omap_gpio_output; bank->chip.direction_output = omap_gpio_output;
bank->chip.set_config = omap_gpio_set_config; bank->chip.set_config = omap_gpio_set_config;
bank->chip.set = omap_gpio_set; bank->chip.set = omap_gpio_set;
bank->chip.set_multiple = omap_gpio_set_multiple;
if (bank->is_mpuio) { if (bank->is_mpuio) {
bank->chip.label = "mpuio"; bank->chip.label = "mpuio";
if (bank->regs->wkup_en) if (bank->regs->wkup_en)
...@@ -1209,10 +1289,14 @@ static int omap_gpio_probe(struct platform_device *pdev) ...@@ -1209,10 +1289,14 @@ static int omap_gpio_probe(struct platform_device *pdev)
pdata->get_context_loss_count; pdata->get_context_loss_count;
} }
if (bank->regs->set_dataout && bank->regs->clr_dataout) if (bank->regs->set_dataout && bank->regs->clr_dataout) {
bank->set_dataout = omap_set_gpio_dataout_reg; bank->set_dataout = omap_set_gpio_dataout_reg;
else bank->set_dataout_multiple = omap_set_gpio_dataout_reg_multiple;
} else {
bank->set_dataout = omap_set_gpio_dataout_mask; bank->set_dataout = omap_set_gpio_dataout_mask;
bank->set_dataout_multiple =
omap_set_gpio_dataout_mask_multiple;
}
raw_spin_lock_init(&bank->lock); raw_spin_lock_init(&bank->lock);
raw_spin_lock_init(&bank->wa_lock); raw_spin_lock_init(&bank->wa_lock);
......
...@@ -708,7 +708,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, ...@@ -708,7 +708,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
{ {
struct i2c_client *client = chip->client; struct i2c_client *client = chip->client;
if (irq_base != -1 && (chip->driver_data & PCA_INT)) if (client->irq && irq_base != -1 && (chip->driver_data & PCA_INT))
dev_warn(&client->dev, "interrupt support not compiled in\n"); dev_warn(&client->dev, "interrupt support not compiled in\n");
return 0; return 0;
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
* GNU General Public License version 2 for more details. * GNU General Public License version 2 for more details.
*/ */
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h> #include <linux/gpio/driver.h>
...@@ -90,6 +92,25 @@ static int pisosr_gpio_get(struct gpio_chip *chip, unsigned offset) ...@@ -90,6 +92,25 @@ static int pisosr_gpio_get(struct gpio_chip *chip, unsigned offset)
return (gpio->buffer[offset / 8] >> (offset % 8)) & 0x1; return (gpio->buffer[offset / 8] >> (offset % 8)) & 0x1;
} }
static int pisosr_gpio_get_multiple(struct gpio_chip *chip,
unsigned long *mask, unsigned long *bits)
{
struct pisosr_gpio *gpio = gpiochip_get_data(chip);
unsigned int nbytes = DIV_ROUND_UP(chip->ngpio, 8);
unsigned int i, j;
pisosr_gpio_refresh(gpio);
bitmap_zero(bits, chip->ngpio);
for (i = 0; i < nbytes; i++) {
j = i / sizeof(unsigned long);
bits[j] |= ((unsigned long) gpio->buffer[i])
<< (8 * (i % sizeof(unsigned long)));
}
return 0;
}
static const struct gpio_chip template_chip = { static const struct gpio_chip template_chip = {
.label = "pisosr-gpio", .label = "pisosr-gpio",
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -97,6 +118,7 @@ static const struct gpio_chip template_chip = { ...@@ -97,6 +118,7 @@ static const struct gpio_chip template_chip = {
.direction_input = pisosr_gpio_direction_input, .direction_input = pisosr_gpio_direction_input,
.direction_output = pisosr_gpio_direction_output, .direction_output = pisosr_gpio_direction_output,
.get = pisosr_gpio_get, .get = pisosr_gpio_get,
.get_multiple = pisosr_gpio_get_multiple,
.base = -1, .base = -1,
.ngpio = DEFAULT_NGPIO, .ngpio = DEFAULT_NGPIO,
.can_sleep = true, .can_sleep = true,
......
...@@ -241,6 +241,17 @@ int pxa_irq_to_gpio(int irq) ...@@ -241,6 +241,17 @@ int pxa_irq_to_gpio(int irq)
return irq_gpio0; return irq_gpio0;
} }
static bool pxa_gpio_has_pinctrl(void)
{
switch (gpio_type) {
case PXA3XX_GPIO:
return false;
default:
return true;
}
}
static int pxa_gpio_to_irq(struct gpio_chip *chip, unsigned offset) static int pxa_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{ {
struct pxa_gpio_chip *pchip = chip_to_pxachip(chip); struct pxa_gpio_chip *pchip = chip_to_pxachip(chip);
...@@ -255,9 +266,11 @@ static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ...@@ -255,9 +266,11 @@ static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
unsigned long flags; unsigned long flags;
int ret; int ret;
ret = pinctrl_gpio_direction_input(chip->base + offset); if (pxa_gpio_has_pinctrl()) {
if (!ret) ret = pinctrl_gpio_direction_input(chip->base + offset);
return 0; if (!ret)
return 0;
}
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
...@@ -282,9 +295,11 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip, ...@@ -282,9 +295,11 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip,
writel_relaxed(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET)); writel_relaxed(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET));
ret = pinctrl_gpio_direction_output(chip->base + offset); if (pxa_gpio_has_pinctrl()) {
if (ret) ret = pinctrl_gpio_direction_output(chip->base + offset);
return ret; if (ret)
return ret;
}
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
...@@ -348,8 +363,12 @@ static int pxa_init_gpio_chip(struct pxa_gpio_chip *pchip, int ngpio, ...@@ -348,8 +363,12 @@ static int pxa_init_gpio_chip(struct pxa_gpio_chip *pchip, int ngpio,
pchip->chip.set = pxa_gpio_set; pchip->chip.set = pxa_gpio_set;
pchip->chip.to_irq = pxa_gpio_to_irq; pchip->chip.to_irq = pxa_gpio_to_irq;
pchip->chip.ngpio = ngpio; pchip->chip.ngpio = ngpio;
pchip->chip.request = gpiochip_generic_request;
pchip->chip.free = gpiochip_generic_free; if (pxa_gpio_has_pinctrl()) {
pchip->chip.request = gpiochip_generic_request;
pchip->chip.free = gpiochip_generic_free;
}
#ifdef CONFIG_OF_GPIO #ifdef CONFIG_OF_GPIO
pchip->chip.of_node = np; pchip->chip.of_node = np;
pchip->chip.of_xlate = pxa_gpio_of_xlate; pchip->chip.of_xlate = pxa_gpio_of_xlate;
...@@ -607,7 +626,7 @@ static int pxa_gpio_probe(struct platform_device *pdev) ...@@ -607,7 +626,7 @@ static int pxa_gpio_probe(struct platform_device *pdev)
struct pxa_gpio_platform_data *info; struct pxa_gpio_platform_data *info;
void __iomem *gpio_reg_base; void __iomem *gpio_reg_base;
int gpio, ret; int gpio, ret;
int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0; int irq0 = 0, irq1 = 0, irq_mux;
pchip = devm_kzalloc(&pdev->dev, sizeof(*pchip), GFP_KERNEL); pchip = devm_kzalloc(&pdev->dev, sizeof(*pchip), GFP_KERNEL);
if (!pchip) if (!pchip)
...@@ -646,14 +665,13 @@ static int pxa_gpio_probe(struct platform_device *pdev) ...@@ -646,14 +665,13 @@ static int pxa_gpio_probe(struct platform_device *pdev)
pchip->irq0 = irq0; pchip->irq0 = irq0;
pchip->irq1 = irq1; pchip->irq1 = irq1;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -EINVAL;
gpio_reg_base = devm_ioremap(&pdev->dev, res->start, gpio_reg_base = devm_ioremap(&pdev->dev, res->start,
resource_size(res)); resource_size(res));
if (!gpio_reg_base) if (!gpio_reg_base)
return -EINVAL; return -EINVAL;
if (irq0 > 0)
gpio_offset = 2;
clk = clk_get(&pdev->dev, NULL); clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(&pdev->dev, "Error %ld to get gpio clock\n", dev_err(&pdev->dev, "Error %ld to get gpio clock\n",
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/mfd/rc5t583.h> #include <linux/mfd/rc5t583.h>
struct rc5t583_gpio { struct rc5t583_gpio {
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
*/ */
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
...@@ -278,6 +278,13 @@ static void gpio_rcar_free(struct gpio_chip *chip, unsigned offset) ...@@ -278,6 +278,13 @@ static void gpio_rcar_free(struct gpio_chip *chip, unsigned offset)
pm_runtime_put(&p->pdev->dev); pm_runtime_put(&p->pdev->dev);
} }
static int gpio_rcar_get_direction(struct gpio_chip *chip, unsigned int offset)
{
struct gpio_rcar_priv *p = gpiochip_get_data(chip);
return !(gpio_rcar_read(p, INOUTSEL) & BIT(offset));
}
static int gpio_rcar_direction_input(struct gpio_chip *chip, unsigned offset) static int gpio_rcar_direction_input(struct gpio_chip *chip, unsigned offset)
{ {
gpio_rcar_config_general_input_output_mode(chip, offset, false); gpio_rcar_config_general_input_output_mode(chip, offset, false);
...@@ -461,6 +468,7 @@ static int gpio_rcar_probe(struct platform_device *pdev) ...@@ -461,6 +468,7 @@ static int gpio_rcar_probe(struct platform_device *pdev)
gpio_chip = &p->gpio_chip; gpio_chip = &p->gpio_chip;
gpio_chip->request = gpio_rcar_request; gpio_chip->request = gpio_rcar_request;
gpio_chip->free = gpio_rcar_free; gpio_chip->free = gpio_rcar_free;
gpio_chip->get_direction = gpio_rcar_get_direction;
gpio_chip->direction_input = gpio_rcar_direction_input; gpio_chip->direction_input = gpio_rcar_direction_input;
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;
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/mfd/rdc321x.h> #include <linux/mfd/rdc321x.h>
#include <linux/slab.h> #include <linux/slab.h>
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/io.h> #include <linux/io.h>
......
...@@ -26,8 +26,7 @@ ...@@ -26,8 +26,7 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pci_ids.h> #include <linux/pci_ids.h>
#include <linux/gpio/driver.h>
#include <linux/gpio.h>
#define GEN 0x00 #define GEN 0x00
#define GIO 0x04 #define GIO 0x04
...@@ -138,6 +137,13 @@ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num, ...@@ -138,6 +137,13 @@ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
return 0; return 0;
} }
static int sch_gpio_get_direction(struct gpio_chip *gc, unsigned gpio_num)
{
struct sch_gpio *sch = gpiochip_get_data(gc);
return sch_gpio_reg_get(sch, gpio_num, GIO);
}
static const struct gpio_chip sch_gpio_chip = { static const struct gpio_chip sch_gpio_chip = {
.label = "sch_gpio", .label = "sch_gpio",
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -145,6 +151,7 @@ static const struct gpio_chip sch_gpio_chip = { ...@@ -145,6 +151,7 @@ static const struct gpio_chip sch_gpio_chip = {
.get = sch_gpio_get, .get = sch_gpio_get,
.direction_output = sch_gpio_direction_out, .direction_output = sch_gpio_direction_out,
.set = sch_gpio_set, .set = sch_gpio_set,
.get_direction = sch_gpio_get_direction,
}; };
static int sch_gpio_probe(struct platform_device *pdev) static int sch_gpio_probe(struct platform_device *pdev)
......
...@@ -17,16 +17,15 @@ ...@@ -17,16 +17,15 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/io.h> #include <linux/io.h>
#define DRV_NAME "gpio-sch311x" #define DRV_NAME "gpio-sch311x"
#define SCH311X_GPIO_CONF_OUT 0x00 #define SCH311X_GPIO_CONF_DIR BIT(0)
#define SCH311X_GPIO_CONF_IN 0x01 #define SCH311X_GPIO_CONF_INVERT BIT(1)
#define SCH311X_GPIO_CONF_INVERT 0x02 #define SCH311X_GPIO_CONF_OPEN_DRAIN BIT(7)
#define SCH311X_GPIO_CONF_OPEN_DRAIN 0x80
#define SIO_CONFIG_KEY_ENTER 0x55 #define SIO_CONFIG_KEY_ENTER 0x55
#define SIO_CONFIG_KEY_EXIT 0xaa #define SIO_CONFIG_KEY_EXIT 0xaa
...@@ -163,7 +162,7 @@ static void sch311x_gpio_free(struct gpio_chip *chip, unsigned offset) ...@@ -163,7 +162,7 @@ static void sch311x_gpio_free(struct gpio_chip *chip, unsigned offset)
static int sch311x_gpio_get(struct gpio_chip *chip, unsigned offset) static int sch311x_gpio_get(struct gpio_chip *chip, unsigned offset)
{ {
struct sch311x_gpio_block *block = gpiochip_get_data(chip); struct sch311x_gpio_block *block = gpiochip_get_data(chip);
unsigned char data; u8 data;
spin_lock(&block->lock); spin_lock(&block->lock);
data = inb(block->runtime_reg + block->data_reg); data = inb(block->runtime_reg + block->data_reg);
...@@ -175,7 +174,7 @@ static int sch311x_gpio_get(struct gpio_chip *chip, unsigned offset) ...@@ -175,7 +174,7 @@ static int sch311x_gpio_get(struct gpio_chip *chip, unsigned offset)
static void __sch311x_gpio_set(struct sch311x_gpio_block *block, static void __sch311x_gpio_set(struct sch311x_gpio_block *block,
unsigned offset, int value) unsigned offset, int value)
{ {
unsigned char data = inb(block->runtime_reg + block->data_reg); u8 data = inb(block->runtime_reg + block->data_reg);
if (value) if (value)
data |= BIT(offset); data |= BIT(offset);
else else
...@@ -196,10 +195,12 @@ static void sch311x_gpio_set(struct gpio_chip *chip, unsigned offset, ...@@ -196,10 +195,12 @@ static void sch311x_gpio_set(struct gpio_chip *chip, unsigned offset,
static int sch311x_gpio_direction_in(struct gpio_chip *chip, unsigned offset) static int sch311x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
{ {
struct sch311x_gpio_block *block = gpiochip_get_data(chip); struct sch311x_gpio_block *block = gpiochip_get_data(chip);
u8 data;
spin_lock(&block->lock); spin_lock(&block->lock);
outb(SCH311X_GPIO_CONF_IN, block->runtime_reg + data = inb(block->runtime_reg + block->config_regs[offset]);
block->config_regs[offset]); data |= SCH311X_GPIO_CONF_DIR;
outb(data, block->runtime_reg + block->config_regs[offset]);
spin_unlock(&block->lock); spin_unlock(&block->lock);
return 0; return 0;
...@@ -209,18 +210,59 @@ static int sch311x_gpio_direction_out(struct gpio_chip *chip, unsigned offset, ...@@ -209,18 +210,59 @@ static int sch311x_gpio_direction_out(struct gpio_chip *chip, unsigned offset,
int value) int value)
{ {
struct sch311x_gpio_block *block = gpiochip_get_data(chip); struct sch311x_gpio_block *block = gpiochip_get_data(chip);
u8 data;
spin_lock(&block->lock); spin_lock(&block->lock);
outb(SCH311X_GPIO_CONF_OUT, block->runtime_reg + data = inb(block->runtime_reg + block->config_regs[offset]);
block->config_regs[offset]); data &= ~SCH311X_GPIO_CONF_DIR;
outb(data, block->runtime_reg + block->config_regs[offset]);
__sch311x_gpio_set(block, offset, value); __sch311x_gpio_set(block, offset, value);
spin_unlock(&block->lock); spin_unlock(&block->lock);
return 0; return 0;
} }
static int sch311x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
struct sch311x_gpio_block *block = gpiochip_get_data(chip);
u8 data;
spin_lock(&block->lock);
data = inb(block->runtime_reg + block->config_regs[offset]);
spin_unlock(&block->lock);
return !!(data & SCH311X_GPIO_CONF_DIR);
}
static int sch311x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
unsigned long config)
{
struct sch311x_gpio_block *block = gpiochip_get_data(chip);
enum pin_config_param param = pinconf_to_config_param(config);
u8 data;
switch (param) {
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
spin_lock(&block->lock);
data = inb(block->runtime_reg + block->config_regs[offset]);
data |= SCH311X_GPIO_CONF_OPEN_DRAIN;
outb(data, block->runtime_reg + block->config_regs[offset]);
spin_unlock(&block->lock);
return 0;
case PIN_CONFIG_DRIVE_PUSH_PULL:
spin_lock(&block->lock);
data = inb(block->runtime_reg + block->config_regs[offset]);
data &= ~SCH311X_GPIO_CONF_OPEN_DRAIN;
outb(data, block->runtime_reg + block->config_regs[offset]);
spin_unlock(&block->lock);
return 0;
default:
break;
}
return -ENOTSUPP;
}
static int sch311x_gpio_probe(struct platform_device *pdev) static int sch311x_gpio_probe(struct platform_device *pdev)
{ {
struct sch311x_pdev_data *pdata = dev_get_platdata(&pdev->dev); struct sch311x_pdev_data *pdata = dev_get_platdata(&pdev->dev);
...@@ -253,6 +295,8 @@ static int sch311x_gpio_probe(struct platform_device *pdev) ...@@ -253,6 +295,8 @@ static int sch311x_gpio_probe(struct platform_device *pdev)
block->chip.free = sch311x_gpio_free; block->chip.free = sch311x_gpio_free;
block->chip.direction_input = sch311x_gpio_direction_in; block->chip.direction_input = sch311x_gpio_direction_in;
block->chip.direction_output = sch311x_gpio_direction_out; block->chip.direction_output = sch311x_gpio_direction_out;
block->chip.get_direction = sch311x_gpio_get_direction;
block->chip.set_config = sch311x_gpio_set_config;
block->chip.get = sch311x_gpio_get; block->chip.get = sch311x_gpio_get;
block->chip.set = sch311x_gpio_set; block->chip.set = sch311x_gpio_set;
block->chip.ngpio = 8; block->chip.ngpio = 8;
...@@ -309,7 +353,7 @@ static int __init sch311x_detect(int sio_config_port, unsigned short *addr) ...@@ -309,7 +353,7 @@ static int __init sch311x_detect(int sio_config_port, unsigned short *addr)
{ {
int err = 0, reg; int err = 0, reg;
unsigned short base_addr; unsigned short base_addr;
unsigned char dev_id; u8 dev_id;
err = sch311x_sio_enter(sio_config_port); err = sch311x_sio_enter(sio_config_port);
if (err) if (err)
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
*/ */
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/of.h> #include <linux/of.h>
......
...@@ -23,7 +23,8 @@ ...@@ -23,7 +23,8 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/bitops.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/pci.h> #include <linux/pci.h>
...@@ -58,16 +59,6 @@ struct gsta_gpio { ...@@ -58,16 +59,6 @@ struct gsta_gpio {
unsigned irq_type[GSTA_NR_GPIO]; unsigned irq_type[GSTA_NR_GPIO];
}; };
static inline struct gsta_regs __iomem *__regs(struct gsta_gpio *chip, int nr)
{
return chip->regs[nr / GSTA_GPIO_PER_BLOCK];
}
static inline u32 __bit(int nr)
{
return 1U << (nr % GSTA_GPIO_PER_BLOCK);
}
/* /*
* gpio methods * gpio methods
*/ */
...@@ -75,8 +66,8 @@ static inline u32 __bit(int nr) ...@@ -75,8 +66,8 @@ static inline u32 __bit(int nr)
static void gsta_gpio_set(struct gpio_chip *gpio, unsigned nr, int val) static void gsta_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
{ {
struct gsta_gpio *chip = gpiochip_get_data(gpio); struct gsta_gpio *chip = gpiochip_get_data(gpio);
struct gsta_regs __iomem *regs = __regs(chip, nr); struct gsta_regs __iomem *regs = chip->regs[nr / GSTA_GPIO_PER_BLOCK];
u32 bit = __bit(nr); u32 bit = BIT(nr % GSTA_GPIO_PER_BLOCK);
if (val) if (val)
writel(bit, &regs->dats); writel(bit, &regs->dats);
...@@ -87,8 +78,8 @@ static void gsta_gpio_set(struct gpio_chip *gpio, unsigned nr, int val) ...@@ -87,8 +78,8 @@ static void gsta_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
static int gsta_gpio_get(struct gpio_chip *gpio, unsigned nr) static int gsta_gpio_get(struct gpio_chip *gpio, unsigned nr)
{ {
struct gsta_gpio *chip = gpiochip_get_data(gpio); struct gsta_gpio *chip = gpiochip_get_data(gpio);
struct gsta_regs __iomem *regs = __regs(chip, nr); struct gsta_regs __iomem *regs = chip->regs[nr / GSTA_GPIO_PER_BLOCK];
u32 bit = __bit(nr); u32 bit = BIT(nr % GSTA_GPIO_PER_BLOCK);
return !!(readl(&regs->dat) & bit); return !!(readl(&regs->dat) & bit);
} }
...@@ -97,8 +88,8 @@ static int gsta_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, ...@@ -97,8 +88,8 @@ static int gsta_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
int val) int val)
{ {
struct gsta_gpio *chip = gpiochip_get_data(gpio); struct gsta_gpio *chip = gpiochip_get_data(gpio);
struct gsta_regs __iomem *regs = __regs(chip, nr); struct gsta_regs __iomem *regs = chip->regs[nr / GSTA_GPIO_PER_BLOCK];
u32 bit = __bit(nr); u32 bit = BIT(nr % GSTA_GPIO_PER_BLOCK);
writel(bit, &regs->dirs); writel(bit, &regs->dirs);
/* Data register after direction, otherwise pullup/down is selected */ /* Data register after direction, otherwise pullup/down is selected */
...@@ -112,8 +103,8 @@ static int gsta_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, ...@@ -112,8 +103,8 @@ static int gsta_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
static int gsta_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) static int gsta_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
{ {
struct gsta_gpio *chip = gpiochip_get_data(gpio); struct gsta_gpio *chip = gpiochip_get_data(gpio);
struct gsta_regs __iomem *regs = __regs(chip, nr); struct gsta_regs __iomem *regs = chip->regs[nr / GSTA_GPIO_PER_BLOCK];
u32 bit = __bit(nr); u32 bit = BIT(nr % GSTA_GPIO_PER_BLOCK);
writel(bit, &regs->dirc); writel(bit, &regs->dirc);
return 0; return 0;
...@@ -165,9 +156,9 @@ static void gsta_gpio_setup(struct gsta_gpio *chip) /* called from probe */ ...@@ -165,9 +156,9 @@ static void gsta_gpio_setup(struct gsta_gpio *chip) /* called from probe */
*/ */
static void gsta_set_config(struct gsta_gpio *chip, int nr, unsigned cfg) static void gsta_set_config(struct gsta_gpio *chip, int nr, unsigned cfg)
{ {
struct gsta_regs __iomem *regs = __regs(chip, nr); struct gsta_regs __iomem *regs = chip->regs[nr / GSTA_GPIO_PER_BLOCK];
unsigned long flags; unsigned long flags;
u32 bit = __bit(nr); u32 bit = BIT(nr % GSTA_GPIO_PER_BLOCK);
u32 val; u32 val;
int err = 0; int err = 0;
...@@ -234,8 +225,8 @@ static void gsta_irq_disable(struct irq_data *data) ...@@ -234,8 +225,8 @@ static void gsta_irq_disable(struct irq_data *data)
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
struct gsta_gpio *chip = gc->private; struct gsta_gpio *chip = gc->private;
int nr = data->irq - chip->irq_base; int nr = data->irq - chip->irq_base;
struct gsta_regs __iomem *regs = __regs(chip, nr); struct gsta_regs __iomem *regs = chip->regs[nr / GSTA_GPIO_PER_BLOCK];
u32 bit = __bit(nr); u32 bit = BIT(nr % GSTA_GPIO_PER_BLOCK);
u32 val; u32 val;
unsigned long flags; unsigned long flags;
...@@ -257,8 +248,8 @@ static void gsta_irq_enable(struct irq_data *data) ...@@ -257,8 +248,8 @@ static void gsta_irq_enable(struct irq_data *data)
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
struct gsta_gpio *chip = gc->private; struct gsta_gpio *chip = gc->private;
int nr = data->irq - chip->irq_base; int nr = data->irq - chip->irq_base;
struct gsta_regs __iomem *regs = __regs(chip, nr); struct gsta_regs __iomem *regs = chip->regs[nr / GSTA_GPIO_PER_BLOCK];
u32 bit = __bit(nr); u32 bit = BIT(nr % GSTA_GPIO_PER_BLOCK);
u32 val; u32 val;
int type; int type;
unsigned long flags; unsigned long flags;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/mfd/stmpe.h> #include <linux/mfd/stmpe.h>
......
...@@ -13,9 +13,8 @@ ...@@ -13,9 +13,8 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_gpio.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/err.h> #include <linux/err.h>
...@@ -90,6 +89,20 @@ struct xway_stp { ...@@ -90,6 +89,20 @@ struct xway_stp {
u8 reserved; /* mask out the hw driven bits in gpio_request */ u8 reserved; /* mask out the hw driven bits in gpio_request */
}; };
/**
* xway_stp_get() - gpio_chip->get - get gpios.
* @gc: Pointer to gpio_chip device structure.
* @gpio: GPIO signal number.
*
* Gets the shadow value.
*/
static int xway_stp_get(struct gpio_chip *gc, unsigned int gpio)
{
struct xway_stp *chip = gpiochip_get_data(gc);
return (xway_stp_r32(chip->virt, XWAY_STP_CPU0) & BIT(gpio));
}
/** /**
* xway_stp_set() - gpio_chip->set - set gpios. * xway_stp_set() - gpio_chip->set - set gpios.
* @gc: Pointer to gpio_chip device structure. * @gc: Pointer to gpio_chip device structure.
...@@ -215,6 +228,7 @@ static int xway_stp_probe(struct platform_device *pdev) ...@@ -215,6 +228,7 @@ static int xway_stp_probe(struct platform_device *pdev)
chip->gc.parent = &pdev->dev; chip->gc.parent = &pdev->dev;
chip->gc.label = "stp-xway"; chip->gc.label = "stp-xway";
chip->gc.direction_output = xway_stp_dir_out; chip->gc.direction_output = xway_stp_dir_out;
chip->gc.get = xway_stp_get;
chip->gc.set = xway_stp_set; chip->gc.set = xway_stp_set;
chip->gc.request = xway_stp_request; chip->gc.request = xway_stp_request;
chip->gc.base = -1; chip->gc.base = -1;
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
*/ */
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
...@@ -135,6 +135,33 @@ static const struct syscon_gpio_data clps711x_mctrl_gpio = { ...@@ -135,6 +135,33 @@ static const struct syscon_gpio_data clps711x_mctrl_gpio = {
.dat_bit_offset = 0x40 * 8 + 8, .dat_bit_offset = 0x40 * 8 + 8,
}; };
static void rockchip_gpio_set(struct gpio_chip *chip, unsigned int offset,
int val)
{
struct syscon_gpio_priv *priv = gpiochip_get_data(chip);
unsigned int offs;
u8 bit;
u32 data;
int ret;
offs = priv->dreg_offset + priv->data->dat_bit_offset + offset;
bit = offs % SYSCON_REG_BITS;
data = (val ? BIT(bit) : 0) | BIT(bit + 16);
ret = regmap_write(priv->syscon,
(offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE,
data);
if (ret < 0)
dev_err(chip->parent, "gpio write failed ret(%d)\n", ret);
}
static const struct syscon_gpio_data rockchip_rk3328_gpio_mute = {
/* RK3328 GPIO_MUTE is an output only pin at GRF_SOC_CON10[1] */
.flags = GPIO_SYSCON_FEAT_OUT,
.bit_count = 1,
.dat_bit_offset = 0x0428 * 8 + 1,
.set = rockchip_gpio_set,
};
#define KEYSTONE_LOCK_BIT BIT(0) #define KEYSTONE_LOCK_BIT BIT(0)
static void keystone_gpio_set(struct gpio_chip *chip, unsigned offset, int val) static void keystone_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
...@@ -175,6 +202,10 @@ static const struct of_device_id syscon_gpio_ids[] = { ...@@ -175,6 +202,10 @@ static const struct of_device_id syscon_gpio_ids[] = {
.compatible = "ti,keystone-dsp-gpio", .compatible = "ti,keystone-dsp-gpio",
.data = &keystone_dsp_gpio, .data = &keystone_dsp_gpio,
}, },
{
.compatible = "rockchip,rk3328-grf-gpio",
.data = &rockchip_rk3328_gpio_mute,
},
{ } { }
}; };
MODULE_DEVICE_TABLE(of, syscon_gpio_ids); MODULE_DEVICE_TABLE(of, syscon_gpio_ids);
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -207,7 +207,7 @@ static int tegra_gpio_get_direction(struct gpio_chip *chip, ...@@ -207,7 +207,7 @@ static int tegra_gpio_get_direction(struct gpio_chip *chip,
oe = tegra_gpio_readl(tgi, GPIO_OE(tgi, offset)); oe = tegra_gpio_readl(tgi, GPIO_OE(tgi, offset));
return (oe & pin_mask) ? GPIOF_DIR_OUT : GPIOF_DIR_IN; return !(oe & pin_mask);
} }
static int tegra_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset, static int tegra_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
...@@ -323,13 +323,6 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) ...@@ -323,13 +323,6 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
return -EINVAL; return -EINVAL;
} }
ret = gpiochip_lock_as_irq(&tgi->gc, gpio);
if (ret) {
dev_err(tgi->dev,
"unable to lock Tegra GPIO %u as IRQ\n", gpio);
return ret;
}
spin_lock_irqsave(&bank->lvl_lock[port], flags); spin_lock_irqsave(&bank->lvl_lock[port], flags);
val = tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio)); val = tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio));
...@@ -342,6 +335,14 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) ...@@ -342,6 +335,14 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, gpio), gpio, 0); tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, gpio), gpio, 0);
tegra_gpio_enable(tgi, gpio); tegra_gpio_enable(tgi, gpio);
ret = gpiochip_lock_as_irq(&tgi->gc, gpio);
if (ret) {
dev_err(tgi->dev,
"unable to lock Tegra GPIO %u as IRQ\n", gpio);
tegra_gpio_disable(tgi, gpio);
return ret;
}
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
irq_set_handler_locked(d, handle_level_irq); irq_set_handler_locked(d, handle_level_irq);
else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
...@@ -550,13 +551,6 @@ static const struct dev_pm_ops tegra_gpio_pm_ops = { ...@@ -550,13 +551,6 @@ static const struct dev_pm_ops tegra_gpio_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(tegra_gpio_suspend, tegra_gpio_resume) SET_SYSTEM_SLEEP_PM_OPS(tegra_gpio_suspend, tegra_gpio_resume)
}; };
/*
* This lock class tells lockdep that GPIO irqs are in a different category
* than their parents, so it won't report false recursion.
*/
static struct lock_class_key gpio_lock_class;
static struct lock_class_key gpio_request_class;
static int tegra_gpio_probe(struct platform_device *pdev) static int tegra_gpio_probe(struct platform_device *pdev)
{ {
struct tegra_gpio_info *tgi; struct tegra_gpio_info *tgi;
...@@ -661,8 +655,6 @@ static int tegra_gpio_probe(struct platform_device *pdev) ...@@ -661,8 +655,6 @@ static int tegra_gpio_probe(struct platform_device *pdev)
bank = &tgi->bank_info[GPIO_BANK(gpio)]; bank = &tgi->bank_info[GPIO_BANK(gpio)];
irq_set_lockdep_class(irq, &gpio_lock_class,
&gpio_request_class);
irq_set_chip_data(irq, bank); irq_set_chip_data(irq, bank);
irq_set_chip_and_handler(irq, &tgi->ic, handle_simple_irq); irq_set_chip_and_handler(irq, &tgi->ic, handle_simple_irq);
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <dt-bindings/gpio/tegra186-gpio.h> #include <dt-bindings/gpio/tegra186-gpio.h>
#include <dt-bindings/gpio/tegra194-gpio.h>
#define TEGRA186_GPIO_ENABLE_CONFIG 0x00 #define TEGRA186_GPIO_ENABLE_CONFIG 0x00
#define TEGRA186_GPIO_ENABLE_CONFIG_ENABLE BIT(0) #define TEGRA186_GPIO_ENABLE_CONFIG_ENABLE BIT(0)
...@@ -593,6 +594,73 @@ static const struct tegra_gpio_soc tegra186_aon_soc = { ...@@ -593,6 +594,73 @@ static const struct tegra_gpio_soc tegra186_aon_soc = {
.name = "tegra186-gpio-aon", .name = "tegra186-gpio-aon",
}; };
#define TEGRA194_MAIN_GPIO_PORT(port, base, count, controller) \
[TEGRA194_MAIN_GPIO_PORT_##port] = { \
.name = #port, \
.offset = base, \
.pins = count, \
.irq = controller, \
}
static const struct tegra_gpio_port tegra194_main_ports[] = {
TEGRA194_MAIN_GPIO_PORT( A, 0x1400, 8, 1),
TEGRA194_MAIN_GPIO_PORT( B, 0x4e00, 2, 4),
TEGRA194_MAIN_GPIO_PORT( C, 0x4600, 8, 4),
TEGRA194_MAIN_GPIO_PORT( D, 0x4800, 4, 4),
TEGRA194_MAIN_GPIO_PORT( E, 0x4a00, 8, 4),
TEGRA194_MAIN_GPIO_PORT( F, 0x4c00, 6, 4),
TEGRA194_MAIN_GPIO_PORT( G, 0x4000, 8, 4),
TEGRA194_MAIN_GPIO_PORT( H, 0x4200, 8, 4),
TEGRA194_MAIN_GPIO_PORT( I, 0x4400, 5, 4),
TEGRA194_MAIN_GPIO_PORT( J, 0x5200, 6, 5),
TEGRA194_MAIN_GPIO_PORT( K, 0x3000, 8, 3),
TEGRA194_MAIN_GPIO_PORT( L, 0x3200, 4, 3),
TEGRA194_MAIN_GPIO_PORT( M, 0x2600, 8, 2),
TEGRA194_MAIN_GPIO_PORT( N, 0x2800, 3, 2),
TEGRA194_MAIN_GPIO_PORT( O, 0x5000, 6, 5),
TEGRA194_MAIN_GPIO_PORT( P, 0x2a00, 8, 2),
TEGRA194_MAIN_GPIO_PORT( Q, 0x2c00, 8, 2),
TEGRA194_MAIN_GPIO_PORT( R, 0x2e00, 6, 2),
TEGRA194_MAIN_GPIO_PORT( S, 0x3600, 8, 3),
TEGRA194_MAIN_GPIO_PORT( T, 0x3800, 8, 3),
TEGRA194_MAIN_GPIO_PORT( U, 0x3a00, 1, 3),
TEGRA194_MAIN_GPIO_PORT( V, 0x1000, 8, 1),
TEGRA194_MAIN_GPIO_PORT( W, 0x1200, 2, 1),
TEGRA194_MAIN_GPIO_PORT( X, 0x2000, 8, 2),
TEGRA194_MAIN_GPIO_PORT( Y, 0x2200, 8, 2),
TEGRA194_MAIN_GPIO_PORT( Z, 0x2400, 8, 2),
TEGRA194_MAIN_GPIO_PORT(FF, 0x3400, 2, 3),
TEGRA194_MAIN_GPIO_PORT(GG, 0x0000, 2, 0)
};
static const struct tegra_gpio_soc tegra194_main_soc = {
.num_ports = ARRAY_SIZE(tegra194_main_ports),
.ports = tegra194_main_ports,
.name = "tegra194-gpio",
};
#define TEGRA194_AON_GPIO_PORT(port, base, count, controller) \
[TEGRA194_AON_GPIO_PORT_##port] = { \
.name = #port, \
.offset = base, \
.pins = count, \
.irq = controller, \
}
static const struct tegra_gpio_port tegra194_aon_ports[] = {
TEGRA194_AON_GPIO_PORT(AA, 0x0600, 8, 0),
TEGRA194_AON_GPIO_PORT(BB, 0x0800, 4, 0),
TEGRA194_AON_GPIO_PORT(CC, 0x0200, 8, 0),
TEGRA194_AON_GPIO_PORT(DD, 0x0400, 3, 0),
TEGRA194_AON_GPIO_PORT(EE, 0x0000, 7, 0)
};
static const struct tegra_gpio_soc tegra194_aon_soc = {
.num_ports = ARRAY_SIZE(tegra194_aon_ports),
.ports = tegra194_aon_ports,
.name = "tegra194-gpio-aon",
};
static const struct of_device_id tegra186_gpio_of_match[] = { static const struct of_device_id tegra186_gpio_of_match[] = {
{ {
.compatible = "nvidia,tegra186-gpio", .compatible = "nvidia,tegra186-gpio",
...@@ -600,6 +668,12 @@ static const struct of_device_id tegra186_gpio_of_match[] = { ...@@ -600,6 +668,12 @@ static const struct of_device_id tegra186_gpio_of_match[] = {
}, { }, {
.compatible = "nvidia,tegra186-gpio-aon", .compatible = "nvidia,tegra186-gpio-aon",
.data = &tegra186_aon_soc .data = &tegra186_aon_soc
}, {
.compatible = "nvidia,tegra194-gpio",
.data = &tegra194_main_soc
}, {
.compatible = "nvidia,tegra194-gpio-aon",
.data = &tegra194_aon_soc
}, { }, {
/* sentinel */ /* sentinel */
} }
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/io.h> #include <linux/io.h>
......
...@@ -310,8 +310,7 @@ static int uniphier_gpio_irq_domain_activate(struct irq_domain *domain, ...@@ -310,8 +310,7 @@ static int uniphier_gpio_irq_domain_activate(struct irq_domain *domain,
struct uniphier_gpio_priv *priv = domain->host_data; struct uniphier_gpio_priv *priv = domain->host_data;
struct gpio_chip *chip = &priv->chip; struct gpio_chip *chip = &priv->chip;
gpiochip_lock_as_irq(chip, data->hwirq + UNIPHIER_GPIO_IRQ_OFFSET); return gpiochip_lock_as_irq(chip, data->hwirq + UNIPHIER_GPIO_IRQ_OFFSET);
return 0;
} }
static void uniphier_gpio_irq_domain_deactivate(struct irq_domain *domain, static void uniphier_gpio_irq_domain_deactivate(struct irq_domain *domain,
......
...@@ -138,10 +138,16 @@ static void unmask_giuint_low(struct irq_data *d) ...@@ -138,10 +138,16 @@ static void unmask_giuint_low(struct irq_data *d)
static unsigned int startup_giuint(struct irq_data *data) static unsigned int startup_giuint(struct irq_data *data)
{ {
if (gpiochip_lock_as_irq(&vr41xx_gpio_chip, data->hwirq)) int ret;
ret = gpiochip_lock_as_irq(&vr41xx_gpio_chip, irqd_to_hwirq(data));
if (ret) {
dev_err(vr41xx_gpio_chip.parent, dev_err(vr41xx_gpio_chip.parent,
"unable to lock HW IRQ %lu for IRQ\n", "unable to lock HW IRQ %lu for IRQ\n",
data->hwirq); data->hwirq);
return ret;
}
/* Satisfy the .enable semantics by unmasking the line */ /* Satisfy the .enable semantics by unmasking the line */
unmask_giuint_low(data); unmask_giuint_low(data);
return 0; return 0;
......
...@@ -143,12 +143,14 @@ static int xgene_gpio_sb_domain_activate(struct irq_domain *d, ...@@ -143,12 +143,14 @@ static int xgene_gpio_sb_domain_activate(struct irq_domain *d,
{ {
struct xgene_gpio_sb *priv = d->host_data; struct xgene_gpio_sb *priv = d->host_data;
u32 gpio = HWIRQ_TO_GPIO(priv, irq_data->hwirq); u32 gpio = HWIRQ_TO_GPIO(priv, irq_data->hwirq);
int ret;
if (gpiochip_lock_as_irq(&priv->gc, gpio)) { ret = gpiochip_lock_as_irq(&priv->gc, gpio);
if (ret) {
dev_err(priv->gc.parent, dev_err(priv->gc.parent,
"Unable to configure XGene GPIO standby pin %d as IRQ\n", "Unable to configure XGene GPIO standby pin %d as IRQ\n",
gpio); gpio);
return -ENOSPC; return ret;
} }
xgene_gpio_set_bit(&priv->gc, priv->regs + MPA_GPIO_SEL_LO, xgene_gpio_set_bit(&priv->gc, priv->regs + MPA_GPIO_SEL_LO,
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/slab.h> #include <linux/slab.h>
/* Register Offset Definitions */ /* Register Offset Definitions */
......
...@@ -621,9 +621,6 @@ int of_gpiochip_add(struct gpio_chip *chip) ...@@ -621,9 +621,6 @@ int of_gpiochip_add(struct gpio_chip *chip)
{ {
int status; int status;
if ((!chip->of_node) && (chip->parent))
chip->of_node = chip->parent->of_node;
if (!chip->of_node) if (!chip->of_node)
return 0; return 0;
......
...@@ -431,7 +431,7 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd, ...@@ -431,7 +431,7 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd,
int i; int i;
if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) { if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) {
/* TODO: check if descriptors are really input */ /* NOTE: It's ok to read values of output lines. */
int ret = gpiod_get_array_value_complex(false, int ret = gpiod_get_array_value_complex(false,
true, true,
lh->numdescs, lh->numdescs,
...@@ -449,7 +449,13 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd, ...@@ -449,7 +449,13 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd,
return 0; return 0;
} else if (cmd == GPIOHANDLE_SET_LINE_VALUES_IOCTL) { } else if (cmd == GPIOHANDLE_SET_LINE_VALUES_IOCTL) {
/* TODO: check if descriptors are really output */ /*
* All line descriptors were created at once with the same
* flags so just check if the first one is really output.
*/
if (!test_bit(FLAG_IS_OUT, &lh->descs[0]->flags))
return -EPERM;
if (copy_from_user(&ghd, ip, sizeof(ghd))) if (copy_from_user(&ghd, ip, sizeof(ghd)))
return -EFAULT; return -EFAULT;
...@@ -1256,6 +1262,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, ...@@ -1256,6 +1262,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
/* If the gpiochip has an assigned OF node this takes precedence */ /* If the gpiochip has an assigned OF node this takes precedence */
if (chip->of_node) if (chip->of_node)
gdev->dev.of_node = chip->of_node; gdev->dev.of_node = chip->of_node;
else
chip->of_node = gdev->dev.of_node;
#endif #endif
gdev->id = ida_simple_get(&gpio_ida, 0, 0, GFP_KERNEL); gdev->id = ida_simple_get(&gpio_ida, 0, 0, GFP_KERNEL);
...@@ -1408,9 +1416,9 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, ...@@ -1408,9 +1416,9 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
err_free_gdev: err_free_gdev:
ida_simple_remove(&gpio_ida, gdev->id); ida_simple_remove(&gpio_ida, gdev->id);
/* failures here can mean systems won't boot... */ /* failures here can mean systems won't boot... */
pr_err("%s: GPIOs %d..%d (%s) failed to register\n", __func__, pr_err("%s: GPIOs %d..%d (%s) failed to register, %d\n", __func__,
gdev->base, gdev->base + gdev->ngpio - 1, gdev->base, gdev->base + gdev->ngpio - 1,
chip->label ? : "generic"); chip->label ? : "generic", status);
kfree(gdev); kfree(gdev);
return status; return status;
} }
...@@ -1664,8 +1672,7 @@ static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gpiochip, ...@@ -1664,8 +1672,7 @@ static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gpiochip,
if (parent_handler) { if (parent_handler) {
if (gpiochip->can_sleep) { if (gpiochip->can_sleep) {
chip_err(gpiochip, chip_err(gpiochip,
"you cannot have chained interrupts on a " "you cannot have chained interrupts on a chip that may sleep\n");
"chip that may sleep\n");
return; return;
} }
/* /*
...@@ -1800,16 +1807,18 @@ static const struct irq_domain_ops gpiochip_domain_ops = { ...@@ -1800,16 +1807,18 @@ static const struct irq_domain_ops gpiochip_domain_ops = {
static int gpiochip_irq_reqres(struct irq_data *d) static int gpiochip_irq_reqres(struct irq_data *d)
{ {
struct gpio_chip *chip = irq_data_get_irq_chip_data(d); struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
int ret;
if (!try_module_get(chip->gpiodev->owner)) if (!try_module_get(chip->gpiodev->owner))
return -ENODEV; return -ENODEV;
if (gpiochip_lock_as_irq(chip, d->hwirq)) { ret = gpiochip_lock_as_irq(chip, d->hwirq);
if (ret) {
chip_err(chip, chip_err(chip,
"unable to lock HW IRQ %lu for IRQ\n", "unable to lock HW IRQ %lu for IRQ\n",
d->hwirq); d->hwirq);
module_put(chip->gpiodev->owner); module_put(chip->gpiodev->owner);
return -EINVAL; return ret;
} }
return 0; return 0;
} }
...@@ -1850,8 +1859,7 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, ...@@ -1850,8 +1859,7 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip,
return 0; return 0;
if (gpiochip->irq.parent_handler && gpiochip->can_sleep) { if (gpiochip->irq.parent_handler && gpiochip->can_sleep) {
chip_err(gpiochip, "you cannot have chained interrupts on a " chip_err(gpiochip, "you cannot have chained interrupts on a chip that may sleep\n");
"chip that may sleep\n");
return -EINVAL; return -EINVAL;
} }
...@@ -2259,6 +2267,7 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label) ...@@ -2259,6 +2267,7 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label)
struct gpio_chip *chip = desc->gdev->chip; struct gpio_chip *chip = desc->gdev->chip;
int status; int status;
unsigned long flags; unsigned long flags;
unsigned offset;
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
...@@ -2277,7 +2286,11 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label) ...@@ -2277,7 +2286,11 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label)
if (chip->request) { if (chip->request) {
/* chip->request may sleep */ /* chip->request may sleep */
spin_unlock_irqrestore(&gpio_lock, flags); spin_unlock_irqrestore(&gpio_lock, flags);
status = chip->request(chip, gpio_chip_hwgpio(desc)); offset = gpio_chip_hwgpio(desc);
if (gpiochip_line_is_valid(chip, offset))
status = chip->request(chip, offset);
else
status = -EINVAL;
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
if (status < 0) { if (status < 0) {
...@@ -3193,6 +3206,19 @@ int gpiod_cansleep(const struct gpio_desc *desc) ...@@ -3193,6 +3206,19 @@ int gpiod_cansleep(const struct gpio_desc *desc)
} }
EXPORT_SYMBOL_GPL(gpiod_cansleep); EXPORT_SYMBOL_GPL(gpiod_cansleep);
/**
* gpiod_set_consumer_name() - set the consumer name for the descriptor
* @desc: gpio to set the consumer name on
* @name: the new consumer name
*/
void gpiod_set_consumer_name(struct gpio_desc *desc, const char *name)
{
VALIDATE_DESC_VOID(desc);
/* Just overwrite whatever the previous name was */
desc->label = name;
}
EXPORT_SYMBOL_GPL(gpiod_set_consumer_name);
/** /**
* gpiod_to_irq() - return the IRQ corresponding to a GPIO * gpiod_to_irq() - return the IRQ corresponding to a GPIO
* @desc: gpio whose IRQ will be returned (already requested) * @desc: gpio whose IRQ will be returned (already requested)
...@@ -3249,18 +3275,19 @@ int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset) ...@@ -3249,18 +3275,19 @@ int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
* behind our back * behind our back
*/ */
if (!chip->can_sleep && chip->get_direction) { if (!chip->can_sleep && chip->get_direction) {
int dir = chip->get_direction(chip, offset); int dir = gpiod_get_direction(desc);
if (dir) if (dir < 0) {
clear_bit(FLAG_IS_OUT, &desc->flags); chip_err(chip, "%s: cannot get GPIO direction\n",
else __func__);
set_bit(FLAG_IS_OUT, &desc->flags); return dir;
}
} }
if (test_bit(FLAG_IS_OUT, &desc->flags)) { if (test_bit(FLAG_IS_OUT, &desc->flags)) {
chip_err(chip, chip_err(chip,
"%s: tried to flag a GPIO set as output for IRQ\n", "%s: tried to flag a GPIO set as output for IRQ\n",
__func__); __func__);
return -EIO; return -EIO;
} }
...@@ -3639,9 +3666,16 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, ...@@ -3639,9 +3666,16 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
chip = find_chip_by_name(p->chip_label); chip = find_chip_by_name(p->chip_label);
if (!chip) { if (!chip) {
dev_err(dev, "cannot find GPIO chip %s\n", /*
p->chip_label); * As the lookup table indicates a chip with
return ERR_PTR(-ENODEV); * p->chip_label should exist, assume it may
* still appear later and let the interested
* consumer be probed again or let the Deferred
* Probe infrastructure handle the error.
*/
dev_warn(dev, "cannot find GPIO chip %s, deferring\n",
p->chip_label);
return ERR_PTR(-EPROBE_DEFER);
} }
if (chip->ngpio <= p->chip_hwnum) { if (chip->ngpio <= p->chip_hwnum) {
...@@ -4215,7 +4249,7 @@ static int __init gpiolib_dev_init(void) ...@@ -4215,7 +4249,7 @@ static int __init gpiolib_dev_init(void)
int ret; int ret;
/* Register GPIO sysfs bus */ /* Register GPIO sysfs bus */
ret = bus_register(&gpio_bus_type); ret = bus_register(&gpio_bus_type);
if (ret < 0) { if (ret < 0) {
pr_err("gpiolib: could not register GPIO bus type\n"); pr_err("gpiolib: could not register GPIO bus type\n");
return ret; return ret;
...@@ -4259,9 +4293,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev) ...@@ -4259,9 +4293,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev)
seq_printf(s, " gpio-%-3d (%-20.20s|%-20.20s) %s %s %s", seq_printf(s, " gpio-%-3d (%-20.20s|%-20.20s) %s %s %s",
gpio, gdesc->name ? gdesc->name : "", gdesc->label, gpio, gdesc->name ? gdesc->name : "", gdesc->label,
is_out ? "out" : "in ", is_out ? "out" : "in ",
chip->get chip->get ? (chip->get(chip, i) ? "hi" : "lo") : "? ",
? (chip->get(chip, i) ? "hi" : "lo")
: "? ",
is_irq ? "IRQ" : " "); is_irq ? "IRQ" : " ");
seq_printf(s, "\n"); seq_printf(s, "\n");
} }
......
...@@ -92,7 +92,7 @@ struct acpi_gpio_info { ...@@ -92,7 +92,7 @@ struct acpi_gpio_info {
}; };
/* gpio suffixes used for ACPI and device tree lookup */ /* gpio suffixes used for ACPI and device tree lookup */
static const char * const gpio_suffixes[] = { "gpios", "gpio" }; static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" };
#ifdef CONFIG_OF_GPIO #ifdef CONFIG_OF_GPIO
struct gpio_desc *of_find_gpio(struct device *dev, struct gpio_desc *of_find_gpio(struct device *dev,
......
...@@ -49,7 +49,7 @@ config W1_MASTER_DS1WM ...@@ -49,7 +49,7 @@ config W1_MASTER_DS1WM
config W1_MASTER_GPIO config W1_MASTER_GPIO
tristate "GPIO 1-wire busmaster" tristate "GPIO 1-wire busmaster"
depends on GPIOLIB depends on GPIOLIB || COMPILE_TEST
help help
Say Y here if you want to communicate with your 1-wire devices using Say Y here if you want to communicate with your 1-wire devices using
GPIO pins. This driver uses the GPIO API to control the wire. GPIO pins. This driver uses the GPIO API to control the wire.
......
#ifndef __GPIO_ASPEED_H
#define __GPIO_ASPEED_H
struct aspeed_gpio_copro_ops {
int (*request_access)(void *data);
int (*release_access)(void *data);
};
int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc,
u16 *vreg_offset, u16 *dreg_offset, u8 *bit);
int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc);
int aspeed_gpio_copro_set_ops(const struct aspeed_gpio_copro_ops *ops, void *data);
#endif /* __GPIO_ASPEED_H */
...@@ -41,11 +41,8 @@ enum gpiod_flags { ...@@ -41,11 +41,8 @@ enum gpiod_flags {
GPIOD_OUT_LOW = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT, GPIOD_OUT_LOW = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT,
GPIOD_OUT_HIGH = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT | GPIOD_OUT_HIGH = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT |
GPIOD_FLAGS_BIT_DIR_VAL, GPIOD_FLAGS_BIT_DIR_VAL,
GPIOD_OUT_LOW_OPEN_DRAIN = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_OUT_LOW_OPEN_DRAIN = GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_OPEN_DRAIN,
GPIOD_FLAGS_BIT_DIR_OUT | GPIOD_FLAGS_BIT_OPEN_DRAIN, GPIOD_OUT_HIGH_OPEN_DRAIN = GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_OPEN_DRAIN,
GPIOD_OUT_HIGH_OPEN_DRAIN = GPIOD_FLAGS_BIT_DIR_SET |
GPIOD_FLAGS_BIT_DIR_OUT | GPIOD_FLAGS_BIT_DIR_VAL |
GPIOD_FLAGS_BIT_OPEN_DRAIN,
}; };
#ifdef CONFIG_GPIOLIB #ifdef CONFIG_GPIOLIB
...@@ -145,6 +142,7 @@ int gpiod_is_active_low(const struct gpio_desc *desc); ...@@ -145,6 +142,7 @@ int gpiod_is_active_low(const struct gpio_desc *desc);
int gpiod_cansleep(const struct gpio_desc *desc); int gpiod_cansleep(const struct gpio_desc *desc);
int gpiod_to_irq(const struct gpio_desc *desc); int gpiod_to_irq(const struct gpio_desc *desc);
void gpiod_set_consumer_name(struct gpio_desc *desc, const char *name);
/* Convert between the old gpio_ and new gpiod_ interfaces */ /* Convert between the old gpio_ and new gpiod_ interfaces */
struct gpio_desc *gpio_to_desc(unsigned gpio); struct gpio_desc *gpio_to_desc(unsigned gpio);
...@@ -467,6 +465,12 @@ static inline int gpiod_to_irq(const struct gpio_desc *desc) ...@@ -467,6 +465,12 @@ static inline int gpiod_to_irq(const struct gpio_desc *desc)
return -EINVAL; return -EINVAL;
} }
static inline void gpiod_set_consumer_name(struct gpio_desc *desc, const char *name)
{
/* GPIO can never have been requested */
WARN_ON(1);
}
static inline struct gpio_desc *gpio_to_desc(unsigned gpio) static inline struct gpio_desc *gpio_to_desc(unsigned gpio)
{ {
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
......
...@@ -201,6 +201,8 @@ static inline struct gpio_irq_chip *to_gpio_irq_chip(struct irq_chip *chip) ...@@ -201,6 +201,8 @@ static inline struct gpio_irq_chip *to_gpio_irq_chip(struct irq_chip *chip)
* @reg_set: output set register (out=high) for generic GPIO * @reg_set: output set register (out=high) for generic GPIO
* @reg_clr: output clear register (out=low) for generic GPIO * @reg_clr: output clear register (out=low) for generic GPIO
* @reg_dir: direction setting register for generic GPIO * @reg_dir: direction setting register for generic GPIO
* @bgpio_dir_inverted: indicates that the direction register is inverted
* (gpiolib private state variable)
* @bgpio_bits: number of register bits used for a generic GPIO i.e. * @bgpio_bits: number of register bits used for a generic GPIO i.e.
* <register width> * 8 * <register width> * 8
* @bgpio_lock: used to lock chip->bgpio_data. Also, this is needed to keep * @bgpio_lock: used to lock chip->bgpio_data. Also, this is needed to keep
...@@ -267,6 +269,7 @@ struct gpio_chip { ...@@ -267,6 +269,7 @@ struct gpio_chip {
void __iomem *reg_set; void __iomem *reg_set;
void __iomem *reg_clr; void __iomem *reg_clr;
void __iomem *reg_dir; void __iomem *reg_dir;
bool bgpio_dir_inverted;
int bgpio_bits; int bgpio_bits;
spinlock_t bgpio_lock; spinlock_t bgpio_lock;
unsigned long bgpio_data; unsigned long bgpio_data;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <asm-generic/gpio.h> #include <asm-generic/gpio.h>
#define MAX_REGS_BANKS 5 #define MAX_REGS_BANKS 5
#define MAX_INT_PER_BANK 32
struct davinci_gpio_platform_data { struct davinci_gpio_platform_data {
u32 ngpio; u32 ngpio;
...@@ -41,7 +42,7 @@ struct davinci_gpio_controller { ...@@ -41,7 +42,7 @@ struct davinci_gpio_controller {
spinlock_t lock; spinlock_t lock;
void __iomem *regs[MAX_REGS_BANKS]; void __iomem *regs[MAX_REGS_BANKS];
int gpio_unbanked; int gpio_unbanked;
unsigned int base_irq; int irqs[MAX_INT_PER_BANK];
unsigned int base; unsigned int base;
}; };
......
...@@ -225,10 +225,10 @@ int gpio_pin_test(struct gpiochip_info *cinfo, int line, int flag, int value) ...@@ -225,10 +225,10 @@ int gpio_pin_test(struct gpiochip_info *cinfo, int line, int flag, int value)
if (flag & GPIOHANDLE_REQUEST_ACTIVE_LOW) if (flag & GPIOHANDLE_REQUEST_ACTIVE_LOW)
debugfs_value = !debugfs_value; debugfs_value = !debugfs_value;
if (!(debugfs_dir == OUT && value == debugfs_value)) if (!(debugfs_dir == OUT && value == debugfs_value)) {
errno = -EINVAL; errno = -EINVAL;
ret = -errno; ret = -errno;
}
} }
gpiotools_release_linehandle(fd); gpiotools_release_linehandle(fd);
......
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