blob: 2bb985285a5e477a540e729cd248aa86a01977dc [file] [log] [blame]
Werner Zehfa6f8612016-04-20 10:08:17 +02001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2007-2009 coresystems GmbH
5 * Copyright (C) 2011 Google Inc.
Werner Zehf7da8922018-02-14 08:08:24 +01006 * Copyright (C) 2016-2018 Siemens AG
Werner Zehfa6f8612016-04-20 10:08:17 +02007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <types.h>
19#include <string.h>
20#include <device/device.h>
Werner Zehfa6f8612016-04-20 10:08:17 +020021#include <device/pci_def.h>
22#include <device/pci_ops.h>
Werner Zeh96b89ae2017-06-28 12:56:31 +020023#include <device/pci_ids.h>
Werner Zehf7da8922018-02-14 08:08:24 +010024#include <device/path.h>
Werner Zehfa6f8612016-04-20 10:08:17 +020025#include <console/console.h>
Julius Wernercd49cce2019-03-05 16:53:33 -080026#if CONFIG(VGA_ROM_RUN)
Werner Zehfa6f8612016-04-20 10:08:17 +020027#include <x86emu/x86emu.h>
28#endif
Kyösti Mälkki13f66502019-03-03 08:01:05 +020029#include <device/mmio.h>
Werner Zehfa6f8612016-04-20 10:08:17 +020030#include <arch/interrupt.h>
31#include <boot/coreboot_tables.h>
Werner Zehb2213ed2016-06-30 08:21:17 +020032#include <hwilib.h>
33#include <i210.h>
Werner Zehe1d6aa62016-07-06 11:59:10 +020034#include <soc/pci_devs.h>
Werner Zeha845f422016-07-07 07:10:50 +020035#include <soc/irq.h>
Werner Zeh9d18e332016-09-08 07:52:03 +020036#include <soc/lpc.h>
Werner Zehc0d1e312017-10-10 12:35:10 +020037#include <bootstate.h>
38#include <timer.h>
39#include <timestamp.h>
Werner Zehf7da8922018-02-14 08:08:24 +010040#include <pca9538.h>
Werner Zehfa6f8612016-04-20 10:08:17 +020041
Werner Zehb2213ed2016-06-30 08:21:17 +020042#define MAX_PATH_DEPTH 12
43#define MAX_NUM_MAPPINGS 10
Werner Zehe1d6aa62016-07-06 11:59:10 +020044
45/*
46 * SPI Opcode Menu setup for SPIBAR lock down
47 * should support most common flash chips.
48 */
49#define SPI_OPMENU_0 0x01 /* WRSR: Write Status Register */
50#define SPI_OPTYPE_0 0x01 /* Write, no address */
51
52#define SPI_OPMENU_1 0x02 /* BYPR: Byte Program */
53#define SPI_OPTYPE_1 0x03 /* Write, address required */
54
55#define SPI_OPMENU_2 0x03 /* READ: Read Data */
56#define SPI_OPTYPE_2 0x02 /* Read, address required */
57
58#define SPI_OPMENU_3 0x05 /* RDSR: Read Status Register */
59#define SPI_OPTYPE_3 0x00 /* Read, no address */
60
61#define SPI_OPMENU_4 0x20 /* SE20: Sector Erase 0x20 */
62#define SPI_OPTYPE_4 0x03 /* Write, address required */
63
64#define SPI_OPMENU_5 0x9f /* RDID: Read ID */
65#define SPI_OPTYPE_5 0x00 /* Read, no address */
66
67#define SPI_OPMENU_6 0xd8 /* BED8: Block Erase 0xd8 */
68#define SPI_OPTYPE_6 0x03 /* Write, address required */
69
70#define SPI_OPMENU_7 0x0b /* FAST: Fast Read */
71#define SPI_OPTYPE_7 0x02 /* Read, address required */
72
73#define SPI_OPMENU_UPPER ((SPI_OPMENU_7 << 24) | (SPI_OPMENU_6 << 16) | \
74 (SPI_OPMENU_5 << 8) | SPI_OPMENU_4)
75#define SPI_OPMENU_LOWER ((SPI_OPMENU_3 << 24) | (SPI_OPMENU_2 << 16) | \
76 (SPI_OPMENU_1 << 8) | SPI_OPMENU_0)
77
78#define SPI_OPTYPE ((SPI_OPTYPE_7 << 14) | (SPI_OPTYPE_6 << 12) | \
79 (SPI_OPTYPE_5 << 10) | (SPI_OPTYPE_4 << 8) | \
80 (SPI_OPTYPE_3 << 6) | (SPI_OPTYPE_2 << 4) | \
81 (SPI_OPTYPE_1 << 2) | (SPI_OPTYPE_0))
82
83#define SPI_OPPREFIX ((0x50 << 8) | 0x06) /* EWSR and WREN */
84
85#define SPIBAR_OFFSET 0x3800
86#define SPI_REG_PREOP 0x94
87#define SPI_REG_OPTYPE 0x96
88#define SPI_REG_OPMENU_L 0x98
89#define SPI_REG_OPMENU_H 0x9c
90
Werner Zehf7da8922018-02-14 08:08:24 +010091/* Define the slave address for the I/O expander. */
92#define PCA9538_SLAVE_ADR 0x71
Werner Zehfa6f8612016-04-20 10:08:17 +020093/*
94 * mainboard_enable is executed as first thing after enumerate_buses().
95 * This is the earliest point to add customization.
96 */
Elyes HAOUAS47503cd2018-05-04 21:58:51 +020097static void mainboard_enable(struct device *dev)
Werner Zehfa6f8612016-04-20 10:08:17 +020098{
99
100}
Werner Zehe1d6aa62016-07-06 11:59:10 +0200101
Werner Zeha845f422016-07-07 07:10:50 +0200102static void mainboard_init(void *chip_info)
103{
104 uint8_t actl = 0;
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300105 struct device *dev = pcidev_on_root(LPC_DEV, LPC_FUNC);
Werner Zeha845f422016-07-07 07:10:50 +0200106
107 /* Route SCI to IRQ 10 to free IRQ 9 slot. */
108 actl = pci_read_config8(dev, ACPI_CNTL_OFFSET);
109 actl &= ~SCIS_MASK;
110 actl |= SCIS_IRQ10;
111 pci_write_config8(dev, ACPI_CNTL_OFFSET, actl);
Werner Zeh9d18e332016-09-08 07:52:03 +0200112
113 /* Enable additional I/O decoding ranges on LPC for COM 3 and COM 4 */
114 pci_write_config32(dev, LPC_GEN1_DEC, 0x1C02E9);
115 pci_write_config32(dev, LPC_GEN2_DEC, 0x1C03E9);
Werner Zeha845f422016-07-07 07:10:50 +0200116}
117
Werner Zehe1d6aa62016-07-06 11:59:10 +0200118static void mainboard_final(void *chip_info)
119{
120 void *spi_base = NULL;
121 uint32_t rcba = 0;
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300122 struct device *dev = pcidev_on_root(LPC_DEV, LPC_FUNC);
Werner Zehe1d6aa62016-07-06 11:59:10 +0200123
124 /* Get address of SPI controller. */
125 rcba = (pci_read_config32(dev, 0xf0) & 0xffffc000);
126 if (!rcba)
127 return;
128 spi_base = (void *)(rcba + SPIBAR_OFFSET);
129 /* Setup OPCODE menu */
130 write16((spi_base + SPI_REG_PREOP), SPI_OPPREFIX);
131 write16((spi_base + SPI_REG_OPTYPE), SPI_OPTYPE);
132 write32((spi_base + SPI_REG_OPMENU_L), SPI_OPMENU_LOWER);
133 write32((spi_base + SPI_REG_OPMENU_H), SPI_OPMENU_UPPER);
Werner Zeh96b89ae2017-06-28 12:56:31 +0200134
135 /* Set Master Enable for on-board PCI devices. */
136 dev = dev_find_device(PCI_VENDOR_ID_SIEMENS, 0x403e, 0);
137 if (dev) {
138 uint16_t cmd = pci_read_config16(dev, PCI_COMMAND);
139 cmd |= PCI_COMMAND_MASTER;
140 pci_write_config16(dev, PCI_COMMAND, cmd);
141 }
142 dev = dev_find_device(PCI_VENDOR_ID_SIEMENS, 0x403f, 0);
143 if (dev) {
144 uint16_t cmd = pci_read_config16(dev, PCI_COMMAND);
145 cmd |= PCI_COMMAND_MASTER;
146 pci_write_config16(dev, PCI_COMMAND, cmd);
147 }
Werner Zehf7da8922018-02-14 08:08:24 +0100148 /* Show the mainboard version well-visible on console. */
149 printk(BIOS_NOTICE, "***************************\n"
150 "* Mainboard version: 0x%02x *\n"
151 "***************************\n",
152 pca9538_read_input());
Werner Zehe1d6aa62016-07-06 11:59:10 +0200153}
154
Werner Zehb2213ed2016-06-30 08:21:17 +0200155/** \brief This function can decide if a given MAC address is valid or not.
156 * Currently, addresses filled with 0xff or 0x00 are not valid.
157 * @param mac Buffer to the MAC address to check
158 * @return 0 if address is not valid, otherwise 1
159 */
160static uint8_t is_mac_adr_valid(uint8_t mac[6])
161{
162 uint8_t buf[6];
163
164 memset(buf, 0, sizeof(buf));
165 if (!memcmp(buf, mac, sizeof(buf)))
166 return 0;
167 memset(buf, 0xff, sizeof(buf));
168 if (!memcmp(buf, mac, sizeof(buf)))
169 return 0;
170 return 1;
171}
172 /** \brief This function will search for a MAC address which can be assigned
173 * to a MACPHY.
174 * @param dev pointer to PCI device
175 * @param mac buffer where to store the MAC address
176 * @return cb_err CB_ERR or CB_SUCCESS
177 */
178enum cb_err mainboard_get_mac_address(struct device *dev, uint8_t mac[6])
179{
180 struct bus *parent = dev->bus;
181 uint8_t buf[16], mapping[16], i = 0, chain_len = 0;
182
183 memset(buf, 0, sizeof(buf));
184 memset(mapping, 0, sizeof(mapping));
185
186 /* The first entry in the tree is the device itself. */
187 buf[0] = dev->path.pci.devfn;
188 chain_len = 1;
189 for (i = 1; i < MAX_PATH_DEPTH && parent->dev->bus->subordinate; i++) {
190 buf[i] = parent->dev->path.pci.devfn;
191 chain_len++;
192 parent = parent->dev->bus;
193 }
194 if (i == MAX_PATH_DEPTH) {
195 /* The path is deeper than MAX_PATH_DEPTH devices, error. */
196 printk(BIOS_ERR, "Too many bridges for %s\n", dev_path(dev));
197 return CB_ERR;
198 }
199 /* Now construct the mapping based on the device chain starting from */
200 /* root bridge device to the device itself. */
201 mapping[0] = 1;
202 mapping[1] = chain_len;
203 for (i = 0; i < chain_len; i++)
204 mapping[i + 4] = buf[chain_len - i - 1];
205
206 /* Open main hwinfo block */
207 if (hwilib_find_blocks("hwinfo.hex") != CB_SUCCESS)
208 return CB_ERR;
209 /* Now try to find a valid MAC address in hwinfo for this mapping.*/
210 for (i = 0; i < MAX_NUM_MAPPINGS; i++) {
211 if ((hwilib_get_field(XMac1Mapping + i, buf, 16) == 16) &&
212 !(memcmp(buf, mapping, chain_len + 4))) {
213 /* There is a matching mapping available, get MAC address. */
214 if ((hwilib_get_field(XMac1 + i, mac, 6) == 6) &&
215 (is_mac_adr_valid(mac))) {
216 return CB_SUCCESS;
217 } else {
218 return CB_ERR;
219 }
220 } else
221 continue;
222 }
223 /* No MAC address found for */
224 return CB_ERR;
225}
Werner Zehfa6f8612016-04-20 10:08:17 +0200226
Werner Zehc0d1e312017-10-10 12:35:10 +0200227static void wait_for_legacy_dev(void *unused)
228{
229 uint32_t legacy_delay, us_since_boot;
230 struct stopwatch sw;
231
232 /* Open main hwinfo block. */
233 if (hwilib_find_blocks("hwinfo.hex") != CB_SUCCESS)
234 return;
235
236 /* Get legacy delay parameter from hwinfo. */
237 if (hwilib_get_field(LegacyDelay, (uint8_t *) &legacy_delay,
238 sizeof(legacy_delay)) != sizeof(legacy_delay))
239 return;
240
241 us_since_boot = get_us_since_boot();
242 /* No need to wait if the time since boot is already long enough.*/
243 if (us_since_boot > legacy_delay)
244 return;
245 stopwatch_init_msecs_expire(&sw, (legacy_delay - us_since_boot) / 1000);
246 printk(BIOS_NOTICE, "Wait remaining %d of %d us for legacy devices...",
247 legacy_delay - us_since_boot, legacy_delay);
248 stopwatch_wait_until_expired(&sw);
249 printk(BIOS_NOTICE, "done!\n");
250}
251
Werner Zehf7da8922018-02-14 08:08:24 +0100252/*
253 * To access the I/O expander PCA9538 we need to know its device structure.
254 * This function will provide it as mainboard code has the knowledge of the
255 * right I2C slave address for the I/O expander.
256 */
257struct device *pca9538_get_dev(void)
258{
259 struct device *dev = NULL;
Werner Zeh5ea714a2018-02-19 09:49:52 +0100260
261 while ((dev = dev_find_path(dev, DEVICE_PATH_I2C))) {
Werner Zehf7da8922018-02-14 08:08:24 +0100262 if (dev->path.i2c.device == PCA9538_SLAVE_ADR)
263 break;
Werner Zeh5ea714a2018-02-19 09:49:52 +0100264 }
Werner Zehf7da8922018-02-14 08:08:24 +0100265 return dev;
266}
267
268
Werner Zehc0d1e312017-10-10 12:35:10 +0200269BOOT_STATE_INIT_ENTRY(BS_DEV_ENUMERATE, BS_ON_ENTRY, wait_for_legacy_dev, NULL);
270
Werner Zehfa6f8612016-04-20 10:08:17 +0200271struct chip_operations mainboard_ops = {
272 .enable_dev = mainboard_enable,
Werner Zeha845f422016-07-07 07:10:50 +0200273 .init = mainboard_init,
Werner Zehe1d6aa62016-07-06 11:59:10 +0200274 .final = mainboard_final
Werner Zehfa6f8612016-04-20 10:08:17 +0200275};