1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "sde_hwio.h"
#include "sde_hw_catalog.h"
#include "sde_hw_vbif.h"
#include "sde_dbg.h"
#define VBIF_VERSION 0x0000
#define VBIF_CLK_FORCE_CTRL0 0x0008
#define VBIF_CLK_FORCE_CTRL1 0x000C
#define VBIF_QOS_REMAP_00 0x0020
#define VBIF_QOS_REMAP_01 0x0024
#define VBIF_QOS_REMAP_10 0x0028
#define VBIF_QOS_REMAP_11 0x002C
#define VBIF_WRITE_GATHTER_EN 0x00AC
#define VBIF_IN_RD_LIM_CONF0 0x00B0
#define VBIF_IN_RD_LIM_CONF1 0x00B4
#define VBIF_IN_RD_LIM_CONF2 0x00B8
#define VBIF_IN_WR_LIM_CONF0 0x00C0
#define VBIF_IN_WR_LIM_CONF1 0x00C4
#define VBIF_IN_WR_LIM_CONF2 0x00C8
#define VBIF_OUT_RD_LIM_CONF0 0x00D0
#define VBIF_OUT_WR_LIM_CONF0 0x00D4
#define VBIF_XIN_HALT_CTRL0 0x0200
#define VBIF_XIN_HALT_CTRL1 0x0204
static void sde_hw_set_limit_conf(struct sde_hw_vbif *vbif,
u32 xin_id, bool rd, u32 limit)
{
struct sde_hw_blk_reg_map *c = &vbif->hw;
u32 reg_val;
u32 reg_off;
u32 bit_off;
if (rd)
reg_off = VBIF_IN_RD_LIM_CONF0;
else
reg_off = VBIF_IN_WR_LIM_CONF0;
reg_off += (xin_id / 4) * 4;
bit_off = (xin_id % 4) * 8;
reg_val = SDE_REG_READ(c, reg_off);
reg_val &= ~(0xFF << bit_off);
reg_val |= (limit) << bit_off;
SDE_REG_WRITE(c, reg_off, reg_val);
}
static u32 sde_hw_get_limit_conf(struct sde_hw_vbif *vbif,
u32 xin_id, bool rd)
{
struct sde_hw_blk_reg_map *c = &vbif->hw;
u32 reg_val;
u32 reg_off;
u32 bit_off;
u32 limit;
if (rd)
reg_off = VBIF_IN_RD_LIM_CONF0;
else
reg_off = VBIF_IN_WR_LIM_CONF0;
reg_off += (xin_id / 4) * 4;
bit_off = (xin_id % 4) * 8;
reg_val = SDE_REG_READ(c, reg_off);
limit = (reg_val >> bit_off) & 0xFF;
return limit;
}
static void sde_hw_set_halt_ctrl(struct sde_hw_vbif *vbif,
u32 xin_id, bool enable)
{
struct sde_hw_blk_reg_map *c = &vbif->hw;
u32 reg_val;
reg_val = SDE_REG_READ(c, VBIF_XIN_HALT_CTRL0);
if (enable)
reg_val |= BIT(xin_id);
else
reg_val &= ~BIT(xin_id);
SDE_REG_WRITE(c, VBIF_XIN_HALT_CTRL0, reg_val);
}
static bool sde_hw_get_halt_ctrl(struct sde_hw_vbif *vbif,
u32 xin_id)
{
struct sde_hw_blk_reg_map *c = &vbif->hw;
u32 reg_val;
reg_val = SDE_REG_READ(c, VBIF_XIN_HALT_CTRL1);
return (reg_val & BIT(xin_id)) ? true : false;
}
static void _setup_vbif_ops(struct sde_hw_vbif_ops *ops,
unsigned long cap)
{
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;
}
static const struct sde_vbif_cfg *_top_offset(enum sde_vbif vbif,
const struct sde_mdss_cfg *m,
void __iomem *addr,
struct sde_hw_blk_reg_map *b)
{
int i;
for (i = 0; i < m->vbif_count; i++) {
if (vbif == m->vbif[i].id) {
b->base_off = addr;
b->blk_off = m->vbif[i].base;
b->length = m->vbif[i].len;
b->hwversion = m->hwversion;
b->log_mask = SDE_DBG_MASK_VBIF;
return &m->vbif[i];
}
}
return ERR_PTR(-EINVAL);
}
struct sde_hw_vbif *sde_hw_vbif_init(enum sde_vbif idx,
void __iomem *addr,
const struct sde_mdss_cfg *m)
{
struct sde_hw_vbif *c;
const struct sde_vbif_cfg *cfg;
c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c)
return ERR_PTR(-ENOMEM);
cfg = _top_offset(idx, m, addr, &c->hw);
if (IS_ERR_OR_NULL(cfg)) {
kfree(c);
return ERR_PTR(-EINVAL);
}
/*
* Assign ops
*/
c->idx = idx;
c->cap = cfg;
_setup_vbif_ops(&c->ops, c->cap->features);
/* no need to register sub-range in sde dbg, dump entire vbif io base */
return c;
}
void sde_hw_vbif_destroy(struct sde_hw_vbif *vbif)
{
kfree(vbif);
}
|