diff --git a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt index 1114838590f8..57c9b9294481 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt @@ -32,7 +32,8 @@ Properties: "qcom,pdc-sm6150", "qcom,pdc-sm8150", "qcom,pdc-sdxprairie", - "qcom,pdc-atoll" + "qcom,pdc-atoll", + "qcom,pdc-virt" - reg: Usage: required @@ -58,6 +59,14 @@ Properties: Value type: Definition: Identifies the node as an interrupt controller. +- qcom,pdc-pins: + Usage: optional + Value type: + Definition: Specifies the PDC pin and its mapping hwirq. + The first element of the tuple is the PDC port. + The second element is the GIC hwirq number for the PDC port. + Usage is required when using "qcom,pdc-virt" as compatible. + Example: pdcgic: interrupt-controller@0xb220000{ @@ -67,3 +76,12 @@ pdcgic: interrupt-controller@0xb220000{ interrupt-parent = <&intc>; interrupt-controller; }; + +pdcgic: interrupt-controller@0xb220000{ + compatible = "qcom,pdc-virt"; + reg = <0xb220000 0x30000>; + #interrupt-cells = <3>; + interrupt-parent = <&intc>; + interrupt-controller; + qcom,pdc-pins = <8 520>, <9 521>; +}; diff --git a/drivers/irqchip/qcom/Kconfig b/drivers/irqchip/qcom/Kconfig index 7165658dcfbe..c96fb42e1aa5 100644 --- a/drivers/irqchip/qcom/Kconfig +++ b/drivers/irqchip/qcom/Kconfig @@ -58,3 +58,11 @@ config QTI_MPM help QTI MSM Power Manager driver to manage and configure wakeup IRQs. + +config QTI_PDC_VIRT + bool "QTI PDC VIRT" + select QTI_PDC + help + QTI Power Domain Controller for Virtual platforms + This is used for managing and configuring + the wakeup interrupts on virtual platforms. \ No newline at end of file diff --git a/drivers/irqchip/qcom/Makefile b/drivers/irqchip/qcom/Makefile index 27200a1f42d7..c6cf4bb89a14 100644 --- a/drivers/irqchip/qcom/Makefile +++ b/drivers/irqchip/qcom/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_QTI_PDC_SDXPRAIRIE) += pdc-sdxprairie.o obj-$(CONFIG_QTI_PDC_ATOLL) += pdc-atoll.o obj-$(CONFIG_QTI_MPM) += mpm.o mpm-8937.o mpm-qcs405.o mpm-trinket.o \ mpm-9607.o mpm-sdm660.o +obj-$(CONFIG_QTI_PDC_VIRT) += pdc-virt.o \ No newline at end of file diff --git a/drivers/irqchip/qcom/pdc-virt.c b/drivers/irqchip/qcom/pdc-virt.c new file mode 100644 index 000000000000..436db76bfebc --- /dev/null +++ b/drivers/irqchip/qcom/pdc-virt.c @@ -0,0 +1,77 @@ +/* Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include "pdc.h" + +static struct pdc_pin *pdc_pins_dt; + +static int pdc_read_pin_mapping_from_dt(struct device_node *node) +{ + int ret = 0, n; + int pdc_pin_count; + + n = of_property_count_elems_of_size(node, "qcom,pdc-pins", sizeof(u32)); + if (n <= 0 || n % 2) + return -EINVAL; + + pdc_pin_count = n / 2; + + pdc_pins_dt = kcalloc(pdc_pin_count + 1, sizeof(struct pdc_pin), + GFP_KERNEL); + if (!pdc_pins_dt) + return -ENOMEM; + + for (n = 0; n < pdc_pin_count; n++) { + ret = of_property_read_u32_index(node, "qcom,pdc-pins", + n * 2, + &pdc_pins_dt[n].pin); + if (ret) + goto err; + + ret = of_property_read_u32_index(node, "qcom,pdc-pins", + (n * 2) + 1, + (u32 *)&pdc_pins_dt[n].hwirq); + if (ret) + goto err; + } + + pdc_pins_dt[pdc_pin_count].pin = -1; + + return ret; + +err: + kfree(pdc_pins_dt); + return ret; +} + +static int __init qcom_pdc_gic_init(struct device_node *node, + struct device_node *parent) +{ + int ret; + + ret = pdc_read_pin_mapping_from_dt(node); + if (ret) { + pr_err("%s: Error reading PDC pin mapping: %d\n", + __func__, ret); + return ret; + } + + ret = qcom_pdc_init(node, parent, pdc_pins_dt); + + pr_info("PDC virt initialized\n"); + + return ret; +} + +IRQCHIP_DECLARE(pdc_virt, "qcom,pdc-virt", qcom_pdc_gic_init);