blob: fd19cd13aeceb939981a3cb73ceeff20a41aa761 [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 Scheithauer480eab02017-02-16 13:39:16 +01005 * Copyright (C) 2017 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 Scheithauer092db952017-01-31 15:45:13 +010018#include <device/device.h>
Mario Scheithauerb83858a2017-09-05 15:32:49 +020019#include <device/pci.h>
20#include <device/pci_ids.h>
Mario Scheithauerdda58a22017-10-23 14:37:14 +020021#include <gpio.h>
Mario Scheithauer480eab02017-02-16 13:39:16 +010022#include <hwilib.h>
23#include <i210.h>
Ravi Sarawadiefa606b2017-08-04 16:26:09 -070024#include <intelblocks/lpc_lib.h>
Mario Scheithauerd9583002017-10-23 16:10:04 +020025#include <intelblocks/pcr.h>
Ravi Sarawadiefa606b2017-08-04 16:26:09 -070026#include <soc/pci_devs.h>
Mario Scheithauerd9583002017-10-23 16:10:04 +020027#include <soc/pcr_ids.h>
Ravi Sarawadiefa606b2017-08-04 16:26:09 -070028#include <string.h>
Werner Zehefd0eb32017-09-12 08:58:44 +020029#include <bootstate.h>
30#include <timer.h>
31#include <timestamp.h>
Mario Scheithauer2d981202017-03-27 13:25:57 +020032#include "brd_gpio.h"
Mario Scheithauer956a9f62017-03-29 17:09:37 +020033#include "ptn3460.h"
Mario Scheithauer480eab02017-02-16 13:39:16 +010034
35#define MAX_PATH_DEPTH 12
36#define MAX_NUM_MAPPINGS 10
37
38/** \brief This function can decide if a given MAC address is valid or not.
39 * Currently, addresses filled with 0xff or 0x00 are not valid.
40 * @param mac Buffer to the MAC address to check
41 * @return 0 if address is not valid, otherwise 1
42 */
43static uint8_t is_mac_adr_valid(uint8_t mac[6])
44{
45 uint8_t buf[6];
46
47 memset(buf, 0, sizeof(buf));
48 if (!memcmp(buf, mac, sizeof(buf)))
49 return 0;
50 memset(buf, 0xff, sizeof(buf));
51 if (!memcmp(buf, mac, sizeof(buf)))
52 return 0;
53 return 1;
54}
55
56/** \brief This function will search for a MAC address which can be assigned
57 * to a MACPHY.
58 * @param dev pointer to PCI device
59 * @param mac buffer where to store the MAC address
60 * @return cb_err CB_ERR or CB_SUCCESS
61 */
62enum cb_err mainboard_get_mac_address(struct device *dev, uint8_t mac[6])
63{
64 struct bus *parent = dev->bus;
65 uint8_t buf[16], mapping[16], i = 0, chain_len = 0;
66
67 memset(buf, 0, sizeof(buf));
68 memset(mapping, 0, sizeof(mapping));
69
70 /* The first entry in the tree is the device itself. */
71 buf[0] = dev->path.pci.devfn;
72 chain_len = 1;
73 for (i = 1; i < MAX_PATH_DEPTH && parent->dev->bus->subordinate; i++) {
74 buf[i] = parent->dev->path.pci.devfn;
75 chain_len++;
76 parent = parent->dev->bus;
77 }
78 if (i == MAX_PATH_DEPTH) {
79 /* The path is deeper than MAX_PATH_DEPTH devices, error. */
80 printk(BIOS_ERR, "Too many bridges for %s\n", dev_path(dev));
81 return CB_ERR;
82 }
83 /*
84 * Now construct the mapping based on the device chain starting from
85 * root bridge device to the device itself.
86 */
87 mapping[0] = 1;
88 mapping[1] = chain_len;
89 for (i = 0; i < chain_len; i++)
90 mapping[i + 4] = buf[chain_len - i - 1];
91
92 /* Open main hwinfo block */
93 if (hwilib_find_blocks("hwinfo.hex") != CB_SUCCESS)
94 return CB_ERR;
95 /* Now try to find a valid MAC address in hwinfo for this mapping.*/
96 for (i = 0; i < MAX_NUM_MAPPINGS; i++) {
97 if ((hwilib_get_field(XMac1Mapping + i, buf, 16) == 16) &&
98 !(memcmp(buf, mapping, chain_len + 4))) {
99 /* There is a matching mapping available, get MAC address. */
100 if ((hwilib_get_field(XMac1 + i, mac, 6) == 6) &&
101 (is_mac_adr_valid(mac))) {
102 return CB_SUCCESS;
103 } else {
104 return CB_ERR;
105 }
106 } else
107 continue;
108 }
109 /* No MAC address found for */
110 return CB_ERR;
111}
Mario Scheithauer092db952017-01-31 15:45:13 +0100112
113static void mainboard_init(void *chip_info)
114{
Mario Scheithauer2d981202017-03-27 13:25:57 +0200115 const struct pad_config *pads;
116 size_t num;
117
118 pads = brd_gpio_table(&num);
119 gpio_configure_pads(pads, num);
Mario Scheithauer092db952017-01-31 15:45:13 +0100120}
121
Mario Scheithauer956a9f62017-03-29 17:09:37 +0200122static void mainboard_final(void *chip_info)
123{
124 int status;
Mario Scheithauerb83858a2017-09-05 15:32:49 +0200125 uint16_t cmd = 0;
126 device_t dev = NULL;
Mario Scheithauer956a9f62017-03-29 17:09:37 +0200127
128 /**
129 * Set up the DP2LVDS converter.
130 * ptn3460_init() may only be executed after i2c bus init.
131 */
132 status = ptn3460_init("hwinfo.hex");
133 if (status)
134 printk(BIOS_ERR, "LCD: Set up PTN with status 0x%x\n", status);
135 else
136 printk(BIOS_INFO, "LCD: Set up PTN was successful.\n");
Mario Scheithauer71dacac2017-06-21 12:42:10 +0200137
138 /* Enable additional I/O decoding range on LPC for COM 3 */
139 lpc_open_pmio_window(0x3e8, 8);
Mario Scheithauerb83858a2017-09-05 15:32:49 +0200140
141 /* Set Master Enable for on-board PCI device. */
142 dev = dev_find_device(PCI_VENDOR_ID_SIEMENS, 0x403f, 0);
143 if (dev) {
144 cmd = pci_read_config16(dev, PCI_COMMAND);
145 cmd |= PCI_COMMAND_MASTER;
146 pci_write_config16(dev, PCI_COMMAND, cmd);
147 }
Mario Scheithauerd9583002017-10-23 16:10:04 +0200148
149 /*
150 * PIR6 register mapping for PCIe root ports
151 * INTA#->PIRQB#, INTB#->PIRQC#, INTC#->PIRQD#, INTD#-> PIRQA#
152 */
153 pcr_write16(PID_ITSS, 0x314c, 0x0321);
Mario Scheithauer956a9f62017-03-29 17:09:37 +0200154}
155
Werner Zehefd0eb32017-09-12 08:58:44 +0200156static void wait_for_legacy_dev(void *unused)
157{
158 uint32_t legacy_delay, us_since_boot;
159 struct stopwatch sw;
160
161 /* Open main hwinfo block. */
162 if (hwilib_find_blocks("hwinfo.hex") != CB_SUCCESS)
163 return;
164
165 /* Get legacy delay parameter from hwinfo. */
166 if (hwilib_get_field(LegacyDelay, (uint8_t *) &legacy_delay,
167 sizeof(legacy_delay)) != sizeof(legacy_delay))
168 return;
169
170 us_since_boot = get_us_since_boot();
171 /* No need to wait if the time since boot is already long enough.*/
172 if (us_since_boot > legacy_delay)
173 return;
174 stopwatch_init_msecs_expire(&sw, (legacy_delay - us_since_boot) / 1000);
175 printk(BIOS_NOTICE, "Wait remaining %d of %d us for legacy devices...",
176 legacy_delay - us_since_boot, legacy_delay);
Jonathan Neuschäferc9660752017-09-19 15:19:54 +0200177 stopwatch_wait_until_expired(&sw);
Werner Zehefd0eb32017-09-12 08:58:44 +0200178 printk(BIOS_NOTICE, "done!\n");
179}
180
Mario Scheithauerdda58a22017-10-23 14:37:14 +0200181static void finalize_boot(void *unused)
182{
183 /* Set coreboot ready LED. */
184 gpio_output(CNV_RGI_DT, 1);
185}
186
Werner Zehefd0eb32017-09-12 08:58:44 +0200187BOOT_STATE_INIT_ENTRY(BS_DEV_ENUMERATE, BS_ON_ENTRY, wait_for_legacy_dev, NULL);
Mario Scheithauerdda58a22017-10-23 14:37:14 +0200188BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, finalize_boot, NULL);
Werner Zehefd0eb32017-09-12 08:58:44 +0200189
Mario Scheithauer092db952017-01-31 15:45:13 +0100190struct chip_operations mainboard_ops = {
191 .init = mainboard_init,
Mario Scheithauer956a9f62017-03-29 17:09:37 +0200192 .final = mainboard_final,
Mario Scheithauer092db952017-01-31 15:45:13 +0100193};