Merge tag 'gpio-v4.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 8 Jun 2018 17:31:52 +0000 (10:31 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 8 Jun 2018 17:31:52 +0000 (10:31 -0700)
Pull GPIO updates from Linus Walleij:
 "This is the bulk of GPIO changes for the v4.18 development cycle.

  Core changes:

   - We have killed off VLA from the core library and all drivers.

     The background should be clear for everyone at this point:

        https://lwn.net/Articles/749064/

     Also I just don't like VLA's, kernel developers hate it when
     compilers do things behind their back. It's as simple as that.

     I'm sorry that they even slipped in to begin with. Kudos to Laura
     Abbott for exorcising them.

   - Support GPIO hogs in machines/board files.

  New drivers and chip support:

   - R-Car r8a77470 (RZ/G1C)

   - R-Car r8a77965 (M3-N)

   - R-Car r8a77990 (E3)

   - PCA953x driver improvements to accomodate more variants.

  Improvements and new features:

   - Support one interrupt per line on port A in the DesignWare dwapb
     driver.

  Misc:

   - Random cleanups, right header files in the drivers, some size
     optimizations etc"

* tag 'gpio-v4.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (73 commits)
  gpio: davinci: fix build warning when !CONFIG_OF
  gpio: dwapb: Fix rework support for 1 interrupt per port A GPIO
  gpio: pxa: Include the right header
  gpio: pl061: Include the right header
  gpio: pch: Include the right header
  gpio: pcf857x: Include the right header
  gpio: pca953x: Include the right header
  gpio: palmas: Include the right header
  gpio: omap: Include the right header
  gpio: octeon: Include the right header
  gpio: mxs: Switch to SPDX identifier
  gpio: Remove VLA from stmpe driver
  gpio: mxc: Switch to SPDX identifier
  gpio: mxc: add clock operation
  gpio: Remove VLA from gpiolib
  gpio: aspeed: Use a cache of output data registers
  gpio: aspeed: Set output latch before changing direction
  gpio: pca953x: fix address calculation for pcal6524
  gpio: pca953x: define masks for addressing common and extended registers
  gpio: pca953x: set the PCA_PCAL flag also when matching by DT
  ...

54 files changed:
Documentation/devicetree/bindings/gpio/gpio-pca953x.txt
Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt
Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
Documentation/driver-api/gpio/board.rst
Documentation/driver-api/gpio/drivers-on-gpio.rst
drivers/gpio/Kconfig
drivers/gpio/gpio-104-dio-48e.c
drivers/gpio/gpio-104-idi-48.c
drivers/gpio/gpio-74xx-mmio.c
drivers/gpio/gpio-aspeed.c
drivers/gpio/gpio-davinci.c
drivers/gpio/gpio-dwapb.c
drivers/gpio/gpio-eic-sprd.c
drivers/gpio/gpio-ge.c
drivers/gpio/gpio-gpio-mm.c
drivers/gpio/gpio-ingenic.c
drivers/gpio/gpio-loongson.c
drivers/gpio/gpio-lp3943.c
drivers/gpio/gpio-lp873x.c
drivers/gpio/gpio-lpc32xx.c
drivers/gpio/gpio-lynxpoint.c
drivers/gpio/gpio-max730x.c
drivers/gpio/gpio-mc33880.c
drivers/gpio/gpio-mc9s08dz60.c
drivers/gpio/gpio-ml-ioh.c
drivers/gpio/gpio-mm-lantiq.c
drivers/gpio/gpio-mockup.c
drivers/gpio/gpio-msic.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-mxc.c
drivers/gpio/gpio-mxs.c
drivers/gpio/gpio-octeon.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-palmas.c
drivers/gpio/gpio-pca953x.c
drivers/gpio/gpio-pcf857x.c
drivers/gpio/gpio-pch.c
drivers/gpio/gpio-pl061.c
drivers/gpio/gpio-pmic-eic-sprd.c
drivers/gpio/gpio-pxa.c
drivers/gpio/gpio-stmpe.c
drivers/gpio/gpio-syscon.c
drivers/gpio/gpio-ts4900.c
drivers/gpio/gpio-vf610.c
drivers/gpio/gpio-xlp.c
drivers/gpio/gpio-xra1403.c
drivers/gpio/gpio-zynq.c
drivers/gpio/gpiolib-of.c
drivers/gpio/gpiolib.c
drivers/gpio/gpiolib.h
drivers/mfd/intel_quark_i2c_gpio.c
include/linux/gpio/consumer.h
include/linux/gpio/machine.h
include/linux/platform_data/gpio-dwapb.h

index d2a9376828369b33aaa4108ac5def0343f669409..88f22866550750f93d02e90b4026d5df28b70799 100644 (file)
@@ -31,10 +31,15 @@ Required properties:
        ti,tca9554
        onnn,pca9654
        exar,xra1202
+ - gpio-controller: if used as gpio expander.
+ - #gpio-cells: if used as gpio expander.
+ - interrupt-controller: if to be used as interrupt expander.
+ - #interrupt-cells: if to be used as interrupt expander.
 
 Optional properties:
  - reset-gpios: GPIO specification for the RESET input. This is an
                active low signal to the PCA953x.
+ - vcc-supply: power supply regulator.
 
 Example:
 
@@ -47,3 +52,32 @@ Example:
                interrupt-parent = <&gpio3>;
                interrupts = <23 IRQ_TYPE_LEVEL_LOW>;
        };
+
+
+Example with Interrupts:
+
+
+       gpio99: gpio@22 {
+               compatible = "nxp,pcal6524";
+               reg = <0x22>;
+               interrupt-parent = <&gpio6>;
+               interrupts = <1 IRQ_TYPE_EDGE_FALLING>; /* gpio6_161 */
+               interrupt-controller;
+               #interrupt-cells = <2>;
+               vcc-supply = <&vdds_1v8_main>;
+               gpio-controller;
+               #gpio-cells = <2>;
+               gpio-line-names =
+                       "hdmi-ct-hpd", "hdmi.ls-oe", "p02", "p03", "vibra", "fault2", "p06", "p07",
+                       "en-usb", "en-host1", "en-host2", "chg-int", "p14", "p15", "mic-int", "en-modem",
+                       "shdn-hs-amp", "chg-status+red", "green", "blue", "en-esata", "fault1", "p26", "p27";
+       };
+
+       ts3a227@3b {
+               compatible = "ti,ts3a227e";
+               reg = <0x3b>;
+               interrupt-parent = <&gpio99>;
+               interrupts = <14 IRQ_TYPE_EDGE_RISING>;
+               ti,micbias = <0>;       /* 2.1V */
+       };
+
index 9474138d776ed58da02dd925105dd89daa3c6cb4..378f1322211e9a382a65fe0618c1557fc3577852 100644 (file)
@@ -5,6 +5,7 @@ Required Properties:
   - compatible: should contain one or more of the following:
     - "renesas,gpio-r8a7743": for R8A7743 (RZ/G1M) compatible GPIO controller.
     - "renesas,gpio-r8a7745": for R8A7745 (RZ/G1E) compatible GPIO controller.
+    - "renesas,gpio-r8a77470": for R8A77470 (RZ/G1C) compatible GPIO controller.
     - "renesas,gpio-r8a7778": for R8A7778 (R-Car M1) compatible GPIO controller.
     - "renesas,gpio-r8a7779": for R8A7779 (R-Car H1) compatible GPIO controller.
     - "renesas,gpio-r8a7790": for R8A7790 (R-Car H2) compatible GPIO controller.
@@ -14,7 +15,9 @@ Required Properties:
     - "renesas,gpio-r8a7794": for R8A7794 (R-Car E2) compatible GPIO controller.
     - "renesas,gpio-r8a7795": for R8A7795 (R-Car H3) 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-r8a77970": for R8A77970 (R-Car V3M) 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,rcar-gen1-gpio": for a generic R-Car Gen1 GPIO controller.
     - "renesas,rcar-gen2-gpio": for a generic R-Car Gen2 or RZ/G1 GPIO controller.
index 4a75da7051bd218c12ef8ff3bf49e555e2e0991c..3c1118bc67f50cb1214327a06d4ff57366d92eaf 100644 (file)
@@ -26,8 +26,13 @@ controller.
   the second encodes the triger flags encoded as described in
   Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
 - interrupt-parent : The parent interrupt controller.
-- interrupts : The interrupt to the parent controller raised when GPIOs
-  generate the interrupts.
+- interrupts : The interrupts to the parent controller raised when GPIOs
+  generate the interrupts. If the controller provides one combined interrupt
+  for all GPIOs, specify a single interrupt. If the controller provides one
+  interrupt for each GPIO, provide a list of interrupts that correspond to each
+  of the GPIO pins. When specifying multiple interrupts, if any are unconnected,
+  use the interrupts-extended property to specify the interrupts and set the
+  interrupt controller handle for unused interrupts to 0.
 - snps,nr-gpios : The number of pins in the port, a single cell.
 - resets : Reset line for the controller.
 
index 25d62b2e9fd0b26968bbadcebf780d7d70c0a6a8..2c112553df841444730beee24d30485857d99145 100644 (file)
@@ -177,3 +177,19 @@ mapping and is thus transparent to GPIO consumers.
 
 A set of functions such as gpiod_set_value() is available to work with
 the new descriptor-oriented interface.
+
+Boards using platform data can also hog GPIO lines by defining GPIO hog tables.
+
+.. code-block:: c
+
+        struct gpiod_hog gpio_hog_table[] = {
+                GPIO_HOG("gpio.0", 10, "foo", GPIO_ACTIVE_LOW, GPIOD_OUT_HIGH),
+                { }
+        };
+
+And the table can be added to the board code as follows::
+
+        gpiod_add_hogs(gpio_hog_table);
+
+The line will be hogged as soon as the gpiochip is created or - in case the
+chip was created earlier - when the hog table is registered.
index 7da0c1dd1f7a4936c1787022fbf4dfcd011fa584..f3a189320e11fc28705292db44150b44b224658d 100644 (file)
@@ -85,6 +85,10 @@ hardware descriptions such as device tree or ACPI:
   any other serio bus to the system and makes it possible to connect drivers
   for e.g. keyboards and other PS/2 protocol based devices.
 
