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_(>215_devinit, device, type, inst, pinit);
150151abd44SBen Skeggs }
151