History

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 ...

Linus Torvalds committed 7 years ago

Commit d9351ea2 parents 39feaa3 fb4e05938 files · +2511 −229Browse files

Unified · Split

38 files
  1. Documentation/devicetree/bindings/arm/keystone/ti,sci.txt +2 −1
  2. Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.txt +66 −0
  3. Documentation/devicetree/bindings/interrupt-controller/ti,sci-intr.txt +82 −0
  4. MAINTAINERS +6 −0
  5. arch/arm64/Kconfig.platforms +5 −0
  6. drivers/firmware/ti_sci.c +651 −0
  7. drivers/firmware/ti_sci.h +102 −0
  8. drivers/gpio/gpio-thunderx.c +4 −12
  9. drivers/iommu/Kconfig +1 −0
  10. drivers/iommu/dma-iommu.c +28 −20
  11. drivers/irqchip/Kconfig +21 −6
  12. drivers/irqchip/Makefile +2 −0
  13. drivers/irqchip/irq-bcm7038-l1.c +3 −0
  14. drivers/irqchip/irq-bcm7120-l2.c +3 −0
  15. drivers/irqchip/irq-brcmstb-l2.c +2 −0
  16. drivers/irqchip/irq-gic-pm.c +39 −37
  17. drivers/irqchip/irq-gic-v2m.c +7 −1
  18. drivers/irqchip/irq-gic-v3-its.c +43 −41
  19. drivers/irqchip/irq-gic-v3-mbi.c +8 −2
  20. drivers/irqchip/irq-imx-irqsteer.c +1 −3
  21. drivers/irqchip/irq-ls-scfg-msi.c +6 −1
  22. drivers/irqchip/irq-renesas-intc-irqpin.c +1 −3
  23. drivers/irqchip/irq-stm32-exti.c +140 −93
  24. drivers/irqchip/irq-ti-sci-inta.c +615 −0
  25. drivers/irqchip/irq-ti-sci-intr.c +275 −0
  26. drivers/soc/ti/Kconfig +6 −0
  27. drivers/soc/ti/Makefile +1 −0
  28. drivers/soc/ti/ti_sci_inta_msi.c +146 −0
  29. include/linux/dma-iommu.h +22 −2
  30. include/linux/irq.h +2 −0
  31. include/linux/irqchip/arm-gic-v3.h +6 −6
  32. include/linux/irqdomain.h +1 −0
  33. include/linux/msi.h +36 −0
  34. include/linux/soc/ti/ti_sci_inta_msi.h +23 −0
  35. include/linux/soc/ti/ti_sci_protocol.h +124 −0
  36. kernel/irq/Kconfig +3 −0
  37. kernel/irq/chip.c +27 −0
  38. kernel/irq/irqdomain.c +1 −1
