aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-05-19 13:58:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-05-19 13:58:45 -0400
commitd9351ea14ddca708d3cb384f828af4bf82fcc772 (patch)
tree90c5fe9067f1005ce512c63b2e664a670af72b4f
parent39feaa3ff4453594297574e116a55bd6d5371f37 (diff)
parentfb4e0592654adb31bc6f3a738d6499b816a655d6 (diff)
Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull IRQ chip updates from Ingo Molnar: "A late irqchips update: - New TI INTR/INTA set of drivers - Rewrite of the stm32mp1-exti driver as a platform driver - Update the IOMMU MSI mapping API to be RT friendly - A number of cleanups and other low impact fixes" * 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (34 commits) iommu/dma-iommu: Remove iommu_dma_map_msi_msg() irqchip/gic-v3-mbi: Don't map the MSI page in mbi_compose_m{b, s}i_msg() irqchip/ls-scfg-msi: Don't map the MSI page in ls_scfg_msi_compose_msg() irqchip/gic-v3-its: Don't map the MSI page in its_irq_compose_msi_msg() irqchip/gicv2m: Don't map the MSI page in gicv2m_compose_msi_msg() iommu/dma-iommu: Split iommu_dma_map_msi_msg() in two parts genirq/msi: Add a new field in msi_desc to store an IOMMU cookie arm64: arch_k3: Enable interrupt controller drivers irqchip/ti-sci-inta: Add msi domain support soc: ti: Add MSI domain bus support for Interrupt Aggregator irqchip/ti-sci-inta: Add support for Interrupt Aggregator driver dt-bindings: irqchip: Introduce TISCI Interrupt Aggregator bindings irqchip/ti-sci-intr: Add support for Interrupt Router driver dt-bindings: irqchip: Introduce TISCI Interrupt router bindings gpio: thunderx: Use the default parent apis for {request,release}_resources genirq: Introduce irq_chip_{request,release}_resource_parent() apis firmware: ti_sci: Add helper apis to manage resources firmware: ti_sci: Add RM mapping table for am654 firmware: ti_sci: Add support for IRQ management firmware: ti_sci: Add support for RM core ops ...
-rw-r--r--Documentation/devicetree/bindings/arm/keystone/ti,sci.txt3
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.txt66
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/ti,sci-intr.txt82
-rw-r--r--MAINTAINERS6
-rw-r--r--arch/arm64/Kconfig.platforms5
-rw-r--r--drivers/firmware/ti_sci.c651
-rw-r--r--drivers/firmware/ti_sci.h102
-rw-r--r--drivers/gpio/gpio-thunderx.c16
-rw-r--r--drivers/iommu/Kconfig1
-rw-r--r--drivers/iommu/dma-iommu.c48
-rw-r--r--drivers/irqchip/Kconfig27
-rw-r--r--drivers/irqchip/Makefile2
-rw-r--r--drivers/irqchip/irq-bcm7038-l1.c3
-rw-r--r--drivers/irqchip/irq-bcm7120-l2.c3
-rw-r--r--drivers/irqchip/irq-brcmstb-l2.c2
-rw-r--r--drivers/irqchip/irq-gic-pm.c76
-rw-r--r--drivers/irqchip/irq-gic-v2m.c8
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c84
-rw-r--r--drivers/irqchip/irq-gic-v3-mbi.c10
-rw-r--r--drivers/irqchip/irq-imx-irqsteer.c4
-rw-r--r--drivers/irqchip/irq-ls-scfg-msi.c7
-rw-r--r--drivers/irqchip/irq-renesas-intc-irqpin.c4
-rw-r--r--drivers/irqchip/irq-stm32-exti.c233
-rw-r--r--drivers/irqchip/irq-ti-sci-inta.c615
-rw-r--r--drivers/irqchip/irq-ti-sci-intr.c275
-rw-r--r--drivers/soc/ti/Kconfig6
-rw-r--r--drivers/soc/ti/Makefile1
-rw-r--r--drivers/soc/ti/ti_sci_inta_msi.c146
-rw-r--r--include/linux/dma-iommu.h24
-rw-r--r--include/linux/irq.h2
-rw-r--r--include/linux/irqchip/arm-gic-v3.h12
-rw-r--r--include/linux/irqdomain.h1
-rw-r--r--include/linux/msi.h36
-rw-r--r--include/linux/soc/ti/ti_sci_inta_msi.h23
-rw-r--r--include/linux/soc/ti/ti_sci_protocol.h124
-rw-r--r--kernel/irq/Kconfig3
-rw-r--r--kernel/irq/chip.c27
-rw-r--r--kernel/irq/irqdomain.c2
38 files changed, 2511 insertions, 229 deletions
diff --git a/Documentation/devicetree/bindings/arm/keystone/ti,sci.txt b/Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
index b56a02c10ae6..6f0cd31c1520 100644
--- a/Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
+++ b/Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
@@ -24,7 +24,8 @@ relationship between the TI-SCI parent node to the child node.
24 24
25Required properties: 25Required properties:
26------------------- 26-------------------
27- compatible: should be "ti,k2g-sci" 27- compatible: should be "ti,k2g-sci" for TI 66AK2G SoC
28 should be "ti,am654-sci" for for TI AM654 SoC
28- mbox-names: 29- mbox-names:
29 "rx" - Mailbox corresponding to receive path 30 "rx" - Mailbox corresponding to receive path
30 "tx" - Mailbox corresponding to transmit path 31 "tx" - Mailbox corresponding to transmit path
diff --git a/Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.txt b/Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.txt
new file mode 100644
index 000000000000..7841cb099e13
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.txt
@@ -0,0 +1,66 @@
1Texas Instruments K3 Interrupt Aggregator
2=========================================
3
4The Interrupt Aggregator (INTA) provides a centralized machine
5which handles the termination of system events to that they can
6be coherently processed by the host(s) in the system. A maximum
7of 64 events can be mapped to a single interrupt.
8
9
10 Interrupt Aggregator
11 +-----------------------------------------+
12 | Intmap VINT |
13 | +--------------+ +------------+ |
14 m ------>| | vint | bit | | 0 |.....|63| vint0 |
15 . | +--------------+ +------------+ | +------+
16 . | . . | | HOST |
17Globalevents ------>| . . |------>| IRQ |
18 . | . . | | CTRL |
19 . | . . | +------+
20 n ------>| +--------------+ +------------+ |
21 | | vint | bit | | 0 |.....|63| vintx |
22 | +--------------+ +------------+ |
23 | |
24 +-----------------------------------------+
25
26Configuration of these Intmap registers that maps global events to vint is done
27by a system controller (like the Device Memory and Security Controller on K3
28AM654 SoC). Driver should request the system controller to get the range
29of global events and vints assigned to the requesting host. Management
30of these requested resources should be handled by driver and requests
31system controller to map specific global event to vint, bit pair.
32
33Communication between the host processor running an OS and the system
34controller happens through a protocol called TI System Control Interface
35(TISCI protocol). For more details refer:
36Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
37
38TISCI Interrupt Aggregator Node:
39-------------------------------
40- compatible: Must be "ti,sci-inta".
41- reg: Should contain registers location and length.
42- interrupt-controller: Identifies the node as an interrupt controller
43- msi-controller: Identifies the node as an MSI controller.
44- interrupt-parent: phandle of irq parent.
45- ti,sci: Phandle to TI-SCI compatible System controller node.
46- ti,sci-dev-id: TISCI device ID of the Interrupt Aggregator.
47- ti,sci-rm-range-vint: Array of TISCI subtype ids representing vints(inta
48 outputs) range within this INTA, assigned to the
49 requesting host context.
50- ti,sci-rm-range-global-event: Array of TISCI subtype ids representing the
51 global events range reaching this IA and are assigned
52 to the requesting host context.
53
54Example:
55--------
56main_udmass_inta: interrupt-controller@33d00000 {
57 compatible = "ti,sci-inta";
58 reg = <0x0 0x33d00000 0x0 0x100000>;
59 interrupt-controller;
60 msi-controller;
61 interrupt-parent = <&main_navss_intr>;
62 ti,sci = <&dmsc>;
63 ti,sci-dev-id = <179>;
64 ti,sci-rm-range-vint = <0x0>;
65 ti,sci-rm-range-global-event = <0x1>;
66};
diff --git a/Documentation/devicetree/bindings/interrupt-controller/ti,sci-intr.txt b/Documentation/devicetree/bindings/interrupt-controller/ti,sci-intr.txt
new file mode 100644
index 000000000000..1a8718f8855d
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/ti,sci-intr.txt
@@ -0,0 +1,82 @@
1Texas Instruments K3 Interrupt Router
2=====================================
3
4The Interrupt Router (INTR) module provides a mechanism to mux M
5interrupt inputs to N interrupt outputs, where all M inputs are selectable
6to be driven per N output. An Interrupt Router can either handle edge triggered
7or level triggered interrupts and that is fixed in hardware.
8
9 Interrupt Router
10 +----------------------+
11 | Inputs Outputs |
12 +-------+ | +------+ +-----+ |
13 | GPIO |----------->| | irq0 | | 0 | | Host IRQ
14 +-------+ | +------+ +-----+ | controller
15 | . . | +-------+
16 +-------+ | . . |----->| IRQ |
17 | INTA |----------->| . . | +-------+
18 +-------+ | . +-----+ |
19 | +------+ | N | |
20 | | irqM | +-----+ |
21 | +------+ |
22 | |
23 +----------------------+
24
25There is one register per output (MUXCNTL_N) that controls the selection.
26Configuration of these MUXCNTL_N registers is done by a system controller
27(like the Device Memory and Security Controller on K3 AM654 SoC). System
28controller will keep track of the used and unused registers within the Router.
29Driver should request the system controller to get the range of GIC IRQs
30assigned to the requesting hosts. It is the drivers responsibility to keep
31track of Host IRQs.
32
33Communication between the host processor running an OS and the system
34controller happens through a protocol called TI System Control Interface
35(TISCI protocol). For more details refer:
36Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
37
38TISCI Interrupt Router Node:
39----------------------------
40Required Properties:
41- compatible: Must be "ti,sci-intr".
42- ti,intr-trigger-type: Should be one of the following:
43 1: If intr supports edge triggered interrupts.
44 4: If intr supports level triggered interrupts.
45- interrupt-controller: Identifies the node as an interrupt controller
46- #interrupt-cells: Specifies the number of cells needed to encode an
47 interrupt source. The value should be 2.
48 First cell should contain the TISCI device ID of source
49 Second cell should contain the interrupt source offset
50 within the device.
51- ti,sci: Phandle to TI-SCI compatible System controller node.
52- ti,sci-dst-id: TISCI device ID of the destination IRQ controller.
53- ti,sci-rm-range-girq: Array of TISCI subtype ids representing the host irqs
54 assigned to this interrupt router. Each subtype id
55 corresponds to a range of host irqs.
56
57For more details on TISCI IRQ resource management refer:
58http://downloads.ti.com/tisci/esd/latest/2_tisci_msgs/rm/rm_irq.html
59
60Example:
61--------
62The following example demonstrates both interrupt router node and the consumer
63node(main gpio) on the AM654 SoC:
64
65main_intr: interrupt-controller0 {
66 compatible = "ti,sci-intr";
67 ti,intr-trigger-type = <1>;
68 interrupt-controller;
69 interrupt-parent = <&gic500>;
70 #interrupt-cells = <2>;
71 ti,sci = <&dmsc>;
72 ti,sci-dst-id = <56>;
73 ti,sci-rm-range-girq = <0x1>;
74};
75
76main_gpio0: gpio@600000 {
77 ...
78 interrupt-parent = <&main_intr>;
79 interrupts = <57 256>, <57 257>, <57 258>,
80 <57 259>, <57 260>, <57 261>;
81 ...
82};
diff --git a/MAINTAINERS b/MAINTAINERS
index 9cc6767e1b12..4f4dd9413da7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15547,6 +15547,12 @@ F: Documentation/devicetree/bindings/reset/ti,sci-reset.txt
15547F: Documentation/devicetree/bindings/clock/ti,sci-clk.txt 15547F: Documentation/devicetree/bindings/clock/ti,sci-clk.txt
15548F: drivers/clk/keystone/sci-clk.c 15548F: drivers/clk/keystone/sci-clk.c
15549F: drivers/reset/reset-ti-sci.c 15549F: drivers/reset/reset-ti-sci.c
15550F: Documentation/devicetree/bindings/interrupt-controller/ti,sci-intr.txt
15551F: Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.txt
15552F: drivers/irqchip/irq-ti-sci-intr.c
15553F: drivers/irqchip/irq-ti-sci-inta.c
15554F: include/linux/soc/ti/ti_sci_inta_msi.h
15555F: drivers/soc/ti/ti_sci_inta_msi.c
15550 15556
15551Texas Instruments ASoC drivers 15557Texas Instruments ASoC drivers
15552M: Peter Ujfalusi <peter.ujfalusi@ti.com> 15558M: Peter Ujfalusi <peter.ujfalusi@ti.com>
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 1001410c4782..42eca656faa8 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -87,6 +87,11 @@ config ARCH_EXYNOS
87config ARCH_K3 87config ARCH_K3
88 bool "Texas Instruments Inc. K3 multicore SoC architecture" 88 bool "Texas Instruments Inc. K3 multicore SoC architecture"
89 select PM_GENERIC_DOMAINS if PM 89 select PM_GENERIC_DOMAINS if PM
90 select MAILBOX
91 select TI_MESSAGE_MANAGER
92 select TI_SCI_PROTOCOL
93 select TI_SCI_INTR_IRQCHIP
94 select TI_SCI_INTA_IRQCHIP
90 help 95 help
91 This enables support for Texas Instruments' K3 multicore SoC 96 This enables support for Texas Instruments' K3 multicore SoC
92 architecture. 97 architecture.
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index 3fbbb61012c4..ef93406ace1b 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -65,18 +65,36 @@ struct ti_sci_xfers_info {
65}; 65};
66 66
67/** 67/**
68 * struct ti_sci_rm_type_map - Structure representing TISCI Resource
69 * management representation of dev_ids.
70 * @dev_id: TISCI device ID
71 * @type: Corresponding id as identified by TISCI RM.
72 *
73 * Note: This is used only as a work around for using RM range apis
74 * for AM654 SoC. For future SoCs dev_id will be used as type
75 * for RM range APIs. In order to maintain ABI backward compatibility
76 * type is not being changed for AM654 SoC.
77 */
78struct ti_sci_rm_type_map {
79 u32 dev_id;
80 u16 type;
81};
82
83/**
68 * struct ti_sci_desc - Description of SoC integration 84 * struct ti_sci_desc - Description of SoC integration
69 * @default_host_id: Host identifier representing the compute entity 85 * @default_host_id: Host identifier representing the compute entity
70 * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds) 86 * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds)
71 * @max_msgs: Maximum number of messages that can be pending 87 * @max_msgs: Maximum number of messages that can be pending
72 * simultaneously in the system 88 * simultaneously in the system
73 * @max_msg_size: Maximum size of data per message that can be handled. 89 * @max_msg_size: Maximum size of data per message that can be handled.
90 * @rm_type_map: RM resource type mapping structure.
74 */ 91 */
75struct ti_sci_desc { 92struct ti_sci_desc {
76 u8 default_host_id; 93 u8 default_host_id;
77 int max_rx_timeout_ms; 94 int max_rx_timeout_ms;
78 int max_msgs; 95 int max_msgs;
79 int max_msg_size; 96 int max_msg_size;
97 struct ti_sci_rm_type_map *rm_type_map;
80}; 98};
81 99
82/** 100/**
@@ -1600,6 +1618,392 @@ fail:
1600 return ret; 1618 return ret;
1601} 1619}
1602 1620
1621static int ti_sci_get_resource_type(struct ti_sci_info *info, u16 dev_id,
1622 u16 *type)
1623{
1624 struct ti_sci_rm_type_map *rm_type_map = info->desc->rm_type_map;
1625 bool found = false;
1626 int i;
1627
1628 /* If map is not provided then assume dev_id is used as type */
1629 if (!rm_type_map) {
1630 *type = dev_id;
1631 return 0;
1632 }
1633
1634 for (i = 0; rm_type_map[i].dev_id; i++) {
1635 if (rm_type_map[i].dev_id == dev_id) {
1636 *type = rm_type_map[i].type;
1637 found = true;
1638 break;
1639 }
1640 }
1641
1642 if (!found)
1643 return -EINVAL;
1644
1645 return 0;
1646}
1647
1648/**
1649 * ti_sci_get_resource_range - Helper to get a range of resources assigned
1650 * to a host. Resource is uniquely identified by
1651 * type and subtype.
1652 * @handle: Pointer to TISCI handle.
1653 * @dev_id: TISCI device ID.
1654 * @subtype: Resource assignment subtype that is being requested
1655 * from the given device.
1656 * @s_host: Host processor ID to which the resources are allocated
1657 * @range_start: Start index of the resource range
1658 * @range_num: Number of resources in the range
1659 *
1660 * Return: 0 if all went fine, else return appropriate error.
1661 */
1662static int ti_sci_get_resource_range(const struct ti_sci_handle *handle,
1663 u32 dev_id, u8 subtype, u8 s_host,
1664 u16 *range_start, u16 *range_num)
1665{
1666 struct ti_sci_msg_resp_get_resource_range *resp;
1667 struct ti_sci_msg_req_get_resource_range *req;
1668 struct ti_sci_xfer *xfer;
1669 struct ti_sci_info *info;
1670 struct device *dev;
1671 u16 type;
1672 int ret = 0;
1673
1674 if (IS_ERR(handle))
1675 return PTR_ERR(handle);
1676 if (!handle)
1677 return -EINVAL;
1678
1679 info = handle_to_ti_sci_info(handle);
1680 dev = info->dev;
1681
1682 xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_RESOURCE_RANGE,
1683 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1684 sizeof(*req), sizeof(*resp));
1685 if (IS_ERR(xfer)) {
1686 ret = PTR_ERR(xfer);
1687 dev_err(dev, "Message alloc failed(%d)\n", ret);
1688 return ret;
1689 }
1690
1691 ret = ti_sci_get_resource_type(info, dev_id, &type);
1692 if (ret) {
1693 dev_err(dev, "rm type lookup failed for %u\n", dev_id);
1694 goto fail;
1695 }
1696
1697 req = (struct ti_sci_msg_req_get_resource_range *)xfer->xfer_buf;
1698 req->secondary_host = s_host;
1699 req->type = type & MSG_RM_RESOURCE_TYPE_MASK;
1700 req->subtype = subtype & MSG_RM_RESOURCE_SUBTYPE_MASK;
1701
1702 ret = ti_sci_do_xfer(info, xfer);
1703 if (ret) {
1704 dev_err(dev, "Mbox send fail %d\n", ret);
1705 goto fail;
1706 }
1707
1708 resp = (struct ti_sci_msg_resp_get_resource_range *)xfer->xfer_buf;
1709
1710 if (!ti_sci_is_response_ack(resp)) {
1711 ret = -ENODEV;
1712 } else if (!resp->range_start && !resp->range_num) {
1713 ret = -ENODEV;
1714 } else {
1715 *range_start = resp->range_start;
1716 *range_num = resp->range_num;
1717 };
1718
1719fail:
1720 ti_sci_put_one_xfer(&info->minfo, xfer);
1721
1722 return ret;
1723}
1724
1725/**
1726 * ti_sci_cmd_get_resource_range - Get a range of resources assigned to host
1727 * that is same as ti sci interface host.
1728 * @handle: Pointer to TISCI handle.
1729 * @dev_id: TISCI device ID.
1730 * @subtype: Resource assignment subtype that is being requested
1731 * from the given device.
1732 * @range_start: Start index of the resource range
1733 * @range_num: Number of resources in the range
1734 *
1735 * Return: 0 if all went fine, else return appropriate error.
1736 */
1737static int ti_sci_cmd_get_resource_range(const struct ti_sci_handle *handle,
1738 u32 dev_id, u8 subtype,
1739 u16 *range_start, u16 *range_num)
1740{
1741 return ti_sci_get_resource_range(handle, dev_id, subtype,
1742 TI_SCI_IRQ_SECONDARY_HOST_INVALID,
1743 range_start, range_num);
1744}
1745
1746/**
1747 * ti_sci_cmd_get_resource_range_from_shost - Get a range of resources
1748 * assigned to a specified host.
1749 * @handle: Pointer to TISCI handle.
1750 * @dev_id: TISCI device ID.
1751 * @subtype: Resource assignment subtype that is being requested
1752 * from the given device.
1753 * @s_host: Host processor ID to which the resources are allocated
1754 * @range_start: Start index of the resource range
1755 * @range_num: Number of resources in the range
1756 *
1757 * Return: 0 if all went fine, else return appropriate error.
1758 */
1759static
1760int ti_sci_cmd_get_resource_range_from_shost(const struct ti_sci_handle *handle,
1761 u32 dev_id, u8 subtype, u8 s_host,
1762 u16 *range_start, u16 *range_num)
1763{
1764 return ti_sci_get_resource_range(handle, dev_id, subtype, s_host,
1765 range_start, range_num);
1766}
1767
1768/**
1769 * ti_sci_manage_irq() - Helper api to configure/release the irq route between
1770 * the requested source and destination
1771 * @handle: Pointer to TISCI handle.
1772 * @valid_params: Bit fields defining the validity of certain params
1773 * @src_id: Device ID of the IRQ source
1774 * @src_index: IRQ source index within the source device
1775 * @dst_id: Device ID of the IRQ destination
1776 * @dst_host_irq: IRQ number of the destination device
1777 * @ia_id: Device ID of the IA, if the IRQ flows through this IA
1778 * @vint: Virtual interrupt to be used within the IA
1779 * @global_event: Global event number to be used for the requesting event
1780 * @vint_status_bit: Virtual interrupt status bit to be used for the event
1781 * @s_host: Secondary host ID to which the irq/event is being
1782 * requested for.
1783 * @type: Request type irq set or release.
1784 *
1785 * Return: 0 if all went fine, else return appropriate error.
1786 */
1787static int ti_sci_manage_irq(const struct ti_sci_handle *handle,
1788 u32 valid_params, u16 src_id, u16 src_index,
1789 u16 dst_id, u16 dst_host_irq, u16 ia_id, u16 vint,
1790 u16 global_event, u8 vint_status_bit, u8 s_host,
1791 u16 type)
1792{
1793 struct ti_sci_msg_req_manage_irq *req;
1794 struct ti_sci_msg_hdr *resp;
1795 struct ti_sci_xfer *xfer;
1796 struct ti_sci_info *info;
1797 struct device *dev;
1798 int ret = 0;
1799
1800 if (IS_ERR(handle))
1801 return PTR_ERR(handle);
1802 if (!handle)
1803 return -EINVAL;
1804
1805 info = handle_to_ti_sci_info(handle);
1806 dev = info->dev;
1807
1808 xfer = ti_sci_get_one_xfer(info, type, TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1809 sizeof(*req), sizeof(*resp));
1810 if (IS_ERR(xfer)) {
1811 ret = PTR_ERR(xfer);
1812 dev_err(dev, "Message alloc failed(%d)\n", ret);
1813 return ret;
1814 }
1815 req = (struct ti_sci_msg_req_manage_irq *)xfer->xfer_buf;
1816 req->valid_params = valid_params;
1817 req->src_id = src_id;
1818 req->src_index = src_index;
1819 req->dst_id = dst_id;
1820 req->dst_host_irq = dst_host_irq;
1821 req->ia_id = ia_id;
1822 req->vint = vint;
1823 req->global_event = global_event;
1824 req->vint_status_bit = vint_status_bit;
1825 req->secondary_host = s_host;
1826
1827 ret = ti_sci_do_xfer(info, xfer);
1828 if (ret) {
1829 dev_err(dev, "Mbox send fail %d\n", ret);
1830 goto fail;
1831 }
1832
1833 resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
1834
1835 ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
1836
1837fail:
1838 ti_sci_put_one_xfer(&info->minfo, xfer);
1839
1840 return ret;
1841}
1842
1843/**
1844 * ti_sci_set_irq() - Helper api to configure the irq route between the
1845 * requested source and destination
1846 * @handle: Pointer to TISCI handle.
1847 * @valid_params: Bit fields defining the validity of certain params
1848 * @src_id: Device ID of the IRQ source
1849 * @src_index: IRQ source index within the source device
1850 * @dst_id: Device ID of the IRQ destination
1851 * @dst_host_irq: IRQ number of the destination device
1852 * @ia_id: Device ID of the IA, if the IRQ flows through this IA
1853 * @vint: Virtual interrupt to be used within the IA
1854 * @global_event: Global event number to be used for the requesting event
1855 * @vint_status_bit: Virtual interrupt status bit to be used for the event
1856 * @s_host: Secondary host ID to which the irq/event is being
1857 * requested for.
1858 *
1859 * Return: 0 if all went fine, else return appropriate error.
1860 */
1861static int ti_sci_set_irq(const struct ti_sci_handle *handle, u32 valid_params,
1862 u16 src_id, u16 src_index, u16 dst_id,
1863 u16 dst_host_irq, u16 ia_id, u16 vint,
1864 u16 global_event, u8 vint_status_bit, u8 s_host)
1865{
1866 pr_debug("%s: IRQ set with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n",
1867 __func__, valid_params, src_id, src_index,
1868 dst_id, dst_host_irq, ia_id, vint, global_event,
1869 vint_status_bit);
1870
1871 return ti_sci_manage_irq(handle, valid_params, src_id, src_index,
1872 dst_id, dst_host_irq, ia_id, vint,
1873 global_event, vint_status_bit, s_host,
1874 TI_SCI_MSG_SET_IRQ);
1875}
1876
1877/**
1878 * ti_sci_free_irq() - Helper api to free the irq route between the
1879 * requested source and destination
1880 * @handle: Pointer to TISCI handle.
1881 * @valid_params: Bit fields defining the validity of certain params
1882 * @src_id: Device ID of the IRQ source
1883 * @src_index: IRQ source index within the source device
1884 * @dst_id: Device ID of the IRQ destination
1885 * @dst_host_irq: IRQ number of the destination device
1886 * @ia_id: Device ID of the IA, if the IRQ flows through this IA
1887 * @vint: Virtual interrupt to be used within the IA
1888 * @global_event: Global event number to be used for the requesting event
1889 * @vint_status_bit: Virtual interrupt status bit to be used for the event
1890 * @s_host: Secondary host ID to which the irq/event is being
1891 * requested for.
1892 *
1893 * Return: 0 if all went fine, else return appropriate error.
1894 */
1895static int ti_sci_free_irq(const struct ti_sci_handle *handle, u32 valid_params,
1896 u16 src_id, u16 src_index, u16 dst_id,
1897 u16 dst_host_irq, u16 ia_id, u16 vint,
1898 u16 global_event, u8 vint_status_bit, u8 s_host)
1899{
1900 pr_debug("%s: IRQ release with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n",
1901 __func__, valid_params, src_id, src_index,
1902 dst_id, dst_host_irq, ia_id, vint, global_event,
1903 vint_status_bit);
1904
1905 return ti_sci_manage_irq(handle, valid_params, src_id, src_index,
1906 dst_id, dst_host_irq, ia_id, vint,
1907 global_event, vint_status_bit, s_host,
1908 TI_SCI_MSG_FREE_IRQ);
1909}
1910
1911/**
1912 * ti_sci_cmd_set_irq() - Configure a host irq route between the requested
1913 * source and destination.
1914 * @handle: Pointer to TISCI handle.
1915 * @src_id: Device ID of the IRQ source
1916 * @src_index: IRQ source index within the source device
1917 * @dst_id: Device ID of the IRQ destination
1918 * @dst_host_irq: IRQ number of the destination device
1919 * @vint_irq: Boolean specifying if this interrupt belongs to
1920 * Interrupt Aggregator.
1921 *
1922 * Return: 0 if all went fine, else return appropriate error.
1923 */
1924static int ti_sci_cmd_set_irq(const struct ti_sci_handle *handle, u16 src_id,
1925 u16 src_index, u16 dst_id, u16 dst_host_irq)
1926{
1927 u32 valid_params = MSG_FLAG_DST_ID_VALID | MSG_FLAG_DST_HOST_IRQ_VALID;
1928
1929 return ti_sci_set_irq(handle, valid_params, src_id, src_index, dst_id,
1930 dst_host_irq, 0, 0, 0, 0, 0);
1931}
1932
1933/**
1934 * ti_sci_cmd_set_event_map() - Configure an event based irq route between the
1935 * requested source and Interrupt Aggregator.
1936 * @handle: Pointer to TISCI handle.
1937 * @src_id: Device ID of the IRQ source
1938 * @src_index: IRQ source index within the source device
1939 * @ia_id: Device ID of the IA, if the IRQ flows through this IA
1940 * @vint: Virtual interrupt to be used within the IA
1941 * @global_event: Global event number to be used for the requesting event
1942 * @vint_status_bit: Virtual interrupt status bit to be used for the event
1943 *
1944 * Return: 0 if all went fine, else return appropriate error.
1945 */
1946static int ti_sci_cmd_set_event_map(const struct ti_sci_handle *handle,
1947 u16 src_id, u16 src_index, u16 ia_id,
1948 u16 vint, u16 global_event,
1949 u8 vint_status_bit)
1950{
1951 u32 valid_params = MSG_FLAG_IA_ID_VALID | MSG_FLAG_VINT_VALID |
1952 MSG_FLAG_GLB_EVNT_VALID |
1953 MSG_FLAG_VINT_STS_BIT_VALID;
1954
1955 return ti_sci_set_irq(handle, valid_params, src_id, src_index, 0, 0,
1956 ia_id, vint, global_event, vint_status_bit, 0);
1957}
1958
1959/**
1960 * ti_sci_cmd_free_irq() - Free a host irq route between the between the
1961 * requested source and destination.
1962 * @handle: Pointer to TISCI handle.
1963 * @src_id: Device ID of the IRQ source
1964 * @src_index: IRQ source index within the source device
1965 * @dst_id: Device ID of the IRQ destination
1966 * @dst_host_irq: IRQ number of the destination device
1967 * @vint_irq: Boolean specifying if this interrupt belongs to
1968 * Interrupt Aggregator.
1969 *
1970 * Return: 0 if all went fine, else return appropriate error.
1971 */
1972static int ti_sci_cmd_free_irq(const struct ti_sci_handle *handle, u16 src_id,
1973 u16 src_index, u16 dst_id, u16 dst_host_irq)
1974{
1975 u32 valid_params = MSG_FLAG_DST_ID_VALID | MSG_FLAG_DST_HOST_IRQ_VALID;
1976
1977 return ti_sci_free_irq(handle, valid_params, src_id, src_index, dst_id,
1978 dst_host_irq, 0, 0, 0, 0, 0);
1979}
1980
1981/**
1982 * ti_sci_cmd_free_event_map() - Free an event map between the requested source
1983 * and Interrupt Aggregator.
1984 * @handle: Pointer to TISCI handle.
1985 * @src_id: Device ID of the IRQ source
1986 * @src_index: IRQ source index within the source device
1987 * @ia_id: Device ID of the IA, if the IRQ flows through this IA
1988 * @vint: Virtual interrupt to be used within the IA
1989 * @global_event: Global event number to be used for the requesting event
1990 * @vint_status_bit: Virtual interrupt status bit to be used for the event
1991 *
1992 * Return: 0 if all went fine, else return appropriate error.
1993 */
1994static int ti_sci_cmd_free_event_map(const struct ti_sci_handle *handle,
1995 u16 src_id, u16 src_index, u16 ia_id,
1996 u16 vint, u16 global_event,
1997 u8 vint_status_bit)
1998{
1999 u32 valid_params = MSG_FLAG_IA_ID_VALID |
2000 MSG_FLAG_VINT_VALID | MSG_FLAG_GLB_EVNT_VALID |
2001 MSG_FLAG_VINT_STS_BIT_VALID;
2002
2003 return ti_sci_free_irq(handle, valid_params, src_id, src_index, 0, 0,
2004 ia_id, vint, global_event, vint_status_bit, 0);
2005}
2006
1603/* 2007/*
1604 * ti_sci_setup_ops() - Setup the operations structures 2008 * ti_sci_setup_ops() - Setup the operations structures
1605 * @info: pointer to TISCI pointer 2009 * @info: pointer to TISCI pointer
@@ -1610,6 +2014,8 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
1610 struct ti_sci_core_ops *core_ops = &ops->core_ops; 2014 struct ti_sci_core_ops *core_ops = &ops->core_ops;
1611 struct ti_sci_dev_ops *dops = &ops->dev_ops; 2015 struct ti_sci_dev_ops *dops = &ops->dev_ops;
1612 struct ti_sci_clk_ops *cops = &ops->clk_ops; 2016 struct ti_sci_clk_ops *cops = &ops->clk_ops;
2017 struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops;
2018 struct ti_sci_rm_irq_ops *iops = &ops->rm_irq_ops;
1613 2019
1614 core_ops->reboot_device = ti_sci_cmd_core_reboot; 2020 core_ops->reboot_device = ti_sci_cmd_core_reboot;
1615 2021
@@ -1640,6 +2046,15 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
1640 cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq; 2046 cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq;
1641 cops->set_freq = ti_sci_cmd_clk_set_freq; 2047 cops->set_freq = ti_sci_cmd_clk_set_freq;
1642 cops->get_freq = ti_sci_cmd_clk_get_freq; 2048 cops->get_freq = ti_sci_cmd_clk_get_freq;
2049
2050 rm_core_ops->get_range = ti_sci_cmd_get_resource_range;
2051 rm_core_ops->get_range_from_shost =
2052 ti_sci_cmd_get_resource_range_from_shost;
2053
2054 iops->set_irq = ti_sci_cmd_set_irq;
2055 iops->set_event_map = ti_sci_cmd_set_event_map;
2056 iops->free_irq = ti_sci_cmd_free_irq;
2057 iops->free_event_map = ti_sci_cmd_free_event_map;
1643} 2058}
1644 2059
1645/** 2060/**
@@ -1764,6 +2179,219 @@ const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev)
1764} 2179}
1765EXPORT_SYMBOL_GPL(devm_ti_sci_get_handle); 2180EXPORT_SYMBOL_GPL(devm_ti_sci_get_handle);
1766 2181
2182/**
2183 * ti_sci_get_by_phandle() - Get the TI SCI handle using DT phandle
2184 * @np: device node
2185 * @property: property name containing phandle on TISCI node
2186 *
2187 * NOTE: The function does not track individual clients of the framework
2188 * and is expected to be maintained by caller of TI SCI protocol library.
2189 * ti_sci_put_handle must be balanced with successful ti_sci_get_by_phandle
2190 * Return: pointer to handle if successful, else:
2191 * -EPROBE_DEFER if the instance is not ready
2192 * -ENODEV if the required node handler is missing
2193 * -EINVAL if invalid conditions are encountered.
2194 */
2195const struct ti_sci_handle *ti_sci_get_by_phandle(struct device_node *np,
2196 const char *property)
2197{
2198 struct ti_sci_handle *handle = NULL;
2199 struct device_node *ti_sci_np;
2200 struct ti_sci_info *info;
2201 struct list_head *p;
2202
2203 if (!np) {
2204 pr_err("I need a device pointer\n");
2205 return ERR_PTR(-EINVAL);
2206 }
2207
2208 ti_sci_np = of_parse_phandle(np, property, 0);
2209 if (!ti_sci_np)
2210 return ERR_PTR(-ENODEV);
2211
2212 mutex_lock(&ti_sci_list_mutex);
2213 list_for_each(p, &ti_sci_list) {
2214 info = list_entry(p, struct ti_sci_info, node);
2215 if (ti_sci_np == info->dev->of_node) {
2216 handle = &info->handle;
2217 info->users++;
2218 break;
2219 }
2220 }
2221 mutex_unlock(&ti_sci_list_mutex);
2222 of_node_put(ti_sci_np);
2223
2224 if (!handle)
2225 return ERR_PTR(-EPROBE_DEFER);
2226
2227 return handle;
2228}
2229EXPORT_SYMBOL_GPL(ti_sci_get_by_phandle);
2230
2231/**
2232 * devm_ti_sci_get_by_phandle() - Managed get handle using phandle
2233 * @dev: Device pointer requesting TISCI handle
2234 * @property: property name containing phandle on TISCI node
2235 *
2236 * NOTE: This releases the handle once the device resources are
2237 * no longer needed. MUST NOT BE released with ti_sci_put_handle.
2238 * The function does not track individual clients of the framework
2239 * and is expected to be maintained by caller of TI SCI protocol library.
2240 *
2241 * Return: 0 if all went fine, else corresponding error.
2242 */
2243const struct ti_sci_handle *devm_ti_sci_get_by_phandle(struct device *dev,
2244 const char *property)
2245{
2246 const struct ti_sci_handle *handle;
2247 const struct ti_sci_handle **ptr;
2248
2249 ptr = devres_alloc(devm_ti_sci_release, sizeof(*ptr), GFP_KERNEL);
2250 if (!ptr)
2251 return ERR_PTR(-ENOMEM);
2252 handle = ti_sci_get_by_phandle(dev_of_node(dev), property);
2253
2254 if (!IS_ERR(handle)) {
2255 *ptr = handle;
2256 devres_add(dev, ptr);
2257 } else {
2258 devres_free(ptr);
2259 }
2260
2261 return handle;
2262}
2263EXPORT_SYMBOL_GPL(devm_ti_sci_get_by_phandle);
2264
2265/**
2266 * ti_sci_get_free_resource() - Get a free resource from TISCI resource.
2267 * @res: Pointer to the TISCI resource
2268 *
2269 * Return: resource num if all went ok else TI_SCI_RESOURCE_NULL.
2270 */
2271u16 ti_sci_get_free_resource(struct ti_sci_resource *res)
2272{
2273 unsigned long flags;
2274 u16 set, free_bit;
2275
2276 raw_spin_lock_irqsave(&res->lock, flags);
2277 for (set = 0; set < res->sets; set++) {
2278 free_bit = find_first_zero_bit(res->desc[set].res_map,
2279 res->desc[set].num);
2280 if (free_bit != res->desc[set].num) {
2281 set_bit(free_bit, res->desc[set].res_map);
2282 raw_spin_unlock_irqrestore(&res->lock, flags);
2283 return res->desc[set].start + free_bit;
2284 }
2285 }
2286 raw_spin_unlock_irqrestore(&res->lock, flags);
2287
2288 return TI_SCI_RESOURCE_NULL;
2289}
2290EXPORT_SYMBOL_GPL(ti_sci_get_free_resource);
2291
2292/**
2293 * ti_sci_release_resource() - Release a resource from TISCI resource.
2294 * @res: Pointer to the TISCI resource
2295 * @id: Resource id to be released.
2296 */
2297void ti_sci_release_resource(struct ti_sci_resource *res, u16 id)
2298{
2299 unsigned long flags;
2300 u16 set;
2301
2302 raw_spin_lock_irqsave(&res->lock, flags);
2303 for (set = 0; set < res->sets; set++) {
2304 if (res->desc[set].start <= id &&
2305 (res->desc[set].num + res->desc[set].start) > id)
2306 clear_bit(id - res->desc[set].start,
2307 res->desc[set].res_map);
2308 }
2309 raw_spin_unlock_irqrestore(&res->lock, flags);
2310}
2311EXPORT_SYMBOL_GPL(ti_sci_release_resource);
2312
2313/**
2314 * ti_sci_get_num_resources() - Get the number of resources in TISCI resource
2315 * @res: Pointer to the TISCI resource
2316 *
2317 * Return: Total number of available resources.
2318 */
2319u32 ti_sci_get_num_resources(struct ti_sci_resource *res)
2320{
2321 u32 set, count = 0;
2322
2323 for (set = 0; set < res->sets; set++)
2324 count += res->desc[set].num;
2325
2326 return count;
2327}
2328EXPORT_SYMBOL_GPL(ti_sci_get_num_resources);
2329
2330/**
2331 * devm_ti_sci_get_of_resource() - Get a TISCI resource assigned to a device
2332 * @handle: TISCI handle
2333 * @dev: Device pointer to which the resource is assigned
2334 * @dev_id: TISCI device id to which the resource is assigned
2335 * @of_prop: property name by which the resource are represented
2336 *
2337 * Return: Pointer to ti_sci_resource if all went well else appropriate
2338 * error pointer.
2339 */
2340struct ti_sci_resource *
2341devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle,
2342 struct device *dev, u32 dev_id, char *of_prop)
2343{
2344 struct ti_sci_resource *res;
2345 u32 resource_subtype;
2346 int i, ret;
2347
2348 res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
2349 if (!res)
2350 return ERR_PTR(-ENOMEM);
2351
2352 res->sets = of_property_count_elems_of_size(dev_of_node(dev), of_prop,
2353 sizeof(u32));
2354 if (res->sets < 0) {
2355 dev_err(dev, "%s resource type ids not available\n", of_prop);
2356 return ERR_PTR(res->sets);
2357 }
2358
2359 res->desc = devm_kcalloc(dev, res->sets, sizeof(*res->desc),
2360 GFP_KERNEL);
2361 if (!res->desc)
2362 return ERR_PTR(-ENOMEM);
2363
2364 for (i = 0; i < res->sets; i++) {
2365 ret = of_property_read_u32_index(dev_of_node(dev), of_prop, i,
2366 &resource_subtype);
2367 if (ret)
2368 return ERR_PTR(-EINVAL);
2369
2370 ret = handle->ops.rm_core_ops.get_range(handle, dev_id,
2371 resource_subtype,
2372 &res->desc[i].start,
2373 &res->desc[i].num);
2374 if (ret) {
2375 dev_err(dev, "dev = %d subtype %d not allocated for this host\n",
2376 dev_id, resource_subtype);
2377 return ERR_PTR(ret);
2378 }
2379
2380 dev_dbg(dev, "dev = %d, subtype = %d, start = %d, num = %d\n",
2381 dev_id, resource_subtype, res->desc[i].start,
2382 res->desc[i].num);
2383
2384 res->desc[i].res_map =
2385 devm_kzalloc(dev, BITS_TO_LONGS(res->desc[i].num) *
2386 sizeof(*res->desc[i].res_map), GFP_KERNEL);
2387 if (!res->desc[i].res_map)
2388 return ERR_PTR(-ENOMEM);
2389 }
2390 raw_spin_lock_init(&res->lock);
2391
2392 return res;
2393}
2394
1767static int tisci_reboot_handler(struct notifier_block *nb, unsigned long mode, 2395static int tisci_reboot_handler(struct notifier_block *nb, unsigned long mode,
1768 void *cmd) 2396 void *cmd)
1769{ 2397{
@@ -1784,10 +2412,33 @@ static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = {
1784 /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */ 2412 /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */
1785 .max_msgs = 20, 2413 .max_msgs = 20,
1786 .max_msg_size = 64, 2414 .max_msg_size = 64,
2415 .rm_type_map = NULL,
2416};
2417
2418static struct ti_sci_rm_type_map ti_sci_am654_rm_type_map[] = {
2419 {.dev_id = 56, .type = 0x00b}, /* GIC_IRQ */
2420 {.dev_id = 179, .type = 0x000}, /* MAIN_NAV_UDMASS_IA0 */
2421 {.dev_id = 187, .type = 0x009}, /* MAIN_NAV_RA */
2422 {.dev_id = 188, .type = 0x006}, /* MAIN_NAV_UDMAP */
2423 {.dev_id = 194, .type = 0x007}, /* MCU_NAV_UDMAP */
2424 {.dev_id = 195, .type = 0x00a}, /* MCU_NAV_RA */
2425 {.dev_id = 0, .type = 0x000}, /* end of table */
2426};
2427
2428/* Description for AM654 */
2429static const struct ti_sci_desc ti_sci_pmmc_am654_desc = {
2430 .default_host_id = 12,
2431 /* Conservative duration */
2432 .max_rx_timeout_ms = 10000,
2433 /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */
2434 .max_msgs = 20,
2435 .max_msg_size = 60,
2436 .rm_type_map = ti_sci_am654_rm_type_map,
1787}; 2437};
1788 2438
1789static const struct of_device_id ti_sci_of_match[] = { 2439static const struct of_device_id ti_sci_of_match[] = {
1790 {.compatible = "ti,k2g-sci", .data = &ti_sci_pmmc_k2g_desc}, 2440 {.compatible = "ti,k2g-sci", .data = &ti_sci_pmmc_k2g_desc},
2441 {.compatible = "ti,am654-sci", .data = &ti_sci_pmmc_am654_desc},
1791 { /* Sentinel */ }, 2442 { /* Sentinel */ },
1792}; 2443};
1793MODULE_DEVICE_TABLE(of, ti_sci_of_match); 2444MODULE_DEVICE_TABLE(of, ti_sci_of_match);
diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
index 12bf316b68df..4983827151bf 100644
--- a/drivers/firmware/ti_sci.h
+++ b/drivers/firmware/ti_sci.h
@@ -35,6 +35,13 @@
35#define TI_SCI_MSG_QUERY_CLOCK_FREQ 0x010d 35#define TI_SCI_MSG_QUERY_CLOCK_FREQ 0x010d
36#define TI_SCI_MSG_GET_CLOCK_FREQ 0x010e 36#define TI_SCI_MSG_GET_CLOCK_FREQ 0x010e
37 37
38/* Resource Management Requests */
39#define TI_SCI_MSG_GET_RESOURCE_RANGE 0x1500
40
41/* IRQ requests */
42#define TI_SCI_MSG_SET_IRQ 0x1000
43#define TI_SCI_MSG_FREE_IRQ 0x1001
44
38/** 45/**
39 * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses 46 * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses
40 * @type: Type of messages: One of TI_SCI_MSG* values 47 * @type: Type of messages: One of TI_SCI_MSG* values
@@ -461,4 +468,99 @@ struct ti_sci_msg_resp_get_clock_freq {
461 u64 freq_hz; 468 u64 freq_hz;
462} __packed; 469} __packed;
463 470
471#define TI_SCI_IRQ_SECONDARY_HOST_INVALID 0xff
472
473/**
474 * struct ti_sci_msg_req_get_resource_range - Request to get a host's assigned
475 * range of resources.
476 * @hdr: Generic Header
477 * @type: Unique resource assignment type
478 * @subtype: Resource assignment subtype within the resource type.
479 * @secondary_host: Host processing entity to which the resources are
480 * allocated. This is required only when the destination
481 * host id id different from ti sci interface host id,
482 * else TI_SCI_IRQ_SECONDARY_HOST_INVALID can be passed.
483 *
484 * Request type is TI_SCI_MSG_GET_RESOURCE_RANGE. Responded with requested
485 * resource range which is of type TI_SCI_MSG_GET_RESOURCE_RANGE.
486 */
487struct ti_sci_msg_req_get_resource_range {
488 struct ti_sci_msg_hdr hdr;
489#define MSG_RM_RESOURCE_TYPE_MASK GENMASK(9, 0)
490#define MSG_RM_RESOURCE_SUBTYPE_MASK GENMASK(5, 0)
491 u16 type;
492 u8 subtype;
493 u8 secondary_host;
494} __packed;
495
496/**
497 * struct ti_sci_msg_resp_get_resource_range - Response to resource get range.
498 * @hdr: Generic Header
499 * @range_start: Start index of the resource range.
500 * @range_num: Number of resources in the range.
501 *
502 * Response to request TI_SCI_MSG_GET_RESOURCE_RANGE.
503 */
504struct ti_sci_msg_resp_get_resource_range {
505 struct ti_sci_msg_hdr hdr;
506 u16 range_start;
507 u16 range_num;
508} __packed;
509
510/**
511 * struct ti_sci_msg_req_manage_irq - Request to configure/release the route
512 * between the dev and the host.
513 * @hdr: Generic Header
514 * @valid_params: Bit fields defining the validity of interrupt source
515 * parameters. If a bit is not set, then corresponding
516 * field is not valid and will not be used for route set.
517 * Bit field definitions:
518 * 0 - Valid bit for @dst_id
519 * 1 - Valid bit for @dst_host_irq
520 * 2 - Valid bit for @ia_id
521 * 3 - Valid bit for @vint
522 * 4 - Valid bit for @global_event
523 * 5 - Valid bit for @vint_status_bit_index
524 * 31 - Valid bit for @secondary_host
525 * @src_id: IRQ source peripheral ID.
526 * @src_index: IRQ source index within the peripheral
527 * @dst_id: IRQ Destination ID. Based on the architecture it can be
528 * IRQ controller or host processor ID.
529 * @dst_host_irq: IRQ number of the destination host IRQ controller
530 * @ia_id: Device ID of the interrupt aggregator in which the
531 * vint resides.
532 * @vint: Virtual interrupt number if the interrupt route
533 * is through an interrupt aggregator.
534 * @global_event: Global event that is to be mapped to interrupt
535 * aggregator virtual interrupt status bit.
536 * @vint_status_bit: Virtual interrupt status bit if the interrupt route
537 * utilizes an interrupt aggregator status bit.
538 * @secondary_host: Host ID of the IRQ destination computing entity. This is
539 * required only when destination host id is different
540 * from ti sci interface host id.
541 *
542 * Request type is TI_SCI_MSG_SET/RELEASE_IRQ.
543 * Response is generic ACK / NACK message.
544 */
545struct ti_sci_msg_req_manage_irq {
546 struct ti_sci_msg_hdr hdr;
547#define MSG_FLAG_DST_ID_VALID TI_SCI_MSG_FLAG(0)
548#define MSG_FLAG_DST_HOST_IRQ_VALID TI_SCI_MSG_FLAG(1)
549#define MSG_FLAG_IA_ID_VALID TI_SCI_MSG_FLAG(2)
550#define MSG_FLAG_VINT_VALID TI_SCI_MSG_FLAG(3)
551#define MSG_FLAG_GLB_EVNT_VALID TI_SCI_MSG_FLAG(4)
552#define MSG_FLAG_VINT_STS_BIT_VALID TI_SCI_MSG_FLAG(5)
553#define MSG_FLAG_SHOST_VALID TI_SCI_MSG_FLAG(31)
554 u32 valid_params;
555 u16 src_id;
556 u16 src_index;
557 u16 dst_id;
558 u16 dst_host_irq;
559 u16 ia_id;
560 u16 vint;
561 u16 global_event;
562 u8 vint_status_bit;
563 u8 secondary_host;
564} __packed;
565
464#endif /* __TI_SCI_H */ 566#endif /* __TI_SCI_H */
diff --git a/drivers/gpio/gpio-thunderx.c b/drivers/gpio/gpio-thunderx.c
index 1306722faa5a..715371b5102a 100644
--- a/drivers/gpio/gpio-thunderx.c
+++ b/drivers/gpio/gpio-thunderx.c
@@ -363,22 +363,16 @@ static int thunderx_gpio_irq_request_resources(struct irq_data *data)
363{ 363{
364 struct thunderx_line *txline = irq_data_get_irq_chip_data(data); 364 struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
365 struct thunderx_gpio *txgpio = txline->txgpio; 365 struct thunderx_gpio *txgpio = txline->txgpio;
366 struct irq_data *parent_data = data->parent_data;
367 int r; 366 int r;
368 367
369 r = gpiochip_lock_as_irq(&txgpio->chip, txline->line); 368 r = gpiochip_lock_as_irq(&txgpio->chip, txline->line);
370 if (r) 369 if (r)
371 return r; 370 return r;
372 371
373 if (parent_data && parent_data->chip->irq_request_resources) { 372 r = irq_chip_request_resources_parent(data);
374 r = parent_data->chip->irq_request_resources(parent_data); 373 if (r)
375 if (r) 374 gpiochip_unlock_as_irq(&txgpio->chip, txline->line);
376 goto error;
377 }
378 375
379 return 0;
380error:
381 gpiochip_unlock_as_irq(&txgpio->chip, txline->line);
382 return r; 376 return r;
383} 377}
384 378
@@ -386,10 +380,8 @@ static void thunderx_gpio_irq_release_resources(struct irq_data *data)
386{ 380{
387 struct thunderx_line *txline = irq_data_get_irq_chip_data(data); 381 struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
388 struct thunderx_gpio *txgpio = txline->txgpio; 382 struct thunderx_gpio *txgpio = txline->txgpio;
389 struct irq_data *parent_data = data->parent_data;
390 383
391 if (parent_data && parent_data->chip->irq_release_resources) 384 irq_chip_release_resources_parent(data);
392 parent_data->chip->irq_release_resources(parent_data);
393 385
394 gpiochip_unlock_as_irq(&txgpio->chip, txline->line); 386 gpiochip_unlock_as_irq(&txgpio->chip, txline->line);
395} 387}
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 15b831113ded..e559e43c8ac2 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -94,6 +94,7 @@ config IOMMU_DMA
94 bool 94 bool
95 select IOMMU_API 95 select IOMMU_API
96 select IOMMU_IOVA 96 select IOMMU_IOVA
97 select IRQ_MSI_IOMMU
97 select NEED_SG_DMA_LENGTH 98 select NEED_SG_DMA_LENGTH
98 99
99config FSL_PAMU 100config FSL_PAMU
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 5e898047c390..129c4badf9ae 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -907,17 +907,18 @@ out_free_page:
907 return NULL; 907 return NULL;
908} 908}
909 909
910void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg) 910int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
911{ 911{
912 struct device *dev = msi_desc_to_dev(irq_get_msi_desc(irq)); 912 struct device *dev = msi_desc_to_dev(desc);
913 struct iommu_domain *domain = iommu_get_domain_for_dev(dev); 913 struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
914 struct iommu_dma_cookie *cookie; 914 struct iommu_dma_cookie *cookie;
915 struct iommu_dma_msi_page *msi_page; 915 struct iommu_dma_msi_page *msi_page;
916 phys_addr_t msi_addr = (u64)msg->address_hi << 32 | msg->address_lo;
917 unsigned long flags; 916 unsigned long flags;
918 917
919 if (!domain || !domain->iova_cookie) 918 if (!domain || !domain->iova_cookie) {
920 return; 919 desc->iommu_cookie = NULL;
920 return 0;
921 }
921 922
922 cookie = domain->iova_cookie; 923 cookie = domain->iova_cookie;
923 924
@@ -930,19 +931,26 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
930 msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain); 931 msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain);
931 spin_unlock_irqrestore(&cookie->msi_lock, flags); 932 spin_unlock_irqrestore(&cookie->msi_lock, flags);
932 933
933 if (WARN_ON(!msi_page)) { 934 msi_desc_set_iommu_cookie(desc, msi_page);
934 /* 935
935 * We're called from a void callback, so the best we can do is 936 if (!msi_page)
936 * 'fail' by filling the message with obviously bogus values. 937 return -ENOMEM;
937 * Since we got this far due to an IOMMU being present, it's 938 return 0;
938 * not like the existing address would have worked anyway... 939}
939 */ 940
940 msg->address_hi = ~0U; 941void iommu_dma_compose_msi_msg(struct msi_desc *desc,
941 msg->address_lo = ~0U; 942 struct msi_msg *msg)
942 msg->data = ~0U; 943{
943 } else { 944 struct device *dev = msi_desc_to_dev(desc);
944 msg->address_hi = upper_32_bits(msi_page->iova); 945 const struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
945 msg->address_lo &= cookie_msi_granule(cookie) - 1; 946 const struct iommu_dma_msi_page *msi_page;
946 msg->address_lo += lower_32_bits(msi_page->iova); 947
947 } 948 msi_page = msi_desc_get_iommu_cookie(desc);
949
950 if (!domain || !domain->iova_cookie || WARN_ON(!msi_page))
951 return;
952
953 msg->address_hi = upper_32_bits(msi_page->iova);
954 msg->address_lo &= cookie_msi_granule(domain->iova_cookie) - 1;
955 msg->address_lo += lower_32_bits(msi_page->iova);
948} 956}
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index cf7984991062..1c1f3f66dfd3 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -6,7 +6,6 @@ config IRQCHIP
6 6
7config ARM_GIC 7config ARM_GIC
8 bool 8 bool
9 select IRQ_DOMAIN
10 select IRQ_DOMAIN_HIERARCHY 9 select IRQ_DOMAIN_HIERARCHY
11 select GENERIC_IRQ_MULTI_HANDLER 10 select GENERIC_IRQ_MULTI_HANDLER
12 select GENERIC_IRQ_EFFECTIVE_AFF_MASK 11 select GENERIC_IRQ_EFFECTIVE_AFF_MASK
@@ -33,7 +32,6 @@ config GIC_NON_BANKED
33 32
34config ARM_GIC_V3 33config ARM_GIC_V3
35 bool 34 bool
36 select IRQ_DOMAIN
37 select GENERIC_IRQ_MULTI_HANDLER 35 select GENERIC_IRQ_MULTI_HANDLER
38 select IRQ_DOMAIN_HIERARCHY 36 select IRQ_DOMAIN_HIERARCHY
39 select PARTITION_PERCPU 37 select PARTITION_PERCPU
@@ -59,7 +57,6 @@ config ARM_GIC_V3_ITS_FSL_MC
59 57
60config ARM_NVIC 58config ARM_NVIC
61 bool 59 bool
62 select IRQ_DOMAIN
63 select IRQ_DOMAIN_HIERARCHY 60 select IRQ_DOMAIN_HIERARCHY
64 select GENERIC_IRQ_CHIP 61 select GENERIC_IRQ_CHIP
65 62
@@ -358,7 +355,6 @@ config STM32_EXTI
358config QCOM_IRQ_COMBINER 355config QCOM_IRQ_COMBINER
359 bool "QCOM IRQ combiner support" 356 bool "QCOM IRQ combiner support"
360 depends on ARCH_QCOM && ACPI 357 depends on ARCH_QCOM && ACPI
361 select IRQ_DOMAIN
362 select IRQ_DOMAIN_HIERARCHY 358 select IRQ_DOMAIN_HIERARCHY
363 help 359 help
364 Say yes here to add support for the IRQ combiner devices embedded 360 Say yes here to add support for the IRQ combiner devices embedded
@@ -375,7 +371,6 @@ config IRQ_UNIPHIER_AIDET
375config MESON_IRQ_GPIO 371config MESON_IRQ_GPIO
376 bool "Meson GPIO Interrupt Multiplexer" 372 bool "Meson GPIO Interrupt Multiplexer"
377 depends on ARCH_MESON 373 depends on ARCH_MESON
378 select IRQ_DOMAIN
379 select IRQ_DOMAIN_HIERARCHY 374 select IRQ_DOMAIN_HIERARCHY
380 help 375 help
381 Support Meson SoC Family GPIO Interrupt Multiplexer 376 Support Meson SoC Family GPIO Interrupt Multiplexer
@@ -391,7 +386,6 @@ config GOLDFISH_PIC
391config QCOM_PDC 386config QCOM_PDC
392 bool "QCOM PDC" 387 bool "QCOM PDC"
393 depends on ARCH_QCOM 388 depends on ARCH_QCOM
394 select IRQ_DOMAIN
395 select IRQ_DOMAIN_HIERARCHY 389 select IRQ_DOMAIN_HIERARCHY
396 help 390 help
397 Power Domain Controller driver to manage and configure wakeup 391 Power Domain Controller driver to manage and configure wakeup
@@ -431,6 +425,27 @@ config LS1X_IRQ
431 help 425 help
432 Support for the Loongson-1 platform Interrupt Controller. 426 Support for the Loongson-1 platform Interrupt Controller.
433 427
428config TI_SCI_INTR_IRQCHIP
429 bool
430 depends on TI_SCI_PROTOCOL
431 select IRQ_DOMAIN_HIERARCHY
432 help
433 This enables the irqchip driver support for K3 Interrupt router
434 over TI System Control Interface available on some new TI's SoCs.
435 If you wish to use interrupt router irq resources managed by the
436 TI System Controller, say Y here. Otherwise, say N.
437
438config TI_SCI_INTA_IRQCHIP
439 bool
440 depends on TI_SCI_PROTOCOL
441 select IRQ_DOMAIN_HIERARCHY
442 select TI_SCI_INTA_MSI_DOMAIN
443 help
444 This enables the irqchip driver support for K3 Interrupt aggregator
445 over TI System Control Interface available on some new TI's SoCs.
446 If you wish to use interrupt aggregator irq resources managed by the
447 TI System Controller, say Y here. Otherwise, say N.
448
434endmenu 449endmenu
435 450
436config SIFIVE_PLIC 451config SIFIVE_PLIC
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index f8c66e958a64..606a003a0000 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -98,3 +98,5 @@ obj-$(CONFIG_SIFIVE_PLIC) += irq-sifive-plic.o
98obj-$(CONFIG_IMX_IRQSTEER) += irq-imx-irqsteer.o 98obj-$(CONFIG_IMX_IRQSTEER) += irq-imx-irqsteer.o
99obj-$(CONFIG_MADERA_IRQ) += irq-madera.o 99obj-$(CONFIG_MADERA_IRQ) += irq-madera.o
100obj-$(CONFIG_LS1X_IRQ) += irq-ls1x.o 100obj-$(CONFIG_LS1X_IRQ) += irq-ls1x.o
101obj-$(CONFIG_TI_SCI_INTR_IRQCHIP) += irq-ti-sci-intr.o
102obj-$(CONFIG_TI_SCI_INTA_IRQCHIP) += irq-ti-sci-inta.o
diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c
index 0f6e30e9009d..0acebac1920b 100644
--- a/drivers/irqchip/irq-bcm7038-l1.c
+++ b/drivers/irqchip/irq-bcm7038-l1.c
@@ -343,6 +343,9 @@ int __init bcm7038_l1_of_init(struct device_node *dn,
343 goto out_unmap; 343 goto out_unmap;
344 } 344 }
345 345
346 pr_info("registered BCM7038 L1 intc (%pOF, IRQs: %d)\n",
347 dn, IRQS_PER_WORD * intc->n_words);
348
346 return 0; 349 return 0;
347 350
348out_unmap: 351out_unmap:
diff --git a/drivers/irqchip/irq-bcm7120-l2.c b/drivers/irqchip/irq-bcm7120-l2.c
index 8968e5e93fcb..541bdca9f4af 100644
--- a/drivers/irqchip/irq-bcm7120-l2.c
+++ b/drivers/irqchip/irq-bcm7120-l2.c
@@ -318,6 +318,9 @@ static int __init bcm7120_l2_intc_probe(struct device_node *dn,
318 } 318 }
319 } 319 }
320 320
321 pr_info("registered %s intc (%pOF, parent IRQ(s): %d)\n",
322 intc_name, dn, data->num_parent_irqs);
323
321 return 0; 324 return 0;
322 325
323out_free_domain: 326out_free_domain:
diff --git a/drivers/irqchip/irq-brcmstb-l2.c b/drivers/irqchip/irq-brcmstb-l2.c
index 5e4ca139e4ea..a0642b59befa 100644
--- a/drivers/irqchip/irq-brcmstb-l2.c
+++ b/drivers/irqchip/irq-brcmstb-l2.c
@@ -264,6 +264,8 @@ static int __init brcmstb_l2_intc_of_init(struct device_node *np,
264 ct->chip.irq_set_wake = irq_gc_set_wake; 264 ct->chip.irq_set_wake = irq_gc_set_wake;
265 } 265 }
266 266
267 pr_info("registered L2 intc (%pOF, parent irq: %d)\n", np, parent_irq);
268
267 return 0; 269 return 0;
268 270
269out_free_domain: 271out_free_domain:
diff --git a/drivers/irqchip/irq-gic-pm.c b/drivers/irqchip/irq-gic-pm.c
index ecafd295c31c..c4aac0977d8a 100644
--- a/drivers/irqchip/irq-gic-pm.c
+++ b/drivers/irqchip/irq-gic-pm.c
@@ -19,7 +19,6 @@
19#include <linux/of_irq.h> 19#include <linux/of_irq.h>
20#include <linux/irqchip/arm-gic.h> 20#include <linux/irqchip/arm-gic.h>
21#include <linux/platform_device.h> 21#include <linux/platform_device.h>
22#include <linux/pm_clock.h>
23#include <linux/pm_runtime.h> 22#include <linux/pm_runtime.h>
24#include <linux/slab.h> 23#include <linux/slab.h>
25 24
@@ -28,17 +27,27 @@ struct gic_clk_data {
28 const char *const *clocks; 27 const char *const *clocks;
29}; 28};
30 29
30struct gic_chip_pm {
31 struct gic_chip_data *chip_data;
32 const struct gic_clk_data *clk_data;
33 struct clk_bulk_data *clks;
34};
35
31static int gic_runtime_resume(struct device *dev) 36static int gic_runtime_resume(struct device *dev)
32{ 37{
33 struct gic_chip_data *gic = dev_get_drvdata(dev); 38 struct gic_chip_pm *chip_pm = dev_get_drvdata(dev);
39 struct gic_chip_data *gic = chip_pm->chip_data;
40 const struct gic_clk_data *data = chip_pm->clk_data;
34 int ret; 41 int ret;
35 42
36 ret = pm_clk_resume(dev); 43 ret = clk_bulk_prepare_enable(data->num_clocks, chip_pm->clks);
37 if (ret) 44 if (ret) {
45 dev_err(dev, "clk_enable failed: %d\n", ret);
38 return ret; 46 return ret;
47 }
39 48
40 /* 49 /*
41 * On the very first resume, the pointer to the driver data 50 * On the very first resume, the pointer to chip_pm->chip_data
42 * will be NULL and this is intentional, because we do not 51 * will be NULL and this is intentional, because we do not
43 * want to restore the GIC on the very first resume. So if 52 * want to restore the GIC on the very first resume. So if
44 * the pointer is not valid just return. 53 * the pointer is not valid just return.
@@ -54,35 +63,14 @@ static int gic_runtime_resume(struct device *dev)
54 63
55static int gic_runtime_suspend(struct device *dev) 64static int gic_runtime_suspend(struct device *dev)
56{ 65{
57 struct gic_chip_data *gic = dev_get_drvdata(dev); 66 struct gic_chip_pm *chip_pm = dev_get_drvdata(dev);
67 struct gic_chip_data *gic = chip_pm->chip_data;
68 const struct gic_clk_data *data = chip_pm->clk_data;
58 69
59 gic_dist_save(gic); 70 gic_dist_save(gic);
60 gic_cpu_save(gic); 71 gic_cpu_save(gic);
61 72
62 return pm_clk_suspend(dev); 73 clk_bulk_disable_unprepare(data->num_clocks, chip_pm->clks);
63}
64
65static int gic_get_clocks(struct device *dev, const struct gic_clk_data *data)
66{
67 unsigned int i;
68 int ret;
69
70 if (!dev || !data)
71 return -EINVAL;
72
73 ret = pm_clk_create(dev);
74 if (ret)
75 return ret;
76
77 for (i = 0; i < data->num_clocks; i++) {
78 ret = of_pm_clk_add_clk(dev, data->clocks[i]);
79 if (ret) {
80 dev_err(dev, "failed to add clock %s\n",
81 data->clocks[i]);
82 pm_clk_destroy(dev);
83 return ret;
84 }
85 }
86 74
87 return 0; 75 return 0;
88} 76}
@@ -91,8 +79,8 @@ static int gic_probe(struct platform_device *pdev)
91{ 79{
92 struct device *dev = &pdev->dev; 80 struct device *dev = &pdev->dev;
93 const struct gic_clk_data *data; 81 const struct gic_clk_data *data;
94 struct gic_chip_data *gic; 82 struct gic_chip_pm *chip_pm;
95 int ret, irq; 83 int ret, irq, i;
96 84
97 data = of_device_get_match_data(&pdev->dev); 85 data = of_device_get_match_data(&pdev->dev);
98 if (!data) { 86 if (!data) {
@@ -100,28 +88,41 @@ static int gic_probe(struct platform_device *pdev)
100 return -ENODEV; 88 return -ENODEV;
101 } 89 }
102 90
91 chip_pm = devm_kzalloc(dev, sizeof(*chip_pm), GFP_KERNEL);
92 if (!chip_pm)
93 return -ENOMEM;
94
103 irq = irq_of_parse_and_map(dev->of_node, 0); 95 irq = irq_of_parse_and_map(dev->of_node, 0);
104 if (!irq) { 96 if (!irq) {
105 dev_err(dev, "no parent interrupt found!\n"); 97 dev_err(dev, "no parent interrupt found!\n");
106 return -EINVAL; 98 return -EINVAL;
107 } 99 }
108 100
109 ret = gic_get_clocks(dev, data); 101 chip_pm->clks = devm_kcalloc(dev, data->num_clocks,
102 sizeof(*chip_pm->clks), GFP_KERNEL);
103 if (!chip_pm->clks)
104 return -ENOMEM;
105
106 for (i = 0; i < data->num_clocks; i++)
107 chip_pm->clks[i].id = data->clocks[i];
108
109 ret = devm_clk_bulk_get(dev, data->num_clocks, chip_pm->clks);
110 if (ret) 110 if (ret)
111 goto irq_dispose; 111 goto irq_dispose;
112 112
113 chip_pm->clk_data = data;
114 dev_set_drvdata(dev, chip_pm);
115
113 pm_runtime_enable(dev); 116 pm_runtime_enable(dev);
114 117
115 ret = pm_runtime_get_sync(dev); 118 ret = pm_runtime_get_sync(dev);
116 if (ret < 0) 119 if (ret < 0)
117 goto rpm_disable; 120 goto rpm_disable;
118 121
119 ret = gic_of_init_child(dev, &gic, irq); 122 ret = gic_of_init_child(dev, &chip_pm->chip_data, irq);
120 if (ret) 123 if (ret)
121 goto rpm_put; 124 goto rpm_put;
122 125
123 platform_set_drvdata(pdev, gic);
124
125 pm_runtime_put(dev); 126 pm_runtime_put(dev);
126 127
127 dev_info(dev, "GIC IRQ controller registered\n"); 128 dev_info(dev, "GIC IRQ controller registered\n");
@@ -132,7 +133,6 @@ rpm_put:
132 pm_runtime_put_sync(dev); 133 pm_runtime_put_sync(dev);
133rpm_disable: 134rpm_disable:
134 pm_runtime_disable(dev); 135 pm_runtime_disable(dev);
135 pm_clk_destroy(dev);
136irq_dispose: 136irq_dispose:
137 irq_dispose_mapping(irq); 137 irq_dispose_mapping(irq);
138 138
@@ -142,6 +142,8 @@ irq_dispose:
142static const struct dev_pm_ops gic_pm_ops = { 142static const struct dev_pm_ops gic_pm_ops = {
143 SET_RUNTIME_PM_OPS(gic_runtime_suspend, 143 SET_RUNTIME_PM_OPS(gic_runtime_suspend,
144 gic_runtime_resume, NULL) 144 gic_runtime_resume, NULL)
145 SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
146 pm_runtime_force_resume)
145}; 147};
146 148
147static const char * const gic400_clocks[] = { 149static const char * const gic400_clocks[] = {
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index de14e06fd9ec..3c77ab676e54 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -110,7 +110,7 @@ static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
110 if (v2m->flags & GICV2M_NEEDS_SPI_OFFSET) 110 if (v2m->flags & GICV2M_NEEDS_SPI_OFFSET)
111 msg->data -= v2m->spi_offset; 111 msg->data -= v2m->spi_offset;
112 112
113 iommu_dma_map_msi_msg(data->irq, msg); 113 iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), msg);
114} 114}
115 115
116static struct irq_chip gicv2m_irq_chip = { 116static struct irq_chip gicv2m_irq_chip = {
@@ -167,6 +167,7 @@ static void gicv2m_unalloc_msi(struct v2m_data *v2m, unsigned int hwirq,
167static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, 167static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
168 unsigned int nr_irqs, void *args) 168 unsigned int nr_irqs, void *args)
169{ 169{
170 msi_alloc_info_t *info = args;
170 struct v2m_data *v2m = NULL, *tmp; 171 struct v2m_data *v2m = NULL, *tmp;
171 int hwirq, offset, i, err = 0; 172 int hwirq, offset, i, err = 0;
172 173
@@ -186,6 +187,11 @@ static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
186 187
187 hwirq = v2m->spi_start + offset; 188 hwirq = v2m->spi_start + offset;
188 189
190 err = iommu_dma_prepare_msi(info->desc,
191 v2m->res.start + V2M_MSI_SETSPI_NS);
192 if (err)
193 return err;
194
189 for (i = 0; i < nr_irqs; i++) { 195 for (i = 0; i < nr_irqs; i++) {
190 err = gicv2m_irq_gic_domain_alloc(domain, virq + i, hwirq + i); 196 err = gicv2m_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
191 if (err) 197 if (err)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 128ac893d7e4..cfb9b4e5f914 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -26,7 +26,6 @@
26#include <linux/interrupt.h> 26#include <linux/interrupt.h>
27#include <linux/irqdomain.h> 27#include <linux/irqdomain.h>
28#include <linux/list.h> 28#include <linux/list.h>
29#include <linux/list_sort.h>
30#include <linux/log2.h> 29#include <linux/log2.h>
31#include <linux/memblock.h> 30#include <linux/memblock.h>
32#include <linux/mm.h> 31#include <linux/mm.h>
@@ -1179,7 +1178,7 @@ static void its_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg)
1179 msg->address_hi = upper_32_bits(addr); 1178 msg->address_hi = upper_32_bits(addr);
1180 msg->data = its_get_event_id(d); 1179 msg->data = its_get_event_id(d);
1181 1180
1182 iommu_dma_map_msi_msg(d->irq, msg); 1181 iommu_dma_compose_msi_msg(irq_data_get_msi_desc(d), msg);
1183} 1182}
1184 1183
1185static int its_irq_set_irqchip_state(struct irq_data *d, 1184static int its_irq_set_irqchip_state(struct irq_data *d,
@@ -1465,9 +1464,8 @@ static struct lpi_range *mk_lpi_range(u32 base, u32 span)
1465{ 1464{
1466 struct lpi_range *range; 1465 struct lpi_range *range;
1467 1466
1468 range = kzalloc(sizeof(*range), GFP_KERNEL); 1467 range = kmalloc(sizeof(*range), GFP_KERNEL);
1469 if (range) { 1468 if (range) {
1470 INIT_LIST_HEAD(&range->entry);
1471 range->base_id = base; 1469 range->base_id = base;
1472 range->span = span; 1470 range->span = span;
1473 } 1471 }
@@ -1475,31 +1473,6 @@ static struct lpi_range *mk_lpi_range(u32 base, u32 span)
1475 return range; 1473 return range;
1476} 1474}
1477 1475
1478static int lpi_range_cmp(void *priv, struct list_head *a, struct list_head *b)
1479{
1480 struct lpi_range *ra, *rb;
1481
1482 ra = container_of(a, struct lpi_range, entry);
1483 rb = container_of(b, struct lpi_range, entry);
1484
1485 return ra->base_id - rb->base_id;
1486}
1487
1488static void merge_lpi_ranges(void)
1489{
1490 struct lpi_range *range, *tmp;
1491
1492 list_for_each_entry_safe(range, tmp, &lpi_range_list, entry) {
1493 if (!list_is_last(&range->entry, &lpi_range_list) &&
1494 (tmp->base_id == (range->base_id + range->span))) {
1495 tmp->base_id = range->base_id;
1496 tmp->span += range->span;
1497 list_del(&range->entry);
1498 kfree(range);
1499 }
1500 }
1501}
1502
1503static int alloc_lpi_range(u32 nr_lpis, u32 *base) 1476static int alloc_lpi_range(u32 nr_lpis, u32 *base)
1504{ 1477{
1505 struct lpi_range *range, *tmp; 1478 struct lpi_range *range, *tmp;
@@ -1529,25 +1502,49 @@ static int alloc_lpi_range(u32 nr_lpis, u32 *base)
1529 return err; 1502 return err;
1530} 1503}
1531 1504
1505static void merge_lpi_ranges(struct lpi_range *a, struct lpi_range *b)
1506{
1507 if (&a->entry == &lpi_range_list || &b->entry == &lpi_range_list)
1508 return;
1509 if (a->base_id + a->span != b->base_id)
1510 return;
1511 b->base_id = a->base_id;
1512 b->span += a->span;
1513 list_del(&a->entry);
1514 kfree(a);
1515}
1516
1532static int free_lpi_range(u32 base, u32 nr_lpis) 1517static int free_lpi_range(u32 base, u32 nr_lpis)
1533{ 1518{
1534 struct lpi_range *new; 1519 struct lpi_range *new, *old;
1535 int err = 0; 1520
1521 new = mk_lpi_range(base, nr_lpis);
1522 if (!new)
1523 return -ENOMEM;
1536 1524
1537 mutex_lock(&lpi_range_lock); 1525 mutex_lock(&lpi_range_lock);
1538 1526
1539 new = mk_lpi_range(base, nr_lpis); 1527 list_for_each_entry_reverse(old, &lpi_range_list, entry) {
1540 if (!new) { 1528 if (old->base_id < base)
1541 err = -ENOMEM; 1529 break;
1542 goto out;
1543 } 1530 }
1531 /*
1532 * old is the last element with ->base_id smaller than base,
1533 * so new goes right after it. If there are no elements with
1534 * ->base_id smaller than base, &old->entry ends up pointing
1535 * at the head of the list, and inserting new it the start of
1536 * the list is the right thing to do in that case as well.
1537 */
1538 list_add(&new->entry, &old->entry);
1539 /*
1540 * Now check if we can merge with the preceding and/or
1541 * following ranges.
1542 */
1543 merge_lpi_ranges(old, new);
1544 merge_lpi_ranges(new, list_next_entry(new, entry));
1544 1545
1545 list_add(&new->entry, &lpi_range_list);
1546 list_sort(NULL, &lpi_range_list, lpi_range_cmp);
1547 merge_lpi_ranges();
1548out:
1549 mutex_unlock(&lpi_range_lock); 1546 mutex_unlock(&lpi_range_lock);
1550 return err; 1547 return 0;
1551} 1548}
1552 1549
1553static int __init its_lpi_init(u32 id_bits) 1550static int __init its_lpi_init(u32 id_bits)
@@ -2487,7 +2484,7 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
2487 int err = 0; 2484 int err = 0;
2488 2485
2489 /* 2486 /*
2490 * We ignore "dev" entierely, and rely on the dev_id that has 2487 * We ignore "dev" entirely, and rely on the dev_id that has
2491 * been passed via the scratchpad. This limits this domain's 2488 * been passed via the scratchpad. This limits this domain's
2492 * usefulness to upper layers that definitely know that they 2489 * usefulness to upper layers that definitely know that they
2493 * are built on top of the ITS. 2490 * are built on top of the ITS.
@@ -2566,6 +2563,7 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
2566{ 2563{
2567 msi_alloc_info_t *info = args; 2564 msi_alloc_info_t *info = args;
2568 struct its_device *its_dev = info->scratchpad[0].ptr; 2565 struct its_device *its_dev = info->scratchpad[0].ptr;
2566 struct its_node *its = its_dev->its;
2569 irq_hw_number_t hwirq; 2567 irq_hw_number_t hwirq;
2570 int err; 2568 int err;
2571 int i; 2569 int i;
@@ -2574,6 +2572,10 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
2574 if (err) 2572 if (err)
2575 return err; 2573 return err;
2576 2574
2575 err = iommu_dma_prepare_msi(info->desc, its->get_msi_base(its_dev));
2576 if (err)
2577 return err;
2578
2577 for (i = 0; i < nr_irqs; i++) { 2579 for (i = 0; i < nr_irqs; i++) {
2578 err = its_irq_gic_domain_alloc(domain, virq + i, hwirq + i); 2580 err = its_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
2579 if (err) 2581 if (err)
diff --git a/drivers/irqchip/irq-gic-v3-mbi.c b/drivers/irqchip/irq-gic-v3-mbi.c
index fbfa7ff6deb1..563a9b366294 100644
--- a/drivers/irqchip/irq-gic-v3-mbi.c
+++ b/drivers/irqchip/irq-gic-v3-mbi.c
@@ -84,6 +84,7 @@ static void mbi_free_msi(struct mbi_range *mbi, unsigned int hwirq,
84static int mbi_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, 84static int mbi_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
85 unsigned int nr_irqs, void *args) 85 unsigned int nr_irqs, void *args)
86{ 86{
87 msi_alloc_info_t *info = args;
87 struct mbi_range *mbi = NULL; 88 struct mbi_range *mbi = NULL;
88 int hwirq, offset, i, err = 0; 89 int hwirq, offset, i, err = 0;
89 90
@@ -104,6 +105,11 @@ static int mbi_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
104 105
105 hwirq = mbi->spi_start + offset; 106 hwirq = mbi->spi_start + offset;
106 107
108 err = iommu_dma_prepare_msi(info->desc,
109 mbi_phys_base + GICD_SETSPI_NSR);
110 if (err)
111 return err;
112
107 for (i = 0; i < nr_irqs; i++) { 113 for (i = 0; i < nr_irqs; i++) {
108 err = mbi_irq_gic_domain_alloc(domain, virq + i, hwirq + i); 114 err = mbi_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
109 if (err) 115 if (err)
@@ -142,7 +148,7 @@ static void mbi_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
142 msg[0].address_lo = lower_32_bits(mbi_phys_base + GICD_SETSPI_NSR); 148 msg[0].address_lo = lower_32_bits(mbi_phys_base + GICD_SETSPI_NSR);
143 msg[0].data = data->parent_data->hwirq; 149 msg[0].data = data->parent_data->hwirq;
144 150
145 iommu_dma_map_msi_msg(data->irq, msg); 151 iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), msg);
146} 152}
147 153
148#ifdef CONFIG_PCI_MSI 154#ifdef CONFIG_PCI_MSI
@@ -202,7 +208,7 @@ static void mbi_compose_mbi_msg(struct irq_data *data, struct msi_msg *msg)
202 msg[1].address_lo = lower_32_bits(mbi_phys_base + GICD_CLRSPI_NSR); 208 msg[1].address_lo = lower_32_bits(mbi_phys_base + GICD_CLRSPI_NSR);
203 msg[1].data = data->parent_data->hwirq; 209 msg[1].data = data->parent_data->hwirq;
204 210
205 iommu_dma_map_msi_msg(data->irq, &msg[1]); 211 iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), &msg[1]);
206} 212}
207 213
208/* Platform-MSI specific irqchip */ 214/* Platform-MSI specific irqchip */
diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
index 88df3d00052c..290531ec3d61 100644
--- a/drivers/irqchip/irq-imx-irqsteer.c
+++ b/drivers/irqchip/irq-imx-irqsteer.c
@@ -144,7 +144,6 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
144{ 144{
145 struct device_node *np = pdev->dev.of_node; 145 struct device_node *np = pdev->dev.of_node;
146 struct irqsteer_data *data; 146 struct irqsteer_data *data;
147 struct resource *res;
148 u32 irqs_num; 147 u32 irqs_num;
149 int i, ret; 148 int i, ret;
150 149
@@ -152,8 +151,7 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
152 if (!data) 151 if (!data)
153 return -ENOMEM; 152 return -ENOMEM;
154 153
155 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 154 data->regs = devm_platform_ioremap_resource(pdev, 0);
156 data->regs = devm_ioremap_resource(&pdev->dev, res);
157 if (IS_ERR(data->regs)) { 155 if (IS_ERR(data->regs)) {
158 dev_err(&pdev->dev, "failed to initialize reg\n"); 156 dev_err(&pdev->dev, "failed to initialize reg\n");
159 return PTR_ERR(data->regs); 157 return PTR_ERR(data->regs);
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
index c671b3212010..669d29105772 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -100,7 +100,7 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
100 msg->data |= cpumask_first(mask); 100 msg->data |= cpumask_first(mask);
101 } 101 }
102 102
103 iommu_dma_map_msi_msg(data->irq, msg); 103 iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), msg);
104} 104}
105 105
106static int ls_scfg_msi_set_affinity(struct irq_data *irq_data, 106static int ls_scfg_msi_set_affinity(struct irq_data *irq_data,
@@ -141,6 +141,7 @@ static int ls_scfg_msi_domain_irq_alloc(struct irq_domain *domain,
141 unsigned int nr_irqs, 141 unsigned int nr_irqs,
142 void *args) 142 void *args)
143{ 143{
144 msi_alloc_info_t *info = args;
144 struct ls_scfg_msi *msi_data = domain->host_data; 145 struct ls_scfg_msi *msi_data = domain->host_data;
145 int pos, err = 0; 146 int pos, err = 0;
146 147
@@ -157,6 +158,10 @@ static int ls_scfg_msi_domain_irq_alloc(struct irq_domain *domain,
157 if (err) 158 if (err)
158 return err; 159 return err;
159 160
161 err = iommu_dma_prepare_msi(info->desc, msi_data->msiir_addr);
162 if (err)
163 return err;
164
160 irq_domain_set_info(domain, virq, pos, 165 irq_domain_set_info(domain, virq, pos,
161 &ls_scfg_msi_parent_chip, msi_data, 166 &ls_scfg_msi_parent_chip, msi_data,
162 handle_simple_irq, NULL, NULL); 167 handle_simple_irq, NULL, NULL);
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
index 8c039525703f..04c05a18600c 100644
--- a/drivers/irqchip/irq-renesas-intc-irqpin.c
+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
@@ -389,10 +389,8 @@ static int intc_irqpin_probe(struct platform_device *pdev)
389 int k; 389 int k;
390 390
391 p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL); 391 p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);
392 if (!p) { 392 if (!p)
393 dev_err(dev, "failed to allocate driver data\n");
394 return -ENOMEM; 393 return -ENOMEM;
395 }
396 394
397 /* deal with driver instance configuration */ 395 /* deal with driver instance configuration */
398 of_property_read_u32(dev->of_node, "sense-bitfield-width", 396 of_property_read_u32(dev->of_node, "sense-bitfield-width",
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
index 7bd1d4cb2e19..e00f2fa27f00 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -14,8 +14,10 @@
14#include <linux/irqchip.h> 14#include <linux/irqchip.h>
15#include <linux/irqchip/chained_irq.h> 15#include <linux/irqchip/chained_irq.h>
16#include <linux/irqdomain.h> 16#include <linux/irqdomain.h>
17#include <linux/module.h>
17#include <linux/of_address.h> 18#include <linux/of_address.h>
18#include <linux/of_irq.h> 19#include <linux/of_irq.h>
20#include <linux/of_platform.h>
19#include <linux/syscore_ops.h> 21#include <linux/syscore_ops.h>
20 22
21#include <dt-bindings/interrupt-controller/arm-gic.h> 23#include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -37,12 +39,6 @@ struct stm32_exti_bank {
37 39
38#define UNDEF_REG ~0 40#define UNDEF_REG ~0
39 41
40enum stm32_exti_hwspinlock {
41 HWSPINLOCK_UNKNOWN,
42 HWSPINLOCK_NONE,
43 HWSPINLOCK_READY,
44};
45
46struct stm32_desc_irq { 42struct stm32_desc_irq {
47 u32 exti; 43 u32 exti;
48 u32 irq_parent; 44 u32 irq_parent;
@@ -69,8 +65,6 @@ struct stm32_exti_host_data {
69 void __iomem *base; 65 void __iomem *base;
70 struct stm32_exti_chip_data *chips_data; 66 struct stm32_exti_chip_data *chips_data;
71 const struct stm32_exti_drv_data *drv_data; 67 const struct stm32_exti_drv_data *drv_data;
72 struct device_node *node;
73 enum stm32_exti_hwspinlock hwlock_state;
74 struct hwspinlock *hwlock; 68 struct hwspinlock *hwlock;
75}; 69};
76 70
@@ -285,49 +279,27 @@ static int stm32_exti_set_type(struct irq_data *d,
285 279
286static int stm32_exti_hwspin_lock(struct stm32_exti_chip_data *chip_data) 280static int stm32_exti_hwspin_lock(struct stm32_exti_chip_data *chip_data)
287{ 281{
288 struct stm32_exti_host_data *host_data = chip_data->host_data; 282 int ret, timeout = 0;
289 struct hwspinlock *hwlock;
290 int id, ret = 0, timeout = 0;
291
292 /* first time, check for hwspinlock availability */
293 if (unlikely(host_data->hwlock_state == HWSPINLOCK_UNKNOWN)) {
294 id = of_hwspin_lock_get_id(host_data->node, 0);
295 if (id >= 0) {
296 hwlock = hwspin_lock_request_specific(id);
297 if (hwlock) {
298 /* found valid hwspinlock */
299 host_data->hwlock_state = HWSPINLOCK_READY;
300 host_data->hwlock = hwlock;
301 pr_debug("%s hwspinlock = %d\n", __func__, id);
302 } else {
303 host_data->hwlock_state = HWSPINLOCK_NONE;
304 }
305 } else if (id != -EPROBE_DEFER) {
306 host_data->hwlock_state = HWSPINLOCK_NONE;
307 } else {
308 /* hwspinlock driver shall be ready at that stage */
309 ret = -EPROBE_DEFER;
310 }
311 }
312 283
313 if (likely(host_data->hwlock_state == HWSPINLOCK_READY)) { 284 if (!chip_data->host_data->hwlock)
314 /* 285 return 0;
315 * Use the x_raw API since we are under spin_lock protection. 286
316 * Do not use the x_timeout API because we are under irq_disable 287 /*
317 * mode (see __setup_irq()) 288 * Use the x_raw API since we are under spin_lock protection.
318 */ 289 * Do not use the x_timeout API because we are under irq_disable
319 do { 290 * mode (see __setup_irq())
320 ret = hwspin_trylock_raw(host_data->hwlock); 291 */
321 if (!ret) 292 do {
322 return 0; 293 ret = hwspin_trylock_raw(chip_data->host_data->hwlock);
323 294 if (!ret)
324 udelay(HWSPNLCK_RETRY_DELAY); 295 return 0;
325 timeout += HWSPNLCK_RETRY_DELAY; 296
326 } while (timeout < HWSPNLCK_TIMEOUT); 297 udelay(HWSPNLCK_RETRY_DELAY);
327 298 timeout += HWSPNLCK_RETRY_DELAY;
328 if (ret == -EBUSY) 299 } while (timeout < HWSPNLCK_TIMEOUT);
329 ret = -ETIMEDOUT; 300
330 } 301 if (ret == -EBUSY)
302 ret = -ETIMEDOUT;
331 303
332 if (ret) 304 if (ret)
333 pr_err("%s can't get hwspinlock (%d)\n", __func__, ret); 305 pr_err("%s can't get hwspinlock (%d)\n", __func__, ret);
@@ -337,7 +309,7 @@ static int stm32_exti_hwspin_lock(struct stm32_exti_chip_data *chip_data)
337 309
338static void stm32_exti_hwspin_unlock(struct stm32_exti_chip_data *chip_data) 310static void stm32_exti_hwspin_unlock(struct stm32_exti_chip_data *chip_data)
339{ 311{
340 if (likely(chip_data->host_data->hwlock_state == HWSPINLOCK_READY)) 312 if (chip_data->host_data->hwlock)
341 hwspin_unlock_raw(chip_data->host_data->hwlock); 313 hwspin_unlock_raw(chip_data->host_data->hwlock);
342} 314}
343 315
@@ -586,8 +558,7 @@ static int stm32_exti_h_set_affinity(struct irq_data *d,
586 return -EINVAL; 558 return -EINVAL;
587} 559}
588 560
589#ifdef CONFIG_PM 561static int __maybe_unused stm32_exti_h_suspend(void)
590static int stm32_exti_h_suspend(void)
591{ 562{
592 struct stm32_exti_chip_data *chip_data; 563 struct stm32_exti_chip_data *chip_data;
593 int i; 564 int i;
@@ -602,7 +573,7 @@ static int stm32_exti_h_suspend(void)
602 return 0; 573 return 0;
603} 574}
604 575
605static void stm32_exti_h_resume(void) 576static void __maybe_unused stm32_exti_h_resume(void)
606{ 577{
607 struct stm32_exti_chip_data *chip_data; 578 struct stm32_exti_chip_data *chip_data;
608 int i; 579 int i;
@@ -616,17 +587,22 @@ static void stm32_exti_h_resume(void)
616} 587}
617 588
618static struct syscore_ops stm32_exti_h_syscore_ops = { 589static struct syscore_ops stm32_exti_h_syscore_ops = {
590#ifdef CONFIG_PM_SLEEP
619 .suspend = stm32_exti_h_suspend, 591 .suspend = stm32_exti_h_suspend,
620 .resume = stm32_exti_h_resume, 592 .resume = stm32_exti_h_resume,
593#endif
621}; 594};
622 595
623static void stm32_exti_h_syscore_init(void) 596static void stm32_exti_h_syscore_init(struct stm32_exti_host_data *host_data)
624{ 597{
598 stm32_host_data = host_data;
625 register_syscore_ops(&stm32_exti_h_syscore_ops); 599 register_syscore_ops(&stm32_exti_h_syscore_ops);
626} 600}
627#else 601
628static inline void stm32_exti_h_syscore_init(void) {} 602static void stm32_exti_h_syscore_deinit(void)
629#endif 603{
604 unregister_syscore_ops(&stm32_exti_h_syscore_ops);
605}
630 606
631static struct irq_chip stm32_exti_h_chip = { 607static struct irq_chip stm32_exti_h_chip = {
632 .name = "stm32-exti-h", 608 .name = "stm32-exti-h",
@@ -683,8 +659,6 @@ stm32_exti_host_data *stm32_exti_host_init(const struct stm32_exti_drv_data *dd,
683 return NULL; 659 return NULL;
684 660
685 host_data->drv_data = dd; 661 host_data->drv_data = dd;
686 host_data->node = node;
687 host_data->hwlock_state = HWSPINLOCK_UNKNOWN;
688 host_data->chips_data = kcalloc(dd->bank_nr, 662 host_data->chips_data = kcalloc(dd->bank_nr,
689 sizeof(struct stm32_exti_chip_data), 663 sizeof(struct stm32_exti_chip_data),
690 GFP_KERNEL); 664 GFP_KERNEL);
@@ -711,7 +685,8 @@ free_host_data:
711 685
712static struct 686static struct
713stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data, 687stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data,
714 u32 bank_idx) 688 u32 bank_idx,
689 struct device_node *node)
715{ 690{
716 const struct stm32_exti_bank *stm32_bank; 691 const struct stm32_exti_bank *stm32_bank;
717 struct stm32_exti_chip_data *chip_data; 692 struct stm32_exti_chip_data *chip_data;
@@ -731,7 +706,7 @@ stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data,
731 writel_relaxed(0, base + stm32_bank->imr_ofst); 706 writel_relaxed(0, base + stm32_bank->imr_ofst);
732 writel_relaxed(0, base + stm32_bank->emr_ofst); 707 writel_relaxed(0, base + stm32_bank->emr_ofst);
733 708
734 pr_info("%pOF: bank%d\n", h_data->node, bank_idx); 709 pr_info("%pOF: bank%d\n", node, bank_idx);
735 710
736 return chip_data; 711 return chip_data;
737} 712}
@@ -771,7 +746,7 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
771 struct stm32_exti_chip_data *chip_data; 746 struct stm32_exti_chip_data *chip_data;
772 747
773 stm32_bank = drv_data->exti_banks[i]; 748 stm32_bank = drv_data->exti_banks[i];
774 chip_data = stm32_exti_chip_init(host_data, i); 749 chip_data = stm32_exti_chip_init(host_data, i, node);
775 750
776 gc = irq_get_domain_generic_chip(domain, i * IRQS_PER_BANK); 751 gc = irq_get_domain_generic_chip(domain, i * IRQS_PER_BANK);
777 752
@@ -815,50 +790,130 @@ static const struct irq_domain_ops stm32_exti_h_domain_ops = {
815 .xlate = irq_domain_xlate_twocell, 790 .xlate = irq_domain_xlate_twocell,
816}; 791};
817 792
818static int 793static void stm32_exti_remove_irq(void *data)
819__init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data, 794{
820 struct device_node *node, 795 struct irq_domain *domain = data;
821 struct device_node *parent) 796
797 irq_domain_remove(domain);
798}
799
800static int stm32_exti_remove(struct platform_device *pdev)
801{
802 stm32_exti_h_syscore_deinit();
803 return 0;
804}
805
806static int stm32_exti_probe(struct platform_device *pdev)
822{ 807{
808 int ret, i;
809 struct device *dev = &pdev->dev;
810 struct device_node *np = dev->of_node;
823 struct irq_domain *parent_domain, *domain; 811 struct irq_domain *parent_domain, *domain;
824 struct stm32_exti_host_data *host_data; 812 struct stm32_exti_host_data *host_data;
825 int ret, i; 813 const struct stm32_exti_drv_data *drv_data;
814 struct resource *res;
826 815
827 parent_domain = irq_find_host(parent); 816 host_data = devm_kzalloc(dev, sizeof(*host_data), GFP_KERNEL);
828 if (!parent_domain) { 817 if (!host_data)
829 pr_err("interrupt-parent not found\n"); 818 return -ENOMEM;
830 return -EINVAL; 819
820 /* check for optional hwspinlock which may be not available yet */
821 ret = of_hwspin_lock_get_id(np, 0);
822 if (ret == -EPROBE_DEFER)
823 /* hwspinlock framework not yet ready */
824 return ret;
825
826 if (ret >= 0) {
827 host_data->hwlock = devm_hwspin_lock_request_specific(dev, ret);
828 if (!host_data->hwlock) {
829 dev_err(dev, "Failed to request hwspinlock\n");
830 return -EINVAL;
831 }
832 } else if (ret != -ENOENT) {
833 /* note: ENOENT is a valid case (means 'no hwspinlock') */
834 dev_err(dev, "Failed to get hwspinlock\n");
835 return ret;
831 } 836 }
832 837
833 host_data = stm32_exti_host_init(drv_data, node); 838 /* initialize host_data */
834 if (!host_data) 839 drv_data = of_device_get_match_data(dev);
840 if (!drv_data) {
841 dev_err(dev, "no of match data\n");
842 return -ENODEV;
843 }
844 host_data->drv_data = drv_data;
845
846 host_data->chips_data = devm_kcalloc(dev, drv_data->bank_nr,
847 sizeof(*host_data->chips_data),
848 GFP_KERNEL);
849 if (!host_data->chips_data)
835 return -ENOMEM; 850 return -ENOMEM;
836 851
852 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
853 host_data->base = devm_ioremap_resource(dev, res);
854 if (IS_ERR(host_data->base)) {
855 dev_err(dev, "Unable to map registers\n");
856 return PTR_ERR(host_data->base);
857 }
858
837 for (i = 0; i < drv_data->bank_nr; i++) 859 for (i = 0; i < drv_data->bank_nr; i++)
838 stm32_exti_chip_init(host_data, i); 860 stm32_exti_chip_init(host_data, i, np);
861
862 parent_domain = irq_find_host(of_irq_find_parent(np));
863 if (!parent_domain) {
864 dev_err(dev, "GIC interrupt-parent not found\n");
865 return -EINVAL;
866 }
839 867
840 domain = irq_domain_add_hierarchy(parent_domain, 0, 868 domain = irq_domain_add_hierarchy(parent_domain, 0,
841 drv_data->bank_nr * IRQS_PER_BANK, 869 drv_data->bank_nr * IRQS_PER_BANK,
842 node, &stm32_exti_h_domain_ops, 870 np, &stm32_exti_h_domain_ops,
843 host_data); 871 host_data);
844 872
845 if (!domain) { 873 if (!domain) {
846 pr_err("%pOFn: Could not register exti domain.\n", node); 874 dev_err(dev, "Could not register exti domain\n");
847 ret = -ENOMEM; 875 return -ENOMEM;
848 goto out_unmap;
849 } 876 }
850 877
851 stm32_exti_h_syscore_init(); 878 ret = devm_add_action_or_reset(dev, stm32_exti_remove_irq, domain);
879 if (ret)
880 return ret;
881
882 stm32_exti_h_syscore_init(host_data);
852 883
853 return 0; 884 return 0;
885}
854 886
855out_unmap: 887/* platform driver only for MP1 */
856 iounmap(host_data->base); 888static const struct of_device_id stm32_exti_ids[] = {
857 kfree(host_data->chips_data); 889 { .compatible = "st,stm32mp1-exti", .data = &stm32mp1_drv_data},
858 kfree(host_data); 890 {},
859 return ret; 891};
892MODULE_DEVICE_TABLE(of, stm32_exti_ids);
893
894static struct platform_driver stm32_exti_driver = {
895 .probe = stm32_exti_probe,
896 .remove = stm32_exti_remove,
897 .driver = {
898 .name = "stm32_exti",
899 .of_match_table = stm32_exti_ids,
900 },
901};
902
903static int __init stm32_exti_arch_init(void)
904{
905 return platform_driver_register(&stm32_exti_driver);
860} 906}
861 907
908static void __exit stm32_exti_arch_exit(void)
909{
910 return platform_driver_unregister(&stm32_exti_driver);
911}
912
913arch_initcall(stm32_exti_arch_init);
914module_exit(stm32_exti_arch_exit);
915
916/* no platform driver for F4 and H7 */
862static int __init stm32f4_exti_of_init(struct device_node *np, 917static int __init stm32f4_exti_of_init(struct device_node *np,
863 struct device_node *parent) 918 struct device_node *parent)
864{ 919{
@@ -874,11 +929,3 @@ static int __init stm32h7_exti_of_init(struct device_node *np,
874} 929}
875 930
876IRQCHIP_DECLARE(stm32h7_exti, "st,stm32h7-exti", stm32h7_exti_of_init); 931IRQCHIP_DECLARE(stm32h7_exti, "st,stm32h7-exti", stm32h7_exti_of_init);
877
878static int __init stm32mp1_exti_of_init(struct device_node *np,
879 struct device_node *parent)
880{
881 return stm32_exti_hierarchy_init(&stm32mp1_drv_data, np, parent);
882}
883
884IRQCHIP_DECLARE(stm32mp1_exti, "st,stm32mp1-exti", stm32mp1_exti_of_init);
diff --git a/drivers/irqchip/irq-ti-sci-inta.c b/drivers/irqchip/irq-ti-sci-inta.c
new file mode 100644
index 000000000000..011b60a49e3f
--- /dev/null
+++ b/drivers/irqchip/irq-ti-sci-inta.c
@@ -0,0 +1,615 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Texas Instruments' K3 Interrupt Aggregator irqchip driver
4 *
5 * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/
6 * Lokesh Vutla <lokeshvutla@ti.com>
7 */
8
9#include <linux/err.h>
10#include <linux/io.h>
11#include <linux/irqchip.h>
12#include <linux/irqdomain.h>
13#include <linux/interrupt.h>
14#include <linux/msi.h>
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/of_address.h>
18#include <linux/of_irq.h>
19#include <linux/of_platform.h>
20#include <linux/irqchip/chained_irq.h>
21#include <linux/soc/ti/ti_sci_inta_msi.h>
22#include <linux/soc/ti/ti_sci_protocol.h>
23#include <asm-generic/msi.h>
24
25#define TI_SCI_DEV_ID_MASK 0xffff
26#define TI_SCI_DEV_ID_SHIFT 16
27#define TI_SCI_IRQ_ID_MASK 0xffff
28#define TI_SCI_IRQ_ID_SHIFT 0
29#define HWIRQ_TO_DEVID(hwirq) (((hwirq) >> (TI_SCI_DEV_ID_SHIFT)) & \
30 (TI_SCI_DEV_ID_MASK))
31#define HWIRQ_TO_IRQID(hwirq) ((hwirq) & (TI_SCI_IRQ_ID_MASK))
32#define TO_HWIRQ(dev, index) ((((dev) & TI_SCI_DEV_ID_MASK) << \
33 TI_SCI_DEV_ID_SHIFT) | \
34 ((index) & TI_SCI_IRQ_ID_MASK))
35
36#define MAX_EVENTS_PER_VINT 64
37#define VINT_ENABLE_SET_OFFSET 0x0
38#define VINT_ENABLE_CLR_OFFSET 0x8
39#define VINT_STATUS_OFFSET 0x18
40
41/**
42 * struct ti_sci_inta_event_desc - Description of an event coming to
43 * Interrupt Aggregator. This serves
44 * as a mapping table for global event,
45 * hwirq and vint bit.
46 * @global_event: Global event number corresponding to this event
47 * @hwirq: Hwirq of the incoming interrupt
48 * @vint_bit: Corresponding vint bit to which this event is attached.
49 */
50struct ti_sci_inta_event_desc {
51 u16 global_event;
52 u32 hwirq;
53 u8 vint_bit;
54};
55
56/**
57 * struct ti_sci_inta_vint_desc - Description of a virtual interrupt coming out
58 * of Interrupt Aggregator.
59 * @domain: Pointer to IRQ domain to which this vint belongs.
60 * @list: List entry for the vint list
61 * @event_map: Bitmap to manage the allocation of events to vint.
62 * @events: Array of event descriptors assigned to this vint.
63 * @parent_virq: Linux IRQ number that gets attached to parent
64 * @vint_id: TISCI vint ID
65 */
66struct ti_sci_inta_vint_desc {
67 struct irq_domain *domain;
68 struct list_head list;
69 DECLARE_BITMAP(event_map, MAX_EVENTS_PER_VINT);
70 struct ti_sci_inta_event_desc events[MAX_EVENTS_PER_VINT];
71 unsigned int parent_virq;
72 u16 vint_id;
73};
74
75/**
76 * struct ti_sci_inta_irq_domain - Structure representing a TISCI based
77 * Interrupt Aggregator IRQ domain.
78 * @sci: Pointer to TISCI handle
79 * @vint: TISCI resource pointer representing IA inerrupts.
80 * @global_event: TISCI resource pointer representing global events.
81 * @vint_list: List of the vints active in the system
82 * @vint_mutex: Mutex to protect vint_list
83 * @base: Base address of the memory mapped IO registers
84 * @pdev: Pointer to platform device.
85 */
86struct ti_sci_inta_irq_domain {
87 const struct ti_sci_handle *sci;
88 struct ti_sci_resource *vint;
89 struct ti_sci_resource *global_event;
90 struct list_head vint_list;
91 /* Mutex to protect vint list */
92 struct mutex vint_mutex;
93 void __iomem *base;
94 struct platform_device *pdev;
95};
96
97#define to_vint_desc(e, i) container_of(e, struct ti_sci_inta_vint_desc, \
98 events[i])
99
100/**
101 * ti_sci_inta_irq_handler() - Chained IRQ handler for the vint irqs
102 * @desc: Pointer to irq_desc corresponding to the irq
103 */
104static void ti_sci_inta_irq_handler(struct irq_desc *desc)
105{
106 struct ti_sci_inta_vint_desc *vint_desc;
107 struct ti_sci_inta_irq_domain *inta;
108 struct irq_domain *domain;
109 unsigned int virq, bit;
110 unsigned long val;
111
112 vint_desc = irq_desc_get_handler_data(desc);
113 domain = vint_desc->domain;
114 inta = domain->host_data;
115
116 chained_irq_enter(irq_desc_get_chip(desc), desc);
117
118 val = readq_relaxed(inta->base + vint_desc->vint_id * 0x1000 +
119 VINT_STATUS_OFFSET);
120
121 for_each_set_bit(bit, &val, MAX_EVENTS_PER_VINT) {
122 virq = irq_find_mapping(domain, vint_desc->events[bit].hwirq);
123 if (virq)
124 generic_handle_irq(virq);
125 }
126
127 chained_irq_exit(irq_desc_get_chip(desc), desc);
128}
129
130/**
131 * ti_sci_inta_alloc_parent_irq() - Allocate parent irq to Interrupt aggregator
132 * @domain: IRQ domain corresponding to Interrupt Aggregator
133 *
134 * Return 0 if all went well else corresponding error value.
135 */
136static struct ti_sci_inta_vint_desc *ti_sci_inta_alloc_parent_irq(struct irq_domain *domain)
137{
138 struct ti_sci_inta_irq_domain *inta = domain->host_data;
139 struct ti_sci_inta_vint_desc *vint_desc;
140 struct irq_fwspec parent_fwspec;
141 unsigned int parent_virq;
142 u16 vint_id;
143
144 vint_id = ti_sci_get_free_resource(inta->vint);
145 if (vint_id == TI_SCI_RESOURCE_NULL)
146 return ERR_PTR(-EINVAL);
147
148 vint_desc = kzalloc(sizeof(*vint_desc), GFP_KERNEL);
149 if (!vint_desc)
150 return ERR_PTR(-ENOMEM);
151
152 vint_desc->domain = domain;
153 vint_desc->vint_id = vint_id;
154 INIT_LIST_HEAD(&vint_desc->list);
155
156 parent_fwspec.fwnode = of_node_to_fwnode(of_irq_find_parent(dev_of_node(&inta->pdev->dev)));
157 parent_fwspec.param_count = 2;
158 parent_fwspec.param[0] = inta->pdev->id;
159 parent_fwspec.param[1] = vint_desc->vint_id;
160
161 parent_virq = irq_create_fwspec_mapping(&parent_fwspec);
162 if (parent_virq <= 0) {
163 kfree(vint_desc);
164 return ERR_PTR(parent_virq);
165 }
166 vint_desc->parent_virq = parent_virq;
167
168 list_add_tail(&vint_desc->list, &inta->vint_list);
169 irq_set_chained_handler_and_data(vint_desc->parent_virq,
170 ti_sci_inta_irq_handler, vint_desc);
171
172 return vint_desc;
173}
174
175/**
176 * ti_sci_inta_alloc_event() - Attach an event to a IA vint.
177 * @vint_desc: Pointer to vint_desc to which the event gets attached
178 * @free_bit: Bit inside vint to which event gets attached
179 * @hwirq: hwirq of the input event
180 *
181 * Return event_desc pointer if all went ok else appropriate error value.
182 */
183static struct ti_sci_inta_event_desc *ti_sci_inta_alloc_event(struct ti_sci_inta_vint_desc *vint_desc,
184 u16 free_bit,
185 u32 hwirq)
186{
187 struct ti_sci_inta_irq_domain *inta = vint_desc->domain->host_data;
188 struct ti_sci_inta_event_desc *event_desc;
189 u16 dev_id, dev_index;
190 int err;
191
192 dev_id = HWIRQ_TO_DEVID(hwirq);
193 dev_index = HWIRQ_TO_IRQID(hwirq);
194
195 event_desc = &vint_desc->events[free_bit];
196 event_desc->hwirq = hwirq;
197 event_desc->vint_bit = free_bit;
198 event_desc->global_event = ti_sci_get_free_resource(inta->global_event);
199 if (event_desc->global_event == TI_SCI_RESOURCE_NULL)
200 return ERR_PTR(-EINVAL);
201
202 err = inta->sci->ops.rm_irq_ops.set_event_map(inta->sci,
203 dev_id, dev_index,
204 inta->pdev->id,
205 vint_desc->vint_id,
206 event_desc->global_event,
207 free_bit);
208 if (err)
209 goto free_global_event;
210
211 return event_desc;
212free_global_event:
213 ti_sci_release_resource(inta->global_event, event_desc->global_event);
214 return ERR_PTR(err);
215}
216
217/**
218 * ti_sci_inta_alloc_irq() - Allocate an irq within INTA domain
219 * @domain: irq_domain pointer corresponding to INTA
220 * @hwirq: hwirq of the input event
221 *
222 * Note: Allocation happens in the following manner:
223 * - Find a free bit available in any of the vints available in the list.
224 * - If not found, allocate a vint from the vint pool
225 * - Attach the free bit to input hwirq.
226 * Return event_desc if all went ok else appropriate error value.
227 */
228static struct ti_sci_inta_event_desc *ti_sci_inta_alloc_irq(struct irq_domain *domain,
229 u32 hwirq)
230{
231 struct ti_sci_inta_irq_domain *inta = domain->host_data;
232 struct ti_sci_inta_vint_desc *vint_desc = NULL;
233 struct ti_sci_inta_event_desc *event_desc;
234 u16 free_bit;
235
236 mutex_lock(&inta->vint_mutex);
237 list_for_each_entry(vint_desc, &inta->vint_list, list) {
238 free_bit = find_first_zero_bit(vint_desc->event_map,
239 MAX_EVENTS_PER_VINT);
240 if (free_bit != MAX_EVENTS_PER_VINT) {
241 set_bit(free_bit, vint_desc->event_map);
242 goto alloc_event;
243 }
244 }
245
246 /* No free bits available. Allocate a new vint */
247 vint_desc = ti_sci_inta_alloc_parent_irq(domain);
248 if (IS_ERR(vint_desc)) {
249 mutex_unlock(&inta->vint_mutex);
250 return ERR_PTR(PTR_ERR(vint_desc));
251 }
252
253 free_bit = find_first_zero_bit(vint_desc->event_map,
254 MAX_EVENTS_PER_VINT);
255 set_bit(free_bit, vint_desc->event_map);
256
257alloc_event:
258 event_desc = ti_sci_inta_alloc_event(vint_desc, free_bit, hwirq);
259 if (IS_ERR(event_desc))
260 clear_bit(free_bit, vint_desc->event_map);
261
262 mutex_unlock(&inta->vint_mutex);
263 return event_desc;
264}
265
266/**
267 * ti_sci_inta_free_parent_irq() - Free a parent irq to INTA
268 * @inta: Pointer to inta domain.
269 * @vint_desc: Pointer to vint_desc that needs to be freed.
270 */
271static void ti_sci_inta_free_parent_irq(struct ti_sci_inta_irq_domain *inta,
272 struct ti_sci_inta_vint_desc *vint_desc)
273{
274 if (find_first_bit(vint_desc->event_map, MAX_EVENTS_PER_VINT) == MAX_EVENTS_PER_VINT) {
275 list_del(&vint_desc->list);
276 ti_sci_release_resource(inta->vint, vint_desc->vint_id);
277 irq_dispose_mapping(vint_desc->parent_virq);
278 kfree(vint_desc);
279 }
280}
281
282/**
283 * ti_sci_inta_free_irq() - Free an IRQ within INTA domain
284 * @event_desc: Pointer to event_desc that needs to be freed.
285 * @hwirq: Hwirq number within INTA domain that needs to be freed
286 */
287static void ti_sci_inta_free_irq(struct ti_sci_inta_event_desc *event_desc,
288 u32 hwirq)
289{
290 struct ti_sci_inta_vint_desc *vint_desc;
291 struct ti_sci_inta_irq_domain *inta;
292
293 vint_desc = to_vint_desc(event_desc, event_desc->vint_bit);
294 inta = vint_desc->domain->host_data;
295 /* free event irq */
296 mutex_lock(&inta->vint_mutex);
297 inta->sci->ops.rm_irq_ops.free_event_map(inta->sci,
298 HWIRQ_TO_DEVID(hwirq),
299 HWIRQ_TO_IRQID(hwirq),
300 inta->pdev->id,
301 vint_desc->vint_id,
302 event_desc->global_event,
303 event_desc->vint_bit);
304
305 clear_bit(event_desc->vint_bit, vint_desc->event_map);
306 ti_sci_release_resource(inta->global_event, event_desc->global_event);
307 event_desc->global_event = TI_SCI_RESOURCE_NULL;
308 event_desc->hwirq = 0;
309
310 ti_sci_inta_free_parent_irq(inta, vint_desc);
311 mutex_unlock(&inta->vint_mutex);
312}
313
314/**
315 * ti_sci_inta_request_resources() - Allocate resources for input irq
316 * @data: Pointer to corresponding irq_data
317 *
318 * Note: This is the core api where the actual allocation happens for input
319 * hwirq. This allocation involves creating a parent irq for vint.
320 * If this is done in irq_domain_ops.alloc() then a deadlock is reached
321 * for allocation. So this allocation is being done in request_resources()
322 *
323 * Return: 0 if all went well else corresponding error.
324 */
325static int ti_sci_inta_request_resources(struct irq_data *data)
326{
327 struct ti_sci_inta_event_desc *event_desc;
328
329 event_desc = ti_sci_inta_alloc_irq(data->domain, data->hwirq);
330 if (IS_ERR(event_desc))
331 return PTR_ERR(event_desc);
332
333 data->chip_data = event_desc;
334
335 return 0;
336}
337
338/**
339 * ti_sci_inta_release_resources - Release resources for input irq
340 * @data: Pointer to corresponding irq_data
341 *
342 * Note: Corresponding to request_resources(), all the unmapping and deletion
343 * of parent vint irqs happens in this api.
344 */
345static void ti_sci_inta_release_resources(struct irq_data *data)
346{
347 struct ti_sci_inta_event_desc *event_desc;
348
349 event_desc = irq_data_get_irq_chip_data(data);
350 ti_sci_inta_free_irq(event_desc, data->hwirq);
351}
352
353/**
354 * ti_sci_inta_manage_event() - Control the event based on the offset
355 * @data: Pointer to corresponding irq_data
356 * @offset: register offset using which event is controlled.
357 */
358static void ti_sci_inta_manage_event(struct irq_data *data, u32 offset)
359{
360 struct ti_sci_inta_event_desc *event_desc;
361 struct ti_sci_inta_vint_desc *vint_desc;
362 struct ti_sci_inta_irq_domain *inta;
363
364 event_desc = irq_data_get_irq_chip_data(data);
365 vint_desc = to_vint_desc(event_desc, event_desc->vint_bit);
366 inta = data->domain->host_data;
367
368 writeq_relaxed(BIT(event_desc->vint_bit),
369 inta->base + vint_desc->vint_id * 0x1000 + offset);
370}
371
372/**
373 * ti_sci_inta_mask_irq() - Mask an event
374 * @data: Pointer to corresponding irq_data
375 */
376static void ti_sci_inta_mask_irq(struct irq_data *data)
377{
378 ti_sci_inta_manage_event(data, VINT_ENABLE_CLR_OFFSET);
379}
380
381/**
382 * ti_sci_inta_unmask_irq() - Unmask an event
383 * @data: Pointer to corresponding irq_data
384 */
385static void ti_sci_inta_unmask_irq(struct irq_data *data)
386{
387 ti_sci_inta_manage_event(data, VINT_ENABLE_SET_OFFSET);
388}
389
390/**
391 * ti_sci_inta_ack_irq() - Ack an event
392 * @data: Pointer to corresponding irq_data
393 */
394static void ti_sci_inta_ack_irq(struct irq_data *data)
395{
396 /*
397 * Do not clear the event if hardware is capable of sending
398 * a down event.
399 */
400 if (irqd_get_trigger_type(data) != IRQF_TRIGGER_HIGH)
401 ti_sci_inta_manage_event(data, VINT_STATUS_OFFSET);
402}
403
404static int ti_sci_inta_set_affinity(struct irq_data *d,
405 const struct cpumask *mask_val, bool force)
406{
407 return -EINVAL;
408}
409
410/**
411 * ti_sci_inta_set_type() - Update the trigger type of the irq.
412 * @data: Pointer to corresponding irq_data
413 * @type: Trigger type as specified by user
414 *
415 * Note: This updates the handle_irq callback for level msi.
416 *
417 * Return 0 if all went well else appropriate error.
418 */
419static int ti_sci_inta_set_type(struct irq_data *data, unsigned int type)
420{
421 /*
422 * .alloc default sets handle_edge_irq. But if the user specifies
423 * that IRQ is level MSI, then update the handle to handle_level_irq
424 */
425 switch (type & IRQ_TYPE_SENSE_MASK) {
426 case IRQF_TRIGGER_HIGH:
427 irq_set_handler_locked(data, handle_level_irq);
428 return 0;
429 case IRQF_TRIGGER_RISING:
430 return 0;
431 default:
432 return -EINVAL;
433 }
434
435 return -EINVAL;
436}
437
438static struct irq_chip ti_sci_inta_irq_chip = {
439 .name = "INTA",
440 .irq_ack = ti_sci_inta_ack_irq,
441 .irq_mask = ti_sci_inta_mask_irq,
442 .irq_set_type = ti_sci_inta_set_type,
443 .irq_unmask = ti_sci_inta_unmask_irq,
444 .irq_set_affinity = ti_sci_inta_set_affinity,
445 .irq_request_resources = ti_sci_inta_request_resources,
446 .irq_release_resources = ti_sci_inta_release_resources,
447};
448
449/**
450 * ti_sci_inta_irq_domain_free() - Free an IRQ from the IRQ domain
451 * @domain: Domain to which the irqs belong
452 * @virq: base linux virtual IRQ to be freed.
453 * @nr_irqs: Number of continuous irqs to be freed
454 */
455static void ti_sci_inta_irq_domain_free(struct irq_domain *domain,
456 unsigned int virq, unsigned int nr_irqs)
457{
458 struct irq_data *data = irq_domain_get_irq_data(domain, virq);
459
460 irq_domain_reset_irq_data(data);
461}
462
463/**
464 * ti_sci_inta_irq_domain_alloc() - Allocate Interrupt aggregator IRQs
465 * @domain: Point to the interrupt aggregator IRQ domain
466 * @virq: Corresponding Linux virtual IRQ number
467 * @nr_irqs: Continuous irqs to be allocated
468 * @data: Pointer to firmware specifier
469 *
470 * No actual allocation happens here.
471 *
472 * Return 0 if all went well else appropriate error value.
473 */
474static int ti_sci_inta_irq_domain_alloc(struct irq_domain *domain,
475 unsigned int virq, unsigned int nr_irqs,
476 void *data)
477{
478 msi_alloc_info_t *arg = data;
479
480 irq_domain_set_info(domain, virq, arg->hwirq, &ti_sci_inta_irq_chip,
481 NULL, handle_edge_irq, NULL, NULL);
482
483 return 0;
484}
485
486static const struct irq_domain_ops ti_sci_inta_irq_domain_ops = {
487 .free = ti_sci_inta_irq_domain_free,
488 .alloc = ti_sci_inta_irq_domain_alloc,
489};
490
491static struct irq_chip ti_sci_inta_msi_irq_chip = {
492 .name = "MSI-INTA",
493 .flags = IRQCHIP_SUPPORTS_LEVEL_MSI,
494};
495
496static void ti_sci_inta_msi_set_desc(msi_alloc_info_t *arg,
497 struct msi_desc *desc)
498{
499 struct platform_device *pdev = to_platform_device(desc->dev);
500
501 arg->desc = desc;
502 arg->hwirq = TO_HWIRQ(pdev->id, desc->inta.dev_index);
503}
504
505static struct msi_domain_ops ti_sci_inta_msi_ops = {
506 .set_desc = ti_sci_inta_msi_set_desc,
507};
508
509static struct msi_domain_info ti_sci_inta_msi_domain_info = {
510 .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
511 MSI_FLAG_LEVEL_CAPABLE),
512 .ops = &ti_sci_inta_msi_ops,
513 .chip = &ti_sci_inta_msi_irq_chip,
514};
515
516static int ti_sci_inta_irq_domain_probe(struct platform_device *pdev)
517{
518 struct irq_domain *parent_domain, *domain, *msi_domain;
519 struct device_node *parent_node, *node;
520 struct ti_sci_inta_irq_domain *inta;
521 struct device *dev = &pdev->dev;
522 struct resource *res;
523 int ret;
524
525 node = dev_of_node(dev);
526 parent_node = of_irq_find_parent(node);
527 if (!parent_node) {
528 dev_err(dev, "Failed to get IRQ parent node\n");
529 return -ENODEV;
530 }
531
532 parent_domain = irq_find_host(parent_node);
533 if (!parent_domain)
534 return -EPROBE_DEFER;
535
536 inta = devm_kzalloc(dev, sizeof(*inta), GFP_KERNEL);
537 if (!inta)
538 return -ENOMEM;
539
540 inta->pdev = pdev;
541 inta->sci = devm_ti_sci_get_by_phandle(dev, "ti,sci");
542 if (IS_ERR(inta->sci)) {
543 ret = PTR_ERR(inta->sci);
544 if (ret != -EPROBE_DEFER)
545 dev_err(dev, "ti,sci read fail %d\n", ret);
546 inta->sci = NULL;
547 return ret;
548 }
549
550 ret = of_property_read_u32(dev->of_node, "ti,sci-dev-id", &pdev->id);
551 if (ret) {
552 dev_err(dev, "missing 'ti,sci-dev-id' property\n");
553 return -EINVAL;
554 }
555
556 inta->vint = devm_ti_sci_get_of_resource(inta->sci, dev, pdev->id,
557 "ti,sci-rm-range-vint");
558 if (IS_ERR(inta->vint)) {
559 dev_err(dev, "VINT resource allocation failed\n");
560 return PTR_ERR(inta->vint);
561 }
562
563 inta->global_event = devm_ti_sci_get_of_resource(inta->sci, dev, pdev->id,
564 "ti,sci-rm-range-global-event");
565 if (IS_ERR(inta->global_event)) {
566 dev_err(dev, "Global event resource allocation failed\n");
567 return PTR_ERR(inta->global_event);
568 }
569
570 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
571 inta->base = devm_ioremap_resource(dev, res);
572 if (IS_ERR(inta->base))
573 return -ENODEV;
574
575 domain = irq_domain_add_linear(dev_of_node(dev),
576 ti_sci_get_num_resources(inta->vint),
577 &ti_sci_inta_irq_domain_ops, inta);
578 if (!domain) {
579 dev_err(dev, "Failed to allocate IRQ domain\n");
580 return -ENOMEM;
581 }
582
583 msi_domain = ti_sci_inta_msi_create_irq_domain(of_node_to_fwnode(node),
584 &ti_sci_inta_msi_domain_info,
585 domain);
586 if (!msi_domain) {
587 irq_domain_remove(domain);
588 dev_err(dev, "Failed to allocate msi domain\n");
589 return -ENOMEM;
590 }
591
592 INIT_LIST_HEAD(&inta->vint_list);
593 mutex_init(&inta->vint_mutex);
594
595 return 0;
596}
597
598static const struct of_device_id ti_sci_inta_irq_domain_of_match[] = {
599 { .compatible = "ti,sci-inta", },
600 { /* sentinel */ },
601};
602MODULE_DEVICE_TABLE(of, ti_sci_inta_irq_domain_of_match);
603
604static struct platform_driver ti_sci_inta_irq_domain_driver = {
605 .probe = ti_sci_inta_irq_domain_probe,
606 .driver = {
607 .name = "ti-sci-inta",
608 .of_match_table = ti_sci_inta_irq_domain_of_match,
609 },
610};
611module_platform_driver(ti_sci_inta_irq_domain_driver);
612
613MODULE_AUTHOR("Lokesh Vutla <lokeshvutla@ticom>");
614MODULE_DESCRIPTION("K3 Interrupt Aggregator driver over TI SCI protocol");
615MODULE_LICENSE("GPL v2");
diff --git a/drivers/irqchip/irq-ti-sci-intr.c b/drivers/irqchip/irq-ti-sci-intr.c
new file mode 100644
index 000000000000..59d51a20bbd8
--- /dev/null
+++ b/drivers/irqchip/irq-ti-sci-intr.c
@@ -0,0 +1,275 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Texas Instruments' K3 Interrupt Router irqchip driver
4 *
5 * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/
6 * Lokesh Vutla <lokeshvutla@ti.com>
7 */
8
9#include <linux/err.h>
10#include <linux/module.h>
11#include <linux/moduleparam.h>
12#include <linux/io.h>
13#include <linux/irqchip.h>
14#include <linux/irqdomain.h>
15#include <linux/of_platform.h>
16#include <linux/of_address.h>
17#include <linux/of_irq.h>
18#include <linux/soc/ti/ti_sci_protocol.h>
19
20#define TI_SCI_DEV_ID_MASK 0xffff
21#define TI_SCI_DEV_ID_SHIFT 16
22#define TI_SCI_IRQ_ID_MASK 0xffff
23#define TI_SCI_IRQ_ID_SHIFT 0
24#define HWIRQ_TO_DEVID(hwirq) (((hwirq) >> (TI_SCI_DEV_ID_SHIFT)) & \
25 (TI_SCI_DEV_ID_MASK))
26#define HWIRQ_TO_IRQID(hwirq) ((hwirq) & (TI_SCI_IRQ_ID_MASK))
27#define TO_HWIRQ(dev, index) ((((dev) & TI_SCI_DEV_ID_MASK) << \
28 TI_SCI_DEV_ID_SHIFT) | \
29 ((index) & TI_SCI_IRQ_ID_MASK))
30
31/**
32 * struct ti_sci_intr_irq_domain - Structure representing a TISCI based
33 * Interrupt Router IRQ domain.
34 * @sci: Pointer to TISCI handle
35 * @dst_irq: TISCI resource pointer representing GIC irq controller.
36 * @dst_id: TISCI device ID of the GIC irq controller.
37 * @type: Specifies the trigger type supported by this Interrupt Router
38 */
39struct ti_sci_intr_irq_domain {
40 const struct ti_sci_handle *sci;
41 struct ti_sci_resource *dst_irq;
42 u32 dst_id;
43 u32 type;
44};
45
46static struct irq_chip ti_sci_intr_irq_chip = {
47 .name = "INTR",
48 .irq_eoi = irq_chip_eoi_parent,
49 .irq_mask = irq_chip_mask_parent,
50 .irq_unmask = irq_chip_unmask_parent,
51 .irq_set_type = irq_chip_set_type_parent,
52 .irq_retrigger = irq_chip_retrigger_hierarchy,
53 .irq_set_affinity = irq_chip_set_affinity_parent,
54};
55
56/**
57 * ti_sci_intr_irq_domain_translate() - Retrieve hwirq and type from
58 * IRQ firmware specific handler.
59 * @domain: Pointer to IRQ domain
60 * @fwspec: Pointer to IRQ specific firmware structure
61 * @hwirq: IRQ number identified by hardware
62 * @type: IRQ type
63 *
64 * Return 0 if all went ok else appropriate error.
65 */
66static int ti_sci_intr_irq_domain_translate(struct irq_domain *domain,
67 struct irq_fwspec *fwspec,
68 unsigned long *hwirq,
69 unsigned int *type)
70{
71 struct ti_sci_intr_irq_domain *intr = domain->host_data;
72
73 if (fwspec->param_count != 2)
74 return -EINVAL;
75
76 *hwirq = TO_HWIRQ(fwspec->param[0], fwspec->param[1]);
77 *type = intr->type;
78
79 return 0;
80}
81
82/**
83 * ti_sci_intr_irq_domain_free() - Free the specified IRQs from the domain.
84 * @domain: Domain to which the irqs belong
85 * @virq: Linux virtual IRQ to be freed.
86 * @nr_irqs: Number of continuous irqs to be freed
87 */
88static void ti_sci_intr_irq_domain_free(struct irq_domain *domain,
89 unsigned int virq, unsigned int nr_irqs)
90{
91 struct ti_sci_intr_irq_domain *intr = domain->host_data;
92 struct irq_data *data, *parent_data;
93 u16 dev_id, irq_index;
94
95 parent_data = irq_domain_get_irq_data(domain->parent, virq);
96 data = irq_domain_get_irq_data(domain, virq);
97 irq_index = HWIRQ_TO_IRQID(data->hwirq);
98 dev_id = HWIRQ_TO_DEVID(data->hwirq);
99
100 intr->sci->ops.rm_irq_ops.free_irq(intr->sci, dev_id, irq_index,
101 intr->dst_id, parent_data->hwirq);
102 ti_sci_release_resource(intr->dst_irq, parent_data->hwirq);
103 irq_domain_free_irqs_parent(domain, virq, 1);
104 irq_domain_reset_irq_data(data);
105}
106
107/**
108 * ti_sci_intr_alloc_gic_irq() - Allocate GIC specific IRQ
109 * @domain: Pointer to the interrupt router IRQ domain
110 * @virq: Corresponding Linux virtual IRQ number
111 * @hwirq: Corresponding hwirq for the IRQ within this IRQ domain
112 *
113 * Returns 0 if all went well else appropriate error pointer.
114 */
115static int ti_sci_intr_alloc_gic_irq(struct irq_domain *domain,
116 unsigned int virq, u32 hwirq)
117{
118 struct ti_sci_intr_irq_domain *intr = domain->host_data;
119 struct irq_fwspec fwspec;
120 u16 dev_id, irq_index;
121 u16 dst_irq;
122 int err;
123
124 dev_id = HWIRQ_TO_DEVID(hwirq);
125 irq_index = HWIRQ_TO_IRQID(hwirq);
126
127 dst_irq = ti_sci_get_free_resource(intr->dst_irq);
128 if (dst_irq == TI_SCI_RESOURCE_NULL)
129 return -EINVAL;
130
131 fwspec.fwnode = domain->parent->fwnode;
132 fwspec.param_count = 3;
133 fwspec.param[0] = 0; /* SPI */
134 fwspec.param[1] = dst_irq - 32; /* SPI offset */
135 fwspec.param[2] = intr->type;
136
137 err = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
138 if (err)
139 goto err_irqs;
140
141 err = intr->sci->ops.rm_irq_ops.set_irq(intr->sci, dev_id, irq_index,
142 intr->dst_id, dst_irq);
143 if (err)
144 goto err_msg;
145
146 return 0;
147
148err_msg:
149 irq_domain_free_irqs_parent(domain, virq, 1);
150err_irqs:
151 ti_sci_release_resource(intr->dst_irq, dst_irq);
152 return err;
153}
154
155/**
156 * ti_sci_intr_irq_domain_alloc() - Allocate Interrupt router IRQs
157 * @domain: Point to the interrupt router IRQ domain
158 * @virq: Corresponding Linux virtual IRQ number
159 * @nr_irqs: Continuous irqs to be allocated
160 * @data: Pointer to firmware specifier
161 *
162 * Return 0 if all went well else appropriate error value.
163 */
164static int ti_sci_intr_irq_domain_alloc(struct irq_domain *domain,
165 unsigned int virq, unsigned int nr_irqs,
166 void *data)
167{
168 struct irq_fwspec *fwspec = data;
169 unsigned long hwirq;
170 unsigned int flags;
171 int err;
172
173 err = ti_sci_intr_irq_domain_translate(domain, fwspec, &hwirq, &flags);
174 if (err)
175 return err;
176
177 err = ti_sci_intr_alloc_gic_irq(domain, virq, hwirq);
178 if (err)
179 return err;
180
181 irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
182 &ti_sci_intr_irq_chip, NULL);
183
184 return 0;
185}
186
187static const struct irq_domain_ops ti_sci_intr_irq_domain_ops = {
188 .free = ti_sci_intr_irq_domain_free,
189 .alloc = ti_sci_intr_irq_domain_alloc,
190 .translate = ti_sci_intr_irq_domain_translate,
191};
192
193static int ti_sci_intr_irq_domain_probe(struct platform_device *pdev)
194{
195 struct irq_domain *parent_domain, *domain;
196 struct ti_sci_intr_irq_domain *intr;
197 struct device_node *parent_node;
198 struct device *dev = &pdev->dev;
199 int ret;
200
201 parent_node = of_irq_find_parent(dev_of_node(dev));
202 if (!parent_node) {
203 dev_err(dev, "Failed to get IRQ parent node\n");
204 return -ENODEV;
205 }
206
207 parent_domain = irq_find_host(parent_node);
208 if (!parent_domain) {
209 dev_err(dev, "Failed to find IRQ parent domain\n");
210 return -ENODEV;
211 }
212
213 intr = devm_kzalloc(dev, sizeof(*intr), GFP_KERNEL);
214 if (!intr)
215 return -ENOMEM;
216
217 ret = of_property_read_u32(dev_of_node(dev), "ti,intr-trigger-type",
218 &intr->type);
219 if (ret) {
220 dev_err(dev, "missing ti,intr-trigger-type property\n");
221 return -EINVAL;
222 }
223
224 intr->sci = devm_ti_sci_get_by_phandle(dev, "ti,sci");
225 if (IS_ERR(intr->sci)) {
226 ret = PTR_ERR(intr->sci);
227 if (ret != -EPROBE_DEFER)
228 dev_err(dev, "ti,sci read fail %d\n", ret);
229 intr->sci = NULL;
230 return ret;
231 }
232
233 ret = of_property_read_u32(dev_of_node(dev), "ti,sci-dst-id",
234 &intr->dst_id);
235 if (ret) {
236 dev_err(dev, "missing 'ti,sci-dst-id' property\n");
237 return -EINVAL;
238 }
239
240 intr->dst_irq = devm_ti_sci_get_of_resource(intr->sci, dev,
241 intr->dst_id,
242 "ti,sci-rm-range-girq");
243 if (IS_ERR(intr->dst_irq)) {
244 dev_err(dev, "Destination irq resource allocation failed\n");
245 return PTR_ERR(intr->dst_irq);
246 }
247
248 domain = irq_domain_add_hierarchy(parent_domain, 0, 0, dev_of_node(dev),
249 &ti_sci_intr_irq_domain_ops, intr);
250 if (!domain) {
251 dev_err(dev, "Failed to allocate IRQ domain\n");
252 return -ENOMEM;
253 }
254
255 return 0;
256}
257
258static const struct of_device_id ti_sci_intr_irq_domain_of_match[] = {
259 { .compatible = "ti,sci-intr", },
260 { /* sentinel */ },
261};
262MODULE_DEVICE_TABLE(of, ti_sci_intr_irq_domain_of_match);
263
264static struct platform_driver ti_sci_intr_irq_domain_driver = {
265 .probe = ti_sci_intr_irq_domain_probe,
266 .driver = {
267 .name = "ti-sci-intr",
268 .of_match_table = ti_sci_intr_irq_domain_of_match,
269 },
270};
271module_platform_driver(ti_sci_intr_irq_domain_driver);
272
273MODULE_AUTHOR("Lokesh Vutla <lokeshvutla@ticom>");
274MODULE_DESCRIPTION("K3 Interrupt Router driver over TI SCI protocol");
275MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig
index 57960e92ebe0..dbd6c60b81db 100644
--- a/drivers/soc/ti/Kconfig
+++ b/drivers/soc/ti/Kconfig
@@ -74,4 +74,10 @@ config TI_SCI_PM_DOMAINS
74 called ti_sci_pm_domains. Note this is needed early in boot before 74 called ti_sci_pm_domains. Note this is needed early in boot before
75 rootfs may be available. 75 rootfs may be available.
76 76
77config TI_SCI_INTA_MSI_DOMAIN
78 bool
79 select GENERIC_MSI_IRQ_DOMAIN
80 help
81 Driver to enable Interrupt Aggregator specific MSI Domain.
82
77endif # SOC_TI 83endif # SOC_TI
diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile
index a22edc0b258a..b3868d392d4f 100644
--- a/drivers/soc/ti/Makefile
+++ b/drivers/soc/ti/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA) += knav_dma.o
8obj-$(CONFIG_AMX3_PM) += pm33xx.o 8obj-$(CONFIG_AMX3_PM) += pm33xx.o
9obj-$(CONFIG_WKUP_M3_IPC) += wkup_m3_ipc.o 9obj-$(CONFIG_WKUP_M3_IPC) += wkup_m3_ipc.o
10obj-$(CONFIG_TI_SCI_PM_DOMAINS) += ti_sci_pm_domains.o 10obj-$(CONFIG_TI_SCI_PM_DOMAINS) += ti_sci_pm_domains.o
11obj-$(CONFIG_TI_SCI_INTA_MSI_DOMAIN) += ti_sci_inta_msi.o
diff --git a/drivers/soc/ti/ti_sci_inta_msi.c b/drivers/soc/ti/ti_sci_inta_msi.c
new file mode 100644
index 000000000000..0eb9462f609e
--- /dev/null
+++ b/drivers/soc/ti/ti_sci_inta_msi.c
@@ -0,0 +1,146 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Texas Instruments' K3 Interrupt Aggregator MSI bus
4 *
5 * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/
6 * Lokesh Vutla <lokeshvutla@ti.com>
7 */
8
9#include <linux/irq.h>
10#include <linux/irqdomain.h>
11#include <linux/msi.h>
12#include <linux/of_address.h>
13#include <linux/of_device.h>
14#include <linux/of_irq.h>
15#include <linux/soc/ti/ti_sci_inta_msi.h>
16#include <linux/soc/ti/ti_sci_protocol.h>
17
18static void ti_sci_inta_msi_write_msg(struct irq_data *data,
19 struct msi_msg *msg)
20{
21 /* Nothing to do */
22}
23
24static void ti_sci_inta_msi_compose_msi_msg(struct irq_data *data,
25 struct msi_msg *msg)
26{
27 /* Nothing to do */
28}
29
30static void ti_sci_inta_msi_update_chip_ops(struct msi_domain_info *info)
31{
32 struct irq_chip *chip = info->chip;
33
34 if (WARN_ON(!chip))
35 return;
36
37 chip->irq_request_resources = irq_chip_request_resources_parent;
38 chip->irq_release_resources = irq_chip_release_resources_parent;
39 chip->irq_compose_msi_msg = ti_sci_inta_msi_compose_msi_msg;
40 chip->irq_write_msi_msg = ti_sci_inta_msi_write_msg;
41 chip->irq_set_type = irq_chip_set_type_parent;
42 chip->irq_unmask = irq_chip_unmask_parent;
43 chip->irq_mask = irq_chip_mask_parent;
44 chip->irq_ack = irq_chip_ack_parent;
45}
46
47struct irq_domain *ti_sci_inta_msi_create_irq_domain(struct fwnode_handle *fwnode,
48 struct msi_domain_info *info,
49 struct irq_domain *parent)
50{
51 struct irq_domain *domain;
52
53 ti_sci_inta_msi_update_chip_ops(info);
54
55 domain = msi_create_irq_domain(fwnode, info, parent);
56 if (domain)
57 irq_domain_update_bus_token(domain, DOMAIN_BUS_TI_SCI_INTA_MSI);
58
59 return domain;
60}
61EXPORT_SYMBOL_GPL(ti_sci_inta_msi_create_irq_domain);
62
63static void ti_sci_inta_msi_free_descs(struct device *dev)
64{
65 struct msi_desc *desc, *tmp;
66
67 list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
68 list_del(&desc->list);
69 free_msi_entry(desc);
70 }
71}
72
73static int ti_sci_inta_msi_alloc_descs(struct device *dev,
74 struct ti_sci_resource *res)
75{
76 struct msi_desc *msi_desc;
77 int set, i, count = 0;
78
79 for (set = 0; set < res->sets; set++) {
80 for (i = 0; i < res->desc[set].num; i++) {
81 msi_desc = alloc_msi_entry(dev, 1, NULL);
82 if (!msi_desc) {
83 ti_sci_inta_msi_free_descs(dev);
84 return -ENOMEM;
85 }
86
87 msi_desc->inta.dev_index = res->desc[set].start + i;
88 INIT_LIST_HEAD(&msi_desc->list);
89 list_add_tail(&msi_desc->list, dev_to_msi_list(dev));
90 count++;
91 }
92 }
93
94 return count;
95}
96
97int ti_sci_inta_msi_domain_alloc_irqs(struct device *dev,
98 struct ti_sci_resource *res)
99{
100 struct platform_device *pdev = to_platform_device(dev);
101 struct irq_domain *msi_domain;
102 int ret, nvec;
103
104 msi_domain = dev_get_msi_domain(dev);
105 if (!msi_domain)
106 return -EINVAL;
107
108 if (pdev->id < 0)
109 return -ENODEV;
110
111 nvec = ti_sci_inta_msi_alloc_descs(dev, res);
112 if (nvec <= 0)
113 return nvec;
114
115 ret = msi_domain_alloc_irqs(msi_domain, dev, nvec);
116 if (ret) {
117 dev_err(dev, "Failed to allocate IRQs %d\n", ret);
118 goto cleanup;
119 }
120
121 return 0;
122
123cleanup:
124 ti_sci_inta_msi_free_descs(&pdev->dev);
125 return ret;
126}
127EXPORT_SYMBOL_GPL(ti_sci_inta_msi_domain_alloc_irqs);
128
129void ti_sci_inta_msi_domain_free_irqs(struct device *dev)
130{
131 msi_domain_free_irqs(dev->msi_domain, dev);
132 ti_sci_inta_msi_free_descs(dev);
133}
134EXPORT_SYMBOL_GPL(ti_sci_inta_msi_domain_free_irqs);
135
136unsigned int ti_sci_inta_msi_get_virq(struct device *dev, u32 dev_index)
137{
138 struct msi_desc *desc;
139
140 for_each_msi_entry(desc, dev)
141 if (desc->inta.dev_index == dev_index)
142 return desc->irq;
143
144 return -ENODEV;
145}
146EXPORT_SYMBOL_GPL(ti_sci_inta_msi_get_virq);
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
index e760dc5d1fa8..476e0c54de2d 100644
--- a/include/linux/dma-iommu.h
+++ b/include/linux/dma-iommu.h
@@ -71,12 +71,25 @@ void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
71 size_t size, enum dma_data_direction dir, unsigned long attrs); 71 size_t size, enum dma_data_direction dir, unsigned long attrs);
72 72
73/* The DMA API isn't _quite_ the whole story, though... */ 73/* The DMA API isn't _quite_ the whole story, though... */
74void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg); 74/*
75 * iommu_dma_prepare_msi() - Map the MSI page in the IOMMU device
76 *
77 * The MSI page will be stored in @desc.
78 *
79 * Return: 0 on success otherwise an error describing the failure.
80 */
81int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr);
82
83/* Update the MSI message if required. */
84void iommu_dma_compose_msi_msg(struct msi_desc *desc,
85 struct msi_msg *msg);
86
75void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list); 87void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list);
76 88
77#else 89#else
78 90
79struct iommu_domain; 91struct iommu_domain;
92struct msi_desc;
80struct msi_msg; 93struct msi_msg;
81struct device; 94struct device;
82 95
@@ -99,7 +112,14 @@ static inline void iommu_put_dma_cookie(struct iommu_domain *domain)
99{ 112{
100} 113}
101 114
102static inline void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg) 115static inline int iommu_dma_prepare_msi(struct msi_desc *desc,
116 phys_addr_t msi_addr)
117{
118 return 0;
119}
120
121static inline void iommu_dma_compose_msi_msg(struct msi_desc *desc,
122 struct msi_msg *msg)
103{ 123{
104} 124}
105 125
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 7ae8de5ad0f2..fb301cf29148 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -625,6 +625,8 @@ extern int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on);
625extern int irq_chip_set_vcpu_affinity_parent(struct irq_data *data, 625extern int irq_chip_set_vcpu_affinity_parent(struct irq_data *data,
626 void *vcpu_info); 626 void *vcpu_info);
627extern int irq_chip_set_type_parent(struct irq_data *data, unsigned int type); 627extern int irq_chip_set_type_parent(struct irq_data *data, unsigned int type);
628extern int irq_chip_request_resources_parent(struct irq_data *data);
629extern void irq_chip_release_resources_parent(struct irq_data *data);
628#endif 630#endif
629 631
630/* Handling of unhandled and spurious interrupts: */ 632/* Handling of unhandled and spurious interrupts: */
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index c848a7cc502e..c7e3e39224c6 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -165,7 +165,7 @@
165#define GICR_PROPBASER_nCnB GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, nCnB) 165#define GICR_PROPBASER_nCnB GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, nCnB)
166#define GICR_PROPBASER_nC GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, nC) 166#define GICR_PROPBASER_nC GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, nC)
167#define GICR_PROPBASER_RaWt GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RaWt) 167#define GICR_PROPBASER_RaWt GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RaWt)
168#define GICR_PROPBASER_RaWb GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RaWt) 168#define GICR_PROPBASER_RaWb GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RaWb)
169#define GICR_PROPBASER_WaWt GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, WaWt) 169#define GICR_PROPBASER_WaWt GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, WaWt)
170#define GICR_PROPBASER_WaWb GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, WaWb) 170#define GICR_PROPBASER_WaWb GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, WaWb)
171#define GICR_PROPBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RaWaWt) 171#define GICR_PROPBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RaWaWt)
@@ -192,7 +192,7 @@
192#define GICR_PENDBASER_nCnB GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, nCnB) 192#define GICR_PENDBASER_nCnB GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, nCnB)
193#define GICR_PENDBASER_nC GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, nC) 193#define GICR_PENDBASER_nC GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, nC)
194#define GICR_PENDBASER_RaWt GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RaWt) 194#define GICR_PENDBASER_RaWt GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RaWt)
195#define GICR_PENDBASER_RaWb GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RaWt) 195#define GICR_PENDBASER_RaWb GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RaWb)
196#define GICR_PENDBASER_WaWt GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, WaWt) 196#define GICR_PENDBASER_WaWt GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, WaWt)
197#define GICR_PENDBASER_WaWb GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, WaWb) 197#define GICR_PENDBASER_WaWb GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, WaWb)
198#define GICR_PENDBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RaWaWt) 198#define GICR_PENDBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RaWaWt)
@@ -251,7 +251,7 @@
251#define GICR_VPROPBASER_nCnB GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, nCnB) 251#define GICR_VPROPBASER_nCnB GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, nCnB)
252#define GICR_VPROPBASER_nC GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, nC) 252#define GICR_VPROPBASER_nC GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, nC)
253#define GICR_VPROPBASER_RaWt GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWt) 253#define GICR_VPROPBASER_RaWt GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWt)
254#define GICR_VPROPBASER_RaWb GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWt) 254#define GICR_VPROPBASER_RaWb GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWb)
255#define GICR_VPROPBASER_WaWt GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, WaWt) 255#define GICR_VPROPBASER_WaWt GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, WaWt)
256#define GICR_VPROPBASER_WaWb GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, WaWb) 256#define GICR_VPROPBASER_WaWb GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, WaWb)
257#define GICR_VPROPBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWaWt) 257#define GICR_VPROPBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWaWt)
@@ -277,7 +277,7 @@
277#define GICR_VPENDBASER_nCnB GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, nCnB) 277#define GICR_VPENDBASER_nCnB GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, nCnB)
278#define GICR_VPENDBASER_nC GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, nC) 278#define GICR_VPENDBASER_nC GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, nC)
279#define GICR_VPENDBASER_RaWt GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, RaWt) 279#define GICR_VPENDBASER_RaWt GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, RaWt)
280#define GICR_VPENDBASER_RaWb GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, RaWt) 280#define GICR_VPENDBASER_RaWb GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, RaWb)
281#define GICR_VPENDBASER_WaWt GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, WaWt) 281#define GICR_VPENDBASER_WaWt GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, WaWt)
282#define GICR_VPENDBASER_WaWb GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, WaWb) 282#define GICR_VPENDBASER_WaWb GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, WaWb)
283#define GICR_VPENDBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, RaWaWt) 283#define GICR_VPENDBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, RaWaWt)
@@ -351,7 +351,7 @@
351#define GITS_CBASER_nCnB GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nCnB) 351#define GITS_CBASER_nCnB GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nCnB)
352#define GITS_CBASER_nC GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nC) 352#define GITS_CBASER_nC GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nC)
353#define GITS_CBASER_RaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWt) 353#define GITS_CBASER_RaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWt)
354#define GITS_CBASER_RaWb GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWt) 354#define GITS_CBASER_RaWb GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWb)
355#define GITS_CBASER_WaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWt) 355#define GITS_CBASER_WaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWt)
356#define GITS_CBASER_WaWb GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWb) 356#define GITS_CBASER_WaWb GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWb)
357#define GITS_CBASER_RaWaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWaWt) 357#define GITS_CBASER_RaWaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWaWt)
@@ -377,7 +377,7 @@
377#define GITS_BASER_nCnB GIC_BASER_CACHEABILITY(GITS_BASER, INNER, nCnB) 377#define GITS_BASER_nCnB GIC_BASER_CACHEABILITY(GITS_BASER, INNER, nCnB)
378#define GITS_BASER_nC GIC_BASER_CACHEABILITY(GITS_BASER, INNER, nC) 378#define GITS_BASER_nC GIC_BASER_CACHEABILITY(GITS_BASER, INNER, nC)
379#define GITS_BASER_RaWt GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWt) 379#define GITS_BASER_RaWt GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWt)
380#define GITS_BASER_RaWb GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWt) 380#define GITS_BASER_RaWb GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWb)
381#define GITS_BASER_WaWt GIC_BASER_CACHEABILITY(GITS_BASER, INNER, WaWt) 381#define GITS_BASER_WaWt GIC_BASER_CACHEABILITY(GITS_BASER, INNER, WaWt)
382#define GITS_BASER_WaWb GIC_BASER_CACHEABILITY(GITS_BASER, INNER, WaWb) 382#define GITS_BASER_WaWb GIC_BASER_CACHEABILITY(GITS_BASER, INNER, WaWb)
383#define GITS_BASER_RaWaWt GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWaWt) 383#define GITS_BASER_RaWaWt GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWaWt)
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 61706b430907..07ec8b390161 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -82,6 +82,7 @@ enum irq_domain_bus_token {
82 DOMAIN_BUS_NEXUS, 82 DOMAIN_BUS_NEXUS,
83 DOMAIN_BUS_IPI, 83 DOMAIN_BUS_IPI,
84 DOMAIN_BUS_FSL_MC_MSI, 84 DOMAIN_BUS_FSL_MC_MSI,
85 DOMAIN_BUS_TI_SCI_INTA_MSI,
85}; 86};
86 87
87/** 88/**
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 052f04fcf953..d48e919d55ae 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -48,6 +48,14 @@ struct fsl_mc_msi_desc {
48}; 48};
49 49
50/** 50/**
51 * ti_sci_inta_msi_desc - TISCI based INTA specific msi descriptor data
52 * @dev_index: TISCI device index
53 */
54struct ti_sci_inta_msi_desc {
55 u16 dev_index;
56};
57
58/**
51 * struct msi_desc - Descriptor structure for MSI based interrupts 59 * struct msi_desc - Descriptor structure for MSI based interrupts
52 * @list: List head for management 60 * @list: List head for management
53 * @irq: The base interrupt number 61 * @irq: The base interrupt number
@@ -68,6 +76,7 @@ struct fsl_mc_msi_desc {
68 * @mask_base: [PCI MSI-X] Mask register base address 76 * @mask_base: [PCI MSI-X] Mask register base address
69 * @platform: [platform] Platform device specific msi descriptor data 77 * @platform: [platform] Platform device specific msi descriptor data
70 * @fsl_mc: [fsl-mc] FSL MC device specific msi descriptor data 78 * @fsl_mc: [fsl-mc] FSL MC device specific msi descriptor data
79 * @inta: [INTA] TISCI based INTA specific msi descriptor data
71 */ 80 */
72struct msi_desc { 81struct msi_desc {
73 /* Shared device/bus type independent data */ 82 /* Shared device/bus type independent data */
@@ -77,6 +86,9 @@ struct msi_desc {
77 struct device *dev; 86 struct device *dev;
78 struct msi_msg msg; 87 struct msi_msg msg;
79 struct irq_affinity_desc *affinity; 88 struct irq_affinity_desc *affinity;
89#ifdef CONFIG_IRQ_MSI_IOMMU
90 const void *iommu_cookie;
91#endif
80 92
81 union { 93 union {
82 /* PCI MSI/X specific data */ 94 /* PCI MSI/X specific data */
@@ -106,6 +118,7 @@ struct msi_desc {
106 */ 118 */
107 struct platform_msi_desc platform; 119 struct platform_msi_desc platform;
108 struct fsl_mc_msi_desc fsl_mc; 120 struct fsl_mc_msi_desc fsl_mc;
121 struct ti_sci_inta_msi_desc inta;
109 }; 122 };
110}; 123};
111 124
@@ -119,6 +132,29 @@ struct msi_desc {
119#define for_each_msi_entry_safe(desc, tmp, dev) \ 132#define for_each_msi_entry_safe(desc, tmp, dev) \
120 list_for_each_entry_safe((desc), (tmp), dev_to_msi_list((dev)), list) 133 list_for_each_entry_safe((desc), (tmp), dev_to_msi_list((dev)), list)
121 134
135#ifdef CONFIG_IRQ_MSI_IOMMU
136static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
137{
138 return desc->iommu_cookie;
139}
140
141static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc,
142 const void *iommu_cookie)
143{
144 desc->iommu_cookie = iommu_cookie;
145}
146#else
147static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
148{
149 return NULL;
150}
151
152static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc,
153 const void *iommu_cookie)
154{
155}
156#endif
157
122#ifdef CONFIG_PCI_MSI 158#ifdef CONFIG_PCI_MSI
123#define first_pci_msi_entry(pdev) first_msi_entry(&(pdev)->dev) 159#define first_pci_msi_entry(pdev) first_msi_entry(&(pdev)->dev)
124#define for_each_pci_msi_entry(desc, pdev) \ 160#define for_each_pci_msi_entry(desc, pdev) \
diff --git a/include/linux/soc/ti/ti_sci_inta_msi.h b/include/linux/soc/ti/ti_sci_inta_msi.h
new file mode 100644
index 000000000000..11fb5048f5f6
--- /dev/null
+++ b/include/linux/soc/ti/ti_sci_inta_msi.h
@@ -0,0 +1,23 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Texas Instruments' K3 TI SCI INTA MSI helper
4 *
5 * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/
6 * Lokesh Vutla <lokeshvutla@ti.com>
7 */
8
9#ifndef __INCLUDE_LINUX_TI_SCI_INTA_MSI_H
10#define __INCLUDE_LINUX_TI_SCI_INTA_MSI_H
11
12#include <linux/msi.h>
13#include <linux/soc/ti/ti_sci_protocol.h>
14
15struct irq_domain
16*ti_sci_inta_msi_create_irq_domain(struct fwnode_handle *fwnode,
17 struct msi_domain_info *info,
18 struct irq_domain *parent);
19int ti_sci_inta_msi_domain_alloc_irqs(struct device *dev,
20 struct ti_sci_resource *res);
21unsigned int ti_sci_inta_msi_get_virq(struct device *dev, u32 index);
22void ti_sci_inta_msi_domain_free_irqs(struct device *dev);
23#endif /* __INCLUDE_LINUX_IRQCHIP_TI_SCI_INTA_H */
diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h
index 18435e5c6364..568722a041bf 100644
--- a/include/linux/soc/ti/ti_sci_protocol.h
+++ b/include/linux/soc/ti/ti_sci_protocol.h
@@ -193,14 +193,67 @@ struct ti_sci_clk_ops {
193}; 193};
194 194
195/** 195/**
196 * struct ti_sci_rm_core_ops - Resource management core operations
197 * @get_range: Get a range of resources belonging to ti sci host.
198 * @get_rage_from_shost: Get a range of resources belonging to
199 * specified host id.
200 * - s_host: Host processing entity to which the
201 * resources are allocated
202 *
203 * NOTE: for these functions, all the parameters are consolidated and defined
204 * as below:
205 * - handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
206 * - dev_id: TISCI device ID.
207 * - subtype: Resource assignment subtype that is being requested
208 * from the given device.
209 * - range_start: Start index of the resource range
210 * - range_end: Number of resources in the range
211 */
212struct ti_sci_rm_core_ops {
213 int (*get_range)(const struct ti_sci_handle *handle, u32 dev_id,
214 u8 subtype, u16 *range_start, u16 *range_num);
215 int (*get_range_from_shost)(const struct ti_sci_handle *handle,
216 u32 dev_id, u8 subtype, u8 s_host,
217 u16 *range_start, u16 *range_num);
218};
219
220/**
221 * struct ti_sci_rm_irq_ops: IRQ management operations
222 * @set_irq: Set an IRQ route between the requested source
223 * and destination
224 * @set_event_map: Set an Event based peripheral irq to Interrupt
225 * Aggregator.
226 * @free_irq: Free an an IRQ route between the requested source
227 * destination.
228 * @free_event_map: Free an event based peripheral irq to Interrupt
229 * Aggregator.
230 */
231struct ti_sci_rm_irq_ops {
232 int (*set_irq)(const struct ti_sci_handle *handle, u16 src_id,
233 u16 src_index, u16 dst_id, u16 dst_host_irq);
234 int (*set_event_map)(const struct ti_sci_handle *handle, u16 src_id,
235 u16 src_index, u16 ia_id, u16 vint,
236 u16 global_event, u8 vint_status_bit);
237 int (*free_irq)(const struct ti_sci_handle *handle, u16 src_id,
238 u16 src_index, u16 dst_id, u16 dst_host_irq);
239 int (*free_event_map)(const struct ti_sci_handle *handle, u16 src_id,
240 u16 src_index, u16 ia_id, u16 vint,
241 u16 global_event, u8 vint_status_bit);
242};
243
244/**
196 * struct ti_sci_ops - Function support for TI SCI 245 * struct ti_sci_ops - Function support for TI SCI
197 * @dev_ops: Device specific operations 246 * @dev_ops: Device specific operations
198 * @clk_ops: Clock specific operations 247 * @clk_ops: Clock specific operations
248 * @rm_core_ops: Resource management core operations.
249 * @rm_irq_ops: IRQ management specific operations
199 */ 250 */
200struct ti_sci_ops { 251struct ti_sci_ops {
201 struct ti_sci_core_ops core_ops; 252 struct ti_sci_core_ops core_ops;
202 struct ti_sci_dev_ops dev_ops; 253 struct ti_sci_dev_ops dev_ops;
203 struct ti_sci_clk_ops clk_ops; 254 struct ti_sci_clk_ops clk_ops;
255 struct ti_sci_rm_core_ops rm_core_ops;
256 struct ti_sci_rm_irq_ops rm_irq_ops;
204}; 257};
205 258
206/** 259/**
@@ -213,10 +266,47 @@ struct ti_sci_handle {
213 struct ti_sci_ops ops; 266 struct ti_sci_ops ops;
214}; 267};
215 268
269#define TI_SCI_RESOURCE_NULL 0xffff
270
271/**
272 * struct ti_sci_resource_desc - Description of TI SCI resource instance range.
273 * @start: Start index of the resource.
274 * @num: Number of resources.
275 * @res_map: Bitmap to manage the allocation of these resources.
276 */
277struct ti_sci_resource_desc {
278 u16 start;
279 u16 num;
280 unsigned long *res_map;
281};
282
283/**
284 * struct ti_sci_resource - Structure representing a resource assigned
285 * to a device.
286 * @sets: Number of sets available from this resource type
287 * @lock: Lock to guard the res map in each set.
288 * @desc: Array of resource descriptors.
289 */
290struct ti_sci_resource {
291 u16 sets;
292 raw_spinlock_t lock;
293 struct ti_sci_resource_desc *desc;
294};
295
216#if IS_ENABLED(CONFIG_TI_SCI_PROTOCOL) 296#if IS_ENABLED(CONFIG_TI_SCI_PROTOCOL)
217const struct ti_sci_handle *ti_sci_get_handle(struct device *dev); 297const struct ti_sci_handle *ti_sci_get_handle(struct device *dev);
218int ti_sci_put_handle(const struct ti_sci_handle *handle); 298int ti_sci_put_handle(const struct ti_sci_handle *handle);
219const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev); 299const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev);
300const struct ti_sci_handle *ti_sci_get_by_phandle(struct device_node *np,
301 const char *property);
302const struct ti_sci_handle *devm_ti_sci_get_by_phandle(struct device *dev,
303 const char *property);
304u16 ti_sci_get_free_resource(struct ti_sci_resource *res);
305void ti_sci_release_resource(struct ti_sci_resource *res, u16 id);
306u32 ti_sci_get_num_resources(struct ti_sci_resource *res);
307struct ti_sci_resource *
308devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle,
309 struct device *dev, u32 dev_id, char *of_prop);
220 310
221#else /* CONFIG_TI_SCI_PROTOCOL */ 311#else /* CONFIG_TI_SCI_PROTOCOL */
222 312
@@ -236,6 +326,40 @@ const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev)
236 return ERR_PTR(-EINVAL); 326 return ERR_PTR(-EINVAL);
237} 327}
238 328
329static inline
330const struct ti_sci_handle *ti_sci_get_by_phandle(struct device_node *np,
331 const char *property)
332{
333 return ERR_PTR(-EINVAL);
334}
335
336static inline
337const struct ti_sci_handle *devm_ti_sci_get_by_phandle(struct device *dev,
338 const char *property)
339{
340 return ERR_PTR(-EINVAL);
341}
342
343static inline u16 ti_sci_get_free_resource(struct ti_sci_resource *res)
344{
345 return TI_SCI_RESOURCE_NULL;
346}
347
348static inline void ti_sci_release_resource(struct ti_sci_resource *res, u16 id)
349{
350}
351
352static inline u32 ti_sci_get_num_resources(struct ti_sci_resource *res)
353{
354 return 0;
355}
356
357static inline struct ti_sci_resource *
358devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle,
359 struct device *dev, u32 dev_id, char *of_prop)
360{
361 return ERR_PTR(-EINVAL);
362}
239#endif /* CONFIG_TI_SCI_PROTOCOL */ 363#endif /* CONFIG_TI_SCI_PROTOCOL */
240 364
241#endif /* __TISCI_PROTOCOL_H */ 365#endif /* __TISCI_PROTOCOL_H */
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
index 5f3e2baefca9..8fee06625c37 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -91,6 +91,9 @@ config GENERIC_MSI_IRQ_DOMAIN
91 select IRQ_DOMAIN_HIERARCHY 91 select IRQ_DOMAIN_HIERARCHY
92 select GENERIC_MSI_IRQ 92 select GENERIC_MSI_IRQ
93 93
94config IRQ_MSI_IOMMU
95 bool
96
94config HANDLE_DOMAIN_IRQ 97config HANDLE_DOMAIN_IRQ
95 bool 98 bool
96 99
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 51128bea3846..29d6c7d070b4 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -1459,6 +1459,33 @@ int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on)
1459 return -ENOSYS; 1459 return -ENOSYS;
1460} 1460}
1461EXPORT_SYMBOL_GPL(irq_chip_set_wake_parent); 1461EXPORT_SYMBOL_GPL(irq_chip_set_wake_parent);
1462
1463/**
1464 * irq_chip_request_resources_parent - Request resources on the parent interrupt
1465 * @data: Pointer to interrupt specific data
1466 */
1467int irq_chip_request_resources_parent(struct irq_data *data)
1468{
1469 data = data->parent_data;
1470
1471 if (data->chip->irq_request_resources)
1472 return data->chip->irq_request_resources(data);
1473
1474 return -ENOSYS;
1475}
1476EXPORT_SYMBOL_GPL(irq_chip_request_resources_parent);
1477
1478/**
1479 * irq_chip_release_resources_parent - Release resources on the parent interrupt
1480 * @data: Pointer to interrupt specific data
1481 */
1482void irq_chip_release_resources_parent(struct irq_data *data)
1483{
1484 data = data->parent_data;
1485 if (data->chip->irq_release_resources)
1486 data->chip->irq_release_resources(data);
1487}
1488EXPORT_SYMBOL_GPL(irq_chip_release_resources_parent);
1462#endif 1489#endif
1463 1490
1464/** 1491/**
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 9ed29e4a7dbf..a453e229f99c 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -1297,7 +1297,7 @@ int irq_domain_alloc_irqs_hierarchy(struct irq_domain *domain,
1297/** 1297/**
1298 * __irq_domain_alloc_irqs - Allocate IRQs from domain 1298 * __irq_domain_alloc_irqs - Allocate IRQs from domain
1299 * @domain: domain to allocate from 1299 * @domain: domain to allocate from
1300 * @irq_base: allocate specified IRQ nubmer if irq_base >= 0 1300 * @irq_base: allocate specified IRQ number if irq_base >= 0
1301 * @nr_irqs: number of IRQs to allocate 1301 * @nr_irqs: number of IRQs to allocate
1302 * @node: NUMA node id for memory allocation 1302 * @node: NUMA node id for memory allocation
1303 * @arg: domain specific argument 1303 * @arg: domain specific argument