Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

firmware: ti_sci: Add support for IRQ management

TISCI abstracts the handling of IRQ routes where interrupt sources
are not directly connected to host interrupt controller. Add support
for the set of TISCI commands for requesting and releasing IRQs.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
Acked-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

authored by

Lokesh Vutla and committed by
Marc Zyngier
997b001f 9c19fb68

+331
+245
drivers/firmware/ti_sci.c
··· 1765 1765 range_start, range_num); 1766 1766 } 1767 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 + 1768 2007 /* 1769 2008 * ti_sci_setup_ops() - Setup the operations structures 1770 2009 * @info: pointer to TISCI pointer ··· 2015 1776 struct ti_sci_dev_ops *dops = &ops->dev_ops; 2016 1777 struct ti_sci_clk_ops *cops = &ops->clk_ops; 2017 1778 struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops; 1779 + struct ti_sci_rm_irq_ops *iops = &ops->rm_irq_ops; 2018 1780 2019 1781 core_ops->reboot_device = ti_sci_cmd_core_reboot; 2020 1782 ··· 2050 1810 rm_core_ops->get_range = ti_sci_cmd_get_resource_range; 2051 1811 rm_core_ops->get_range_from_shost = 2052 1812 ti_sci_cmd_get_resource_range_from_shost; 1813 + 1814 + iops->set_irq = ti_sci_cmd_set_irq; 1815 + iops->set_event_map = ti_sci_cmd_set_event_map; 1816 + iops->free_irq = ti_sci_cmd_free_irq; 1817 + iops->free_event_map = ti_sci_cmd_free_event_map; 2053 1818 } 2054 1819 2055 1820 /**
+60
drivers/firmware/ti_sci.h
··· 38 38 /* Resource Management Requests */ 39 39 #define TI_SCI_MSG_GET_RESOURCE_RANGE 0x1500 40 40 41 + /* IRQ requests */ 42 + #define TI_SCI_MSG_SET_IRQ 0x1000 43 + #define TI_SCI_MSG_FREE_IRQ 0x1001 44 + 41 45 /** 42 46 * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses 43 47 * @type: Type of messages: One of TI_SCI_MSG* values ··· 505 501 struct ti_sci_msg_hdr hdr; 506 502 u16 range_start; 507 503 u16 range_num; 504 + } __packed; 505 + 506 + /** 507 + * struct ti_sci_msg_req_manage_irq - Request to configure/release the route 508 + * between the dev and the host. 509 + * @hdr: Generic Header 510 + * @valid_params: Bit fields defining the validity of interrupt source 511 + * parameters. If a bit is not set, then corresponding 512 + * field is not valid and will not be used for route set. 513 + * Bit field definitions: 514 + * 0 - Valid bit for @dst_id 515 + * 1 - Valid bit for @dst_host_irq 516 + * 2 - Valid bit for @ia_id 517 + * 3 - Valid bit for @vint 518 + * 4 - Valid bit for @global_event 519 + * 5 - Valid bit for @vint_status_bit_index 520 + * 31 - Valid bit for @secondary_host 521 + * @src_id: IRQ source peripheral ID. 522 + * @src_index: IRQ source index within the peripheral 523 + * @dst_id: IRQ Destination ID. Based on the architecture it can be 524 + * IRQ controller or host processor ID. 525 + * @dst_host_irq: IRQ number of the destination host IRQ controller 526 + * @ia_id: Device ID of the interrupt aggregator in which the 527 + * vint resides. 528 + * @vint: Virtual interrupt number if the interrupt route 529 + * is through an interrupt aggregator. 530 + * @global_event: Global event that is to be mapped to interrupt 531 + * aggregator virtual interrupt status bit. 532 + * @vint_status_bit: Virtual interrupt status bit if the interrupt route 533 + * utilizes an interrupt aggregator status bit. 534 + * @secondary_host: Host ID of the IRQ destination computing entity. This is 535 + * required only when destination host id is different 536 + * from ti sci interface host id. 537 + * 538 + * Request type is TI_SCI_MSG_SET/RELEASE_IRQ. 539 + * Response is generic ACK / NACK message. 540 + */ 541 + struct ti_sci_msg_req_manage_irq { 542 + struct ti_sci_msg_hdr hdr; 543 + #define MSG_FLAG_DST_ID_VALID TI_SCI_MSG_FLAG(0) 544 + #define MSG_FLAG_DST_HOST_IRQ_VALID TI_SCI_MSG_FLAG(1) 545 + #define MSG_FLAG_IA_ID_VALID TI_SCI_MSG_FLAG(2) 546 + #define MSG_FLAG_VINT_VALID TI_SCI_MSG_FLAG(3) 547 + #define MSG_FLAG_GLB_EVNT_VALID TI_SCI_MSG_FLAG(4) 548 + #define MSG_FLAG_VINT_STS_BIT_VALID TI_SCI_MSG_FLAG(5) 549 + #define MSG_FLAG_SHOST_VALID TI_SCI_MSG_FLAG(31) 550 + u32 valid_params; 551 + u16 src_id; 552 + u16 src_index; 553 + u16 dst_id; 554 + u16 dst_host_irq; 555 + u16 ia_id; 556 + u16 vint; 557 + u16 global_event; 558 + u8 vint_status_bit; 559 + u8 secondary_host; 508 560 } __packed; 509 561 510 562 #endif /* __TI_SCI_H */
+26
include/linux/soc/ti/ti_sci_protocol.h
··· 218 218 }; 219 219 220 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 + 244 + /** 221 245 * struct ti_sci_ops - Function support for TI SCI 222 246 * @dev_ops: Device specific operations 223 247 * @clk_ops: Clock specific operations 224 248 * @rm_core_ops: Resource management core operations. 249 + * @rm_irq_ops: IRQ management specific operations 225 250 */ 226 251 struct ti_sci_ops { 227 252 struct ti_sci_core_ops core_ops; 228 253 struct ti_sci_dev_ops dev_ops; 229 254 struct ti_sci_clk_ops clk_ops; 230 255 struct ti_sci_rm_core_ops rm_core_ops; 256 + struct ti_sci_rm_irq_ops rm_irq_ops; 231 257 }; 232 258 233 259 /**