Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 1 | /* |
| 2 | * This file is part of the coreboot project. |
| 3 | * |
| 4 | * Copyright (C) 2014 Google Inc. |
Lee Leahy | 1d14b3e | 2015-05-12 18:23:27 -0700 | [diff] [blame] | 5 | * Copyright (C) 2015 Intel Corporation. |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 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. |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 15 | */ |
| 16 | |
| 17 | #include <arch/acpi.h> |
| 18 | #include <arch/io.h> |
Furquan Shaikh | 2a12e2e | 2016-07-25 11:48:03 -0700 | [diff] [blame] | 19 | #include <bootmode.h> |
Lee Leahy | 1d14b3e | 2015-05-12 18:23:27 -0700 | [diff] [blame] | 20 | #include <chip.h> |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 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> |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 26 | #include <drivers/intel/gma/i915_reg.h> |
Naresh G Solanki | a2d4062 | 2016-08-30 20:47:13 +0530 | [diff] [blame] | 27 | #include <fsp/util.h> |
robbie zhang | b45dde0 | 2015-10-01 17:21:33 -0700 | [diff] [blame] | 28 | #include <soc/acpi.h> |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 29 | #include <soc/cpu.h> |
| 30 | #include <soc/pm.h> |
| 31 | #include <soc/ramstage.h> |
| 32 | #include <soc/systemagent.h> |
Duncan Laurie | 68957b3 | 2015-09-03 16:07:35 -0700 | [diff] [blame] | 33 | #include <stdlib.h> |
| 34 | #include <string.h> |
Furquan Shaikh | 2a12e2e | 2016-07-25 11:48:03 -0700 | [diff] [blame] | 35 | #include <vboot/vbnv.h> |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 36 | |
Naresh G Solanki | a2d4062 | 2016-08-30 20:47:13 +0530 | [diff] [blame] | 37 | uintptr_t fsp_soc_get_igd_bar(void) |
| 38 | { |
| 39 | return find_resource(SA_DEV_IGD, PCI_BASE_ADDRESS_2)->base; |
| 40 | } |
| 41 | |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 42 | u32 map_oprom_vendev(u32 vendev) |
| 43 | { |
| 44 | return SA_IGD_OPROM_VENDEV; |
| 45 | } |
| 46 | |
| 47 | static struct resource *gtt_res = NULL; |
| 48 | |
| 49 | static unsigned long gtt_read(unsigned long reg) |
| 50 | { |
| 51 | u32 val; |
Lee Leahy | 1d14b3e | 2015-05-12 18:23:27 -0700 | [diff] [blame] | 52 | val = read32((void *)(unsigned int)(gtt_res->base + reg)); |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 53 | return val; |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 54 | } |
| 55 | |
| 56 | static void gtt_write(unsigned long reg, unsigned long data) |
| 57 | { |
Lee Leahy | 1d14b3e | 2015-05-12 18:23:27 -0700 | [diff] [blame] | 58 | write32((void *)(unsigned int)(gtt_res->base + reg), data); |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 59 | } |
| 60 | |
| 61 | static 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 Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 69 | static void igd_init(struct device *dev) |
| 70 | { |
Duncan Laurie | 3054c8b | 2016-02-10 17:10:05 -0800 | [diff] [blame] | 71 | 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 Solanki | a2d4062 | 2016-08-30 20:47:13 +0530 | [diff] [blame] | 88 | if (IS_ENABLED(CONFIG_ADD_VBT_DATA_FILE)) |
robbie zhang | b45dde0 | 2015-10-01 17:21:33 -0700 | [diff] [blame] | 89 | return; |
| 90 | |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 91 | /* 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 Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 96 | /* Wait for any configured pre-graphics delay */ |
Duncan Laurie | 68957b3 | 2015-09-03 16:07:35 -0700 | [diff] [blame] | 97 | if (!acpi_is_wakeup_s3()) { |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 98 | #if IS_ENABLED(CONFIG_CHROMEOS) |
Furquan Shaikh | 0325dc6 | 2016-07-25 13:02:36 -0700 | [diff] [blame] | 99 | if (display_init_required() || vboot_wants_oprom()) |
Duncan Laurie | 68957b3 | 2015-09-03 16:07:35 -0700 | [diff] [blame] | 100 | mdelay(CONFIG_PRE_GRAPHICS_DELAY); |
Lee Leahy | 1d14b3e | 2015-05-12 18:23:27 -0700 | [diff] [blame] | 101 | #else |
Duncan Laurie | 68957b3 | 2015-09-03 16:07:35 -0700 | [diff] [blame] | 102 | mdelay(CONFIG_PRE_GRAPHICS_DELAY); |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 103 | #endif |
| 104 | } |
Duncan Laurie | 68957b3 | 2015-09-03 16:07:35 -0700 | [diff] [blame] | 105 | |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 106 | /* Initialize PCI device, load/execute BIOS Option ROM */ |
| 107 | pci_dev_init(dev); |
| 108 | |
Lee Leahy | 1d14b3e | 2015-05-12 18:23:27 -0700 | [diff] [blame] | 109 | #if IS_ENABLED(CONFIG_CHROMEOS) |
| 110 | if (!gfx_get_init_done() && !acpi_is_wakeup_s3()) { |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 111 | /* |
| 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 Laurie | 68957b3 | 2015-09-03 16:07:35 -0700 | [diff] [blame] | 121 | #endif |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 122 | } |
| 123 | |
robbie zhang | b45dde0 | 2015-10-01 17:21:33 -0700 | [diff] [blame] | 124 | /* Initialize IGD OpRegion, called from ACPI code */ |
Rizwan Qureshi | 1222a73 | 2016-08-23 14:31:23 +0530 | [diff] [blame] | 125 | static int update_igd_opregion(igd_opregion_t *opregion) |
robbie zhang | b45dde0 | 2015-10-01 17:21:33 -0700 | [diff] [blame] | 126 | { |
robbie zhang | b45dde0 | 2015-10-01 17:21:33 -0700 | [diff] [blame] | 127 | u16 reg16; |
| 128 | |
robbie zhang | b45dde0 | 2015-10-01 17:21:33 -0700 | [diff] [blame] | 129 | /* 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 | |
| 156 | static 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 Solanki | a2d4062 | 2016-08-30 20:47:13 +0530 | [diff] [blame] | 162 | if (!IS_ENABLED(CONFIG_ADD_VBT_DATA_FILE)) |
robbie zhang | b45dde0 | 2015-10-01 17:21:33 -0700 | [diff] [blame] | 163 | 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 Qureshi | 1222a73 | 2016-08-23 14:31:23 +0530 | [diff] [blame] | 172 | update_igd_opregion(opregion); |
robbie zhang | b45dde0 | 2015-10-01 17:21:33 -0700 | [diff] [blame] | 173 | current += sizeof(igd_opregion_t); |
Aaron Durbin | 07a1b28 | 2015-12-10 17:07:38 -0600 | [diff] [blame] | 174 | current = acpi_align_current(current); |
robbie zhang | b45dde0 | 2015-10-01 17:21:33 -0700 | [diff] [blame] | 175 | |
| 176 | printk(BIOS_DEBUG, "current = %lx\n", current); |
| 177 | return current; |
| 178 | } |
| 179 | |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 180 | static 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 Leahy | 1d14b3e | 2015-05-12 18:23:27 -0700 | [diff] [blame] | 185 | .ops_pci = &soc_pci_ops, |
robbie zhang | b45dde0 | 2015-10-01 17:21:33 -0700 | [diff] [blame] | 186 | .write_acpi_tables = write_acpi_igd_opregion, |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 187 | }; |
| 188 | |
| 189 | static const unsigned short pci_device_ids[] = { |
Lee Leahy | 1d14b3e | 2015-05-12 18:23:27 -0700 | [diff] [blame] | 190 | IGD_SKYLAKE_GT1_SULTM, |
| 191 | IGD_SKYLAKE_GT2_SULXM, |
| 192 | IGD_SKYLAKE_GT2_SULTM, |
Sooi, Li Cheng | c76e998 | 2017-01-04 13:36:06 +0800 | [diff] [blame] | 193 | IGD_SKYLAKE_GT2_SHALM, |
| 194 | IGD_SKYLAKE_GT4_SHALM, |
Barnali Sarkar | 9912310 | 2016-08-26 14:48:46 +0530 | [diff] [blame] | 195 | IGD_KABYLAKE_GT1_SULTM, |
| 196 | IGD_KABYLAKE_GT2_SULXM, |
| 197 | IGD_KABYLAKE_GT2_SULTM, |
Sooi, Li Cheng | c76e998 | 2017-01-04 13:36:06 +0800 | [diff] [blame] | 198 | IGD_KABYLAKE_GT2_SHALM, |
Lee Leahy | b000513 | 2015-05-12 18:19:47 -0700 | [diff] [blame] | 199 | 0, |
| 200 | }; |
| 201 | |
| 202 | static const struct pci_driver igd_driver __pci_driver = { |
| 203 | .ops = &igd_ops, |
| 204 | .vendor = PCI_VENDOR_ID_INTEL, |
| 205 | .devices = pci_device_ids, |
| 206 | }; |