@@ -44,6 +44,9 @@ static const struct of_device_id tegra_mc_of_match[] = {
4444#endif
4545#ifdef CONFIG_ARCH_TEGRA_194_SOC
4646 { .compatible = "nvidia,tegra194-mc" , .data = & tegra194_mc_soc },
47+ #endif
48+ #ifdef CONFIG_ARCH_TEGRA_234_SOC
49+ { .compatible = "nvidia,tegra234-mc" , .data = & tegra234_mc_soc },
4750#endif
4851 { /* sentinel */ }
4952};
@@ -505,33 +508,125 @@ int tegra30_mc_probe(struct tegra_mc *mc)
505508 return 0 ;
506509}
507510
508- 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 )
509536{
510537 struct tegra_mc * mc = data ;
538+ unsigned int bit , channel ;
511539 unsigned long status ;
512- unsigned int bit ;
513540
514- /* mask all interrupts to avoid flooding */
515- 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+
516559 if (!status )
517560 return IRQ_NONE ;
518561
519562 for_each_set_bit (bit , & status , 32 ) {
520563 const char * error = tegra_mc_status_names [bit ] ?: "unknown" ;
521564 const char * client = "unknown" , * desc ;
522565 const char * direction , * secure ;
566+ u32 status_reg , addr_reg ;
567+ u32 intmask = BIT (bit );
523568 phys_addr_t addr = 0 ;
569+ #ifdef CONFIG_PHYS_ADDR_T_64BIT
570+ u32 addr_hi_reg = 0 ;
571+ #endif
524572 unsigned int i ;
525573 char perm [7 ];
526574 u8 id , type ;
527575 u32 value ;
528576
529- 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 );
530618
531619#ifdef CONFIG_PHYS_ADDR_T_64BIT
532620 if (mc -> soc -> num_address_bits > 32 ) {
533- addr = ((value >> MC_ERR_STATUS_ADR_HI_SHIFT ) &
534- 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+ }
535630 addr <<= 32 ;
536631 }
537632#endif
@@ -588,7 +683,10 @@ static irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
588683 break ;
589684 }
590685
591- 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 );
592690 addr |= value ;
593691
594692 dev_err_ratelimited (mc -> dev , "%s: %s%s @%pa: %s (%s%s)\n" ,
@@ -597,17 +695,18 @@ static irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
597695 }
598696
599697 /* clear interrupts */
600- 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+ }
601706
602707 return IRQ_HANDLED ;
603708}
604709
605- const struct tegra_mc_ops tegra30_mc_ops = {
606- .probe = tegra30_mc_probe ,
607- .handle_irq = tegra30_mc_handle_irq ,
608- };
609- #endif
610-
611710const char * const tegra_mc_status_names [32 ] = {
612711 [ 1 ] = "External interrupt" ,
613712 [ 6 ] = "EMEM address decode error" ,
@@ -619,6 +718,8 @@ const char *const tegra_mc_status_names[32] = {
619718 [12 ] = "VPR violation" ,
620719 [13 ] = "Secure carveout violation" ,
621720 [16 ] = "MTS carveout violation" ,
721+ [17 ] = "Generalized carveout violation" ,
722+ [20 ] = "Route Sanity error" ,
622723};
623724
624725const char * const tegra_mc_error_names [8 ] = {
@@ -759,7 +860,11 @@ static int tegra_mc_probe(struct platform_device *pdev)
759860
760861 WARN (!mc -> soc -> client_id_mask , "missing client ID mask for this SoC\n" );
761862
762- mc_writel (mc , mc -> soc -> intmask , MC_INTMASK );
863+ if (mc -> soc -> num_channels )
864+ mc_ch_writel (mc , MC_BROADCAST_CHANNEL , mc -> soc -> intmask ,
865+ MC_INTMASK );
866+ else
867+ mc_writel (mc , mc -> soc -> intmask , MC_INTMASK );
763868
764869 err = devm_request_irq (& pdev -> dev , mc -> irq , mc -> soc -> ops -> handle_irq , 0 ,
765870 dev_name (& pdev -> dev ), mc );
0 commit comments