فهرست منبع

disp: msm: sde: add vbif axi port halt request support

Add vbif axi port halt request support before
MDSS core GDSC power collapse state. It is needed
for targets without MDSS RSC support.

Change-Id: I1fbf281c4206ecd4ad1c2d1348a95e002740e2f1
Signed-off-by: Dhaval Patel <[email protected]>
Dhaval Patel 5 سال پیش
والد
کامیت
ac8fbffff5
5فایلهای تغییر یافته به همراه120 افزوده شده و 29 حذف شده
  1. 29 4
      msm/sde/sde_hw_vbif.c
  2. 17 5
      msm/sde/sde_hw_vbif.h
  3. 2 0
      msm/sde/sde_kms.c
  4. 65 19
      msm/sde/sde_vbif.c
  5. 7 1
      msm/sde/sde_vbif.h

+ 29 - 4
msm/sde/sde_hw_vbif.c

@@ -2,6 +2,7 @@
 /*
  * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
  */
+#include <linux/iopoll.h>
 
 #include "sde_hwio.h"
 #include "sde_hw_catalog.h"
@@ -9,6 +10,7 @@
 #include "sde_dbg.h"
 
 #define VBIF_VERSION			0x0000
+#define VBIF_CLKON			0x0004
 #define VBIF_CLK_FORCE_CTRL0		0x0008
 #define VBIF_CLK_FORCE_CTRL1		0x000C
 #define VBIF_QOS_REMAP_00		0x0020
@@ -33,6 +35,8 @@
 #define VBIF_XIN_CLR_ERR		0x019C
 #define VBIF_XIN_HALT_CTRL0		0x0200
 #define VBIF_XIN_HALT_CTRL1		0x0204
+#define VBIF_AXI_HALT_CTRL0		0x0208
+#define VBIF_AXI_HALT_CTRL1		0x020c
 #define VBIF_XINL_QOS_RP_REMAP_000	0x0550
 #define VBIF_XINL_QOS_LVL_REMAP_000	0x0590
 
@@ -154,7 +158,7 @@ static u32 sde_hw_get_limit_conf(struct sde_hw_vbif *vbif,
 	return limit;
 }
 