Documentation/devicetree/bindings/arm/keystone/ti,sci.txt+2−1
@@ -24,7 +24,8 @@ relationship between the TI-SCI parent node to the child node. · 23 unmodified lines
2424
2525 Required properties:
2626 -------------------
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
2829 - mbox-names:
2930 "rx" - Mailbox corresponding to receive path
3031 "tx" - Mailbox corresponding to transmit path
Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.txt+66−0
@@ -0,0 +1,66 @@
1+Texas Instruments K3 Interrupt Aggregator
2+=========================================
3+
4+The Interrupt Aggregator (INTA) provides a centralized machine
5+which handles the termination of system events to that they can
6+be coherently processed by the host(s) in the system. A maximum
7+of 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 |
17+Globalevents ------>| . . |------>| IRQ |
18+ . | . . | | CTRL |
19+ . | . . | +------+
20+ n ------>| +--------------+ +------------+ |
21+ | | vint | bit | | 0 |.....|63| vintx |
22+ | +--------------+ +------------+ |
23+ | |
24+ +-----------------------------------------+
25+
26+Configuration of these Intmap registers that maps global events to vint is done
27+by a system controller (like the Device Memory and Security Controller on K3
28+AM654 SoC). Driver should request the system controller to get the range
29+of global events and vints assigned to the requesting host. Management
30+of these requested resources should be handled by driver and requests
31+system controller to map specific global event to vint, bit pair.
32+
33+Communication between the host processor running an OS and the system
34+controller happens through a protocol called TI System Control Interface
35+(TISCI protocol). For more details refer:
36+Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
37+
38+TISCI 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+
54+Example:
55+--------
56+main_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+};
Documentation/devicetree/bindings/interrupt-controller/ti,sci-intr.txt+82−0
@@ -0,0 +1,82 @@
1+Texas Instruments K3 Interrupt Router
2+=====================================
3+
4+The Interrupt Router (INTR) module provides a mechanism to mux M
5+interrupt inputs to N interrupt outputs, where all M inputs are selectable
6+to be driven per N output. An Interrupt Router can either handle edge triggered
7+or 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+
25+There is one register per output (MUXCNTL_N) that controls the selection.
26+Configuration of these MUXCNTL_N registers is done by a system controller
27+(like the Device Memory and Security Controller on K3 AM654 SoC). System
28+controller will keep track of the used and unused registers within the Router.
29+Driver should request the system controller to get the range of GIC IRQs
30+assigned to the requesting hosts. It is the drivers responsibility to keep
31+track of Host IRQs.
32+
33+Communication between the host processor running an OS and the system
34+controller happens through a protocol called TI System Control Interface
35+(TISCI protocol). For more details refer:
36+Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
37+
38+TISCI Interrupt Router Node:
39+----------------------------
40+Required 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+
57+For more details on TISCI IRQ resource management refer:
58+http://downloads.ti.com/tisci/esd/latest/2_tisci_msgs/rm/rm_irq.html
59+
60+Example:
61+--------
62+The following example demonstrates both interrupt router node and the consumer
63+node(main gpio) on the AM654 SoC:
64+
65+main_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+
76+main_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+};
MAINTAINERS+6−0
@@ -15547,6 +15547,12 @@ F: Documentation/devicetree/bindings/reset/ti,sci-reset.txt · 15546 unmodified lines
1554715547 F: Documentation/devicetree/bindings/clock/ti,sci-clk.txt
1554815548 F: drivers/clk/keystone/sci-clk.c
1554915549 F: drivers/reset/reset-ti-sci.c
15550+F: Documentation/devicetree/bindings/interrupt-controller/ti,sci-intr.txt
15551+F: Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.txt
15552+F: drivers/irqchip/irq-ti-sci-intr.c
15553+F: drivers/irqchip/irq-ti-sci-inta.c
15554+F: include/linux/soc/ti/ti_sci_inta_msi.h
15555+F: drivers/soc/ti/ti_sci_inta_msi.c
1555015556
1555115557 Texas Instruments ASoC drivers
1555215558 M: Peter Ujfalusi <peter.ujfalusi@ti.com>
arch/arm64/Kconfig.platforms+5−0
@@ -87,6 +87,11 @@ config ARCH_EXYNOS · 86 unmodified lines
8787 config ARCH_K3
8888 bool "Texas Instruments Inc. K3 multicore SoC architecture"
8989 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
9095 help
9196 This enables support for Texas Instruments' K3 multicore SoC
9297 architecture.
drivers/firmware/ti_sci.c+651−0
@@ -64,6 +64,22 @@ struct ti_sci_xfers_info { · 63 unmodified lines
6464 spinlock_t xfer_lock;
6565 };
6666
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+ */
78+struct ti_sci_rm_type_map {
79+ u32 dev_id;
80+ u16 type;
81+};
82+
6783 /**
6884 * struct ti_sci_desc - Description of SoC integration
6985 * @default_host_id: Host identifier representing the compute entity
@@ -71,12 +87,14 @@ struct ti_sci_xfers_info { · 1 unmodified line
7187 * @max_msgs: Maximum number of messages that can be pending
7288 * simultaneously in the system
7389 * @max_msg_size: Maximum size of data per message that can be handled.
90+ * @rm_type_map: RM resource type mapping structure.
7491 */
7592 struct ti_sci_desc {
7693 u8 default_host_id;
7794 int max_rx_timeout_ms;
7895 int max_msgs;
7996 int max_msg_size;
97+ struct ti_sci_rm_type_map *rm_type_map;
8098 };
8199
82100 /**
@@ -1600,6 +1618,392 @@ fail: · 1517 unmodified lines
16001618 return ret;
16011619 }
16021620
1621+static 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+ */
1662+static 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+
1719+fail:
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+ */
1737+static 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+ */
1759+static
1760+int 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+ */
1787+static 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+
1837+fail:
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+ */
1861+static 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+ */
1895+static 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+ */
1924+static 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+ */
1946+static 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+ */
1972+static 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+ */
1994+static 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+
16032007 /*
16042008 * ti_sci_setup_ops() - Setup the operations structures
16052009 * @info: pointer to TISCI pointer
@@ -1610,6 +2014,8 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) · 4 unmodified lines
16102014 struct ti_sci_core_ops *core_ops = &ops->core_ops;
16112015 struct ti_sci_dev_ops *dops = &ops->dev_ops;
16122016 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;
16132019
16142020 core_ops->reboot_device = ti_sci_cmd_core_reboot;
16152021
@@ -1640,6 +2046,15 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) · 24 unmodified lines
16402046 cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq;
16412047 cops->set_freq = ti_sci_cmd_clk_set_freq;
16422048 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;
16432058 }
16442059
16452060 /**
@@ -1764,6 +2179,219 @@ const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev) · 118 unmodified lines
17642179 }
17652180 EXPORT_SYMBOL_GPL(devm_ti_sci_get_handle);
17662181
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+ */
2195+const 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+}
2229+EXPORT_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+ */
2243+const 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+}
2263+EXPORT_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+ */
2271+u16 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+}
2290+EXPORT_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+ */
2297+void 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+}
2311+EXPORT_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+ */
2319+u32 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+}
2328+EXPORT_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+ */
2340+struct ti_sci_resource *
2341+devm_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+
17672395 static int tisci_reboot_handler(struct notifier_block *nb, unsigned long mode,
17682396 void *cmd)
17692397 {
@@ -1784,10 +2412,33 @@ static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = { · 14 unmodified lines
17842412 /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */
17852413 .max_msgs = 20,
17862414 .max_msg_size = 64,
2415+ .rm_type_map = NULL,
2416+};
2417+
2418+static 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 */
2429+static 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,
17872437 };
17882438
17892439 static const struct of_device_id ti_sci_of_match[] = {
17902440 {.compatible = "ti,k2g-sci", .data = &ti_sci_pmmc_k2g_desc},
2441+ {.compatible = "ti,am654-sci", .data = &ti_sci_pmmc_am654_desc},
17912442 { /* Sentinel */ },
17922443 };
17932444 MODULE_DEVICE_TABLE(of, ti_sci_of_match);
drivers/firmware/ti_sci.h+102−0
@@ -35,6 +35,13 @@ · 34 unmodified lines
3535 #define TI_SCI_MSG_QUERY_CLOCK_FREQ 0x010d
3636 #define TI_SCI_MSG_GET_CLOCK_FREQ 0x010e
3737
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+
3845 /**
3946 * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses
4047 * @type: Type of messages: One of TI_SCI_MSG* values
@@ -461,4 +468,99 @@ struct ti_sci_msg_resp_get_clock_freq { · 420 unmodified lines
461468 u64 freq_hz;
462469 } __packed;
463470
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+ */
487+struct 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+ */
504+struct 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+ */
545+struct 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+
464566 #endif /* __TI_SCI_H */
drivers/gpio/gpio-thunderx.c+4−12
@@ -363,22 +363,16 @@ static int thunderx_gpio_irq_request_resources(struct irq_data *data) · 362 unmodified lines
363363 {
364364 struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
365365 struct thunderx_gpio *txgpio = txline->txgpio;
366− struct irq_data *parent_data = data->parent_data;
367366 int r;
368367
369368 r = gpiochip_lock_as_irq(&txgpio->chip, txline->line);
370369 if (r)
371370 return r;
372371
373− if (parent_data && parent_data->chip->irq_request_resources) {
374− r = parent_data->chip->irq_request_resources(parent_data);
375− if (r)
376− goto error;
377− }
372+ r = irq_chip_request_resources_parent(data);
373+ if (r)
374+ gpiochip_unlock_as_irq(&txgpio->chip, txline->line);
378375
379− return 0;
380−error:
381− gpiochip_unlock_as_irq(&txgpio->chip, txline->line);
382376 return r;
383377 }
384378
@@ -386,10 +380,8 @@ static void thunderx_gpio_irq_release_resources(struct irq_data *data) · 1 unmodified line
386380 {
387381 struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
388382 struct thunderx_gpio *txgpio = txline->txgpio;
389− struct irq_data *parent_data = data->parent_data;
390383
391− if (parent_data && parent_data->chip->irq_release_resources)
392− parent_data->chip->irq_release_resources(parent_data);
384+ irq_chip_release_resources_parent(data);
393385
394386 gpiochip_unlock_as_irq(&txgpio->chip, txline->line);
395387 }
drivers/iommu/Kconfig+1−0
@@ -94,6 +94,7 @@ config IOMMU_DMA · 93 unmodified lines
9494 bool
9595 select IOMMU_API
9696 select IOMMU_IOVA
97+ select IRQ_MSI_IOMMU
9798 select NEED_SG_DMA_LENGTH
9899
99100 config FSL_PAMU
drivers/iommu/dma-iommu.c+28−20
@@ -907,17 +907,18 @@ out_free_page: · 906 unmodified lines
907907 return NULL;
908908 }
909909
910−void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
910+int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
911911 {
912− struct device *dev = msi_desc_to_dev(irq_get_msi_desc(irq));
912+ struct device *dev = msi_desc_to_dev(desc);
913913 struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
914914 struct iommu_dma_cookie *cookie;
915915 struct iommu_dma_msi_page *msi_page;
916− phys_addr_t msi_addr = (u64)msg->address_hi << 32 | msg->address_lo;
917916 unsigned long flags;
918917
919− if (!domain || !domain->iova_cookie)
920− return;
918+ if (!domain || !domain->iova_cookie) {
919+ desc->iommu_cookie = NULL;
920+ return 0;
921+ }
921922
922923 cookie = domain->iova_cookie;
923924
@@ -930,19 +931,26 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg) · 6 unmodified lines
930931 msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain);
931932 spin_unlock_irqrestore(&cookie->msi_lock, flags);
932933
933− if (WARN_ON(!msi_page)) {
934− /*
935− * We're called from a void callback, so the best we can do is
936− * 'fail' by filling the message with obviously bogus values.
937− * Since we got this far due to an IOMMU being present, it's
938− * not like the existing address would have worked anyway...
939− */
940− msg->address_hi = ~0U;
941− msg->address_lo = ~0U;
942− msg->data = ~0U;
943− } else {
944− msg->address_hi = upper_32_bits(msi_page->iova);
945− msg->address_lo &= cookie_msi_granule(cookie) - 1;
946− msg->address_lo += lower_32_bits(msi_page->iova);
947− }
934+ msi_desc_set_iommu_cookie(desc, msi_page);
935+
936+ if (!msi_page)
937+ return -ENOMEM;
938+ return 0;
939+}
940+
941+void iommu_dma_compose_msi_msg(struct msi_desc *desc,
942+ struct msi_msg *msg)
943+{
944+ struct device *dev = msi_desc_to_dev(desc);
945+ const struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
946+ const struct iommu_dma_msi_page *msi_page;
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);
948956 }
drivers/irqchip/Kconfig+21−6
@@ -6,7 +6,6 @@ config IRQCHIP · 5 unmodified lines
66
77 config ARM_GIC
88 bool
9− select IRQ_DOMAIN
109 select IRQ_DOMAIN_HIERARCHY
1110 select GENERIC_IRQ_MULTI_HANDLER
1211 select GENERIC_IRQ_EFFECTIVE_AFF_MASK
@@ -33,7 +32,6 @@ config GIC_NON_BANKED · 20 unmodified lines
3332
3433 config ARM_GIC_V3
3534 bool
36− select IRQ_DOMAIN
3735 select GENERIC_IRQ_MULTI_HANDLER
3836 select IRQ_DOMAIN_HIERARCHY
3937 select PARTITION_PERCPU
@@ -59,7 +57,6 @@ config ARM_GIC_V3_ITS_FSL_MC · 19 unmodified lines
5957
6058 config ARM_NVIC
6159 bool
62− select IRQ_DOMAIN
6360 select IRQ_DOMAIN_HIERARCHY
6461 select GENERIC_IRQ_CHIP
6562
@@ -358,7 +355,6 @@ config STM32_EXTI · 292 unmodified lines
358355 config QCOM_IRQ_COMBINER
359356 bool "QCOM IRQ combiner support"
360357 depends on ARCH_QCOM && ACPI
361− select IRQ_DOMAIN
362358 select IRQ_DOMAIN_HIERARCHY
363359 help
364360 Say yes here to add support for the IRQ combiner devices embedded
@@ -375,7 +371,6 @@ config IRQ_UNIPHIER_AIDET · 10 unmodified lines
375371 config MESON_IRQ_GPIO
376372 bool "Meson GPIO Interrupt Multiplexer"
377373 depends on ARCH_MESON
378− select IRQ_DOMAIN
379374 select IRQ_DOMAIN_HIERARCHY
380375 help
381376 Support Meson SoC Family GPIO Interrupt Multiplexer
@@ -391,7 +386,6 @@ config GOLDFISH_PIC · 9 unmodified lines
391386 config QCOM_PDC
392387 bool "QCOM PDC"
393388 depends on ARCH_QCOM
394− select IRQ_DOMAIN
395389 select IRQ_DOMAIN_HIERARCHY
396390 help
397391 Power Domain Controller driver to manage and configure wakeup
@@ -431,6 +425,27 @@ config LS1X_IRQ · 33 unmodified lines
431425 help
432426 Support for the Loongson-1 platform Interrupt Controller.
433427
428+config 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+
438+config 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+
434449 endmenu
435450
436451 config SIFIVE_PLIC
drivers/irqchip/Makefile+2−0
@@ -98,3 +98,5 @@ obj-$(CONFIG_SIFIVE_PLIC) += irq-sifive-plic.o · 97 unmodified lines
9898 obj-$(CONFIG_IMX_IRQSTEER) += irq-imx-irqsteer.o
9999 obj-$(CONFIG_MADERA_IRQ) += irq-madera.o
100100 obj-$(CONFIG_LS1X_IRQ) += irq-ls1x.o
101+obj-$(CONFIG_TI_SCI_INTR_IRQCHIP) += irq-ti-sci-intr.o
102+obj-$(CONFIG_TI_SCI_INTA_IRQCHIP) += irq-ti-sci-inta.o
drivers/irqchip/irq-bcm7038-l1.c+3−0
@@ -343,6 +343,9 @@ int __init bcm7038_l1_of_init(struct device_node *dn, · 342 unmodified lines
343343 goto out_unmap;
344344 }
345345
346+ pr_info("registered BCM7038 L1 intc (%pOF, IRQs: %d)\n",
347+ dn, IRQS_PER_WORD * intc->n_words);
348+
346349 return 0;
347350
348351 out_unmap:
drivers/irqchip/irq-bcm7120-l2.c+3−0
@@ -318,6 +318,9 @@ static int __init bcm7120_l2_intc_probe(struct device_node *dn, · 317 unmodified lines
318318 }
319319 }
320320
321+ pr_info("registered %s intc (%pOF, parent IRQ(s): %d)\n",
322+ intc_name, dn, data->num_parent_irqs);
323+
321324 return 0;
322325
323326 out_free_domain:
drivers/irqchip/irq-brcmstb-l2.c+2−0
@@ -264,6 +264,8 @@ static int __init brcmstb_l2_intc_of_init(struct device_node *np, · 263 unmodified lines
264264 ct->chip.irq_set_wake = irq_gc_set_wake;
265265 }
266266
267+ pr_info("registered L2 intc (%pOF, parent irq: %d)\n", np, parent_irq);
268+
267269 return 0;
268270
269271 out_free_domain:
drivers/irqchip/irq-gic-pm.c+39−37
@@ -19,7 +19,6 @@ · 18 unmodified lines
1919 #include <linux/of_irq.h>
2020 #include <linux/irqchip/arm-gic.h>
2121 #include <linux/platform_device.h>
22−#include <linux/pm_clock.h>
2322 #include <linux/pm_runtime.h>
2423 #include <linux/slab.h>
2524
@@ -28,17 +27,27 @@ struct gic_clk_data { · 2 unmodified lines
2827 const char *const *clocks;
2928 };
3029
30+struct 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+
3136 static int gic_runtime_resume(struct device *dev)
3237 {
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;
3441 int ret;
3542
36− ret = pm_clk_resume(dev);
37− if (ret)
43+ ret = clk_bulk_prepare_enable(data->num_clocks, chip_pm->clks);
44+ if (ret) {
45+ dev_err(dev, "clk_enable failed: %d\n", ret);
3846 return ret;
47+ }
3948
4049 /*
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
4251 * will be NULL and this is intentional, because we do not
4352 * want to restore the GIC on the very first resume. So if
4453 * the pointer is not valid just return.
@@ -54,35 +63,14 @@ static int gic_runtime_resume(struct device *dev) · 9 unmodified lines
5463
5564 static int gic_runtime_suspend(struct device *dev)
5665 {
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;
5869
5970 gic_dist_save(gic);
6071 gic_cpu_save(gic);
6172
62− return pm_clk_suspend(dev);
63−}
64−
65−static 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− }
73+ clk_bulk_disable_unprepare(data->num_clocks, chip_pm->clks);
8674
8775 return 0;
8876 }
@@ -91,8 +79,8 @@ static int gic_probe(struct platform_device *pdev) · 2 unmodified lines
9179 {
9280 struct device *dev = &pdev->dev;
9381 const struct gic_clk_data *data;
94− struct gic_chip_data *gic;
95− int ret, irq;
82+ struct gic_chip_pm *chip_pm;
83+ int ret, irq, i;
9684
9785 data = of_device_get_match_data(&pdev->dev);
9886 if (!data) {
@@ -100,28 +88,41 @@ static int gic_probe(struct platform_device *pdev) · 1 unmodified line
10088 return -ENODEV;
10189 }
10290
91+ chip_pm = devm_kzalloc(dev, sizeof(*chip_pm), GFP_KERNEL);
92+ if (!chip_pm)
93+ return -ENOMEM;
94+
10395 irq = irq_of_parse_and_map(dev->of_node, 0);
10496 if (!irq) {
10597 dev_err(dev, "no parent interrupt found!\n");
10698 return -EINVAL;
10799 }
108100
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);
110110 if (ret)
111111 goto irq_dispose;
112112
113+ chip_pm->clk_data = data;
114+ dev_set_drvdata(dev, chip_pm);
115+
113116 pm_runtime_enable(dev);
114117
115118 ret = pm_runtime_get_sync(dev);
116119 if (ret < 0)
117120 goto rpm_disable;
118121
119− ret = gic_of_init_child(dev, &gic, irq);
122+ ret = gic_of_init_child(dev, &chip_pm->chip_data, irq);
120123 if (ret)
121124 goto rpm_put;
122125
123− platform_set_drvdata(pdev, gic);
124−
125126 pm_runtime_put(dev);
126127
127128 dev_info(dev, "GIC IRQ controller registered\n");
@@ -132,7 +133,6 @@ rpm_put: · 4 unmodified lines
132133 pm_runtime_put_sync(dev);
133134 rpm_disable:
134135 pm_runtime_disable(dev);
135− pm_clk_destroy(dev);
136136 irq_dispose:
137137 irq_dispose_mapping(irq);
138138
@@ -142,6 +142,8 @@ irq_dispose: · 3 unmodified lines
142142 static const struct dev_pm_ops gic_pm_ops = {
143143 SET_RUNTIME_PM_OPS(gic_runtime_suspend,
144144 gic_runtime_resume, NULL)
145+ SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
146+ pm_runtime_force_resume)
145147 };
146148
147149 static const char * const gic400_clocks[] = {
drivers/irqchip/irq-gic-v2m.c+7−1
@@ -110,7 +110,7 @@ static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) · 109 unmodified lines
110110 if (v2m->flags & GICV2M_NEEDS_SPI_OFFSET)
111111 msg->data -= v2m->spi_offset;
112112
113− iommu_dma_map_msi_msg(data->irq, msg);
113+ iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), msg);
114114 }
115115
116116 static struct irq_chip gicv2m_irq_chip = {
@@ -167,6 +167,7 @@ static void gicv2m_unalloc_msi(struct v2m_data *v2m, unsigned int hwirq, · 50 unmodified lines
167167 static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
168168 unsigned int nr_irqs, void *args)
169169 {
170+ msi_alloc_info_t *info = args;
170171 struct v2m_data *v2m = NULL, *tmp;
171172 int hwirq, offset, i, err = 0;
172173
@@ -186,6 +187,11 @@ static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, · 13 unmodified lines
186187
187188 hwirq = v2m->spi_start + offset;
188189
190+ err = iommu_dma_prepare_msi(info->desc,
191+ v2m->res.start + V2M_MSI_SETSPI_NS);
192+ if (err)
193+ return err;
194+
189195 for (i = 0; i < nr_irqs; i++) {
190196 err = gicv2m_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
191197 if (err)
drivers/irqchip/irq-gic-v3-its.c+43−41
@@ -26,7 +26,6 @@ · 25 unmodified lines
2626 #include <linux/interrupt.h>
2727 #include <linux/irqdomain.h>
2828 #include <linux/list.h>
29−#include <linux/list_sort.h>
3029 #include <linux/log2.h>
3130 #include <linux/memblock.h>
3231 #include <linux/mm.h>
@@ -1179,7 +1178,7 @@ static void its_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg) · 1146 unmodified lines
11791178 msg->address_hi = upper_32_bits(addr);
11801179 msg->data = its_get_event_id(d);
11811180
1182− iommu_dma_map_msi_msg(d->irq, msg);
1181+ iommu_dma_compose_msi_msg(irq_data_get_msi_desc(d), msg);
11831182 }
11841183
11851184 static 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) · 279 unmodified lines
14651464 {
14661465 struct lpi_range *range;
14671466
1468− range = kzalloc(sizeof(*range), GFP_KERNEL);
1467+ range = kmalloc(sizeof(*range), GFP_KERNEL);
14691468 if (range) {
1470− INIT_LIST_HEAD(&range->entry);
14711469 range->base_id = base;
14721470 range->span = span;
14731471 }
@@ -1475,31 +1473,6 @@ static struct lpi_range *mk_lpi_range(u32 base, u32 span) · 1 unmodified line
14751473 return range;
14761474 }
14771475
1478−static 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−
1488−static 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−
15031476 static int alloc_lpi_range(u32 nr_lpis, u32 *base)
15041477 {
15051478 struct lpi_range *range, *tmp;
@@ -1529,25 +1502,49 @@ static int alloc_lpi_range(u32 nr_lpis, u32 *base) · 23 unmodified lines
15291502 return err;
15301503 }
15311504
1505+static 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+
15321517 static int free_lpi_range(u32 base, u32 nr_lpis)
15331518 {
1534− struct lpi_range *new;
1535− int err = 0;
1519+ struct lpi_range *new, *old;
1520+
1521+ new = mk_lpi_range(base, nr_lpis);
1522+ if (!new)
1523+ return -ENOMEM;
15361524
15371525 mutex_lock(&lpi_range_lock);
15381526
1539− new = mk_lpi_range(base, nr_lpis);
1540− if (!new) {
1541− err = -ENOMEM;
1542− goto out;
1527+ list_for_each_entry_reverse(old, &lpi_range_list, entry) {
1528+ if (old->base_id < base)
1529+ break;
15431530 }
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));
15441545
1545− list_add(&new->entry, &lpi_range_list);
1546− list_sort(NULL, &lpi_range_list, lpi_range_cmp);
1547− merge_lpi_ranges();
1548−out:
15491546 mutex_unlock(&lpi_range_lock);
1550− return err;
1547+ return 0;
15511548 }
15521549
15531550 static int __init its_lpi_init(u32 id_bits)
@@ -2487,7 +2484,7 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev, · 933 unmodified lines
24872484 int err = 0;
24882485
24892486 /*
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
24912488 * been passed via the scratchpad. This limits this domain's
24922489 * usefulness to upper layers that definitely know that they
24932490 * are built on top of the ITS.
@@ -2566,6 +2563,7 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, · 72 unmodified lines
25662563 {
25672564 msi_alloc_info_t *info = args;
25682565 struct its_device *its_dev = info->scratchpad[0].ptr;
2566+ struct its_node *its = its_dev->its;
25692567 irq_hw_number_t hwirq;
25702568 int err;
25712569 int i;
@@ -2574,6 +2572,10 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, · 2 unmodified lines
25742572 if (err)
25752573 return err;
25762574
2575+ err = iommu_dma_prepare_msi(info->desc, its->get_msi_base(its_dev));
2576+ if (err)
2577+ return err;
2578+
25772579 for (i = 0; i < nr_irqs; i++) {
25782580 err = its_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
25792581 if (err)
drivers/irqchip/irq-gic-v3-mbi.c+8−2
@@ -84,6 +84,7 @@ static void mbi_free_msi(struct mbi_range *mbi, unsigned int hwirq, · 83 unmodified lines
8484 static int mbi_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
8585 unsigned int nr_irqs, void *args)
8686 {
87+ msi_alloc_info_t *info = args;
8788 struct mbi_range *mbi = NULL;
8889 int hwirq, offset, i, err = 0;
8990
@@ -104,6 +105,11 @@ static int mbi_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, · 14 unmodified lines
104105
105106 hwirq = mbi->spi_start + offset;
106107
108+ err = iommu_dma_prepare_msi(info->desc,
109+ mbi_phys_base + GICD_SETSPI_NSR);
110+ if (err)
111+ return err;
112+
107113 for (i = 0; i < nr_irqs; i++) {
108114 err = mbi_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
109115 if (err)
@@ -142,7 +148,7 @@ static void mbi_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) · 32 unmodified lines
142148 msg[0].address_lo = lower_32_bits(mbi_phys_base + GICD_SETSPI_NSR);
143149 msg[0].data = data->parent_data->hwirq;
144150
145− iommu_dma_map_msi_msg(data->irq, msg);
151+ iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), msg);
146152 }
147153
148154 #ifdef CONFIG_PCI_MSI
@@ -202,7 +208,7 @@ static void mbi_compose_mbi_msg(struct irq_data *data, struct msi_msg *msg) · 53 unmodified lines
202208 msg[1].address_lo = lower_32_bits(mbi_phys_base + GICD_CLRSPI_NSR);
203209 msg[1].data = data->parent_data->hwirq;
204210
205− iommu_dma_map_msi_msg(data->irq, &msg[1]);
211+ iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), &msg[1]);
206212 }
207213
208214 /* Platform-MSI specific irqchip */
drivers/irqchip/irq-imx-irqsteer.c+1−3
@@ -144,7 +144,6 @@ static int imx_irqsteer_probe(struct platform_device *pdev) · 143 unmodified lines
144144 {
145145 struct device_node *np = pdev->dev.of_node;
146146 struct irqsteer_data *data;
147− struct resource *res;
148147 u32 irqs_num;
149148 int i, ret;
150149
@@ -152,8 +151,7 @@ static int imx_irqsteer_probe(struct platform_device *pdev) · 1 unmodified line
152151 if (!data)
153152 return -ENOMEM;
154153
155− res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
156− data->regs = devm_ioremap_resource(&pdev->dev, res);
154+ data->regs = devm_platform_ioremap_resource(pdev, 0);
157155 if (IS_ERR(data->regs)) {
158156 dev_err(&pdev->dev, "failed to initialize reg\n");
159157 return PTR_ERR(data->regs);
drivers/irqchip/irq-ls-scfg-msi.c+6−1
@@ -100,7 +100,7 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg) · 99 unmodified lines
100100 msg->data |= cpumask_first(mask);
101101 }
102102
103− iommu_dma_map_msi_msg(data->irq, msg);
103+ iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), msg);
104104 }
105105
106106 static 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, · 34 unmodified lines
141141 unsigned int nr_irqs,
142142 void *args)
143143 {
144+ msi_alloc_info_t *info = args;
144145 struct ls_scfg_msi *msi_data = domain->host_data;
145146 int pos, err = 0;
146147
@@ -154,6 +155,10 @@ static int ls_scfg_msi_domain_irq_alloc(struct irq_domain *domain, · 7 unmodified lines
154155 err = -ENOSPC;
155156 spin_unlock(&msi_data->lock);
156157
158+ if (err)
159+ return err;
160+
161+ err = iommu_dma_prepare_msi(info->desc, msi_data->msiir_addr);
157162 if (err)
158163 return err;
159164
drivers/irqchip/irq-renesas-intc-irqpin.c+1−3
@@ -389,10 +389,8 @@ static int intc_irqpin_probe(struct platform_device *pdev) · 388 unmodified lines
389389 int k;
390390
391391 p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);
392− if (!p) {
393− dev_err(dev, "failed to allocate driver data\n");
392+ if (!p)
394393 return -ENOMEM;
395− }
396394
397395 /* deal with driver instance configuration */
398396 of_property_read_u32(dev->of_node, "sense-bitfield-width",
drivers/irqchip/irq-stm32-exti.c+140−93
@@ -14,8 +14,10 @@ · 13 unmodified lines
1414 #include <linux/irqchip.h>
1515 #include <linux/irqchip/chained_irq.h>
1616 #include <linux/irqdomain.h>
17+#include <linux/module.h>
1718 #include <linux/of_address.h>
1819 #include <linux/of_irq.h>
20+#include <linux/of_platform.h>
1921 #include <linux/syscore_ops.h>
2022
2123 #include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -37,12 +39,6 @@ struct stm32_exti_bank { · 15 unmodified lines
3739
3840 #define UNDEF_REG ~0
3941
40−enum stm32_exti_hwspinlock {
41− HWSPINLOCK_UNKNOWN,
42− HWSPINLOCK_NONE,
43− HWSPINLOCK_READY,
44−};
45−
4642 struct stm32_desc_irq {
4743 u32 exti;
4844 u32 irq_parent;
@@ -69,8 +65,6 @@ struct stm32_exti_host_data { · 20 unmodified lines
6965 void __iomem *base;
7066 struct stm32_exti_chip_data *chips_data;
7167 const struct stm32_exti_drv_data *drv_data;
72− struct device_node *node;
73− enum stm32_exti_hwspinlock hwlock_state;
7468 struct hwspinlock *hwlock;
7569 };
7670
@@ -285,49 +279,27 @@ static int stm32_exti_set_type(struct irq_data *d, · 208 unmodified lines
285279
286280 static int stm32_exti_hwspin_lock(struct stm32_exti_chip_data *chip_data)
287281 {
288− struct stm32_exti_host_data *host_data = chip_data->host_data;
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− }
282+ int ret, timeout = 0;
312283
313− if (likely(host_data->hwlock_state == HWSPINLOCK_READY)) {
314− /*
315− * Use the x_raw API since we are under spin_lock protection.
316− * Do not use the x_timeout API because we are under irq_disable
317− * mode (see __setup_irq())
318− */
319− do {
320− ret = hwspin_trylock_raw(host_data->hwlock);
321− if (!ret)
322− return 0;
323−
324− udelay(HWSPNLCK_RETRY_DELAY);
325− timeout += HWSPNLCK_RETRY_DELAY;
326− } while (timeout < HWSPNLCK_TIMEOUT);
327−
328− if (ret == -EBUSY)
329− ret = -ETIMEDOUT;
330− }
284+ if (!chip_data->host_data->hwlock)
285+ return 0;
286+
287+ /*
288+ * Use the x_raw API since we are under spin_lock protection.
289+ * Do not use the x_timeout API because we are under irq_disable
290+ * mode (see __setup_irq())
291+ */
292+ do {
293+ ret = hwspin_trylock_raw(chip_data->host_data->hwlock);
294+ if (!ret)
295+ return 0;
296+
297+ udelay(HWSPNLCK_RETRY_DELAY);
298+ timeout += HWSPNLCK_RETRY_DELAY;
299+ } while (timeout < HWSPNLCK_TIMEOUT);
300+
301+ if (ret == -EBUSY)
302+ ret = -ETIMEDOUT;
331303
332304 if (ret)
333305 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) · 3 unmodified lines
337309
338310 static void stm32_exti_hwspin_unlock(struct stm32_exti_chip_data *chip_data)
339311 {
340− if (likely(chip_data->host_data->hwlock_state == HWSPINLOCK_READY))
312+ if (chip_data->host_data->hwlock)
341313 hwspin_unlock_raw(chip_data->host_data->hwlock);
342314 }
343315
@@ -586,8 +558,7 @@ static int stm32_exti_h_set_affinity(struct irq_data *d, · 242 unmodified lines
586558 return -EINVAL;
587559 }
588560
589−#ifdef CONFIG_PM
590−static int stm32_exti_h_suspend(void)
561+static int __maybe_unused stm32_exti_h_suspend(void)
591562 {
592563 struct stm32_exti_chip_data *chip_data;
593564 int i;
@@ -602,7 +573,7 @@ static int stm32_exti_h_suspend(void) · 8 unmodified lines
602573 return 0;
603574 }
604575
605−static void stm32_exti_h_resume(void)
576+static void __maybe_unused stm32_exti_h_resume(void)
606577 {
607578 struct stm32_exti_chip_data *chip_data;
608579 int i;
@@ -616,17 +587,22 @@ static void stm32_exti_h_resume(void) · 7 unmodified lines
616587 }
617588
618589 static struct syscore_ops stm32_exti_h_syscore_ops = {
590+#ifdef CONFIG_PM_SLEEP
619591 .suspend = stm32_exti_h_suspend,
620592 .resume = stm32_exti_h_resume,
593+#endif
621594 };
622595
623−static void stm32_exti_h_syscore_init(void)
596+static void stm32_exti_h_syscore_init(struct stm32_exti_host_data *host_data)
624597 {
598+ stm32_host_data = host_data;
625599 register_syscore_ops(&stm32_exti_h_syscore_ops);
626600 }
627−#else
628−static inline void stm32_exti_h_syscore_init(void) {}
629−#endif
601+
602+static void stm32_exti_h_syscore_deinit(void)
603+{
604+ unregister_syscore_ops(&stm32_exti_h_syscore_ops);
605+}
630606
631607 static struct irq_chip stm32_exti_h_chip = {
632608 .name = "stm32-exti-h",
@@ -683,8 +659,6 @@ stm32_exti_host_data *stm32_exti_host_init(const struct stm32_exti_drv_data *dd, · 50 unmodified lines
683659 return NULL;
684660
685661 host_data->drv_data = dd;
686− host_data->node = node;
687− host_data->hwlock_state = HWSPINLOCK_UNKNOWN;
688662 host_data->chips_data = kcalloc(dd->bank_nr,
689663 sizeof(struct stm32_exti_chip_data),
690664 GFP_KERNEL);
@@ -711,7 +685,8 @@ free_host_data: · 20 unmodified lines
711685
712686 static struct
713687 stm32_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)
715690 {
716691 const struct stm32_exti_bank *stm32_bank;
717692 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, · 13 unmodified lines
731706 writel_relaxed(0, base + stm32_bank->imr_ofst);
732707 writel_relaxed(0, base + stm32_bank->emr_ofst);
733708
734− pr_info("%pOF: bank%d\n", h_data->node, bank_idx);
709+ pr_info("%pOF: bank%d\n", node, bank_idx);
735710
736711 return chip_data;
737712 }
@@ -771,7 +746,7 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data, · 33 unmodified lines
771746 struct stm32_exti_chip_data *chip_data;
772747
773748 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);
775750
776751 gc = irq_get_domain_generic_chip(domain, i * IRQS_PER_BANK);
777752
@@ -815,50 +790,130 @@ static const struct irq_domain_ops stm32_exti_h_domain_ops = { · 37 unmodified lines
815790 .xlate = irq_domain_xlate_twocell,
816791 };
817792
818−static int
819−__init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data,
820− struct device_node *node,
821− struct device_node *parent)
793+static void stm32_exti_remove_irq(void *data)
794+{
795+ struct irq_domain *domain = data;
796+
797+ irq_domain_remove(domain);
798+}
799+
800+static int stm32_exti_remove(struct platform_device *pdev)
801+{
802+ stm32_exti_h_syscore_deinit();
803+ return 0;
804+}
805+
806+static int stm32_exti_probe(struct platform_device *pdev)
822807 {
808+ int ret, i;
809+ struct device *dev = &pdev->dev;
810+ struct device_node *np = dev->of_node;
823811 struct irq_domain *parent_domain, *domain;
824812 struct stm32_exti_host_data *host_data;
825− int ret, i;
813+ const struct stm32_exti_drv_data *drv_data;
814+ struct resource *res;
826815
827− parent_domain = irq_find_host(parent);
828− if (!parent_domain) {
829− pr_err("interrupt-parent not found\n");
830− return -EINVAL;
816+ host_data = devm_kzalloc(dev, sizeof(*host_data), GFP_KERNEL);
817+ if (!host_data)
818+ return -ENOMEM;
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;
831836 }
832837
833− host_data = stm32_exti_host_init(drv_data, node);
834− if (!host_data)
838+ /* initialize 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)
835850 return -ENOMEM;
836851
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+
837859 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+ }
839867
840868 domain = irq_domain_add_hierarchy(parent_domain, 0,
841869 drv_data->bank_nr * IRQS_PER_BANK,
842− node, &stm32_exti_h_domain_ops,
870+ np, &stm32_exti_h_domain_ops,
843871 host_data);
844872
845873 if (!domain) {
846− pr_err("%pOFn: Could not register exti domain.\n", node);
847− ret = -ENOMEM;
848− goto out_unmap;
874+ dev_err(dev, "Could not register exti domain\n");
875+ return -ENOMEM;
849876 }
850877
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);
852883
853884 return 0;
885+}
854886
855−out_unmap:
856− iounmap(host_data->base);
857− kfree(host_data->chips_data);
858− kfree(host_data);
859− return ret;
887+/* platform driver only for MP1 */
888+static const struct of_device_id stm32_exti_ids[] = {
889+ { .compatible = "st,stm32mp1-exti", .data = &stm32mp1_drv_data},
890+ {},
891+};
892+MODULE_DEVICE_TABLE(of, stm32_exti_ids);
893+
894+static 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+
903+static int __init stm32_exti_arch_init(void)
904+{
905+ return platform_driver_register(&stm32_exti_driver);
860906 }
861907
908+static void __exit stm32_exti_arch_exit(void)
909+{
910+ return platform_driver_unregister(&stm32_exti_driver);
911+}
912+
913+arch_initcall(stm32_exti_arch_init);
914+module_exit(stm32_exti_arch_exit);
915+
916+/* no platform driver for F4 and H7 */
862917 static int __init stm32f4_exti_of_init(struct device_node *np,
863918 struct device_node *parent)
864919 {
@@ -874,11 +929,3 @@ static int __init stm32h7_exti_of_init(struct device_node *np, · 9 unmodified lines
874929 }
875930
876931 IRQCHIP_DECLARE(stm32h7_exti, "st,stm32h7-exti", stm32h7_exti_of_init);
877−
878−static 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−
884−IRQCHIP_DECLARE(stm32mp1_exti, "st,stm32mp1-exti", stm32mp1_exti_of_init);
drivers/irqchip/irq-ti-sci-inta.c+615−0
@@ -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+ */
50+struct 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+ */
66+struct 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+ */
86+struct 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+ */
104+static 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+ */
136+static 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+ */
183+static 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;
212+free_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+ */
228+static 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+
257+alloc_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+ */
271+static 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+ */
287+static 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+ */
325+static 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+ */
345+static 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+ */
358+static 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+ */
376+static 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+ */
385+static 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+ */
394+static 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+
404+static 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+ */
419+static 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+
438+static 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+ */
455+static 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+ */
474+static 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+
486+static 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+
491+static struct irq_chip ti_sci_inta_msi_irq_chip = {
492+ .name = "MSI-INTA",
493+ .flags = IRQCHIP_SUPPORTS_LEVEL_MSI,
494+};
495+
496+static 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+
505+static struct msi_domain_ops ti_sci_inta_msi_ops = {
506+ .set_desc = ti_sci_inta_msi_set_desc,
507+};
508+
509+static 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+
516+static 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+
598+static const struct of_device_id ti_sci_inta_irq_domain_of_match[] = {
599+ { .compatible = "ti,sci-inta", },
600+ { /* sentinel */ },
601+};
602+MODULE_DEVICE_TABLE(of, ti_sci_inta_irq_domain_of_match);
603+
604+static 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+};
611+module_platform_driver(ti_sci_inta_irq_domain_driver);
612+
613+MODULE_AUTHOR("Lokesh Vutla <lokeshvutla@ticom>");
614+MODULE_DESCRIPTION("K3 Interrupt Aggregator driver over TI SCI protocol");
615+MODULE_LICENSE("GPL v2");
drivers/irqchip/irq-ti-sci-intr.c+275−0
@@ -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+ */
39+struct 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+
46+static 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+ */
66+static 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+ */
88+static 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+ */
115+static 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+
148+err_msg:
149+ irq_domain_free_irqs_parent(domain, virq, 1);
150+err_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+ */
164+static 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+
187+static 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+
193+static 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+
258+static const struct of_device_id ti_sci_intr_irq_domain_of_match[] = {
259+ { .compatible = "ti,sci-intr", },
260+ { /* sentinel */ },
261+};
262+MODULE_DEVICE_TABLE(of, ti_sci_intr_irq_domain_of_match);
263+
264+static 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+};
271+module_platform_driver(ti_sci_intr_irq_domain_driver);
272+
273+MODULE_AUTHOR("Lokesh Vutla <lokeshvutla@ticom>");
274+MODULE_DESCRIPTION("K3 Interrupt Router driver over TI SCI protocol");
275+MODULE_LICENSE("GPL v2");
drivers/soc/ti/Kconfig+6−0
@@ -74,4 +74,10 @@ config TI_SCI_PM_DOMAINS · 73 unmodified lines
7474 called ti_sci_pm_domains. Note this is needed early in boot before
7575 rootfs may be available.
7676
77+config 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+
7783 endif # SOC_TI
drivers/soc/ti/Makefile+1−0
@@ -8,3 +8,4 @@ obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA) += knav_dma.o · 7 unmodified lines
88 obj-$(CONFIG_AMX3_PM) += pm33xx.o
99 obj-$(CONFIG_WKUP_M3_IPC) += wkup_m3_ipc.o
1010 obj-$(CONFIG_TI_SCI_PM_DOMAINS) += ti_sci_pm_domains.o
11+obj-$(CONFIG_TI_SCI_INTA_MSI_DOMAIN) += ti_sci_inta_msi.o
drivers/soc/ti/ti_sci_inta_msi.c+146−0
@@ -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+
18+static void ti_sci_inta_msi_write_msg(struct irq_data *data,
19+ struct msi_msg *msg)
20+{
21+ /* Nothing to do */
22+}
23+
24+static void ti_sci_inta_msi_compose_msi_msg(struct irq_data *data,
25+ struct msi_msg *msg)
26+{
27+ /* Nothing to do */
28+}
29+
30+static 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+
47+struct 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+}
61+EXPORT_SYMBOL_GPL(ti_sci_inta_msi_create_irq_domain);
62+
63+static 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+
73+static 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+
97+int 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+
123+cleanup:
124+ ti_sci_inta_msi_free_descs(&pdev->dev);
125+ return ret;
126+}
127+EXPORT_SYMBOL_GPL(ti_sci_inta_msi_domain_alloc_irqs);
128+
129+void 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+}
134+EXPORT_SYMBOL_GPL(ti_sci_inta_msi_domain_free_irqs);
135+
136+unsigned 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+}
146+EXPORT_SYMBOL_GPL(ti_sci_inta_msi_get_virq);
include/linux/dma-iommu.h+22−2
@@ -71,12 +71,25 @@ void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle, · 70 unmodified lines
7171 size_t size, enum dma_data_direction dir, unsigned long attrs);
7272
7373 /* The DMA API isn't _quite_ the whole story, though... */
74−void 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+ */
81+int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr);
82+
83+/* Update the MSI message if required. */
84+void iommu_dma_compose_msi_msg(struct msi_desc *desc,
85+ struct msi_msg *msg);
86+
7587 void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list);
7688
7789 #else
7890
7991 struct iommu_domain;
92+struct msi_desc;
8093 struct msi_msg;
8194 struct device;
8295
@@ -99,7 +112,14 @@ static inline void iommu_put_dma_cookie(struct iommu_domain *domain) · 16 unmodified lines
99112 {
100113 }
101114
102−static inline void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
115+static inline int iommu_dma_prepare_msi(struct msi_desc *desc,
116+ phys_addr_t msi_addr)
117+{
118+ return 0;
119+}
120+
121+static inline void iommu_dma_compose_msi_msg(struct msi_desc *desc,
122+ struct msi_msg *msg)
103123 {
104124 }
105125
include/linux/irq.h+2−0
@@ -625,6 +625,8 @@ extern int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on); · 624 unmodified lines
625625 extern int irq_chip_set_vcpu_affinity_parent(struct irq_data *data,
626626 void *vcpu_info);
627627 extern int irq_chip_set_type_parent(struct irq_data *data, unsigned int type);
628+extern int irq_chip_request_resources_parent(struct irq_data *data);
629+extern void irq_chip_release_resources_parent(struct irq_data *data);
628630 #endif
629631
630632 /* Handling of unhandled and spurious interrupts: */
include/linux/irqchip/arm-gic-v3.h+6−6
@@ -165,7 +165,7 @@ · 164 unmodified lines
165165 #define GICR_PROPBASER_nCnB GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, nCnB)
166166 #define GICR_PROPBASER_nC GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, nC)
167167 #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)
169169 #define GICR_PROPBASER_WaWt GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, WaWt)
170170 #define GICR_PROPBASER_WaWb GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, WaWb)
171171 #define GICR_PROPBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RaWaWt)
@@ -192,7 +192,7 @@ · 20 unmodified lines
192192 #define GICR_PENDBASER_nCnB GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, nCnB)
193193 #define GICR_PENDBASER_nC GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, nC)
194194 #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)
196196 #define GICR_PENDBASER_WaWt GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, WaWt)
197197 #define GICR_PENDBASER_WaWb GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, WaWb)
198198 #define GICR_PENDBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RaWaWt)
@@ -251,7 +251,7 @@ · 52 unmodified lines
251251 #define GICR_VPROPBASER_nCnB GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, nCnB)
252252 #define GICR_VPROPBASER_nC GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, nC)
253253 #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)
255255 #define GICR_VPROPBASER_WaWt GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, WaWt)
256256 #define GICR_VPROPBASER_WaWb GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, WaWb)
257257 #define GICR_VPROPBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWaWt)
@@ -277,7 +277,7 @@ · 19 unmodified lines
277277 #define GICR_VPENDBASER_nCnB GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, nCnB)
278278 #define GICR_VPENDBASER_nC GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, nC)
279279 #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)
281281 #define GICR_VPENDBASER_WaWt GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, WaWt)
282282 #define GICR_VPENDBASER_WaWb GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, WaWb)
283283 #define GICR_VPENDBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, RaWaWt)
@@ -351,7 +351,7 @@ · 67 unmodified lines
351351 #define GITS_CBASER_nCnB GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nCnB)
352352 #define GITS_CBASER_nC GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nC)
353353 #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)
355355 #define GITS_CBASER_WaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWt)
356356 #define GITS_CBASER_WaWb GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWb)
357357 #define GITS_CBASER_RaWaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWaWt)
@@ -377,7 +377,7 @@ · 19 unmodified lines
377377 #define GITS_BASER_nCnB GIC_BASER_CACHEABILITY(GITS_BASER, INNER, nCnB)
378378 #define GITS_BASER_nC GIC_BASER_CACHEABILITY(GITS_BASER, INNER, nC)
379379 #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)
381381 #define GITS_BASER_WaWt GIC_BASER_CACHEABILITY(GITS_BASER, INNER, WaWt)
382382 #define GITS_BASER_WaWb GIC_BASER_CACHEABILITY(GITS_BASER, INNER, WaWb)
383383 #define GITS_BASER_RaWaWt GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWaWt)
include/linux/irqdomain.h+1−0
@@ -82,6 +82,7 @@ enum irq_domain_bus_token { · 81 unmodified lines
8282 DOMAIN_BUS_NEXUS,
8383 DOMAIN_BUS_IPI,
8484 DOMAIN_BUS_FSL_MC_MSI,
85+ DOMAIN_BUS_TI_SCI_INTA_MSI,
8586 };
8687
8788 /**
include/linux/msi.h+36−0
@@ -47,6 +47,14 @@ struct fsl_mc_msi_desc { · 46 unmodified lines
4747 u16 msi_index;
4848 };
4949
50+/**
51+ * ti_sci_inta_msi_desc - TISCI based INTA specific msi descriptor data
52+ * @dev_index: TISCI device index
53+ */
54+struct ti_sci_inta_msi_desc {
55+ u16 dev_index;
56+};
57+
5058 /**
5159 * struct msi_desc - Descriptor structure for MSI based interrupts
5260 * @list: List head for management
@@ -68,6 +76,7 @@ struct fsl_mc_msi_desc { · 15 unmodified lines
6876 * @mask_base: [PCI MSI-X] Mask register base address
6977 * @platform: [platform] Platform device specific msi descriptor data
7078 * @fsl_mc: [fsl-mc] FSL MC device specific msi descriptor data
79+ * @inta: [INTA] TISCI based INTA specific msi descriptor data
7180 */
7281 struct msi_desc {
7382 /* Shared device/bus type independent data */
@@ -77,6 +86,9 @@ struct msi_desc { · 3 unmodified lines
7786 struct device *dev;
7887 struct msi_msg msg;
7988 struct irq_affinity_desc *affinity;
89+#ifdef CONFIG_IRQ_MSI_IOMMU
90+ const void *iommu_cookie;
91+#endif
8092
8193 union {
8294 /* PCI MSI/X specific data */
@@ -106,6 +118,7 @@ struct msi_desc { · 23 unmodified lines
106118 */
107119 struct platform_msi_desc platform;
108120 struct fsl_mc_msi_desc fsl_mc;
121+ struct ti_sci_inta_msi_desc inta;
109122 };
110123 };
111124
@@ -119,6 +132,29 @@ struct msi_desc { · 7 unmodified lines
119132 #define for_each_msi_entry_safe(desc, tmp, dev) \
120133 list_for_each_entry_safe((desc), (tmp), dev_to_msi_list((dev)), list)
121134
135+#ifdef CONFIG_IRQ_MSI_IOMMU
136+static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
137+{
138+ return desc->iommu_cookie;
139+}
140+
141+static 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
147+static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
148+{
149+ return NULL;
150+}
151+
152+static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc,
153+ const void *iommu_cookie)
154+{
155+}
156+#endif
157+
122158 #ifdef CONFIG_PCI_MSI
123159 #define first_pci_msi_entry(pdev) first_msi_entry(&(pdev)->dev)
124160 #define for_each_pci_msi_entry(desc, pdev) \
include/linux/soc/ti/ti_sci_inta_msi.h+23−0
@@ -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+
15+struct 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);
19+int ti_sci_inta_msi_domain_alloc_irqs(struct device *dev,
20+ struct ti_sci_resource *res);
21+unsigned int ti_sci_inta_msi_get_virq(struct device *dev, u32 index);
22+void ti_sci_inta_msi_domain_free_irqs(struct device *dev);
23+#endif /* __INCLUDE_LINUX_IRQCHIP_TI_SCI_INTA_H */
include/linux/soc/ti/ti_sci_protocol.h+124−0
@@ -192,15 +192,68 @@ struct ti_sci_clk_ops { · 191 unmodified lines
192192 u64 *current_freq);
193193 };
194194
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+ */
212+struct 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+ */
231+struct 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+
195244 /**
196245 * struct ti_sci_ops - Function support for TI SCI
197246 * @dev_ops: Device specific operations
198247 * @clk_ops: Clock specific operations
248+ * @rm_core_ops: Resource management core operations.
249+ * @rm_irq_ops: IRQ management specific operations
199250 */
200251 struct ti_sci_ops {
201252 struct ti_sci_core_ops core_ops;
202253 struct ti_sci_dev_ops dev_ops;
203254 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;
204257 };
205258
206259 /**
@@ -213,10 +266,47 @@ struct ti_sci_handle { · 6 unmodified lines
213266 struct ti_sci_ops ops;
214267 };
215268
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+ */
277+struct 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+ */
290+struct ti_sci_resource {
291+ u16 sets;
292+ raw_spinlock_t lock;
293+ struct ti_sci_resource_desc *desc;
294+};
295+
216296 #if IS_ENABLED(CONFIG_TI_SCI_PROTOCOL)
217297 const struct ti_sci_handle *ti_sci_get_handle(struct device *dev);
218298 int ti_sci_put_handle(const struct ti_sci_handle *handle);
219299 const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev);
300+const struct ti_sci_handle *ti_sci_get_by_phandle(struct device_node *np,
301+ const char *property);
302+const struct ti_sci_handle *devm_ti_sci_get_by_phandle(struct device *dev,
303+ const char *property);
304+u16 ti_sci_get_free_resource(struct ti_sci_resource *res);
305+void ti_sci_release_resource(struct ti_sci_resource *res, u16 id);
306+u32 ti_sci_get_num_resources(struct ti_sci_resource *res);
307+struct ti_sci_resource *
308+devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle,
309+ struct device *dev, u32 dev_id, char *of_prop);
220310
221311 #else /* CONFIG_TI_SCI_PROTOCOL */
222312
@@ -236,6 +326,40 @@ const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev) · 13 unmodified lines
236326 return ERR_PTR(-EINVAL);
237327 }
238328
329+static inline
330+const 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+
336+static inline
337+const 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+
343+static inline u16 ti_sci_get_free_resource(struct ti_sci_resource *res)
344+{
345+ return TI_SCI_RESOURCE_NULL;
346+}
347+
348+static inline void ti_sci_release_resource(struct ti_sci_resource *res, u16 id)
349+{
350+}
351+
352+static inline u32 ti_sci_get_num_resources(struct ti_sci_resource *res)
353+{
354+ return 0;
355+}
356+
357+static inline struct ti_sci_resource *
358+devm_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+}
239363 #endif /* CONFIG_TI_SCI_PROTOCOL */
240364
241365 #endif /* __TISCI_PROTOCOL_H */
kernel/irq/Kconfig+3−0
@@ -91,6 +91,9 @@ config GENERIC_MSI_IRQ_DOMAIN · 90 unmodified lines
9191 select IRQ_DOMAIN_HIERARCHY
9292 select GENERIC_MSI_IRQ
9393
94+config IRQ_MSI_IOMMU
95+ bool
96+
9497 config HANDLE_DOMAIN_IRQ
9598 bool
9699
kernel/irq/chip.c+27−0
@@ -1459,6 +1459,33 @@ int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on) · 1458 unmodified lines
14591459 return -ENOSYS;
14601460 }
14611461 EXPORT_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+ */
1467+int 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+}
1476+EXPORT_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+ */
1482+void 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+}
1488+EXPORT_SYMBOL_GPL(irq_chip_release_resources_parent);
14621489 #endif
14631490
14641491 /**
kernel/irq/irqdomain.c+1−1
@@ -1297,7 +1297,7 @@ int irq_domain_alloc_irqs_hierarchy(struct irq_domain *domain, · 1296 unmodified lines
12971297 /**
12981298 * __irq_domain_alloc_irqs - Allocate IRQs from domain
12991299 * @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
13011301 * @nr_irqs: number of IRQs to allocate
13021302 * @node: NUMA node id for memory allocation
13031303 * @arg: domain specific argument