]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge tag 'gpio-v5.5-updates-for-linus-part-1' of git://git.kernel.org/pub/scm/linux...
authorLinus Walleij <linus.walleij@linaro.org>
Wed, 23 Oct 2019 11:31:36 +0000 (13:31 +0200)
committerLinus Walleij <linus.walleij@linaro.org>
Wed, 23 Oct 2019 11:31:36 +0000 (13:31 +0200)
gpio updates for v5.5

- only get the second IRQ when there is more than one IRQ in mxc
- move the code around in lineevent_create() for some shrinkage
- fix formatting for GPIO docs
- add DT binding for r8a774b1
- convert drivers that prevously used nocache ioremap() to using regular
  devm_platform_ioremap_resource()
- remove some redundant error messages
- shrink object code in 104-idi-48e
- drop an unneeded warning from gpiolib-of

14 files changed:
Documentation/driver-api/gpio/bt8xxgpio.rst [moved from Documentation/driver-api/bt8xxgpio.rst with 98% similarity]
Documentation/driver-api/gpio/index.rst
Documentation/driver-api/index.rst
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-aspeed-sgpio.c [moved from drivers/gpio/sgpio-aspeed.c with 100% similarity]
drivers/gpio/gpio-max77620.c
drivers/gpio/gpio-mpc8xxx.c
drivers/gpio/gpio-tegra186.c
drivers/gpio/gpiolib-devres.c
drivers/gpio/gpiolib-of.c
drivers/gpio/gpiolib.c
include/linux/gpio/consumer.h
include/uapi/linux/gpio.h

similarity index 98%
rename from Documentation/driver-api/bt8xxgpio.rst
rename to Documentation/driver-api/gpio/bt8xxgpio.rst
index a845feb074de7486efc855f76b53b51e2de8a3d5..d7e75f1234e7468312dc1abc0a5e32bfba75c323 100644 (file)
@@ -2,7 +2,7 @@
 A driver for a selfmade cheap BT8xx based PCI GPIO-card (bt8xxgpio)
 ===================================================================
 
-For advanced documentation, see http://www.bu3sch.de/btgpio.php
+For advanced documentation, see https://bues.ch/cms/unmaintained/btgpio.html
 
 A generic digital 24-port PCI GPIO card can be built out of an ordinary
 Brooktree bt848, bt849, bt878 or bt879 based analog TV tuner card. The
index c5b8467f91043e288b7d5386c8f44da056ffb2c4..5b61032aa4ea95a3b0b5bc1a8fee40e56d8811d2 100644 (file)
@@ -13,6 +13,7 @@ Contents:
    board
    drivers-on-gpio
    legacy
+   bt8xxgpio
 
 Core
 ====
index 38e638abe3ebcee44d990bb74da7089a6421b1fc..2b3b6949381eda7ea906ce24c1f404eaaef81af7 100644 (file)
@@ -69,7 +69,6 @@ available subsections can be seen below.
    fpga/index
    acpi/index
    backlight/lp855x-driver.rst
-   bt8xxgpio
    connector
    console
    dcdbas
index 38e096e6925fa65dfbd95e84bf9081feeba43cd0..088a8a0f8add52d525a9e4f4e55e35b3751095e7 100644 (file)
@@ -120,6 +120,14 @@ config GPIO_ASPEED
        help
          Say Y here to support Aspeed AST2400 and AST2500 GPIO controllers.
 
+config GPIO_ASPEED_SGPIO
+       bool "Aspeed SGPIO support"
+       depends on (ARCH_ASPEED || COMPILE_TEST) && OF_GPIO
+       select GPIO_GENERIC
+       select GPIOLIB_IRQCHIP
+       help
+         Say Y here to support Aspeed AST2500 SGPIO functionality.
+
 config GPIO_ATH79
        tristate "Atheros AR71XX/AR724X/AR913X GPIO support"
        default y if ATH79
@@ -531,6 +539,7 @@ config GPIO_TEGRA186
        depends on ARCH_TEGRA_186_SOC || COMPILE_TEST
        depends on OF_GPIO
        select GPIOLIB_IRQCHIP
+       select IRQ_DOMAIN_HIERARCHY
        help
          Say yes here to support GPIO pins on NVIDIA Tegra186 SoCs.
 
@@ -1320,7 +1329,7 @@ config GPIO_BT8XX
          The card needs to be physically altered for using it as a
          GPIO card. For more information on how to build a GPIO card
          from a BT8xx TV card, see the documentation file at
-         Documentation/driver-api/bt8xxgpio.rst
+         Documentation/driver-api/gpio/bt8xxgpio.rst
 
          If unsure, say N.
 
