Sfoglia il codice sorgente

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

qctecmdr 5 anni fa
parent
commit
9d96e47c53
5 ha cambiato i file con 120 aggiunte e 29 eliminazioni
  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

@@ -2948,6 +2948,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.