hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
....@@ -1,15 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2015, Sony Mobile Communications AB.
34 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
4
- *
5
- * This program is free software; you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License version 2 and
7
- * only version 2 as published by the Free Software Foundation.
8
- *
9
- * This program is distributed in the hope that it will be useful,
10
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- * GNU General Public License for more details.
135 */
146
157 #include <linux/module.h>
....@@ -20,7 +12,7 @@
2012 #include <linux/pinctrl/pinconf-generic.h>
2113 #include <linux/slab.h>
2214 #include <linux/regmap.h>
23
-#include <linux/gpio.h>
15
+#include <linux/gpio/driver.h>
2416 #include <linux/interrupt.h>
2517 #include <linux/of_device.h>
2618 #include <linux/of_irq.h>
....@@ -55,6 +47,8 @@
5547
5648 #define PM8XXX_MAX_GPIOS 44
5749
50
+#define PM8XXX_GPIO_PHYSICAL_OFFSET 1
51
+
5852 /* custom pinconf parameters */
5953 #define PM8XXX_QCOM_DRIVE_STRENGH (PIN_CONFIG_END + 1)
6054 #define PM8XXX_QCOM_PULL_UP_STRENGTH (PIN_CONFIG_END + 2)
....@@ -62,7 +56,6 @@
6256 /**
6357 * struct pm8xxx_pin_data - dynamic configuration for a pin
6458 * @reg: address of the control register
65
- * @irq: IRQ from the PMIC interrupt controller
6659 * @power_source: logical selected voltage source, mapping in static data
6760 * is used translate to register values
6861 * @mode: operating mode for the pin (input/output)
....@@ -78,7 +71,6 @@
7871 */
7972 struct pm8xxx_pin_data {
8073 unsigned reg;
81
- int irq;
8274 u8 power_source;
8375 u8 mode;
8476 bool open_drain;
....@@ -354,7 +346,7 @@
354346 return -EINVAL;
355347 }
356348 pin->pull_up_strength = arg;
357
- /* FALLTHROUGH */
349
+ fallthrough;
358350 case PIN_CONFIG_BIAS_PULL_UP:
359351 pin->bias = pin->pull_up_strength;
360352 banks |= BIT(2);
....@@ -447,7 +439,7 @@
447439 .pin_config_group_set = pm8xxx_pin_config_set,
448440 };
449441
450
-static struct pinctrl_desc pm8xxx_pinctrl_desc = {
442
+static const struct pinctrl_desc pm8xxx_pinctrl_desc = {
451443 .name = "pm8xxx_gpio",
452444 .pctlops = &pm8xxx_pinctrl_ops,
453445 .pmxops = &pm8xxx_pinmux_ops,
....@@ -494,16 +486,20 @@
494486 {
495487 struct pm8xxx_gpio *pctrl = gpiochip_get_data(chip);
496488 struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
489
+ int ret, irq;
497490 bool state;
498
- int ret;
499491
500
- if (pin->mode == PM8XXX_GPIO_MODE_OUTPUT) {
501
- ret = pin->output_value;
502
- } else {
503
- ret = irq_get_irqchip_state(pin->irq, IRQCHIP_STATE_LINE_LEVEL, &state);
492
+ if (pin->mode == PM8XXX_GPIO_MODE_OUTPUT)
493
+ return pin->output_value;
494
+
495
+ irq = chip->to_irq(chip, offset);
496
+ if (irq >= 0) {
497
+ ret = irq_get_irqchip_state(irq, IRQCHIP_STATE_LINE_LEVEL,
498
+ &state);
504499 if (!ret)
505500 ret = !!state;
506
- }
501
+ } else
502
+ ret = -EINVAL;
507503
508504 return ret;
509505 }
....@@ -533,17 +529,9 @@
533529 if (flags)
534530 *flags = gpio_desc->args[1];
535531
536
- return gpio_desc->args[0] - 1;
532
+ return gpio_desc->args[0] - PM8XXX_GPIO_PHYSICAL_OFFSET;
537533 }
538534
539
-
540
-static int pm8xxx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
541
-{
542
- struct pm8xxx_gpio *pctrl = gpiochip_get_data(chip);
543
- struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
544
-
545
- return pin->irq;
546
-}
547535
548536 #ifdef CONFIG_DEBUG_FS
549537 #include <linux/seq_file.h>
....@@ -571,7 +559,7 @@
571559 "no", "high", "medium", "low"
572560 };
573561
574
- seq_printf(s, " gpio%-2d:", offset + 1);
562
+ seq_printf(s, " gpio%-2d:", offset + PM8XXX_GPIO_PHYSICAL_OFFSET);
575563 if (pin->disable) {
576564 seq_puts(s, " ---");
577565 } else {
....@@ -608,7 +596,6 @@
608596 .get = pm8xxx_gpio_get,
609597 .set = pm8xxx_gpio_set,
610598 .of_xlate = pm8xxx_gpio_of_xlate,
611
- .to_irq = pm8xxx_gpio_to_irq,
612599 .dbg_show = pm8xxx_gpio_dbg_show,
613600 .owner = THIS_MODULE,
614601 };
....@@ -664,13 +651,56 @@
664651 return 0;
665652 }
666653
654
+static struct irq_chip pm8xxx_irq_chip = {
655
+ .name = "ssbi-gpio",
656
+ .irq_mask_ack = irq_chip_mask_ack_parent,
657
+ .irq_unmask = irq_chip_unmask_parent,
658
+ .irq_set_type = irq_chip_set_type_parent,
659
+ .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
660
+};
661
+
662
+static int pm8xxx_domain_translate(struct irq_domain *domain,
663
+ struct irq_fwspec *fwspec,
664
+ unsigned long *hwirq,
665
+ unsigned int *type)
666
+{
667
+ struct pm8xxx_gpio *pctrl = container_of(domain->host_data,
668
+ struct pm8xxx_gpio, chip);
669
+
670
+ if (fwspec->param_count != 2 || fwspec->param[0] < 1 ||
671
+ fwspec->param[0] > pctrl->chip.ngpio)
672
+ return -EINVAL;
673
+
674
+ *hwirq = fwspec->param[0] - PM8XXX_GPIO_PHYSICAL_OFFSET;
675
+ *type = fwspec->param[1];
676
+
677
+ return 0;
678
+}
679
+
680
+static unsigned int pm8xxx_child_offset_to_irq(struct gpio_chip *chip,
681
+ unsigned int offset)
682
+{
683
+ return offset + PM8XXX_GPIO_PHYSICAL_OFFSET;
684
+}
685
+
686
+static int pm8xxx_child_to_parent_hwirq(struct gpio_chip *chip,
687
+ unsigned int child_hwirq,
688
+ unsigned int child_type,
689
+ unsigned int *parent_hwirq,
690
+ unsigned int *parent_type)
691
+{
692
+ *parent_hwirq = child_hwirq + 0xc0;
693
+ *parent_type = child_type;
694
+
695
+ return 0;
696
+}
697
+
667698 static const struct of_device_id pm8xxx_gpio_of_match[] = {
668
- { .compatible = "qcom,pm8018-gpio" },
669
- { .compatible = "qcom,pm8038-gpio" },
670
- { .compatible = "qcom,pm8058-gpio" },
671
- { .compatible = "qcom,pm8917-gpio" },
672
- { .compatible = "qcom,pm8921-gpio" },
673
- { .compatible = "qcom,ssbi-gpio" },
699
+ { .compatible = "qcom,pm8018-gpio", .data = (void *) 6 },
700
+ { .compatible = "qcom,pm8038-gpio", .data = (void *) 12 },
701
+ { .compatible = "qcom,pm8058-gpio", .data = (void *) 44 },
702
+ { .compatible = "qcom,pm8917-gpio", .data = (void *) 38 },
703
+ { .compatible = "qcom,pm8921-gpio", .data = (void *) 44 },
674704 { },
675705 };
676706 MODULE_DEVICE_TABLE(of, pm8xxx_gpio_of_match);
....@@ -678,22 +708,19 @@
678708 static int pm8xxx_gpio_probe(struct platform_device *pdev)
679709 {
680710 struct pm8xxx_pin_data *pin_data;
711
+ struct irq_domain *parent_domain;
712
+ struct device_node *parent_node;
681713 struct pinctrl_pin_desc *pins;
714
+ struct gpio_irq_chip *girq;
682715 struct pm8xxx_gpio *pctrl;
683
- int ret;
684
- int i, npins;
716
+ int ret, i;
685717
686718 pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
687719 if (!pctrl)
688720 return -ENOMEM;
689721
690722 pctrl->dev = &pdev->dev;
691
- npins = platform_irq_count(pdev);
692
- if (!npins)
693
- return -EINVAL;
694
- if (npins < 0)
695
- return npins;
696
- pctrl->npins = npins;
723
+ pctrl->npins = (uintptr_t) device_get_match_data(&pdev->dev);
697724
698725 pctrl->regmap = dev_get_regmap(pdev->dev.parent, NULL);
699726 if (!pctrl->regmap) {
....@@ -720,12 +747,6 @@
720747
721748 for (i = 0; i < pctrl->desc.npins; i++) {
722749 pin_data[i].reg = SSBI_REG_ADDR_GPIO(i);
723
- pin_data[i].irq = platform_get_irq(pdev, i);
724
- if (pin_data[i].irq < 0) {
725
- dev_err(&pdev->dev,
726
- "missing interrupts for pin %d\n", i);
727
- return pin_data[i].irq;
728
- }
729750
730751 ret = pm8xxx_pin_populate(pctrl, &pin_data[i]);
731752 if (ret)
....@@ -756,6 +777,27 @@
756777 pctrl->chip.of_gpio_n_cells = 2;
757778 pctrl->chip.label = dev_name(pctrl->dev);
758779 pctrl->chip.ngpio = pctrl->npins;
780
+
781
+ parent_node = of_irq_find_parent(pctrl->dev->of_node);
782
+ if (!parent_node)
783
+ return -ENXIO;
784
+
785
+ parent_domain = irq_find_host(parent_node);
786
+ of_node_put(parent_node);
787
+ if (!parent_domain)
788
+ return -ENXIO;
789
+
790
+ girq = &pctrl->chip.irq;
791
+ girq->chip = &pm8xxx_irq_chip;
792
+ girq->default_type = IRQ_TYPE_NONE;
793
+ girq->handler = handle_level_irq;
794
+ girq->fwnode = of_node_to_fwnode(pctrl->dev->of_node);
795
+ girq->parent_domain = parent_domain;
796
+ girq->child_to_parent_hwirq = pm8xxx_child_to_parent_hwirq;
797
+ girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_twocell;
798
+ girq->child_offset_to_irq = pm8xxx_child_offset_to_irq;
799
+ girq->child_irq_domain_ops.translate = pm8xxx_domain_translate;
800
+
759801 ret = gpiochip_add_data(&pctrl->chip, pctrl);
760802 if (ret) {
761803 dev_err(&pdev->dev, "failed register gpiochip\n");