index d2fd19c15bae3fbad7b7f7ce2fbf2ca9f1429efb..e4599f90f702c8fa1e50641d9e592908c223180c 100644 (file)
@@ -32,6 +32,7 @@ obj-$(CONFIG_GPIO_AMD_FCH)            += gpio-amd-fch.o
 obj-$(CONFIG_GPIO_AMDPT)               += gpio-amdpt.o
 obj-$(CONFIG_GPIO_ARIZONA)             += gpio-arizona.o
 obj-$(CONFIG_GPIO_ASPEED)              += gpio-aspeed.o
+obj-$(CONFIG_GPIO_ASPEED_SGPIO)                += gpio-aspeed-sgpio.o
 obj-$(CONFIG_GPIO_ATH79)               += gpio-ath79.o
 obj-$(CONFIG_GPIO_BCM_KONA)            += gpio-bcm-kona.o
 obj-$(CONFIG_GPIO_BD70528)             += gpio-bd70528.o
index 47d05e357e61a05b742fd75d892fa3d3e5506af0..3ece63ae6f938662f5081e10d95f8c6bba8646d0 100644 (file)
@@ -18,109 +18,115 @@ struct max77620_gpio {
        struct gpio_chip        gpio_chip;
        struct regmap           *rmap;
        struct device           *dev;
+       struct mutex            buslock; /* irq_bus_lock */
+       unsigned int            irq_type[8];
+       bool                    irq_enabled[8];
 };
 
