drm/tegra: vic: Support stream ID register programming
authorThierry Reding <treding@nvidia.com>
Fri, 1 Feb 2019 13:28:36 +0000 (14:28 +0100)
committerThierry Reding <treding@nvidia.com>
Thu, 7 Feb 2019 17:29:01 +0000 (18:29 +0100)
The version of VIC found in Tegra186 and later incorporates improvements
with regards to context isolation. As part of those improvements, stream
ID registers were added that allow to specify separate stream IDs for
the Falcon microcontroller and the VIC memory interface.

While it is possible to also set the stream ID dynamically at runtime to
allow userspace contexts to be completely separated, this commit doesn't
implement that yet. Instead, the static VIC stream ID is programmed when
the Falcon is booted. This ensures that memory accesses by the Falcon or
the VIC are properly translated via the SMMU.

Signed-off-by: Thierry Reding <treding@nvidia.com>
drivers/gpu/drm/tegra/vic.c
drivers/gpu/drm/tegra/vic.h

index 55a8cc162e9d57e1132347ded544b093e49970c3..39bfed9623de28f0e62a0297f8e84b7151c28238 100644 (file)
@@ -26,6 +26,7 @@
 struct vic_config {
        const char *firmware;
        unsigned int version;
+       bool supports_sid;
 };
 
 struct vic {
@@ -105,6 +106,22 @@ static int vic_boot(struct vic *vic)
        if (vic->booted)
                return 0;
 
+       if (vic->config->supports_sid) {
+               struct iommu_fwspec *spec = dev_iommu_fwspec_get(vic->dev);
+               u32 value;
+
+               value = TRANSCFG_ATT(1, TRANSCFG_SID_FALCON) |
+                       TRANSCFG_ATT(0, TRANSCFG_SID_HW);
+               vic_writel(vic, value, VIC_TFBIF_TRANSCFG);
+
+               if (spec && spec->num_ids > 0) {
+                       value = spec->ids[0] & 0xffff;
+
+                       vic_writel(vic, value, VIC_THI_STREAMID0);
+                       vic_writel(vic, value, VIC_THI_STREAMID1);
+               }
+       }
+
        /* setup clockgating registers */
        vic_writel(vic, CG_IDLE_CG_DLY_CNT(4) |
                        CG_IDLE_CG_EN |
@@ -314,6 +331,7 @@ static const struct tegra_drm_client_ops vic_ops = {
 static const struct vic_config vic_t124_config = {
        .firmware = NVIDIA_TEGRA_124_VIC_FIRMWARE,
        .version = 0x40,
+       .supports_sid = false,
 };
 
 #define NVIDIA_TEGRA_210_VIC_FIRMWARE "nvidia/tegra210/vic04_ucode.bin"
@@ -321,6 +339,7 @@ static const struct vic_config vic_t124_config = {
 static const struct vic_config vic_t210_config = {
        .firmware = NVIDIA_TEGRA_210_VIC_FIRMWARE,
        .version = 0x21,
+       .supports_sid = false,
 };
 
 #define NVIDIA_TEGRA_186_VIC_FIRMWARE "nvidia/tegra186/vic04_ucode.bin"
@@ -328,6 +347,7 @@ static const struct vic_config vic_t210_config = {
 static const struct vic_config vic_t186_config = {
        .firmware = NVIDIA_TEGRA_186_VIC_FIRMWARE,
        .version = 0x18,
+       .supports_sid = true,
 };
 
 #define NVIDIA_TEGRA_194_VIC_FIRMWARE "nvidia/tegra194/vic.bin"
@@ -335,6 +355,7 @@ static const struct vic_config vic_t186_config = {
 static const struct vic_config vic_t194_config = {
        .firmware = NVIDIA_TEGRA_194_VIC_FIRMWARE,
        .version = 0x19,
+       .supports_sid = true,
 };
 
 static const struct of_device_id vic_match[] = {
index 21844817a7e1201eab0a5b98e0f88355e0888c8f..017584340dd62c92c592f00a3ce6b37f487a15d0 100644 (file)
 
 /* VIC registers */
 
+#define VIC_THI_STREAMID0      0x00000030
+#define VIC_THI_STREAMID1      0x00000034
+
 #define NV_PVIC_MISC_PRI_VIC_CG                        0x000016d0
 #define CG_IDLE_CG_DLY_CNT(val)                        ((val & 0x3f) << 0)
 #define CG_IDLE_CG_EN                          (1 << 6)
 #define CG_WAKEUP_DLY_CNT(val)                 ((val & 0xf) << 16)
 
+#define VIC_TFBIF_TRANSCFG     0x00002044
+#define  TRANSCFG_ATT(i, v)    (((v) & 0x3) << (i * 4))
+#define  TRANSCFG_SID_HW       0
+#define  TRANSCFG_SID_PHY      1
+#define  TRANSCFG_SID_FALCON   2
+
 /* Firmware offsets */
 
 #define VIC_UCODE_FCE_HEADER_OFFSET            (6*4)