diff options
| author | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2014-04-02 06:47:37 -0400 |
|---|---|---|
| committer | Joerg Roedel <jroedel@suse.de> | 2014-05-26 05:18:21 -0400 |
| commit | d25a2a16f0889de4a1cd8639896f35dc9465f6f5 (patch) | |
| tree | 3b7e1425317bbc6bd965a05c47e87aff4f2be26d | |
| parent | 4b660a7f5c8099d88d1a43d8ae138965112592c7 (diff) | |
iommu: Add driver for Renesas VMSA-compatible IPMMU
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
| -rw-r--r-- | drivers/iommu/Kconfig | 12 | ||||
| -rw-r--r-- | drivers/iommu/Makefile | 1 | ||||
| -rw-r--r-- | drivers/iommu/ipmmu-vmsa.c | 1070 | ||||
| -rw-r--r-- | include/linux/platform_data/ipmmu-vmsa.h | 24 |
4 files changed, 1107 insertions, 0 deletions
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index df56e4c74a7e..a22b537caacd 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig | |||
| @@ -272,6 +272,18 @@ config SHMOBILE_IOMMU_L1SIZE | |||
| 272 | default 256 if SHMOBILE_IOMMU_ADDRSIZE_64MB | 272 | default 256 if SHMOBILE_IOMMU_ADDRSIZE_64MB |
| 273 | default 128 if SHMOBILE_IOMMU_ADDRSIZE_32MB | 273 | default 128 if SHMOBILE_IOMMU_ADDRSIZE_32MB |
| 274 | 274 | ||
| 275 | config IPMMU_VMSA | ||
| 276 | bool "Renesas VMSA-compatible IPMMU" | ||
| 277 | depends on ARM_LPAE | ||
| 278 | depends on ARCH_SHMOBILE || COMPILE_TEST | ||
| 279 | select IOMMU_API | ||
| 280 | select ARM_DMA_USE_IOMMU | ||
| 281 | help | ||
| 282 | Support for the Renesas VMSA-compatible IPMMU Renesas found in the | ||
| 283 | R-Mobile APE6 and R-Car H2/M2 SoCs. | ||
| 284 | |||
| 285 | If unsure, say N. | ||
| 286 | |||
| 275 | config SPAPR_TCE_IOMMU | 287 | config SPAPR_TCE_IOMMU |
| 276 | bool "sPAPR TCE IOMMU Support" | 288 | bool "sPAPR TCE IOMMU Support" |
| 277 | depends on PPC_POWERNV || PPC_PSERIES | 289 | depends on PPC_POWERNV || PPC_PSERIES |
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 5d58bf16e9e3..8893bad048e0 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile | |||
| @@ -7,6 +7,7 @@ obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o | |||
| 7 | obj-$(CONFIG_ARM_SMMU) += arm-smmu.o | 7 | obj-$(CONFIG_ARM_SMMU) += arm-smmu.o |
| 8 | obj-$(CONFIG_DMAR_TABLE) += dmar.o | 8 | obj-$(CONFIG_DMAR_TABLE) += dmar.o |
| 9 | obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o | 9 | obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o |
| 10 | obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o | ||
| 10 | obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o | 11 | obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o |
| 11 | obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o | 12 | obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o |
| 12 | obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o | 13 | obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o |
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c new file mode 100644 index 000000000000..b084530babf4 --- /dev/null +++ b/drivers/iommu/ipmmu-vmsa.c | |||
| @@ -0,0 +1,1070 @@ | |||
| 1 | /* | ||
| 2 | * IPMMU VMSA | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Renesas Electronics Corporation | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; version 2 of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/delay.h> | ||
| 12 | #include <linux/dma-mapping.h> | ||
| 13 | #include <linux/err.h> | ||
| 14 | #include <linux/export.h> | ||
| 15 | #include <linux/interrupt.h> | ||
| 16 | #include <linux/io.h> | ||
| 17 | #include <linux/iommu.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/platform_data/ipmmu-vmsa.h> | ||
| 20 | #include <linux/platform_device.h> | ||
| 21 | #include <linux/sizes.h> | ||
| 22 | #include <linux/slab.h> | ||
| 23 | |||
| 24 | #include <asm/dma-iommu.h> | ||
| 25 | #include <asm/pgalloc.h> | ||
| 26 | |||
| 27 | struct ipmmu_vmsa_device { | ||
| 28 | struct device *dev; | ||
| 29 | void __iomem *base; | ||
| 30 | struct list_head list; | ||
| 31 | |||
| 32 | const struct ipmmu_vmsa_platform_data *pdata; | ||
| 33 | unsigned int num_utlbs; | ||
| 34 | |||
| 35 | struct dma_iommu_mapping *mapping; | ||
| 36 | }; | ||
| 37 | |||
| 38 | struct ipmmu_vmsa_domain { | ||
| 39 | struct ipmmu_vmsa_device *mmu; | ||
| 40 | struct iommu_domain *io_domain; | ||
| 41 | |||
| 42 | unsigned int context_id; | ||
| 43 | spinlock_t lock; /* Protects mappings */ | ||
| 44 | pgd_t *pgd; | ||
| 45 | }; | ||
| 46 | |||
| 47 | static DEFINE_SPINLOCK(ipmmu_devices_lock); | ||
| 48 | static LIST_HEAD(ipmmu_devices); | ||
| 49 | |||
| 50 | #define TLB_LOOP_TIMEOUT 100 /* 100us */ | ||
| 51 | |||
| 52 | /* ----------------------------------------------------------------------------- | ||
| 53 | * Registers Definition | ||
| 54 | */ | ||
| 55 | |||
| 56 | #define IM_CTX_SIZE 0x40 | ||
| 57 | |||
| 58 | #define IMCTR 0x0000 | ||
| 59 | #define IMCTR_TRE (1 << 17) | ||
| 60 | #define IMCTR_AFE (1 << 16) | ||
| 61 | #define IMCTR_RTSEL_MASK (3 << 4) | ||
| 62 | #define IMCTR_RTSEL_SHIFT 4 | ||
| 63 | #define IMCTR_TREN (1 << 3) | ||
| 64 | #define IMCTR_INTEN (1 << 2) | ||
| 65 | #define IMCTR_FLUSH (1 << 1) | ||
| 66 | #define IMCTR_MMUEN (1 << 0) | ||
| 67 | |||
| 68 | #define IMCAAR 0x0004 | ||
| 69 | |||
| 70 | #define IMTTBCR 0x0008 | ||
| 71 | #define IMTTBCR_EAE (1 << 31) | ||
| 72 | #define IMTTBCR_PMB (1 << 30) | ||
| 73 | #define IMTTBCR_SH1_NON_SHAREABLE (0 << 28) | ||
| 74 | #define IMTTBCR_SH1_OUTER_SHAREABLE (2 << 28) | ||
| 75 | #define IMTTBCR_SH1_INNER_SHAREABLE (3 << 28) | ||
| 76 | #define IMTTBCR_SH1_MASK (3 << 28) | ||
| 77 | #define IMTTBCR_ORGN1_NC (0 << 26) | ||
| 78 | #define IMTTBCR_ORGN1_WB_WA (1 << 26) | ||
| 79 | #define IMTTBCR_ORGN1_WT (2 << 26) | ||
| 80 | #define IMTTBCR_ORGN1_WB (3 << 26) | ||
| 81 | #define IMTTBCR_ORGN1_MASK (3 << 26) | ||
| 82 | #define IMTTBCR_IRGN1_NC (0 << 24) | ||
| 83 | #define IMTTBCR_IRGN1_WB_WA (1 << 24) | ||
| 84 | #define IMTTBCR_IRGN1_WT (2 << 24) | ||
| 85 | #define IMTTBCR_IRGN1_WB (3 << 24) | ||
| 86 | #define IMTTBCR_IRGN1_MASK (3 << 24) | ||
| 87 | #define IMTTBCR_TSZ1_MASK (7 << 16) | ||
| 88 | #define IMTTBCR_TSZ1_SHIFT 16 | ||
| 89 | #define IMTTBCR_SH0_NON_SHAREABLE (0 << 12) | ||
| 90 | #define IMTTBCR_SH0_OUTER_SHAREABLE (2 << 12) | ||
| 91 | #define IMTTBCR_SH0_INNER_SHAREABLE (3 << 12) | ||
| 92 | #define IMTTBCR_SH0_MASK (3 << 12) | ||
| 93 | #define IMTTBCR_ORGN0_NC (0 << 10) | ||
| 94 | #define IMTTBCR_ORGN0_WB_WA (1 << 10) | ||
| 95 | #define IMTTBCR_ORGN0_WT (2 << 10) | ||
| 96 | #define IMTTBCR_ORGN0_WB (3 << 10) | ||
| 97 | #define IMTTBCR_ORGN0_MASK (3 << 10) | ||
| 98 | #define IMTTBCR_IRGN0_NC (0 << 8) | ||
| 99 | #define IMTTBCR_IRGN0_WB_WA (1 << 8) | ||
| 100 | #define IMTTBCR_IRGN0_WT (2 << 8) | ||
| 101 | #define IMTTBCR_IRGN0_WB (3 << 8) | ||
| 102 | #define IMTTBCR_IRGN0_MASK (3 << 8) | ||
| 103 | #define IMTTBCR_SL0_LVL_2 (0 << 4) | ||
| 104 | #define IMTTBCR_SL0_LVL_1 (1 << 4) | ||
| 105 | #define IMTTBCR_TSZ0_MASK (7 << 0) | ||
| 106 | #define IMTTBCR_TSZ0_SHIFT O | ||
| 107 | |||
| 108 | #define IMBUSCR 0x000c | ||
| 109 | #define IMBUSCR_DVM (1 << 2) | ||
| 110 | #define IMBUSCR_BUSSEL_SYS (0 << 0) | ||
| 111 | #define IMBUSCR_BUSSEL_CCI (1 << 0) | ||
| 112 | #define IMBUSCR_BUSSEL_IMCAAR (2 << 0) | ||
| 113 | #define IMBUSCR_BUSSEL_CCI_IMCAAR (3 << 0) | ||
| 114 | #define IMBUSCR_BUSSEL_MASK (3 << 0) | ||
| 115 | |||
| 116 | #define IMTTLBR0 0x0010 | ||
| 117 | #define IMTTUBR0 0x0014 | ||
| 118 | #define IMTTLBR1 0x0018 | ||
| 119 | #define IMTTUBR1 0x001c | ||
| 120 | |||
| 121 | #define IMSTR 0x0020 | ||
| 122 | #define IMSTR_ERRLVL_MASK (3 << 12) | ||
| 123 | #define IMSTR_ERRLVL_SHIFT 12 | ||
| 124 | #define IMSTR_ERRCODE_TLB_FORMAT (1 << 8) | ||
| 125 | #define IMSTR_ERRCODE_ACCESS_PERM (4 << 8) | ||
| 126 | #define IMSTR_ERRCODE_SECURE_ACCESS (5 << 8) | ||
| 127 | #define IMSTR_ERRCODE_MASK (7 << 8) | ||
| 128 | #define IMSTR_MHIT (1 << 4) | ||
| 129 | #define IMSTR_ABORT (1 << 2) | ||
| 130 | #define IMSTR_PF (1 << 1) | ||
| 131 | #define IMSTR_TF (1 << 0) | ||
| 132 | |||
| 133 | #define IMMAIR0 0x0028 | ||
| 134 | #define IMMAIR1 0x002c | ||
| 135 | #define IMMAIR_ATTR_MASK 0xff | ||
| 136 | #define IMMAIR_ATTR_DEVICE 0x04 | ||
| 137 | #define IMMAIR_ATTR_NC 0x44 | ||
| 138 | #define IMMAIR_ATTR_WBRWA 0xff | ||
| 139 | #define IMMAIR_ATTR_SHIFT(n) ((n) << 3) | ||
| 140 | #define IMMAIR_ATTR_IDX_NC 0 | ||
| 141 | #define IMMAIR_ATTR_IDX_WBRWA 1 | ||
| 142 | #define IMMAIR_ATTR_IDX_DEV 2 | ||
| 143 | |||
| 144 | #define IMEAR 0x0030 | ||
| 145 | |||
| 146 | #define IMPCTR 0x0200 | ||
| 147 | #define IMPSTR 0x0208 | ||
| 148 | #define IMPEAR 0x020c | ||
| 149 | #define IMPMBA(n) (0x0280 + ((n) * 4)) | ||
| 150 | #define IMPMBD(n) (0x02c0 + ((n) * 4)) | ||
| 151 | |||
| 152 | #define IMUCTR(n) (0x0300 + ((n) * 16)) | ||
| 153 | #define IMUCTR_FIXADDEN (1 << 31) | ||
| 154 | #define IMUCTR_FIXADD_MASK (0xff << 16) | ||
| 155 | #define IMUCTR_FIXADD_SHIFT 16 | ||
| 156 | #define IMUCTR_TTSEL_MMU(n) ((n) << 4) | ||
| 157 | #define IMUCTR_TTSEL_PMB (8 << 4) | ||
| 158 | #define IMUCTR_TTSEL_MASK (15 << 4) | ||
| 159 | #define IMUCTR_FLUSH (1 << 1) | ||
| 160 | #define IMUCTR_MMUEN (1 << 0) | ||
| 161 | |||
| 162 | #define IMUASID(n) (0x0308 + ((n) * 16)) | ||
| 163 | #define IMUASID_ASID8_MASK (0xff << 8) | ||
| 164 | #define IMUASID_ASID8_SHIFT 8 | ||
| 165 | #define IMUASID_ASID0_MASK (0xff << 0) | ||
| 166 | #define IMUASID_ASID0_SHIFT 0 | ||
| 167 | |||
