blob: c59936d7dc36b34296cad0fd9d9f35af44cec986 [file] [log] [blame]
Angel Ponsae593872020-04-04 18:50:57 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Marc Jones24484842017-05-04 21:17:45 -06002
Martin Rothf09b4b62020-07-06 23:35:40 -06003#include <amdblocks/spi.h>
Marc Jones24484842017-05-04 21:17:45 -06004#include <console/console.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02005#include <device/mmio.h>
Marshall Dawson8a906df2017-06-13 14:19:02 -06006#include <bootstate.h>
Marshall Dawsone9b862e2017-09-22 15:14:46 -06007#include <cpu/x86/smm.h>
Marc Jones24484842017-05-04 21:17:45 -06008#include <device/device.h>
9#include <device/pci.h>
Marc Jones24484842017-05-04 21:17:45 -060010#include <device/pci_ops.h>
11#include <cbmem.h>
Kyösti Mälkki5daa1d32020-06-14 12:01:58 +030012#include <acpi/acpi_gnvs.h>
Richard Spiegel2bbc3dc2017-12-06 16:14:58 -070013#include <amdblocks/amd_pci_util.h>
Richard Spiegel71081072018-07-26 10:51:38 -070014#include <amdblocks/agesawrapper.h>
Felix Held5b3831c2020-11-30 17:56:59 +010015#include <amdblocks/aoac.h>
Nico Huber73c11192018-10-06 18:20:47 +020016#include <amdblocks/reset.h>
Marshall Dawson69486ca2019-05-02 12:03:45 -060017#include <amdblocks/acpimmio.h>
Marshall Dawson6ab5ed32019-05-29 09:24:18 -060018#include <amdblocks/lpc.h>
Marshall Dawson4ee83b22019-05-03 11:44:22 -060019#include <amdblocks/acpi.h>
Felix Held875e5aa2020-12-01 00:34:11 +010020#include <amdblocks/smbus.h>
Marc Jonesdfeb1c42017-08-07 19:08:24 -060021#include <soc/southbridge.h>
Marc Jones24484842017-05-04 21:17:45 -060022#include <soc/smi.h>
Richard Spiegel376dc822017-12-01 08:24:26 -070023#include <soc/amd_pci_int_defs.h>
Richard Spiegelbec44f22017-11-24 07:41:29 -070024#include <delay.h>
25#include <soc/pci_devs.h>
Marshall Dawson2942db62017-12-14 10:00:27 -070026#include <agesa_headers.h>
Richard Spiegeldbee8ae2018-05-09 17:34:04 -070027#include <soc/nvs.h>
Elyes HAOUAS27d02d82019-05-15 21:11:39 +020028#include <types.h>
Marshall Dawson2942db62017-12-14 10:00:27 -070029
Richard Spiegel0e0e93c2018-03-13 10:19:51 -070030/*
31 * Table of devices that need their AOAC registers enabled and waited
32 * upon (usually about .55 milliseconds). Instead of individual delays
33 * waiting for each device to become available, a single delay will be
Richard Spiegel6dfbb592018-03-15 15:45:44 -070034 * executed.
Richard Spiegel0e0e93c2018-03-13 10:19:51 -070035 */
Felix Heldab0d85c2020-11-30 17:27:30 +010036static const unsigned int aoac_devs[] = {
37 FCH_AOAC_DEV_UART0 + CONFIG_UART_FOR_CONSOLE * 2,
38 FCH_AOAC_DEV_AMBA,
39 FCH_AOAC_DEV_I2C0,
40 FCH_AOAC_DEV_I2C1,
41 FCH_AOAC_DEV_I2C2,
42 FCH_AOAC_DEV_I2C3,
Richard Spiegel0e0e93c2018-03-13 10:19:51 -070043};
44
Marshall Dawson2942db62017-12-14 10:00:27 -070045static int is_sata_config(void)
46{
Richard Spiegelbdd272a2018-10-16 13:53:05 -070047 return !((SataNativeIde == CONFIG_STONEYRIDGE_SATA_MODE)
48 || (SataLegacyIde == CONFIG_STONEYRIDGE_SATA_MODE));
Marshall Dawson2942db62017-12-14 10:00:27 -070049}
50
Richard Spiegel7ea8e022018-01-16 14:40:10 -070051static inline int sb_sata_enable(void)
52{
53 /* True if IDE or AHCI. */
Richard Spiegelbdd272a2018-10-16 13:53:05 -070054 return (SataNativeIde == CONFIG_STONEYRIDGE_SATA_MODE) ||
55 (SataAhci == CONFIG_STONEYRIDGE_SATA_MODE);
Richard Spiegel7ea8e022018-01-16 14:40:10 -070056}
57
58static inline int sb_ide_enable(void)
59{
60 /* True if IDE or LEGACY IDE. */
Richard Spiegelbdd272a2018-10-16 13:53:05 -070061 return (SataNativeIde == CONFIG_STONEYRIDGE_SATA_MODE) ||
62 (SataLegacyIde == CONFIG_STONEYRIDGE_SATA_MODE);
Richard Spiegel7ea8e022018-01-16 14:40:10 -070063}
64
Marshall Dawson2942db62017-12-14 10:00:27 -070065void SetFchResetParams(FCH_RESET_INTERFACE *params)
66{
Kyösti Mälkkie7377552018-06-21 16:20:55 +030067 const struct device *dev = pcidev_path_on_root(SATA_DEVFN);
Julius Wernercd49cce2019-03-05 16:53:33 -080068 params->Xhci0Enable = CONFIG(STONEYRIDGE_XHCI_ENABLE);
Richard Spiegelbb18b432018-08-03 10:37:28 -070069 if (dev && dev->enabled) {
70 params->SataEnable = sb_sata_enable();
71 params->IdeEnable = sb_ide_enable();
72 } else {
73 params->SataEnable = FALSE;
74 params->IdeEnable = FALSE;
75 }
Marshall Dawson2942db62017-12-14 10:00:27 -070076}
77
78void SetFchEnvParams(FCH_INTERFACE *params)
79{
Kyösti Mälkkie7377552018-06-21 16:20:55 +030080 const struct device *dev = pcidev_path_on_root(SATA_DEVFN);
Marshall Dawson2942db62017-12-14 10:00:27 -070081 params->AzaliaController = AzEnable;
82 params->SataClass = CONFIG_STONEYRIDGE_SATA_MODE;
Richard Spiegelbb18b432018-08-03 10:37:28 -070083 if (dev && dev->enabled) {
84 params->SataEnable = is_sata_config();
85 params->IdeEnable = !params->SataEnable;
86 params->SataIdeMode = (CONFIG_STONEYRIDGE_SATA_MODE ==
87 SataLegacyIde);
88 } else {
89 params->SataEnable = FALSE;
90 params->IdeEnable = FALSE;
91 params->SataIdeMode = FALSE;
92 }
Marshall Dawson2942db62017-12-14 10:00:27 -070093}
94
95void SetFchMidParams(FCH_INTERFACE *params)
96{
97 SetFchEnvParams(params);
98}
Marc Jones24484842017-05-04 21:17:45 -060099
Richard Spiegel376dc822017-12-01 08:24:26 -0700100/*
101 * Table of APIC register index and associated IRQ name. Using IDX_XXX_NAME
Jonathan Neuschäfer5268b762018-02-12 12:24:25 +0100102 * provides a visible association with the index, therefore helping
Richard Spiegel376dc822017-12-01 08:24:26 -0700103 * maintainability of table. If a new index/name is defined in
104 * amd_pci_int_defs.h, just add the pair at the end of this table.
105 * Order is not important.
106 */
Elyes HAOUAS68ec3eb2019-06-22 09:21:18 +0200107static const struct irq_idx_name irq_association[] = {
Richard Spiegele89d4442017-12-08 07:52:42 -0700108 { PIRQ_A, "INTA#" },
109 { PIRQ_B, "INTB#" },
110 { PIRQ_C, "INTC#" },
111 { PIRQ_D, "INTD#" },
112 { PIRQ_E, "INTE#" },
113 { PIRQ_F, "INTF#" },
114 { PIRQ_G, "INTG#" },
115 { PIRQ_H, "INTH#" },
116 { PIRQ_MISC, "Misc" },
117 { PIRQ_MISC0, "Misc0" },
118 { PIRQ_MISC1, "Misc1" },
119 { PIRQ_MISC2, "Misc2" },
Richard Spiegel376dc822017-12-01 08:24:26 -0700120 { PIRQ_SIRQA, "Ser IRQ INTA" },
121 { PIRQ_SIRQB, "Ser IRQ INTB" },
122 { PIRQ_SIRQC, "Ser IRQ INTC" },
123 { PIRQ_SIRQD, "Ser IRQ INTD" },
Richard Spiegele89d4442017-12-08 07:52:42 -0700124 { PIRQ_SCI, "SCI" },
125 { PIRQ_SMBUS, "SMBUS" },
126 { PIRQ_ASF, "ASF" },
127 { PIRQ_HDA, "HDA" },
128 { PIRQ_FC, "FC" },
129 { PIRQ_PMON, "PerMon" },
130 { PIRQ_SD, "SD" },
131 { PIRQ_SDIO, "SDIOt" },
Richard Spiegele89d4442017-12-08 07:52:42 -0700132 { PIRQ_EHCI, "EHCI" },
133 { PIRQ_XHCI, "XHCI" },
134 { PIRQ_SATA, "SATA" },
135 { PIRQ_GPIO, "GPIO" },
136 { PIRQ_I2C0, "I2C0" },
137 { PIRQ_I2C1, "I2C1" },
138 { PIRQ_I2C2, "I2C2" },
139 { PIRQ_I2C3, "I2C3" },
140 { PIRQ_UART0, "UART0" },
141 { PIRQ_UART1, "UART1" },
Richard Spiegel376dc822017-12-01 08:24:26 -0700142};
143
144const struct irq_idx_name *sb_get_apic_reg_association(size_t *size)
145{
146 *size = ARRAY_SIZE(irq_association);
147 return irq_association;
148}
149
Richard Spiegel0e0e93c2018-03-13 10:19:51 -0700150void enable_aoac_devices(void)
Garrett Kirkendalla0ff6fc2018-03-06 09:23:47 -0600151{
152 bool status;
Richard Spiegel0e0e93c2018-03-13 10:19:51 -0700153 int i;
Garrett Kirkendalla0ff6fc2018-03-06 09:23:47 -0600154
Richard Spiegel0e0e93c2018-03-13 10:19:51 -0700155 for (i = 0; i < ARRAY_SIZE(aoac_devs); i++)
Felix Heldab0d85c2020-11-30 17:27:30 +0100156 power_on_aoac_device(aoac_devs[i]);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700157
Richard Spiegel0e0e93c2018-03-13 10:19:51 -0700158 /* Wait for AOAC devices to indicate power and clock OK */
159 do {
160 udelay(100);
161 status = true;
162 for (i = 0; i < ARRAY_SIZE(aoac_devs); i++)
Felix Heldab0d85c2020-11-30 17:27:30 +0100163 status &= is_aoac_device_enabled(aoac_devs[i]);
Richard Spiegel0e0e93c2018-03-13 10:19:51 -0700164 } while (!status);
165}
166
Marshall Dawson6ab5ed32019-05-29 09:24:18 -0600167static void sb_enable_lpc(void)
Richard Spiegelbec44f22017-11-24 07:41:29 -0700168{
169 u8 byte;
170
171 /* Enable LPC controller */
Marshall Dawson939bfcc2019-05-05 15:39:40 -0600172 byte = pm_io_read8(PM_LPC_GATING);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700173 byte |= PM_LPC_ENABLE;
Marshall Dawson939bfcc2019-05-05 15:39:40 -0600174 pm_io_write8(PM_LPC_GATING, byte);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700175}
176
Marshall Dawson6ab5ed32019-05-29 09:24:18 -0600177static void sb_lpc_decode(void)
Richard Spiegelbec44f22017-11-24 07:41:29 -0700178{
179 u32 tmp = 0;
180
181 /* Enable I/O decode to LPC bus */
182 tmp = DECODE_ENABLE_PARALLEL_PORT0 | DECODE_ENABLE_PARALLEL_PORT2
183 | DECODE_ENABLE_PARALLEL_PORT4 | DECODE_ENABLE_SERIAL_PORT0
184 | DECODE_ENABLE_SERIAL_PORT1 | DECODE_ENABLE_SERIAL_PORT2
185 | DECODE_ENABLE_SERIAL_PORT3 | DECODE_ENABLE_SERIAL_PORT4
186 | DECODE_ENABLE_SERIAL_PORT5 | DECODE_ENABLE_SERIAL_PORT6
187 | DECODE_ENABLE_SERIAL_PORT7 | DECODE_ENABLE_AUDIO_PORT0
188 | DECODE_ENABLE_AUDIO_PORT1 | DECODE_ENABLE_AUDIO_PORT2
189 | DECODE_ENABLE_AUDIO_PORT3 | DECODE_ENABLE_MSS_PORT2
190 | DECODE_ENABLE_MSS_PORT3 | DECODE_ENABLE_FDC_PORT0
191 | DECODE_ENABLE_FDC_PORT1 | DECODE_ENABLE_GAME_PORT
192 | DECODE_ENABLE_KBC_PORT | DECODE_ENABLE_ACPIUC_PORT
193 | DECODE_ENABLE_ADLIB_PORT;
194
Marshall Dawson6ab5ed32019-05-29 09:24:18 -0600195 /* Decode SIOs at 2E/2F and 4E/4F */
196 if (CONFIG(STONEYRIDGE_LEGACY_FREE))
197 tmp |= DECODE_ALTERNATE_SIO_ENABLE | DECODE_SIO_ENABLE;
198
199 lpc_enable_decode(tmp);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700200}
201
Raul E Rangel5b058232018-06-28 16:31:45 -0600202static void sb_enable_cf9_io(void)
203{
204 uint32_t reg = pm_read32(PM_DECODE_EN);
205
206 pm_write32(PM_DECODE_EN, reg | CF9_IO_EN);
207}
208
Raul E Rangel9abc3fe2018-06-28 16:31:45 -0600209static void sb_enable_legacy_io(void)
210{
211 uint32_t reg = pm_read32(PM_DECODE_EN);
212
213 pm_write32(PM_DECODE_EN, reg | LEGACY_IO_EN);
214}
215
Richard Spiegelc93d4ab2019-02-12 19:17:02 -0700216void sb_clk_output_48Mhz(u32 osc)
Richard Spiegelbec44f22017-11-24 07:41:29 -0700217{
218 u32 ctrl;
219
220 /*
Richard Spiegelc93d4ab2019-02-12 19:17:02 -0700221 * Clear the disable for OSCOUT1 (signal typically named XnnM_25M_48M)
222 * or OSCOUT2 (USBCLK/25M_48M_OSC). The frequency defaults to 48MHz.
Richard Spiegelbec44f22017-11-24 07:41:29 -0700223 */
Marshall Dawsonb4b9efc2019-05-01 17:33:42 -0600224 ctrl = misc_read32(MISC_CLK_CNTL1);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700225
Richard Spiegelc93d4ab2019-02-12 19:17:02 -0700226 switch (osc) {
227 case 1:
228 ctrl &= ~OSCOUT1_CLK_OUTPUT_ENB;
229 break;
230 case 2:
231 ctrl &= ~OSCOUT2_CLK_OUTPUT_ENB;
232 break;
233 default:
234 return; /* do nothing if invalid */
235 }
Marshall Dawsonb4b9efc2019-05-01 17:33:42 -0600236 misc_write32(MISC_CLK_CNTL1, ctrl);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700237}
238
Martin Rothf09b4b62020-07-06 23:35:40 -0600239static void sb_init_spi_base(void)
Marshall Dawsoneceaa972019-05-05 18:35:12 -0600240{
Richard Spiegelbec44f22017-11-24 07:41:29 -0700241 /* Make sure the base address is predictable */
Martin Rothf09b4b62020-07-06 23:35:40 -0600242 if (ENV_X86)
243 lpc_set_spibase(SPI_BASE_ADDRESS);
Furquan Shaikhd82c7d22020-05-09 17:18:48 -0700244 lpc_enable_spi_rom(SPI_ROM_ENABLE);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700245}
246
247void sb_set_spi100(u16 norm, u16 fast, u16 alt, u16 tpm)
248{
Martin Rothcbdd8902020-07-23 16:12:33 -0600249 spi_write16(SPI100_SPEED_CONFIG,
Richard Spiegelbec44f22017-11-24 07:41:29 -0700250 (norm << SPI_NORM_SPEED_NEW_SH) |
251 (fast << SPI_FAST_SPEED_NEW_SH) |
252 (alt << SPI_ALT_SPEED_NEW_SH) |
253 (tpm << SPI_TPM_SPEED_NEW_SH));
Martin Rothcbdd8902020-07-23 16:12:33 -0600254 spi_write16(SPI100_ENABLE, SPI_USE_SPI100);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700255}
256
257void sb_disable_4dw_burst(void)
258{
Martin Rothcbdd8902020-07-23 16:12:33 -0600259 spi_write16(SPI100_HOST_PREF_CONFIG,
260 spi_read16(SPI100_HOST_PREF_CONFIG) & ~SPI_RD4DW_EN_HOST);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700261}
262
Richard Spiegelbec44f22017-11-24 07:41:29 -0700263void sb_read_mode(u32 mode)
264{
Martin Rothcbdd8902020-07-23 16:12:33 -0600265 spi_write32(SPI_CNTRL0,
266 (spi_read32(SPI_CNTRL0) & ~SPI_READ_MODE_MASK) | mode);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700267}
268
Raul E Rangel79053412018-08-06 10:40:02 -0600269static void setup_spread_spectrum(int *reboot)
Raul E Rangel6b0fc802018-08-02 15:56:34 -0600270{
271 uint16_t rstcfg = pm_read16(PWR_RESET_CFG);
272
273 rstcfg &= ~TOGGLE_ALL_PWR_GOOD;
274 pm_write16(PWR_RESET_CFG, rstcfg);
275
276 uint32_t cntl1 = misc_read32(MISC_CLK_CNTL1);
277
278 if (cntl1 & CG1PLL_FBDIV_TEST) {
279 printk(BIOS_DEBUG, "Spread spectrum is ready\n");
280 misc_write32(MISC_CGPLL_CONFIG1,
281 misc_read32(MISC_CGPLL_CONFIG1) |
282 CG1PLL_SPREAD_SPECTRUM_ENABLE);
283
284 return;
285 }
286
287 printk(BIOS_DEBUG, "Setting up spread spectrum\n");
288
289 uint32_t cfg6 = misc_read32(MISC_CGPLL_CONFIG6);
290 cfg6 &= ~CG1PLL_LF_MODE_MASK;
Marshall Dawsonecce8472018-10-05 15:41:03 -0600291 cfg6 |= (0x0f8 << CG1PLL_LF_MODE_SHIFT) & CG1PLL_LF_MODE_MASK;
Raul E Rangel6b0fc802018-08-02 15:56:34 -0600292 misc_write32(MISC_CGPLL_CONFIG6, cfg6);
293
294 uint32_t cfg3 = misc_read32(MISC_CGPLL_CONFIG3);
295 cfg3 &= ~CG1PLL_REFDIV_MASK;
296 cfg3 |= (0x003 << CG1PLL_REFDIV_SHIFT) & CG1PLL_REFDIV_MASK;
297 cfg3 &= ~CG1PLL_FBDIV_MASK;
Marshall Dawsonecce8472018-10-05 15:41:03 -0600298 cfg3 |= (0x04b << CG1PLL_FBDIV_SHIFT) & CG1PLL_FBDIV_MASK;
Raul E Rangel6b0fc802018-08-02 15:56:34 -0600299 misc_write32(MISC_CGPLL_CONFIG3, cfg3);
300
301 uint32_t cfg5 = misc_read32(MISC_CGPLL_CONFIG5);
Marshall Dawsonedba21e2018-10-05 19:01:52 -0600302 cfg5 &= ~SS_AMOUNT_NFRAC_SLIP_MASK;
303 cfg5 |= (0x2 << SS_AMOUNT_NFRAC_SLIP_SHIFT) & SS_AMOUNT_NFRAC_SLIP_MASK;
Raul E Rangel6b0fc802018-08-02 15:56:34 -0600304 misc_write32(MISC_CGPLL_CONFIG5, cfg5);
305
306 uint32_t cfg4 = misc_read32(MISC_CGPLL_CONFIG4);
Marshall Dawsonedba21e2018-10-05 19:01:52 -0600307 cfg4 &= ~SS_AMOUNT_DSFRAC_MASK;
308 cfg4 |= (0xd000 << SS_AMOUNT_DSFRAC_SHIFT) & SS_AMOUNT_DSFRAC_MASK;
309 cfg4 &= ~SS_STEP_SIZE_DSFRAC_MASK;
310 cfg4 |= (0x02d5 << SS_STEP_SIZE_DSFRAC_SHIFT)
311 & SS_STEP_SIZE_DSFRAC_MASK;
Raul E Rangel6b0fc802018-08-02 15:56:34 -0600312 misc_write32(MISC_CGPLL_CONFIG4, cfg4);
313
314 rstcfg |= TOGGLE_ALL_PWR_GOOD;
315 pm_write16(PWR_RESET_CFG, rstcfg);
316
317 cntl1 |= CG1PLL_FBDIV_TEST;
318 misc_write32(MISC_CLK_CNTL1, cntl1);
319
Raul E Rangel79053412018-08-06 10:40:02 -0600320 *reboot = 1;
321}
322
323static void setup_misc(int *reboot)
324{
325 /* Undocumented register */
326 uint32_t reg = misc_read32(0x50);
327 if (!(reg & BIT(16))) {
328 reg |= BIT(16);
329
330 misc_write32(0x50, reg);
331 *reboot = 1;
332 }
Raul E Rangel6b0fc802018-08-02 15:56:34 -0600333}
334
Raul E Rangeld820f4b82018-08-13 10:39:03 -0600335/* Before console init */
Richard Spiegelbec44f22017-11-24 07:41:29 -0700336void bootblock_fch_early_init(void)
337{
Raul E Rangel79053412018-08-06 10:40:02 -0600338 int reboot = 0;
339
Marshall Dawson6ab5ed32019-05-29 09:24:18 -0600340 lpc_enable_rom();
341 sb_enable_lpc();
342 lpc_enable_port80();
Richard Spiegelbec44f22017-11-24 07:41:29 -0700343 sb_lpc_decode();
Marshall Dawson6ab5ed32019-05-29 09:24:18 -0600344 lpc_enable_spi_prefetch();
Marshall Dawsoneceaa972019-05-05 18:35:12 -0600345 sb_init_spi_base();
Marc Jonescfb16802018-04-20 16:27:41 -0600346 sb_disable_4dw_burst(); /* Must be disabled on CZ(ST) */
Michał Żygowski73a544d2019-11-24 14:16:34 +0100347 enable_acpimmio_decode_pm04();
Richard Spiegelb40e1932018-10-24 12:51:21 -0700348 fch_smbus_init();
Raul E Rangel5b058232018-06-28 16:31:45 -0600349 sb_enable_cf9_io();
Raul E Rangel79053412018-08-06 10:40:02 -0600350 setup_spread_spectrum(&reboot);
351 setup_misc(&reboot);
352
353 if (reboot)
Nico Huber73c11192018-10-06 18:20:47 +0200354 warm_reset();
Raul E Rangel79053412018-08-06 10:40:02 -0600355
Raul E Rangel9abc3fe2018-06-28 16:31:45 -0600356 sb_enable_legacy_io();
Richard Spiegel0e0e93c2018-03-13 10:19:51 -0700357 enable_aoac_devices();
Richard Spiegelbec44f22017-11-24 07:41:29 -0700358}
359
Edward Hillcc680342018-08-10 16:20:02 -0600360static void print_num_status_bits(int num_bits, uint32_t status,
361 const char *const bit_names[])
362{
363 int i;
364
365 if (!status)
366 return;
367
368 for (i = num_bits - 1; i >= 0; i--) {
369 if (status & (1 << i)) {
370 if (bit_names[i])
371 printk(BIOS_DEBUG, "%s ", bit_names[i]);
372 else
373 printk(BIOS_DEBUG, "BIT%d ", i);
374 }
375 }
376}
377
378static void sb_print_pmxc0_status(void)
379{
380 /* PMxC0 S5/Reset Status shows the source of previous reset. */
381 uint32_t pmxc0_status = pm_read32(PM_RST_STATUS);
382
Edward Hill917b4002018-10-02 14:17:19 -0600383 static const char *const pmxc0_status_bits[32] = {
Edward Hillcc680342018-08-10 16:20:02 -0600384 [0] = "ThermalTrip",
385 [1] = "FourSecondPwrBtn",
386 [2] = "Shutdown",
387 [3] = "ThermalTripFromTemp",
388 [4] = "RemotePowerDownFromASF",
389 [5] = "ShutDownFan0",
390 [16] = "UserRst",
391 [17] = "SoftPciRst",
392 [18] = "DoInit",
393 [19] = "DoReset",
394 [20] = "DoFullReset",
395 [21] = "SleepReset",
396 [22] = "KbReset",
397 [23] = "LtReset",
398 [24] = "FailBootRst",
399 [25] = "WatchdogIssueReset",
400 [26] = "RemoteResetFromASF",
401 [27] = "SyncFlood",
402 [28] = "HangReset",
403 [29] = "EcWatchdogRst",
Edward Hillcc680342018-08-10 16:20:02 -0600404 };
405
Edward Hill917b4002018-10-02 14:17:19 -0600406 printk(BIOS_DEBUG, "PMxC0 STATUS: 0x%x ", pmxc0_status);
Edward Hillcc680342018-08-10 16:20:02 -0600407 print_num_status_bits(ARRAY_SIZE(pmxc0_status_bits), pmxc0_status,
408 pmxc0_status_bits);
Edward Hill917b4002018-10-02 14:17:19 -0600409 printk(BIOS_DEBUG, "\n");
Edward Hillcc680342018-08-10 16:20:02 -0600410}
411
Raul E Rangeld820f4b82018-08-13 10:39:03 -0600412/* After console init */
Edward Hillcc680342018-08-10 16:20:02 -0600413void bootblock_fch_init(void)
414{
415 sb_print_pmxc0_status();
416}
Raul E Rangeld820f4b82018-08-13 10:39:03 -0600417
Elyes HAOUASc5ad2672018-12-05 10:58:34 +0100418void sb_enable(struct device *dev)
Marc Jones24484842017-05-04 21:17:45 -0600419{
Marc Jonesdfeb1c42017-08-07 19:08:24 -0600420 printk(BIOS_DEBUG, "%s\n", __func__);
Marc Jones24484842017-05-04 21:17:45 -0600421}
422
Marc Jonesdfeb1c42017-08-07 19:08:24 -0600423static void sb_init_acpi_ports(void)
Marc Jones24484842017-05-04 21:17:45 -0600424{
Marshall Dawson91b80412017-09-27 16:44:40 -0600425 u32 reg;
426
Marc Jones24484842017-05-04 21:17:45 -0600427 /* We use some of these ports in SMM regardless of whether or not
428 * ACPI tables are generated. Enable these ports indiscriminately.
429 */
430
431 pm_write16(PM_EVT_BLK, ACPI_PM_EVT_BLK);
432 pm_write16(PM1_CNT_BLK, ACPI_PM1_CNT_BLK);
433 pm_write16(PM_TMR_BLK, ACPI_PM_TMR_BLK);
434 pm_write16(PM_GPE0_BLK, ACPI_GPE0_BLK);
Michał Żygowski9550e972020-03-20 13:56:46 +0100435 /* CpuControl is in \_SB.CP00, 6 bytes */
Marc Jones24484842017-05-04 21:17:45 -0600436 pm_write16(PM_CPU_CTRL, ACPI_CPU_CONTROL);
437
Julius Wernercd49cce2019-03-05 16:53:33 -0800438 if (CONFIG(HAVE_SMI_HANDLER)) {
Marshall Dawsona05fdcb2017-09-27 15:01:37 -0600439 /* APMC - SMI Command Port */
Marshall Dawsone9b862e2017-09-22 15:14:46 -0600440 pm_write16(PM_ACPI_SMI_CMD, APM_CNT);
Marshall Dawsona05fdcb2017-09-27 15:01:37 -0600441 configure_smi(SMITYPE_SMI_CMD_PORT, SMI_MODE_SMI);
Marshall Dawson91b80412017-09-27 16:44:40 -0600442
443 /* SMI on SlpTyp requires sending SMI before completion
444 * response of the I/O write. The BKDG also specifies
445 * clearing ForceStpClkRetry for SMI trapping.
446 */
447 reg = pm_read32(PM_PCI_CTRL);
448 reg |= FORCE_SLPSTATE_RETRY;
449 reg &= ~FORCE_STPCLK_RETRY;
450 pm_write32(PM_PCI_CTRL, reg);
451
452 /* Disable SlpTyp feature */
453 reg = pm_read8(PM_RST_CTRL1);
454 reg &= ~SLPTYPE_CONTROL_EN;
455 pm_write8(PM_RST_CTRL1, reg);
456
457 configure_smi(SMITYPE_SLP_TYP, SMI_MODE_SMI);
Marc Jones24484842017-05-04 21:17:45 -0600458 } else {
459 pm_write16(PM_ACPI_SMI_CMD, 0);
460 }
461
Marshall Dawson5e2e74f2017-11-10 09:59:56 -0700462 /* Decode ACPI registers and enable standard features */
463 pm_write8(PM_ACPI_CONF, PM_ACPI_DECODE_STD |
464 PM_ACPI_GLOBAL_EN |
465 PM_ACPI_RTC_EN_EN |
466 PM_ACPI_TIMER_EN_EN);
Marc Jones24484842017-05-04 21:17:45 -0600467}
468
Richard Spiegeldbee8ae2018-05-09 17:34:04 -0700469static void set_nvs_sws(void *unused)
470{
Aaron Durbin5a5e4d02020-08-14 16:22:11 -0600471 struct acpi_pm_gpe_state *state;
Kyösti Mälkki0c1dd9c2020-06-17 23:37:49 +0300472 struct global_nvs *gnvs;
Richard Spiegeldbee8ae2018-05-09 17:34:04 -0700473
Aaron Durbin5a5e4d02020-08-14 16:22:11 -0600474 state = cbmem_find(CBMEM_ID_POWER_STATE);
475 if (state == NULL)
Richard Spiegel35282a02018-06-14 14:57:54 -0700476 return;
Kyösti Mälkki5daa1d32020-06-14 12:01:58 +0300477 gnvs = acpi_get_gnvs();
Richard Spiegeldbee8ae2018-05-09 17:34:04 -0700478 if (gnvs == NULL)
479 return;
480
Aaron Durbin5a5e4d02020-08-14 16:22:11 -0600481 acpi_fill_gnvs(gnvs, state);
Richard Spiegeldbee8ae2018-05-09 17:34:04 -0700482}
483
484BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, set_nvs_sws, NULL);
485
Marc Jonesdfeb1c42017-08-07 19:08:24 -0600486void southbridge_init(void *chip_info)
Marc Jones24484842017-05-04 21:17:45 -0600487{
Aaron Durbin5a5e4d02020-08-14 16:22:11 -0600488 struct acpi_pm_gpe_state *state;
489
Marc Jonesdfeb1c42017-08-07 19:08:24 -0600490 sb_init_acpi_ports();
Aaron Durbin5a5e4d02020-08-14 16:22:11 -0600491
492 state = cbmem_add(CBMEM_ID_POWER_STATE, sizeof(*state));
493 if (state) {
494 acpi_fill_pm_gpe_state(state);
495 acpi_pm_gpe_add_events_print_events(state);
496 }
497
498 acpi_clear_pm_gpe_status();
Marc Jones24484842017-05-04 21:17:45 -0600499}
500
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600501static void set_sb_final_nvs(void)
502{
503 uintptr_t amdfw_rom;
504 uintptr_t xhci_fw;
505 uintptr_t fwaddr;
506 size_t fwsize;
Richard Spiegel41baf0c2018-10-22 13:57:18 -0700507 const struct device *sd, *sata;
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600508
Kyösti Mälkki0c1dd9c2020-06-17 23:37:49 +0300509 struct global_nvs *gnvs = acpi_get_gnvs();
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600510 if (gnvs == NULL)
511 return;
512
Felix Heldab0d85c2020-11-30 17:27:30 +0100513 gnvs->aoac.ic0e = is_aoac_device_enabled(FCH_AOAC_DEV_I2C0);
514 gnvs->aoac.ic1e = is_aoac_device_enabled(FCH_AOAC_DEV_I2C1);
515 gnvs->aoac.ic2e = is_aoac_device_enabled(FCH_AOAC_DEV_I2C2);
516 gnvs->aoac.ic3e = is_aoac_device_enabled(FCH_AOAC_DEV_I2C3);
517 gnvs->aoac.ut0e = is_aoac_device_enabled(FCH_AOAC_DEV_UART0);
518 gnvs->aoac.ut1e = is_aoac_device_enabled(FCH_AOAC_DEV_UART1);
519 gnvs->aoac.ehce = is_aoac_device_enabled(FCH_AOAC_DEV_USB2);
520 gnvs->aoac.xhce = is_aoac_device_enabled(FCH_AOAC_DEV_USB3);
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600521 /* Rely on these being in sync with devicetree */
Kyösti Mälkkie7377552018-06-21 16:20:55 +0300522 sd = pcidev_path_on_root(SD_DEVFN);
Marshall Dawson6d3b7e62019-04-18 17:01:01 -0600523 gnvs->aoac.sd_e = sd && sd->enabled ? 1 : 0;
Kyösti Mälkkie7377552018-06-21 16:20:55 +0300524 sata = pcidev_path_on_root(SATA_DEVFN);
Marshall Dawson6d3b7e62019-04-18 17:01:01 -0600525 gnvs->aoac.st_e = sata && sata->enabled ? 1 : 0;
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600526 gnvs->aoac.espi = 1;
527
528 amdfw_rom = 0x20000 - (0x80000 << CONFIG_AMD_FWM_POSITION_INDEX);
529 xhci_fw = read32((void *)(amdfw_rom + XHCI_FW_SIG_OFFSET));
530
531 fwaddr = 2 + read16((void *)(xhci_fw + XHCI_FW_ADDR_OFFSET
532 + XHCI_FW_BOOTRAM_SIZE));
533 fwsize = read16((void *)(xhci_fw + XHCI_FW_SIZE_OFFSET
534 + XHCI_FW_BOOTRAM_SIZE));
535 gnvs->fw00 = 0;
536 gnvs->fw01 = ((32 * KiB) << 16) + 0;
537 gnvs->fw02 = fwaddr + XHCI_FW_BOOTRAM_SIZE;
538 gnvs->fw03 = fwsize << 16;
539
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600540 gnvs->eh10 = pci_read_config32(SOC_EHCI1_DEV, PCI_BASE_ADDRESS_0)
541 & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
542}
543
Marc Jonesdfeb1c42017-08-07 19:08:24 -0600544void southbridge_final(void *chip_info)
Marc Jones24484842017-05-04 21:17:45 -0600545{
Richard Spiegel6a389142018-03-05 14:28:10 -0700546 uint8_t restored_power = PM_S5_AT_POWER_RECOVERY;
547
Julius Wernercd49cce2019-03-05 16:53:33 -0800548 if (CONFIG(MAINBOARD_POWER_RESTORE))
Richard Spiegel6a389142018-03-05 14:28:10 -0700549 restored_power = PM_RESTORE_S0_IF_PREV_S0;
550 pm_write8(PM_RTC_SHADOW, restored_power);
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600551
552 set_sb_final_nvs();
Marc Jones24484842017-05-04 21:17:45 -0600553}
Marshall Dawson8a906df2017-06-13 14:19:02 -0600554
555/*
556 * Update the PCI devices with a valid IRQ number
557 * that is set in the mainboard PCI_IRQ structures.
558 */
559static void set_pci_irqs(void *unused)
560{
561 /* Write PCI_INTR regs 0xC00/0xC01 */
562 write_pci_int_table();
563
564 /* Write IRQs for all devicetree enabled devices */
565 write_pci_cfg_irqs();
566}
567
568/*
569 * Hook this function into the PCI state machine
570 * on entry into BS_DEV_ENABLE.
571 */
572BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_ENTRY, set_pci_irqs, NULL);