+- cec-gpio: drivers/media/platform/cec-gpio/ is used to interact with a CEC
+  Consumer Electronics Control bus using only GPIO. It is used to communicate
+  with devices on the HDMI bus.
+
 Apart from this there are special GPIO drivers in subsystems like MMC/SD to
 read card detect and write protect GPIO lines, and in the TTY serial subsystem
 to emulate MCTRL (modem control) signals CTS/RTS by using two GPIO lines. The
index b960f6f35abd37c2b61d68e85e2c5290c5211245..71c0ab46f216dcf936e30e644c7a807b1f3fcd6c 100644 (file)
@@ -22,6 +22,18 @@ menuconfig GPIOLIB
 
 if GPIOLIB
 
+config GPIOLIB_FASTPATH_LIMIT
+       int "Maximum number of GPIOs for fast path"
+       range 32 512
+       default 512
+       help
+          This adjusts the point at which certain APIs will switch from
+          using a stack allocated buffer to a dynamically allocated buffer.
+
+          You shouldn't need to change this unless you really need to
+          optimize either stack space or performance. Change this carefully
+          since setting an incorrect value could cause stack corruption.
+
 config OF_GPIO
        def_bool y
        depends on OF
index 31e22c93e84484d6fbbd2269d02b76c55a26d885..9c4e07fcb74b5f8fb1286c209a3b3c47d5a412b3 100644 (file)
@@ -188,7 +188,7 @@ static int dio48e_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
 {
        struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
        size_t i;
-       const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
+       static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
        const unsigned int gpio_reg_size = 8;
        unsigned int bits_offset;
        size_t word_index;
index f35632609379432440e9ca1df167f88dab1422a0..2c9738adb3a68434eb877d380954185342c13a37 100644 (file)
@@ -94,7 +94,7 @@ static int idi_48_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
 {
        struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
        size_t i;
-       const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
+       static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
        const unsigned int gpio_reg_size = 8;
        unsigned int bits_offset;
        size_t word_index;
index 0475e8ec96d0170ff2c6de7c543596bc773104d9..49616ec815ee351b0d807d69b49e990b235f9de4 100644 (file)
@@ -105,27 +105,22 @@ static int mmio_74xx_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 
 static int mmio_74xx_gpio_probe(struct platform_device *pdev)
 {
-       const struct of_device_id *of_id;
        struct mmio_74xx_gpio_priv *priv;
        struct resource *res;
        void __iomem *dat;
        int err;
 
-       of_id = of_match_device(mmio_74xx_gpio_ids, &pdev->dev);
-       if (!of_id)
-               return -ENODEV;
-
        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
+       priv->flags = (uintptr_t)of_device_get_match_data(&pdev->dev);
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        dat = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(dat))
                return PTR_ERR(dat);
 
-       priv->flags = (uintptr_t) of_id->data;
-
        err = bgpio_init(&priv->gc, &pdev->dev,
                         DIV_ROUND_UP(MMIO_74XX_BIT_CNT(priv->flags), 8),
                         dat, NULL, NULL, NULL, NULL, 0);
index 6f693b7d5220a02b110ae28b8fb6dd5a997d631f..5e89f1c74a3398b6fb8337b63f29f5e4ad4c1264 100644 (file)
@@ -54,6 +54,8 @@ struct aspeed_gpio {
        u8 *offset_timer;
        unsigned int timer_users[4];
        struct clk *clk;
+
+       u32 *dcache;
 };
 
 struct aspeed_gpio_bank {
@@ -231,12 +233,13 @@ static void __aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
        u32 reg;
 
        addr = bank_val_reg(gpio, bank, GPIO_DATA);
-       reg = ioread32(addr);
+       reg = gpio->dcache[GPIO_BANK(offset)];
 
        if (val)
                reg |= GPIO_BIT(offset);
        else
                reg &= ~GPIO_BIT(offset);
+       gpio->dcache[GPIO_BANK(offset)] = reg;
 
        iowrite32(reg, addr);
 }
@@ -287,11 +290,10 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,
 
        spin_lock_irqsave(&gpio->lock, flags);
 
+       __aspeed_gpio_set(gc, offset, val);
        reg = ioread32(bank_val_reg(gpio, bank, GPIO_DIR));
        iowrite32(reg | GPIO_BIT(offset), bank_val_reg(gpio, bank, GPIO_DIR));
 
-       __aspeed_gpio_set(gc, offset, val);
-
        spin_unlock_irqrestore(&gpio->lock, flags);
 
        return 0;
@@ -852,7 +854,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
        const struct of_device_id *gpio_id;
        struct aspeed_gpio *gpio;
        struct resource *res;
-       int rc;
+       int rc, i, banks;
 
        gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
        if (!gpio)
@@ -893,6 +895,20 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
        gpio->chip.base = -1;
        gpio->chip.irq.need_valid_mask = true;
 
+       /* Allocate a cache of the output registers */
+       banks = gpio->config->nr_gpios >> 5;
+       gpio->dcache = devm_kzalloc(&pdev->dev,
+                                   sizeof(u32) * banks, GFP_KERNEL);
+       if (!gpio->dcache)
+               return -ENOMEM;
+
+       /* Populate it with initial values read from the HW */
+       for (i = 0; i < banks; i++) {
+               const struct aspeed_gpio_bank *bank = &aspeed_gpio_banks[i];
+               gpio->dcache[i] = ioread32(gpio->base + bank->val_regs +
+                                          GPIO_DATA);
+       }
+
        rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
        if (rc < 0)
                return rc;
index 987126c4c6f611630d35222e6577d1bc80c10281..b574ecff7761696d63bd2fc613c07238098fc441 100644 (file)
@@ -610,14 +610,12 @@ done:
        return 0;
 }
 
-#if IS_ENABLED(CONFIG_OF)
 static const struct of_device_id davinci_gpio_ids[] = {
        { .compatible = "ti,keystone-gpio", keystone_gpio_get_irq_chip},
        { .compatible = "ti,dm6441-gpio", davinci_gpio_get_irq_chip},
        { /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, davinci_gpio_ids);
-#endif
 
 static struct platform_driver davinci_gpio_driver = {
        .probe          = davinci_gpio_probe,
index 226977f78482a842a79bde8bad43e40db7ddf261..7a2de3de65719a6de3177c07e731a0f6f62d708d 100644 (file)
@@ -441,14 +441,19 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
        irq_gc->chip_types[1].handler = handle_edge_irq;
 
        if (!pp->irq_shared) {
-               irq_set_chained_handler_and_data(pp->irq, dwapb_irq_handler,
-                                                gpio);
+               int i;
+
+               for (i = 0; i < pp->ngpio; i++) {
+                       if (pp->irq[i] >= 0)
+                               irq_set_chained_handler_and_data(pp->irq[i],
+                                               dwapb_irq_handler, gpio);
+               }
        } else {
                /*
                 * Request a shared IRQ since where MFD would have devices
                 * using the same irq pin
                 */
-               err = devm_request_irq(gpio->dev, pp->irq,
+               err = devm_request_irq(gpio->dev, pp->irq[0],
                                       dwapb_irq_handler_mfd,
                                       IRQF_SHARED, "gpio-dwapb-mfd", gpio);
                if (err) {
@@ -524,7 +529,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
        if (pp->idx == 0)
                port->gc.set_config = dwapb_gpio_set_config;
 
-       if (pp->irq)
+       if (pp->has_irq)
                dwapb_configure_irqs(gpio, port, pp);
 
        err = gpiochip_add_data(&port->gc, port);
@@ -535,7 +540,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
                port->is_registered = true;
 
        /* Add GPIO-signaled ACPI event support */
-       if (pp->irq)
+       if (pp->has_irq)
                acpi_gpiochip_request_interrupts(&port->gc);
 
        return err;
@@ -557,7 +562,7 @@ dwapb_gpio_get_pdata(struct device *dev)
        struct dwapb_platform_data *pdata;
        struct dwapb_port_property *pp;
        int nports;
-       int i;
+       int i, j;
 
        nports = device_get_child_node_count(dev);
        if (nports == 0)
@@ -575,6 +580,8 @@ dwapb_gpio_get_pdata(struct device *dev)
 
        i = 0;
        device_for_each_child_node(dev, fwnode)  {
+               struct device_node *np = NULL;
+
                pp = &pdata->properties[i++];
                pp->fwnode = fwnode;
 
@@ -594,23 +601,35 @@ dwapb_gpio_get_pdata(struct device *dev)
                        pp->ngpio = 32;
                }
 
+               pp->irq_shared  = false;
+               pp->gpio_base   = -1;
+
                /*
                 * Only port A can provide interrupts in all configurations of
                 * the IP.
                 */
-               if (dev->of_node && pp->idx == 0 &&
-                       fwnode_property_read_bool(fwnode,
+               if (pp->idx != 0)
+                       continue;
+
+               if (dev->of_node && fwnode_property_read_bool(fwnode,
                                                  "interrupt-controller")) {
-                       pp->irq = irq_of_parse_and_map(to_of_node(fwnode), 0);
-                       if (!pp->irq)
-                               dev_warn(dev, "no irq for port%d\n", pp->idx);
+                       np = to_of_node(fwnode);
                }
 
-               if (has_acpi_companion(dev) && pp->idx == 0)
-                       pp->irq = platform_get_irq(to_platform_device(dev), 0);
+               for (j = 0; j < pp->ngpio; j++) {
+                       pp->irq[j] = -ENXIO;
 
-               pp->irq_shared  = false;
-               pp->gpio_base   = -1;
+                       if (np)
+                               pp->irq[j] = of_irq_get(np, j);
+                       else if (has_acpi_companion(dev))
+                               pp->irq[j] = platform_get_irq(to_platform_device(dev), j);
+
+                       if (pp->irq[j] >= 0)
+                               pp->has_irq = true;
+               }
+
+               if (!pp->has_irq)
+                       dev_warn(dev, "no irq for port%d\n", pp->idx);
        }
 
        return pdata;
@@ -684,13 +703,7 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
 
        gpio->flags = 0;
        if (dev->of_node) {
-               const struct of_device_id *of_devid;
-
-               of_devid = of_match_device(dwapb_of_match, dev);
-               if (of_devid) {
-                       if (of_devid->data)
-                               gpio->flags = (uintptr_t)of_devid->data;
-               }
+               gpio->flags = (uintptr_t)of_device_get_match_data(dev);
        } else if (has_acpi_companion(dev)) {
                const struct acpi_device_id *acpi_id;
 
index de7dd939c04314bc54debf94c3c5943fe06debae..e0d6a0a7bc697d0de1e3f1b364a0dc4041ad9b2a 100644 (file)
@@ -300,6 +300,7 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
        struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
        struct sprd_eic *sprd_eic = gpiochip_get_data(chip);
        u32 offset = irqd_to_hwirq(data);
+       int state;
 
        switch (sprd_eic->type) {
        case SPRD_EIC_DEBOUNCE:
@@ -310,6 +311,17 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
                case IRQ_TYPE_LEVEL_LOW:
                        sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 0);
                        break;
+               case IRQ_TYPE_EDGE_RISING:
+               case IRQ_TYPE_EDGE_FALLING:
+               case IRQ_TYPE_EDGE_BOTH:
+                       state = sprd_eic_get(chip, offset);
+                       if (state)
+                               sprd_eic_update(chip, offset,
+                                               SPRD_EIC_DBNC_IEV, 0);
+                       else
+                               sprd_eic_update(chip, offset,
+                                               SPRD_EIC_DBNC_IEV, 1);
+                       break;
                default:
                        return -ENOTSUPP;
                }
@@ -324,6 +336,17 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
                case IRQ_TYPE_LEVEL_LOW:
                        sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 1);
                        break;
+               case IRQ_TYPE_EDGE_RISING:
+               case IRQ_TYPE_EDGE_FALLING:
+               case IRQ_TYPE_EDGE_BOTH:
+                       state = sprd_eic_get(chip, offset);
+                       if (state)
+                               sprd_eic_update(chip, offset,
+                                               SPRD_EIC_LATCH_INTPOL, 0);
+                       else
+                               sprd_eic_update(chip, offset,
+                                               SPRD_EIC_LATCH_INTPOL, 1);
+                       break;
                default:
                        return -ENOTSUPP;
                }
@@ -405,6 +428,55 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
        return 0;
 }
 
+static void sprd_eic_toggle_trigger(struct gpio_chip *chip, unsigned int irq,
+                                   unsigned int offset)
+{
+       struct sprd_eic *sprd_eic = gpiochip_get_data(chip);
+       struct irq_data *data = irq_get_irq_data(irq);
+       u32 trigger = irqd_get_trigger_type(data);
+       int state, post_state;
+
+       /*
+        * The debounce EIC and latch EIC can only support level trigger, so we
+        * can toggle the level trigger to emulate the edge trigger.
+        */
+       if ((sprd_eic->type != SPRD_EIC_DEBOUNCE &&
+            sprd_eic->type != SPRD_EIC_LATCH) ||
+           !(trigger & IRQ_TYPE_EDGE_BOTH))
+               return;
+
+       sprd_eic_irq_mask(data);
+       state = sprd_eic_get(chip, offset);
+
+retry:
+       switch (sprd_eic->type) {
+       case SPRD_EIC_DEBOUNCE:
+               if (state)
+                       sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 0);
+               else
+                       sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 1);
+               break;
+       case SPRD_EIC_LATCH:
+               if (state)
+                       sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 0);
+               else
+                       sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 1);
+               break;
+       default:
+               sprd_eic_irq_unmask(data);
+               return;
+       }
+
+       post_state = sprd_eic_get(chip, offset);
+       if (state != post_state) {
+               dev_warn(chip->parent, "EIC level was changed.\n");
+               state = post_state;
+               goto retry;
+       }
+
+       sprd_eic_irq_unmask(data);
+}
+
 static int sprd_eic_match_chip_by_type(struct gpio_chip *chip, void *data)
 {
        enum sprd_eic_type type = *(enum sprd_eic_type *)data;
@@ -448,6 +520,7 @@ static void sprd_eic_handle_one_type(struct gpio_chip *chip)
                                        bank * SPRD_EIC_PER_BANK_NR + n);
 
                        generic_handle_irq(girq);
