hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/drivers/spmi/spmi-pmic-arb.c
....@@ -1,14 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
2
- * Copyright (c) 2012-2015, 2017, 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.
3
+ * Copyright (c) 2012-2015, 2017, 2021, The Linux Foundation. All rights reserved.
124 */
135 #include <linux/bitmap.h>
146 #include <linux/delay.h>
....@@ -513,8 +505,7 @@
513505 static void periph_interrupt(struct spmi_pmic_arb *pmic_arb, u16 apid)
514506 {
515507 unsigned int irq;
516
- u32 status;
517
- int id;
508
+ u32 status, id;
518509 u8 sid = (pmic_arb->apid_data[apid].ppid >> 8) & 0xF;
519510 u8 per = pmic_arb->apid_data[apid].ppid & 0xFF;
520511
....@@ -666,7 +657,8 @@
666657 return 0;
667658 }
668659
669
-static int qpnpint_irq_request_resources(struct irq_data *d)
660
+static int qpnpint_irq_domain_activate(struct irq_domain *domain,
661
+ struct irq_data *d, bool reserve)
670662 {
671663 struct spmi_pmic_arb *pmic_arb = irq_data_get_irq_chip_data(d);
672664 u16 periph = hwirq_to_per(d->hwirq);
....@@ -692,27 +684,25 @@
692684 .irq_set_type = qpnpint_irq_set_type,
693685 .irq_set_wake = qpnpint_irq_set_wake,
694686 .irq_get_irqchip_state = qpnpint_get_irqchip_state,
695
- .irq_request_resources = qpnpint_irq_request_resources,
696687 .flags = IRQCHIP_MASK_ON_SUSPEND,
697688 };
698689
699
-static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
700
- struct device_node *controller,
701
- const u32 *intspec,
702
- unsigned int intsize,
703
- unsigned long *out_hwirq,
704
- unsigned int *out_type)
690
+static int qpnpint_irq_domain_translate(struct irq_domain *d,
691
+ struct irq_fwspec *fwspec,
692
+ unsigned long *out_hwirq,
693
+ unsigned int *out_type)
705694 {
706695 struct spmi_pmic_arb *pmic_arb = d->host_data;
696
+ u32 *intspec = fwspec->param;
707697 u16 apid, ppid;
708698 int rc;
709699
710700 dev_dbg(&pmic_arb->spmic->dev, "intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x\n",
711701 intspec[0], intspec[1], intspec[2]);
712702
713
- if (irq_domain_get_of_node(d) != controller)
703
+ if (irq_domain_get_of_node(d) != pmic_arb->spmic->dev.of_node)
714704 return -EINVAL;
715
- if (intsize != 4)
705
+ if (fwspec->param_count != 4)
716706 return -EINVAL;
717707 if (intspec[0] > 0xF || intspec[1] > 0xFF || intspec[2] > 0x7)
718708 return -EINVAL;
....@@ -740,17 +730,47 @@
740730 return 0;
741731 }
742732
743
-static int qpnpint_irq_domain_map(struct irq_domain *d,
744
- unsigned int virq,
745
- irq_hw_number_t hwirq)
733
+static struct lock_class_key qpnpint_irq_lock_class, qpnpint_irq_request_class;
734
+
735
+static void qpnpint_irq_domain_map(struct spmi_pmic_arb *pmic_arb,
736
+ struct irq_domain *domain, unsigned int virq,
737
+ irq_hw_number_t hwirq, unsigned int type)
746738 {
747
- struct spmi_pmic_arb *pmic_arb = d->host_data;
739
+ irq_flow_handler_t handler;
748740
749
- dev_dbg(&pmic_arb->spmic->dev, "virq = %u, hwirq = %lu\n", virq, hwirq);
741
+ dev_dbg(&pmic_arb->spmic->dev, "virq = %u, hwirq = %lu, type = %u\n",
742
+ virq, hwirq, type);
750743
751
- irq_set_chip_and_handler(virq, &pmic_arb_irqchip, handle_level_irq);
752
- irq_set_chip_data(virq, d->host_data);
753
- irq_set_noprobe(virq);
744
+ if (type & IRQ_TYPE_EDGE_BOTH)
745
+ handler = handle_edge_irq;
746
+ else
747
+ handler = handle_level_irq;
748
+
749
+
750
+ irq_set_lockdep_class(virq, &qpnpint_irq_lock_class,
751
+ &qpnpint_irq_request_class);
752
+ irq_domain_set_info(domain, virq, hwirq, &pmic_arb_irqchip, pmic_arb,
753
+ handler, NULL, NULL);
754
+}
755
+
756
+static int qpnpint_irq_domain_alloc(struct irq_domain *domain,
757
+ unsigned int virq, unsigned int nr_irqs,
758
+ void *data)
759
+{
760
+ struct spmi_pmic_arb *pmic_arb = domain->host_data;
761
+ struct irq_fwspec *fwspec = data;
762
+ irq_hw_number_t hwirq;
763
+ unsigned int type;
764
+ int ret, i;
765
+
766
+ ret = qpnpint_irq_domain_translate(domain, fwspec, &hwirq, &type);
767
+ if (ret)
768
+ return ret;
769
+
770
+ for (i = 0; i < nr_irqs; i++)
771
+ qpnpint_irq_domain_map(pmic_arb, domain, virq + i, hwirq + i,
772
+ type);
773
+
754774 return 0;
755775 }
756776
....@@ -867,7 +887,8 @@
867887 * version 5, there is more than one APID mapped to each PPID.
868888 * The owner field for each of these mappings specifies the EE which is
869889 * allowed to write to the APID. The owner of the last (highest) APID
870
- * for a given PPID will receive interrupts from the PPID.
890
+ * which has the IRQ owner bit set for a given PPID will receive
891
+ * interrupts from the PPID.
871892 */
872893 for (i = 0; ; i++, apidd++) {
873894 offset = pmic_arb->ver_ops->apid_map_offset(i);
....@@ -890,16 +911,16 @@
890911 apid = pmic_arb->ppid_to_apid[ppid] & ~PMIC_ARB_APID_VALID;
891912 prev_apidd = &pmic_arb->apid_data[apid];
892913
893
- if (valid && is_irq_ee &&
894
- prev_apidd->write_ee == pmic_arb->ee) {
914
+ if (!valid || apidd->write_ee == pmic_arb->ee) {
915
+ /* First PPID mapping or one for this EE */
916
+ pmic_arb->ppid_to_apid[ppid] = i | PMIC_ARB_APID_VALID;
917
+ } else if (valid && is_irq_ee &&
918
+ prev_apidd->write_ee == pmic_arb->ee) {
895919 /*
896920 * Duplicate PPID mapping after the one for this EE;
897921 * override the irq owner
898922 */
899923 prev_apidd->irq_ee = apidd->irq_ee;
900
- } else if (!valid || is_irq_ee) {
901
- /* First PPID mapping or duplicate for another EE */
902
- pmic_arb->ppid_to_apid[ppid] = i | PMIC_ARB_APID_VALID;
903924 }
904925
905926 apidd->ppid = ppid;
....@@ -1126,8 +1147,10 @@
11261147 };
11271148
11281149 static const struct irq_domain_ops pmic_arb_irq_domain_ops = {
1129
- .map = qpnpint_irq_domain_map,
1130
- .xlate = qpnpint_irq_domain_dt_translate,
1150
+ .activate = qpnpint_irq_domain_activate,
1151
+ .alloc = qpnpint_irq_domain_alloc,
1152
+ .free = irq_domain_free_irqs_common,
1153
+ .translate = qpnpint_irq_domain_translate,
11311154 };
11321155
11331156 static int spmi_pmic_arb_probe(struct platform_device *pdev)