@@ -508,33 +508,125 @@ int tegra30_mc_probe(struct tegra_mc *mc)
508508 return 0 ;
509509}
510510
511- static irqreturn_t tegra30_mc_handle_irq (int irq , void * data )
511+ const struct tegra_mc_ops tegra30_mc_ops = {
512+ .probe = tegra30_mc_probe ,
513+ .handle_irq = tegra30_mc_handle_irq ,
514+ };
515+ #endif
516+
517+ static int mc_global_intstatus_to_channel (const struct tegra_mc * mc , u32 status ,
518+ unsigned int * mc_channel )
519+ {
520+ if ((status & mc -> soc -> ch_intmask ) == 0 )
521+ return - EINVAL ;
522+
523+ * mc_channel = __ffs ((status & mc -> soc -> ch_intmask ) >>
524+ mc -> soc -> global_intstatus_channel_shift );
525+
526+ return 0 ;
527+ }
528+
529+ static u32 mc_channel_to_global_intstatus (const struct tegra_mc * mc ,
530+ unsigned int channel )
531+ {
532+ return BIT (channel ) << mc -> soc -> global_intstatus_channel_shift ;
533+ }
534+
535+ irqreturn_t tegra30_mc_handle_irq (int irq , void * data )
512536{
513537 struct tegra_mc * mc = data ;
538+ unsigned int bit , channel ;
514539 unsigned long status ;
515- unsigned int bit ;
516540
517- /* mask all interrupts to avoid flooding */
518- status = mc_readl (mc , MC_INTSTATUS ) & mc -> soc -> intmask ;
541+ if (mc -> soc -> num_channels ) {
542+ u32 global_status ;
543+ int err ;
544+
545+ global_status = mc_ch_readl (mc , MC_BROADCAST_CHANNEL , MC_GLOBAL_INTSTATUS );
546+ err = mc_global_intstatus_to_channel (mc , global_status , & channel );
547+ if (err < 0 ) {
548+ dev_err_ratelimited (mc -> dev , "unknown interrupt channel 0x%08x\n" ,
549+ global_status );
550+ return IRQ_NONE ;
551+ }
552+
553+ /* mask all interrupts to avoid flooding */
554+ status = mc_ch_readl (mc , channel , MC_INTSTATUS ) & mc -> soc -> intmask ;
555+ } else {
556+ status = mc_readl (mc , MC_INTSTATUS ) & mc -> soc -> intmask ;
557+ }
558+
519559 if (!status )
520560 return IRQ_NONE ;
521561
522562 for_each_set_bit (bit , & status , 32 ) {
523563 const char * error = tegra_mc_status_names [bit ] ?: "unknown" ;
524564 const char * client = "unknown" , * desc ;
525565 const char * direction , * secure ;
566+ u32 status_reg , addr_reg ;
567+ u32 intmask = BIT (bit );
526568 phys_addr_t addr = 0 ;
569+ #ifdef CONFIG_PHYS_ADDR_T_64BIT
570+ u32 addr_hi_reg = 0 ;
571+ #endif
527572 unsigned int i ;
528573 char perm [7 ];
529574 u8 id , type ;
530575 u32 value ;
531576
532- value = mc_readl (mc , MC_ERR_STATUS );
577+ switch (intmask ) {
578+ case MC_INT_DECERR_VPR :
579+ status_reg = MC_ERR_VPR_STATUS ;
580+ addr_reg = MC_ERR_VPR_ADR ;
581+ break ;
582+
583+ case MC_INT_SECERR_SEC :
584+ status_reg = MC_ERR_SEC_STATUS ;
585+ addr_reg = MC_ERR_SEC_ADR ;
586+ break ;
587+
588+ case MC_INT_DECERR_MTS :
589+ status_reg = MC_ERR_MTS_STATUS ;
590+ addr_reg = MC_ERR_MTS_ADR ;
591+ break ;
592+
593+ case MC_INT_DECERR_GENERALIZED_CARVEOUT :
594+ status_reg = MC_ERR_GENERALIZED_CARVEOUT_STATUS ;
595+ addr_reg = MC_ERR_GENERALIZED_CARVEOUT_ADR ;
596+ break ;
597+
598+ case MC_INT_DECERR_ROUTE_SANITY :
599+ status_reg = MC_ERR_ROUTE_SANITY_STATUS ;
600+ addr_reg = MC_ERR_ROUTE_SANITY_ADR ;
601+ break ;
602+
603+ default :
604+ status_reg = MC_ERR_STATUS ;
605+ addr_reg = MC_ERR_ADR ;
606+
607+ #ifdef CONFIG_PHYS_ADDR_T_64BIT
608+ if (mc -> soc -> has_addr_hi_reg )
609+ addr_hi_reg = MC_ERR_ADR_HI ;
610+ #endif
611+ break ;
612+ }
613+
614+ if (mc -> soc -> num_channels )
615+ value = mc_ch_readl (mc , channel , status_reg );
616+ else
617+ value = mc_readl (mc , status_reg );
533618
534619#ifdef CONFIG_PHYS_ADDR_T_64BIT
535620 if (mc -> soc -> num_address_bits > 32 ) {
536- addr = ((value >> MC_ERR_STATUS_ADR_HI_SHIFT ) &
537- MC_ERR_STATUS_ADR_HI_MASK );
621+ if (addr_hi_reg ) {
622+ if (mc -> soc -> num_channels )
623+ addr = mc_ch_readl (mc , channel , addr_hi_reg );
624+ else
625+ addr = mc_readl (mc , addr_hi_reg );
626+ } else {
627+ addr = ((value >> MC_ERR_STATUS_ADR_HI_SHIFT ) &
628+ MC_ERR_STATUS_ADR_HI_MASK );
629+ }
538630 addr <<= 32 ;
539631 }
540632#endif
@@ -591,7 +683,10 @@ static irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
591683 break ;
592684 }
593685
594- value = mc_readl (mc , MC_ERR_ADR );
686+ if (mc -> soc -> num_channels )
687+ value = mc_ch_readl (mc , channel , addr_reg );
688+ else
689+ value = mc_readl (mc , addr_reg );
595690 addr |= value ;
596691
597692 dev_err_ratelimited (mc -> dev , "%s: %s%s @%pa: %s (%s%s)\n" ,
@@ -600,17 +695,18 @@ static irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
600695 }
601696
602697 /* clear interrupts */
603- mc_writel (mc , status , MC_INTSTATUS );
698+ if (mc -> soc -> num_channels ) {
699+ mc_ch_writel (mc , channel , status , MC_INTSTATUS );
700+ mc_ch_writel (mc , MC_BROADCAST_CHANNEL ,
701+ mc_channel_to_global_intstatus (mc , channel ),
702+ MC_GLOBAL_INTSTATUS );
703+ } else {
704+ mc_writel (mc , status , MC_INTSTATUS );
705+ }
604706
605707 return IRQ_HANDLED ;
606708}
607709
608- const struct tegra_mc_ops tegra30_mc_ops = {
609- .probe = tegra30_mc_probe ,
610- .handle_irq = tegra30_mc_handle_irq ,
611- };
612- #endif
613-
614710const char * const tegra_mc_status_names [32 ] = {
615711 [ 1 ] = "External interrupt" ,
616712 [ 6 ] = "EMEM address decode error" ,
@@ -622,6 +718,8 @@ const char *const tegra_mc_status_names[32] = {
622718 [12 ] = "VPR violation" ,
623719 [13 ] = "Secure carveout violation" ,
624720 [16 ] = "MTS carveout violation" ,
721+ [17 ] = "Generalized carveout violation" ,
722+ [20 ] = "Route Sanity error" ,
625723};
626724
627725const char * const tegra_mc_error_names [8 ] = {
@@ -764,7 +862,11 @@ static int tegra_mc_probe(struct platform_device *pdev)
764862
765863 WARN (!mc -> soc -> client_id_mask , "missing client ID mask for this SoC\n" );
766864
767- mc_writel (mc , mc -> soc -> intmask , MC_INTMASK );
865+ if (mc -> soc -> num_channels )
866+ mc_ch_writel (mc , MC_BROADCAST_CHANNEL , mc -> soc -> intmask ,
867+ MC_INTMASK );
868+ else
869+ mc_writel (mc , mc -> soc -> intmask , MC_INTMASK );
768870
769871 err = devm_request_irq (& pdev -> dev , mc -> irq , mc -> soc -> ops -> handle_irq , 0 ,
770872 dev_name (& pdev -> dev ), mc );
0 commit comments