1 // SPDX-License-Identifier: MIT
2 #include <subdev/clk.h>
3 #include <subdev/timer.h>
4 #include <core/device.h>
5 #include <core/tegra.h>
6
7 #include "priv.h"
8 #include "gk20a_devfreq.h"
9 #include "gk20a.h"
10 #include "gp10b.h"
11
12 static int
gp10b_clk_init(struct nvkm_clk * base)13 gp10b_clk_init(struct nvkm_clk *base)
14 {
15 struct gp10b_clk *clk = gp10b_clk(base);
16 struct nvkm_subdev *subdev = &clk->base.subdev;
17 int ret;
18
19 /* Start with the highest frequency, matching the BPMP default */
20 base->func->calc(base, &base->func->pstates[base->func->nr_pstates - 1].base);
21 ret = base->func->prog(base);
22 if (ret) {
23 nvkm_error(subdev, "cannot initialize clock\n");
24 return ret;
25 }
26
27 ret = gk20a_devfreq_init(base, &clk->devfreq);
28 if (ret)
29 return ret;
30
31 return 0;
32 }
33
34 static int
gp10b_clk_read(struct nvkm_clk * base,enum nv_clk_src src)35 gp10b_clk_read(struct nvkm_clk *base, enum nv_clk_src src)
36 {
37 struct gp10b_clk *clk = gp10b_clk(base);
38 struct nvkm_subdev *subdev = &clk->base.subdev;
39
40 switch (src) {
41 case nv_clk_src_gpc:
42 return clk_get_rate(clk->clk) / GK20A_CLK_GPC_MDIV;
43 default:
44 nvkm_error(subdev, "invalid clock source %d\n", src);
45 return -EINVAL;
46 }
47 }
48
49 static int
gp10b_clk_calc(struct nvkm_clk * base,struct nvkm_cstate * cstate)50 gp10b_clk_calc(struct nvkm_clk *base, struct nvkm_cstate *cstate)
51 {
52 struct gp10b_clk *clk = gp10b_clk(base);
53 u32 target_rate = cstate->domain[nv_clk_src_gpc] * GK20A_CLK_GPC_MDIV;
54
55 clk->new_rate = clk_round_rate(clk->clk, target_rate) / GK20A_CLK_GPC_MDIV;
56
57 return 0;
58 }
59
60 static int
gp10b_clk_prog(struct nvkm_clk * base)61 gp10b_clk_prog(struct nvkm_clk *base)
62 {
63 struct gp10b_clk *clk = gp10b_clk(base);
64 int ret;
65
66 ret = clk_set_rate(clk->clk, clk->new_rate * GK20A_CLK_GPC_MDIV);
67 if (ret < 0)
68 return ret;
69
70 clk->rate = clk_get_rate(clk->clk) / GK20A_CLK_GPC_MDIV;
71
72 return 0;
73 }
74
75 static struct nvkm_pstate
76 gp10b_pstates[] = {
77 {
78 .base = {
79 .domain[nv_clk_src_gpc] = 114750,
80 },
81 },
82 {
83 .base = {
84 .domain[nv_clk_src_gpc] = 216750,
85 },
86 },
87 {
88 .base = {
89 .domain[nv_clk_src_gpc] = 318750,
90 },
91 },
92 {
93 .base = {
94 .domain[nv_clk_src_gpc] = 420750,
95 },
96 },
97 {
98 .base = {
99 .domain[nv_clk_src_gpc] = 522750,
100 },
101 },
102 {
103 .base = {
104 .domain[nv_clk_src_gpc] = 624750,
105 },
106 },
107 {
108 .base = {
109 .domain[nv_clk_src_gpc] = 726750,
110 },
111 },
112 {
113 .base = {
114 .domain[nv_clk_src_gpc] = 828750,
115 },
116 },
117 {
118 .base = {
119 .domain[nv_clk_src_gpc] = 930750,
120 },
121 },
122 {
123 .base = {
124 .domain[nv_clk_src_gpc] = 1032750,
125 },
126 },
127 {
128 .base = {
129 .domain[nv_clk_src_gpc] = 1134750,
130 },
131 },
132 {
133 .base = {
134 .domain[nv_clk_src_gpc] = 1236750,
135 },
136 },
137 {
138 .base = {
139 .domain[nv_clk_src_gpc] = 1300500,
140 },
141 },
142 };
143
144 static const struct nvkm_clk_func
145 gp10b_clk = {
146 .init = gp10b_clk_init,
147 .read = gp10b_clk_read,
148 .calc = gp10b_clk_calc,
149 .prog = gp10b_clk_prog,
150 .tidy = gk20a_clk_tidy,
151 .pstates = gp10b_pstates,
152 .nr_pstates = ARRAY_SIZE(gp10b_pstates),
153 .domains = {
154 { nv_clk_src_gpc, 0xff, 0, "core", GK20A_CLK_GPC_MDIV },
155 { nv_clk_src_max }
156 }
157 };
158
159 int
gp10b_clk_new(struct nvkm_device * device,enum nvkm_subdev_type type,int inst,struct nvkm_clk ** pclk)160 gp10b_clk_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
161 struct nvkm_clk **pclk)
162 {
163 struct nvkm_device_tegra *tdev = device->func->tegra(device);
164 const struct nvkm_clk_func *func = &gp10b_clk;
165 struct gp10b_clk *clk;
166 int ret, i;
167
168 clk = kzalloc_obj(*clk);
169 if (!clk)
170 return -ENOMEM;
171 *pclk = &clk->base;
172 clk->clk = tdev->clk;
173
174 /* Finish initializing the pstates */
175 for (i = 0; i < func->nr_pstates; i++) {
176 INIT_LIST_HEAD(&func->pstates[i].list);
177 func->pstates[i].pstate = i + 1;
178 }
179
180 ret = nvkm_clk_ctor(func, device, type, inst, true, &clk->base);
181 if (ret)
182 return ret;
183
184 return 0;
185 }
186