.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or modify |
---|
5 | | - * it under the terms of the GNU General Public License version 2 and |
---|
6 | | - * only version 2 as published by the Free Software Foundation. |
---|
7 | | - * |
---|
8 | | - * This program is distributed in the hope that it will be useful, |
---|
9 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
10 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
11 | | - * GNU General Public License for more details. |
---|
12 | 4 | */ |
---|
13 | 5 | |
---|
14 | | -#include <linux/gpio.h> |
---|
| 6 | +#include <linux/gpio/driver.h> |
---|
| 7 | +#include <linux/interrupt.h> |
---|
15 | 8 | #include <linux/module.h> |
---|
16 | 9 | #include <linux/of.h> |
---|
17 | 10 | #include <linux/of_irq.h> |
---|
.. | .. |
---|
136 | 129 | /** |
---|
137 | 130 | * struct pmic_gpio_pad - keep current GPIO settings |
---|
138 | 131 | * @base: Address base in SPMI device. |
---|
139 | | - * @irq: IRQ number which this GPIO generate. |
---|
140 | 132 | * @is_enabled: Set to false when GPIO should be put in high Z state. |
---|
141 | 133 | * @out_value: Cached pin output value |
---|
142 | 134 | * @have_buffer: Set to true if GPIO output could be configured in push-pull, |
---|
.. | .. |
---|
156 | 148 | */ |
---|
157 | 149 | struct pmic_gpio_pad { |
---|
158 | 150 | u16 base; |
---|
159 | | - int irq; |
---|
160 | 151 | bool is_enabled; |
---|
161 | 152 | bool out_value; |
---|
162 | 153 | bool have_buffer; |
---|
.. | .. |
---|
179 | 170 | struct regmap *map; |
---|
180 | 171 | struct pinctrl_dev *ctrl; |
---|
181 | 172 | struct gpio_chip chip; |
---|
| 173 | + struct irq_chip irq; |
---|
182 | 174 | }; |
---|
183 | 175 | |
---|
184 | 176 | static const struct pinconf_generic_params pmic_gpio_bindings[] = { |
---|
.. | .. |
---|
674 | 666 | else |
---|
675 | 667 | seq_printf(s, " %-4s", |
---|
676 | 668 | pad->output_enabled ? "out" : "in"); |
---|
| 669 | + seq_printf(s, " %-4s", pad->out_value ? "high" : "low"); |
---|
677 | 670 | seq_printf(s, " %-7s", pmic_gpio_functions[function]); |
---|
678 | 671 | seq_printf(s, " vin-%d", pad->power_source); |
---|
679 | 672 | seq_printf(s, " %-27s", biases[pad->pullup]); |
---|
680 | 673 | seq_printf(s, " %-10s", buffer_types[pad->buffer_type]); |
---|
681 | | - seq_printf(s, " %-4s", pad->out_value ? "high" : "low"); |
---|
682 | 674 | seq_printf(s, " %-7s", strengths[pad->strength]); |
---|
683 | 675 | seq_printf(s, " atest-%d", pad->atest); |
---|
684 | 676 | seq_printf(s, " dtest-%d", pad->dtest_buffer); |
---|
.. | .. |
---|
758 | 750 | return gpio_desc->args[0] - PMIC_GPIO_PHYSICAL_OFFSET; |
---|
759 | 751 | } |
---|
760 | 752 | |
---|
761 | | -static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned pin) |
---|
762 | | -{ |
---|
763 | | - struct pmic_gpio_state *state = gpiochip_get_data(chip); |
---|
764 | | - struct pmic_gpio_pad *pad; |
---|
765 | | - |
---|
766 | | - pad = state->ctrl->desc->pins[pin].drv_data; |
---|
767 | | - |
---|
768 | | - return pad->irq; |
---|
769 | | -} |
---|
770 | | - |
---|
771 | 753 | static void pmic_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) |
---|
772 | 754 | { |
---|
773 | 755 | struct pmic_gpio_state *state = gpiochip_get_data(chip); |
---|
.. | .. |
---|
787 | 769 | .request = gpiochip_generic_request, |
---|
788 | 770 | .free = gpiochip_generic_free, |
---|
789 | 771 | .of_xlate = pmic_gpio_of_xlate, |
---|
790 | | - .to_irq = pmic_gpio_to_irq, |
---|
791 | 772 | .dbg_show = pmic_gpio_dbg_show, |
---|
792 | 773 | }; |
---|
793 | 774 | |
---|
.. | .. |
---|
813 | 794 | switch (subtype) { |
---|
814 | 795 | case PMIC_GPIO_SUBTYPE_GPIO_4CH: |
---|
815 | 796 | pad->have_buffer = true; |
---|
| 797 | + fallthrough; |
---|
816 | 798 | case PMIC_GPIO_SUBTYPE_GPIOC_4CH: |
---|
817 | 799 | pad->num_sources = 4; |
---|
818 | 800 | break; |
---|
819 | 801 | case PMIC_GPIO_SUBTYPE_GPIO_8CH: |
---|
820 | 802 | pad->have_buffer = true; |
---|
| 803 | + fallthrough; |
---|
821 | 804 | case PMIC_GPIO_SUBTYPE_GPIOC_8CH: |
---|
822 | 805 | pad->num_sources = 8; |
---|
823 | 806 | break; |
---|
.. | .. |
---|
935 | 918 | return 0; |
---|
936 | 919 | } |
---|
937 | 920 | |
---|
| 921 | +static int pmic_gpio_domain_translate(struct irq_domain *domain, |
---|
| 922 | + struct irq_fwspec *fwspec, |
---|
| 923 | + unsigned long *hwirq, |
---|
| 924 | + unsigned int *type) |
---|
| 925 | +{ |
---|
| 926 | + struct pmic_gpio_state *state = container_of(domain->host_data, |
---|
| 927 | + struct pmic_gpio_state, |
---|
| 928 | + chip); |
---|
| 929 | + |
---|
| 930 | + if (fwspec->param_count != 2 || |
---|
| 931 | + fwspec->param[0] < 1 || fwspec->param[0] > state->chip.ngpio) |
---|
| 932 | + return -EINVAL; |
---|
| 933 | + |
---|
| 934 | + *hwirq = fwspec->param[0] - PMIC_GPIO_PHYSICAL_OFFSET; |
---|
| 935 | + *type = fwspec->param[1]; |
---|
| 936 | + |
---|
| 937 | + return 0; |
---|
| 938 | +} |
---|
| 939 | + |
---|
| 940 | +static unsigned int pmic_gpio_child_offset_to_irq(struct gpio_chip *chip, |
---|
| 941 | + unsigned int offset) |
---|
| 942 | +{ |
---|
| 943 | + return offset + PMIC_GPIO_PHYSICAL_OFFSET; |
---|
| 944 | +} |
---|
| 945 | + |
---|
| 946 | +static int pmic_gpio_child_to_parent_hwirq(struct gpio_chip *chip, |
---|
| 947 | + unsigned int child_hwirq, |
---|
| 948 | + unsigned int child_type, |
---|
| 949 | + unsigned int *parent_hwirq, |
---|
| 950 | + unsigned int *parent_type) |
---|
| 951 | +{ |
---|
| 952 | + *parent_hwirq = child_hwirq + 0xc0; |
---|
| 953 | + *parent_type = child_type; |
---|
| 954 | + |
---|
| 955 | + return 0; |
---|
| 956 | +} |
---|
| 957 | + |
---|
938 | 958 | static int pmic_gpio_probe(struct platform_device *pdev) |
---|
939 | 959 | { |
---|
| 960 | + struct irq_domain *parent_domain; |
---|
| 961 | + struct device_node *parent_node; |
---|
940 | 962 | struct device *dev = &pdev->dev; |
---|
941 | 963 | struct pinctrl_pin_desc *pindesc; |
---|
942 | 964 | struct pinctrl_desc *pctrldesc; |
---|
943 | 965 | struct pmic_gpio_pad *pad, *pads; |
---|
944 | 966 | struct pmic_gpio_state *state; |
---|
| 967 | + struct gpio_irq_chip *girq; |
---|
945 | 968 | int ret, npins, i; |
---|
946 | 969 | u32 reg; |
---|
947 | 970 | |
---|
.. | .. |
---|
951 | 974 | return ret; |
---|
952 | 975 | } |
---|
953 | 976 | |
---|
954 | | - npins = platform_irq_count(pdev); |
---|
955 | | - if (!npins) |
---|
956 | | - return -EINVAL; |
---|
957 | | - if (npins < 0) |
---|
958 | | - return npins; |
---|
959 | | - |
---|
960 | | - BUG_ON(npins > ARRAY_SIZE(pmic_gpio_groups)); |
---|
| 977 | + npins = (uintptr_t) device_get_match_data(&pdev->dev); |
---|
961 | 978 | |
---|
962 | 979 | state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL); |
---|
963 | 980 | if (!state) |
---|
.. | .. |
---|
999 | 1016 | pindesc->number = i; |
---|
1000 | 1017 | pindesc->name = pmic_gpio_groups[i]; |
---|
1001 | 1018 | |
---|
1002 | | - pad->irq = platform_get_irq(pdev, i); |
---|
1003 | | - if (pad->irq < 0) |
---|
1004 | | - return pad->irq; |
---|
1005 | | - |
---|
1006 | 1019 | pad->base = reg + i * PMIC_GPIO_ADDRESS_RANGE; |
---|
1007 | 1020 | |
---|
1008 | 1021 | ret = pmic_gpio_populate(state, pad); |
---|
.. | .. |
---|
1021 | 1034 | state->ctrl = devm_pinctrl_register(dev, pctrldesc, state); |
---|
1022 | 1035 | if (IS_ERR(state->ctrl)) |
---|
1023 | 1036 | return PTR_ERR(state->ctrl); |
---|
| 1037 | + |
---|
| 1038 | + parent_node = of_irq_find_parent(state->dev->of_node); |
---|
| 1039 | + if (!parent_node) |
---|
| 1040 | + return -ENXIO; |
---|
| 1041 | + |
---|
| 1042 | + parent_domain = irq_find_host(parent_node); |
---|
| 1043 | + of_node_put(parent_node); |
---|
| 1044 | + if (!parent_domain) |
---|
| 1045 | + return -ENXIO; |
---|
| 1046 | + |
---|
| 1047 | + state->irq.name = "spmi-gpio", |
---|
| 1048 | + state->irq.irq_ack = irq_chip_ack_parent, |
---|
| 1049 | + state->irq.irq_mask = irq_chip_mask_parent, |
---|
| 1050 | + state->irq.irq_unmask = irq_chip_unmask_parent, |
---|
| 1051 | + state->irq.irq_set_type = irq_chip_set_type_parent, |
---|
| 1052 | + state->irq.irq_set_wake = irq_chip_set_wake_parent, |
---|
| 1053 | + state->irq.flags = IRQCHIP_MASK_ON_SUSPEND, |
---|
| 1054 | + |
---|
| 1055 | + girq = &state->chip.irq; |
---|
| 1056 | + girq->chip = &state->irq; |
---|
| 1057 | + girq->default_type = IRQ_TYPE_NONE; |
---|
| 1058 | + girq->handler = handle_level_irq; |
---|
| 1059 | + girq->fwnode = of_node_to_fwnode(state->dev->of_node); |
---|
| 1060 | + girq->parent_domain = parent_domain; |
---|
| 1061 | + girq->child_to_parent_hwirq = pmic_gpio_child_to_parent_hwirq; |
---|
| 1062 | + girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_fourcell; |
---|
| 1063 | + girq->child_offset_to_irq = pmic_gpio_child_offset_to_irq; |
---|
| 1064 | + girq->child_irq_domain_ops.translate = pmic_gpio_domain_translate; |
---|
1024 | 1065 | |
---|
1025 | 1066 | ret = gpiochip_add_data(&state->chip, state); |
---|
1026 | 1067 | if (ret) { |
---|
.. | .. |
---|
1063 | 1104 | } |
---|
1064 | 1105 | |
---|
1065 | 1106 | static const struct of_device_id pmic_gpio_of_match[] = { |
---|
1066 | | - { .compatible = "qcom,pm8916-gpio" }, /* 4 GPIO's */ |
---|
1067 | | - { .compatible = "qcom,pm8941-gpio" }, /* 36 GPIO's */ |
---|
1068 | | - { .compatible = "qcom,pm8994-gpio" }, /* 22 GPIO's */ |
---|
1069 | | - { .compatible = "qcom,pmi8994-gpio" }, /* 10 GPIO's */ |
---|
1070 | | - { .compatible = "qcom,pma8084-gpio" }, /* 22 GPIO's */ |
---|
1071 | | - { .compatible = "qcom,spmi-gpio" }, /* Generic */ |
---|
| 1107 | + { .compatible = "qcom,pm8005-gpio", .data = (void *) 4 }, |
---|
| 1108 | + { .compatible = "qcom,pm8916-gpio", .data = (void *) 4 }, |
---|
| 1109 | + { .compatible = "qcom,pm8941-gpio", .data = (void *) 36 }, |
---|
| 1110 | + /* pm8950 has 8 GPIOs with holes on 3 */ |
---|
| 1111 | + { .compatible = "qcom,pm8950-gpio", .data = (void *) 8 }, |
---|
| 1112 | + { .compatible = "qcom,pmi8950-gpio", .data = (void *) 2 }, |
---|
| 1113 | + { .compatible = "qcom,pm8994-gpio", .data = (void *) 22 }, |
---|
| 1114 | + { .compatible = "qcom,pmi8994-gpio", .data = (void *) 10 }, |
---|
| 1115 | + { .compatible = "qcom,pm8998-gpio", .data = (void *) 26 }, |
---|
| 1116 | + { .compatible = "qcom,pmi8998-gpio", .data = (void *) 14 }, |
---|
| 1117 | + { .compatible = "qcom,pma8084-gpio", .data = (void *) 22 }, |
---|
| 1118 | + /* pms405 has 12 GPIOs with holes on 1, 9, and 10 */ |
---|
| 1119 | + { .compatible = "qcom,pms405-gpio", .data = (void *) 12 }, |
---|
| 1120 | + /* pm660 has 13 GPIOs with holes on 1, 5, 6, 7, 8 and 10 */ |
---|
| 1121 | + { .compatible = "qcom,pm660-gpio", .data = (void *) 13 }, |
---|
| 1122 | + /* pm660l has 12 GPIOs with holes on 1, 2, 10, 11 and 12 */ |
---|
| 1123 | + { .compatible = "qcom,pm660l-gpio", .data = (void *) 12 }, |
---|
| 1124 | + /* pm8150 has 10 GPIOs with holes on 2, 5, 7 and 8 */ |
---|
| 1125 | + { .compatible = "qcom,pm8150-gpio", .data = (void *) 10 }, |
---|
| 1126 | + /* pm8150b has 12 GPIOs with holes on 3, r and 7 */ |
---|
| 1127 | + { .compatible = "qcom,pm8150b-gpio", .data = (void *) 12 }, |
---|
| 1128 | + /* pm8150l has 12 GPIOs with holes on 7 */ |
---|
| 1129 | + { .compatible = "qcom,pm8150l-gpio", .data = (void *) 12 }, |
---|
| 1130 | + { .compatible = "qcom,pm6150-gpio", .data = (void *) 10 }, |
---|
| 1131 | + { .compatible = "qcom,pm6150l-gpio", .data = (void *) 12 }, |
---|
1072 | 1132 | { }, |
---|
1073 | 1133 | }; |
---|
1074 | 1134 | |
---|