xref: /linux/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gp10b.c (revision f6e8dc9edf963dbc99085e54f6ced6da9daa6100)
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
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
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
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
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
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(sizeof(*clk), GFP_KERNEL);
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