+                       sprd_eic_toggle_trigger(chip, girq, n);
                }
        }
 }
index 1fe2d3418f2f3464b359a4d1ecde4f355f715505..636952769bc82bd251c31d51ea38821deed49b7a 100644 (file)
@@ -52,8 +52,6 @@ MODULE_DEVICE_TABLE(of, gef_gpio_ids);
 
 static int __init gef_gpio_probe(struct platform_device *pdev)
 {
-       const struct of_device_id *of_id =
-               of_match_device(gef_gpio_ids, &pdev->dev);
        struct gpio_chip *gc;
        void __iomem *regs;
        int ret;
@@ -82,7 +80,7 @@ static int __init gef_gpio_probe(struct platform_device *pdev)
        }
 
        gc->base = -1;
-       gc->ngpio = (u16)(uintptr_t)of_id->data;
+       gc->ngpio = (u16)(uintptr_t)of_device_get_match_data(&pdev->dev);
        gc->of_gpio_n_cells = 2;
        gc->of_node = pdev->dev.of_node;
 
index d496cc56c2a2d03d60321980caae64fda6f5fe2a..b56ff2efbf3690129d3d781b5a39890e9c5d307d 100644 (file)
@@ -177,7 +177,7 @@ static int gpiomm_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
 {
        struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
        size_t i;
-       const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
+       static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
        const unsigned int gpio_reg_size = 8;
        unsigned int bits_offset;
        size_t word_index;
index 15fb2bc796a849889cd8213ccf9faf4196be361f..e738e384a5ca7722756dcc3d46619e566f6811e3 100644 (file)
@@ -285,8 +285,6 @@ MODULE_DEVICE_TABLE(of, ingenic_gpio_of_match);
 static int ingenic_gpio_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       const struct of_device_id *of_id = of_match_device(
-                       ingenic_gpio_of_match, dev);
        struct ingenic_gpio_chip *jzgc;
        u32 bank;
        int err;
@@ -323,7 +321,7 @@ static int ingenic_gpio_probe(struct platform_device *pdev)
        jzgc->gc.parent = dev;
        jzgc->gc.of_node = dev->of_node;
        jzgc->gc.owner = THIS_MODULE;
-       jzgc->version = (enum jz_version)of_id->data;
+       jzgc->version = (enum jz_version)of_device_get_match_data(dev);
 
        jzgc->gc.set = ingenic_gpio_set;
        jzgc->gc.get = ingenic_gpio_get;
index 92c4fe7b26773c9e7bf6eb8278a263b9b6e596d6..16cfbe9e72fe2bcbeffe8398548384f477bbd0d1 100644 (file)
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/err.h>
+#include <linux/gpio/driver.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
 #include <asm/types.h>
 #include <loongson.h>
-#include <linux/gpio.h>
 
 #define STLS2F_N_GPIO          4
 #define STLS3A_N_GPIO          16
 #define LOONGSON_N_GPIO        STLS2F_N_GPIO
 #endif
 
+/*
+ * Offset into the register where we read lines, we write them from offset 0.
+ * This offset is the only thing that stand between us and using
+ * GPIO_GENERIC.
+ */
 #define LOONGSON_GPIO_IN_OFFSET        16
 
 static DEFINE_SPINLOCK(gpio_lock);
 
-static int loongson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+static int loongson_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
 {
-       u32 temp;
-       u32 mask;
+       u32 val;
 
        spin_lock(&gpio_lock);
-       mask = 1 << gpio;
-       temp = LOONGSON_GPIOIE;
-       temp |= mask;
-       LOONGSON_GPIOIE = temp;
+       val = LOONGSON_GPIODATA;
        spin_unlock(&gpio_lock);
 
-       return 0;
+       return !!(val & BIT(gpio + LOONGSON_GPIO_IN_OFFSET));
 }
 
-static int loongson_gpio_direction_output(struct gpio_chip *chip,
-               unsigned gpio, int level)
+static void loongson_gpio_set_value(struct gpio_chip *chip,
+               unsigned gpio, int value)
+{
+       u32 val;
+
+       spin_lock(&gpio_lock);
+       val = LOONGSON_GPIODATA;
+       if (value)
+               val |= BIT(gpio);
+       else
+               val &= ~BIT(gpio);
+       LOONGSON_GPIODATA = val;
+       spin_unlock(&gpio_lock);
+}
+
+static int loongson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
 {
        u32 temp;
-       u32 mask;
 
-       gpio_set_value(gpio, level);
        spin_lock(&gpio_lock);
-       mask = 1 << gpio;
        temp = LOONGSON_GPIOIE;
-       temp &= (~mask);
+       temp |= BIT(gpio);
        LOONGSON_GPIOIE = temp;
        spin_unlock(&gpio_lock);
 
        return 0;
 }
 
-static int loongson_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+static int loongson_gpio_direction_output(struct gpio_chip *chip,
+               unsigned gpio, int level)
 {
-       u32 val;
-       u32 mask;
+       u32 temp;
 
-       mask = 1 << (gpio + LOONGSON_GPIO_IN_OFFSET);
+       loongson_gpio_set_value(chip, gpio, level);
        spin_lock(&gpio_lock);
-       val = LOONGSON_GPIODATA;
+       temp = LOONGSON_GPIOIE;
+       temp &= ~BIT(gpio);
+       LOONGSON_GPIOIE = temp;
        spin_unlock(&gpio_lock);
 
-       return (val & mask) != 0;
+       return 0;
 }
 
-static void loongson_gpio_set_value(struct gpio_chip *chip,
-               unsigned gpio, int value)
+static int loongson_gpio_probe(struct platform_device *pdev)
 {
-       u32 val;
-       u32 mask;
-
-       mask = 1 << gpio;
-
-       spin_lock(&gpio_lock);
-       val = LOONGSON_GPIODATA;
-       if (value)
-               val |= mask;
-       else
-               val &= (~mask);
-       LOONGSON_GPIODATA = val;
-       spin_unlock(&gpio_lock);
+       struct gpio_chip *gc;
+       struct device *dev = &pdev->dev;
+
+       gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
+       if (!gc)
+               return -ENOMEM;
+
+       gc->label = "loongson-gpio-chip";
+       gc->base = 0;
+       gc->ngpio = LOONGSON_N_GPIO;
+       gc->get = loongson_gpio_get_value;
+       gc->set = loongson_gpio_set_value;
+       gc->direction_input = loongson_gpio_direction_input;
+       gc->direction_output = loongson_gpio_direction_output;
+
+       return gpiochip_add_data(gc, NULL);
 }
 
-static struct gpio_chip loongson_chip = {
-       .label                  = "Loongson-gpio-chip",
-       .direction_input        = loongson_gpio_direction_input,
-       .get                    = loongson_gpio_get_value,
-       .direction_output       = loongson_gpio_direction_output,
-       .set                    = loongson_gpio_set_value,
-       .base                   = 0,
-       .ngpio                  = LOONGSON_N_GPIO,
-       .can_sleep              = false,
+static struct platform_driver loongson_gpio_driver = {
+       .driver = {
+               .name = "loongson-gpio",
+       },
+       .probe = loongson_gpio_probe,
 };
 
 static int __init loongson_gpio_setup(void)
 {
-       return gpiochip_add_data(&loongson_chip, NULL);
+       struct platform_device *pdev;
+       int ret;
+
+       ret = platform_driver_register(&loongson_gpio_driver);
+       if (ret) {
+               pr_err("error registering loongson GPIO driver\n");
+               return ret;
+       }
+
+       pdev = platform_device_register_simple("loongson-gpio", -1, NULL, 0);
+       return PTR_ERR_OR_ZERO(pdev);
 }
 postcore_initcall(loongson_gpio_setup);
index 6dc6725403ecd70f2b3d36deefd48a75df475648..c3a3b9b7b5539712273a8a92d612365fe1c6449a 100644 (file)
@@ -12,7 +12,7 @@
 
 #include <linux/bitops.h>
 #include <linux/err.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/i2c.h>
 #include <linux/mfd/lp3943.h>
 #include <linux/module.h>
index df0ad2cef0d2bfc3b3d80bd9aed01f3482379ff3..801995dd9b2605908f3ee1ea9ffdb02583d42c2f 100644 (file)
@@ -14,7 +14,7 @@
  * Based on the TPS65218 driver
  */
 
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
index 92b3ae2a67357f7714faa224a10f86a440bd4257..aa74cc4d8b14f3ad9a80a63e51caeb74f39bbe91 100644 (file)
@@ -20,9 +20,8 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/errno.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/of.h>
-#include <linux/of_gpio.h>
 #include <linux/platform_device.h>
 #include <linux/module.h>
 
index 1e557b10d73ed3c66e8f6806994e144d19f257c2..b5b5e500e72cfa3a854fe33c5174890783bb7a5c 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/types.h>
 #include <linux/bitops.h>
 #include <linux/interrupt.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
 #include <linux/platform_device.h>
index 946d09195598f4dacde27162193e1ee99490481f..198a36b07773dcae0ed4b360faa1a0bd8ee7efe7 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
 #include <linux/spi/max7301.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/slab.h>
 
 /*
index 0f0df795626404a340d4191b03d01ba0ecbe43d6..18a5a58d634afdb32eda5c9d844034db22de78af 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/mutex.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/mc33880.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 
index 2fcad5b9cca51233287ad3b0bac6474147904dc9..d8d846d2189acd2f81f380ded58e3a5299ab38a2 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 
 #define GPIO_GROUP_NUM 2
 #define GPIO_NUM_PER_GROUP 8
index b3678bd1c120c8d18daff31f5489ba7909688dcb..e2bee27eb526d172be23be709a36be84604d7eac 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 
index b1cf76dd84bacb6310616226a3f39dd02d560be4..b0754fe69e772bf7f2e69fae68c5281fdbd02b5e 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/types.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/io.h>
index 76c2fe91a901dcd1f9b4154e3e31858a9f5e2a9a..d66b7a768ecd264d5872997e6acf8715344640e8 100644 (file)
@@ -1,15 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * GPIO Testing Device Driver
  *
  * Copyright (C) 2014  Kamlakant Patel <kamlakant.patel@broadcom.com>
  * Copyright (C) 2015-2016  Bamvor Jian Zhang <bamv2005@gmail.com>
  * Copyright (C) 2017 Bartosz Golaszewski <brgl@bgdev.pl>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
  */
 
 #include <linux/init.h>
index 6cb67595d15f63b3f046512a1f1b4ee5e7b04301..3b34dbecef994e12264b79acce9172f9549dca06 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/intel_msic.h>
 
index 45c65f805fd6ba5a3899b5c29a9651fa2d6dcc43..6e02148c208b2cc600d75263d1c87064db2ebc23 100644 (file)
@@ -36,7 +36,8 @@
 #include <linux/bitops.h>
 #include <linux/clk.h>
 #include <linux/err.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio/consumer.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/irq.h>
@@ -51,8 +52,6 @@
 #include <linux/regmap.h>
 #include <linux/slab.h>
 
-#include "gpiolib.h"
-
 /*
  * GPIO unit register offsets.
  */
@@ -608,19 +607,16 @@ static int mvebu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
        if (mvpwm->gpiod) {
                ret = -EBUSY;
        } else {
-               desc = gpio_to_desc(mvchip->chip.base + pwm->hwpwm);
-               if (!desc) {
-                       ret = -ENODEV;
+               desc = gpiochip_request_own_desc(&mvchip->chip,
+                                                pwm->hwpwm, "mvebu-pwm");
+               if (IS_ERR(desc)) {
+                       ret = PTR_ERR(desc);
                        goto out;
                }
 
-               ret = gpiod_request(desc, "mvebu-pwm");
-               if (ret)
-                       goto out;
-
                ret = gpiod_direction_output(desc, 0);
                if (ret) {
-                       gpiod_free(desc);
+                       gpiochip_free_own_desc(desc);
                        goto out;
                }
 
@@ -637,7 +633,7 @@ static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
        unsigned long flags;
 
        spin_lock_irqsave(&mvpwm->lock, flags);
-       gpiod_free(mvpwm->gpiod);
+       gpiochip_free_own_desc(mvpwm->gpiod);
        mvpwm->gpiod = NULL;
        spin_unlock_irqrestore(&mvpwm->lock, flags);
 }
index 5245a2fe62aeebe6fdd0d4f68ccaea2c22b6ddcc..2f2829966d4c49a8836a68a54634d034820aa681 100644 (file)
@@ -1,25 +1,13 @@
-/*
- * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * Based on code from Freescale Semiconductor,
- * Authors: Daniel Mack, Juergen Beisert.
- * Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
+// SPDX-License-Identifier: GPL-2.0+
+//
+// MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
+// Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+//
+// Based on code from Freescale Semiconductor,
+// Authors: Daniel Mack, Juergen Beisert.
+// Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+
+#include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -30,8 +18,6 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/gpio/driver.h>
-/* FIXME: for gpio_get_value() replace this with direct register read */
-#include <linux/gpio.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/bug.h>
@@ -62,6 +48,7 @@ struct mxc_gpio_hwdata {
 struct mxc_gpio_port {
        struct list_head node;
        void __iomem *base;
+       struct clk *clk;
        int irq;
        int irq_high;
        struct irq_domain *domain;
@@ -174,7 +161,6 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
        struct mxc_gpio_port *port = gc->private;
        u32 bit, val;
        u32 gpio_idx = d->hwirq;
-       u32 gpio = port->gc.base + gpio_idx;
        int edge;
        void __iomem *reg = port->base;
 
@@ -190,13 +176,13 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
                if (GPIO_EDGE_SEL >= 0) {
                        edge = GPIO_INT_BOTH_EDGES;
                } else {
-                       val = gpio_get_value(gpio);
+                       val = port->gc.get(&port->gc, gpio_idx);
                        if (val) {
                                edge = GPIO_INT_LOW_LEV;
-                               pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
+                               pr_debug("mxc: set GPIO %d to low trigger\n", gpio_idx);
                        } else {
                                edge = GPIO_INT_HIGH_LEV;
-                               pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
+                               pr_debug("mxc: set GPIO %d to high trigger\n", gpio_idx);
                        }
                        port->both_edges |= 1 << gpio_idx;
                }
@@ -437,6 +423,17 @@ static int mxc_gpio_probe(struct platform_device *pdev)
        if (port->irq < 0)
                return port->irq;
 
+       /* the controller clock is optional */
+       port->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(port->clk))
+               port->clk = NULL;
+
+       err = clk_prepare_enable(port->clk);
+       if (err) {
+               dev_err(&pdev->dev, "Unable to enable clock.\n");
+               return err;
+       }
+
        /* disable the interrupt and clear the status */
        writel(0, port->base + GPIO_IMR);
        writel(~0, port->base + GPIO_ISR);
@@ -505,6 +502,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
 out_irqdomain_remove:
        irq_domain_remove(port->domain);
 out_bgio:
+       clk_disable_unprepare(port->clk);
        dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
        return err;
 }
index 435def22445d9a64ba1b105a6d317f45b6258a55..e2831ee70cdc612e3a7fd3f8564bff486a2214b9 100644 (file)
@@ -1,24 +1,10 @@
-/*
- * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * Based on code from Freescale,
- * Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
+// Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+//
+// Based on code from Freescale,
+// Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
 
 #include <linux/err.h>
 #include <linux/init.h>
@@ -290,8 +276,6 @@ MODULE_DEVICE_TABLE(of, mxs_gpio_dt_ids);
 
 static int mxs_gpio_probe(struct platform_device *pdev)
 {
-       const struct of_device_id *of_id =
-                       of_match_device(mxs_gpio_dt_ids, &pdev->dev);
        struct device_node *np = pdev->dev.of_node;
        struct device_node *parent;
        static void __iomem *base;
@@ -306,7 +290,7 @@ static int mxs_gpio_probe(struct platform_device *pdev)
        port->id = of_alias_get_id(np, "gpio");
        if (port->id < 0)
                return port->id;
-       port->devid = (enum mxs_gpio_id) of_id->data;
+       port->devid = (enum mxs_gpio_id)of_device_get_match_data(&pdev->dev);
        port->dev = &pdev->dev;
        port->irq = platform_get_irq(pdev, 0);
        if (port->irq < 0)
index 96a8a8cb27298770c0de722749fac048b6c8829e..1b19c88ea7bb9e9fd4fbe161981b8c02153c97f0 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/platform_device.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/io.h>
 
 #include <asm/octeon/octeon.h>
index 35971a341c402e6fad3b7886b1aa497284b5df3f..d1afedf4dcbf0203005f1eb783a3468b0d77afe2 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/pm.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/bitops.h>
 #include <linux/platform_data/gpio-omap.h>
 
index 3d818195e351a7e6d16138bd38b1d81abd2ac0ba..05b0cd5dcf11904081f36155bbd0c0abb7ca4efd 100644 (file)
@@ -18,7 +18,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/mfd/palmas.h>
@@ -159,13 +159,9 @@ static int palmas_gpio_probe(struct platform_device *pdev)
        struct palmas_platform_data *palmas_pdata;
        struct palmas_gpio *palmas_gpio;
        int ret;
-       const struct of_device_id *match;
        const struct palmas_device_data *dev_data;
 
-       match = of_match_device(of_palmas_gpio_match, &pdev->dev);
-       if (!match)
-               return -ENODEV;
-       dev_data = match->data;
+       dev_data = of_device_get_match_data(&pdev->dev);
        if (!dev_data)
                dev_data = &palmas_dev_data;
 
index d2ead4b1cf610745350171dff45c62542f1b7ff2..c55ad157e820028ecd072b8bb36f8fd7cb1faa2a 100644 (file)
@@ -12,7 +12,7 @@
  */
 
 #include <linux/acpi.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
 
 #include <asm/unaligned.h>
 
-#define PCA953X_INPUT          0
-#define PCA953X_OUTPUT         1
-#define PCA953X_INVERT         2
-#define PCA953X_DIRECTION      3
+#define PCA953X_INPUT          0x00
+#define PCA953X_OUTPUT         0x01
+#define PCA953X_INVERT         0x02
+#define PCA953X_DIRECTION      0x03
 
 #define REG_ADDR_AI            0x80
 
-#define PCA957X_IN             0
-#define PCA957X_INVRT          1
-#define PCA957X_BKEN           2
-#define PCA957X_PUPD           3
-#define PCA957X_CFG            4
-#define PCA957X_OUT            5
-#define PCA957X_MSK            6
-#define PCA957X_INTS           7
-
-#define PCAL953X_IN_LATCH      34
-#define PCAL953X_INT_MASK      37
-#define PCAL953X_INT_STAT      38
+#define PCA957X_IN             0x00
+#define PCA957X_INVRT          0x01
+#define PCA957X_BKEN           0x02
+#define PCA957X_PUPD           0x03
+#define PCA957X_CFG            0x04
+#define PCA957X_OUT            0x05
+#define PCA957X_MSK            0x06
+#define PCA957X_INTS           0x07
+
+#define PCAL953X_OUT_STRENGTH  0x20
+#define PCAL953X_IN_LATCH      0x22
+#define PCAL953X_PULL_EN       0x23
+#define PCAL953X_PULL_SEL      0x24
+#define PCAL953X_INT_MASK      0x25
+#define PCAL953X_INT_STAT      0x26
+#define PCAL953X_OUT_CONF      0x27
+
+#define PCAL6524_INT_EDGE      0x28
+#define PCAL6524_INT_CLR       0x2a
+#define PCAL6524_IN_STATUS     0x2b
+#define PCAL6524_OUT_INDCONF   0x2c
+#define PCAL6524_DEBOUNCE      0x2d
 
 #define PCA_GPIO_MASK          0x00FF
+
+#define PCAL_GPIO_MASK         0x1f
+#define PCAL_PINCTRL_MASK      0xe0
+
 #define PCA_INT                        0x0100
 #define PCA_PCAL               0x0200
+#define PCA_LATCH_INT (PCA_PCAL | PCA_INT)
 #define PCA953X_TYPE           0x1000
 #define PCA957X_TYPE           0x2000
 #define PCA_TYPE_MASK          0xF000
@@ -207,9 +222,11 @@ static int pca957x_write_regs_16(struct pca953x_chip *chip, int reg, u8 *val)
 static int pca953x_write_regs_24(struct pca953x_chip *chip, int reg, u8 *val)
 {
        int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ);
+       int addr = (reg & PCAL_GPIO_MASK) << bank_shift;
+       int pinctrl = (reg & PCAL_PINCTRL_MASK) << 1;
 
        return i2c_smbus_write_i2c_block_data(chip->client,
-                                             (reg << bank_shift) | REG_ADDR_AI,
+                                             pinctrl | addr | REG_ADDR_AI,
                                              NBANK(chip), val);
 }
 
@@ -249,9 +266,11 @@ static int pca953x_read_regs_16(struct pca953x_chip *chip, int reg, u8 *val)
 static int pca953x_read_regs_24(struct pca953x_chip *chip, int reg, u8 *val)
 {
        int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ);
+       int addr = (reg & PCAL_GPIO_MASK) << bank_shift;
+       int pinctrl = (reg & PCAL_PINCTRL_MASK) << 1;
 
        return i2c_smbus_read_i2c_block_data(chip->client,
-                                            (reg << bank_shift) | REG_ADDR_AI,
+                                            pinctrl | addr | REG_ADDR_AI,
                                             NBANK(chip), val);
 }
 
@@ -522,6 +541,15 @@ static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
        return 0;
 }
 
