xref: /linux/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gt215.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1a8c4362bSBen Skeggs /*
2a8c4362bSBen Skeggs  * Copyright 2013 Red Hat Inc.
3a8c4362bSBen Skeggs  *
4a8c4362bSBen Skeggs  * Permission is hereby granted, free of charge, to any person obtaining a
5a8c4362bSBen Skeggs  * copy of this software and associated documentation files (the "Software"),
6a8c4362bSBen Skeggs  * to deal in the Software without restriction, including without limitation
7a8c4362bSBen Skeggs  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8a8c4362bSBen Skeggs  * and/or sell copies of the Software, and to permit persons to whom the
9a8c4362bSBen Skeggs  * Software is furnished to do so, subject to the following conditions:
10a8c4362bSBen Skeggs  *
11a8c4362bSBen Skeggs  * The above copyright notice and this permission notice shall be included in
12a8c4362bSBen Skeggs  * all copies or substantial portions of the Software.
13a8c4362bSBen Skeggs  *
14a8c4362bSBen Skeggs  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15a8c4362bSBen Skeggs  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16a8c4362bSBen Skeggs  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17a8c4362bSBen Skeggs  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18a8c4362bSBen Skeggs  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19a8c4362bSBen Skeggs  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20a8c4362bSBen Skeggs  * OTHER DEALINGS IN THE SOFTWARE.
21a8c4362bSBen Skeggs  *
22a8c4362bSBen Skeggs  * Authors: Ben Skeggs
23a8c4362bSBen Skeggs  */
24a8c4362bSBen Skeggs #include "nv50.h"
25a8c4362bSBen Skeggs 
26a8c4362bSBen Skeggs #include <subdev/bios.h>
27a8c4362bSBen Skeggs #include <subdev/bios/init.h>
28a8c4362bSBen Skeggs #include <subdev/bios/pll.h>
29a8c4362bSBen Skeggs #include <subdev/clk/pll.h>
30a8c4362bSBen Skeggs 
31a8c4362bSBen Skeggs int
gt215_devinit_pll_set(struct nvkm_devinit * init,u32 type,u32 freq)328ac3f64fSBen Skeggs gt215_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq)
33a8c4362bSBen Skeggs {
348ac3f64fSBen Skeggs 	struct nvkm_subdev *subdev = &init->subdev;
358ac3f64fSBen Skeggs 	struct nvkm_device *device = subdev->device;
36a8c4362bSBen Skeggs 	struct nvbios_pll info;
37a8c4362bSBen Skeggs 	int N, fN, M, P;
38a8c4362bSBen Skeggs 	int ret;
39a8c4362bSBen Skeggs 
408ac3f64fSBen Skeggs 	ret = nvbios_pll_parse(device->bios, type, &info);
41a8c4362bSBen Skeggs 	if (ret)
42a8c4362bSBen Skeggs 		return ret;
43a8c4362bSBen Skeggs 
448ac3f64fSBen Skeggs 	ret = gt215_pll_calc(subdev, &info, freq, &N, &fN, &M, &P);
45a8c4362bSBen Skeggs 	if (ret < 0)
46a8c4362bSBen Skeggs 		return ret;
47a8c4362bSBen Skeggs 
48a8c4362bSBen Skeggs 	switch (info.type) {
49a8c4362bSBen Skeggs 	case PLL_VPLL0:
50a8c4362bSBen Skeggs 	case PLL_VPLL1:
518ac3f64fSBen Skeggs 		nvkm_wr32(device, info.reg + 0, 0x50000610);
528ac3f64fSBen Skeggs 		nvkm_mask(device, info.reg + 4, 0x003fffff,
53a8c4362bSBen Skeggs 						(P << 16) | (M << 8) | N);
548ac3f64fSBen Skeggs 		nvkm_wr32(device, info.reg + 8, fN);
55a8c4362bSBen Skeggs 		break;
56a8c4362bSBen Skeggs 	default:
57aa860e4bSBen Skeggs 		nvkm_warn(subdev, "%08x/%dKhz unimplemented\n", type, freq);
58a8c4362bSBen Skeggs 		ret = -EINVAL;
59a8c4362bSBen Skeggs 		break;
60a8c4362bSBen Skeggs 	}
61a8c4362bSBen Skeggs 
62a8c4362bSBen Skeggs 	return ret;
63a8c4362bSBen Skeggs }
64a8c4362bSBen Skeggs 
65*da2b1a0aSDeepak R Varma static void
gt215_devinit_disable(struct nvkm_devinit * init)668ac3f64fSBen Skeggs gt215_devinit_disable(struct nvkm_devinit *init)
67a8c4362bSBen Skeggs {
688ac3f64fSBen Skeggs 	struct nvkm_device *device = init->subdev.device;
698ac3f64fSBen Skeggs 	u32 r001540 = nvkm_rd32(device, 0x001540);
708ac3f64fSBen Skeggs 	u32 r00154c = nvkm_rd32(device, 0x00154c);
71a8c4362bSBen Skeggs 
72a8c4362bSBen Skeggs 	if (!(r001540 & 0x40000000)) {
7396321606SBen Skeggs 		nvkm_subdev_disable(device, NVKM_ENGINE_MSPDEC, 0);
7407a356bbSBen Skeggs 		nvkm_subdev_disable(device, NVKM_ENGINE_MSPPP, 0);
75a8c4362bSBen Skeggs 	}
76a8c4362bSBen Skeggs 
77a8c4362bSBen Skeggs 	if (!(r00154c & 0x00000004))
78a7f000ecSBen Skeggs 		nvkm_subdev_disable(device, NVKM_ENGINE_DISP, 0);
79a8c4362bSBen Skeggs 	if (!(r00154c & 0x00000020))
80b15147bdSBen Skeggs 		nvkm_subdev_disable(device, NVKM_ENGINE_MSVLD, 0);
81a8c4362bSBen Skeggs 	if (!(r00154c & 0x00000200))
8250551b15SBen Skeggs 		nvkm_subdev_disable(device, NVKM_ENGINE_CE, 0);
83a8c4362bSBen Skeggs }
84a8c4362bSBen Skeggs 
85a8c4362bSBen Skeggs static u32
86a8c4362bSBen Skeggs gt215_devinit_mmio_part[] = {
87a8c4362bSBen Skeggs 	0x100720, 0x1008bc, 4,
88a8c4362bSBen Skeggs 	0x100a20, 0x100adc, 4,
89a8c4362bSBen Skeggs 	0x100d80, 0x100ddc, 4,
90a8c4362bSBen Skeggs 	0x110000, 0x110f9c, 4,
91a8c4362bSBen Skeggs 	0x111000, 0x11103c, 8,
92a8c4362bSBen Skeggs 	0x111080, 0x1110fc, 4,
93a8c4362bSBen Skeggs 	0x111120, 0x1111fc, 4,
94a8c4362bSBen Skeggs 	0x111300, 0x1114bc, 4,
95a8c4362bSBen Skeggs 	0,
96a8c4362bSBen Skeggs };
97a8c4362bSBen Skeggs 
98a8c4362bSBen Skeggs static u32
gt215_devinit_mmio(struct nvkm_devinit * base,u32 addr)99151abd44SBen Skeggs gt215_devinit_mmio(struct nvkm_devinit *base, u32 addr)
100a8c4362bSBen Skeggs {
101151abd44SBen Skeggs 	struct nv50_devinit *init = nv50_devinit(base);
1028ac3f64fSBen Skeggs 	struct nvkm_device *device = init->base.subdev.device;
103a8c4362bSBen Skeggs 	u32 *mmio = gt215_devinit_mmio_part;
104a8c4362bSBen Skeggs 
105a8c4362bSBen Skeggs 	/* the init tables on some boards have INIT_RAM_RESTRICT_ZM_REG_GROUP
106a8c4362bSBen Skeggs 	 * instructions which touch registers that may not even exist on
107a8c4362bSBen Skeggs 	 * some configurations (Quadro 400), which causes the register
108a8c4362bSBen Skeggs 	 * interface to screw up for some amount of time after attempting to
109a8c4362bSBen Skeggs 	 * write to one of these, and results in all sorts of things going
110a8c4362bSBen Skeggs 	 * horribly wrong.
111a8c4362bSBen Skeggs 	 *
112a8c4362bSBen Skeggs 	 * the binary driver avoids touching these registers at all, however,
113a8c4362bSBen Skeggs 	 * the video bios doesn't care and does what the scripts say.  it's
114266f8b5eSBen Skeggs 	 * presumed that the io-port access to init registers isn't effected
115a8c4362bSBen Skeggs 	 * by the screw-up bug mentioned above.
116a8c4362bSBen Skeggs 	 *
117a8c4362bSBen Skeggs 	 * really, a new opcode should've been invented to handle these
118a8c4362bSBen Skeggs 	 * requirements, but whatever, it's too late for that now.
119a8c4362bSBen Skeggs 	 */
120a8c4362bSBen Skeggs 	while (mmio[0]) {
121a8c4362bSBen Skeggs 		if (addr >= mmio[0] && addr <= mmio[1]) {
122a8c4362bSBen Skeggs 			u32 part = (addr / mmio[2]) & 7;
123266f8b5eSBen Skeggs 			if (!init->r001540)
1248ac3f64fSBen Skeggs 				init->r001540 = nvkm_rd32(device, 0x001540);
125266f8b5eSBen Skeggs 			if (part >= hweight8((init->r001540 >> 16) & 0xff))
126a8c4362bSBen Skeggs 				return ~0;
127a8c4362bSBen Skeggs 			return addr;
128a8c4362bSBen Skeggs 		}
129a8c4362bSBen Skeggs 		mmio += 3;
130a8c4362bSBen Skeggs 	}
131a8c4362bSBen Skeggs 
132a8c4362bSBen Skeggs 	return addr;
133a8c4362bSBen Skeggs }
134a8c4362bSBen Skeggs 
135151abd44SBen Skeggs static const struct nvkm_devinit_func
136151abd44SBen Skeggs gt215_devinit = {
137151abd44SBen Skeggs 	.preinit = nv50_devinit_preinit,
138a8c4362bSBen Skeggs 	.init = nv50_devinit_init,
139151abd44SBen Skeggs 	.post = nv04_devinit_post,
140151abd44SBen Skeggs 	.mmio = gt215_devinit_mmio,
141a8c4362bSBen Skeggs 	.pll_set = gt215_devinit_pll_set,
142a8c4362bSBen Skeggs 	.disable = gt215_devinit_disable,
143151abd44SBen Skeggs };
144151abd44SBen Skeggs 
145151abd44SBen Skeggs int
gt215_devinit_new(struct nvkm_device * device,enum nvkm_subdev_type type,int inst,struct nvkm_devinit ** pinit)1464a34fd0eSBen Skeggs gt215_devinit_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
147151abd44SBen Skeggs 		  struct nvkm_devinit **pinit)
148151abd44SBen Skeggs {
1494a34fd0eSBen Skeggs 	return nv50_devinit_new_(&gt215_devinit, device, type, inst, pinit);
150151abd44SBen Skeggs }
151