-static const struct regmap_irq max77620_gpio_irqs[] = {
-       [0] = {
-               .reg_offset = 0,
-               .mask = MAX77620_IRQ_LVL2_GPIO_EDGE0,
-               .type = {
-                       .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING,
-                       .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING,
-                       .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK,
-                       .type_reg_offset = 0,
-                       .types_supported = IRQ_TYPE_EDGE_BOTH,
-               },
-       },
-       [1] = {
-               .reg_offset = 0,
-               .mask = MAX77620_IRQ_LVL2_GPIO_EDGE1,
-               .type = {
-                       .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING,
-                       .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING,
-                       .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK,
-                       .type_reg_offset = 1,
-                       .types_supported = IRQ_TYPE_EDGE_BOTH,
-               },
-       },
-       [2] = {
-               .reg_offset = 0,
-               .mask = MAX77620_IRQ_LVL2_GPIO_EDGE2,
-               .type = {
-                       .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING,
-                       .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING,
-                       .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK,
-                       .type_reg_offset = 2,
-                       .types_supported = IRQ_TYPE_EDGE_BOTH,
-               },
-       },
-       [3] = {
-               .reg_offset = 0,
-               .mask = MAX77620_IRQ_LVL2_GPIO_EDGE3,
-               .type = {
-                       .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING,
-                       .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING,
-                       .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK,
-                       .type_reg_offset = 3,
-                       .types_supported = IRQ_TYPE_EDGE_BOTH,
-               },
-       },
-       [4] = {
-               .reg_offset = 0,
-               .mask = MAX77620_IRQ_LVL2_GPIO_EDGE4,
-               .type = {
-                       .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING,
-                       .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING,
-                       .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK,
-                       .type_reg_offset = 4,
-                       .types_supported = IRQ_TYPE_EDGE_BOTH,
-               },
-       },
-       [5] = {
-               .reg_offset = 0,
-               .mask = MAX77620_IRQ_LVL2_GPIO_EDGE5,
-               .type = {
-                       .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING,
-                       .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING,
-                       .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK,
-                       .type_reg_offset = 5,
-                       .types_supported = IRQ_TYPE_EDGE_BOTH,
-               },
-       },
-       [6] = {
-               .reg_offset = 0,
-               .mask = MAX77620_IRQ_LVL2_GPIO_EDGE6,
-               .type = {
-                       .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING,
-                       .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING,
-                       .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK,
-                       .type_reg_offset = 6,
-                       .types_supported = IRQ_TYPE_EDGE_BOTH,
-               },
-       },
-       [7] = {
-               .reg_offset = 0,
-               .mask = MAX77620_IRQ_LVL2_GPIO_EDGE7,
-               .type = {
-                       .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING,
-                       .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING,
-                       .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK,
-                       .type_reg_offset = 7,
-                       .types_supported = IRQ_TYPE_EDGE_BOTH,
-               },
-       },
-};
+static irqreturn_t max77620_gpio_irqhandler(int irq, void *data)
+{
+       struct max77620_gpio *gpio = data;
+       unsigned int value, offset;
+       unsigned long pending;
+       int err;
+
+       err = regmap_read(gpio->rmap, MAX77620_REG_IRQ_LVL2_GPIO, &value);
+       if (err < 0) {
+               dev_err(gpio->dev, "REG_IRQ_LVL2_GPIO read failed: %d\n", err);
+               return IRQ_NONE;
+       }
+
+       pending = value;
+
+       for_each_set_bit(offset, &pending, 8) {
+               unsigned int virq;
+
+               virq = irq_find_mapping(gpio->gpio_chip.irq.domain, offset);
+               handle_nested_irq(virq);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static void max77620_gpio_irq_mask(struct irq_data *data)
+{
+       struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+       struct max77620_gpio *gpio = gpiochip_get_data(chip);
+
+       gpio->irq_enabled[data->hwirq] = false;
+}
 
-static const struct regmap_irq_chip max77620_gpio_irq_chip = {
-       .name = "max77620-gpio",
-       .irqs = max77620_gpio_irqs,
-       .num_irqs = ARRAY_SIZE(max77620_gpio_irqs),
-       .num_regs = 1,
-       .num_type_reg = 8,
-       .irq_reg_stride = 1,
-       .type_reg_stride = 1,
-       .status_base = MAX77620_REG_IRQ_LVL2_GPIO,
-       .type_base = MAX77620_REG_GPIO0,
+static void max77620_gpio_irq_unmask(struct irq_data *data)
+{
+       struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+       struct max77620_gpio *gpio = gpiochip_get_data(chip);
+
+       gpio->irq_enabled[data->hwirq] = true;
+}
+
+static int max77620_gpio_set_irq_type(struct irq_data *data, unsigned int type)
+{
+       struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+       struct max77620_gpio *gpio = gpiochip_get_data(chip);
+       unsigned int irq_type;
+
+       switch (type) {
+       case IRQ_TYPE_EDGE_RISING:
+               irq_type = MAX77620_CNFG_GPIO_INT_RISING;
+               break;
+
+       case IRQ_TYPE_EDGE_FALLING:
+               irq_type = MAX77620_CNFG_GPIO_INT_FALLING;
+               break;
+
+       case IRQ_TYPE_EDGE_BOTH:
+               irq_type = MAX77620_CNFG_GPIO_INT_RISING |
+                          MAX77620_CNFG_GPIO_INT_FALLING;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       gpio->irq_type[data->hwirq] = irq_type;
+
+       return 0;
+}
+
+static void max77620_gpio_bus_lock(struct irq_data *data)
+{
+       struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+       struct max77620_gpio *gpio = gpiochip_get_data(chip);
+
+       mutex_lock(&gpio->buslock);
+}
+
+static void max77620_gpio_bus_sync_unlock(struct irq_data *data)
+{
+       struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+       struct max77620_gpio *gpio = gpiochip_get_data(chip);
+       unsigned int value, offset = data->hwirq;
+       int err;
+
+       value = gpio->irq_enabled[offset] ? gpio->irq_type[offset] : 0;
+
+       err = regmap_update_bits(gpio->rmap, GPIO_REG_ADDR(offset),
+                                MAX77620_CNFG_GPIO_INT_MASK, value);
+       if (err < 0)
+               dev_err(chip->parent, "failed to update interrupt mask: %d\n",
+                       err);
+
+       mutex_unlock(&gpio->buslock);
+}
+
+static struct irq_chip max77620_gpio_irqchip = {
+       .name           = "max77620-gpio",
+       .irq_mask       = max77620_gpio_irq_mask,
+       .irq_unmask     = max77620_gpio_irq_unmask,
+       .irq_set_type   = max77620_gpio_set_irq_type,
+       .irq_bus_lock   = max77620_gpio_bus_lock,
+       .irq_bus_sync_unlock = max77620_gpio_bus_sync_unlock,
+       .flags          = IRQCHIP_MASK_ON_SUSPEND,
 };
 
 static int max77620_gpio_dir_input(struct gpio_chip *gc, unsigned int offset)
@@ -254,14 +260,6 @@ static int max77620_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
        return -ENOTSUPP;
 }
 
-static int max77620_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
-{
-       struct max77620_gpio *mgpio = gpiochip_get_data(gc);
-       struct max77620_chip *chip = dev_get_drvdata(mgpio->dev->parent);
-
-       return regmap_irq_get_virq(chip->gpio_irq_data, offset);
-}
-
 static int max77620_gpio_probe(struct platform_device *pdev)
 {
        struct max77620_chip *chip =  dev_get_drvdata(pdev->dev.parent);
@@ -287,7 +285,6 @@ static int max77620_gpio_probe(struct platform_device *pdev)
        mgpio->gpio_chip.direction_output = max77620_gpio_dir_output;
        mgpio->gpio_chip.set = max77620_gpio_set;
        mgpio->gpio_chip.set_config = max77620_gpio_set_config;
-       mgpio->gpio_chip.to_irq = max77620_gpio_to_irq;
        mgpio->gpio_chip.ngpio = MAX77620_GPIO_NR;
        mgpio->gpio_chip.can_sleep = 1;
        mgpio->gpio_chip.base = -1;
@@ -303,15 +300,21 @@ static int max77620_gpio_probe(struct platform_device *pdev)
                return ret;
        }
 
-       ret = devm_regmap_add_irq_chip(&pdev->dev, chip->rmap, gpio_irq,
-                                      IRQF_ONESHOT, -1,
-                                      &max77620_gpio_irq_chip,
-                                      &chip->gpio_irq_data);
+       mutex_init(&mgpio->buslock);
+
+       gpiochip_irqchip_add_nested(&mgpio->gpio_chip, &max77620_gpio_irqchip,
+                                   0, handle_edge_irq, IRQ_TYPE_NONE);
+
+       ret = request_threaded_irq(gpio_irq, NULL, max77620_gpio_irqhandler,
+                                  IRQF_ONESHOT, "max77620-gpio", mgpio);
        if (ret < 0) {
-               dev_err(&pdev->dev, "Failed to add gpio irq_chip %d\n", ret);
+               dev_err(&pdev->dev, "failed to request IRQ: %d\n", ret);
                return ret;
        }
 
+       gpiochip_set_nested_irqchip(&mgpio->gpio_chip, &max77620_gpio_irqchip,
+                                   gpio_irq);
+
        return 0;
 }
 
index 16a47de29c94c43bbcbceb0063510e77a50df753..58ff37219fce0d1f4555647a3e8a4082e7d94aa3 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/irq.h>
 #include <linux/gpio/driver.h>
 #include <linux/bitops.h>
+#include <linux/interrupt.h>
 
 #define MPC8XXX_GPIO_PINS      32
 
@@ -127,20 +128,19 @@ static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
                return -ENXIO;
 }
 
-static void mpc8xxx_gpio_irq_cascade(struct irq_desc *desc)
+static irqreturn_t mpc8xxx_gpio_irq_cascade(int irq, void *data)
 {
-       struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_desc_get_handler_data(desc);
-       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct mpc8xxx_gpio_chip *mpc8xxx_gc = data;
        struct gpio_chip *gc = &mpc8xxx_gc->gc;
-       unsigned int mask;
+       unsigned long mask;
+       int i;
 
        mask = gc->read_reg(mpc8xxx_gc->regs + GPIO_IER)
                & gc->read_reg(mpc8xxx_gc->regs + GPIO_IMR);
-       if (mask)
-               generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq,
-                                                    32 - ffs(mask)));
-       if (chip->irq_eoi)
-               chip->irq_eoi(&desc->irq_data);
+       for_each_set_bit(i, &mask, 32)
+               generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq, 31 - i));
+
+       return IRQ_HANDLED;
 }
 
 static void mpc8xxx_irq_unmask(struct irq_data *d)
