diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk.c | 151 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk.h | 10 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/pmu/pmu_fw.c | 4 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 12 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuifclk.h | 7 |
6 files changed, 179 insertions, 6 deletions
diff --git a/drivers/gpu/nvgpu/clk/clk.c b/drivers/gpu/nvgpu/clk/clk.c index 28f08cb6..5d6ae19d 100644 --- a/drivers/gpu/nvgpu/clk/clk.c +++ b/drivers/gpu/nvgpu/clk/clk.c | |||
@@ -182,6 +182,7 @@ u32 clk_pmu_vin_load(struct gk20a *g) | |||
182 | (u32)sizeof(struct pmu_hdr); | 182 | (u32)sizeof(struct pmu_hdr); |
183 | 183 | ||
184 | cmd.cmd.clk.cmd_type = NV_PMU_CLK_CMD_ID_RPC; | 184 | cmd.cmd.clk.cmd_type = NV_PMU_CLK_CMD_ID_RPC; |
185 | cmd.cmd.clk.generic.b_perf_daemon_cmd =false; | ||
185 | 186 | ||
186 | payload.in.buf = (u8 *)&rpccall; | 187 | payload.in.buf = (u8 *)&rpccall; |
187 | payload.in.size = (u32)sizeof(struct nv_pmu_clk_rpc); | 188 | payload.in.size = (u32)sizeof(struct nv_pmu_clk_rpc); |
@@ -547,6 +548,156 @@ u32 clk_domain_print_vf_table(struct gk20a *g, u32 clkapidomain) | |||
547 | return status; | 548 | return status; |
548 | } | 549 | } |
549 | 550 | ||
551 | static int clk_program_fllclks(struct gk20a *g, struct change_fll_clk *fllclk) | ||
552 | { | ||
553 | int status = -EINVAL; | ||
554 | struct clk_domain *pdomain; | ||
555 | u8 i; | ||
556 | struct clk_pmupstate *pclk = &g->clk_pmu; | ||
557 | u16 clkmhz = 0; | ||
558 | struct clk_domain_3x_master *p3xmaster; | ||
559 | struct clk_domain_3x_slave *p3xslave; | ||
560 | unsigned long slaveidxmask; | ||
561 | struct set_fll_clk setfllclk; | ||
562 | |||
563 | if (fllclk->api_clk_domain != CTRL_CLK_DOMAIN_GPCCLK) | ||
564 | return -EINVAL; | ||
565 | if (fllclk->voltuv == 0) | ||
566 | return -EINVAL; | ||
567 | if (fllclk->clkmhz == 0) | ||
568 | return -EINVAL; | ||
569 | |||
570 | setfllclk.voltuv = fllclk->voltuv; | ||
571 | setfllclk.gpc2clkmhz = fllclk->clkmhz; | ||
572 | |||
573 | BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super), | ||
574 | struct clk_domain *, pdomain, i) { | ||
575 | |||
576 | if (pdomain->api_domain == fllclk->api_clk_domain) { | ||
577 | |||
578 | if (!pdomain->super.implements(g, &pdomain->super, | ||
579 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER)) { | ||
580 | status = -EINVAL; | ||
581 | goto done; | ||
582 | } | ||
583 | p3xmaster = (struct clk_domain_3x_master *)pdomain; | ||
584 | slaveidxmask = p3xmaster->slave_idxs_mask; | ||
585 | for_each_set_bit(i, &slaveidxmask, 32) { | ||
586 | p3xslave = (struct clk_domain_3x_slave *) | ||
587 | CLK_CLK_DOMAIN_GET(pclk, i); | ||
588 | if ((p3xslave->super.super.super.api_domain != | ||
589 | CTRL_CLK_DOMAIN_XBARCLK) && | ||
590 | (p3xslave->super.super.super.api_domain != | ||
591 | CTRL_CLK_DOMAIN_SYSCLK)) | ||
592 | continue; | ||
593 | clkmhz = 0; | ||
594 | status = p3xslave->clkdomainclkgetslaveclk(g, | ||
595 | pclk, | ||
596 | (struct clk_domain *)p3xslave, | ||
597 | &clkmhz, | ||
598 | fllclk->clkmhz); | ||
599 | if (status) { | ||
600 | status = -EINVAL; | ||
601 | goto done; | ||
602 | } | ||
603 | if (p3xslave->super.super.super.api_domain == | ||
604 | CTRL_CLK_DOMAIN_XBARCLK) | ||
605 | setfllclk.xbar2clkmhz = clkmhz; | ||
606 | if (p3xslave->super.super.super.api_domain == | ||
607 | CTRL_CLK_DOMAIN_SYSCLK) | ||
608 | setfllclk.sys2clkmhz = clkmhz; | ||
609 | } | ||
610 | } | ||
611 | } | ||
612 | /*set regime ids */ | ||
613 | status = get_regime_id(g, CTRL_CLK_DOMAIN_GPCCLK, | ||
614 | &setfllclk.current_regime_id_gpc); | ||
615 | if (status) | ||
616 | goto done; | ||
617 | |||
618 | setfllclk.target_regime_id_gpc = find_regime_id(g, | ||
619 | CTRL_CLK_DOMAIN_GPCCLK, setfllclk.gpc2clkmhz); | ||
620 | |||
621 | status = get_regime_id(g, CTRL_CLK_DOMAIN_SYSCLK, | ||
622 | &setfllclk.current_regime_id_sys); | ||
623 | if (status) | ||
624 | goto done; | ||
625 | |||
626 | setfllclk.target_regime_id_sys = find_regime_id(g, | ||
627 | CTRL_CLK_DOMAIN_SYSCLK, setfllclk.sys2clkmhz); | ||
628 | |||
629 | status = get_regime_id(g, CTRL_CLK_DOMAIN_XBARCLK, | ||
630 | &setfllclk.current_regime_id_xbar); | ||
631 | if (status) | ||
632 | goto done; | ||
633 | |||
634 | setfllclk.target_regime_id_xbar = find_regime_id(g, | ||
635 | CTRL_CLK_DOMAIN_XBARCLK, setfllclk.xbar2clkmhz); | ||
636 | |||
637 | status = clk_pmu_vf_inject(g, &setfllclk); | ||
638 | |||
639 | if (status) | ||
640 | nvgpu_err(g, | ||
641 | "vf inject to change clk failed"); | ||
642 | |||
643 | /* save regime ids */ | ||
644 | status = set_regime_id(g, CTRL_CLK_DOMAIN_XBARCLK, | ||
645 | setfllclk.target_regime_id_xbar); | ||
646 | if (status) | ||
647 | goto done; | ||
648 | |||
649 | status = set_regime_id(g, CTRL_CLK_DOMAIN_GPCCLK, | ||
650 | setfllclk.target_regime_id_gpc); | ||
651 | if (status) | ||
652 | goto done; | ||
653 | |||
654 | status = set_regime_id(g, CTRL_CLK_DOMAIN_SYSCLK, | ||
655 | setfllclk.target_regime_id_sys); | ||
656 | if (status) | ||
657 | goto done; | ||
658 | done: | ||
659 | return status; | ||
660 | } | ||
661 | |||
662 | u32 nvgpu_clk_set_boot_fll_clk_gv10x(struct gk20a *g) | ||
663 | { | ||
664 | int status; | ||
665 | struct change_fll_clk bootfllclk; | ||
666 | u16 gpcclk_clkmhz = BOOT_GPCCLK_MHZ; | ||
667 | u32 gpcclk_voltuv = 0; | ||
668 | u32 voltuv = 0; | ||
669 | |||
670 | status = clk_vf_point_cache(g); | ||
671 | if (status) { | ||
672 | nvgpu_err(g,"caching failed"); | ||
673 | return status; | ||
674 | } | ||
675 | |||
676 | status = clk_domain_get_f_or_v(g, CTRL_CLK_DOMAIN_GPCCLK, | ||
677 | &gpcclk_clkmhz, &gpcclk_voltuv, CTRL_VOLT_DOMAIN_LOGIC); | ||
678 | if (status) { | ||
679 | nvgpu_err(g,"failed 1"); | ||
680 | return status; | ||
681 | } | ||
682 | |||
683 | voltuv = gpcclk_voltuv; | ||
684 | |||
685 | status = volt_set_voltage(g, voltuv, 0); | ||
686 | if (status) | ||
687 | nvgpu_err(g, | ||
688 | "attempt to set boot voltage failed %d", | ||
689 | voltuv); | ||
690 | |||
691 | bootfllclk.api_clk_domain = CTRL_CLK_DOMAIN_GPCCLK; | ||
692 | bootfllclk.clkmhz = gpcclk_clkmhz; | ||
693 | bootfllclk.voltuv = voltuv; | ||
694 | status = clk_program_fllclks(g, &bootfllclk); | ||
695 | if (status) | ||
696 | nvgpu_err(g, "attempt to set boot gpcclk failed"); | ||
697 | |||
698 | return status; | ||
699 | } | ||
700 | |||
550 | u32 clk_domain_get_f_or_v( | 701 | u32 clk_domain_get_f_or_v( |
551 | struct gk20a *g, | 702 | struct gk20a *g, |
552 | u32 clkapidomain, | 703 | u32 clkapidomain, |
diff --git a/drivers/gpu/nvgpu/clk/clk.h b/drivers/gpu/nvgpu/clk/clk.h index 019a1c11..70b04fc4 100644 --- a/drivers/gpu/nvgpu/clk/clk.h +++ b/drivers/gpu/nvgpu/clk/clk.h | |||
@@ -35,9 +35,12 @@ | |||
35 | #define NV_PERF_DOMAIN_4X_CLOCK_DOMAIN_SKIP 0x10 | 35 | #define NV_PERF_DOMAIN_4X_CLOCK_DOMAIN_SKIP 0x10 |
36 | #define NV_PERF_DOMAIN_4X_CLOCK_DOMAIN_MASK 0x1F | 36 | #define NV_PERF_DOMAIN_4X_CLOCK_DOMAIN_MASK 0x1F |
37 | #define NV_PERF_DOMAIN_4X_CLOCK_DOMAIN_SHIFT 0 | 37 | #define NV_PERF_DOMAIN_4X_CLOCK_DOMAIN_SHIFT 0 |
38 | #define BOOT_GPCCLK_MHZ 952 | ||
38 | 39 | ||
39 | struct gk20a; | 40 | struct gk20a; |
40 | 41 | ||
42 | int clk_set_boot_fll_clk(struct gk20a *g); | ||
43 | |||
41 | /* clock related defines for GPUs supporting clock control from pmu*/ | 44 | /* clock related defines for GPUs supporting clock control from pmu*/ |
42 | struct clk_pmupstate { | 45 | struct clk_pmupstate { |
43 | struct avfsvinobjs avfs_vinobjs; | 46 | struct avfsvinobjs avfs_vinobjs; |
@@ -56,6 +59,12 @@ struct clockentry { | |||
56 | u32 api_clk_domain; | 59 | u32 api_clk_domain; |
57 | }; | 60 | }; |
58 | 61 | ||
62 | struct change_fll_clk { | ||
63 | u32 api_clk_domain; | ||
64 | u16 clkmhz; | ||
65 | u32 voltuv; | ||
66 | }; | ||
67 | |||
59 | struct set_fll_clk { | 68 | struct set_fll_clk { |
60 | u32 voltuv; | 69 | u32 voltuv; |
61 | u16 gpc2clkmhz; | 70 | u16 gpc2clkmhz; |
@@ -133,4 +142,5 @@ u32 nvgpu_clk_vf_change_inject_data_fill_gv10x(struct gk20a *g, | |||
133 | u32 nvgpu_clk_vf_change_inject_data_fill_gp10x(struct gk20a *g, | 142 | u32 nvgpu_clk_vf_change_inject_data_fill_gp10x(struct gk20a *g, |
134 | struct nv_pmu_clk_rpc *rpccall, | 143 | struct nv_pmu_clk_rpc *rpccall, |
135 | struct set_fll_clk *setfllclk); | 144 | struct set_fll_clk *setfllclk); |
145 | u32 nvgpu_clk_set_boot_fll_clk_gv10x(struct gk20a *g); | ||
136 | #endif | 146 | #endif |
diff --git a/drivers/gpu/nvgpu/common/pmu/pmu_fw.c b/drivers/gpu/nvgpu/common/pmu/pmu_fw.c index 1e33ecc2..a1e3dfd0 100644 --- a/drivers/gpu/nvgpu/common/pmu/pmu_fw.c +++ b/drivers/gpu/nvgpu/common/pmu/pmu_fw.c | |||
@@ -1313,6 +1313,8 @@ static int nvgpu_init_pmu_fw_ver_ops(struct nvgpu_pmu *pmu) | |||
1313 | nvgpu_clk_vf_change_inject_data_fill_gv10x; | 1313 | nvgpu_clk_vf_change_inject_data_fill_gv10x; |
1314 | g->ops.pmu_ver.clk.perf_pmu_vfe_load = | 1314 | g->ops.pmu_ver.clk.perf_pmu_vfe_load = |
1315 | perf_pmu_vfe_load_gv10x; | 1315 | perf_pmu_vfe_load_gv10x; |
1316 | g->ops.pmu_ver.clk.clk_set_boot_clk = | ||
1317 | nvgpu_clk_set_boot_fll_clk_gv10x; | ||
1316 | } else { | 1318 | } else { |
1317 | g->ops.pmu_ver.get_pmu_init_msg_pmu_queue_params = | 1319 | g->ops.pmu_ver.get_pmu_init_msg_pmu_queue_params = |
1318 | get_pmu_init_msg_pmu_queue_params_v4; | 1320 | get_pmu_init_msg_pmu_queue_params_v4; |
@@ -1484,8 +1486,6 @@ static int nvgpu_init_pmu_fw_ver_ops(struct nvgpu_pmu *pmu) | |||
1484 | clk_avfs_get_vin_cal_fuse_v10; | 1486 | clk_avfs_get_vin_cal_fuse_v10; |
1485 | g->ops.pmu_ver.clk.clk_vf_change_inject_data_fill = | 1487 | g->ops.pmu_ver.clk.clk_vf_change_inject_data_fill = |
1486 | nvgpu_clk_vf_change_inject_data_fill_gp10x; | 1488 | nvgpu_clk_vf_change_inject_data_fill_gp10x; |
1487 | g->ops.pmu_ver.clk.clk_set_boot_clk = | ||
1488 | nvgpu_clk_set_boot_fll_clk_gv10x; | ||
1489 | g->ops.pmu_ver.clk.perf_pmu_vfe_load = | 1489 | g->ops.pmu_ver.clk.perf_pmu_vfe_load = |
1490 | perf_pmu_vfe_load; | 1490 | perf_pmu_vfe_load; |
1491 | break; | 1491 | break; |
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index c48d7cf8..9ce2ef53 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c | |||
@@ -281,10 +281,14 @@ int gk20a_finalize_poweron(struct gk20a *g) | |||
281 | } | 281 | } |
282 | } | 282 | } |
283 | 283 | ||
284 | err = nvgpu_clk_arb_init_arbiter(g); | 284 | if (g->ops.pmu_ver.clk.clk_set_boot_clk && nvgpu_is_enabled(g, NVGPU_PMU_PSTATE)) |
285 | if (err) { | 285 | g->ops.pmu_ver.clk.clk_set_boot_clk(g); |
286 | nvgpu_err(g, "failed to init clk arb"); | 286 | else { |
287 | goto done; | 287 | err = nvgpu_clk_arb_init_arbiter(g); |
288 | if (err) { | ||
289 | nvgpu_err(g, "failed to init clk arb"); | ||
290 | goto done; | ||
291 | } | ||
288 | } | 292 | } |
289 | 293 | ||
290 | err = gk20a_init_therm_support(g); | 294 | err = gk20a_init_therm_support(g); |
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 8f35e2c9..07ff28f6 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -820,6 +820,7 @@ struct gpu_ops { | |||
820 | struct nv_pmu_clk_rpc *rpccall, | 820 | struct nv_pmu_clk_rpc *rpccall, |
821 | struct set_fll_clk *setfllclk); | 821 | struct set_fll_clk *setfllclk); |
822 | u32 (*perf_pmu_vfe_load)(struct gk20a *g); | 822 | u32 (*perf_pmu_vfe_load)(struct gk20a *g); |
823 | u32 (*clk_set_boot_clk)(struct gk20a *g); | ||
823 | }clk; | 824 | }clk; |
824 | } pmu_ver; | 825 | } pmu_ver; |
825 | struct { | 826 | struct { |
diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuifclk.h b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuifclk.h index 471892ca..fe9a70db 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuifclk.h +++ b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuifclk.h | |||
@@ -448,6 +448,12 @@ struct nv_pmu_clk_cmd_rpc { | |||
448 | struct nv_pmu_allocation request; | 448 | struct nv_pmu_allocation request; |
449 | }; | 449 | }; |
450 | 450 | ||
451 | struct nv_pmu_clk_cmd_generic { | ||
452 | u8 cmd_type; | ||
453 | bool b_perf_daemon_cmd; | ||
454 | u8 pad[2]; | ||
455 | }; | ||
456 | |||
451 | #define NV_PMU_CLK_CMD_RPC_ALLOC_OFFSET \ | 457 | #define NV_PMU_CLK_CMD_RPC_ALLOC_OFFSET \ |
452 | (offsetof(struct nv_pmu_clk_cmd_rpc, request)) | 458 | (offsetof(struct nv_pmu_clk_cmd_rpc, request)) |
453 | 459 | ||
@@ -455,6 +461,7 @@ struct nv_pmu_clk_cmd { | |||
455 | union { | 461 | union { |
456 | u8 cmd_type; | 462 | u8 cmd_type; |
457 | struct nv_pmu_boardobj_cmd_grp grp_set; | 463 | struct nv_pmu_boardobj_cmd_grp grp_set; |
464 | struct nv_pmu_clk_cmd_generic generic; | ||
458 | struct nv_pmu_clk_cmd_rpc rpc; | 465 | struct nv_pmu_clk_cmd_rpc rpc; |
459 | struct nv_pmu_boardobj_cmd_grp grp_get_status; | 466 | struct nv_pmu_boardobj_cmd_grp grp_get_status; |
460 | }; | 467 | }; |