blob: d8374fc2a4b5cc862ba2ecc257bc2996301b08f9 [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 Scheithauer480eab02017-02-16 13:39:16 +010021#include <hwilib.h>
22#include <i210.h>
Ravi Sarawadiefa606b2017-08-04 16:26:09 -070023#include <intelblocks/lpc_lib.h>
24#include <soc/pci_devs.h>
25#include <string.h>
Mario Scheithauer2d981202017-03-27 13:25:57 +020026#include "brd_gpio.h"
Mario Scheithauer956a9f62017-03-29 17:09:37 +020027#include "ptn3460.h"
Mario Scheithauer480eab02017-02-16 13:39:16 +010028
29#define MAX_PATH_DEPTH 12
30#define MAX_NUM_MAPPINGS 10
31
32/** \brief This function can decide if a given MAC address is valid or not.
33 * Currently, addresses filled with 0xff or 0x00 are not valid.
34 * @param mac Buffer to the MAC address to check
35 * @return 0 if address is not valid, otherwise 1
36 */
37static uint8_t is_mac_adr_valid(uint8_t mac[6])
38{
39 uint8_t buf[6];
40
41 memset(buf, 0, sizeof(buf));
42 if (!memcmp(buf, mac, sizeof(buf)))
43 return 0;
44 memset(buf, 0xff, sizeof(buf));
45 if (!memcmp(buf, mac, sizeof(buf)))
46 return 0;
47 return 1;
48}
49
50/** \brief This function will search for a MAC address which can be assigned
51 * to a MACPHY.
52 * @param dev pointer to PCI device
53 * @param mac buffer where to store the MAC address
54 * @return cb_err CB_ERR or CB_SUCCESS
55 */
56enum cb_err mainboard_get_mac_address(struct device *dev, uint8_t mac[6])
57{
58 struct bus *parent = dev->bus;
59 uint8_t buf[16], mapping[16], i = 0, chain_len = 0;
60
61 memset(buf, 0, sizeof(buf));
62 memset(mapping, 0, sizeof(mapping));
63
64 /* The first entry in the tree is the device itself. */
65 buf[0] = dev->path.pci.devfn;
66 chain_len = 1;
67 for (i = 1; i < MAX_PATH_DEPTH && parent->dev->bus->subordinate; i++) {
68 buf[i] = parent->dev->path.pci.devfn;
69 chain_len++;
70 parent = parent->dev->bus;
71 }
72 if (i == MAX_PATH_DEPTH) {
73 /* The path is deeper than MAX_PATH_DEPTH devices, error. */
74 printk(BIOS_ERR, "Too many bridges for %s\n", dev_path(dev));
75 return CB_ERR;
76 }
77 /*
78 * Now construct the mapping based on the device chain starting from
79 * root bridge device to the device itself.
80 */
81 mapping[0] = 1;
82 mapping[1] = chain_len;
83 for (i = 0; i < chain_len; i++)
84 mapping[i + 4] = buf[chain_len - i - 1];
85
86 /* Open main hwinfo block */
87 if (hwilib_find_blocks("hwinfo.hex") != CB_SUCCESS)
88 return CB_ERR;
89 /* Now try to find a valid MAC address in hwinfo for this mapping.*/
90 for (i = 0; i < MAX_NUM_MAPPINGS; i++) {
91 if ((hwilib_get_field(XMac1Mapping + i, buf, 16) == 16) &&
92 !(memcmp(buf, mapping, chain_len + 4))) {
93 /* There is a matching mapping available, get MAC address. */
94 if ((hwilib_get_field(XMac1 + i, mac, 6) == 6) &&
95 (is_mac_adr_valid(mac))) {
96 return CB_SUCCESS;
97 } else {
98 return CB_ERR;
99 }
100 } else
101 continue;
102 }
103 /* No MAC address found for */
104 return CB_ERR;
105}
Mario Scheithauer092db952017-01-31 15:45:13 +0100106
107static void mainboard_init(void *chip_info)
108{
Mario Scheithauer2d981202017-03-27 13:25:57 +0200109 const struct pad_config *pads;
110 size_t num;
111
112 pads = brd_gpio_table(&num);
113 gpio_configure_pads(pads, num);
Mario Scheithauer092db952017-01-31 15:45:13 +0100114}
115
Mario Scheithauer956a9f62017-03-29 17:09:37 +0200116static void mainboard_final(void *chip_info)
117{
118 int status;
Mario Scheithauerb83858a2017-09-05 15:32:49 +0200119 uint16_t cmd = 0;
120 device_t dev = NULL;
Mario Scheithauer956a9f62017-03-29 17:09:37 +0200121
122 /**
123 * Set up the DP2LVDS converter.
124 * ptn3460_init() may only be executed after i2c bus init.
125 */
126 status = ptn3460_init("hwinfo.hex");
127 if (status)
128 printk(BIOS_ERR, "LCD: Set up PTN with status 0x%x\n", status);
129 else
130 printk(BIOS_INFO, "LCD: Set up PTN was successful.\n");
Mario Scheithauer71dacac2017-06-21 12:42:10 +0200131
132 /* Enable additional I/O decoding range on LPC for COM 3 */
133 lpc_open_pmio_window(0x3e8, 8);
Mario Scheithauerb83858a2017-09-05 15:32:49 +0200134
135 /* Set Master Enable for on-board PCI device. */
136 dev = dev_find_device(PCI_VENDOR_ID_SIEMENS, 0x403f, 0);
137 if (dev) {
138 cmd = pci_read_config16(dev, PCI_COMMAND);
139 cmd |= PCI_COMMAND_MASTER;
140 pci_write_config16(dev, PCI_COMMAND, cmd);
141 }
Mario Scheithauer956a9f62017-03-29 17:09:37 +0200142}
143
Mario Scheithauer092db952017-01-31 15:45:13 +0100144struct chip_operations mainboard_ops = {
145 .init = mainboard_init,
Mario Scheithauer956a9f62017-03-29 17:09:37 +0200146 .final = mainboard_final,
Mario Scheithauer092db952017-01-31 15:45:13 +0100147};