]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/iommu/ipmmu-vmsa.c
Merge tag 'linux-kselftest-5.5-rc1-fixes2' of git://git.kernel.org/pub/scm/linux...
[linux.git] / drivers / iommu / ipmmu-vmsa.c
index 2639fc7181171c4ab1db52bb0765c8f0a8b24bd6..d02edd2751f32077bdb1ebed449c5958b8abcd19 100644 (file)
@@ -50,6 +50,9 @@ struct ipmmu_features {
        bool twobit_imttbcr_sl0;
        bool reserved_context;
        bool cache_snoop;
+       unsigned int ctx_offset_base;
+       unsigned int ctx_offset_stride;
+       unsigned int utlb_offset_base;
 };
 
 struct ipmmu_vmsa_device {
@@ -99,125 +102,49 @@ static struct ipmmu_vmsa_device *to_ipmmu(struct device *dev)
 
 #define IM_NS_ALIAS_OFFSET             0x800
 
-#define IM_CTX_SIZE                    0x40
-
-#define IMCTR                          0x0000
-#define IMCTR_TRE                      (1 << 17)
-#define IMCTR_AFE                      (1 << 16)
-#define IMCTR_RTSEL_MASK               (3 << 4)
-#define IMCTR_RTSEL_SHIFT              4
-#define IMCTR_TREN                     (1 << 3)
-#define IMCTR_INTEN                    (1 << 2)
-#define IMCTR_FLUSH                    (1 << 1)
-#define IMCTR_MMUEN                    (1 << 0)
-
-#define IMCAAR                         0x0004
-
-#define IMTTBCR                                0x0008
-#define IMTTBCR_EAE                    (1 << 31)
-#define IMTTBCR_PMB                    (1 << 30)
-#define IMTTBCR_SH1_NON_SHAREABLE      (0 << 28)       /* R-Car Gen2 only */
-#define IMTTBCR_SH1_OUTER_SHAREABLE    (2 << 28)       /* R-Car Gen2 only */
-#define IMTTBCR_SH1_INNER_SHAREABLE    (3 << 28)       /* R-Car Gen2 only */
-#define IMTTBCR_SH1_MASK               (3 << 28)       /* R-Car Gen2 only */
-#define IMTTBCR_ORGN1_NC               (0 << 26)       /* R-Car Gen2 only */
-#define IMTTBCR_ORGN1_WB_WA            (1 << 26)       /* R-Car Gen2 only */
-#define IMTTBCR_ORGN1_WT               (2 << 26)       /* R-Car Gen2 only */
-#define IMTTBCR_ORGN1_WB               (3 << 26)       /* R-Car Gen2 only */
-#define IMTTBCR_ORGN1_MASK             (3 << 26)       /* R-Car Gen2 only */
-#define IMTTBCR_IRGN1_NC               (0 << 24)       /* R-Car Gen2 only */
-#define IMTTBCR_IRGN1_WB_WA            (1 << 24)       /* R-Car Gen2 only */
-#define IMTTBCR_IRGN1_WT               (2 << 24)       /* R-Car Gen2 only */
-#define IMTTBCR_IRGN1_WB               (3 << 24)       /* R-Car Gen2 only */
-#define IMTTBCR_IRGN1_MASK             (3 << 24)       /* R-Car Gen2 only */
-#define IMTTBCR_TSZ1_MASK              (7 << 16)
-#define IMTTBCR_TSZ1_SHIFT             16
-#define IMTTBCR_SH0_NON_SHAREABLE      (0 << 12)       /* R-Car Gen2 only */
-#define IMTTBCR_SH0_OUTER_SHAREABLE    (2 << 12)       /* R-Car Gen2 only */
+/* MMU "context" registers */
+#define IMCTR                          0x0000          /* R-Car Gen2/3 */
+#define IMCTR_INTEN                    (1 << 2)        /* R-Car Gen2/3 */
+#define IMCTR_FLUSH                    (1 << 1)        /* R-Car Gen2/3 */
+#define IMCTR_MMUEN                    (1 << 0)        /* R-Car Gen2/3 */
+
+#define IMTTBCR                                0x0008          /* R-Car Gen2/3 */
+#define IMTTBCR_EAE                    (1 << 31)       /* R-Car Gen2/3 */
 #define IMTTBCR_SH0_INNER_SHAREABLE    (3 << 12)       /* R-Car Gen2 only */
-#define IMTTBCR_SH0_MASK               (3 << 12)       /* R-Car Gen2 only */
-#define IMTTBCR_ORGN0_NC               (0 << 10)       /* R-Car Gen2 only */
 #define IMTTBCR_ORGN0_WB_WA            (1 << 10)       /* R-Car Gen2 only */
-#define IMTTBCR_ORGN0_WT               (2 << 10)       /* R-Car Gen2 only */
-#define IMTTBCR_ORGN0_WB               (3 << 10)       /* R-Car Gen2 only */
-#define IMTTBCR_ORGN0_MASK             (3 << 10)       /* R-Car Gen2 only */
-#define IMTTBCR_IRGN0_NC               (0 << 8)        /* R-Car Gen2 only */
 #define IMTTBCR_IRGN0_WB_WA            (1 << 8)        /* R-Car Gen2 only */
-#define IMTTBCR_IRGN0_WT               (2 << 8)        /* R-Car Gen2 only */
-#define IMTTBCR_IRGN0_WB               (3 << 8)        /* R-Car Gen2 only */
-#define IMTTBCR_IRGN0_MASK             (3 << 8)        /* R-Car Gen2 only */
-#define IMTTBCR_SL0_TWOBIT_LVL_3       (0 << 6)        /* R-Car Gen3 only */
-#define IMTTBCR_SL0_TWOBIT_LVL_2       (1 << 6)        /* R-Car Gen3 only */
 #define IMTTBCR_SL0_TWOBIT_LVL_1       (2 << 6)        /* R-Car Gen3 only */
-#define IMTTBCR_SL0_LVL_2              (0 << 4)
-#define IMTTBCR_SL0_LVL_1              (1 << 4)
-#define IMTTBCR_TSZ0_MASK              (7 << 0)
-#define IMTTBCR_TSZ0_SHIFT             O
-
-#define IMBUSCR                                0x000c
-#define IMBUSCR_DVM                    (1 << 2)
-#define IMBUSCR_BUSSEL_SYS             (0 << 0)
-#define IMBUSCR_BUSSEL_CCI             (1 << 0)
-#define IMBUSCR_BUSSEL_IMCAAR          (2 << 0)
-#define IMBUSCR_BUSSEL_CCI_IMCAAR      (3 << 0)
-#define IMBUSCR_BUSSEL_MASK            (3 << 0)
-
-#define IMTTLBR0                       0x0010
-#define IMTTUBR0                       0x0014
-#define IMTTLBR1                       0x0018
-#define IMTTUBR1                       0x001c
-
-#define IMSTR                          0x0020
-#define IMSTR_ERRLVL_MASK              (3 << 12)
-#define IMSTR_ERRLVL_SHIFT             12
-#define IMSTR_ERRCODE_TLB_FORMAT       (1 << 8)
-#define IMSTR_ERRCODE_ACCESS_PERM      (4 << 8)
-#define IMSTR_ERRCODE_SECURE_ACCESS    (5 << 8)
-#define IMSTR_ERRCODE_MASK             (7 << 8)
-#define IMSTR_MHIT                     (1 << 4)
-#define IMSTR_ABORT                    (1 << 2)
-#define IMSTR_PF                       (1 << 1)
-#define IMSTR_TF                       (1 << 0)
-
-#define IMMAIR0                                0x0028
-#define IMMAIR1                                0x002c
-#define IMMAIR_ATTR_MASK               0xff
-#define IMMAIR_ATTR_DEVICE             0x04
-#define IMMAIR_ATTR_NC                 0x44
-#define IMMAIR_ATTR_WBRWA              0xff
-#define IMMAIR_ATTR_SHIFT(n)           ((n) << 3)
-#define IMMAIR_ATTR_IDX_NC             0
-#define IMMAIR_ATTR_IDX_WBRWA          1
-#define IMMAIR_ATTR_IDX_DEV            2
-
-#define IMELAR                         0x0030  /* IMEAR on R-Car Gen2 */
-#define IMEUAR                         0x0034  /* R-Car Gen3 only */
-
-#define IMPCTR                         0x0200
-#define IMPSTR                         0x0208
-#define IMPEAR                         0x020c
-#define IMPMBA(n)                      (0x0280 + ((n) * 4))
-#define IMPMBD(n)                      (0x02c0 + ((n) * 4))
+#define IMTTBCR_SL0_LVL_1              (1 << 4)        /* R-Car Gen2 only */
+
+#define IMBUSCR                                0x000c          /* R-Car Gen2 only */
+#define IMBUSCR_DVM                    (1 << 2)        /* R-Car Gen2 only */
+#define IMBUSCR_BUSSEL_MASK            (3 << 0)        /* R-Car Gen2 only */
+
+#define IMTTLBR0                       0x0010          /* R-Car Gen2/3 */
+#define IMTTUBR0                       0x0014          /* R-Car Gen2/3 */
+
+#define IMSTR                          0x0020          /* R-Car Gen2/3 */
+#define IMSTR_MHIT                     (1 << 4)        /* R-Car Gen2/3 */
+#define IMSTR_ABORT                    (1 << 2)        /* R-Car Gen2/3 */
+#define IMSTR_PF                       (1 << 1)        /* R-Car Gen2/3 */
+#define IMSTR_TF                       (1 << 0)        /* R-Car Gen2/3 */
 
+#define IMMAIR0                                0x0028          /* R-Car Gen2/3 */
+
+#define IMELAR                         0x0030          /* R-Car Gen2/3, IMEAR on R-Car Gen2 */
+#define IMEUAR                         0x0034          /* R-Car Gen3 only */
+
+/* uTLB registers */
 #define IMUCTR(n)                      ((n) < 32 ? IMUCTR0(n) : IMUCTR32(n))
-#define IMUCTR0(n)                     (0x0300 + ((n) * 16))
-#define IMUCTR32(n)                    (0x0600 + (((n) - 32) * 16))
-#define IMUCTR_FIXADDEN                        (1 << 31)
-#define IMUCTR_FIXADD_MASK             (0xff << 16)
-#define IMUCTR_FIXADD_SHIFT            16
-#define IMUCTR_TTSEL_MMU(n)            ((n) << 4)
-#define IMUCTR_TTSEL_PMB               (8 << 4)
-#define IMUCTR_TTSEL_MASK              (15 << 4)
-#define IMUCTR_FLUSH                   (1 << 1)
-#define IMUCTR_MMUEN                   (1 << 0)
+#define IMUCTR0(n)                     (0x0300 + ((n) * 16))           /* R-Car Gen2/3 */
+#define IMUCTR32(n)                    (0x0600 + (((n) - 32) * 16))    /* R-Car Gen3 only */
+#define IMUCTR_TTSEL_MMU(n)            ((n) << 4)      /* R-Car Gen2/3 */
+#define IMUCTR_FLUSH                   (1 << 1)        /* R-Car Gen2/3 */
+#define IMUCTR_MMUEN                   (1 << 0)        /* R-Car Gen2/3 */
 
 #define IMUASID(n)                     ((n) < 32 ? IMUASID0(n) : IMUASID32(n))
-#define IMUASID0(n)                    (0x0308 + ((n) * 16))
-#define IMUASID32(n)                   (0x0608 + (((n) - 32) * 16))
-#define IMUASID_ASID8_MASK             (0xff << 8)
-#define IMUASID_ASID8_SHIFT            8
-#define IMUASID_ASID0_MASK             (0xff << 0)
-#define IMUASID_ASID0_SHIFT            0
+#define IMUASID0(n)                    (0x0308 + ((n) * 16))           /* R-Car Gen2/3 */
+#define IMUASID32(n)                   (0x0608 + (((n) - 32) * 16))    /* R-Car Gen3 only */
 
 /* -----------------------------------------------------------------------------
  * Root device handling
@@ -264,29 +191,61 @@ static void ipmmu_write(struct ipmmu_vmsa_device *mmu, unsigned int offset,
        iowrite32(data, mmu->base + offset);
 }
 
+static unsigned int ipmmu_ctx_reg(struct ipmmu_vmsa_device *mmu,
+                                 unsigned int context_id, unsigned int reg)
+{
+       return mmu->features->ctx_offset_base +
+              context_id * mmu->features->ctx_offset_stride + reg;
+}
+
+static u32 ipmmu_ctx_read(struct ipmmu_vmsa_device *mmu,
+                         unsigned int context_id, unsigned int reg)
+{
+       return ipmmu_read(mmu, ipmmu_ctx_reg(mmu, context_id, reg));
+}
+
+static void ipmmu_ctx_write(struct ipmmu_vmsa_device *mmu,
+                           unsigned int context_id, unsigned int reg, u32 data)
+{
+       ipmmu_write(mmu, ipmmu_ctx_reg(mmu, context_id, reg), data);
+}
+
 static u32 ipmmu_ctx_read_root(struct ipmmu_vmsa_domain *domain,
                               unsigned int reg)
 {
-       return ipmmu_read(domain->mmu->root,
-                         domain->context_id * IM_CTX_SIZE + reg);
+       return ipmmu_ctx_read(domain->mmu->root, domain->context_id, reg);
 }
 
 static void ipmmu_ctx_write_root(struct ipmmu_vmsa_domain *domain,
                                 unsigned int reg, u32 data)
 {
-       ipmmu_write(domain->mmu->root,
-                   domain->context_id * IM_CTX_SIZE + reg, data);
+       ipmmu_ctx_write(domain->mmu->root, domain->context_id, reg, data);
 }
 
 static void ipmmu_ctx_write_all(struct ipmmu_vmsa_domain *domain,
                                unsigned int reg, u32 data)
 {
        if (domain->mmu != domain->mmu->root)
-               ipmmu_write(domain->mmu,
-                           domain->context_id * IM_CTX_SIZE + reg, data);
+               ipmmu_ctx_write(domain->mmu, domain->context_id, reg, data);
 
-       ipmmu_write(domain->mmu->root,
-                   domain->context_id * IM_CTX_SIZE + reg, data);
+       ipmmu_ctx_write(domain->mmu->root, domain->context_id, reg, data);
+}
+
+static u32 ipmmu_utlb_reg(struct ipmmu_vmsa_device *mmu, unsigned int reg)
+{
+       return mmu->features->utlb_offset_base + reg;
+}
+
+static void ipmmu_imuasid_write(struct ipmmu_vmsa_device *mmu,
+                               unsigned int utlb, u32 data)
+{
+       ipmmu_write(mmu, ipmmu_utlb_reg(mmu, IMUASID(utlb)), data);
+}
+
+static void ipmmu_imuctr_write(struct ipmmu_vmsa_device *mmu,
+                              unsigned int utlb, u32 data)
+{
+       ipmmu_write(mmu, ipmmu_utlb_reg(mmu, IMUCTR(utlb)), data);
 }
 
 /* -----------------------------------------------------------------------------
@@ -334,11 +293,10 @@ static void ipmmu_utlb_enable(struct ipmmu_vmsa_domain *domain,
         */
 
        /* TODO: What should we set the ASID to ? */
-       ipmmu_write(mmu, IMUASID(utlb), 0);
+       ipmmu_imuasid_write(mmu, utlb, 0);
        /* TODO: Do we need to flush the microTLB ? */
-       ipmmu_write(mmu, IMUCTR(utlb),
-                   IMUCTR_TTSEL_MMU(domain->context_id) | IMUCTR_FLUSH |
-                   IMUCTR_MMUEN);
+       ipmmu_imuctr_write(mmu, utlb, IMUCTR_TTSEL_MMU(domain->context_id) |
+                                     IMUCTR_FLUSH | IMUCTR_MMUEN);
        mmu->utlb_ctx[utlb] = domain->context_id;
 }
 
