mb/google/brya: Create rull variant
[coreboot2.git] / src / mainboard / pcengines / apu2 / mainboard.c
blob242ad9d932ed3aba1c9edccb71e9287efeb54f09
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <amdblocks/acpimmio.h>
4 #include <device/mmio.h>
5 #include <device/pci_ops.h>
6 #include <console/console.h>
7 #include <device/device.h>
8 #include <device/pci_def.h>
9 #include <gpio.h>
10 #include <identity.h>
11 #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>
14 #include <northbridge/amd/agesa/agesa_helper.h>
15 #include <northbridge/amd/pi/00730F01/pci_devs.h>
16 #include <southbridge/amd/common/amd_pci_util.h>
17 #include <superio/nuvoton/nct5104d/nct5104d.h>
18 #include <smbios.h>
19 #include <stdio.h>
20 #include <AGESA.h>
21 #include "gpio_ftns.h"
23 #define SPD_SIZE 128
24 #define PM_RTC_CONTROL 0x56
25 #define PM_S_STATE_CONTROL 0xBA
27 /***********************************************************
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.
35 * These values are used by the PCI configuration space,
36 * MP Tables. TODO: Make ACPI use these values too.
38 static const u8 mainboard_picr_data[FCH_INT_TABLE_SIZE] = {
39 [0 ... FCH_INT_TABLE_SIZE-1] = 0x1F,
40 /* 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
61 static const u8 mainboard_intr_data[FCH_INT_TABLE_SIZE] = {
62 [0 ... FCH_INT_TABLE_SIZE-1] = 0x1F,
63 /* 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 */
68 [0x10] = 0x09,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x10,
69 [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 */
74 [0x30] = 0x12,0x1F,0x12,0x1F,0x12,0x1F,0x1F,0x00,
75 [0x38] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
76 /* SATA */
77 [0x40] = 0x1F,0x13,0x00,0x00,0x00,0x00,0x00,0x00,
78 [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
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.
94 static 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}}, /* mPCIe/NIC: 02.1 */
99 {NB_PCIE_PORT2_DEVFN, {PIRQ_B, PIRQ_C, PIRQ_D, PIRQ_A}}, /* NIC: 02.2 */
100 {NB_PCIE_PORT3_DEVFN, {PIRQ_C, PIRQ_D, PIRQ_A, PIRQ_B}}, /* NIC: 02.3 */
101 {NB_PCIE_PORT4_DEVFN, {PIRQ_D, PIRQ_A, PIRQ_B, PIRQ_C}}, /* NIC: 02.4 */
102 {NB_PCIE_PORT5_DEVFN, {PIRQ_A, PIRQ_B, PIRQ_C, PIRQ_D}}, /* mPCIe: 02.5 */
103 {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 */
110 {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 */
112 {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) */
116 /* PIRQ Setup */
117 static void pirq_setup(void)
119 pirq_data_ptr = mainboard_pirq_data;
120 pirq_data_size = ARRAY_SIZE(mainboard_pirq_data);
121 intr_data_ptr = mainboard_intr_data;
122 picr_data_ptr = mainboard_picr_data;
125 /* Wrapper to enable GPIO/UART devices under menuconfig. Revisit
126 * once configuration file format for SPI flash storage is complete.
128 #define SIO_PORT 0x2e
130 static void config_gpio_mux(void)
132 struct device *uart, *gpio;
134 uart = dev_find_slot_pnp(SIO_PORT, NCT5104D_SP3);
135 gpio = dev_find_slot_pnp(SIO_PORT, NCT5104D_GPIO0);
136 if (uart)
137 uart->enabled = CONFIG(APU2_PINMUX_UART_C);
138 if (gpio)
139 gpio->enabled = CONFIG(APU2_PINMUX_GPIO0);
141 uart = dev_find_slot_pnp(SIO_PORT, NCT5104D_SP4);
142 gpio = dev_find_slot_pnp(SIO_PORT, NCT5104D_GPIO1);
143 if (uart)
144 uart->enabled = CONFIG(APU2_PINMUX_UART_D);
145 if (gpio)
146 gpio->enabled = CONFIG(APU2_PINMUX_GPIO1);
149 /**********************************************
150 * enable the dedicated function in mainboard.
151 **********************************************/
152 #if CONFIG(GENERATE_SMBIOS_TABLES)
153 static int mainboard_smbios_type16(DMI_INFO *agesa_dmi, int *handle,
154 unsigned long *current)
156 const u32 max_capacity = get_spd_offset() ? 4 : 2; /* 4GB or 2GB variant */
158 struct smbios_type16 *t = smbios_carve_table(*current, SMBIOS_PHYS_MEMORY_ARRAY,
159 sizeof(*t), *handle);
161 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;
168 const int len = smbios_full_table_len(&t->header, t->eos);
169 *current += len;
170 return len;
173 static int mainboard_smbios_type17(DMI_INFO *agesa_dmi, int *handle,
174 unsigned long *current)
176 struct smbios_type17 *t = smbios_carve_table(*current, SMBIOS_MEMORY_DEVICE,
177 sizeof(*t), *handle + 1);
179 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;
204 const int len = smbios_full_table_len(&t->header, t->eos);
205 *current += len;
206 return len;
209 static int mainboard_smbios_data(struct device *dev, int *handle,
210 unsigned long *current)
212 DMI_INFO *agesa_dmi;
213 int len = 0;
215 agesa_dmi = agesawrapper_getlateinitptr(PICK_DMI);
217 if (!agesa_dmi)
218 return len;
220 len += mainboard_smbios_type16(agesa_dmi, handle, current);
221 len += mainboard_smbios_type17(agesa_dmi, handle, current);
223 *handle += 2;
225 return len;
227 #endif
229 static void mainboard_enable(struct device *dev)
231 /* Maintain this text unchanged for manufacture process. */
232 printk(BIOS_INFO, "Mainboard %s Enable.\n", mainboard_part_number);
234 config_gpio_mux();
237 // Enable the RTC output
239 pm_write16(PM_RTC_CONTROL, pm_read16(PM_RTC_CONTROL) | (1 << 11));
242 // Enable power on from WAKE#
244 pm_write16(PM_S_STATE_CONTROL, pm_read16(PM_S_STATE_CONTROL) | (1 << 14));
246 /* Initialize the PIRQ data structures for consumption */
247 pirq_setup();
248 #if CONFIG(GENERATE_SMBIOS_TABLES)
249 dev->ops->get_smbios_data = mainboard_smbios_data;
250 #endif
253 static void mainboard_final(void *chip_info)
256 // Turn off LED 2 and LED 3
258 gpio_set(GPIO_58, 1);
259 gpio_set(GPIO_59, 1);
263 * We will stuff a modified version of the first NICs (BDF 1:0.0) MAC address
264 * into the smbios serial number location.
266 const char *smbios_mainboard_serial_number(void)
268 static char serial[10];
269 struct device *dev;
270 uintptr_t bar10;
271 u32 mac_addr = 0;
272 int i;
274 /* Already initialized. */
275 if (serial[0] != 0)
276 return serial;
278 dev = pcidev_on_root(2, 2);
279 if (dev)
280 dev = pcidev_path_behind(dev->downstream, PCI_DEVFN(0, 0));
281 if (!dev)
282 return serial;
284 /* Read in the last 3 bytes of NIC's MAC address. */
285 bar10 = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
286 bar10 &= 0xFFFE0000;
287 bar10 += 0x5400;
288 for (i = 3; i < 6; i++) {
289 mac_addr <<= 8;
290 mac_addr |= read8((u8 *)bar10 + i);
292 mac_addr &= 0x00FFFFFF;
293 mac_addr /= 4;
294 mac_addr -= 64;
296 snprintf(serial, sizeof(serial), "%d", mac_addr);
297 return serial;
301 * We will stuff the memory size into the smbios sku location.
303 const char *smbios_system_sku(void)
305 static char sku[5];
306 if (sku[0] != 0)
307 return sku;
309 if (!get_spd_offset())
310 snprintf(sku, sizeof(sku), "2 GB");
311 else
312 snprintf(sku, sizeof(sku), "4 GB");
313 return sku;
316 struct chip_operations mainboard_ops = {
317 .enable_dev = mainboard_enable,
318 .final = mainboard_final,