+static void pca953x_irq_shutdown(struct irq_data *d)
+{
+       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+       u8 mask = 1 << (d->hwirq % BANK_SZ);
+
+       chip->irq_trig_raise[d->hwirq / BANK_SZ] &= ~mask;
+       chip->irq_trig_fall[d->hwirq / BANK_SZ] &= ~mask;
+}
+
 static struct irq_chip pca953x_irq_chip = {
        .name                   = "pca953x",
        .irq_mask               = pca953x_irq_mask,
@@ -529,6 +557,7 @@ static struct irq_chip pca953x_irq_chip = {
        .irq_bus_lock           = pca953x_irq_bus_lock,
        .irq_bus_sync_unlock    = pca953x_irq_bus_sync_unlock,
        .irq_set_type           = pca953x_irq_set_type,
+       .irq_shutdown           = pca953x_irq_shutdown,
 };
 
 static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending)
@@ -810,13 +839,11 @@ static int pca953x_probe(struct i2c_client *client,
                chip->driver_data = i2c_id->driver_data;
        } else {
                const struct acpi_device_id *acpi_id;
-               const struct of_device_id *match;
+               struct device *dev = &client->dev;
 
-               match = of_match_device(pca953x_dt_ids, &client->dev);
-               if (match) {
-                       chip->driver_data = (int)(uintptr_t)match->data;
-               } else {
-                       acpi_id = acpi_match_device(pca953x_acpi_ids, &client->dev);
+               chip->driver_data = (uintptr_t)of_device_get_match_data(dev);
+               if (!chip->driver_data) {
+                       acpi_id = acpi_match_device(pca953x_acpi_ids, dev);
                        if (!acpi_id) {
                                ret = -ENODEV;
                                goto err_exit;
@@ -936,8 +963,8 @@ static const struct of_device_id pca953x_dt_ids[] = {
        { .compatible = "nxp,pca9575", .data = OF_957X(16, PCA_INT), },
        { .compatible = "nxp,pca9698", .data = OF_953X(40, 0), },
 
-       { .compatible = "nxp,pcal6524", .data = OF_953X(24, PCA_INT), },
-       { .compatible = "nxp,pcal9555a", .data = OF_953X(16, PCA_INT), },
+       { .compatible = "nxp,pcal6524", .data = OF_953X(24, PCA_LATCH_INT), },
+       { .compatible = "nxp,pcal9555a", .data = OF_953X(16, PCA_LATCH_INT), },
 
        { .compatible = "maxim,max7310", .data = OF_953X( 8, 0), },
        { .compatible = "maxim,max7312", .data = OF_953X(16, PCA_INT), },
index 38fbb420c6cd213325b0c2cdbf6795e100fabf30..adf72dda25a2b543e32e6e2aee1d2f4d1b82d352 100644 (file)
@@ -18,7 +18,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/i2c.h>
 #include <linux/platform_data/pcf857x.h>
 #include <linux/interrupt.h>
index 68c6d0c5a6d19362d6f5dfb9979080415acf8c42..ffce0ab912ed1df6c48a288649f5d0f74a87bc8c 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/slab.h>
index b70974cb9ef178b5ca56b961ec0dc3e80d9eb5b5..2afd9de84a0d051fed6ca12e7c97e0e266e314fd 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/irq.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/bitops.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/device.h>
 #include <linux/amba/bus.h>
 #include <linux/slab.h>
index 66d68d99116255afd9bf46f90d4eab995157b0ab..29e044ff4b17d0c607a6fbe1388aac18d527b5a6 100644 (file)
@@ -178,6 +178,14 @@ static int sprd_pmic_eic_irq_set_type(struct irq_data *data,
        case IRQ_TYPE_LEVEL_LOW:
                pmic_eic->reg[REG_IEV] = 0;
                break;
+       case IRQ_TYPE_EDGE_RISING:
+       case IRQ_TYPE_EDGE_FALLING:
+       case IRQ_TYPE_EDGE_BOTH:
+               /*
+                * Will set the trigger level according to current EIC level
+                * in irq_bus_sync_unlock() interface, so here nothing to do.
+                */
+               break;
        default:
                return -ENOTSUPP;
        }
@@ -197,11 +205,22 @@ static void sprd_pmic_eic_bus_sync_unlock(struct irq_data *data)
 {
        struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
        struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
+       u32 trigger = irqd_get_trigger_type(data);
        u32 offset = irqd_to_hwirq(data);
+       int state;
 
        /* Set irq type */
-       sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV,
-                            pmic_eic->reg[REG_IEV]);
+       if (trigger & IRQ_TYPE_EDGE_BOTH) {
+               state = sprd_pmic_eic_get(chip, offset);
+               if (state)
+                       sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV, 0);
+               else
+                       sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV, 1);
+       } else {
+               sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV,
+                                    pmic_eic->reg[REG_IEV]);
+       }
+
        /* Set irq unmask */
        sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IE,
                             pmic_eic->reg[REG_IE]);
@@ -212,6 +231,35 @@ static void sprd_pmic_eic_bus_sync_unlock(struct irq_data *data)
        mutex_unlock(&pmic_eic->buslock);
 }
 
