diff options
-rw-r--r-- | drivers/gpu/nvgpu/perf/perf.h | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/pstate/pstate.c | 204 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/pstate/pstate.h | 32 |
3 files changed, 238 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/perf/perf.h b/drivers/gpu/nvgpu/perf/perf.h index 02aed7a6..3ffaf4e1 100644 --- a/drivers/gpu/nvgpu/perf/perf.h +++ b/drivers/gpu/nvgpu/perf/perf.h | |||
@@ -15,6 +15,7 @@ | |||
15 | 15 | ||
16 | #include "vfe_equ.h" | 16 | #include "vfe_equ.h" |
17 | #include "vfe_var.h" | 17 | #include "vfe_var.h" |
18 | #include "pstate/pstate.h" | ||
18 | #include "gk20a/gk20a.h" | 19 | #include "gk20a/gk20a.h" |
19 | 20 | ||
20 | #define CTRL_PERF_VFE_VAR_TYPE_INVALID 0x00 | 21 | #define CTRL_PERF_VFE_VAR_TYPE_INVALID 0x00 |
@@ -53,6 +54,7 @@ | |||
53 | struct perf_pmupstate { | 54 | struct perf_pmupstate { |
54 | struct vfe_vars vfe_varobjs; | 55 | struct vfe_vars vfe_varobjs; |
55 | struct vfe_equs vfe_equobjs; | 56 | struct vfe_equs vfe_equobjs; |
57 | struct pstates pstatesobjs; | ||
56 | }; | 58 | }; |
57 | 59 | ||
58 | u32 perf_pmu_vfe_load(struct gk20a *g); | 60 | u32 perf_pmu_vfe_load(struct gk20a *g); |
diff --git a/drivers/gpu/nvgpu/pstate/pstate.c b/drivers/gpu/nvgpu/pstate/pstate.c index da1a49db..f4cc50ab 100644 --- a/drivers/gpu/nvgpu/pstate/pstate.c +++ b/drivers/gpu/nvgpu/pstate/pstate.c | |||
@@ -17,6 +17,10 @@ | |||
17 | #include "clk/clk.h" | 17 | #include "clk/clk.h" |
18 | #include "perf/perf.h" | 18 | #include "perf/perf.h" |
19 | #include "pmgr/pmgr.h" | 19 | #include "pmgr/pmgr.h" |
20 | #include "include/bios.h" | ||
21 | #include "pstate/pstate.h" | ||
22 | |||
23 | static int pstate_sw_setup(struct gk20a *g); | ||
20 | 24 | ||
21 | /*sw setup for pstate components*/ | 25 | /*sw setup for pstate components*/ |
22 | int gk20a_init_pstate_support(struct gk20a *g) | 26 | int gk20a_init_pstate_support(struct gk20a *g) |
@@ -53,6 +57,10 @@ int gk20a_init_pstate_support(struct gk20a *g) | |||
53 | if (err) | 57 | if (err) |
54 | return err; | 58 | return err; |
55 | 59 | ||
60 | err = pstate_sw_setup(g); | ||
61 | if (err) | ||
62 | return err; | ||
63 | |||
56 | err = pmgr_domain_sw_setup(g); | 64 | err = pmgr_domain_sw_setup(g); |
57 | return err; | 65 | return err; |
58 | } | 66 | } |
@@ -112,3 +120,199 @@ int gk20a_init_pstate_pmu_support(struct gk20a *g) | |||
112 | return err; | 120 | return err; |
113 | } | 121 | } |
114 | 122 | ||
123 | int pstate_construct_super(struct gk20a *g, struct boardobj **ppboardobj, | ||
124 | u16 size, void *args) | ||
125 | { | ||
126 | struct pstate *ptmppstate = (struct pstate *)args; | ||
127 | struct pstate *pstate; | ||
128 | int err; | ||
129 | |||
130 | err = boardobj_construct_super(g, ppboardobj, size, args); | ||
131 | if (err) | ||
132 | return err; | ||
133 | |||
134 | pstate = (struct pstate *)*ppboardobj; | ||
135 | |||
136 | pstate->num = ptmppstate->num; | ||
137 | pstate->clklist = ptmppstate->clklist; | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | int pstate_construct_3x(struct gk20a *g, struct boardobj **ppboardobj, | ||
143 | u16 size, void *args) | ||
144 | { | ||
145 | struct boardobj *ptmpobj = (struct boardobj *)args; | ||
146 | |||
147 | ptmpobj->type_mask |= BIT(CTRL_PERF_PSTATE_TYPE_3X); | ||
148 | return pstate_construct_super(g, ppboardobj, size, args); | ||
149 | } | ||
150 | |||
151 | struct pstate *pstate_construct(struct gk20a *g, void *args) | ||
152 | { | ||
153 | struct pstate *pstate = NULL; | ||
154 | struct pstate *tmp = (struct pstate *)args; | ||
155 | |||
156 | if ((tmp->super.type != CTRL_PERF_PSTATE_TYPE_3X) || | ||
157 | (pstate_construct_3x(g, (struct boardobj **)&pstate, | ||
158 | sizeof(struct pstate), args))) | ||
159 | gk20a_err(dev_from_gk20a(g), | ||
160 | "error constructing pstate num=%u", tmp->num); | ||
161 | |||
162 | return pstate; | ||
163 | } | ||
164 | |||
165 | int pstate_insert(struct gk20a *g, struct pstate *pstate, int index) | ||
166 | { | ||
167 | struct pstates *pstates = &(g->perf_pmu.pstatesobjs); | ||
168 | int err; | ||
169 | |||
170 | err = boardobjgrp_objinsert(&pstates->super.super, | ||
171 | (struct boardobj *)pstate, index); | ||
172 | if (err) { | ||
173 | gk20a_err(dev_from_gk20a(g), | ||
174 | "error adding pstate boardobj %d", index); | ||
175 | return err; | ||
176 | } | ||
177 | |||
178 | pstates->num_levels++; | ||
179 | |||
180 | return err; | ||
181 | } | ||
182 | |||
183 | static int parse_pstate_entry_5x(struct gk20a *g, | ||
184 | struct vbios_pstate_header_5x *hdr, | ||
185 | struct vbios_pstate_entry_5x *entry, | ||
186 | struct pstate *pstate) | ||
187 | { | ||
188 | u8 *p = (u8 *)entry; | ||
189 | u32 clkidx; | ||
190 | |||
191 | p += hdr->base_entry_size; | ||
192 | |||
193 | memset(pstate, 0, sizeof(struct pstate)); | ||
194 | pstate->super.type = CTRL_PERF_PSTATE_TYPE_3X; | ||
195 | pstate->num = 0x0F - entry->pstate_level; | ||
196 | pstate->clklist.clksetinfolistsize = hdr->clock_entry_count; | ||
197 | |||
198 | gk20a_dbg_info("pstate P%u", pstate->num); | ||
199 | |||
200 | for (clkidx = 0; clkidx < hdr->clock_entry_count; clkidx++) { | ||
201 | struct clk_set_info *pclksetinfo; | ||
202 | struct vbios_pstate_entry_clock_5x *clk_entry; | ||
203 | struct clk_domain *clk_domain; | ||
204 | |||
205 | clk_domain = (struct clk_domain *)BOARDOBJGRP_OBJ_GET_BY_IDX( | ||
206 | &g->clk_pmu.clk_domainobjs.super.super, clkidx); | ||
207 | |||
208 | pclksetinfo = &pstate->clklist.clksetinfo[clkidx]; | ||
209 | clk_entry = (struct vbios_pstate_entry_clock_5x *)p; | ||
210 | |||
211 | pclksetinfo->clkwhich = clk_domain->domain; | ||
212 | pclksetinfo->nominal_mhz = | ||
213 | BIOS_GET_FIELD(clk_entry->param0, | ||
214 | VBIOS_PSTATE_5X_CLOCK_PROG_PARAM0_NOM_FREQ_MHZ); | ||
215 | pclksetinfo->min_mhz = | ||
216 | BIOS_GET_FIELD(clk_entry->param1, | ||
217 | VBIOS_PSTATE_5X_CLOCK_PROG_PARAM1_MIN_FREQ_MHZ); | ||
218 | pclksetinfo->max_mhz = | ||
219 | BIOS_GET_FIELD(clk_entry->param1, | ||
220 | VBIOS_PSTATE_5X_CLOCK_PROG_PARAM1_MAX_FREQ_MHZ); | ||
221 | |||
222 | gk20a_dbg_info( | ||
223 | "clk_domain=%u nominal_mhz=%u min_mhz=%u max_mhz=%u", | ||
224 | pclksetinfo->clkwhich, pclksetinfo->nominal_mhz, | ||
225 | pclksetinfo->min_mhz, pclksetinfo->max_mhz); | ||
226 | |||
227 | p += hdr->clock_entry_size; | ||
228 | } | ||
229 | |||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static int parse_pstate_table_5x(struct gk20a *g, | ||
234 | struct vbios_pstate_header_5x *hdr) | ||
235 | { | ||
236 | struct pstate _pstate, *pstate = &_pstate; | ||
237 | struct vbios_pstate_entry_5x *entry; | ||
238 | u32 entry_size; | ||
239 | u8 i; | ||
240 | u8 *p = (u8 *)hdr; | ||
241 | int err = 0; | ||
242 | |||
243 | if ((hdr->header_size != VBIOS_PSTATE_HEADER_5X_SIZE_10) || | ||
244 | (hdr->base_entry_count == 0) || | ||
245 | ((hdr->base_entry_size != VBIOS_PSTATE_BASE_ENTRY_5X_SIZE_2) && | ||
246 | (hdr->base_entry_size != VBIOS_PSTATE_BASE_ENTRY_5X_SIZE_3)) || | ||
247 | (hdr->clock_entry_size != VBIOS_PSTATE_CLOCK_ENTRY_5X_SIZE_6) || | ||
248 | (hdr->clock_entry_count > CLK_SET_INFO_MAX_SIZE)) | ||
249 | return -EINVAL; | ||
250 | |||
251 | p += hdr->header_size; | ||
252 | |||
253 | entry_size = hdr->base_entry_size + | ||
254 | hdr->clock_entry_count * hdr->clock_entry_size; | ||
255 | |||
256 | for (i = 0; i < hdr->base_entry_count; i++, p += entry_size) { | ||
257 | entry = (struct vbios_pstate_entry_5x *)p; | ||
258 | |||
259 | if (entry->pstate_level == VBIOS_PERFLEVEL_SKIP_ENTRY) | ||
260 | continue; | ||
261 | |||
262 | err = parse_pstate_entry_5x(g, hdr, entry, pstate); | ||
263 | if (err) | ||
264 | goto done; | ||
265 | |||
266 | pstate = pstate_construct(g, pstate); | ||
267 | if (!pstate) | ||
268 | goto done; | ||
269 | |||
270 | err = pstate_insert(g, pstate, i); | ||
271 | if (err) | ||
272 | goto done; | ||
273 | } | ||
274 | |||
275 | done: | ||
276 | return err; | ||
277 | } | ||
278 | |||
279 | static int pstate_sw_setup(struct gk20a *g) | ||
280 | { | ||
281 | struct vbios_pstate_header_5x *hdr = NULL; | ||
282 | int err = 0; | ||
283 | |||
284 | gk20a_dbg_fn(""); | ||
285 | |||
286 | err = boardobjgrpconstruct_e32(&g->perf_pmu.pstatesobjs.super); | ||
287 | if (err) { | ||
288 | gk20a_err(dev_from_gk20a(g), | ||
289 | "error creating boardobjgrp for pstates, err=%d", | ||
290 | err); | ||
291 | goto done; | ||
292 | } | ||
293 | |||
294 | if (g->ops.bios.get_perf_table_ptrs) { | ||
295 | hdr = (struct vbios_pstate_header_5x *) | ||
296 | g->ops.bios.get_perf_table_ptrs(g, | ||
297 | g->bios.perf_token, PERFORMANCE_TABLE); | ||
298 | } | ||
299 | |||
300 | if (!hdr) { | ||
301 | gk20a_err(dev_from_gk20a(g), | ||
302 | "performance table not found"); | ||
303 | err = -EINVAL; | ||
304 | goto done; | ||
305 | } | ||
306 | |||
307 | if (hdr->version != VBIOS_PSTATE_TABLE_VERSION_5X) { | ||
308 | gk20a_err(dev_from_gk20a(g), | ||
309 | "unknown/unsupported clocks table version=0x%02x", | ||
310 | hdr->version); | ||
311 | err = -EINVAL; | ||
312 | goto done; | ||
313 | } | ||
314 | |||
315 | err = parse_pstate_table_5x(g, hdr); | ||
316 | done: | ||
317 | return err; | ||
318 | } | ||
diff --git a/drivers/gpu/nvgpu/pstate/pstate.h b/drivers/gpu/nvgpu/pstate/pstate.h index fb49adf3..11fa4c77 100644 --- a/drivers/gpu/nvgpu/pstate/pstate.h +++ b/drivers/gpu/nvgpu/pstate/pstate.h | |||
@@ -12,8 +12,40 @@ | |||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
13 | * more details. | 13 | * more details. |
14 | */ | 14 | */ |
15 | #ifndef __PSTATE_H__ | ||
16 | #define __PSTATE_H__ | ||
15 | 17 | ||
16 | #include "gk20a/gk20a.h" | 18 | #include "gk20a/gk20a.h" |
19 | #include "clk/clk.h" | ||
20 | |||
21 | #define CTRL_PERF_PSTATE_TYPE_3X 0x3 | ||
22 | |||
23 | #define CLK_SET_INFO_MAX_SIZE (32) | ||
24 | |||
25 | struct clk_set_info { | ||
26 | enum nv_pmu_clk_clkwhich clkwhich; | ||
27 | u32 nominal_mhz; | ||
28 | u32 min_mhz; | ||
29 | u32 max_mhz; | ||
30 | }; | ||
31 | |||
32 | struct clk_set_info_list { | ||
33 | u32 clksetinfolistsize; | ||
34 | struct clk_set_info clksetinfo[CLK_SET_INFO_MAX_SIZE]; | ||
35 | }; | ||
36 | |||
37 | struct pstate { | ||
38 | struct boardobj super; | ||
39 | u32 num; | ||
40 | struct clk_set_info_list clklist; | ||
41 | }; | ||
42 | |||
43 | struct pstates { | ||
44 | struct boardobjgrp_e32 super; | ||
45 | u32 num_levels; | ||
46 | }; | ||
17 | 47 | ||
18 | int gk20a_init_pstate_support(struct gk20a *g); | 48 | int gk20a_init_pstate_support(struct gk20a *g); |
19 | int gk20a_init_pstate_pmu_support(struct gk20a *g); | 49 | int gk20a_init_pstate_pmu_support(struct gk20a *g); |
50 | |||
51 | #endif /* __PSTATE_H__ */ | ||