diff options
author | Vijayakumar Subbu <vsubbu@nvidia.com> | 2016-07-30 13:44:30 -0400 |
---|---|---|
committer | Deepak Nibade <dnibade@nvidia.com> | 2016-12-27 04:56:49 -0500 |
commit | 432017248e432df0619dc2df30f915a52634338f (patch) | |
tree | 40bb7a77983fb2753271bc46b346a44ebd6121cf /drivers/gpu/nvgpu/clk/clk_vf_point.c | |
parent | 38ad90b4840434df4650c617a236e1b01f8a43c6 (diff) |
gpu: nvgpu: Add dGPU clocks support
JIRA DNVGPU-42
Change-Id: Ic2fca9d0cf82f2823654ac5e8f0772a1eec7b3b5
Signed-off-by: Vijayakumar Subbu <vsubbu@nvidia.com>
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/1205850
(cherry picked from commit b9f5c6bc4e649162d63e33d65b725872340ca114)
Reviewed-on: http://git-master/r/1227257
GVS: Gerrit_Virtual_Submit
Diffstat (limited to 'drivers/gpu/nvgpu/clk/clk_vf_point.c')
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk_vf_point.c | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/clk/clk_vf_point.c b/drivers/gpu/nvgpu/clk/clk_vf_point.c new file mode 100644 index 00000000..275bef96 --- /dev/null +++ b/drivers/gpu/nvgpu/clk/clk_vf_point.c | |||
@@ -0,0 +1,347 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | */ | ||
13 | |||
14 | #include "gk20a/gk20a.h" | ||
15 | #include "clk.h" | ||
16 | #include "clk_vf_point.h" | ||
17 | #include "include/bios.h" | ||
18 | #include "boardobj/boardobjgrp.h" | ||
19 | #include "boardobj/boardobjgrp_e32.h" | ||
20 | #include "pmuif/gpmuifboardobj.h" | ||
21 | #include "pmuif/gpmuifclk.h" | ||
22 | #include "gm206/bios_gm206.h" | ||
23 | #include "ctrl/ctrlclk.h" | ||
24 | #include "ctrl/ctrlvolt.h" | ||
25 | #include "gk20a/pmu_gk20a.h" | ||
26 | |||
27 | static u32 _clk_vf_point_pmudatainit_super(struct gk20a *g, struct boardobj | ||
28 | *board_obj_ptr, struct nv_pmu_boardobj *ppmudata); | ||
29 | |||
30 | static u32 _clk_vf_points_pmudatainit(struct gk20a *g, | ||
31 | struct boardobjgrp *pboardobjgrp, | ||
32 | struct nv_pmu_boardobjgrp_super *pboardobjgrppmu) | ||
33 | { | ||
34 | u32 status = 0; | ||
35 | |||
36 | status = boardobjgrp_pmudatainit_e32(g, pboardobjgrp, pboardobjgrppmu); | ||
37 | if (status) { | ||
38 | gk20a_err(dev_from_gk20a(g), | ||
39 | "error updating pmu boardobjgrp for clk vfpoint 0x%x", | ||
40 | status); | ||
41 | goto done; | ||
42 | } | ||
43 | |||
44 | done: | ||
45 | return status; | ||
46 | } | ||
47 | |||
48 | static u32 _clk_vf_points_pmudata_instget(struct gk20a *g, | ||
49 | struct nv_pmu_boardobjgrp *pmuboardobjgrp, | ||
50 | struct nv_pmu_boardobj **ppboardobjpmudata, | ||
51 | u8 idx) | ||
52 | { | ||
53 | struct nv_pmu_clk_clk_vf_point_boardobj_grp_set *pgrp_set = | ||
54 | (struct nv_pmu_clk_clk_vf_point_boardobj_grp_set *) | ||
55 | pmuboardobjgrp; | ||
56 | |||
57 | gk20a_dbg_info(""); | ||
58 | |||
59 | /*check whether pmuboardobjgrp has a valid boardobj in index*/ | ||
60 | if (idx >= CTRL_BOARDOBJGRP_E255_MAX_OBJECTS) | ||
61 | return -EINVAL; | ||
62 | |||
63 | *ppboardobjpmudata = (struct nv_pmu_boardobj *) | ||
64 | &pgrp_set->objects[idx].data.board_obj; | ||
65 | gk20a_dbg_info(" Done"); | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static u32 _clk_vf_points_pmustatus_instget(struct gk20a *g, | ||
70 | void *pboardobjgrppmu, | ||
71 | struct nv_pmu_boardobj_query **ppboardobjpmustatus, | ||
72 | u8 idx) | ||
73 | { | ||
74 | struct nv_pmu_clk_clk_vf_point_boardobj_grp_get_status *pgrp_get_status = | ||
75 | (struct nv_pmu_clk_clk_vf_point_boardobj_grp_get_status *) | ||
76 | pboardobjgrppmu; | ||
77 | |||
78 | /*check whether pmuboardobjgrp has a valid boardobj in index*/ | ||
79 | if (idx >= CTRL_BOARDOBJGRP_E255_MAX_OBJECTS) | ||
80 | return -EINVAL; | ||
81 | |||
82 | *ppboardobjpmustatus = (struct nv_pmu_boardobj_query *) | ||
83 | &pgrp_get_status->objects[idx].data.board_obj; | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | u32 clk_vf_point_sw_setup(struct gk20a *g) | ||
88 | { | ||
89 | u32 status; | ||
90 | struct boardobjgrp *pboardobjgrp = NULL; | ||
91 | struct clk_vf_points *pclkvfpointobjs; | ||
92 | |||
93 | gk20a_dbg_info(""); | ||
94 | |||
95 | status = boardobjgrpconstruct_e255(&g->clk_pmu.clk_vf_pointobjs.super); | ||
96 | if (status) { | ||
97 | gk20a_err(dev_from_gk20a(g), | ||
98 | "error creating boardobjgrp for clk vfpoint, status - 0x%x", | ||
99 | status); | ||
100 | goto done; | ||
101 | } | ||
102 | |||
103 | pboardobjgrp = &g->clk_pmu.clk_vf_pointobjs.super.super; | ||
104 | pclkvfpointobjs = &(g->clk_pmu.clk_vf_pointobjs); | ||
105 | |||
106 | BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, CLK, CLK_VF_POINT); | ||
107 | |||
108 | status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp, | ||
109 | clk, CLK, clk_vf_point, CLK_VF_POINT); | ||
110 | if (status) { | ||
111 | gk20a_err(dev_from_gk20a(g), | ||
112 | "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x", | ||
113 | status); | ||
114 | goto done; | ||
115 | } | ||
116 | |||
117 | status = BOARDOBJGRP_PMU_CMD_GRP_GET_STATUS_CONSTRUCT(g, | ||
118 | &g->clk_pmu.clk_vf_pointobjs.super.super, | ||
119 | clk, CLK, clk_vf_point, CLK_VF_POINT); | ||
120 | if (status) { | ||
121 | gk20a_err(dev_from_gk20a(g), | ||
122 | "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x", | ||
123 | status); | ||
124 | goto done; | ||
125 | } | ||
126 | |||
127 | pboardobjgrp->pmudatainit = _clk_vf_points_pmudatainit; | ||
128 | pboardobjgrp->pmudatainstget = _clk_vf_points_pmudata_instget; | ||
129 | pboardobjgrp->pmustatusinstget = _clk_vf_points_pmustatus_instget; | ||
130 | |||
131 | done: | ||
132 | gk20a_dbg_info(" done status %x", status); | ||
133 | return status; | ||
134 | } | ||
135 | |||
136 | u32 clk_vf_point_pmu_setup(struct gk20a *g) | ||
137 | { | ||
138 | u32 status; | ||
139 | struct boardobjgrp *pboardobjgrp = NULL; | ||
140 | |||
141 | gk20a_dbg_info(""); | ||
142 | |||
143 | pboardobjgrp = &g->clk_pmu.clk_vf_pointobjs.super.super; | ||
144 | |||
145 | if (!pboardobjgrp->bconstructed) | ||
146 | return -EINVAL; | ||
147 | |||
148 | status = pboardobjgrp->pmuinithandle(g, pboardobjgrp); | ||
149 | |||
150 | gk20a_dbg_info("Done"); | ||
151 | return status; | ||
152 | } | ||
153 | |||
154 | static u32 clk_vf_point_construct_super(struct gk20a *g, | ||
155 | struct boardobj **ppboardobj, | ||
156 | u16 size, void *pargs) | ||
157 | { | ||
158 | struct clk_vf_point *pclkvfpoint; | ||
159 | struct clk_vf_point *ptmpvfpoint = | ||
160 | (struct clk_vf_point *)pargs; | ||
161 | u32 status = 0; | ||
162 | |||
163 | status = boardobj_construct_super(g, ppboardobj, | ||
164 | size, pargs); | ||
165 | if (status) | ||
166 | return -EINVAL; | ||
167 | |||
168 | pclkvfpoint = (struct clk_vf_point *)*ppboardobj; | ||
169 | |||
170 | pclkvfpoint->super.pmudatainit = | ||
171 | _clk_vf_point_pmudatainit_super; | ||
172 | |||
173 | pclkvfpoint->vfe_equ_idx = ptmpvfpoint->vfe_equ_idx; | ||
174 | pclkvfpoint->volt_rail_idx = ptmpvfpoint->volt_rail_idx; | ||
175 | |||
176 | return status; | ||
177 | } | ||
178 | |||
179 | static u32 _clk_vf_point_pmudatainit_volt(struct gk20a *g, | ||
180 | struct boardobj *board_obj_ptr, | ||
181 | struct nv_pmu_boardobj *ppmudata) | ||
182 | { | ||
183 | u32 status = 0; | ||
184 | struct clk_vf_point_volt *pclk_vf_point_volt; | ||
185 | struct nv_pmu_clk_clk_vf_point_volt_boardobj_set *pset; | ||
186 | |||
187 | gk20a_dbg_info(""); | ||
188 | |||
189 | status = _clk_vf_point_pmudatainit_super(g, board_obj_ptr, ppmudata); | ||
190 | if (status != 0) | ||
191 | return status; | ||
192 | |||
193 | pclk_vf_point_volt = | ||
194 | (struct clk_vf_point_volt *)board_obj_ptr; | ||
195 | |||
196 | pset = (struct nv_pmu_clk_clk_vf_point_volt_boardobj_set *) | ||
197 | ppmudata; | ||
198 | |||
199 | pset->source_voltage_uv = pclk_vf_point_volt->source_voltage_uv; | ||
200 | pset->vf_gain_vfe_equ_idx = pclk_vf_point_volt->vf_gain_vfe_equ_idx; | ||
201 | pset->clk_domain_idx = pclk_vf_point_volt->clk_domain_idx; | ||
202 | pset->freq_delta_khz = pclk_vf_point_volt->freq_delta_khz; | ||
203 | |||
204 | return status; | ||
205 | } | ||
206 | |||
207 | static u32 _clk_vf_point_pmudatainit_freq(struct gk20a *g, | ||
208 | struct boardobj *board_obj_ptr, | ||
209 | struct nv_pmu_boardobj *ppmudata) | ||
210 | { | ||
211 | u32 status = 0; | ||
212 | struct clk_vf_point_freq *pclk_vf_point_freq; | ||
213 | struct nv_pmu_clk_clk_vf_point_freq_boardobj_set *pset; | ||
214 | |||
215 | gk20a_dbg_info(""); | ||
216 | |||
217 | status = _clk_vf_point_pmudatainit_super(g, board_obj_ptr, ppmudata); | ||
218 | if (status != 0) | ||
219 | return status; | ||
220 | |||
221 | pclk_vf_point_freq = | ||
222 | (struct clk_vf_point_freq *)board_obj_ptr; | ||
223 | |||
224 | pset = (struct nv_pmu_clk_clk_vf_point_freq_boardobj_set *) | ||
225 | ppmudata; | ||
226 | |||
227 | pset->freq_mhz = | ||
228 | clkvfpointfreqmhzget(g, &pclk_vf_point_freq->super); | ||
229 | |||
230 | pset->volt_delta_uv = pclk_vf_point_freq->volt_delta_uv; | ||
231 | |||
232 | return status; | ||
233 | } | ||
234 | |||
235 | static u32 clk_vf_point_construct_volt(struct gk20a *g, | ||
236 | struct boardobj **ppboardobj, | ||
237 | u16 size, void *pargs) | ||
238 | { | ||
239 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
240 | struct clk_vf_point_volt *pclkvfpoint; | ||
241 | struct clk_vf_point_volt *ptmpvfpoint = | ||
242 | (struct clk_vf_point_volt *)pargs; | ||
243 | u32 status = 0; | ||
244 | |||
245 | if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_VF_POINT_TYPE_VOLT) | ||
246 | return -EINVAL; | ||
247 | |||
248 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_VF_POINT_TYPE_VOLT); | ||
249 | status = clk_vf_point_construct_super(g, ppboardobj, size, pargs); | ||
250 | if (status) | ||
251 | return -EINVAL; | ||
252 | |||
253 | pclkvfpoint = (struct clk_vf_point_volt *)*ppboardobj; | ||
254 | |||
255 | pclkvfpoint->super.super.pmudatainit = | ||
256 | _clk_vf_point_pmudatainit_volt; | ||
257 | |||
258 | pclkvfpoint->source_voltage_uv = ptmpvfpoint->source_voltage_uv; | ||
259 | pclkvfpoint->vf_gain_vfe_equ_idx = ptmpvfpoint->vf_gain_vfe_equ_idx; | ||
260 | pclkvfpoint->clk_domain_idx = ptmpvfpoint->clk_domain_idx; | ||
261 | |||
262 | return status; | ||
263 | } | ||
264 | |||
265 | static u32 clk_vf_point_construct_freq(struct gk20a *g, | ||
266 | struct boardobj **ppboardobj, | ||
267 | u16 size, void *pargs) | ||
268 | { | ||
269 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
270 | struct clk_vf_point_freq *pclkvfpoint; | ||
271 | struct clk_vf_point_freq *ptmpvfpoint = | ||
272 | (struct clk_vf_point_freq *)pargs; | ||
273 | u32 status = 0; | ||
274 | |||
275 | if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_VF_POINT_TYPE_FREQ) | ||
276 | return -EINVAL; | ||
277 | |||
278 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_VF_POINT_TYPE_FREQ); | ||
279 | status = clk_vf_point_construct_super(g, ppboardobj, size, pargs); | ||
280 | if (status) | ||
281 | return -EINVAL; | ||
282 | |||
283 | pclkvfpoint = (struct clk_vf_point_freq *)*ppboardobj; | ||
284 | |||
285 | pclkvfpoint->super.super.pmudatainit = | ||
286 | _clk_vf_point_pmudatainit_freq; | ||
287 | |||
288 | clkvfpointfreqmhzset(g, &pclkvfpoint->super, | ||
289 | clkvfpointfreqmhzget(g, &ptmpvfpoint->super)); | ||
290 | |||
291 | return status; | ||
292 | } | ||
293 | |||
294 | struct clk_vf_point *construct_clk_vf_point(struct gk20a *g, void *pargs) | ||
295 | { | ||
296 | struct boardobj *board_obj_ptr = NULL; | ||
297 | u32 status; | ||
298 | |||
299 | gk20a_dbg_info(""); | ||
300 | switch (BOARDOBJ_GET_TYPE(pargs)) { | ||
301 | case CTRL_CLK_CLK_VF_POINT_TYPE_FREQ: | ||
302 | status = clk_vf_point_construct_freq(g, &board_obj_ptr, | ||
303 | sizeof(struct clk_vf_point_freq), pargs); | ||
304 | break; | ||
305 | |||
306 | case CTRL_CLK_CLK_VF_POINT_TYPE_VOLT: | ||
307 | status = clk_vf_point_construct_volt(g, &board_obj_ptr, | ||
308 | sizeof(struct clk_vf_point_volt), pargs); | ||
309 | break; | ||
310 | |||
311 | default: | ||
312 | return NULL; | ||
313 | } | ||
314 | |||
315 | if (status) | ||
316 | return NULL; | ||
317 | |||
318 | gk20a_dbg_info(" Done"); | ||
319 | |||
320 | return (struct clk_vf_point *)board_obj_ptr; | ||
321 | } | ||
322 | |||
323 | static u32 _clk_vf_point_pmudatainit_super(struct gk20a *g, | ||
324 | struct boardobj *board_obj_ptr, | ||
325 | struct nv_pmu_boardobj *ppmudata) | ||
326 | { | ||
327 | u32 status = 0; | ||
328 | struct clk_vf_point *pclk_vf_point; | ||
329 | struct nv_pmu_clk_clk_vf_point_boardobj_set *pset; | ||
330 | |||
331 | gk20a_dbg_info(""); | ||
332 | |||
333 | status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata); | ||
334 | if (status != 0) | ||
335 | return status; | ||
336 | |||
337 | pclk_vf_point = | ||
338 | (struct clk_vf_point *)board_obj_ptr; | ||
339 | |||
340 | pset = (struct nv_pmu_clk_clk_vf_point_boardobj_set *) | ||
341 | ppmudata; | ||
342 | |||
343 | |||
344 | pset->vfe_equ_idx = pclk_vf_point->vfe_equ_idx; | ||
345 | pset->volt_rail_idx = pclk_vf_point->volt_rail_idx; | ||
346 | return status; | ||
347 | } | ||