blob: 09cd66269d426383d052ffe529a7a744f7d2bd44 [file] [log] [blame]
Duncan Lauriee3f75f82013-10-28 15:49:34 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2013 Google Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <arch/io.h>
21#include <console/console.h>
22#include <delay.h>
23#include <device/device.h>
24#include <device/pci.h>
25#include <device/pci_ids.h>
26
27#include <baytrail/gfx.h>
28#include <baytrail/iosf.h>
29#include <baytrail/pci_devs.h>
30#include <baytrail/ramstage.h>
31
32struct gt_reg {
33 u32 reg;
34 u32 andmask;
35 u32 ormask;
36};
37
38static const struct gt_reg gfx_powermeter_weights[] = {
39 /* SET1 */
40 { 0xA800, 0xFFFFFFFF, 0x00000000 },
41 { 0xA804, 0xFFFFFFFF, 0x00000000 },
42 { 0xA808, 0xFFFFFFFF, 0x0000ff0A },
43 { 0xA80C, 0xFFFFFFFF, 0x1D000000 },
44 { 0xA810, 0xFFFFFFFF, 0xAC004900 },
45 { 0xA814, 0xFFFFFFFF, 0x000F0000 },
46 { 0xA818, 0xFFFFFFFF, 0x5A000000 },
47 { 0xA81C, 0xFFFFFFFF, 0x2600001F },
48 { 0xA820, 0xFFFFFFFF, 0x00090000 },
49 { 0xA824, 0xFFFFFFFF, 0x2000ff00 },
50 { 0xA828, 0xFFFFFFFF, 0xff090016 },
51 { 0xA82C, 0xFFFFFFFF, 0x00000000 },
52 { 0xA830, 0xFFFFFFFF, 0x00000100 },
53 { 0xA834, 0xFFFFFFFF, 0x00A00F51 },
54 { 0xA838, 0xFFFFFFFF, 0x000B0000 },
55 { 0xA83C, 0xFFFFFFFF, 0xcb7D3307 },
56 { 0xA840, 0xFFFFFFFF, 0x003C0000 },
57 { 0xA844, 0xFFFFFFFF, 0xFFFF0000 },
58 { 0xA848, 0xFFFFFFFF, 0x00220000 },
59 { 0xA84c, 0xFFFFFFFF, 0x43000000 },
60 { 0xA850, 0xFFFFFFFF, 0x00000800 },
61 { 0xA854, 0xFFFFFFFF, 0x00000F00 },
62 { 0xA858, 0xFFFFFFFF, 0x00000021 },
63 { 0xA85c, 0xFFFFFFFF, 0x00000000 },
64 { 0xA860, 0xFFFFFFFF, 0x00190000 },
65 { 0xAA80, 0xFFFFFFFF, 0x00FF00FF },
66 { 0xAA84, 0xFFFFFFFF, 0x00000000 },
67 { 0x1300A4, 0xFFFFFFFF, 0x00000000 },
68
69 /* SET2 */
70 { 0xA900, 0xFFFFFFFF, 0x00000000 },
71 { 0xA904, 0xFFFFFFFF, 0x00000000 },
72 { 0xA908, 0xFFFFFFFF, 0x00000000 },
73 { 0xa90c, 0xFFFFFFFF, 0x1D000000 },
74 { 0xa910, 0xFFFFFFFF, 0xAC005000 },
75 { 0xa914, 0xFFFFFFFF, 0x000F0000 },
76 { 0xa918, 0xFFFFFFFF, 0x5A000000 },
77 { 0xa91c, 0xFFFFFFFF, 0x2600001F },
78 { 0xa920, 0xFFFFFFFF, 0x00090000 },
79 { 0xa924, 0xFFFFFFFF, 0x2000ff00 },
80 { 0xa928, 0xFFFFFFFF, 0xff090016 },
81 { 0xa92c, 0xFFFFFFFF, 0x00000000 },
82 { 0xa930, 0xFFFFFFFF, 0x00000100 },
83 { 0xa934, 0xFFFFFFFF, 0x00A00F51 },
84 { 0xa938, 0xFFFFFFFF, 0x000B0000 },
85 { 0xA93C, 0xFFFFFFFF, 0xcb7D3307 },
86 { 0xA940, 0xFFFFFFFF, 0x003C0000 },
87 { 0xA944, 0xFFFFFFFF, 0xFFFF0000 },
88 { 0xA948, 0xFFFFFFFF, 0x00220000 },
89 { 0xA94C, 0xFFFFFFFF, 0x43000000 },
90 { 0xA950, 0xFFFFFFFF, 0x00000800 },
91 { 0xA954, 0xFFFFFFFF, 0x00000000 },
92 { 0xA960, 0xFFFFFFFF, 0x00000000 },
93
94 /* SET3 */
95 { 0xaa3c, 0xFFFFFFFF, 0x00000000 },
96 { 0xaa54, 0xFFFFFFFF, 0x00000000 },
97 { 0xaa60, 0xFFFFFFFF, 0x00000000 },
98
99 /* Enable PowerMeter Counters */
100 { 0xA248, 0xFFFFFFFF, 0x00000058 },
101
102 { 0 }
103};
104
105static const struct gt_reg gfx_rc6_registers[] = {
106 { 0xA090, 0xFFFFFFFF, 0x00000000 },
107
108 /* RC1e - RC6/6p - RC6pp Wake Rate Limits */
109 { 0xA09C, 0xFFFFFFFF, 0x00280000 },
110 { 0xA0A8, 0xFFFFFFFF, 0x0001E848 },
111 { 0xA0AC, 0xFFFFFFFF, 0x00000019 },
112
113 /* RC Sleep / RCx Thresholds */
114 { 0xA0B0, 0xFFFFFFFF, 0x00000000 },
115 { 0xA0B8, 0xFFFFFFFF, 0x00000557 },
116
117 { 0 }
118};
119
120static const struct gt_reg gfx_turbo_registers[] = {
121 /* Render/Video/Blitter Idle Max Count */
122 { 0x2054, 0xFFFFFFFF, 0x0000000A },
123 { 0x12054, 0xFFFFFFFF, 0x0000000A },
124 { 0x22054, 0xFFFFFFFF, 0x0000000A },
125
126 /* RP Down Timeout */
127 { 0xA010, 0xFFFFFFFF, 0x000F4240 },
128
129 { 0 }
130};
131
132static const struct gt_reg gfx_turbo_ctl_registers[] = {
133 /* RP Up/Down Threshold */
134 { 0xA02C, 0xFFFFFFFF, 0x0000E8E8 },
135 { 0xA030, 0xFFFFFFFF, 0x0003BD08 },
136
137 /* RP Up/Down EI */
138 { 0xA068, 0xFFFFFFFF, 0x000101D0 },
139 { 0xA06C, 0xFFFFFFFF, 0x00055730 },
140
141 { 0 }
142};
143
144static struct resource *gtt_res = NULL;
145
146static inline unsigned long gtt_read(unsigned long reg)
147{
148 u32 val;
149 val = read32(gtt_res->base + reg);
150 return val;
151
152}
153
154static inline void gtt_write(unsigned long reg, unsigned long data)
155{
156 write32(gtt_res->base + reg, data);
157}
158
159static inline void gtt_rmw(u32 reg, u32 andmask, u32 ormask)
160{
161 u32 val = gtt_read(reg);
162 val &= andmask;
163 val |= ormask;
164 gtt_write(reg, val);
165}
166
167static void gtt_write_regs(const struct gt_reg *gt)
168{
169 for (; gt && gt->reg; gt++)
170 gtt_rmw(gt->reg, gt->andmask, gt->ormask);
171}
172
173#define GFX_POLL_RETRY 10000
174
175static int gtt_poll(u32 reg, u32 mask, u32 value)
176{
177 unsigned try = GFX_POLL_RETRY;
178 u32 data;
179
180 while (try--) {
181 data = gtt_read(reg);
182 if ((data & mask) == value)
183 return 1;
184 udelay(100);
185 }
186
187 printk(BIOS_ERR, "GTT timeout\n");
188 return 0;
189}
190
191static int gfx_poll_power_gate(u32 mask, u32 value)
192{
193 unsigned try = GFX_POLL_RETRY;
194 u32 data;
195
196 while (try--) {
197 data = iosf_punit_read(PUNIT_PWRGT_STATUS);
198 if ((data & mask) == value)
199 return 1;
200 udelay(100);
201 }
202
203 printk(BIOS_ERR, "Power Gate timeout\n");
204 return 0;
205}
206
207/*
208 * Lock Power Context Base Register to point to a 24KB block
209 * of memory in GSM. Power context save data is stored here.
210 */
211static void gfx_lock_pcbase(device_t dev)
212{
213 const u16 gms_size_map[17] = { 0,32,64,96,128,160,192,224,256,
214 288,320,352,384,416,448,480,512 };
215 u32 pcsize = 24 << 10; /* 24KB */
216 u32 wopcmsz = 0x100000; /* PAVP offset */
217 u32 gms, gmsize, pcbase;
218
219 gms = pci_read_config32(dev, GGC) & GGC_GSM_SIZE_MASK;
220 gms >>= 3;
221 if (gms > sizeof(gms_size_map))
222 return;
223 gmsize = gms_size_map[gms];
224
225 /* PcBase = BDSM + GMS Size - WOPCMSZ - PowerContextSize */
226 pcbase = pci_read_config32(dev, GSM_BASE) & 0xfff00000;
227 pcbase += (gmsize-1) * wopcmsz - pcsize;
228 pcbase |= 1; /* Lock */
229
230 gtt_write(0x182120, pcbase);
231}
232
233static void gfx_pm_init(device_t dev)
234{
235 printk(BIOS_INFO, "GFX: Power Management Init\n");
236
237 /*
238 * Allow-Wake render/media wells.
239 * Used by PUNIT as part of S0IX save/restore.
240 */
241 gtt_rmw(0x130090, ~1, 1);
242 if (!gtt_poll(0x130094, 1, 1)) {
243 printk(BIOS_ERR, "gfx_pm_init: Unable to allow-wake\n");
244 return;
245 }
246
247 /* Render Force-Wake */
248 gtt_write(0x1300B0, 0x80008000);
249 if (!gtt_poll(0x1300B4, 0x8000, 0x8000)) {
250 printk(BIOS_ERR, "gfx_pm_init: Unable to force-wake render\n");
251 return;
252 }
253
254 /* Media Force-Wake */
255 gtt_write(0x1300B8, 0x80008000);
256 if (!gtt_poll(0x1300BC, 0x8000, 0x8000)) {
257 printk(BIOS_ERR, "gfx_pm_init: Unable to force-wake media\n");
258 return;
259 };
260
261 /* Workaround - X0:261954/A0:261955 */
262 gtt_rmw(0x182060, ~0xf, 1);
263
264 /* Program GT PowerMeter weights */
265 gtt_write_regs(gfx_powermeter_weights);
266
267 /* Program PUNIT_GPU_EC_VIRUS based on DPTF SDP */
268 /* SDP Profile 4 == 0x11940, others 0xcf08 */
269 iosf_punit_write(PUNIT_GPU_EC_VIRUS, 0xcf08);
270
271 /* GfxPause */
272 gtt_write(0xa000, 0x00071388);
273
274 /* Dynamic EU Control Settings */
275 gtt_write(0xa080, 0x00000004);
276
277 /* Lock ECO Bit Settings */
278 gtt_write(0xa180, 0x80000000);
279
280 /* DOP Clock Gating */
281 gtt_write(0x9424, 0x00000001);
282
283 /* MBCunit will send the VCR (Fuse) writes as NP-W */
284 gtt_rmw(0x907c, 0xfffeffff, 0x00010000);
285
286 /* RC6 Settings */
287 gtt_write_regs(gfx_rc6_registers);
288
289 /* Turbo Settings */
290 gtt_write_regs(gfx_turbo_registers);
291
292 /* Turbo Control Settings */
293 gtt_write_regs(gfx_turbo_ctl_registers);
294
295 /* RP Idle Hysteresis */
296 gtt_write(0xa070, 0x0000000a);
297
298 /* HW RC6 Control Settings */
299 gtt_write(0xa090, 0x11000000);
300
301 /* RP Control */
302 gtt_write(0xa024, 0x00000592);
303
304 /* Enable PM Interrupts */
305 gtt_write(0x44024, 0x03000000);
306 gtt_write(0x4402c, 0x03000076);
307 gtt_write(0xa168, 0x0000007e);
308
309 /* Lock power context base */
310 gfx_lock_pcbase(dev);
311
312 /* Aggressive Clock Gating */
313 gtt_write(0x9400, 0);
314 gtt_write(0x9404, 0);
315 gtt_write(0x9408, 0);
316 gtt_write(0x940c, 0);
317}
318
319static void gfx_pre_vbios_init(device_t dev)
320{
321 /* Display */
322 iosf_punit_write(PUNIT_PWRGT_CONTROL, 0xc0);
323 gfx_poll_power_gate(0xc0, 0xc0);
324
325 /* Tx/Rx Lanes */
326 iosf_punit_write(PUNIT_PWRGT_CONTROL, 0xfff0c0);
327 gfx_poll_power_gate(0xfff0c0, 0xfff0c0);
328
329 /* Common Lane */
330 iosf_punit_write(PUNIT_PWRGT_CONTROL, 0xfffcc0);
331 gfx_poll_power_gate(0xfffcc0, 0xfffcc0);
332
333 /* Ungating Tx only */
334 iosf_punit_write(PUNIT_PWRGT_CONTROL, 0xf00cc0);
335 gfx_poll_power_gate(0xfffcc0, 0xf00cc0);
336
337 /* Ungating Common Lane only */
338 iosf_punit_write(PUNIT_PWRGT_CONTROL, 0xf000c0);
339 gfx_poll_power_gate(0xffffc0, 0xf000c0);
340
341 /* Ungating Display */
342 iosf_punit_write(PUNIT_PWRGT_CONTROL, 0xf00000);
343 gfx_poll_power_gate(0xfffff0, 0xf00000);
344}
345
346static void gfx_post_vbios_init(device_t dev)
347{
348 /* Deassert Render Force-Wake */
349 gtt_write(0x1300B0, 0x80000000);
350 gtt_poll(0x1300B4, 0x8000, 0);
351
352 /* Deassert Media Force-Wake */
353 gtt_write(0x1300B8, 0x80000000);
354 gtt_poll(0x1300BC, 0x8000, 0);
355
356 /* Set Lock bits */
357 pci_write_config32(dev, GGC, pci_read_config32(dev, GGC) | 1);
358 pci_write_config32(dev, GSM_BASE, pci_read_config32(dev, GSM_BASE) | 1);
359 pci_write_config32(dev, GTT_BASE, pci_read_config32(dev, GTT_BASE) | 1);
360}
361
362static void gfx_init(device_t dev)
363{
364 u32 reg32;
365
366 /* Find GTT resource */
367 gtt_res = find_resource(dev, PCI_BASE_ADDRESS_0);
368 if (!gtt_res || !gtt_res->base)
369 return;
370
371 /* GFX needs to be Bus Master */
372 reg32 = pci_read_config32(dev, PCI_COMMAND);
373 reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
374 pci_write_config32(dev, PCI_COMMAND, reg32);
375
376 /* Pre VBIOS Init */
377 gfx_pre_vbios_init(dev);
378 gfx_pm_init(dev);
379
380 /* Run VBIOS */
381 pci_dev_init(dev);
382
383 /* Post VBIOS Init */
384 gfx_post_vbios_init(dev);
385}
386
387static struct device_operations gfx_device_ops = {
388 .read_resources = pci_dev_read_resources,
389 .set_resources = pci_dev_set_resources,
390 .enable_resources = pci_dev_enable_resources,
391 .init = gfx_init,
392 .ops_pci = &soc_pci_ops,
393};
394
395static const struct pci_driver gfx_driver __pci_driver = {
396 .ops = &gfx_device_ops,
397 .vendor = PCI_VENDOR_ID_INTEL,
398 .device = GFX_DEVID,
399};