blob: c7a0e9b94192b20a2d13f966e81a2433f0900701 [file] [log] [blame]
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2011 Chromium OS Authors
5 * Copyright (C) 2013 Vladimir Serbinenko
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <arch/io.h>
22#include <console/console.h>
23#include <delay.h>
24#include <device/device.h>
25#include <device/pci.h>
26#include <device/pci_ids.h>
27#include <string.h>
28#include <device/pci_ops.h>
29#include <cpu/x86/msr.h>
30#include <cpu/x86/mtrr.h>
31
32#include "chip.h"
33#include "nehalem.h"
34
35struct gt_powermeter {
36 u16 reg;
37 u32 value;
38};
39
40static const struct gt_powermeter snb_pm_gt1[] = {
41 {0xa200, 0xcc000000},
42 {0xa204, 0x07000040},
43 {0xa208, 0x0000fe00},
44 {0xa20c, 0x00000000},
45 {0xa210, 0x17000000},
46 {0xa214, 0x00000021},
47 {0xa218, 0x0817fe19},
48 {0xa21c, 0x00000000},
49 {0xa220, 0x00000000},
50 {0xa224, 0xcc000000},
51 {0xa228, 0x07000040},
52 {0xa22c, 0x0000fe00},
53 {0xa230, 0x00000000},
54 {0xa234, 0x17000000},
55 {0xa238, 0x00000021},
56 {0xa23c, 0x0817fe19},
57 {0xa240, 0x00000000},
58 {0xa244, 0x00000000},
59 {0xa248, 0x8000421e},
60 {0}
61};
62
63static const struct gt_powermeter snb_pm_gt2[] = {
64 {0xa200, 0x330000a6},
65 {0xa204, 0x402d0031},
66 {0xa208, 0x00165f83},
67 {0xa20c, 0xf1000000},
68 {0xa210, 0x00000000},
69 {0xa214, 0x00160016},
70 {0xa218, 0x002a002b},
71 {0xa21c, 0x00000000},
72 {0xa220, 0x00000000},
73 {0xa224, 0x330000a6},
74 {0xa228, 0x402d0031},
75 {0xa22c, 0x00165f83},
76 {0xa230, 0xf1000000},
77 {0xa234, 0x00000000},
78 {0xa238, 0x00160016},
79 {0xa23c, 0x002a002b},
80 {0xa240, 0x00000000},
81 {0xa244, 0x00000000},
82 {0xa248, 0x8000421e},
83 {0}
84};
85
86static const struct gt_powermeter ivb_pm_gt1[] = {
87 {0xa800, 0x00000000},
88 {0xa804, 0x00021c00},
89 {0xa808, 0x00000403},
90 {0xa80c, 0x02001700},
91 {0xa810, 0x05000200},
92 {0xa814, 0x00000000},
93 {0xa818, 0x00690500},
94 {0xa81c, 0x0000007f},
95 {0xa820, 0x01002501},
96 {0xa824, 0x00000300},
97 {0xa828, 0x01000331},
98 {0xa82c, 0x0000000c},
99 {0xa830, 0x00010016},
100 {0xa834, 0x01100101},
101 {0xa838, 0x00010103},
102 {0xa83c, 0x00041300},
103 {0xa840, 0x00000b30},
104 {0xa844, 0x00000000},
105 {0xa848, 0x7f000000},
106 {0xa84c, 0x05000008},
107 {0xa850, 0x00000001},
108 {0xa854, 0x00000004},
109 {0xa858, 0x00000007},
110 {0xa85c, 0x00000000},
111 {0xa860, 0x00010000},
112 {0xa248, 0x0000221e},
113 {0xa900, 0x00000000},
114 {0xa904, 0x00001c00},
115 {0xa908, 0x00000000},
116 {0xa90c, 0x06000000},
117 {0xa910, 0x09000200},
118 {0xa914, 0x00000000},
119 {0xa918, 0x00590000},
120 {0xa91c, 0x00000000},
121 {0xa920, 0x04002501},
122 {0xa924, 0x00000100},
123 {0xa928, 0x03000410},
124 {0xa92c, 0x00000000},
125 {0xa930, 0x00020000},
126 {0xa934, 0x02070106},
127 {0xa938, 0x00010100},
128 {0xa93c, 0x00401c00},
129 {0xa940, 0x00000000},
130 {0xa944, 0x00000000},
131 {0xa948, 0x10000e00},
132 {0xa94c, 0x02000004},
133 {0xa950, 0x00000001},
134 {0xa954, 0x00000004},
135 {0xa960, 0x00060000},
136 {0xaa3c, 0x00001c00},
137 {0xaa54, 0x00000004},
138 {0xaa60, 0x00060000},
139 {0}
140};
141
142static const struct gt_powermeter ivb_pm_gt2[] = {
143 {0xa800, 0x10000000},
144 {0xa804, 0x00033800},
145 {0xa808, 0x00000902},
146 {0xa80c, 0x0c002f00},
147 {0xa810, 0x12000400},
148 {0xa814, 0x00000000},
149 {0xa818, 0x00d20800},
150 {0xa81c, 0x00000002},
151 {0xa820, 0x03004b02},
152 {0xa824, 0x00000600},
153 {0xa828, 0x07000773},
154 {0xa82c, 0x00000000},
155 {0xa830, 0x00010032},
156 {0xa834, 0x1520040d},
157 {0xa838, 0x00020105},
158 {0xa83c, 0x00083700},
159 {0xa840, 0x0000151d},
160 {0xa844, 0x00000000},
161 {0xa848, 0x20001b00},
162 {0xa84c, 0x0a000010},
163 {0xa850, 0x00000000},
164 {0xa854, 0x00000008},
165 {0xa858, 0x00000008},
166 {0xa85c, 0x00000000},
167 {0xa860, 0x00020000},
168 {0xa248, 0x0000221e},
169 {0xa900, 0x00000000},
170 {0xa904, 0x00003500},
171 {0xa908, 0x00000000},
172 {0xa90c, 0x0c000000},
173 {0xa910, 0x12000500},
174 {0xa914, 0x00000000},
175 {0xa918, 0x00b20000},
176 {0xa91c, 0x00000000},
177 {0xa920, 0x08004b02},
178 {0xa924, 0x00000200},
179 {0xa928, 0x07000820},
180 {0xa92c, 0x00000000},
181 {0xa930, 0x00030000},
182 {0xa934, 0x050f020d},
183 {0xa938, 0x00020300},
184 {0xa93c, 0x00903900},
185 {0xa940, 0x00000000},
186 {0xa944, 0x00000000},
187 {0xa948, 0x20001b00},
188 {0xa94c, 0x0a000010},
189 {0xa950, 0x00000000},
190 {0xa954, 0x00000008},
191 {0xa960, 0x00110000},
192 {0xaa3c, 0x00003900},
193 {0xaa54, 0x00000008},
194 {0xaa60, 0x00110000},
195 {0}
196};
197
198static const struct gt_powermeter ivb_pm_gt2_17w[] = {
199 {0xa800, 0x20000000},
200 {0xa804, 0x000e3800},
201 {0xa808, 0x00000806},
202 {0xa80c, 0x0c002f00},
203 {0xa810, 0x0c000800},
204 {0xa814, 0x00000000},
205 {0xa818, 0x00d20d00},
206 {0xa81c, 0x000000ff},
207 {0xa820, 0x03004b02},
208 {0xa824, 0x00000600},
209 {0xa828, 0x07000773},
210 {0xa82c, 0x00000000},
211 {0xa830, 0x00020032},
212 {0xa834, 0x1520040d},
213 {0xa838, 0x00020105},
214 {0xa83c, 0x00083700},
215 {0xa840, 0x000016ff},
216 {0xa844, 0x00000000},
217 {0xa848, 0xff000000},
218 {0xa84c, 0x0a000010},
219 {0xa850, 0x00000002},
220 {0xa854, 0x00000008},
221 {0xa858, 0x0000000f},
222 {0xa85c, 0x00000000},
223 {0xa860, 0x00020000},
224 {0xa248, 0x0000221e},
225 {0xa900, 0x00000000},
226 {0xa904, 0x00003800},
227 {0xa908, 0x00000000},
228 {0xa90c, 0x0c000000},
229 {0xa910, 0x12000800},
230 {0xa914, 0x00000000},
231 {0xa918, 0x00b20000},
232 {0xa91c, 0x00000000},
233 {0xa920, 0x08004b02},
234 {0xa924, 0x00000300},
235 {0xa928, 0x01000820},
236 {0xa92c, 0x00000000},
237 {0xa930, 0x00030000},
238 {0xa934, 0x15150406},
239 {0xa938, 0x00020300},
240 {0xa93c, 0x00903900},
241 {0xa940, 0x00000000},
242 {0xa944, 0x00000000},
243 {0xa948, 0x20001b00},
244 {0xa94c, 0x0a000010},
245 {0xa950, 0x00000000},
246 {0xa954, 0x00000008},
247 {0xa960, 0x00110000},
248 {0xaa3c, 0x00003900},
249 {0xaa54, 0x00000008},
250 {0xaa60, 0x00110000},
251 {0}
252};
253
254static const struct gt_powermeter ivb_pm_gt2_35w[] = {
255 {0xa800, 0x00000000},
256 {0xa804, 0x00030400},
257 {0xa808, 0x00000806},
258 {0xa80c, 0x0c002f00},
259 {0xa810, 0x0c000300},
260 {0xa814, 0x00000000},
261 {0xa818, 0x00d20d00},
262 {0xa81c, 0x000000ff},
263 {0xa820, 0x03004b02},
264 {0xa824, 0x00000600},
265 {0xa828, 0x07000773},
266 {0xa82c, 0x00000000},
267 {0xa830, 0x00020032},
268 {0xa834, 0x1520040d},
269 {0xa838, 0x00020105},
270 {0xa83c, 0x00083700},
271 {0xa840, 0x000016ff},
272 {0xa844, 0x00000000},
273 {0xa848, 0xff000000},
274 {0xa84c, 0x0a000010},
275 {0xa850, 0x00000001},
276 {0xa854, 0x00000008},
277 {0xa858, 0x00000008},
278 {0xa85c, 0x00000000},
279 {0xa860, 0x00020000},
280 {0xa248, 0x0000221e},
281 {0xa900, 0x00000000},
282 {0xa904, 0x00003800},
283 {0xa908, 0x00000000},
284 {0xa90c, 0x0c000000},
285 {0xa910, 0x12000800},
286 {0xa914, 0x00000000},
287 {0xa918, 0x00b20000},
288 {0xa91c, 0x00000000},
289 {0xa920, 0x08004b02},
290 {0xa924, 0x00000300},
291 {0xa928, 0x01000820},
292 {0xa92c, 0x00000000},
293 {0xa930, 0x00030000},
294 {0xa934, 0x15150406},
295 {0xa938, 0x00020300},
296 {0xa93c, 0x00903900},
297 {0xa940, 0x00000000},
298 {0xa944, 0x00000000},
299 {0xa948, 0x20001b00},
300 {0xa94c, 0x0a000010},
301 {0xa950, 0x00000000},
302 {0xa954, 0x00000008},
303 {0xa960, 0x00110000},
304 {0xaa3c, 0x00003900},
305 {0xaa54, 0x00000008},
306 {0xaa60, 0x00110000},
307 {0}
308};
309
310/* some vga option roms are used for several chipsets but they only have one
311 * PCI ID in their header. If we encounter such an option rom, we need to do
312 * the mapping ourselfes
313 */
314
315u32 map_oprom_vendev(u32 vendev)
316{
317 u32 new_vendev = vendev;
318
319 /* none curently. */
320
321 return new_vendev;
322}
323
324static struct resource *gtt_res = NULL;
325
326static inline u32 gtt_read(u32 reg)
327{
328 return read32(gtt_res->base + reg);
329}
330
331static inline void gtt_write(u32 reg, u32 data)
332{
333 write32(gtt_res->base + reg, data);
334}
335
336static inline void gtt_write_powermeter(const struct gt_powermeter *pm)
337{
338 for (; pm && pm->reg; pm++)
339 gtt_write(pm->reg, pm->value);
340}
341
342#define GTT_RETRY 1000
343static int gtt_poll(u32 reg, u32 mask, u32 value)
344{
345 unsigned try = GTT_RETRY;
346 u32 data;
347
348 while (try--) {
349 data = gtt_read(reg);
350 if ((data & mask) == value)
351 return 1;
352 udelay(10);
353 }
354
355 printk(BIOS_ERR, "GT init timeout\n");
356 return 0;
357}
358
359static void gma_pm_init_pre_vbios(struct device *dev)
360{
361 u32 reg32;
362
363 printk(BIOS_DEBUG, "GT Power Management Init\n");
364
365 gtt_res = find_resource(dev, PCI_BASE_ADDRESS_0);
366 if (!gtt_res || !gtt_res->base)
367 return;
368
369 if (bridge_silicon_revision() < IVB_STEP_C0) {
370 /* 1: Enable force wake */
371 gtt_write(0xa18c, 0x00000001);
372 gtt_poll(0x130090, (1 << 0), (1 << 0));
373 } else {
374 gtt_write(0xa180, 1 << 5);
375 gtt_write(0xa188, 0xffff0001);
376 gtt_poll(0x130040, (1 << 0), (1 << 0));
377 }
378
379 if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_SNB) {
380 /* 1d: Set GTT+0x42004 [15:14]=11 (SnB C1+) */
381 reg32 = gtt_read(0x42004);
382 reg32 |= (1 << 14) | (1 << 15);
383 gtt_write(0x42004, reg32);
384 }
385
386 if (bridge_silicon_revision() >= IVB_STEP_A0) {
387 /* Display Reset Acknowledge Settings */
388 reg32 = gtt_read(0x45010);
389 reg32 |= (1 << 1) | (1 << 0);
390 gtt_write(0x45010, reg32);
391 }
392
393 /* 2: Get GT SKU from GTT+0x911c[13] */
394 reg32 = gtt_read(0x911c);
395 if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_SNB) {
396 if (reg32 & (1 << 13)) {
397 printk(BIOS_DEBUG, "SNB GT1 Power Meter Weights\n");
398 gtt_write_powermeter(snb_pm_gt1);
399 } else {
400 printk(BIOS_DEBUG, "SNB GT2 Power Meter Weights\n");
401 gtt_write_powermeter(snb_pm_gt2);
402 }
403 } else {
404 u32 unit = MCHBAR32(0x5938) & 0xf;
405
406 if (reg32 & (1 << 13)) {
407 /* GT1 SKU */
408 printk(BIOS_DEBUG, "IVB GT1 Power Meter Weights\n");
409 gtt_write_powermeter(ivb_pm_gt1);
410 } else {
411 /* GT2 SKU */
412 u32 tdp = MCHBAR32(0x5930) & 0x7fff;
413 tdp /= (1 << unit);
414
415 if (tdp <= 17) {
416 /* <=17W ULV */
417 printk(BIOS_DEBUG, "IVB GT2 17W "
418 "Power Meter Weights\n");
419 gtt_write_powermeter(ivb_pm_gt2_17w);
420 } else if ((tdp >= 25) && (tdp <= 35)) {
421 /* 25W-35W */
422 printk(BIOS_DEBUG, "IVB GT2 25W-35W "
423 "Power Meter Weights\n");
424 gtt_write_powermeter(ivb_pm_gt2_35w);
425 } else {
426 /* All others */
427 printk(BIOS_DEBUG, "IVB GT2 35W "
428 "Power Meter Weights\n");
429 gtt_write_powermeter(ivb_pm_gt2_35w);
430 }
431 }
432 }
433
434 /* 3: Gear ratio map */
435 gtt_write(0xa004, 0x00000010);
436
437 /* 4: GFXPAUSE */
438 gtt_write(0xa000, 0x00070020);
439
440 /* 5: Dynamic EU trip control */
441 gtt_write(0xa080, 0x00000004);
442
443 /* 6: ECO bits */
444 reg32 = gtt_read(0xa180);
445 reg32 |= (1 << 26) | (1 << 31);
446 /* (bit 20=1 for SNB step D1+ / IVB A0+) */
447 if (bridge_silicon_revision() >= SNB_STEP_D1)
448 reg32 |= (1 << 20);
449 gtt_write(0xa180, reg32);
450
451 /* 6a: for SnB step D2+ only */
452 if (((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_SNB) &&
453 (bridge_silicon_revision() >= SNB_STEP_D2)) {
454 reg32 = gtt_read(0x9400);
455 reg32 |= (1 << 7);
456 gtt_write(0x9400, reg32);
457
458 reg32 = gtt_read(0x941c);
459 reg32 &= 0xf;
460 reg32 |= (1 << 1);
461 gtt_write(0x941c, reg32);
462 gtt_poll(0x941c, (1 << 1), (0 << 1));
463 }
464
465 if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_IVB) {
466 reg32 = gtt_read(0x907c);
467 reg32 |= (1 << 16);
468 gtt_write(0x907c, reg32);
469
470 /* 6b: Clocking reset controls */
471 gtt_write(0x9424, 0x00000001);
472 } else {
473 /* 6b: Clocking reset controls */
474 gtt_write(0x9424, 0x00000000);
475 }
476
477 /* 7 */
478 if (gtt_poll(0x138124, (1 << 31), (0 << 31))) {
479 gtt_write(0x138128, 0x00000029); /* Mailbox Data */
480 gtt_write(0x138124, 0x80000004); /* Mailbox Cmd for RC6 VID */
481 if (gtt_poll(0x138124, (1 << 31), (0 << 31)))
482 gtt_write(0x138124, 0x8000000a);
483 gtt_poll(0x138124, (1 << 31), (0 << 31));
484 }
485
486 /* 8 */
487 gtt_write(0xa090, 0x00000000); /* RC Control */
488 gtt_write(0xa098, 0x03e80000); /* RC1e Wake Rate Limit */
489 gtt_write(0xa09c, 0x0028001e); /* RC6/6p Wake Rate Limit */
490 gtt_write(0xa0a0, 0x0000001e); /* RC6pp Wake Rate Limit */
491 gtt_write(0xa0a8, 0x0001e848); /* RC Evaluation Interval */
492 gtt_write(0xa0ac, 0x00000019); /* RC Idle Hysteresis */
493
494 /* 9 */
495 gtt_write(0x2054, 0x0000000a); /* Render Idle Max Count */
496 gtt_write(0x12054, 0x0000000a); /* Video Idle Max Count */
497 gtt_write(0x22054, 0x0000000a); /* Blitter Idle Max Count */
498
499 /* 10 */
500 gtt_write(0xa0b0, 0x00000000); /* Unblock Ack to Busy */
501 gtt_write(0xa0b4, 0x000003e8); /* RC1e Threshold */
502 gtt_write(0xa0b8, 0x0000c350); /* RC6 Threshold */
503 gtt_write(0xa0bc, 0x000186a0); /* RC6p Threshold */
504 gtt_write(0xa0c0, 0x0000fa00); /* RC6pp Threshold */
505
506 /* 11 */
507 gtt_write(0xa010, 0x000f4240); /* RP Down Timeout */
508 gtt_write(0xa014, 0x12060000); /* RP Interrupt Limits */
509 gtt_write(0xa02c, 0x00015f90); /* RP Up Threshold */
510 gtt_write(0xa030, 0x000186a0); /* RP Down Threshold */
511 gtt_write(0xa068, 0x000186a0); /* RP Up EI */
512 gtt_write(0xa06c, 0x000493e0); /* RP Down EI */
513 gtt_write(0xa070, 0x0000000a); /* RP Idle Hysteresis */
514
515 /* 11a: Enable Render Standby (RC6) */
516 if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_IVB) {
517 /*
518 * IvyBridge should also support DeepRenderStandby.
519 *
520 * Unfortunately it does not work reliably on all SKUs so
521 * disable it here and it can be enabled by the kernel.
522 */
523 gtt_write(0xa090, 0x88040000); /* HW RC Control */
524 } else {
525 gtt_write(0xa090, 0x88040000); /* HW RC Control */
526 }
527
528 /* 12: Normal Frequency Request */
529 /* RPNFREQ_VAL comes from MCHBAR 0x5998 23:16 (8 bits!? use 7) */
530 reg32 = MCHBAR32(0x5998);
531 reg32 >>= 16;
532 reg32 &= 0xef;
533 reg32 <<= 25;
534 gtt_write(0xa008, reg32);
535
536 /* 13: RP Control */
537 gtt_write(0xa024, 0x00000592);
538
539 /* 14: Enable PM Interrupts */
540 gtt_write(0x4402c, 0x03000076);
541
542 /* Clear 0x6c024 [8:6] */
543 reg32 = gtt_read(0x6c024);
544 reg32 &= ~0x000001c0;
545 gtt_write(0x6c024, reg32);
546}
547
548#include <pc80/vga.h>
549#include <pc80/vga_io.h>
550
Vladimir Serbinenko503e4fe2014-01-03 04:27:39 +0100551#if CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +0100552static void fake_vbios(void)
553{
554#include "fake_vbios.c"
555}
Vladimir Serbinenko503e4fe2014-01-03 04:27:39 +0100556#endif
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +0100557
558static void gma_pm_init_post_vbios(struct device *dev)
559{
560 struct northbridge_intel_nehalem_config *conf = dev->chip_info;
561 u32 reg32;
562
563 printk(BIOS_DEBUG, "GT Power Management Init (post VBIOS)\n");
564
565 /* 15: Deassert Force Wake */
566 if (bridge_silicon_revision() < IVB_STEP_C0) {
567 gtt_write(0xa18c, gtt_read(0xa18c) & ~1);
568 gtt_poll(0x130090, (1 << 0), (0 << 0));
569 } else {
570 gtt_write(0xa188, 0x1fffe);
571 if (gtt_poll(0x130040, (1 << 0), (0 << 0)))
572 gtt_write(0xa188, gtt_read(0xa188) | 1);
573 }
574
575 /* 16: SW RC Control */
576 gtt_write(0xa094, 0x00060000);
577
578 /* Setup Digital Port Hotplug */
579 reg32 = gtt_read(0xc4030);
580 if (!reg32) {
581 reg32 = (conf->gpu_dp_b_hotplug & 0x7) << 2;
582 reg32 |= (conf->gpu_dp_c_hotplug & 0x7) << 10;
583 reg32 |= (conf->gpu_dp_d_hotplug & 0x7) << 18;
584 gtt_write(0xc4030, reg32);
585 }
586
587 /* Setup Panel Power On Delays */
588 reg32 = gtt_read(0xc7208);
589 if (!reg32) {
590 reg32 = (conf->gpu_panel_port_select & 0x3) << 30;
591 reg32 |= (conf->gpu_panel_power_up_delay & 0x1fff) << 16;
592 reg32 |= (conf->gpu_panel_power_backlight_on_delay & 0x1fff);
593 gtt_write(0xc7208, reg32);
594 }
595
596 /* Setup Panel Power Off Delays */
597 reg32 = gtt_read(0xc720c);
598 if (!reg32) {
599 reg32 = (conf->gpu_panel_power_down_delay & 0x1fff) << 16;
600 reg32 |= (conf->gpu_panel_power_backlight_off_delay & 0x1fff);
601 gtt_write(0xc720c, reg32);
602 }
603
604 /* Setup Panel Power Cycle Delay */
605 if (conf->gpu_panel_power_cycle_delay) {
606 reg32 = gtt_read(0xc7210);
607 reg32 &= ~0xff;
608 reg32 |= conf->gpu_panel_power_cycle_delay & 0xff;
609 gtt_write(0xc7210, reg32);
610 }
611
612 /* Enable Backlight if needed */
613 if (conf->gpu_cpu_backlight) {
614 gtt_write(0x48250, (1 << 31));
615 gtt_write(0x48254, conf->gpu_cpu_backlight);
616 }
617 if (conf->gpu_pch_backlight) {
618 gtt_write(0xc8250, (1 << 31));
619 gtt_write(0xc8254, conf->gpu_pch_backlight);
620 }
621}
622
623static void gma_func0_init(struct device *dev)
624{
625 u32 reg32;
626
627 /* IGD needs to be Bus Master */
628 reg32 = pci_read_config32(dev, PCI_COMMAND);
629 reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
630 pci_write_config32(dev, PCI_COMMAND, reg32);
631
632 /* Init graphics power management */
633 gma_pm_init_pre_vbios(dev);
634
635#if !CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT
636 /* PCI Init, will run VBIOS */
637 pci_dev_init(dev);
638#else
639 printk(BIOS_SPEW, "Initializing VGA without OPROM.\n");
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +0100640 fake_vbios();
Vladimir Serbinenko503e4fe2014-01-03 04:27:39 +0100641#endif
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +0100642
643 /* Linux relies on VBT for panel info. */
644 if (read16(0xc0000) != 0xaa55) {
645 optionrom_header_t *oh = (void *)0xc0000;
646 optionrom_pcir_t *pcir;
647 int sz;
648
649 memset(oh->reserved, 0, 8192);
650
651 sz = (0x80 + sizeof(fake_vbt) + 511) / 512;
652 oh->signature = 0xaa55;
653 oh->size = sz;
654 oh->pcir_offset = 0x40;
655 oh->vbt_offset = 0x80;
656
657 pcir = (void *)0xc0040;
658 pcir->signature = 0x52494350; // PCIR
659 pcir->vendor = dev->vendor;
660 pcir->device = dev->device;
661 pcir->length = sizeof(*pcir);
662 pcir->revision = dev->class;
663 pcir->classcode[0] = dev->class >> 8;
664 pcir->classcode[1] = dev->class >> 16;
665 pcir->classcode[2] = dev->class >> 24;
666 pcir->imagelength = sz;
667 pcir->indicator = 0x80;
668
669 memcpy((void *)0xc0080, fake_vbt, sizeof(fake_vbt));
670 }
671
672
673 /* Post VBIOS init */
674 gma_pm_init_post_vbios(dev);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +0100675}
676
677static void gma_set_subsystem(device_t dev, unsigned vendor, unsigned device)
678{
679 if (!vendor || !device) {
680 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
681 pci_read_config32(dev, PCI_VENDOR_ID));
682 } else {
683 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
684 ((device & 0xffff) << 16) | (vendor &
685 0xffff));
686 }
687}
688
689static void gma_read_resources(struct device *dev)
690{
691 pci_dev_read_resources(dev);
692
693 struct resource *res;
694
695 /* Set the graphics memory to write combining. */
696 res = find_resource(dev, PCI_BASE_ADDRESS_2);
697 if (res == NULL) {
698 printk(BIOS_DEBUG, "gma: memory resource not found.\n");
699 return;
700 }
701 res->flags |= IORESOURCE_RESERVE | IORESOURCE_FIXED | IORESOURCE_ASSIGNED;
702 pci_write_config32(dev, PCI_BASE_ADDRESS_2,
703 0xd0000001);
704 pci_write_config32(dev, PCI_BASE_ADDRESS_2 + 4,
705 0);
706#if CONFIG_MARK_GRAPHICS_MEM_WRCOMB
707 res->flags |= IORESOURCE_WRCOMB;
708#endif
709 res->base = (resource_t) 0xd0000000;
710 res->size = (resource_t) 0x10000000;
711}
712
713static struct pci_operations gma_pci_ops = {
714 .set_subsystem = gma_set_subsystem,
715};
716
717static struct device_operations gma_func0_ops = {
718 .read_resources = gma_read_resources,
719 .set_resources = pci_dev_set_resources,
720 .enable_resources = pci_dev_enable_resources,
721 .init = gma_func0_init,
722 .scan_bus = 0,
723 .enable = 0,
724 .ops_pci = &gma_pci_ops,
725};
726
727static const unsigned short pci_device_ids[] =
728 { 0x0046, 0x0102, 0x0106, 0x010a, 0x0112,
729 0x0116, 0x0122, 0x0126, 0x0156,
730 0x0166,
731 0
732};
733
734static const struct pci_driver gma __pci_driver = {
735 .ops = &gma_func0_ops,
736 .vendor = PCI_VENDOR_ID_INTEL,
737 .devices = pci_device_ids,
738};