-static void sde_hw_set_halt_ctrl(struct sde_hw_vbif *vbif,
+static void sde_hw_set_xin_halt(struct sde_hw_vbif *vbif,
 		u32 xin_id, bool enable)
 {
 	struct sde_hw_blk_reg_map *c = &vbif->hw;
@@ -168,9 +172,10 @@ static void sde_hw_set_halt_ctrl(struct sde_hw_vbif *vbif,
 		reg_val &= ~BIT(xin_id);
 
 	SDE_REG_WRITE(c, VBIF_XIN_HALT_CTRL0, reg_val);
+	wmb(); /* make sure that xin client halted */
 }
 
-static bool sde_hw_get_halt_ctrl(struct sde_hw_vbif *vbif,
+static bool sde_hw_get_xin_halt_status(struct sde_hw_vbif *vbif,
 		u32 xin_id)
 {
 	struct sde_hw_blk_reg_map *c = &vbif->hw;
@@ -181,6 +186,24 @@ static bool sde_hw_get_halt_ctrl(struct sde_hw_vbif *vbif,
 	return ((reg_val >> 16) & BIT(xin_id)) ? true : false;
 }
 
+static void sde_hw_set_axi_halt(struct sde_hw_vbif *vbif)
+{
+	struct sde_hw_blk_reg_map *c = &vbif->hw;
+
+	SDE_REG_WRITE(c, VBIF_CLKON, BIT(0));
+	SDE_REG_WRITE(c, VBIF_AXI_HALT_CTRL0, BIT(0));
+	wmb(); /* make sure that axi transactions are halted */
+}
+
+static int sde_hw_get_axi_halt_status(struct sde_hw_vbif *vbif)
+{
+	struct sde_hw_blk_reg_map *c = &vbif->hw;
+	int ctrl = 0;
+
+	return readl_poll_timeout(c->base_off + c->blk_off +
+		VBIF_AXI_HALT_CTRL1, ctrl, ctrl & BIT(0), 100, 4000);
+}
+
 static void sde_hw_set_qos_remap(struct sde_hw_vbif *vbif,
 		u32 xin_id, u32 level, u32 remap_level)
 {
@@ -230,8 +253,10 @@ static void _setup_vbif_ops(const struct sde_mdss_cfg *m,
 {
 	ops->set_limit_conf = sde_hw_set_limit_conf;
 	ops->get_limit_conf = sde_hw_get_limit_conf;
-	ops->set_halt_ctrl = sde_hw_set_halt_ctrl;
-	ops->get_halt_ctrl = sde_hw_get_halt_ctrl;
+	ops->set_axi_halt = sde_hw_set_axi_halt;
+	ops->get_axi_halt_status = sde_hw_get_axi_halt_status;
+	ops->set_xin_halt = sde_hw_set_xin_halt;
+	ops->get_xin_halt_status = sde_hw_get_xin_halt_status;
 	if (test_bit(SDE_VBIF_QOS_REMAP, &cap))
 		ops->set_qos_remap = sde_hw_set_qos_remap;
 	if (test_bit(SDE_VBIF_DISABLE_SHAREABLE, &cap))

+ 17 - 5
msm/sde/sde_hw_vbif.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _SDE_HW_VBIF_H
@@ -38,23 +38,35 @@ struct sde_hw_vbif_ops {
 			u32 xin_id, bool rd);
 
 	/**
-	 * set_halt_ctrl - set halt control
+	 * set_xin_halt - set xin client halt control
 	 * @vbif: vbif context driver
 	 * @xin_id: client interface identifier
 	 * @enable: halt control enable
 	 */
-	void (*set_halt_ctrl)(struct sde_hw_vbif *vbif,
+	void (*set_xin_halt)(struct sde_hw_vbif *vbif,
 			u32 xin_id, bool enable);
 
 	/**
-	 * get_halt_ctrl - get halt control
+	 * get_xin_halt_status - get xin client halt control
 	 * @vbif: vbif context driver
 	 * @xin_id: client interface identifier
 	 * @return: halt control enable
 	 */
-	bool (*get_halt_ctrl)(struct sde_hw_vbif *vbif,
+	bool (*get_xin_halt_status)(struct sde_hw_vbif *vbif,
 			u32 xin_id);
 
+	/**
+	 * set_axi_halt - set axi port halt control
+	 * @vbif: vbif context driver
+	 */
+	void (*set_axi_halt)(struct sde_hw_vbif *vbif);
+
+	/**
+	 * get_axi_halt_status - get axi port halt control status
+	 * @vbif: vbif context driver
+	 */
+	int (*get_axi_halt_status)(struct sde_hw_vbif *vbif);
+
 	/**
 	 * set_qos_remap - set QoS priority remap
 	 * @vbif: vbif context driver

+ 2 - 0
msm/sde/sde_kms.c

@@ -2947,6 +2947,8 @@ static void sde_kms_handle_power_event(u32 event_type, void *usr)
 		sde_irq_update(msm_kms, false);
 		sde_kms->first_kickoff = false;
 		_sde_kms_active_override(sde_kms, true);
+		if (!is_sde_rsc_available(SDE_RSC_INDEX))
+			sde_vbif_axi_halt_request(sde_kms);
 	}
 }
 

+ 65 - 19
msm/sde/sde_vbif.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
  */
 
 #define pr_fmt(fmt)	"[drm:%s:%d] " fmt, __func__, __LINE__
@@ -26,18 +26,18 @@ static int _sde_vbif_wait_for_xin_halt(struct sde_hw_vbif *vbif, u32 xin_id)
 	bool status;
 	int rc;
 
-	if (!vbif || !vbif->cap || !vbif->ops.get_halt_ctrl) {
+	if (!vbif || !vbif->cap || !vbif->ops.get_xin_halt_status) {
 		SDE_ERROR("invalid arguments vbif %d\n", !vbif);
 		return -EINVAL;
 	}
 
 	timeout = ktime_add_us(ktime_get(), vbif->cap->xin_halt_timeout);
 	for (;;) {
-		status = vbif->ops.get_halt_ctrl(vbif, xin_id);
+		status = vbif->ops.get_xin_halt_status(vbif, xin_id);
 		if (status)
 			break;
 		if (ktime_compare_safe(ktime_get(), timeout) > 0) {
-			status = vbif->ops.get_halt_ctrl(vbif, xin_id);
+			status = vbif->ops.get_xin_halt_status(vbif, xin_id);
 			break;
 		}
 		usleep_range(501, 1000);
@@ -56,6 +56,26 @@ static int _sde_vbif_wait_for_xin_halt(struct sde_hw_vbif *vbif, u32 xin_id)
 	return rc;
 }
 
+static int _sde_vbif_wait_for_axi_halt(struct sde_hw_vbif *vbif)
+{
+	int rc;
+
+	if (!vbif || !vbif->cap || !vbif->ops.get_axi_halt_status) {
+		SDE_ERROR("invalid arguments vbif %d\n", !vbif);
+		return -EINVAL;
+	}
+
+	rc = vbif->ops.get_axi_halt_status(vbif);
+	if (rc)
+		SDE_ERROR("VBIF %d AXI port(s) not halting. TIMEDOUT.\n",
+				vbif->idx - VBIF_0);
+	else
+		SDE_DEBUG("VBIF %d AXI port(s) halted\n",
+				vbif->idx - VBIF_0);
+
+	return rc;
+}
+
 int sde_vbif_halt_plane_xin(struct sde_kms *sde_kms, u32 xin_id, u32 clk_ctrl)
 {
 	struct sde_hw_vbif *vbif = NULL;
@@ -76,8 +96,8 @@ int sde_vbif_halt_plane_xin(struct sde_kms *sde_kms, u32 xin_id, u32 clk_ctrl)
 
 	vbif = sde_kms->hw_vbif[VBIF_RT];
 	mdp = sde_kms->hw_mdp;
-	if (!vbif || !mdp || !vbif->ops.get_halt_ctrl ||
-		       !vbif->ops.set_halt_ctrl ||
+	if (!vbif || !mdp || !vbif->ops.get_xin_halt_status ||
+		       !vbif->ops.set_xin_halt ||
 		       !mdp->ops.setup_clk_force_ctrl) {
 		SDE_ERROR("invalid vbif or mdp arguments\n");
 		return -EINVAL;
@@ -92,7 +112,7 @@ int sde_vbif_halt_plane_xin(struct sde_kms *sde_kms, u32 xin_id, u32 clk_ctrl)
 	 * while halting by forcing it ON only if it was not previously
 	 * forced on. If status is 1 then its already halted.
 	 */
-	status = vbif->ops.get_halt_ctrl(vbif, xin_id);
+	status = vbif->ops.get_xin_halt_status(vbif, xin_id);
 	if (status) {
 		mutex_unlock(&vbif->mutex);
 		return 0;
@@ -101,7 +121,7 @@ int sde_vbif_halt_plane_xin(struct sde_kms *sde_kms, u32 xin_id, u32 clk_ctrl)
 	forced_on = mdp->ops.setup_clk_force_ctrl(mdp, clk_ctrl, true);
 
 	/* send halt request for unused plane's xin client */
-	vbif->ops.set_halt_ctrl(vbif, xin_id, true);
+	vbif->ops.set_xin_halt(vbif, xin_id, true);
 
 	rc = _sde_vbif_wait_for_xin_halt(vbif, xin_id);
 	if (rc) {
@@ -112,7 +132,7 @@ int sde_vbif_halt_plane_xin(struct sde_kms *sde_kms, u32 xin_id, u32 clk_ctrl)
 	}
 
 	/* open xin client to enable transactions */
-	vbif->ops.set_halt_ctrl(vbif, xin_id, false);
+	vbif->ops.set_xin_halt(vbif, xin_id, false);
 	if (forced_on)
 		mdp->ops.setup_clk_force_ctrl(mdp, clk_ctrl, false);
 
@@ -250,7 +270,7 @@ void sde_vbif_set_ot_limit(struct sde_kms *sde_kms,
 
 	if (!mdp->ops.setup_clk_force_ctrl ||
 			!vbif->ops.set_limit_conf ||
-			!vbif->ops.set_halt_ctrl)
+			!vbif->ops.set_xin_halt)
 		return;
 
 	mutex_lock(&vbif->mutex);
@@ -273,13 +293,13 @@ void sde_vbif_set_ot_limit(struct sde_kms *sde_kms,
 
 	vbif->ops.set_limit_conf(vbif, params->xin_id, params->rd, ot_lim);
 
-	vbif->ops.set_halt_ctrl(vbif, params->xin_id, true);
+	vbif->ops.set_xin_halt(vbif, params->xin_id, true);
 
 	ret = _sde_vbif_wait_for_xin_halt(vbif, params->xin_id);
 	if (ret)
 		SDE_EVT32(vbif->idx, params->xin_id);
 
-	vbif->ops.set_halt_ctrl(vbif, params->xin_id, false);
+	vbif->ops.set_xin_halt(vbif, params->xin_id, false);
 
 	if (forced_on)
 		mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, false);
@@ -357,7 +377,7 @@ bool sde_vbif_set_xin_halt(struct sde_kms *sde_kms,
 	}
 
 	if (!mdp->ops.setup_clk_force_ctrl ||
-			!vbif->ops.set_halt_ctrl)
+			!vbif->ops.set_xin_halt)
 		return false;
 
 	mutex_lock(&vbif->mutex);
@@ -368,13 +388,13 @@ bool sde_vbif_set_xin_halt(struct sde_kms *sde_kms,
 		forced_on = mdp->ops.setup_clk_force_ctrl(mdp,
 				params->clk_ctrl, true);
 
-		vbif->ops.set_halt_ctrl(vbif, params->xin_id, true);
+		vbif->ops.set_xin_halt(vbif, params->xin_id, true);
 
 		ret = _sde_vbif_wait_for_xin_halt(vbif, params->xin_id);
 		if (ret)
 			SDE_EVT32(vbif->idx, params->xin_id, SDE_EVTLOG_ERROR);
 	} else {
-		vbif->ops.set_halt_ctrl(vbif, params->xin_id, false);
+		vbif->ops.set_xin_halt(vbif, params->xin_id, false);
 
 		if (params->forced_on)
 			mdp->ops.setup_clk_force_ctrl(mdp,
@@ -511,6 +531,32 @@ void sde_vbif_init_memtypes(struct sde_kms *sde_kms)
 	}
 }
 
+void sde_vbif_axi_halt_request(struct sde_kms *sde_kms)
+{
+	struct sde_hw_vbif *vbif;
+	int i;
+
+	if (!sde_kms) {
+		SDE_ERROR("invalid argument\n");
+		return;
+	}
+
+	if (!sde_kms_is_vbif_operation_allowed(sde_kms)) {
+		SDE_DEBUG("vbif operations not permitted\n");
+		return;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(sde_kms->hw_vbif); i++) {
+		vbif = sde_kms->hw_vbif[i];
+		if (vbif && vbif->cap && vbif->ops.set_axi_halt) {
+			mutex_lock(&vbif->mutex);
+			vbif->ops.set_axi_halt(vbif);
+			_sde_vbif_wait_for_axi_halt(vbif);
+			mutex_unlock(&vbif->mutex);
+		}
+	}
+}
+
 int sde_vbif_halt_xin_mask(struct sde_kms *sde_kms, u32 xin_id_mask,
 				bool halt)
 {
@@ -524,7 +570,7 @@ int sde_vbif_halt_xin_mask(struct sde_kms *sde_kms, u32 xin_id_mask,
 
 	vbif = sde_kms->hw_vbif[VBIF_RT];
 
-	if (!vbif->ops.get_halt_ctrl || !vbif->ops.set_halt_ctrl)
+	if (!vbif->ops.get_xin_halt_status || !vbif->ops.set_xin_halt)
 		return 0;
 
 	SDE_EVT32(xin_id_mask, halt);
@@ -533,16 +579,16 @@ int sde_vbif_halt_xin_mask(struct sde_kms *sde_kms, u32 xin_id_mask,
 		if (xin_id_mask & BIT(i)) {
 			/* unhalt the xin-clients */
 			if (!halt) {
-				vbif->ops.set_halt_ctrl(vbif, i, false);
+				vbif->ops.set_xin_halt(vbif, i, false);
 				continue;
 			}
 
-			status = vbif->ops.get_halt_ctrl(vbif, i);
+			status = vbif->ops.get_xin_halt_status(vbif, i);
 			if (status)
 				continue;
 
 			/* halt xin-clients and wait for ack */
-			vbif->ops.set_halt_ctrl(vbif, i, true);
+			vbif->ops.set_xin_halt(vbif, i, true);
 
 			rc = _sde_vbif_wait_for_xin_halt(vbif, i);
 			if (rc) {

+ 7 - 1
msm/sde/sde_vbif.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
  */
 
 #ifndef __SDE_VBIF_H__
@@ -98,6 +98,12 @@ void sde_vbif_clear_errors(struct sde_kms *sde_kms);
  */
 void sde_vbif_init_memtypes(struct sde_kms *sde_kms);
 
+/**
+ * sde_vbif_axi_halt_request - halt all axi transcations on vbif
+ * @sde_kms:	SDE handler
+ */
+void sde_vbif_axi_halt_request(struct sde_kms *sde_kms);
+
 /**
  * sde_vbif_halt_plane_xin - halts the xin client for the unused plane
  * On unused plane, check if the vbif for this plane is idle or not.