blob: ab9156f082c2b29d387ba85a91e32fa18b59604d [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}}, */
96 {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 */
98 {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 */
101 {XHCI_DEVFN, {PIRQ_C, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* XHCI: 10.0 */
102 {SATA_DEVFN, {PIRQ_SATA, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* SATA: 11.0 */
103 {OHCI1_DEVFN, {PIRQ_OHCI1, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* OHCI1: 12.0 */
104 {EHCI1_DEVFN, {PIRQ_NC, PIRQ_EHCI1, PIRQ_NC, PIRQ_NC}}, /* EHCI1: 12.2 */
105 {OHCI2_DEVFN, {PIRQ_OHCI2, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* OHCI2: 13.0 */
106 {EHCI2_DEVFN, {PIRQ_NC, PIRQ_EHCI2, PIRQ_NC, PIRQ_NC}}, /* EHCI2: 13.2 */
107 {SMBUS_DEVFN, {PIRQ_SMBUS, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* SMBUS: 14.0 */
108 {HDA_DEVFN, {PIRQ_HDA, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* HDA: 14.2 */
109 {SD_DEVFN, {PIRQ_SD, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* SD: 14.7 */
110 {OHCI3_DEVFN, {PIRQ_OHCI3, PIRQ_NC, PIRQ_NC, PIRQ_NC}}, /* OHCI3: 16.0 (same device as xHCI 10.0) */
111 {EHCI3_DEVFN, {PIRQ_NC, PIRQ_EHCI3, PIRQ_NC, PIRQ_NC}}, /* EHCI3: 16.2 (same device as xHCI 10.1) */
112};
113
114/* PIRQ Setup */
115static void pirq_setup(void)
116{
117 pirq_data_ptr = mainboard_pirq_data;
Patrick Georgi6b688f52021-02-12 13:49:11 +0100118 pirq_data_size = ARRAY_SIZE(mainboard_pirq_data);
Piotr Króldcd2f172016-05-27 12:04:13 +0200119 intr_data_ptr = mainboard_intr_data;
120 picr_data_ptr = mainboard_picr_data;
121}
122
123/* Wrapper to enable GPIO/UART devices under menuconfig. Revisit
124 * once configuration file format for SPI flash storage is complete.
125 */
126#define SIO_PORT 0x2e
127
128static void config_gpio_mux(void)
129{
130 struct device *uart, *gpio;
131
132 uart = dev_find_slot_pnp(SIO_PORT, NCT5104D_SP3);
133 gpio = dev_find_slot_pnp(SIO_PORT, NCT5104D_GPIO0);
134 if (uart)
Julius Wernercd49cce2019-03-05 16:53:33 -0800135 uart->enabled = CONFIG(APU2_PINMUX_UART_C);
Piotr Króldcd2f172016-05-27 12:04:13 +0200136 if (gpio)
Julius Wernercd49cce2019-03-05 16:53:33 -0800137 gpio->enabled = CONFIG(APU2_PINMUX_GPIO0);
Piotr Króldcd2f172016-05-27 12:04:13 +0200138
139 uart = dev_find_slot_pnp(SIO_PORT, NCT5104D_SP4);
140 gpio = dev_find_slot_pnp(SIO_PORT, NCT5104D_GPIO1);
141 if (uart)
Julius Wernercd49cce2019-03-05 16:53:33 -0800142 uart->enabled = CONFIG(APU2_PINMUX_UART_D);
Piotr Króldcd2f172016-05-27 12:04:13 +0200143 if (gpio)
Julius Wernercd49cce2019-03-05 16:53:33 -0800144 gpio->enabled = CONFIG(APU2_PINMUX_GPIO1);
Piotr Króldcd2f172016-05-27 12:04:13 +0200145}
146
147/**********************************************
148 * enable the dedicated function in mainboard.
149 **********************************************/
Michał Żygowski16434322020-01-10 13:08:30 +0100150#if CONFIG(GENERATE_SMBIOS_TABLES)
151static int mainboard_smbios_type16(DMI_INFO *agesa_dmi, int *handle,
152 unsigned long *current)
153{
Angel Pons631cd292021-06-28 15:40:58 +0200154 const u32 max_capacity = get_spd_offset() ? 4 : 2; /* 4GB or 2GB variant */
Michał Żygowski16434322020-01-10 13:08:30 +0100155
Angel Ponsd62a5012021-06-28 17:18:06 +0200156 struct smbios_type16 *t = smbios_carve_table(*current, SMBIOS_PHYS_MEMORY_ARRAY,
157 sizeof(*t), *handle);
Michał Żygowski16434322020-01-10 13:08:30 +0100158
Michał Żygowski16434322020-01-10 13:08:30 +0100159 t->use = MEMORY_ARRAY_USE_SYSTEM;
160 t->location = MEMORY_ARRAY_LOCATION_SYSTEM_BOARD;
161 t->memory_error_correction = agesa_dmi->T16.MemoryErrorCorrection;
162 t->maximum_capacity = max_capacity * 1024 * 1024;
163 t->memory_error_information_handle = 0xfffe;
164 t->number_of_memory_devices = 1;
165
Angel Ponsa37701a2021-06-28 17:36:53 +0200166 const int len = smbios_full_table_len(&t->header, t->eos);
Michał Żygowski16434322020-01-10 13:08:30 +0100167 *current += len;
Michał Żygowski16434322020-01-10 13:08:30 +0100168 return len;
169}
170
171static int mainboard_smbios_type17(DMI_INFO *agesa_dmi, int *handle,
172 unsigned long *current)
173{
Angel Ponsd62a5012021-06-28 17:18:06 +0200174 struct smbios_type17 *t = smbios_carve_table(*current, SMBIOS_MEMORY_DEVICE,
175 sizeof(*t), *handle + 1);
Michał Żygowski16434322020-01-10 13:08:30 +0100176
Michał Żygowski16434322020-01-10 13:08:30 +0100177 t->phys_memory_array_handle = *handle;
178 t->memory_error_information_handle = 0xfffe;
179 t->total_width = agesa_dmi->T17[0][0][0].TotalWidth;
180 t->data_width = agesa_dmi->T17[0][0][0].DataWidth;
181 t->size = agesa_dmi->T17[0][0][0].MemorySize;
182 t->form_factor = agesa_dmi->T17[0][0][0].FormFactor;
183 t->device_set = agesa_dmi->T17[0][0][0].DeviceSet;
184 t->device_locator = smbios_add_string(t->eos,
185 agesa_dmi->T17[0][0][0].DeviceLocator);
186 t->bank_locator = smbios_add_string(t->eos,
187 agesa_dmi->T17[0][0][0].BankLocator);
188 t->memory_type = agesa_dmi->T17[0][0][0].MemoryType;
189 t->type_detail = *(u16 *)&agesa_dmi->T17[0][0][0].TypeDetail;
190 t->speed = agesa_dmi->T17[0][0][0].Speed;
191 t->manufacturer = agesa_dmi->T17[0][0][0].ManufacturerIdCode;
192 t->serial_number = smbios_add_string(t->eos,
193 agesa_dmi->T17[0][0][0].SerialNumber);
194 t->part_number = smbios_add_string(t->eos,
195 agesa_dmi->T17[0][0][0].PartNumber);
196 t->attributes = agesa_dmi->T17[0][0][0].Attributes;
197 t->extended_size = agesa_dmi->T17[0][0][0].ExtSize;
198 t->clock_speed = agesa_dmi->T17[0][0][0].ConfigSpeed;
199 t->minimum_voltage = 1500; /* From SPD: 1.5V */
200 t->maximum_voltage = 1500;
201
Angel Ponsa37701a2021-06-28 17:36:53 +0200202 const int len = smbios_full_table_len(&t->header, t->eos);
Michał Żygowski16434322020-01-10 13:08:30 +0100203 *current += len;
Michał Żygowski16434322020-01-10 13:08:30 +0100204 return len;
205}
206
207static int mainboard_smbios_data(struct device *dev, int *handle,
208 unsigned long *current)
209{
210 DMI_INFO *agesa_dmi;
211 int len = 0;
212
213 agesa_dmi = agesawrapper_getlateinitptr(PICK_DMI);
214
215 if (!agesa_dmi)
216 return len;
217
218 len += mainboard_smbios_type16(agesa_dmi, handle, current);
219 len += mainboard_smbios_type17(agesa_dmi, handle, current);
220
221 *handle += 2;
222
223 return len;
224}
225#endif
Piotr Króldcd2f172016-05-27 12:04:13 +0200226
Elyes HAOUAS9adef1e2018-05-04 22:03:37 +0200227static void mainboard_enable(struct device *dev)
Piotr Króldcd2f172016-05-27 12:04:13 +0200228{
Kyösti Mälkki95be98a2021-02-15 12:57:21 +0200229 /* Maintain this text unchanged for manufacture process. */
Kyösti Mälkkib78e4622022-12-15 22:12:29 +0200230 printk(BIOS_INFO, "Mainboard %s Enable.\n", mainboard_part_number);
Piotr Króldcd2f172016-05-27 12:04:13 +0200231
232 config_gpio_mux();
233
234 //
235 // Enable the RTC output
236 //
Elyes HAOUASa342f392018-10-17 10:56:26 +0200237 pm_write16(PM_RTC_CONTROL, pm_read16(PM_RTC_CONTROL) | (1 << 11));
Piotr Króldcd2f172016-05-27 12:04:13 +0200238
239 //
240 // Enable power on from WAKE#
241 //
Elyes HAOUASa342f392018-10-17 10:56:26 +0200242 pm_write16(PM_S_STATE_CONTROL, pm_read16(PM_S_STATE_CONTROL) | (1 << 14));
Piotr Króldcd2f172016-05-27 12:04:13 +0200243
Piotr Króldcd2f172016-05-27 12:04:13 +0200244 /* Initialize the PIRQ data structures for consumption */
245 pirq_setup();
Michał Żygowski16434322020-01-10 13:08:30 +0100246#if CONFIG(GENERATE_SMBIOS_TABLES)
247 dev->ops->get_smbios_data = mainboard_smbios_data;
248#endif
Piotr Króldcd2f172016-05-27 12:04:13 +0200249}
250
Michał Żygowski68377692018-07-30 12:31:00 +0200251static void mainboard_final(void *chip_info)
252{
253 //
254 // Turn off LED 2 and LED 3
255 //
Kyösti Mälkkidf84a282020-06-18 19:26:05 +0300256 gpio_set(GPIO_58, 1);
257 gpio_set(GPIO_59, 1);
Michał Żygowski68377692018-07-30 12:31:00 +0200258}
259
Kyösti Mälkki10407492017-01-16 19:59:52 +0200260/*
Kyösti Mälkki01bf5992017-01-16 19:50:28 +0200261 * We will stuff a modified version of the first NICs (BDF 1:0.0) MAC address
262 * into the smbios serial number location.
263 */
264const char *smbios_mainboard_serial_number(void)
265{
266 static char serial[10];
Michał Żygowski04864582018-11-26 19:47:23 +0100267 struct device *dev;
Kyösti Mälkki01bf5992017-01-16 19:50:28 +0200268 uintptr_t bar10;
269 u32 mac_addr = 0;
270 int i;
271
Kyösti Mälkkidace2492019-07-03 10:49:44 +0300272 /* Already initialized. */
273 if (serial[0] != 0)
Michał Żygowski04864582018-11-26 19:47:23 +0100274 return serial;
275
Kyösti Mälkkidace2492019-07-03 10:49:44 +0300276 dev = pcidev_on_root(2, 2);
277 if (dev)
278 dev = pcidev_path_behind(dev->link_list, PCI_DEVFN(0, 0));
Michał Żygowski04864582018-11-26 19:47:23 +0100279 if (!dev)
Kyösti Mälkki01bf5992017-01-16 19:50:28 +0200280 return serial;
281
282 /* Read in the last 3 bytes of NIC's MAC address. */
Elyes HAOUAS55a044c2020-08-26 18:03:59 +0200283 bar10 = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
Kyösti Mälkki01bf5992017-01-16 19:50:28 +0200284 bar10 &= 0xFFFE0000;
285 bar10 += 0x5400;
286 for (i = 3; i < 6; i++) {
287 mac_addr <<= 8;
288 mac_addr |= read8((u8 *)bar10 + i);
289 }
290 mac_addr &= 0x00FFFFFF;
291 mac_addr /= 4;
292 mac_addr -= 64;
293
294 snprintf(serial, sizeof(serial), "%d", mac_addr);
295 return serial;
296}
297
298/*
Kyösti Mälkki10407492017-01-16 19:59:52 +0200299 * We will stuff the memory size into the smbios sku location.
300 */
Nico Huberebd8a4f2017-11-01 09:49:16 +0100301const char *smbios_system_sku(void)
Kyösti Mälkki10407492017-01-16 19:59:52 +0200302{
303 static char sku[5];
304 if (sku[0] != 0)
305 return sku;
306
307 if (!get_spd_offset())
308 snprintf(sku, sizeof(sku), "2 GB");
309 else
310 snprintf(sku, sizeof(sku), "4 GB");
311 return sku;
312}
313
Piotr Króldcd2f172016-05-27 12:04:13 +0200314struct chip_operations mainboard_ops = {
315 .enable_dev = mainboard_enable,
Michał Żygowski68377692018-07-30 12:31:00 +0200316 .final = mainboard_final,
Piotr Króldcd2f172016-05-27 12:04:13 +0200317};