7
7
*/
8
8
9
9
#include <linux/bitops.h>
10
+ #include <linux/debugfs.h>
10
11
#include <linux/err.h>
11
12
#include <linux/iommu.h>
12
13
#include <linux/kernel.h>
@@ -31,6 +32,8 @@ struct tegra_smmu {
31
32
struct mutex lock ;
32
33
33
34
struct list_head list ;
35
+
36
+ struct dentry * debugfs ;
34
37
};
35
38
36
39
struct tegra_smmu_as {
@@ -673,6 +676,103 @@ static void tegra_smmu_ahb_enable(void)
673
676
}
674
677
}
675
678
679
+ static int tegra_smmu_swgroups_show (struct seq_file * s , void * data )
680
+ {
681
+ struct tegra_smmu * smmu = s -> private ;
682
+ unsigned int i ;
683
+ u32 value ;
684
+
685
+ seq_printf (s , "swgroup enabled ASID\n" );
686
+ seq_printf (s , "------------------------\n" );
687
+
688
+ for (i = 0 ; i < smmu -> soc -> num_swgroups ; i ++ ) {
689
+ const struct tegra_smmu_swgroup * group = & smmu -> soc -> swgroups [i ];
690
+ const char * status ;
691
+ unsigned int asid ;
692
+
693
+ value = smmu_readl (smmu , group -> reg );
694
+
695
+ if (value & SMMU_ASID_ENABLE )
696
+ status = "yes" ;
697
+ else
698
+ status = "no" ;
699
+
700
+ asid = value & SMMU_ASID_MASK ;
701
+
702
+ seq_printf (s , "%-9s %-7s %#04x\n" , group -> name , status ,
703
+ asid );
704
+ }
705
+
706
+ return 0 ;
707
+ }
708
+
709
+ static int tegra_smmu_swgroups_open (struct inode * inode , struct file * file )
710
+ {
711
+ return single_open (file , tegra_smmu_swgroups_show , inode -> i_private );
712
+ }
713
+
714
+ static const struct file_operations tegra_smmu_swgroups_fops = {
715
+ .open = tegra_smmu_swgroups_open ,
716
+ .read = seq_read ,
717
+ .llseek = seq_lseek ,
718
+ .release = single_release ,
719
+ };
720
+
721
+ static int tegra_smmu_clients_show (struct seq_file * s , void * data )
722
+ {
723
+ struct tegra_smmu * smmu = s -> private ;
724
+ unsigned int i ;
725
+ u32 value ;
726
+
727
+ seq_printf (s , "client enabled\n" );
728
+ seq_printf (s , "--------------------\n" );
729
+
730
+ for (i = 0 ; i < smmu -> soc -> num_clients ; i ++ ) {
731
+ const struct tegra_mc_client * client = & smmu -> soc -> clients [i ];
732
+ const char * status ;
733
+
734
+ value = smmu_readl (smmu , client -> smmu .reg );
735
+
736
+ if (value & BIT (client -> smmu .bit ))
737
+ status = "yes" ;
738
+ else
739
+ status = "no" ;
740
+
741
+ seq_printf (s , "%-12s %s\n" , client -> name , status );
742
+ }
743
+
744
+ return 0 ;
745
+ }
746
+
747
+ static int tegra_smmu_clients_open (struct inode * inode , struct file * file )
748
+ {
749
+ return single_open (file , tegra_smmu_clients_show , inode -> i_private );
750
+ }
751
+
752
+ static const struct file_operations tegra_smmu_clients_fops = {
753
+ .open = tegra_smmu_clients_open ,
754
+ .read = seq_read ,
755
+ .llseek = seq_lseek ,
756
+ .release = single_release ,
757
+ };
758
+
759
+ static void tegra_smmu_debugfs_init (struct tegra_smmu * smmu )
760
+ {
761
+ smmu -> debugfs = debugfs_create_dir ("smmu" , NULL );
762
+ if (!smmu -> debugfs )
763
+ return ;
764
+
765
+ debugfs_create_file ("swgroups" , S_IRUGO , smmu -> debugfs , smmu ,
766
+ & tegra_smmu_swgroups_fops );
767
+ debugfs_create_file ("clients" , S_IRUGO , smmu -> debugfs , smmu ,
768
+ & tegra_smmu_clients_fops );
769
+ }
770
+
771
+ static void tegra_smmu_debugfs_exit (struct tegra_smmu * smmu )
772
+ {
773
+ debugfs_remove_recursive (smmu -> debugfs );
774
+ }
775
+
676
776
struct tegra_smmu * tegra_smmu_probe (struct device * dev ,
677
777
const struct tegra_smmu_soc * soc ,
678
778
struct tegra_mc * mc )
@@ -743,5 +843,14 @@ struct tegra_smmu *tegra_smmu_probe(struct device *dev,
743
843
if (err < 0 )
744
844
return ERR_PTR (err );
745
845
846
+ if (IS_ENABLED (CONFIG_DEBUG_FS ))
847
+ tegra_smmu_debugfs_init (smmu );
848
+
746
849
return smmu ;
747
850
}
851
+
852
+ void tegra_smmu_remove (struct tegra_smmu * smmu )
853
+ {
854
+ if (IS_ENABLED (CONFIG_DEBUG_FS ))
855
+ tegra_smmu_debugfs_exit (smmu );
856
+ }
0 commit comments