aboutsummaryrefslogtreecommitdiffstats
path: root/include/clk/clk_prog.c
diff options
context:
space:
mode:
Diffstat (limited to 'include/clk/clk_prog.c')
-rw-r--r--include/clk/clk_prog.c1152
1 files changed, 1152 insertions, 0 deletions
diff --git a/include/clk/clk_prog.c b/include/clk/clk_prog.c
new file mode 100644
index 0000000..9d44d6d
--- /dev/null
+++ b/include/clk/clk_prog.c
@@ -0,0 +1,1152 @@
1/*
2 * Copyright (c) 2016-2020, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 */
22
23#include <nvgpu/bios.h>
24#include <nvgpu/kmem.h>
25#include <nvgpu/gk20a.h>
26
27#include "clk.h"
28#include "clk_prog.h"
29#include "clk_vf_point.h"
30#include "boardobj/boardobjgrp.h"
31#include "boardobj/boardobjgrp_e32.h"
32#include "gp106/bios_gp106.h"
33#include "ctrl/ctrlclk.h"
34#include "ctrl/ctrlvolt.h"
35
36static struct clk_prog *construct_clk_prog(struct gk20a *g, void *pargs);
37static int devinit_get_clk_prog_table(struct gk20a *g,
38 struct clk_progs *pprogobjs);
39static vf_flatten vfflatten_prog_1x_master;
40static vf_lookup vflookup_prog_1x_master;
41static get_fpoints getfpoints_prog_1x_master;
42static get_slaveclk getslaveclk_prog_1x_master;
43
44static int _clk_progs_pmudatainit(struct gk20a *g,
45 struct boardobjgrp *pboardobjgrp,
46 struct nv_pmu_boardobjgrp_super *pboardobjgrppmu)
47{
48 struct nv_pmu_clk_clk_prog_boardobjgrp_set_header *pset =
49 (struct nv_pmu_clk_clk_prog_boardobjgrp_set_header *)
50 pboardobjgrppmu;
51 struct clk_progs *pprogs = (struct clk_progs *)pboardobjgrp;
52 u32 status = 0;
53
54 status = boardobjgrp_pmudatainit_e32(g, pboardobjgrp, pboardobjgrppmu);
55 if (status) {
56 nvgpu_err(g, "error updating pmu boardobjgrp for clk prog 0x%x",
57 status);
58 goto done;
59 }
60 pset->slave_entry_count = pprogs->slave_entry_count;
61 pset->vf_entry_count = pprogs->vf_entry_count;
62
63done:
64 return status;
65}
66
67static int _clk_progs_pmudata_instget(struct gk20a *g,
68 struct nv_pmu_boardobjgrp *pmuboardobjgrp,
69 struct nv_pmu_boardobj **ppboardobjpmudata,
70 u8 idx)
71{
72 struct nv_pmu_clk_clk_prog_boardobj_grp_set *pgrp_set =
73 (struct nv_pmu_clk_clk_prog_boardobj_grp_set *)pmuboardobjgrp;
74
75 nvgpu_log_info(g, " ");
76
77 /*check whether pmuboardobjgrp has a valid boardobj in index*/
78 if (((u32)BIT(idx) &
79 pgrp_set->hdr.data.super.obj_mask.super.data[0]) == 0) {
80 return -EINVAL;
81 }
82
83 *ppboardobjpmudata = (struct nv_pmu_boardobj *)
84 &pgrp_set->objects[idx].data.board_obj;
85 nvgpu_log_info(g, " Done");
86 return 0;
87}
88
89int clk_prog_sw_setup(struct gk20a *g)
90{
91 int status;
92 struct boardobjgrp *pboardobjgrp = NULL;
93 struct clk_progs *pclkprogobjs;
94
95 nvgpu_log_info(g, " ");
96
97 status = boardobjgrpconstruct_e255(g, &g->clk_pmu.clk_progobjs.super);
98 if (status) {
99 nvgpu_err(g,
100 "error creating boardobjgrp for clk prog, status - 0x%x",
101 status);
102 goto done;
103 }
104
105 pboardobjgrp = &g->clk_pmu.clk_progobjs.super.super;
106 pclkprogobjs = &(g->clk_pmu.clk_progobjs);
107
108 BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, CLK, CLK_PROG);
109
110 status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp,
111 clk, CLK, clk_prog, CLK_PROG);
112 if (status) {
113 nvgpu_err(g,
114 "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x",
115 status);
116 goto done;
117 }
118
119 pboardobjgrp->pmudatainit = _clk_progs_pmudatainit;
120 pboardobjgrp->pmudatainstget = _clk_progs_pmudata_instget;
121
122 status = devinit_get_clk_prog_table(g, pclkprogobjs);
123 if (status) {
124 goto done;
125 }
126
127 status = clk_domain_clk_prog_link(g, &g->clk_pmu);
128 if (status) {
129 nvgpu_err(g, "error constructing VF point board objects");
130 goto done;
131 }
132
133
134done:
135 nvgpu_log_info(g, " done status %x", status);
136 return status;
137}
138
139int clk_prog_pmu_setup(struct gk20a *g)
140{
141 int status;
142 struct boardobjgrp *pboardobjgrp = NULL;
143
144 nvgpu_log_info(g, " ");
145
146 pboardobjgrp = &g->clk_pmu.clk_progobjs.super.super;
147
148 if (!pboardobjgrp->bconstructed) {
149 return -EINVAL;
150 }
151
152 status = pboardobjgrp->pmuinithandle(g, pboardobjgrp);
153
154 nvgpu_log_info(g, "Done");
155 return status;
156}
157
158static int devinit_get_clk_prog_table(struct gk20a *g,
159 struct clk_progs *pclkprogobjs)
160{
161 int status = 0;
162 u8 *clkprogs_tbl_ptr = NULL;
163 struct vbios_clock_programming_table_1x_header header = { 0 };
164 struct vbios_clock_programming_table_1x_entry prog = { 0 };
165 struct vbios_clock_programming_table_1x_slave_entry slaveprog = { 0 };
166 struct vbios_clock_programming_table_1x_vf_entry vfprog = { 0 };
167 u8 *entry = NULL;
168 u8 *slaveentry = NULL;
169 u8 *vfentry = NULL;
170 u32 i, j = 0;
171 struct clk_prog *pprog;
172 u8 prog_type;
173 u32 szfmt = VBIOS_CLOCK_PROGRAMMING_TABLE_1X_ENTRY_SIZE_0D;
174 u32 hszfmt = VBIOS_CLOCK_PROGRAMMING_TABLE_1X_HEADER_SIZE_08;
175 u32 slaveszfmt = VBIOS_CLOCK_PROGRAMMING_TABLE_1X_SLAVE_ENTRY_SIZE_03;
176 u32 vfszfmt = VBIOS_CLOCK_PROGRAMMING_TABLE_1X_VF_ENTRY_SIZE_02;
177 struct ctrl_clk_clk_prog_1x_master_vf_entry
178 vfentries[CTRL_CLK_CLK_PROG_1X_MASTER_VF_ENTRY_MAX_ENTRIES];
179 struct ctrl_clk_clk_prog_1x_master_ratio_slave_entry
180 ratioslaveentries[CTRL_CLK_PROG_1X_MASTER_MAX_SLAVE_ENTRIES];
181 struct ctrl_clk_clk_prog_1x_master_table_slave_entry
182 tableslaveentries[CTRL_CLK_PROG_1X_MASTER_MAX_SLAVE_ENTRIES];
183 union {
184 struct boardobj board_obj;
185 struct clk_prog clkprog;
186 struct clk_prog_1x v1x;
187 struct clk_prog_1x_master v1x_master;
188 struct clk_prog_1x_master_ratio v1x_master_ratio;
189 struct clk_prog_1x_master_table v1x_master_table;
190 } prog_data;
191
192 nvgpu_log_info(g, " ");
193
194 clkprogs_tbl_ptr = (u8 *)nvgpu_bios_get_perf_table_ptrs(g,
195 g->bios.clock_token, CLOCK_PROGRAMMING_TABLE);
196 if (clkprogs_tbl_ptr == NULL) {
197 status = -EINVAL;
198 goto done;
199 }
200
201 memcpy(&header, clkprogs_tbl_ptr, hszfmt);
202 if (header.header_size < hszfmt) {
203 status = -EINVAL;
204 goto done;
205 }
206 hszfmt = header.header_size;
207
208 if (header.entry_size <= VBIOS_CLOCK_PROGRAMMING_TABLE_1X_ENTRY_SIZE_05) {
209 szfmt = header.entry_size;
210 } else if (header.entry_size <= VBIOS_CLOCK_PROGRAMMING_TABLE_1X_ENTRY_SIZE_0D) {
211 szfmt = header.entry_size;
212 } else {
213 status = -EINVAL;
214 goto done;
215 }
216
217 if (header.vf_entry_size < vfszfmt) {
218 status = -EINVAL;
219 goto done;
220 }
221 vfszfmt = header.vf_entry_size;
222 if (header.slave_entry_size < slaveszfmt) {
223 status = -EINVAL;
224 goto done;
225 }