@@ -409,8 +409,16 @@ static int mpc8xxx_probe(struct platform_device *pdev)
        if (devtype->gpio_dir_in_init)
                devtype->gpio_dir_in_init(gc);
 
-       irq_set_chained_handler_and_data(mpc8xxx_gc->irqn,
-                                        mpc8xxx_gpio_irq_cascade, mpc8xxx_gc);
+       ret = devm_request_irq(&pdev->dev, mpc8xxx_gc->irqn,
+                              mpc8xxx_gpio_irq_cascade,
+                              IRQF_NO_THREAD | IRQF_SHARED, "gpio-cascade",
+                              mpc8xxx_gc);
+       if (ret) {
+               dev_err(&pdev->dev, "%s: failed to devm_request_irq(%d), ret = %d\n",
+                       np->full_name, mpc8xxx_gc->irqn, ret);
+               goto err;
+       }
+
        return 0;
 err:
        iounmap(mpc8xxx_gc->regs);
index a9058fda187e3abda62d447a2ed5930c30328c7e..8a2a69178925dc104f32b473c732dfc8d638761d 100644 (file)
@@ -53,6 +53,7 @@ struct tegra_gpio_soc {
        const struct tegra_gpio_port *ports;
        unsigned int num_ports;
        const char *name;
+       unsigned int instance;
 };
 
 struct tegra_gpio {
@@ -327,7 +328,7 @@ static int tegra186_irq_set_type(struct irq_data *data, unsigned int type)
        else
                irq_set_handler_locked(data, handle_edge_irq);
 
-       return 0;
+       return irq_chip_set_type_parent(data, type);
 }
 
 static void tegra186_gpio_irq(struct irq_desc *desc)
@@ -367,39 +368,80 @@ static void tegra186_gpio_irq(struct irq_desc *desc)
        chained_irq_exit(chip, desc);
 }
 
