brintos

brintos / linux-shallow public Read only

0
0
Text · 5.7 KiB · 98e34af Raw
240 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.3 */4 5#include <drm/drm_managed.h>6 7#include "dpu_hwio.h"8#include "dpu_hw_catalog.h"9#include "dpu_hw_vbif.h"10 11#define VBIF_VERSION			0x000012#define VBIF_CLK_FORCE_CTRL0		0x000813#define VBIF_CLK_FORCE_CTRL1		0x000C14#define VBIF_QOS_REMAP_00		0x002015#define VBIF_QOS_REMAP_01		0x002416#define VBIF_QOS_REMAP_10		0x002817#define VBIF_QOS_REMAP_11		0x002C18#define VBIF_WRITE_GATHER_EN		0x00AC19#define VBIF_IN_RD_LIM_CONF0		0x00B020#define VBIF_IN_RD_LIM_CONF1		0x00B421#define VBIF_IN_RD_LIM_CONF2		0x00B822#define VBIF_IN_WR_LIM_CONF0		0x00C023#define VBIF_IN_WR_LIM_CONF1		0x00C424#define VBIF_IN_WR_LIM_CONF2		0x00C825#define VBIF_OUT_RD_LIM_CONF0		0x00D026#define VBIF_OUT_WR_LIM_CONF0		0x00D427#define VBIF_OUT_AXI_AMEMTYPE_CONF0	0x016028#define VBIF_OUT_AXI_AMEMTYPE_CONF1	0x016429#define VBIF_XIN_PND_ERR		0x019030#define VBIF_XIN_SRC_ERR		0x019431#define VBIF_XIN_CLR_ERR		0x019C32#define VBIF_XIN_HALT_CTRL0		0x020033#define VBIF_XIN_HALT_CTRL1		0x020434#define VBIF_XINL_QOS_RP_REMAP_000	0x055035#define VBIF_XINL_QOS_LVL_REMAP_000(vbif)	(VBIF_XINL_QOS_RP_REMAP_000 + (vbif)->cap->qos_rp_remap_size)36 37static void dpu_hw_clear_errors(struct dpu_hw_vbif *vbif,38		u32 *pnd_errors, u32 *src_errors)39{40	struct dpu_hw_blk_reg_map *c;41	u32 pnd, src;42 43	if (!vbif)44		return;45	c = &vbif->hw;46	pnd = DPU_REG_READ(c, VBIF_XIN_PND_ERR);47	src = DPU_REG_READ(c, VBIF_XIN_SRC_ERR);48 49	if (pnd_errors)50		*pnd_errors = pnd;51	if (src_errors)52		*src_errors = src;53 54	DPU_REG_WRITE(c, VBIF_XIN_CLR_ERR, pnd | src);55}56 57static void dpu_hw_set_mem_type(struct dpu_hw_vbif *vbif,58		u32 xin_id, u32 value)59{60	struct dpu_hw_blk_reg_map *c;61	u32 reg_off;62	u32 bit_off;63	u32 reg_val;64 65	/*66	 * Assume 4 bits per bit field, 8 fields per 32-bit register so67	 * 16 bit fields maximum across two registers68	 */69	if (!vbif || xin_id >= MAX_XIN_COUNT || xin_id >= 16)70		return;71 72	c = &vbif->hw;73 74	if (xin_id >= 8) {75		xin_id -= 8;76		reg_off = VBIF_OUT_AXI_AMEMTYPE_CONF1;77	} else {78		reg_off = VBIF_OUT_AXI_AMEMTYPE_CONF0;79	}80	bit_off = (xin_id & 0x7) * 4;81	reg_val = DPU_REG_READ(c, reg_off);82	reg_val &= ~(0x7 << bit_off);83	reg_val |= (value & 0x7) << bit_off;84	DPU_REG_WRITE(c, reg_off, reg_val);85}86 87static void dpu_hw_set_limit_conf(struct dpu_hw_vbif *vbif,88		u32 xin_id, bool rd, u32 limit)89{90	struct dpu_hw_blk_reg_map *c = &vbif->hw;91	u32 reg_val;92	u32 reg_off;93	u32 bit_off;94 95	if (rd)96		reg_off = VBIF_IN_RD_LIM_CONF0;97	else98		reg_off = VBIF_IN_WR_LIM_CONF0;99 100	reg_off += (xin_id / 4) * 4;101	bit_off = (xin_id % 4) * 8;102	reg_val = DPU_REG_READ(c, reg_off);103	reg_val &= ~(0xFF << bit_off);104	reg_val |= (limit) << bit_off;105	DPU_REG_WRITE(c, reg_off, reg_val);106}107 108static u32 dpu_hw_get_limit_conf(struct dpu_hw_vbif *vbif,109		u32 xin_id, bool rd)110{111	struct dpu_hw_blk_reg_map *c = &vbif->hw;112	u32 reg_val;113	u32 reg_off;114	u32 bit_off;115	u32 limit;116 117	if (rd)118		reg_off = VBIF_IN_RD_LIM_CONF0;119	else120		reg_off = VBIF_IN_WR_LIM_CONF0;121 122	reg_off += (xin_id / 4) * 4;123	bit_off = (xin_id % 4) * 8;124	reg_val = DPU_REG_READ(c, reg_off);125	limit = (reg_val >> bit_off) & 0xFF;126 127	return limit;128}129 130static void dpu_hw_set_halt_ctrl(struct dpu_hw_vbif *vbif,131		u32 xin_id, bool enable)132{133	struct dpu_hw_blk_reg_map *c = &vbif->hw;134	u32 reg_val;135 136	reg_val = DPU_REG_READ(c, VBIF_XIN_HALT_CTRL0);137 138	if (enable)139		reg_val |= BIT(xin_id);140	else141		reg_val &= ~BIT(xin_id);142 143	DPU_REG_WRITE(c, VBIF_XIN_HALT_CTRL0, reg_val);144}145 146static bool dpu_hw_get_halt_ctrl(struct dpu_hw_vbif *vbif,147		u32 xin_id)148{149	struct dpu_hw_blk_reg_map *c = &vbif->hw;150	u32 reg_val;151 152	reg_val = DPU_REG_READ(c, VBIF_XIN_HALT_CTRL1);153 154	return (reg_val & BIT(xin_id)) ? true : false;155}156 157static void dpu_hw_set_qos_remap(struct dpu_hw_vbif *vbif,158		u32 xin_id, u32 level, u32 remap_level)159{160	struct dpu_hw_blk_reg_map *c;161	u32 reg_lvl, reg_val, reg_val_lvl, mask, reg_high, reg_shift;162 163	if (!vbif)164		return;165 166	c = &vbif->hw;167 168	reg_lvl = VBIF_XINL_QOS_LVL_REMAP_000(vbif);169	reg_high = ((xin_id & 0x8) >> 3) * 4 + (level * 8);170	reg_shift = (xin_id & 0x7) * 4;171 172	reg_val = DPU_REG_READ(c, VBIF_XINL_QOS_RP_REMAP_000 + reg_high);173	reg_val_lvl = DPU_REG_READ(c, reg_lvl + reg_high);174 175	mask = 0x7 << reg_shift;176 177	reg_val &= ~mask;178	reg_val |= (remap_level << reg_shift) & mask;179 180	reg_val_lvl &= ~mask;181	reg_val_lvl |= (remap_level << reg_shift) & mask;182 183	DPU_REG_WRITE(c, VBIF_XINL_QOS_RP_REMAP_000 + reg_high, reg_val);184	DPU_REG_WRITE(c, reg_lvl + reg_high, reg_val_lvl);185}186 187static void dpu_hw_set_write_gather_en(struct dpu_hw_vbif *vbif, u32 xin_id)188{189	struct dpu_hw_blk_reg_map *c;190	u32 reg_val;191 192	if (!vbif || xin_id >= MAX_XIN_COUNT)193		return;194 195	c = &vbif->hw;196 197	reg_val = DPU_REG_READ(c, VBIF_WRITE_GATHER_EN);198	reg_val |= BIT(xin_id);199	DPU_REG_WRITE(c, VBIF_WRITE_GATHER_EN, reg_val);200}201 202static void _setup_vbif_ops(struct dpu_hw_vbif_ops *ops,203		unsigned long cap)204{205	ops->set_limit_conf = dpu_hw_set_limit_conf;206	ops->get_limit_conf = dpu_hw_get_limit_conf;207	ops->set_halt_ctrl = dpu_hw_set_halt_ctrl;208	ops->get_halt_ctrl = dpu_hw_get_halt_ctrl;209	if (test_bit(DPU_VBIF_QOS_REMAP, &cap))210		ops->set_qos_remap = dpu_hw_set_qos_remap;211	ops->set_mem_type = dpu_hw_set_mem_type;212	ops->clear_errors = dpu_hw_clear_errors;213	ops->set_write_gather_en = dpu_hw_set_write_gather_en;214}215 216struct dpu_hw_vbif *dpu_hw_vbif_init(struct drm_device *dev,217				     const struct dpu_vbif_cfg *cfg,218				     void __iomem *addr)219{220	struct dpu_hw_vbif *c;221 222	c = drmm_kzalloc(dev, sizeof(*c), GFP_KERNEL);223	if (!c)224		return ERR_PTR(-ENOMEM);225 226	c->hw.blk_addr = addr + cfg->base;227	c->hw.log_mask = DPU_DBG_MASK_VBIF;228 229	/*230	 * Assign ops231	 */232	c->idx = cfg->id;233	c->cap = cfg;234	_setup_vbif_ops(&c->ops, c->cap->features);235 236	/* no need to register sub-range in dpu dbg, dump entire vbif io base */237 238	return c;239}240