| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2014-2017 Broadcom |
|---|
| 3 | | - * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or |
|---|
| 5 | | - * modify it under the terms of the GNU General Public License as |
|---|
| 6 | | - * published by the Free Software Foundation version 2. |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is distributed "as is" WITHOUT ANY WARRANTY of any |
|---|
| 9 | | - * kind, whether express or implied; without even the implied warranty |
|---|
| 10 | | - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 11 | | - * GNU General Public License for more details. |
|---|
| 12 | 4 | */ |
|---|
| 13 | 5 | |
|---|
| 14 | 6 | /* |
|---|
| .. | .. |
|---|
| 114 | 106 | |
|---|
| 115 | 107 | raw_spinlock_t lock; |
|---|
| 116 | 108 | |
|---|
| 109 | + struct irq_chip irqchip; |
|---|
| 117 | 110 | struct gpio_chip gc; |
|---|
| 118 | 111 | unsigned num_banks; |
|---|
| 119 | 112 | |
|---|
| .. | .. |
|---|
| 138 | 131 | * iproc_set_bit - set or clear one bit (corresponding to the GPIO pin) in a |
|---|
| 139 | 132 | * Iproc GPIO register |
|---|
| 140 | 133 | * |
|---|
| 141 | | - * @iproc_gpio: Iproc GPIO device |
|---|
| 134 | + * @chip: Iproc GPIO device |
|---|
| 142 | 135 | * @reg: register offset |
|---|
| 143 | 136 | * @gpio: GPIO pin |
|---|
| 144 | 137 | * @set: set or clear |
|---|
| .. | .. |
|---|
| 293 | 286 | iproc_set_bit(chip, IPROC_GPIO_INT_DE_OFFSET, gpio, dual_edge); |
|---|
| 294 | 287 | iproc_set_bit(chip, IPROC_GPIO_INT_EDGE_OFFSET, gpio, |
|---|
| 295 | 288 | rising_or_high); |
|---|
| 289 | + |
|---|
| 290 | + if (type & IRQ_TYPE_EDGE_BOTH) |
|---|
| 291 | + irq_set_handler_locked(d, handle_edge_irq); |
|---|
| 292 | + else |
|---|
| 293 | + irq_set_handler_locked(d, handle_level_irq); |
|---|
| 294 | + |
|---|
| 296 | 295 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
|---|
| 297 | 296 | |
|---|
| 298 | 297 | dev_dbg(chip->dev, |
|---|
| .. | .. |
|---|
| 301 | 300 | |
|---|
| 302 | 301 | return 0; |
|---|
| 303 | 302 | } |
|---|
| 304 | | - |
|---|
| 305 | | -static struct irq_chip iproc_gpio_irq_chip = { |
|---|
| 306 | | - .name = "bcm-iproc-gpio", |
|---|
| 307 | | - .irq_ack = iproc_gpio_irq_ack, |
|---|
| 308 | | - .irq_mask = iproc_gpio_irq_mask, |
|---|
| 309 | | - .irq_unmask = iproc_gpio_irq_unmask, |
|---|
| 310 | | - .irq_set_type = iproc_gpio_irq_set_type, |
|---|
| 311 | | -}; |
|---|
| 312 | 303 | |
|---|
| 313 | 304 | /* |
|---|
| 314 | 305 | * Request the Iproc IOMUX pinmux controller to mux individual pins to GPIO |
|---|
| .. | .. |
|---|
| 364 | 355 | dev_dbg(chip->dev, "gpio:%u set output, value:%d\n", gpio, val); |
|---|
| 365 | 356 | |
|---|
| 366 | 357 | return 0; |
|---|
| 358 | +} |
|---|
| 359 | + |
|---|
| 360 | +static int iproc_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio) |
|---|
| 361 | +{ |
|---|
| 362 | + struct iproc_gpio *chip = gpiochip_get_data(gc); |
|---|
| 363 | + unsigned int offset = IPROC_GPIO_REG(gpio, IPROC_GPIO_OUT_EN_OFFSET); |
|---|
| 364 | + unsigned int shift = IPROC_GPIO_SHIFT(gpio); |
|---|
| 365 | + |
|---|
| 366 | + if (readl(chip->base + offset) & BIT(shift)) |
|---|
| 367 | + return GPIO_LINE_DIRECTION_OUT; |
|---|
| 368 | + |
|---|
| 369 | + return GPIO_LINE_DIRECTION_IN; |
|---|
| 367 | 370 | } |
|---|
| 368 | 371 | |
|---|
| 369 | 372 | static void iproc_gpio_set(struct gpio_chip *gc, unsigned gpio, int val) |
|---|
| .. | .. |
|---|
| 801 | 804 | chip->dev = dev; |
|---|
| 802 | 805 | platform_set_drvdata(pdev, chip); |
|---|
| 803 | 806 | |
|---|
| 804 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 805 | | - chip->base = devm_ioremap_resource(dev, res); |
|---|
| 807 | + chip->base = devm_platform_ioremap_resource(pdev, 0); |
|---|
| 806 | 808 | if (IS_ERR(chip->base)) { |
|---|
| 807 | 809 | dev_err(dev, "unable to map I/O memory\n"); |
|---|
| 808 | 810 | return PTR_ERR(chip->base); |
|---|
| .. | .. |
|---|
| 842 | 844 | gc->free = iproc_gpio_free; |
|---|
| 843 | 845 | gc->direction_input = iproc_gpio_direction_input; |
|---|
| 844 | 846 | gc->direction_output = iproc_gpio_direction_output; |
|---|
| 847 | + gc->get_direction = iproc_gpio_get_direction; |
|---|
| 845 | 848 | gc->set = iproc_gpio_set; |
|---|
| 846 | 849 | gc->get = iproc_gpio_get; |
|---|
| 847 | 850 | |
|---|
| 848 | 851 | chip->pinmux_is_supported = of_property_read_bool(dev->of_node, |
|---|
| 849 | 852 | "gpio-ranges"); |
|---|
| 853 | + |
|---|
| 854 | + /* optional GPIO interrupt support */ |
|---|
| 855 | + irq = platform_get_irq_optional(pdev, 0); |
|---|
| 856 | + if (irq > 0) { |
|---|
| 857 | + struct irq_chip *irqc; |
|---|
| 858 | + struct gpio_irq_chip *girq; |
|---|
| 859 | + |
|---|
| 860 | + irqc = &chip->irqchip; |
|---|
| 861 | + irqc->name = dev_name(dev); |
|---|
| 862 | + irqc->irq_ack = iproc_gpio_irq_ack; |
|---|
| 863 | + irqc->irq_mask = iproc_gpio_irq_mask; |
|---|
| 864 | + irqc->irq_unmask = iproc_gpio_irq_unmask; |
|---|
| 865 | + irqc->irq_set_type = iproc_gpio_irq_set_type; |
|---|
| 866 | + irqc->irq_enable = iproc_gpio_irq_unmask; |
|---|
| 867 | + irqc->irq_disable = iproc_gpio_irq_mask; |
|---|
| 868 | + |
|---|
| 869 | + girq = &gc->irq; |
|---|
| 870 | + girq->chip = irqc; |
|---|
| 871 | + girq->parent_handler = iproc_gpio_irq_handler; |
|---|
| 872 | + girq->num_parents = 1; |
|---|
| 873 | + girq->parents = devm_kcalloc(dev, 1, |
|---|
| 874 | + sizeof(*girq->parents), |
|---|
| 875 | + GFP_KERNEL); |
|---|
| 876 | + if (!girq->parents) |
|---|
| 877 | + return -ENOMEM; |
|---|
| 878 | + girq->parents[0] = irq; |
|---|
| 879 | + girq->default_type = IRQ_TYPE_NONE; |
|---|
| 880 | + girq->handler = handle_bad_irq; |
|---|
| 881 | + } |
|---|
| 850 | 882 | |
|---|
| 851 | 883 | ret = gpiochip_add_data(gc, chip); |
|---|
| 852 | 884 | if (ret < 0) { |
|---|
| .. | .. |
|---|
| 870 | 902 | goto err_rm_gpiochip; |
|---|
| 871 | 903 | } |
|---|
| 872 | 904 | } |
|---|
| 873 | | - } |
|---|
| 874 | | - |
|---|
| 875 | | - /* optional GPIO interrupt support */ |
|---|
| 876 | | - irq = platform_get_irq(pdev, 0); |
|---|
| 877 | | - if (irq) { |
|---|
| 878 | | - ret = gpiochip_irqchip_add(gc, &iproc_gpio_irq_chip, 0, |
|---|
| 879 | | - handle_simple_irq, IRQ_TYPE_NONE); |
|---|
| 880 | | - if (ret) { |
|---|
| 881 | | - dev_err(dev, "no GPIO irqchip\n"); |
|---|
| 882 | | - goto err_rm_gpiochip; |
|---|
| 883 | | - } |
|---|
| 884 | | - |
|---|
| 885 | | - gpiochip_set_chained_irqchip(gc, &iproc_gpio_irq_chip, irq, |
|---|
| 886 | | - iproc_gpio_irq_handler); |
|---|
| 887 | 905 | } |
|---|
| 888 | 906 | |
|---|
| 889 | 907 | return 0; |
|---|