blob: 692a076ee69482b8631c1fb131a7acb7959222ee [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
17#include <device/device.h>
Mario Scheithauer480eab02017-02-16 13:39:16 +010018#include <console/console.h>
19#include <string.h>
20#include <hwilib.h>
21#include <i210.h>
Mario Scheithauer2d981202017-03-27 13:25:57 +020022#include "brd_gpio.h"
Mario Scheithauer480eab02017-02-16 13:39:16 +010023
24#define MAX_PATH_DEPTH 12
25#define MAX_NUM_MAPPINGS 10
26
27/** \brief This function can decide if a given MAC address is valid or not.
28 * Currently, addresses filled with 0xff or 0x00 are not valid.
29 * @param mac Buffer to the MAC address to check
30 * @return 0 if address is not valid, otherwise 1
31 */
32static uint8_t is_mac_adr_valid(uint8_t mac[6])
33{
34 uint8_t buf[6];
35
36 memset(buf, 0, sizeof(buf));
37 if (!memcmp(buf, mac, sizeof(buf)))
38 return 0;
39 memset(buf, 0xff, sizeof(buf));
40 if (!memcmp(buf, mac, sizeof(buf)))
41 return 0;
42 return 1;
43}
44
45/** \brief This function will search for a MAC address which can be assigned
46 * to a MACPHY.
47 * @param dev pointer to PCI device
48 * @param mac buffer where to store the MAC address
49 * @return cb_err CB_ERR or CB_SUCCESS
50 */
51enum cb_err mainboard_get_mac_address(struct device *dev, uint8_t mac[6])
52{
53 struct bus *parent = dev->bus;
54 uint8_t buf[16], mapping[16], i = 0, chain_len = 0;
55
56 memset(buf, 0, sizeof(buf));
57 memset(mapping, 0, sizeof(mapping));
58
59 /* The first entry in the tree is the device itself. */
60 buf[0] = dev->path.pci.devfn;
61 chain_len = 1;
62 for (i = 1; i < MAX_PATH_DEPTH && parent->dev->bus->subordinate; i++) {
63 buf[i] = parent->dev->path.pci.devfn;
64 chain_len++;
65 parent = parent->dev->bus;
66 }
67 if (i == MAX_PATH_DEPTH) {
68 /* The path is deeper than MAX_PATH_DEPTH devices, error. */
69 printk(BIOS_ERR, "Too many bridges for %s\n", dev_path(dev));
70 return CB_ERR;
71 }
72 /*
73 * Now construct the mapping based on the device chain starting from
74 * root bridge device to the device itself.
75 */
76 mapping[0] = 1;
77 mapping[1] = chain_len;
78 for (i = 0; i < chain_len; i++)
79 mapping[i + 4] = buf[chain_len - i - 1];
80
81 /* Open main hwinfo block */
82 if (hwilib_find_blocks("hwinfo.hex") != CB_SUCCESS)
83 return CB_ERR;
84 /* Now try to find a valid MAC address in hwinfo for this mapping.*/
85 for (i = 0; i < MAX_NUM_MAPPINGS; i++) {
86 if ((hwilib_get_field(XMac1Mapping + i, buf, 16) == 16) &&
87 !(memcmp(buf, mapping, chain_len + 4))) {
88 /* There is a matching mapping available, get MAC address. */
89 if ((hwilib_get_field(XMac1 + i, mac, 6) == 6) &&
90 (is_mac_adr_valid(mac))) {
91 return CB_SUCCESS;
92 } else {
93 return CB_ERR;
94 }
95 } else
96 continue;
97 }
98 /* No MAC address found for */
99 return CB_ERR;
100}
Mario Scheithauer092db952017-01-31 15:45:13 +0100101
102static void mainboard_init(void *chip_info)
103{
Mario Scheithauer2d981202017-03-27 13:25:57 +0200104 const struct pad_config *pads;
105 size_t num;
106
107 pads = brd_gpio_table(&num);
108 gpio_configure_pads(pads, num);
Mario Scheithauer092db952017-01-31 15:45:13 +0100109}
110
111struct chip_operations mainboard_ops = {
112 .init = mainboard_init,
113};