blob: 16bbf8a76be32da2f115cf2d223994572468c969 [file] [log] [blame]
Piotr Króldcd2f172016-05-27 12:04:13 +02001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2012 Advanced Micro Devices, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
Kyösti Mälkki13f66502019-03-03 08:01:05 +020016#include <device/mmio.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020017#include <device/pci_ops.h>
Piotr Króldcd2f172016-05-27 12:04:13 +020018#include <console/console.h>
Piotr Króldcd2f172016-05-27 12:04:13 +020019#include <device/device.h>
20#include <device/pci.h>
21#include <device/pci_def.h>
Piotr Króldcd2f172016-05-27 12:04:13 +020022#include <southbridge/amd/pi/hudson/hudson.h>
23#include <southbridge/amd/pi/hudson/pci_devs.h>
24#include <southbridge/amd/pi/hudson/amd_pci_int_defs.h>
25#include <northbridge/amd/pi/00730F01/pci_devs.h>
26#include <southbridge/amd/common/amd_pci_util.h>
27#include <superio/nuvoton/nct5104d/nct5104d.h>
Kyösti Mälkki10407492017-01-16 19:59:52 +020028#include <smbios.h>
29#include <string.h>
Kyösti Mälkki10407492017-01-16 19:59:52 +020030#include "gpio_ftns.h"
Piotr Króldcd2f172016-05-27 12:04:13 +020031
32#define SPD_SIZE 128
33#define PM_RTC_CONTROL 0x56
34#define PM_S_STATE_CONTROL 0xBA
35
36
37/***********************************************************
38 * These arrays set up the FCH PCI_INTR registers 0xC00/0xC01.
39 * This table is responsible for physically routing the PIC and
40 * IOAPIC IRQs to the different PCI devices on the system. It
41 * is read and written via registers 0xC00/0xC01 as an
42 * Index/Data pair. These values are chipset and mainboard
43 * dependent and should be updated accordingly.
44 *
45 * These values are used by the PCI configuration space,
46 * MP Tables. TODO: Make ACPI use these values too.
47 */
48static const u8 mainboard_picr_data[FCH_INT_TABLE_SIZE] = {
Piotr Króldcd2f172016-05-27 12:04:13 +020049 [0 ... FCH_INT_TABLE_SIZE-1] = 0x1F,
Piotr Króldcd2f172016-05-27 12:04:13 +020050 /* INTA# - INTH# */
51 [0x00] = 0x03,0x03,0x05,0x07,0x0B,0x0A,0x1F,0x1F,
52 /* Misc-nil,0,1,2, INT from Serial irq */
53 [0x08] = 0xFA,0xF1,0x00,0x00,0x1F,0x1F,0x1F,0x1F,
54 /* SCI, SMBUS0, ASF, HDA, FC, RSVD, PerMon, SD */
55 [0x10] = 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
56 [0x18] = 0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
57 /* IMC INT0 - 5 */
58 [0x20] = 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x00,0x00,
59 [0x28] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
60 /* USB Devs 18/19/22 INTA-C */
61 [0x30] = 0x05,0x1F,0x05,0x1F,0x04,0x1F,0x1F,0x1F,
62 [0x38] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
63 /* SATA */
64 [0x40] = 0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,
65 [0x48] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
66 [0x50] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
67 [0x58] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
68 [0x60] = 0x00,0x00,0x1F
69};
70
71static const u8 mainboard_intr_data[FCH_INT_TABLE_SIZE] = {
Piotr Króldcd2f172016-05-27 12:04:13 +020072 [0 ... FCH_INT_TABLE_SIZE-1] = 0x1F,
Piotr Króldcd2f172016-05-27 12:04:13 +020073 /* INTA# - INTH# */
74 [0x00] = 0x10,0x10,0x12,0x13,0x14,0x15,0x1F,0x1F,
75 /* Misc-nil,0,1,2, INT from Serial irq */
76 [0x08] = 0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F,0x1F,
77 /* SCI, SMBUS0, ASF, HDA, FC, RSVD, PerMon, SD */
78 [0x10] = 0x09,0x1F,0x1F,0x1F,0x1F,0x1f,0x1F,0x10,
79 [0x18] = 0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
80 /* IMC INT0 - 5 */
81 [0x20] = 0x05,0x1F,0x1F,0x1F,0x1F,0x1F,0x00,0x00,
82 [0x28] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
83 /* USB Devs 18/19/20/22 INTA-C */
84 [0x30] = 0x12,0x1f,0x12,0x1F,0x12,0x1F,0x1F,0x00,
85 [0x38] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
86 /* SATA */
87 [0x40] = 0x1f,0x13,0x00,0x00,0x00,0x00,0x00,0x00,
88 [0x48] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
89 [0x50] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
90 [0x58] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
91 [0x60] = 0x00,0x00,0x1F
92};
93
94/*
95 * This table defines the index into the picr/intr_data
96 * tables for each device. Any enabled device and slot
97 * that uses hardware interrupts should have an entry
98 * in this table to define its index into the FCH
99 * PCI_INTR register 0xC00/0xC01. This index will define
100 * the interrupt that it should use. Putting PIRQ_A into
101 * the PIN A index for a device will tell that device to
102 * use PIC IRQ 10 if it uses PIN A for its hardware INT.
103 */
104static const struct pirq_struct mainboard_pirq_data[] = {
105 /* {PCI_devfn, {PIN A, PIN B, PIN C, PIN D}}, */
106 {GFX_DEVFN, {PIRQ_A, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* VGA: 01.0 */
107 {ACTL_DEVFN,{PIRQ_NC, PIRQ_B, PIRQ_NC, PIRQ_NC}}, /* Audio: 01.1 */
108 {NB_PCIE_PORT1_DEVFN, {PIRQ_A, PIRQ_B, PIRQ_C, PIRQ_D}}, /* x4 PCIe: 02.1 */
109 {NB_PCIE_PORT2_DEVFN, {PIRQ_B, PIRQ_C, PIRQ_D, PIRQ_A}}, /* mPCIe: 02.2 */
110 {NB_PCIE_PORT3_DEVFN, {PIRQ_C, PIRQ_D, PIRQ_A, PIRQ_B}}, /* NIC: 02.3 */
111 {XHCI_DEVFN, {PIRQ_C, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* XHCI: 10.0 */
112 {SATA_DEVFN, {PIRQ_SATA, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* SATA: 11.0 */
113 {OHCI1_DEVFN, {PIRQ_OHCI1, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* OHCI1: 12.0 */
114 {EHCI1_DEVFN, {PIRQ_NC, PIRQ_EHCI1, PIRQ_NC, PIRQ_NC}}, /* EHCI1: 12.2 */
115 {OHCI2_DEVFN, {PIRQ_OHCI2, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* OHCI2: 13.0 */
116 {EHCI2_DEVFN, {PIRQ_NC, PIRQ_EHCI2, PIRQ_NC, PIRQ_NC}}, /* EHCI2: 13.2 */
117 {SMBUS_DEVFN, {PIRQ_SMBUS, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* SMBUS: 14.0 */
118 {HDA_DEVFN, {PIRQ_HDA, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* HDA: 14.2 */
119 {SD_DEVFN, {PIRQ_SD, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* SD: 14.7 */
120 {OHCI3_DEVFN, {PIRQ_OHCI3, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* OHCI3: 16.0 (same device as xHCI 10.0) */
121 {EHCI3_DEVFN, {PIRQ_NC, PIRQ_EHCI3, PIRQ_NC, PIRQ_NC}}, /* EHCI3: 16.2 (same device as xHCI 10.1) */
122};
123
124/* PIRQ Setup */
125static void pirq_setup(void)
126{
127 pirq_data_ptr = mainboard_pirq_data;
128 pirq_data_size = sizeof(mainboard_pirq_data) / sizeof(struct pirq_struct);
129 intr_data_ptr = mainboard_intr_data;
130 picr_data_ptr = mainboard_picr_data;
131}
132
133/* Wrapper to enable GPIO/UART devices under menuconfig. Revisit
134 * once configuration file format for SPI flash storage is complete.
135 */
136#define SIO_PORT 0x2e
137
138static void config_gpio_mux(void)
139{
140 struct device *uart, *gpio;
141
142 uart = dev_find_slot_pnp(SIO_PORT, NCT5104D_SP3);
143 gpio = dev_find_slot_pnp(SIO_PORT, NCT5104D_GPIO0);
144 if (uart)
Elyes HAOUASc1fa4402018-11-14 15:11:00 +0100145 uart->enabled = IS_ENABLED(CONFIG_APU2_PINMUX_UART_C);
Piotr Króldcd2f172016-05-27 12:04:13 +0200146 if (gpio)
Elyes HAOUASc1fa4402018-11-14 15:11:00 +0100147 gpio->enabled = IS_ENABLED(CONFIG_APU2_PINMUX_GPIO0);
Piotr Króldcd2f172016-05-27 12:04:13 +0200148
149 uart = dev_find_slot_pnp(SIO_PORT, NCT5104D_SP4);
150 gpio = dev_find_slot_pnp(SIO_PORT, NCT5104D_GPIO1);
151 if (uart)
Elyes HAOUASc1fa4402018-11-14 15:11:00 +0100152 uart->enabled = IS_ENABLED(CONFIG_APU2_PINMUX_UART_D);
Piotr Króldcd2f172016-05-27 12:04:13 +0200153 if (gpio)
Elyes HAOUASc1fa4402018-11-14 15:11:00 +0100154 gpio->enabled = IS_ENABLED(CONFIG_APU2_PINMUX_GPIO1);
Piotr Króldcd2f172016-05-27 12:04:13 +0200155}
156
157/**********************************************
158 * enable the dedicated function in mainboard.
159 **********************************************/
160
Elyes HAOUAS9adef1e2018-05-04 22:03:37 +0200161static void mainboard_enable(struct device *dev)
Piotr Króldcd2f172016-05-27 12:04:13 +0200162{
163 printk(BIOS_INFO, "Mainboard " CONFIG_MAINBOARD_PART_NUMBER " Enable.\n");
164
165 config_gpio_mux();
166
167 //
168 // Enable the RTC output
169 //
Elyes HAOUASa342f392018-10-17 10:56:26 +0200170 pm_write16(PM_RTC_CONTROL, pm_read16(PM_RTC_CONTROL) | (1 << 11));
Piotr Króldcd2f172016-05-27 12:04:13 +0200171
172 //
173 // Enable power on from WAKE#
174 //
Elyes HAOUASa342f392018-10-17 10:56:26 +0200175 pm_write16(PM_S_STATE_CONTROL, pm_read16(PM_S_STATE_CONTROL) | (1 << 14));
Piotr Króldcd2f172016-05-27 12:04:13 +0200176
Piotr Króldcd2f172016-05-27 12:04:13 +0200177 /* Initialize the PIRQ data structures for consumption */
178 pirq_setup();
179}
180
Michał Żygowski68377692018-07-30 12:31:00 +0200181static void mainboard_final(void *chip_info)
182{
183 //
184 // Turn off LED 2 and LED 3
185 //
186 write_gpio(GPIO_58, 1);
187 write_gpio(GPIO_59, 1);
188}
189
Kyösti Mälkki10407492017-01-16 19:59:52 +0200190/*
Kyösti Mälkki01bf5992017-01-16 19:50:28 +0200191 * We will stuff a modified version of the first NICs (BDF 1:0.0) MAC address
192 * into the smbios serial number location.
193 */
194const char *smbios_mainboard_serial_number(void)
195{
196 static char serial[10];
Michał Żygowski04864582018-11-26 19:47:23 +0100197 struct device *dev;
Kyösti Mälkki01bf5992017-01-16 19:50:28 +0200198 uintptr_t bar10;
199 u32 mac_addr = 0;
Michał Żygowski04864582018-11-26 19:47:23 +0100200 u32 bus_no;
Kyösti Mälkki01bf5992017-01-16 19:50:28 +0200201 int i;
202
Michał Żygowski04864582018-11-26 19:47:23 +0100203 /*
204 * In case we have PCIe module connected to mPCIe2 slot, BDF 1:0.0 may
205 * not be a NIC, because mPCIe2 slot is routed to the very first PCIe
206 * bridge and the first NIC is connected to the second PCIe bridge.
207 * Read secondary bus number from the PCIe bridge where the first NIC is
208 * connected.
209 */
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300210 dev = pcidev_on_root(2, 2);
Michał Żygowski04864582018-11-26 19:47:23 +0100211 if ((serial[0] != 0) || !dev)
212 return serial;
213
214 bus_no = dev->link_list->secondary;
215 dev = dev_find_slot(bus_no, PCI_DEVFN(0, 0));
216 if (!dev)
Kyösti Mälkki01bf5992017-01-16 19:50:28 +0200217 return serial;
218
219 /* Read in the last 3 bytes of NIC's MAC address. */
Michał Żygowski04864582018-11-26 19:47:23 +0100220 bar10 = pci_read_config32(dev, 0x10);
Kyösti Mälkki01bf5992017-01-16 19:50:28 +0200221 bar10 &= 0xFFFE0000;
222 bar10 += 0x5400;
223 for (i = 3; i < 6; i++) {
224 mac_addr <<= 8;
225 mac_addr |= read8((u8 *)bar10 + i);
226 }
227 mac_addr &= 0x00FFFFFF;
228 mac_addr /= 4;
229 mac_addr -= 64;
230
231 snprintf(serial, sizeof(serial), "%d", mac_addr);
232 return serial;
233}
234
235/*
Kyösti Mälkki10407492017-01-16 19:59:52 +0200236 * We will stuff the memory size into the smbios sku location.
237 */
238const char *smbios_mainboard_sku(void)
239{
240 static char sku[5];
241 if (sku[0] != 0)
242 return sku;
243
244 if (!get_spd_offset())
245 snprintf(sku, sizeof(sku), "2 GB");
246 else
247 snprintf(sku, sizeof(sku), "4 GB");
248 return sku;
249}
250
Piotr Króldcd2f172016-05-27 12:04:13 +0200251struct chip_operations mainboard_ops = {
252 .enable_dev = mainboard_enable,
Michał Żygowski68377692018-07-30 12:31:00 +0200253 .final = mainboard_final,
Piotr Króldcd2f172016-05-27 12:04:13 +0200254};