1 /*
2  * Copyright 2012 Red Hat Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: Ben Skeggs
23  */
24 #include <subdev/clk.h>
25 #include "pll.h"
26 
27 #include <subdev/bios.h>
28 #include <subdev/bios/pll.h>
29 #include <subdev/timer.h>
30 
31 struct gf100_clk_info {
32 	u32 freq;
33 	u32 ssel;
34 	u32 mdiv;
35 	u32 dsrc;
36 	u32 ddiv;
37 	u32 coef;
38 };
39 
40 struct gf100_clk {
41 	struct nvkm_clk base;
42 	struct gf100_clk_info eng[16];
43 };
44 
45 static u32 read_div(struct gf100_clk *, int, u32, u32);
46 
47 static u32
48 read_vco(struct gf100_clk *clk, u32 dsrc)
49 {
50 	u32 ssrc = nv_rd32(clk, dsrc);
51 	if (!(ssrc & 0x00000100))
52 		return clk->base.read(&clk->base, nv_clk_src_sppll0);
53 	return clk->base.read(&clk->base, nv_clk_src_sppll1);
54 }
55 
56 static u32
57 read_pll(struct gf100_clk *clk, u32 pll)
58 {
59 	u32 ctrl = nv_rd32(clk, pll + 0x00);
60 	u32 coef = nv_rd32(clk, pll + 0x04);
61 	u32 P = (coef & 0x003f0000) >> 16;
62 	u32 N = (coef & 0x0000ff00) >> 8;
63 	u32 M = (coef & 0x000000ff) >> 0;
64 	u32 sclk;
65 
66 	if (!(ctrl & 0x00000001))
67 		return 0;
68 
69 	switch (pll) {
70 	case 0x00e800:
71 	case 0x00e820:
72 		sclk = nv_device(clk)->crystal;
73 		P = 1;
74 		break;
75 	case 0x132000:
76 		sclk = clk->base.read(&clk->base, nv_clk_src_mpllsrc);
77 		break;
78 	case 0x132020:
79 		sclk = clk->base.read(&clk->base, nv_clk_src_mpllsrcref);
80 		break;
81 	case 0x137000:
82 	case 0x137020:
83 	case 0x137040:
84 	case 0x1370e0:
85 		sclk = read_div(clk, (pll & 0xff) / 0x20, 0x137120, 0x137140);
86 		break;
87 	default:
88 		return 0;
89 	}
90 
91 	return sclk * N / M / P;
92 }
93 
94 static u32
95 read_div(struct gf100_clk *clk, int doff, u32 dsrc, u32 dctl)
96 {
97 	u32 ssrc = nv_rd32(clk, dsrc + (doff * 4));
98 	u32 sctl = nv_rd32(clk, dctl + (doff * 4));
99 
100 	switch (ssrc & 0x00000003) {
101 	case 0:
102 		if ((ssrc & 0x00030000) != 0x00030000)
103 			return nv_device(clk)->crystal;
104 		return 108000;
105 	case 2:
106 		return 100000;
107 	case 3:
108 		if (sctl & 0x80000000) {
109 			u32 sclk = read_vco(clk, dsrc + (doff * 4));
110 			u32 sdiv = (sctl & 0x0000003f) + 2;
111 			return (sclk * 2) / sdiv;
112 		}
113 
114 		return read_vco(clk, dsrc + (doff * 4));
115 	default:
116 		return 0;
117 	}
118 }
119 
120 static u32
121 read_clk(struct gf100_clk *clk, int idx)
122 {
123 	u32 sctl = nv_rd32(clk, 0x137250 + (idx * 4));
124 	u32 ssel = nv_rd32(clk, 0x137100);
125 	u32 sclk, sdiv;
126 
127 	if (ssel & (1 << idx)) {
128 		if (idx < 7)
129 			sclk = read_pll(clk, 0x137000 + (idx * 0x20));
130 		else
131 			sclk = read_pll(clk, 0x1370e0);
132 		sdiv = ((sctl & 0x00003f00) >> 8) + 2;
133 	} else {
134 		sclk = read_div(clk, idx, 0x137160, 0x1371d0);
135 		sdiv = ((sctl & 0x0000003f) >> 0) + 2;
136 	}
137 
138 	if (sctl & 0x80000000)
139 		return (sclk * 2) / sdiv;
140 
141 	return sclk;
142 }
143 
144 static int
145 gf100_clk_read(struct nvkm_clk *obj, enum nv_clk_src src)
146 {
147 	struct gf100_clk *clk = container_of(obj, typeof(*clk), base);
148 	struct nvkm_device *device = nv_device(clk);
149 
150 	switch (src) {
151 	case nv_clk_src_crystal:
152 		return device->crystal;
153 	case nv_clk_src_href:
154 		return 100000;
155 	case nv_clk_src_sppll0:
156 		return read_pll(clk, 0x00e800);
157 	case nv_clk_src_sppll1:
158 		return read_pll(clk, 0x00e820);
159 
160 	case nv_clk_src_mpllsrcref:
161 		return read_div(clk, 0, 0x137320, 0x137330);
162 	case nv_clk_src_mpllsrc:
163 		return read_pll(clk, 0x132020);
164 	case nv_clk_src_mpll:
165 		return read_pll(clk, 0x132000);
166 	case nv_clk_src_mdiv:
167 		return read_div(clk, 0, 0x137300, 0x137310);
168 	case nv_clk_src_mem:
169 		if (nv_rd32(clk, 0x1373f0) & 0x00000002)
170 			return clk->base.read(&clk->base, nv_clk_src_mpll);
171 		return clk->base.read(&clk->base, nv_clk_src_mdiv);
172 
173 	case nv_clk_src_gpc:
174 		return read_clk(clk, 0x00);
175 	case nv_clk_src_rop:
176 		return read_clk(clk, 0x01);
177 	case nv_clk_src_hubk07:
178 		return read_clk(clk, 0x02);
179 	case nv_clk_src_hubk06:
180 		return read_clk(clk, 0x07);
181 	case nv_clk_src_hubk01:
182 		return read_clk(clk, 0x08);
183 	case nv_clk_src_copy:
184 		return read_clk(clk, 0x09);
185 	case nv_clk_src_daemon:
186 		return read_clk(clk, 0x0c);
187 	case nv_clk_src_vdec:
188 		return read_clk(clk, 0x0e);
189 	default:
190 		nv_error(clk, "invalid clock source %d\n", src);
191 		return -EINVAL;
192 	}
193 }
194 
195 static u32
196 calc_div(struct gf100_clk *clk, int idx, u32 ref, u32 freq, u32 *ddiv)
197 {
198 	u32 div = min((ref * 2) / freq, (u32)65);
199 	if (div < 2)
200 		div = 2;
201 
202 	*ddiv = div - 2;
203 	return (ref * 2) / div;
204 }
205 
206 static u32
207 calc_src(struct gf100_clk *clk, int idx, u32 freq, u32 *dsrc, u32 *ddiv)
208 {
209 	u32 sclk;
210 
211 	/* use one of the fixed frequencies if possible */
212 	*ddiv = 0x00000000;
213 	switch (freq) {
214 	case  27000:
215 	case 108000:
216 		*dsrc = 0x00000000;
217 		if (freq == 108000)
218 			*dsrc |= 0x00030000;
219 		return freq;
220 	case 100000:
221 		*dsrc = 0x00000002;
222 		return freq;
223 	default:
224 		*dsrc = 0x00000003;
225 		break;
226 	}
227 
228 	/* otherwise, calculate the closest divider */
229 	sclk = read_vco(clk, 0x137160 + (idx * 4));
230 	if (idx < 7)
231 		sclk = calc_div(clk, idx, sclk, freq, ddiv);
232 	return sclk;
233 }
234 
235 static u32
236 calc_pll(struct gf100_clk *clk, int idx, u32 freq, u32 *coef)
237 {
238 	struct nvkm_bios *bios = nvkm_bios(clk);
239 	struct nvbios_pll limits;
240 	int N, M, P, ret;
241 
242 	ret = nvbios_pll_parse(bios, 0x137000 + (idx * 0x20), &limits);
243 	if (ret)
244 		return 0;
245 
246 	limits.refclk = read_div(clk, idx, 0x137120, 0x137140);
247 	if (!limits.refclk)
248 		return 0;
249 
250 	ret = gt215_pll_calc(nv_subdev(clk), &limits, freq, &N, NULL, &M, &P);
251 	if (ret <= 0)
252 		return 0;
253 
254 	*coef = (P << 16) | (N << 8) | M;
255 	return ret;
256 }
257 
258 static int
259 calc_clk(struct gf100_clk *clk, struct nvkm_cstate *cstate, int idx, int dom)
260 {
261 	struct gf100_clk_info *info = &clk->eng[idx];
262 	u32 freq = cstate->domain[dom];
263 	u32 src0, div0, div1D, div1P = 0;
264 	u32 clk0, clk1 = 0;
265 
266 	/* invalid clock domain */
267 	if (!freq)
268 		return 0;
269 
270 	/* first possible path, using only dividers */
271 	clk0 = calc_src(clk, idx, freq, &src0, &div0);
272 	clk0 = calc_div(clk, idx, clk0, freq, &div1D);
273 
274 	/* see if we can get any closer using PLLs */
275 	if (clk0 != freq && (0x00004387 & (1 << idx))) {
276 		if (idx <= 7)
277 			clk1 = calc_pll(clk, idx, freq, &info->coef);
278 		else
279 			clk1 = cstate->domain[nv_clk_src_hubk06];
280 		clk1 = calc_div(clk, idx, clk1, freq, &div1P);
281 	}
282 
283 	/* select the method which gets closest to target freq */
284 	if (abs((int)freq - clk0) <= abs((int)freq - clk1)) {
285 		info->dsrc = src0;
286 		if (div0) {
287 			info->ddiv |= 0x80000000;
288 			info->ddiv |= div0 << 8;
289 			info->ddiv |= div0;
290 		}
291 		if (div1D) {
292 			info->mdiv |= 0x80000000;
293 			info->mdiv |= div1D;
294 		}
295 		info->ssel = info->coef = 0;
296 		info->freq = clk0;
297 	} else {
298 		if (div1P) {
299 			info->mdiv |= 0x80000000;
300 			info->mdiv |= div1P << 8;
301 		}
302 		info->ssel = (1 << idx);
303 		info->freq = clk1;
304 	}
305 
306 	return 0;
307 }
308 
309 static int
310 gf100_clk_calc(struct nvkm_clk *obj, struct nvkm_cstate *cstate)
311 {
312 	struct gf100_clk *clk = container_of(obj, typeof(*clk), base);
313 	int ret;
314 
315 	if ((ret = calc_clk(clk, cstate, 0x00, nv_clk_src_gpc)) ||
316 	    (ret = calc_clk(clk, cstate, 0x01, nv_clk_src_rop)) ||
317 	    (ret = calc_clk(clk, cstate, 0x02, nv_clk_src_hubk07)) ||
318 	    (ret = calc_clk(clk, cstate, 0x07, nv_clk_src_hubk06)) ||
319 	    (ret = calc_clk(clk, cstate, 0x08, nv_clk_src_hubk01)) ||
320 	    (ret = calc_clk(clk, cstate, 0x09, nv_clk_src_copy)) ||
321 	    (ret = calc_clk(clk, cstate, 0x0c, nv_clk_src_daemon)) ||
322 	    (ret = calc_clk(clk, cstate, 0x0e, nv_clk_src_vdec)))
323 		return ret;
324 
325 	return 0;
326 }
327 
328 static void
329 gf100_clk_prog_0(struct gf100_clk *clk, int idx)
330 {
331 	struct gf100_clk_info *info = &clk->eng[idx];
332 	if (idx < 7 && !info->ssel) {
333 		nv_mask(clk, 0x1371d0 + (idx * 0x04), 0x80003f3f, info->ddiv);
334 		nv_wr32(clk, 0x137160 + (idx * 0x04), info->dsrc);
335 	}
336 }
337 
338 static void
339 gf100_clk_prog_1(struct gf100_clk *clk, int idx)
340 {
341 	nv_mask(clk, 0x137100, (1 << idx), 0x00000000);
342 	nv_wait(clk, 0x137100, (1 << idx), 0x00000000);
343 }
344 
345 static void
346 gf100_clk_prog_2(struct gf100_clk *clk, int idx)
347 {
348 	struct gf100_clk_info *info = &clk->eng[idx];
349 	const u32 addr = 0x137000 + (idx * 0x20);
350 	if (idx <= 7) {
351 		nv_mask(clk, addr + 0x00, 0x00000004, 0x00000000);
352 		nv_mask(clk, addr + 0x00, 0x00000001, 0x00000000);
353 		if (info->coef) {
354 			nv_wr32(clk, addr + 0x04, info->coef);
355 			nv_mask(clk, addr + 0x00, 0x00000001, 0x00000001);
356 			nv_wait(clk, addr + 0x00, 0x00020000, 0x00020000);
357 			nv_mask(clk, addr + 0x00, 0x00020004, 0x00000004);
358 		}
359 	}
360 }
361 
362 static void
363 gf100_clk_prog_3(struct gf100_clk *clk, int idx)
364 {
365 	struct gf100_clk_info *info = &clk->eng[idx];
366 	if (info->ssel) {
367 		nv_mask(clk, 0x137100, (1 << idx), info->ssel);
368 		nv_wait(clk, 0x137100, (1 << idx), info->ssel);
369 	}
370 }
371 
372 static void
373 gf100_clk_prog_4(struct gf100_clk *clk, int idx)
374 {
375 	struct gf100_clk_info *info = &clk->eng[idx];
376 	nv_mask(clk, 0x137250 + (idx * 0x04), 0x00003f3f, info->mdiv);
377 }
378 
379 static int
380 gf100_clk_prog(struct nvkm_clk *obj)
381 {
382 	struct gf100_clk *clk = container_of(obj, typeof(*clk), base);
383 	struct {
384 		void (*exec)(struct gf100_clk *, int);
385 	} stage[] = {
386 		{ gf100_clk_prog_0 }, /* div programming */
387 		{ gf100_clk_prog_1 }, /* select div mode */
388 		{ gf100_clk_prog_2 }, /* (maybe) program pll */
389 		{ gf100_clk_prog_3 }, /* (maybe) select pll mode */
390 		{ gf100_clk_prog_4 }, /* final divider */
391 	};
392 	int i, j;
393 
394 	for (i = 0; i < ARRAY_SIZE(stage); i++) {
395 		for (j = 0; j < ARRAY_SIZE(clk->eng); j++) {
396 			if (!clk->eng[j].freq)
397 				continue;
398 			stage[i].exec(clk, j);
399 		}
400 	}
401 
402 	return 0;
403 }
404 
405 static void
406 gf100_clk_tidy(struct nvkm_clk *obj)
407 {
408 	struct gf100_clk *clk = container_of(obj, typeof(*clk), base);
409 	memset(clk->eng, 0x00, sizeof(clk->eng));
410 }
411 
412 static struct nvkm_domain
413 gf100_domain[] = {
414 	{ nv_clk_src_crystal, 0xff },
415 	{ nv_clk_src_href   , 0xff },
416 	{ nv_clk_src_hubk06 , 0x00 },
417 	{ nv_clk_src_hubk01 , 0x01 },
418 	{ nv_clk_src_copy   , 0x02 },
419 	{ nv_clk_src_gpc    , 0x03, 0, "core", 2000 },
420 	{ nv_clk_src_rop    , 0x04 },
421 	{ nv_clk_src_mem    , 0x05, 0, "memory", 1000 },
422 	{ nv_clk_src_vdec   , 0x06 },
423 	{ nv_clk_src_daemon , 0x0a },
424 	{ nv_clk_src_hubk07 , 0x0b },
425 	{ nv_clk_src_max }
426 };
427 
428 static int
429 gf100_clk_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
430 	       struct nvkm_oclass *oclass, void *data, u32 size,
431 	       struct nvkm_object **pobject)
432 {
433 	struct gf100_clk *clk;
434 	int ret;
435 
436 	ret = nvkm_clk_create(parent, engine, oclass, gf100_domain,
437 			      NULL, 0, false, &clk);
438 	*pobject = nv_object(clk);
439 	if (ret)
440 		return ret;
441 
442 	clk->base.read = gf100_clk_read;
443 	clk->base.calc = gf100_clk_calc;
444 	clk->base.prog = gf100_clk_prog;
445 	clk->base.tidy = gf100_clk_tidy;
446 	return 0;
447 }
448 
449 struct nvkm_oclass
450 gf100_clk_oclass = {
451 	.handle = NV_SUBDEV(CLK, 0xc0),
452 	.ofuncs = &(struct nvkm_ofuncs) {
453 		.ctor = gf100_clk_ctor,
454 		.dtor = _nvkm_clk_dtor,
455 		.init = _nvkm_clk_init,
456 		.fini = _nvkm_clk_fini,
457 	},
458 };
459