-static int tegra186_gpio_irq_domain_xlate(struct irq_domain *domain,
-                                         struct device_node *np,
-                                         const u32 *spec, unsigned int size,
-                                         unsigned long *hwirq,
-                                         unsigned int *type)
+static int tegra186_gpio_irq_domain_translate(struct irq_domain *domain,
+                                             struct irq_fwspec *fwspec,
+                                             unsigned long *hwirq,
+                                             unsigned int *type)
 {
        struct tegra_gpio *gpio = gpiochip_get_data(domain->host_data);
        unsigned int port, pin, i, offset = 0;
 
-       if (size < 2)
+       if (WARN_ON(gpio->gpio.of_gpio_n_cells < 2))
+               return -EINVAL;
+
+       if (WARN_ON(fwspec->param_count < gpio->gpio.of_gpio_n_cells))
                return -EINVAL;
 
-       port = spec[0] / 8;
-       pin = spec[0] % 8;
+       port = fwspec->param[0] / 8;
+       pin = fwspec->param[0] % 8;
 
-       if (port >= gpio->soc->num_ports) {
-               dev_err(gpio->gpio.parent, "invalid port number: %u\n", port);
+       if (port >= gpio->soc->num_ports)
                return -EINVAL;
-       }
 
        for (i = 0; i < port; i++)
                offset += gpio->soc->ports[i].pins;
 
-       *type = spec[1] & IRQ_TYPE_SENSE_MASK;
+       *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
        *hwirq = offset + pin;
 
        return 0;
 }
 
