[PATCH v3 1/2] drm/komeda: Adds SMMU support

2019-06-12 Thread Lowry Li (Arm Technology China)
From: "Lowry Li (Arm Technology China)" 

Adds iommu_connect and disconnect for SMMU support, and configures
TBU translation once SMMU has been attached to the display device.

Signed-off-by: Lowry Li (Arm Technology China) 
---
 .../gpu/drm/arm/display/komeda/d71/d71_component.c |  5 +++
 drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c   | 49 ++
 drivers/gpu/drm/arm/display/komeda/komeda_dev.c| 18 
 drivers/gpu/drm/arm/display/komeda/komeda_dev.h|  7 
 .../drm/arm/display/komeda/komeda_framebuffer.c|  2 +
 .../drm/arm/display/komeda/komeda_framebuffer.h|  2 +
 6 files changed, 83 insertions(+)

diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c 
b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
index 4e26a80..4a48dd6 100644
--- a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
+++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
@@ -215,6 +215,8 @@ static void d71_layer_update(struct komeda_component *c,
malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id);
malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize));
 
+   if (kfb->is_va)
+   ctrl |= L_TBU_EN;
malidp_write32_mask(reg, BLK_CONTROL, ctrl_mask, ctrl);
 }
 
@@ -348,6 +350,9 @@ static void d71_wb_layer_update(struct komeda_component *c,
   fb->pitches[i] & 0x);
}
 
+   if (kfb->is_va)
+   ctrl |= LW_TBU_EN;
+
malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id);
malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize));
malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(>inputs[0]));
diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c 
b/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c
index 8e682c7..3dab5077 100644
--- a/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c
+++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c
@@ -517,6 +517,53 @@ static void d71_init_fmt_tbl(struct komeda_dev *mdev)
table->n_formats = ARRAY_SIZE(d71_format_caps_table);
 }
 
+static int d71_connect_iommu(struct komeda_dev *mdev)
+{
+   struct d71_dev *d71 = mdev->chip_data;
+   u32 __iomem *reg = d71->gcu_addr;
+   u32 check_bits = (d71->num_pipelines == 2) ?
+GCU_STATUS_TCS0 | GCU_STATUS_TCS1 : GCU_STATUS_TCS0;
+   int i, ret;
+
+   if (!d71->integrates_tbu)
+   return -1;
+
+   malidp_write32_mask(reg, BLK_CONTROL, 0x7, TBU_CONNECT_MODE);
+
+   ret = dp_wait_cond(has_bits(check_bits, malidp_read32(reg, BLK_STATUS)),
+   100, 1000, 1000);
+   if (ret < 0) {
+   DRM_ERROR("connect to TCU timeout!\n");
+   malidp_write32_mask(reg, BLK_CONTROL, 0x7, INACTIVE_MODE);
+   return ret;
+   }
+
+   for (i = 0; i < d71->num_pipelines; i++)
+   malidp_write32_mask(d71->pipes[i]->lpu_addr, LPU_TBU_CONTROL,
+   LPU_TBU_CTRL_TLBPEN, LPU_TBU_CTRL_TLBPEN);
+   return 0;
+}
+
+static int d71_disconnect_iommu(struct komeda_dev *mdev)
+{
+   struct d71_dev *d71 = mdev->chip_data;
+   u32 __iomem *reg = d71->gcu_addr;
+   u32 check_bits = (d71->num_pipelines == 2) ?
+GCU_STATUS_TCS0 | GCU_STATUS_TCS1 : GCU_STATUS_TCS0;
+   int ret;
+
+   malidp_write32_mask(reg, BLK_CONTROL, 0x7, TBU_DISCONNECT_MODE);
+
+   ret = dp_wait_cond(((malidp_read32(reg, BLK_STATUS) & check_bits) == 0),
+   100, 1000, 1000);
+   if (ret < 0) {
+   DRM_ERROR("disconnect from TCU timeout!\n");
+   malidp_write32_mask(reg, BLK_CONTROL, 0x7, INACTIVE_MODE);
+   }
+
+   return ret;
+}
+
 static struct komeda_dev_funcs d71_chip_funcs = {
.init_format_table = d71_init_fmt_tbl,
.enum_resources = d71_enum_resources,
@@ -527,6 +574,8 @@ static void d71_init_fmt_tbl(struct komeda_dev *mdev)
.on_off_vblank  = d71_on_off_vblank,
.change_opmode  = d71_change_opmode,
.flush  = d71_flush,
+   .connect_iommu  = d71_connect_iommu,
+   .disconnect_iommu = d71_disconnect_iommu,
 };
 
 struct komeda_dev_funcs *
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c 
b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
index c92e161..e80e673 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
@@ -253,6 +253,19 @@ struct komeda_dev *komeda_dev_create(struct device *dev)
dev->dma_parms = >dma_parms;
dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
 
