diff options
| author | Joshua Bakita <bakitajoshua@gmail.com> | 2024-09-25 16:09:09 -0400 |
|---|---|---|
| committer | Joshua Bakita <bakitajoshua@gmail.com> | 2024-09-25 16:09:09 -0400 |
| commit | f347fde22f1297e4f022600d201780d5ead78114 (patch) | |
| tree | 76be305d6187003a1e0486ff6e91efb1062ae118 /include/clk | |
| parent | 8340d234d78a7d0f46c11a584de538148b78b7cb (diff) | |
Delete no-longer-needed nvgpu headers
The dependency on these was removed in commit 8340d234.
Diffstat (limited to 'include/clk')
| -rw-r--r-- | include/clk/clk.c | 942 | ||||
| -rw-r--r-- | include/clk/clk.h | 144 | ||||
| -rw-r--r-- | include/clk/clk_arb.c | 1087 | ||||
| -rw-r--r-- | include/clk/clk_domain.c | 1666 | ||||
| -rw-r--r-- | include/clk/clk_domain.h | 157 | ||||
| -rw-r--r-- | include/clk/clk_fll.c | 495 | ||||
| -rw-r--r-- | include/clk/clk_fll.h | 81 | ||||
| -rw-r--r-- | include/clk/clk_freq_controller.c | 462 | ||||
| -rw-r--r-- | include/clk/clk_freq_controller.h | 84 | ||||
| -rw-r--r-- | include/clk/clk_mclk.h | 60 | ||||
| -rw-r--r-- | include/clk/clk_prog.c | 1152 | ||||
| -rw-r--r-- | include/clk/clk_prog.h | 100 | ||||
| -rw-r--r-- | include/clk/clk_vf_point.c | 433 | ||||
| -rw-r--r-- | include/clk/clk_vf_point.h | 83 | ||||
| -rw-r--r-- | include/clk/clk_vin.c | 573 | ||||
| -rw-r--r-- | include/clk/clk_vin.h | 79 |
16 files changed, 0 insertions, 7598 deletions
diff --git a/include/clk/clk.c b/include/clk/clk.c deleted file mode 100644 index d8e30c4..0000000 --- a/include/clk/clk.c +++ /dev/null | |||
| @@ -1,942 +0,0 @@ | |||
| 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/pmu.h> | ||
| 24 | #include <nvgpu/pmuif/nvgpu_gpmu_cmdif.h> | ||
| 25 | #include <nvgpu/gk20a.h> | ||
| 26 | |||
| 27 | #include "clk.h" | ||
| 28 | #include "ctrl/ctrlclk.h" | ||
| 29 | #include "ctrl/ctrlvolt.h" | ||
| 30 | #include "volt/volt.h" | ||
| 31 | |||
| 32 | #define BOOT_GPC2CLK_MHZ 2581 | ||
| 33 | #define BOOT_MCLK_MHZ 3003 | ||
| 34 | |||
| 35 | struct clkrpc_pmucmdhandler_params { | ||
| 36 | struct nv_pmu_clk_rpc *prpccall; | ||
| 37 | u32 success; | ||
| 38 | }; | ||
| 39 | |||
| 40 | static void clkrpc_pmucmdhandler(struct gk20a *g, struct pmu_msg *msg, | ||
| 41 | void *param, u32 handle, u32 status) | ||
| 42 | { | ||
| 43 | struct clkrpc_pmucmdhandler_params *phandlerparams = | ||
| 44 | (struct clkrpc_pmucmdhandler_params *)param; | ||
| 45 | |||
| 46 | nvgpu_log_info(g, " "); | ||
| 47 | |||
| 48 | if (msg->msg.clk.msg_type != NV_PMU_CLK_MSG_ID_RPC) { | ||
| 49 | nvgpu_err(g, "unsupported msg for VFE LOAD RPC %x", | ||
| 50 | msg->msg.clk.msg_type); | ||
| 51 | return; | ||
| 52 | } | ||
| 53 | |||
| 54 | if (phandlerparams->prpccall->b_supported) { | ||
| 55 | phandlerparams->success = 1; | ||
| 56 | } | ||
| 57 | } | ||
| 58 | |||
| 59 | |||
| 60 | int clk_pmu_freq_effective_avg_load(struct gk20a *g, bool bload) | ||
| 61 | { | ||
| 62 | struct pmu_cmd cmd; | ||
| 63 | struct pmu_payload payload; | ||
| 64 | u32 status; | ||
| 65 | u32 seqdesc; | ||
| 66 | struct nv_pmu_clk_rpc rpccall; | ||
| 67 | struct clkrpc_pmucmdhandler_params handler; | ||
| 68 | struct nv_pmu_clk_load *clkload; | ||
| 69 | |||
| 70 | memset(&payload, 0, sizeof(struct pmu_payload)); | ||
| 71 | memset(&rpccall, 0, sizeof(struct nv_pmu_clk_rpc)); | ||
| 72 | memset(&handler, 0, sizeof(struct clkrpc_pmucmdhandler_params)); | ||
| 73 | memset(&cmd, 0, sizeof(struct pmu_cmd)); | ||
| 74 | |||
| 75 | rpccall.function = NV_PMU_CLK_RPC_ID_LOAD; | ||
| 76 | clkload = &rpccall.params.clk_load; | ||
| 77 | clkload->feature = NV_NV_PMU_CLK_LOAD_FEATURE_FREQ_EFFECTIVE_AVG; | ||
| 78 | clkload->action_mask = bload ? | ||
| 79 | NV_NV_PMU_CLK_LOAD_ACTION_MASK_FREQ_EFFECTIVE_AVG_CALLBACK_YES : | ||
| 80 | NV_NV_PMU_CLK_LOAD_ACTION_MASK_FREQ_EFFECTIVE_AVG_CALLBACK_NO; | ||
| 81 | |||
| 82 | cmd.hdr.unit_id = PMU_UNIT_CLK; | ||
| 83 | cmd.hdr.size = (u32)sizeof(struct nv_pmu_clk_cmd) + | ||
| 84 | (u32)sizeof(struct pmu_hdr); | ||
| 85 | |||
| 86 | cmd.cmd.clk.cmd_type = NV_PMU_CLK_CMD_ID_RPC; | ||
| 87 | |||
| 88 | payload.in.buf = (u8 *)&rpccall; | ||
| 89 | payload.in.size = (u32)sizeof(struct nv_pmu_clk_rpc); | ||
| 90 | payload.in.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED; | ||
| 91 | payload.in.offset = NV_PMU_CLK_CMD_RPC_ALLOC_OFFSET; | ||
| 92 | |||
| 93 | payload.out.buf = (u8 *)&rpccall; | ||
| 94 | payload.out.size = (u32)sizeof(struct nv_pmu_clk_rpc); | ||
| 95 | payload.out.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED; | ||
| 96 | payload.out.offset = NV_PMU_CLK_MSG_RPC_ALLOC_OFFSET; | ||
| 97 | |||
| 98 | handler.prpccall = &rpccall; | ||
| 99 | handler.success = 0; | ||
| 100 | |||
| 101 | status = nvgpu_pmu_cmd_post(g, &cmd, NULL, &payload, | ||
| 102 | PMU_COMMAND_QUEUE_LPQ, | ||
| 103 | clkrpc_pmucmdhandler, (void *)&handler, | ||
| 104 | &seqdesc, ~0); | ||
| 105 | if (status) { | ||
| 106 | nvgpu_err(g, "unable to post clk RPC cmd %x", | ||
| 107 | cmd.cmd.clk.cmd_type); | ||
| 108 | goto done; | ||
| 109 | } | ||
| 110 | |||
| 111 | pmu_wait_message_cond(&g->pmu, | ||
| 112 | gk20a_get_gr_idle_timeout(g), | ||
| 113 | &handler.success, 1); | ||
| 114 | if (handler.success == 0) { | ||
| 115 | nvgpu_err(g, "rpc call to load Effective avg clk domain freq failed"); | ||
| 116 | status = -EINVAL; | ||
| 117 | } | ||
| 118 | |||
| 119 | done: | ||
| 120 | return status; | ||
| 121 | } | ||
| 122 | |||
| 123 | u32 clk_freq_effective_avg(struct gk20a *g, u32 clkDomainMask) { | ||
| 124 | |||
| 125 | struct pmu_cmd cmd; | ||
| 126 | struct pmu_payload payload; | ||
| 127 | u32 status; | ||
| 128 | u32 seqdesc; | ||
| 129 | struct nv_pmu_clk_rpc rpccall; | ||
| 130 | struct clkrpc_pmucmdhandler_params handler; | ||
| 131 | struct nv_pmu_clk_freq_effective_avg *clk_freq_effective_avg; | ||
| 132 | |||
| 133 | memset(&payload, 0, sizeof(struct pmu_payload)); | ||
| 134 | memset(&rpccall, 0, sizeof(struct nv_pmu_clk_rpc)); | ||
| 135 | memset(&handler, 0, sizeof(struct clkrpc_pmucmdhandler_params)); | ||
| 136 | memset(&cmd, 0, sizeof(struct pmu_cmd)); | ||
| 137 | |||
| 138 | rpccall.function = NV_PMU_CLK_RPC_ID_CLK_FREQ_EFF_AVG; | ||
| 139 | clk_freq_effective_avg = &rpccall.params.clk_freq_effective_avg; | ||
| 140 | clk_freq_effective_avg->clkDomainMask = clkDomainMask; | ||
| 141 | |||
| 142 | cmd.hdr.unit_id = PMU_UNIT_CLK; | ||
| 143 | cmd.hdr.size = (u32)sizeof(struct nv_pmu_clk_cmd) + | ||
| 144 | (u32)sizeof(struct pmu_hdr); | ||
| 145 | |||
| 146 | cmd.cmd.clk.cmd_type = NV_PMU_CLK_CMD_ID_RPC; | ||
| 147 | |||
| 148 | payload.in.buf = (u8 *)&rpccall; | ||
| 149 | payload.in.size = (u32)sizeof(struct nv_pmu_clk_rpc); | ||
| 150 | payload.in.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED; | ||
| 151 | payload.in.offset = NV_PMU_CLK_CMD_RPC_ALLOC_OFFSET; | ||
| 152 | |||
| 153 | payload.out.buf = (u8 *)&rpccall; | ||
| 154 | payload.out.size = (u32)sizeof(struct nv_pmu_clk_rpc); | ||
| 155 | payload.out.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED; | ||
| 156 | payload.out.offset = NV_PMU_CLK_MSG_RPC_ALLOC_OFFSET; | ||
| 157 | |||
| 158 | handler.prpccall = &rpccall; | ||
| 159 | handler.success = 0; | ||
| 160 | |||
| 161 | status = nvgpu_pmu_cmd_post(g, &cmd, NULL, &payload, | ||
| 162 | PMU_COMMAND_QUEUE_LPQ, | ||
| 163 | clkrpc_pmucmdhandler, (void *)&handler, | ||
| 164 | &seqdesc, ~0); | ||
| 165 | if (status) { | ||
| 166 | nvgpu_err(g, "unable to post clk RPC cmd %x", | ||
| 167 | cmd.cmd.clk.cmd_type); | ||
| 168 | goto done; | ||
| 169 | } | ||
| 170 | |||
| 171 | pmu_wait_message_cond(&g->pmu, | ||
| 172 | gk20a_get_gr_idle_timeout(g), | ||
| 173 | &handler.success, 1); | ||
| 174 | if (handler.success == 0) { | ||
| 175 | nvgpu_err(g, "rpc call to get clk frequency average failed"); | ||
| 176 | status = -EINVAL; | ||
| 177 | goto done; | ||
| 178 | } | ||
| 179 | |||
| 180 | return rpccall.params.clk_freq_effective_avg.freqkHz[clkDomainMask]; | ||
| 181 | |||
| 182 | done: | ||
| 183 | return status; | ||
| 184 | } | ||
| 185 | |||
| 186 | int clk_pmu_freq_controller_load(struct gk20a *g, bool bload, u8 bit_idx) | ||
| 187 | { | ||
| 188 | struct pmu_cmd cmd; | ||
| 189 | struct pmu_payload payload; | ||
| 190 | u32 status; | ||
| 191 | u32 seqdesc; | ||
| 192 | struct nv_pmu_clk_rpc rpccall; | ||
| 193 | struct clkrpc_pmucmdhandler_params handler; | ||
| 194 | struct nv_pmu_clk_load *clkload; | ||
| 195 | struct clk_freq_controllers *pclk_freq_controllers; | ||
| 196 | struct ctrl_boardobjgrp_mask_e32 *load_mask; | ||
| 197 | struct boardobjgrpmask_e32 isolate_cfc_mask; | ||
| 198 | |||
| 199 | memset(&payload, 0, sizeof(struct pmu_payload)); | ||
| 200 | memset(&rpccall, 0, sizeof(struct nv_pmu_clk_rpc)); | ||
| 201 | memset(&handler, 0, sizeof(struct clkrpc_pmucmdhandler_params)); | ||
| 202 | |||
| 203 | pclk_freq_controllers = &g->clk_pmu.clk_freq_controllers; | ||
| 204 | rpccall.function = NV_PMU_CLK_RPC_ID_LOAD; | ||
| 205 | clkload = &rpccall.params.clk_load; | ||
| 206 | clkload->feature = NV_NV_PMU_CLK_LOAD_FEATURE_FREQ_CONTROLLER; | ||
| 207 | clkload->action_mask = bload ? | ||
| 208 | NV_NV_PMU_CLK_LOAD_ACTION_MASK_FREQ_CONTROLLER_CALLBACK_YES : | ||
| 209 | NV_NV_PMU_CLK_LOAD_ACTION_MASK_FREQ_CONTROLLER_CALLBACK_NO; | ||
| 210 | |||
| 211 | load_mask = &rpccall.params.clk_load.payload.freq_controllers.load_mask; | ||
| 212 | |||
| 213 | status = boardobjgrpmask_e32_init(&isolate_cfc_mask, NULL); | ||
| 214 | |||
| 215 | if (bit_idx == CTRL_CLK_CLK_FREQ_CONTROLLER_ID_ALL) { | ||
| 216 | status = boardobjgrpmask_export( | ||
| 217 | &pclk_freq_controllers-> | ||
| 218 | freq_ctrl_load_mask.super, | ||
| 219 | pclk_freq_controllers-> | ||
| 220 | freq_ctrl_load_mask.super.bitcount, | ||
| 221 | &load_mask->super); | ||
| 222 | |||
| 223 | |||
| 224 | } else { | ||
| 225 | status = boardobjgrpmask_bitset(&isolate_cfc_mask.super, | ||
| 226 | bit_idx); | ||
| 227 | status = boardobjgrpmask_export(&isolate_cfc_mask.super, | ||
| 228 | isolate_cfc_mask.super.bitcount, | ||
| 229 | &load_mask->super); | ||
| 230 | if (bload) { | ||
| 231 | status = boardobjgrpmask_bitset( | ||
| 232 | &pclk_freq_controllers-> | ||
| 233 | freq_ctrl_load_mask.super, | ||
| 234 | bit_idx); | ||
| 235 | } else { | ||
| 236 | status = boardobjgrpmask_bitclr( | ||
| 237 | &pclk_freq_controllers-> | ||
| 238 | freq_ctrl_load_mask.super, | ||
| 239 | bit_idx); | ||
| 240 | } | ||
| 241 | } | ||
| 242 | |||
| 243 | if (status) { | ||
| 244 | nvgpu_err(g, "Error in generating mask used to select CFC"); | ||
| 245 | goto done; | ||
| 246 | } | ||
| 247 | |||
| 248 | cmd.hdr.unit_id = PMU_UNIT_CLK; | ||
| 249 | cmd.hdr.size = (u32)sizeof(struct nv_pmu_clk_cmd) + | ||
| 250 | (u32)sizeof(struct pmu_hdr); | ||
| 251 | |||
| 252 | cmd.cmd.clk.cmd_type = NV_PMU_CLK_CMD_ID_RPC; | ||
| 253 | |||
| 254 | payload.in.buf = (u8 *)&rpccall; | ||
| 255 | payload.in.size = (u32)sizeof(struct nv_pmu_clk_rpc); | ||
| 256 | payload.in.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED; | ||
| 257 | payload.in.offset = NV_PMU_CLK_CMD_RPC_ALLOC_OFFSET; | ||
| 258 | |||
| 259 | payload.out.buf = (u8 *)&rpccall; | ||
| 260 | payload.out.size = (u32)sizeof(struct nv_pmu_clk_rpc); | ||
| 261 | payload.out.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED; | ||
| 262 | payload.out.offset = NV_PMU_CLK_MSG_RPC_ALLOC_OFFSET; | ||
| 263 | |||
| 264 | handler.prpccall = &rpccall; | ||
| 265 | handler.success = 0; | ||
| 266 | status = nvgpu_pmu_cmd_post(g, &cmd, NULL, &payload, | ||
| 267 | PMU_COMMAND_QUEUE_LPQ, | ||
| 268 | clkrpc_pmucmdhandler, (void *)&handler, | ||
| 269 | &seqdesc, ~0); | ||
| 270 | |||
| 271 | if (status) { | ||
| 272 | nvgpu_err(g, "unable to post clk RPC cmd %x", | ||
| 273 | cmd.cmd.clk.cmd_type); | ||
| 274 | goto done; | ||
| 275 | } | ||
| 276 | |||
| 277 | pmu_wait_message_cond(&g->pmu, | ||
| 278 | gk20a_get_gr_idle_timeout(g), | ||
| 279 | &handler.success, 1); | ||
| 280 | |||
| 281 | if (handler.success == 0) { | ||
| 282 | nvgpu_err(g, "rpc call to load freq cntlr cal failed"); | ||
| 283 | status = -EINVAL; | ||
| 284 | } | ||
| 285 | |||
| 286 | done: | ||
| 287 | return status; | ||
| 288 | } | ||
| 289 | |||
| 290 | u32 clk_pmu_vin_load(struct gk20a *g) | ||
| 291 | { | ||
| 292 | struct pmu_cmd cmd; | ||
| 293 | struct pmu_payload payload; | ||
| 294 | u32 status; | ||
| 295 | u32 seqdesc; | ||
| 296 | struct nv_pmu_clk_rpc rpccall; | ||
| 297 | struct clkrpc_pmucmdhandler_params handler; | ||
| 298 | struct nv_pmu_clk_load *clkload; | ||
| 299 | |||
| 300 | memset(&payload, 0, sizeof(struct pmu_payload)); | ||
| 301 | memset(&rpccall, 0, sizeof(struct nv_pmu_clk_rpc)); | ||
| 302 | memset(&handler, 0, sizeof(struct clkrpc_pmucmdhandler_params)); | ||
| 303 | |||
| 304 | rpccall.function = NV_PMU_CLK_RPC_ID_LOAD; | ||
| 305 | clkload = &rpccall.params.clk_load; | ||
| 306 | clkload->feature = NV_NV_PMU_CLK_LOAD_FEATURE_VIN; | ||
| 307 | clkload->action_mask = NV_NV_PMU_CLK_LOAD_ACTION_MASK_VIN_HW_CAL_PROGRAM_YES << 4; | ||
| 308 | |||
| 309 | cmd.hdr.unit_id = PMU_UNIT_CLK; | ||
| 310 | cmd.hdr.size = (u32)sizeof(struct nv_pmu_clk_cmd) + | ||
| 311 | (u32)sizeof(struct pmu_hdr); | ||
| 312 | |||
| 313 | cmd.cmd.clk.cmd_type = NV_PMU_CLK_CMD_ID_RPC; | ||
| 314 | cmd.cmd.clk.generic.b_perf_daemon_cmd =false; | ||
| 315 | |||
| 316 | payload.in.buf = (u8 *)&rpccall; | ||
| 317 | payload.in.size = (u32)sizeof(struct nv_pmu_clk_rpc); | ||
| 318 | payload.in.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED; | ||
| 319 | payload.in.offset = NV_PMU_CLK_CMD_RPC_ALLOC_OFFSET; | ||
| 320 | |||
| 321 | payload.out.buf = (u8 *)&rpccall; | ||
| 322 | payload.out.size = (u32)sizeof(struct nv_pmu_clk_rpc); | ||
| 323 | payload.out.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED; | ||
| 324 | payload.out.offset = NV_PMU_CLK_MSG_RPC_ALLOC_OFFSET; | ||
| 325 | |||
| 326 | handler.prpccall = &rpccall; | ||
| 327 | handler.success = 0; | ||
| 328 | status = nvgpu_pmu_cmd_post(g, &cmd, NULL, &payload, | ||
| 329 | PMU_COMMAND_QUEUE_LPQ, | ||
| 330 | clkrpc_pmucmdhandler, (void *)&handler, | ||
| 331 | &seqdesc, ~0); | ||
| 332 | |||
| 333 | if (status) { | ||
| 334 | nvgpu_err(g, "unable to post clk RPC cmd %x", | ||
| 335 | cmd.cmd.clk.cmd_type); | ||
| 336 | goto done; | ||
| 337 | } | ||
| 338 | |||
| 339 | pmu_wait_message_cond(&g->pmu, | ||
| 340 | gk20a_get_gr_idle_timeout(g), | ||
| 341 | &handler.success, 1); | ||
| 342 | |||
| 343 | if (handler.success == 0) { | ||
| 344 | nvgpu_err(g, "rpc call to load vin cal failed"); | ||
| 345 | status = -EINVAL; | ||
| 346 | } | ||
| 347 | |||
| 348 | done: | ||
| 349 | return status; | ||
| 350 | } | ||
| 351 | |||
| 352 | u32 nvgpu_clk_vf_change_inject_data_fill_gp10x(struct gk20a *g, | ||
| 353 | struct nv_pmu_clk_rpc *rpccall, | ||
| 354 | struct set_fll_clk *setfllclk) | ||
| 355 | { | ||
| 356 | struct nv_pmu_clk_vf_change_inject *vfchange; | ||
| 357 | |||
| 358 | vfchange = &rpccall->params.clk_vf_change_inject; | ||
| 359 | vfchange->flags = 0; | ||
| 360 | vfchange->clk_list.num_domains = 3; | ||
| 361 | vfchange->clk_list.clk_domains[0].clk_domain = CTRL_CLK_DOMAIN_GPC2CLK; | ||
| 362 | vfchange->clk_list.clk_domains[0].clk_freq_khz = | ||
| 363 | setfllclk->gpc2clkmhz * 1000; | ||
| 364 | vfchange->clk_list.clk_domains[0].clk_flags = 0; | ||
| 365 | vfchange->clk_list.clk_domains[0].current_regime_id = | ||
| 366 | setfllclk->current_regime_id_gpc; | ||
| 367 | vfchange->clk_list.clk_domains[0].target_regime_id = | ||
| 368 | setfllclk->target_regime_id_gpc; | ||
| 369 | vfchange->clk_list.clk_domains[1].clk_domain = CTRL_CLK_DOMAIN_XBAR2CLK; | ||
| 370 | vfchange->clk_list.clk_domains[1].clk_freq_khz = | ||
| 371 | setfllclk->xbar2clkmhz * 1000; | ||
| 372 | vfchange->clk_list.clk_domains[1].clk_flags = 0; | ||
| 373 | vfchange->clk_list.clk_domains[1].current_regime_id = | ||
| 374 | setfllclk->current_regime_id_xbar; | ||
| 375 | vfchange->clk_list.clk_domains[1].target_regime_id = | ||
| 376 | setfllclk->target_regime_id_xbar; | ||
| 377 | vfchange->clk_list.clk_domains[2].clk_domain = CTRL_CLK_DOMAIN_SYS2CLK; | ||
| 378 | vfchange->clk_list.clk_domains[2].clk_freq_khz = | ||
| 379 | setfllclk->sys2clkmhz * 1000; | ||
| 380 | vfchange->clk_list.clk_domains[2].clk_flags = 0; | ||
| 381 | vfchange->clk_list.clk_domains[2].current_regime_id = | ||
| 382 | setfllclk->current_regime_id_sys; | ||
| 383 | vfchange->clk_list.clk_domains[2].target_regime_id = | ||
| 384 | setfllclk->target_regime_id_sys; | ||
| 385 | vfchange->volt_list.num_rails = 1; | ||
| 386 | vfchange->volt_list.rails[0].volt_domain = CTRL_VOLT_DOMAIN_LOGIC; | ||
| 387 | vfchange->volt_list.rails[0].voltage_uv = setfllclk->voltuv; | ||
| 388 | vfchange->volt_list.rails[0].voltage_min_noise_unaware_uv = | ||
| 389 | setfllclk->voltuv; | ||
| 390 | |||
| 391 | return 0; | ||
| 392 | } | ||
| 393 | |||
| 394 | u32 nvgpu_clk_vf_change_inject_data_fill_gv10x(struct gk20a *g, | ||
| 395 | struct nv_pmu_clk_rpc *rpccall, | ||
| 396 | struct set_fll_clk *setfllclk) | ||
| 397 | { | ||
| 398 | struct nv_pmu_clk_vf_change_inject_v1 *vfchange; | ||
| 399 | |||
| 400 | vfchange = &rpccall->params.clk_vf_change_inject_v1; | ||
| 401 | vfchange->flags = 0; | ||
| 402 | vfchange->clk_list.num_domains = 4; | ||
| 403 | vfchange->clk_list.clk_domains[0].clk_domain = CTRL_CLK_DOMAIN_GPCCLK; | ||
| 404 | vfchange->clk_list.clk_domains[0].clk_freq_khz = | ||
| 405 | setfllclk->gpc2clkmhz * 1000; | ||
| 406 | |||
| 407 | vfchange->clk_list.clk_domains[1].clk_domain = CTRL_CLK_DOMAIN_XBARCLK; | ||
| 408 | vfchange->clk_list.clk_domains[1].clk_freq_khz = | ||
| 409 | setfllclk->xbar2clkmhz * 1000; | ||
| 410 | |||
| 411 | vfchange->clk_list.clk_domains[2].clk_domain = CTRL_CLK_DOMAIN_SYSCLK; | ||
| 412 | vfchange->clk_list.clk_domains[2].clk_freq_khz = | ||
| 413 | setfllclk->sys2clkmhz * 1000; | ||
| 414 | |||
| 415 | vfchange->clk_list.clk_domains[3].clk_domain = CTRL_CLK_DOMAIN_NVDCLK; | ||
| 416 | vfchange->clk_list.clk_domains[3].clk_freq_khz = 855 * 1000; | ||
| 417 | |||
| 418 | vfchange->volt_list.num_rails = 1; | ||
| 419 | vfchange->volt_list.rails[0].rail_idx = 0; | ||
| 420 | vfchange->volt_list.rails[0].voltage_uv = setfllclk->voltuv; | ||
| 421 | vfchange->volt_list.rails[0].voltage_min_noise_unaware_uv = | ||
| 422 | setfllclk->voltuv; | ||
| 423 | |||
| 424 | return 0; | ||
| 425 | } | ||
| 426 | |||
| 427 | static u32 clk_pmu_vf_inject(struct gk20a *g, struct set_fll_clk *setfllclk) | ||
| 428 | { | ||
| 429 | struct pmu_cmd cmd; | ||
| 430 | struct pmu_payload payload; | ||
| 431 | u32 status; | ||
| 432 | u32 seqdesc; | ||
| 433 | struct nv_pmu_clk_rpc rpccall; | ||
| 434 | struct clkrpc_pmucmdhandler_params handler; | ||
| 435 | |||
| 436 | memset(&payload, 0, sizeof(struct pmu_payload)); | ||
| 437 | memset(&rpccall, 0, sizeof(struct nv_pmu_clk_rpc)); | ||
| 438 | memset(&handler, 0, sizeof(struct clkrpc_pmucmdhandler_params)); | ||
| 439 | memset(&cmd, 0, sizeof(struct pmu_cmd)); | ||
| 440 | |||
| 441 | if ((setfllclk->gpc2clkmhz == 0) || (setfllclk->xbar2clkmhz == 0) || | ||
| 442 | (setfllclk->sys2clkmhz == 0) || (setfllclk->voltuv == 0)) { | ||
| 443 | return -EINVAL; | ||
| 444 | } | ||
| 445 | |||
| 446 | if ((setfllclk->target_regime_id_gpc > CTRL_CLK_FLL_REGIME_ID_FR) || | ||
| 447 | (setfllclk->target_regime_id_sys > CTRL_CLK_FLL_REGIME_ID_FR) || | ||
| 448 | (setfllclk->target_regime_id_xbar > CTRL_CLK_FLL_REGIME_ID_FR)) { | ||
| 449 | return -EINVAL; | ||
| 450 | } | ||
| 451 | |||
| 452 | rpccall.function = NV_PMU_CLK_RPC_ID_CLK_VF_CHANGE_INJECT; | ||
| 453 | |||
| 454 | g->ops.pmu_ver.clk.clk_vf_change_inject_data_fill(g, | ||
| 455 | &rpccall, setfllclk); | ||
| 456 | |||
| 457 | cmd.hdr.unit_id = PMU_UNIT_CLK; | ||
| 458 | cmd.hdr.size = (u32)sizeof(struct nv_pmu_clk_cmd) + | ||
| 459 | (u32)sizeof(struct pmu_hdr); | ||
| 460 | |||
| 461 | cmd.cmd.clk.cmd_type = NV_PMU_CLK_CMD_ID_RPC; | ||
| 462 | |||
| 463 | payload.in.buf = (u8 *)&rpccall; | ||
| 464 | payload.in.size = (u32)sizeof(struct nv_pmu_clk_rpc); | ||
| 465 | payload.in.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED; | ||
| 466 | payload.in.offset = NV_PMU_CLK_CMD_RPC_ALLOC_OFFSET; | ||
| 467 | |||
| 468 | payload.out.buf = (u8 *)&rpccall; | ||
| 469 | payload.out.size = (u32)sizeof(struct nv_pmu_clk_rpc); | ||
| 470 | payload.out.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED; | ||
| 471 | payload.out.offset = NV_PMU_CLK_MSG_RPC_ALLOC_OFFSET; | ||
| 472 | |||
| 473 | handler.prpccall = &rpccall; | ||
| 474 | handler.success = 0; | ||
| 475 | |||
| 476 | status = nvgpu_pmu_cmd_post(g, &cmd, NULL, &payload, | ||
| 477 | PMU_COMMAND_QUEUE_LPQ, | ||
| 478 | clkrpc_pmucmdhandler, (void *)&handler, | ||
| 479 | &seqdesc, ~0); | ||
| 480 | |||
| 481 | if (status) { | ||
| 482 | nvgpu_err(g, "unable to post clk RPC cmd %x", | ||
| 483 | cmd.cmd.clk.cmd_type); | ||
| 484 | goto done; | ||
| 485 | } | ||
| 486 | |||
| 487 | pmu_wait_message_cond(&g->pmu, | ||
| 488 | gk20a_get_gr_idle_timeout(g), | ||
| 489 | &handler.success, 1); | ||
| 490 | |||
| 491 | if (handler.success == 0) { | ||
| 492 | nvgpu_err(g, "rpc call to inject clock failed"); | ||
| 493 | status = -EINVAL; | ||
| 494 | } | ||
| 495 | done: | ||
| 496 | return status; | ||
| 497 | } | ||
| 498 | |||
| 499 | static u32 find_regime_id(struct gk20a *g, u32 domain, u16 clkmhz) | ||
| 500 | { | ||
| 501 | struct fll_device *pflldev; | ||
| 502 | u8 j; | ||
| 503 | struct clk_pmupstate *pclk = &g->clk_pmu; | ||
| 504 | |||
| 505 | BOARDOBJGRP_FOR_EACH(&(pclk->avfs_fllobjs.super.super), | ||
| 506 | struct fll_device *, pflldev, j) { | ||
| 507 | if (pflldev->clk_domain == domain) { | ||
| 508 | if (pflldev->regime_desc.fixed_freq_regime_limit_mhz >= | ||
| 509 | clkmhz) { | ||
| 510 | return CTRL_CLK_FLL_REGIME_ID_FFR; | ||
| 511 | } else { | ||
| 512 | return CTRL_CLK_FLL_REGIME_ID_FR; | ||
| 513 | } | ||
| 514 | } | ||
| 515 | } | ||
| 516 | return CTRL_CLK_FLL_REGIME_ID_INVALID; | ||
| 517 | } | ||
| 518 | |||
| 519 | static int set_regime_id(struct gk20a *g, u32 domain, u32 regimeid) | ||
| 520 | { | ||
| 521 | struct fll_device *pflldev; | ||
| 522 | u8 j; | ||
| 523 | struct clk_pmupstate *pclk = &g->clk_pmu; | ||
| 524 | |||
| 525 | BOARDOBJGRP_FOR_EACH(&(pclk->avfs_fllobjs.super.super), | ||
| 526 | struct fll_device *, pflldev, j) { | ||
| 527 | if (pflldev->clk_domain == domain) { | ||
| 528 | pflldev->regime_desc.regime_id = regimeid; | ||
| 529 | return 0; | ||
| 530 | } | ||
| 531 | } | ||
| 532 | return -EINVAL; | ||
| 533 | } | ||
| 534 | |||
| 535 | static int get_regime_id(struct gk20a *g, u32 domain, u32 *regimeid) | ||
| 536 | { | ||
| 537 | struct fll_device *pflldev; | ||
| 538 | u8 j; | ||
| 539 | struct clk_pmupstate *pclk = &g->clk_pmu; | ||
| 540 | |||
| 541 | BOARDOBJGRP_FOR_EACH(&(pclk->avfs_fllobjs.super.super), | ||
| 542 | struct fll_device *, pflldev, j) { | ||
| 543 | if (pflldev->clk_domain == domain) { | ||
| 544 | *regimeid = pflldev->regime_desc.regime_id; | ||
| 545 | return 0; | ||
| 546 | } | ||
| 547 | } | ||
| 548 | return -EINVAL; | ||
| 549 | } | ||
| 550 | |||
| 551 | int clk_set_fll_clks(struct gk20a *g, struct set_fll_clk *setfllclk) | ||
| 552 | { | ||
| 553 | int status = -EINVAL; | ||
| 554 | |||
| 555 | /*set regime ids */ | ||
| 556 | status = get_regime_id(g, CTRL_CLK_DOMAIN_GPC2CLK, | ||
| 557 | &setfllclk->current_regime_id_gpc); | ||
| 558 | if (status) { | ||
| 559 | goto done; | ||
| 560 | } | ||
| 561 | |||
| 562 | setfllclk->target_regime_id_gpc = find_regime_id(g, | ||
| 563 | CTRL_CLK_DOMAIN_GPC2CLK, setfllclk->gpc2clkmhz); | ||
| 564 | |||
| 565 | status = get_regime_id(g, CTRL_CLK_DOMAIN_SYS2CLK, | ||
| 566 | &setfllclk->current_regime_id_sys); | ||
| 567 | if (status) { | ||
| 568 | goto done; | ||
| 569 | } | ||
| 570 | |||
| 571 | setfllclk->target_regime_id_sys = find_regime_id(g, | ||
| 572 | CTRL_CLK_DOMAIN_SYS2CLK, setfllclk->sys2clkmhz); | ||
| 573 | |||
| 574 | status = get_regime_id(g, CTRL_CLK_DOMAIN_XBAR2CLK, | ||
| 575 | &setfllclk->current_regime_id_xbar); | ||
| 576 | if (status) { | ||
| 577 | goto done; | ||
| 578 | } | ||
| 579 | |||
| 580 | setfllclk->target_regime_id_xbar = find_regime_id(g, | ||
| 581 | CTRL_CLK_DOMAIN_XBAR2CLK, setfllclk->xbar2clkmhz); | ||
| 582 | |||
| 583 | status = clk_pmu_vf_inject(g, setfllclk); | ||
| 584 | |||
| 585 | if (status) { | ||
| 586 | nvgpu_err(g, "vf inject to change clk failed"); | ||
| 587 | } | ||
| 588 | |||
| 589 | /* save regime ids */ | ||
| 590 | status = set_regime_id(g, CTRL_CLK_DOMAIN_XBAR2CLK, | ||
| 591 | setfllclk->target_regime_id_xbar); | ||
| 592 | if (status) { | ||
| 593 | goto done; | ||
| 594 | } | ||
| 595 | |||
| 596 | status = set_regime_id(g, CTRL_CLK_DOMAIN_GPC2CLK, | ||
| 597 | setfllclk->target_regime_id_gpc); | ||
| 598 | if (status) { | ||
| 599 | goto done; | ||
| 600 | } | ||
| 601 | |||
| 602 | status = set_regime_id(g, CTRL_CLK_DOMAIN_SYS2CLK, | ||
| 603 | setfllclk->target_regime_id_sys); | ||
| 604 | if (status) { | ||
| 605 | goto done; | ||
| 606 | } | ||
| 607 | done: | ||
| 608 | return status; | ||
| 609 | } | ||
| 610 | |||
| 611 | int clk_get_fll_clks(struct gk20a *g, struct set_fll_clk *setfllclk) | ||
| 612 | { | ||
| 613 | int status = -EINVAL; | ||
| 614 | struct clk_domain *pdomain; | ||
| 615 | u8 i; | ||
| 616 | struct clk_pmupstate *pclk = &g->clk_pmu; | ||
| 617 | u16 clkmhz = 0; | ||
| 618 | struct clk_domain_3x_master *p3xmaster; | ||
| 619 | struct clk_domain_3x_slave *p3xslave; | ||
| 620 | unsigned long slaveidxmask; | ||
| 621 | |||
| 622 | if (setfllclk->gpc2clkmhz == 0) { | ||
| 623 | return -EINVAL; | ||
| 624 | } | ||
| 625 | |||
| 626 | BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super), | ||
| 627 | struct clk_domain *, pdomain, i) { | ||
| 628 | |||
| 629 | if (pdomain->api_domain == CTRL_CLK_DOMAIN_GPC2CLK) { | ||
| 630 | |||
| 631 | if (!pdomain->super.implements(g, &pdomain->super, | ||
| 632 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER)) { | ||
| 633 | status = -EINVAL; | ||
| 634 | goto done; | ||
| 635 | } | ||
| 636 | p3xmaster = (struct clk_domain_3x_master *)pdomain; | ||
| 637 | slaveidxmask = p3xmaster->slave_idxs_mask; | ||
| 638 | for_each_set_bit(i, &slaveidxmask, 32) { | ||
| 639 | p3xslave = (struct clk_domain_3x_slave *) | ||
| 640 | CLK_CLK_DOMAIN_GET(pclk, i); | ||
| 641 | if ((p3xslave->super.super.super.api_domain != | ||
| 642 | CTRL_CLK_DOMAIN_XBAR2CLK) && | ||
| 643 | (p3xslave->super.super.super.api_domain != | ||
| 644 | CTRL_CLK_DOMAIN_SYS2CLK)) { | ||
| 645 | continue; | ||
| 646 | } | ||
| 647 | clkmhz = 0; | ||
| 648 | status = p3xslave->clkdomainclkgetslaveclk(g, | ||
| 649 | pclk, | ||
| 650 | (struct clk_domain *)p3xslave, | ||
| 651 | &clkmhz, | ||
| 652 | setfllclk->gpc2clkmhz); | ||
| 653 | if (status) { | ||
| 654 | status = -EINVAL; | ||
| 655 | goto done; | ||
| 656 | } | ||
| 657 | if (p3xslave->super.super.super.api_domain == | ||
| 658 | CTRL_CLK_DOMAIN_XBAR2CLK) { | ||
| 659 | setfllclk->xbar2clkmhz = clkmhz; | ||
| 660 | } | ||
| 661 | if (p3xslave->super.super.super.api_domain == | ||
| 662 | CTRL_CLK_DOMAIN_SYS2CLK) { | ||
| 663 | setfllclk->sys2clkmhz = clkmhz; | ||
| 664 | } | ||
| 665 | } | ||
| 666 | } | ||
| 667 | } | ||
| 668 | done: | ||
| 669 | return status; | ||
| 670 | } | ||
| 671 | |||
| 672 | u32 clk_domain_print_vf_table(struct gk20a *g, u32 clkapidomain) | ||
| 673 | { | ||
| 674 | u32 status = -EINVAL; | ||
| 675 | struct clk_domain *pdomain; | ||
| 676 | u8 i; | ||
| 677 | struct clk_pmupstate *pclk = &g->clk_pmu; | ||
| 678 | u16 clkmhz = 0; | ||
| 679 | u32 volt = 0; | ||
| 680 | |||
| 681 | BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super), | ||
| 682 | struct clk_domain *, pdomain, i) { | ||
| 683 | if (pdomain->api_domain == clkapidomain) { | ||
| 684 | status = pdomain->clkdomainclkvfsearch(g, pclk, | ||
| 685 | pdomain, &clkmhz, &volt, | ||
| 686 | CLK_PROG_VFE_ENTRY_LOGIC); | ||
| 687 | status = pdomain->clkdomainclkvfsearch(g, pclk, | ||
| 688 | pdomain, &clkmhz, &volt, | ||
| 689 | CLK_PROG_VFE_ENTRY_SRAM); | ||
| 690 | } | ||
| 691 | } | ||
| 692 | return status; | ||
| 693 | } | ||
| 694 | |||
| 695 | static int clk_program_fllclks(struct gk20a *g, struct change_fll_clk *fllclk) | ||
| 696 | { | ||
| 697 | int status = -EINVAL; | ||
| 698 | struct clk_domain *pdomain; | ||
| 699 | u8 i; | ||
| 700 | struct clk_pmupstate *pclk = &g->clk_pmu; | ||
| 701 | u16 clkmhz = 0; | ||
| 702 | struct clk_domain_3x_master *p3xmaster; | ||
| 703 | struct clk_domain_3x_slave *p3xslave; | ||
| 704 | unsigned long slaveidxmask; | ||
| 705 | struct set_fll_clk setfllclk; | ||
| 706 | |||
| 707 | if (fllclk->api_clk_domain != CTRL_CLK_DOMAIN_GPCCLK) { | ||
| 708 | return -EINVAL; | ||
| 709 | } | ||
| 710 | if (fllclk->voltuv == 0) { | ||
| 711 | return -EINVAL; | ||
| 712 | } | ||
| 713 | if (fllclk->clkmhz == 0) { | ||
| 714 | return -EINVAL; | ||
| 715 | } | ||
| 716 | |||
| 717 | setfllclk.voltuv = fllclk->voltuv; | ||
| 718 | setfllclk.gpc2clkmhz = fllclk->clkmhz; | ||
| 719 | |||
| 720 | BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super), | ||
| 721 | struct clk_domain *, pdomain, i) { | ||
| 722 | |||
| 723 | if (pdomain->api_domain == fllclk->api_clk_domain) { | ||
| 724 | |||
| 725 | if (!pdomain->super.implements(g, &pdomain->super, | ||
| 726 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER)) { | ||
| 727 | status = -EINVAL; | ||
| 728 | goto done; | ||
| 729 | } | ||
| 730 | p3xmaster = (struct clk_domain_3x_master *)pdomain; | ||
| 731 | slaveidxmask = p3xmaster->slave_idxs_mask; | ||
| 732 | for_each_set_bit(i, &slaveidxmask, 32) { | ||
| 733 | p3xslave = (struct clk_domain_3x_slave *) | ||
| 734 | CLK_CLK_DOMAIN_GET(pclk, i); | ||
| 735 | if ((p3xslave->super.super.super.api_domain != | ||
| 736 | CTRL_CLK_DOMAIN_XBARCLK) && | ||
| 737 | (p3xslave->super.super.super.api_domain != | ||
| 738 | CTRL_CLK_DOMAIN_SYSCLK)) { | ||
| 739 | continue; | ||
| 740 | } | ||
| 741 | clkmhz = 0; | ||
| 742 | status = p3xslave->clkdomainclkgetslaveclk(g, | ||
| 743 | pclk, | ||
| 744 | (struct clk_domain *)p3xslave, | ||
| 745 | &clkmhz, | ||
| 746 | fllclk->clkmhz); | ||
| 747 | if (status) { | ||
| 748 | status = -EINVAL; | ||
| 749 | goto done; | ||
| 750 | } | ||
| 751 | if (p3xslave->super.super.super.api_domain == | ||
| 752 | CTRL_CLK_DOMAIN_XBARCLK) { | ||
| 753 | setfllclk.xbar2clkmhz = clkmhz; | ||
| 754 | } | ||
| 755 | if (p3xslave->super.super.super.api_domain == | ||
| 756 | CTRL_CLK_DOMAIN_SYSCLK) { | ||
| 757 | setfllclk.sys2clkmhz = clkmhz; | ||
| 758 | } | ||
| 759 | } | ||
| 760 | } | ||
| 761 | } | ||
| 762 | /*set regime ids */ | ||
| 763 | status = get_regime_id(g, CTRL_CLK_DOMAIN_GPCCLK, | ||
| 764 | &setfllclk.current_regime_id_gpc); | ||
| 765 | if (status) { | ||
| 766 | goto done; | ||
| 767 | } | ||
| 768 | |||
| 769 | setfllclk.target_regime_id_gpc = find_regime_id(g, | ||
| 770 | CTRL_CLK_DOMAIN_GPCCLK, setfllclk.gpc2clkmhz); | ||
| 771 | |||
| 772 | status = get_regime_id(g, CTRL_CLK_DOMAIN_SYSCLK, | ||
| 773 | &setfllclk.current_regime_id_sys); | ||
| 774 | if (status) { | ||
| 775 | goto done; | ||
| 776 | } | ||
| 777 | |||
| 778 | setfllclk.target_regime_id_sys = find_regime_id(g, | ||
| 779 | CTRL_CLK_DOMAIN_SYSCLK, setfllclk.sys2clkmhz); | ||
| 780 | |||
| 781 | status = get_regime_id(g, CTRL_CLK_DOMAIN_XBARCLK, | ||
| 782 | &setfllclk.current_regime_id_xbar); | ||
| 783 | if (status) { | ||
| 784 | goto done; | ||
| 785 | } | ||
| 786 | |||
| 787 | setfllclk.target_regime_id_xbar = find_regime_id(g, | ||
| 788 | CTRL_CLK_DOMAIN_XBARCLK, setfllclk.xbar2clkmhz); | ||
| 789 | |||
| 790 | status = clk_pmu_vf_inject(g, &setfllclk); | ||
| 791 | |||
| 792 | if (status) { | ||
| 793 | nvgpu_err(g, | ||
| 794 | "vf inject to change clk failed"); | ||
| 795 | } | ||
| 796 | |||
| 797 | /* save regime ids */ | ||
| 798 | status = set_regime_id(g, CTRL_CLK_DOMAIN_XBARCLK, | ||
| 799 | setfllclk.target_regime_id_xbar); | ||
| 800 | if (status) { | ||
| 801 | goto done; | ||
| 802 | } | ||
| 803 | |||
| 804 | status = set_regime_id(g, CTRL_CLK_DOMAIN_GPCCLK, | ||
| 805 | setfllclk.target_regime_id_gpc); | ||
| 806 | if (status) { | ||
| 807 | goto done; | ||
| 808 | } | ||
| 809 | |||
| 810 | status = set_regime_id(g, CTRL_CLK_DOMAIN_SYSCLK, | ||
| 811 | setfllclk.target_regime_id_sys); | ||
| 812 | if (status) { | ||
| 813 | goto done; | ||
| 814 | } | ||
| 815 | done: | ||
| 816 | return status; | ||
| 817 | } | ||
| 818 | |||
| 819 | u32 nvgpu_clk_set_boot_fll_clk_gv10x(struct gk20a *g) | ||
| 820 | { | ||
| 821 | int status; | ||
| 822 | struct change_fll_clk bootfllclk; | ||
| 823 | u16 gpcclk_clkmhz = BOOT_GPCCLK_MHZ; | ||
| 824 | u32 gpcclk_voltuv = 0; | ||
| 825 | u32 voltuv = 0; | ||
| 826 | |||
| 827 | status = clk_vf_point_cache(g); | ||
| 828 | if (status) { | ||
| 829 | nvgpu_err(g,"caching failed"); | ||
| 830 | return status; | ||
| 831 | } | ||
| 832 | |||
| 833 | status = clk_domain_get_f_or_v(g, CTRL_CLK_DOMAIN_GPCCLK, | ||
| 834 | &gpcclk_clkmhz, &gpcclk_voltuv, CTRL_VOLT_DOMAIN_LOGIC); | ||
| 835 | if (status) { | ||
| 836 | return status; | ||
| 837 | } | ||
| 838 | |||
| 839 | voltuv = gpcclk_voltuv; | ||
| 840 | |||
| 841 | status = volt_set_voltage(g, voltuv, 0); | ||
| 842 | if (status) { | ||
| 843 | nvgpu_err(g, | ||
| 844 | "attempt to set boot voltage failed %d", | ||
| 845 | voltuv); | ||
| 846 | } | ||
| 847 | |||
| 848 | bootfllclk.api_clk_domain = CTRL_CLK_DOMAIN_GPCCLK; | ||
| 849 | bootfllclk.clkmhz = gpcclk_clkmhz; | ||
| 850 | bootfllclk.voltuv = voltuv; | ||
| 851 | status = clk_program_fllclks(g, &bootfllclk); | ||
| 852 | if (status) { | ||
| 853 | nvgpu_err(g, "attempt to set boot gpcclk failed"); | ||
| 854 | } | ||
| 855 | |||
| 856 | status = clk_pmu_freq_effective_avg_load(g, true); | ||
| 857 | |||
| 858 | /* | ||
| 859 | * Read clocks after some delay with below method | ||
| 860 | * & extract clock data from buffer | ||
| 861 | * clk_freq_effective_avg(g, CTRL_CLK_DOMAIN_GPCCLK | | ||
| 862 | * CTRL_CLK_DOMAIN_XBARCLK | | ||
| 863 | * CTRL_CLK_DOMAIN_SYSCLK | | ||
| 864 | * CTRL_CLK_DOMAIN_NVDCLK) | ||
| 865 | * */ | ||
| 866 | |||
| 867 | return status; | ||
| 868 | } | ||
| 869 | |||
| 870 | int nvgpu_clk_set_fll_clk_gv10x(struct gk20a *g) | ||
| 871 | { | ||
| 872 | int status; | ||
| 873 | struct change_fll_clk bootfllclk; | ||
| 874 | u16 gpcclk_clkmhz = BOOT_GPCCLK_MHZ; | ||
| 875 | u32 gpcclk_voltuv = 0U; | ||
| 876 | u32 voltuv = 0U; | ||
| 877 | |||
| 878 | status = clk_vf_point_cache(g); | ||
| 879 | if (status != 0) { | ||
| 880 | nvgpu_err(g, "caching failed"); | ||
| 881 | return status; | ||
| 882 | } | ||
| 883 | |||
| 884 | status = clk_domain_get_f_or_v(g, CTRL_CLK_DOMAIN_GPCCLK, | ||
| 885 | &gpcclk_clkmhz, &gpcclk_voltuv, CTRL_VOLT_DOMAIN_LOGIC); | ||
| 886 | if (status != 0) { | ||
| 887 | return status; | ||
| 888 | } | ||
| 889 | |||
| 890 | voltuv = gpcclk_voltuv; | ||
| 891 | |||
| 892 | status = volt_set_voltage(g, voltuv, 0U); | ||
| 893 | if (status != 0) { | ||
| 894 | nvgpu_err(g, "attempt to set max voltage failed %d", voltuv); | ||
| 895 | } | ||
| 896 | |||
| 897 | bootfllclk.api_clk_domain = CTRL_CLK_DOMAIN_GPCCLK; | ||
| 898 | bootfllclk.clkmhz = gpcclk_clkmhz; | ||
| 899 | bootfllclk.voltuv = voltuv; | ||
| 900 | status = clk_program_fllclks(g, &bootfllclk); | ||
| 901 | if (status != 0) { | ||
| 902 | nvgpu_err(g, "attempt to set max gpcclk failed"); | ||
| 903 | } | ||
| 904 | return status; | ||
| 905 | } | ||
| 906 | |||
| 907 | u32 clk_domain_get_f_or_v( | ||
| 908 | struct gk20a *g, | ||
| 909 | u32 clkapidomain, | ||
| 910 | u16 *pclkmhz, | ||
| 911 | u32 *pvoltuv, | ||
| 912 | u8 railidx | ||
| 913 | ) | ||
| 914 | { | ||
| 915 | u32 status = -EINVAL; | ||
| 916 | struct clk_domain *pdomain; | ||
| 917 | u8 i; | ||
| 918 | struct clk_pmupstate *pclk = &g->clk_pmu; | ||
| 919 | u8 rail; | ||
| 920 | |||
| 921 | if ((pclkmhz == NULL) || (pvoltuv == NULL)) { | ||
| 922 | return -EINVAL; | ||
| 923 | } | ||
| 924 | |||
| 925 | if (railidx == CTRL_VOLT_DOMAIN_LOGIC) { | ||
| 926 | rail = CLK_PROG_VFE_ENTRY_LOGIC; | ||
| 927 | } else if (railidx == CTRL_VOLT_DOMAIN_SRAM) { | ||
| 928 | rail = CLK_PROG_VFE_ENTRY_SRAM; | ||
| 929 | } else { | ||
| 930 | return -EINVAL; | ||
| 931 | } | ||
| 932 | |||
| 933 | BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super), | ||
| 934 | struct clk_domain *, pdomain, i) { | ||
| 935 | if (pdomain->api_domain == clkapidomain) { | ||
| 936 | status = pdomain->clkdomainclkvfsearch(g, pclk, | ||
| 937 | pdomain, pclkmhz, pvoltuv, rail); | ||
| 938 | return status; | ||
| 939 | } | ||
| 940 | } | ||
| 941 | return status; | ||
| 942 | } | ||
diff --git a/include/clk/clk.h b/include/clk/clk.h deleted file mode 100644 index 3f4bdf7..0000000 --- a/include/clk/clk.h +++ /dev/null | |||
| @@ -1,144 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * general clock structures & definitions | ||
| 3 | * | ||
| 4 | * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 22 | * DEALINGS IN THE SOFTWARE. | ||
| 23 | */ | ||
| 24 | #ifndef NVGPU_CLK_H | ||
| 25 | #define NVGPU_CLK_H | ||
| 26 | |||
| 27 | #include "clk_vin.h" | ||
| 28 | #include "clk_fll.h" | ||
| 29 | #include "clk_domain.h" | ||
| 30 | #include "clk_prog.h" | ||
| 31 | #include "clk_vf_point.h" | ||
| 32 | #include "clk_mclk.h" | ||
| 33 | #include "clk_freq_controller.h" | ||
| 34 | |||
| 35 | #define NV_PERF_DOMAIN_4X_CLOCK_DOMAIN_SKIP 0x10 | ||
| 36 | #define NV_PERF_DOMAIN_4X_CLOCK_DOMAIN_MASK 0x1F | ||
| 37 | #define NV_PERF_DOMAIN_4X_CLOCK_DOMAIN_SHIFT 0 | ||
| 38 | #define BOOT_GPCCLK_MHZ 952 | ||
| 39 | |||
| 40 | struct gk20a; | ||
| 41 | |||
| 42 | int clk_set_boot_fll_clk(struct gk20a *g); | ||
| 43 | |||
| 44 | /* clock related defines for GPUs supporting clock control from pmu*/ | ||
| 45 | struct clk_pmupstate { | ||
| 46 | struct avfsvinobjs avfs_vinobjs; | ||
| 47 | struct avfsfllobjs avfs_fllobjs; | ||
| 48 | struct clk_domains clk_domainobjs; | ||
| 49 | struct clk_progs clk_progobjs; | ||
| 50 | struct clk_vf_points clk_vf_pointobjs; | ||
| 51 | struct clk_mclk_state clk_mclk; | ||
| 52 | struct clk_freq_controllers clk_freq_controllers; | ||
| 53 | }; | ||
| 54 | |||
| 55 | struct clockentry { | ||
| 56 | u8 vbios_clk_domain; | ||
| 57 | u8 clk_which; | ||
| 58 | u8 perf_index; | ||
| 59 | u32 api_clk_domain; | ||
| 60 | }; | ||
| 61 | |||
| 62 | struct change_fll_clk { | ||
| 63 | u32 api_clk_domain; | ||
| 64 | u16 clkmhz; | ||
| 65 | u32 voltuv; | ||
| 66 | }; | ||
| 67 | |||
| 68 | struct set_fll_clk { | ||
| 69 | u32 voltuv; | ||
| 70 | u16 gpc2clkmhz; | ||
| 71 | u32 current_regime_id_gpc; | ||
| 72 | u32 target_regime_id_gpc; | ||
| 73 | u16 sys2clkmhz; | ||
| 74 | u32 current_regime_id_sys; | ||
| 75 | u32 target_regime_id_sys; | ||
| 76 | u16 xbar2clkmhz; | ||
| 77 | u32 current_regime_id_xbar; | ||
| 78 | u32 target_regime_id_xbar; | ||
| 79 | }; | ||
| 80 | |||
| 81 | #define NV_PERF_HEADER_4X_CLOCKS_DOMAINS_MAX_NUMCLKS 9 | ||
| 82 | |||
| 83 | struct vbios_clock_domain { | ||
| 84 | u8 clock_type; | ||
| 85 | u8 num_domains; | ||
| 86 | struct clockentry clock_entry[NV_PERF_HEADER_4X_CLOCKS_DOMAINS_MAX_NUMCLKS]; | ||
| 87 | }; | ||
| 88 | |||
| 89 | struct vbios_clocks_table_1x_hal_clock_entry { | ||
| 90 | enum nv_pmu_clk_clkwhich domain; | ||
| 91 | bool b_noise_aware_capable; | ||
| 92 | u8 clk_vf_curve_count; | ||
| 93 | }; | ||
| 94 | |||
| 95 | #define NV_PERF_HEADER_4X_CLOCKS_DOMAINS_4_GPC2CLK 0 | ||
| 96 | #define NV_PERF_HEADER_4X_CLOCKS_DOMAINS_4_XBAR2CLK 1 | ||
| 97 | #define NV_PERF_HEADER_4X_CLOCKS_DOMAINS_4_DRAMCLK 2 | ||
| 98 | #define NV_PERF_HEADER_4X_CLOCKS_DOMAINS_4_SYS2CLK 3 | ||
| 99 | #define NV_PERF_HEADER_4X_CLOCKS_DOMAINS_4_HUB2CLK 4 | ||
| 100 | #define NV_PERF_HEADER_4X_CLOCKS_DOMAINS_4_MSDCLK 5 | ||
| 101 | #define NV_PERF_HEADER_4X_CLOCKS_DOMAINS_4_PWRCLK 6 | ||
| 102 | #define NV_PERF_HEADER_4X_CLOCKS_DOMAINS_4_DISPCLK 7 | ||
| 103 | #define NV_PERF_HEADER_4X_CLOCKS_DOMAINS_4_NUMCLKS 8 | ||
| 104 | |||
| 105 | #define PERF_CLK_MCLK 0 | ||
| 106 | #define PERF_CLK_DISPCLK 1 | ||
| 107 | #define PERF_CLK_GPC2CLK 2 | ||
| 108 | #define PERF_CLK_HOSTCLK 3 | ||
| 109 | #define PERF_CLK_LTC2CLK 4 | ||
| 110 | #define PERF_CLK_SYS2CLK 5 | ||
| 111 | #define PERF_CLK_HUB2CLK 6 | ||
| 112 | #define PERF_CLK_LEGCLK 7 | ||
| 113 | #define PERF_CLK_MSDCLK 8 | ||
| 114 | #define PERF_CLK_XCLK 9 | ||
| 115 | #define PERF_CLK_PWRCLK 10 | ||
| 116 | #define PERF_CLK_XBAR2CLK 11 | ||
| 117 | #define PERF_CLK_PCIEGENCLK 12 | ||
| 118 | #define PERF_CLK_NUM 13 | ||
| 119 | |||
| 120 | #define BOOT_GPC2CLK_MHZ 2581 | ||
| 121 | |||
| 122 | u32 clk_pmu_vin_load(struct gk20a *g); | ||
| 123 | u32 clk_domain_print_vf_table(struct gk20a *g, u32 clkapidomain); | ||
| 124 | u32 clk_domain_get_f_or_v( | ||
| 125 | struct gk20a *g, | ||
| 126 | u32 clkapidomain, | ||
| 127 | u16 *pclkmhz, | ||
| 128 | u32 *pvoltuv, | ||
| 129 | u8 railidx | ||
| 130 | ); | ||
| 131 | int clk_get_fll_clks(struct gk20a *g, struct set_fll_clk *fllclk); | ||
| 132 | int clk_set_fll_clks(struct gk20a *g, struct set_fll_clk *fllclk); | ||
| 133 | int clk_pmu_freq_controller_load(struct gk20a *g, bool bload, u8 bit_idx); | ||
| 134 | u32 nvgpu_clk_vf_change_inject_data_fill_gv10x(struct gk20a *g, | ||
| 135 | struct nv_pmu_clk_rpc *rpccall, | ||
| 136 | struct set_fll_clk *setfllclk); | ||
| 137 | u32 nvgpu_clk_vf_change_inject_data_fill_gp10x(struct gk20a *g, | ||
| 138 | struct nv_pmu_clk_rpc *rpccall, | ||
| 139 | struct set_fll_clk *setfllclk); | ||
| 140 | u32 nvgpu_clk_set_boot_fll_clk_gv10x(struct gk20a *g); | ||
| 141 | int nvgpu_clk_set_fll_clk_gv10x(struct gk20a *g); | ||
| 142 | int clk_pmu_freq_effective_avg_load(struct gk20a *g, bool bload); | ||
| 143 | u32 clk_freq_effective_avg(struct gk20a *g, u32 clkDomainMask); | ||
| 144 | #endif /* NVGPU_CLK_H */ | ||
diff --git a/include/clk/clk_arb.c b/include/clk/clk_arb.c deleted file mode 100644 index 8e9fb41..0000000 --- a/include/clk/clk_arb.c +++ /dev/null | |||
| @@ -1,1087 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2016-2021, 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/bitops.h> | ||
| 24 | #include <nvgpu/lock.h> | ||
| 25 | #include <nvgpu/kmem.h> | ||
| 26 | #include <nvgpu/atomic.h> | ||
| 27 | #include <nvgpu/bug.h> | ||
| 28 | #include <nvgpu/kref.h> | ||
| 29 | #include <nvgpu/log.h> | ||
| 30 | #include <nvgpu/barrier.h> | ||
| 31 | #include <nvgpu/cond.h> | ||
| 32 | #include <nvgpu/list.h> | ||
| 33 | #include <nvgpu/clk_arb.h> | ||
| 34 | #include <nvgpu/timers.h> | ||
| 35 | #include <nvgpu/gk20a.h> | ||
| 36 | |||
| 37 | #include "clk/clk.h" | ||
| 38 | #include "pstate/pstate.h" | ||
| 39 | #include "lpwr/lpwr.h" | ||
| 40 | #include "volt/volt.h" | ||
| 41 | |||
| 42 | int nvgpu_clk_notification_queue_alloc(struct gk20a *g, | ||
| 43 | struct nvgpu_clk_notification_queue *queue, | ||
| 44 | size_t events_number) { | ||
| 45 | queue->notifications = nvgpu_kcalloc(g, events_number, | ||
| 46 | sizeof(struct nvgpu_clk_notification)); | ||
| 47 | if (!queue->notifications) | ||
| 48 | return -ENOMEM; | ||
| 49 | queue->size = events_number; | ||
| 50 | |||
| 51 | nvgpu_atomic_set(&queue->head, 0); | ||
| 52 | nvgpu_atomic_set(&queue->tail, 0); | ||
| 53 | |||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | |||
| 57 | void nvgpu_clk_notification_queue_free(struct gk20a *g, | ||
| 58 | struct nvgpu_clk_notification_queue *queue) { | ||
| 59 | if (queue->size > 0) { | ||
| 60 | nvgpu_kfree(g, queue->notifications); | ||
| 61 | queue->size = 0; | ||
| 62 | nvgpu_atomic_set(&queue->head, 0); | ||
| 63 | nvgpu_atomic_set(&queue->tail, 0); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | static void nvgpu_clk_arb_queue_notification(struct gk20a *g, | ||
| 68 | struct nvgpu_clk_notification_queue *queue, | ||
| 69 | u32 alarm_mask) { | ||
| 70 | |||
| 71 | u32 queue_index; | ||
| 72 | u64 timestamp; | ||
| 73 | |||
| 74 | queue_index = (nvgpu_atomic_inc_return(&queue->tail)) % queue->size; | ||
| 75 | /* get current timestamp */ | ||
| 76 | timestamp = (u64) nvgpu_hr_timestamp(); | ||
| 77 | |||
| 78 | queue->notifications[queue_index].timestamp = timestamp; | ||
| 79 | queue->notifications[queue_index].notification = alarm_mask; | ||
| 80 | |||
| 81 | } | ||
| 82 | |||
| 83 | void nvgpu_clk_arb_set_global_alarm(struct gk20a *g, u32 alarm) | ||
| 84 | { | ||
| 85 | struct nvgpu_clk_arb *arb = g->clk_arb; | ||
| 86 | |||
| 87 | u64 current_mask; | ||
| 88 | u32 refcnt; | ||
| 89 | u32 alarm_mask; | ||
| 90 | u64 new_mask; | ||
| 91 | |||
| 92 | do { | ||
| 93 | current_mask = nvgpu_atomic64_read(&arb->alarm_mask); | ||
| 94 | /* atomic operations are strong so they do not need masks */ | ||
| 95 | |||
| 96 | refcnt = ((u32) (current_mask >> 32)) + 1; | ||
| 97 | alarm_mask = (u32) (current_mask & ~0) | alarm; | ||
| 98 | new_mask = ((u64) refcnt << 32) | alarm_mask; | ||
| 99 | |||
| 100 | } while (unlikely(current_mask != | ||
| 101 | (u64)nvgpu_atomic64_cmpxchg(&arb->alarm_mask, | ||
| 102 | current_mask, new_mask))); | ||
| 103 | |||
| 104 | nvgpu_clk_arb_queue_notification(g, &arb->notification_queue, alarm); | ||
| 105 | } | ||
| 106 | |||
| 107 | |||
| 108 | int nvgpu_clk_arb_update_vf_table(struct nvgpu_clk_arb *arb) | ||
| 109 | { | ||
| 110 | struct gk20a *g = arb->g; | ||
| 111 | struct nvgpu_clk_vf_table *table; | ||
| 112 | |||
| 113 | u32 i, j; | ||
| 114 | int status = -EINVAL; | ||
| 115 | u32 gpc2clk_voltuv = 0, mclk_voltuv = 0; | ||
| 116 | u32 gpc2clk_voltuv_sram = 0, mclk_voltuv_sram = 0; | ||
| 117 | u16 clk_cur; | ||
| 118 | u32 num_points; | ||
| 119 | |||
| 120 | struct clk_set_info *p5_info, *p0_info; | ||
| 121 | |||
| 122 | table = NV_ACCESS_ONCE(arb->current_vf_table); | ||
| 123 | /* make flag visible when all data has resolved in the tables */ | ||
| 124 | nvgpu_smp_rmb(); | ||
| 125 | |||
| 126 | table = (table == &arb->vf_table_pool[0]) ? &arb->vf_table_pool[1] : | ||
| 127 | &arb->vf_table_pool[0]; | ||
| 128 | |||
| 129 | /* Get allowed memory ranges */ | ||
| 130 | if (g->ops.clk_arb.get_arbiter_clk_range(g, CTRL_CLK_DOMAIN_GPC2CLK, | ||
| 131 | &arb->gpc2clk_min, | ||
| 132 | &arb->gpc2clk_max) < 0) { | ||
| 133 | nvgpu_err(g, "failed to fetch GPC2CLK range"); | ||
| 134 | goto exit_vf_table; | ||
| 135 | } | ||
| 136 | if (g->ops.clk_arb.get_arbiter_clk_range(g, CTRL_CLK_DOMAIN_MCLK, | ||
| 137 | &arb->mclk_min, | ||
| 138 | &arb->mclk_max) < 0) { | ||
| 139 | nvgpu_err(g, "failed to fetch MCLK range"); | ||
| 140 | goto exit_vf_table; | ||
| 141 | } | ||
| 142 | |||
| 143 | table->gpc2clk_num_points = MAX_F_POINTS; | ||
| 144 | table->mclk_num_points = MAX_F_POINTS; | ||
| 145 | |||
| 146 | if (g->ops.clk.clk_domain_get_f_points(arb->g, CTRL_CLK_DOMAIN_GPC2CLK, | ||
| 147 | &table->gpc2clk_num_points, arb->gpc2clk_f_points)) { | ||
| 148 | nvgpu_err(g, "failed to fetch GPC2CLK frequency points"); | ||
| 149 | goto exit_vf_table; | ||
| 150 | } | ||
| 151 | |||
| 152 | if (g->ops.clk.clk_domain_get_f_points(arb->g, CTRL_CLK_DOMAIN_MCLK, | ||
| 153 | &table->mclk_num_points, arb->mclk_f_points)) { | ||
| 154 | nvgpu_err(g, "failed to fetch MCLK frequency points"); | ||
| 155 | goto exit_vf_table; | ||
| 156 | } | ||
| 157 | if (!table->mclk_num_points || !table->gpc2clk_num_points) { | ||
| 158 | nvgpu_err(g, "empty queries to f points mclk %d gpc2clk %d", | ||
| 159 | table->mclk_num_points, table->gpc2clk_num_points); | ||
| 160 | status = -EINVAL; | ||
| 161 | goto exit_vf_table; | ||
| 162 | } | ||
| 163 | |||
| 164 | memset(table->mclk_points, 0, | ||
| 165 | table->mclk_num_points*sizeof(struct nvgpu_clk_vf_point)); | ||
| 166 | memset(table->gpc2clk_points, 0, | ||
| 167 | table->gpc2clk_num_points*sizeof(struct nvgpu_clk_vf_point)); | ||
| 168 | |||
| 169 | p5_info = pstate_get_clk_set_info(g, | ||
| 170 | CTRL_PERF_PSTATE_P5, clkwhich_mclk); | ||
| 171 | if (!p5_info) { | ||
| 172 | nvgpu_err(g, "failed to get MCLK P5 info"); | ||
| 173 | goto exit_vf_table; | ||
| 174 | } | ||
| 175 | p0_info = pstate_get_clk_set_info(g, | ||
| 176 | CTRL_PERF_PSTATE_P0, clkwhich_mclk); | ||
| 177 | if (!p0_info) { | ||
| 178 | nvgpu_err(g, "failed to get MCLK P0 info"); | ||
| 179 | goto exit_vf_table; | ||
| 180 | } | ||
| 181 | |||
| 182 | for (i = 0, j = 0, num_points = 0, clk_cur = 0; | ||
| 183 | i < table->mclk_num_points; i++) { | ||
| 184 | |||
| 185 | if ((arb->mclk_f_points[i] >= arb->mclk_min) && | ||
| 186 | (arb->mclk_f_points[i] <= arb->mclk_max) && | ||
| 187 | (arb->mclk_f_points[i] != clk_cur)) { | ||
| 188 | |||
| 189 | table->mclk_points[j].mem_mhz = arb->mclk_f_points[i]; | ||
| 190 | mclk_voltuv = mclk_voltuv_sram = 0; | ||
| 191 | |||
| 192 | status = clk_domain_get_f_or_v(g, CTRL_CLK_DOMAIN_MCLK, | ||
| 193 | &table->mclk_points[j].mem_mhz, &mclk_voltuv, | ||
| 194 | CTRL_VOLT_DOMAIN_LOGIC); | ||
| 195 | if (status < 0) { | ||
| 196 | nvgpu_err(g, | ||
| 197 | "failed to get MCLK LOGIC voltage"); | ||
| 198 | goto exit_vf_table; | ||
| 199 | } | ||
| 200 | status = clk_domain_get_f_or_v(g, CTRL_CLK_DOMAIN_MCLK, | ||
| 201 | &table->mclk_points[j].mem_mhz, | ||
| 202 | &mclk_voltuv_sram, | ||
| 203 | CTRL_VOLT_DOMAIN_SRAM); | ||
| 204 | if (status < 0) { | ||
| 205 | nvgpu_err(g, "failed to get MCLK SRAM voltage"); | ||
| 206 | goto exit_vf_table; | ||
| 207 | } | ||
| 208 | |||
| 209 | table->mclk_points[j].uvolt = mclk_voltuv; | ||
| 210 | table->mclk_points[j].uvolt_sram = mclk_voltuv_sram; | ||
| 211 | clk_cur = table->mclk_points[j].mem_mhz; | ||
| 212 | |||
| 213 | if ((clk_cur >= p5_info->min_mhz) && | ||
| 214 | (clk_cur <= p5_info->max_mhz)) | ||
| 215 | VF_POINT_SET_PSTATE_SUPPORTED( | ||
| 216 | &table->mclk_points[j], | ||
| 217 | CTRL_PERF_PSTATE_P5); | ||
| 218 | if ((clk_cur >= p0_info->min_mhz) && | ||
| 219 | (clk_cur <= p0_info->max_mhz)) | ||
| 220 | VF_POINT_SET_PSTATE_SUPPORTED( | ||
| 221 | &table->mclk_points[j], | ||
| 222 | CTRL_PERF_PSTATE_P0); | ||
| 223 | |||
| 224 | j++; | ||
| 225 | num_points++; | ||
| 226 | |||
| 227 | } | ||
| 228 | } | ||
| 229 | table->mclk_num_points = num_points; | ||
| 230 | |||
| 231 | p5_info = pstate_get_clk_set_info(g, | ||
| 232 | CTRL_PERF_PSTATE_P5, clkwhich_gpc2clk); | ||
| 233 | if (!p5_info) { | ||
| 234 | status = -EINVAL; | ||
| 235 | nvgpu_err(g, "failed to get GPC2CLK P5 info"); | ||
| 236 | goto exit_vf_table; | ||
| 237 | } | ||
| 238 | |||
| 239 | p0_info = pstate_get_clk_set_info(g, | ||
| 240 | CTRL_PERF_PSTATE_P0, clkwhich_gpc2clk); | ||
| 241 | if (!p0_info) { | ||
| 242 | status = -EINVAL; | ||
| 243 | nvgpu_err(g, "failed to get GPC2CLK P0 info"); | ||
| 244 | goto exit_vf_table; | ||
| 245 | } | ||
| 246 | |||
| 247 | /* GPC2CLK needs to be checked in two passes. The first determines the | ||
| 248 | * relationships between GPC2CLK, SYS2CLK and XBAR2CLK, while the | ||
| 249 | * second verifies that the clocks minimum is satisfied and sets | ||
| 250 | * the voltages | ||
| 251 | */ | ||
| 252 | for (i = 0, j = 0, num_points = 0, clk_cur = 0; | ||
| 253 | i < table->gpc2clk_num_points; i++) { | ||
| 254 | struct set_fll_clk setfllclk; | ||
| 255 | |||
| 256 | if ((arb->gpc2clk_f_points[i] >= arb->gpc2clk_min) && | ||
| 257 | (arb->gpc2clk_f_points[i] <= arb->gpc2clk_max) && | ||
| 258 | (arb->gpc2clk_f_points[i] != clk_cur)) { | ||
| 259 | |||
| 260 | table->gpc2clk_points[j].gpc_mhz = | ||
| 261 | arb->gpc2clk_f_points[i]; | ||
| 262 | setfllclk.gpc2clkmhz = arb->gpc2clk_f_points[i]; | ||
| 263 | status = clk_get_fll_clks(g, &setfllclk); | ||
| 264 | if (status < 0) { | ||
| 265 | nvgpu_err(g, | ||
| 266 | "failed to get GPC2CLK slave clocks"); | ||
| 267 | goto exit_vf_table; | ||
| 268 | } | ||
| 269 | |||
| 270 | table->gpc2clk_points[j].sys_mhz = | ||
| 271 | setfllclk.sys2clkmhz; | ||
| 272 | table->gpc2clk_points[j].xbar_mhz = | ||
| 273 | setfllclk.xbar2clkmhz; | ||
| 274 | |||
| 275 | clk_cur = table->gpc2clk_points[j].gpc_mhz; | ||
| 276 | |||
| 277 | if ((clk_cur >= p5_info->min_mhz) && | ||
| 278 | (clk_cur <= p5_info->max_mhz)) | ||
| 279 | VF_POINT_SET_PSTATE_SUPPORTED( | ||
| 280 | &table->gpc2clk_points[j], | ||
| 281 | CTRL_PERF_PSTATE_P5); | ||
| 282 | if ((clk_cur >= p0_info->min_mhz) && | ||
| 283 | (clk_cur <= p0_info->max_mhz)) | ||
| 284 | VF_POINT_SET_PSTATE_SUPPORTED( | ||
| 285 | &table->gpc2clk_points[j], | ||
| 286 | CTRL_PERF_PSTATE_P0); | ||
| 287 | |||
| 288 | j++; | ||
| 289 | num_points++; | ||
| 290 | } | ||
| 291 | } | ||
| 292 | table->gpc2clk_num_points = num_points; | ||
| 293 | |||
| 294 | /* Second pass */ | ||
| 295 | for (i = 0, j = 0; i < table->gpc2clk_num_points; i++) { | ||
| 296 | |||
| 297 | u16 alt_gpc2clk = table->gpc2clk_points[i].gpc_mhz; | ||
| 298 | |||
| 299 | gpc2clk_voltuv = gpc2clk_voltuv_sram = 0; | ||
| 300 | |||
| 301 | /* Check sysclk */ | ||
| 302 | p5_info = pstate_get_clk_set_info(g, | ||
| 303 | VF_POINT_GET_PSTATE(&table->gpc2clk_points[i]), | ||
| 304 | clkwhich_sys2clk); | ||
| 305 | if (!p5_info) { | ||
| 306 | status = -EINVAL; | ||
| 307 | nvgpu_err(g, "failed to get SYS2CLK P5 info"); | ||
| 308 | goto exit_vf_table; | ||
| 309 | } | ||
| 310 | |||
| 311 | /* sys2clk below clk min, need to find correct clock */ | ||
| 312 | if (table->gpc2clk_points[i].sys_mhz < p5_info->min_mhz) { | ||
| 313 | for (j = i + 1; j < table->gpc2clk_num_points; j++) { | ||
| 314 | |||
| 315 | if (table->gpc2clk_points[j].sys_mhz >= | ||
| 316 | p5_info->min_mhz) { | ||
| 317 | |||
| 318 | |||
| 319 | table->gpc2clk_points[i].sys_mhz = | ||
| 320 | p5_info->min_mhz; | ||
| 321 | |||
| 322 | alt_gpc2clk = alt_gpc2clk < | ||
| 323 | table->gpc2clk_points[j]. | ||
| 324 | gpc_mhz ? | ||
| 325 | table->gpc2clk_points[j]. | ||
| 326 | gpc_mhz : | ||
| 327 | alt_gpc2clk; | ||
| 328 | break; | ||
| 329 | } | ||
| 330 | } | ||
| 331 | /* no VF exists that satisfies condition */ | ||
| 332 | if (j == table->gpc2clk_num_points) { | ||
| 333 | nvgpu_err(g, "NO SYS2CLK VF point possible"); | ||
| 334 | status = -EINVAL; | ||
| 335 | goto exit_vf_table; | ||
| 336 | } | ||
| 337 | } | ||
| 338 | |||
| 339 | /* Check xbarclk */ | ||
| 340 | p5_info = pstate_get_clk_set_info(g, | ||
| 341 | VF_POINT_GET_PSTATE(&table->gpc2clk_points[i]), | ||
| 342 | clkwhich_xbar2clk); | ||
| 343 | if (!p5_info) { | ||
| 344 | status = -EINVAL; | ||
| 345 | nvgpu_err(g, "failed to get SYS2CLK P5 info"); | ||
| 346 | goto exit_vf_table; | ||
| 347 | } | ||
| 348 | |||
| 349 | /* xbar2clk below clk min, need to find correct clock */ | ||
| 350 | if (table->gpc2clk_points[i].xbar_mhz < p5_info->min_mhz) { | ||
| 351 | for (j = i; j < table->gpc2clk_num_points; j++) { | ||
| 352 | if (table->gpc2clk_points[j].xbar_mhz >= | ||
| 353 | p5_info->min_mhz) { | ||
| 354 | |||
| 355 | table->gpc2clk_points[i].xbar_mhz = | ||
| 356 | p5_info->min_mhz; | ||
| 357 | |||
| 358 | alt_gpc2clk = alt_gpc2clk < | ||
| 359 | table->gpc2clk_points[j]. | ||
| 360 | gpc_mhz ? | ||
| 361 | table->gpc2clk_points[j]. | ||
| 362 | gpc_mhz : | ||
| 363 | alt_gpc2clk; | ||
| 364 | break; | ||
| 365 | } | ||
| 366 | } | ||
| 367 | /* no VF exists that satisfies condition */ | ||
| 368 | if (j == table->gpc2clk_num_points) { | ||
| 369 | status = -EINVAL; | ||
| 370 | nvgpu_err(g, "NO XBAR2CLK VF point possible"); | ||
| 371 | |||
| 372 | goto exit_vf_table; | ||
| 373 | } | ||
| 374 | } | ||
| 375 | |||
| 376 | /* Calculate voltages */ | ||
| 377 | status = clk_domain_get_f_or_v(g, CTRL_CLK_DOMAIN_GPC2CLK, | ||
| 378 | &alt_gpc2clk, &gpc2clk_voltuv, | ||
| 379 | CTRL_VOLT_DOMAIN_LOGIC); | ||
| 380 | if (status < 0) { | ||
| 381 | nvgpu_err(g, "failed to get GPC2CLK LOGIC voltage"); | ||
| 382 | goto exit_vf_table; | ||
| 383 | } | ||
| 384 | |||
| 385 | status = clk_domain_get_f_or_v(g, CTRL_CLK_DOMAIN_GPC2CLK, | ||
| 386 | &alt_gpc2clk, | ||
| 387 | &gpc2clk_voltuv_sram, | ||
| 388 | CTRL_VOLT_DOMAIN_SRAM); | ||
| 389 | if (status < 0) { | ||
| 390 | nvgpu_err(g, "failed to get GPC2CLK SRAM voltage"); | ||
| 391 | goto exit_vf_table; | ||
| 392 | } | ||
| 393 | |||
| 394 | table->gpc2clk_points[i].uvolt = gpc2clk_voltuv; | ||
| 395 | table->gpc2clk_points[i].uvolt_sram = gpc2clk_voltuv_sram; | ||
| 396 | } | ||
| 397 | |||
| 398 | /* make table visible when all data has resolved in the tables */ | ||
| 399 | nvgpu_smp_wmb(); | ||
| 400 | arb->current_vf_table = table; | ||
| 401 | |||
| 402 | exit_vf_table: | ||
| 403 | |||
| 404 | if (status < 0) | ||
| 405 | nvgpu_clk_arb_set_global_alarm(g, | ||
| 406 | EVENT(ALARM_VF_TABLE_UPDATE_FAILED)); | ||
| 407 | nvgpu_clk_arb_worker_enqueue(g, &arb->update_arb_work_item); | ||
| 408 | |||
| 409 | return status; | ||
| 410 | } | ||
| 411 | |||
| 412 | |||
| 413 | static void nvgpu_clk_arb_run_vf_table_cb(struct nvgpu_clk_arb *arb) | ||
| 414 | { | ||
| 415 | struct gk20a *g = arb->g; | ||
| 416 | u32 err; | ||
| 417 | |||
| 418 | /* get latest vf curve from pmu */ | ||
| 419 | err = clk_vf_point_cache(g); | ||
| 420 | if (err) { | ||
| 421 | nvgpu_err(g, "failed to cache VF table"); | ||
| 422 | nvgpu_clk_arb_set_global_alarm(g, | ||
| 423 | EVENT(ALARM_VF_TABLE_UPDATE_FAILED)); | ||
| 424 | nvgpu_clk_arb_worker_enqueue(g, &arb->update_arb_work_item); | ||
| 425 | |||
| 426 | return; | ||
| 427 | } | ||
| 428 | nvgpu_clk_arb_update_vf_table(arb); | ||
| 429 | } | ||
| 430 | |||
| 431 | u32 nvgpu_clk_arb_notify(struct nvgpu_clk_dev *dev, | ||
| 432 | struct nvgpu_clk_arb_target *target, | ||
| 433 | u32 alarm) { | ||
| 434 | |||
| 435 | struct nvgpu_clk_session *session = dev->session; | ||
| 436 | struct nvgpu_clk_arb *arb = session->g->clk_arb; | ||
| 437 | struct nvgpu_clk_notification *notification; | ||
| 438 | |||
| 439 | u32 queue_alarm_mask = 0; | ||
| 440 | u32 enabled_mask = 0; | ||
| 441 | u32 new_alarms_reported = 0; | ||
| 442 | u32 poll_mask = 0; | ||
| 443 | u32 tail, head; | ||
| 444 | u32 queue_index; | ||
| 445 | size_t size; | ||
| 446 | int index; | ||
| 447 | |||
| 448 | enabled_mask = nvgpu_atomic_read(&dev->enabled_mask); | ||
| 449 | size = arb->notification_queue.size; | ||
| 450 | |||
| 451 | /* queue global arbiter notifications in buffer */ | ||
| 452 | do { | ||
| 453 | tail = nvgpu_atomic_read(&arb->notification_queue.tail); | ||
| 454 | /* copy items to the queue */ | ||
| 455 | queue_index = nvgpu_atomic_read(&dev->queue.tail); | ||
| 456 | head = dev->arb_queue_head; | ||
| 457 | head = (tail - head) < arb->notification_queue.size ? | ||
| 458 | head : tail - arb->notification_queue.size; | ||
| 459 | |||
| 460 | for (index = head; _WRAPGTEQ(tail, index); index++) { | ||
| 461 | u32 alarm_detected; | ||
| 462 | |||
| 463 | notification = &arb->notification_queue. | ||
| 464 | notifications[(index+1) % size]; | ||
| 465 | alarm_detected = | ||
| 466 | NV_ACCESS_ONCE(notification->notification); | ||
| 467 | |||
| 468 | if (!(enabled_mask & alarm_detected)) | ||
| 469 | continue; | ||
| 470 | |||
| 471 | queue_index++; | ||
| 472 | dev->queue.notifications[ | ||
| 473 | queue_index % dev->queue.size].timestamp = | ||
| 474 | NV_ACCESS_ONCE(notification->timestamp); | ||
| 475 | |||
| 476 | dev->queue.notifications[ | ||
| 477 | queue_index % dev->queue.size].notification = | ||
| 478 | alarm_detected; | ||
| 479 | |||
| 480 | queue_alarm_mask |= alarm_detected; | ||
| 481 | } | ||
| 482 | } while (unlikely(nvgpu_atomic_read(&arb->notification_queue.tail) != | ||
| 483 | (int)tail)); | ||
| 484 | |||
| 485 | nvgpu_atomic_set(&dev->queue.tail, queue_index); | ||
| 486 | /* update the last notification we processed from global queue */ | ||
| 487 | |||
| 488 | dev->arb_queue_head = tail; | ||
| 489 | |||
| 490 | /* Check if current session targets are met */ | ||
| 491 | if (enabled_mask & EVENT(ALARM_LOCAL_TARGET_VF_NOT_POSSIBLE)) { | ||
| 492 | if ((target->gpc2clk < session->target->gpc2clk) | ||
| 493 | || (target->mclk < session->target->mclk)) { | ||
| 494 | |||
| 495 | poll_mask |= (NVGPU_POLLIN | NVGPU_POLLPRI); | ||
| 496 | nvgpu_clk_arb_queue_notification(arb->g, &dev->queue, | ||
| 497 | EVENT(ALARM_LOCAL_TARGET_VF_NOT_POSSIBLE)); | ||
| 498 | } | ||
| 499 | } | ||
| 500 | |||
| 501 | /* Check if there is a new VF update */ | ||
| 502 | if (queue_alarm_mask & EVENT(VF_UPDATE)) | ||
| 503 | poll_mask |= (NVGPU_POLLIN | NVGPU_POLLRDNORM); | ||
| 504 | |||
| 505 | /* Notify sticky alarms that were not reported on previous run*/ | ||
| 506 | new_alarms_reported = (queue_alarm_mask | | ||
| 507 | (alarm & ~dev->alarms_reported & queue_alarm_mask)); | ||
| 508 | |||
| 509 | if (new_alarms_reported & ~LOCAL_ALARM_MASK) { | ||
| 510 | /* check that we are not re-reporting */ | ||
| 511 | if (new_alarms_reported & EVENT(ALARM_GPU_LOST)) | ||
| 512 | poll_mask |= NVGPU_POLLHUP; | ||
| 513 | |||
| 514 | poll_mask |= (NVGPU_POLLIN | NVGPU_POLLPRI); | ||
| 515 | /* On next run do not report global alarms that were already | ||
| 516 | * reported, but report SHUTDOWN always | ||
| 517 | */ | ||
| 518 | dev->alarms_reported = new_alarms_reported & ~LOCAL_ALARM_MASK & | ||
| 519 | ~EVENT(ALARM_GPU_LOST); | ||
| 520 | } | ||
| 521 | |||
| 522 | if (poll_mask) { | ||
| 523 | nvgpu_atomic_set(&dev->poll_mask, poll_mask); | ||
| 524 | nvgpu_clk_arb_event_post_event(dev); | ||
| 525 | } | ||
| 526 | |||
| 527 | return new_alarms_reported; | ||
| 528 | } | ||
| 529 | |||
| 530 | void nvgpu_clk_arb_clear_global_alarm(struct gk20a *g, u32 alarm) | ||
| 531 | { | ||
| 532 | struct nvgpu_clk_arb *arb = g->clk_arb; | ||
| 533 | |||
| 534 | u64 current_mask; | ||
| 535 | u32 refcnt; | ||
| 536 | u32 alarm_mask; | ||
| 537 | u64 new_mask; | ||
| 538 | |||
| 539 | do { | ||
| 540 | current_mask = nvgpu_atomic64_read(&arb->alarm_mask); | ||
| 541 | /* atomic operations are strong so they do not need masks */ | ||
| 542 | |||
| 543 | refcnt = ((u32) (current_mask >> 32)) + 1; | ||
| 544 | alarm_mask = (u32) (current_mask & ~alarm); | ||
| 545 | new_mask = ((u64) refcnt << 32) | alarm_mask; | ||
| 546 | |||
| 547 | } while (unlikely(current_mask != | ||
| 548 | (u64)nvgpu_atomic64_cmpxchg(&arb->alarm_mask, | ||
| 549 | current_mask, new_mask))); | ||
| 550 | } | ||
| 551 | |||
| 552 | /* | ||
| 553 | * Process one scheduled work item. | ||
| 554 | */ | ||
| 555 | static void nvgpu_clk_arb_worker_process_item( | ||
| 556 | struct nvgpu_clk_arb_work_item *work_item) | ||
| 557 | { | ||
| 558 | struct gk20a *g = work_item->arb->g; | ||
| 559 | |||
| 560 | clk_arb_dbg(g, " "); | ||
| 561 | |||
| 562 | if (work_item->item_type == CLK_ARB_WORK_UPDATE_VF_TABLE) | ||
| 563 | nvgpu_clk_arb_run_vf_table_cb(work_item->arb); | ||
| 564 | else if (work_item->item_type == CLK_ARB_WORK_UPDATE_ARB) | ||
| 565 | g->ops.clk_arb.clk_arb_run_arbiter_cb(work_item->arb); | ||
| 566 | } | ||
| 567 | |||
| 568 | /** | ||
| 569 | * Tell the worker that one more work needs to be done. | ||
| 570 | * | ||
| 571 | * Increase the work counter to synchronize the worker with the new work. Wake | ||
| 572 | * up the worker. If the worker was already running, it will handle this work | ||
| 573 | * before going to sleep. | ||
| 574 | */ | ||
| 575 | static int nvgpu_clk_arb_worker_wakeup(struct gk20a *g) | ||
| 576 | { | ||
| 577 | int put; | ||
| 578 | |||
| 579 | clk_arb_dbg(g, " "); | ||
| 580 | |||
| 581 | put = nvgpu_atomic_inc_return(&g->clk_arb_worker.put); | ||
| 582 | nvgpu_cond_signal_interruptible(&g->clk_arb_worker.wq); | ||
| 583 | |||
| 584 | return put; | ||
| 585 | } | ||
| 586 | |||
| 587 | /** | ||
| 588 | * Test if there is some work pending. | ||
| 589 | * | ||
| 590 | * This is a pair for nvgpu_clk_arb_worker_wakeup to be called from the | ||
| 591 | * worker. The worker has an internal work counter which is incremented once | ||
| 592 | * per finished work item. This is compared with the number of queued jobs. | ||
| 593 | */ | ||
| 594 | static bool nvgpu_clk_arb_worker_pending(struct gk20a *g, int get) | ||
| 595 | { | ||
| 596 | bool pending = nvgpu_atomic_read(&g->clk_arb_worker.put) != get; | ||
| 597 | |||
| 598 | /* We don't need barriers because they are implicit in locking */ | ||
| 599 | return pending; | ||
| 600 | } | ||
| 601 | |||
| 602 | /** | ||
| 603 | * Process the queued works for the worker thread serially. | ||
| 604 | * | ||
| 605 | * Flush all the work items in the queue one by one. This may block timeout | ||
| 606 | * handling for a short while, as these are serialized. | ||
| 607 | */ | ||
| 608 | static void nvgpu_clk_arb_worker_process(struct gk20a *g, int *get) | ||
| 609 | { | ||
| 610 | |||
| 611 | while (nvgpu_clk_arb_worker_pending(g, *get)) { | ||
| 612 | struct nvgpu_clk_arb_work_item *work_item = NULL; | ||
| 613 | |||
| 614 | nvgpu_spinlock_acquire(&g->clk_arb_worker.items_lock); | ||
| 615 | if (!nvgpu_list_empty(&g->clk_arb_worker.items)) { | ||
| 616 | work_item = nvgpu_list_first_entry(&g->clk_arb_worker.items, | ||
| 617 | nvgpu_clk_arb_work_item, worker_item); | ||
| 618 | nvgpu_list_del(&work_item->worker_item); | ||
| 619 | } | ||
| 620 | nvgpu_spinlock_release(&g->clk_arb_worker.items_lock); | ||
| 621 | |||
| 622 | if (!work_item) { | ||
| 623 | /* | ||
| 624 | * Woke up for some other reason, but there are no | ||
| 625 | * other reasons than a work item added in the items list | ||
| 626 | * currently, so warn and ack the message. | ||
| 627 | */ | ||
| 628 | nvgpu_warn(g, "Spurious worker event!"); | ||
| 629 | ++*get; | ||
| 630 | break; | ||
| 631 | } | ||
| 632 | |||
| 633 | nvgpu_clk_arb_worker_process_item(work_item); | ||
| 634 | ++*get; | ||
| 635 | } | ||
| 636 | } | ||
| 637 | |||
| 638 | /* | ||
| 639 | * Process all work items found in the clk arbiter work queue. | ||
| 640 | */ | ||
| 641 | static int nvgpu_clk_arb_poll_worker(void *arg) | ||
| 642 | { | ||
| 643 | struct gk20a *g = (struct gk20a *)arg; | ||
| 644 | struct gk20a_worker *worker = &g->clk_arb_worker; | ||
| 645 | int get = 0; | ||
| 646 | |||
| 647 | clk_arb_dbg(g, " "); | ||
| 648 | |||
| 649 | while (!nvgpu_thread_should_stop(&worker->poll_task)) { | ||
| 650 | int ret; | ||
| 651 | |||
| 652 | ret = NVGPU_COND_WAIT_INTERRUPTIBLE( | ||
| 653 | &worker->wq, | ||
| 654 | nvgpu_clk_arb_worker_pending(g, get), 0); | ||
| 655 | |||
| 656 | if (nvgpu_thread_should_stop(&worker->poll_task)) { | ||
| 657 | break; | ||
| 658 | } | ||
| 659 | |||
| 660 | if (ret == 0) | ||
| 661 | nvgpu_clk_arb_worker_process(g, &get); | ||
| 662 | } | ||
| 663 | return 0; | ||
| 664 | } | ||
| 665 | |||
| 666 | static int __nvgpu_clk_arb_worker_start(struct gk20a *g) | ||
| 667 | { | ||
| 668 | char thread_name[64]; | ||
| 669 | int err = 0; | ||
| 670 | |||
| 671 | if (nvgpu_thread_is_running(&g->clk_arb_worker.poll_task)) | ||
| 672 | return err; | ||
| 673 | |||
| 674 | nvgpu_mutex_acquire(&g->clk_arb_worker.start_lock); | ||
| 675 | |||
| 676 | /* | ||
| 677 | * Mutexes have implicit barriers, so there is no risk of a thread | ||
| 678 | * having a stale copy of the poll_task variable as the call to | ||
| 679 | * thread_is_running is volatile | ||
| 680 | */ | ||
| 681 | |||
| 682 | if (nvgpu_thread_is_running(&g->clk_arb_worker.poll_task)) { | ||
| 683 | nvgpu_mutex_release(&g->clk_arb_worker.start_lock); | ||
| 684 | return err; | ||
| 685 | } | ||
| 686 | |||
| 687 | snprintf(thread_name, sizeof(thread_name), | ||
| 688 | "nvgpu_clk_arb_poll_%s", g->name); | ||
| 689 | |||
| 690 | err = nvgpu_thread_create(&g->clk_arb_worker.poll_task, g, | ||
| 691 | nvgpu_clk_arb_poll_worker, thread_name); | ||
| 692 | |||
| 693 | nvgpu_mutex_release(&g->clk_arb_worker.start_lock); | ||
| 694 | return err; | ||
| 695 | } | ||
| 696 | |||
| 697 | /** | ||
| 698 | * Append a work item to the worker's list. | ||
| 699 | * | ||
| 700 | * This adds work item to the end of the list and wakes the worker | ||
| 701 | * up immediately. If the work item already existed in the list, it's not added, | ||
| 702 | * because in that case it has been scheduled already but has not yet been | ||
| 703 | * processed. | ||
| 704 | */ | ||
| 705 | void nvgpu_clk_arb_worker_enqueue(struct gk20a *g, | ||
| 706 | struct nvgpu_clk_arb_work_item *work_item) | ||
| 707 | { | ||
| 708 | clk_arb_dbg(g, " "); | ||
| 709 | |||
| 710 | /* | ||
| 711 | * Warn if worker thread cannot run | ||
| 712 | */ | ||
| 713 | if (WARN_ON(__nvgpu_clk_arb_worker_start(g))) { | ||
| 714 | nvgpu_warn(g, "clk arb worker cannot run!"); | ||
| 715 | return; | ||
| 716 | } | ||
| 717 | |||
| 718 | nvgpu_spinlock_acquire(&g->clk_arb_worker.items_lock); | ||
| 719 | if (!nvgpu_list_empty(&work_item->worker_item)) { | ||
| 720 | /* | ||
| 721 | * Already queued, so will get processed eventually. | ||
| 722 | * The worker is probably awake already. | ||
| 723 | */ | ||
| 724 | nvgpu_spinlock_release(&g->clk_arb_worker.items_lock); | ||
| 725 | return; | ||
| 726 | } | ||
| 727 | nvgpu_list_add_tail(&work_item->worker_item, &g->clk_arb_worker.items); | ||
| 728 | nvgpu_spinlock_release(&g->clk_arb_worker.items_lock); | ||
| 729 | |||
| 730 | nvgpu_clk_arb_worker_wakeup(g); | ||
| 731 | } | ||
| 732 | |||
| 733 | /** | ||
| 734 | * Initialize the clk arb worker's metadata and start the background thread. | ||
| 735 | */ | ||
| 736 | int nvgpu_clk_arb_worker_init(struct gk20a *g) | ||
| 737 | { | ||
| 738 | int err; | ||
| 739 | |||
| 740 | nvgpu_atomic_set(&g->clk_arb_worker.put, 0); | ||
| 741 | nvgpu_cond_init(&g->clk_arb_worker.wq); | ||
| 742 | nvgpu_init_list_node(&g->clk_arb_worker.items); | ||
| 743 | nvgpu_spinlock_init(&g->clk_arb_worker.items_lock); | ||
| 744 | err = nvgpu_mutex_init(&g->clk_arb_worker.start_lock); | ||
| 745 | if (err) | ||
| 746 | goto error_check; | ||
| 747 | |||
| 748 | err = __nvgpu_clk_arb_worker_start(g); | ||
| 749 | error_check: | ||
| 750 | if (err) { | ||
| 751 | nvgpu_err(g, "failed to start clk arb poller thread"); | ||
| 752 | return err; | ||
| 753 | } | ||
| 754 | return 0; | ||
| 755 | } | ||
| 756 | |||
| 757 | int nvgpu_clk_arb_init_arbiter(struct gk20a *g) | ||
| 758 | { | ||
| 759 | int err = 0; | ||
| 760 | |||
| 761 | if (!g->ops.clk.support_clk_freq_controller || | ||
| 762 | !g->ops.clk_arb.get_arbiter_clk_domains) { | ||
| 763 | return 0; | ||
| 764 | } | ||
| 765 | |||
| 766 | nvgpu_mutex_acquire(&g->clk_arb_enable_lock); | ||
| 767 | |||
| 768 | err = g->ops.clk_arb.arbiter_clk_init(g); | ||
| 769 | |||
| 770 | nvgpu_mutex_release(&g->clk_arb_enable_lock); | ||
| 771 | |||
| 772 | return err; | ||
| 773 | } | ||
| 774 | |||
| 775 | bool nvgpu_clk_arb_has_active_req(struct gk20a *g) | ||
| 776 | { | ||
| 777 | return (nvgpu_atomic_read(&g->clk_arb_global_nr) > 0); | ||
| 778 | } | ||
| 779 | |||
| 780 | void nvgpu_clk_arb_send_thermal_alarm(struct gk20a *g) | ||
| 781 | { | ||
| 782 | nvgpu_clk_arb_schedule_alarm(g, | ||
| 783 | (0x1UL << NVGPU_EVENT_ALARM_THERMAL_ABOVE_THRESHOLD)); | ||
| 784 | } | ||
| 785 | |||
| 786 | void nvgpu_clk_arb_schedule_alarm(struct gk20a *g, u32 alarm) | ||
| 787 | { | ||
| 788 | struct nvgpu_clk_arb *arb = g->clk_arb; | ||
| 789 | |||
| 790 | nvgpu_clk_arb_set_global_alarm(g, alarm); | ||
| 791 | nvgpu_clk_arb_worker_enqueue(g, &arb->update_arb_work_item); | ||
| 792 | } | ||
| 793 | |||
| 794 | static void nvgpu_clk_arb_worker_deinit(struct gk20a *g) | ||
| 795 | { | ||
| 796 | nvgpu_atomic_inc(&g->clk_arb_worker.put); | ||
| 797 | |||
| 798 | nvgpu_mutex_acquire(&g->clk_arb_worker.start_lock); | ||
| 799 | nvgpu_thread_stop(&g->clk_arb_worker.poll_task); | ||
| 800 | nvgpu_mutex_release(&g->clk_arb_worker.start_lock); | ||
| 801 | } | ||
| 802 | |||
| 803 | void nvgpu_clk_arb_cleanup_arbiter(struct gk20a *g) | ||
| 804 | { | ||
| 805 | struct nvgpu_clk_arb *arb = g->clk_arb; | ||
| 806 | |||
| 807 | nvgpu_mutex_acquire(&g->clk_arb_enable_lock); | ||
| 808 | |||
| 809 | if (arb) { | ||
| 810 | nvgpu_clk_arb_worker_deinit(g); | ||
| 811 | g->ops.clk_arb.clk_arb_cleanup(g->clk_arb); | ||
| 812 | } | ||
| 813 | |||
| 814 | nvgpu_mutex_release(&g->clk_arb_enable_lock); | ||
| 815 | } | ||
| 816 | |||
| 817 | int nvgpu_clk_arb_init_session(struct gk20a *g, | ||
| 818 | struct nvgpu_clk_session **_session) | ||
| 819 | { | ||
| 820 | struct nvgpu_clk_arb *arb = g->clk_arb; | ||
| 821 | struct nvgpu_clk_session *session = *(_session); | ||
| 822 | |||
| 823 | clk_arb_dbg(g, " "); | ||
| 824 | |||
| 825 | if (!g->ops.clk.support_clk_freq_controller || | ||
| 826 | !g->ops.clk_arb.get_arbiter_clk_domains) { | ||
| 827 | return 0; | ||
| 828 | } | ||
| 829 | |||
| 830 | session = nvgpu_kzalloc(g, sizeof(struct nvgpu_clk_session)); | ||
| 831 | if (!session) | ||
| 832 | return -ENOMEM; | ||
| 833 | session->g = g; | ||
| 834 | |||
| 835 | nvgpu_ref_init(&session->refcount); | ||
| 836 | |||
| 837 | session->zombie = false; | ||
| 838 | session->target_pool[0].pstate = CTRL_PERF_PSTATE_P8; | ||
| 839 | /* make sure that the initialization of the pool is visible | ||
| 840 | * before the update | ||
| 841 | */ | ||
| 842 | nvgpu_smp_wmb(); | ||
| 843 | session->target = &session->target_pool[0]; | ||
| 844 | |||
| 845 | nvgpu_init_list_node(&session->targets); | ||
| 846 | nvgpu_spinlock_init(&session->session_lock); | ||
| 847 | |||
| 848 | nvgpu_spinlock_acquire(&arb->sessions_lock); | ||
| 849 | nvgpu_list_add_tail(&session->link, &arb->sessions); | ||
| 850 | nvgpu_spinlock_release(&arb->sessions_lock); | ||
| 851 | |||
| 852 | *_session = session; | ||
| 853 | |||
| 854 | return 0; | ||
| 855 | } | ||
| 856 | |||
| 857 | void nvgpu_clk_arb_free_fd(struct nvgpu_ref *refcount) | ||
| 858 | { | ||
| 859 | struct nvgpu_clk_dev *dev = container_of(refcount, | ||
| 860 | struct nvgpu_clk_dev, refcount); | ||
| 861 | struct nvgpu_clk_session *session = dev->session; | ||
| 862 | struct gk20a *g = session->g; | ||
| 863 | |||
| 864 | nvgpu_clk_notification_queue_free(g, &dev->queue); | ||
| 865 | |||
| 866 | nvgpu_atomic_dec(&g->clk_arb_global_nr); | ||
| 867 | nvgpu_kfree(g, dev); | ||
| 868 | } | ||
| 869 | |||
| 870 | void nvgpu_clk_arb_free_session(struct nvgpu_ref *refcount) | ||
| 871 | { | ||
| 872 | struct nvgpu_clk_session *session = container_of(refcount, | ||
| 873 | struct nvgpu_clk_session, refcount); | ||
| 874 | struct nvgpu_clk_arb *arb = session->g->clk_arb; | ||
| 875 | struct gk20a *g = session->g; | ||
| 876 | struct nvgpu_clk_dev *dev, *tmp; | ||
| 877 | |||
| 878 | clk_arb_dbg(g, " "); | ||
| 879 | |||
| 880 | if (arb) { | ||
| 881 | nvgpu_spinlock_acquire(&arb->sessions_lock); | ||
| 882 | nvgpu_list_del(&session->link); | ||
| 883 | nvgpu_spinlock_release(&arb->sessions_lock); | ||
| 884 | } | ||
| 885 | |||
| 886 | nvgpu_spinlock_acquire(&session->session_lock); | ||
| 887 | nvgpu_list_for_each_entry_safe(dev, tmp, &session->targets, | ||
| 888 | nvgpu_clk_dev, node) { | ||
| 889 | nvgpu_list_del(&dev->node); | ||
| 890 | nvgpu_ref_put(&dev->refcount, nvgpu_clk_arb_free_fd); | ||
| 891 | } | ||
| 892 | nvgpu_spinlock_release(&session->session_lock); | ||
| 893 | |||
| 894 | nvgpu_kfree(g, session); | ||
| 895 | } | ||
| 896 | |||
| 897 | void nvgpu_clk_arb_release_session(struct gk20a *g, | ||
| 898 | struct nvgpu_clk_session *session) | ||
| 899 | { | ||
| 900 | struct nvgpu_clk_arb *arb = g->clk_arb; | ||
| 901 | |||
| 902 | clk_arb_dbg(g, " "); | ||
| 903 | |||
| 904 | session->zombie = true; | ||
| 905 | nvgpu_ref_put(&session->refcount, nvgpu_clk_arb_free_session); | ||
| 906 | if (arb) | ||
| 907 | nvgpu_clk_arb_worker_enqueue(g, &arb->update_arb_work_item); | ||
| 908 | } | ||
| 909 | |||
| 910 | void nvgpu_clk_arb_schedule_vf_table_update(struct gk20a *g) | ||
| 911 | { | ||
| 912 | struct nvgpu_clk_arb *arb = g->clk_arb; | ||
| 913 | |||
| 914 | nvgpu_clk_arb_worker_enqueue(g, &arb->update_vf_table_work_item); | ||
| 915 | } | ||
| 916 | |||
| 917 | /* This function is inherently unsafe to call while arbiter is running | ||
| 918 | * arbiter must be blocked before calling this function | ||
| 919 | */ | ||
| 920 | int nvgpu_clk_arb_get_current_pstate(struct gk20a *g) | ||
| 921 | { | ||
| 922 | return NV_ACCESS_ONCE(g->clk_arb->actual->pstate); | ||
| 923 | } | ||
| 924 | |||
| 925 | void nvgpu_clk_arb_pstate_change_lock(struct gk20a *g, bool lock) | ||
| 926 | { | ||
| 927 | struct nvgpu_clk_arb *arb = g->clk_arb; | ||
| 928 | |||
| 929 | if (lock) | ||
| 930 | nvgpu_mutex_acquire(&arb->pstate_lock); | ||
| 931 | else | ||
| 932 | nvgpu_mutex_release(&arb->pstate_lock); | ||
| 933 | } | ||
| 934 | |||
| 935 | bool nvgpu_clk_arb_is_valid_domain(struct gk20a *g, u32 api_domain) | ||
| 936 | { | ||
| 937 | u32 clk_domains = g->ops.clk_arb.get_arbiter_clk_domains(g); | ||
| 938 | |||
| 939 | switch (api_domain) { | ||
| 940 | case NVGPU_CLK_DOMAIN_MCLK: | ||
| 941 | return (clk_domains & CTRL_CLK_DOMAIN_MCLK) != 0; | ||
| 942 | |||
| 943 | case NVGPU_CLK_DOMAIN_GPCCLK: | ||
| 944 | return (clk_domains & CTRL_CLK_DOMAIN_GPC2CLK) != 0; | ||
| 945 | |||
| 946 | default: | ||
| 947 | return false; | ||
| 948 | } | ||
| 949 | } | ||
| 950 | |||
| 951 | int nvgpu_clk_arb_get_arbiter_clk_range(struct gk20a *g, u32 api_domain, | ||
| 952 | u16 *min_mhz, u16 *max_mhz) | ||
| 953 | { | ||
| 954 | int ret; | ||
| 955 | |||
| 956 | switch (api_domain) { | ||
| 957 | case NVGPU_CLK_DOMAIN_MCLK: | ||
| 958 | ret = g->ops.clk_arb.get_arbiter_clk_range(g, | ||
| 959 | CTRL_CLK_DOMAIN_MCLK, min_mhz, max_mhz); | ||
| 960 | return ret; | ||
| 961 | |||
| 962 | case NVGPU_CLK_DOMAIN_GPCCLK: | ||
| 963 | ret = g->ops.clk_arb.get_arbiter_clk_range(g, | ||
| 964 | CTRL_CLK_DOMAIN_GPC2CLK, min_mhz, max_mhz); | ||
| 965 | if (!ret) { | ||
| 966 | *min_mhz /= 2; | ||
| 967 | *max_mhz /= 2; | ||
| 968 | } | ||
| 969 | return ret; | ||
| 970 | |||
| 971 | default: | ||
| 972 | return -EINVAL; | ||
| 973 | } | ||
| 974 | } | ||
| 975 | |||
| 976 | int nvgpu_clk_arb_get_arbiter_clk_f_points(struct gk20a *g, | ||
| 977 | u32 api_domain, u32 *max_points, u16 *fpoints) | ||
| 978 | { | ||
| 979 | int err; | ||
| 980 | u32 i; | ||
| 981 | |||
| 982 | switch (api_domain) { | ||
| 983 | case NVGPU_CLK_DOMAIN_GPCCLK: | ||
| 984 | err = g->ops.clk_arb.get_arbiter_f_points(g, | ||
| 985 | CTRL_CLK_DOMAIN_GPC2CLK, max_points, fpoints); | ||
| 986 | if (err || !fpoints) | ||
| 987 | return err; | ||
| 988 | for (i = 0; i < *max_points; i++) | ||
| 989 | fpoints[i] /= 2; | ||
| 990 | return 0; | ||
| 991 | case NVGPU_CLK_DOMAIN_MCLK: | ||
| 992 | return g->ops.clk_arb.get_arbiter_f_points(g, | ||
| 993 | CTRL_CLK_DOMAIN_MCLK, max_points, fpoints); | ||
| 994 | default: | ||
| 995 | return -EINVAL; | ||
| 996 | } | ||
| 997 | } | ||
| 998 | |||
| 999 | int nvgpu_clk_arb_get_session_target_mhz(struct nvgpu_clk_session *session, | ||
| 1000 | u32 api_domain, u16 *freq_mhz) | ||
| 1001 | { | ||
| 1002 | int err = 0; | ||
| 1003 | struct nvgpu_clk_arb_target *target = session->target; | ||
| 1004 | |||
| 1005 | if (!nvgpu_clk_arb_is_valid_domain(session->g, api_domain)) { | ||
| 1006 | return -EINVAL; | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | switch (api_domain) { | ||
| 1010 | case NVGPU_CLK_DOMAIN_MCLK: | ||
| 1011 | *freq_mhz = target->mclk; | ||
| 1012 | break; | ||
| 1013 | |||
| 1014 | case NVGPU_CLK_DOMAIN_GPCCLK: | ||
| 1015 | *freq_mhz = target->gpc2clk / 2ULL; | ||
| 1016 | break; | ||
| 1017 | |||
| 1018 | default: | ||
| 1019 | *freq_mhz = 0; | ||
| 1020 | err = -EINVAL; | ||
| 1021 | } | ||
| 1022 | return err; | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | int nvgpu_clk_arb_get_arbiter_actual_mhz(struct gk20a *g, | ||
| 1026 | u32 api_domain, u16 *freq_mhz) | ||
| 1027 | { | ||
| 1028 | struct nvgpu_clk_arb *arb = g->clk_arb; | ||
| 1029 | int err = 0; | ||
| 1030 | struct nvgpu_clk_arb_target *actual = arb->actual; | ||
| 1031 | |||
| 1032 | if (!nvgpu_clk_arb_is_valid_domain(g, api_domain)) { | ||
| 1033 | return -EINVAL; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | switch (api_domain) { | ||
| 1037 | case NVGPU_CLK_DOMAIN_MCLK: | ||
| 1038 | *freq_mhz = actual->mclk; | ||
| 1039 | break; | ||
| 1040 | |||
| 1041 | case NVGPU_CLK_DOMAIN_GPCCLK: | ||
| 1042 | *freq_mhz = actual->gpc2clk / 2ULL; | ||
| 1043 | break; | ||
| 1044 | |||
| 1045 | default: | ||
| 1046 | *freq_mhz = 0; | ||
| 1047 | err = -EINVAL; | ||
| 1048 | } | ||
| 1049 | return err; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | unsigned long nvgpu_clk_measure_freq(struct gk20a *g, u32 api_domain) | ||
| 1053 | { | ||
| 1054 | unsigned long freq = 0UL; | ||
| 1055 | |||
| 1056 | switch (api_domain) { | ||
| 1057 | case CTRL_CLK_DOMAIN_GPC2CLK: | ||
| 1058 | freq = g->ops.clk.get_rate(g, CTRL_CLK_DOMAIN_GPCCLK) * 2UL; | ||
| 1059 | break; | ||
| 1060 | default: | ||
| 1061 | break; | ||
| 1062 | } | ||
| 1063 | return freq; | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | int nvgpu_clk_arb_get_arbiter_effective_mhz(struct gk20a *g, | ||
| 1067 | u32 api_domain, u16 *freq_mhz) | ||
| 1068 | { | ||
| 1069 | if (!nvgpu_clk_arb_is_valid_domain(g, api_domain)) { | ||
| 1070 | return -EINVAL; | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | switch (api_domain) { | ||
| 1074 | case NVGPU_CLK_DOMAIN_MCLK: | ||
| 1075 | *freq_mhz = g->ops.clk.measure_freq(g, CTRL_CLK_DOMAIN_MCLK) / | ||
| 1076 | 1000000ULL; | ||
| 1077 | return 0; | ||
| 1078 | |||
| 1079 | case NVGPU_CLK_DOMAIN_GPCCLK: | ||
| 1080 | *freq_mhz = g->ops.clk.measure_freq(g, | ||
| 1081 | CTRL_CLK_DOMAIN_GPC2CLK) / 2000000ULL; | ||
| 1082 | return 0; | ||
| 1083 | |||
| 1084 | default: | ||
| 1085 | return -EINVAL; | ||
| 1086 | } | ||
| 1087 | } | ||
diff --git a/include/clk/clk_domain.c b/include/clk/clk_domain.c deleted file mode 100644 index 3b64f51..0000000 --- a/include/clk/clk_domain.c +++ /dev/null | |||
| @@ -1,1666 +0,0 @@ | |||
| 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 | |||
| 34 | static struct clk_domain *construct_clk_domain(struct gk20a *g, void *pargs); | ||
| 35 | |||
| 36 | static int devinit_get_clocks_table(struct gk20a *g, | ||
| 37 | struct clk_domains *pdomainobjs); | ||
| 38 | |||
| 39 | static int clk_domain_pmudatainit_super(struct gk20a *g, struct boardobj | ||
| 40 | *board_obj_ptr, struct nv_pmu_boardobj *ppmudata); | ||
| 41 | |||
| 42 | static struct vbios_clocks_table_1x_hal_clock_entry | ||
| 43 | vbiosclktbl1xhalentry_gp[] = { | ||
| 44 | { clkwhich_gpc2clk, true, 1, }, | ||
| 45 | { clkwhich_xbar2clk, true, 1, }, | ||
| 46 | { clkwhich_mclk, false, 1, }, | ||
| 47 | { clkwhich_sys2clk, true, 1, }, | ||
| 48 | { clkwhich_hub2clk, false, 1, }, | ||
| 49 | { clkwhich_nvdclk, false, 1, }, | ||
| 50 | { clkwhich_pwrclk, false, 1, }, | ||
| 51 | { clkwhich_dispclk, false, 1, }, | ||
| 52 | { clkwhich_pciegenclk, false, 1, } | ||
| 53 | }; | ||
| 54 | /* | ||
| 55 | * Updated from RM devinit_clock.c | ||
| 56 | * GV100 is 0x03 and | ||
| 57 | * GP10x is 0x02 in clocks_hal. | ||
| 58 | */ | ||
| 59 | static struct vbios_clocks_table_1x_hal_clock_entry | ||
| 60 | vbiosclktbl1xhalentry_gv[] = { | ||
| 61 | { clkwhich_gpcclk, true, 2, }, | ||
| 62 | { clkwhich_xbarclk, true, 1, }, | ||
| 63 | { clkwhich_mclk, false, 1, }, | ||
| 64 | { clkwhich_sysclk, true, 1, }, | ||
| 65 | { clkwhich_hubclk, false, 1, }, | ||
| 66 | { clkwhich_nvdclk, true, 1, }, | ||
| 67 | { clkwhich_pwrclk, false, 1, }, | ||
| 68 | { clkwhich_dispclk, false, 1, }, | ||
| 69 | { clkwhich_pciegenclk, false, 1, }, | ||
| 70 | { clkwhich_hostclk, true, 1, } | ||
| 71 | }; | ||
| 72 | |||
| 73 | static u32 clktranslatehalmumsettoapinumset(u32 clkhaldomains) | ||
| 74 | { | ||
| 75 | u32 clkapidomains = 0; | ||
| 76 | |||
| 77 | if (clkhaldomains & BIT(clkwhich_gpcclk)) { | ||
| 78 | clkapidomains |= CTRL_CLK_DOMAIN_GPCCLK; | ||
| 79 | } | ||
| 80 | if (clkhaldomains & BIT(clkwhich_xbarclk)) { | ||
| 81 | clkapidomains |= CTRL_CLK_DOMAIN_XBARCLK; | ||
| 82 | } | ||
| 83 | if (clkhaldomains & BIT(clkwhich_sysclk)) { | ||
| 84 | clkapidomains |= CTRL_CLK_DOMAIN_SYSCLK; | ||
| 85 | } | ||
| 86 | if (clkhaldomains & BIT(clkwhich_hubclk)) { | ||
| 87 | clkapidomains |= CTRL_CLK_DOMAIN_HUBCLK; | ||
| 88 | } | ||
| 89 | if (clkhaldomains & BIT(clkwhich_hostclk)) { | ||
| 90 | clkapidomains |= CTRL_CLK_DOMAIN_HOSTCLK; | ||
| 91 | } | ||
| 92 | if (clkhaldomains & BIT(clkwhich_gpc2clk)) { | ||
| 93 | clkapidomains |= CTRL_CLK_DOMAIN_GPC2CLK; | ||
| 94 | } | ||
| 95 | if (clkhaldomains & BIT(clkwhich_xbar2clk)) { | ||
| 96 | clkapidomains |= CTRL_CLK_DOMAIN_XBAR2CLK; | ||
| 97 | } | ||
| 98 | if (clkhaldomains & BIT(clkwhich_sys2clk)) { | ||
| 99 | clkapidomains |= CTRL_CLK_DOMAIN_SYS2CLK; | ||
| 100 | } | ||
| 101 | if (clkhaldomains & BIT(clkwhich_hub2clk)) { | ||
| 102 | clkapidomains |= CTRL_CLK_DOMAIN_HUB2CLK; | ||
| 103 | } | ||
| 104 | if (clkhaldomains & BIT(clkwhich_pwrclk)) { | ||
| 105 | clkapidomains |= CTRL_CLK_DOMAIN_PWRCLK; | ||
| 106 | } | ||
| 107 | if (clkhaldomains & BIT(clkwhich_pciegenclk)) { | ||
| 108 | clkapidomains |= CTRL_CLK_DOMAIN_PCIEGENCLK; | ||
| 109 | } | ||
| 110 | if (clkhaldomains & BIT(clkwhich_mclk)) { | ||
| 111 | clkapidomains |= CTRL_CLK_DOMAIN_MCLK; | ||
| 112 | } | ||
| 113 | if (clkhaldomains & BIT(clkwhich_nvdclk)) { | ||
| 114 | clkapidomains |= CTRL_CLK_DOMAIN_NVDCLK; | ||
| 115 | } | ||
| 116 | if (clkhaldomains & BIT(clkwhich_dispclk)) { | ||
| 117 | clkapidomains |= CTRL_CLK_DOMAIN_DISPCLK; | ||
| 118 | } | ||
| 119 | |||
| 120 | return clkapidomains; | ||
| 121 | } | ||
| 122 | |||
| 123 | static int _clk_domains_pmudatainit_3x(struct gk20a *g, | ||
| 124 | struct boardobjgrp *pboardobjgrp, | ||
| 125 | struct nv_pmu_boardobjgrp_super *pboardobjgrppmu) | ||
| 126 | { | ||
| 127 | struct nv_pmu_clk_clk_domain_boardobjgrp_set_header *pset = | ||
| 128 | (struct nv_pmu_clk_clk_domain_boardobjgrp_set_header *) | ||
| 129 | pboardobjgrppmu; | ||
| 130 | struct clk_domains *pdomains = (struct clk_domains *)pboardobjgrp; | ||
| 131 | int status = 0; | ||
| 132 | |||
| 133 | status = boardobjgrp_pmudatainit_e32(g, pboardobjgrp, pboardobjgrppmu); | ||
| 134 | if (status) { | ||
| 135 | nvgpu_err(g, | ||
| 136 | "error updating pmu boardobjgrp for clk domain 0x%x", | ||
| 137 | status); | ||
| 138 | goto done; | ||
| 139 | } | ||
| 140 | |||
| 141 | pset->vbios_domains = pdomains->vbios_domains; | ||
| 142 | pset->cntr_sampling_periodms = pdomains->cntr_sampling_periodms; | ||
| 143 | pset->version = CLK_DOMAIN_BOARDOBJGRP_VERSION; | ||
| 144 | pset->b_override_o_v_o_c = false; | ||
| 145 | pset->b_debug_mode = false; | ||
| 146 | pset->b_enforce_vf_monotonicity = pdomains->b_enforce_vf_monotonicity; | ||
| 147 | pset->b_enforce_vf_smoothening = pdomains->b_enforce_vf_smoothening; | ||
| 148 | if (g->ops.clk.split_rail_support) { | ||
| 149 | pset->volt_rails_max = 2; | ||
| 150 | } else { | ||
| 151 | pset->volt_rails_max = 1; | ||
| 152 | } | ||
| 153 | status = boardobjgrpmask_export( | ||
| 154 | &pdomains->master_domains_mask.super, | ||
| 155 | pdomains->master_domains_mask.super.bitcount, | ||
| 156 | &pset->master_domains_mask.super); | ||
| 157 | |||
| 158 | memcpy(&pset->deltas, &pdomains->deltas, | ||
| 159 | (sizeof(struct ctrl_clk_clk_delta))); | ||
| 160 | |||
| 161 | done: | ||
| 162 | return status; | ||
| 163 | } | ||
| 164 | |||
| 165 | static int _clk_domains_pmudata_instget(struct gk20a *g, | ||
| 166 | struct nv_pmu_boardobjgrp *pmuboardobjgrp, | ||
| 167 | struct nv_pmu_boardobj **ppboardobjpmudata, | ||
| 168 | u8 idx) | ||
| 169 | { | ||
| 170 | struct nv_pmu_clk_clk_domain_boardobj_grp_set *pgrp_set = | ||
| 171 | (struct nv_pmu_clk_clk_domain_boardobj_grp_set *) | ||
| 172 | pmuboardobjgrp; | ||
| 173 | |||
| 174 | nvgpu_log_info(g, " "); | ||
| 175 | |||
| 176 | /*check whether pmuboardobjgrp has a valid boardobj in index*/ | ||
| 177 | if (((u32)BIT(idx) & | ||
| 178 | pgrp_set->hdr.data.super.obj_mask.super.data[0]) == 0) { | ||
| 179 | return -EINVAL; | ||
| 180 | } | ||
| 181 | |||
| 182 | *ppboardobjpmudata = (struct nv_pmu_boardobj *) | ||
| 183 | &pgrp_set->objects[idx].data.board_obj; | ||
| 184 | nvgpu_log_info(g, " Done"); | ||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | int clk_domain_sw_setup(struct gk20a *g) | ||
| 189 | { | ||
| 190 | int status; | ||
| 191 | struct boardobjgrp *pboardobjgrp = NULL; | ||
| 192 | struct clk_domains *pclkdomainobjs; | ||
| 193 | struct clk_domain *pdomain; | ||
| 194 | struct clk_domain_3x_master *pdomain_master; | ||
| 195 | struct clk_domain_3x_slave *pdomain_slave; | ||
| 196 | u8 i; | ||
| 197 | |||
| 198 | nvgpu_log_info(g, " "); | ||
| 199 | |||
| 200 | status = boardobjgrpconstruct_e32(g, &g->clk_pmu.clk_domainobjs.super); | ||
| 201 | if (status) { | ||
| 202 | nvgpu_err(g, | ||
| 203 | "error creating boardobjgrp for clk domain, status - 0x%x", | ||
| 204 | status); | ||
| 205 | goto done; | ||
| 206 | } | ||
| 207 | |||
| 208 | pboardobjgrp = &g->clk_pmu.clk_domainobjs.super.super; | ||
| 209 | pclkdomainobjs = &(g->clk_pmu.clk_domainobjs); | ||
| 210 | |||
| 211 | BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, CLK, CLK_DOMAIN); | ||
| 212 | |||
| 213 | status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp, | ||
| 214 | clk, CLK, clk_domain, CLK_DOMAIN); | ||
| 215 | if (status) { | ||
| 216 | nvgpu_err(g, | ||
| 217 | "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x", | ||
| 218 | status); | ||
| 219 | goto done; | ||
| 220 | } | ||
| 221 | |||
| 222 | pboardobjgrp->pmudatainit = _clk_domains_pmudatainit_3x; | ||
| 223 | pboardobjgrp->pmudatainstget = _clk_domains_pmudata_instget; | ||
| 224 | |||
| 225 | /* Initialize mask to zero.*/ | ||
| 226 | boardobjgrpmask_e32_init(&pclkdomainobjs->prog_domains_mask, NULL); | ||
| 227 | boardobjgrpmask_e32_init(&pclkdomainobjs->master_domains_mask, NULL); | ||
| 228 | pclkdomainobjs->b_enforce_vf_monotonicity = true; | ||
| 229 | pclkdomainobjs->b_enforce_vf_smoothening = true; | ||
| 230 | |||
| 231 | memset(&pclkdomainobjs->ordered_noise_aware_list, 0, | ||
| 232 | sizeof(pclkdomainobjs->ordered_noise_aware_list)); | ||
| 233 | |||
| 234 | memset(&pclkdomainobjs->ordered_noise_unaware_list, 0, | ||
| 235 | sizeof(pclkdomainobjs->ordered_noise_unaware_list)); | ||
| 236 | |||
| 237 | memset(&pclkdomainobjs->deltas, 0, | ||
| 238 | sizeof(struct ctrl_clk_clk_delta)); | ||
| 239 | |||
| 240 | status = devinit_get_clocks_table(g, pclkdomainobjs); | ||
| 241 | if (status) { | ||
| 242 | goto done; | ||
| 243 | } | ||
| 244 | |||
| 245 | BOARDOBJGRP_FOR_EACH(&(pclkdomainobjs->super.super), | ||
| 246 | struct clk_domain *, pdomain, i) { | ||
| 247 | pdomain_master = NULL; | ||
| 248 | if (pdomain->super.implements(g, &pdomain->super, | ||
| 249 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_PROG)) { | ||
| 250 | status = boardobjgrpmask_bitset( | ||
| 251 | &pclkdomainobjs->prog_domains_mask.super, i); | ||
| 252 | if (status) { | ||
| 253 | goto done; | ||
| 254 | } | ||
| 255 | } | ||
| 256 | |||
| 257 | if (pdomain->super.implements(g, &pdomain->super, | ||
| 258 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER)) { | ||
| 259 | status = boardobjgrpmask_bitset( | ||
| 260 | &pclkdomainobjs->master_domains_mask.super, i); | ||
| 261 | if (status) { | ||
| 262 | goto done; | ||
| 263 | } | ||
| 264 | } | ||
| 265 | |||
| 266 | if (pdomain->super.implements(g, &pdomain->super, | ||
| 267 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE)) { | ||
| 268 | pdomain_slave = | ||
| 269 | (struct clk_domain_3x_slave *)pdomain; | ||
| 270 | pdomain_master = | ||
| 271 | (struct clk_domain_3x_master *) | ||
| 272 | (CLK_CLK_DOMAIN_GET((&g->clk_pmu), | ||
| 273 | pdomain_slave->master_idx)); | ||
| 274 | pdomain_master->slave_idxs_mask |= BIT(i); | ||
| 275 | } | ||
| 276 | |||
| 277 | } | ||
| 278 | |||
| 279 | done: | ||
| 280 | nvgpu_log_info(g, " done status %x", status); | ||
| 281 | return status; | ||
| 282 | } | ||
| 283 | |||
| 284 | int clk_domain_pmu_setup(struct gk20a *g) | ||
| 285 | { | ||
| 286 | int status; | ||
| 287 | struct boardobjgrp *pboardobjgrp = NULL; | ||
| 288 | |||
| 289 | nvgpu_log_info(g, " "); | ||
| 290 | |||
| 291 | pboardobjgrp = &g->clk_pmu.clk_domainobjs.super.super; | ||
| 292 | |||
| 293 | if (!pboardobjgrp->bconstructed) { | ||
| 294 | return -EINVAL; | ||
| 295 | } | ||
| 296 | |||
| 297 | status = pboardobjgrp->pmuinithandle(g, pboardobjgrp); | ||
| 298 | |||
| 299 | nvgpu_log_info(g, "Done"); | ||
| 300 | return status; | ||
| 301 | } | ||
| 302 | |||
| 303 | static int devinit_get_clocks_table_35(struct gk20a *g, | ||
| 304 | struct clk_domains *pclkdomainobjs, u8 *clocks_table_ptr) | ||
| 305 | { | ||
| 306 | int status = 0; | ||
| 307 | struct vbios_clocks_table_35_header clocks_table_header = { 0 }; | ||
| 308 | struct vbios_clocks_table_35_entry clocks_table_entry = { 0 }; | ||
| 309 | struct vbios_clocks_table_1x_hal_clock_entry *vbiosclktbl1xhalentry; | ||
| 310 | u8 *clocks_tbl_entry_ptr = NULL; | ||
| 311 | u32 index = 0; | ||
| 312 | struct clk_domain *pclkdomain_dev; | ||
| 313 | union { | ||
| 314 | struct boardobj boardobj; | ||
| 315 | struct clk_domain clk_domain; | ||
| 316 | struct clk_domain_3x v3x; | ||
| 317 | struct clk_domain_3x_fixed v3x_fixed; | ||
| 318 | struct clk_domain_35_prog v35_prog; | ||
| 319 | struct clk_domain_35_master v35_master; | ||
| 320 | struct clk_domain_35_slave v35_slave; | ||
| 321 | } clk_domain_data; | ||
| 322 | |||
| 323 | nvgpu_log_info(g, " "); | ||
| 324 | |||
| 325 | memcpy(&clocks_table_header, clocks_table_ptr, | ||
| 326 | VBIOS_CLOCKS_TABLE_35_HEADER_SIZE_09); | ||
| 327 | if (clocks_table_header.header_size < | ||
| 328 | (u8) VBIOS_CLOCKS_TABLE_35_HEADER_SIZE_09) { | ||
| 329 | status = -EINVAL; | ||
| 330 | goto done; | ||
| 331 | } | ||
| 332 | |||
| 333 | if (clocks_table_header.entry_size < | ||
| 334 | (u8) VBIOS_CLOCKS_TABLE_35_ENTRY_SIZE_11) { | ||
| 335 | status = -EINVAL; | ||
| 336 | goto done; | ||
| 337 | } | ||
| 338 | |||
| 339 | switch (clocks_table_header.clocks_hal) { | ||
| 340 | case CLK_TABLE_HAL_ENTRY_GP: | ||
| 341 | { | ||
| 342 | vbiosclktbl1xhalentry = vbiosclktbl1xhalentry_gp; | ||
| 343 | break; | ||
| 344 | } | ||
| 345 | case CLK_TABLE_HAL_ENTRY_GV: | ||
| 346 | { | ||
| 347 | vbiosclktbl1xhalentry = vbiosclktbl1xhalentry_gv; | ||
| 348 | break; | ||
| 349 | } | ||
| 350 | default: | ||
| 351 | { | ||
| 352 | status = -EINVAL; | ||
| 353 | goto done; | ||
| 354 | } | ||
| 355 | } | ||
| 356 | |||
| 357 | pclkdomainobjs->cntr_sampling_periodms = | ||
| 358 | (u16)clocks_table_header.cntr_sampling_periodms; | ||
| 359 | |||
| 360 | /* Read table entries*/ | ||
| 361 | clocks_tbl_entry_ptr = clocks_table_ptr + | ||
| 362 | clocks_table_header.header_size; | ||
| 363 | for (index = 0; index < clocks_table_header.entry_count; index++) { | ||
| 364 | memcpy((void*) &clocks_table_entry, (void*) clocks_tbl_entry_ptr, | ||
| 365 | clocks_table_header.entry_size); | ||
| 366 | clk_domain_data.clk_domain.domain = | ||
| 367 | (u8) vbiosclktbl1xhalentry[index].domain; | ||
| 368 | clk_domain_data.clk_domain.api_domain = | ||
| 369 | clktranslatehalmumsettoapinumset( | ||
| 370 | (u32) BIT(clk_domain_data.clk_domain.domain)); | ||
| 371 | clk_domain_data.v3x.b_noise_aware_capable = | ||
| 372 | vbiosclktbl1xhalentry[index].b_noise_aware_capable; | ||
| 373 | |||
| 374 | switch (BIOS_GET_FIELD(clocks_table_entry.flags0, | ||
| 375 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE)) { | ||
| 376 | case NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE_FIXED: | ||
| 377 | { | ||
| 378 | clk_domain_data.boardobj.type = | ||
| 379 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_FIXED; | ||
| 380 | clk_domain_data.v3x_fixed.freq_mhz = (u16)BIOS_GET_FIELD( | ||
| 381 | clocks_table_entry.param1, | ||
| 382 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_FIXED_FREQUENCY_MHZ); | ||
| 383 | break; | ||
| 384 | } | ||
| 385 | |||
| 386 | case NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE_MASTER: | ||
| 387 | { | ||
| 388 | clk_domain_data.boardobj.type = | ||
| 389 | CTRL_CLK_CLK_DOMAIN_TYPE_35_MASTER; | ||
| 390 | clk_domain_data.v35_prog.super.clk_prog_idx_first = | ||
| 391 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param0, | ||
| 392 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_FIRST)); | ||
| 393 | clk_domain_data.v35_prog.super.clk_prog_idx_last = | ||
| 394 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param0, | ||
| 395 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_LAST)); | ||
| 396 | clk_domain_data.v35_prog.super.noise_unaware_ordering_index = | ||
| 397 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
| 398 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_NOISE_UNAWARE_ORDERING_IDX)); | ||
| 399 | if (clk_domain_data.v3x.b_noise_aware_capable) { | ||
| 400 | clk_domain_data.v35_prog.super.b_force_noise_unaware_ordering = | ||
| 401 | (bool)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
| 402 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_FORCE_NOISE_UNAWARE_ORDERING)); | ||
| 403 | |||
| 404 | } else { | ||
| 405 | clk_domain_data.v35_prog.super.noise_aware_ordering_index = | ||
| 406 | CTRL_CLK_CLK_DOMAIN_3X_PROG_ORDERING_INDEX_INVALID; | ||
| 407 | clk_domain_data.v35_prog.super.b_force_noise_unaware_ordering = false; | ||
| 408 | } | ||
| 409 | clk_domain_data.v35_prog.pre_volt_ordering_index = | ||
| 410 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
| 411 | NV_VBIOS_CLOCKS_TABLE_35_ENTRY_PARAM2_PROG_PRE_VOLT_ORDERING_IDX)); | ||
| 412 | |||
| 413 | clk_domain_data.v35_prog.post_volt_ordering_index = | ||
| 414 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
| 415 | NV_VBIOS_CLOCKS_TABLE_35_ENTRY_PARAM2_PROG_POST_VOLT_ORDERING_IDX)); | ||
| 416 | |||
| 417 | clk_domain_data.v35_prog.super.factory_delta.data.delta_khz = 0; | ||
| 418 | clk_domain_data.v35_prog.super.factory_delta.type = 0; | ||
| 419 | |||
| 420 | clk_domain_data.v35_prog.super.freq_delta_min_mhz = | ||
| 421 | (u16)(BIOS_GET_FIELD(clocks_table_entry.param1, | ||
| 422 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_MASTER_FREQ_OC_DELTA_MIN_MHZ)); | ||
| 423 | |||
| 424 | clk_domain_data.v35_prog.super.freq_delta_max_mhz = | ||
| 425 | (u16)(BIOS_GET_FIELD(clocks_table_entry.param1, | ||
| 426 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_MASTER_FREQ_OC_DELTA_MAX_MHZ)); | ||
| 427 | clk_domain_data.v35_prog.clk_vf_curve_count = | ||
| 428 | vbiosclktbl1xhalentry[index].clk_vf_curve_count; | ||
| 429 | break; | ||
| 430 | } | ||
| 431 | |||
| 432 | case NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE_SLAVE: | ||
| 433 | { | ||
| 434 | clk_domain_data.boardobj.type = | ||
| 435 | CTRL_CLK_CLK_DOMAIN_TYPE_35_SLAVE; | ||
| 436 | clk_domain_data.v35_prog.super.clk_prog_idx_first = | ||
| 437 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param0, | ||
| 438 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_FIRST)); | ||
| 439 | clk_domain_data.v35_prog.super.clk_prog_idx_last = | ||
| 440 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param0, | ||
| 441 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_LAST)); | ||
| 442 | clk_domain_data.v35_prog.super.noise_unaware_ordering_index = | ||
| 443 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
| 444 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_NOISE_UNAWARE_ORDERING_IDX)); | ||
| 445 | |||
| 446 | if (clk_domain_data.v3x.b_noise_aware_capable) { | ||
| 447 | clk_domain_data.v35_prog.super.b_force_noise_unaware_ordering = | ||
| 448 | (bool)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
| 449 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_FORCE_NOISE_UNAWARE_ORDERING)); | ||
| 450 | |||
| 451 | } else { | ||
| 452 | clk_domain_data.v35_prog.super.noise_aware_ordering_index = | ||
| 453 | CTRL_CLK_CLK_DOMAIN_3X_PROG_ORDERING_INDEX_INVALID; | ||
| 454 | clk_domain_data.v35_prog.super.b_force_noise_unaware_ordering = false; | ||
| 455 | } | ||
| 456 | clk_domain_data.v35_prog.pre_volt_ordering_index = | ||
| 457 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
| 458 | NV_VBIOS_CLOCKS_TABLE_35_ENTRY_PARAM2_PROG_PRE_VOLT_ORDERING_IDX)); | ||
| 459 | |||
| 460 | clk_domain_data.v35_prog.post_volt_ordering_index = | ||
| 461 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
| 462 | NV_VBIOS_CLOCKS_TABLE_35_ENTRY_PARAM2_PROG_POST_VOLT_ORDERING_IDX)); | ||
| 463 | |||
| 464 | clk_domain_data.v35_prog.super.factory_delta.data.delta_khz = 0; | ||
| 465 | clk_domain_data.v35_prog.super.factory_delta.type = 0; | ||
| 466 | clk_domain_data.v35_prog.super.freq_delta_min_mhz = 0; | ||
| 467 | clk_domain_data.v35_prog.super.freq_delta_max_mhz = 0; | ||
| 468 | clk_domain_data.v35_slave.slave.master_idx = | ||
| 469 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param1, | ||
| 470 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_SLAVE_MASTER_DOMAIN)); | ||
| 471 | break; | ||
| 472 | } | ||
| 473 | |||
| 474 | default: | ||
| 475 | { | ||
| 476 | nvgpu_err(g, | ||
| 477 | "error reading clock domain entry %d", index); | ||
| 478 | status = -EINVAL; | ||
| 479 | goto done; | ||
| 480 | } | ||
| 481 | |||
| 482 | } | ||
| 483 | pclkdomain_dev = construct_clk_domain(g, | ||
| 484 | (void *)&clk_domain_data); | ||
| 485 | if (pclkdomain_dev == NULL) { | ||
| 486 | nvgpu_err(g, | ||
| 487 | "unable to construct clock domain boardobj for %d", | ||
| 488 | index); | ||
| 489 | status = -EINVAL; | ||
| 490 | goto done; | ||
| 491 | } | ||
| 492 | status = boardobjgrp_objinsert( | ||
| 493 | &pclkdomainobjs->super.super, | ||
| 494 | (struct boardobj *)(void*) pclkdomain_dev, index); | ||
| 495 | if (status != 0UL) { | ||
| 496 | nvgpu_err(g, | ||
| 497 | "unable to insert clock domain boardobj for %d", index); | ||
| 498 | status = (u32) -EINVAL; | ||
| 499 | goto done; | ||
| 500 | } | ||
| 501 | clocks_tbl_entry_ptr += clocks_table_header.entry_size; | ||
| 502 | } | ||
| 503 | |||
| 504 | done: | ||
| 505 | nvgpu_log_info(g, " done status %x", status); | ||
| 506 | return status; | ||
| 507 | } | ||
| 508 | |||
| 509 | static int devinit_get_clocks_table_1x(struct gk20a *g, | ||
| 510 | struct clk_domains *pclkdomainobjs, u8 *clocks_table_ptr) | ||
| 511 | { | ||
| 512 | int status = 0; | ||
| 513 | struct vbios_clocks_table_1x_header clocks_table_header = { 0 }; | ||
| 514 | struct vbios_clocks_table_1x_entry clocks_table_entry = { 0 }; | ||
| 515 | struct vbios_clocks_table_1x_hal_clock_entry *vbiosclktbl1xhalentry; | ||
| 516 | u8 *clocks_tbl_entry_ptr = NULL; | ||
| 517 | u32 index = 0; | ||
| 518 | struct clk_domain *pclkdomain_dev; | ||
| 519 | union { | ||
| 520 | struct boardobj boardobj; | ||
| 521 | struct clk_domain clk_domain; | ||
| 522 | struct clk_domain_3x v3x; | ||
| 523 | struct clk_domain_3x_fixed v3x_fixed; | ||
| 524 | struct clk_domain_3x_prog v3x_prog; | ||
| 525 | struct clk_domain_3x_master v3x_master; | ||
| 526 | struct clk_domain_3x_slave v3x_slave; | ||
| 527 | } clk_domain_data; | ||
| 528 | |||
| 529 | nvgpu_log_info(g, " "); | ||
| 530 | |||
| 531 | memcpy(&clocks_table_header, clocks_table_ptr, | ||
| 532 | VBIOS_CLOCKS_TABLE_1X_HEADER_SIZE_07); | ||
| 533 | if (clocks_table_header.header_size < | ||
| 534 | (u8) VBIOS_CLOCKS_TABLE_1X_HEADER_SIZE_07) { | ||
| 535 | status = -EINVAL; | ||
| 536 | goto done; | ||
| 537 | } | ||
| 538 | |||
| 539 | if (clocks_table_header.entry_size < | ||
| 540 | (u8) VBIOS_CLOCKS_TABLE_1X_ENTRY_SIZE_09) { | ||
| 541 | status = -EINVAL; | ||
| 542 | goto done; | ||
| 543 | } | ||
| 544 | |||
| 545 | switch (clocks_table_header.clocks_hal) { | ||
| 546 | case CLK_TABLE_HAL_ENTRY_GP: | ||
| 547 | { | ||
| 548 | vbiosclktbl1xhalentry = vbiosclktbl1xhalentry_gp; | ||
| 549 | break; | ||
| 550 | } | ||
| 551 | case CLK_TABLE_HAL_ENTRY_GV: | ||
| 552 | { | ||
| 553 | vbiosclktbl1xhalentry = vbiosclktbl1xhalentry_gv; | ||
| 554 | break; | ||
| 555 | } | ||
| 556 | default: | ||
| 557 | { | ||
| 558 | status = -EINVAL; | ||
| 559 | goto done; | ||
| 560 | } | ||
| 561 | } | ||
| 562 | |||
| 563 | pclkdomainobjs->cntr_sampling_periodms = | ||
| 564 | (u16)clocks_table_header.cntr_sampling_periodms; | ||
| 565 | |||
| 566 | /* Read table entries*/ | ||
| 567 | clocks_tbl_entry_ptr = clocks_table_ptr + | ||
| 568 | VBIOS_CLOCKS_TABLE_1X_HEADER_SIZE_07; | ||
| 569 | for (index = 0; index < clocks_table_header.entry_count; index++) { | ||
| 570 | memcpy((void*) &clocks_table_entry, (void*) clocks_tbl_entry_ptr, | ||
| 571 | clocks_table_header.entry_size); | ||
| 572 | clk_domain_data.clk_domain.domain = | ||
| 573 | (u8) vbiosclktbl1xhalentry[index].domain; | ||
| 574 | clk_domain_data.clk_domain.api_domain = | ||
| 575 | clktranslatehalmumsettoapinumset( | ||
| 576 | BIT(clk_domain_data.clk_domain.domain)); | ||
| 577 | clk_domain_data.v3x.b_noise_aware_capable = | ||
| 578 | vbiosclktbl1xhalentry[index].b_noise_aware_capable; | ||
| 579 | |||
| 580 | switch (BIOS_GET_FIELD(clocks_table_entry.flags0, | ||
| 581 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE)) { | ||
| 582 | case NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE_FIXED: | ||
| 583 | { | ||
| 584 | clk_domain_data.boardobj.type = | ||
| 585 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_FIXED; | ||
| 586 | clk_domain_data.v3x_fixed.freq_mhz = (u16)BIOS_GET_FIELD( | ||
| 587 | clocks_table_entry.param1, | ||
| 588 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_FIXED_FREQUENCY_MHZ); | ||
| 589 | break; | ||
| 590 | } | ||
| 591 | |||
| 592 | case NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE_MASTER: | ||
| 593 | { | ||
| 594 | clk_domain_data.boardobj.type = | ||
| 595 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER; | ||
| 596 | clk_domain_data.v3x_prog.clk_prog_idx_first = | ||
| 597 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param0, | ||
| 598 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_FIRST)); | ||
| 599 | clk_domain_data.v3x_prog.clk_prog_idx_last = | ||
| 600 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param0, | ||
| 601 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_LAST)); | ||
| 602 | clk_domain_data.v3x_prog.noise_unaware_ordering_index = | ||
| 603 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
| 604 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_NOISE_UNAWARE_ORDERING_IDX)); | ||
| 605 | if (clk_domain_data.v3x.b_noise_aware_capable) { | ||
| 606 | clk_domain_data.v3x_prog.noise_aware_ordering_index = | ||
| 607 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
| 608 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_NOISE_AWARE_ORDERING_IDX)); | ||
| 609 | clk_domain_data.v3x_prog.b_force_noise_unaware_ordering = | ||
| 610 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
| 611 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_FORCE_NOISE_UNAWARE_ORDERING)); | ||
| 612 | } else { | ||
| 613 | clk_domain_data.v3x_prog.noise_aware_ordering_index = | ||
| 614 | CTRL_CLK_CLK_DOMAIN_3X_PROG_ORDERING_INDEX_INVALID; | ||
| 615 | clk_domain_data.v3x_prog.b_force_noise_unaware_ordering = false; | ||
| 616 | } | ||
| 617 | |||
| 618 | clk_domain_data.v3x_prog.factory_delta.data.delta_khz = 0; | ||
| 619 | clk_domain_data.v3x_prog.factory_delta.type = 0; | ||
| 620 | |||
| 621 | clk_domain_data.v3x_prog.freq_delta_min_mhz = | ||
| 622 | (u16)(BIOS_GET_FIELD(clocks_table_entry.param1, | ||
| 623 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_MASTER_FREQ_OC_DELTA_MIN_MHZ)); | ||
| 624 | |||
| 625 | clk_domain_data.v3x_prog.freq_delta_max_mhz = | ||
| 626 | (u16)(BIOS_GET_FIELD(clocks_table_entry.param1, | ||
| 627 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_MASTER_FREQ_OC_DELTA_MAX_MHZ)); | ||
| 628 | break; | ||
| 629 | } | ||
| 630 | |||
| 631 | case NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE_SLAVE: | ||
| 632 | { | ||
| 633 | clk_domain_data.boardobj.type = | ||
| 634 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE; | ||
| 635 | clk_domain_data.v3x_prog.clk_prog_idx_first = | ||
| 636 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param0, | ||
| 637 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_FIRST)); | ||
| 638 | clk_domain_data.v3x_prog.clk_prog_idx_last = | ||
| 639 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param0, | ||
| 640 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_LAST)); | ||
| 641 | clk_domain_data.v3x_prog.noise_unaware_ordering_index = | ||
| 642 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
| 643 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_NOISE_UNAWARE_ORDERING_IDX)); | ||
| 644 | |||
| 645 | if (clk_domain_data.v3x.b_noise_aware_capable) { | ||
| 646 | clk_domain_data.v3x_prog.noise_aware_ordering_index = | ||
| 647 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
| 648 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_NOISE_AWARE_ORDERING_IDX)); | ||
| 649 | clk_domain_data.v3x_prog.b_force_noise_unaware_ordering = | ||
| 650 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
| 651 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_FORCE_NOISE_UNAWARE_ORDERING)); | ||
| 652 | } else { | ||
| 653 | clk_domain_data.v3x_prog.noise_aware_ordering_index = | ||
| 654 | CTRL_CLK_CLK_DOMAIN_3X_PROG_ORDERING_INDEX_INVALID; | ||
| 655 | clk_domain_data.v3x_prog.b_force_noise_unaware_ordering = false; | ||
| 656 | } | ||
| 657 | clk_domain_data.v3x_prog.factory_delta.data.delta_khz = 0; | ||
| 658 | clk_domain_data.v3x_prog.factory_delta.type = 0; | ||
| 659 | clk_domain_data.v3x_prog.freq_delta_min_mhz = 0; | ||
| 660 | clk_domain_data.v3x_prog.freq_delta_max_mhz = 0; | ||
| 661 | clk_domain_data.v3x_slave.master_idx = | ||
| 662 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param1, | ||
| 663 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_SLAVE_MASTER_DOMAIN)); | ||
| 664 | break; | ||
| 665 | } | ||
| 666 | |||
| 667 | default: | ||
| 668 | { | ||
| 669 | nvgpu_err(g, | ||
| 670 | "error reading clock domain entry %d", index); | ||
| 671 | status = (u32) -EINVAL; | ||
| 672 | goto done; | ||
| 673 | } | ||
| 674 | |||
| 675 | } | ||
| 676 | pclkdomain_dev = construct_clk_domain(g, | ||
| 677 | (void *)&clk_domain_data); | ||
| 678 | if (pclkdomain_dev == NULL) { | ||
| 679 | nvgpu_err(g, | ||
| 680 | "unable to construct clock domain boardobj for %d", | ||
| 681 | index); | ||
| 682 | status = (u32) -EINVAL; | ||
| 683 | goto done; | ||
| 684 | } | ||
| 685 | status = boardobjgrp_objinsert(&pclkdomainobjs->super.super, | ||
| 686 | (struct boardobj *)(void *)pclkdomain_dev, index); | ||
| 687 | if (status != 0UL) { | ||
| 688 | nvgpu_err(g, | ||
| 689 | "unable to insert clock domain boardobj for %d", index); | ||
| 690 | status = (u32) -EINVAL; | ||
| 691 | goto done; | ||
| 692 | } | ||
| 693 | clocks_tbl_entry_ptr += clocks_table_header.entry_size; | ||
| 694 | } | ||
| 695 | |||
| 696 | done: | ||
| 697 | nvgpu_log_info(g, " done status %x", status); | ||
| 698 | return status; | ||
| 699 | } | ||
| 700 | |||
| 701 | static int devinit_get_clocks_table(struct gk20a *g, | ||
| 702 | struct clk_domains *pclkdomainobjs) | ||
| 703 | { | ||
| 704 | int status = 0; | ||
| 705 | u8 *clocks_table_ptr = NULL; | ||
| 706 | struct vbios_clocks_table_1x_header clocks_table_header = { 0 }; | ||
| 707 | nvgpu_log_info(g, " "); | ||
| 708 | |||
| 709 | clocks_table_ptr = (u8 *)nvgpu_bios_get_perf_table_ptrs(g, | ||
| 710 | g->bios.clock_token, CLOCKS_TABLE); | ||
| 711 | if (clocks_table_ptr == NULL) { | ||
| 712 | status = -EINVAL; | ||
| 713 | goto done; | ||
| 714 | } | ||
| 715 | memcpy(&clocks_table_header, clocks_table_ptr, | ||
| 716 | VBIOS_CLOCKS_TABLE_1X_HEADER_SIZE_07); | ||
| 717 | if (clocks_table_header.version == 0x35U) { | ||
| 718 | devinit_get_clocks_table_35(g, pclkdomainobjs, clocks_table_ptr); | ||
| 719 | } | ||
| 720 | else { | ||
| 721 | devinit_get_clocks_table_1x(g, pclkdomainobjs, clocks_table_ptr); | ||
| 722 | } | ||
| 723 | done: | ||
| 724 | return status; | ||
| 725 | |||
| 726 | } | ||
| 727 | |||
| 728 | static int clkdomainclkproglink_not_supported(struct gk20a *g, | ||
| 729 | struct clk_pmupstate *pclk, | ||
| 730 | struct clk_domain *pdomain) | ||
| 731 | { | ||
| 732 | nvgpu_log_info(g, " "); | ||
| 733 | return -EINVAL; | ||
| 734 | } | ||
| 735 | |||
| 736 | static int clkdomainvfsearch_stub( | ||
| 737 | struct gk20a *g, | ||
| 738 | struct clk_pmupstate *pclk, | ||
| 739 | struct clk_domain *pdomain, | ||
| 740 | u16 *clkmhz, | ||
| 741 | u32 *voltuv, | ||
| 742 | u8 rail) | ||
| 743 | |||
| 744 | { | ||
| 745 | nvgpu_log_info(g, " "); | ||
| 746 | return -EINVAL; | ||
| 747 | } | ||
| 748 | |||
| 749 | static u32 clkdomaingetfpoints_stub( | ||
| 750 | struct gk20a *g, | ||
| 751 | struct clk_pmupstate *pclk, | ||
| 752 | struct clk_domain *pdomain, | ||
| 753 | u32 *pfpointscount, | ||
| 754 | u16 *pfreqpointsinmhz, | ||
| 755 | u8 rail) | ||
| 756 | { | ||
| 757 | nvgpu_log_info(g, " "); | ||
| 758 | return -EINVAL; | ||
| 759 | } | ||
| 760 | |||
| 761 | |||
| 762 | static int clk_domain_construct_super(struct gk20a *g, | ||
| 763 | struct boardobj **ppboardobj, | ||
| 764 | u16 size, void *pargs) | ||
| 765 | { | ||
| 766 | struct clk_domain *pdomain; | ||
| 767 | struct clk_domain *ptmpdomain = (struct clk_domain *)pargs; | ||
| 768 | int status = 0; | ||
| 769 | |||
| 770 | status = boardobj_construct_super(g, ppboardobj, | ||
| 771 | size, pargs); | ||
| 772 | |||
| 773 | if (status) { | ||
| 774 | return -EINVAL; | ||
| 775 | } | ||
| 776 | |||
| 777 | pdomain = (struct clk_domain *)*ppboardobj; | ||
| 778 | |||
| 779 | pdomain->super.pmudatainit = | ||
| 780 | clk_domain_pmudatainit_super; | ||
| 781 | |||
| 782 | pdomain->clkdomainclkproglink = | ||
| 783 | clkdomainclkproglink_not_supported; | ||
| 784 | |||
| 785 | pdomain->clkdomainclkvfsearch = | ||
| 786 | clkdomainvfsearch_stub; | ||
| 787 | |||
| 788 | pdomain->clkdomainclkgetfpoints = | ||
| 789 | clkdomaingetfpoints_stub; | ||
| 790 | |||
| 791 | pdomain->api_domain = ptmpdomain->api_domain; | ||
| 792 | pdomain->domain = ptmpdomain->domain; | ||
| 793 | pdomain->perf_domain_grp_idx = | ||
| 794 | ptmpdomain->perf_domain_grp_idx; | ||
| 795 | |||
| 796 | return status; | ||
| 797 | } | ||
| 798 | |||
| 799 | static int _clk_domain_pmudatainit_3x(struct gk20a *g, | ||
| 800 | struct boardobj *board_obj_ptr, | ||
| 801 | struct nv_pmu_boardobj *ppmudata) | ||
| 802 | { | ||
| 803 | int status = 0; | ||
| 804 | struct clk_domain_3x *pclk_domain_3x; | ||
| 805 | struct nv_pmu_clk_clk_domain_3x_boardobj_set *pset; | ||
| 806 | |||
| 807 | nvgpu_log_info(g, " "); | ||
| 808 | |||
| 809 | status = clk_domain_pmudatainit_super(g, board_obj_ptr, ppmudata); | ||
| 810 | if (status != 0) { | ||
| 811 | return status; | ||
| 812 | } | ||
| 813 | |||
| 814 | pclk_domain_3x = (struct clk_domain_3x *)board_obj_ptr; | ||
| 815 | |||
| 816 | pset = (struct nv_pmu_clk_clk_domain_3x_boardobj_set *)ppmudata; | ||
| 817 | |||
| 818 | pset->b_noise_aware_capable = pclk_domain_3x->b_noise_aware_capable; | ||
| 819 | |||
| 820 | return status; | ||
| 821 | } | ||
| 822 | |||
| 823 | static int clk_domain_construct_3x(struct gk20a *g, | ||
| 824 | struct boardobj **ppboardobj, | ||
| 825 | u16 size, void *pargs) | ||
| 826 | { | ||
| 827 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
| 828 | struct clk_domain_3x *pdomain; | ||
| 829 | struct clk_domain_3x *ptmpdomain = | ||
| 830 | (struct clk_domain_3x *)pargs; | ||
| 831 | int status = 0; | ||
| 832 | |||
| 833 | ptmpobj->type_mask = BIT(CTRL_CLK_CLK_DOMAIN_TYPE_3X); | ||
| 834 | status = clk_domain_construct_super(g, ppboardobj, | ||
| 835 | size, pargs); | ||
| 836 | if (status) { | ||
| 837 | return -EINVAL; | ||
| 838 | } | ||
| 839 | |||
| 840 | pdomain = (struct clk_domain_3x *)*ppboardobj; | ||
| 841 | |||
| 842 | pdomain->super.super.pmudatainit = | ||
| 843 | _clk_domain_pmudatainit_3x; | ||
| 844 | |||
| 845 | pdomain->b_noise_aware_capable = ptmpdomain->b_noise_aware_capable; | ||
| 846 | |||
| 847 | return status; | ||
| 848 | } | ||
| 849 | |||
| 850 | static int clkdomainclkproglink_3x_prog(struct gk20a *g, | ||
| 851 | struct clk_pmupstate *pclk, | ||
| 852 | struct clk_domain *pdomain) | ||
| 853 | { | ||
| 854 | int status = 0; | ||
| 855 | struct clk_domain_3x_prog *p3xprog = | ||
| 856 | (struct clk_domain_3x_prog *)pdomain; | ||
| 857 | struct clk_prog *pprog = NULL; | ||
| 858 | u8 i; | ||
| 859 | |||
| 860 | nvgpu_log_info(g, " "); | ||
| 861 | |||
| 862 | for (i = p3xprog->clk_prog_idx_first; | ||
| 863 | i <= p3xprog->clk_prog_idx_last; | ||
| 864 | i++) { | ||
| 865 | pprog = CLK_CLK_PROG_GET(pclk, i); | ||
| 866 | if (pprog == NULL) { | ||
| 867 | status = -EINVAL; | ||
| 868 | } | ||
| 869 | } | ||
| 870 | return status; | ||
| 871 | } | ||
| 872 | |||
| 873 | static int clkdomaingetslaveclk(struct gk20a *g, | ||
| 874 | struct clk_pmupstate *pclk, | ||
| 875 | struct clk_domain *pdomain, | ||
| 876 | u16 *pclkmhz, | ||
| 877 | u16 masterclkmhz) | ||
| 878 | { | ||
| 879 | int status = 0; | ||
| 880 | struct clk_prog *pprog = NULL; | ||
| 881 | struct clk_prog_1x_master *pprog1xmaster = NULL; | ||
| 882 | u8 slaveidx; | ||
| 883 | struct clk_domain_3x_master *p3xmaster; | ||
| 884 | |||
| 885 | nvgpu_log_info(g, " "); | ||
| 886 | |||
| 887 | if (pclkmhz == NULL) { | ||
| 888 | return -EINVAL; | ||
| 889 | } | ||
| 890 | |||
| 891 | if (masterclkmhz == 0) { | ||
| 892 | return -EINVAL; | ||
| 893 | } | ||
| 894 | |||
| 895 | slaveidx = BOARDOBJ_GET_IDX(pdomain); | ||
| 896 | p3xmaster = (struct clk_domain_3x_master *) | ||
| 897 | CLK_CLK_DOMAIN_GET(pclk, | ||
| 898 | ((struct clk_domain_3x_slave *) | ||
| 899 | pdomain)->master_idx); | ||
| 900 | pprog = CLK_CLK_PROG_GET(pclk, p3xmaster->super.clk_prog_idx_first); | ||
| 901 | pprog1xmaster = (struct clk_prog_1x_master *)pprog; | ||
| 902 | |||
| 903 | status = pprog1xmaster->getslaveclk(g, pclk, pprog1xmaster, | ||
| 904 | slaveidx, pclkmhz, masterclkmhz); | ||
| 905 | return status; | ||
| 906 | } | ||
| 907 | |||
| 908 | static int clkdomainvfsearch(struct gk20a *g, | ||
| 909 | struct clk_pmupstate *pclk, | ||
| 910 | struct clk_domain *pdomain, | ||
| 911 | u16 *pclkmhz, | ||
| 912 | u32 *pvoltuv, | ||
| 913 | u8 rail) | ||
| 914 | { | ||
| 915 | int status = 0; | ||
| 916 | struct clk_domain_3x_master *p3xmaster = | ||
| 917 | (struct clk_domain_3x_master *)pdomain; | ||
| 918 | struct clk_prog *pprog = NULL; | ||
| 919 | struct clk_prog_1x_master *pprog1xmaster = NULL; | ||
| 920 | u8 i; | ||
| 921 | u8 *pslaveidx = NULL; | ||
| 922 | u8 slaveidx; | ||
| 923 | u16 clkmhz; | ||
| 924 | u32 voltuv; | ||
| 925 | u16 bestclkmhz; | ||
| 926 | u32 bestvoltuv; | ||
| 927 | |||
| 928 | nvgpu_log_info(g, " "); | ||
| 929 | |||
| 930 | if ((pclkmhz == NULL) || (pvoltuv == NULL)) { | ||
| 931 | return -EINVAL; | ||
| 932 | } | ||
| 933 | |||
| 934 | if ((*pclkmhz != 0) && (*pvoltuv != 0)) { | ||
| 935 | return -EINVAL; | ||
| 936 | } | ||
| 937 | |||
| 938 | bestclkmhz = *pclkmhz; | ||
| 939 | bestvoltuv = *pvoltuv; | ||
| 940 | |||
| 941 | if (pdomain->super.implements(g, &pdomain->super, | ||
| 942 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE)) { | ||
| 943 | slaveidx = BOARDOBJ_GET_IDX(pdomain); | ||
| 944 | pslaveidx = &slaveidx; | ||
| 945 | p3xmaster = (struct clk_domain_3x_master *) | ||
| 946 | CLK_CLK_DOMAIN_GET(pclk, | ||
| 947 | ((struct clk_domain_3x_slave *) | ||
| 948 | pdomain)->master_idx); | ||
| 949 | } | ||
| 950 | /* Iterate over the set of CLK_PROGs pointed at by this domain.*/ | ||
| 951 | for (i = p3xmaster->super.clk_prog_idx_first; | ||
| 952 | i <= p3xmaster->super.clk_prog_idx_last; | ||
| 953 | i++) { | ||
| 954 | clkmhz = *pclkmhz; | ||
| 955 | voltuv = *pvoltuv; | ||
| 956 | pprog = CLK_CLK_PROG_GET(pclk, i); | ||
| 957 | |||
| 958 | /* MASTER CLK_DOMAINs must point to MASTER CLK_PROGs.*/ | ||
| 959 | if (!pprog->super.implements(g, &pprog->super, | ||
| 960 | CTRL_CLK_CLK_PROG_TYPE_1X_MASTER)) { | ||
| 961 | status = -EINVAL; | ||
| 962 | goto done; | ||
| 963 | } | ||
| 964 | |||
| 965 | pprog1xmaster = (struct clk_prog_1x_master *)pprog; | ||
| 966 | status = pprog1xmaster->vflookup(g, pclk, pprog1xmaster, | ||
| 967 | pslaveidx, &clkmhz, &voltuv, rail); | ||
| 968 | /* if look up has found the V or F value matching to other | ||
| 969 | exit */ | ||
| 970 | if (status == 0) { | ||
| 971 | if (*pclkmhz == 0) { | ||
| 972 | bestclkmhz = clkmhz; | ||
| 973 | } else { | ||
| 974 | bestvoltuv = voltuv; | ||
| 975 | break; | ||
| 976 | } | ||
| 977 | } | ||
| 978 | } | ||
| 979 | /* clk and volt sent as zero to print vf table */ | ||
| 980 | if ((*pclkmhz == 0) && (*pvoltuv == 0)) { | ||
| 981 | status = 0; | ||
| 982 | goto done; | ||
| 983 | } | ||
| 984 | /* atleast one search found a matching value? */ | ||
| 985 | if ((bestvoltuv != 0) && (bestclkmhz != 0)) { | ||
| 986 | *pclkmhz = bestclkmhz; | ||
| 987 | *pvoltuv = bestvoltuv; | ||
| 988 | status = 0; | ||
| 989 | goto done; | ||
| 990 | } | ||
| 991 | done: | ||
| 992 | nvgpu_log_info(g, "done status %x", status); | ||
| 993 | return status; | ||
| 994 | } | ||
| 995 | |||
| 996 | static u32 clkdomaingetfpoints | ||
| 997 | ( | ||
| 998 | struct gk20a *g, | ||
| 999 | struct clk_pmupstate *pclk, | ||
| 1000 | struct clk_domain *pdomain, | ||
| 1001 | u32 *pfpointscount, | ||
| 1002 | u16 *pfreqpointsinmhz, | ||
| 1003 | u8 rail | ||
| 1004 | ) | ||
| 1005 | { | ||
| 1006 | u32 status = 0; | ||
| 1007 | struct clk_domain_3x_master *p3xmaster = | ||
| 1008 | (struct clk_domain_3x_master *)pdomain; | ||
| 1009 | struct clk_prog *pprog = NULL; | ||
| 1010 | struct clk_prog_1x_master *pprog1xmaster = NULL; | ||
| 1011 | u32 fpointscount = 0; | ||
| 1012 | u32 remainingcount; | ||
| 1013 | u32 totalcount; | ||
| 1014 | u16 *freqpointsdata; | ||
| 1015 | u8 i; | ||
| 1016 | |||
| 1017 | nvgpu_log_info(g, " "); | ||
| 1018 | |||
| 1019 | if (pfpointscount == NULL) { | ||
| 1020 | return -EINVAL; | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | if ((pfreqpointsinmhz == NULL) && (*pfpointscount != 0)) { | ||
| 1024 | return -EINVAL; | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | if (pdomain->super.implements(g, &pdomain->super, | ||
| 1028 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE)) { | ||
| 1029 | return -EINVAL; | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | freqpointsdata = pfreqpointsinmhz; | ||
| 1033 | totalcount = 0; | ||
| 1034 | fpointscount = *pfpointscount; | ||
| 1035 | remainingcount = fpointscount; | ||
| 1036 | /* Iterate over the set of CLK_PROGs pointed at by this domain.*/ | ||
| 1037 | for (i = p3xmaster->super.clk_prog_idx_first; | ||
| 1038 | i <= p3xmaster->super.clk_prog_idx_last; | ||
| 1039 | i++) { | ||
| 1040 | pprog = CLK_CLK_PROG_GET(pclk, i); | ||
| 1041 | pprog1xmaster = (struct clk_prog_1x_master *)pprog; | ||
| 1042 | status = pprog1xmaster->getfpoints(g, pclk, pprog1xmaster, | ||
| 1043 | &fpointscount, &freqpointsdata, rail); | ||
| 1044 | if (status) { | ||
| 1045 | *pfpointscount = 0; | ||
| 1046 | goto done; | ||
| 1047 | } | ||
| 1048 | totalcount += fpointscount; | ||
| 1049 | if (*pfpointscount) { | ||
| 1050 | remainingcount -= fpointscount; | ||
| 1051 | fpointscount = remainingcount; | ||
| 1052 | } else { | ||
| 1053 | fpointscount = 0; | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | } | ||
| 1057 | |||
| 1058 | *pfpointscount = totalcount; | ||
| 1059 | done: | ||
| 1060 | nvgpu_log_info(g, "done status %x", status); | ||
| 1061 | return status; | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | static int clk_domain_pmudatainit_35_prog(struct gk20a *g, | ||
| 1065 | struct boardobj *board_obj_ptr, | ||
| 1066 | struct nv_pmu_boardobj *ppmudata) | ||
| 1067 | { | ||
| 1068 | int status = 0; | ||
| 1069 | struct clk_domain_35_prog *pclk_domain_35_prog; | ||
| 1070 | struct clk_domain_3x_prog *pclk_domain_3x_prog; | ||
| 1071 | struct nv_pmu_clk_clk_domain_35_prog_boardobj_set *pset; | ||
| 1072 | struct clk_domains *pdomains = &(g->clk_pmu.clk_domainobjs); | ||
| 1073 | |||
| 1074 | nvgpu_log_info(g, " "); | ||
| 1075 | |||
| 1076 | status = _clk_domain_pmudatainit_3x(g, board_obj_ptr, ppmudata); | ||
| 1077 | if (status != 0UL) { | ||
| 1078 | return status; | ||
| 1079 | } | ||
| 1080 | |||
| 1081 | pclk_domain_35_prog = (struct clk_domain_35_prog *)(void*)board_obj_ptr; | ||
| 1082 | pclk_domain_3x_prog = &pclk_domain_35_prog->super; | ||
| 1083 | |||
| 1084 | pset = (struct nv_pmu_clk_clk_domain_35_prog_boardobj_set *) | ||
| 1085 | (void*) ppmudata; | ||
| 1086 | |||
| 1087 | pset->super.clk_prog_idx_first = pclk_domain_3x_prog->clk_prog_idx_first; | ||
| 1088 | pset->super.clk_prog_idx_last = pclk_domain_3x_prog->clk_prog_idx_last; | ||
| 1089 | pset->super.b_force_noise_unaware_ordering = | ||
| 1090 | pclk_domain_3x_prog->b_force_noise_unaware_ordering; | ||
| 1091 | pset->super.factory_delta = pclk_domain_3x_prog->factory_delta; | ||
| 1092 | pset->super.freq_delta_min_mhz = pclk_domain_3x_prog->freq_delta_min_mhz; | ||
| 1093 | pset->super.freq_delta_max_mhz = pclk_domain_3x_prog->freq_delta_max_mhz; | ||
| 1094 | memcpy(&pset->super.deltas, &pdomains->deltas, | ||
| 1095 | (sizeof(struct ctrl_clk_clk_delta))); | ||
| 1096 | pset->pre_volt_ordering_index = pclk_domain_35_prog->pre_volt_ordering_index; | ||
| 1097 | pset->post_volt_ordering_index = pclk_domain_35_prog->post_volt_ordering_index; | ||
| 1098 | pset->clk_pos = pclk_domain_35_prog->clk_pos; | ||
| 1099 | pset->clk_vf_curve_count = pclk_domain_35_prog->clk_vf_curve_count; | ||
| 1100 | |||
| 1101 | return status; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | static int _clk_domain_pmudatainit_3x_prog(struct gk20a *g, | ||
| 1105 | struct boardobj *board_obj_ptr, | ||
| 1106 | struct nv_pmu_boardobj *ppmudata) | ||
| 1107 | { | ||
| 1108 | int status = 0; | ||
| 1109 | struct clk_domain_3x_prog *pclk_domain_3x_prog; | ||
| 1110 | struct nv_pmu_clk_clk_domain_30_prog_boardobj_set *pset; | ||
| 1111 | struct clk_domains *pdomains = &(g->clk_pmu.clk_domainobjs); | ||
| 1112 | |||
| 1113 | nvgpu_log_info(g, " "); | ||
| 1114 | |||
| 1115 | status = _clk_domain_pmudatainit_3x(g, board_obj_ptr, ppmudata); | ||
| 1116 | if (status != 0) { | ||
| 1117 | return status; | ||
| 1118 | } | ||
| 1119 | |||
| 1120 | pclk_domain_3x_prog = (struct clk_domain_3x_prog *)board_obj_ptr; | ||
| 1121 | |||
| 1122 | pset = (struct nv_pmu_clk_clk_domain_30_prog_boardobj_set *) | ||
| 1123 | ppmudata; | ||
| 1124 | |||
| 1125 | pset->super.clk_prog_idx_first = pclk_domain_3x_prog->clk_prog_idx_first; | ||
| 1126 | pset->super.clk_prog_idx_last = pclk_domain_3x_prog->clk_prog_idx_last; | ||
| 1127 | pset->noise_unaware_ordering_index = | ||
| 1128 | pclk_domain_3x_prog->noise_unaware_ordering_index; | ||
| 1129 | pset->noise_aware_ordering_index = | ||
| 1130 | pclk_domain_3x_prog->noise_aware_ordering_index; | ||
| 1131 | pset->super.b_force_noise_unaware_ordering = | ||
| 1132 | pclk_domain_3x_prog->b_force_noise_unaware_ordering; | ||
| 1133 | pset->super.factory_delta = pclk_domain_3x_prog->factory_delta; | ||
| 1134 | pset->super.freq_delta_min_mhz = pclk_domain_3x_prog->freq_delta_min_mhz; | ||
| 1135 | pset->super.freq_delta_max_mhz = pclk_domain_3x_prog->freq_delta_max_mhz; | ||
| 1136 | memcpy(&pset->super.deltas, &pdomains->deltas, | ||
| 1137 | (sizeof(struct ctrl_clk_clk_delta))); | ||
| 1138 | |||
| 1139 | return status; | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | static int clk_domain_construct_35_prog(struct gk20a *g, | ||
| 1143 | struct boardobj **ppboardobj, | ||
| 1144 | u16 size, void *pargs) | ||
| 1145 | { | ||
| 1146 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
| 1147 | struct clk_domain_35_prog *pdomain; | ||
| 1148 | struct clk_domain_35_prog *ptmpdomain = | ||
| 1149 | (struct clk_domain_35_prog *)pargs; | ||
| 1150 | int status = 0; | ||
| 1151 | |||
| 1152 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_DOMAIN_TYPE_3X_PROG); | ||
| 1153 | status = clk_domain_construct_3x(g, ppboardobj, size, pargs); | ||
| 1154 | if (status != 0UL) | ||
| 1155 | { | ||
| 1156 | return (u32) -EINVAL; | ||
| 1157 | } | ||
| 1158 | |||
| 1159 | pdomain = (struct clk_domain_35_prog *)(void*) *ppboardobj; | ||
| 1160 | |||
| 1161 | pdomain->super.super.super.super.pmudatainit = | ||
| 1162 | clk_domain_pmudatainit_35_prog; | ||
| 1163 | |||
| 1164 | pdomain->super.super.super.clkdomainclkproglink = | ||
| 1165 | clkdomainclkproglink_3x_prog; | ||
| 1166 | |||
| 1167 | pdomain->super.super.super.clkdomainclkvfsearch = | ||
| 1168 | clkdomainvfsearch; | ||
| 1169 | |||
| 1170 | pdomain->super.super.super.clkdomainclkgetfpoints = | ||
| 1171 | clkdomaingetfpoints; | ||
| 1172 | |||
| 1173 | pdomain->super.clk_prog_idx_first = ptmpdomain->super.clk_prog_idx_first; | ||
| 1174 | pdomain->super.clk_prog_idx_last = ptmpdomain->super.clk_prog_idx_last; | ||
| 1175 | pdomain->super.noise_unaware_ordering_index = | ||
| 1176 | ptmpdomain->super.noise_unaware_ordering_index; | ||
| 1177 | pdomain->super.noise_aware_ordering_index = | ||
| 1178 | ptmpdomain->super.noise_aware_ordering_index; | ||
| 1179 | pdomain->super.b_force_noise_unaware_ordering = | ||
| 1180 | ptmpdomain->super.b_force_noise_unaware_ordering; | ||
| 1181 | pdomain->super.factory_delta = ptmpdomain->super.factory_delta; | ||
| 1182 | pdomain->super.freq_delta_min_mhz = ptmpdomain->super.freq_delta_min_mhz; | ||
| 1183 | pdomain->super.freq_delta_max_mhz = ptmpdomain->super.freq_delta_max_mhz; | ||
| 1184 | pdomain->pre_volt_ordering_index = ptmpdomain->pre_volt_ordering_index; | ||
| 1185 | pdomain->post_volt_ordering_index = ptmpdomain->post_volt_ordering_index; | ||
| 1186 | pdomain->clk_pos = ptmpdomain->clk_pos; | ||
| 1187 | pdomain->clk_vf_curve_count = ptmpdomain->clk_vf_curve_count; | ||
| 1188 | |||
| 1189 | return status; | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | static int clk_domain_construct_3x_prog(struct gk20a *g, | ||
| 1193 | struct boardobj **ppboardobj, | ||
| 1194 | u16 size, void *pargs) | ||
| 1195 | { | ||
| 1196 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
| 1197 | struct clk_domain_3x_prog *pdomain; | ||
| 1198 | struct clk_domain_3x_prog *ptmpdomain = | ||
| 1199 | (struct clk_domain_3x_prog *)pargs; | ||
| 1200 | int status = 0; | ||
| 1201 | |||
| 1202 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_DOMAIN_TYPE_3X_PROG); | ||
| 1203 | status = clk_domain_construct_3x(g, ppboardobj, size, pargs); | ||
| 1204 | if (status) { | ||
| 1205 | return -EINVAL; | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | pdomain = (struct clk_domain_3x_prog *)*ppboardobj; | ||
| 1209 | |||
| 1210 | pdomain->super.super.super.pmudatainit = | ||
| 1211 | _clk_domain_pmudatainit_3x_prog; | ||
| 1212 | |||
| 1213 | pdomain->super.super.clkdomainclkproglink = | ||
| 1214 | clkdomainclkproglink_3x_prog; | ||
| 1215 | |||
| 1216 | pdomain->super.super.clkdomainclkvfsearch = | ||
| 1217 | clkdomainvfsearch; | ||
| 1218 | |||
| 1219 | pdomain->super.super.clkdomainclkgetfpoints = | ||
| 1220 | clkdomaingetfpoints; | ||
| 1221 | |||
| 1222 | pdomain->clk_prog_idx_first = ptmpdomain->clk_prog_idx_first; | ||
| 1223 | pdomain->clk_prog_idx_last = ptmpdomain->clk_prog_idx_last; | ||
| 1224 | pdomain->noise_unaware_ordering_index = | ||
| 1225 | ptmpdomain->noise_unaware_ordering_index; | ||
| 1226 | pdomain->noise_aware_ordering_index = | ||
| 1227 | ptmpdomain->noise_aware_ordering_index; | ||
| 1228 | pdomain->b_force_noise_unaware_ordering = | ||
| 1229 | ptmpdomain->b_force_noise_unaware_ordering; | ||
| 1230 | pdomain->factory_delta = ptmpdomain->factory_delta; | ||
| 1231 | pdomain->freq_delta_min_mhz = ptmpdomain->freq_delta_min_mhz; | ||
| 1232 | pdomain->freq_delta_max_mhz = ptmpdomain->freq_delta_max_mhz; | ||
| 1233 | |||
| 1234 | return status; | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | static int _clk_domain_pmudatainit_35_slave(struct gk20a *g, | ||
| 1238 | struct boardobj *board_obj_ptr, | ||
| 1239 | struct nv_pmu_boardobj *ppmudata) | ||
| 1240 | { | ||
| 1241 | int status = 0; | ||
| 1242 | struct clk_domain_35_slave *pclk_domain_35_slave; | ||
| 1243 | struct nv_pmu_clk_clk_domain_35_slave_boardobj_set *pset; | ||
| 1244 | |||
| 1245 | nvgpu_log_info(g, " "); | ||
| 1246 | |||
| 1247 | status = clk_domain_pmudatainit_35_prog(g, board_obj_ptr, ppmudata); | ||
| 1248 | if (status != 0UL) { | ||
| 1249 | return status; | ||
| 1250 | } | ||
| 1251 | |||
| 1252 | pclk_domain_35_slave = (struct clk_domain_35_slave *)(void*)board_obj_ptr; | ||
| 1253 | |||
| 1254 | pset = (struct nv_pmu_clk_clk_domain_35_slave_boardobj_set *) | ||
| 1255 | (void*) ppmudata; | ||
| 1256 | |||
| 1257 | pset->slave.master_idx = pclk_domain_35_slave->slave.master_idx; | ||
| 1258 | |||
| 1259 | return status; | ||
| 1260 | } | ||
| 1261 | |||
| 1262 | static int clk_domain_pmudatainit_3x_slave(struct gk20a *g, | ||
| 1263 | struct boardobj *board_obj_ptr, | ||
| 1264 | struct nv_pmu_boardobj *ppmudata) | ||
| 1265 | { | ||
| 1266 | int status = 0; | ||
| 1267 | struct clk_domain_3x_slave *pclk_domain_3x_slave; | ||
| 1268 | struct nv_pmu_clk_clk_domain_3x_slave_boardobj_set *pset; | ||
| 1269 | |||
| 1270 | nvgpu_log_info(g, " "); | ||
| 1271 | |||
| 1272 | status = _clk_domain_pmudatainit_3x_prog(g, board_obj_ptr, ppmudata); | ||
| 1273 | if (status != 0) { | ||
| 1274 | return status; | ||
| 1275 | } | ||
| 1276 | |||
| 1277 | pclk_domain_3x_slave = (struct clk_domain_3x_slave *)board_obj_ptr; | ||
| 1278 | |||
| 1279 | pset = (struct nv_pmu_clk_clk_domain_3x_slave_boardobj_set *) | ||
| 1280 | ppmudata; | ||
| 1281 | |||
| 1282 | pset->master_idx = pclk_domain_3x_slave->master_idx; | ||
| 1283 | |||
| 1284 | return status; | ||
| 1285 | } | ||
| 1286 | |||
| 1287 | static int clk_domain_construct_35_slave(struct gk20a *g, | ||
| 1288 | struct boardobj **ppboardobj, | ||
| 1289 | u16 size, void *pargs) | ||
| 1290 | { | ||
| 1291 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
| 1292 | struct clk_domain_35_slave *pdomain; | ||
| 1293 | struct clk_domain_35_slave *ptmpdomain = | ||
| 1294 | (struct clk_domain_35_slave *)pargs; | ||
| 1295 | int status = 0; | ||
| 1296 | |||
| 1297 | if (BOARDOBJ_GET_TYPE(pargs) != (u8) CTRL_CLK_CLK_DOMAIN_TYPE_35_SLAVE) { | ||
| 1298 | return (u32) -EINVAL; | ||
| 1299 | } | ||
| 1300 | |||
| 1301 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_DOMAIN_TYPE_35_SLAVE); | ||
| 1302 | status = clk_domain_construct_35_prog(g, ppboardobj, size, pargs); | ||
| 1303 | if (status != 0UL) { | ||
| 1304 | return (u32) -EINVAL; | ||
| 1305 | } | ||
| 1306 | |||
| 1307 | pdomain = (struct clk_domain_35_slave *)(void*)*ppboardobj; | ||
| 1308 | |||
| 1309 | pdomain->super.super.super.super.super.pmudatainit = | ||
| 1310 | _clk_domain_pmudatainit_35_slave; | ||
| 1311 | |||
| 1312 | pdomain->slave.master_idx = ptmpdomain->slave.master_idx; | ||
| 1313 | |||
| 1314 | pdomain->slave.clkdomainclkgetslaveclk = | ||
| 1315 | clkdomaingetslaveclk; | ||
| 1316 | |||
| 1317 | return status; | ||
| 1318 | } | ||
| 1319 | |||
| 1320 | static int clk_domain_construct_3x_slave(struct gk20a *g, | ||
| 1321 | struct boardobj **ppboardobj, | ||
| 1322 | u16 size, void *pargs) | ||
| 1323 | { | ||
| 1324 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
| 1325 | struct clk_domain_3x_slave *pdomain; | ||
| 1326 | struct clk_domain_3x_slave *ptmpdomain = | ||
| 1327 | (struct clk_domain_3x_slave *)pargs; | ||
| 1328 | int status = 0; | ||
| 1329 | |||
| 1330 | if (BOARDOBJ_GET_TYPE(pargs) != (u8) CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE) { | ||
| 1331 | return -EINVAL; | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE); | ||
| 1335 | status = clk_domain_construct_3x_prog(g, ppboardobj, size, pargs); | ||
| 1336 | if (status != 0UL) { | ||
| 1337 | return -EINVAL; | ||
| 1338 | } | ||
| 1339 | |||
| 1340 | pdomain = (struct clk_domain_3x_slave *)*ppboardobj; | ||
| 1341 | |||
| 1342 | pdomain->super.super.super.super.pmudatainit = | ||
| 1343 | clk_domain_pmudatainit_3x_slave; | ||
| 1344 | |||
| 1345 | pdomain->master_idx = ptmpdomain->master_idx; | ||
| 1346 | |||
| 1347 | pdomain->clkdomainclkgetslaveclk = | ||
| 1348 | clkdomaingetslaveclk; | ||
| 1349 | |||
| 1350 | return status; | ||
| 1351 | } | ||
| 1352 | |||
| 1353 | static int clkdomainclkproglink_3x_master(struct gk20a *g, | ||
| 1354 | struct clk_pmupstate *pclk, | ||
| 1355 | struct clk_domain *pdomain) | ||
| 1356 | { | ||
| 1357 | int status = 0; | ||
| 1358 | struct clk_domain_3x_master *p3xmaster = | ||
| 1359 | (struct clk_domain_3x_master *)pdomain; | ||
| 1360 | struct clk_prog *pprog = NULL; | ||
| 1361 | struct clk_prog_1x_master *pprog1xmaster = NULL; | ||
| 1362 | u16 freq_max_last_mhz = 0; | ||
| 1363 | u8 i; | ||
| 1364 | |||
| 1365 | nvgpu_log_info(g, " "); | ||
| 1366 | |||
| 1367 | status = clkdomainclkproglink_3x_prog(g, pclk, pdomain); | ||
| 1368 | if (status) { | ||
| 1369 | goto done; | ||
| 1370 | } | ||
| 1371 | |||
| 1372 | /* Iterate over the set of CLK_PROGs pointed at by this domain.*/ | ||
| 1373 | for (i = p3xmaster->super.clk_prog_idx_first; | ||
| 1374 | i <= p3xmaster->super.clk_prog_idx_last; | ||
| 1375 | i++) { | ||
| 1376 | pprog = CLK_CLK_PROG_GET(pclk, i); | ||
| 1377 | |||
| 1378 | /* MASTER CLK_DOMAINs must point to MASTER CLK_PROGs.*/ | ||
| 1379 | if (!pprog->super.implements(g, &pprog->super, | ||
| 1380 | CTRL_CLK_CLK_PROG_TYPE_1X_MASTER)) { | ||
| 1381 | status = -EINVAL; | ||
| 1382 | goto done; | ||
| 1383 | } | ||
| 1384 | |||
| 1385 | pprog1xmaster = (struct clk_prog_1x_master *)pprog; | ||
| 1386 | status = pprog1xmaster->vfflatten(g, pclk, pprog1xmaster, | ||
| 1387 | BOARDOBJ_GET_IDX(p3xmaster), &freq_max_last_mhz); | ||
| 1388 | if (status) { | ||
| 1389 | goto done; | ||
| 1390 | } | ||
| 1391 | } | ||
| 1392 | done: | ||
| 1393 | nvgpu_log_info(g, "done status %x", status); | ||
| 1394 | return status; | ||
| 1395 | } | ||
| 1396 | |||
| 1397 | static int clk_domain_pmudatainit_35_master(struct gk20a *g, | ||
| 1398 | struct boardobj *board_obj_ptr, | ||
| 1399 | struct nv_pmu_boardobj *ppmudata) | ||
| 1400 | { | ||
| 1401 | int status = 0; | ||
| 1402 | struct clk_domain_35_master *pclk_domain_35_master; | ||
| 1403 | struct nv_pmu_clk_clk_domain_35_master_boardobj_set *pset; | ||
| 1404 | |||
| 1405 | nvgpu_log_info(g, " "); | ||
| 1406 | |||
| 1407 | status = clk_domain_pmudatainit_35_prog(g, board_obj_ptr, ppmudata); | ||
| 1408 | if (status != 0UL) { | ||
| 1409 | return status; | ||
| 1410 | } | ||
| 1411 | |||
| 1412 | pclk_domain_35_master = (struct clk_domain_35_master *) | ||
| 1413 | (void*) board_obj_ptr; | ||
| 1414 | |||
| 1415 | pset = (struct nv_pmu_clk_clk_domain_35_master_boardobj_set *) | ||
| 1416 | (void*) ppmudata; | ||
| 1417 | |||
| 1418 | pset->master.slave_idxs_mask = pclk_domain_35_master->master.slave_idxs_mask; | ||
| 1419 | |||
| 1420 | return status; | ||
| 1421 | } | ||
| 1422 | |||
| 1423 | static int _clk_domain_pmudatainit_3x_master(struct gk20a *g, | ||
| 1424 | struct boardobj *board_obj_ptr, | ||
| 1425 | struct nv_pmu_boardobj *ppmudata) | ||
| 1426 | { | ||
| 1427 | int status = 0; | ||
| 1428 | struct clk_domain_3x_master *pclk_domain_3x_master; | ||
| 1429 | struct nv_pmu_clk_clk_domain_3x_master_boardobj_set *pset; | ||
| 1430 | |||
| 1431 | nvgpu_log_info(g, " "); | ||
| 1432 | |||
| 1433 | status = _clk_domain_pmudatainit_3x_prog(g, board_obj_ptr, ppmudata); | ||
| 1434 | if (status != 0) { | ||
| 1435 | return status; | ||
| 1436 | } | ||
| 1437 | |||
| 1438 | pclk_domain_3x_master = (struct clk_domain_3x_master *)board_obj_ptr; | ||
| 1439 | |||
| 1440 | pset = (struct nv_pmu_clk_clk_domain_3x_master_boardobj_set *) | ||
| 1441 | ppmudata; | ||
| 1442 | |||
| 1443 | pset->slave_idxs_mask = pclk_domain_3x_master->slave_idxs_mask; | ||
| 1444 | |||
| 1445 | return status; | ||
| 1446 | } | ||
| 1447 | |||
| 1448 | static int clk_domain_construct_35_master(struct gk20a *g, | ||
| 1449 | struct boardobj **ppboardobj, | ||
| 1450 | u16 size, void *pargs) | ||
| 1451 | { | ||
| 1452 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
| 1453 | struct clk_domain_35_master *pdomain; | ||
| 1454 | int status = 0; | ||
| 1455 | |||
| 1456 | if (BOARDOBJ_GET_TYPE(pargs) != (u8) CTRL_CLK_CLK_DOMAIN_TYPE_35_MASTER) { | ||
| 1457 | return -EINVAL; | ||
| 1458 | } | ||
| 1459 | |||
| 1460 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_DOMAIN_TYPE_35_MASTER); | ||
| 1461 | status = clk_domain_construct_35_prog(g, ppboardobj, size, pargs); | ||
| 1462 | if (status != 0UL) { | ||
| 1463 | return (u32) -EINVAL; | ||
| 1464 | } | ||
| 1465 | |||
| 1466 | pdomain = (struct clk_domain_35_master *)(void*) *ppboardobj; | ||
| 1467 | |||
| 1468 | pdomain->super.super.super.super.super.pmudatainit = | ||
| 1469 | clk_domain_pmudatainit_35_master; | ||
| 1470 | pdomain->super.super.super.super.clkdomainclkproglink = | ||
| 1471 | clkdomainclkproglink_3x_master; | ||
| 1472 | |||
| 1473 | pdomain->master.slave_idxs_mask = 0; | ||
| 1474 | |||
| 1475 | return status; | ||
| 1476 | } | ||
| 1477 | |||
| 1478 | static int clk_domain_construct_3x_master(struct gk20a *g, | ||
| 1479 | struct boardobj **ppboardobj, | ||
| 1480 | u16 size, void *pargs) | ||
| 1481 | { | ||
| 1482 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
| 1483 | struct clk_domain_3x_master *pdomain; | ||
| 1484 | int status = 0; | ||
| 1485 | |||
| 1486 | if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER) { | ||
| 1487 | return -EINVAL; | ||
| 1488 | } | ||
| 1489 | |||
| 1490 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER); | ||
| 1491 | status = clk_domain_construct_3x_prog(g, ppboardobj, size, pargs); | ||
| 1492 | if (status) { | ||
| 1493 | return -EINVAL; | ||
| 1494 | } | ||
| 1495 | |||
| 1496 | pdomain = (struct clk_domain_3x_master *)*ppboardobj; | ||
| 1497 | |||
| 1498 | pdomain->super.super.super.super.pmudatainit = | ||
| 1499 | _clk_domain_pmudatainit_3x_master; | ||
| 1500 | pdomain->super.super.super.clkdomainclkproglink = | ||
| 1501 | clkdomainclkproglink_3x_master; | ||
| 1502 | |||
| 1503 | pdomain->slave_idxs_mask = 0; | ||
| 1504 | |||
| 1505 | return status; | ||
| 1506 | } | ||
| 1507 | |||
| 1508 | static int clkdomainclkproglink_fixed(struct gk20a *g, | ||
| 1509 | struct clk_pmupstate *pclk, | ||
| 1510 | struct clk_domain *pdomain) | ||
| 1511 | { | ||
| 1512 | nvgpu_log_info(g, " "); | ||
| 1513 | return 0; | ||
| 1514 | } | ||
| 1515 | |||
| 1516 | static int _clk_domain_pmudatainit_3x_fixed(struct gk20a *g, | ||
| 1517 | struct boardobj *board_obj_ptr, | ||
| 1518 | struct nv_pmu_boardobj *ppmudata) | ||
| 1519 | { | ||
| 1520 | int status = 0; | ||
| 1521 | struct clk_domain_3x_fixed *pclk_domain_3x_fixed; | ||
| 1522 | struct nv_pmu_clk_clk_domain_3x_fixed_boardobj_set *pset; | ||
| 1523 | |||
| 1524 | nvgpu_log_info(g, " "); | ||
| 1525 | |||
| 1526 | status = _clk_domain_pmudatainit_3x(g, board_obj_ptr, ppmudata); | ||
| 1527 | if (status != 0) { | ||
| 1528 | return status; | ||
| 1529 | } | ||
| 1530 | |||
| 1531 | pclk_domain_3x_fixed = (struct clk_domain_3x_fixed *)board_obj_ptr; | ||
| 1532 | |||
| 1533 | pset = (struct nv_pmu_clk_clk_domain_3x_fixed_boardobj_set *) | ||
| 1534 | ppmudata; | ||
| 1535 | |||
| 1536 | pset->freq_mhz = pclk_domain_3x_fixed->freq_mhz; | ||
| 1537 | |||
| 1538 | return status; | ||
| 1539 | } | ||
| 1540 | |||
| 1541 | static int clk_domain_construct_3x_fixed(struct gk20a *g, | ||
| 1542 | struct boardobj **ppboardobj, | ||
| 1543 | u16 size, void *pargs) | ||
| 1544 | { | ||
| 1545 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
| 1546 | struct clk_domain_3x_fixed *pdomain; | ||
| 1547 | struct clk_domain_3x_fixed *ptmpdomain = | ||
| 1548 | (struct clk_domain_3x_fixed *)pargs; | ||
| 1549 | int status = 0; | ||
| 1550 | |||
| 1551 | if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_DOMAIN_TYPE_3X_FIXED) { | ||
| 1552 | return -EINVAL; | ||
| 1553 | } | ||
| 1554 | |||
| 1555 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_DOMAIN_TYPE_3X_FIXED); | ||
| 1556 | status = clk_domain_construct_3x(g, ppboardobj, size, pargs); | ||
| 1557 | if (status) { | ||
| 1558 | return -EINVAL; | ||
| 1559 | } | ||
| 1560 | |||
| 1561 | pdomain = (struct clk_domain_3x_fixed *)*ppboardobj; | ||
| 1562 | |||
| 1563 | pdomain->super.super.super.pmudatainit = | ||
| 1564 | _clk_domain_pmudatainit_3x_fixed; | ||
| 1565 | |||
| 1566 | pdomain->super.super.clkdomainclkproglink = | ||
| 1567 | clkdomainclkproglink_fixed; | ||
| 1568 | |||
| 1569 | pdomain->freq_mhz = ptmpdomain->freq_mhz; | ||
| 1570 | |||
| 1571 | return status; | ||
| 1572 | } | ||
| 1573 | |||
| 1574 | static struct clk_domain *construct_clk_domain(struct gk20a *g, void *pargs) | ||
| 1575 | { | ||
| 1576 | struct boardobj *board_obj_ptr = NULL; | ||
| 1577 | u32 status; | ||
| 1578 | |||
| 1579 | nvgpu_log_info(g, " %d", BOARDOBJ_GET_TYPE(pargs)); | ||
| 1580 | switch (BOARDOBJ_GET_TYPE(pargs)) { | ||
| 1581 | case CTRL_CLK_CLK_DOMAIN_TYPE_3X_FIXED: | ||
| 1582 | status = clk_domain_construct_3x_fixed(g, &board_obj_ptr, | ||
| 1583 | sizeof(struct clk_domain_3x_fixed), pargs); | ||
| 1584 | break; | ||
| 1585 | |||
| 1586 | case CTRL_CLK_CLK_DOMAIN_TYPE_35_MASTER: | ||
| 1587 | status = clk_domain_construct_35_master(g, &board_obj_ptr, | ||
| 1588 | sizeof(struct clk_domain_35_master), pargs); | ||
| 1589 | break; | ||
| 1590 | |||
| 1591 | |||
| 1592 | case CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER: | ||
| 1593 | status = clk_domain_construct_3x_master(g, &board_obj_ptr, | ||
| 1594 | sizeof(struct clk_domain_3x_master), pargs); | ||
| 1595 | break; | ||
| 1596 | |||
| 1597 | case CTRL_CLK_CLK_DOMAIN_TYPE_35_SLAVE: | ||
| 1598 | status = clk_domain_construct_35_slave(g, &board_obj_ptr, | ||
| 1599 | sizeof(struct clk_domain_35_slave), pargs); | ||
| 1600 | break; | ||
| 1601 | |||
| 1602 | case CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE: | ||
| 1603 | status = clk_domain_construct_3x_slave(g, &board_obj_ptr, | ||
| 1604 | sizeof(struct clk_domain_3x_slave), pargs); | ||
| 1605 | break; | ||
| 1606 | |||
| 1607 | default: | ||
| 1608 | return NULL; | ||
| 1609 | } | ||
| 1610 | |||
| 1611 | if (status) { | ||
| 1612 | return NULL; | ||
| 1613 | } | ||
| 1614 | |||
| 1615 | nvgpu_log_info(g, " Done"); | ||
| 1616 | |||
| 1617 | return (struct clk_domain *)board_obj_ptr; | ||
| 1618 | } | ||
| 1619 | |||
| 1620 | static int clk_domain_pmudatainit_super(struct gk20a *g, | ||
| 1621 | struct boardobj *board_obj_ptr, | ||
| 1622 | struct nv_pmu_boardobj *ppmudata) | ||
| 1623 | { | ||
| 1624 | int status = 0; | ||
| 1625 | struct clk_domain *pclk_domain; | ||
| 1626 | struct nv_pmu_clk_clk_domain_boardobj_set *pset; | ||
| 1627 | |||
| 1628 | nvgpu_log_info(g, " "); | ||
| 1629 | |||
| 1630 | status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata); | ||
| 1631 | if (status != 0) { | ||
| 1632 | return status; | ||
| 1633 | } | ||
| 1634 | |||
| 1635 | pclk_domain = (struct clk_domain *)board_obj_ptr; | ||
| 1636 | |||
| 1637 | pset = (struct nv_pmu_clk_clk_domain_boardobj_set *)ppmudata; | ||
| 1638 | |||
| 1639 | pset->domain = pclk_domain->domain; | ||
| 1640 | pset->api_domain = pclk_domain->api_domain; | ||
| 1641 | pset->perf_domain_grp_idx = pclk_domain->perf_domain_grp_idx; | ||
| 1642 | |||
| 1643 | return status; | ||
| 1644 | } | ||
| 1645 | |||
| 1646 | int clk_domain_clk_prog_link(struct gk20a *g, struct clk_pmupstate *pclk) | ||
| 1647 | { | ||
| 1648 | int status = 0; | ||
| 1649 | struct clk_domain *pdomain; | ||
| 1650 | u8 i; | ||
| 1651 | |||
| 1652 | /* Iterate over all CLK_DOMAINs and flatten their VF curves.*/ | ||
| 1653 | BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super), | ||
| 1654 | struct clk_domain *, pdomain, i) { | ||
| 1655 | status = pdomain->clkdomainclkproglink(g, pclk, pdomain); | ||
| 1656 | if (status) { | ||
| 1657 | nvgpu_err(g, | ||
| 1658 | "error flattening VF for CLK DOMAIN - 0x%x", | ||
| 1659 | pdomain->domain); | ||
| 1660 | goto done; | ||
| 1661 | } | ||
| 1662 | } | ||
| 1663 | |||
| 1664 | done: | ||
| 1665 | return status; | ||
| 1666 | } | ||
diff --git a/include/clk/clk_domain.h b/include/clk/clk_domain.h deleted file mode 100644 index e5a7153..0000000 --- a/include/clk/clk_domain.h +++ /dev/null | |||
| @@ -1,157 +0,0 @@ | |||
| 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 | #ifndef NVGPU_CLK_DOMAIN_H | ||
| 24 | #define NVGPU_CLK_DOMAIN_H | ||
| 25 | |||
| 26 | #include "ctrl/ctrlclk.h" | ||
| 27 | #include "ctrl/ctrlboardobj.h" | ||
| 28 | #include <nvgpu/pmuif/nvgpu_gpmu_cmdif.h> | ||
| 29 | #include "boardobj/boardobjgrp_e32.h" | ||
| 30 | #include "boardobj/boardobjgrpmask.h" | ||
| 31 | |||
| 32 | #define CLK_DOMAIN_BOARDOBJGRP_VERSION 0x30 | ||
| 33 | #define CLK_TABLE_HAL_ENTRY_GP 0x02 | ||
| 34 | #define CLK_TABLE_HAL_ENTRY_GV 0x03 | ||
| 35 | |||
| 36 | struct clk_domains; | ||
| 37 | struct clk_domain; | ||
| 38 | enum nv_pmu_clk_clkwhich; | ||
| 39 | |||
| 40 | /*data and function definition to talk to driver*/ | ||
| 41 | int clk_domain_sw_setup(struct gk20a *g); | ||
| 42 | int clk_domain_pmu_setup(struct gk20a *g); | ||
| 43 | |||
| 44 | typedef int clkproglink(struct gk20a *g, struct clk_pmupstate *pclk, | ||
| 45 | struct clk_domain *pdomain); | ||
| 46 | |||
| 47 | typedef int clkvfsearch(struct gk20a *g, struct clk_pmupstate *pclk, | ||
| 48 | struct clk_domain *pdomain, u16 *clkmhz, | ||
| 49 | u32 *voltuv, u8 rail); | ||
| 50 | |||
| 51 | typedef int clkgetslaveclk(struct gk20a *g, struct clk_pmupstate *pclk, | ||
| 52 | struct clk_domain *pdomain, u16 *clkmhz, | ||
| 53 | u16 masterclkmhz); | ||
| 54 | |||
| 55 | typedef u32 clkgetfpoints(struct gk20a *g, struct clk_pmupstate *pclk, | ||
| 56 | struct clk_domain *pdomain, u32 *pfpointscount, | ||
| 57 | u16 *pfreqpointsinmhz, u8 rail); | ||
| 58 | |||
| 59 | struct clk_domains { | ||
| 60 | struct boardobjgrp_e32 super; | ||
| 61 | u8 n_num_entries; | ||
| 62 | u8 version; | ||
| 63 | bool b_enforce_vf_monotonicity; | ||
| 64 | bool b_enforce_vf_smoothening; | ||
| 65 | bool b_override_o_v_o_c; | ||
| 66 | bool b_debug_mode; | ||
| 67 | u32 vbios_domains; | ||
| 68 | u16 cntr_sampling_periodms; | ||
| 69 | struct boardobjgrpmask_e32 prog_domains_mask; | ||
| 70 | struct boardobjgrpmask_e32 master_domains_mask; | ||
| 71 | struct ctrl_clk_clk_delta deltas; | ||
| 72 | |||
| 73 | struct clk_domain *ordered_noise_aware_list[CTRL_BOARDOBJ_MAX_BOARD_OBJECTS]; | ||
| 74 | |||
| 75 | struct clk_domain *ordered_noise_unaware_list[CTRL_BOARDOBJ_MAX_BOARD_OBJECTS]; | ||
| 76 | }; | ||
| 77 | |||
| 78 | struct clk_domain { | ||
| 79 | struct boardobj super; | ||
| 80 | u32 api_domain; | ||
| 81 | u32 part_mask; | ||
| 82 | enum nv_pmu_clk_clkwhich domain; | ||
| 83 | u8 perf_domain_index; | ||
| 84 | u8 perf_domain_grp_idx; | ||
| 85 | u8 ratio_domain; | ||
| 86 | u8 usage; | ||
| 87 | clkproglink *clkdomainclkproglink; | ||
| 88 | clkvfsearch *clkdomainclkvfsearch; | ||
| 89 | clkgetfpoints *clkdomainclkgetfpoints; | ||
| 90 | }; | ||
| 91 | |||
| 92 | struct clk_domain_3x { | ||
| 93 | struct clk_domain super; | ||
| 94 | bool b_noise_aware_capable; | ||
| 95 | }; | ||
| 96 | |||
| 97 | struct clk_domain_3x_fixed { | ||
| 98 | struct clk_domain_3x super; | ||
| 99 | u16 freq_mhz; | ||
| 100 | }; | ||
| 101 | |||
| 102 | struct clk_domain_3x_prog { | ||
| 103 | struct clk_domain_3x super; | ||
| 104 | u8 clk_prog_idx_first; | ||
| 105 | u8 clk_prog_idx_last; | ||
| 106 | bool b_force_noise_unaware_ordering; | ||
| 107 | struct ctrl_clk_freq_delta factory_delta; | ||
| 108 | short freq_delta_min_mhz; | ||
| 109 | short freq_delta_max_mhz; | ||
| 110 | struct ctrl_clk_clk_delta deltas; | ||
| 111 | u8 noise_unaware_ordering_index; | ||
| 112 | u8 noise_aware_ordering_index; | ||
| 113 | }; | ||
| 114 | |||
| 115 | struct clk_domain_35_prog { | ||
| 116 | struct clk_domain_3x_prog super; | ||
| 117 | u8 pre_volt_ordering_index; | ||
| 118 | u8 post_volt_ordering_index; | ||
| 119 | u8 clk_pos; | ||
| 120 | u8 clk_vf_curve_count; | ||
| 121 | }; | ||
| 122 | |||
| 123 | struct clk_domain_3x_master { | ||
| 124 | struct clk_domain_3x_prog super; | ||
| 125 | u32 slave_idxs_mask; | ||
| 126 | }; | ||
| 127 | |||
| 128 | struct clk_domain_35_master { | ||
| 129 | struct clk_domain_35_prog super; | ||
| 130 | struct clk_domain_3x_master master; | ||
| 131 | struct boardobjgrpmask_e32 master_slave_domains_grp_mask; | ||
| 132 | }; | ||
| 133 | |||
| 134 | struct clk_domain_3x_slave { | ||
| 135 | struct clk_domain_3x_prog super; | ||
| 136 | u8 master_idx; | ||
| 137 | clkgetslaveclk *clkdomainclkgetslaveclk; | ||
| 138 | }; | ||
| 139 | |||
| 140 | struct clk_domain_30_slave { | ||
| 141 | u8 rsvd; | ||
| 142 | u8 master_idx; | ||
| 143 | clkgetslaveclk *clkdomainclkgetslaveclk; | ||
| 144 | }; | ||
| 145 | |||
| 146 | struct clk_domain_35_slave { | ||
| 147 | struct clk_domain_35_prog super; | ||
| 148 | struct clk_domain_30_slave slave; | ||
| 149 | }; | ||
| 150 | |||
| 151 | int clk_domain_clk_prog_link(struct gk20a *g, struct clk_pmupstate *pclk); | ||
| 152 | |||
| 153 | #define CLK_CLK_DOMAIN_GET(pclk, idx) \ | ||
| 154 | ((struct clk_domain *)BOARDOBJGRP_OBJ_GET_BY_IDX( \ | ||
| 155 | &pclk->clk_domainobjs.super.super, (u8)(idx))) | ||
| 156 | |||
| 157 | #endif /* NVGPU_CLK_DOMAIN_H */ | ||
diff --git a/include/clk/clk_fll.c b/include/clk/clk_fll.c deleted file mode 100644 index e67dd35..0000000 --- a/include/clk/clk_fll.c +++ /dev/null | |||
| @@ -1,495 +0,0 @@ | |||
| 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 | |||
| 34 | static int devinit_get_fll_device_table(struct gk20a *g, | ||
| 35 | struct avfsfllobjs *pfllobjs); | ||
| 36 | static struct fll_device *construct_fll_device(struct gk20a *g, | ||
| 37 | void *pargs); | ||
| 38 | static int fll_device_init_pmudata_super(struct gk20a *g, | ||
| 39 | struct boardobj *board_obj_ptr, | ||
| 40 | struct nv_pmu_boardobj *ppmudata); | ||
| 41 | |||
| 42 | static 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 | |||
| 74 | static 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 | |||
| 97 | static 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 | |||
| 117 | int 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 | } | ||
| 207 | done: | ||
| 208 | nvgpu_log_info(g, " done status %x", status); | ||
| 209 | return status; | ||
| 210 | } | ||
| 211 | |||
| 212 | int 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 | } | ||
| 224 | |||
| 225 | status = pboardobjgrp->pmuinithandle(g, pboardobjgrp); | ||
| 226 | |||
| 227 | nvgpu_log_info(g, "Done"); | ||
| 228 | return status; | ||
| 229 | } | ||
| 230 | |||
| 231 | static int devinit_get_fll_device_table(struct gk20a *g, | ||
| 232 | struct avfsfllobjs *pfllobjs) | ||
| 233 | { | ||
| 234 | int status = 0; | ||
| 235 | u8 *fll_table_ptr = NULL; | ||
| 236 | struct fll_descriptor_header fll_desc_table_header_sz = { 0 }; | ||
| 237 | struct fll_descriptor_header_10 fll_desc_table_header = { 0 }; | ||
| 238 | struct fll_descriptor_entry_10 fll_desc_table_entry = { 0 }; | ||
| 239 | u8 *fll_tbl_entry_ptr = NULL; | ||
| 240 | u32 index = 0; | ||
| 241 | struct fll_device fll_dev_data; | ||
| 242 | struct fll_device *pfll_dev; | ||
| 243 | struct vin_device *pvin_dev; | ||
| 244 | u32 desctablesize; | ||
| 245 | u32 vbios_domain = NV_PERF_DOMAIN_4X_CLOCK_DOMAIN_SKIP; | ||
| 246 | struct avfsvinobjs *pvinobjs = &g->clk_pmu.avfs_vinobjs; | ||
| 247 | |||
| 248 | nvgpu_log_info(g, " "); | ||
| 249 | |||
| 250 | fll_table_ptr = (u8 *)nvgpu_bios_get_perf_table_ptrs(g, | ||
| 251 | g->bios.clock_token, FLL_TABLE); | ||
| 252 | if (fll_table_ptr == NULL) { | ||
| 253 | status = -1; | ||
| 254 | goto done; | ||
| 255 | } | ||
| 256 | |||
| 257 | memcpy(&fll_desc_table_header_sz, fll_table_ptr, | ||
| 258 | sizeof(struct fll_descriptor_header)); | ||
| 259 | if (fll_desc_table_header_sz.size >= FLL_DESCRIPTOR_HEADER_10_SIZE_6) { | ||
| 260 | desctablesize = FLL_DESCRIPTOR_HEADER_10_SIZE_6; | ||
| 261 | } else { | ||
| 262 | desctablesize = FLL_DESCRIPTOR_HEADER_10_SIZE_4; | ||
| 263 | } | ||
| 264 | |||
| 265 | memcpy(&fll_desc_table_header, fll_table_ptr, desctablesize); | ||
| 266 | |||
| 267 | if (desctablesize == FLL_DESCRIPTOR_HEADER_10_SIZE_6) { | ||
| 268 | pfllobjs->max_min_freq_mhz = | ||
| 269 | fll_desc_table_header.max_min_freq_mhz; | ||
| 270 | } else { | ||
| 271 | pfllobjs->max_min_freq_mhz = 0; | ||
| 272 | } | ||
| 273 | |||
| 274 | /* Read table entries*/ | ||
| 275 | fll_tbl_entry_ptr = fll_table_ptr + desctablesize; | ||
| 276 | for (index = 0; index < fll_desc_table_header.entry_count; index++) { | ||
| 277 | u32 fll_id; | ||
| 278 | |||
| 279 | memcpy(&fll_desc_table_entry, fll_tbl_entry_ptr, | ||
| 280 | sizeof(struct fll_descriptor_entry_10)); | ||
| 281 | |||
| 282 | if (fll_desc_table_entry.fll_device_type == CTRL_CLK_FLL_TYPE_DISABLED) { | ||
| 283 | continue; | ||
| 284 | } | ||
| 285 | |||
| 286 | fll_id = fll_desc_table_entry.fll_device_id; | ||
| 287 | |||
| 288 | if ( (u8)fll_desc_table_entry.vin_idx_logic != CTRL_CLK_VIN_ID_UNDEFINED) { | ||
| 289 | pvin_dev = CLK_GET_VIN_DEVICE(pvinobjs, | ||
| 290 | (u8)fll_desc_table_entry.vin_idx_logic); | ||
| 291 | if (pvin_dev == NULL) { | ||
| 292 | return -EINVAL; | ||
| 293 | } else { | ||
| 294 | pvin_dev->flls_shared_mask |= BIT(fll_id); | ||
| 295 | } | ||
| 296 | } else { | ||
| 297 | /* Return if Logic ADC device index is invalid*/ | ||
| 298 | nvgpu_err(g, "Invalid Logic ADC specified for Nafll ID"); | ||
| 299 | return -EINVAL; | ||
| 300 | } | ||
| 301 | |||
| 302 | fll_dev_data.lut_device.vselect_mode = | ||
| 303 | (u8)BIOS_GET_FIELD(fll_desc_table_entry.lut_params, | ||
| 304 | NV_FLL_DESC_LUT_PARAMS_VSELECT); | ||
| 305 | |||
| 306 | if ( (u8)fll_desc_table_entry.vin_idx_sram != CTRL_CLK_VIN_ID_UNDEFINED) { | ||
| 307 | pvin_dev = CLK_GET_VIN_DEVICE(pvinobjs, | ||
| 308 | (u8)fll_desc_table_entry.vin_idx_sram); | ||
| 309 | if (pvin_dev == NULL) { | ||
| 310 | return -EINVAL; | ||
| 311 | } else { | ||
| 312 | pvin_dev->flls_shared_mask |= BIT(fll_id); | ||
| 313 | } | ||
| 314 | } else { | ||
| 315 | /* Make sure VSELECT mode is set correctly to _LOGIC*/ | ||
| 316 | if (fll_dev_data.lut_device.vselect_mode != CTRL_CLK_FLL_LUT_VSELECT_LOGIC) { | ||
| 317 | return -EINVAL; | ||
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 321 | fll_dev_data.super.type = | ||
| 322 | (u8)fll_desc_table_entry.fll_device_type; | ||
| 323 | fll_dev_data.id = (u8)fll_desc_table_entry.fll_device_id; | ||
| 324 | fll_dev_data.mdiv = (u8)BIOS_GET_FIELD( | ||
| 325 | fll_desc_table_entry.fll_params, | ||
| 326 | NV_FLL_DESC_FLL_PARAMS_MDIV); | ||
| 327 | fll_dev_data.input_freq_mhz = | ||
| 328 | (u16)fll_desc_table_entry.ref_freq_mhz; | ||
| 329 | fll_dev_data.min_freq_vfe_idx = | ||
| 330 | (u8)fll_desc_table_entry.min_freq_vfe_idx; | ||
| 331 | fll_dev_data.freq_ctrl_idx = CTRL_BOARDOBJ_IDX_INVALID; | ||
| 332 | |||
| 333 | vbios_domain = (u32)(fll_desc_table_entry.clk_domain & | ||
| 334 | NV_PERF_DOMAIN_4X_CLOCK_DOMAIN_MASK); | ||
| 335 | fll_dev_data.clk_domain = | ||
| 336 | g->ops.pmu_ver.clk.get_vbios_clk_domain(vbios_domain); | ||
| 337 | |||
| 338 | fll_dev_data.rail_idx_for_lut = 0; | ||
| 339 | fll_dev_data.vin_idx_logic = | ||
| 340 | (u8)fll_desc_table_entry.vin_idx_logic; | ||
| 341 | fll_dev_data.vin_idx_sram = | ||
| 342 | (u8)fll_desc_table_entry.vin_idx_sram; | ||
| 343 | fll_dev_data.b_skip_pldiv_below_dvco_min = | ||
| 344 | (bool)BIOS_GET_FIELD(fll_desc_table_entry.fll_params, | ||
| 345 | NV_FLL_DESC_FLL_PARAMS_SKIP_PLDIV_BELOW_DVCO_MIN); | ||
| 346 | fll_dev_data.lut_device.hysteresis_threshold = | ||
| 347 | (u8)BIOS_GET_FIELD(fll_desc_table_entry.lut_params, | ||
| 348 | NV_FLL_DESC_LUT_PARAMS_HYSTERISIS_THRESHOLD); | ||
| 349 | fll_dev_data.regime_desc.regime_id = | ||
| 350 | CTRL_CLK_FLL_REGIME_ID_FFR; | ||
| 351 | fll_dev_data.regime_desc.fixed_freq_regime_limit_mhz = | ||
| 352 | (u16)fll_desc_table_entry.ffr_cutoff_freq_mhz; | ||
| 353 | fll_dev_data.regime_desc.target_regime_id_override=0; | ||
| 354 | |||
| 355 | /*construct fll device*/ | ||
| 356 | pfll_dev = construct_fll_device(g, (void *)&fll_dev_data); | ||
| 357 | |||
| 358 | status = boardobjgrp_objinsert(&pfllobjs->super.super, | ||
| 359 | (struct boardobj *)pfll_dev, index); | ||
| 360 | fll_tbl_entry_ptr += fll_desc_table_header.entry_size; | ||
| 361 | } | ||
| 362 | |||
| 363 | done: | ||
| 364 | nvgpu_log_info(g, " done status %x", status); | ||
| 365 | return status; | ||
| 366 | } | ||
| 367 | |||
| 368 | u32 nvgpu_clk_get_vbios_clk_domain_gv10x( u32 vbios_domain) | ||
| 369 | { | ||
| 370 | if (vbios_domain == 0) { | ||
| 371 | return CTRL_CLK_DOMAIN_GPCCLK; | ||
| 372 | } else if (vbios_domain == 1) { | ||
| 373 | return CTRL_CLK_DOMAIN_XBARCLK; | ||
| 374 | } else if (vbios_domain == 3) { | ||
| 375 | return CTRL_CLK_DOMAIN_SYSCLK; | ||
| 376 | } else if (vbios_domain == 5) { | ||
| 377 | return CTRL_CLK_DOMAIN_NVDCLK; | ||
| 378 | } | ||
| 379 | return 0; | ||
| 380 | } | ||
| 381 | |||
| 382 | u32 nvgpu_clk_get_vbios_clk_domain_gp10x( u32 vbios_domain) | ||
| 383 | { | ||
| 384 | if (vbios_domain == 0) { | ||
| 385 | return CTRL_CLK_DOMAIN_GPC2CLK; | ||
| 386 | } else if (vbios_domain == 1) { | ||
| 387 | return CTRL_CLK_DOMAIN_XBAR2CLK; | ||
| 388 | } else if (vbios_domain == 3) { | ||
| 389 | return CTRL_CLK_DOMAIN_SYS2CLK; | ||
| 390 | } | ||
| 391 | return 0; | ||
| 392 | } | ||
| 393 | |||
| 394 | static u32 lutbroadcastslaveregister(struct gk20a *g, | ||
| 395 | struct avfsfllobjs *pfllobjs, | ||
| 396 | struct fll_device *pfll, | ||
| 397 | struct fll_device *pfll_slave) | ||
| 398 | { | ||
| 399 | if (pfll->clk_domain != pfll_slave->clk_domain) { | ||
| 400 | return -EINVAL; | ||
| 401 | } | ||
| 402 | |||
| 403 | return boardobjgrpmask_bitset(&pfll-> | ||
| 404 | lut_prog_broadcast_slave_mask.super, | ||
| 405 | BOARDOBJ_GET_IDX(pfll_slave)); | ||
| 406 | } | ||
| 407 | |||
| 408 | static struct fll_device *construct_fll_device(struct gk20a *g, | ||
| 409 | void *pargs) | ||
| 410 | { | ||
| 411 | struct boardobj *board_obj_ptr = NULL; | ||
| 412 | struct fll_device *pfll_dev; | ||
| 413 | struct fll_device *board_obj_fll_ptr = NULL; | ||
| 414 | int status; | ||
| 415 | |||
| 416 | nvgpu_log_info(g, " "); | ||
| 417 | status = boardobj_construct_super(g, &board_obj_ptr, | ||
| 418 | sizeof(struct fll_device), pargs); | ||
| 419 | if (status) { | ||
| 420 | return NULL; | ||
| 421 | } | ||
| 422 | |||
| 423 | pfll_dev = (struct fll_device *)pargs; | ||
| 424 | board_obj_fll_ptr = (struct fll_device *)board_obj_ptr; | ||
| 425 | board_obj_ptr->pmudatainit = fll_device_init_pmudata_super; | ||
| 426 | board_obj_fll_ptr->lut_broadcast_slave_register = | ||
| 427 | lutbroadcastslaveregister; | ||
| 428 | board_obj_fll_ptr->id = pfll_dev->id; | ||
| 429 | board_obj_fll_ptr->mdiv = pfll_dev->mdiv; | ||
| 430 | board_obj_fll_ptr->rail_idx_for_lut = pfll_dev->rail_idx_for_lut; | ||
| 431 | board_obj_fll_ptr->input_freq_mhz = pfll_dev->input_freq_mhz; | ||
| 432 | board_obj_fll_ptr->clk_domain = pfll_dev->clk_domain; | ||
| 433 | board_obj_fll_ptr->vin_idx_logic = pfll_dev->vin_idx_logic; | ||
| 434 | board_obj_fll_ptr->vin_idx_sram = pfll_dev->vin_idx_sram; | ||
| 435 | board_obj_fll_ptr->min_freq_vfe_idx = | ||
| 436 | pfll_dev->min_freq_vfe_idx; | ||
| 437 | board_obj_fll_ptr->freq_ctrl_idx = pfll_dev->freq_ctrl_idx; | ||
| 438 | board_obj_fll_ptr->b_skip_pldiv_below_dvco_min = | ||
| 439 | pfll_dev->b_skip_pldiv_below_dvco_min; | ||
| 440 | memcpy(&board_obj_fll_ptr->lut_device, &pfll_dev->lut_device, | ||
| 441 | sizeof(struct nv_pmu_clk_lut_device_desc)); | ||
| 442 | memcpy(&board_obj_fll_ptr->regime_desc, &pfll_dev->regime_desc, | ||
| 443 | sizeof(struct nv_pmu_clk_regime_desc)); | ||
| 444 | boardobjgrpmask_e32_init( | ||
| 445 | &board_obj_fll_ptr->lut_prog_broadcast_slave_mask, NULL); | ||
| 446 | |||
| 447 | nvgpu_log_info(g, " Done"); | ||
| 448 | |||
| 449 | return (struct fll_device *)board_obj_ptr; | ||
| 450 | } | ||
| 451 | |||
| 452 | static int fll_device_init_pmudata_super(struct gk20a *g, | ||
| 453 | struct boardobj *board_obj_ptr, | ||
| 454 | struct nv_pmu_boardobj *ppmudata) | ||
| 455 | { | ||
| 456 | int status = 0; | ||
| 457 | struct fll_device *pfll_dev; | ||
| 458 | struct nv_pmu_clk_clk_fll_device_boardobj_set *perf_pmu_data; | ||
| 459 | |||
| 460 | nvgpu_log_info(g, " "); | ||
| 461 | |||
| 462 | status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata); | ||
| 463 | if (status != 0) { | ||
| 464 | return status; | ||
| 465 | } | ||
| 466 | |||
| 467 | pfll_dev = (struct fll_device *)board_obj_ptr; | ||
| 468 | perf_pmu_data = (struct nv_pmu_clk_clk_fll_device_boardobj_set *) | ||
| 469 | ppmudata; | ||
| 470 | |||
| 471 | perf_pmu_data->id = pfll_dev->id; | ||
| 472 | perf_pmu_data->mdiv = pfll_dev->mdiv; | ||
| 473 | perf_pmu_data->rail_idx_for_lut = pfll_dev->rail_idx_for_lut; | ||
| 474 | perf_pmu_data->input_freq_mhz = pfll_dev->input_freq_mhz; | ||
| 475 | perf_pmu_data->vin_idx_logic = pfll_dev->vin_idx_logic; | ||
| 476 | perf_pmu_data->vin_idx_sram = pfll_dev->vin_idx_sram; | ||
| 477 | perf_pmu_data->clk_domain = pfll_dev->clk_domain; | ||
| 478 | perf_pmu_data->min_freq_vfe_idx = | ||
| 479 | pfll_dev->min_freq_vfe_idx; | ||
| 480 | perf_pmu_data->freq_ctrl_idx = pfll_dev->freq_ctrl_idx; | ||
| 481 | perf_pmu_data->b_skip_pldiv_below_dvco_min = pfll_dev->b_skip_pldiv_below_dvco_min; | ||
| 482 | memcpy(&perf_pmu_data->lut_device, &pfll_dev->lut_device, | ||
| 483 | sizeof(struct nv_pmu_clk_lut_device_desc)); | ||
| 484 | memcpy(&perf_pmu_data->regime_desc, &pfll_dev->regime_desc, | ||
| 485 | sizeof(struct nv_pmu_clk_regime_desc)); | ||
| 486 | |||
| 487 | status = boardobjgrpmask_export( | ||
| 488 | &pfll_dev->lut_prog_broadcast_slave_mask.super, | ||
| 489 | pfll_dev->lut_prog_broadcast_slave_mask.super.bitcount, | ||
| 490 | &perf_pmu_data->lut_prog_broadcast_slave_mask.super); | ||
| 491 | |||
| 492 | nvgpu_log_info(g, " Done"); | ||
| 493 | |||
| 494 | return status; | ||
| 495 | } | ||
diff --git a/include/clk/clk_fll.h b/include/clk/clk_fll.h deleted file mode 100644 index 6cbdfe2..0000000 --- a/include/clk/clk_fll.h +++ /dev/null | |||
| @@ -1,81 +0,0 @@ | |||
| 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 | #ifndef NVGPU_CLK_FLL_H | ||
| 24 | #define NVGPU_CLK_FLL_H | ||
| 25 | |||
| 26 | #include <nvgpu/pmuif/nvgpu_gpmu_cmdif.h> | ||
| 27 | #include "boardobj/boardobjgrp_e32.h" | ||
| 28 | #include "boardobj/boardobjgrpmask.h" | ||
| 29 | |||
| 30 | /*data and function definition to talk to driver*/ | ||
| 31 | int clk_fll_sw_setup(struct gk20a *g); | ||
| 32 | int clk_fll_pmu_setup(struct gk20a *g); | ||
| 33 | |||
| 34 | struct avfsfllobjs { | ||
| 35 | struct boardobjgrp_e32 super; | ||
| 36 | struct boardobjgrpmask_e32 lut_prog_master_mask; | ||
| 37 | u32 lut_step_size_uv; | ||
| 38 | u32 lut_min_voltage_uv; | ||
| 39 | u8 lut_num_entries; | ||
| 40 | u16 max_min_freq_mhz; | ||
| 41 | }; | ||
| 42 | |||
| 43 | struct fll_device; | ||
| 44 | |||
| 45 | typedef u32 fll_lut_broadcast_slave_register(struct gk20a *g, | ||
| 46 | struct avfsfllobjs *pfllobjs, | ||
| 47 | struct fll_device *pfll, | ||
| 48 | struct fll_device *pfll_slave); | ||
| 49 | |||
| 50 | struct fll_device { | ||
| 51 | struct boardobj super; | ||
| 52 | u8 id; | ||
| 53 | u8 mdiv; | ||
| 54 | u16 input_freq_mhz; | ||
| 55 | u32 clk_domain; | ||
| 56 | u8 vin_idx_logic; | ||
| 57 | u8 vin_idx_sram; | ||
| 58 | u8 rail_idx_for_lut; | ||
| 59 | struct nv_pmu_clk_lut_device_desc lut_device; | ||
| 60 | struct nv_pmu_clk_regime_desc regime_desc; | ||
| 61 | u8 min_freq_vfe_idx; | ||
| 62 | u8 freq_ctrl_idx; | ||
| 63 | u8 target_regime_id_override; | ||
| 64 | bool b_skip_pldiv_below_dvco_min; | ||
| 65 | bool b_dvco_1x; | ||
| 66 | struct boardobjgrpmask_e32 lut_prog_broadcast_slave_mask; | ||
| 67 | fll_lut_broadcast_slave_register *lut_broadcast_slave_register; | ||
| 68 | }; | ||
| 69 | |||
| 70 | u32 nvgpu_clk_get_vbios_clk_domain_gv10x( u32 vbios_domain); | ||
| 71 | u32 nvgpu_clk_get_vbios_clk_domain_gp10x( u32 vbios_domain); | ||
| 72 | |||
| 73 | #define CLK_FLL_LUT_VF_NUM_ENTRIES(pclk) \ | ||
| 74 | (pclk->avfs_fllobjs.lut_num_entries) | ||
| 75 | |||
| 76 | #define CLK_FLL_LUT_MIN_VOLTAGE_UV(pclk) \ | ||
| 77 | (pclk->avfs_fllobjs.lut_min_voltage_uv) | ||
| 78 | #define CLK_FLL_LUT_STEP_SIZE_UV(pclk) \ | ||
| 79 | (pclk->avfs_fllobjs.lut_step_size_uv) | ||
| 80 | |||
| 81 | #endif /* NVGPU_CLK_FLL_H */ | ||
diff --git a/include/clk/clk_freq_controller.c b/include/clk/clk_freq_controller.c deleted file mode 100644 index f4d09b0..0000000 --- a/include/clk/clk_freq_controller.c +++ /dev/null | |||
| @@ -1,462 +0,0 @@ | |||
| 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 "clk_freq_controller.h" | ||
| 30 | #include "boardobj/boardobjgrp.h" | ||
| 31 | #include "boardobj/boardobjgrp_e32.h" | ||
| 32 | #include "ctrl/ctrlclk.h" | ||
| 33 | #include "ctrl/ctrlvolt.h" | ||
| 34 | |||
| 35 | static int clk_freq_controller_pmudatainit_super(struct gk20a *g, | ||
| 36 | struct boardobj *board_obj_ptr, | ||
| 37 | struct nv_pmu_boardobj *ppmudata) | ||
| 38 | { | ||
| 39 | struct nv_pmu_clk_clk_freq_controller_boardobj_set *pfreq_cntlr_set; | ||
| 40 | struct clk_freq_controller *pfreq_cntlr; | ||
| 41 | int status = 0; | ||
| 42 | |||
| 43 | status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata); | ||
| 44 | if (status) { | ||
| 45 | return status; | ||
| 46 | } | ||
| 47 | |||
| 48 | pfreq_cntlr_set = | ||
| 49 | (struct nv_pmu_clk_clk_freq_controller_boardobj_set *)ppmudata; | ||
| 50 | pfreq_cntlr = (struct clk_freq_controller *)board_obj_ptr; | ||
| 51 | |||
| 52 | pfreq_cntlr_set->controller_id = pfreq_cntlr->controller_id; | ||
| 53 | pfreq_cntlr_set->clk_domain = pfreq_cntlr->clk_domain; | ||
| 54 | pfreq_cntlr_set->parts_freq_mode = pfreq_cntlr->parts_freq_mode; | ||
| 55 | pfreq_cntlr_set->bdisable = pfreq_cntlr->bdisable; | ||
| 56 | pfreq_cntlr_set->freq_cap_noise_unaware_vmin_above = | ||
| 57 | pfreq_cntlr->freq_cap_noise_unaware_vmin_above; | ||
| 58 | pfreq_cntlr_set->freq_cap_noise_unaware_vmin_below = | ||
| 59 | pfreq_cntlr->freq_cap_noise_unaware_vmin_below; | ||
| 60 | pfreq_cntlr_set->freq_hyst_pos_mhz = pfreq_cntlr->freq_hyst_pos_mhz; | ||
| 61 | pfreq_cntlr_set->freq_hyst_neg_mhz = pfreq_cntlr->freq_hyst_neg_mhz; | ||
| 62 | |||
| 63 | return status; | ||
| 64 | } | ||
| 65 | |||
| 66 | static int clk_freq_controller_pmudatainit_pi(struct gk20a *g, | ||
| 67 | struct boardobj *board_obj_ptr, | ||
| 68 | struct nv_pmu_boardobj *ppmudata) | ||
| 69 | { | ||
| 70 | struct nv_pmu_clk_clk_freq_controller_pi_boardobj_set | ||
| 71 | *pfreq_cntlr_pi_set; | ||
| 72 | struct clk_freq_controller_pi *pfreq_cntlr_pi; | ||
| 73 | int status = 0; | ||
| 74 | |||
| 75 | status = clk_freq_controller_pmudatainit_super(g, | ||
| 76 | board_obj_ptr, ppmudata); | ||
| 77 | if (status) { | ||
| 78 | return -1; | ||
| 79 | } | ||
| 80 | |||
| 81 | pfreq_cntlr_pi_set = | ||
| 82 | (struct nv_pmu_clk_clk_freq_controller_pi_boardobj_set *) | ||
| 83 | ppmudata; | ||
| 84 | pfreq_cntlr_pi = (struct clk_freq_controller_pi *)board_obj_ptr; | ||
| 85 | |||
| 86 | pfreq_cntlr_pi_set->prop_gain = pfreq_cntlr_pi->prop_gain; | ||
| 87 | pfreq_cntlr_pi_set->integ_gain = pfreq_cntlr_pi->integ_gain; | ||
| 88 | pfreq_cntlr_pi_set->integ_decay = pfreq_cntlr_pi->integ_decay; | ||
| 89 | pfreq_cntlr_pi_set->volt_delta_min = pfreq_cntlr_pi->volt_delta_min; | ||
| 90 | pfreq_cntlr_pi_set->volt_delta_max = pfreq_cntlr_pi->volt_delta_max; | ||
| 91 | pfreq_cntlr_pi_set->slowdown_pct_min = pfreq_cntlr_pi->slowdown_pct_min; | ||
| 92 | pfreq_cntlr_pi_set->bpoison = pfreq_cntlr_pi->bpoison; | ||
| 93 | |||
| 94 | return status; | ||
| 95 | } | ||
| 96 | |||
| 97 | static int clk_freq_controller_construct_super(struct gk20a *g, | ||
| 98 | struct boardobj **ppboardobj, | ||
| 99 | u16 size, void *pargs) | ||
| 100 | { | ||
| 101 | struct clk_freq_controller *pfreq_cntlr = NULL; | ||
| 102 | struct clk_freq_controller *pfreq_cntlr_tmp = NULL; | ||
| 103 | int status = 0; | ||
| 104 | |||
| 105 | status = boardobj_construct_super(g, ppboardobj, size, pargs); | ||
| 106 | if (status) { | ||
| 107 | return -EINVAL; | ||
| 108 | } | ||
| 109 | |||
| 110 | pfreq_cntlr_tmp = (struct clk_freq_controller *)pargs; | ||
| 111 | pfreq_cntlr = (struct clk_freq_controller *)*ppboardobj; | ||
| 112 | |||
| 113 | pfreq_cntlr->super.pmudatainit = clk_freq_controller_pmudatainit_super; | ||
| 114 | |||
| 115 | pfreq_cntlr->controller_id = pfreq_cntlr_tmp->controller_id; | ||
| 116 | pfreq_cntlr->clk_domain = pfreq_cntlr_tmp->clk_domain; | ||
| 117 | pfreq_cntlr->parts_freq_mode = pfreq_cntlr_tmp->parts_freq_mode; | ||
| 118 | pfreq_cntlr->freq_cap_noise_unaware_vmin_above = | ||
| 119 | pfreq_cntlr_tmp->freq_cap_noise_unaware_vmin_above; | ||
| 120 | pfreq_cntlr->freq_cap_noise_unaware_vmin_below = | ||
| 121 | pfreq_cntlr_tmp->freq_cap_noise_unaware_vmin_below; | ||
| 122 | pfreq_cntlr->freq_hyst_pos_mhz = pfreq_cntlr_tmp->freq_hyst_pos_mhz; | ||
| 123 | pfreq_cntlr->freq_hyst_neg_mhz = pfreq_cntlr_tmp->freq_hyst_neg_mhz; | ||
| 124 | |||
| 125 | return status; | ||
| 126 | } | ||
| 127 | |||
| 128 | static int clk_freq_controller_construct_pi(struct gk20a *g, | ||
| 129 | struct boardobj **ppboardobj, | ||
| 130 | u16 size, void *pargs) | ||
| 131 | { | ||
| 132 | struct clk_freq_controller_pi *pfreq_cntlr_pi = NULL; | ||
| 133 | struct clk_freq_controller_pi *pfreq_cntlr_pi_tmp = NULL; | ||
| 134 | int status = 0; | ||
| 135 | |||
| 136 | status = clk_freq_controller_construct_super(g, ppboardobj, | ||
| 137 | size, pargs); | ||
| 138 | if (status) { | ||
| 139 | return -EINVAL; | ||
| 140 | } | ||
| 141 | |||
| 142 | pfreq_cntlr_pi = (struct clk_freq_controller_pi *)*ppboardobj; | ||
| 143 | pfreq_cntlr_pi_tmp = (struct clk_freq_controller_pi *)pargs; | ||
| 144 | |||
| 145 | pfreq_cntlr_pi->super.super.pmudatainit = | ||
| 146 | clk_freq_controller_pmudatainit_pi; | ||
| 147 | |||
| 148 | pfreq_cntlr_pi->prop_gain = pfreq_cntlr_pi_tmp->prop_gain; | ||
| 149 | pfreq_cntlr_pi->integ_gain = pfreq_cntlr_pi_tmp->integ_gain; | ||
| 150 | pfreq_cntlr_pi->integ_decay = pfreq_cntlr_pi_tmp->integ_decay; | ||
| 151 | pfreq_cntlr_pi->volt_delta_min = pfreq_cntlr_pi_tmp->volt_delta_min; | ||
| 152 | pfreq_cntlr_pi->volt_delta_max = pfreq_cntlr_pi_tmp->volt_delta_max; | ||
| 153 | pfreq_cntlr_pi->slowdown_pct_min = pfreq_cntlr_pi_tmp->slowdown_pct_min; | ||
| 154 | pfreq_cntlr_pi->bpoison = pfreq_cntlr_pi_tmp->bpoison; | ||
| 155 | |||
| 156 | return status; | ||
| 157 | } | ||
| 158 | |||
| 159 | static struct clk_freq_controller *clk_clk_freq_controller_construct( | ||
| 160 | struct gk20a *g, | ||
| 161 | void *pargs) | ||
| 162 | { | ||
| 163 | struct boardobj *board_obj_ptr = NULL; | ||
| 164 | int status = 0; | ||
| 165 | |||
| 166 | if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_FREQ_CONTROLLER_TYPE_PI) { | ||
| 167 | return NULL; | ||
| 168 | } | ||
| 169 | |||
| 170 | status = clk_freq_controller_construct_pi(g, &board_obj_ptr, | ||
| 171 | sizeof(struct clk_freq_controller_pi), pargs); | ||
| 172 | if (status) { | ||
| 173 | return NULL; | ||
| 174 | } | ||
| 175 | |||
| 176 | return (struct clk_freq_controller *)board_obj_ptr; | ||
| 177 | } | ||
| 178 | |||
| 179 | |||
| 180 | static int clk_get_freq_controller_table(struct gk20a *g, | ||
| 181 | struct clk_freq_controllers *pclk_freq_controllers) | ||
| 182 | { | ||
| 183 | int status = 0; | ||
| 184 | u8 *pfreq_controller_table_ptr = NULL; | ||
| 185 | struct vbios_fct_1x_header header = { 0 }; | ||
| 186 | struct vbios_fct_1x_entry entry = { 0 }; | ||
| 187 | u8 entry_idx; | ||
| 188 | u8 *entry_offset; | ||
| 189 | struct clk_freq_controller *pclk_freq_cntr = NULL; | ||
| 190 | struct clk_freq_controller *ptmp_freq_cntr = NULL; | ||
| 191 | struct clk_freq_controller_pi *ptmp_freq_cntr_pi = NULL; | ||
| 192 | struct clk_domain *pclk_domain; | ||
| 193 | |||
| 194 | struct freq_controller_data_type { | ||
| 195 | union { | ||
| 196 | struct boardobj board_obj; | ||
| 197 | struct clk_freq_controller freq_controller; | ||
| 198 | struct clk_freq_controller_pi freq_controller_pi; | ||
| 199 | }; | ||
| 200 | } freq_controller_data; | ||
| 201 | |||
| 202 | pfreq_controller_table_ptr = | ||
| 203 | (u8 *)nvgpu_bios_get_perf_table_ptrs(g, | ||
| 204 | g->bios.clock_token, | ||
| 205 | FREQUENCY_CONTROLLER_TABLE); | ||
| 206 | if (pfreq_controller_table_ptr == NULL) { | ||
| 207 | status = -EINVAL; | ||
| 208 | goto done; | ||
| 209 | } | ||
| 210 | |||
| 211 | memcpy(&header, pfreq_controller_table_ptr, | ||
| 212 | sizeof(struct vbios_fct_1x_header)); | ||
| 213 | |||
| 214 | pclk_freq_controllers->sampling_period_ms = header.sampling_period_ms; | ||
| 215 | pclk_freq_controllers->volt_policy_idx = 0; | ||
| 216 | |||
| 217 | /* Read in the entries. */ | ||
| 218 | for (entry_idx = 0; entry_idx < header.entry_count; entry_idx++) { | ||
| 219 | entry_offset = (pfreq_controller_table_ptr + | ||
| 220 | header.header_size + (entry_idx * header.entry_size)); | ||
| 221 | |||
| 222 | memset(&freq_controller_data, 0x0, | ||
| 223 | sizeof(struct freq_controller_data_type)); | ||
| 224 | ptmp_freq_cntr = &freq_controller_data.freq_controller; | ||
| 225 | ptmp_freq_cntr_pi = &freq_controller_data.freq_controller_pi; | ||
| 226 | |||
| 227 | memcpy(&entry, entry_offset, | ||
| 228 | sizeof(struct vbios_fct_1x_entry)); | ||
| 229 | |||
| 230 | if (!BIOS_GET_FIELD(entry.flags0, | ||
| 231 | NV_VBIOS_FCT_1X_ENTRY_FLAGS0_TYPE)) { | ||
| 232 | continue; | ||
| 233 | } | ||
| 234 | |||
| 235 | freq_controller_data.board_obj.type = (u8)BIOS_GET_FIELD( | ||
| 236 | entry.flags0, NV_VBIOS_FCT_1X_ENTRY_FLAGS0_TYPE); | ||
| 237 | |||
| 238 | ptmp_freq_cntr->controller_id = | ||
| 239 | (u8)BIOS_GET_FIELD(entry.param0, | ||
| 240 | NV_VBIOS_FCT_1X_ENTRY_PARAM0_ID); | ||
| 241 | |||
| 242 | pclk_domain = CLK_CLK_DOMAIN_GET((&g->clk_pmu), | ||
| 243 | (u32)entry.clk_domain_idx); | ||
| 244 | freq_controller_data.freq_controller.clk_domain = | ||
| 245 | pclk_domain->api_domain; | ||
| 246 | |||
| 247 | ptmp_freq_cntr->parts_freq_mode = | ||
| 248 | (u8)BIOS_GET_FIELD(entry.param0, | ||
| 249 | NV_VBIOS_FCT_1X_ENTRY_PARAM0_FREQ_MODE); | ||
| 250 | |||
| 251 | /* Populate PI specific data */ | ||
| 252 | ptmp_freq_cntr_pi->slowdown_pct_min = | ||
| 253 | (u8)BIOS_GET_FIELD(entry.param1, | ||
| 254 | NV_VBIOS_FCT_1X_ENTRY_PARAM1_SLOWDOWN_PCT_MIN); | ||
| 255 | |||
| 256 | ptmp_freq_cntr_pi->bpoison = | ||
| 257 | BIOS_GET_FIELD(entry.param1, | ||
| 258 | NV_VBIOS_FCT_1X_ENTRY_PARAM1_POISON); | ||
| 259 | |||
| 260 | ptmp_freq_cntr_pi->prop_gain = | ||
| 261 | (s32)BIOS_GET_FIELD(entry.param2, | ||
| 262 | NV_VBIOS_FCT_1X_ENTRY_PARAM2_PROP_GAIN); | ||
| 263 | |||
| 264 | ptmp_freq_cntr_pi->integ_gain = | ||
| 265 | (s32)BIOS_GET_FIELD(entry.param3, | ||
| 266 | NV_VBIOS_FCT_1X_ENTRY_PARAM3_INTEG_GAIN); | ||
| 267 | |||
| 268 | ptmp_freq_cntr_pi->integ_decay = | ||
| 269 | (s32)BIOS_GET_FIELD(entry.param4, | ||
| 270 | NV_VBIOS_FCT_1X_ENTRY_PARAM4_INTEG_DECAY); | ||
| 271 | |||
| 272 | ptmp_freq_cntr_pi->volt_delta_min = | ||
| 273 | (s32)BIOS_GET_FIELD(entry.param5, | ||
| 274 | NV_VBIOS_FCT_1X_ENTRY_PARAM5_VOLT_DELTA_MIN); | ||
| 275 | |||
| 276 | ptmp_freq_cntr_pi->volt_delta_max = | ||
| 277 | (s32)BIOS_GET_FIELD(entry.param6, | ||
| 278 | NV_VBIOS_FCT_1X_ENTRY_PARAM6_VOLT_DELTA_MAX); | ||
| 279 | |||
| 280 | ptmp_freq_cntr->freq_cap_noise_unaware_vmin_above = | ||
| 281 | (s16)BIOS_GET_FIELD(entry.param7, | ||
| 282 | NV_VBIOS_FCT_1X_ENTRY_PARAM7_FREQ_CAP_VF); | ||
| 283 | |||
| 284 | ptmp_freq_cntr->freq_cap_noise_unaware_vmin_below = | ||
| 285 | (s16)BIOS_GET_FIELD(entry.param7, | ||
| 286 | NV_VBIOS_FCT_1X_ENTRY_PARAM7_FREQ_CAP_VMIN); | ||
| 287 | |||
| 288 | ptmp_freq_cntr->freq_hyst_pos_mhz = | ||
| 289 | (s16)BIOS_GET_FIELD(entry.param8, | ||
| 290 | NV_VBIOS_FCT_1X_ENTRY_PARAM8_FREQ_HYST_POS); | ||
| 291 | ptmp_freq_cntr->freq_hyst_neg_mhz = | ||
| 292 | (s16)BIOS_GET_FIELD(entry.param8, | ||
| 293 | NV_VBIOS_FCT_1X_ENTRY_PARAM8_FREQ_HYST_NEG); | ||
| 294 | |||
| 295 | if (ptmp_freq_cntr_pi->volt_delta_max < | ||
| 296 | ptmp_freq_cntr_pi->volt_delta_min) { | ||
| 297 | goto done; | ||
| 298 | } | ||
| 299 | |||
| 300 | pclk_freq_cntr = clk_clk_freq_controller_construct(g, | ||
| 301 | (void *)&freq_controller_data); | ||
| 302 | |||
| 303 | if (pclk_freq_cntr == NULL) { | ||
| 304 | nvgpu_err(g, | ||
| 305 | "unable to construct clock freq cntlr boardobj for %d", | ||
| 306 | entry_idx); | ||
| 307 | status = -EINVAL; | ||
| 308 | goto done; | ||
| 309 | } | ||
| 310 | |||
| 311 | status = boardobjgrp_objinsert( | ||
| 312 | &pclk_freq_controllers->super.super, | ||
| 313 | (struct boardobj *)pclk_freq_cntr, entry_idx); | ||
| 314 | if (status) { | ||
| 315 | nvgpu_err(g, | ||
| 316 | "unable to insert clock freq cntlr boardobj for"); | ||
| 317 | status = -EINVAL; | ||
| 318 | goto done; | ||
| 319 | } | ||
| 320 | |||
| 321 | } | ||
| 322 | |||
| 323 | done: | ||
| 324 | return status; | ||
| 325 | } | ||
| 326 | |||
| 327 | int clk_freq_controller_pmu_setup(struct gk20a *g) | ||
| 328 | { | ||
| 329 | int status; | ||
| 330 | struct boardobjgrp *pboardobjgrp = NULL; | ||
| 331 | |||
| 332 | nvgpu_log_info(g, " "); | ||
| 333 | |||
| 334 | pboardobjgrp = &g->clk_pmu.clk_freq_controllers.super.super; | ||
| 335 | |||
| 336 | if (!pboardobjgrp->bconstructed) { | ||
| 337 | return -EINVAL; | ||
| 338 | } | ||
| 339 | |||
| 340 | status = pboardobjgrp->pmuinithandle(g, pboardobjgrp); | ||
| 341 | |||
| 342 | nvgpu_log_info(g, "Done"); | ||
| 343 | return status; | ||
| 344 | } | ||
| 345 | |||
| 346 | static int _clk_freq_controller_devgrp_pmudata_instget(struct gk20a *g, | ||
| 347 | struct nv_pmu_boardobjgrp *pmuboardobjgrp, | ||
| 348 | struct nv_pmu_boardobj **ppboardobjpmudata, | ||
| 349 | u8 idx) | ||
| 350 | { | ||
| 351 | struct nv_pmu_clk_clk_freq_controller_boardobj_grp_set *pgrp_set = | ||
| 352 | (struct nv_pmu_clk_clk_freq_controller_boardobj_grp_set *) | ||
| 353 | pmuboardobjgrp; | ||
| 354 | |||
| 355 | nvgpu_log_info(g, " "); | ||
| 356 | |||
| 357 | /*check whether pmuboardobjgrp has a valid boardobj in index*/ | ||
| 358 | if (((u32)BIT(idx) & | ||
| 359 | pgrp_set->hdr.data.super.obj_mask.super.data[0]) == 0) { | ||
| 360 | return -EINVAL; | ||
| 361 | } | ||
| 362 | |||
| 363 | *ppboardobjpmudata = (struct nv_pmu_boardobj *) | ||
| 364 | &pgrp_set->objects[idx].data.board_obj; | ||
| 365 | nvgpu_log_info(g, " Done"); | ||
| 366 | return 0; | ||
| 367 | } | ||
| 368 | |||
| 369 | static int _clk_freq_controllers_pmudatainit(struct gk20a *g, | ||
| 370 | struct boardobjgrp *pboardobjgrp, | ||
| 371 | struct nv_pmu_boardobjgrp_super *pboardobjgrppmu) | ||
| 372 | { | ||
| 373 | struct nv_pmu_clk_clk_freq_controller_boardobjgrp_set_header *pset = | ||
| 374 | (struct nv_pmu_clk_clk_freq_controller_boardobjgrp_set_header *) | ||
| 375 | pboardobjgrppmu; | ||
| 376 | struct clk_freq_controllers *pcntrs = | ||
| 377 | (struct clk_freq_controllers *)pboardobjgrp; | ||
| 378 | int status = 0; | ||
| 379 | |||
| 380 | status = boardobjgrp_pmudatainit_e32(g, pboardobjgrp, pboardobjgrppmu); | ||
| 381 | if (status) { | ||
| 382 | nvgpu_err(g, | ||
| 383 | "error updating pmu boardobjgrp for clk freq ctrs 0x%x", | ||
| 384 | status); | ||
| 385 | goto done; | ||
| 386 | } | ||
| 387 | pset->sampling_period_ms = pcntrs->sampling_period_ms; | ||
| 388 | pset->volt_policy_idx = pcntrs->volt_policy_idx; | ||
| 389 | |||
| 390 | done: | ||
| 391 | return status; | ||
| 392 | } | ||
| 393 | |||
| 394 | int clk_freq_controller_sw_setup(struct gk20a *g) | ||
| 395 | { | ||
| 396 | int status = 0; | ||
| 397 | struct boardobjgrp *pboardobjgrp = NULL; | ||
| 398 | struct clk_freq_controllers *pclk_freq_controllers; | ||
| 399 | struct avfsfllobjs *pfllobjs = &(g->clk_pmu.avfs_fllobjs); | ||
| 400 | struct fll_device *pfll; | ||
| 401 | struct clk_freq_controller *pclkfreqctrl; | ||
| 402 | u8 i; | ||
| 403 | u8 j; | ||
| 404 | |||
| 405 | nvgpu_log_info(g, " "); | ||
| 406 | |||
| 407 | pclk_freq_controllers = &g->clk_pmu.clk_freq_controllers; | ||
| 408 | status = boardobjgrpconstruct_e32(g, &pclk_freq_controllers->super); | ||
| 409 | if (status) { | ||
| 410 | nvgpu_err(g, | ||
| 411 | "error creating boardobjgrp for clk FCT, status - 0x%x", | ||
| 412 | status); | ||
| 413 | goto done; | ||
| 414 | } | ||
| 415 | |||
| 416 | pboardobjgrp = &g->clk_pmu.clk_freq_controllers.super.super; | ||
| 417 | |||
| 418 | pboardobjgrp->pmudatainit = _clk_freq_controllers_pmudatainit; | ||
| 419 | pboardobjgrp->pmudatainstget = | ||
| 420 | _clk_freq_controller_devgrp_pmudata_instget; | ||
| 421 | pboardobjgrp->pmustatusinstget = NULL; | ||
| 422 | |||
| 423 | /* Initialize mask to zero.*/ | ||
| 424 | boardobjgrpmask_e32_init(&pclk_freq_controllers->freq_ctrl_load_mask, | ||
| 425 | NULL); | ||
| 426 | |||
| 427 | BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, CLK, CLK_FREQ_CONTROLLER); | ||
| 428 | |||
| 429 | status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp, | ||
| 430 | clk, CLK, clk_freq_controller, CLK_FREQ_CONTROLLER); | ||
| 431 | if (status) { | ||
| 432 | nvgpu_err(g, | ||
| 433 | "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x", | ||
| 434 | status); | ||
| 435 | goto done; | ||
| 436 | } | ||
| 437 | |||
| 438 | status = clk_get_freq_controller_table(g, pclk_freq_controllers); | ||
| 439 | if (status) { | ||
| 440 | nvgpu_err(g, "error reading freq controller table - 0x%x", | ||
| 441 | status); | ||
| 442 | goto done; | ||
| 443 | } | ||
| 444 | |||
| 445 | BOARDOBJGRP_FOR_EACH(&(pclk_freq_controllers->super.super), | ||
| 446 | struct clk_freq_controller *, pclkfreqctrl, i) { | ||
| 447 | pfll = NULL; | ||
| 448 | j = 0; | ||
| 449 | BOARDOBJGRP_FOR_EACH(&(pfllobjs->super.super), | ||
| 450 | struct fll_device *, pfll, j) { | ||
| 451 | if (pclkfreqctrl->controller_id == pfll->id) { | ||
| 452 | pfll->freq_ctrl_idx = i; | ||
| 453 | break; | ||
| 454 | } | ||
| 455 | } | ||
| 456 | boardobjgrpmask_bitset(&pclk_freq_controllers-> | ||
| 457 | freq_ctrl_load_mask.super, i); | ||
| 458 | } | ||
| 459 | done: | ||
| 460 | nvgpu_log_info(g, " done status %x", status); | ||
| 461 | return status; | ||
| 462 | } | ||
diff --git a/include/clk/clk_freq_controller.h b/include/clk/clk_freq_controller.h deleted file mode 100644 index 7ae475c..0000000 --- a/include/clk/clk_freq_controller.h +++ /dev/null | |||
| @@ -1,84 +0,0 @@ | |||
| 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 | #ifndef NVGPU_CLK_FREQ_CONTROLLER_H | ||
| 24 | #define NVGPU_CLK_FREQ_CONTROLLER_H | ||
| 25 | |||
| 26 | #define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_ALL 0xFF | ||
| 27 | #define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_SYS 0x00 | ||
| 28 | #define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_LTC 0x01 | ||
| 29 | #define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_XBAR 0x02 | ||
| 30 | #define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC0 0x03 | ||
| 31 | #define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC1 0x04 | ||
| 32 | #define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC2 0x05 | ||
| 33 | #define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC3 0x06 | ||
| 34 | #define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC4 0x07 | ||
| 35 | #define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC5 0x08 | ||
| 36 | #define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPCS 0x09 | ||
| 37 | |||
| 38 | #define CTRL_CLK_CLK_FREQ_CONTROLLER_MASK_UNICAST_GPC \ | ||
| 39 | (BIT(CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC0) | \ | ||
| 40 | BIT(CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC1) | \ | ||
| 41 | BIT(CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC2) | \ | ||
| 42 | BIT(CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC3) | \ | ||
| 43 | BIT(CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC4) | \ | ||
| 44 | BIT(CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC5)) | ||
| 45 | |||
| 46 | #define CTRL_CLK_CLK_FREQ_CONTROLLER_TYPE_DISABLED 0x00 | ||
| 47 | #define CTRL_CLK_CLK_FREQ_CONTROLLER_TYPE_PI 0x01 | ||
| 48 | |||
| 49 | |||
| 50 | struct clk_freq_controller { | ||
| 51 | struct boardobj super; | ||
| 52 | u8 controller_id; | ||
| 53 | u8 parts_freq_mode; | ||
| 54 | bool bdisable; | ||
| 55 | u32 clk_domain; | ||
| 56 | s16 freq_cap_noise_unaware_vmin_above; | ||
| 57 | s16 freq_cap_noise_unaware_vmin_below; | ||
| 58 | s16 freq_hyst_pos_mhz; | ||
| 59 | s16 freq_hyst_neg_mhz; | ||
| 60 | }; | ||
| 61 | |||
| 62 | struct clk_freq_controller_pi { | ||
| 63 | struct clk_freq_controller super; | ||
| 64 | s32 prop_gain; | ||
| 65 | s32 integ_gain; | ||
| 66 | s32 integ_decay; | ||
| 67 | s32 volt_delta_min; | ||
| 68 | s32 volt_delta_max; | ||
| 69 | u8 slowdown_pct_min; | ||
| 70 | bool bpoison; | ||
| 71 | }; | ||
| 72 | |||
| 73 | struct clk_freq_controllers { | ||
| 74 | struct boardobjgrp_e32 super; | ||
| 75 | u32 sampling_period_ms; | ||
| 76 | struct boardobjgrpmask_e32 freq_ctrl_load_mask; | ||
| 77 | u8 volt_policy_idx; | ||
| 78 | void *pprereq_load; | ||
| 79 | }; | ||
| 80 | |||
| 81 | int clk_freq_controller_sw_setup(struct gk20a *g); | ||
| 82 | int clk_freq_controller_pmu_setup(struct gk20a *g); | ||
| 83 | |||
| 84 | #endif /* NVGPU_CLK_FREQ_CONTROLLER_H */ | ||
diff --git a/include/clk/clk_mclk.h b/include/clk/clk_mclk.h deleted file mode 100644 index 47c81d1..0000000 --- a/include/clk/clk_mclk.h +++ /dev/null | |||
| @@ -1,60 +0,0 @@ | |||
| 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 | #ifndef NVGPU_CLK_MCLK_H | ||
| 24 | #define NVGPU_CLK_MCLK_H | ||
| 25 | |||
| 26 | #include <nvgpu/lock.h> | ||
| 27 | |||
| 28 | #define GP106_MCLK_LOW_SPEED 0U | ||
| 29 | #define GP106_MCLK_MID_SPEED 1U | ||
| 30 | #define GP106_MCLK_HIGH_SPEED 2U | ||
| 31 | #define GP106_MCLK_NUM_SPEED 3U | ||
| 32 | |||
| 33 | enum gk20a_mclk_speed { | ||
| 34 | gk20a_mclk_low_speed, | ||
| 35 | gk20a_mclk_mid_speed, | ||
| 36 | gk20a_mclk_high_speed, | ||
| 37 | }; | ||
| 38 | |||
| 39 | struct clk_mclk_state { | ||
| 40 | u32 speed; | ||
| 41 | struct nvgpu_mutex mclk_lock; | ||
| 42 | struct nvgpu_mutex data_lock; | ||
| 43 | |||
| 44 | u16 p5_min; | ||
| 45 | u16 p0_min; | ||
| 46 | |||
| 47 | void *vreg_buf; | ||
| 48 | bool init; | ||
| 49 | |||
| 50 | #ifdef CONFIG_DEBUG_FS | ||
| 51 | s64 switch_max; | ||
| 52 | s64 switch_min; | ||
| 53 | u64 switch_num; | ||
| 54 | s64 switch_avg; | ||
| 55 | s64 switch_std; | ||
| 56 | bool debugfs_set; | ||
| 57 | #endif | ||
| 58 | }; | ||
| 59 | |||
| 60 | #endif /* NVGPU_CLK_MCLK_H */ | ||
diff --git a/include/clk/clk_prog.c b/include/clk/clk_prog.c deleted file mode 100644 index 9d44d6d..0000000 --- a/include/clk/clk_prog.c +++ /dev/null | |||
| @@ -1,1152 +0,0 @@ | |||
| 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 | |||
| 36 | static struct clk_prog *construct_clk_prog(struct gk20a *g, void *pargs); | ||
| 37 | static int devinit_get_clk_prog_table(struct gk20a *g, | ||
| 38 | struct clk_progs *pprogobjs); | ||
| 39 | static vf_flatten vfflatten_prog_1x_master; | ||
| 40 | static vf_lookup vflookup_prog_1x_master; | ||
| 41 | static get_fpoints getfpoints_prog_1x_master; | ||
| 42 | static get_slaveclk getslaveclk_prog_1x_master; | ||
| 43 | |||
| 44 | static 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 | |||
| 63 | done: | ||
| 64 | return status; | ||
| 65 | } | ||
| 66 | |||
| 67 | static 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 | |||
| 89 | int 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 | |||
| 134 | done: | ||
| 135 | nvgpu_log_info(g, " done status %x", status); | ||
| 136 | return status; | ||
| 137 | } | ||
| 138 | |||
| 139 | int 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 | |||
| 158 | static 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 | } | ||
| 226 | slaveszfmt = header.slave_entry_size; | ||
| 227 | if (header.vf_entry_count > CTRL_CLK_CLK_DELTA_MAX_VOLT_RAILS) { | ||
| 228 | status = -EINVAL; | ||
| 229 | goto done; | ||
| 230 | } | ||
| 231 | |||
| 232 | pclkprogobjs->slave_entry_count = header.slave_entry_count; | ||
| 233 | pclkprogobjs->vf_entry_count = header.vf_entry_count; | ||
| 234 | |||
| 235 | for (i = 0; i < header.entry_count; i++) { | ||
| 236 | memset(&prog_data, 0x0, (u32)sizeof(prog_data)); | ||
| 237 | |||
| 238 | /* Read table entries*/ | ||
| 239 | entry = clkprogs_tbl_ptr + hszfmt + | ||
| 240 | (i * (szfmt + (header.slave_entry_count * slaveszfmt) + | ||
| 241 | (header.vf_entry_count * vfszfmt))); | ||
| 242 | |||
| 243 | memcpy(&prog, entry, szfmt); | ||
| 244 | memset(vfentries, 0xFF, | ||
| 245 | sizeof(struct ctrl_clk_clk_prog_1x_master_vf_entry) * | ||
| 246 | CTRL_CLK_CLK_PROG_1X_MASTER_VF_ENTRY_MAX_ENTRIES); | ||
| 247 | memset(ratioslaveentries, 0xFF, | ||
| 248 | sizeof(struct ctrl_clk_clk_prog_1x_master_ratio_slave_entry) * | ||
| 249 | CTRL_CLK_PROG_1X_MASTER_MAX_SLAVE_ENTRIES); | ||
| 250 | memset(tableslaveentries, 0xFF, | ||
| 251 | sizeof(struct ctrl_clk_clk_prog_1x_master_table_slave_entry) * | ||
| 252 | CTRL_CLK_PROG_1X_MASTER_MAX_SLAVE_ENTRIES); | ||
| 253 | prog_type = (u8)BIOS_GET_FIELD(prog.flags0, | ||
| 254 | NV_VBIOS_CLOCK_PROGRAMMING_TABLE_1X_ENTRY_FLAGS0_SOURCE); | ||
| 255 | |||
| 256 | switch (prog_type) { | ||
| 257 | case NV_VBIOS_CLOCK_PROGRAMMING_TABLE_1X_ENTRY_FLAGS0_SOURCE_PLL: | ||
| 258 | prog_data.v1x.source = CTRL_CLK_PROG_1X_SOURCE_PLL; | ||
| 259 | prog_data.v1x.source_data.pll.pll_idx = | ||
| 260 | (u8)BIOS_GET_FIELD(prog.param0, | ||
| 261 | NV_VBIOS_CLOCK_PROGRAMMING_TABLE_1X_ENTRY_PARAM0_PLL_PLL_INDEX); | ||
| 262 | prog_data.v1x.source_data.pll.freq_step_size_mhz = | ||
| 263 | (u8)BIOS_GET_FIELD(prog.param1, | ||
| 264 | NV_VBIOS_CLOCK_PROGRAMMING_TABLE_1X_ENTRY_PARAM1_PLL_FREQ_STEP_SIZE); | ||
| 265 | break; | ||
| 266 | |||
| 267 | case NV_VBIOS_CLOCK_PROGRAMMING_TABLE_1X_ENTRY_FLAGS0_SOURCE_ONE_SOURCE: | ||
| 268 | prog_data.v1x.source = CTRL_CLK_PROG_1X_SOURCE_ONE_SOURCE; | ||
| 269 | break; | ||
| 270 | |||
| 271 | case NV_VBIOS_CLOCK_PROGRAMMING_TABLE_1X_ENTRY_FLAGS0_SOURCE_FLL: | ||
| 272 | prog_data.v1x.source = CTRL_CLK_PROG_1X_SOURCE_FLL; | ||
| 273 | break; | ||
| 274 | |||
| 275 | default: | ||
| 276 | nvgpu_err(g, "invalid source %d", prog_type); | ||
| 277 | status = -EINVAL; | ||
| 278 | goto done; | ||
| 279 | } | ||
| 280 | |||
| 281 | prog_data.v1x.freq_max_mhz = (u16)prog.freq_max_mhz; | ||
| 282 | |||
| 283 | prog_type = (u8)BIOS_GET_FIELD(prog.flags0, | ||
| 284 | NV_VBIOS_CLOCK_PROGRAMMING_TABLE_1X_ENTRY_FLAGS0_TYPE); | ||
| 285 | |||
| 286 | vfentry = entry + szfmt + | ||
| 287 | header.slave_entry_count * slaveszfmt; | ||
| 288 | slaveentry = entry + szfmt; | ||
| 289 | switch (prog_type) { | ||
| 290 | case NV_VBIOS_CLOCK_PROGRAMMING_TABLE_1X_ENTRY_FLAGS0_TYPE_MASTER_RATIO: | ||
| 291 | case NV_VBIOS_CLOCK_PROGRAMMING_TABLE_1X_ENTRY_FLAGS0_TYPE_MASTER_TABLE: | ||
| 292 | prog_data.v1x_master.b_o_c_o_v_enabled = false; | ||
| 293 | for (j = 0; j < header.vf_entry_count; j++) { | ||
| 294 | memcpy(&vfprog, vfentry, vfszfmt); | ||
| 295 | |||
| 296 | vfentries[j].vfe_idx = (u8)vfprog.vfe_idx; | ||
| 297 | if (CTRL_CLK_PROG_1X_SOURCE_FLL == | ||
| 298 | prog_data.v1x.source) { | ||
| 299 | vfentries[j].gain_vfe_idx = (u8)BIOS_GET_FIELD( | ||
| 300 | vfprog.param0, | ||
| 301 | NV_VBIOS_CLOCK_PROGRAMMING_TABLE_1X_VF_ENTRY_PARAM0_FLL_GAIN_VFE_IDX); | ||
| 302 | } else { | ||
| 303 | vfentries[j].gain_vfe_idx = CTRL_BOARDOBJ_IDX_INVALID; | ||
| 304 | } | ||
| 305 | vfentry += vfszfmt; | ||
| 306 | } | ||
| 307 | |||
| 308 | prog_data.v1x_master.p_vf_entries = vfentries; | ||
| 309 | |||
| 310 | for (j = 0; j < header.slave_entry_count; j++) { | ||
| 311 | memcpy(&slaveprog, slaveentry, slaveszfmt); | ||
| 312 | |||
| 313 | switch (prog_type) { | ||
| 314 | case NV_VBIOS_CLOCK_PROGRAMMING_TABLE_1X_ENTRY_FLAGS0_TYPE_MASTER_RATIO: | ||
| 315 | ratioslaveentries[j].clk_dom_idx = | ||
| 316 | (u8)slaveprog.clk_dom_idx; | ||
| 317 | ratioslaveentries[j].ratio = (u8) | ||
| 318 | BIOS_GET_FIELD(slaveprog.param0, | ||
| 319 | NV_VBIOS_CLOCK_PROGRAMMING_TABLE_1X_SLAVE_ENTRY_PARAM0_MASTER_RATIO_RATIO); | ||
| 320 | break; | ||
| 321 | |||
| 322 | case NV_VBIOS_CLOCK_PROGRAMMING_TABLE_1X_ENTRY_FLAGS0_TYPE_MASTER_TABLE: | ||
| 323 | tableslaveentries[j].clk_dom_idx = | ||
| 324 | (u8)slaveprog.clk_dom_idx; | ||
| 325 | tableslaveentries[j].freq_mhz = | ||
| 326 | (u16)BIOS_GET_FIELD(slaveprog.param0, | ||
| 327 | NV_VBIOS_CLOCK_PROGRAMMING_TABLE_1X_SLAVE_ENTRY_PARAM0_MASTER_TABLE_FREQ); | ||
| 328 | break; | ||
| 329 | } | ||
| 330 | slaveentry += slaveszfmt; | ||
| 331 | } | ||
| 332 | |||
| 333 | switch (prog_type) { | ||
| 334 | case NV_VBIOS_CLOCK_PROGRAMMING_TABLE_1X_ENTRY_FLAGS0_TYPE_MASTER_RATIO: | ||
| 335 | prog_data.board_obj.type = CTRL_CLK_CLK_PROG_TYPE_1X_MASTER_RATIO; | ||
| 336 | prog_data.v1x_master_ratio.p_slave_entries = | ||
| 337 | ratioslaveentries; | ||
| 338 | break; | ||
| 339 | |||
| 340 | case NV_VBIOS_CLOCK_PROGRAMMING_TABLE_1X_ENTRY_FLAGS0_TYPE_MASTER_TABLE: | ||
| 341 | prog_data.board_obj.type = CTRL_CLK_CLK_PROG_TYPE_1X_MASTER_TABLE; | ||
| 342 | |||
| 343 | prog_data.v1x_master_table.p_slave_entries = | ||
| 344 | tableslaveentries; | ||
| 345 | break; | ||
| 346 | |||
| 347 | } | ||
| 348 | break; | ||
| 349 | |||
| 350 | case NV_VBIOS_CLOCK_PROGRAMMING_TABLE_1X_ENTRY_FLAGS0_TYPE_SLAVE: | ||
| 351 | prog_data.board_obj.type = CTRL_CLK_CLK_PROG_TYPE_1X; | ||
| 352 | break; | ||
| 353 | |||
| 354 | |||
| 355 | default: | ||
| 356 | nvgpu_err(g, "source issue %d", prog_type); | ||
| 357 | status = -EINVAL; | ||
| 358 | goto done; | ||
| 359 | } | ||
| 360 | |||
| 361 | pprog = construct_clk_prog(g, (void *)&prog_data); | ||
| 362 | if (pprog == NULL) { | ||
| 363 | nvgpu_err(g, | ||
| 364 | "error constructing clk_prog boardobj %d", i); | ||
| 365 | status = -EINVAL; | ||
| 366 | goto done; | ||
| 367 | } | ||
| 368 | |||
| 369 | status = boardobjgrp_objinsert(&pclkprogobjs->super.super, | ||
| 370 | (struct boardobj *)pprog, i); | ||
| 371 | if (status) { | ||
| 372 | nvgpu_err(g, "error adding clk_prog boardobj %d", i); | ||
| 373 | status = -EINVAL; | ||
| 374 | goto done; | ||
| 375 | } | ||
| 376 | } | ||
| 377 | done: | ||
| 378 | nvgpu_log_info(g, " done status %x", status); | ||
| 379 | return status; | ||
| 380 | } | ||
| 381 | |||
| 382 | static int _clk_prog_pmudatainit_super(struct gk20a *g, | ||
| 383 | struct boardobj *board_obj_ptr, | ||
| 384 | struct nv_pmu_boardobj *ppmudata) | ||
| 385 | { | ||
| 386 | int status = 0; | ||
| 387 | |||
| 388 | nvgpu_log_info(g, " "); | ||
| 389 | |||
| 390 | status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata); | ||
| 391 | return status; | ||
| 392 | } | ||
| 393 | |||
| 394 | static int _clk_prog_pmudatainit_1x(struct gk20a *g, | ||
| 395 | struct boardobj *board_obj_ptr, | ||
| 396 | struct nv_pmu_boardobj *ppmudata) | ||
| 397 | { | ||
| 398 | int status = 0; | ||
| 399 | struct clk_prog_1x *pclk_prog_1x; | ||
| 400 | struct nv_pmu_clk_clk_prog_1x_boardobj_set *pset; | ||
| 401 | |||
| 402 | nvgpu_log_info(g, " "); | ||
| 403 | |||
| 404 | status = _clk_prog_pmudatainit_super(g, board_obj_ptr, ppmudata); | ||
| 405 | if (status != 0) { | ||
| 406 | return status; | ||
| 407 | } | ||
| 408 | |||
| 409 | pclk_prog_1x = (struct clk_prog_1x *)board_obj_ptr; | ||
| 410 | |||
| 411 | pset = (struct nv_pmu_clk_clk_prog_1x_boardobj_set *) | ||
| 412 | ppmudata; | ||
| 413 | |||
| 414 | pset->source = pclk_prog_1x->source; | ||
| 415 | pset->freq_max_mhz = pclk_prog_1x->freq_max_mhz; | ||
| 416 | pset->source_data = pclk_prog_1x->source_data; | ||
| 417 | |||
| 418 | return status; | ||
| 419 | } | ||
| 420 | |||
| 421 | static int _clk_prog_pmudatainit_1x_master(struct gk20a *g, | ||
| 422 | struct boardobj *board_obj_ptr, | ||
| 423 | struct nv_pmu_boardobj *ppmudata) | ||
| 424 | { | ||
| 425 | int status = 0; | ||
| 426 | struct clk_prog_1x_master *pclk_prog_1x_master; | ||
| 427 | struct nv_pmu_clk_clk_prog_1x_master_boardobj_set *pset; | ||
| 428 | u32 vfsize = sizeof(struct ctrl_clk_clk_prog_1x_master_vf_entry) * | ||
| 429 | g->clk_pmu.clk_progobjs.vf_entry_count; | ||
| 430 | |||
| 431 | nvgpu_log_info(g, " "); | ||
| 432 | |||
| 433 | status = _clk_prog_pmudatainit_1x(g, board_obj_ptr, ppmudata); | ||
| 434 | |||
| 435 | pclk_prog_1x_master = | ||
| 436 | (struct clk_prog_1x_master *)board_obj_ptr; | ||
| 437 | |||
| 438 | pset = (struct nv_pmu_clk_clk_prog_1x_master_boardobj_set *) | ||
| 439 | ppmudata; | ||
| 440 | |||
| 441 | memcpy(pset->vf_entries, pclk_prog_1x_master->p_vf_entries, vfsize); | ||
| 442 | |||
| 443 | pset->b_o_c_o_v_enabled = pclk_prog_1x_master->b_o_c_o_v_enabled; | ||
| 444 | pset->source_data = pclk_prog_1x_master->source_data; | ||
| 445 | |||
| 446 | memcpy(&pset->deltas, &pclk_prog_1x_master->deltas, | ||
| 447 | (u32) sizeof(struct ctrl_clk_clk_delta)); | ||
| 448 | |||
| 449 | return status; | ||
| 450 | } | ||
| 451 | |||
| 452 | static int _clk_prog_pmudatainit_1x_master_ratio(struct gk20a *g, | ||
| 453 | struct boardobj *board_obj_ptr, | ||
| 454 | struct nv_pmu_boardobj *ppmudata) | ||
| 455 | { | ||
| 456 | int status = 0; | ||
| 457 | struct clk_prog_1x_master_ratio *pclk_prog_1x_master_ratio; | ||
| 458 | struct nv_pmu_clk_clk_prog_1x_master_ratio_boardobj_set *pset; | ||
| 459 | u32 slavesize = sizeof(struct ctrl_clk_clk_prog_1x_master_ratio_slave_entry) * | ||
| 460 | g->clk_pmu.clk_progobjs.slave_entry_count; | ||
| 461 | |||
| 462 | nvgpu_log_info(g, " "); | ||
| 463 | |||
| 464 | status = _clk_prog_pmudatainit_1x_master(g, board_obj_ptr, ppmudata); | ||
| 465 | if (status != 0) { | ||
| 466 | return status; | ||
| 467 | } | ||
| 468 | |||
| 469 | pclk_prog_1x_master_ratio = | ||
| 470 | (struct clk_prog_1x_master_ratio *)board_obj_ptr; | ||
| 471 | |||
| 472 | pset = (struct nv_pmu_clk_clk_prog_1x_master_ratio_boardobj_set *) | ||
| 473 | ppmudata; | ||
| 474 | |||
| 475 | memcpy(pset->slave_entries, | ||
| 476 | pclk_prog_1x_master_ratio->p_slave_entries, slavesize); | ||
| 477 | |||
| 478 | return status; | ||
| 479 | } | ||
| 480 | |||
| 481 | static int _clk_prog_pmudatainit_1x_master_table(struct gk20a *g, | ||
| 482 | struct boardobj *board_obj_ptr, | ||
| 483 | struct nv_pmu_boardobj *ppmudata) | ||
| 484 | { | ||
| 485 | int status = 0; | ||
| 486 | struct clk_prog_1x_master_table *pclk_prog_1x_master_table; | ||
| 487 | struct nv_pmu_clk_clk_prog_1x_master_table_boardobj_set *pset; | ||
| 488 | u32 slavesize = sizeof(struct ctrl_clk_clk_prog_1x_master_ratio_slave_entry) * | ||
| 489 | g->clk_pmu.clk_progobjs.slave_entry_count; | ||
| 490 | |||
| 491 | nvgpu_log_info(g, " "); | ||
| 492 | |||
| 493 | status = _clk_prog_pmudatainit_1x_master(g, board_obj_ptr, ppmudata); | ||
| 494 | if (status != 0) { | ||
| 495 | return status; | ||
| 496 | } | ||
| 497 | |||
| 498 | pclk_prog_1x_master_table = | ||
| 499 | (struct clk_prog_1x_master_table *)board_obj_ptr; | ||
| 500 | |||
| 501 | pset = (struct nv_pmu_clk_clk_prog_1x_master_table_boardobj_set *) | ||
| 502 | ppmudata; | ||
| 503 | memcpy(pset->slave_entries, | ||
| 504 | pclk_prog_1x_master_table->p_slave_entries, slavesize); | ||
| 505 | |||
| 506 | return status; | ||
| 507 | } | ||
| 508 | |||
| 509 | static u32 _clk_prog_1x_master_rail_construct_vf_point(struct gk20a *g, | ||
| 510 | struct clk_pmupstate *pclk, | ||
| 511 | struct clk_prog_1x_master *p1xmaster, | ||
| 512 | struct ctrl_clk_clk_prog_1x_master_vf_entry *p_vf_rail, | ||
| 513 | struct clk_vf_point *p_vf_point_tmp, | ||
| 514 | u8 *p_vf_point_idx) | ||
| 515 | { | ||
| 516 | struct clk_vf_point *p_vf_point; | ||
| 517 | u32 status; | ||
| 518 | |||
| 519 | nvgpu_log_info(g, " "); | ||
| 520 | |||
| 521 | p_vf_point = construct_clk_vf_point(g, (void *)p_vf_point_tmp); | ||
| 522 | if (p_vf_point == NULL) { | ||
| 523 | status = -ENOMEM; | ||
| 524 | goto done; | ||
| 525 | } | ||
| 526 | status = pclk->clk_vf_pointobjs.super.super.objinsert( | ||
| 527 | &pclk->clk_vf_pointobjs.super.super, | ||
| 528 | &p_vf_point->super, | ||
| 529 | *p_vf_point_idx); | ||
| 530 | if (status) { | ||
| 531 | goto done; | ||
| 532 | } | ||
| 533 | |||
| 534 | p_vf_rail->vf_point_idx_last = (*p_vf_point_idx)++; | ||
| 535 | |||
| 536 | done: | ||
| 537 | nvgpu_log_info(g, "done status %x", status); | ||
| 538 | return status; | ||
| 539 | } | ||
| 540 | |||
| 541 | static int clk_prog_construct_super(struct gk20a *g, | ||
| 542 | struct boardobj **ppboardobj, | ||
| 543 | u16 size, void *pargs) | ||
| 544 | { | ||
| 545 | struct clk_prog *pclkprog; | ||
| 546 | int status = 0; | ||
| 547 | |||
| 548 | status = boardobj_construct_super(g, ppboardobj, | ||
| 549 | size, pargs); | ||
| 550 | if (status) { | ||
| 551 | return -EINVAL; | ||
| 552 | } | ||
| 553 | |||
| 554 | pclkprog = (struct clk_prog *)*ppboardobj; | ||
| 555 | |||
| 556 | pclkprog->super.pmudatainit = | ||
| 557 | _clk_prog_pmudatainit_super; | ||
| 558 | return status; | ||
| 559 | } | ||
| 560 | |||
| 561 | |||
| 562 | static int clk_prog_construct_1x(struct gk20a *g, | ||
| 563 | struct boardobj **ppboardobj, | ||
| 564 | u16 size, void *pargs) | ||
| 565 | { | ||
| 566 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
| 567 | struct clk_prog_1x *pclkprog; | ||
| 568 | struct clk_prog_1x *ptmpprog = | ||
| 569 | (struct clk_prog_1x *)pargs; | ||
| 570 | int status = 0; | ||
| 571 | |||
| 572 | nvgpu_log_info(g, " "); | ||
| 573 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_PROG_TYPE_1X); | ||
| 574 | status = clk_prog_construct_super(g, ppboardobj, size, pargs); | ||
| 575 | if (status) { | ||
| 576 | return -EINVAL; | ||
| 577 | } | ||
| 578 | |||
| 579 | pclkprog = (struct clk_prog_1x *)*ppboardobj; | ||
| 580 | |||
| 581 | pclkprog->super.super.pmudatainit = | ||
| 582 | _clk_prog_pmudatainit_1x; | ||
| 583 | |||
| 584 | pclkprog->source = ptmpprog->source; | ||
| 585 | pclkprog->freq_max_mhz = ptmpprog->freq_max_mhz; | ||
| 586 | pclkprog->source_data = ptmpprog->source_data; | ||
| 587 | |||
| 588 | return status; | ||
| 589 | } | ||
| 590 | |||
| 591 | static int clk_prog_construct_1x_master(struct gk20a *g, | ||
| 592 | struct boardobj **ppboardobj, | ||
| 593 | u16 size, void *pargs) | ||
| 594 | { | ||
| 595 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
| 596 | struct clk_prog_1x_master *pclkprog; | ||
| 597 | struct clk_prog_1x_master *ptmpprog = | ||
| 598 | (struct clk_prog_1x_master *)pargs; | ||
| 599 | int status = 0; | ||
| 600 | u32 vfsize = sizeof(struct ctrl_clk_clk_prog_1x_master_vf_entry) * | ||
| 601 | g->clk_pmu.clk_progobjs.vf_entry_count; | ||
| 602 | u8 railidx; | ||
| 603 | |||
| 604 | nvgpu_log_info(g, " type - %x", BOARDOBJ_GET_TYPE(pargs)); | ||
| 605 | |||
| 606 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_PROG_TYPE_1X_MASTER); | ||
| 607 | status = clk_prog_construct_1x(g, ppboardobj, size, pargs); | ||
| 608 | if (status) { | ||
| 609 | return -EINVAL; | ||
| 610 | } | ||
| 611 | |||
| 612 | pclkprog = (struct clk_prog_1x_master *)*ppboardobj; | ||
| 613 | |||
| 614 | pclkprog->super.super.super.pmudatainit = | ||
| 615 | _clk_prog_pmudatainit_1x_master; | ||
| 616 | |||
| 617 | pclkprog->vfflatten = | ||
| 618 | vfflatten_prog_1x_master; | ||
| 619 | |||
| 620 | pclkprog->vflookup = | ||
| 621 | vflookup_prog_1x_master; | ||
| 622 | |||
| 623 | pclkprog->getfpoints = | ||
| 624 | getfpoints_prog_1x_master; | ||
| 625 | |||
| 626 | pclkprog->getslaveclk = | ||
| 627 | getslaveclk_prog_1x_master; | ||
| 628 | |||
| 629 | pclkprog->p_vf_entries = (struct ctrl_clk_clk_prog_1x_master_vf_entry *) | ||
| 630 | nvgpu_kzalloc(g, vfsize); | ||
| 631 | if (!pclkprog->p_vf_entries) | ||
| 632 | return -ENOMEM; | ||
| 633 | |||
| 634 | memcpy(pclkprog->p_vf_entries, ptmpprog->p_vf_entries, vfsize); | ||
| 635 | |||
| 636 | pclkprog->b_o_c_o_v_enabled = ptmpprog->b_o_c_o_v_enabled; | ||
| 637 | |||
| 638 | for (railidx = 0; | ||
| 639 | railidx < g->clk_pmu.clk_progobjs.vf_entry_count; | ||
| 640 | railidx++) { | ||
| 641 | pclkprog->p_vf_entries[railidx].vf_point_idx_first = | ||
| 642 | CTRL_CLK_CLK_VF_POINT_IDX_INVALID; | ||
| 643 | pclkprog->p_vf_entries[railidx].vf_point_idx_last = | ||
| 644 | CTRL_CLK_CLK_VF_POINT_IDX_INVALID; | ||
| 645 | } | ||
| 646 | |||
| 647 | return status; | ||
| 648 | } | ||
| 649 | |||
| 650 | static int clk_prog_construct_1x_master_ratio(struct gk20a *g, | ||
| 651 | struct boardobj **ppboardobj, | ||
| 652 | u16 size, void *pargs) | ||
| 653 | { | ||
| 654 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
| 655 | struct clk_prog_1x_master_ratio *pclkprog; | ||
| 656 | struct clk_prog_1x_master_ratio *ptmpprog = | ||
| 657 | (struct clk_prog_1x_master_ratio *)pargs; | ||
| 658 | int status = 0; | ||
| 659 | u32 slavesize = sizeof(struct ctrl_clk_clk_prog_1x_master_ratio_slave_entry) * | ||
| 660 | g->clk_pmu.clk_progobjs.slave_entry_count; | ||
| 661 | |||
| 662 | if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_PROG_TYPE_1X_MASTER_RATIO) { | ||
| 663 | return -EINVAL; | ||
| 664 | } | ||
| 665 | |||
| 666 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_PROG_TYPE_1X_MASTER_RATIO); | ||
| 667 | status = clk_prog_construct_1x_master(g, ppboardobj, size, pargs); | ||
| 668 | if (status) { | ||
| 669 | return -EINVAL; | ||
| 670 | } | ||
| 671 | |||
| 672 | pclkprog = (struct clk_prog_1x_master_ratio *)*ppboardobj; | ||
| 673 | |||
| 674 | pclkprog->super.super.super.super.pmudatainit = | ||
| 675 | _clk_prog_pmudatainit_1x_master_ratio; | ||
| 676 | |||
| 677 | pclkprog->p_slave_entries = | ||
| 678 | (struct ctrl_clk_clk_prog_1x_master_ratio_slave_entry *) | ||
| 679 | nvgpu_kzalloc(g, slavesize); | ||
| 680 | if (!pclkprog->p_slave_entries) { | ||
| 681 | return -ENOMEM; | ||
| 682 | } | ||
| 683 | |||
| 684 | memset(pclkprog->p_slave_entries, CTRL_CLK_CLK_DOMAIN_INDEX_INVALID, | ||
| 685 | slavesize); | ||
| 686 | |||
| 687 | memcpy(pclkprog->p_slave_entries, ptmpprog->p_slave_entries, slavesize); | ||
| 688 | |||
| 689 | return status; | ||
| 690 | } | ||
| 691 | |||
| 692 | static int clk_prog_construct_1x_master_table(struct gk20a *g, | ||
| 693 | struct boardobj **ppboardobj, | ||
| 694 | u16 size, void *pargs) | ||
| 695 | { | ||
| 696 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
| 697 | struct clk_prog_1x_master_table *pclkprog; | ||
| 698 | struct clk_prog_1x_master_table *ptmpprog = | ||
| 699 | (struct clk_prog_1x_master_table *)pargs; | ||
| 700 | int status = 0; | ||
| 701 | u32 slavesize = sizeof(struct ctrl_clk_clk_prog_1x_master_ratio_slave_entry) * | ||
| 702 | g->clk_pmu.clk_progobjs.slave_entry_count; | ||
| 703 | |||
| 704 | nvgpu_log_info(g, "type - %x", BOARDOBJ_GET_TYPE(pargs)); | ||
| 705 | |||
| 706 | if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_PROG_TYPE_1X_MASTER_TABLE) { | ||
| 707 | return -EINVAL; | ||
| 708 | } | ||
| 709 | |||
| 710 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_PROG_TYPE_1X_MASTER_TABLE); | ||
| 711 | status = clk_prog_construct_1x_master(g, ppboardobj, size, pargs); | ||
| 712 | if (status) { | ||
| 713 | return -EINVAL; | ||
| 714 | } | ||
| 715 | |||
| 716 | pclkprog = (struct clk_prog_1x_master_table *)*ppboardobj; | ||
| 717 | |||
| 718 | pclkprog->super.super.super.super.pmudatainit = | ||
| 719 | _clk_prog_pmudatainit_1x_master_table; | ||
| 720 | |||
| 721 | pclkprog->p_slave_entries = | ||
| 722 | (struct ctrl_clk_clk_prog_1x_master_table_slave_entry *) | ||
| 723 | nvgpu_kzalloc(g, slavesize); | ||
| 724 | |||
| 725 | if (!pclkprog->p_slave_entries) { | ||
| 726 | status = -ENOMEM; | ||
| 727 | goto exit; | ||
| 728 | } | ||
| 729 | |||
| 730 | memset(pclkprog->p_slave_entries, CTRL_CLK_CLK_DOMAIN_INDEX_INVALID, | ||
| 731 | slavesize); | ||
| 732 | |||
| 733 | memcpy(pclkprog->p_slave_entries, ptmpprog->p_slave_entries, slavesize); | ||
| 734 | |||
| 735 | exit: | ||
| 736 | if (status) { | ||
| 737 | (*ppboardobj)->destruct(*ppboardobj); | ||
| 738 | } | ||
| 739 | |||
| 740 | return status; | ||
| 741 | } | ||
| 742 | |||
| 743 | static struct clk_prog *construct_clk_prog(struct gk20a *g, void *pargs) | ||
| 744 | { | ||
| 745 | struct boardobj *board_obj_ptr = NULL; | ||
| 746 | int status; | ||
| 747 | |||
| 748 | nvgpu_log_info(g, " type - %x", BOARDOBJ_GET_TYPE(pargs)); | ||
| 749 | switch (BOARDOBJ_GET_TYPE(pargs)) { | ||
| 750 | case CTRL_CLK_CLK_PROG_TYPE_1X: | ||
| 751 | status = clk_prog_construct_1x(g, &board_obj_ptr, | ||
| 752 | sizeof(struct clk_prog_1x), pargs); | ||
| 753 | break; | ||
| 754 | |||
| 755 | case CTRL_CLK_CLK_PROG_TYPE_1X_MASTER_TABLE: | ||
| 756 | status = clk_prog_construct_1x_master_table(g, &board_obj_ptr, | ||
| 757 | sizeof(struct clk_prog_1x_master_table), pargs); | ||
| 758 | break; | ||
| 759 | |||
| 760 | case CTRL_CLK_CLK_PROG_TYPE_1X_MASTER_RATIO: | ||
| 761 | status = clk_prog_construct_1x_master_ratio(g, &board_obj_ptr, | ||
| 762 | sizeof(struct clk_prog_1x_master_ratio), pargs); | ||
| 763 | break; | ||
| 764 | |||
| 765 | default: | ||
| 766 | return NULL; | ||
| 767 | } | ||
| 768 | |||
| 769 | if (status) { | ||
| 770 | if (board_obj_ptr) { | ||
| 771 | board_obj_ptr->destruct(board_obj_ptr); | ||
| 772 | } | ||
| 773 | return NULL; | ||
| 774 | } | ||
| 775 | |||
| 776 | nvgpu_log_info(g, " Done"); | ||
| 777 | |||
| 778 | return (struct clk_prog *)board_obj_ptr; | ||
| 779 | } | ||
| 780 | |||
| 781 | static u32 vfflatten_prog_1x_master(struct gk20a *g, | ||
| 782 | struct clk_pmupstate *pclk, | ||
| 783 | struct clk_prog_1x_master *p1xmaster, | ||
| 784 | u8 clk_domain_idx, u16 *pfreqmaxlastmhz) | ||
| 785 | { | ||
| 786 | struct ctrl_clk_clk_prog_1x_master_vf_entry *p_vf_rail; | ||
| 787 | union { | ||
| 788 | struct boardobj board_obj; | ||
| 789 | struct clk_vf_point vf_point; | ||
| 790 | struct clk_vf_point_freq freq; | ||
| 791 | struct clk_vf_point_volt volt; | ||
| 792 | } vf_point_data; | ||
| 793 | u32 status = 0; | ||
| 794 | u8 step_count; | ||
| 795 | u8 freq_step_size_mhz = 0; | ||
| 796 | u8 vf_point_idx; | ||
| 797 | u8 vf_rail_idx; | ||
| 798 | |||
| 799 | nvgpu_log_info(g, " "); | ||
| 800 | memset(&vf_point_data, 0x0, sizeof(vf_point_data)); | ||
| 801 | |||
| 802 | vf_point_idx = BOARDOBJGRP_NEXT_EMPTY_IDX( | ||
| 803 | &pclk->clk_vf_pointobjs.super.super); | ||
| 804 | |||
| 805 | for (vf_rail_idx = 0; | ||
| 806 | vf_rail_idx < pclk->clk_progobjs.vf_entry_count; | ||
| 807 | vf_rail_idx++) { | ||
| 808 | u32 voltage_min_uv; | ||
| 809 | u32 voltage_step_size_uv; | ||
| 810 | u8 i; | ||
| 811 | |||
| 812 | p_vf_rail = &p1xmaster->p_vf_entries[vf_rail_idx]; | ||
| 813 | if (p_vf_rail->vfe_idx == CTRL_BOARDOBJ_IDX_INVALID) { | ||
| 814 | continue; | ||
| 815 | } | ||
| 816 | |||
| 817 | p_vf_rail->vf_point_idx_first = vf_point_idx; | ||
| 818 | |||
| 819 | vf_point_data.vf_point.vfe_equ_idx = p_vf_rail->vfe_idx; | ||
| 820 | vf_point_data.vf_point.volt_rail_idx = vf_rail_idx; | ||
| 821 | |||
| 822 | step_count = 0; | ||
| 823 | |||
| 824 | switch (p1xmaster->super.source) { | ||
| 825 | case CTRL_CLK_PROG_1X_SOURCE_PLL: | ||
| 826 | freq_step_size_mhz = | ||
| 827 | p1xmaster->super.source_data.pll.freq_step_size_mhz; | ||
| 828 | step_count = (freq_step_size_mhz == 0) ? 0 : | ||
| 829 | (p1xmaster->super.freq_max_mhz - *pfreqmaxlastmhz - 1) / | ||
| 830 | freq_step_size_mhz; | ||
| 831 | /* Intentional fall-through.*/ | ||
| 832 | |||
| 833 | case CTRL_CLK_PROG_1X_SOURCE_ONE_SOURCE: | ||
| 834 | vf_point_data.board_obj.type = | ||
| 835 | CTRL_CLK_CLK_VF_POINT_TYPE_FREQ; | ||
| 836 | do { | ||
| 837 | clkvfpointfreqmhzset(g, &vf_point_data.vf_point, | ||
| 838 | p1xmaster->super.freq_max_mhz - | ||
| 839 | step_count * freq_step_size_mhz); | ||
| 840 | |||
| 841 | status = _clk_prog_1x_master_rail_construct_vf_point(g, pclk, | ||
| 842 | p1xmaster, p_vf_rail, | ||
| 843 | &vf_point_data.vf_point, &vf_point_idx); | ||
| 844 | if (status) { | ||
| 845 | goto done; | ||
| 846 | } | ||
| 847 | } while (step_count-- > 0); | ||
| 848 | break; | ||
| 849 | |||
| 850 | case CTRL_CLK_PROG_1X_SOURCE_FLL: | ||
| 851 | voltage_min_uv = CLK_FLL_LUT_MIN_VOLTAGE_UV(pclk); | ||
| 852 | voltage_step_size_uv = CLK_FLL_LUT_STEP_SIZE_UV(pclk); | ||
| 853 | step_count = CLK_FLL_LUT_VF_NUM_ENTRIES(pclk); | ||
| 854 | |||
| 855 | /* FLL sources use a voltage-based VF_POINT.*/ | ||
| 856 | vf_point_data.board_obj.type = | ||
| 857 | CTRL_CLK_CLK_VF_POINT_TYPE_VOLT; | ||
| 858 | for (i = 0; i < step_count; i++) { | ||
| 859 | vf_point_data.volt.source_voltage_uv = | ||
| 860 | voltage_min_uv + i * voltage_step_size_uv; | ||
| 861 | |||
| 862 | status = _clk_prog_1x_master_rail_construct_vf_point(g, pclk, | ||
| 863 | p1xmaster, p_vf_rail, | ||
| 864 | &vf_point_data.vf_point, &vf_point_idx); | ||
| 865 | if (status) { | ||
| 866 | goto done; | ||
| 867 | } | ||
| 868 | } | ||
| 869 | break; | ||
| 870 | } | ||
| 871 | } | ||
| 872 | |||
| 873 | *pfreqmaxlastmhz = p1xmaster->super.freq_max_mhz; | ||
| 874 | |||
| 875 | done: | ||
| 876 | nvgpu_log_info(g, "done status %x", status); | ||
| 877 | return status; | ||
| 878 | } | ||
| 879 | |||
| 880 | static u32 vflookup_prog_1x_master | ||
| 881 | ( | ||
| 882 | struct gk20a *g, | ||
| 883 | struct clk_pmupstate *pclk, | ||
| 884 | struct clk_prog_1x_master *p1xmaster, | ||
| 885 | u8 *slave_clk_domain, | ||
| 886 | u16 *pclkmhz, | ||
| 887 | u32 *pvoltuv, | ||
| 888 | u8 rail | ||
| 889 | ) | ||
| 890 | { | ||
| 891 | int j; | ||
| 892 | struct ctrl_clk_clk_prog_1x_master_vf_entry | ||
| 893 | *pvfentry; | ||
| 894 | struct clk_vf_point *pvfpoint; | ||
| 895 | struct clk_progs *pclkprogobjs; | ||
| 896 | struct clk_prog_1x_master_ratio *p1xmasterratio; | ||
| 897 | u16 clkmhz; | ||
| 898 | u32 voltuv; | ||
| 899 | u8 slaveentrycount; | ||
| 900 | int i; | ||
| 901 | struct ctrl_clk_clk_prog_1x_master_ratio_slave_entry *pslaveents; | ||
| 902 | |||
| 903 | if ((*pclkmhz != 0) && (*pvoltuv != 0)) { | ||
| 904 | return -EINVAL; | ||
| 905 | } | ||
| 906 | |||
| 907 | pclkprogobjs = &(pclk->clk_progobjs); | ||
| 908 | |||
| 909 | slaveentrycount = pclkprogobjs->slave_entry_count; | ||
| 910 | |||
| 911 | if (pclkprogobjs->vf_entry_count > | ||
| 912 | CTRL_CLK_CLK_PROG_1X_MASTER_VF_ENTRY_MAX_ENTRIES) { | ||
| 913 | return -EINVAL; | ||
| 914 | } | ||
| 915 | |||
| 916 | if (rail >= pclkprogobjs->vf_entry_count) { | ||
| 917 | return -EINVAL; | ||
| 918 | } | ||
| 919 | |||
| 920 | pvfentry = p1xmaster->p_vf_entries; | ||
| 921 | |||
| 922 | pvfentry = (struct ctrl_clk_clk_prog_1x_master_vf_entry *)( | ||
| 923 | (u8 *)pvfentry + | ||
| 924 | (sizeof(struct ctrl_clk_clk_prog_1x_master_vf_entry) * | ||
| 925 | rail)); | ||
| 926 | |||
| 927 | clkmhz = *pclkmhz; | ||
| 928 | voltuv = *pvoltuv; | ||
| 929 | |||
| 930 | /*if domain is slave domain and freq is input | ||
| 931 | then derive master clk */ | ||
| 932 | if ((slave_clk_domain != NULL) && (*pclkmhz != 0)) { | ||
| 933 | if (p1xmaster->super.super.super.implements(g, | ||
| 934 | &p1xmaster->super.super.super, | ||
| 935 | CTRL_CLK_CLK_PROG_TYPE_1X_MASTER_RATIO)) { | ||
| 936 | |||
| 937 | p1xmasterratio = | ||
| 938 | (struct clk_prog_1x_master_ratio *)p1xmaster; | ||
| 939 | pslaveents = p1xmasterratio->p_slave_entries; | ||
| 940 | for (i = 0; i < slaveentrycount; i++) { | ||
| 941 | if (pslaveents->clk_dom_idx == | ||
| 942 | *slave_clk_domain) { | ||
| 943 | break; | ||
| 944 | } | ||
| 945 | pslaveents++; | ||
| 946 | } | ||
| 947 | if (i == slaveentrycount) { | ||
| 948 | return -EINVAL; | ||
| 949 | } | ||
| 950 | clkmhz = (clkmhz * 100)/pslaveents->ratio; | ||
| 951 | } else { | ||
| 952 | /* only support ratio for now */ | ||
| 953 | return -EINVAL; | ||
| 954 | } | ||
| 955 | } | ||
| 956 | |||
| 957 | /* if both volt and clks are zero simply print*/ | ||
| 958 | if ((*pvoltuv == 0) && (*pclkmhz == 0)) { | ||
| 959 | for (j = pvfentry->vf_point_idx_first; | ||
| 960 | j <= pvfentry->vf_point_idx_last; j++) { | ||
| 961 | pvfpoint = CLK_CLK_VF_POINT_GET(pclk, j); | ||
| 962 | nvgpu_err(g, "v %x c %x", | ||
| 963 | clkvfpointvoltageuvget(g, pvfpoint), | ||
| 964 | clkvfpointfreqmhzget(g, pvfpoint)); | ||
| 965 | } | ||
| 966 | return -EINVAL; | ||
| 967 | } | ||
| 968 | /* start looking up f for v for v for f */ | ||
| 969 | /* looking for volt? */ | ||
| 970 | if (*pvoltuv == 0) { | ||
| 971 | pvfpoint = CLK_CLK_VF_POINT_GET(pclk, | ||
| 972 | pvfentry->vf_point_idx_last); | ||
| 973 | /* above range? */ | ||
| 974 | if (clkmhz > clkvfpointfreqmhzget(g, pvfpoint)) { | ||
| 975 | return -EINVAL; | ||
| 976 | } | ||
| 977 | |||
| 978 | for (j = pvfentry->vf_point_idx_last; | ||
| 979 | j >= pvfentry->vf_point_idx_first; j--) { | ||
| 980 | pvfpoint = CLK_CLK_VF_POINT_GET(pclk, j); | ||
| 981 | if (clkmhz <= clkvfpointfreqmhzget(g, pvfpoint)) { | ||
| 982 | voltuv = clkvfpointvoltageuvget(g, pvfpoint); | ||
| 983 | } else { | ||
| 984 | break; | ||
| 985 | } | ||
| 986 | } | ||
| 987 | } else { /* looking for clk? */ | ||
| 988 | |||
| 989 | pvfpoint = CLK_CLK_VF_POINT_GET(pclk, | ||
| 990 | pvfentry->vf_point_idx_first); | ||
| 991 | /* below range? */ | ||
| 992 | if (voltuv < clkvfpointvoltageuvget(g, pvfpoint)) { | ||
| 993 | return -EINVAL; | ||
| 994 | } | ||
| 995 | |||
| 996 | for (j = pvfentry->vf_point_idx_first; | ||
| 997 | j <= pvfentry->vf_point_idx_last; j++) { | ||
| 998 | pvfpoint = CLK_CLK_VF_POINT_GET(pclk, j); | ||
| 999 | if (voltuv >= clkvfpointvoltageuvget(g, pvfpoint)) { | ||
| 1000 | clkmhz = clkvfpointfreqmhzget(g, pvfpoint); | ||
| 1001 | } else { | ||
| 1002 | break; | ||
| 1003 | } | ||
| 1004 | } | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | /*if domain is slave domain and freq was looked up | ||
| 1008 | then derive slave clk */ | ||
| 1009 | if ((slave_clk_domain != NULL) && (*pclkmhz == 0)) { | ||
| 1010 | if (p1xmaster->super.super.super.implements(g, | ||
| 1011 | &p1xmaster->super.super.super, | ||
| 1012 | CTRL_CLK_CLK_PROG_TYPE_1X_MASTER_RATIO)) { | ||
| 1013 | |||
| 1014 | p1xmasterratio = | ||
| 1015 | (struct clk_prog_1x_master_ratio *)p1xmaster; | ||
| 1016 | pslaveents = p1xmasterratio->p_slave_entries; | ||
| 1017 | for (i = 0; i < slaveentrycount; i++) { | ||
| 1018 | if (pslaveents->clk_dom_idx == | ||
| 1019 | *slave_clk_domain) { | ||
| 1020 | break; | ||
| 1021 | } | ||
| 1022 | pslaveents++; | ||
| 1023 | } | ||
| 1024 | if (i == slaveentrycount) { | ||
| 1025 | return -EINVAL; | ||
| 1026 | } | ||
| 1027 | clkmhz = (clkmhz * pslaveents->ratio)/100; | ||
| 1028 | } else { | ||
| 1029 | /* only support ratio for now */ | ||
| 1030 | return -EINVAL; | ||
| 1031 | } | ||
| 1032 | } | ||
| 1033 | *pclkmhz = clkmhz; | ||
| 1034 | *pvoltuv = voltuv; | ||
| 1035 | if ((clkmhz == 0) || (voltuv == 0)) { | ||
| 1036 | return -EINVAL; | ||
| 1037 | } | ||
| 1038 | return 0; | ||
| 1039 | } | ||
| 1040 | |||
| 1041 | static u32 getfpoints_prog_1x_master | ||
| 1042 | ( | ||
| 1043 | struct gk20a *g, | ||
| 1044 | struct clk_pmupstate *pclk, | ||
| 1045 | struct clk_prog_1x_master *p1xmaster, | ||
| 1046 | u32 *pfpointscount, | ||
| 1047 | u16 **ppfreqpointsinmhz, | ||
| 1048 | u8 rail | ||
| 1049 | ) | ||
| 1050 | { | ||
| 1051 | |||
| 1052 | struct ctrl_clk_clk_prog_1x_master_vf_entry | ||
| 1053 | *pvfentry; | ||
| 1054 | struct clk_vf_point *pvfpoint; | ||
| 1055 | struct clk_progs *pclkprogobjs; | ||
| 1056 | u8 j; | ||
| 1057 | u32 fpointscount = 0; | ||
| 1058 | |||
| 1059 | if (pfpointscount == NULL) { | ||
| 1060 | return -EINVAL; | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | pclkprogobjs = &(pclk->clk_progobjs); | ||
| 1064 | |||
| 1065 | if (pclkprogobjs->vf_entry_count > | ||
| 1066 | CTRL_CLK_CLK_PROG_1X_MASTER_VF_ENTRY_MAX_ENTRIES) { | ||
| 1067 | return -EINVAL; | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | if (rail >= pclkprogobjs->vf_entry_count) { | ||
| 1071 | return -EINVAL; | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | pvfentry = p1xmaster->p_vf_entries; | ||
| 1075 | |||
| 1076 | pvfentry = (struct ctrl_clk_clk_prog_1x_master_vf_entry *)( | ||
| 1077 | (u8 *)pvfentry + | ||
| 1078 | (sizeof(struct ctrl_clk_clk_prog_1x_master_vf_entry) * | ||
| 1079 | (rail+1))); | ||
| 1080 | |||
| 1081 | fpointscount = pvfentry->vf_point_idx_last - | ||
| 1082 | pvfentry->vf_point_idx_first + 1; | ||
| 1083 | |||
| 1084 | /* if pointer for freq data is NULL simply return count */ | ||
| 1085 | if (*ppfreqpointsinmhz == NULL) { | ||
| 1086 | goto done; | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | if (fpointscount > *pfpointscount) { | ||
| 1090 | return -ENOMEM; | ||
| 1091 | } | ||
| 1092 | for (j = pvfentry->vf_point_idx_first; | ||
| 1093 | j <= pvfentry->vf_point_idx_last; j++) { | ||
| 1094 | pvfpoint = CLK_CLK_VF_POINT_GET(pclk, j); | ||
| 1095 | **ppfreqpointsinmhz = clkvfpointfreqmhzget(g, pvfpoint); | ||
| 1096 | (*ppfreqpointsinmhz)++; | ||
| 1097 | } | ||
| 1098 | done: | ||
| 1099 | *pfpointscount = fpointscount; | ||
| 1100 | return 0; | ||
| 1101 | } | ||
| 1102 | |||
| 1103 | static int getslaveclk_prog_1x_master(struct gk20a *g, | ||
| 1104 | struct clk_pmupstate *pclk, | ||
| 1105 | struct clk_prog_1x_master *p1xmaster, | ||
| 1106 | u8 slave_clk_domain, | ||
| 1107 | u16 *pclkmhz, | ||
| 1108 | u16 masterclkmhz | ||
| 1109 | ) | ||
| 1110 | { | ||
| 1111 | struct clk_progs *pclkprogobjs; | ||
| 1112 | struct clk_prog_1x_master_ratio *p1xmasterratio; | ||
| 1113 | u8 slaveentrycount; | ||
| 1114 | u8 i; | ||
| 1115 | struct ctrl_clk_clk_prog_1x_master_ratio_slave_entry *pslaveents; | ||
| 1116 | |||
| 1117 | if (pclkmhz == NULL) { | ||
| 1118 | return -EINVAL; | ||
| 1119 | } | ||
| 1120 | |||
| 1121 | if (masterclkmhz == 0) { | ||
| 1122 | return -EINVAL; | ||
| 1123 | } | ||
| 1124 | |||
| 1125 | *pclkmhz = 0; | ||
| 1126 | pclkprogobjs = &(pclk->clk_progobjs); | ||
| 1127 | |||
| 1128 | slaveentrycount = pclkprogobjs->slave_entry_count; | ||
| 1129 | |||
| 1130 | if (p1xmaster->super.super.super.implements(g, | ||
| 1131 | &p1xmaster->super.super.super, | ||
| 1132 | CTRL_CLK_CLK_PROG_TYPE_1X_MASTER_RATIO)) { | ||
| 1133 | p1xmasterratio = | ||
| 1134 | (struct clk_prog_1x_master_ratio *)p1xmaster; | ||
| 1135 | pslaveents = p1xmasterratio->p_slave_entries; | ||
| 1136 | for (i = 0; i < slaveentrycount; i++) { | ||
| 1137 | if (pslaveents->clk_dom_idx == | ||
| 1138 | slave_clk_domain) { | ||
| 1139 | break; | ||
| 1140 | } | ||
| 1141 | pslaveents++; | ||
| 1142 | } | ||
| 1143 | if (i == slaveentrycount) { | ||
| 1144 | return -EINVAL; | ||
| 1145 | } | ||
| 1146 | *pclkmhz = (masterclkmhz * pslaveents->ratio)/100; | ||
| 1147 | } else { | ||
| 1148 | /* only support ratio for now */ | ||
| 1149 | return -EINVAL; | ||
| 1150 | } | ||
| 1151 | return 0; | ||
| 1152 | } | ||
diff --git a/include/clk/clk_prog.h b/include/clk/clk_prog.h deleted file mode 100644 index af6368f..0000000 --- a/include/clk/clk_prog.h +++ /dev/null | |||
| @@ -1,100 +0,0 @@ | |||
| 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 | #ifndef NVGPU_CLK_PROG_H | ||
| 24 | #define NVGPU_CLK_PROG_H | ||
| 25 | #include "ctrl/ctrlclk.h" | ||
| 26 | #include "ctrl/ctrlboardobj.h" | ||
| 27 | #include <nvgpu/pmuif/nvgpu_gpmu_cmdif.h> | ||
| 28 | #include "boardobj/boardobjgrp_e32.h" | ||
| 29 | #include "boardobj/boardobjgrp_e255.h" | ||
| 30 | #include "boardobj/boardobjgrpmask.h" | ||
| 31 | |||
| 32 | int clk_prog_sw_setup(struct gk20a *g); | ||
| 33 | int clk_prog_pmu_setup(struct gk20a *g); | ||
| 34 | struct clk_prog_1x_master; | ||
| 35 | |||
| 36 | typedef u32 vf_flatten(struct gk20a *g, struct clk_pmupstate *pclk, | ||
| 37 | struct clk_prog_1x_master *p1xmaster, | ||
| 38 | u8 clk_domain_idx, u16 *pfreqmaxlastmhz); | ||
| 39 | |||
| 40 | typedef u32 vf_lookup(struct gk20a *g, struct clk_pmupstate *pclk, | ||
| 41 | struct clk_prog_1x_master *p1xmaster, | ||
| 42 | u8 *slave_clk_domain_idx, u16 *pclkmhz, | ||
| 43 | u32 *pvoltuv, u8 rail); | ||
| 44 | |||
| 45 | typedef int get_slaveclk(struct gk20a *g, struct clk_pmupstate *pclk, | ||
| 46 | struct clk_prog_1x_master *p1xmaster, | ||
| 47 | u8 slave_clk_domain_idx, u16 *pclkmhz, | ||
| 48 | u16 masterclkmhz); | ||
| 49 | |||
| 50 | typedef u32 get_fpoints(struct gk20a *g, struct clk_pmupstate *pclk, | ||
| 51 | struct clk_prog_1x_master *p1xmaster, | ||
| 52 | u32 *pfpointscount, | ||
| 53 | u16 **ppfreqpointsinmhz, u8 rail); | ||
| 54 | |||
| 55 | |||
| 56 | struct clk_progs { | ||
| 57 | struct boardobjgrp_e255 super; | ||
| 58 | u8 slave_entry_count; | ||
| 59 | u8 vf_entry_count; | ||
| 60 | |||
| 61 | }; | ||
| 62 | |||
| 63 | struct clk_prog { | ||
| 64 | struct boardobj super; | ||
| 65 | }; | ||
| 66 | |||
| 67 | struct clk_prog_1x { | ||
| 68 | struct clk_prog super; | ||
| 69 | u8 source; | ||
| 70 | u16 freq_max_mhz; | ||
| 71 | union ctrl_clk_clk_prog_1x_source_data source_data; | ||
| 72 | }; | ||
| 73 | |||
| 74 | struct clk_prog_1x_master { | ||
| 75 | struct clk_prog_1x super; | ||
| 76 | bool b_o_c_o_v_enabled; | ||
| 77 | struct ctrl_clk_clk_prog_1x_master_vf_entry *p_vf_entries; | ||
| 78 | struct ctrl_clk_clk_delta deltas; | ||
| 79 | union ctrl_clk_clk_prog_1x_master_source_data source_data; | ||
| 80 | vf_flatten *vfflatten; | ||
| 81 | vf_lookup *vflookup; | ||
| 82 | get_fpoints *getfpoints; | ||
| 83 | get_slaveclk *getslaveclk; | ||
| 84 | }; | ||
| 85 | |||
| 86 | struct clk_prog_1x_master_ratio { | ||
| 87 | struct clk_prog_1x_master super; | ||
| 88 | struct ctrl_clk_clk_prog_1x_master_ratio_slave_entry *p_slave_entries; | ||
| 89 | }; | ||
| 90 | |||
| 91 | struct clk_prog_1x_master_table { | ||
| 92 | struct clk_prog_1x_master super; | ||
| 93 | struct ctrl_clk_clk_prog_1x_master_table_slave_entry *p_slave_entries; | ||
| 94 | }; | ||
| 95 | |||
| 96 | #define CLK_CLK_PROG_GET(pclk, idx) \ | ||
| 97 | ((struct clk_prog *)BOARDOBJGRP_OBJ_GET_BY_IDX( \ | ||
| 98 | &pclk->clk_progobjs.super.super, (u8)(idx))) | ||
| 99 | |||
| 100 | #endif /* NVGPU_CLK_PROG_H */ | ||
diff --git a/include/clk/clk_vf_point.c b/include/clk/clk_vf_point.c deleted file mode 100644 index 96413c8..0000000 --- a/include/clk/clk_vf_point.c +++ /dev/null | |||
| @@ -1,433 +0,0 @@ | |||
| 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/gk20a.h> | ||
| 24 | |||
| 25 | #include "clk.h" | ||
| 26 | #include "clk_vf_point.h" | ||
| 27 | #include "boardobj/boardobjgrp.h" | ||
| 28 | #include "boardobj/boardobjgrp_e32.h" | ||
| 29 | #include "ctrl/ctrlclk.h" | ||
| 30 | #include "ctrl/ctrlvolt.h" | ||
| 31 | |||
| 32 | static int _clk_vf_point_pmudatainit_super(struct gk20a *g, struct boardobj | ||
| 33 | *board_obj_ptr, struct nv_pmu_boardobj *ppmudata); | ||
| 34 | |||
| 35 | static int _clk_vf_points_pmudatainit(struct gk20a *g, | ||
| 36 | struct boardobjgrp *pboardobjgrp, | ||
| 37 | struct nv_pmu_boardobjgrp_super *pboardobjgrppmu) | ||
| 38 | { | ||
| 39 | u32 status = 0; | ||
| 40 | |||
| 41 | status = boardobjgrp_pmudatainit_e32(g, pboardobjgrp, pboardobjgrppmu); | ||
| 42 | if (status) { | ||
| 43 | nvgpu_err(g, | ||
| 44 | "error updating pmu boardobjgrp for clk vfpoint 0x%x", | ||
| 45 | status); | ||
| 46 | goto done; | ||
| 47 | } | ||
| 48 | |||
| 49 | done: | ||
| 50 | return status; | ||
| 51 | } | ||
| 52 | |||
| 53 | static int _clk_vf_points_pmudata_instget(struct gk20a *g, | ||
| 54 | struct nv_pmu_boardobjgrp *pmuboardobjgrp, | ||
| 55 | struct nv_pmu_boardobj **ppboardobjpmudata, | ||
| 56 | u8 idx) | ||
| 57 | { | ||
| 58 | struct nv_pmu_clk_clk_vf_point_boardobj_grp_set *pgrp_set = | ||
| 59 | (struct nv_pmu_clk_clk_vf_point_boardobj_grp_set *) | ||
| 60 | pmuboardobjgrp; | ||
| 61 | |||
| 62 | nvgpu_log_info(g, " "); | ||
| 63 | |||
| 64 | /*check whether pmuboardobjgrp has a valid boardobj in index*/ | ||
| 65 | if (idx >= CTRL_BOARDOBJGRP_E255_MAX_OBJECTS) { | ||
| 66 | return -EINVAL; | ||
| 67 | } | ||
| 68 | |||
| 69 | *ppboardobjpmudata = (struct nv_pmu_boardobj *) | ||
| 70 | &pgrp_set->objects[idx].data.board_obj; | ||
| 71 | nvgpu_log_info(g, " Done"); | ||
| 72 | return 0; | ||
| 73 | } | ||
| 74 | |||
| 75 | static int _clk_vf_points_pmustatus_instget(struct gk20a *g, | ||
| 76 | void *pboardobjgrppmu, | ||
| 77 | struct nv_pmu_boardobj_query **ppboardobjpmustatus, | ||
| 78 | u8 idx) | ||
| 79 | { | ||
| 80 | struct nv_pmu_clk_clk_vf_point_boardobj_grp_get_status *pgrp_get_status = | ||
| 81 | (struct nv_pmu_clk_clk_vf_point_boardobj_grp_get_status *) | ||
| 82 | pboardobjgrppmu; | ||
| 83 | |||
| 84 | /*check whether pmuboardobjgrp has a valid boardobj in index*/ | ||
| 85 | if (idx >= CTRL_BOARDOBJGRP_E255_MAX_OBJECTS) { | ||
| 86 | return -EINVAL; | ||
| 87 | } | ||
| 88 | |||
| 89 | *ppboardobjpmustatus = (struct nv_pmu_boardobj_query *) | ||
| 90 | &pgrp_get_status->objects[idx].data.board_obj; | ||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | int clk_vf_point_sw_setup(struct gk20a *g) | ||
| 95 | { | ||
| 96 | int status; | ||
| 97 | struct boardobjgrp *pboardobjgrp = NULL; | ||
| 98 | |||
| 99 | nvgpu_log_info(g, " "); | ||
| 100 | |||
| 101 | status = boardobjgrpconstruct_e255(g, &g->clk_pmu.clk_vf_pointobjs.super); | ||
| 102 | if (status) { | ||
| 103 | nvgpu_err(g, | ||
| 104 | "error creating boardobjgrp for clk vfpoint, status - 0x%x", | ||
| 105 | status); | ||
| 106 | goto done; | ||
| 107 | } | ||
| 108 | |||
| 109 | pboardobjgrp = &g->clk_pmu.clk_vf_pointobjs.super.super; | ||
| 110 | |||
| 111 | BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, CLK, CLK_VF_POINT); | ||
| 112 | |||
| 113 | status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp, | ||
| 114 | clk, CLK, clk_vf_point, CLK_VF_POINT); | ||
| 115 | if (status) { | ||
| 116 | nvgpu_err(g, | ||
| 117 | "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x", | ||
| 118 | status); | ||
| 119 | goto done; | ||
| 120 | } | ||
| 121 | |||
| 122 | status = BOARDOBJGRP_PMU_CMD_GRP_GET_STATUS_CONSTRUCT(g, | ||
| 123 | &g->clk_pmu.clk_vf_pointobjs.super.super, | ||
| 124 | clk, CLK, clk_vf_point, CLK_VF_POINT); | ||
| 125 | if (status) { | ||
| 126 | nvgpu_err(g, | ||
| 127 | "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x", | ||
| 128 | status); | ||
| 129 | goto done; | ||
| 130 | } | ||
| 131 | |||
| 132 | pboardobjgrp->pmudatainit = _clk_vf_points_pmudatainit; | ||
| 133 | pboardobjgrp->pmudatainstget = _clk_vf_points_pmudata_instget; | ||
| 134 | pboardobjgrp->pmustatusinstget = _clk_vf_points_pmustatus_instget; | ||
| 135 | |||
| 136 | done: | ||
| 137 | nvgpu_log_info(g, " done status %x", status); | ||
| 138 | return status; | ||
| 139 | } | ||
| 140 | |||
| 141 | int clk_vf_point_pmu_setup(struct gk20a *g) | ||
| 142 | { | ||
| 143 | int status; | ||
| 144 | struct boardobjgrp *pboardobjgrp = NULL; | ||
| 145 | |||
| 146 | nvgpu_log_info(g, " "); | ||
| 147 | |||
| 148 | pboardobjgrp = &g->clk_pmu.clk_vf_pointobjs.super.super; | ||
| 149 | |||
| 150 | if (!pboardobjgrp->bconstructed) { | ||
| 151 | return -EINVAL; | ||
| 152 | } | ||
| 153 | |||
| 154 | status = pboardobjgrp->pmuinithandle(g, pboardobjgrp); | ||
| 155 | |||
| 156 | nvgpu_log_info(g, "Done"); | ||
| 157 | return status; | ||
| 158 | } | ||
| 159 | |||
| 160 | static int clk_vf_point_construct_super(struct gk20a *g, | ||
| 161 | struct boardobj **ppboardobj, | ||
| 162 | u16 size, void *pargs) | ||
| 163 | { | ||
| 164 | struct clk_vf_point *pclkvfpoint; | ||
| 165 | struct clk_vf_point *ptmpvfpoint = | ||
| 166 | (struct clk_vf_point *)pargs; | ||
| 167 | int status = 0; | ||
| 168 | |||
| 169 | status = boardobj_construct_super(g, ppboardobj, | ||
| 170 | size, pargs); | ||
| 171 | if (status) { | ||
| 172 | return -EINVAL; | ||
| 173 | } | ||
| 174 | |||
| 175 | pclkvfpoint = (struct clk_vf_point *)*ppboardobj; | ||
| 176 | |||
| 177 | pclkvfpoint->super.pmudatainit = | ||
| 178 | _clk_vf_point_pmudatainit_super; | ||
| 179 | |||
| 180 | pclkvfpoint->vfe_equ_idx = ptmpvfpoint->vfe_equ_idx; | ||
| 181 | pclkvfpoint->volt_rail_idx = ptmpvfpoint->volt_rail_idx; | ||
| 182 | |||
| 183 | return status; | ||
| 184 | } | ||
| 185 | |||
| 186 | static int _clk_vf_point_pmudatainit_volt(struct gk20a *g, | ||
| 187 | struct boardobj *board_obj_ptr, | ||
| 188 | struct nv_pmu_boardobj *ppmudata) | ||
| 189 | { | ||
| 190 | int status = 0; | ||
| 191 | struct clk_vf_point_volt *pclk_vf_point_volt; | ||
| 192 | struct nv_pmu_clk_clk_vf_point_volt_boardobj_set *pset; | ||
| 193 | |||
| 194 | nvgpu_log_info(g, " "); | ||
| 195 | |||
| 196 | status = _clk_vf_point_pmudatainit_super(g, board_obj_ptr, ppmudata); | ||
| 197 | if (status != 0) { | ||
| 198 | return status; | ||
| 199 | } | ||
| 200 | |||
| 201 | pclk_vf_point_volt = | ||
| 202 | (struct clk_vf_point_volt *)board_obj_ptr; | ||
| 203 | |||
| 204 | pset = (struct nv_pmu_clk_clk_vf_point_volt_boardobj_set *) | ||
| 205 | ppmudata; | ||
| 206 | |||
| 207 | pset->source_voltage_uv = pclk_vf_point_volt->source_voltage_uv; | ||
| 208 | pset->freq_delta.data = pclk_vf_point_volt->freq_delta.data; | ||
| 209 | pset->freq_delta.type = pclk_vf_point_volt->freq_delta.type; | ||
| 210 | |||
| 211 | return status; | ||
| 212 | } | ||
| 213 | |||
| 214 | static int _clk_vf_point_pmudatainit_freq(struct gk20a *g, | ||
| 215 | struct boardobj *board_obj_ptr, | ||
| 216 | struct nv_pmu_boardobj *ppmudata) | ||
| 217 | { | ||
| 218 | int status = 0; | ||
| 219 | struct clk_vf_point_freq *pclk_vf_point_freq; | ||
| 220 | struct nv_pmu_clk_clk_vf_point_freq_boardobj_set *pset; | ||
| 221 | |||
| 222 | nvgpu_log_info(g, " "); | ||
| 223 | |||
| 224 | status = _clk_vf_point_pmudatainit_super(g, board_obj_ptr, ppmudata); | ||
| 225 | if (status != 0) { | ||
| 226 | return status; | ||
| 227 | } | ||
| 228 | |||
| 229 | pclk_vf_point_freq = | ||
| 230 | (struct clk_vf_point_freq *)board_obj_ptr; | ||
| 231 | |||
| 232 | pset = (struct nv_pmu_clk_clk_vf_point_freq_boardobj_set *) | ||
| 233 | ppmudata; | ||
| 234 | |||
| 235 | pset->freq_mhz = | ||
| 236 | clkvfpointfreqmhzget(g, &pclk_vf_point_freq->super); | ||
| 237 | |||
| 238 | pset->volt_delta_uv = pclk_vf_point_freq->volt_delta_uv; | ||
| 239 | |||
| 240 | return status; | ||
| 241 | } | ||
| 242 | |||
| 243 | static int clk_vf_point_construct_volt(struct gk20a *g, | ||
| 244 | struct boardobj **ppboardobj, | ||
| 245 | u16 size, void *pargs) | ||
| 246 | { | ||
| 247 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
| 248 | struct clk_vf_point_volt *pclkvfpoint; | ||
| 249 | struct clk_vf_point_volt *ptmpvfpoint = | ||
| 250 | (struct clk_vf_point_volt *)pargs; | ||
| 251 | int status = 0; | ||
| 252 | |||
| 253 | if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_VF_POINT_TYPE_VOLT) { | ||
| 254 | return -EINVAL; | ||
| 255 | } | ||
| 256 | |||
| 257 | ptmpobj->type_mask = BIT(CTRL_CLK_CLK_VF_POINT_TYPE_VOLT); | ||
| 258 | status = clk_vf_point_construct_super(g, ppboardobj, size, pargs); | ||
| 259 | if (status) { | ||
| 260 | return -EINVAL; | ||
| 261 | } | ||
| 262 | |||
| 263 | pclkvfpoint = (struct clk_vf_point_volt *)*ppboardobj; | ||
| 264 | |||
| 265 | pclkvfpoint->super.super.pmudatainit = | ||
| 266 | _clk_vf_point_pmudatainit_volt; | ||
| 267 | |||
| 268 | pclkvfpoint->source_voltage_uv = ptmpvfpoint->source_voltage_uv; | ||
| 269 | pclkvfpoint->freq_delta = ptmpvfpoint->freq_delta; | ||
| 270 | |||
| 271 | return status; | ||
| 272 | } | ||
| 273 | |||
| 274 | static int clk_vf_point_construct_freq(struct gk20a *g, | ||
| 275 | struct boardobj **ppboardobj, | ||
| 276 | u16 size, void *pargs) | ||
| 277 | { | ||
| 278 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
| 279 | struct clk_vf_point_freq *pclkvfpoint; | ||
| 280 | struct clk_vf_point_freq *ptmpvfpoint = | ||
| 281 | (struct clk_vf_point_freq *)pargs; | ||
| 282 | int status = 0; | ||
| 283 | |||
| 284 | if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_VF_POINT_TYPE_FREQ) { | ||
| 285 | return -EINVAL; | ||
| 286 | } | ||
| 287 | |||
| 288 | ptmpobj->type_mask = BIT(CTRL_CLK_CLK_VF_POINT_TYPE_FREQ); | ||
| 289 | status = clk_vf_point_construct_super(g, ppboardobj, size, pargs); | ||
| 290 | if (status) { | ||
| 291 | return -EINVAL; | ||
| 292 | } | ||
| 293 | |||
| 294 | pclkvfpoint = (struct clk_vf_point_freq *)*ppboardobj; | ||
| 295 | |||
| 296 | pclkvfpoint->super.super.pmudatainit = | ||
| 297 | _clk_vf_point_pmudatainit_freq; | ||
| 298 | |||
| 299 | clkvfpointfreqmhzset(g, &pclkvfpoint->super, | ||
| 300 | clkvfpointfreqmhzget(g, &ptmpvfpoint->super)); | ||
| 301 | |||
| 302 | return status; | ||
| 303 | } | ||
| 304 | |||
| 305 | struct clk_vf_point *construct_clk_vf_point(struct gk20a *g, void *pargs) | ||
| 306 | { | ||
| 307 | struct boardobj *board_obj_ptr = NULL; | ||
| 308 | int status; | ||
| 309 | |||
| 310 | nvgpu_log_info(g, " "); | ||
| 311 | switch (BOARDOBJ_GET_TYPE(pargs)) { | ||
| 312 | case CTRL_CLK_CLK_VF_POINT_TYPE_FREQ: | ||
| 313 | status = clk_vf_point_construct_freq(g, &board_obj_ptr, | ||
| 314 | sizeof(struct clk_vf_point_freq), pargs); | ||
| 315 | break; | ||
| 316 | |||
| 317 | case CTRL_CLK_CLK_VF_POINT_TYPE_VOLT: | ||
| 318 | status = clk_vf_point_construct_volt(g, &board_obj_ptr, | ||
| 319 | sizeof(struct clk_vf_point_volt), pargs); | ||
| 320 | break; | ||
| 321 | |||
| 322 | default: | ||
| 323 | return NULL; | ||
| 324 | } | ||
| 325 | |||
| 326 | if (status) { | ||
| 327 | return NULL; | ||
| 328 | } | ||
| 329 | |||
| 330 | nvgpu_log_info(g, " Done"); | ||
| 331 | |||
| 332 | return (struct clk_vf_point *)board_obj_ptr; | ||
| 333 | } | ||
| 334 | |||
| 335 | static int _clk_vf_point_pmudatainit_super(struct gk20a *g, | ||
| 336 | struct boardobj *board_obj_ptr, | ||
| 337 | struct nv_pmu_boardobj *ppmudata) | ||
| 338 | { | ||
| 339 | int status = 0; | ||
| 340 | struct clk_vf_point *pclk_vf_point; | ||
| 341 | struct nv_pmu_clk_clk_vf_point_boardobj_set *pset; | ||
| 342 | |||
| 343 | nvgpu_log_info(g, " "); | ||
| 344 | |||
| 345 | status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata); | ||
| 346 | if (status != 0) { | ||
| 347 | return status; | ||
| 348 | } | ||
| 349 | |||
| 350 | pclk_vf_point = | ||
| 351 | (struct clk_vf_point *)board_obj_ptr; | ||
| 352 | |||
| 353 | pset = (struct nv_pmu_clk_clk_vf_point_boardobj_set *) | ||
| 354 | ppmudata; | ||
| 355 | |||
| 356 | |||
| 357 | pset->vfe_equ_idx = pclk_vf_point->vfe_equ_idx; | ||
| 358 | pset->volt_rail_idx = pclk_vf_point->volt_rail_idx; | ||
| 359 | return status; | ||
| 360 | } | ||
| 361 | |||
| 362 | |||
| 363 | static int clk_vf_point_update(struct gk20a *g, | ||
| 364 | struct boardobj *board_obj_ptr, | ||
| 365 | struct nv_pmu_boardobj *ppmudata) | ||
| 366 | { | ||
| 367 | struct clk_vf_point *pclk_vf_point; | ||
| 368 | struct nv_pmu_clk_clk_vf_point_boardobj_get_status *pstatus; | ||
| 369 | |||
| 370 | nvgpu_log_info(g, " "); | ||
| 371 | |||
| 372 | |||
| 373 | pclk_vf_point = | ||
| 374 | (struct clk_vf_point *)board_obj_ptr; | ||
| 375 | |||
| 376 | pstatus = (struct nv_pmu_clk_clk_vf_point_boardobj_get_status *) | ||
| 377 | ppmudata; | ||
| 378 | |||
| 379 | if (pstatus->super.type != pclk_vf_point->super.type) { | ||
| 380 | nvgpu_err(g, | ||
| 381 | "pmu data and boardobj type not matching"); | ||
| 382 | return -EINVAL; | ||
| 383 | } | ||
| 384 | /* now copy VF pair */ | ||
| 385 | memcpy(&pclk_vf_point->pair, &pstatus->pair, | ||
| 386 | sizeof(struct ctrl_clk_vf_pair)); | ||
| 387 | return 0; | ||
| 388 | } | ||
| 389 | |||
| 390 | /*get latest vf point data from PMU */ | ||
| 391 | int clk_vf_point_cache(struct gk20a *g) | ||
| 392 | { | ||
| 393 | |||
| 394 | struct clk_vf_points *pclk_vf_points; | ||
| 395 | struct boardobjgrp *pboardobjgrp; | ||
| 396 | struct boardobjgrpmask *pboardobjgrpmask; | ||
| 397 | struct nv_pmu_boardobjgrp_super *pboardobjgrppmu; | ||
| 398 | struct boardobj *pboardobj = NULL; | ||
| 399 | struct nv_pmu_boardobj_query *pboardobjpmustatus = NULL; | ||
| 400 | int status; | ||
| 401 | u8 index; | ||
| 402 | |||
| 403 | nvgpu_log_info(g, " "); | ||
| 404 | pclk_vf_points = &g->clk_pmu.clk_vf_pointobjs; | ||
| 405 | pboardobjgrp = &pclk_vf_points->super.super; | ||
| 406 | pboardobjgrpmask = &pclk_vf_points->super.mask.super; | ||
| 407 | |||
| 408 | status = pboardobjgrp->pmugetstatus(g, pboardobjgrp, pboardobjgrpmask); | ||
| 409 | if (status) { | ||
| 410 | nvgpu_err(g, "err getting boardobjs from pmu"); | ||
| 411 | return status; | ||
| 412 | } | ||
| 413 | pboardobjgrppmu = pboardobjgrp->pmu.getstatus.buf; | ||
| 414 | |||
| 415 | BOARDOBJGRP_FOR_EACH(pboardobjgrp, struct boardobj*, pboardobj, index) { | ||
| 416 | status = pboardobjgrp->pmustatusinstget(g, | ||
| 417 | (struct nv_pmu_boardobjgrp *)pboardobjgrppmu, | ||
| 418 | &pboardobjpmustatus, index); | ||
| 419 | if (status) { | ||
| 420 | nvgpu_err(g, "could not get status object instance"); | ||
| 421 | return status; | ||
| 422 | } | ||
| 423 | |||
| 424 | status = clk_vf_point_update(g, pboardobj, | ||
| 425 | (struct nv_pmu_boardobj *)pboardobjpmustatus); | ||
| 426 | if (status) { | ||
| 427 | nvgpu_err(g, "invalid data from pmu at %d", index); | ||
| 428 | return status; | ||
| 429 | } | ||
| 430 | } | ||
| 431 | |||
| 432 | return 0; | ||
| 433 | } | ||
diff --git a/include/clk/clk_vf_point.h b/include/clk/clk_vf_point.h deleted file mode 100644 index b72fe64..0000000 --- a/include/clk/clk_vf_point.h +++ /dev/null | |||
| @@ -1,83 +0,0 @@ | |||
| 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 | #ifndef NVGPU_CLK_VF_POINT_H | ||
| 24 | #define NVGPU_CLK_VF_POINT_H | ||
| 25 | #include "ctrl/ctrlclk.h" | ||
| 26 | #include "ctrl/ctrlboardobj.h" | ||
| 27 | #include <nvgpu/pmuif/nvgpu_gpmu_cmdif.h> | ||
| 28 | #include "boardobj/boardobjgrp_e32.h" | ||
| 29 | #include "boardobj/boardobjgrpmask.h" | ||
| 30 | |||
| 31 | int clk_vf_point_sw_setup(struct gk20a *g); | ||
| 32 | int clk_vf_point_pmu_setup(struct gk20a *g); | ||
| 33 | int clk_vf_point_cache(struct gk20a *g); | ||
| 34 | |||
| 35 | struct clk_vf_points { | ||
| 36 | struct boardobjgrp_e255 super; | ||
| 37 | }; | ||
| 38 | |||
| 39 | struct clk_vf_point { | ||
| 40 | struct boardobj super; | ||
| 41 | u8 vfe_equ_idx; | ||
| 42 | u8 volt_rail_idx; | ||
| 43 | struct ctrl_clk_vf_pair pair; | ||
| 44 | }; | ||
| 45 | |||
| 46 | struct clk_vf_point_volt { | ||
| 47 | struct clk_vf_point super; | ||
| 48 | u32 source_voltage_uv; | ||
| 49 | struct ctrl_clk_freq_delta freq_delta; | ||
| 50 | }; | ||
| 51 | |||
| 52 | struct clk_vf_point_freq { | ||
| 53 | struct clk_vf_point super; | ||
| 54 | int volt_delta_uv; | ||
| 55 | }; | ||
| 56 | |||
| 57 | #define CLK_CLK_VF_POINT_GET(pclk, idx) \ | ||
| 58 | ((struct clk_vf_point *)BOARDOBJGRP_OBJ_GET_BY_IDX( \ | ||
| 59 | &pclk->clk_vf_pointobjs.super.super, (u8)(idx))) | ||
| 60 | |||
| 61 | #define clkvfpointpairget(pvfpoint) \ | ||
| 62 | (&((pvfpoint)->pair)) | ||
| 63 | |||
| 64 | #define clkvfpointfreqmhzget(pgpu, pvfpoint) \ | ||
| 65 | CTRL_CLK_VF_PAIR_FREQ_MHZ_GET(clkvfpointpairget(pvfpoint)) | ||
| 66 | |||
| 67 | #define clkvfpointfreqdeltamhzGet(pgpu, pvfPoint) \ | ||
| 68 | ((BOARDOBJ_GET_TYPE(pvfpoint) == CTRL_CLK_CLK_VF_POINT_TYPE_VOLT) ? \ | ||
| 69 | (((struct clk_vf_point_volt *)(pvfpoint))->freq_delta_khz / 1000) : 0) | ||
| 70 | |||
| 71 | #define clkvfpointfreqmhzset(pgpu, pvfpoint, _freqmhz) \ | ||
| 72 | CTRL_CLK_VF_PAIR_FREQ_MHZ_SET(clkvfpointpairget(pvfpoint), _freqmhz) | ||
| 73 | |||
| 74 | #define clkvfpointvoltageuvset(pgpu, pvfpoint, _voltageuv) \ | ||
| 75 | CTRL_CLK_VF_PAIR_VOLTAGE_UV_SET(clkvfpointpairget(pvfpoint), \ | ||
| 76 | _voltageuv) | ||
| 77 | |||
| 78 | #define clkvfpointvoltageuvget(pgpu, pvfpoint) \ | ||
| 79 | CTRL_CLK_VF_PAIR_VOLTAGE_UV_GET(clkvfpointpairget(pvfpoint)) \ | ||
| 80 | |||
| 81 | struct clk_vf_point *construct_clk_vf_point(struct gk20a *g, void *pargs); | ||
| 82 | |||
| 83 | #endif /* NVGPU_CLK_VF_POINT_H */ | ||
diff --git a/include/clk/clk_vin.c b/include/clk/clk_vin.c deleted file mode 100644 index e0a4a5b..0000000 --- a/include/clk/clk_vin.c +++ /dev/null | |||
| @@ -1,573 +0,0 @@ | |||
| 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/pmuif/nvgpu_gpmu_cmdif.h> | ||
| 25 | #include <nvgpu/io.h> | ||
| 26 | #include <nvgpu/gk20a.h> | ||
| 27 | |||
| 28 | #include "boardobj/boardobjgrp.h" | ||
| 29 | #include "boardobj/boardobjgrp_e32.h" | ||
| 30 | |||
| 31 | #include "ctrl/ctrlvolt.h" | ||
| 32 | |||
| 33 | #include "gp106/bios_gp106.h" | ||
| 34 | |||
| 35 | #include "clk.h" | ||
| 36 | #include "clk_vin.h" | ||
| 37 | |||
| 38 | static int devinit_get_vin_device_table(struct gk20a *g, | ||
| 39 | struct avfsvinobjs *pvinobjs); | ||
| 40 | |||
| 41 | static int vin_device_construct_v10(struct gk20a *g, | ||
| 42 | struct boardobj **ppboardobj, | ||
| 43 | u16 size, void *pargs); | ||
| 44 | static int vin_device_construct_v20(struct gk20a *g, | ||
| 45 | struct boardobj **ppboardobj, | ||
| 46 | u16 size, void *pargs); | ||
| 47 | static int vin_device_construct_super(struct gk20a *g, | ||
| 48 | struct boardobj **ppboardobj, | ||
| 49 | u16 size, void *pargs); | ||
| 50 | static struct vin_device *construct_vin_device(struct gk20a *g, void *pargs); | ||
| 51 | |||
| 52 | static int vin_device_init_pmudata_v10(struct gk20a *g, | ||
| 53 | struct boardobj *board_obj_ptr, | ||
| 54 | struct nv_pmu_boardobj *ppmudata); | ||
| 55 | static int vin_device_init_pmudata_v20(struct gk20a *g, | ||
| 56 | struct boardobj *board_obj_ptr, | ||
| 57 | struct nv_pmu_boardobj *ppmudata); | ||
| 58 | static int vin_device_init_pmudata_super(struct gk20a *g, | ||
| 59 | struct boardobj *board_obj_ptr, | ||
| 60 | struct nv_pmu_boardobj *ppmudata); | ||
| 61 | |||
| 62 | u32 clk_avfs_get_vin_cal_fuse_v10(struct gk20a *g, | ||
| 63 | struct avfsvinobjs *pvinobjs, | ||
| 64 | struct vin_device_v20 *pvindev) | ||
| 65 | { | ||
| 66 | u32 status = 0; | ||
| 67 | u32 slope, intercept; | ||
| 68 | u8 i; | ||
| 69 | |||
| 70 | if (pvinobjs->calibration_rev_vbios == g->ops.fuse.read_vin_cal_fuse_rev(g)) { | ||
| 71 | BOARDOBJGRP_FOR_EACH(&(pvinobjs->super.super), | ||
| 72 | struct vin_device_v20 *, pvindev, i) { | ||
| 73 | slope = 0; | ||
| 74 | intercept = 0; | ||
| 75 | pvindev = (struct vin_device_v20 *)CLK_GET_VIN_DEVICE(pvinobjs, i); | ||
| 76 | status = g->ops.fuse.read_vin_cal_slope_intercept_fuse(g, | ||
| 77 | pvindev->super.id, &slope, &intercept); | ||
| 78 | if (status) { | ||
| 79 | nvgpu_err(g, | ||
| 80 | "err reading vin cal for id %x", pvindev->super.id); | ||
| 81 | return status; | ||
| 82 | } | ||
| 83 | pvindev->data.vin_cal.cal_v10.slope = slope; | ||
| 84 | pvindev->data.vin_cal.cal_v10.intercept = intercept; | ||
| 85 | } | ||
| 86 | } | ||
| 87 | return status; | ||
| 88 | |||
| 89 | } | ||
| 90 | |||
| 91 | u32 clk_avfs_get_vin_cal_fuse_v20(struct gk20a *g, | ||
| 92 | struct avfsvinobjs *pvinobjs, | ||
| 93 | struct vin_device_v20 *pvindev) | ||
| 94 | { | ||
| 95 | u32 status = 0; | ||
| 96 | s8 gain, offset; | ||
| 97 | u8 i; | ||
| 98 | |||
| 99 | if (pvinobjs->calibration_rev_vbios == g->ops.fuse.read_vin_cal_fuse_rev(g)) { | ||
| 100 | BOARDOBJGRP_FOR_EACH(&(pvinobjs->super.super), | ||
| 101 | struct vin_device_v20 *, pvindev, i) { | ||
| 102 | gain = '\0'; | ||
| 103 | offset = '\0'; | ||
| 104 | pvindev = (struct vin_device_v20 *)CLK_GET_VIN_DEVICE(pvinobjs, i); | ||
| 105 | status = g->ops.fuse.read_vin_cal_gain_offset_fuse(g, | ||
| 106 | pvindev->super.id, &gain, &offset); | ||
| 107 | if (status) { | ||
| 108 | nvgpu_err(g, | ||
| 109 | "err reading vin cal for id %x", pvindev->super.id); | ||
| 110 | return status; | ||
| 111 | } | ||
| 112 | pvindev->data.vin_cal.cal_v20.gain = gain; | ||
| 113 | pvindev->data.vin_cal.cal_v20.offset = offset; | ||
| 114 | } | ||
| 115 | } | ||
| 116 | return status; | ||
| 117 | |||
| 118 | } | ||
| 119 | |||
| 120 | static int _clk_vin_devgrp_pmudatainit_super(struct gk20a *g, | ||
| 121 | struct boardobjgrp *pboardobjgrp, | ||
| 122 | struct nv_pmu_boardobjgrp_super *pboardobjgrppmu) | ||
| 123 | { | ||
| 124 | struct nv_pmu_clk_clk_vin_device_boardobjgrp_set_header *pset = | ||
| 125 | (struct nv_pmu_clk_clk_vin_device_boardobjgrp_set_header *) | ||
| 126 | pboardobjgrppmu; | ||
| 127 | struct avfsvinobjs *pvin_obbj = (struct avfsvinobjs *)pboardobjgrp; | ||
| 128 | int status = 0; | ||
| 129 | |||
| 130 | nvgpu_log_info(g, " "); | ||
| 131 | |||
| 132 | status = boardobjgrp_pmudatainit_e32(g, pboardobjgrp, pboardobjgrppmu); | ||
| 133 | |||
| 134 | pset->b_vin_is_disable_allowed = pvin_obbj->vin_is_disable_allowed; | ||
| 135 | |||
| 136 | nvgpu_log_info(g, " Done"); | ||
| 137 | return status; | ||
| 138 | } | ||
| 139 | |||
| 140 | static int _clk_vin_devgrp_pmudata_instget(struct gk20a *g, | ||
| 141 | struct nv_pmu_boardobjgrp *pmuboardobjgrp, | ||
| 142 | struct nv_pmu_boardobj **ppboardobjpmudata, | ||
| 143 | u8 idx) | ||
| 144 | { | ||
| 145 | struct nv_pmu_clk_clk_vin_device_boardobj_grp_set *pgrp_set = | ||
| 146 | (struct nv_pmu_clk_clk_vin_device_boardobj_grp_set *) | ||
| 147 | pmuboardobjgrp; | ||
| 148 | |||
| 149 | nvgpu_log_info(g, " "); | ||
| 150 | |||
| 151 | /*check whether pmuboardobjgrp has a valid boardobj in index*/ | ||
| 152 | if (((u32)BIT(idx) & | ||
| 153 | pgrp_set->hdr.data.super.obj_mask.super.data[0]) == 0) { | ||
| 154 | return -EINVAL; | ||
| 155 | } | ||
| 156 | |||
| 157 | *ppboardobjpmudata = (struct nv_pmu_boardobj *) | ||
| 158 | &pgrp_set->objects[idx].data.board_obj; | ||
| 159 | nvgpu_log_info(g, " Done"); | ||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | static int _clk_vin_devgrp_pmustatus_instget(struct gk20a *g, | ||
| 164 | void *pboardobjgrppmu, | ||
| 165 | struct nv_pmu_boardobj_query **ppboardobjpmustatus, | ||
| 166 | u8 idx) | ||
| 167 | { | ||
| 168 | struct nv_pmu_clk_clk_vin_device_boardobj_grp_get_status *pgrp_get_status = | ||
| 169 | (struct nv_pmu_clk_clk_vin_device_boardobj_grp_get_status *) | ||
| 170 | pboardobjgrppmu; | ||
| 171 | |||
| 172 | /*check whether pmuboardobjgrp has a valid boardobj in index*/ | ||
| 173 | if (((u32)BIT(idx) & | ||
| 174 | pgrp_get_status->hdr.data.super.obj_mask.super.data[0]) == 0) { | ||
| 175 | return -EINVAL; | ||
| 176 | } | ||
| 177 | |||
| 178 | *ppboardobjpmustatus = (struct nv_pmu_boardobj_query *) | ||
| 179 | &pgrp_get_status->objects[idx].data.board_obj; | ||
| 180 | return 0; | ||
| 181 | } | ||
| 182 | |||
| 183 | int clk_vin_sw_setup(struct gk20a *g) | ||
| 184 | { | ||
| 185 | int status; | ||
| 186 | struct boardobjgrp *pboardobjgrp = NULL; | ||
| 187 | struct vin_device_v20 *pvindev = NULL; | ||
| 188 | struct avfsvinobjs *pvinobjs; | ||
| 189 | |||
| 190 | nvgpu_log_info(g, " "); | ||
| 191 | |||
| 192 | status = boardobjgrpconstruct_e32(g, &g->clk_pmu.avfs_vinobjs.super); | ||
| 193 | if (status) { | ||
| 194 | nvgpu_err(g, | ||
| 195 | "error creating boardobjgrp for clk vin, statu - 0x%x", | ||
| 196 | status); | ||
| 197 | goto done; | ||
| 198 | } | ||
| 199 | |||
| 200 | pboardobjgrp = &g->clk_pmu.avfs_vinobjs.super.super; | ||
| 201 | pvinobjs = &g->clk_pmu.avfs_vinobjs; | ||
| 202 | |||
| 203 | BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, CLK, VIN_DEVICE); | ||
| 204 | |||
| 205 | status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp, | ||
| 206 | clk, CLK, clk_vin_device, CLK_VIN_DEVICE); | ||
| 207 | if (status) { | ||
| 208 | nvgpu_err(g, | ||
| 209 | "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x", | ||
| 210 | status); | ||
| 211 | goto done; | ||
| 212 | } | ||
| 213 | |||
| 214 | pboardobjgrp->pmudatainit = _clk_vin_devgrp_pmudatainit_super; | ||
| 215 | pboardobjgrp->pmudatainstget = _clk_vin_devgrp_pmudata_instget; | ||
| 216 | pboardobjgrp->pmustatusinstget = _clk_vin_devgrp_pmustatus_instget; | ||
| 217 | |||
| 218 | status = devinit_get_vin_device_table(g, &g->clk_pmu.avfs_vinobjs); | ||
| 219 | if (status) { | ||
| 220 | goto done; | ||
| 221 | } | ||
| 222 | |||
| 223 | /*update vin calibration to fuse */ | ||
| 224 | g->ops.pmu_ver.clk.clk_avfs_get_vin_cal_data(g, pvinobjs, pvindev); | ||
| 225 | |||
| 226 | status = BOARDOBJGRP_PMU_CMD_GRP_GET_STATUS_CONSTRUCT(g, | ||
| 227 | &g->clk_pmu.avfs_vinobjs.super.super, | ||
| 228 | clk, CLK, clk_vin_device, CLK_VIN_DEVICE); | ||
| 229 | if (status) { | ||
| 230 | nvgpu_err(g, | ||
| 231 | "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x", | ||
| 232 | status); | ||
| 233 | goto done; | ||
| 234 | } | ||
| 235 | |||
| 236 | done: | ||
| 237 | nvgpu_log_info(g, " done status %x", status); | ||
| 238 | return status; | ||
| 239 | } | ||
| 240 | |||
| 241 | int clk_vin_pmu_setup(struct gk20a *g) | ||
| 242 | { | ||
| 243 | int status; | ||
| 244 | struct boardobjgrp *pboardobjgrp = NULL; | ||
| 245 | |||
| 246 | nvgpu_log_info(g, " "); | ||
| 247 | |||
| 248 | pboardobjgrp = &g->clk_pmu.avfs_vinobjs.super.super; | ||
| 249 | |||
| 250 | if (!pboardobjgrp->bconstructed) { | ||
| 251 | return -EINVAL; | ||
| 252 | } | ||
| 253 | |||
| 254 | status = pboardobjgrp->pmuinithandle(g, pboardobjgrp); | ||
| 255 | |||
| 256 | nvgpu_log_info(g, "Done"); | ||
| 257 | return status; | ||
| 258 | } | ||
| 259 | |||
| 260 | static int devinit_get_vin_device_table(struct gk20a *g, | ||
| 261 | struct avfsvinobjs *pvinobjs) | ||
| 262 | { | ||
| 263 | int status = 0; | ||
| 264 | u8 *vin_table_ptr = NULL; | ||
| 265 | struct vin_descriptor_header_10 vin_desc_table_header = { 0 }; | ||
| 266 | struct vin_descriptor_entry_10 vin_desc_table_entry = { 0 }; | ||
| 267 | u8 *vin_tbl_entry_ptr = NULL; | ||
| 268 | u32 index = 0; | ||
| 269 | u32 slope=0, intercept=0; | ||
| 270 | s8 offset='\0', gain='\0'; | ||
| 271 | struct vin_device *pvin_dev; | ||
| 272 | u32 cal_type; | ||
| 273 | |||
| 274 | union { | ||
| 275 | struct boardobj boardobj; | ||
| 276 | struct vin_device vin_device; | ||
| 277 | struct vin_device_v10 vin_device_v10; | ||
| 278 | struct vin_device_v20 vin_device_v20; | ||
| 279 | } vin_device_data; | ||
| 280 | |||
| 281 | nvgpu_log_info(g, " "); | ||
| 282 | |||
| 283 | vin_table_ptr = (u8 *)nvgpu_bios_get_perf_table_ptrs(g, | ||
| 284 | g->bios.clock_token, VIN_TABLE); | ||
| 285 | if (vin_table_ptr == NULL) { | ||
| 286 | status = -1; | ||
| 287 | goto done; | ||
| 288 | } | ||
| 289 | |||
| 290 | memcpy(&vin_desc_table_header, vin_table_ptr, | ||
| 291 | sizeof(struct vin_descriptor_header_10)); | ||
| 292 | |||
| 293 | pvinobjs->calibration_rev_vbios = | ||
| 294 | BIOS_GET_FIELD(vin_desc_table_header.flags0, | ||
| 295 | NV_VIN_DESC_FLAGS0_VIN_CAL_REVISION); | ||
| 296 | pvinobjs->vin_is_disable_allowed = | ||
| 297 | BIOS_GET_FIELD(vin_desc_table_header.flags0, | ||
| 298 | NV_VIN_DESC_FLAGS0_DISABLE_CONTROL); | ||
| 299 | cal_type = BIOS_GET_FIELD(vin_desc_table_header.flags0, | ||
| 300 | NV_VIN_DESC_FLAGS0_VIN_CAL_TYPE); | ||
| 301 | if (!cal_type) { | ||
| 302 | cal_type = CTRL_CLK_VIN_CAL_TYPE_V10; | ||
| 303 | } | ||
| 304 | |||
| 305 | switch (cal_type) { | ||
| 306 | case CTRL_CLK_VIN_CAL_TYPE_V10: | ||
| 307 | /* VIN calibration slope: XX.YYY mV/code => XXYYY uV/code*/ | ||
| 308 | slope = ((BIOS_GET_FIELD(vin_desc_table_header.vin_cal, | ||
| 309 | NV_VIN_DESC_VIN_CAL_SLOPE_INTEGER) * 1000)) + | ||
| 310 | ((BIOS_GET_FIELD(vin_desc_table_header.vin_cal, | ||
| 311 | NV_VIN_DESC_VIN_CAL_SLOPE_FRACTION))); | ||
| 312 | |||
| 313 | /* VIN calibration intercept: ZZZ.W mV => ZZZW00 uV */ | ||
| 314 | intercept = ((BIOS_GET_FIELD(vin_desc_table_header.vin_cal, | ||
| 315 | NV_VIN_DESC_VIN_CAL_INTERCEPT_INTEGER) * 1000)) + | ||
| 316 | ((BIOS_GET_FIELD(vin_desc_table_header.vin_cal, | ||
| 317 | NV_VIN_DESC_VIN_CAL_INTERCEPT_FRACTION) * 100)); | ||
| 318 | |||
| 319 | break; | ||
| 320 | case CTRL_CLK_VIN_CAL_TYPE_V20: | ||
| 321 | offset = BIOS_GET_FIELD(vin_desc_table_header.vin_cal, | ||
| 322 | NV_VIN_DESC_VIN_CAL_OFFSET); | ||
| 323 | gain = BIOS_GET_FIELD(vin_desc_table_header.vin_cal, | ||
| 324 | NV_VIN_DESC_VIN_CAL_GAIN); | ||
| 325 | break; | ||
| 326 | default: | ||
| 327 | status = -1; | ||
| 328 | goto done; | ||
| 329 | } | ||
| 330 | /* Read table entries*/ | ||
| 331 | vin_tbl_entry_ptr = vin_table_ptr + vin_desc_table_header.header_sizee; | ||
| 332 | for (index = 0; index < vin_desc_table_header.entry_count; index++) { | ||
| 333 | memcpy(&vin_desc_table_entry, vin_tbl_entry_ptr, | ||
| 334 | sizeof(struct vin_descriptor_entry_10)); | ||
| 335 | |||
| 336 | if (vin_desc_table_entry.vin_device_type == CTRL_CLK_VIN_TYPE_DISABLED) { | ||
| 337 | continue; | ||
| 338 | } | ||
| 339 | |||
| 340 | vin_device_data.boardobj.type = | ||
| 341 | (u8)vin_desc_table_entry.vin_device_type; | ||
| 342 | vin_device_data.vin_device.id = (u8)vin_desc_table_entry.vin_device_id; | ||
| 343 | vin_device_data.vin_device.volt_domain_vbios = | ||
| 344 | (u8)vin_desc_table_entry.volt_domain_vbios; | ||
| 345 | vin_device_data.vin_device.flls_shared_mask = 0; | ||
| 346 | |||
| 347 | switch (vin_device_data.boardobj.type) { | ||
| 348 | case CTRL_CLK_VIN_TYPE_V10: | ||
| 349 | vin_device_data.vin_device_v10.data.vin_cal.slope = slope; | ||
| 350 | vin_device_data.vin_device_v10.data.vin_cal.intercept = intercept; | ||
| 351 | break; | ||
| 352 | case CTRL_CLK_VIN_TYPE_V20: | ||
| 353 | vin_device_data.vin_device_v20.data.cal_type = (u8) cal_type; | ||
| 354 | vin_device_data.vin_device_v20.data.vin_cal.cal_v20.offset = offset; | ||
| 355 | vin_device_data.vin_device_v20.data.vin_cal.cal_v20.gain = gain; | ||
| 356 | break; | ||
| 357 | default: | ||
| 358 | status = -1; | ||
| 359 | goto done; | ||
| 360 | }; | ||
| 361 | |||
| 362 | pvin_dev = construct_vin_device(g, (void *)&vin_device_data); | ||
| 363 | |||
| 364 | status = boardobjgrp_objinsert(&pvinobjs->super.super, | ||
| 365 | (struct boardobj *)pvin_dev, index); | ||
| 366 | |||
| 367 | vin_tbl_entry_ptr += vin_desc_table_header.entry_size; | ||
| 368 | } | ||
| 369 | |||
| 370 | done: | ||
| 371 | nvgpu_log_info(g, " done status %x", status); | ||
| 372 | return status; | ||
| 373 | } | ||
| 374 | |||
| 375 | static int vin_device_construct_v10(struct gk20a *g, | ||
| 376 | struct boardobj **ppboardobj, | ||
| 377 | u16 size, void *pargs) | ||
| 378 | { | ||
| 379 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
| 380 | struct vin_device_v10 *pvin_device_v10; | ||
| 381 | struct vin_device_v10 *ptmpvin_device_v10 = (struct vin_device_v10 *)pargs; | ||
| 382 | int status = 0; | ||
| 383 | |||
| 384 | if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_VIN_TYPE_V10) { | ||
| 385 | return -EINVAL; | ||
| 386 | } | ||
| 387 | |||
| 388 | ptmpobj->type_mask |= BIT(CTRL_CLK_VIN_TYPE_V10); | ||
| 389 | status = vin_device_construct_super(g, ppboardobj, size, pargs); | ||
| 390 | if (status) { | ||
| 391 | return -EINVAL; | ||
| 392 | } | ||
| 393 | |||
| 394 | pvin_device_v10 = (struct vin_device_v10 *)*ppboardobj; | ||
| 395 | |||
| 396 | pvin_device_v10->super.super.pmudatainit = | ||
| 397 | vin_device_init_pmudata_v10; | ||
| 398 | |||
| 399 | pvin_device_v10->data.vin_cal.slope = ptmpvin_device_v10->data.vin_cal.slope; | ||
| 400 | pvin_device_v10->data.vin_cal.intercept = ptmpvin_device_v10->data.vin_cal.intercept; | ||
| 401 | |||
| 402 | return status; | ||
| 403 | } | ||
| 404 | |||
| 405 | static int vin_device_construct_v20(struct gk20a *g, | ||
| 406 | struct boardobj **ppboardobj, | ||
| 407 | u16 size, void *pargs) | ||
| 408 | { | ||
| 409 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
| 410 | struct vin_device_v20 *pvin_device_v20; | ||
| 411 | struct vin_device_v20 *ptmpvin_device_v20 = (struct vin_device_v20 *)pargs; | ||
| 412 | int status = 0; | ||
| 413 | |||
| 414 | if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_VIN_TYPE_V20) { | ||
| 415 | return -EINVAL; | ||
| 416 | } | ||
| 417 | |||
| 418 | ptmpobj->type_mask |= BIT(CTRL_CLK_VIN_TYPE_V20); | ||
| 419 | status = vin_device_construct_super(g, ppboardobj, size, pargs); | ||
| 420 | if (status) { | ||
| 421 | return -EINVAL; | ||
| 422 | } | ||
| 423 | |||
| 424 | pvin_device_v20 = (struct vin_device_v20 *)*ppboardobj; | ||
| 425 | |||
| 426 | pvin_device_v20->super.super.pmudatainit = | ||
| 427 | vin_device_init_pmudata_v20; | ||
| 428 | |||
| 429 | pvin_device_v20->data.cal_type = ptmpvin_device_v20->data.cal_type; | ||
| 430 | pvin_device_v20->data.vin_cal.cal_v20.offset = ptmpvin_device_v20->data.vin_cal.cal_v20.offset; | ||
| 431 | pvin_device_v20->data.vin_cal.cal_v20.gain = ptmpvin_device_v20->data.vin_cal.cal_v20.gain; | ||
| 432 | |||
| 433 | return status; | ||
| 434 | } | ||
| 435 | static int vin_device_construct_super(struct gk20a *g, | ||
| 436 | struct boardobj **ppboardobj, | ||
| 437 | u16 size, void *pargs) | ||
| 438 | { | ||
| 439 | struct vin_device *pvin_device; | ||
| 440 | struct vin_device *ptmpvin_device = (struct vin_device *)pargs; | ||
| 441 | int status = 0; | ||
| 442 | status = boardobj_construct_super(g, ppboardobj, size, pargs); | ||
| 443 | |||
| 444 | if (status) { | ||
| 445 | return -EINVAL; | ||
| 446 | } | ||
| 447 | |||
| 448 | pvin_device = (struct vin_device *)*ppboardobj; | ||
| 449 | |||
| 450 | pvin_device->super.pmudatainit = | ||
| 451 | vin_device_init_pmudata_super; | ||
| 452 | |||
| 453 | pvin_device->id = ptmpvin_device->id; | ||
| 454 | pvin_device->volt_domain_vbios = ptmpvin_device->volt_domain_vbios; | ||
| 455 | pvin_device->flls_shared_mask = ptmpvin_device->flls_shared_mask; | ||
| 456 | pvin_device->volt_domain = CTRL_VOLT_DOMAIN_LOGIC; | ||
| 457 | |||
| 458 | return status; | ||
| 459 | } | ||
| 460 | static struct vin_device *construct_vin_device(struct gk20a *g, void *pargs) | ||
| 461 | { | ||
| 462 | struct boardobj *board_obj_ptr = NULL; | ||
| 463 | int status; | ||
| 464 | |||
| 465 | nvgpu_log_info(g, " %d", BOARDOBJ_GET_TYPE(pargs)); | ||
| 466 | switch (BOARDOBJ_GET_TYPE(pargs)) { | ||
| 467 | case CTRL_CLK_VIN_TYPE_V10: | ||
| 468 | status = vin_device_construct_v10(g, &board_obj_ptr, | ||
| 469 | sizeof(struct vin_device_v10), pargs); | ||
| 470 | break; | ||
| 471 | |||
| 472 | case CTRL_CLK_VIN_TYPE_V20: | ||
| 473 | status = vin_device_construct_v20(g, &board_obj_ptr, | ||
| 474 | sizeof(struct vin_device_v20), pargs); | ||
| 475 | break; | ||
| 476 | |||
| 477 | default: | ||
| 478 | return NULL; | ||
| 479 | }; | ||
| 480 | |||
| 481 | if (status) { | ||
| 482 | return NULL; | ||
| 483 | } | ||
| 484 | |||
| 485 | nvgpu_log_info(g, " Done"); | ||
| 486 | |||
| 487 | return (struct vin_device *)board_obj_ptr; | ||
| 488 | } | ||
| 489 | |||
| 490 | |||
| 491 | |||
| 492 | static int vin_device_init_pmudata_v10(struct gk20a *g, | ||
| 493 | struct boardobj *board_obj_ptr, | ||
| 494 | struct nv_pmu_boardobj *ppmudata) | ||
| 495 | { | ||
| 496 | int status = 0; | ||
| 497 | struct vin_device_v20 *pvin_dev_v20; | ||
| 498 | struct nv_pmu_clk_clk_vin_device_v10_boardobj_set *perf_pmu_data; | ||
| 499 | |||
| 500 | nvgpu_log_info(g, " "); | ||
| 501 | |||
| 502 | status = vin_device_init_pmudata_super(g, board_obj_ptr, ppmudata); | ||
| 503 | if (status != 0) { | ||
| 504 | return status; | ||
| 505 | } | ||
| 506 | |||
| 507 | pvin_dev_v20 = (struct vin_device_v20 *)board_obj_ptr; | ||
| 508 | perf_pmu_data = (struct nv_pmu_clk_clk_vin_device_v10_boardobj_set *) | ||
| 509 | ppmudata; | ||
| 510 | |||
| 511 | perf_pmu_data->data.vin_cal.intercept = pvin_dev_v20->data.vin_cal.cal_v10.intercept; | ||
| 512 | perf_pmu_data->data.vin_cal.slope = pvin_dev_v20->data.vin_cal.cal_v10.slope; | ||
| 513 | |||
| 514 | nvgpu_log_info(g, " Done"); | ||
| 515 | |||
| 516 | return status; | ||
| 517 | } | ||
| 518 | |||
| 519 | static int vin_device_init_pmudata_v20(struct gk20a *g, | ||
| 520 | struct boardobj *board_obj_ptr, | ||
| 521 | struct nv_pmu_boardobj *ppmudata) | ||
| 522 | { | ||
| 523 | int status = 0; | ||
| 524 | struct vin_device_v20 *pvin_dev_v20; | ||
| 525 | struct nv_pmu_clk_clk_vin_device_v20_boardobj_set *perf_pmu_data; | ||
| 526 | |||
| 527 | nvgpu_log_info(g, " "); | ||
| 528 | |||
| 529 | status = vin_device_init_pmudata_super(g, board_obj_ptr, ppmudata); | ||
| 530 | if (status != 0) { | ||
| 531 | return status; | ||
| 532 | } | ||
| 533 | |||
| 534 | pvin_dev_v20 = (struct vin_device_v20 *)board_obj_ptr; | ||
| 535 | perf_pmu_data = (struct nv_pmu_clk_clk_vin_device_v20_boardobj_set *) | ||
| 536 | ppmudata; | ||
| 537 | |||
| 538 | perf_pmu_data->data.cal_type = pvin_dev_v20->data.cal_type; | ||
| 539 | perf_pmu_data->data.vin_cal.cal_v20.offset = pvin_dev_v20->data.vin_cal.cal_v20.offset; | ||
| 540 | perf_pmu_data->data.vin_cal.cal_v20.gain = pvin_dev_v20->data.vin_cal.cal_v20.gain; | ||
| 541 | |||
| 542 | nvgpu_log_info(g, " Done"); | ||
| 543 | |||
| 544 | return status; | ||
| 545 | } | ||
| 546 | |||
| 547 | static int vin_device_init_pmudata_super(struct gk20a *g, | ||
| 548 | struct boardobj *board_obj_ptr, | ||
| 549 | struct nv_pmu_boardobj *ppmudata) | ||
| 550 | { | ||
| 551 | int status = 0; | ||
| 552 | struct vin_device *pvin_dev; | ||
| 553 | struct nv_pmu_clk_clk_vin_device_boardobj_set *perf_pmu_data; | ||
| 554 | |||
| 555 | nvgpu_log_info(g, " "); | ||
| 556 | |||
| 557 | status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata); | ||
| 558 | if (status != 0) { | ||
| 559 | return status; | ||
| 560 | } | ||
| 561 | |||
| 562 | pvin_dev = (struct vin_device *)board_obj_ptr; | ||
| 563 | perf_pmu_data = (struct nv_pmu_clk_clk_vin_device_boardobj_set *) | ||
| 564 | ppmudata; | ||
| 565 | |||
| 566 | perf_pmu_data->id = pvin_dev->id; | ||
| 567 | perf_pmu_data->volt_domain = pvin_dev->volt_domain; | ||
| 568 | perf_pmu_data->flls_shared_mask = pvin_dev->flls_shared_mask; | ||
| 569 | |||
| 570 | nvgpu_log_info(g, " Done"); | ||
| 571 | |||
| 572 | return status; | ||
| 573 | } | ||
diff --git a/include/clk/clk_vin.h b/include/clk/clk_vin.h deleted file mode 100644 index 73b93e4..0000000 --- a/include/clk/clk_vin.h +++ /dev/null | |||
| @@ -1,79 +0,0 @@ | |||
| 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 | #ifndef NVGPU_CLK_VIN_H | ||
| 24 | #define NVGPU_CLK_VIN_H | ||
| 25 | |||
| 26 | #include "boardobj/boardobj.h" | ||
| 27 | #include "boardobj/boardobjgrp.h" | ||
| 28 | #include "boardobj/boardobjgrp_e32.h" | ||
| 29 | |||
| 30 | struct vin_device; | ||
| 31 | struct clk_pmupstate; | ||
| 32 | |||
| 33 | struct avfsvinobjs { | ||
| 34 | struct boardobjgrp_e32 super; | ||
| 35 | u8 calibration_rev_vbios; | ||
| 36 | u8 calibration_rev_fused; | ||
| 37 | bool vin_is_disable_allowed; | ||
| 38 | }; | ||
| 39 | typedef u32 vin_device_state_load(struct gk20a *g, | ||
| 40 | struct clk_pmupstate *clk, struct vin_device *pdev); | ||
| 41 | |||
| 42 | struct vin_device { | ||
| 43 | struct boardobj super; | ||
| 44 | u8 id; | ||
| 45 | u8 volt_domain; | ||
| 46 | u8 volt_domain_vbios; | ||
| 47 | u32 flls_shared_mask; | ||
| 48 | |||
| 49 | vin_device_state_load *state_load; | ||
| 50 | }; | ||
| 51 | |||
| 52 | struct vin_device_v10 { | ||
| 53 | struct vin_device super; | ||
| 54 | struct ctrl_clk_vin_device_info_data_v10 data; | ||
| 55 | }; | ||
| 56 | |||
| 57 | struct vin_device_v20 { | ||
| 58 | struct vin_device super; | ||
| 59 | struct ctrl_clk_vin_device_info_data_v20 data; | ||
| 60 | }; | ||
| 61 | |||
| 62 | /* get vin device object from descriptor table index*/ | ||
| 63 | #define CLK_GET_VIN_DEVICE(pvinobjs, dev_index) \ | ||
| 64 | ((struct vin_device *)BOARDOBJGRP_OBJ_GET_BY_IDX( \ | ||
| 65 | ((struct boardobjgrp *)&(pvinobjs->super.super)), (dev_index))) | ||
| 66 | |||
| 67 | boardobj_construct construct_vindevice; | ||
| 68 | boardobj_pmudatainit vindeviceinit_pmudata_super; | ||
| 69 | |||
| 70 | int clk_vin_sw_setup(struct gk20a *g); | ||
| 71 | int clk_vin_pmu_setup(struct gk20a *g); | ||
| 72 | u32 clk_avfs_get_vin_cal_fuse_v10(struct gk20a *g, | ||
| 73 | struct avfsvinobjs *pvinobjs, | ||
| 74 | struct vin_device_v20 *pvindev); | ||
| 75 | u32 clk_avfs_get_vin_cal_fuse_v20(struct gk20a *g, | ||
| 76 | struct avfsvinobjs *pvinobjs, | ||
| 77 | struct vin_device_v20 *pvindev); | ||
| 78 | |||
| 79 | #endif /* NVGPU_CLK_VIN_H */ | ||