@@ -350,7 +308,7 @@ static void ipmmu_utlb_disable(struct ipmmu_vmsa_domain *domain,
 {
        struct ipmmu_vmsa_device *mmu = domain->mmu;
 
-       ipmmu_write(mmu, IMUCTR(utlb), 0);
+       ipmmu_imuctr_write(mmu, utlb, 0);
        mmu->utlb_ctx[utlb] = IPMMU_CTX_INVALID;
 }
 
@@ -438,7 +396,7 @@ static void ipmmu_domain_setup_context(struct ipmmu_vmsa_domain *domain)
 
        /* MAIR0 */
        ipmmu_ctx_write_root(domain, IMMAIR0,
-                            domain->cfg.arm_lpae_s1_cfg.mair[0]);
+                            domain->cfg.arm_lpae_s1_cfg.mair);
 
        /* IMBUSCR */
        if (domain->mmu->features->setup_imbuscr)
@@ -724,7 +682,7 @@ static void ipmmu_detach_device(struct iommu_domain *io_domain,
 }
 
 static int ipmmu_map(struct iommu_domain *io_domain, unsigned long iova,
-                    phys_addr_t paddr, size_t size, int prot)
+                    phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
 {
        struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
 
@@ -783,6 +741,7 @@ static int ipmmu_init_platform_device(struct device *dev,
 
 static const struct soc_device_attribute soc_rcar_gen3[] = {
        { .soc_id = "r8a774a1", },
+       { .soc_id = "r8a774b1", },
        { .soc_id = "r8a774c0", },
        { .soc_id = "r8a7795", },
        { .soc_id = "r8a7796", },
@@ -794,6 +753,7 @@ static const struct soc_device_attribute soc_rcar_gen3[] = {
 };
 
 static const struct soc_device_attribute soc_rcar_gen3_whitelist[] = {
+       { .soc_id = "r8a774b1", },
        { .soc_id = "r8a774c0", },
        { .soc_id = "r8a7795", .revision = "ES3.*" },
        { .soc_id = "r8a77965", },
@@ -985,7 +945,7 @@ static void ipmmu_device_reset(struct ipmmu_vmsa_device *mmu)
 
        /* Disable all contexts. */
        for (i = 0; i < mmu->num_ctx; ++i)
-               ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
+               ipmmu_ctx_write(mmu, i, IMCTR, 0);
 }
 
 static const struct ipmmu_features ipmmu_features_default = {
@@ -997,6 +957,9 @@ static const struct ipmmu_features ipmmu_features_default = {
        .twobit_imttbcr_sl0 = false,
        .reserved_context = false,
        .cache_snoop = true,
+       .ctx_offset_base = 0,
+       .ctx_offset_stride = 0x40,
+       .utlb_offset_base = 0,
 };
 
 static const struct ipmmu_features ipmmu_features_rcar_gen3 = {
@@ -1008,6 +971,9 @@ static const struct ipmmu_features ipmmu_features_rcar_gen3 = {
        .twobit_imttbcr_sl0 = true,
        .reserved_context = true,
        .cache_snoop = false,
+       .ctx_offset_base = 0,
+       .ctx_offset_stride = 0x40,
+       .utlb_offset_base = 0,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {
@@ -1017,6 +983,9 @@ static const struct of_device_id ipmmu_of_ids[] = {
        }, {
                .compatible = "renesas,ipmmu-r8a774a1",
                .data = &ipmmu_features_rcar_gen3,
+       }, {
+               .compatible = "renesas,ipmmu-r8a774b1",
+               .data = &ipmmu_features_rcar_gen3,
        }, {
                .compatible = "renesas,ipmmu-r8a774c0",
                .data = &ipmmu_features_rcar_gen3,