+static void sprd_pmic_eic_toggle_trigger(struct gpio_chip *chip,
+                                        unsigned int irq, unsigned int offset)
+{
+       u32 trigger = irq_get_trigger_type(irq);
+       int state, post_state;
+
+       if (!(trigger & IRQ_TYPE_EDGE_BOTH))
+               return;
+
+       state = sprd_pmic_eic_get(chip, offset);
+retry:
+       if (state)
+               sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV, 0);
+       else
+               sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV, 1);
+
+       post_state = sprd_pmic_eic_get(chip, offset);
+       if (state != post_state) {
+               dev_warn(chip->parent, "PMIC EIC level was changed.\n");
+               state = post_state;
+               goto retry;
+       }
+
+       /* Set irq unmask */
+       sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IE, 1);
+       /* Generate trigger start pulse for debounce EIC */
+       sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_TRIG, 1);
+}
+
 static irqreturn_t sprd_pmic_eic_irq_handler(int irq, void *data)
 {
        struct sprd_pmic_eic *pmic_eic = data;
@@ -233,6 +281,12 @@ static irqreturn_t sprd_pmic_eic_irq_handler(int irq, void *data)
 
                girq = irq_find_mapping(chip->irq.domain, n);
                handle_nested_irq(girq);
+
+               /*
+                * The PMIC EIC can only support level trigger, so we can
+                * toggle the level trigger to emulate the edge trigger.
+                */
+               sprd_pmic_eic_toggle_trigger(chip, girq, n);
        }
 
        return IRQ_HANDLED;
