blob: 937e56cde003020a99f70db17ed6b222485a8d9e [file] [log] [blame]
Andrey Petrova00e1042017-06-05 13:22:59 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2014 Google Inc.
Subrata Banikb3585b92018-01-08 13:57:43 +05305 * Copyright (C) 2015-2018 Intel Corporation.
Andrey Petrova00e1042017-06-05 13:22:59 -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.
15 */
16
17#include <arch/cpu.h>
18#include <arch/io.h>
19#include <console/console.h>
20#include <cpu/x86/msr.h>
21#include <device/pci.h>
22#include <device/pci_ids.h>
Subrata Banikb3585b92018-01-08 13:57:43 +053023#include <intelblocks/mp_init.h>
Andrey Petrova00e1042017-06-05 13:22:59 -070024#include <soc/bootblock.h>
Andrey Petrova00e1042017-06-05 13:22:59 -070025#include <soc/pch.h>
26#include <soc/pci_devs.h>
27#include <string.h>
28
29#define BIOS_SIGN_ID 0x8B
30
31static struct {
32 u32 cpuid;
33 const char *name;
34} cpu_table[] = {
35 { CPUID_CANNONLAKE_A0, "Cannonlake A0" },
36 { CPUID_CANNONLAKE_B0, "Cannonlake B0" },
37 { CPUID_CANNONLAKE_C0, "Cannonlake C0" },
Lijian Zhaoe9872282018-01-21 21:05:54 -080038 { CPUID_CANNONLAKE_D0, "Cannonlake D0" },
Maulikfc19ab52018-01-05 22:40:35 +053039 { CPUID_COFFEELAKE_D0, "Coffeelake D0" },
40 { CPUID_WHISKEYLAKE_W0, "Whiskeylake W0"},
Andrey Petrova00e1042017-06-05 13:22:59 -070041};
42
43static struct {
44 u16 mchid;
45 const char *name;
46} mch_table[] = {
47 { PCI_DEVICE_ID_INTEL_CNL_ID_U, "Cannonlake-U" },
48 { PCI_DEVICE_ID_INTEL_CNL_ID_Y, "Cannonlake-Y" },
Maulikfc19ab52018-01-05 22:40:35 +053049 { PCI_DEVICE_ID_INTEL_CFL_ID_U, "Coffeelake U (4+3e)"},
Krzysztof Sywulabb0cf012018-08-15 09:26:35 -070050 { PCI_DEVICE_ID_INTEL_WHL_ID_Wx4, "Whiskeylake W (4+2)"},
51 { PCI_DEVICE_ID_INTEL_WHL_ID_Wx2, "Whiskeylake W (2+2)"},
Andrey Petrova00e1042017-06-05 13:22:59 -070052};
53
54static struct {
Subrata Banikec10fbb2017-12-07 11:48:48 +053055 u16 lpcid;
56 const char *name;
57} pch_table[] = {
58 { PCI_DEVICE_ID_INTEL_CNL_BASE_U_LPC, "Cannonlake-U Base" },
59 { PCI_DEVICE_ID_INTEL_CNL_U_PREMIUM_LPC, "Cannonlake-U Premium" },
60 { PCI_DEVICE_ID_INTEL_CNL_Y_PREMIUM_LPC, "Cannonlake-Y Premium" },
61};
62
63static struct {
Andrey Petrova00e1042017-06-05 13:22:59 -070064 u16 igdid;
65 const char *name;
66} igd_table[] = {
67 { PCI_DEVICE_ID_INTEL_CNL_GT2_ULX_1, "Cannonlake ULX GT2" },
68 { PCI_DEVICE_ID_INTEL_CNL_GT2_ULX_2, "Cannonlake ULX GT1.5" },
69 { PCI_DEVICE_ID_INTEL_CNL_GT2_ULX_3, "Cannonlake ULX GT1" },
70 { PCI_DEVICE_ID_INTEL_CNL_GT2_ULX_4, "Cannonlake ULX GT0.5" },
71 { PCI_DEVICE_ID_INTEL_CNL_GT2_ULT_1, "Cannonlake ULT GT2" },
72 { PCI_DEVICE_ID_INTEL_CNL_GT2_ULT_2, "Cannonlake ULT GT1.5" },
73 { PCI_DEVICE_ID_INTEL_CNL_GT2_ULT_3, "Cannonlake ULT GT1" },
74 { PCI_DEVICE_ID_INTEL_CNL_GT2_ULT_4, "Cannonlake ULT GT0.5" },
Maulikfc19ab52018-01-05 22:40:35 +053075 { PCI_DEVICE_ID_INTEL_CFL_GT2_ULT, "Coffeelake ULT GT2"},
76 { PCI_DEVICE_ID_INTEL_WHL_GT2_ULT_1, "Whiskeylake ULT GT1"},
Andrey Petrova00e1042017-06-05 13:22:59 -070077};
78
Elyes HAOUASc8a649c2018-06-10 23:36:44 +020079static uint8_t get_dev_revision(pci_devfn_t dev)
Subrata Banikec10fbb2017-12-07 11:48:48 +053080{
81 return pci_read_config8(dev, PCI_REVISION_ID);
82}
83
Elyes HAOUASc8a649c2018-06-10 23:36:44 +020084static uint16_t get_dev_id(pci_devfn_t dev)
Subrata Banikec10fbb2017-12-07 11:48:48 +053085{
86 return pci_read_config16(dev, PCI_DEVICE_ID);
87}
88
Andrey Petrova00e1042017-06-05 13:22:59 -070089static void report_cpu_info(void)
90{
91 struct cpuid_result cpuidr;
92 u32 i, index;
93 char cpu_string[50], *cpu_name = cpu_string; /* 48 bytes are reported */
94 int vt, txt, aes;
95 msr_t microcode_ver;
Elyes HAOUAS39303d52018-07-08 12:40:45 +020096 static const char *const mode[] = {"NOT ", ""};
Andrey Petrova00e1042017-06-05 13:22:59 -070097 const char *cpu_type = "Unknown";
Martin Roth3f6421e2017-07-21 09:17:58 -060098 u32 p[13];
Andrey Petrova00e1042017-06-05 13:22:59 -070099
100 index = 0x80000000;
101 cpuidr = cpuid(index);
102 if (cpuidr.eax < 0x80000004) {
103 strcpy(cpu_string, "Platform info not available");
104 } else {
Andrey Petrova00e1042017-06-05 13:22:59 -0700105 int j=0;
106
107 for (i = 2; i <= 4; i++) {
108 cpuidr = cpuid(index + i);
109 p[j++] = cpuidr.eax;
110 p[j++] = cpuidr.ebx;
111 p[j++] = cpuidr.ecx;
112 p[j++] = cpuidr.edx;
113 }
114 p[12]=0;
115 cpu_name = (char *)p;
116 }
117 /* Skip leading spaces in CPU name string */
118 while (cpu_name[0] == ' ')
119 cpu_name++;
120
121 microcode_ver.lo = 0;
122 microcode_ver.hi = 0;
123 wrmsr(BIOS_SIGN_ID, microcode_ver);
124 cpuidr = cpuid(1);
125 microcode_ver = rdmsr(BIOS_SIGN_ID);
126
127 /* Look for string to match the name */
128 for (i = 0; i < ARRAY_SIZE(cpu_table); i++) {
129 if (cpu_table[i].cpuid == cpuidr.eax) {
130 cpu_type = cpu_table[i].name;
131 break;
132 }
133 }
134
135 printk(BIOS_DEBUG, "CPU: %s\n", cpu_name);
136 printk(BIOS_DEBUG, "CPU: ID %x, %s, ucode: %08x\n",
137 cpuidr.eax, cpu_type, microcode_ver.hi);
138
139 aes = (cpuidr.ecx & (1 << 25)) ? 1 : 0;
140 txt = (cpuidr.ecx & (1 << 6)) ? 1 : 0;
141 vt = (cpuidr.ecx & (1 << 5)) ? 1 : 0;
142 printk(BIOS_DEBUG,
143 "CPU: AES %ssupported, TXT %ssupported, VT %ssupported\n",
144 mode[aes], mode[txt], mode[vt]);
145}
146
147static void report_mch_info(void)
148{
149 int i;
Elyes HAOUASc8a649c2018-06-10 23:36:44 +0200150 pci_devfn_t dev = SA_DEV_ROOT;
Subrata Banikec10fbb2017-12-07 11:48:48 +0530151 uint16_t mchid = get_dev_id(dev);
152 uint8_t mch_revision = get_dev_revision(dev);
Andrey Petrova00e1042017-06-05 13:22:59 -0700153 const char *mch_type = "Unknown";
154
155 for (i = 0; i < ARRAY_SIZE(mch_table); i++) {
156 if (mch_table[i].mchid == mchid) {
157 mch_type = mch_table[i].name;
158 break;
159 }
160 }
161
162 printk(BIOS_DEBUG, "MCH: device id %04x (rev %02x) is %s\n",
Subrata Banikec10fbb2017-12-07 11:48:48 +0530163 mchid, mch_revision, mch_type);
164}
165
166static void report_pch_info(void)
167{
168 int i;
Elyes HAOUASc8a649c2018-06-10 23:36:44 +0200169 pci_devfn_t dev = PCH_DEV_LPC;
Subrata Banikec10fbb2017-12-07 11:48:48 +0530170 uint16_t lpcid = get_dev_id(dev);
171 const char *pch_type = "Unknown";
172
173 for (i = 0; i < ARRAY_SIZE(pch_table); i++) {
174 if (pch_table[i].lpcid == lpcid) {
175 pch_type = pch_table[i].name;
176 break;
177 }
178 }
179 printk(BIOS_DEBUG, "PCH: device id %04x (rev %02x) is %s\n",
180 lpcid, get_dev_revision(dev), pch_type);
Andrey Petrova00e1042017-06-05 13:22:59 -0700181}
182
183static void report_igd_info(void)
184{
185 int i;
Elyes HAOUASc8a649c2018-06-10 23:36:44 +0200186 pci_devfn_t dev = SA_DEV_IGD;
Subrata Banikec10fbb2017-12-07 11:48:48 +0530187 uint16_t igdid = get_dev_id(dev);
Andrey Petrova00e1042017-06-05 13:22:59 -0700188 const char *igd_type = "Unknown";
189
190 for (i = 0; i < ARRAY_SIZE(igd_table); i++) {
191 if (igd_table[i].igdid == igdid) {
192 igd_type = igd_table[i].name;
193 break;
194 }
195 }
196 printk(BIOS_DEBUG, "IGD: device id %04x (rev %02x) is %s\n",
Subrata Banikec10fbb2017-12-07 11:48:48 +0530197 igdid, get_dev_revision(dev), igd_type);
Andrey Petrova00e1042017-06-05 13:22:59 -0700198}
199
200void report_platform_info(void)
201{
202 report_cpu_info();
203 report_mch_info();
Subrata Banikec10fbb2017-12-07 11:48:48 +0530204 report_pch_info();
Andrey Petrova00e1042017-06-05 13:22:59 -0700205 report_igd_info();
206}