xref: /linux/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c (revision 4db102dcb0396a4ccf89b1eac0f4eb3fd167a080)
197fb5e8dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
225fdd593SJeykumar Sankaran /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
325fdd593SJeykumar Sankaran  */
425fdd593SJeykumar Sankaran 
5*bdfa47d9SDmitry Baryshkov #include <drm/drm_managed.h>
6*bdfa47d9SDmitry Baryshkov 
725fdd593SJeykumar Sankaran #include "dpu_hwio.h"
825fdd593SJeykumar Sankaran #include "dpu_hw_catalog.h"
925fdd593SJeykumar Sankaran #include "dpu_hw_vbif.h"
1025fdd593SJeykumar Sankaran 
1125fdd593SJeykumar Sankaran #define VBIF_VERSION			0x0000
1225fdd593SJeykumar Sankaran #define VBIF_CLK_FORCE_CTRL0		0x0008
1325fdd593SJeykumar Sankaran #define VBIF_CLK_FORCE_CTRL1		0x000C
1425fdd593SJeykumar Sankaran #define VBIF_QOS_REMAP_00		0x0020
1525fdd593SJeykumar Sankaran #define VBIF_QOS_REMAP_01		0x0024
1625fdd593SJeykumar Sankaran #define VBIF_QOS_REMAP_10		0x0028
1725fdd593SJeykumar Sankaran #define VBIF_QOS_REMAP_11		0x002C
1825fdd593SJeykumar Sankaran #define VBIF_WRITE_GATHER_EN		0x00AC
1925fdd593SJeykumar Sankaran #define VBIF_IN_RD_LIM_CONF0		0x00B0
2025fdd593SJeykumar Sankaran #define VBIF_IN_RD_LIM_CONF1		0x00B4
2125fdd593SJeykumar Sankaran #define VBIF_IN_RD_LIM_CONF2		0x00B8
2225fdd593SJeykumar Sankaran #define VBIF_IN_WR_LIM_CONF0		0x00C0
2325fdd593SJeykumar Sankaran #define VBIF_IN_WR_LIM_CONF1		0x00C4
2425fdd593SJeykumar Sankaran #define VBIF_IN_WR_LIM_CONF2		0x00C8
2525fdd593SJeykumar Sankaran #define VBIF_OUT_RD_LIM_CONF0		0x00D0
2625fdd593SJeykumar Sankaran #define VBIF_OUT_WR_LIM_CONF0		0x00D4
2725fdd593SJeykumar Sankaran #define VBIF_OUT_AXI_AMEMTYPE_CONF0	0x0160
2825fdd593SJeykumar Sankaran #define VBIF_OUT_AXI_AMEMTYPE_CONF1	0x0164
2925fdd593SJeykumar Sankaran #define VBIF_XIN_PND_ERR		0x0190
3025fdd593SJeykumar Sankaran #define VBIF_XIN_SRC_ERR		0x0194
3125fdd593SJeykumar Sankaran #define VBIF_XIN_CLR_ERR		0x019C
3225fdd593SJeykumar Sankaran #define VBIF_XIN_HALT_CTRL0		0x0200
3325fdd593SJeykumar Sankaran #define VBIF_XIN_HALT_CTRL1		0x0204
3425fdd593SJeykumar Sankaran #define VBIF_XINL_QOS_RP_REMAP_000	0x0550
35c8744315SDmitry Baryshkov #define VBIF_XINL_QOS_LVL_REMAP_000(vbif)	(VBIF_XINL_QOS_RP_REMAP_000 + (vbif)->cap->qos_rp_remap_size)
3625fdd593SJeykumar Sankaran 
dpu_hw_clear_errors(struct dpu_hw_vbif * vbif,u32 * pnd_errors,u32 * src_errors)3725fdd593SJeykumar Sankaran static void dpu_hw_clear_errors(struct dpu_hw_vbif *vbif,
3825fdd593SJeykumar Sankaran 		u32 *pnd_errors, u32 *src_errors)
3925fdd593SJeykumar Sankaran {
4025fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c;
4125fdd593SJeykumar Sankaran 	u32 pnd, src;
4225fdd593SJeykumar Sankaran 
4325fdd593SJeykumar Sankaran 	if (!vbif)
4425fdd593SJeykumar Sankaran 		return;
4525fdd593SJeykumar Sankaran 	c = &vbif->hw;
4625fdd593SJeykumar Sankaran 	pnd = DPU_REG_READ(c, VBIF_XIN_PND_ERR);
4725fdd593SJeykumar Sankaran 	src = DPU_REG_READ(c, VBIF_XIN_SRC_ERR);
4825fdd593SJeykumar Sankaran 
4925fdd593SJeykumar Sankaran 	if (pnd_errors)
5025fdd593SJeykumar Sankaran 		*pnd_errors = pnd;
5125fdd593SJeykumar Sankaran 	if (src_errors)
5225fdd593SJeykumar Sankaran 		*src_errors = src;
5325fdd593SJeykumar Sankaran 
5425fdd593SJeykumar Sankaran 	DPU_REG_WRITE(c, VBIF_XIN_CLR_ERR, pnd | src);
5525fdd593SJeykumar Sankaran }
5625fdd593SJeykumar Sankaran 
dpu_hw_set_mem_type(struct dpu_hw_vbif * vbif,u32 xin_id,u32 value)5725fdd593SJeykumar Sankaran static void dpu_hw_set_mem_type(struct dpu_hw_vbif *vbif,
5825fdd593SJeykumar Sankaran 		u32 xin_id, u32 value)
5925fdd593SJeykumar Sankaran {
6025fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c;
6125fdd593SJeykumar Sankaran 	u32 reg_off;
6225fdd593SJeykumar Sankaran 	u32 bit_off;
6325fdd593SJeykumar Sankaran 	u32 reg_val;
6425fdd593SJeykumar Sankaran 
6525fdd593SJeykumar Sankaran 	/*
6625fdd593SJeykumar Sankaran 	 * Assume 4 bits per bit field, 8 fields per 32-bit register so
6725fdd593SJeykumar Sankaran 	 * 16 bit fields maximum across two registers
6825fdd593SJeykumar Sankaran 	 */
6925fdd593SJeykumar Sankaran 	if (!vbif || xin_id >= MAX_XIN_COUNT || xin_id >= 16)
7025fdd593SJeykumar Sankaran 		return;
7125fdd593SJeykumar Sankaran 
7225fdd593SJeykumar Sankaran 	c = &vbif->hw;
7325fdd593SJeykumar Sankaran 
7425fdd593SJeykumar Sankaran 	if (xin_id >= 8) {
7525fdd593SJeykumar Sankaran 		xin_id -= 8;
7625fdd593SJeykumar Sankaran 		reg_off = VBIF_OUT_AXI_AMEMTYPE_CONF1;
7725fdd593SJeykumar Sankaran 	} else {
7825fdd593SJeykumar Sankaran 		reg_off = VBIF_OUT_AXI_AMEMTYPE_CONF0;
7925fdd593SJeykumar Sankaran 	}
8025fdd593SJeykumar Sankaran 	bit_off = (xin_id & 0x7) * 4;
8125fdd593SJeykumar Sankaran 	reg_val = DPU_REG_READ(c, reg_off);
8225fdd593SJeykumar Sankaran 	reg_val &= ~(0x7 << bit_off);
8325fdd593SJeykumar Sankaran 	reg_val |= (value & 0x7) << bit_off;
8425fdd593SJeykumar Sankaran 	DPU_REG_WRITE(c, reg_off, reg_val);
8525fdd593SJeykumar Sankaran }
8625fdd593SJeykumar Sankaran 
dpu_hw_set_limit_conf(struct dpu_hw_vbif * vbif,u32 xin_id,bool rd,u32 limit)8725fdd593SJeykumar Sankaran static void dpu_hw_set_limit_conf(struct dpu_hw_vbif *vbif,
8825fdd593SJeykumar Sankaran 		u32 xin_id, bool rd, u32 limit)
8925fdd593SJeykumar Sankaran {
9025fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c = &vbif->hw;
9125fdd593SJeykumar Sankaran 	u32 reg_val;
9225fdd593SJeykumar Sankaran 	u32 reg_off;
9325fdd593SJeykumar Sankaran 	u32 bit_off;
9425fdd593SJeykumar Sankaran 
9525fdd593SJeykumar Sankaran 	if (rd)
9625fdd593SJeykumar Sankaran 		reg_off = VBIF_IN_RD_LIM_CONF0;
9725fdd593SJeykumar Sankaran 	else
9825fdd593SJeykumar Sankaran 		reg_off = VBIF_IN_WR_LIM_CONF0;
9925fdd593SJeykumar Sankaran 
10025fdd593SJeykumar Sankaran 	reg_off += (xin_id / 4) * 4;
10125fdd593SJeykumar Sankaran 	bit_off = (xin_id % 4) * 8;
10225fdd593SJeykumar Sankaran 	reg_val = DPU_REG_READ(c, reg_off);
10325fdd593SJeykumar Sankaran 	reg_val &= ~(0xFF << bit_off);
10425fdd593SJeykumar Sankaran 	reg_val |= (limit) << bit_off;
10525fdd593SJeykumar Sankaran 	DPU_REG_WRITE(c, reg_off, reg_val);
10625fdd593SJeykumar Sankaran }
10725fdd593SJeykumar Sankaran 
dpu_hw_get_limit_conf(struct dpu_hw_vbif * vbif,u32 xin_id,bool rd)10825fdd593SJeykumar Sankaran static u32 dpu_hw_get_limit_conf(struct dpu_hw_vbif *vbif,
10925fdd593SJeykumar Sankaran 		u32 xin_id, bool rd)
11025fdd593SJeykumar Sankaran {
11125fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c = &vbif->hw;
11225fdd593SJeykumar Sankaran 	u32 reg_val;
11325fdd593SJeykumar Sankaran 	u32 reg_off;
11425fdd593SJeykumar Sankaran 	u32 bit_off;
11525fdd593SJeykumar Sankaran 	u32 limit;
11625fdd593SJeykumar Sankaran 
11725fdd593SJeykumar Sankaran 	if (rd)
11825fdd593SJeykumar Sankaran 		reg_off = VBIF_IN_RD_LIM_CONF0;
11925fdd593SJeykumar Sankaran 	else
12025fdd593SJeykumar Sankaran 		reg_off = VBIF_IN_WR_LIM_CONF0;
12125fdd593SJeykumar Sankaran 
12225fdd593SJeykumar Sankaran 	reg_off += (xin_id / 4) * 4;
12325fdd593SJeykumar Sankaran 	bit_off = (xin_id % 4) * 8;
12425fdd593SJeykumar Sankaran 	reg_val = DPU_REG_READ(c, reg_off);
12525fdd593SJeykumar Sankaran 	limit = (reg_val >> bit_off) & 0xFF;
12625fdd593SJeykumar Sankaran 
12725fdd593SJeykumar Sankaran 	return limit;
12825fdd593SJeykumar Sankaran }
12925fdd593SJeykumar Sankaran 
dpu_hw_set_halt_ctrl(struct dpu_hw_vbif * vbif,u32 xin_id,bool enable)13025fdd593SJeykumar Sankaran static void dpu_hw_set_halt_ctrl(struct dpu_hw_vbif *vbif,
13125fdd593SJeykumar Sankaran 		u32 xin_id, bool enable)
13225fdd593SJeykumar Sankaran {
13325fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c = &vbif->hw;
13425fdd593SJeykumar Sankaran 	u32 reg_val;
13525fdd593SJeykumar Sankaran 
13625fdd593SJeykumar Sankaran 	reg_val = DPU_REG_READ(c, VBIF_XIN_HALT_CTRL0);
13725fdd593SJeykumar Sankaran 
13825fdd593SJeykumar Sankaran 	if (enable)
13925fdd593SJeykumar Sankaran 		reg_val |= BIT(xin_id);
14025fdd593SJeykumar Sankaran 	else
14125fdd593SJeykumar Sankaran 		reg_val &= ~BIT(xin_id);
14225fdd593SJeykumar Sankaran 
14325fdd593SJeykumar Sankaran 	DPU_REG_WRITE(c, VBIF_XIN_HALT_CTRL0, reg_val);
14425fdd593SJeykumar Sankaran }
14525fdd593SJeykumar Sankaran 
dpu_hw_get_halt_ctrl(struct dpu_hw_vbif * vbif,u32 xin_id)14625fdd593SJeykumar Sankaran static bool dpu_hw_get_halt_ctrl(struct dpu_hw_vbif *vbif,
14725fdd593SJeykumar Sankaran 		u32 xin_id)
14825fdd593SJeykumar Sankaran {
14925fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c = &vbif->hw;
15025fdd593SJeykumar Sankaran 	u32 reg_val;
15125fdd593SJeykumar Sankaran 
15225fdd593SJeykumar Sankaran 	reg_val = DPU_REG_READ(c, VBIF_XIN_HALT_CTRL1);
15325fdd593SJeykumar Sankaran 
15425fdd593SJeykumar Sankaran 	return (reg_val & BIT(xin_id)) ? true : false;
15525fdd593SJeykumar Sankaran }
15625fdd593SJeykumar Sankaran 
dpu_hw_set_qos_remap(struct dpu_hw_vbif * vbif,u32 xin_id,u32 level,u32 remap_level)15725fdd593SJeykumar Sankaran static void dpu_hw_set_qos_remap(struct dpu_hw_vbif *vbif,
15825fdd593SJeykumar Sankaran 		u32 xin_id, u32 level, u32 remap_level)
15925fdd593SJeykumar Sankaran {
16025fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c;
161e0485f1dSAngeloGioacchino Del Regno 	u32 reg_lvl, reg_val, reg_val_lvl, mask, reg_high, reg_shift;
16225fdd593SJeykumar Sankaran 
16325fdd593SJeykumar Sankaran 	if (!vbif)
16425fdd593SJeykumar Sankaran 		return;
16525fdd593SJeykumar Sankaran 
16625fdd593SJeykumar Sankaran 	c = &vbif->hw;
16725fdd593SJeykumar Sankaran 
168c8744315SDmitry Baryshkov 	reg_lvl = VBIF_XINL_QOS_LVL_REMAP_000(vbif);
16925fdd593SJeykumar Sankaran 	reg_high = ((xin_id & 0x8) >> 3) * 4 + (level * 8);
17025fdd593SJeykumar Sankaran 	reg_shift = (xin_id & 0x7) * 4;
17125fdd593SJeykumar Sankaran 
17225fdd593SJeykumar Sankaran 	reg_val = DPU_REG_READ(c, VBIF_XINL_QOS_RP_REMAP_000 + reg_high);
173e0485f1dSAngeloGioacchino Del Regno 	reg_val_lvl = DPU_REG_READ(c, reg_lvl + reg_high);
17425fdd593SJeykumar Sankaran 
17525fdd593SJeykumar Sankaran 	mask = 0x7 << reg_shift;
17625fdd593SJeykumar Sankaran 
17725fdd593SJeykumar Sankaran 	reg_val &= ~mask;
17825fdd593SJeykumar Sankaran 	reg_val |= (remap_level << reg_shift) & mask;
17925fdd593SJeykumar Sankaran 
18025fdd593SJeykumar Sankaran 	reg_val_lvl &= ~mask;
18125fdd593SJeykumar Sankaran 	reg_val_lvl |= (remap_level << reg_shift) & mask;
18225fdd593SJeykumar Sankaran 
18325fdd593SJeykumar Sankaran 	DPU_REG_WRITE(c, VBIF_XINL_QOS_RP_REMAP_000 + reg_high, reg_val);
184e0485f1dSAngeloGioacchino Del Regno 	DPU_REG_WRITE(c, reg_lvl + reg_high, reg_val_lvl);
18525fdd593SJeykumar Sankaran }
18625fdd593SJeykumar Sankaran 
dpu_hw_set_write_gather_en(struct dpu_hw_vbif * vbif,u32 xin_id)18725fdd593SJeykumar Sankaran static void dpu_hw_set_write_gather_en(struct dpu_hw_vbif *vbif, u32 xin_id)
18825fdd593SJeykumar Sankaran {
18925fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c;
19025fdd593SJeykumar Sankaran 	u32 reg_val;
19125fdd593SJeykumar Sankaran 
19225fdd593SJeykumar Sankaran 	if (!vbif || xin_id >= MAX_XIN_COUNT)
19325fdd593SJeykumar Sankaran 		return;
19425fdd593SJeykumar Sankaran 
19525fdd593SJeykumar Sankaran 	c = &vbif->hw;
19625fdd593SJeykumar Sankaran 
19725fdd593SJeykumar Sankaran 	reg_val = DPU_REG_READ(c, VBIF_WRITE_GATHER_EN);
19825fdd593SJeykumar Sankaran 	reg_val |= BIT(xin_id);
19925fdd593SJeykumar Sankaran 	DPU_REG_WRITE(c, VBIF_WRITE_GATHER_EN, reg_val);
20025fdd593SJeykumar Sankaran }
20125fdd593SJeykumar Sankaran 
_setup_vbif_ops(struct dpu_hw_vbif_ops * ops,unsigned long cap)20225fdd593SJeykumar Sankaran static void _setup_vbif_ops(struct dpu_hw_vbif_ops *ops,
20325fdd593SJeykumar Sankaran 		unsigned long cap)
20425fdd593SJeykumar Sankaran {
20525fdd593SJeykumar Sankaran 	ops->set_limit_conf = dpu_hw_set_limit_conf;
20625fdd593SJeykumar Sankaran 	ops->get_limit_conf = dpu_hw_get_limit_conf;
20725fdd593SJeykumar Sankaran 	ops->set_halt_ctrl = dpu_hw_set_halt_ctrl;
20825fdd593SJeykumar Sankaran 	ops->get_halt_ctrl = dpu_hw_get_halt_ctrl;
20925fdd593SJeykumar Sankaran 	if (test_bit(DPU_VBIF_QOS_REMAP, &cap))
21025fdd593SJeykumar Sankaran 		ops->set_qos_remap = dpu_hw_set_qos_remap;
21125fdd593SJeykumar Sankaran 	ops->set_mem_type = dpu_hw_set_mem_type;
21225fdd593SJeykumar Sankaran 	ops->clear_errors = dpu_hw_clear_errors;
21325fdd593SJeykumar Sankaran 	ops->set_write_gather_en = dpu_hw_set_write_gather_en;
21425fdd593SJeykumar Sankaran }
21525fdd593SJeykumar Sankaran 
dpu_hw_vbif_init(struct drm_device * dev,const struct dpu_vbif_cfg * cfg,void __iomem * addr)216*bdfa47d9SDmitry Baryshkov struct dpu_hw_vbif *dpu_hw_vbif_init(struct drm_device *dev,
217*bdfa47d9SDmitry Baryshkov 				     const struct dpu_vbif_cfg *cfg,
218babdb815SMarijn Suijten 				     void __iomem *addr)
21925fdd593SJeykumar Sankaran {
22025fdd593SJeykumar Sankaran 	struct dpu_hw_vbif *c;
22125fdd593SJeykumar Sankaran 
222*bdfa47d9SDmitry Baryshkov 	c = drmm_kzalloc(dev, sizeof(*c), GFP_KERNEL);
22325fdd593SJeykumar Sankaran 	if (!c)
22425fdd593SJeykumar Sankaran 		return ERR_PTR(-ENOMEM);
22525fdd593SJeykumar Sankaran 
226babdb815SMarijn Suijten 	c->hw.blk_addr = addr + cfg->base;
227babdb815SMarijn Suijten 	c->hw.log_mask = DPU_DBG_MASK_VBIF;
22825fdd593SJeykumar Sankaran 
22925fdd593SJeykumar Sankaran 	/*
23025fdd593SJeykumar Sankaran 	 * Assign ops
23125fdd593SJeykumar Sankaran 	 */
232babdb815SMarijn Suijten 	c->idx = cfg->id;
23325fdd593SJeykumar Sankaran 	c->cap = cfg;
23425fdd593SJeykumar Sankaran 	_setup_vbif_ops(&c->ops, c->cap->features);
23525fdd593SJeykumar Sankaran 
23625fdd593SJeykumar Sankaran 	/* no need to register sub-range in dpu dbg, dump entire vbif io base */
23725fdd593SJeykumar Sankaran 
23825fdd593SJeykumar Sankaran 	return c;
23925fdd593SJeykumar Sankaran }
240