index f480fb896963a784ec6bb9b1adf545095746b9ad..1e66f808051cfc4e255be01f326d86d017b170f2 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/err.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/gpio-pxa.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -579,15 +579,9 @@ static int pxa_gpio_probe_dt(struct platform_device *pdev,
                             struct pxa_gpio_chip *pchip)
 {
        int nr_gpios;
-       const struct of_device_id *of_id =
-                               of_match_device(pxa_gpio_dt_ids, &pdev->dev);
        const struct pxa_gpio_id *gpio_id;
 
-       if (!of_id || !of_id->data) {
-               dev_err(&pdev->dev, "Failed to find gpio controller\n");
-               return -EFAULT;
-       }
-       gpio_id = of_id->data;
+       gpio_id = of_device_get_match_data(&pdev->dev);
        gpio_type = gpio_id->type;
 
        nr_gpios = gpio_id->gpio_nums;
index f8d7d1cd8488ebe0a905b15ce69870003018ac06..8d6a5a7e612d0089a2af2ea8a3c7e675da437c51 100644 (file)
@@ -363,13 +363,15 @@ static struct irq_chip stmpe_gpio_irq_chip = {
        .irq_set_type           = stmpe_gpio_irq_set_type,
 };
 
+#define MAX_GPIOS 24
+
 static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
 {
        struct stmpe_gpio *stmpe_gpio = dev;
        struct stmpe *stmpe = stmpe_gpio->stmpe;
        u8 statmsbreg;
        int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8);
-       u8 status[num_banks];
+       u8 status[DIV_ROUND_UP(MAX_GPIOS, 8)];
        int ret;
        int i;
 
@@ -434,6 +436,11 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
        struct stmpe_gpio *stmpe_gpio;
        int ret, irq;
 
+       if (stmpe->num_gpios > MAX_GPIOS) {
+               dev_err(&pdev->dev, "Need to increase maximum GPIO number\n");
+               return -EINVAL;
+       }
+
        stmpe_gpio = kzalloc(sizeof(*stmpe_gpio), GFP_KERNEL);
        if (!stmpe_gpio)
                return -ENOMEM;
index 537cec7583fcac038865c38c8731182287fcb4b1..8b0a69c5ba88632da2d79281aec0b4e8f8313b65 100644 (file)
@@ -182,20 +182,15 @@ MODULE_DEVICE_TABLE(of, syscon_gpio_ids);
 static int syscon_gpio_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       const struct of_device_id *of_id;
        struct syscon_gpio_priv *priv;
        struct device_node *np = dev->of_node;
        int ret;
 
-       of_id = of_match_device(syscon_gpio_ids, dev);
-       if (!of_id)
-               return -ENODEV;
-
        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
-       priv->data = of_id->data;
+       priv->data = of_device_get_match_data(dev);
 
        if (priv->data->compatible) {
                priv->syscon = syscon_regmap_lookup_by_compatible(
@@ -205,6 +200,8 @@ static int syscon_gpio_probe(struct platform_device *pdev)
        } else {
                priv->syscon =
                        syscon_regmap_lookup_by_phandle(np, "gpio,syscon-dev");
+               if (IS_ERR(priv->syscon) && np->parent)
+                       priv->syscon = syscon_node_to_regmap(np->parent);
                if (IS_ERR(priv->syscon))
                        return PTR_ERR(priv->syscon);
 
index 5bd21725e6043db85583b6dbf5344dcdd12810c8..1da8d05863295b06f15e1d3b99255b867575ec1a 100644 (file)
@@ -128,15 +128,10 @@ MODULE_DEVICE_TABLE(of, ts4900_gpio_of_match_table);
 static int ts4900_gpio_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
-       const struct of_device_id *match;
        struct ts4900_gpio_priv *priv;
        u32 ngpio;
        int ret;
 
-       match = of_match_device(ts4900_gpio_of_match_table, &client->dev);
-       if (!match)
-               return -EINVAL;
-
        if (of_property_read_u32(client->dev.of_node, "ngpios", &ngpio))
                ngpio = DEFAULT_PIN_NUMBER;
 
@@ -148,7 +143,7 @@ static int ts4900_gpio_probe(struct i2c_client *client,
        priv->gpio_chip.label = "ts4900-gpio";
        priv->gpio_chip.ngpio = ngpio;
        priv->gpio_chip.parent = &client->dev;
-       priv->input_bit = (uintptr_t)match->data;
+       priv->input_bit = (uintptr_t)of_device_get_match_data(&client->dev);
 
        priv->regmap = devm_regmap_init_i2c(client, &ts4900_regmap_config);
        if (IS_ERR(priv->regmap)) {
index 4610cc2938ad01710250da1e52b992db43332fd4..d4ad6d0e02a25be60755b39b600c16cbbcd43981 100644 (file)
@@ -254,8 +254,6 @@ static struct irq_chip vf610_gpio_irq_chip = {
 
 static int vf610_gpio_probe(struct platform_device *pdev)
 {
-       const struct of_device_id *of_id = of_match_device(vf610_gpio_dt_ids,
-                                                          &pdev->dev);
        struct device *dev = &pdev->dev;
        struct device_node *np = dev->of_node;
        struct vf610_gpio_port *port;
@@ -267,7 +265,7 @@ static int vf610_gpio_probe(struct platform_device *pdev)
        if (!port)
                return -ENOMEM;
 
-       port->sdata = of_id->data;
+       port->sdata = of_device_get_match_data(dev);
        iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        port->base = devm_ioremap_resource(dev, iores);
        if (IS_ERR(port->base))
index e74bd43a69743af3d27f77eb7f419e6bc0b6e9a5..8e4275eaa7d73c10194e778835c7fc8f5c10d556 100644 (file)
@@ -322,14 +322,7 @@ static int xlp_gpio_probe(struct platform_device *pdev)
                return irq;
 
        if (pdev->dev.of_node) {
-               const struct of_device_id *of_id;
-
-               of_id = of_match_device(xlp_gpio_of_ids, &pdev->dev);
-               if (!of_id) {
-                       dev_err(&pdev->dev, "Unable to match OF ID\n");
-                       return -ENODEV;
-               }
-               soc_type = (uintptr_t) of_id->data;
+               soc_type = (uintptr_t)of_device_get_match_data(&pdev->dev);
        } else {
                const struct acpi_device_id *acpi_id;
 
index 8d4c8e99b251968a4ece65012a97b72ac0ec6e40..8711a790756894a4d42a90d6190b7287e45411c5 100644 (file)
@@ -39,6 +39,7 @@
 #define XRA_REIR  0x10 /* Input Rising Edge Interrupt Enable */
 #define XRA_FEIR  0x12 /* Input Falling Edge Interrupt Enable */
 #define XRA_IFR   0x14 /* Input Filter Enable/Disable */
+#define XRA_LAST  0x15 /* Bounds */
 
 struct xra1403 {
        struct gpio_chip  chip;
@@ -50,7 +51,7 @@ static const struct regmap_config xra1403_regmap_cfg = {
                .pad_bits = 1,
                .val_bits = 8,
 
-               .max_register = XRA_IFR | 0x01,
+               .max_register = XRA_LAST,
 };
 
 static unsigned int to_reg(unsigned int reg, unsigned int offset)
@@ -126,21 +127,16 @@ static void xra1403_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 {
        int reg;
        struct xra1403 *xra = gpiochip_get_data(chip);
-       int *value;
+       int value[XRA_LAST];
        int i;
        unsigned int gcr;
        unsigned int gsr;
 
-       value = kmalloc_array(xra1403_regmap_cfg.max_register, sizeof(*value),
-                               GFP_KERNEL);
-       if (!value)
-               return;
-
        seq_puts(s, "xra reg:");
-       for (reg = 0; reg <= xra1403_regmap_cfg.max_register; reg++)
+       for (reg = 0; reg <= XRA_LAST; reg++)
                seq_printf(s, " %2.2x", reg);
        seq_puts(s, "\n  value:");
-       for (reg = 0; reg < xra1403_regmap_cfg.max_register; reg++) {
+       for (reg = 0; reg < XRA_LAST; reg++) {
                regmap_read(xra->regmap, reg, &value[reg]);
                seq_printf(s, " %2.2x", value[reg]);
        }
@@ -159,7 +155,6 @@ static void xra1403_dbg_show(struct seq_file *s, struct gpio_chip *chip)
                           (gcr & BIT(i)) ? "in" : "out",
                           (gsr & BIT(i)) ? "hi" : "lo");
        }
-       kfree(value);
 }
 #else
 #define xra1403_dbg_show NULL
index 75ee877e5cd5f53815c79d46fe6c69dba6599f3e..3f5fcdd5a4291dd41c35e5032122a4b39873686d 100644 (file)
@@ -665,10 +665,8 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio)
 
 static int __maybe_unused zynq_gpio_suspend(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       int irq = platform_get_irq(pdev, 0);
-       struct irq_data *data = irq_get_irq_data(irq);
-       struct zynq_gpio *gpio = platform_get_drvdata(pdev);
+       struct zynq_gpio *gpio = dev_get_drvdata(dev);
+       struct irq_data *data = irq_get_irq_data(gpio->irq);
 
        if (!irqd_is_wakeup_set(data)) {
                zynq_gpio_save_context(gpio);
@@ -680,10 +678,8 @@ static int __maybe_unused zynq_gpio_suspend(struct device *dev)
 
 static int __maybe_unused zynq_gpio_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       int irq = platform_get_irq(pdev, 0);
-       struct irq_data *data = irq_get_irq_data(irq);
-       struct zynq_gpio *gpio = platform_get_drvdata(pdev);
+       struct zynq_gpio *gpio = dev_get_drvdata(dev);
+       struct irq_data *data = irq_get_irq_data(gpio->irq);
        int ret;
 
        if (!irqd_is_wakeup_set(data)) {
@@ -831,7 +827,7 @@ static int zynq_gpio_probe(struct platform_device *pdev)
        chip->free = zynq_gpio_free;
        chip->direction_input = zynq_gpio_dir_in;
        chip->direction_output = zynq_gpio_dir_out;
-       chip->base = -1;
+       chip->base = of_alias_get_id(pdev->dev.of_node, "gpio");
        chip->ngpio = gpio->p_data->ngpio;
 
        /* Retrieve GPIO clock */
index 586d15137c03b85254c6b030b985abdaacdce537..28d968088131f433901d3b5b4bee4da8a9002250 100644 (file)
@@ -210,11 +210,8 @@ static struct gpio_desc *of_find_regulator_gpio(struct device *dev, const char *
        if (!con_id)
                return ERR_PTR(-ENOENT);
 
-       for (i = 0; i < ARRAY_SIZE(whitelist); i++)
-               if (!strcmp(con_id, whitelist[i]))
-                       break;
-
-       if (i == ARRAY_SIZE(whitelist))
+       i = match_string(whitelist, ARRAY_SIZE(whitelist), con_id);
+       if (i < 0)
                return ERR_PTR(-ENOENT);
 
        desc = of_get_named_gpiod_flags(np, con_id, 0, of_flags);
index 5dfd3c17fffc90fe999be8091ec59a2bec88185a..e11a3bb0382090b70cd80ceeb8194d03ca3106f1 100644 (file)
@@ -61,6 +61,11 @@ static struct bus_type gpio_bus_type = {
        .name = "gpio",
 };
 
+/*
+ * Number of GPIOs to use for the fast path in set array
+ */
+#define FASTPATH_NGPIO CONFIG_GPIOLIB_FASTPATH_LIMIT
+
 /* gpio_lock prevents conflicts during gpio_desc[] table updates.
  * While any GPIO is requested, its gpio_chip is not removable;
  * each GPIO's "requested" flag serves as a lock and refcount.
@@ -71,6 +76,9 @@ static DEFINE_MUTEX(gpio_lookup_lock);
 static LIST_HEAD(gpio_lookup_list);
 LIST_HEAD(gpio_devices);
 
+static DEFINE_MUTEX(gpio_machine_hogs_mutex);
+static LIST_HEAD(gpio_machine_hogs);
+
 static void gpiochip_free_hogs(struct gpio_chip *chip);
 static int gpiochip_add_irqchip(struct gpio_chip *gpiochip,
                                struct lock_class_key *lock_key,
@@ -450,12 +458,11 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd,
                        vals[i] = !!ghd.values[i];
 
                /* Reuse the array setting function */
-               gpiod_set_array_value_complex(false,
+               return gpiod_set_array_value_complex(false,
                                              true,
                                              lh->numdescs,
                                              lh->descs,
                                              vals);
-               return 0;
        }
        return -EINVAL;
 }
@@ -1172,6 +1179,41 @@ err_remove_device:
        return status;
 }
 
+static void gpiochip_machine_hog(struct gpio_chip *chip, struct gpiod_hog *hog)
+{
+       struct gpio_desc *desc;
+       int rv;
+
+       desc = gpiochip_get_desc(chip, hog->chip_hwnum);
+       if (IS_ERR(desc)) {
+               pr_err("%s: unable to get GPIO desc: %ld\n",
+                      __func__, PTR_ERR(desc));
+               return;
+       }
+
+       if (test_bit(FLAG_IS_HOGGED, &desc->flags))
+               return;
+
+       rv = gpiod_hog(desc, hog->line_name, hog->lflags, hog->dflags);
+       if (rv)
+               pr_err("%s: unable to hog GPIO line (%s:%u): %d\n",
+                      __func__, chip->label, hog->chip_hwnum, rv);
+}
+
+static void machine_gpiochip_add(struct gpio_chip *chip)
+{
+       struct gpiod_hog *hog;
+
+       mutex_lock(&gpio_machine_hogs_mutex);
+
+       list_for_each_entry(hog, &gpio_machine_hogs, list) {
+               if (!strcmp(chip->label, hog->chip_label))
+                       gpiochip_machine_hog(chip, hog);
+       }
+
+       mutex_unlock(&gpio_machine_hogs_mutex);
+}
+
 static void gpiochip_setup_devs(void)
 {
        struct gpio_device *gdev;
@@ -1244,6 +1286,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
                goto err_free_descs;
        }
 
+       if (chip->ngpio > FASTPATH_NGPIO)
+               chip_warn(chip, "line cnt %u is greater than fast path cnt %u\n",
+               chip->ngpio, FASTPATH_NGPIO);
+
        gdev->label = kstrdup_const(chip->label ?: "unknown", GFP_KERNEL);
        if (!gdev->label) {
                status = -ENOMEM;
@@ -1327,6 +1373,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
 
        acpi_gpiochip_add(chip);
 
+       machine_gpiochip_add(chip);
+
        /*
         * By first adding the chardev, and then adding the device,
         * we get a device node entry in sysfs under
@@ -2729,16 +2777,28 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep,
 
        while (i < array_size) {
                struct gpio_chip *chip = desc_array[i]->gdev->chip;
-               unsigned long mask[BITS_TO_LONGS(chip->ngpio)];
-               unsigned long bits[BITS_TO_LONGS(chip->ngpio)];
+               unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)];
+               unsigned long *mask, *bits;
                int first, j, ret;
 
+               if (likely(chip->ngpio <= FASTPATH_NGPIO)) {
+                       mask = fastpath;
+               } else {
+                       mask = kmalloc_array(2 * BITS_TO_LONGS(chip->ngpio),
+                                          sizeof(*mask),
+                                          can_sleep ? GFP_KERNEL : GFP_ATOMIC);
+                       if (!mask)
+                               return -ENOMEM;
+               }
+
+               bits = mask + BITS_TO_LONGS(chip->ngpio);
+               bitmap_zero(mask, chip->ngpio);
+
                if (!can_sleep)
                        WARN_ON(chip->can_sleep);
 
                /* collect all inputs belonging to the same chip */
                first = i;
-               memset(mask, 0, sizeof(mask));
                do {
                        const struct gpio_desc *desc = desc_array[i];
                        int hwgpio = gpio_chip_hwgpio(desc);
@@ -2749,8 +2809,11 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep,
                         (desc_array[i]->gdev->chip == chip));
 
                ret = gpio_chip_get_multiple(chip, mask, bits);
-               if (ret)
+               if (ret) {
+                       if (mask != fastpath)
+                               kfree(mask);
                        return ret;
+               }
 
                for (j = first; j < i; j++) {
                        const struct gpio_desc *desc = desc_array[j];
@@ -2762,6 +2825,9 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep,
                        value_array[j] = value;
                        trace_gpio_value(desc_to_gpio(desc), 1, value);
                }
+
+               if (mask != fastpath)
+                       kfree(mask);
        }
        return 0;
 }
@@ -2945,7 +3011,7 @@ static void gpio_chip_set_multiple(struct gpio_chip *chip,
        }
 }
 
-void gpiod_set_array_value_complex(bool raw, bool can_sleep,
+int gpiod_set_array_value_complex(bool raw, bool can_sleep,
                                   unsigned int array_size,
                                   struct gpio_desc **desc_array,
                                   int *value_array)
@@ -2954,14 +3020,26 @@ void gpiod_set_array_value_complex(bool raw, bool can_sleep,
 
        while (i < array_size) {
                struct gpio_chip *chip = desc_array[i]->gdev->chip;
-               unsigned long mask[BITS_TO_LONGS(chip->ngpio)];
-               unsigned long bits[BITS_TO_LONGS(chip->ngpio)];
+               unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)];
+               unsigned long *mask, *bits;
                int count = 0;
 
+               if (likely(chip->ngpio <= FASTPATH_NGPIO)) {
+                       mask = fastpath;
+               } else {
+                       mask = kmalloc_array(2 * BITS_TO_LONGS(chip->ngpio),
+                                          sizeof(*mask),
+                                          can_sleep ? GFP_KERNEL : GFP_ATOMIC);
+                       if (!mask)
+                               return -ENOMEM;
+               }
+
+               bits = mask + BITS_TO_LONGS(chip->ngpio);
+               bitmap_zero(mask, chip->ngpio);
+
                if (!can_sleep)
                        WARN_ON(chip->can_sleep);
 
-               memset(mask, 0, sizeof(mask));
                do {
                        struct gpio_desc *desc = desc_array[i];
                        int hwgpio = gpio_chip_hwgpio(desc);
@@ -2992,7 +3070,11 @@ void gpiod_set_array_value_complex(bool raw, bool can_sleep,
                /* push collected bits to outputs */
                if (count != 0)
                        gpio_chip_set_multiple(chip, mask, bits);
+
+               if (mask != fastpath)
+                       kfree(mask);
        }
+       return 0;
 }
 
 /**
@@ -3067,13 +3149,13 @@ EXPORT_SYMBOL_GPL(gpiod_set_value);
  * This function should be called from contexts where we cannot sleep, and will
  * complain if the GPIO chip functions potentially sleep.
  */
-void gpiod_set_raw_array_value(unsigned int array_size,
+int gpiod_set_raw_array_value(unsigned int array_size,
                         struct gpio_desc **desc_array, int *value_array)
 {
        if (!desc_array)
-               return;
-       gpiod_set_array_value_complex(true, false, array_size, desc_array,
-                                     value_array);
+               return -EINVAL;
+       return gpiod_set_array_value_complex(true, false, array_size,
+                                       desc_array, value_array);
 }
 EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value);
 
@@ -3393,14 +3475,14 @@ EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep);
  *
  * This function is to be called from contexts that can sleep.
  */
-void gpiod_set_raw_array_value_cansleep(unsigned int array_size,
+int gpiod_set_raw_array_value_cansleep(unsigned int array_size,
                                        struct gpio_desc **desc_array,
                                        int *value_array)
 {
        might_sleep_if(extra_checks);
        if (!desc_array)
-               return;
-       gpiod_set_array_value_complex(true, true, array_size, desc_array,
+               return -EINVAL;
+       return gpiod_set_array_value_complex(true, true, array_size, desc_array,
                                      value_array);
 }
 EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value_cansleep);
@@ -3473,6 +3555,33 @@ void gpiod_remove_lookup_table(struct gpiod_lookup_table *table)
 }
 EXPORT_SYMBOL_GPL(gpiod_remove_lookup_table);
 
+/**
+ * gpiod_add_hogs() - register a set of GPIO hogs from machine code
+ * @hogs: table of gpio hog entries with a zeroed sentinel at the end
+ */
+void gpiod_add_hogs(struct gpiod_hog *hogs)
+{
+       struct gpio_chip *chip;
+       struct gpiod_hog *hog;
+
+       mutex_lock(&gpio_machine_hogs_mutex);
+
+       for (hog = &hogs[0]; hog->chip_label; hog++) {
+               list_add_tail(&hog->list, &gpio_machine_hogs);
+
+               /*
+                * The chip may have been registered earlier, so check if it
+                * exists and, if so, try to hog the line now.
+                */
+               chip = find_chip_by_name(hog->chip_label);
+               if (chip)
+                       gpiochip_machine_hog(chip, hog);
+       }
+
+       mutex_unlock(&gpio_machine_hogs_mutex);
+}
+EXPORT_SYMBOL_GPL(gpiod_add_hogs);
+
 static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev)
 {
        const char *dev_id = dev ? dev_name(dev) : NULL;
index ad456b6f9d8b5e3ea9859e8cef73eacee431705b..1a8e20363861b523cc5aad9bf4b7c3d82f64302b 100644 (file)
@@ -188,7 +188,7 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep,
                                  unsigned int array_size,
                                  struct gpio_desc **desc_array,
                                  int *value_array);
-void gpiod_set_array_value_complex(bool raw, bool can_sleep,
+int gpiod_set_array_value_complex(bool raw, bool can_sleep,
                                   unsigned int array_size,
                                   struct gpio_desc **desc_array,
                                   int *value_array);
index 90e35dec8648f3235c41a0b380c16e686eb53fcc..5bddb84cfc1f477b8b0c19bce799b0176731d5f5 100644 (file)
@@ -233,7 +233,8 @@ static int intel_quark_gpio_setup(struct pci_dev *pdev, struct mfd_cell *cell)
        pdata->properties->idx          = 0;
        pdata->properties->ngpio        = INTEL_QUARK_MFD_NGPIO;
        pdata->properties->gpio_base    = INTEL_QUARK_MFD_GPIO_BASE;
-       pdata->properties->irq          = pdev->irq;
+       pdata->properties->irq[0]       = pdev->irq;
+       pdata->properties->has_irq      = true;
        pdata->properties->irq_shared   = true;
 
        cell->platform_data = pdata;
index dbd06596329661dee0a84170c0bdf2fc4b7d853a..243112c7fa7d091f182c249db3b42a8feafbd545 100644 (file)
@@ -116,7 +116,7 @@ int gpiod_get_raw_array_value(unsigned int array_size,
                              struct gpio_desc **desc_array,
                              int *value_array);
 void gpiod_set_raw_value(struct gpio_desc *desc, int value);
-void gpiod_set_raw_array_value(unsigned int array_size,
+int gpiod_set_raw_array_value(unsigned int array_size,
                               struct gpio_desc **desc_array,
                               int *value_array);
 
@@ -134,7 +134,7 @@ int gpiod_get_raw_array_value_cansleep(unsigned int array_size,
                                       struct gpio_desc **desc_array,
                                       int *value_array);
 void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value);
-void gpiod_set_raw_array_value_cansleep(unsigned int array_size,
+int gpiod_set_raw_array_value_cansleep(unsigned int array_size,
                                        struct gpio_desc **desc_array,
                                        int *value_array);
 
@@ -369,12 +369,13 @@ static inline void gpiod_set_raw_value(struct gpio_desc *desc, int value)
        /* GPIO can never have been requested */
        WARN_ON(1);
 }
-static inline void gpiod_set_raw_array_value(unsigned int array_size,
+static inline int gpiod_set_raw_array_value(unsigned int array_size,
                                             struct gpio_desc **desc_array,
                                             int *value_array)
 {
        /* GPIO can never have been requested */
        WARN_ON(1);
+       return 0;
 }
 
 static inline int gpiod_get_value_cansleep(const struct gpio_desc *desc)
@@ -423,12 +424,13 @@ static inline void gpiod_set_raw_value_cansleep(struct gpio_desc *desc,
        /* GPIO can never have been requested */
        WARN_ON(1);
 }
-static inline void gpiod_set_raw_array_value_cansleep(unsigned int array_size,
+static inline int gpiod_set_raw_array_value_cansleep(unsigned int array_size,
                                                struct gpio_desc **desc_array,
                                                int *value_array)
 {
        /* GPIO can never have been requested */
        WARN_ON(1);
+       return 0;
 }
 
 static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
index b2f2dc638463ce9da4c0fc0feaf8f391d11927d3..daa44eac9241b008a3848ad76ef6b73dbf6495d0 100644 (file)
@@ -39,6 +39,23 @@ struct gpiod_lookup_table {
        struct gpiod_lookup table[];
 };
 
+/**
+ * struct gpiod_hog - GPIO line hog table
+ * @chip_label: name of the chip the GPIO belongs to
+ * @chip_hwnum: hardware number (i.e. relative to the chip) of the GPIO
+ * @line_name: consumer name for the hogged line
+ * @lflags: mask of GPIO lookup flags
+ * @dflags: GPIO flags used to specify the direction and value
+ */
+struct gpiod_hog {
+       struct list_head list;
+       const char *chip_label;
+       u16 chip_hwnum;
+       const char *line_name;
+       enum gpio_lookup_flags lflags;
+       int dflags;
+};
+
 /*
  * Simple definition of a single GPIO under a con_id
  */
@@ -59,10 +76,23 @@ struct gpiod_lookup_table {
        .flags = _flags,                                                  \
 }
 
+/*
+ * Simple definition of a single GPIO hog in an array.
+ */
+#define GPIO_HOG(_chip_label, _chip_hwnum, _line_name, _lflags, _dflags)  \
+{                                                                         \
+       .chip_label = _chip_label,                                        \
+       .chip_hwnum = _chip_hwnum,                                        \
+       .line_name = _line_name,                                          \
+       .lflags = _lflags,                                                \
+       .dflags = _dflags,                                                \
+}
+
 #ifdef CONFIG_GPIOLIB
 void gpiod_add_lookup_table(struct gpiod_lookup_table *table);
 void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n);
 void gpiod_remove_lookup_table(struct gpiod_lookup_table *table);
+void gpiod_add_hogs(struct gpiod_hog *hogs);
 #else
 static inline
 void gpiod_add_lookup_table(struct gpiod_lookup_table *table) {}
@@ -70,6 +100,7 @@ static inline
 void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n) {}
 static inline
 void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) {}
+static inline void gpiod_add_hogs(struct gpiod_hog *hogs) {}
 #endif
 
 #endif /* __LINUX_GPIO_MACHINE_H */
index 2dc7f4a8ab095a0d87c8f5bd649624b13c303d33..419cfacb4b42cd96392d50b84fb350cc662dc929 100644 (file)
@@ -19,7 +19,8 @@ struct dwapb_port_property {
        unsigned int    idx;
        unsigned int    ngpio;
        unsigned int    gpio_base;
-       unsigned int    irq;
+       int             irq[32];
+       bool            has_irq;
        bool            irq_shared;
 };