aboutsummaryrefslogtreecommitdiffstats
path: root/include/clk/clk_fll.c
diff options
context:
space:
mode:
Diffstat (limited to 'include/clk/clk_fll.c')
-rw-r--r--include/clk/clk_fll.c495
1 files changed, 495 insertions, 0 deletions
diff --git a/include/clk/clk_fll.c b/include/clk/clk_fll.c
new file mode 100644
index 0000000..e67dd35
--- /dev/null
+++ b/include/clk/clk_fll.c
@@ -0,0 +1,495 @@
1/*
2 * Copyright (c) 2016-2018, 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/gk20a.h>
25
26#include "clk.h"
27#include "clk_fll.h"
28#include "clk_domain.h"
29#include "boardobj/boardobjgrp.h"
30#include "boardobj/boardobjgrp_e32.h"
31#include "ctrl/ctrlclk.h"
32#include "ctrl/ctrlvolt.h"
33
34static int devinit_get_fll_device_table(struct gk20a *g,
35 struct avfsfllobjs *pfllobjs);
36static struct fll_device *construct_fll_device(struct gk20a *g,
37 void *pargs);
38static int fll_device_init_pmudata_super(struct gk20a *g,
39 struct boardobj *board_obj_ptr,
40 struct nv_pmu_boardobj *ppmudata);
41
42static int _clk_fll_devgrp_pmudatainit_super(struct gk20a *g,
43 struct boardobjgrp *pboardobjgrp,
44 struct nv_pmu_boardobjgrp_super *pboardobjgrppmu)
45{
46 struct nv_pmu_clk_clk_fll_device_boardobjgrp_set_header *pset =
47 (struct nv_pmu_clk_clk_fll_device_boardobjgrp_set_header *)
48 pboardobjgrppmu;
49 struct avfsfllobjs *pfll_objs = (struct avfsfllobjs *)
50 pboardobjgrp;
51 int status = 0;
52
53 nvgpu_log_info(g, " ");
54
55 status = boardobjgrp_pmudatainit_e32(g, pboardobjgrp, pboardobjgrppmu);
56 if (status) {
57 nvgpu_err(g, "failed to init fll pmuobjgrp");
58 return status;
59 }
60 pset->lut_num_entries = pfll_objs->lut_num_entries;
61 pset->lut_step_size_uv = pfll_objs->lut_step_size_uv;
62 pset->lut_min_voltage_uv = pfll_objs->lut_min_voltage_uv;
63 pset->max_min_freq_mhz = pfll_objs->max_min_freq_mhz;
64
65 status = boardobjgrpmask_export(
66 &pfll_objs->lut_prog_master_mask.super,
67 pfll_objs->lut_prog_master_mask.super.bitcount,
68 &pset->lut_prog_master_mask.super);
69
70 nvgpu_log_info(g, " Done");
71 return status;
72}
73
74static int _clk_fll_devgrp_pmudata_instget(struct gk20a *g,
75 struct nv_pmu_boardobjgrp *pmuboardobjgrp,
76 struct nv_pmu_boardobj **ppboardobjpmudata,
77 u8 idx)
78{
79 struct nv_pmu_clk_clk_fll_device_boardobj_grp_set *pgrp_set =
80 (struct nv_pmu_clk_clk_fll_device_boardobj_grp_set *)
81 pmuboardobjgrp;
82
83 nvgpu_log_info(g, " ");
84
85 /*check whether pmuboardobjgrp has a valid boardobj in index*/
86 if (((u32)BIT(idx) &
87 pgrp_set->hdr.data.super.obj_mask.super.data[0]) == 0) {
88 return -EINVAL;
89 }
90
91 *ppboardobjpmudata = (struct nv_pmu_boardobj *)
92 &pgrp_set->objects[idx].data.board_obj;
93 nvgpu_log_info(g, " Done");
94 return 0;
95}
96
97static int _clk_fll_devgrp_pmustatus_instget(struct gk20a *g,
98 void *pboardobjgrppmu,
99 struct nv_pmu_boardobj_query **ppboardobjpmustatus,
100 u8 idx)
101{
102 struct nv_pmu_clk_clk_fll_device_boardobj_grp_get_status *pgrp_get_status =
103 (struct nv_pmu_clk_clk_fll_device_boardobj_grp_get_status *)
104 pboardobjgrppmu;
105
106 /*check whether pmuboardobjgrp has a valid boardobj in index*/
107 if (((u32)BIT(idx) &
108 pgrp_get_status->hdr.data.super.obj_mask.super.data[0]) == 0) {
109 return -EINVAL;
110 }
111
112 *ppboardobjpmustatus = (struct nv_pmu_boardobj_query *)
113 &pgrp_get_status->objects[idx].data.board_obj;
114 return 0;
115}
116
117int clk_fll_sw_setup(struct gk20a *g)
118{
119 int status;
120 struct boardobjgrp *pboardobjgrp = NULL;
121 struct avfsfllobjs *pfllobjs;
122 struct fll_device *pfll;
123 struct fll_device *pfll_master;
124 struct fll_device *pfll_local;
125 u8 i;
126 u8 j;
127
128 nvgpu_log_info(g, " ");
129
130 status = boardobjgrpconstruct_e32(g, &g->clk_pmu.avfs_fllobjs.super);
131 if (status) {
132 nvgpu_err(g,
133 "error creating boardobjgrp for fll, status - 0x%x", status);
134 goto done;
135 }
136 pfllobjs = &(g->clk_pmu.avfs_fllobjs);
137 pboardobjgrp = &(g->clk_pmu.avfs_fllobjs.super.super);
138
139 BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, CLK, FLL_DEVICE);
140
141 status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp,
142 clk, CLK, clk_fll_device, CLK_FLL_DEVICE);
143 if (status) {
144 nvgpu_err(g,
145 "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x",
146 status);
147 goto done;
148 }
149
150 pboardobjgrp->pmudatainit = _clk_fll_devgrp_pmudatainit_super;
151 pboardobjgrp->pmudatainstget = _clk_fll_devgrp_pmudata_instget;
152 pboardobjgrp->pmustatusinstget = _clk_fll_devgrp_pmustatus_instget;
153 pfllobjs = (struct avfsfllobjs *)pboardobjgrp;
154 pfllobjs->lut_num_entries = g->ops.clk.lut_num_entries;
155 pfllobjs->lut_step_size_uv = CTRL_CLK_VIN_STEP_SIZE_UV;
156 pfllobjs->lut_min_voltage_uv = CTRL_CLK_LUT_MIN_VOLTAGE_UV;
157
158 /* Initialize lut prog master mask to zero.*/
159 boardobjgrpmask_e32_init(&pfllobjs->lut_prog_master_mask, NULL);
160
161 status = devinit_get_fll_device_table(g, pfllobjs);
162 if (status) {
163 goto done;
164 }
165
166 status = BOARDOBJGRP_PMU_CMD_GRP_GET_STATUS_CONSTRUCT(g,
167 &g->clk_pmu.avfs_fllobjs.super.super,
168 clk, CLK, clk_fll_device, CLK_FLL_DEVICE);
169 if (status) {
170 nvgpu_err(g,
171 "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x",
172 status);
173 goto done;
174 }
175
176 BOARDOBJGRP_FOR_EACH(&(pfllobjs->super.super),
177 struct fll_device *, pfll, i) {
178 pfll_master = NULL;
179 j = 0;
180 BOARDOBJGRP_ITERATOR(&(pfllobjs->super.super),
181 struct fll_device *, pfll_local, j,
182 &pfllobjs->lut_prog_master_mask.super) {
183 if (pfll_local->clk_domain == pfll->clk_domain) {
184 pfll_master = pfll_local;
185 break;
186 }
187 }
188
189 if (pfll_master == NULL) {
190 status = boardobjgrpmask_bitset(
191 &pfllobjs->lut_prog_master_mask.super,
192 BOARDOBJ_GET_IDX(pfll));
193 if (status) {
194 nvgpu_err(g, "err setting lutprogmask");
195 goto done;
196 }
197 pfll_master = pfll;
198 }
199 status = pfll_master->lut_broadcast_slave_register(
200 g, pfllobjs, pfll_master, pfll);
201
202 if (status) {
203 nvgpu_err(g, "err setting lutslavemask");
204 goto done;
205 }
206 }
207done:
208 nvgpu_log_info(g, " done status %x", status);
209 return status;
210}
211
212int clk_fll_pmu_setup(struct gk20a *g)
213{
214 int status;
215 struct boardobjgrp *pboardobjgrp = NULL;
216
217 nvgpu_log_info(g, " ");
218
219 pboardobjgrp = &g->clk_pmu.avfs_fllobjs.super.super;
220
221 if (!pboardobjgrp->bconstructed) {
222 return -EINVAL;
223 }