| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Oxford Semiconductor OXNAS SoC Family pinctrl driver |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 6 | 7 | * Based on pinctrl-pic32.c |
|---|
| 7 | 8 | * Joshua Henderson, <joshua.henderson@microchip.com> |
|---|
| 8 | 9 | * Copyright (C) 2015 Microchip Technology Inc. All rights reserved. |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is free software; you can distribute it and/or modify it |
|---|
| 11 | | - * under the terms of the GNU General Public License (Version 2) as |
|---|
| 12 | | - * published by the Free Software Foundation. |
|---|
| 13 | | - * |
|---|
| 14 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
|---|
| 15 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 16 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|---|
| 17 | | - * for more details. |
|---|
| 18 | 10 | */ |
|---|
| 19 | 11 | #include <linux/gpio/driver.h> |
|---|
| 20 | 12 | #include <linux/interrupt.h> |
|---|
| .. | .. |
|---|
| 764 | 756 | struct oxnas_gpio_bank *bank = gpiochip_get_data(chip); |
|---|
| 765 | 757 | u32 mask = BIT(offset); |
|---|
| 766 | 758 | |
|---|
| 767 | | - return !(readl_relaxed(bank->reg_base + OUTPUT_EN) & mask); |
|---|
| 759 | + if (readl_relaxed(bank->reg_base + OUTPUT_EN) & mask) |
|---|
| 760 | + return GPIO_LINE_DIRECTION_OUT; |
|---|
| 761 | + |
|---|
| 762 | + return GPIO_LINE_DIRECTION_IN; |
|---|
| 768 | 763 | } |
|---|
| 769 | 764 | |
|---|
| 770 | 765 | static int oxnas_gpio_direction_input(struct gpio_chip *chip, |
|---|
| .. | .. |
|---|
| 910 | 905 | struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
|---|
| 911 | 906 | struct oxnas_gpio_bank *bank = pctl_to_bank(pctl, pin); |
|---|
| 912 | 907 | unsigned int param; |
|---|
| 913 | | - u32 arg; |
|---|
| 914 | 908 | unsigned int i; |
|---|
| 915 | 909 | u32 offset = pin - bank->gpio_chip.base; |
|---|
| 916 | 910 | u32 mask = BIT(offset); |
|---|
| .. | .. |
|---|
| 920 | 914 | |
|---|
| 921 | 915 | for (i = 0; i < num_configs; i++) { |
|---|
| 922 | 916 | param = pinconf_to_config_param(configs[i]); |
|---|
| 923 | | - arg = pinconf_to_config_argument(configs[i]); |
|---|
| 924 | 917 | |
|---|
| 925 | 918 | switch (param) { |
|---|
| 926 | 919 | case PIN_CONFIG_BIAS_PULL_UP: |
|---|
| .. | .. |
|---|
| 949 | 942 | struct oxnas_gpio_bank *bank = pctl_to_bank(pctl, pin); |
|---|
| 950 | 943 | unsigned int bank_offset = (bank->id ? PINMUX_820_BANK_OFFSET : 0); |
|---|
| 951 | 944 | unsigned int param; |
|---|
| 952 | | - u32 arg; |
|---|
| 953 | 945 | unsigned int i; |
|---|
| 954 | 946 | u32 offset = pin - bank->gpio_chip.base; |
|---|
| 955 | 947 | u32 mask = BIT(offset); |
|---|
| .. | .. |
|---|
| 959 | 951 | |
|---|
| 960 | 952 | for (i = 0; i < num_configs; i++) { |
|---|
| 961 | 953 | param = pinconf_to_config_param(configs[i]); |
|---|
| 962 | | - arg = pinconf_to_config_argument(configs[i]); |
|---|
| 963 | 954 | |
|---|
| 964 | 955 | switch (param) { |
|---|
| 965 | 956 | case PIN_CONFIG_BIAS_PULL_UP: |
|---|
| .. | .. |
|---|
| 1208 | 1199 | struct oxnas_gpio_bank *bank; |
|---|
| 1209 | 1200 | unsigned int id, ngpios; |
|---|
| 1210 | 1201 | int irq, ret; |
|---|
| 1211 | | - struct resource *res; |
|---|
| 1202 | + struct gpio_irq_chip *girq; |
|---|
| 1212 | 1203 | |
|---|
| 1213 | 1204 | if (of_parse_phandle_with_fixed_args(np, "gpio-ranges", |
|---|
| 1214 | 1205 | 3, 0, &pinspec)) { |
|---|
| .. | .. |
|---|
| 1231 | 1222 | |
|---|
| 1232 | 1223 | bank = &oxnas_gpio_banks[id]; |
|---|
| 1233 | 1224 | |
|---|
| 1234 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 1235 | | - bank->reg_base = devm_ioremap_resource(&pdev->dev, res); |
|---|
| 1225 | + bank->reg_base = devm_platform_ioremap_resource(pdev, 0); |
|---|
| 1236 | 1226 | if (IS_ERR(bank->reg_base)) |
|---|
| 1237 | 1227 | return PTR_ERR(bank->reg_base); |
|---|
| 1238 | 1228 | |
|---|
| 1239 | 1229 | irq = platform_get_irq(pdev, 0); |
|---|
| 1240 | | - if (irq < 0) { |
|---|
| 1241 | | - dev_err(&pdev->dev, "irq get failed\n"); |
|---|
| 1230 | + if (irq < 0) |
|---|
| 1242 | 1231 | return irq; |
|---|
| 1243 | | - } |
|---|
| 1244 | 1232 | |
|---|
| 1245 | 1233 | bank->id = id; |
|---|
| 1246 | 1234 | bank->gpio_chip.parent = &pdev->dev; |
|---|
| 1247 | 1235 | bank->gpio_chip.of_node = np; |
|---|
| 1248 | 1236 | bank->gpio_chip.ngpio = ngpios; |
|---|
| 1237 | + girq = &bank->gpio_chip.irq; |
|---|
| 1238 | + girq->chip = &bank->irq_chip; |
|---|
| 1239 | + girq->parent_handler = oxnas_gpio_irq_handler; |
|---|
| 1240 | + girq->num_parents = 1; |
|---|
| 1241 | + girq->parents = devm_kcalloc(&pdev->dev, 1, sizeof(*girq->parents), |
|---|
| 1242 | + GFP_KERNEL); |
|---|
| 1243 | + if (!girq->parents) |
|---|
| 1244 | + return -ENOMEM; |
|---|
| 1245 | + girq->parents[0] = irq; |
|---|
| 1246 | + girq->default_type = IRQ_TYPE_NONE; |
|---|
| 1247 | + girq->handler = handle_level_irq; |
|---|
| 1248 | + |
|---|
| 1249 | 1249 | ret = gpiochip_add_data(&bank->gpio_chip, bank); |
|---|
| 1250 | 1250 | if (ret < 0) { |
|---|
| 1251 | 1251 | dev_err(&pdev->dev, "Failed to add GPIO chip %u: %d\n", |
|---|
| 1252 | 1252 | id, ret); |
|---|
| 1253 | 1253 | return ret; |
|---|
| 1254 | 1254 | } |
|---|
| 1255 | | - |
|---|
| 1256 | | - ret = gpiochip_irqchip_add(&bank->gpio_chip, &bank->irq_chip, |
|---|
| 1257 | | - 0, handle_level_irq, IRQ_TYPE_NONE); |
|---|
| 1258 | | - if (ret < 0) { |
|---|
| 1259 | | - dev_err(&pdev->dev, "Failed to add IRQ chip %u: %d\n", |
|---|
| 1260 | | - id, ret); |
|---|
| 1261 | | - gpiochip_remove(&bank->gpio_chip); |
|---|
| 1262 | | - return ret; |
|---|
| 1263 | | - } |
|---|
| 1264 | | - |
|---|
| 1265 | | - gpiochip_set_chained_irqchip(&bank->gpio_chip, &bank->irq_chip, |
|---|
| 1266 | | - irq, oxnas_gpio_irq_handler); |
|---|
| 1267 | 1255 | |
|---|
| 1268 | 1256 | return 0; |
|---|
| 1269 | 1257 | } |
|---|