blob: 30c9eda9b0e889a66b0c07aacd25d7b9a49b555a [file] [log] [blame]
Lee Leahyb0005132015-05-12 18:19:47 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2014 Google Inc.
Lee Leahy1d14b3e2015-05-12 18:23:27 -07005 * Copyright (C) 2015 Intel Corporation.
Lee Leahyb0005132015-05-12 18:19:47 -07006 *
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.
Lee Leahyb0005132015-05-12 18:19:47 -070015 */
16
17#include <arch/acpi.h>
18#include <arch/io.h>
Furquan Shaikh2a12e2e2016-07-25 11:48:03 -070019#include <bootmode.h>
Lee Leahy1d14b3e2015-05-12 18:23:27 -070020#include <chip.h>
Lee Leahyb0005132015-05-12 18:19:47 -070021#include <console/console.h>
22#include <delay.h>
23#include <device/device.h>
24#include <device/pci.h>
25#include <device/pci_ids.h>
Lee Leahyb0005132015-05-12 18:19:47 -070026#include <drivers/intel/gma/i915_reg.h>
Naresh G Solankia2d40622016-08-30 20:47:13 +053027#include <fsp/util.h>
robbie zhangb45dde02015-10-01 17:21:33 -070028#include <soc/acpi.h>
Lee Leahyb0005132015-05-12 18:19:47 -070029#include <soc/cpu.h>
30#include <soc/pm.h>
31#include <soc/ramstage.h>
32#include <soc/systemagent.h>
Duncan Laurie68957b32015-09-03 16:07:35 -070033#include <stdlib.h>
34#include <string.h>
Furquan Shaikh2a12e2e2016-07-25 11:48:03 -070035#include <vboot/vbnv.h>
Lee Leahyb0005132015-05-12 18:19:47 -070036
Naresh G Solankia2d40622016-08-30 20:47:13 +053037uintptr_t fsp_soc_get_igd_bar(void)
38{
39 return find_resource(SA_DEV_IGD, PCI_BASE_ADDRESS_2)->base;
40}
41
Lee Leahyb0005132015-05-12 18:19:47 -070042u32 map_oprom_vendev(u32 vendev)
43{
44 return SA_IGD_OPROM_VENDEV;
45}
46
47static struct resource *gtt_res = NULL;
48
49static unsigned long gtt_read(unsigned long reg)
50{
51 u32 val;
Lee Leahy1d14b3e2015-05-12 18:23:27 -070052 val = read32((void *)(unsigned int)(gtt_res->base + reg));
Lee Leahyb0005132015-05-12 18:19:47 -070053 return val;
Lee Leahyb0005132015-05-12 18:19:47 -070054}
55
56static void gtt_write(unsigned long reg, unsigned long data)
57{
Lee Leahy1d14b3e2015-05-12 18:23:27 -070058 write32((void *)(unsigned int)(gtt_res->base + reg), data);
Lee Leahyb0005132015-05-12 18:19:47 -070059}
60
61static inline void gtt_rmw(u32 reg, u32 andmask, u32 ormask)
62{
63 u32 val = gtt_read(reg);
64 val &= andmask;
65 val |= ormask;
66 gtt_write(reg, val);
67}
68
Lee Leahyb0005132015-05-12 18:19:47 -070069static void igd_init(struct device *dev)
70{
Duncan Laurie3054c8b2016-02-10 17:10:05 -080071 u32 ddi_buf_ctl;
72
73 gtt_res = find_resource(dev, PCI_BASE_ADDRESS_0);
74 if (!gtt_res || !gtt_res->base)
75 return;
76
77 /*
78 * Enable DDI-A (eDP) 4-lane operation if the link is not up yet.
79 * This will allow the kernel to use 4-lane eDP links properly
80 * if the VBIOS or GOP driver does not execute.
81 */
82 ddi_buf_ctl = gtt_read(DDI_BUF_CTL_A);
83 if (!acpi_is_wakeup_s3() && !(ddi_buf_ctl & DDI_BUF_CTL_ENABLE)) {
84 ddi_buf_ctl |= DDI_A_4_LANES;
85 gtt_write(DDI_BUF_CTL_A, ddi_buf_ctl);
86 }
87
Naresh G Solankia2d40622016-08-30 20:47:13 +053088 if (IS_ENABLED(CONFIG_ADD_VBT_DATA_FILE))
robbie zhangb45dde02015-10-01 17:21:33 -070089 return;
90
Lee Leahyb0005132015-05-12 18:19:47 -070091 /* IGD needs to be Bus Master */
92 u32 reg32 = pci_read_config32(dev, PCI_COMMAND);
93 reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
94 pci_write_config32(dev, PCI_COMMAND, reg32);
95
Lee Leahyb0005132015-05-12 18:19:47 -070096 /* Wait for any configured pre-graphics delay */
Duncan Laurie68957b32015-09-03 16:07:35 -070097 if (!acpi_is_wakeup_s3()) {
Lee Leahyb0005132015-05-12 18:19:47 -070098#if IS_ENABLED(CONFIG_CHROMEOS)
Furquan Shaikh0325dc62016-07-25 13:02:36 -070099 if (display_init_required() || vboot_wants_oprom())
Duncan Laurie68957b32015-09-03 16:07:35 -0700100 mdelay(CONFIG_PRE_GRAPHICS_DELAY);
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700101#else
Duncan Laurie68957b32015-09-03 16:07:35 -0700102 mdelay(CONFIG_PRE_GRAPHICS_DELAY);
Lee Leahyb0005132015-05-12 18:19:47 -0700103#endif
104 }
Duncan Laurie68957b32015-09-03 16:07:35 -0700105
Lee Leahyb0005132015-05-12 18:19:47 -0700106 /* Initialize PCI device, load/execute BIOS Option ROM */
107 pci_dev_init(dev);
108
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700109#if IS_ENABLED(CONFIG_CHROMEOS)
110 if (!gfx_get_init_done() && !acpi_is_wakeup_s3()) {
Lee Leahyb0005132015-05-12 18:19:47 -0700111 /*
112 * Enable DDI-A if the Option ROM did not execute:
113 *
114 * bit 0: Display detected (RO)
115 * bit 4: DDI A supports 4 lanes and DDI E is not used
116 * bit 7: DDI buffer is idle
117 */
118 gtt_write(DDI_BUF_CTL_A, DDI_BUF_IS_IDLE | DDI_A_4_LANES |
119 DDI_INIT_DISPLAY_DETECTED);
120 }
Duncan Laurie68957b32015-09-03 16:07:35 -0700121#endif
Lee Leahyb0005132015-05-12 18:19:47 -0700122}
123
robbie zhangb45dde02015-10-01 17:21:33 -0700124/* Initialize IGD OpRegion, called from ACPI code */
Rizwan Qureshi1222a732016-08-23 14:31:23 +0530125static int update_igd_opregion(igd_opregion_t *opregion)
robbie zhangb45dde02015-10-01 17:21:33 -0700126{
robbie zhangb45dde02015-10-01 17:21:33 -0700127 u16 reg16;
128
robbie zhangb45dde02015-10-01 17:21:33 -0700129 /* Initialize Mailbox 3 */
130 opregion->mailbox3.bclp = IGD_BACKLIGHT_BRIGHTNESS;
131 opregion->mailbox3.pfit = IGD_FIELD_VALID | IGD_PFIT_STRETCH;
132 opregion->mailbox3.pcft = 0; /* should be (IMON << 1) & 0x3e */
133 opregion->mailbox3.cblv = IGD_FIELD_VALID | IGD_INITIAL_BRIGHTNESS;
134 opregion->mailbox3.bclm[0] = IGD_WORD_FIELD_VALID + 0x0000;
135 opregion->mailbox3.bclm[1] = IGD_WORD_FIELD_VALID + 0x0a19;
136 opregion->mailbox3.bclm[2] = IGD_WORD_FIELD_VALID + 0x1433;
137 opregion->mailbox3.bclm[3] = IGD_WORD_FIELD_VALID + 0x1e4c;
138 opregion->mailbox3.bclm[4] = IGD_WORD_FIELD_VALID + 0x2866;
139 opregion->mailbox3.bclm[5] = IGD_WORD_FIELD_VALID + 0x327f;
140 opregion->mailbox3.bclm[6] = IGD_WORD_FIELD_VALID + 0x3c99;
141 opregion->mailbox3.bclm[7] = IGD_WORD_FIELD_VALID + 0x46b2;
142 opregion->mailbox3.bclm[8] = IGD_WORD_FIELD_VALID + 0x50cc;
143 opregion->mailbox3.bclm[9] = IGD_WORD_FIELD_VALID + 0x5ae5;
144 opregion->mailbox3.bclm[10] = IGD_WORD_FIELD_VALID + 0x64ff;
145
146 /* TODO This may need to happen in S3 resume */
147 pci_write_config32(SA_DEV_IGD, ASLS, (u32)opregion);
148 reg16 = pci_read_config16(SA_DEV_IGD, SWSCI);
149 reg16 &= ~GSSCIE;
150 reg16 |= SMISCISEL;
151 pci_write_config16(SA_DEV_IGD, SWSCI, reg16);
152
153 return 0;
154}
155
156static unsigned long write_acpi_igd_opregion(device_t device,
157 unsigned long current, struct acpi_rsdp *rsdp)
158{
159 igd_opregion_t *opregion;
160
161 /* If GOP is not used, exit here */
Naresh G Solankia2d40622016-08-30 20:47:13 +0530162 if (!IS_ENABLED(CONFIG_ADD_VBT_DATA_FILE))
robbie zhangb45dde02015-10-01 17:21:33 -0700163 return current;
164
165 /* If IGD is disabled, exit here */
166 if (pci_read_config16(device, PCI_VENDOR_ID) == 0xFFFF)
167 return current;
168
169 printk(BIOS_DEBUG, "ACPI: * IGD OpRegion\n");
170 opregion = (igd_opregion_t *)current;
171 init_igd_opregion(opregion);
Rizwan Qureshi1222a732016-08-23 14:31:23 +0530172 update_igd_opregion(opregion);
robbie zhangb45dde02015-10-01 17:21:33 -0700173 current += sizeof(igd_opregion_t);
Aaron Durbin07a1b282015-12-10 17:07:38 -0600174 current = acpi_align_current(current);
robbie zhangb45dde02015-10-01 17:21:33 -0700175
176 printk(BIOS_DEBUG, "current = %lx\n", current);
177 return current;
178}
179
Lee Leahyb0005132015-05-12 18:19:47 -0700180static struct device_operations igd_ops = {
181 .read_resources = &pci_dev_read_resources,
182 .set_resources = &pci_dev_set_resources,
183 .enable_resources = &pci_dev_enable_resources,
184 .init = &igd_init,
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700185 .ops_pci = &soc_pci_ops,
robbie zhangb45dde02015-10-01 17:21:33 -0700186 .write_acpi_tables = write_acpi_igd_opregion,
Lee Leahyb0005132015-05-12 18:19:47 -0700187};
188
189static const unsigned short pci_device_ids[] = {
Lee Leahy1d14b3e2015-05-12 18:23:27 -0700190 IGD_SKYLAKE_GT1_SULTM,
191 IGD_SKYLAKE_GT2_SULXM,
192 IGD_SKYLAKE_GT2_SULTM,
Sooi, Li Chengc76e9982017-01-04 13:36:06 +0800193 IGD_SKYLAKE_GT2_SHALM,
194 IGD_SKYLAKE_GT4_SHALM,
Barnali Sarkar99123102016-08-26 14:48:46 +0530195 IGD_KABYLAKE_GT1_SULTM,
196 IGD_KABYLAKE_GT2_SULXM,
197 IGD_KABYLAKE_GT2_SULTM,
Sooi, Li Chengc76e9982017-01-04 13:36:06 +0800198 IGD_KABYLAKE_GT2_SHALM,
Lee Leahyb0005132015-05-12 18:19:47 -0700199 0,
200};
201
202static const struct pci_driver igd_driver __pci_driver = {
203 .ops = &igd_ops,
204 .vendor = PCI_VENDOR_ID_INTEL,
205 .devices = pci_device_ids,
206};