blob: ec110d87a5e884fb23c91131dd255ddeb8c85613 [file] [log] [blame]
Mario Scheithauer092db952017-01-31 15:45:13 +01001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2016 Google Inc.
Mario Scheithauerd127be12018-04-23 10:55:39 +02005 * Copyright (C) 2017-2018 Siemens AG
Mario Scheithauer092db952017-01-31 15:45:13 +01006 *
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
Ravi Sarawadiefa606b2017-08-04 16:26:09 -070017#include <console/console.h>
Mario Scheithauer0af272c2018-04-10 12:40:11 +020018#include <delay.h>
Mario Scheithauer092db952017-01-31 15:45:13 +010019#include <device/device.h>
Mario Scheithauerb83858a2017-09-05 15:32:49 +020020#include <device/pci.h>
21#include <device/pci_ids.h>
Mario Scheithauerdda58a22017-10-23 14:37:14 +020022#include <gpio.h>
Mario Scheithauer480eab02017-02-16 13:39:16 +010023#include <hwilib.h>
24#include <i210.h>
Mario Scheithauer0af272c2018-04-10 12:40:11 +020025#include <intelblocks/cpulib.h>
Ravi Sarawadiefa606b2017-08-04 16:26:09 -070026#include <intelblocks/lpc_lib.h>
Mario Scheithauerd9583002017-10-23 16:10:04 +020027#include <intelblocks/pcr.h>
Mario Scheithauer0af272c2018-04-10 12:40:11 +020028#include <intelblocks/systemagent.h>
Ravi Sarawadiefa606b2017-08-04 16:26:09 -070029#include <soc/pci_devs.h>
Mario Scheithauerd9583002017-10-23 16:10:04 +020030#include <soc/pcr_ids.h>
Ravi Sarawadiefa606b2017-08-04 16:26:09 -070031#include <string.h>
Werner Zehefd0eb32017-09-12 08:58:44 +020032#include <bootstate.h>
33#include <timer.h>
34#include <timestamp.h>
Mario Scheithauerd127be12018-04-23 10:55:39 +020035#include <baseboard/variants.h>
Mario Scheithauer956a9f62017-03-29 17:09:37 +020036#include "ptn3460.h"
Mario Scheithauer480eab02017-02-16 13:39:16 +010037
38#define MAX_PATH_DEPTH 12
39#define MAX_NUM_MAPPINGS 10
40
Mario Scheithauer0af272c2018-04-10 12:40:11 +020041#define BIOS_MAILBOX_WAIT_MAX_MS 1000
42#define BIOS_MAILBOX_DATA 0x7080
43#define BIOS_MAILBOX_INTERFACE 0x7084
44#define RUN_BUSY_STS (1 << 31)
45
Mario Scheithauer480eab02017-02-16 13:39:16 +010046/** \brief This function can decide if a given MAC address is valid or not.
47 * Currently, addresses filled with 0xff or 0x00 are not valid.
48 * @param mac Buffer to the MAC address to check
49 * @return 0 if address is not valid, otherwise 1
50 */
51static uint8_t is_mac_adr_valid(uint8_t mac[6])
52{
53 uint8_t buf[6];
54
55 memset(buf, 0, sizeof(buf));
56 if (!memcmp(buf, mac, sizeof(buf)))
57 return 0;
58 memset(buf, 0xff, sizeof(buf));
59 if (!memcmp(buf, mac, sizeof(buf)))
60 return 0;
61 return 1;
62}
63
64/** \brief This function will search for a MAC address which can be assigned
65 * to a MACPHY.
66 * @param dev pointer to PCI device
67 * @param mac buffer where to store the MAC address
68 * @return cb_err CB_ERR or CB_SUCCESS
69 */
70enum cb_err mainboard_get_mac_address(struct device *dev, uint8_t mac[6])
71{
72 struct bus *parent = dev->bus;
73 uint8_t buf[16], mapping[16], i = 0, chain_len = 0;
74
75 memset(buf, 0, sizeof(buf));
76 memset(mapping, 0, sizeof(mapping));
77
78 /* The first entry in the tree is the device itself. */
79 buf[0] = dev->path.pci.devfn;
80 chain_len = 1;
81 for (i = 1; i < MAX_PATH_DEPTH && parent->dev->bus->subordinate; i++) {
82 buf[i] = parent->dev->path.pci.devfn;
83 chain_len++;
84 parent = parent->dev->bus;
85 }
86 if (i == MAX_PATH_DEPTH) {
87 /* The path is deeper than MAX_PATH_DEPTH devices, error. */
88 printk(BIOS_ERR, "Too many bridges for %s\n", dev_path(dev));
89 return CB_ERR;
90 }
91 /*
92 * Now construct the mapping based on the device chain starting from
93 * root bridge device to the device itself.
94 */
95 mapping[0] = 1;
96 mapping[1] = chain_len;
97 for (i = 0; i < chain_len; i++)
98 mapping[i + 4] = buf[chain_len - i - 1];
99
100 /* Open main hwinfo block */
101 if (hwilib_find_blocks("hwinfo.hex") != CB_SUCCESS)
102 return CB_ERR;
103 /* Now try to find a valid MAC address in hwinfo for this mapping.*/
104 for (i = 0; i < MAX_NUM_MAPPINGS; i++) {
105 if ((hwilib_get_field(XMac1Mapping + i, buf, 16) == 16) &&
106 !(memcmp(buf, mapping, chain_len + 4))) {
107 /* There is a matching mapping available, get MAC address. */
108 if ((hwilib_get_field(XMac1 + i, mac, 6) == 6) &&
109 (is_mac_adr_valid(mac))) {
110 return CB_SUCCESS;
111 } else {
112 return CB_ERR;
113 }
114 } else
115 continue;
116 }
117 /* No MAC address found for */
118 return CB_ERR;
119}
Mario Scheithauer092db952017-01-31 15:45:13 +0100120
Mario Scheithauer0af272c2018-04-10 12:40:11 +0200121/** \brief This function fixes an accuracy issue with IDT PMIC.
122 * The current reported system power consumption is higher than the
123 * actual consumption. With a correction of slope and offset for Vcc
124 * and Vnn, the issue is solved.
125 */
126static void config_pmic_imon(void)
127{
128 struct stopwatch sw;
129 uint32_t power_max;
130
131 printk(BIOS_DEBUG, "PMIC: Configure PMIC IMON - Start\n");
132
133 /* Calculate CPU TDP in mW */
134 power_max = cpu_get_power_max();
135 printk(BIOS_INFO, "PMIC: CPU TDP %d mW.\n", power_max);
136
137 /*
138 * Fix Vnn slope and offset value.
139 * slope = 0x4a4 # 2.32
140 * offset = 0xfa0d # -2.975
141 */
142 stopwatch_init_msecs_expire(&sw, BIOS_MAILBOX_WAIT_MAX_MS);
143 /* Read P_CR_BIOS_MAILBOX_INTERFACE_0_0_0_MCHBAR and check RUN_BUSY. */
144 while ((MCHBAR32(BIOS_MAILBOX_INTERFACE) & RUN_BUSY_STS)) {
145 if (stopwatch_expired(&sw)) {
146 printk(BIOS_ERR, "PMIC: Power consumption measurement "
147 "setup fails for Vnn.\n");
148 return;
149 }
150 }
151 /* Set Vnn values into P_CR_BIOS_MAILBOX_DATA_0_0_0_MCHBAR. */
152 MCHBAR32(BIOS_MAILBOX_DATA) = 0xfa0d04a4;
153 /* Set command, address and busy bit. */
154 MCHBAR32(BIOS_MAILBOX_INTERFACE) = 0x8000011d;
155 printk(BIOS_DEBUG, "PMIC: Fix Vnn slope and offset value.\n");
156
157 /*
158 * Fix Vcc slope and offset value.
159 * Premium and High SKU:
160 * slope = 0x466 # 2.2
161 * offset = 0xe833 # -11.9
162 * Low and Intermediate SKU:
163 * slope = 0x3b3 # 1.85
164 * offset = 0xed33 # -9.4
165 */
166 stopwatch_init_msecs_expire(&sw, BIOS_MAILBOX_WAIT_MAX_MS);
167 while ((MCHBAR32(BIOS_MAILBOX_INTERFACE) & RUN_BUSY_STS)) {
168 if (stopwatch_expired(&sw)) {
169 printk(BIOS_ERR, "PMIC: Power consumption measurement "
170 "setup fails for Vcc.\n");
171 return;
172 }
173 }
174
175 /*
176 * CPU TDP limit between Premium/High and Low/Intermediate SKU
177 * is 9010 mW.
178 */
179 if (power_max > 9010) {
180 MCHBAR32(BIOS_MAILBOX_DATA) = 0xe8330466;
181 MCHBAR32(BIOS_MAILBOX_INTERFACE) = 0x8000001d;
182 printk(BIOS_INFO, "PMIC: Fix Vcc for Premium SKU.\n");
183 } else {
184 MCHBAR32(BIOS_MAILBOX_DATA) = 0xed3303b3;
185 MCHBAR32(BIOS_MAILBOX_INTERFACE) = 0x8000001d;
186 printk(BIOS_INFO, "PMIC: Fix Vcc for Low SKU.\n");
187 }
188
189 printk(BIOS_DEBUG, "PMIC: Configure PMIC IMON - End\n");
190}
191
Mario Scheithauer092db952017-01-31 15:45:13 +0100192static void mainboard_init(void *chip_info)
193{
Mario Scheithauer2d981202017-03-27 13:25:57 +0200194 const struct pad_config *pads;
195 size_t num;
196
Mario Scheithauerd127be12018-04-23 10:55:39 +0200197 pads = variant_gpio_table(&num);
Mario Scheithauer2d981202017-03-27 13:25:57 +0200198 gpio_configure_pads(pads, num);
Mario Scheithauer0af272c2018-04-10 12:40:11 +0200199
200 config_pmic_imon();
Mario Scheithauer092db952017-01-31 15:45:13 +0100201}
202
Mario Scheithauer956a9f62017-03-29 17:09:37 +0200203static void mainboard_final(void *chip_info)
204{
205 int status;
Mario Scheithauerb83858a2017-09-05 15:32:49 +0200206 uint16_t cmd = 0;
207 device_t dev = NULL;
Mario Scheithauer956a9f62017-03-29 17:09:37 +0200208
Mario Scheithauer0af272c2018-04-10 12:40:11 +0200209 /*
Mario Scheithauer956a9f62017-03-29 17:09:37 +0200210 * Set up the DP2LVDS converter.
211 * ptn3460_init() may only be executed after i2c bus init.
212 */
213 status = ptn3460_init("hwinfo.hex");
214 if (status)
215 printk(BIOS_ERR, "LCD: Set up PTN with status 0x%x\n", status);
216 else
217 printk(BIOS_INFO, "LCD: Set up PTN was successful.\n");
Mario Scheithauer71dacac2017-06-21 12:42:10 +0200218
219 /* Enable additional I/O decoding range on LPC for COM 3 */
220 lpc_open_pmio_window(0x3e8, 8);
Mario Scheithauerb83858a2017-09-05 15:32:49 +0200221
222 /* Set Master Enable for on-board PCI device. */
223 dev = dev_find_device(PCI_VENDOR_ID_SIEMENS, 0x403f, 0);
224 if (dev) {
225 cmd = pci_read_config16(dev, PCI_COMMAND);
226 cmd |= PCI_COMMAND_MASTER;
227 pci_write_config16(dev, PCI_COMMAND, cmd);
228 }
Mario Scheithauerd9583002017-10-23 16:10:04 +0200229
230 /*
231 * PIR6 register mapping for PCIe root ports
232 * INTA#->PIRQB#, INTB#->PIRQC#, INTC#->PIRQD#, INTD#-> PIRQA#
233 */
234 pcr_write16(PID_ITSS, 0x314c, 0x0321);
Mario Scheithauer956a9f62017-03-29 17:09:37 +0200235}
236
Werner Zehefd0eb32017-09-12 08:58:44 +0200237static void wait_for_legacy_dev(void *unused)
238{
239 uint32_t legacy_delay, us_since_boot;
240 struct stopwatch sw;
241
242 /* Open main hwinfo block. */
243 if (hwilib_find_blocks("hwinfo.hex") != CB_SUCCESS)
244 return;
245
246 /* Get legacy delay parameter from hwinfo. */
247 if (hwilib_get_field(LegacyDelay, (uint8_t *) &legacy_delay,
248 sizeof(legacy_delay)) != sizeof(legacy_delay))
249 return;
250
251 us_since_boot = get_us_since_boot();
252 /* No need to wait if the time since boot is already long enough.*/
253 if (us_since_boot > legacy_delay)
254 return;
255 stopwatch_init_msecs_expire(&sw, (legacy_delay - us_since_boot) / 1000);
256 printk(BIOS_NOTICE, "Wait remaining %d of %d us for legacy devices...",
257 legacy_delay - us_since_boot, legacy_delay);
Jonathan Neuschäferc9660752017-09-19 15:19:54 +0200258 stopwatch_wait_until_expired(&sw);
Werner Zehefd0eb32017-09-12 08:58:44 +0200259 printk(BIOS_NOTICE, "done!\n");
260}
261
Mario Scheithauerdda58a22017-10-23 14:37:14 +0200262static void finalize_boot(void *unused)
263{
264 /* Set coreboot ready LED. */
265 gpio_output(CNV_RGI_DT, 1);
266}
267
Werner Zehefd0eb32017-09-12 08:58:44 +0200268BOOT_STATE_INIT_ENTRY(BS_DEV_ENUMERATE, BS_ON_ENTRY, wait_for_legacy_dev, NULL);
Mario Scheithauerdda58a22017-10-23 14:37:14 +0200269BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, finalize_boot, NULL);
Werner Zehefd0eb32017-09-12 08:58:44 +0200270
Mario Scheithauer092db952017-01-31 15:45:13 +0100271struct chip_operations mainboard_ops = {
272 .init = mainboard_init,
Mario Scheithauer956a9f62017-03-29 17:09:37 +0200273 .final = mainboard_final,
Mario Scheithauer092db952017-01-31 15:45:13 +0100274};