@@ -51,14 +51,15 @@ struct qcom_iommu_dev {
5151 struct clk_bulk_data clks [CLK_NUM ];
5252 void __iomem * local_base ;
5353 u32 sec_id ;
54- u8 num_ctxs ;
55- struct qcom_iommu_ctx * ctxs []; /* indexed by asid-1 */
54+ u8 max_asid ;
55+ struct qcom_iommu_ctx * ctxs []; /* indexed by asid */
5656};
5757
5858struct qcom_iommu_ctx {
5959 struct device * dev ;
6060 void __iomem * base ;
6161 bool secure_init ;
62+ bool secured_ctx ;
6263 u8 asid ; /* asid and ctx bank # are 1:1 */
6364 struct iommu_domain * domain ;
6465};
@@ -94,7 +95,7 @@ static struct qcom_iommu_ctx * to_ctx(struct qcom_iommu_domain *d, unsigned asid
9495 struct qcom_iommu_dev * qcom_iommu = d -> iommu ;
9596 if (!qcom_iommu )
9697 return NULL ;
97- return qcom_iommu -> ctxs [asid - 1 ];
98+ return qcom_iommu -> ctxs [asid ];
9899}
99100
100101static inline void
@@ -273,6 +274,19 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain,
273274 ctx -> secure_init = true;
274275 }
275276
277+ /* Secured QSMMU-500/QSMMU-v2 contexts cannot be programmed */
278+ if (ctx -> secured_ctx ) {
279+ ctx -> domain = domain ;
280+ continue ;
281+ }
282+
283+ /* Disable context bank before programming */
284+ iommu_writel (ctx , ARM_SMMU_CB_SCTLR , 0 );
285+
286+ /* Clear context bank fault address fault status registers */
287+ iommu_writel (ctx , ARM_SMMU_CB_FAR , 0 );
288+ iommu_writel (ctx , ARM_SMMU_CB_FSR , ARM_SMMU_FSR_FAULT );
289+
276290 /* TTBRs */
277291 iommu_writeq (ctx , ARM_SMMU_CB_TTBR0 ,
278292 pgtbl_cfg .arm_lpae_s1_cfg .ttbr |
@@ -527,11 +541,10 @@ static int qcom_iommu_of_xlate(struct device *dev, struct of_phandle_args *args)
527541 qcom_iommu = platform_get_drvdata (iommu_pdev );
528542
529543 /* make sure the asid specified in dt is valid, so we don't have
530- * to sanity check this elsewhere, since 'asid - 1' is used to
531- * index into qcom_iommu->ctxs:
544+ * to sanity check this elsewhere:
532545 */
533- if (WARN_ON (asid < 1 ) ||
534- WARN_ON (asid > qcom_iommu -> num_ctxs )) {
546+ if (WARN_ON (asid > qcom_iommu -> max_asid ) ||
547+ WARN_ON (qcom_iommu -> ctxs [ asid ] == NULL )) {
535548 put_device (& iommu_pdev -> dev );
536549 return - EINVAL ;
537550 }
@@ -617,23 +630,33 @@ static int qcom_iommu_sec_ptbl_init(struct device *dev)
617630
618631static int get_asid (const struct device_node * np )
619632{
620- u32 reg ;
633+ u32 reg , val ;
634+ int asid ;
621635
622636 /* read the "reg" property directly to get the relative address
623637 * of the context bank, and calculate the asid from that:
624638 */
625639 if (of_property_read_u32_index (np , "reg" , 0 , & reg ))
626640 return - ENODEV ;
627641
628- return reg / 0x1000 ; /* context banks are 0x1000 apart */
642+ /*
643+ * Context banks are 0x1000 apart but, in some cases, the ASID
644+ * number doesn't match to this logic and needs to be passed
645+ * from the DT configuration explicitly.
646+ */
647+ if (!of_property_read_u32 (np , "qcom,ctx-asid" , & val ))
648+ asid = val ;
649+ else
650+ asid = reg / 0x1000 ;
651+
652+ return asid ;
629653}
630654
631655static int qcom_iommu_ctx_probe (struct platform_device * pdev )
632656{
633657 struct qcom_iommu_ctx * ctx ;
634658 struct device * dev = & pdev -> dev ;
635659 struct qcom_iommu_dev * qcom_iommu = dev_get_drvdata (dev -> parent );
636- struct resource * res ;
637660 int ret , irq ;
638661
639662 ctx = devm_kzalloc (dev , sizeof (* ctx ), GFP_KERNEL );
@@ -643,19 +666,22 @@ static int qcom_iommu_ctx_probe(struct platform_device *pdev)
643666 ctx -> dev = dev ;
644667 platform_set_drvdata (pdev , ctx );
645668
646- res = platform_get_resource (pdev , IORESOURCE_MEM , 0 );
647- ctx -> base = devm_ioremap_resource (dev , res );
669+ ctx -> base = devm_platform_ioremap_resource (pdev , 0 );
648670 if (IS_ERR (ctx -> base ))
649671 return PTR_ERR (ctx -> base );
650672
651673 irq = platform_get_irq (pdev , 0 );
652674 if (irq < 0 )
653- return - ENODEV ;
675+ return irq ;
676+
677+ if (of_device_is_compatible (dev -> of_node , "qcom,msm-iommu-v2-sec" ))
678+ ctx -> secured_ctx = true;
654679
655680 /* clear IRQs before registering fault handler, just in case the
656681 * boot-loader left us a surprise:
657682 */
658- iommu_writel (ctx , ARM_SMMU_CB_FSR , iommu_readl (ctx , ARM_SMMU_CB_FSR ));
683+ if (!ctx -> secured_ctx )
684+ iommu_writel (ctx , ARM_SMMU_CB_FSR , iommu_readl (ctx , ARM_SMMU_CB_FSR ));
659685
660686 ret = devm_request_irq (dev , irq ,
661687 qcom_iommu_fault ,
@@ -677,7 +703,7 @@ static int qcom_iommu_ctx_probe(struct platform_device *pdev)
677703
678704 dev_dbg (dev , "found asid %u\n" , ctx -> asid );
679705
680- qcom_iommu -> ctxs [ctx -> asid - 1 ] = ctx ;
706+ qcom_iommu -> ctxs [ctx -> asid ] = ctx ;
681707
682708 return 0 ;
683709}
@@ -689,12 +715,14 @@ static void qcom_iommu_ctx_remove(struct platform_device *pdev)
689715
690716 platform_set_drvdata (pdev , NULL );
691717
692- qcom_iommu -> ctxs [ctx -> asid - 1 ] = NULL ;
718+ qcom_iommu -> ctxs [ctx -> asid ] = NULL ;
693719}
694720
695721static const struct of_device_id ctx_of_match [] = {
696722 { .compatible = "qcom,msm-iommu-v1-ns" },
697723 { .compatible = "qcom,msm-iommu-v1-sec" },
724+ { .compatible = "qcom,msm-iommu-v2-ns" },
725+ { .compatible = "qcom,msm-iommu-v2-sec" },
698726 { /* sentinel */ }
699727};
700728
@@ -712,7 +740,8 @@ static bool qcom_iommu_has_secure_context(struct qcom_iommu_dev *qcom_iommu)
712740 struct device_node * child ;
713741
714742 for_each_child_of_node (qcom_iommu -> dev -> of_node , child ) {
715- if (of_device_is_compatible (child , "qcom,msm-iommu-v1-sec" )) {
743+ if (of_device_is_compatible (child , "qcom,msm-iommu-v1-sec" ) ||
744+ of_device_is_compatible (child , "qcom,msm-iommu-v2-sec" )) {
716745 of_node_put (child );
717746 return true;
718747 }
@@ -736,11 +765,11 @@ static int qcom_iommu_device_probe(struct platform_device *pdev)
736765 for_each_child_of_node (dev -> of_node , child )
737766 max_asid = max (max_asid , get_asid (child ));
738767
739- qcom_iommu = devm_kzalloc (dev , struct_size (qcom_iommu , ctxs , max_asid ),
768+ qcom_iommu = devm_kzalloc (dev , struct_size (qcom_iommu , ctxs , max_asid + 1 ),
740769 GFP_KERNEL );
741770 if (!qcom_iommu )
742771 return - ENOMEM ;
743- qcom_iommu -> num_ctxs = max_asid ;
772+ qcom_iommu -> max_asid = max_asid ;
744773 qcom_iommu -> dev = dev ;
745774
746775 res = platform_get_resource (pdev , IORESOURCE_MEM , 0 );
@@ -856,6 +885,7 @@ static const struct dev_pm_ops qcom_iommu_pm_ops = {
856885
857886static const struct of_device_id qcom_iommu_of_match [] = {
858887 { .compatible = "qcom,msm-iommu-v1" },
888+ { .compatible = "qcom,msm-iommu-v2" },
859889 { /* sentinel */ }
860890};
861891
0 commit comments