root/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dpu_hw_clear_errors
  2. dpu_hw_set_mem_type
  3. dpu_hw_set_limit_conf
  4. dpu_hw_get_limit_conf
  5. dpu_hw_set_halt_ctrl
  6. dpu_hw_get_halt_ctrl
  7. dpu_hw_set_qos_remap
  8. dpu_hw_set_write_gather_en
  9. _setup_vbif_ops
  10. _top_offset
  11. dpu_hw_vbif_init
  12. dpu_hw_vbif_destroy

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
   3  */
   4 
   5 #include "dpu_hwio.h"
   6 #include "dpu_hw_catalog.h"
   7 #include "dpu_hw_vbif.h"
   8 
   9 #define VBIF_VERSION                    0x0000
  10 #define VBIF_CLK_FORCE_CTRL0            0x0008
  11 #define VBIF_CLK_FORCE_CTRL1            0x000C
  12 #define VBIF_QOS_REMAP_00               0x0020
  13 #define VBIF_QOS_REMAP_01               0x0024
  14 #define VBIF_QOS_REMAP_10               0x0028
  15 #define VBIF_QOS_REMAP_11               0x002C
  16 #define VBIF_WRITE_GATHER_EN            0x00AC
  17 #define VBIF_IN_RD_LIM_CONF0            0x00B0
  18 #define VBIF_IN_RD_LIM_CONF1            0x00B4
  19 #define VBIF_IN_RD_LIM_CONF2            0x00B8
  20 #define VBIF_IN_WR_LIM_CONF0            0x00C0
  21 #define VBIF_IN_WR_LIM_CONF1            0x00C4
  22 #define VBIF_IN_WR_LIM_CONF2            0x00C8
  23 #define VBIF_OUT_RD_LIM_CONF0           0x00D0
  24 #define VBIF_OUT_WR_LIM_CONF0           0x00D4
  25 #define VBIF_OUT_AXI_AMEMTYPE_CONF0     0x0160
  26 #define VBIF_OUT_AXI_AMEMTYPE_CONF1     0x0164
  27 #define VBIF_XIN_PND_ERR                0x0190
  28 #define VBIF_XIN_SRC_ERR                0x0194
  29 #define VBIF_XIN_CLR_ERR                0x019C
  30 #define VBIF_XIN_HALT_CTRL0             0x0200
  31 #define VBIF_XIN_HALT_CTRL1             0x0204
  32 #define VBIF_XINL_QOS_RP_REMAP_000      0x0550
  33 #define VBIF_XINL_QOS_LVL_REMAP_000     0x0590
  34 
  35 static void dpu_hw_clear_errors(struct dpu_hw_vbif *vbif,
  36                 u32 *pnd_errors, u32 *src_errors)
  37 {
  38         struct dpu_hw_blk_reg_map *c;
  39         u32 pnd, src;
  40 
  41         if (!vbif)
  42                 return;
  43         c = &vbif->hw;
  44         pnd = DPU_REG_READ(c, VBIF_XIN_PND_ERR);
  45         src = DPU_REG_READ(c, VBIF_XIN_SRC_ERR);
  46 
  47         if (pnd_errors)
  48                 *pnd_errors = pnd;
  49         if (src_errors)
  50                 *src_errors = src;
  51 
  52         DPU_REG_WRITE(c, VBIF_XIN_CLR_ERR, pnd | src);
  53 }
  54 
  55 static void dpu_hw_set_mem_type(struct dpu_hw_vbif *vbif,
  56                 u32 xin_id, u32 value)
  57 {
  58         struct dpu_hw_blk_reg_map *c;
  59         u32 reg_off;
  60         u32 bit_off;
  61         u32 reg_val;
  62 
  63         /*
  64          * Assume 4 bits per bit field, 8 fields per 32-bit register so
  65          * 16 bit fields maximum across two registers
  66          */
  67         if (!vbif || xin_id >= MAX_XIN_COUNT || xin_id >= 16)
  68                 return;
  69 
  70         c = &vbif->hw;
  71 
  72         if (xin_id >= 8) {
  73                 xin_id -= 8;
  74                 reg_off = VBIF_OUT_AXI_AMEMTYPE_CONF1;
  75         } else {
  76                 reg_off = VBIF_OUT_AXI_AMEMTYPE_CONF0;
  77         }
  78         bit_off = (xin_id & 0x7) * 4;
  79         reg_val = DPU_REG_READ(c, reg_off);
  80         reg_val &= ~(0x7 << bit_off);
  81         reg_val |= (value & 0x7) << bit_off;
  82         DPU_REG_WRITE(c, reg_off, reg_val);
  83 }
  84 
  85 static void dpu_hw_set_limit_conf(struct dpu_hw_vbif *vbif,
  86                 u32 xin_id, bool rd, u32 limit)
  87 {
  88         struct dpu_hw_blk_reg_map *c = &vbif->hw;
  89         u32 reg_val;
  90         u32 reg_off;
  91         u32 bit_off;
  92 
  93         if (rd)
  94                 reg_off = VBIF_IN_RD_LIM_CONF0;
  95         else
  96                 reg_off = VBIF_IN_WR_LIM_CONF0;
  97 
  98         reg_off += (xin_id / 4) * 4;
  99         bit_off = (xin_id % 4) * 8;
 100         reg_val = DPU_REG_READ(c, reg_off);
 101         reg_val &= ~(0xFF << bit_off);
 102         reg_val |= (limit) << bit_off;
 103         DPU_REG_WRITE(c, reg_off, reg_val);
 104 }
 105 
 106 static u32 dpu_hw_get_limit_conf(struct dpu_hw_vbif *vbif,
 107                 u32 xin_id, bool rd)
 108 {
 109         struct dpu_hw_blk_reg_map *c = &vbif->hw;
 110         u32 reg_val;
 111         u32 reg_off;
 112         u32 bit_off;
 113         u32 limit;
 114 
 115         if (rd)
 116                 reg_off = VBIF_IN_RD_LIM_CONF0;
 117         else
 118                 reg_off = VBIF_IN_WR_LIM_CONF0;
 119 
 120         reg_off += (xin_id / 4) * 4;
 121         bit_off = (xin_id % 4) * 8;
 122         reg_val = DPU_REG_READ(c, reg_off);
 123         limit = (reg_val >> bit_off) & 0xFF;
 124 
 125         return limit;
 126 }
 127 
 128 static void dpu_hw_set_halt_ctrl(struct dpu_hw_vbif *vbif,
 129                 u32 xin_id, bool enable)
 130 {
 131         struct dpu_hw_blk_reg_map *c = &vbif->hw;
 132         u32 reg_val;
 133 
 134         reg_val = DPU_REG_READ(c, VBIF_XIN_HALT_CTRL0);
 135 
 136         if (enable)
 137                 reg_val |= BIT(xin_id);
 138         else
 139                 reg_val &= ~BIT(xin_id);
 140 
 141         DPU_REG_WRITE(c, VBIF_XIN_HALT_CTRL0, reg_val);
 142 }
 143 
 144 static bool dpu_hw_get_halt_ctrl(struct dpu_hw_vbif *vbif,
 145                 u32 xin_id)
 146 {
 147         struct dpu_hw_blk_reg_map *c = &vbif->hw;
 148         u32 reg_val;
 149 
 150         reg_val = DPU_REG_READ(c, VBIF_XIN_HALT_CTRL1);
 151 
 152         return (reg_val & BIT(xin_id)) ? true : false;
 153 }
 154 
 155 static void dpu_hw_set_qos_remap(struct dpu_hw_vbif *vbif,
 156                 u32 xin_id, u32 level, u32 remap_level)
 157 {
 158         struct dpu_hw_blk_reg_map *c;
 159         u32 reg_val, reg_val_lvl, mask, reg_high, reg_shift;
 160 
 161         if (!vbif)
 162                 return;
 163 
 164         c = &vbif->hw;
 165 
 166         reg_high = ((xin_id & 0x8) >> 3) * 4 + (level * 8);
 167         reg_shift = (xin_id & 0x7) * 4;
 168 
 169         reg_val = DPU_REG_READ(c, VBIF_XINL_QOS_RP_REMAP_000 + reg_high);
 170         reg_val_lvl = DPU_REG_READ(c, VBIF_XINL_QOS_LVL_REMAP_000 + reg_high);
 171 
 172         mask = 0x7 << reg_shift;
 173 
 174         reg_val &= ~mask;
 175         reg_val |= (remap_level << reg_shift) & mask;
 176 
 177         reg_val_lvl &= ~mask;
 178         reg_val_lvl |= (remap_level << reg_shift) & mask;
 179 
 180         DPU_REG_WRITE(c, VBIF_XINL_QOS_RP_REMAP_000 + reg_high, reg_val);
 181         DPU_REG_WRITE(c, VBIF_XINL_QOS_LVL_REMAP_000 + reg_high, reg_val_lvl);
 182 }
 183 
 184 static void dpu_hw_set_write_gather_en(struct dpu_hw_vbif *vbif, u32 xin_id)
 185 {
 186         struct dpu_hw_blk_reg_map *c;
 187         u32 reg_val;
 188 
 189         if (!vbif || xin_id >= MAX_XIN_COUNT)
 190                 return;
 191 
 192         c = &vbif->hw;
 193 
 194         reg_val = DPU_REG_READ(c, VBIF_WRITE_GATHER_EN);
 195         reg_val |= BIT(xin_id);
 196         DPU_REG_WRITE(c, VBIF_WRITE_GATHER_EN, reg_val);
 197 }
 198 
 199 static void _setup_vbif_ops(struct dpu_hw_vbif_ops *ops,
 200                 unsigned long cap)
 201 {
 202         ops->set_limit_conf = dpu_hw_set_limit_conf;
 203         ops->get_limit_conf = dpu_hw_get_limit_conf;
 204         ops->set_halt_ctrl = dpu_hw_set_halt_ctrl;
 205         ops->get_halt_ctrl = dpu_hw_get_halt_ctrl;
 206         if (test_bit(DPU_VBIF_QOS_REMAP, &cap))
 207                 ops->set_qos_remap = dpu_hw_set_qos_remap;
 208         ops->set_mem_type = dpu_hw_set_mem_type;
 209         ops->clear_errors = dpu_hw_clear_errors;
 210         ops->set_write_gather_en = dpu_hw_set_write_gather_en;
 211 }
 212 
 213 static const struct dpu_vbif_cfg *_top_offset(enum dpu_vbif vbif,
 214                 const struct dpu_mdss_cfg *m,
 215                 void __iomem *addr,
 216                 struct dpu_hw_blk_reg_map *b)
 217 {
 218         int i;
 219 
 220         for (i = 0; i < m->vbif_count; i++) {
 221                 if (vbif == m->vbif[i].id) {
 222                         b->base_off = addr;
 223                         b->blk_off = m->vbif[i].base;
 224                         b->length = m->vbif[i].len;
 225                         b->hwversion = m->hwversion;
 226                         b->log_mask = DPU_DBG_MASK_VBIF;
 227                         return &m->vbif[i];
 228                 }
 229         }
 230 
 231         return ERR_PTR(-EINVAL);
 232 }
 233 
 234 struct dpu_hw_vbif *dpu_hw_vbif_init(enum dpu_vbif idx,
 235                 void __iomem *addr,
 236                 const struct dpu_mdss_cfg *m)
 237 {
 238         struct dpu_hw_vbif *c;
 239         const struct dpu_vbif_cfg *cfg;
 240 
 241         c = kzalloc(sizeof(*c), GFP_KERNEL);
 242         if (!c)
 243                 return ERR_PTR(-ENOMEM);
 244 
 245         cfg = _top_offset(idx, m, addr, &c->hw);
 246         if (IS_ERR_OR_NULL(cfg)) {
 247                 kfree(c);
 248                 return ERR_PTR(-EINVAL);
 249         }
 250 
 251         /*
 252          * Assign ops
 253          */
 254         c->idx = idx;
 255         c->cap = cfg;
 256         _setup_vbif_ops(&c->ops, c->cap->features);
 257 
 258         /* no need to register sub-range in dpu dbg, dump entire vbif io base */
 259 
 260         return c;
 261 }
 262 
 263 void dpu_hw_vbif_destroy(struct dpu_hw_vbif *vbif)
 264 {
 265         kfree(vbif);
 266 }

/* [<][>][^][v][top][bottom][index][help] */