blob: 4fe1a121f3026a5af91ef942fc90a866feec77e9 [file] [log] [blame]
Angel Pons560796c2020-04-03 01:22:52 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Piotr Króldcd2f172016-05-27 12:04:13 +02002
Michał Żygowskif3db2ae2019-11-24 13:26:10 +01003#include <amdblocks/acpimmio.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02004#include <device/mmio.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02005#include <device/pci_ops.h>
Piotr Króldcd2f172016-05-27 12:04:13 +02006#include <console/console.h>
Piotr Króldcd2f172016-05-27 12:04:13 +02007#include <device/device.h>
Piotr Króldcd2f172016-05-27 12:04:13 +02008#include <device/pci_def.h>
Kyösti Mälkkidf84a282020-06-18 19:26:05 +03009#include <gpio.h>
Kyösti Mälkkib78e4622022-12-15 22:12:29 +020010#include <identity.h>
Piotr Króldcd2f172016-05-27 12:04:13 +020011#include <southbridge/amd/pi/hudson/hudson.h>
12#include <southbridge/amd/pi/hudson/pci_devs.h>
13#include <southbridge/amd/pi/hudson/amd_pci_int_defs.h>
Michał Żygowski16434322020-01-10 13:08:30 +010014#include <northbridge/amd/agesa/agesa_helper.h>
Piotr Króldcd2f172016-05-27 12:04:13 +020015#include <northbridge/amd/pi/00730F01/pci_devs.h>
16#include <southbridge/amd/common/amd_pci_util.h>
17#include <superio/nuvoton/nct5104d/nct5104d.h>
Kyösti Mälkki10407492017-01-16 19:59:52 +020018#include <smbios.h>
19#include <string.h>
Michał Żygowski16434322020-01-10 13:08:30 +010020#include <AGESA.h>
Kyösti Mälkki10407492017-01-16 19:59:52 +020021#include "gpio_ftns.h"
Piotr Króldcd2f172016-05-27 12:04:13 +020022
23#define SPD_SIZE 128
24#define PM_RTC_CONTROL 0x56
25#define PM_S_STATE_CONTROL 0xBA
26
Piotr Króldcd2f172016-05-27 12:04:13 +020027/***********************************************************
28 * These arrays set up the FCH PCI_INTR registers 0xC00/0xC01.
29 * This table is responsible for physically routing the PIC and
30 * IOAPIC IRQs to the different PCI devices on the system. It
31 * is read and written via registers 0xC00/0xC01 as an
32 * Index/Data pair. These values are chipset and mainboard
33 * dependent and should be updated accordingly.
34 *
35 * These values are used by the PCI configuration space,
36 * MP Tables. TODO: Make ACPI use these values too.
37 */
38static const u8 mainboard_picr_data[FCH_INT_TABLE_SIZE] = {
Piotr Króldcd2f172016-05-27 12:04:13 +020039 [0 ... FCH_INT_TABLE_SIZE-1] = 0x1F,
Piotr Króldcd2f172016-05-27 12:04:13 +020040 /* INTA# - INTH# */
41 [0x00] = 0x03,0x03,0x05,0x07,0x0B,0x0A,0x1F,0x1F,
42 /* Misc-nil,0,1,2, INT from Serial irq */
43 [0x08] = 0xFA,0xF1,0x00,0x00,0x1F,0x1F,0x1F,0x1F,
44 /* SCI, SMBUS0, ASF, HDA, FC, RSVD, PerMon, SD */
45 [0x10] = 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
46 [0x18] = 0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
47 /* IMC INT0 - 5 */
48 [0x20] = 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x00,0x00,
49 [0x28] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
50 /* USB Devs 18/19/22 INTA-C */
51 [0x30] = 0x05,0x1F,0x05,0x1F,0x04,0x1F,0x1F,0x1F,
52 [0x38] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
53 /* SATA */
54 [0x40] = 0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,
55 [0x48] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
56 [0x50] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
57 [0x58] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
58 [0x60] = 0x00,0x00,0x1F
59};
60
61static const u8 mainboard_intr_data[FCH_INT_TABLE_SIZE] = {
Piotr Króldcd2f172016-05-27 12:04:13 +020062 [0 ... FCH_INT_TABLE_SIZE-1] = 0x1F,
Piotr Króldcd2f172016-05-27 12:04:13 +020063 /* INTA# - INTH# */
64 [0x00] = 0x10,0x10,0x12,0x13,0x14,0x15,0x1F,0x1F,
65 /* Misc-nil,0,1,2, INT from Serial irq */
66 [0x08] = 0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F,0x1F,
67 /* SCI, SMBUS0, ASF, HDA, FC, RSVD, PerMon, SD */
Piotr Kleinschmidt49e0e002020-06-15 10:44:44 +020068 [0x10] = 0x09,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x10,
Piotr Króldcd2f172016-05-27 12:04:13 +020069 [0x18] = 0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
70 /* IMC INT0 - 5 */
71 [0x20] = 0x05,0x1F,0x1F,0x1F,0x1F,0x1F,0x00,0x00,
72 [0x28] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
73 /* USB Devs 18/19/20/22 INTA-C */
Piotr Kleinschmidt49e0e002020-06-15 10:44:44 +020074 [0x30] = 0x12,0x1F,0x12,0x1F,0x12,0x1F,0x1F,0x00,
Piotr Króldcd2f172016-05-27 12:04:13 +020075 [0x38] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
76 /* SATA */
Piotr Kleinschmidt49e0e002020-06-15 10:44:44 +020077 [0x40] = 0x1F,0x13,0x00,0x00,0x00,0x00,0x00,0x00,
Piotr Króldcd2f172016-05-27 12:04:13 +020078 [0x48] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
79 [0x50] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
80 [0x58] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
81 [0x60] = 0x00,0x00,0x1F
82};
83
84/*
85 * This table defines the index into the picr/intr_data
86 * tables for each device. Any enabled device and slot
87 * that uses hardware interrupts should have an entry
88 * in this table to define its index into the FCH
89 * PCI_INTR register 0xC00/0xC01. This index will define
90 * the interrupt that it should use. Putting PIRQ_A into
91 * the PIN A index for a device will tell that device to
92 * use PIC IRQ 10 if it uses PIN A for its hardware INT.
93 */
94static const struct pirq_struct mainboard_pirq_data[] = {
95 /* {PCI_devfn, {PIN A, PIN B, PIN C, PIN D}}, */
Felix Held8d8c6812023-12-21 00:11:44 +010096 {GFX_DEVFN, {PIRQ_A, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* VGA: 01.0 */
97 {ACTL_DEVFN, {PIRQ_NC, PIRQ_B, PIRQ_NC, PIRQ_NC}}, /* Audio: 01.1 */
Piotr Króldcd2f172016-05-27 12:04:13 +020098 {NB_PCIE_PORT1_DEVFN, {PIRQ_A, PIRQ_B, PIRQ_C, PIRQ_D}}, /* x4 PCIe: 02.1 */
99 {NB_PCIE_PORT2_DEVFN, {PIRQ_B, PIRQ_C, PIRQ_D, PIRQ_A}}, /* mPCIe: 02.2 */
100 {NB_PCIE_PORT3_DEVFN, {PIRQ_C, PIRQ_D, PIRQ_A, PIRQ_B}}, /* NIC: 02.3 */
Krystian Hebel59e3bb82019-03-04 13:12:32 +0100101 {NB_PCIE_PORT4_DEVFN, {PIRQ_D, PIRQ_A, PIRQ_B, PIRQ_C}}, /* 02.4 */
102 {NB_PCIE_PORT5_DEVFN, {PIRQ_A, PIRQ_B, PIRQ_C, PIRQ_D}}, /* 02.5 */
Piotr Króldcd2f172016-05-27 12:04:13 +0200103 {XHCI_DEVFN, {PIRQ_C, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* XHCI: 10.0 */
104 {SATA_DEVFN, {PIRQ_SATA, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* SATA: 11.0 */
105 {OHCI1_DEVFN, {PIRQ_OHCI1, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* OHCI1: 12.0 */
106 {EHCI1_DEVFN, {PIRQ_NC, PIRQ_EHCI1, PIRQ_NC, PIRQ_NC}}, /* EHCI1: 12.2 */
107 {OHCI2_DEVFN, {PIRQ_OHCI2, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* OHCI2: 13.0 */
108 {EHCI2_DEVFN, {PIRQ_NC, PIRQ_EHCI2, PIRQ_NC, PIRQ_NC}}, /* EHCI2: 13.2 */
109 {SMBUS_DEVFN, {PIRQ_SMBUS, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* SMBUS: 14.0 */
Felix Held8d8c6812023-12-21 00:11:44 +0100110 {HDA_DEVFN, {PIRQ_HDA, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* HDA: 14.2 */
111 {SD_DEVFN, {PIRQ_SD, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* SD: 14.7 */
Piotr Króldcd2f172016-05-27 12:04:13 +0200112 {OHCI3_DEVFN, {PIRQ_OHCI3, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* OHCI3: 16.0 (same device as xHCI 10.0) */
113 {EHCI3_DEVFN, {PIRQ_NC, PIRQ_EHCI3, PIRQ_NC, PIRQ_NC}}, /* EHCI3: 16.2 (same device as xHCI 10.1) */
114};
115
116/* PIRQ Setup */
117static void pirq_setup(void)
118{
119 pirq_data_ptr = mainboard_pirq_data;
Patrick Georgi6b688f52021-02-12 13:49:11 +0100120 pirq_data_size = ARRAY_SIZE(mainboard_pirq_data);
Piotr Króldcd2f172016-05-27 12:04:13 +0200121 intr_data_ptr = mainboard_intr_data;
122 picr_data_ptr = mainboard_picr_data;
123}
124
125/* Wrapper to enable GPIO/UART devices under menuconfig. Revisit
126 * once configuration file format for SPI flash storage is complete.
127 */
128#define SIO_PORT 0x2e
129
130static void config_gpio_mux(void)
131{
132 struct device *uart, *gpio;
133
134 uart = dev_find_slot_pnp(SIO_PORT, NCT5104D_SP3);
135 gpio = dev_find_slot_pnp(SIO_PORT, NCT5104D_GPIO0);
136 if (uart)
Julius Wernercd49cce2019-03-05 16:53:33 -0800137 uart->enabled = CONFIG(APU2_PINMUX_UART_C);
Piotr Króldcd2f172016-05-27 12:04:13 +0200138 if (gpio)
Julius Wernercd49cce2019-03-05 16:53:33 -0800139 gpio->enabled = CONFIG(APU2_PINMUX_GPIO0);
Piotr Króldcd2f172016-05-27 12:04:13 +0200140
141 uart = dev_find_slot_pnp(SIO_PORT, NCT5104D_SP4);
142 gpio = dev_find_slot_pnp(SIO_PORT, NCT5104D_GPIO1);
143 if (uart)
Julius Wernercd49cce2019-03-05 16:53:33 -0800144 uart->enabled = CONFIG(APU2_PINMUX_UART_D);
Piotr Króldcd2f172016-05-27 12:04:13 +0200145 if (gpio)
Julius Wernercd49cce2019-03-05 16:53:33 -0800146 gpio->enabled = CONFIG(APU2_PINMUX_GPIO1);
Piotr Króldcd2f172016-05-27 12:04:13 +0200147}
148
149/**********************************************
150 * enable the dedicated function in mainboard.
151 **********************************************/
Michał Żygowski16434322020-01-10 13:08:30 +0100152#if CONFIG(GENERATE_SMBIOS_TABLES)
153static int mainboard_smbios_type16(DMI_INFO *agesa_dmi, int *handle,
154 unsigned long *current)
155{
Angel Pons631cd292021-06-28 15:40:58 +0200156 const u32 max_capacity = get_spd_offset() ? 4 : 2; /* 4GB or 2GB variant */
Michał Żygowski16434322020-01-10 13:08:30 +0100157
Angel Ponsd62a5012021-06-28 17:18:06 +0200158 struct smbios_type16 *t = smbios_carve_table(*current, SMBIOS_PHYS_MEMORY_ARRAY,
159 sizeof(*t), *handle);
Michał Żygowski16434322020-01-10 13:08:30 +0100160
Michał Żygowski16434322020-01-10 13:08:30 +0100161 t->use = MEMORY_ARRAY_USE_SYSTEM;
162 t->location = MEMORY_ARRAY_LOCATION_SYSTEM_BOARD;
163 t->memory_error_correction = agesa_dmi->T16.MemoryErrorCorrection;
164 t->maximum_capacity = max_capacity * 1024 * 1024;
165 t->memory_error_information_handle = 0xfffe;
166 t->number_of_memory_devices = 1;
167
Angel Ponsa37701a2021-06-28 17:36:53 +0200168 const int len = smbios_full_table_len(&t->header, t->eos);
Michał Żygowski16434322020-01-10 13:08:30 +0100169 *current += len;
Michał Żygowski16434322020-01-10 13:08:30 +0100170 return len;
171}
172
173static int mainboard_smbios_type17(DMI_INFO *agesa_dmi, int *handle,
174 unsigned long *current)
175{
Angel Ponsd62a5012021-06-28 17:18:06 +0200176 struct smbios_type17 *t = smbios_carve_table(*current, SMBIOS_MEMORY_DEVICE,
177 sizeof(*t), *handle + 1);
Michał Żygowski16434322020-01-10 13:08:30 +0100178
Michał Żygowski16434322020-01-10 13:08:30 +0100179 t->phys_memory_array_handle = *handle;
180 t->memory_error_information_handle = 0xfffe;
181 t->total_width = agesa_dmi->T17[0][0][0].TotalWidth;
182 t->data_width = agesa_dmi->T17[0][0][0].DataWidth;
183 t->size = agesa_dmi->T17[0][0][0].MemorySize;
184 t->form_factor = agesa_dmi->T17[0][0][0].FormFactor;
185 t->device_set = agesa_dmi->T17[0][0][0].DeviceSet;
186 t->device_locator = smbios_add_string(t->eos,
187 agesa_dmi->T17[0][0][0].DeviceLocator);
188 t->bank_locator = smbios_add_string(t->eos,
189 agesa_dmi->T17[0][0][0].BankLocator);
190 t->memory_type = agesa_dmi->T17[0][0][0].MemoryType;
191 t->type_detail = *(u16 *)&agesa_dmi->T17[0][0][0].TypeDetail;
192 t->speed = agesa_dmi->T17[0][0][0].Speed;
193 t->manufacturer = agesa_dmi->T17[0][0][0].ManufacturerIdCode;
194 t->serial_number = smbios_add_string(t->eos,
195 agesa_dmi->T17[0][0][0].SerialNumber);
196 t->part_number = smbios_add_string(t->eos,
197 agesa_dmi->T17[0][0][0].PartNumber);
198 t->attributes = agesa_dmi->T17[0][0][0].Attributes;
199 t->extended_size = agesa_dmi->T17[0][0][0].ExtSize;
200 t->clock_speed = agesa_dmi->T17[0][0][0].ConfigSpeed;
201 t->minimum_voltage = 1500; /* From SPD: 1.5V */
202 t->maximum_voltage = 1500;
203
Angel Ponsa37701a2021-06-28 17:36:53 +0200204 const int len = smbios_full_table_len(&t->header, t->eos);
Michał Żygowski16434322020-01-10 13:08:30 +0100205 *current += len;
Michał Żygowski16434322020-01-10 13:08:30 +0100206 return len;
207}
208
209static int mainboard_smbios_data(struct device *dev, int *handle,
210 unsigned long *current)
211{
212 DMI_INFO *agesa_dmi;
213 int len = 0;
214
215 agesa_dmi = agesawrapper_getlateinitptr(PICK_DMI);
216
217 if (!agesa_dmi)
218 return len;
219
220 len += mainboard_smbios_type16(agesa_dmi, handle, current);
221 len += mainboard_smbios_type17(agesa_dmi, handle, current);
222
223 *handle += 2;
224
225 return len;
226}
227#endif
Piotr Króldcd2f172016-05-27 12:04:13 +0200228
Elyes HAOUAS9adef1e2018-05-04 22:03:37 +0200229static void mainboard_enable(struct device *dev)
Piotr Króldcd2f172016-05-27 12:04:13 +0200230{
Kyösti Mälkki95be98a2021-02-15 12:57:21 +0200231 /* Maintain this text unchanged for manufacture process. */
Kyösti Mälkkib78e4622022-12-15 22:12:29 +0200232 printk(BIOS_INFO, "Mainboard %s Enable.\n", mainboard_part_number);
Piotr Króldcd2f172016-05-27 12:04:13 +0200233
234 config_gpio_mux();
235
236 //
237 // Enable the RTC output
238 //
Elyes HAOUASa342f392018-10-17 10:56:26 +0200239 pm_write16(PM_RTC_CONTROL, pm_read16(PM_RTC_CONTROL) | (1 << 11));
Piotr Króldcd2f172016-05-27 12:04:13 +0200240
241 //
242 // Enable power on from WAKE#
243 //
Elyes HAOUASa342f392018-10-17 10:56:26 +0200244 pm_write16(PM_S_STATE_CONTROL, pm_read16(PM_S_STATE_CONTROL) | (1 << 14));
Piotr Króldcd2f172016-05-27 12:04:13 +0200245
Piotr Króldcd2f172016-05-27 12:04:13 +0200246 /* Initialize the PIRQ data structures for consumption */
247 pirq_setup();
Michał Żygowski16434322020-01-10 13:08:30 +0100248#if CONFIG(GENERATE_SMBIOS_TABLES)
249 dev->ops->get_smbios_data = mainboard_smbios_data;
250#endif
Piotr Króldcd2f172016-05-27 12:04:13 +0200251}
252
Michał Żygowski68377692018-07-30 12:31:00 +0200253static void mainboard_final(void *chip_info)
254{
255 //
256 // Turn off LED 2 and LED 3
257 //
Kyösti Mälkkidf84a282020-06-18 19:26:05 +0300258 gpio_set(GPIO_58, 1);
259 gpio_set(GPIO_59, 1);
Michał Żygowski68377692018-07-30 12:31:00 +0200260}
261
Kyösti Mälkki10407492017-01-16 19:59:52 +0200262/*
Kyösti Mälkki01bf5992017-01-16 19:50:28 +0200263 * We will stuff a modified version of the first NICs (BDF 1:0.0) MAC address
264 * into the smbios serial number location.
265 */
266const char *smbios_mainboard_serial_number(void)
267{
268 static char serial[10];
Michał Żygowski04864582018-11-26 19:47:23 +0100269 struct device *dev;
Kyösti Mälkki01bf5992017-01-16 19:50:28 +0200270 uintptr_t bar10;
271 u32 mac_addr = 0;
272 int i;
273
Kyösti Mälkkidace2492019-07-03 10:49:44 +0300274 /* Already initialized. */
275 if (serial[0] != 0)
Michał Żygowski04864582018-11-26 19:47:23 +0100276 return serial;
277
Kyösti Mälkkidace2492019-07-03 10:49:44 +0300278 dev = pcidev_on_root(2, 2);
279 if (dev)
280 dev = pcidev_path_behind(dev->link_list, PCI_DEVFN(0, 0));
Michał Żygowski04864582018-11-26 19:47:23 +0100281 if (!dev)
Kyösti Mälkki01bf5992017-01-16 19:50:28 +0200282 return serial;
283
284 /* Read in the last 3 bytes of NIC's MAC address. */
Elyes HAOUAS55a044c2020-08-26 18:03:59 +0200285 bar10 = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
Kyösti Mälkki01bf5992017-01-16 19:50:28 +0200286 bar10 &= 0xFFFE0000;
287 bar10 += 0x5400;
288 for (i = 3; i < 6; i++) {
289 mac_addr <<= 8;
290 mac_addr |= read8((u8 *)bar10 + i);
291 }
292 mac_addr &= 0x00FFFFFF;
293 mac_addr /= 4;
294 mac_addr -= 64;
295
296 snprintf(serial, sizeof(serial), "%d", mac_addr);
297 return serial;
298}
299
300/*
Kyösti Mälkki10407492017-01-16 19:59:52 +0200301 * We will stuff the memory size into the smbios sku location.
302 */
Nico Huberebd8a4f2017-11-01 09:49:16 +0100303const char *smbios_system_sku(void)
Kyösti Mälkki10407492017-01-16 19:59:52 +0200304{
305 static char sku[5];
306 if (sku[0] != 0)
307 return sku;
308
309 if (!get_spd_offset())
310 snprintf(sku, sizeof(sku), "2 GB");
311 else
312 snprintf(sku, sizeof(sku), "4 GB");
313 return sku;
314}
315
Piotr Króldcd2f172016-05-27 12:04:13 +0200316struct chip_operations mainboard_ops = {
317 .enable_dev = mainboard_enable,
Michał Żygowski68377692018-07-30 12:31:00 +0200318 .final = mainboard_final,
Piotr Króldcd2f172016-05-27 12:04:13 +0200319};