1 /* 2 * Copyright (C) 2016 Google, Inc 3 * 4 * SPDX-License-Identifier: GPL-2.0 5 */ 6 7 #include <common.h> 8 #include <bios_emul.h> 9 #include <dm.h> 10 #include <errno.h> 11 #include <fdtdec.h> 12 #include <pci_rom.h> 13 #include <vbe.h> 14 #include <asm/intel_regs.h> 15 #include <asm/io.h> 16 #include <asm/mtrr.h> 17 #include <asm/pci.h> 18 #include <asm/arch/pch.h> 19 #include <asm/arch/sandybridge.h> 20 21 struct gt_powermeter { 22 u16 reg; 23 u32 value; 24 }; 25 26 /* These are magic values - unfortunately the meaning is unknown */ 27 static const struct gt_powermeter snb_pm_gt1[] = { 28 { 0xa200, 0xcc000000 }, 29 { 0xa204, 0x07000040 }, 30 { 0xa208, 0x0000fe00 }, 31 { 0xa20c, 0x00000000 }, 32 { 0xa210, 0x17000000 }, 33 { 0xa214, 0x00000021 }, 34 { 0xa218, 0x0817fe19 }, 35 { 0xa21c, 0x00000000 }, 36 { 0xa220, 0x00000000 }, 37 { 0xa224, 0xcc000000 }, 38 { 0xa228, 0x07000040 }, 39 { 0xa22c, 0x0000fe00 }, 40 { 0xa230, 0x00000000 }, 41 { 0xa234, 0x17000000 }, 42 { 0xa238, 0x00000021 }, 43 { 0xa23c, 0x0817fe19 }, 44 { 0xa240, 0x00000000 }, 45 { 0xa244, 0x00000000 }, 46 { 0xa248, 0x8000421e }, 47 { 0 } 48 }; 49 50 static const struct gt_powermeter snb_pm_gt2[] = { 51 { 0xa200, 0x330000a6 }, 52 { 0xa204, 0x402d0031 }, 53 { 0xa208, 0x00165f83 }, 54 { 0xa20c, 0xf1000000 }, 55 { 0xa210, 0x00000000 }, 56 { 0xa214, 0x00160016 }, 57 { 0xa218, 0x002a002b }, 58 { 0xa21c, 0x00000000 }, 59 { 0xa220, 0x00000000 }, 60 { 0xa224, 0x330000a6 }, 61 { 0xa228, 0x402d0031 }, 62 { 0xa22c, 0x00165f83 }, 63 { 0xa230, 0xf1000000 }, 64 { 0xa234, 0x00000000 }, 65 { 0xa238, 0x00160016 }, 66 { 0xa23c, 0x002a002b }, 67 { 0xa240, 0x00000000 }, 68 { 0xa244, 0x00000000 }, 69 { 0xa248, 0x8000421e }, 70 { 0 } 71 }; 72 73 static const struct gt_powermeter ivb_pm_gt1[] = { 74 { 0xa800, 0x00000000 }, 75 { 0xa804, 0x00021c00 }, 76 { 0xa808, 0x00000403 }, 77 { 0xa80c, 0x02001700 }, 78 { 0xa810, 0x05000200 }, 79 { 0xa814, 0x00000000 }, 80 { 0xa818, 0x00690500 }, 81 { 0xa81c, 0x0000007f }, 82 { 0xa820, 0x01002501 }, 83 { 0xa824, 0x00000300 }, 84 { 0xa828, 0x01000331 }, 85 { 0xa82c, 0x0000000c }, 86 { 0xa830, 0x00010016 }, 87 { 0xa834, 0x01100101 }, 88 { 0xa838, 0x00010103 }, 89 { 0xa83c, 0x00041300 }, 90 { 0xa840, 0x00000b30 }, 91 { 0xa844, 0x00000000 }, 92 { 0xa848, 0x7f000000 }, 93 { 0xa84c, 0x05000008 }, 94 { 0xa850, 0x00000001 }, 95 { 0xa854, 0x00000004 }, 96 { 0xa858, 0x00000007 }, 97 { 0xa85c, 0x00000000 }, 98 { 0xa860, 0x00010000 }, 99 { 0xa248, 0x0000221e }, 100 { 0xa900, 0x00000000 }, 101 { 0xa904, 0x00001c00 }, 102 { 0xa908, 0x00000000 }, 103 { 0xa90c, 0x06000000 }, 104 { 0xa910, 0x09000200 }, 105 { 0xa914, 0x00000000 }, 106 { 0xa918, 0x00590000 }, 107 { 0xa91c, 0x00000000 }, 108 { 0xa920, 0x04002501 }, 109 { 0xa924, 0x00000100 }, 110 { 0xa928, 0x03000410 }, 111 { 0xa92c, 0x00000000 }, 112 { 0xa930, 0x00020000 }, 113 { 0xa934, 0x02070106 }, 114 { 0xa938, 0x00010100 }, 115 { 0xa93c, 0x00401c00 }, 116 { 0xa940, 0x00000000 }, 117 { 0xa944, 0x00000000 }, 118 { 0xa948, 0x10000e00 }, 119 { 0xa94c, 0x02000004 }, 120 { 0xa950, 0x00000001 }, 121 { 0xa954, 0x00000004 }, 122 { 0xa960, 0x00060000 }, 123 { 0xaa3c, 0x00001c00 }, 124 { 0xaa54, 0x00000004 }, 125 { 0xaa60, 0x00060000 }, 126 { 0 } 127 }; 128 129 static const struct gt_powermeter ivb_pm_gt2[] = { 130 { 0xa800, 0x10000000 }, 131 { 0xa804, 0x00033800 }, 132 { 0xa808, 0x00000902 }, 133 { 0xa80c, 0x0c002f00 }, 134 { 0xa810, 0x12000400 }, 135 { 0xa814, 0x00000000 }, 136 { 0xa818, 0x00d20800 }, 137 { 0xa81c, 0x00000002 }, 138 { 0xa820, 0x03004b02 }, 139 { 0xa824, 0x00000600 }, 140 { 0xa828, 0x07000773 }, 141 { 0xa82c, 0x00000000 }, 142 { 0xa830, 0x00010032 }, 143 { 0xa834, 0x1520040d }, 144 { 0xa838, 0x00020105 }, 145 { 0xa83c, 0x00083700 }, 146 { 0xa840, 0x0000151d }, 147 { 0xa844, 0x00000000 }, 148 { 0xa848, 0x20001b00 }, 149 { 0xa84c, 0x0a000010 }, 150 { 0xa850, 0x00000000 }, 151 { 0xa854, 0x00000008 }, 152 { 0xa858, 0x00000008 }, 153 { 0xa85c, 0x00000000 }, 154 { 0xa860, 0x00020000 }, 155 { 0xa248, 0x0000221e }, 156 { 0xa900, 0x00000000 }, 157 { 0xa904, 0x00003500 }, 158 { 0xa908, 0x00000000 }, 159 { 0xa90c, 0x0c000000 }, 160 { 0xa910, 0x12000500 }, 161 { 0xa914, 0x00000000 }, 162 { 0xa918, 0x00b20000 }, 163 { 0xa91c, 0x00000000 }, 164 { 0xa920, 0x08004b02 }, 165 { 0xa924, 0x00000200 }, 166 { 0xa928, 0x07000820 }, 167 { 0xa92c, 0x00000000 }, 168 { 0xa930, 0x00030000 }, 169 { 0xa934, 0x050f020d }, 170 { 0xa938, 0x00020300 }, 171 { 0xa93c, 0x00903900 }, 172 { 0xa940, 0x00000000 }, 173 { 0xa944, 0x00000000 }, 174 { 0xa948, 0x20001b00 }, 175 { 0xa94c, 0x0a000010 }, 176 { 0xa950, 0x00000000 }, 177 { 0xa954, 0x00000008 }, 178 { 0xa960, 0x00110000 }, 179 { 0xaa3c, 0x00003900 }, 180 { 0xaa54, 0x00000008 }, 181 { 0xaa60, 0x00110000 }, 182 { 0 } 183 }; 184 185 static const struct gt_powermeter ivb_pm_gt2_17w[] = { 186 { 0xa800, 0x20000000 }, 187 { 0xa804, 0x000e3800 }, 188 { 0xa808, 0x00000806 }, 189 { 0xa80c, 0x0c002f00 }, 190 { 0xa810, 0x0c000800 }, 191 { 0xa814, 0x00000000 }, 192 { 0xa818, 0x00d20d00 }, 193 { 0xa81c, 0x000000ff }, 194 { 0xa820, 0x03004b02 }, 195 { 0xa824, 0x00000600 }, 196 { 0xa828, 0x07000773 }, 197 { 0xa82c, 0x00000000 }, 198 { 0xa830, 0x00020032 }, 199 { 0xa834, 0x1520040d }, 200 { 0xa838, 0x00020105 }, 201 { 0xa83c, 0x00083700 }, 202 { 0xa840, 0x000016ff }, 203 { 0xa844, 0x00000000 }, 204 { 0xa848, 0xff000000 }, 205 { 0xa84c, 0x0a000010 }, 206 { 0xa850, 0x00000002 }, 207 { 0xa854, 0x00000008 }, 208 { 0xa858, 0x0000000f }, 209 { 0xa85c, 0x00000000 }, 210 { 0xa860, 0x00020000 }, 211 { 0xa248, 0x0000221e }, 212 { 0xa900, 0x00000000 }, 213 { 0xa904, 0x00003800 }, 214 { 0xa908, 0x00000000 }, 215 { 0xa90c, 0x0c000000 }, 216 { 0xa910, 0x12000800 }, 217 { 0xa914, 0x00000000 }, 218 { 0xa918, 0x00b20000 }, 219 { 0xa91c, 0x00000000 }, 220 { 0xa920, 0x08004b02 }, 221 { 0xa924, 0x00000300 }, 222 { 0xa928, 0x01000820 }, 223 { 0xa92c, 0x00000000 }, 224 { 0xa930, 0x00030000 }, 225 { 0xa934, 0x15150406 }, 226 { 0xa938, 0x00020300 }, 227 { 0xa93c, 0x00903900 }, 228 { 0xa940, 0x00000000 }, 229 { 0xa944, 0x00000000 }, 230 { 0xa948, 0x20001b00 }, 231 { 0xa94c, 0x0a000010 }, 232 { 0xa950, 0x00000000 }, 233 { 0xa954, 0x00000008 }, 234 { 0xa960, 0x00110000 }, 235 { 0xaa3c, 0x00003900 }, 236 { 0xaa54, 0x00000008 }, 237 { 0xaa60, 0x00110000 }, 238 { 0 } 239 }; 240 241 static const struct gt_powermeter ivb_pm_gt2_35w[] = { 242 { 0xa800, 0x00000000 }, 243 { 0xa804, 0x00030400 }, 244 { 0xa808, 0x00000806 }, 245 { 0xa80c, 0x0c002f00 }, 246 { 0xa810, 0x0c000300 }, 247 { 0xa814, 0x00000000 }, 248 { 0xa818, 0x00d20d00 }, 249 { 0xa81c, 0x000000ff }, 250 { 0xa820, 0x03004b02 }, 251 { 0xa824, 0x00000600 }, 252 { 0xa828, 0x07000773 }, 253 { 0xa82c, 0x00000000 }, 254 { 0xa830, 0x00020032 }, 255 { 0xa834, 0x1520040d }, 256 { 0xa838, 0x00020105 }, 257 { 0xa83c, 0x00083700 }, 258 { 0xa840, 0x000016ff }, 259 { 0xa844, 0x00000000 }, 260 { 0xa848, 0xff000000 }, 261 { 0xa84c, 0x0a000010 }, 262 { 0xa850, 0x00000001 }, 263 { 0xa854, 0x00000008 }, 264 { 0xa858, 0x00000008 }, 265 { 0xa85c, 0x00000000 }, 266 { 0xa860, 0x00020000 }, 267 { 0xa248, 0x0000221e }, 268 { 0xa900, 0x00000000 }, 269 { 0xa904, 0x00003800 }, 270 { 0xa908, 0x00000000 }, 271 { 0xa90c, 0x0c000000 }, 272 { 0xa910, 0x12000800 }, 273 { 0xa914, 0x00000000 }, 274 { 0xa918, 0x00b20000 }, 275 { 0xa91c, 0x00000000 }, 276 { 0xa920, 0x08004b02 }, 277 { 0xa924, 0x00000300 }, 278 { 0xa928, 0x01000820 }, 279 { 0xa92c, 0x00000000 }, 280 { 0xa930, 0x00030000 }, 281 { 0xa934, 0x15150406 }, 282 { 0xa938, 0x00020300 }, 283 { 0xa93c, 0x00903900 }, 284 { 0xa940, 0x00000000 }, 285 { 0xa944, 0x00000000 }, 286 { 0xa948, 0x20001b00 }, 287 { 0xa94c, 0x0a000010 }, 288 { 0xa950, 0x00000000 }, 289 { 0xa954, 0x00000008 }, 290 { 0xa960, 0x00110000 }, 291 { 0xaa3c, 0x00003900 }, 292 { 0xaa54, 0x00000008 }, 293 { 0xaa60, 0x00110000 }, 294 { 0 } 295 }; 296 297 static inline u32 gtt_read(void *bar, u32 reg) 298 { 299 return readl(bar + reg); 300 } 301 302 static inline void gtt_write(void *bar, u32 reg, u32 data) 303 { 304 writel(data, bar + reg); 305 } 306 307 static void gtt_write_powermeter(void *bar, const struct gt_powermeter *pm) 308 { 309 for (; pm && pm->reg; pm++) 310 gtt_write(bar, pm->reg, pm->value); 311 } 312 313 #define GTT_RETRY 1000 314 static int gtt_poll(void *bar, u32 reg, u32 mask, u32 value) 315 { 316 unsigned try = GTT_RETRY; 317 u32 data; 318 319 while (try--) { 320 data = gtt_read(bar, reg); 321 if ((data & mask) == value) 322 return 1; 323 udelay(10); 324 } 325 326 printf("GT init timeout\n"); 327 return 0; 328 } 329 330 static int gma_pm_init_pre_vbios(void *gtt_bar, int rev) 331 { 332 u32 reg32; 333 334 debug("GT Power Management Init, silicon = %#x\n", rev); 335 336 if (rev < IVB_STEP_C0) { 337 /* 1: Enable force wake */ 338 gtt_write(gtt_bar, 0xa18c, 0x00000001); 339 gtt_poll(gtt_bar, 0x130090, (1 << 0), (1 << 0)); 340 } else { 341 gtt_write(gtt_bar, 0xa180, 1 << 5); 342 gtt_write(gtt_bar, 0xa188, 0xffff0001); 343 gtt_poll(gtt_bar, 0x130040, (1 << 0), (1 << 0)); 344 } 345 346 if ((rev & BASE_REV_MASK) == BASE_REV_SNB) { 347 /* 1d: Set GTT+0x42004 [15:14]=11 (SnB C1+) */ 348 reg32 = gtt_read(gtt_bar, 0x42004); 349 reg32 |= (1 << 14) | (1 << 15); 350 gtt_write(gtt_bar, 0x42004, reg32); 351 } 352 353 if (rev >= IVB_STEP_A0) { 354 /* Display Reset Acknowledge Settings */ 355 reg32 = gtt_read(gtt_bar, 0x45010); 356 reg32 |= (1 << 1) | (1 << 0); 357 gtt_write(gtt_bar, 0x45010, reg32); 358 } 359 360 /* 2: Get GT SKU from GTT+0x911c[13] */ 361 reg32 = gtt_read(gtt_bar, 0x911c); 362 if ((rev & BASE_REV_MASK) == BASE_REV_SNB) { 363 if (reg32 & (1 << 13)) { 364 debug("SNB GT1 Power Meter Weights\n"); 365 gtt_write_powermeter(gtt_bar, snb_pm_gt1); 366 } else { 367 debug("SNB GT2 Power Meter Weights\n"); 368 gtt_write_powermeter(gtt_bar, snb_pm_gt2); 369 } 370 } else { 371 u32 unit = readl(MCHBAR_REG(0x5938)) & 0xf; 372 373 if (reg32 & (1 << 13)) { 374 /* GT1 SKU */ 375 debug("IVB GT1 Power Meter Weights\n"); 376 gtt_write_powermeter(gtt_bar, ivb_pm_gt1); 377 } else { 378 /* GT2 SKU */ 379 u32 tdp = readl(MCHBAR_REG(0x5930)) & 0x7fff; 380 tdp /= (1 << unit); 381 382 if (tdp <= 17) { 383 /* <=17W ULV */ 384 debug("IVB GT2 17W Power Meter Weights\n"); 385 gtt_write_powermeter(gtt_bar, ivb_pm_gt2_17w); 386 } else if ((tdp >= 25) && (tdp <= 35)) { 387 /* 25W-35W */ 388 debug("IVB GT2 25W-35W Power Meter Weights\n"); 389 gtt_write_powermeter(gtt_bar, ivb_pm_gt2_35w); 390 } else { 391 /* All others */ 392 debug("IVB GT2 35W Power Meter Weights\n"); 393 gtt_write_powermeter(gtt_bar, ivb_pm_gt2_35w); 394 } 395 } 396 } 397 398 /* 3: Gear ratio map */ 399 gtt_write(gtt_bar, 0xa004, 0x00000010); 400 401 /* 4: GFXPAUSE */ 402 gtt_write(gtt_bar, 0xa000, 0x00070020); 403 404 /* 5: Dynamic EU trip control */ 405 gtt_write(gtt_bar, 0xa080, 0x00000004); 406 407 /* 6: ECO bits */ 408 reg32 = gtt_read(gtt_bar, 0xa180); 409 reg32 |= (1 << 26) | (1 << 31); 410 /* (bit 20=1 for SNB step D1+ / IVB A0+) */ 411 if (rev >= SNB_STEP_D1) 412 reg32 |= (1 << 20); 413 gtt_write(gtt_bar, 0xa180, reg32); 414 415 /* 6a: for SnB step D2+ only */ 416 if (((rev & BASE_REV_MASK) == BASE_REV_SNB) && 417 (rev >= SNB_STEP_D2)) { 418 reg32 = gtt_read(gtt_bar, 0x9400); 419 reg32 |= (1 << 7); 420 gtt_write(gtt_bar, 0x9400, reg32); 421 422 reg32 = gtt_read(gtt_bar, 0x941c); 423 reg32 &= 0xf; 424 reg32 |= (1 << 1); 425 gtt_write(gtt_bar, 0x941c, reg32); 426 gtt_poll(gtt_bar, 0x941c, (1 << 1), (0 << 1)); 427 } 428 429 if ((rev & BASE_REV_MASK) == BASE_REV_IVB) { 430 reg32 = gtt_read(gtt_bar, 0x907c); 431 reg32 |= (1 << 16); 432 gtt_write(gtt_bar, 0x907c, reg32); 433 434 /* 6b: Clocking reset controls */ 435 gtt_write(gtt_bar, 0x9424, 0x00000001); 436 } else { 437 /* 6b: Clocking reset controls */ 438 gtt_write(gtt_bar, 0x9424, 0x00000000); 439 } 440 441 /* 7 */ 442 if (gtt_poll(gtt_bar, 0x138124, (1 << 31), (0 << 31))) { 443 gtt_write(gtt_bar, 0x138128, 0x00000029); /* Mailbox Data */ 444 /* Mailbox Cmd for RC6 VID */ 445 gtt_write(gtt_bar, 0x138124, 0x80000004); 446 if (gtt_poll(gtt_bar, 0x138124, (1 << 31), (0 << 31))) 447 gtt_write(gtt_bar, 0x138124, 0x8000000a); 448 gtt_poll(gtt_bar, 0x138124, (1 << 31), (0 << 31)); 449 } 450 451 /* 8 */ 452 gtt_write(gtt_bar, 0xa090, 0x00000000); /* RC Control */ 453 gtt_write(gtt_bar, 0xa098, 0x03e80000); /* RC1e Wake Rate Limit */ 454 gtt_write(gtt_bar, 0xa09c, 0x0028001e); /* RC6/6p Wake Rate Limit */ 455 gtt_write(gtt_bar, 0xa0a0, 0x0000001e); /* RC6pp Wake Rate Limit */ 456 gtt_write(gtt_bar, 0xa0a8, 0x0001e848); /* RC Evaluation Interval */ 457 gtt_write(gtt_bar, 0xa0ac, 0x00000019); /* RC Idle Hysteresis */ 458 459 /* 9 */ 460 gtt_write(gtt_bar, 0x2054, 0x0000000a); /* Render Idle Max Count */ 461 gtt_write(gtt_bar, 0x12054, 0x0000000a); /* Video Idle Max Count */ 462 gtt_write(gtt_bar, 0x22054, 0x0000000a); /* Blitter Idle Max Count */ 463 464 /* 10 */ 465 gtt_write(gtt_bar, 0xa0b0, 0x00000000); /* Unblock Ack to Busy */ 466 gtt_write(gtt_bar, 0xa0b4, 0x000003e8); /* RC1e Threshold */ 467 gtt_write(gtt_bar, 0xa0b8, 0x0000c350); /* RC6 Threshold */ 468 gtt_write(gtt_bar, 0xa0bc, 0x000186a0); /* RC6p Threshold */ 469 gtt_write(gtt_bar, 0xa0c0, 0x0000fa00); /* RC6pp Threshold */ 470 471 /* 11 */ 472 gtt_write(gtt_bar, 0xa010, 0x000f4240); /* RP Down Timeout */ 473 gtt_write(gtt_bar, 0xa014, 0x12060000); /* RP Interrupt Limits */ 474 gtt_write(gtt_bar, 0xa02c, 0x00015f90); /* RP Up Threshold */ 475 gtt_write(gtt_bar, 0xa030, 0x000186a0); /* RP Down Threshold */ 476 gtt_write(gtt_bar, 0xa068, 0x000186a0); /* RP Up EI */ 477 gtt_write(gtt_bar, 0xa06c, 0x000493e0); /* RP Down EI */ 478 gtt_write(gtt_bar, 0xa070, 0x0000000a); /* RP Idle Hysteresis */ 479 480 /* 11a: Enable Render Standby (RC6) */ 481 if ((rev & BASE_REV_MASK) == BASE_REV_IVB) { 482 /* 483 * IvyBridge should also support DeepRenderStandby. 484 * 485 * Unfortunately it does not work reliably on all SKUs so 486 * disable it here and it can be enabled by the kernel. 487 */ 488 gtt_write(gtt_bar, 0xa090, 0x88040000); /* HW RC Control */ 489 } else { 490 gtt_write(gtt_bar, 0xa090, 0x88040000); /* HW RC Control */ 491 } 492 493 /* 12: Normal Frequency Request */ 494 /* RPNFREQ_VAL comes from MCHBAR 0x5998 23:16 (8 bits!? use 7) */ 495 reg32 = readl(MCHBAR_REG(0x5998)); 496 reg32 >>= 16; 497 reg32 &= 0xef; 498 reg32 <<= 25; 499 gtt_write(gtt_bar, 0xa008, reg32); 500 501 /* 13: RP Control */ 502 gtt_write(gtt_bar, 0xa024, 0x00000592); 503 504 /* 14: Enable PM Interrupts */ 505 gtt_write(gtt_bar, 0x4402c, 0x03000076); 506 507 /* Clear 0x6c024 [8:6] */ 508 reg32 = gtt_read(gtt_bar, 0x6c024); 509 reg32 &= ~0x000001c0; 510 gtt_write(gtt_bar, 0x6c024, reg32); 511 512 return 0; 513 } 514 515 static int gma_pm_init_post_vbios(struct udevice *dev, int rev, void *gtt_bar) 516 { 517 const void *blob = gd->fdt_blob; 518 int node = dev->of_offset; 519 u32 reg32, cycle_delay; 520 521 debug("GT Power Management Init (post VBIOS)\n"); 522 523 /* 15: Deassert Force Wake */ 524 if (rev < IVB_STEP_C0) { 525 gtt_write(gtt_bar, 0xa18c, gtt_read(gtt_bar, 0xa18c) & ~1); 526 gtt_poll(gtt_bar, 0x130090, (1 << 0), (0 << 0)); 527 } else { 528 gtt_write(gtt_bar, 0xa188, 0x1fffe); 529 if (gtt_poll(gtt_bar, 0x130040, (1 << 0), (0 << 0))) { 530 gtt_write(gtt_bar, 0xa188, 531 gtt_read(gtt_bar, 0xa188) | 1); 532 } 533 } 534 535 /* 16: SW RC Control */ 536 gtt_write(gtt_bar, 0xa094, 0x00060000); 537 538 /* Setup Digital Port Hotplug */ 539 reg32 = gtt_read(gtt_bar, 0xc4030); 540 if (!reg32) { 541 u32 dp_hotplug[3]; 542 543 if (fdtdec_get_int_array(blob, node, "intel,dp_hotplug", 544 dp_hotplug, ARRAY_SIZE(dp_hotplug))) 545 return -EINVAL; 546 547 reg32 = (dp_hotplug[0] & 0x7) << 2; 548 reg32 |= (dp_hotplug[0] & 0x7) << 10; 549 reg32 |= (dp_hotplug[0] & 0x7) << 18; 550 gtt_write(gtt_bar, 0xc4030, reg32); 551 } 552 553 /* Setup Panel Power On Delays */ 554 reg32 = gtt_read(gtt_bar, 0xc7208); 555 if (!reg32) { 556 reg32 = (unsigned)fdtdec_get_int(blob, node, 557 "panel-port-select", 0) << 30; 558 reg32 |= fdtdec_get_int(blob, node, "panel-power-up-delay", 0) 559 << 16; 560 reg32 |= fdtdec_get_int(blob, node, 561 "panel-power-backlight-on-delay", 0); 562 gtt_write(gtt_bar, 0xc7208, reg32); 563 } 564 565 /* Setup Panel Power Off Delays */ 566 reg32 = gtt_read(gtt_bar, 0xc720c); 567 if (!reg32) { 568 reg32 = fdtdec_get_int(blob, node, "panel-power-down-delay", 0) 569 << 16; 570 reg32 |= fdtdec_get_int(blob, node, 571 "panel-power-backlight-off-delay", 0); 572 gtt_write(gtt_bar, 0xc720c, reg32); 573 } 574 575 /* Setup Panel Power Cycle Delay */ 576 cycle_delay = fdtdec_get_int(blob, node, 577 "intel,panel-power-cycle-delay", 0); 578 if (cycle_delay) { 579 reg32 = gtt_read(gtt_bar, 0xc7210); 580 reg32 &= ~0xff; 581 reg32 |= cycle_delay; 582 gtt_write(gtt_bar, 0xc7210, reg32); 583 } 584 585 /* Enable Backlight if needed */ 586 reg32 = fdtdec_get_int(blob, node, "intel,cpu-backlight", 0); 587 if (reg32) { 588 gtt_write(gtt_bar, 0x48250, (1 << 31)); 589 gtt_write(gtt_bar, 0x48254, reg32); 590 } 591 reg32 = fdtdec_get_int(blob, node, "intel,pch-backlight", 0); 592 if (reg32) { 593 gtt_write(gtt_bar, 0xc8250, (1 << 31)); 594 gtt_write(gtt_bar, 0xc8254, reg32); 595 } 596 597 return 0; 598 } 599 600 /* 601 * Some vga option roms are used for several chipsets but they only have one 602 * PCI ID in their header. If we encounter such an option rom, we need to do 603 * the mapping ourselves. 604 */ 605 606 uint32_t board_map_oprom_vendev(uint32_t vendev) 607 { 608 switch (vendev) { 609 case 0x80860102: /* GT1 Desktop */ 610 case 0x8086010a: /* GT1 Server */ 611 case 0x80860112: /* GT2 Desktop */ 612 case 0x80860116: /* GT2 Mobile */ 613 case 0x80860122: /* GT2 Desktop >=1.3GHz */ 614 case 0x80860126: /* GT2 Mobile >=1.3GHz */ 615 case 0x80860156: /* IVB */ 616 case 0x80860166: /* IVB */ 617 return 0x80860106; /* GT1 Mobile */ 618 } 619 620 return vendev; 621 } 622 623 static int int15_handler(void) 624 { 625 int res = 0; 626 627 debug("%s: INT15 function %04x!\n", __func__, M.x86.R_AX); 628 629 switch (M.x86.R_AX) { 630 case 0x5f34: 631 /* 632 * Set Panel Fitting Hook: 633 * bit 2 = Graphics Stretching 634 * bit 1 = Text Stretching 635 * bit 0 = Centering (do not set with bit1 or bit2) 636 * 0 = video bios default 637 */ 638 M.x86.R_AX = 0x005f; 639 M.x86.R_CL = 0x00; /* Use video bios default */ 640 res = 1; 641 break; 642 case 0x5f35: 643 /* 644 * Boot Display Device Hook: 645 * bit 0 = CRT 646 * bit 1 = TV (eDP) 647 * bit 2 = EFP 648 * bit 3 = LFP 649 * bit 4 = CRT2 650 * bit 5 = TV2 (eDP) 651 * bit 6 = EFP2 652 * bit 7 = LFP2 653 */ 654 M.x86.R_AX = 0x005f; 655 M.x86.R_CX = 0x0000; /* Use video bios default */ 656 res = 1; 657 break; 658 case 0x5f51: 659 /* 660 * Hook to select active LFP configuration: 661 * 00h = No LVDS, VBIOS does not enable LVDS 662 * 01h = Int-LVDS, LFP driven by integrated LVDS decoder 663 * 02h = SVDO-LVDS, LFP driven by SVDO decoder 664 * 03h = eDP, LFP Driven by Int-DisplayPort encoder 665 */ 666 M.x86.R_AX = 0x005f; 667 M.x86.R_CX = 0x0003; /* eDP */ 668 res = 1; 669 break; 670 case 0x5f70: 671 switch (M.x86.R_CH) { 672 case 0: 673 /* Get Mux */ 674 M.x86.R_AX = 0x005f; 675 M.x86.R_CX = 0x0000; 676 res = 1; 677 break; 678 case 1: 679 /* Set Mux */ 680 M.x86.R_AX = 0x005f; 681 M.x86.R_CX = 0x0000; 682 res = 1; 683 break; 684 case 2: 685 /* Get SG/Non-SG mode */ 686 M.x86.R_AX = 0x005f; 687 M.x86.R_CX = 0x0000; 688 res = 1; 689 break; 690 default: 691 /* Interrupt was not handled */ 692 debug("Unknown INT15 5f70 function: 0x%02x\n", 693 M.x86.R_CH); 694 break; 695 } 696 break; 697 case 0x5fac: 698 res = 1; 699 break; 700 default: 701 debug("Unknown INT15 function %04x!\n", M.x86.R_AX); 702 break; 703 } 704 return res; 705 } 706 707 static void sandybridge_setup_graphics(struct udevice *dev, 708 struct udevice *video_dev) 709 { 710 u32 reg32; 711 u16 reg16; 712 u8 reg8; 713 714 dm_pci_read_config16(video_dev, PCI_DEVICE_ID, ®16); 715 switch (reg16) { 716 case 0x0102: /* GT1 Desktop */ 717 case 0x0106: /* GT1 Mobile */ 718 case 0x010a: /* GT1 Server */ 719 case 0x0112: /* GT2 Desktop */ 720 case 0x0116: /* GT2 Mobile */ 721 case 0x0122: /* GT2 Desktop >=1.3GHz */ 722 case 0x0126: /* GT2 Mobile >=1.3GHz */ 723 case 0x0156: /* IvyBridge */ 724 case 0x0166: /* IvyBridge */ 725 break; 726 default: 727 debug("Graphics not supported by this CPU/chipset\n"); 728 return; 729 } 730 731 debug("Initialising Graphics\n"); 732 733 /* Setup IGD memory by setting GGC[7:3] = 1 for 32MB */ 734 dm_pci_read_config16(dev, GGC, ®16); 735 reg16 &= ~0x00f8; 736 reg16 |= 1 << 3; 737 /* Program GTT memory by setting GGC[9:8] = 2MB */ 738 reg16 &= ~0x0300; 739 reg16 |= 2 << 8; 740 /* Enable VGA decode */ 741 reg16 &= ~0x0002; 742 dm_pci_write_config16(dev, GGC, reg16); 743 744 /* Enable 256MB aperture */ 745 dm_pci_read_config8(video_dev, MSAC, ®8); 746 reg8 &= ~0x06; 747 reg8 |= 0x02; 748 dm_pci_write_config8(video_dev, MSAC, reg8); 749 750 /* Erratum workarounds */ 751 reg32 = readl(MCHBAR_REG(0x5f00)); 752 reg32 |= (1 << 9) | (1 << 10); 753 writel(reg32, MCHBAR_REG(0x5f00)); 754 755 /* Enable SA Clock Gating */ 756 reg32 = readl(MCHBAR_REG(0x5f00)); 757 writel(reg32 | 1, MCHBAR_REG(0x5f00)); 758 759 /* GPU RC6 workaround for sighting 366252 */ 760 reg32 = readl(MCHBAR_REG(0x5d14)); 761 reg32 |= (1 << 31); 762 writel(reg32, MCHBAR_REG(0x5d14)); 763 764 /* VLW */ 765 reg32 = readl(MCHBAR_REG(0x6120)); 766 reg32 &= ~(1 << 0); 767 writel(reg32, MCHBAR_REG(0x6120)); 768 769 reg32 = readl(MCHBAR_REG(0x5418)); 770 reg32 |= (1 << 4) | (1 << 5); 771 writel(reg32, MCHBAR_REG(0x5418)); 772 } 773 774 static int gma_func0_init(struct udevice *dev) 775 { 776 struct udevice *nbridge; 777 void *gtt_bar; 778 ulong base; 779 u32 reg32; 780 int ret; 781 int rev; 782 783 /* Enable PCH Display Port */ 784 writew(0x0010, RCB_REG(DISPBDF)); 785 setbits_le32(RCB_REG(FD2), PCH_ENABLE_DBDF); 786 787 ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &nbridge); 788 if (ret) 789 return ret; 790 rev = bridge_silicon_revision(nbridge); 791 sandybridge_setup_graphics(nbridge, dev); 792 793 /* IGD needs to be Bus Master */ 794 dm_pci_read_config32(dev, PCI_COMMAND, ®32); 795 reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; 796 dm_pci_write_config32(dev, PCI_COMMAND, reg32); 797 798 /* Use write-combining for the graphics memory, 256MB */ 799 base = dm_pci_read_bar32(dev, 2); 800 mtrr_add_request(MTRR_TYPE_WRCOMB, base, 256 << 20); 801 mtrr_commit(true); 802 803 gtt_bar = (void *)dm_pci_read_bar32(dev, 0); 804 debug("GT bar %p\n", gtt_bar); 805 ret = gma_pm_init_pre_vbios(gtt_bar, rev); 806 if (ret) 807 return ret; 808 809 return rev; 810 } 811 812 static int bd82x6x_video_probe(struct udevice *dev) 813 { 814 void *gtt_bar; 815 int ret, rev; 816 817 rev = gma_func0_init(dev); 818 if (rev < 0) 819 return rev; 820 ret = vbe_setup_video(dev, int15_handler); 821 if (ret) 822 return ret; 823 824 /* Post VBIOS init */ 825 gtt_bar = (void *)dm_pci_read_bar32(dev, 0); 826 ret = gma_pm_init_post_vbios(dev, rev, gtt_bar); 827 if (ret) 828 return ret; 829 830 return 0; 831 } 832 833 static const struct udevice_id bd82x6x_video_ids[] = { 834 { .compatible = "intel,gma" }, 835 { } 836 }; 837 838 U_BOOT_DRIVER(bd82x6x_video) = { 839 .name = "bd82x6x_video", 840 .id = UCLASS_VIDEO, 841 .of_match = bd82x6x_video_ids, 842 .probe = bd82x6x_video_probe, 843 }; 844