-static const struct irq_domain_ops tegra186_gpio_irq_domain_ops = {
-       .map = gpiochip_irq_map,
-       .unmap = gpiochip_irq_unmap,
-       .xlate = tegra186_gpio_irq_domain_xlate,
+static void tegra186_gpio_populate_parent_fwspec(struct gpio_chip *chip,
+                                                struct irq_fwspec *fwspec,
+                                                unsigned int parent_hwirq,
+                                                unsigned int parent_type)
+{
+       struct tegra_gpio *gpio = gpiochip_get_data(chip);
+
+       fwspec->param_count = 3;
+       fwspec->param[0] = gpio->soc->instance;
+       fwspec->param[1] = parent_hwirq;
+       fwspec->param[2] = parent_type;
+}
+
+static int tegra186_gpio_child_to_parent_hwirq(struct gpio_chip *chip,
+                                              unsigned int hwirq,
+                                              unsigned int type,
+                                              unsigned int *parent_hwirq,
+                                              unsigned int *parent_type)
+{
+       *parent_hwirq = chip->irq.child_offset_to_irq(chip, hwirq);
+       *parent_type = type;
+
+       return 0;
+}
+
+static unsigned int tegra186_gpio_child_offset_to_irq(struct gpio_chip *chip,
+                                                     unsigned int offset)
+{
+       struct tegra_gpio *gpio = gpiochip_get_data(chip);
+       unsigned int i;
+
+       for (i = 0; i < gpio->soc->num_ports; i++) {
+               if (offset < gpio->soc->ports[i].pins)
+                       break;
+
+               offset -= gpio->soc->ports[i].pins;
+       }
+
+       return offset + i * 8;
+}
+
+static const struct of_device_id tegra186_pmc_of_match[] = {
+       { .compatible = "nvidia,tegra186-pmc" },
+       { .compatible = "nvidia,tegra194-pmc" },
+       { /* sentinel */ }
 };
 
 static int tegra186_gpio_probe(struct platform_device *pdev)
@@ -407,6 +449,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
        unsigned int i, j, offset;
        struct gpio_irq_chip *irq;
        struct tegra_gpio *gpio;
+       struct device_node *np;
        struct resource *res;
        char **names;
        int err;
@@ -487,10 +530,15 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
        gpio->intc.irq_mask = tegra186_irq_mask;
        gpio->intc.irq_unmask = tegra186_irq_unmask;
        gpio->intc.irq_set_type = tegra186_irq_set_type;
+       gpio->intc.irq_set_wake = irq_chip_set_wake_parent;
 
        irq = &gpio->gpio.irq;
        irq->chip = &gpio->intc;
-       irq->domain_ops = &tegra186_gpio_irq_domain_ops;
+       irq->fwnode = of_node_to_fwnode(pdev->dev.of_node);
+       irq->child_to_parent_hwirq = tegra186_gpio_child_to_parent_hwirq;
+       irq->populate_parent_fwspec = tegra186_gpio_populate_parent_fwspec;
+       irq->child_offset_to_irq = tegra186_gpio_child_offset_to_irq;
+       irq->child_irq_domain_ops.translate = tegra186_gpio_irq_domain_translate;
        irq->handler = handle_simple_irq;
        irq->default_type = IRQ_TYPE_NONE;
        irq->parent_handler = tegra186_gpio_irq;
@@ -498,6 +546,15 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
        irq->num_parents = gpio->num_irq;
        irq->parents = gpio->irq;
 
+       np = of_find_matching_node(NULL, tegra186_pmc_of_match);
+       if (np) {
+               irq->parent_domain = irq_find_host(np);
+               of_node_put(np);
+
+               if (!irq->parent_domain)
+                       return -EPROBE_DEFER;
+       }
+
        irq->map = devm_kcalloc(&pdev->dev, gpio->gpio.ngpio,
                                sizeof(*irq->map), GFP_KERNEL);
        if (!irq->map)
@@ -564,6 +621,7 @@ static const struct tegra_gpio_soc tegra186_main_soc = {
        .num_ports = ARRAY_SIZE(tegra186_main_ports),
        .ports = tegra186_main_ports,
        .name = "tegra186-gpio",
+       .instance = 0,
 };
 
 #define TEGRA186_AON_GPIO_PORT(port, base, count, controller)  \
@@ -589,6 +647,7 @@ static const struct tegra_gpio_soc tegra186_aon_soc = {
        .num_ports = ARRAY_SIZE(tegra186_aon_ports),
        .ports = tegra186_aon_ports,
        .name = "tegra186-gpio-aon",
+       .instance = 1,
 };
 
 #define TEGRA194_MAIN_GPIO_PORT(port, base, count, controller) \
@@ -634,6 +693,7 @@ static const struct tegra_gpio_soc tegra194_main_soc = {
        .num_ports = ARRAY_SIZE(tegra194_main_ports),
        .ports = tegra194_main_ports,
        .name = "tegra194-gpio",
+       .instance = 0,
 };
 
 #define TEGRA194_AON_GPIO_PORT(port, base, count, controller)  \
@@ -656,6 +716,7 @@ static const struct tegra_gpio_soc tegra194_aon_soc = {
        .num_ports = ARRAY_SIZE(tegra194_aon_ports),
        .ports = tegra194_aon_ports,
        .name = "tegra194-gpio-aon",
+       .instance = 1,
 };
 
 static const struct of_device_id tegra186_gpio_of_match[] = {
index 98e3c20d9730e66ad46bff8317e96fb4996eda32..4421be09b960591cfb8ce202a33766606b1df552 100644 (file)
@@ -185,12 +185,11 @@ struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
 EXPORT_SYMBOL_GPL(devm_gpiod_get_from_of_node);
 
 /**
- * devm_fwnode_get_index_gpiod_from_child - get a GPIO descriptor from a
- *                                         device's child node
+ * devm_fwnode_gpiod_get_index - get a GPIO descriptor from a given node
  * @dev:       GPIO consumer
+ * @fwnode:    firmware node containing GPIO reference
  * @con_id:    function within the GPIO consumer
  * @index:     index of the GPIO to obtain in the consumer
- * @child:     firmware node (child of @dev)
  * @flags:     GPIO initialization flags
  * @label:     label to attach to the requested GPIO
  *
@@ -200,35 +199,21 @@ EXPORT_SYMBOL_GPL(devm_gpiod_get_from_of_node);
  * On successful request the GPIO pin is configured in accordance with
  * provided @flags.
  */
-struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
-                                               const char *con_id, int index,
-                                               struct fwnode_handle *child,
-                                               enum gpiod_flags flags,
-                                               const char *label)
+struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev,
+                                             struct fwnode_handle *fwnode,
+                                             const char *con_id, int index,
+                                             enum gpiod_flags flags,
+                                             const char *label)
 {
-       char prop_name[32]; /* 32 is max size of property name */
        struct gpio_desc **dr;
        struct gpio_desc *desc;
-       unsigned int i;
 
        dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
                          GFP_KERNEL);
        if (!dr)
                return ERR_PTR(-ENOMEM);
 
-       for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
-               if (con_id)
-                       snprintf(prop_name, sizeof(prop_name), "%s-%s",
-                                           con_id, gpio_suffixes[i]);
-               else
-                       snprintf(prop_name, sizeof(prop_name), "%s",
-                                           gpio_suffixes[i]);
-
-               desc = fwnode_get_named_gpiod(child, prop_name, index, flags,
-                                             label);
-               if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT))
-                       break;
-       }
+       desc = fwnode_gpiod_get_index(fwnode, con_id, index, flags, label);
        if (IS_ERR(desc)) {
                devres_free(dr);
                return desc;
@@ -239,7 +224,7 @@ struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
 
        return desc;
 }
