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

This commit is contained in:
qctecmdr
2020-02-27 14:37:43 -08:00
committed by Gerrit - the friendly Code Review server
5 changed files with 120 additions and 29 deletions

View File

@@ -2,6 +2,7 @@
/* /*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
*/ */
#include <linux/iopoll.h>
#include "sde_hwio.h" #include "sde_hwio.h"
#include "sde_hw_catalog.h" #include "sde_hw_catalog.h"
@@ -9,6 +10,7 @@
#include "sde_dbg.h" #include "sde_dbg.h"
#define VBIF_VERSION 0x0000 #define VBIF_VERSION 0x0000
#define VBIF_CLKON 0x0004
#define VBIF_CLK_FORCE_CTRL0 0x0008 #define VBIF_CLK_FORCE_CTRL0 0x0008
#define VBIF_CLK_FORCE_CTRL1 0x000C #define VBIF_CLK_FORCE_CTRL1 0x000C
#define VBIF_QOS_REMAP_00 0x0020 #define VBIF_QOS_REMAP_00 0x0020
@@ -33,6 +35,8 @@
#define VBIF_XIN_CLR_ERR 0x019C #define VBIF_XIN_CLR_ERR 0x019C
#define VBIF_XIN_HALT_CTRL0 0x0200 #define VBIF_XIN_HALT_CTRL0 0x0200
#define VBIF_XIN_HALT_CTRL1 0x0204 #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_RP_REMAP_000 0x0550
#define VBIF_XINL_QOS_LVL_REMAP_000 0x0590 #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; 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) u32 xin_id, bool enable)
{ {
struct sde_hw_blk_reg_map *c = &vbif->hw; 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); reg_val &= ~BIT(xin_id);
SDE_REG_WRITE(c, VBIF_XIN_HALT_CTRL0, reg_val); 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) u32 xin_id)
{ {
struct sde_hw_blk_reg_map *c = &vbif->hw; 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; 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, static void sde_hw_set_qos_remap(struct sde_hw_vbif *vbif,
u32 xin_id, u32 level, u32 remap_level) 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->set_limit_conf = sde_hw_set_limit_conf;
ops->get_limit_conf = sde_hw_get_limit_conf; ops->get_limit_conf = sde_hw_get_limit_conf;
ops->set_halt_ctrl = sde_hw_set_halt_ctrl; ops->set_axi_halt = sde_hw_set_axi_halt;
ops->get_halt_ctrl = sde_hw_get_halt_ctrl; 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)) if (test_bit(SDE_VBIF_QOS_REMAP, &cap))
ops->set_qos_remap = sde_hw_set_qos_remap; ops->set_qos_remap = sde_hw_set_qos_remap;
if (test_bit(SDE_VBIF_DISABLE_SHAREABLE, &cap)) if (test_bit(SDE_VBIF_DISABLE_SHAREABLE, &cap))

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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 #ifndef _SDE_HW_VBIF_H
@@ -38,23 +38,35 @@ struct sde_hw_vbif_ops {
u32 xin_id, bool rd); u32 xin_id, bool rd);
/** /**
* set_halt_ctrl - set halt control * set_xin_halt - set xin client halt control
* @vbif: vbif context driver * @vbif: vbif context driver
* @xin_id: client interface identifier * @xin_id: client interface identifier
* @enable: halt control enable * @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); u32 xin_id, bool enable);
/** /**
* get_halt_ctrl - get halt control * get_xin_halt_status - get xin client halt control
* @vbif: vbif context driver * @vbif: vbif context driver
* @xin_id: client interface identifier * @xin_id: client interface identifier
* @return: halt control enable * @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); 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 * set_qos_remap - set QoS priority remap
* @vbif: vbif context driver * @vbif: vbif context driver

View File

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

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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__ #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; bool status;
int rc; 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); SDE_ERROR("invalid arguments vbif %d\n", !vbif);
return -EINVAL; return -EINVAL;
} }
timeout = ktime_add_us(ktime_get(), vbif->cap->xin_halt_timeout); timeout = ktime_add_us(ktime_get(), vbif->cap->xin_halt_timeout);
for (;;) { for (;;) {
status = vbif->ops.get_halt_ctrl(vbif, xin_id); status = vbif->ops.get_xin_halt_status(vbif, xin_id);
if (status) if (status)
break; break;
if (ktime_compare_safe(ktime_get(), timeout) > 0) { 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; break;
} }
usleep_range(501, 1000); 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; 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) int sde_vbif_halt_plane_xin(struct sde_kms *sde_kms, u32 xin_id, u32 clk_ctrl)
{ {
struct sde_hw_vbif *vbif = NULL; 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]; vbif = sde_kms->hw_vbif[VBIF_RT];
mdp = sde_kms->hw_mdp; mdp = sde_kms->hw_mdp;
if (!vbif || !mdp || !vbif->ops.get_halt_ctrl || if (!vbif || !mdp || !vbif->ops.get_xin_halt_status ||
!vbif->ops.set_halt_ctrl || !vbif->ops.set_xin_halt ||
!mdp->ops.setup_clk_force_ctrl) { !mdp->ops.setup_clk_force_ctrl) {
SDE_ERROR("invalid vbif or mdp arguments\n"); SDE_ERROR("invalid vbif or mdp arguments\n");
return -EINVAL; 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 * while halting by forcing it ON only if it was not previously
* forced on. If status is 1 then its already halted. * 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) { if (status) {
mutex_unlock(&vbif->mutex); mutex_unlock(&vbif->mutex);
return 0; 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); forced_on = mdp->ops.setup_clk_force_ctrl(mdp, clk_ctrl, true);
/* send halt request for unused plane's xin client */ /* 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); rc = _sde_vbif_wait_for_xin_halt(vbif, xin_id);
if (rc) { 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 */ /* 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) if (forced_on)
mdp->ops.setup_clk_force_ctrl(mdp, clk_ctrl, false); 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 || if (!mdp->ops.setup_clk_force_ctrl ||
!vbif->ops.set_limit_conf || !vbif->ops.set_limit_conf ||
!vbif->ops.set_halt_ctrl) !vbif->ops.set_xin_halt)
return; return;
mutex_lock(&vbif->mutex); 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_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); ret = _sde_vbif_wait_for_xin_halt(vbif, params->xin_id);
if (ret) if (ret)
SDE_EVT32(vbif->idx, params->xin_id); 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) if (forced_on)
mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, false); 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 || if (!mdp->ops.setup_clk_force_ctrl ||
!vbif->ops.set_halt_ctrl) !vbif->ops.set_xin_halt)
return false; return false;
mutex_lock(&vbif->mutex); 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, forced_on = mdp->ops.setup_clk_force_ctrl(mdp,
params->clk_ctrl, true); 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); ret = _sde_vbif_wait_for_xin_halt(vbif, params->xin_id);
if (ret) if (ret)
SDE_EVT32(vbif->idx, params->xin_id, SDE_EVTLOG_ERROR); SDE_EVT32(vbif->idx, params->xin_id, SDE_EVTLOG_ERROR);
} else { } 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) if (params->forced_on)
mdp->ops.setup_clk_force_ctrl(mdp, 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, int sde_vbif_halt_xin_mask(struct sde_kms *sde_kms, u32 xin_id_mask,
bool halt) 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]; 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; return 0;
SDE_EVT32(xin_id_mask, halt); 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)) { if (xin_id_mask & BIT(i)) {
/* unhalt the xin-clients */ /* unhalt the xin-clients */
if (!halt) { if (!halt) {
vbif->ops.set_halt_ctrl(vbif, i, false); vbif->ops.set_xin_halt(vbif, i, false);
continue; continue;
} }
status = vbif->ops.get_halt_ctrl(vbif, i); status = vbif->ops.get_xin_halt_status(vbif, i);
if (status) if (status)
continue; continue;
/* halt xin-clients and wait for ack */ /* 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); rc = _sde_vbif_wait_for_xin_halt(vbif, i);
if (rc) { if (rc) {

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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__ #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); 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 * 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. * On unused plane, check if the vbif for this plane is idle or not.