]>
Commit | Line | Data |
---|---|---|
dceef5d8 BS |
1 | /* |
2 | * Copyright 2013 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 | */ | |
d36a99d2 BS |
24 | #define nv50_ram(p) container_of((p), struct nv50_ram, base) |
25 | #include "ram.h" | |
639c308e | 26 | #include "ramseq.h" |
d36a99d2 | 27 | #include "nv50.h" |
dceef5d8 | 28 | |
639c308e | 29 | #include <core/option.h> |
dceef5d8 | 30 | #include <subdev/bios.h> |
aae95ca7 | 31 | #include <subdev/bios/perf.h> |
639c308e | 32 | #include <subdev/bios/pll.h> |
35fe024a | 33 | #include <subdev/bios/rammap.h> |
aae95ca7 | 34 | #include <subdev/bios/timing.h> |
f3867f43 | 35 | #include <subdev/clk/pll.h> |
1cf688dd | 36 | #include <subdev/gpio.h> |
dceef5d8 | 37 | |
aae95ca7 BS |
38 | struct nv50_ramseq { |
39 | struct hwsq base; | |
40 | struct hwsq_reg r_0x002504; | |
41 | struct hwsq_reg r_0x004008; | |
42 | struct hwsq_reg r_0x00400c; | |
43 | struct hwsq_reg r_0x00c040; | |
82a74fd2 | 44 | struct hwsq_reg r_0x100200; |
aae95ca7 | 45 | struct hwsq_reg r_0x100210; |
82a74fd2 | 46 | struct hwsq_reg r_0x10021c; |
aae95ca7 BS |
47 | struct hwsq_reg r_0x1002d0; |
48 | struct hwsq_reg r_0x1002d4; | |
49 | struct hwsq_reg r_0x1002dc; | |
82a74fd2 RS |
50 | struct hwsq_reg r_0x10053c; |
51 | struct hwsq_reg r_0x1005a0; | |
52 | struct hwsq_reg r_0x1005a4; | |
53 | struct hwsq_reg r_0x100710; | |
54 | struct hwsq_reg r_0x100714; | |
55 | struct hwsq_reg r_0x100718; | |
56 | struct hwsq_reg r_0x10071c; | |
d4cc5f0c | 57 | struct hwsq_reg r_0x100da0; |
aae95ca7 BS |
58 | struct hwsq_reg r_0x100e20; |
59 | struct hwsq_reg r_0x100e24; | |
60 | struct hwsq_reg r_0x611200; | |
61 | struct hwsq_reg r_timing[9]; | |
62 | struct hwsq_reg r_mr[4]; | |
1cf688dd | 63 | struct hwsq_reg r_gpio[4]; |
aae95ca7 BS |
64 | }; |
65 | ||
75faef78 | 66 | struct nv50_ram { |
639c308e | 67 | struct nvkm_ram base; |
aae95ca7 | 68 | struct nv50_ramseq hwsq; |
75faef78 BS |
69 | }; |
70 | ||
35fe024a RS |
71 | #define T(t) cfg->timing_10_##t |
72 | static int | |
d36a99d2 | 73 | nv50_ram_timing_calc(struct nv50_ram *ram, u32 *timing) |
35fe024a | 74 | { |
35fe024a | 75 | struct nvbios_ramcfg *cfg = &ram->base.target.bios; |
d36a99d2 | 76 | struct nvkm_subdev *subdev = &ram->base.fb->subdev; |
3ecd329b | 77 | struct nvkm_device *device = subdev->device; |
b1e4553c | 78 | u32 cur2, cur4, cur7, cur8; |
35fe024a RS |
79 | u8 unkt3b; |
80 | ||
6758745b BS |
81 | cur2 = nvkm_rd32(device, 0x100228); |
82 | cur4 = nvkm_rd32(device, 0x100230); | |
83 | cur7 = nvkm_rd32(device, 0x10023c); | |
84 | cur8 = nvkm_rd32(device, 0x100240); | |
35fe024a RS |
85 | |
86 | switch ((!T(CWL)) * ram->base.type) { | |
d36a99d2 | 87 | case NVKM_RAM_TYPE_DDR2: |
35fe024a RS |
88 | T(CWL) = T(CL) - 1; |
89 | break; | |
d36a99d2 | 90 | case NVKM_RAM_TYPE_GDDR3: |
35fe024a RS |
91 | T(CWL) = ((cur2 & 0xff000000) >> 24) + 1; |
92 | break; | |
93 | } | |
94 | ||
95 | /* XXX: N=1 is not proper statistics */ | |
d36a99d2 | 96 | if (device->chipset == 0xa0) { |
35fe024a RS |
97 | unkt3b = 0x19 + ram->base.next->bios.rammap_00_16_40; |
98 | timing[6] = (0x2d + T(CL) - T(CWL) + | |
99 | ram->base.next->bios.rammap_00_16_40) << 16 | | |
100 | T(CWL) << 8 | | |
101 | (0x2f + T(CL) - T(CWL)); | |
102 | } else { | |
103 | unkt3b = 0x16; | |
104 | timing[6] = (0x2b + T(CL) - T(CWL)) << 16 | | |
105 | max_t(s8, T(CWL) - 2, 1) << 8 | | |
106 | (0x2e + T(CL) - T(CWL)); | |
107 | } | |
108 | ||
109 | timing[0] = (T(RP) << 24 | T(RAS) << 16 | T(RFC) << 8 | T(RC)); | |
110 | timing[1] = (T(WR) + 1 + T(CWL)) << 24 | | |
111 | max_t(u8, T(18), 1) << 16 | | |
112 | (T(WTR) + 1 + T(CWL)) << 8 | | |
113 | (3 + T(CL) - T(CWL)); | |
114 | timing[2] = (T(CWL) - 1) << 24 | | |
115 | (T(RRD) << 16) | | |
116 | (T(RCDWR) << 8) | | |
117 | T(RCDRD); | |
118 | timing[3] = (unkt3b - 2 + T(CL)) << 24 | | |
119 | unkt3b << 16 | | |
120 | (T(CL) - 1) << 8 | | |
121 | (T(CL) - 1); | |
122 | timing[4] = (cur4 & 0xffff0000) | | |
123 | T(13) << 8 | | |
124 | T(13); | |
125 | timing[5] = T(RFC) << 24 | | |
126 | max_t(u8, T(RCDRD), T(RCDWR)) << 16 | | |
127 | T(RP); | |
128 | /* Timing 6 is already done above */ | |
129 | timing[7] = (cur7 & 0xff00ffff) | (T(CL) - 1) << 16; | |
130 | timing[8] = (cur8 & 0xffffff00); | |
131 | ||
132 | /* XXX: P.version == 1 only has DDR2 and GDDR3? */ | |
d36a99d2 | 133 | if (ram->base.type == NVKM_RAM_TYPE_DDR2) { |
35fe024a RS |
134 | timing[5] |= (T(CL) + 3) << 8; |
135 | timing[8] |= (T(CL) - 4); | |
d36a99d2 BS |
136 | } else |
137 | if (ram->base.type == NVKM_RAM_TYPE_GDDR3) { | |
35fe024a RS |
138 | timing[5] |= (T(CL) + 2) << 8; |
139 | timing[8] |= (T(CL) - 2); | |
140 | } | |
141 | ||
3ecd329b BS |
142 | nvkm_debug(subdev, " 220: %08x %08x %08x %08x\n", |
143 | timing[0], timing[1], timing[2], timing[3]); | |
144 | nvkm_debug(subdev, " 230: %08x %08x %08x %08x\n", | |
145 | timing[4], timing[5], timing[6], timing[7]); | |
146 | nvkm_debug(subdev, " 240: %08x\n", timing[8]); | |
35fe024a RS |
147 | return 0; |
148 | } | |
797eb6ed RS |
149 | |
150 | static int | |
151 | nv50_ram_timing_read(struct nv50_ram *ram, u32 *timing) | |
152 | { | |
153 | unsigned int i; | |
154 | struct nvbios_ramcfg *cfg = &ram->base.target.bios; | |
155 | struct nvkm_subdev *subdev = &ram->base.fb->subdev; | |
156 | struct nvkm_device *device = subdev->device; | |
157 | ||
158 | for (i = 0; i <= 8; i++) | |
159 | timing[i] = nvkm_rd32(device, 0x100220 + (i * 4)); | |
160 | ||
161 | /* Derive the bare minimum for the MR calculation to succeed */ | |
162 | cfg->timing_ver = 0x10; | |
163 | T(CL) = (timing[3] & 0xff) + 1; | |
164 | ||
165 | switch (ram->base.type) { | |
166 | case NVKM_RAM_TYPE_DDR2: | |
167 | T(CWL) = T(CL) - 1; | |
168 | break; | |
169 | case NVKM_RAM_TYPE_GDDR3: | |
170 | T(CWL) = ((timing[2] & 0xff000000) >> 24) + 1; | |
171 | break; | |
172 | default: | |
173 | return -ENOSYS; | |
174 | break; | |
175 | } | |
176 | ||
177 | T(WR) = ((timing[1] >> 24) & 0xff) - 1 - T(CWL); | |
178 | ||
179 | return 0; | |
180 | } | |
35fe024a RS |
181 | #undef T |
182 | ||
82a74fd2 RS |
183 | static void |
184 | nvkm_sddr2_dll_reset(struct nv50_ramseq *hwsq) | |
185 | { | |
186 | ram_mask(hwsq, mr[0], 0x100, 0x100); | |
187 | ram_mask(hwsq, mr[0], 0x100, 0x000); | |
188 | ram_nsec(hwsq, 24000); | |
189 | } | |
aae95ca7 | 190 | |
1cf688dd RS |
191 | static void |
192 | nv50_ram_gpio(struct nv50_ramseq *hwsq, u8 tag, u32 val) | |
193 | { | |
194 | struct nvkm_gpio *gpio = hwsq->base.subdev->device->gpio; | |
195 | struct dcb_gpio_func func; | |
196 | u32 reg, sh, gpio_val; | |
197 | int ret; | |
198 | ||
199 | if (nvkm_gpio_get(gpio, 0, tag, DCB_GPIO_UNUSED) != val) { | |
200 | ret = nvkm_gpio_find(gpio, 0, tag, DCB_GPIO_UNUSED, &func); | |
201 | if (ret) | |
202 | return; | |
203 | ||
204 | reg = func.line >> 3; | |
205 | sh = (func.line & 0x7) << 2; | |
206 | gpio_val = ram_rd32(hwsq, gpio[reg]); | |
207 | ||
208 | if (gpio_val & (8 << sh)) | |
209 | val = !val; | |
210 | if (!(func.log[1] & 1)) | |
211 | val = !val; | |
212 | ||
213 | ram_mask(hwsq, gpio[reg], (0x3 << sh), ((val | 0x2) << sh)); | |
214 | ram_nsec(hwsq, 20000); | |
215 | } | |
216 | } | |
217 | ||
aae95ca7 | 218 | static int |
d36a99d2 | 219 | nv50_ram_calc(struct nvkm_ram *base, u32 freq) |
aae95ca7 | 220 | { |
d36a99d2 | 221 | struct nv50_ram *ram = nv50_ram(base); |
aae95ca7 | 222 | struct nv50_ramseq *hwsq = &ram->hwsq; |
d36a99d2 | 223 | struct nvkm_subdev *subdev = &ram->base.fb->subdev; |
3ecd329b | 224 | struct nvkm_bios *bios = subdev->device->bios; |
aae95ca7 BS |
225 | struct nvbios_perfE perfE; |
226 | struct nvbios_pll mpll; | |
35fe024a RS |
227 | struct nvkm_ram_data *next; |
228 | u8 ver, hdr, cnt, len, strap, size; | |
229 | u32 data; | |
82a74fd2 | 230 | u32 r100da0, r004008, unk710, unk714, unk718, unk71c; |
aae95ca7 BS |
231 | int N1, M1, N2, M2, P; |
232 | int ret, i; | |
35fe024a RS |
233 | u32 timing[9]; |
234 | ||
235 | next = &ram->base.target; | |
236 | next->freq = freq; | |
237 | ram->base.next = next; | |
aae95ca7 BS |
238 | |
239 | /* lookup closest matching performance table entry for frequency */ | |
240 | i = 0; | |
241 | do { | |
35fe024a | 242 | data = nvbios_perfEp(bios, i++, &ver, &hdr, &cnt, |
d36a99d2 | 243 | &size, &perfE); |
35fe024a RS |
244 | if (!data || (ver < 0x25 || ver >= 0x40) || |
245 | (size < 2)) { | |
3ecd329b | 246 | nvkm_error(subdev, "invalid/missing perftab entry\n"); |
aae95ca7 BS |
247 | return -EINVAL; |
248 | } | |
249 | } while (perfE.memory < freq); | |
250 | ||
2813e19f RS |
251 | nvbios_rammapEp_from_perf(bios, data, hdr, &next->bios); |
252 | ||
aae95ca7 | 253 | /* locate specific data set for the attached memory */ |
d36a99d2 | 254 | strap = nvbios_ramcfg_index(subdev); |
aae95ca7 | 255 | if (strap >= cnt) { |
3ecd329b | 256 | nvkm_error(subdev, "invalid ramcfg strap\n"); |
aae95ca7 BS |
257 | return -EINVAL; |
258 | } | |
259 | ||
35fe024a RS |
260 | data = nvbios_rammapSp_from_perf(bios, data + hdr, size, strap, |
261 | &next->bios); | |
262 | if (!data) { | |
3ecd329b | 263 | nvkm_error(subdev, "invalid/missing rammap entry "); |
35fe024a RS |
264 | return -EINVAL; |
265 | } | |
aae95ca7 BS |
266 | |
267 | /* lookup memory timings, if bios says they're present */ | |
35fe024a RS |
268 | if (next->bios.ramcfg_timing != 0xff) { |
269 | data = nvbios_timingEp(bios, next->bios.ramcfg_timing, | |
270 | &ver, &hdr, &cnt, &len, &next->bios); | |
271 | if (!data || ver != 0x10 || hdr < 0x12) { | |
3ecd329b | 272 | nvkm_error(subdev, "invalid/missing timing entry " |
aae95ca7 | 273 | "%02x %04x %02x %02x\n", |
35fe024a | 274 | strap, data, ver, hdr); |
aae95ca7 BS |
275 | return -EINVAL; |
276 | } | |
797eb6ed RS |
277 | nv50_ram_timing_calc(ram, timing); |
278 | } else { | |
279 | nv50_ram_timing_read(ram, timing); | |
aae95ca7 BS |
280 | } |
281 | ||
d36a99d2 | 282 | ret = ram_init(hwsq, subdev); |
35fe024a RS |
283 | if (ret) |
284 | return ret; | |
285 | ||
286 | /* Determine ram-specific MR values */ | |
287 | ram->base.mr[0] = ram_rd32(hwsq, mr[0]); | |
288 | ram->base.mr[1] = ram_rd32(hwsq, mr[1]); | |
289 | ram->base.mr[2] = ram_rd32(hwsq, mr[2]); | |
290 | ||
291 | switch (ram->base.type) { | |
d36a99d2 | 292 | case NVKM_RAM_TYPE_GDDR3: |
35fe024a RS |
293 | ret = nvkm_gddr3_calc(&ram->base); |
294 | break; | |
295 | default: | |
296 | ret = -ENOSYS; | |
297 | break; | |
298 | } | |
299 | ||
797eb6ed RS |
300 | if (ret) { |
301 | nvkm_error(subdev, "Could not calculate MR\n"); | |
35fe024a | 302 | return ret; |
797eb6ed | 303 | } |
35fe024a | 304 | |
4d9faafa RS |
305 | if (subdev->device->chipset <= 0x96 && !next->bios.ramcfg_00_03_02) |
306 | ram_mask(hwsq, 0x100710, 0x00000200, 0x00000000); | |
307 | ||
82a74fd2 RS |
308 | /* Always disable this bit during reclock */ |
309 | ram_mask(hwsq, 0x100200, 0x00000800, 0x00000000); | |
d4cc5f0c | 310 | |
271c2766 | 311 | ram_wait_vblank(hwsq); |
aae95ca7 BS |
312 | ram_wr32(hwsq, 0x611200, 0x00003300); |
313 | ram_wr32(hwsq, 0x002504, 0x00000001); /* block fifo */ | |
314 | ram_nsec(hwsq, 8000); | |
315 | ram_setf(hwsq, 0x10, 0x00); /* disable fb */ | |
316 | ram_wait(hwsq, 0x00, 0x01); /* wait for fb disabled */ | |
82a74fd2 | 317 | ram_nsec(hwsq, 2000); |
aae95ca7 | 318 | |
1cf688dd RS |
319 | if (next->bios.timing_10_ODT) |
320 | nv50_ram_gpio(hwsq, 0x2e, 1); | |
321 | ||
aae95ca7 BS |
322 | ram_wr32(hwsq, 0x1002d4, 0x00000001); /* precharge */ |
323 | ram_wr32(hwsq, 0x1002d0, 0x00000001); /* refresh */ | |
324 | ram_wr32(hwsq, 0x1002d0, 0x00000001); /* refresh */ | |
325 | ram_wr32(hwsq, 0x100210, 0x00000000); /* disable auto-refresh */ | |
326 | ram_wr32(hwsq, 0x1002dc, 0x00000001); /* enable self-refresh */ | |
327 | ||
328 | ret = nvbios_pll_parse(bios, 0x004008, &mpll); | |
329 | mpll.vco2.max_freq = 0; | |
b1e4553c | 330 | if (ret >= 0) { |
d36a99d2 | 331 | ret = nv04_pll_calc(subdev, &mpll, freq, |
639c308e | 332 | &N1, &M1, &N2, &M2, &P); |
b1e4553c | 333 | if (ret <= 0) |
aae95ca7 BS |
334 | ret = -EINVAL; |
335 | } | |
336 | ||
337 | if (ret < 0) | |
338 | return ret; | |
339 | ||
82a74fd2 RS |
340 | /* XXX: 750MHz seems rather arbitrary */ |
341 | if (freq <= 750000) { | |
342 | r100da0 = 0x00000010; | |
343 | r004008 = 0x90000000; | |
344 | } else { | |
345 | r100da0 = 0x00000000; | |
346 | r004008 = 0x80000000; | |
347 | } | |
348 | ||
349 | r004008 |= (mpll.bias_p << 19) | (P << 22) | (P << 16); | |
350 | ||
aae95ca7 | 351 | ram_mask(hwsq, 0x00c040, 0xc000c000, 0x0000c000); |
82a74fd2 RS |
352 | /* XXX: Is rammap_00_16_40 the DLL bit we've seen in GT215? Why does |
353 | * it have a different rammap bit from DLLoff? */ | |
354 | ram_mask(hwsq, 0x004008, 0x00004200, 0x00000200 | | |
355 | next->bios.rammap_00_16_40 << 14); | |
aae95ca7 | 356 | ram_mask(hwsq, 0x00400c, 0x0000ffff, (N1 << 8) | M1); |
82a74fd2 | 357 | ram_mask(hwsq, 0x004008, 0x91ff0000, r004008); |
4d9faafa RS |
358 | |
359 | /* XXX: GDDR3 only? */ | |
360 | if (subdev->device->chipset >= 0x92) | |
82a74fd2 | 361 | ram_wr32(hwsq, 0x100da0, r100da0); |
4d9faafa | 362 | |
1cf688dd | 363 | nv50_ram_gpio(hwsq, 0x18, !next->bios.ramcfg_FBVDDQ); |
82a74fd2 RS |
364 | ram_nsec(hwsq, 64000); /*XXX*/ |
365 | ram_nsec(hwsq, 32000); /*XXX*/ | |
d4cc5f0c | 366 | |
aae95ca7 BS |
367 | ram_mask(hwsq, 0x004008, 0x00002200, 0x00002000); |
368 | ||
369 | ram_wr32(hwsq, 0x1002dc, 0x00000000); /* disable self-refresh */ | |
82a74fd2 | 370 | ram_wr32(hwsq, 0x1002d4, 0x00000001); /* disable self-refresh */ |
aae95ca7 BS |
371 | ram_wr32(hwsq, 0x100210, 0x80000000); /* enable auto-refresh */ |
372 | ||
373 | ram_nsec(hwsq, 12000); | |
374 | ||
375 | switch (ram->base.type) { | |
d36a99d2 | 376 | case NVKM_RAM_TYPE_DDR2: |
aae95ca7 BS |
377 | ram_nuke(hwsq, mr[0]); /* force update */ |
378 | ram_mask(hwsq, mr[0], 0x000, 0x000); | |
379 | break; | |
d36a99d2 | 380 | case NVKM_RAM_TYPE_GDDR3: |
82a74fd2 RS |
381 | ram_nuke(hwsq, mr[1]); /* force update */ |
382 | ram_wr32(hwsq, mr[1], ram->base.mr[1]); | |
aae95ca7 | 383 | ram_nuke(hwsq, mr[0]); /* force update */ |
82a74fd2 | 384 | ram_wr32(hwsq, mr[0], ram->base.mr[0]); |
aae95ca7 BS |
385 | break; |
386 | default: | |
387 | break; | |
388 | } | |
389 | ||
35fe024a RS |
390 | ram_mask(hwsq, timing[3], 0xffffffff, timing[3]); |
391 | ram_mask(hwsq, timing[1], 0xffffffff, timing[1]); | |
392 | ram_mask(hwsq, timing[6], 0xffffffff, timing[6]); | |
393 | ram_mask(hwsq, timing[7], 0xffffffff, timing[7]); | |
394 | ram_mask(hwsq, timing[8], 0xffffffff, timing[8]); | |
395 | ram_mask(hwsq, timing[0], 0xffffffff, timing[0]); | |
396 | ram_mask(hwsq, timing[2], 0xffffffff, timing[2]); | |
397 | ram_mask(hwsq, timing[4], 0xffffffff, timing[4]); | |
398 | ram_mask(hwsq, timing[5], 0xffffffff, timing[5]); | |
aae95ca7 | 399 | |
82a74fd2 RS |
400 | if (!next->bios.ramcfg_00_03_02) |
401 | ram_mask(hwsq, 0x10021c, 0x00010000, 0x00000000); | |
402 | ram_mask(hwsq, 0x100200, 0x00001000, !next->bios.ramcfg_00_04_02 << 12); | |
403 | ||
404 | /* XXX: A lot of this could be "chipset"/"ram type" specific stuff */ | |
4d9faafa | 405 | unk710 = ram_rd32(hwsq, 0x100710) & ~0x00000100; |
82a74fd2 RS |
406 | unk714 = ram_rd32(hwsq, 0x100714) & ~0xf0000020; |
407 | unk718 = ram_rd32(hwsq, 0x100718) & ~0x00000100; | |
408 | unk71c = ram_rd32(hwsq, 0x10071c) & ~0x00000100; | |
4d9faafa RS |
409 | if (subdev->device->chipset <= 0x96) { |
410 | unk710 &= ~0x0000006e; | |
411 | unk714 &= ~0x00000100; | |
412 | ||
413 | if (!next->bios.ramcfg_00_03_08) | |
414 | unk710 |= 0x00000060; | |
415 | if (!next->bios.ramcfg_FBVDDQ) | |
416 | unk714 |= 0x00000100; | |
417 | if ( next->bios.ramcfg_00_04_04) | |
418 | unk710 |= 0x0000000e; | |
419 | } else { | |
420 | unk710 &= ~0x00000001; | |
421 | ||
422 | if (!next->bios.ramcfg_00_03_08) | |
423 | unk710 |= 0x00000001; | |
424 | } | |
82a74fd2 RS |
425 | |
426 | if ( next->bios.ramcfg_00_03_01) | |
427 | unk71c |= 0x00000100; | |
428 | if ( next->bios.ramcfg_00_03_02) | |
429 | unk710 |= 0x00000100; | |
4d9faafa RS |
430 | if (!next->bios.ramcfg_00_03_08) |
431 | unk714 |= 0x00000020; | |
82a74fd2 RS |
432 | if ( next->bios.ramcfg_00_04_04) |
433 | unk714 |= 0x70000000; | |
434 | if ( next->bios.ramcfg_00_04_20) | |
435 | unk718 |= 0x00000100; | |
436 | ||
437 | ram_mask(hwsq, 0x100714, 0xffffffff, unk714); | |
438 | ram_mask(hwsq, 0x10071c, 0xffffffff, unk71c); | |
439 | ram_mask(hwsq, 0x100718, 0xffffffff, unk718); | |
440 | ram_mask(hwsq, 0x100710, 0xffffffff, unk710); | |
441 | ||
4d9faafa RS |
442 | /* XXX: G94 does not even test these regs in trace. Harmless we do it, |
443 | * but why is it omitted? */ | |
82a74fd2 RS |
444 | if (next->bios.rammap_00_16_20) { |
445 | ram_wr32(hwsq, 0x1005a0, next->bios.ramcfg_00_07 << 16 | | |
446 | next->bios.ramcfg_00_06 << 8 | | |
447 | next->bios.ramcfg_00_05); | |
448 | ram_wr32(hwsq, 0x1005a4, next->bios.ramcfg_00_09 << 8 | | |
449 | next->bios.ramcfg_00_08); | |
450 | ram_mask(hwsq, 0x10053c, 0x00001000, 0x00000000); | |
451 | } else { | |
452 | ram_mask(hwsq, 0x10053c, 0x00001000, 0x00001000); | |
453 | } | |
454 | ram_mask(hwsq, mr[1], 0xffffffff, ram->base.mr[1]); | |
aae95ca7 | 455 | |
1cf688dd RS |
456 | if (!next->bios.timing_10_ODT) |
457 | nv50_ram_gpio(hwsq, 0x2e, 0); | |
458 | ||
82a74fd2 RS |
459 | /* Reset DLL */ |
460 | if (!next->bios.ramcfg_DLLoff) | |
461 | nvkm_sddr2_dll_reset(hwsq); | |
aae95ca7 BS |
462 | |
463 | ram_setf(hwsq, 0x10, 0x01); /* enable fb */ | |
464 | ram_wait(hwsq, 0x00, 0x00); /* wait for fb enabled */ | |
465 | ram_wr32(hwsq, 0x611200, 0x00003330); | |
466 | ram_wr32(hwsq, 0x002504, 0x00000000); /* un-block fifo */ | |
82a74fd2 RS |
467 | |
468 | if (next->bios.rammap_00_17_02) | |
469 | ram_mask(hwsq, 0x100200, 0x00000800, 0x00000800); | |
470 | if (!next->bios.rammap_00_16_40) | |
471 | ram_mask(hwsq, 0x004008, 0x00004000, 0x00000000); | |
472 | if (next->bios.ramcfg_00_03_02) | |
473 | ram_mask(hwsq, 0x10021c, 0x00010000, 0x00010000); | |
4d9faafa RS |
474 | if (subdev->device->chipset <= 0x96 && next->bios.ramcfg_00_03_02) |
475 | ram_mask(hwsq, 0x100710, 0x00000200, 0x00000200); | |
82a74fd2 | 476 | |
aae95ca7 BS |
477 | return 0; |
478 | } | |
479 | ||
480 | static int | |
d36a99d2 | 481 | nv50_ram_prog(struct nvkm_ram *base) |
aae95ca7 | 482 | { |
d36a99d2 BS |
483 | struct nv50_ram *ram = nv50_ram(base); |
484 | struct nvkm_device *device = ram->base.fb->subdev.device; | |
485 | ram_exec(&ram->hwsq, nvkm_boolopt(device->cfgopt, "NvMemExec", true)); | |
aae95ca7 BS |
486 | return 0; |
487 | } | |
488 | ||
489 | static void | |
d36a99d2 | 490 | nv50_ram_tidy(struct nvkm_ram *base) |
aae95ca7 | 491 | { |
d36a99d2 BS |
492 | struct nv50_ram *ram = nv50_ram(base); |
493 | ram_exec(&ram->hwsq, false); | |
aae95ca7 BS |
494 | } |
495 | ||
dceef5d8 | 496 | void |
d36a99d2 | 497 | __nv50_ram_put(struct nvkm_ram *ram, struct nvkm_mem *mem) |
dceef5d8 | 498 | { |
134fdc1a BS |
499 | struct nvkm_mm_node *next = mem->mem; |
500 | struct nvkm_mm_node *node; | |
501 | while ((node = next)) { | |
502 | next = node->next; | |
503 | nvkm_mm_free(&ram->vram, &node); | |
dceef5d8 | 504 | } |
dedaa8f0 RS |
505 | } |
506 | ||
507 | void | |
d36a99d2 | 508 | nv50_ram_put(struct nvkm_ram *ram, struct nvkm_mem **pmem) |
dedaa8f0 | 509 | { |
639c308e | 510 | struct nvkm_mem *mem = *pmem; |
dedaa8f0 RS |
511 | |
512 | *pmem = NULL; | |
513 | if (unlikely(mem == NULL)) | |
514 | return; | |
515 | ||
d36a99d2 BS |
516 | mutex_lock(&ram->fb->subdev.mutex); |
517 | __nv50_ram_put(ram, mem); | |
518 | mutex_unlock(&ram->fb->subdev.mutex); | |
dceef5d8 BS |
519 | |
520 | kfree(mem); | |
521 | } | |
522 | ||
75faef78 | 523 | int |
d36a99d2 | 524 | nv50_ram_get(struct nvkm_ram *ram, u64 size, u32 align, u32 ncmin, |
639c308e | 525 | u32 memtype, struct nvkm_mem **pmem) |
dceef5d8 | 526 | { |
d36a99d2 | 527 | struct nvkm_mm *heap = &ram->vram; |
134fdc1a | 528 | struct nvkm_mm_node **node, *r; |
639c308e | 529 | struct nvkm_mem *mem; |
dceef5d8 BS |
530 | int comp = (memtype & 0x300) >> 8; |
531 | int type = (memtype & 0x07f); | |
532 | int back = (memtype & 0x800); | |
533 | int min, max, ret; | |
534 | ||
d36a99d2 BS |
535 | max = (size >> NVKM_RAM_MM_SHIFT); |
536 | min = ncmin ? (ncmin >> NVKM_RAM_MM_SHIFT) : max; | |
537 | align >>= NVKM_RAM_MM_SHIFT; | |
dceef5d8 BS |
538 | |
539 | mem = kzalloc(sizeof(*mem), GFP_KERNEL); | |
540 | if (!mem) | |
541 | return -ENOMEM; | |
542 | ||
d36a99d2 | 543 | mutex_lock(&ram->fb->subdev.mutex); |
dceef5d8 BS |
544 | mem->memtype = (comp << 7) | type; |
545 | mem->size = max; | |
546 | ||
547 | type = nv50_fb_memtype[type]; | |
134fdc1a | 548 | node = &mem->mem; |
dceef5d8 BS |
549 | do { |
550 | if (back) | |
639c308e | 551 | ret = nvkm_mm_tail(heap, 0, type, max, min, align, &r); |
dceef5d8 | 552 | else |
639c308e | 553 | ret = nvkm_mm_head(heap, 0, type, max, min, align, &r); |
dceef5d8 | 554 | if (ret) { |
d36a99d2 BS |
555 | mutex_unlock(&ram->fb->subdev.mutex); |
556 | ram->func->put(ram, &mem); | |
dceef5d8 BS |
557 | return ret; |
558 | } | |
559 | ||
134fdc1a BS |
560 | *node = r; |
561 | node = &r->next; | |
dceef5d8 BS |
562 | max -= r->length; |
563 | } while (max); | |
d36a99d2 | 564 | mutex_unlock(&ram->fb->subdev.mutex); |
dceef5d8 | 565 | |
134fdc1a | 566 | mem->offset = (u64)mem->mem->offset << NVKM_RAM_MM_SHIFT; |
dceef5d8 BS |
567 | *pmem = mem; |
568 | return 0; | |
569 | } | |
570 | ||
d36a99d2 BS |
571 | static const struct nvkm_ram_func |
572 | nv50_ram_func = { | |
573 | .get = nv50_ram_get, | |
574 | .put = nv50_ram_put, | |
575 | .calc = nv50_ram_calc, | |
576 | .prog = nv50_ram_prog, | |
577 | .tidy = nv50_ram_tidy, | |
578 | }; | |
579 | ||
dceef5d8 | 580 | static u32 |
d36a99d2 | 581 | nv50_fb_vram_rblock(struct nvkm_ram *ram) |
dceef5d8 | 582 | { |
d36a99d2 | 583 | struct nvkm_subdev *subdev = &ram->fb->subdev; |
3ecd329b | 584 | struct nvkm_device *device = subdev->device; |
de1c4e28 | 585 | int colbits, rowbitsa, rowbitsb, banks; |
dceef5d8 | 586 | u64 rowsize, predicted; |
de1c4e28 | 587 | u32 r0, r4, rt, rblock_size; |
dceef5d8 | 588 | |
6758745b BS |
589 | r0 = nvkm_rd32(device, 0x100200); |
590 | r4 = nvkm_rd32(device, 0x100204); | |
591 | rt = nvkm_rd32(device, 0x100250); | |
3ecd329b BS |
592 | nvkm_debug(subdev, "memcfg %08x %08x %08x %08x\n", |
593 | r0, r4, rt, nvkm_rd32(device, 0x001540)); | |
dceef5d8 BS |
594 | |
595 | colbits = (r4 & 0x0000f000) >> 12; | |
596 | rowbitsa = ((r4 & 0x000f0000) >> 16) + 8; | |
597 | rowbitsb = ((r4 & 0x00f00000) >> 20) + 8; | |
598 | banks = 1 << (((r4 & 0x03000000) >> 24) + 2); | |
599 | ||
de1c4e28 | 600 | rowsize = ram->parts * banks * (1 << colbits) * 8; |
dceef5d8 BS |
601 | predicted = rowsize << rowbitsa; |
602 | if (r0 & 0x00000004) | |
603 | predicted += rowsize << rowbitsb; | |
604 | ||
605 | if (predicted != ram->size) { | |
3ecd329b BS |
606 | nvkm_warn(subdev, "memory controller reports %d MiB VRAM\n", |
607 | (u32)(ram->size >> 20)); | |
dceef5d8 BS |
608 | } |
609 | ||
610 | rblock_size = rowsize; | |
611 | if (rt & 1) | |
612 | rblock_size *= 3; | |
613 | ||
3ecd329b | 614 | nvkm_debug(subdev, "rblock %d bytes\n", rblock_size); |
dceef5d8 BS |
615 | return rblock_size; |
616 | } | |
617 | ||
75faef78 | 618 | int |
d36a99d2 BS |
619 | nv50_ram_ctor(const struct nvkm_ram_func *func, |
620 | struct nvkm_fb *fb, struct nvkm_ram *ram) | |
dceef5d8 | 621 | { |
6758745b BS |
622 | struct nvkm_device *device = fb->subdev.device; |
623 | struct nvkm_bios *bios = device->bios; | |
d36a99d2 BS |
624 | const u32 rsvd_head = ( 256 * 1024); /* vga memory */ |
625 | const u32 rsvd_tail = (1024 * 1024); /* vbios etc */ | |
626 | u64 size = nvkm_rd32(device, 0x10020c); | |
d36a99d2 | 627 | enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN; |
dceef5d8 BS |
628 | int ret; |
629 | ||
6758745b | 630 | switch (nvkm_rd32(device, 0x100714) & 0x00000007) { |
d36a99d2 | 631 | case 0: type = NVKM_RAM_TYPE_DDR1; break; |
75faef78 | 632 | case 1: |
d36a99d2 BS |
633 | if (nvkm_fb_bios_memtype(bios) == NVKM_RAM_TYPE_DDR3) |
634 | type = NVKM_RAM_TYPE_DDR3; | |
75faef78 | 635 | else |
d36a99d2 | 636 | type = NVKM_RAM_TYPE_DDR2; |
dceef5d8 | 637 | break; |
d36a99d2 BS |
638 | case 2: type = NVKM_RAM_TYPE_GDDR3; break; |
639 | case 3: type = NVKM_RAM_TYPE_GDDR4; break; | |
640 | case 4: type = NVKM_RAM_TYPE_GDDR5; break; | |
dceef5d8 | 641 | default: |
dceef5d8 BS |
642 | break; |
643 | } | |
644 | ||
d36a99d2 BS |
645 | size = (size & 0x000000ff) << 32 | (size & 0xffffff00); |
646 | ||
af793b8c | 647 | ret = nvkm_ram_ctor(func, fb, type, size, ram); |
75faef78 BS |
648 | if (ret) |
649 | return ret; | |
650 | ||
d36a99d2 BS |
651 | ram->part_mask = (nvkm_rd32(device, 0x001540) & 0x00ff0000) >> 16; |
652 | ram->parts = hweight8(ram->part_mask); | |
6758745b | 653 | ram->ranks = (nvkm_rd32(device, 0x100200) & 0x4) ? 2 : 1; |
d36a99d2 BS |
654 | nvkm_mm_fini(&ram->vram); |
655 | ||
4d058fab BS |
656 | return nvkm_mm_init(&ram->vram, NVKM_RAM_MM_NORMAL, |
657 | rsvd_head >> NVKM_RAM_MM_SHIFT, | |
d36a99d2 BS |
658 | (size - rsvd_head - rsvd_tail) >> NVKM_RAM_MM_SHIFT, |
659 | nv50_fb_vram_rblock(ram) >> NVKM_RAM_MM_SHIFT); | |
dceef5d8 BS |
660 | } |
661 | ||
d36a99d2 BS |
662 | int |
663 | nv50_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) | |
75faef78 BS |
664 | { |
665 | struct nv50_ram *ram; | |
aae95ca7 | 666 | int ret, i; |
75faef78 | 667 | |
d36a99d2 BS |
668 | if (!(ram = kzalloc(sizeof(*ram), GFP_KERNEL))) |
669 | return -ENOMEM; | |
670 | *pram = &ram->base; | |
671 | ||
672 | ret = nv50_ram_ctor(&nv50_ram_func, fb, &ram->base); | |
75faef78 BS |
673 | if (ret) |
674 | return ret; | |
675 | ||
aae95ca7 BS |
676 | ram->hwsq.r_0x002504 = hwsq_reg(0x002504); |
677 | ram->hwsq.r_0x00c040 = hwsq_reg(0x00c040); | |
678 | ram->hwsq.r_0x004008 = hwsq_reg(0x004008); | |
679 | ram->hwsq.r_0x00400c = hwsq_reg(0x00400c); | |
82a74fd2 | 680 | ram->hwsq.r_0x100200 = hwsq_reg(0x100200); |
aae95ca7 | 681 | ram->hwsq.r_0x100210 = hwsq_reg(0x100210); |
82a74fd2 | 682 | ram->hwsq.r_0x10021c = hwsq_reg(0x10021c); |
aae95ca7 BS |
683 | ram->hwsq.r_0x1002d0 = hwsq_reg(0x1002d0); |
684 | ram->hwsq.r_0x1002d4 = hwsq_reg(0x1002d4); | |
685 | ram->hwsq.r_0x1002dc = hwsq_reg(0x1002dc); | |
82a74fd2 RS |
686 | ram->hwsq.r_0x10053c = hwsq_reg(0x10053c); |
687 | ram->hwsq.r_0x1005a0 = hwsq_reg(0x1005a0); | |
688 | ram->hwsq.r_0x1005a4 = hwsq_reg(0x1005a4); | |
689 | ram->hwsq.r_0x100710 = hwsq_reg(0x100710); | |
690 | ram->hwsq.r_0x100714 = hwsq_reg(0x100714); | |
691 | ram->hwsq.r_0x100718 = hwsq_reg(0x100718); | |
692 | ram->hwsq.r_0x10071c = hwsq_reg(0x10071c); | |
d4cc5f0c | 693 | ram->hwsq.r_0x100da0 = hwsq_stride(0x100da0, 4, ram->base.part_mask); |
aae95ca7 BS |
694 | ram->hwsq.r_0x100e20 = hwsq_reg(0x100e20); |
695 | ram->hwsq.r_0x100e24 = hwsq_reg(0x100e24); | |
696 | ram->hwsq.r_0x611200 = hwsq_reg(0x611200); | |
697 | ||
698 | for (i = 0; i < 9; i++) | |
699 | ram->hwsq.r_timing[i] = hwsq_reg(0x100220 + (i * 0x04)); | |
700 | ||
701 | if (ram->base.ranks > 1) { | |
702 | ram->hwsq.r_mr[0] = hwsq_reg2(0x1002c0, 0x1002c8); | |
703 | ram->hwsq.r_mr[1] = hwsq_reg2(0x1002c4, 0x1002cc); | |
704 | ram->hwsq.r_mr[2] = hwsq_reg2(0x1002e0, 0x1002e8); | |
705 | ram->hwsq.r_mr[3] = hwsq_reg2(0x1002e4, 0x1002ec); | |
706 | } else { | |
707 | ram->hwsq.r_mr[0] = hwsq_reg(0x1002c0); | |
708 | ram->hwsq.r_mr[1] = hwsq_reg(0x1002c4); | |
709 | ram->hwsq.r_mr[2] = hwsq_reg(0x1002e0); | |
710 | ram->hwsq.r_mr[3] = hwsq_reg(0x1002e4); | |
711 | } | |
712 | ||
1cf688dd RS |
713 | ram->hwsq.r_gpio[0] = hwsq_reg(0x00e104); |
714 | ram->hwsq.r_gpio[1] = hwsq_reg(0x00e108); | |
715 | ram->hwsq.r_gpio[2] = hwsq_reg(0x00e120); | |
716 | ram->hwsq.r_gpio[3] = hwsq_reg(0x00e124); | |
717 | ||
75faef78 BS |
718 | return 0; |
719 | } |