+   mdev->iommu = iommu_get_domain_for_dev(mdev->dev);
+   if (!mdev->iommu)
+   DRM_INFO("continue without IOMMU support!\n");
+
+   if (mdev->iommu && mdev->funcs->connect_iommu) {
+   err = mdev->funcs->connect_iommu(mdev);
+   if (err) {
+   mdev->iommu = NULL;
+

[PATCH v3 1/2] drm/komeda: Adds SMMU support

2019-06-12 Thread Lowry Li (Arm Technology China)
From: "Lowry Li (Arm Technology China)" 

Adds iommu_connect and disconnect for SMMU support, and configures
TBU translation once SMMU has been attached to the display device.

Signed-off-by: Lowry Li (Arm Technology China) 
---
 .../gpu/drm/arm/display/komeda/d71/d71_component.c |  5 +++
 drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c   | 49 ++
 drivers/gpu/drm/arm/display/komeda/komeda_dev.c| 18 
 drivers/gpu/drm/arm/display/komeda/komeda_dev.h|  7 
 .../drm/arm/display/komeda/komeda_framebuffer.c|  2 +
 .../drm/arm/display/komeda/komeda_framebuffer.h|  2 +
 6 files changed, 83 insertions(+)

diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c 
b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
index 4e26a80..4a48dd6 100644
--- a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
+++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
@@ -215,6 +215,8 @@ static void d71_layer_update(struct komeda_component *c,
malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id);
malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize));
 
+   if (kfb->is_va)
+   ctrl |= L_TBU_EN;
malidp_write32_mask(reg, BLK_CONTROL, ctrl_mask, ctrl);
 }
 
@@ -348,6 +350,9 @@ static void d71_wb_layer_update(struct komeda_component *c,
   fb->pitches[i] & 0x);
}
 
+   if (kfb->is_va)
+   ctrl |= LW_TBU_EN;
+
malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id);
malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize));
malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(>inputs[0]));
diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c 
b/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c
index 8e682c7..f88d93a 100644
--- a/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c
+++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c
@@ -517,6 +517,53 @@ static void d71_init_fmt_tbl(struct komeda_dev *mdev)
table->n_formats = ARRAY_SIZE(d71_format_caps_table);
 }
 
+static int d71_connect_iommu(struct komeda_dev *mdev)
+{
+   struct d71_dev *d71 = mdev->chip_data;
+   u32 __iomem *reg = d71->gcu_addr;
+   u32 check_bits = (d71->num_pipelines == 2) ?
+GCU_STATUS_TCS0 | GCU_STATUS_TCS1 : GCU_STATUS_TCS0;
+   int i, ret;
+
+   if (!d71->integrates_tbu)
+   return -1;
+
+   malidp_write32_mask(reg, BLK_CONTROL, 0x7, TBU_CONNECT_MODE);
+
+   ret = dp_wait_cond(has_bits(check_bits, malidp_read32(reg, BLK_STATUS)),
+   100, 1000, 1000);
+   if (ret < 0) {
+   DRM_ERROR("connect to TCU timeout!\n");
+   malidp_write32_mask(reg, BLK_CONTROL, 0x7, INACTIVE_MODE);
+   return -ETIMEDOUT;
+   }
+
+   for (i = 0; i < d71->num_pipelines; i++)
+   malidp_write32_mask(d71->pipes[i]->lpu_addr, LPU_TBU_CONTROL,
+   LPU_TBU_CTRL_TLBPEN, LPU_TBU_CTRL_TLBPEN);
+   return 0;
+}
+
+static int d71_disconnect_iommu(struct komeda_dev *mdev)
+{
+   struct d71_dev *d71 = mdev->chip_data;
+   u32 __iomem *reg = d71->gcu_addr;
+   u32 check_bits = (d71->num_pipelines == 2) ?
+GCU_STATUS_TCS0 | GCU_STATUS_TCS1 : GCU_STATUS_TCS0;
+   int ret;
+
+   malidp_write32_mask(reg, BLK_CONTROL, 0x7, TBU_DISCONNECT_MODE);
+
+   ret = dp_wait_cond(((malidp_read32(reg, BLK_STATUS) & check_bits) == 0),
+   100, 1000, 1000);
+   if (ret < 0) {
+   DRM_ERROR("disconnect from TCU timeout!\n");
+   malidp_write32_mask(reg, BLK_CONTROL, 0x7, INACTIVE_MODE);
+   }
+
+   return ret;
+}
+
 static struct komeda_dev_funcs d71_chip_funcs = {
.init_format_table = d71_init_fmt_tbl,
.enum_resources = d71_enum_resources,
@@ -527,6 +574,8 @@ static void d71_init_fmt_tbl(struct komeda_dev *mdev)
.on_off_vblank  = d71_on_off_vblank,
.change_opmode  = d71_change_opmode,
.flush  = d71_flush,
+   .connect_iommu  = d71_connect_iommu,
+   .disconnect_iommu = d71_disconnect_iommu,
 };
 
 struct komeda_dev_funcs *
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c 
b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
index c92e161..e80e673 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
@@ -253,6 +253,19 @@ struct komeda_dev *komeda_dev_create(struct device *dev)
dev->dma_parms = >dma_parms;
dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
 
+   mdev->iommu = iommu_get_domain_for_dev(mdev->dev);
+   if (!mdev->iommu)
+   DRM_INFO("continue without IOMMU support!\n");
+
+   if (mdev->iommu && mdev->funcs->connect_iommu) {
+   err = mdev->funcs->connect_iommu(mdev);
+   if (err) {
+   mdev->iommu =