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