-EXPORT_SYMBOL_GPL(devm_fwnode_get_index_gpiod_from_child);
+EXPORT_SYMBOL_GPL(devm_fwnode_gpiod_get_index);
 
 /**
  * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()
index 576c7419bbc1e1dd27aacf0d7d1bf60d9e8c13a8..99adc801a0675df20611dac79d495cbb2d8b9fd3 100644 (file)
@@ -84,8 +84,9 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip,
 /**
  * of_gpio_need_valid_mask() - figure out if the OF GPIO driver needs
  * to set the .valid_mask
- * @dev: the device for the GPIO provider
- * @return: true if the valid mask needs to be set
+ * @gc: the target gpio_chip
+ *
+ * Return: true if the valid mask needs to be set
  */
 bool of_gpio_need_valid_mask(const struct gpio_chip *gc)
 {
index e8964493c571177f0a865ac2759e203ec16ac91e..ec92ed3f3055eeb2c72e415aa5b83b06e8a13d2d 100644 (file)
@@ -421,6 +421,8 @@ struct linehandle_state {
        (GPIOHANDLE_REQUEST_INPUT | \
        GPIOHANDLE_REQUEST_OUTPUT | \
        GPIOHANDLE_REQUEST_ACTIVE_LOW | \
+       GPIOHANDLE_REQUEST_PULL_UP | \
+       GPIOHANDLE_REQUEST_PULL_DOWN | \
        GPIOHANDLE_REQUEST_OPEN_DRAIN | \
        GPIOHANDLE_REQUEST_OPEN_SOURCE)
 
@@ -592,6 +594,10 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
                        set_bit(FLAG_OPEN_DRAIN, &desc->flags);
                if (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE)
                        set_bit(FLAG_OPEN_SOURCE, &desc->flags);
+               if (lflags & GPIOHANDLE_REQUEST_PULL_DOWN)
+                       set_bit(FLAG_PULL_DOWN, &desc->flags);
+               if (lflags & GPIOHANDLE_REQUEST_PULL_UP)
+                       set_bit(FLAG_PULL_UP, &desc->flags);
 
                ret = gpiod_set_transitory(desc, false);
                if (ret < 0)
@@ -1091,6 +1097,10 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                if (test_bit(FLAG_OPEN_SOURCE, &desc->flags))
                        lineinfo.flags |= (GPIOLINE_FLAG_OPEN_SOURCE |
                                           GPIOLINE_FLAG_IS_OUT);
+               if (test_bit(FLAG_PULL_DOWN, &desc->flags))
+                       lineinfo.flags |= GPIOLINE_FLAG_PULL_DOWN;
+               if (test_bit(FLAG_PULL_UP, &desc->flags))
+                       lineinfo.flags |= GPIOLINE_FLAG_PULL_UP;
 
                if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
                        return -EFAULT;
@@ -2764,6 +2774,8 @@ static bool gpiod_free_commit(struct gpio_desc *desc)
                clear_bit(FLAG_REQUESTED, &desc->flags);
                clear_bit(FLAG_OPEN_DRAIN, &desc->flags);
                clear_bit(FLAG_OPEN_SOURCE, &desc->flags);
+               clear_bit(FLAG_PULL_UP, &desc->flags);
+               clear_bit(FLAG_PULL_DOWN, &desc->flags);
                clear_bit(FLAG_IS_HOGGED, &desc->flags);
                ret = true;
        }
@@ -4318,6 +4330,54 @@ static int platform_gpio_count(struct device *dev, const char *con_id)
        return count;
 }
 
