diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-12-01 17:56:50 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-12-01 17:56:50 -0800 |
commit | 99a0d9f5e87352c4bd8d01bc9b39f7091c12e4d4 (patch) | |
tree | db8608677da8ec882f495bfb3885727f2a5b5d40 /drivers/gpio/gpio-merrifield.c | |
parent | 37323918cac24c89facdc009b0566b25cce94ea5 (diff) | |
parent | 41c4616bb81ff9b2efd981453f2c5d8f57d0c0b8 (diff) |
Merge tag 'gpio-v5.5-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO updates from Linus Walleij:
"This is the bulk of GPIO changes for the v5.5 kernel cycle
Core changes:
- Expose pull up/down flags for the GPIO character device to
userspace.
After clear input from the RaspberryPi and Beagle communities, it
has been established that prototyping, industrial automation and
make communities strongly need this feature, and as we want people
to use the character device, we have implemented the simple pull
up/down interface for GPIO lines.
This means we can specify that a (chip-specific) pull up/down
resistor can be enabled, but does not offer fine-grained control
such as cases where the resistance of the same pull resistor can be
controlled (yet).
- Introduce devm_fwnode_gpiod_get_index() and start to phase out the
old symbol devm_fwnode_get_index_gpiod_from_child().
- A bit of documentation clean-up work.
- Introduce a define for GPIO line directions and deploy it in all
GPIO drivers in the drivers/gpio directory.
- Add a special callback to populate pin ranges when cooperating with
the pin control subsystem and registering ranges as part of adding
a gpiolib driver and a gpio_irq_chip driver at the same time. This
is also deployed in the Intel Merrifield driver.
New drivers:
- RDA Micro GPIO controller.
- XGS-iproc GPIO driver.
Driver improvements:
- Wake event and debounce support on the Tegra 186 driver.
- Finalize the Aspeed SGPIO driver.
- MPC8xxx uses a normal IRQ handler rather than a chained handler"
* tag 'gpio-v5.5-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (64 commits)
gpio: Add TODO item for regmap helper
Documentation: gpio: driver.rst: Fix warnings
gpio: of: Fix bogus reference to gpiod_get_count()
gpiolib: Grammar s/manager/managed/
gpio: lynxpoint: Setup correct IRQ handlers
MAINTAINERS: Replace my email by one @kernel.org
gpiolib: acpi: Make acpi_gpiochip_alloc_event always return AE_OK
gpio/mpc8xxx: fix qoriq GPIO reading
gpio: mpc8xxx: Don't overwrite default irq_set_type callback
gpiolib: acpi: Print pin number on acpi_gpiochip_alloc_event errors
gpiolib: fix coding style in gpiod_hog()
drm/bridge: ti-tfp410: switch to using fwnode_gpiod_get_index()
gpio: merrifield: Pass irqchip when adding gpiochip
gpio: merrifield: Add GPIO <-> pin mapping ranges via callback
gpiolib: Introduce ->add_pin_ranges() callback
gpio: mmio: remove untrue leftover comment
gpio: em: Use platform_get_irq() to obtain interrupts
gpio: tegra186: Add debounce support
gpio: tegra186: Program interrupt route mapping
gpio: tegra186: Derive register offsets from bank/port
...
Diffstat (limited to 'drivers/gpio/gpio-merrifield.c')
-rw-r--r-- | drivers/gpio/gpio-merrifield.c | 79 |
1 files changed, 48 insertions, 31 deletions
diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c index 3302125e5265..48918a016cd8 100644 --- a/drivers/gpio/gpio-merrifield.c +++ b/drivers/gpio/gpio-merrifield.c @@ -162,7 +162,10 @@ static int mrfld_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) { void __iomem *gpdr = gpio_reg(chip, offset, GPDR); - return !(readl(gpdr) & BIT(offset % 32)); + if (readl(gpdr) & BIT(offset % 32)) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int mrfld_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset, @@ -362,8 +365,9 @@ static void mrfld_irq_handler(struct irq_desc *desc) chained_irq_exit(irqchip, desc); } -static void mrfld_irq_init_hw(struct mrfld_gpio *priv) +static int mrfld_irq_init_hw(struct gpio_chip *chip) { + struct mrfld_gpio *priv = gpiochip_get_data(chip); void __iomem *reg; unsigned int base; @@ -375,6 +379,8 @@ static void mrfld_irq_init_hw(struct mrfld_gpio *priv) reg = gpio_reg(&priv->chip, base, GFER); writel(0, reg); } + + return 0; } static const char *mrfld_gpio_get_pinctrl_dev_name(struct mrfld_gpio *priv) @@ -393,14 +399,36 @@ static const char *mrfld_gpio_get_pinctrl_dev_name(struct mrfld_gpio *priv) return name; } -static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id) +static int mrfld_gpio_add_pin_ranges(struct gpio_chip *chip) { + struct mrfld_gpio *priv = gpiochip_get_data(chip); const struct mrfld_gpio_pinrange *range; const char *pinctrl_dev_name; + unsigned int i; + int retval; + + pinctrl_dev_name = mrfld_gpio_get_pinctrl_dev_name(priv); + for (i = 0; i < ARRAY_SIZE(mrfld_gpio_ranges); i++) { + range = &mrfld_gpio_ranges[i]; + retval = gpiochip_add_pin_range(&priv->chip, pinctrl_dev_name, + range->gpio_base, + range->pin_base, + range->npins); + if (retval) { + dev_err(priv->dev, "failed to add GPIO pin range\n"); + return retval; + } + } + + return 0; +} + +static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct gpio_irq_chip *girq; struct mrfld_gpio *priv; u32 gpio_base, irq_base; void __iomem *base; - unsigned int i; int retval; retval = pcim_enable_device(pdev); @@ -441,42 +469,31 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id priv->chip.base = gpio_base; priv->chip.ngpio = MRFLD_NGPIO; priv->chip.can_sleep = false; + priv->chip.add_pin_ranges = mrfld_gpio_add_pin_ranges; raw_spin_lock_init(&priv->lock); - pci_set_drvdata(pdev, priv); + girq = &priv->chip.irq; + girq->chip = &mrfld_irqchip; + girq->init_hw = mrfld_irq_init_hw; + girq->parent_handler = mrfld_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents, + sizeof(*girq->parents), GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = pdev->irq; + girq->first = irq_base; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv); if (retval) { dev_err(&pdev->dev, "gpiochip_add error %d\n", retval); return retval; } - pinctrl_dev_name = mrfld_gpio_get_pinctrl_dev_name(priv); - for (i = 0; i < ARRAY_SIZE(mrfld_gpio_ranges); i++) { - range = &mrfld_gpio_ranges[i]; - retval = gpiochip_add_pin_range(&priv->chip, - pinctrl_dev_name, - range->gpio_base, - range->pin_base, - range->npins); - if (retval) { - dev_err(&pdev->dev, "failed to add GPIO pin range\n"); - return retval; - } - } - - retval = gpiochip_irqchip_add(&priv->chip, &mrfld_irqchip, irq_base, - handle_bad_irq, IRQ_TYPE_NONE); - if (retval) { - dev_err(&pdev->dev, "could not connect irqchip to gpiochip\n"); - return retval; - } - - mrfld_irq_init_hw(priv); - - gpiochip_set_chained_irqchip(&priv->chip, &mrfld_irqchip, pdev->irq, - mrfld_irq_handler); - + pci_set_drvdata(pdev, priv); return 0; } |