This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[FAQ] TDA4VM: Routing interrupts via the interrupt router

Part Number: TDA4VM

How to route an interrupt from a peripheral via the interrupt router to the core?

  • For certain standard peripherals (like GPIO etc) all interrupts cannot be directly corrected to host interrupt controller. For this purpose, Interrupt Router(INTR) is introduced in the SoC. INTR just does a classic interrupt redirection.

    The inputs of the Interrupt Routers are connected to different peripherals whose interrupts are not connected directly to the CORE, the outputs of Interrupt routers are connected to the CORE's interrupts.

    You can think about these connections as hard wired connections. The configurability lies within the INTR.

    R5FSS0_INTROUTER0 Interrupt Router Input Sources: http://software-dl.ti.com/tisci/esd/latest/5_soc_doc/j721e/interrupt_cfg.html#r5fss0-introuter0-interrupt-router-input-sources

    R5FSS0_INTROUTER0 Interrupt Router Output destinations - http://software-dl.ti.com/tisci/esd/latest/5_soc_doc/j721e/interrupt_cfg.html#r5fss0-introuter0-interrupt-router-output-destinations

    The inputs can be routed to any of the output and hence providing a path for the peripheral to interrupt the CORE. This mapping of a particular input to a particular output is done using SCIClient API like Sciclient_rmIrqSet like below:

    void CanApp_InterruptConfig(void)
    {
        uint32 idx;
        OsalRegisterIntrParams_t    intrPrms;
        OsalInterruptRetCode_e      osalRetVal;
        HwiP_Handle hwiHandle;
        struct tisci_msg_rm_irq_set_req     rmIrqReq;
        struct tisci_msg_rm_irq_set_resp    rmIrqResp;
        Int32 retVal;
        const Can_ConfigType *Can_ConfigPtr;
    
    #if (STD_ON == CAN_VARIANT_PRE_COMPILE)
        Can_ConfigPtr = &CAN_INIT_CONFIG_PC;
    #else
        Can_ConfigPtr = &CanConfigSet;
    #endif
    
        for (idx = 0U; idx < Can_ConfigPtr->CanMaxControllerCount; idx++)
        {
            /* If the CAN instance is not in MCU domain, the interrupt router will
                have to be configured */
            /* Set the destination interrupt */
            if ((CAN_CONTROLLER_INSTANCE_MCU_MCAN0 !=
                CanConfigSet_CanController_List_PC[idx]->CanControllerInst) &&
               (CAN_CONTROLLER_INSTANCE_MCU_MCAN1 !=
                CanConfigSet_CanController_List_PC[idx]->CanControllerInst))
            {
                CanApp_IntNumbers[idx]          = CanApp_RoutIntNumbers[idx];
                rmIrqReq.valid_params           = TISCI_MSG_VALUE_RM_DST_ID_VALID;
                rmIrqReq.valid_params          |= TISCI_MSG_VALUE_RM_DST_HOST_IRQ_VALID;
                rmIrqReq.src_id                 = CanApp_InstanceSrcId[idx];
                rmIrqReq.global_event           = 0U;
                /* Src Index 0 - mcanss_ext_ts_rollover_lvl_int,
                   Src Index 1 - mcanss_mcan_lvl_int Line 0,
                   Src Index 2 - mcanss_mcan_lvl_int Line 1 */
                rmIrqReq.src_index              = 1U;
                rmIrqReq.dst_id                 = TISCI_DEV_MCU_R5FSS0_CORE0;
                rmIrqReq.dst_host_irq           = CanApp_RoutIntNumbers[idx];
                rmIrqReq.ia_id                  = 0U;
                rmIrqReq.vint                   = 0U;
                rmIrqReq.vint_status_bit_index  = 0U;
                rmIrqReq.secondary_host         = TISCI_MSG_VALUE_RM_UNUSED_SECONDARY_HOST;
                retVal = Sciclient_rmIrqSet(
                             &rmIrqReq, &rmIrqResp, APP_SCICLIENT_TIMEOUT);
                if(CSL_PASS != retVal)
                {
                    AppUtils_Printf(MSG_NORMAL,
                    "CAN_APP: Error in SciClient Interrupt Params Configuration!!!\n");
                }
            }
    
            Osal_RegisterInterrupt_initParams(&intrPrms);
            intrPrms.corepacConfig.arg          = (uintptr_t)CanApp_Isr[idx];
            intrPrms.corepacConfig.isrRoutine   = &CanApp_CanXIsr;
            intrPrms.corepacConfig.priority     = 1U;
            intrPrms.corepacConfig.corepacEventNum = 0U; /* NOT USED ? */
            intrPrms.corepacConfig.intVecNum        = CanApp_IntNumbers[idx];
    
            osalRetVal = Osal_RegisterInterrupt(&intrPrms, &hwiHandle);
            if(OSAL_INT_SUCCESS != osalRetVal)
            {
                AppUtils_Printf(MSG_NORMAL,
                                "CAN_APP: Error %d !!!\n");
                break;
            }
        }
    
        return;
    }

    There is a relevant query related to this at https://e2e.ti.com/support/processors/f/791/t/910443

    Explanation of high level interrupt architecture of k3 family based SoCs(Including tda4) - https://lwn.net/Articles/775615/

    Interrupt aggregator described in depth: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.txt

    Interrupt router described in depth: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/interrupt-controller/ti,sci-intr.txt

    Regards,
    Karan