+/**
+ * fwnode_gpiod_get_index - obtain a GPIO from firmware node
+ * @fwnode:    handle of the firmware node
+ * @con_id:    function within the GPIO consumer
+ * @index:     index of the GPIO to obtain for the consumer
+ * @flags:     GPIO initialization flags
+ * @label:     label to attach to the requested GPIO
+ *
+ * This function can be used for drivers that get their configuration
+ * from opaque firmware.
+ *
+ * The function properly finds the corresponding GPIO using whatever is the
+ * underlying firmware interface and then makes sure that the GPIO
+ * descriptor is requested before it is returned to the caller.
+ *
+ * Returns:
+ * On successful request the GPIO pin is configured in accordance with
+ * provided @flags.
+ *
+ * In case of error an ERR_PTR() is returned.
+ */
+struct gpio_desc *fwnode_gpiod_get_index(struct fwnode_handle *fwnode,
+                                        const char *con_id, int index,
+                                        enum gpiod_flags flags,
+                                        const char *label)
+{
+       struct gpio_desc *desc;
+       char prop_name[32]; /* 32 is max size of property name */
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
+               if (con_id)
+                       snprintf(prop_name, sizeof(prop_name), "%s-%s",
+                                           con_id, gpio_suffixes[i]);
+               else
+                       snprintf(prop_name, sizeof(prop_name), "%s",
+                                           gpio_suffixes[i]);
+
+               desc = fwnode_get_named_gpiod(fwnode, prop_name, index, flags,
+                                             label);
+               if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT))
+                       break;
+       }
+
+       return desc;
+}
+EXPORT_SYMBOL_GPL(fwnode_gpiod_get_index);
+
 /**
  * gpiod_count - return the number of GPIOs associated with a device / function
  *             or -ENOENT if no GPIO has been assigned to the requested function
index b70af921c6145527322bd00cb97fa5749d4a335a..5215fdba6b9a6dea6ca572b22398d8f2accf8c6e 100644 (file)
@@ -176,11 +176,15 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
                                         const char *propname, int index,
                                         enum gpiod_flags dflags,
                                         const char *label);
-struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
-                                               const char *con_id, int index,
-                                               struct fwnode_handle *child,
-                                               enum gpiod_flags flags,
-                                               const char *label);
+struct gpio_desc *fwnode_gpiod_get_index(struct fwnode_handle *fwnode,
+                                        const char *con_id, int index,
+                                        enum gpiod_flags flags,
+                                        const char *label);
+struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev,
+                                             struct fwnode_handle *child,
+                                             const char *con_id, int index,
+                                             enum gpiod_flags flags,
+                                             const char *label);
 
 #else /* CONFIG_GPIOLIB */
 
@@ -531,6 +535,38 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
        return ERR_PTR(-ENOSYS);
 }
 
+static inline
+struct gpio_desc *fwnode_gpiod_get_index(struct fwnode_handle *fwnode,
+                                        const char *con_id, int index,
+                                        enum gpiod_flags flags,
+                                        const char *label)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
+static inline
+struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev,
+                                             struct fwnode_handle *fwnode,
+                                             const char *con_id, int index,
+                                             enum gpiod_flags flags,
+                                             const char *label)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
+#endif /* CONFIG_GPIOLIB */
+
+static inline
+struct gpio_desc *devm_fwnode_gpiod_get(struct device *dev,
+                                       struct fwnode_handle *fwnode,
+                                       const char *con_id,
+                                       enum gpiod_flags flags,
+                                       const char *label)
+{
+       return devm_fwnode_gpiod_get_index(dev, fwnode, con_id, 0,
+                                          flags, label);
+}
+
 static inline
 struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
                                                const char *con_id, int index,
@@ -538,11 +574,10 @@ struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
                                                enum gpiod_flags flags,
                                                const char *label)
 {
-       return ERR_PTR(-ENOSYS);
+       return devm_fwnode_gpiod_get_index(dev, child, con_id, index,
+                                          flags, label);
 }
 
-#endif /* CONFIG_GPIOLIB */
-
 static inline
 struct gpio_desc *devm_fwnode_get_gpiod_from_child(struct device *dev,
                                                   const char *con_id,
@@ -550,8 +585,7 @@ struct gpio_desc *devm_fwnode_get_gpiod_from_child(struct device *dev,
                                                   enum gpiod_flags flags,
                                                   const char *label)
 {
-       return devm_fwnode_get_index_gpiod_from_child(dev, con_id, 0, child,
-                                                     flags, label);
+       return devm_fwnode_gpiod_get_index(dev, child, con_id, 0, flags, label);
 }
 
 #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_OF_GPIO)
index 4ebfe0ac6c5b942e6078945b3a2fc9446db846bc..c2d1f7d908d6f22ea0a8a4efa0910edc2ba0821f 100644 (file)
@@ -33,6 +33,8 @@ struct gpiochip_info {
 #define GPIOLINE_FLAG_ACTIVE_LOW       (1UL << 2)
 #define GPIOLINE_FLAG_OPEN_DRAIN       (1UL << 3)
 #define GPIOLINE_FLAG_OPEN_SOURCE      (1UL << 4)
+#define GPIOLINE_FLAG_PULL_UP  (1UL << 5)
+#define GPIOLINE_FLAG_PULL_DOWN        (1UL << 6)
 
 /**
  * struct gpioline_info - Information about a certain GPIO line
@@ -62,6 +64,8 @@ struct gpioline_info {
 #define GPIOHANDLE_REQUEST_ACTIVE_LOW  (1UL << 2)
 #define GPIOHANDLE_REQUEST_OPEN_DRAIN  (1UL << 3)
 #define GPIOHANDLE_REQUEST_OPEN_SOURCE (1UL << 4)
+#define GPIOHANDLE_REQUEST_PULL_UP     (1UL << 5)
+#define GPIOHANDLE_REQUEST_PULL_DOWN   (1UL << 6)
 
 /**
  * struct gpiohandle_request - Information about a GPIO handle request