Lines Matching +full:- +full:clk
41 nvkm_clk_adjust(struct nvkm_clk *clk, bool adjust, in nvkm_clk_adjust() argument
44 struct nvkm_bios *bios = clk->subdev.device->bios; in nvkm_clk_adjust()
76 * C-States
79 nvkm_cstate_valid(struct nvkm_clk *clk, struct nvkm_cstate *cstate, in nvkm_cstate_valid() argument
82 const struct nvkm_domain *domain = clk->domains; in nvkm_cstate_valid()
83 struct nvkm_volt *volt = clk->subdev.device->volt; in nvkm_cstate_valid()
86 while (domain && domain->name != nv_clk_src_max) { in nvkm_cstate_valid()
87 if (domain->flags & NVKM_CLK_DOM_FLAG_VPSTATE) { in nvkm_cstate_valid()
88 u32 freq = cstate->domain[domain->name]; in nvkm_cstate_valid()
89 switch (clk->boost_mode) { in nvkm_cstate_valid()
91 if (clk->base_khz && freq > clk->base_khz) in nvkm_cstate_valid()
95 if (clk->boost_khz && freq > clk->boost_khz) in nvkm_cstate_valid()
105 voltage = nvkm_volt_map(volt, cstate->voltage, temp); in nvkm_cstate_valid()
108 return voltage <= min(max_volt, volt->max_uv); in nvkm_cstate_valid()
112 nvkm_cstate_find_best(struct nvkm_clk *clk, struct nvkm_pstate *pstate, in nvkm_cstate_find_best() argument
115 struct nvkm_device *device = clk->subdev.device; in nvkm_cstate_find_best()
116 struct nvkm_volt *volt = device->volt; in nvkm_cstate_find_best()
125 max_volt = volt->max_uv; in nvkm_cstate_find_best()
126 if (volt->max0_id != 0xff) in nvkm_cstate_find_best()
128 nvkm_volt_map(volt, volt->max0_id, clk->temp)); in nvkm_cstate_find_best()
129 if (volt->max1_id != 0xff) in nvkm_cstate_find_best()
131 nvkm_volt_map(volt, volt->max1_id, clk->temp)); in nvkm_cstate_find_best()
132 if (volt->max2_id != 0xff) in nvkm_cstate_find_best()
134 nvkm_volt_map(volt, volt->max2_id, clk->temp)); in nvkm_cstate_find_best()
136 list_for_each_entry_from_reverse(cstate, &pstate->list, head) { in nvkm_cstate_find_best()
137 if (nvkm_cstate_valid(clk, cstate, max_volt, clk->temp)) in nvkm_cstate_find_best()
145 nvkm_cstate_get(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei) in nvkm_cstate_get() argument
149 return list_last_entry(&pstate->list, typeof(*cstate), head); in nvkm_cstate_get()
151 list_for_each_entry(cstate, &pstate->list, head) { in nvkm_cstate_get()
152 if (cstate->id == cstatei) in nvkm_cstate_get()
160 nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei) in nvkm_cstate_prog() argument
162 struct nvkm_subdev *subdev = &clk->subdev; in nvkm_cstate_prog()
163 struct nvkm_device *device = subdev->device; in nvkm_cstate_prog()
164 struct nvkm_therm *therm = device->therm; in nvkm_cstate_prog()
165 struct nvkm_volt *volt = device->volt; in nvkm_cstate_prog()
169 if (!list_empty(&pstate->list)) { in nvkm_cstate_prog()
170 cstate = nvkm_cstate_get(clk, pstate, cstatei); in nvkm_cstate_prog()
171 cstate = nvkm_cstate_find_best(clk, pstate, cstate); in nvkm_cstate_prog()
173 return -EINVAL; in nvkm_cstate_prog()
175 cstate = &pstate->base; in nvkm_cstate_prog()
179 ret = nvkm_therm_cstate(therm, pstate->fanspeed, +1); in nvkm_cstate_prog()
180 if (ret && ret != -ENODEV) { in nvkm_cstate_prog()
187 ret = nvkm_volt_set_id(volt, cstate->voltage, in nvkm_cstate_prog()
188 pstate->base.voltage, clk->temp, +1); in nvkm_cstate_prog()
189 if (ret && ret != -ENODEV) { in nvkm_cstate_prog()
195 ret = clk->func->calc(clk, cstate); in nvkm_cstate_prog()
197 ret = clk->func->prog(clk); in nvkm_cstate_prog()
198 clk->func->tidy(clk); in nvkm_cstate_prog()
202 ret = nvkm_volt_set_id(volt, cstate->voltage, in nvkm_cstate_prog()
203 pstate->base.voltage, clk->temp, -1); in nvkm_cstate_prog()
204 if (ret && ret != -ENODEV) in nvkm_cstate_prog()
209 ret = nvkm_therm_cstate(therm, pstate->fanspeed, -1); in nvkm_cstate_prog()
210 if (ret && ret != -ENODEV) in nvkm_cstate_prog()
220 list_del(&cstate->head); in nvkm_cstate_del()
225 nvkm_cstate_new(struct nvkm_clk *clk, int idx, struct nvkm_pstate *pstate) in nvkm_cstate_new() argument
227 struct nvkm_bios *bios = clk->subdev.device->bios; in nvkm_cstate_new()
228 struct nvkm_volt *volt = clk->subdev.device->volt; in nvkm_cstate_new()
229 const struct nvkm_domain *domain = clk->domains; in nvkm_cstate_new()
237 return -ENOENT; in nvkm_cstate_new()
239 if (volt && nvkm_volt_map_min(volt, cstepX.voltage) > volt->max_uv) in nvkm_cstate_new()
240 return -EINVAL; in nvkm_cstate_new()
244 return -ENOMEM; in nvkm_cstate_new()
246 *cstate = pstate->base; in nvkm_cstate_new()
247 cstate->voltage = cstepX.voltage; in nvkm_cstate_new()
248 cstate->id = idx; in nvkm_cstate_new()
250 while (domain && domain->name != nv_clk_src_max) { in nvkm_cstate_new()
251 if (domain->flags & NVKM_CLK_DOM_FLAG_CORE) { in nvkm_cstate_new()
252 u32 freq = nvkm_clk_adjust(clk, true, pstate->pstate, in nvkm_cstate_new()
253 domain->bios, cstepX.freq); in nvkm_cstate_new()
254 cstate->domain[domain->name] = freq; in nvkm_cstate_new()
259 list_add(&cstate->head, &pstate->list); in nvkm_cstate_new()
264 * P-States
267 nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei) in nvkm_pstate_prog() argument
269 struct nvkm_subdev *subdev = &clk->subdev; in nvkm_pstate_prog()
270 struct nvkm_fb *fb = subdev->device->fb; in nvkm_pstate_prog()
271 struct nvkm_pci *pci = subdev->device->pci; in nvkm_pstate_prog()
275 list_for_each_entry(pstate, &clk->states, head) { in nvkm_pstate_prog()
281 clk->pstate = pstatei; in nvkm_pstate_prog()
283 nvkm_pcie_set_link(pci, pstate->pcie_speed, pstate->pcie_width); in nvkm_pstate_prog()
285 if (fb && fb->ram && fb->ram->func->calc) { in nvkm_pstate_prog()
286 struct nvkm_ram *ram = fb->ram; in nvkm_pstate_prog()
287 int khz = pstate->base.domain[nv_clk_src_mem]; in nvkm_pstate_prog()
289 ret = ram->func->calc(ram, khz); in nvkm_pstate_prog()
291 ret = ram->func->prog(ram); in nvkm_pstate_prog()
293 ram->func->tidy(ram); in nvkm_pstate_prog()
296 return nvkm_cstate_prog(clk, pstate, NVKM_CLK_CSTATE_HIGHEST); in nvkm_pstate_prog()
302 struct nvkm_clk *clk = container_of(work, typeof(*clk), work); in nvkm_pstate_work() local
303 struct nvkm_subdev *subdev = &clk->subdev; in nvkm_pstate_work()
306 if (!atomic_xchg(&clk->waiting, 0)) in nvkm_pstate_work()
308 clk->pwrsrc = power_supply_is_system_supplied(); in nvkm_pstate_work()
311 clk->pstate, clk->pwrsrc, clk->ustate_ac, clk->ustate_dc, in nvkm_pstate_work()
312 clk->astate, clk->temp, clk->dstate); in nvkm_pstate_work()
314 pstate = clk->pwrsrc ? clk->ustate_ac : clk->ustate_dc; in nvkm_pstate_work()
315 if (clk->state_nr && pstate != -1) { in nvkm_pstate_work()
316 pstate = (pstate < 0) ? clk->astate : pstate; in nvkm_pstate_work()
317 pstate = min(pstate, clk->state_nr - 1); in nvkm_pstate_work()
318 pstate = max(pstate, clk->dstate); in nvkm_pstate_work()
320 pstate = clk->pstate = -1; in nvkm_pstate_work()
323 nvkm_trace(subdev, "-> %d\n", pstate); in nvkm_pstate_work()
324 if (pstate != clk->pstate) { in nvkm_pstate_work()
325 int ret = nvkm_pstate_prog(clk, pstate); in nvkm_pstate_work()
332 wake_up_all(&clk->wait); in nvkm_pstate_work()
336 nvkm_pstate_calc(struct nvkm_clk *clk, bool wait) in nvkm_pstate_calc() argument
338 atomic_set(&clk->waiting, 1); in nvkm_pstate_calc()
339 schedule_work(&clk->work); in nvkm_pstate_calc()
341 wait_event(clk->wait, !atomic_read(&clk->waiting)); in nvkm_pstate_calc()
346 nvkm_pstate_info(struct nvkm_clk *clk, struct nvkm_pstate *pstate) in nvkm_pstate_info() argument
348 const struct nvkm_domain *clock = clk->domains - 1; in nvkm_pstate_info()
350 struct nvkm_subdev *subdev = &clk->subdev; in nvkm_pstate_info()
352 char name[4] = "--"; in nvkm_pstate_info()
353 int i = -1; in nvkm_pstate_info()
355 if (pstate->pstate != 0xff) in nvkm_pstate_info()
356 snprintf(name, sizeof(name), "%02x", pstate->pstate); in nvkm_pstate_info()
358 while ((++clock)->name != nv_clk_src_max) { in nvkm_pstate_info()
359 u32 lo = pstate->base.domain[clock->name]; in nvkm_pstate_info()
364 nvkm_debug(subdev, "%02x: %10d KHz\n", clock->name, lo); in nvkm_pstate_info()
365 list_for_each_entry(cstate, &pstate->list, head) { in nvkm_pstate_info()
366 u32 freq = cstate->domain[clock->name]; in nvkm_pstate_info()
372 if (clock->mname && ++i < ARRAY_SIZE(info)) { in nvkm_pstate_info()
373 lo /= clock->mdiv; in nvkm_pstate_info()
374 hi /= clock->mdiv; in nvkm_pstate_info()
377 clock->mname, lo); in nvkm_pstate_info()
380 "%s %d-%d MHz", clock->mname, lo, hi); in nvkm_pstate_info()
393 list_for_each_entry_safe(cstate, temp, &pstate->list, head) { in nvkm_pstate_del()
397 list_del(&pstate->head); in nvkm_pstate_del()
402 nvkm_pstate_new(struct nvkm_clk *clk, int idx) in nvkm_pstate_new() argument
404 struct nvkm_bios *bios = clk->subdev.device->bios; in nvkm_pstate_new()
405 const struct nvkm_domain *domain = clk->domains - 1; in nvkm_pstate_new()
415 return -EINVAL; in nvkm_pstate_new()
421 return -ENOMEM; in nvkm_pstate_new()
423 INIT_LIST_HEAD(&pstate->list); in nvkm_pstate_new()
425 pstate->pstate = perfE.pstate; in nvkm_pstate_new()
426 pstate->fanspeed = perfE.fanspeed; in nvkm_pstate_new()
427 pstate->pcie_speed = perfE.pcie_speed; in nvkm_pstate_new()
428 pstate->pcie_width = perfE.pcie_width; in nvkm_pstate_new()
429 cstate = &pstate->base; in nvkm_pstate_new()
430 cstate->voltage = perfE.voltage; in nvkm_pstate_new()
431 cstate->domain[nv_clk_src_core] = perfE.core; in nvkm_pstate_new()
432 cstate->domain[nv_clk_src_shader] = perfE.shader; in nvkm_pstate_new()
433 cstate->domain[nv_clk_src_mem] = perfE.memory; in nvkm_pstate_new()
434 cstate->domain[nv_clk_src_vdec] = perfE.vdec; in nvkm_pstate_new()
435 cstate->domain[nv_clk_src_dom6] = perfE.disp; in nvkm_pstate_new()
437 while (ver >= 0x40 && (++domain)->name != nv_clk_src_max) { in nvkm_pstate_new()
440 u32 perfSe = nvbios_perfSp(bios, data, domain->bios, in nvkm_pstate_new()
445 if (domain->flags & NVKM_CLK_DOM_FLAG_CORE) { in nvkm_pstate_new()
446 perfS.v40.freq = nvkm_clk_adjust(clk, false, in nvkm_pstate_new()
447 pstate->pstate, in nvkm_pstate_new()
448 domain->bios, in nvkm_pstate_new()
452 cstate->domain[domain->name] = perfS.v40.freq; in nvkm_pstate_new()
455 data = nvbios_cstepEm(bios, pstate->pstate, &ver, &hdr, &cstepE); in nvkm_pstate_new()
459 nvkm_cstate_new(clk, idx, pstate); in nvkm_pstate_new()
460 } while(idx--); in nvkm_pstate_new()
463 nvkm_pstate_info(clk, pstate); in nvkm_pstate_new()
464 list_add_tail(&pstate->head, &clk->states); in nvkm_pstate_new()
465 clk->state_nr++; in nvkm_pstate_new()
473 nvkm_clk_ustate_update(struct nvkm_clk *clk, int req) in nvkm_clk_ustate_update() argument
478 if (!clk->allow_reclock) in nvkm_clk_ustate_update()
479 return -ENOSYS; in nvkm_clk_ustate_update()
481 if (req != -1 && req != -2) { in nvkm_clk_ustate_update()
482 list_for_each_entry(pstate, &clk->states, head) { in nvkm_clk_ustate_update()
483 if (pstate->pstate == req) in nvkm_clk_ustate_update()
488 if (pstate->pstate != req) in nvkm_clk_ustate_update()
489 return -EINVAL; in nvkm_clk_ustate_update()
497 nvkm_clk_nstate(struct nvkm_clk *clk, const char *mode, int arglen) in nvkm_clk_nstate() argument
501 if (clk->allow_reclock && !strncasecmpz(mode, "auto", arglen)) in nvkm_clk_nstate()
502 return -2; in nvkm_clk_nstate()
510 ret = nvkm_clk_ustate_update(clk, v); in nvkm_clk_nstate()
517 return ret - 2; in nvkm_clk_nstate()
521 nvkm_clk_ustate(struct nvkm_clk *clk, int req, int pwr) in nvkm_clk_ustate() argument
523 int ret = nvkm_clk_ustate_update(clk, req); in nvkm_clk_ustate()
525 if (ret -= 2, pwr) clk->ustate_ac = ret; in nvkm_clk_ustate()
526 else clk->ustate_dc = ret; in nvkm_clk_ustate()
527 return nvkm_pstate_calc(clk, true); in nvkm_clk_ustate()
533 nvkm_clk_astate(struct nvkm_clk *clk, int req, int rel, bool wait) in nvkm_clk_astate() argument
535 if (!rel) clk->astate = req; in nvkm_clk_astate()
536 if ( rel) clk->astate += rel; in nvkm_clk_astate()
537 clk->astate = min(clk->astate, clk->state_nr - 1); in nvkm_clk_astate()
538 clk->astate = max(clk->astate, 0); in nvkm_clk_astate()
539 return nvkm_pstate_calc(clk, wait); in nvkm_clk_astate()
543 nvkm_clk_tstate(struct nvkm_clk *clk, u8 temp) in nvkm_clk_tstate() argument
545 if (clk->temp == temp) in nvkm_clk_tstate()
547 clk->temp = temp; in nvkm_clk_tstate()
548 return nvkm_pstate_calc(clk, false); in nvkm_clk_tstate()
552 nvkm_clk_dstate(struct nvkm_clk *clk, int req, int rel) in nvkm_clk_dstate() argument
554 if (!rel) clk->dstate = req; in nvkm_clk_dstate()
555 if ( rel) clk->dstate += rel; in nvkm_clk_dstate()
556 clk->dstate = min(clk->dstate, clk->state_nr - 1); in nvkm_clk_dstate()
557 clk->dstate = max(clk->dstate, 0); in nvkm_clk_dstate()
558 return nvkm_pstate_calc(clk, true); in nvkm_clk_dstate()
564 if (device->clk) in nvkm_clk_pwrsrc()
565 return nvkm_pstate_calc(device->clk, false); in nvkm_clk_pwrsrc()
574 nvkm_clk_read(struct nvkm_clk *clk, enum nv_clk_src src) in nvkm_clk_read() argument
576 return clk->func->read(clk, src); in nvkm_clk_read()
582 struct nvkm_clk *clk = nvkm_clk(subdev); in nvkm_clk_fini() local
583 flush_work(&clk->work); in nvkm_clk_fini()
584 if (clk->func->fini) in nvkm_clk_fini()
585 clk->func->fini(clk); in nvkm_clk_fini()
592 struct nvkm_clk *clk = nvkm_clk(subdev); in nvkm_clk_init() local
593 const struct nvkm_domain *clock = clk->domains; in nvkm_clk_init()
596 memset(&clk->bstate, 0x00, sizeof(clk->bstate)); in nvkm_clk_init()
597 INIT_LIST_HEAD(&clk->bstate.list); in nvkm_clk_init()
598 clk->bstate.pstate = 0xff; in nvkm_clk_init()
600 while (clock->name != nv_clk_src_max) { in nvkm_clk_init()
601 ret = nvkm_clk_read(clk, clock->name); in nvkm_clk_init()
603 nvkm_error(subdev, "%02x freq unknown\n", clock->name); in nvkm_clk_init()
606 clk->bstate.base.domain[clock->name] = ret; in nvkm_clk_init()
610 nvkm_pstate_info(clk, &clk->bstate); in nvkm_clk_init()
612 if (clk->func->init) in nvkm_clk_init()
613 return clk->func->init(clk); in nvkm_clk_init()
615 clk->astate = clk->state_nr - 1; in nvkm_clk_init()
616 clk->dstate = 0; in nvkm_clk_init()
617 clk->pstate = -1; in nvkm_clk_init()
618 clk->temp = 90; /* reasonable default value */ in nvkm_clk_init()
619 nvkm_pstate_calc(clk, true); in nvkm_clk_init()
626 struct nvkm_clk *clk = nvkm_clk(subdev); in nvkm_clk_dtor() local
630 if (clk->func->pstates) in nvkm_clk_dtor()
631 return clk; in nvkm_clk_dtor()
633 list_for_each_entry_safe(pstate, temp, &clk->states, head) { in nvkm_clk_dtor()
637 return clk; in nvkm_clk_dtor()
649 enum nvkm_subdev_type type, int inst, bool allow_reclock, struct nvkm_clk *clk) in nvkm_clk_ctor() argument
651 struct nvkm_subdev *subdev = &clk->subdev; in nvkm_clk_ctor()
652 struct nvkm_bios *bios = device->bios; in nvkm_clk_ctor()
662 clk->boost_khz = boost.clock_mhz * 1000; in nvkm_clk_ctor()
664 clk->base_khz = base.clock_mhz * 1000; in nvkm_clk_ctor()
667 clk->func = func; in nvkm_clk_ctor()
668 INIT_LIST_HEAD(&clk->states); in nvkm_clk_ctor()
669 clk->domains = func->domains; in nvkm_clk_ctor()
670 clk->ustate_ac = -1; in nvkm_clk_ctor()
671 clk->ustate_dc = -1; in nvkm_clk_ctor()
672 clk->allow_reclock = allow_reclock; in nvkm_clk_ctor()
674 INIT_WORK(&clk->work, nvkm_pstate_work); in nvkm_clk_ctor()
675 init_waitqueue_head(&clk->wait); in nvkm_clk_ctor()
676 atomic_set(&clk->waiting, 0); in nvkm_clk_ctor()
679 if (!func->pstates) { in nvkm_clk_ctor()
682 ret = nvkm_pstate_new(clk, idx++); in nvkm_clk_ctor()
685 for (idx = 0; idx < func->nr_pstates; idx++) in nvkm_clk_ctor()
686 list_add_tail(&func->pstates[idx].head, &clk->states); in nvkm_clk_ctor()
687 clk->state_nr = func->nr_pstates; in nvkm_clk_ctor()
690 mode = nvkm_stropt(device->cfgopt, "NvClkMode", &arglen); in nvkm_clk_ctor()
692 clk->ustate_ac = nvkm_clk_nstate(clk, mode, arglen); in nvkm_clk_ctor()
693 clk->ustate_dc = nvkm_clk_nstate(clk, mode, arglen); in nvkm_clk_ctor()
696 mode = nvkm_stropt(device->cfgopt, "NvClkModeAC", &arglen); in nvkm_clk_ctor()
698 clk->ustate_ac = nvkm_clk_nstate(clk, mode, arglen); in nvkm_clk_ctor()
700 mode = nvkm_stropt(device->cfgopt, "NvClkModeDC", &arglen); in nvkm_clk_ctor()
702 clk->ustate_dc = nvkm_clk_nstate(clk, mode, arglen); in nvkm_clk_ctor()
704 clk->boost_mode = nvkm_longopt(device->cfgopt, "NvBoost", in nvkm_clk_ctor()
714 return -ENOMEM; in nvkm_clk_new_()