iommu/io-pgtable-arm-v7s: Extend to support PA[33:32] for MediaTek
authorYong Wu <yong.wu@mediatek.com>
Sat, 24 Aug 2019 03:01:54 +0000 (11:01 +0800)
committerJoerg Roedel <jroedel@suse.de>
Fri, 30 Aug 2019 13:57:26 +0000 (15:57 +0200)
MediaTek extend the arm v7s descriptor to support up to 34 bits PA where
the bit32 and bit33 are encoded in the bit9 and bit4 of the PTE
respectively. Meanwhile the iova still is 32bits.

Regarding whether the pagetable address could be over 4GB, the mt8183
support it while the previous mt8173 don't, thus keep it as is.

Signed-off-by: Yong Wu <yong.wu@mediatek.com>
Acked-by: Will Deacon <will@kernel.org>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/io-pgtable-arm-v7s.c
include/linux/io-pgtable.h

index 77cc1eb1243baf71b217219af8b3111413bfcc12..5452871481478643f6c397c63fce0843d4812b5c 100644 (file)
 #define ARM_V7S_TEX_MASK               0x7
 #define ARM_V7S_ATTR_TEX(val)          (((val) & ARM_V7S_TEX_MASK) << ARM_V7S_TEX_SHIFT)
 
-#define ARM_V7S_ATTR_MTK_4GB           BIT(9) /* MTK extend it for 4GB mode */
+/* MediaTek extend the two bits for PA 32bit/33bit */
+#define ARM_V7S_ATTR_MTK_PA_BIT32      BIT(9)
+#define ARM_V7S_ATTR_MTK_PA_BIT33      BIT(4)
 
 /* *well, except for TEX on level 2 large pages, of course :( */
 #define ARM_V7S_CONT_PAGE_TEX_SHIFT    6
@@ -176,16 +178,32 @@ static dma_addr_t __arm_v7s_dma_addr(void *pages)
        return (dma_addr_t)virt_to_phys(pages);
 }
 
+static bool arm_v7s_is_mtk_enabled(struct io_pgtable_cfg *cfg)
+{
+       return IS_ENABLED(CONFIG_PHYS_ADDR_T_64BIT) &&
+               (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_EXT);
+}
+
 static arm_v7s_iopte paddr_to_iopte(phys_addr_t paddr, int lvl,
                                    struct io_pgtable_cfg *cfg)
 {
-       return paddr & ARM_V7S_LVL_MASK(lvl);
+       arm_v7s_iopte pte = paddr & ARM_V7S_LVL_MASK(lvl);
+
+       if (!arm_v7s_is_mtk_enabled(cfg))
+               return pte;
+
+       if (paddr & BIT_ULL(32))
+               pte |= ARM_V7S_ATTR_MTK_PA_BIT32;
+       if (paddr & BIT_ULL(33))
+               pte |= ARM_V7S_ATTR_MTK_PA_BIT33;
+       return pte;
 }
 
 static phys_addr_t iopte_to_paddr(arm_v7s_iopte pte, int lvl,
                                  struct io_pgtable_cfg *cfg)
 {
        arm_v7s_iopte mask;
+       phys_addr_t paddr;
 
        if (ARM_V7S_PTE_IS_TABLE(pte, lvl))
                mask = ARM_V7S_TABLE_MASK;
@@ -194,7 +212,15 @@ static phys_addr_t iopte_to_paddr(arm_v7s_iopte pte, int lvl,
        else
                mask = ARM_V7S_LVL_MASK(lvl);
 
-       return pte & mask;
+       paddr = pte & mask;
+       if (!arm_v7s_is_mtk_enabled(cfg))
+               return paddr;
+
+       if (pte & ARM_V7S_ATTR_MTK_PA_BIT32)
+               paddr |= BIT_ULL(32);
+       if (pte & ARM_V7S_ATTR_MTK_PA_BIT33)
+               paddr |= BIT_ULL(33);
+       return paddr;
 }
 
 static arm_v7s_iopte *iopte_deref(arm_v7s_iopte pte, int lvl,
@@ -315,9 +341,6 @@ static arm_v7s_iopte arm_v7s_prot_to_pte(int prot, int lvl,
        if (lvl == 1 && (cfg->quirks & IO_PGTABLE_QUIRK_ARM_NS))
                pte |= ARM_V7S_ATTR_NS_SECTION;
 
-       if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_EXT)
-               pte |= ARM_V7S_ATTR_MTK_4GB;
-
        return pte;
 }
 
@@ -731,7 +754,10 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,
 {
        struct arm_v7s_io_pgtable *data;
 
-       if (cfg->ias > ARM_V7S_ADDR_BITS || cfg->oas > ARM_V7S_ADDR_BITS)
+       if (cfg->ias > ARM_V7S_ADDR_BITS)
+               return NULL;
+
+       if (cfg->oas > (arm_v7s_is_mtk_enabled(cfg) ? 34 : ARM_V7S_ADDR_BITS))
                return NULL;
 
        if (cfg->quirks & ~(IO_PGTABLE_QUIRK_ARM_NS |
index 915fb7303aa38bb37d92da45f170e279f718c6c3..a2a52c349fe4caa33b6767876f37820f21ec2fb1 100644 (file)
@@ -65,10 +65,9 @@ struct io_pgtable_cfg {
         *      (unmapped) entries but the hardware might do so anyway, perform
         *      TLB maintenance when mapping as well as when unmapping.
         *
-        * IO_PGTABLE_QUIRK_ARM_MTK_EXT: (ARM v7s format) Set bit 9 in all
-        *      PTEs, for Mediatek IOMMUs which treat it as a 33rd address bit
-        *      when the SoC is in "4GB mode" and they can only access the high
-        *      remap of DRAM (0x1_00000000 to 0x1_ffffffff).
+        * IO_PGTABLE_QUIRK_ARM_MTK_EXT: (ARM v7s format) MediaTek IOMMUs extend
+        *      to support up to 34 bits PA where the bit32 and bit33 are
+        *      encoded in the bit9 and bit4 of the PTE respectively.
         *
         * IO_PGTABLE_QUIRK_NON_STRICT: Skip issuing synchronous leaf TLBIs
         *      on unmap, for DMA domains using the flush queue mechanism for