blob: f411179c92231acc7d762e94ba4e6d3384fd9fe7 [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>
Marc Jonesdfeb1c42017-08-07 19:08:24 -060020#include <soc/southbridge.h>
Marc Jones24484842017-05-04 21:17:45 -060021#include <soc/smi.h>
Richard Spiegel376dc822017-12-01 08:24:26 -070022#include <soc/amd_pci_int_defs.h>
Richard Spiegelbec44f22017-11-24 07:41:29 -070023#include <delay.h>
24#include <soc/pci_devs.h>
Marshall Dawson2942db62017-12-14 10:00:27 -070025#include <agesa_headers.h>
Richard Spiegeldbee8ae2018-05-09 17:34:04 -070026#include <soc/nvs.h>
Elyes HAOUAS27d02d82019-05-15 21:11:39 +020027#include <types.h>
Marshall Dawson2942db62017-12-14 10:00:27 -070028
Richard Spiegel0e0e93c2018-03-13 10:19:51 -070029/*
30 * Table of devices that need their AOAC registers enabled and waited
31 * upon (usually about .55 milliseconds). Instead of individual delays
32 * waiting for each device to become available, a single delay will be
Richard Spiegel6dfbb592018-03-15 15:45:44 -070033 * executed.
Richard Spiegel0e0e93c2018-03-13 10:19:51 -070034 */
Felix Heldab0d85c2020-11-30 17:27:30 +010035static const unsigned int aoac_devs[] = {
36 FCH_AOAC_DEV_UART0 + CONFIG_UART_FOR_CONSOLE * 2,
37 FCH_AOAC_DEV_AMBA,
38 FCH_AOAC_DEV_I2C0,
39 FCH_AOAC_DEV_I2C1,
40 FCH_AOAC_DEV_I2C2,
41 FCH_AOAC_DEV_I2C3,
Richard Spiegel0e0e93c2018-03-13 10:19:51 -070042};
43
Marshall Dawson2942db62017-12-14 10:00:27 -070044static int is_sata_config(void)
45{
Richard Spiegelbdd272a2018-10-16 13:53:05 -070046 return !((SataNativeIde == CONFIG_STONEYRIDGE_SATA_MODE)
47 || (SataLegacyIde == CONFIG_STONEYRIDGE_SATA_MODE));
Marshall Dawson2942db62017-12-14 10:00:27 -070048}
49
Richard Spiegel7ea8e022018-01-16 14:40:10 -070050static inline int sb_sata_enable(void)
51{
52 /* True if IDE or AHCI. */
Richard Spiegelbdd272a2018-10-16 13:53:05 -070053 return (SataNativeIde == CONFIG_STONEYRIDGE_SATA_MODE) ||
54 (SataAhci == CONFIG_STONEYRIDGE_SATA_MODE);
Richard Spiegel7ea8e022018-01-16 14:40:10 -070055}
56
57static inline int sb_ide_enable(void)
58{
59 /* True if IDE or LEGACY IDE. */
Richard Spiegelbdd272a2018-10-16 13:53:05 -070060 return (SataNativeIde == CONFIG_STONEYRIDGE_SATA_MODE) ||
61 (SataLegacyIde == CONFIG_STONEYRIDGE_SATA_MODE);
Richard Spiegel7ea8e022018-01-16 14:40:10 -070062}
63
Marshall Dawson2942db62017-12-14 10:00:27 -070064void SetFchResetParams(FCH_RESET_INTERFACE *params)
65{
Kyösti Mälkkie7377552018-06-21 16:20:55 +030066 const struct device *dev = pcidev_path_on_root(SATA_DEVFN);
Julius Wernercd49cce2019-03-05 16:53:33 -080067 params->Xhci0Enable = CONFIG(STONEYRIDGE_XHCI_ENABLE);
Richard Spiegelbb18b432018-08-03 10:37:28 -070068 if (dev && dev->enabled) {
69 params->SataEnable = sb_sata_enable();
70 params->IdeEnable = sb_ide_enable();
71 } else {
72 params->SataEnable = FALSE;
73 params->IdeEnable = FALSE;
74 }
Marshall Dawson2942db62017-12-14 10:00:27 -070075}
76
77void SetFchEnvParams(FCH_INTERFACE *params)
78{
Kyösti Mälkkie7377552018-06-21 16:20:55 +030079 const struct device *dev = pcidev_path_on_root(SATA_DEVFN);
Marshall Dawson2942db62017-12-14 10:00:27 -070080 params->AzaliaController = AzEnable;
81 params->SataClass = CONFIG_STONEYRIDGE_SATA_MODE;
Richard Spiegelbb18b432018-08-03 10:37:28 -070082 if (dev && dev->enabled) {
83 params->SataEnable = is_sata_config();
84 params->IdeEnable = !params->SataEnable;
85 params->SataIdeMode = (CONFIG_STONEYRIDGE_SATA_MODE ==
86 SataLegacyIde);
87 } else {
88 params->SataEnable = FALSE;
89 params->IdeEnable = FALSE;
90 params->SataIdeMode = FALSE;
91 }
Marshall Dawson2942db62017-12-14 10:00:27 -070092}
93
94void SetFchMidParams(FCH_INTERFACE *params)
95{
96 SetFchEnvParams(params);
97}
Marc Jones24484842017-05-04 21:17:45 -060098
Richard Spiegel376dc822017-12-01 08:24:26 -070099/*
100 * Table of APIC register index and associated IRQ name. Using IDX_XXX_NAME
Jonathan Neuschäfer5268b762018-02-12 12:24:25 +0100101 * provides a visible association with the index, therefore helping
Richard Spiegel376dc822017-12-01 08:24:26 -0700102 * maintainability of table. If a new index/name is defined in
103 * amd_pci_int_defs.h, just add the pair at the end of this table.
104 * Order is not important.
105 */
Elyes HAOUAS68ec3eb2019-06-22 09:21:18 +0200106static const struct irq_idx_name irq_association[] = {
Richard Spiegele89d4442017-12-08 07:52:42 -0700107 { PIRQ_A, "INTA#" },
108 { PIRQ_B, "INTB#" },
109 { PIRQ_C, "INTC#" },
110 { PIRQ_D, "INTD#" },
111 { PIRQ_E, "INTE#" },
112 { PIRQ_F, "INTF#" },
113 { PIRQ_G, "INTG#" },
114 { PIRQ_H, "INTH#" },
115 { PIRQ_MISC, "Misc" },
116 { PIRQ_MISC0, "Misc0" },
117 { PIRQ_MISC1, "Misc1" },
118 { PIRQ_MISC2, "Misc2" },
Richard Spiegel376dc822017-12-01 08:24:26 -0700119 { PIRQ_SIRQA, "Ser IRQ INTA" },
120 { PIRQ_SIRQB, "Ser IRQ INTB" },
121 { PIRQ_SIRQC, "Ser IRQ INTC" },
122 { PIRQ_SIRQD, "Ser IRQ INTD" },
Richard Spiegele89d4442017-12-08 07:52:42 -0700123 { PIRQ_SCI, "SCI" },
124 { PIRQ_SMBUS, "SMBUS" },
125 { PIRQ_ASF, "ASF" },
126 { PIRQ_HDA, "HDA" },
127 { PIRQ_FC, "FC" },
128 { PIRQ_PMON, "PerMon" },
129 { PIRQ_SD, "SD" },
130 { PIRQ_SDIO, "SDIOt" },
Richard Spiegele89d4442017-12-08 07:52:42 -0700131 { PIRQ_EHCI, "EHCI" },
132 { PIRQ_XHCI, "XHCI" },
133 { PIRQ_SATA, "SATA" },
134 { PIRQ_GPIO, "GPIO" },
135 { PIRQ_I2C0, "I2C0" },
136 { PIRQ_I2C1, "I2C1" },
137 { PIRQ_I2C2, "I2C2" },
138 { PIRQ_I2C3, "I2C3" },
139 { PIRQ_UART0, "UART0" },
140 { PIRQ_UART1, "UART1" },
Richard Spiegel376dc822017-12-01 08:24:26 -0700141};
142
143const struct irq_idx_name *sb_get_apic_reg_association(size_t *size)
144{
145 *size = ARRAY_SIZE(irq_association);
146 return irq_association;
147}
148
Richard Spiegel0e0e93c2018-03-13 10:19:51 -0700149void enable_aoac_devices(void)
Garrett Kirkendalla0ff6fc2018-03-06 09:23:47 -0600150{
151 bool status;
Richard Spiegel0e0e93c2018-03-13 10:19:51 -0700152 int i;
Garrett Kirkendalla0ff6fc2018-03-06 09:23:47 -0600153
Richard Spiegel0e0e93c2018-03-13 10:19:51 -0700154 for (i = 0; i < ARRAY_SIZE(aoac_devs); i++)
Felix Heldab0d85c2020-11-30 17:27:30 +0100155 power_on_aoac_device(aoac_devs[i]);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700156
Richard Spiegel0e0e93c2018-03-13 10:19:51 -0700157 /* Wait for AOAC devices to indicate power and clock OK */
158 do {
159 udelay(100);
160 status = true;
161 for (i = 0; i < ARRAY_SIZE(aoac_devs); i++)
Felix Heldab0d85c2020-11-30 17:27:30 +0100162 status &= is_aoac_device_enabled(aoac_devs[i]);
Richard Spiegel0e0e93c2018-03-13 10:19:51 -0700163 } while (!status);
164}
165
Marshall Dawson6ab5ed32019-05-29 09:24:18 -0600166static void sb_enable_lpc(void)
Richard Spiegelbec44f22017-11-24 07:41:29 -0700167{
168 u8 byte;
169
170 /* Enable LPC controller */
Marshall Dawson939bfcc2019-05-05 15:39:40 -0600171 byte = pm_io_read8(PM_LPC_GATING);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700172 byte |= PM_LPC_ENABLE;
Marshall Dawson939bfcc2019-05-05 15:39:40 -0600173 pm_io_write8(PM_LPC_GATING, byte);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700174}
175
Marshall Dawson6ab5ed32019-05-29 09:24:18 -0600176static void sb_lpc_decode(void)
Richard Spiegelbec44f22017-11-24 07:41:29 -0700177{
178 u32 tmp = 0;
179
180 /* Enable I/O decode to LPC bus */
181 tmp = DECODE_ENABLE_PARALLEL_PORT0 | DECODE_ENABLE_PARALLEL_PORT2
182 | DECODE_ENABLE_PARALLEL_PORT4 | DECODE_ENABLE_SERIAL_PORT0
183 | DECODE_ENABLE_SERIAL_PORT1 | DECODE_ENABLE_SERIAL_PORT2
184 | DECODE_ENABLE_SERIAL_PORT3 | DECODE_ENABLE_SERIAL_PORT4
185 | DECODE_ENABLE_SERIAL_PORT5 | DECODE_ENABLE_SERIAL_PORT6
186 | DECODE_ENABLE_SERIAL_PORT7 | DECODE_ENABLE_AUDIO_PORT0
187 | DECODE_ENABLE_AUDIO_PORT1 | DECODE_ENABLE_AUDIO_PORT2
188 | DECODE_ENABLE_AUDIO_PORT3 | DECODE_ENABLE_MSS_PORT2
189 | DECODE_ENABLE_MSS_PORT3 | DECODE_ENABLE_FDC_PORT0
190 | DECODE_ENABLE_FDC_PORT1 | DECODE_ENABLE_GAME_PORT
191 | DECODE_ENABLE_KBC_PORT | DECODE_ENABLE_ACPIUC_PORT
192 | DECODE_ENABLE_ADLIB_PORT;
193
Marshall Dawson6ab5ed32019-05-29 09:24:18 -0600194 /* Decode SIOs at 2E/2F and 4E/4F */
195 if (CONFIG(STONEYRIDGE_LEGACY_FREE))
196 tmp |= DECODE_ALTERNATE_SIO_ENABLE | DECODE_SIO_ENABLE;
197
198 lpc_enable_decode(tmp);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700199}
200
Raul E Rangel5b058232018-06-28 16:31:45 -0600201static void sb_enable_cf9_io(void)
202{
203 uint32_t reg = pm_read32(PM_DECODE_EN);
204
205 pm_write32(PM_DECODE_EN, reg | CF9_IO_EN);
206}
207
Raul E Rangel9abc3fe2018-06-28 16:31:45 -0600208static void sb_enable_legacy_io(void)
209{
210 uint32_t reg = pm_read32(PM_DECODE_EN);
211
212 pm_write32(PM_DECODE_EN, reg | LEGACY_IO_EN);
213}
214
Richard Spiegelc93d4ab2019-02-12 19:17:02 -0700215void sb_clk_output_48Mhz(u32 osc)
Richard Spiegelbec44f22017-11-24 07:41:29 -0700216{
217 u32 ctrl;
218
219 /*
Richard Spiegelc93d4ab2019-02-12 19:17:02 -0700220 * Clear the disable for OSCOUT1 (signal typically named XnnM_25M_48M)
221 * or OSCOUT2 (USBCLK/25M_48M_OSC). The frequency defaults to 48MHz.
Richard Spiegelbec44f22017-11-24 07:41:29 -0700222 */
Marshall Dawsonb4b9efc2019-05-01 17:33:42 -0600223 ctrl = misc_read32(MISC_CLK_CNTL1);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700224
Richard Spiegelc93d4ab2019-02-12 19:17:02 -0700225 switch (osc) {
226 case 1:
227 ctrl &= ~OSCOUT1_CLK_OUTPUT_ENB;
228 break;
229 case 2:
230 ctrl &= ~OSCOUT2_CLK_OUTPUT_ENB;
231 break;
232 default:
233 return; /* do nothing if invalid */
234 }
Marshall Dawsonb4b9efc2019-05-01 17:33:42 -0600235 misc_write32(MISC_CLK_CNTL1, ctrl);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700236}
237
Martin Rothf09b4b62020-07-06 23:35:40 -0600238static void sb_init_spi_base(void)
Marshall Dawsoneceaa972019-05-05 18:35:12 -0600239{
Richard Spiegelbec44f22017-11-24 07:41:29 -0700240 /* Make sure the base address is predictable */
Martin Rothf09b4b62020-07-06 23:35:40 -0600241 if (ENV_X86)
242 lpc_set_spibase(SPI_BASE_ADDRESS);
Furquan Shaikhd82c7d22020-05-09 17:18:48 -0700243 lpc_enable_spi_rom(SPI_ROM_ENABLE);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700244}
245
246void sb_set_spi100(u16 norm, u16 fast, u16 alt, u16 tpm)
247{
Martin Rothcbdd8902020-07-23 16:12:33 -0600248 spi_write16(SPI100_SPEED_CONFIG,
Richard Spiegelbec44f22017-11-24 07:41:29 -0700249 (norm << SPI_NORM_SPEED_NEW_SH) |
250 (fast << SPI_FAST_SPEED_NEW_SH) |
251 (alt << SPI_ALT_SPEED_NEW_SH) |
252 (tpm << SPI_TPM_SPEED_NEW_SH));
Martin Rothcbdd8902020-07-23 16:12:33 -0600253 spi_write16(SPI100_ENABLE, SPI_USE_SPI100);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700254}
255
256void sb_disable_4dw_burst(void)
257{
Martin Rothcbdd8902020-07-23 16:12:33 -0600258 spi_write16(SPI100_HOST_PREF_CONFIG,
259 spi_read16(SPI100_HOST_PREF_CONFIG) & ~SPI_RD4DW_EN_HOST);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700260}
261
Richard Spiegelbec44f22017-11-24 07:41:29 -0700262void sb_read_mode(u32 mode)
263{
Martin Rothcbdd8902020-07-23 16:12:33 -0600264 spi_write32(SPI_CNTRL0,
265 (spi_read32(SPI_CNTRL0) & ~SPI_READ_MODE_MASK) | mode);
Richard Spiegelbec44f22017-11-24 07:41:29 -0700266}
267
Raul E Rangel79053412018-08-06 10:40:02 -0600268static void setup_spread_spectrum(int *reboot)
Raul E Rangel6b0fc802018-08-02 15:56:34 -0600269{
270 uint16_t rstcfg = pm_read16(PWR_RESET_CFG);
271
272 rstcfg &= ~TOGGLE_ALL_PWR_GOOD;
273 pm_write16(PWR_RESET_CFG, rstcfg);
274
275 uint32_t cntl1 = misc_read32(MISC_CLK_CNTL1);
276
277 if (cntl1 & CG1PLL_FBDIV_TEST) {
278 printk(BIOS_DEBUG, "Spread spectrum is ready\n");
279 misc_write32(MISC_CGPLL_CONFIG1,
280 misc_read32(MISC_CGPLL_CONFIG1) |
281 CG1PLL_SPREAD_SPECTRUM_ENABLE);
282
283 return;
284 }
285
286 printk(BIOS_DEBUG, "Setting up spread spectrum\n");
287
288 uint32_t cfg6 = misc_read32(MISC_CGPLL_CONFIG6);
289 cfg6 &= ~CG1PLL_LF_MODE_MASK;
Marshall Dawsonecce8472018-10-05 15:41:03 -0600290 cfg6 |= (0x0f8 << CG1PLL_LF_MODE_SHIFT) & CG1PLL_LF_MODE_MASK;
Raul E Rangel6b0fc802018-08-02 15:56:34 -0600291 misc_write32(MISC_CGPLL_CONFIG6, cfg6);
292
293 uint32_t cfg3 = misc_read32(MISC_CGPLL_CONFIG3);
294 cfg3 &= ~CG1PLL_REFDIV_MASK;
295 cfg3 |= (0x003 << CG1PLL_REFDIV_SHIFT) & CG1PLL_REFDIV_MASK;
296 cfg3 &= ~CG1PLL_FBDIV_MASK;
Marshall Dawsonecce8472018-10-05 15:41:03 -0600297 cfg3 |= (0x04b << CG1PLL_FBDIV_SHIFT) & CG1PLL_FBDIV_MASK;
Raul E Rangel6b0fc802018-08-02 15:56:34 -0600298 misc_write32(MISC_CGPLL_CONFIG3, cfg3);
299
300 uint32_t cfg5 = misc_read32(MISC_CGPLL_CONFIG5);
Marshall Dawsonedba21e2018-10-05 19:01:52 -0600301 cfg5 &= ~SS_AMOUNT_NFRAC_SLIP_MASK;
302 cfg5 |= (0x2 << SS_AMOUNT_NFRAC_SLIP_SHIFT) & SS_AMOUNT_NFRAC_SLIP_MASK;
Raul E Rangel6b0fc802018-08-02 15:56:34 -0600303 misc_write32(MISC_CGPLL_CONFIG5, cfg5);
304
305 uint32_t cfg4 = misc_read32(MISC_CGPLL_CONFIG4);
Marshall Dawsonedba21e2018-10-05 19:01:52 -0600306 cfg4 &= ~SS_AMOUNT_DSFRAC_MASK;
307 cfg4 |= (0xd000 << SS_AMOUNT_DSFRAC_SHIFT) & SS_AMOUNT_DSFRAC_MASK;
308 cfg4 &= ~SS_STEP_SIZE_DSFRAC_MASK;
309 cfg4 |= (0x02d5 << SS_STEP_SIZE_DSFRAC_SHIFT)
310 & SS_STEP_SIZE_DSFRAC_MASK;
Raul E Rangel6b0fc802018-08-02 15:56:34 -0600311 misc_write32(MISC_CGPLL_CONFIG4, cfg4);
312
313 rstcfg |= TOGGLE_ALL_PWR_GOOD;
314 pm_write16(PWR_RESET_CFG, rstcfg);
315
316 cntl1 |= CG1PLL_FBDIV_TEST;
317 misc_write32(MISC_CLK_CNTL1, cntl1);
318
Raul E Rangel79053412018-08-06 10:40:02 -0600319 *reboot = 1;
320}
321
322static void setup_misc(int *reboot)
323{
324 /* Undocumented register */
325 uint32_t reg = misc_read32(0x50);
326 if (!(reg & BIT(16))) {
327 reg |= BIT(16);
328
329 misc_write32(0x50, reg);
330 *reboot = 1;
331 }
Raul E Rangel6b0fc802018-08-02 15:56:34 -0600332}
333
Richard Spiegelb40e1932018-10-24 12:51:21 -0700334static void fch_smbus_init(void)
335{
Aaron Durbin5c0ef702020-01-28 10:56:46 -0700336 /* 400 kHz smbus speed. */
337 const uint8_t smbus_speed = (66000000 / (400000 * 4));
338
Richard Spiegelb40e1932018-10-24 12:51:21 -0700339 pm_write8(SMB_ASF_IO_BASE, SMB_BASE_ADDR >> 8);
Aaron Durbin5c0ef702020-01-28 10:56:46 -0700340 smbus_write8(SMBTIMING, smbus_speed);
Richard Spiegelb40e1932018-10-24 12:51:21 -0700341 /* Clear all SMBUS status bits */
Marshall Dawson753c2252019-05-05 14:08:59 -0600342 smbus_write8(SMBHSTSTAT, SMBHST_STAT_CLEAR);
343 smbus_write8(SMBSLVSTAT, SMBSLV_STAT_CLEAR);
344 asf_write8(SMBHSTSTAT, SMBHST_STAT_CLEAR);
345 asf_write8(SMBSLVSTAT, SMBSLV_STAT_CLEAR);
Richard Spiegelb40e1932018-10-24 12:51:21 -0700346}
347
Raul E Rangeld820f4b82018-08-13 10:39:03 -0600348/* Before console init */
Richard Spiegelbec44f22017-11-24 07:41:29 -0700349void bootblock_fch_early_init(void)
350{
Raul E Rangel79053412018-08-06 10:40:02 -0600351 int reboot = 0;
352
Marshall Dawson6ab5ed32019-05-29 09:24:18 -0600353 lpc_enable_rom();
354 sb_enable_lpc();
355 lpc_enable_port80();
Richard Spiegelbec44f22017-11-24 07:41:29 -0700356 sb_lpc_decode();
Marshall Dawson6ab5ed32019-05-29 09:24:18 -0600357 lpc_enable_spi_prefetch();
Marshall Dawsoneceaa972019-05-05 18:35:12 -0600358 sb_init_spi_base();
Marc Jonescfb16802018-04-20 16:27:41 -0600359 sb_disable_4dw_burst(); /* Must be disabled on CZ(ST) */
Michał Żygowski73a544d2019-11-24 14:16:34 +0100360 enable_acpimmio_decode_pm04();
Richard Spiegelb40e1932018-10-24 12:51:21 -0700361 fch_smbus_init();
Raul E Rangel5b058232018-06-28 16:31:45 -0600362 sb_enable_cf9_io();
Raul E Rangel79053412018-08-06 10:40:02 -0600363 setup_spread_spectrum(&reboot);
364 setup_misc(&reboot);
365
366 if (reboot)
Nico Huber73c11192018-10-06 18:20:47 +0200367 warm_reset();
Raul E Rangel79053412018-08-06 10:40:02 -0600368
Raul E Rangel9abc3fe2018-06-28 16:31:45 -0600369 sb_enable_legacy_io();
Richard Spiegel0e0e93c2018-03-13 10:19:51 -0700370 enable_aoac_devices();
Richard Spiegelbec44f22017-11-24 07:41:29 -0700371}
372
Edward Hillcc680342018-08-10 16:20:02 -0600373static void print_num_status_bits(int num_bits, uint32_t status,
374 const char *const bit_names[])
375{
376 int i;
377
378 if (!status)
379 return;
380
381 for (i = num_bits - 1; i >= 0; i--) {
382 if (status & (1 << i)) {
383 if (bit_names[i])
384 printk(BIOS_DEBUG, "%s ", bit_names[i]);
385 else
386 printk(BIOS_DEBUG, "BIT%d ", i);
387 }
388 }
389}
390
391static void sb_print_pmxc0_status(void)
392{
393 /* PMxC0 S5/Reset Status shows the source of previous reset. */
394 uint32_t pmxc0_status = pm_read32(PM_RST_STATUS);
395
Edward Hill917b4002018-10-02 14:17:19 -0600396 static const char *const pmxc0_status_bits[32] = {
Edward Hillcc680342018-08-10 16:20:02 -0600397 [0] = "ThermalTrip",
398 [1] = "FourSecondPwrBtn",
399 [2] = "Shutdown",
400 [3] = "ThermalTripFromTemp",
401 [4] = "RemotePowerDownFromASF",
402 [5] = "ShutDownFan0",
403 [16] = "UserRst",
404 [17] = "SoftPciRst",
405 [18] = "DoInit",
406 [19] = "DoReset",
407 [20] = "DoFullReset",
408 [21] = "SleepReset",
409 [22] = "KbReset",
410 [23] = "LtReset",
411 [24] = "FailBootRst",
412 [25] = "WatchdogIssueReset",
413 [26] = "RemoteResetFromASF",
414 [27] = "SyncFlood",
415 [28] = "HangReset",
416 [29] = "EcWatchdogRst",
Edward Hillcc680342018-08-10 16:20:02 -0600417 };
418
Edward Hill917b4002018-10-02 14:17:19 -0600419 printk(BIOS_DEBUG, "PMxC0 STATUS: 0x%x ", pmxc0_status);
Edward Hillcc680342018-08-10 16:20:02 -0600420 print_num_status_bits(ARRAY_SIZE(pmxc0_status_bits), pmxc0_status,
421 pmxc0_status_bits);
Edward Hill917b4002018-10-02 14:17:19 -0600422 printk(BIOS_DEBUG, "\n");
Edward Hillcc680342018-08-10 16:20:02 -0600423}
424
Raul E Rangeld820f4b82018-08-13 10:39:03 -0600425/* After console init */
Edward Hillcc680342018-08-10 16:20:02 -0600426void bootblock_fch_init(void)
427{
428 sb_print_pmxc0_status();
429}
Raul E Rangeld820f4b82018-08-13 10:39:03 -0600430
Elyes HAOUASc5ad2672018-12-05 10:58:34 +0100431void sb_enable(struct device *dev)
Marc Jones24484842017-05-04 21:17:45 -0600432{
Marc Jonesdfeb1c42017-08-07 19:08:24 -0600433 printk(BIOS_DEBUG, "%s\n", __func__);
Marc Jones24484842017-05-04 21:17:45 -0600434}
435
Marc Jonesdfeb1c42017-08-07 19:08:24 -0600436static void sb_init_acpi_ports(void)
Marc Jones24484842017-05-04 21:17:45 -0600437{
Marshall Dawson91b80412017-09-27 16:44:40 -0600438 u32 reg;
439
Marc Jones24484842017-05-04 21:17:45 -0600440 /* We use some of these ports in SMM regardless of whether or not
441 * ACPI tables are generated. Enable these ports indiscriminately.
442 */
443
444 pm_write16(PM_EVT_BLK, ACPI_PM_EVT_BLK);
445 pm_write16(PM1_CNT_BLK, ACPI_PM1_CNT_BLK);
446 pm_write16(PM_TMR_BLK, ACPI_PM_TMR_BLK);
447 pm_write16(PM_GPE0_BLK, ACPI_GPE0_BLK);
Michał Żygowski9550e972020-03-20 13:56:46 +0100448 /* CpuControl is in \_SB.CP00, 6 bytes */
Marc Jones24484842017-05-04 21:17:45 -0600449 pm_write16(PM_CPU_CTRL, ACPI_CPU_CONTROL);
450
Julius Wernercd49cce2019-03-05 16:53:33 -0800451 if (CONFIG(HAVE_SMI_HANDLER)) {
Marshall Dawsona05fdcb2017-09-27 15:01:37 -0600452 /* APMC - SMI Command Port */
Marshall Dawsone9b862e2017-09-22 15:14:46 -0600453 pm_write16(PM_ACPI_SMI_CMD, APM_CNT);
Marshall Dawsona05fdcb2017-09-27 15:01:37 -0600454 configure_smi(SMITYPE_SMI_CMD_PORT, SMI_MODE_SMI);
Marshall Dawson91b80412017-09-27 16:44:40 -0600455
456 /* SMI on SlpTyp requires sending SMI before completion
457 * response of the I/O write. The BKDG also specifies
458 * clearing ForceStpClkRetry for SMI trapping.
459 */
460 reg = pm_read32(PM_PCI_CTRL);
461 reg |= FORCE_SLPSTATE_RETRY;
462 reg &= ~FORCE_STPCLK_RETRY;
463 pm_write32(PM_PCI_CTRL, reg);
464
465 /* Disable SlpTyp feature */
466 reg = pm_read8(PM_RST_CTRL1);
467 reg &= ~SLPTYPE_CONTROL_EN;
468 pm_write8(PM_RST_CTRL1, reg);
469
470 configure_smi(SMITYPE_SLP_TYP, SMI_MODE_SMI);
Marc Jones24484842017-05-04 21:17:45 -0600471 } else {
472 pm_write16(PM_ACPI_SMI_CMD, 0);
473 }
474
Marshall Dawson5e2e74f2017-11-10 09:59:56 -0700475 /* Decode ACPI registers and enable standard features */
476 pm_write8(PM_ACPI_CONF, PM_ACPI_DECODE_STD |
477 PM_ACPI_GLOBAL_EN |
478 PM_ACPI_RTC_EN_EN |
479 PM_ACPI_TIMER_EN_EN);
Marc Jones24484842017-05-04 21:17:45 -0600480}
481
Richard Spiegeldbee8ae2018-05-09 17:34:04 -0700482static void set_nvs_sws(void *unused)
483{
Aaron Durbin5a5e4d02020-08-14 16:22:11 -0600484 struct acpi_pm_gpe_state *state;
Kyösti Mälkki0c1dd9c2020-06-17 23:37:49 +0300485 struct global_nvs *gnvs;
Richard Spiegeldbee8ae2018-05-09 17:34:04 -0700486
Aaron Durbin5a5e4d02020-08-14 16:22:11 -0600487 state = cbmem_find(CBMEM_ID_POWER_STATE);
488 if (state == NULL)
Richard Spiegel35282a02018-06-14 14:57:54 -0700489 return;
Kyösti Mälkki5daa1d32020-06-14 12:01:58 +0300490 gnvs = acpi_get_gnvs();
Richard Spiegeldbee8ae2018-05-09 17:34:04 -0700491 if (gnvs == NULL)
492 return;
493
Aaron Durbin5a5e4d02020-08-14 16:22:11 -0600494 acpi_fill_gnvs(gnvs, state);
Richard Spiegeldbee8ae2018-05-09 17:34:04 -0700495}
496
497BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, set_nvs_sws, NULL);
498
Marc Jonesdfeb1c42017-08-07 19:08:24 -0600499void southbridge_init(void *chip_info)
Marc Jones24484842017-05-04 21:17:45 -0600500{
Aaron Durbin5a5e4d02020-08-14 16:22:11 -0600501 struct acpi_pm_gpe_state *state;
502
Marc Jonesdfeb1c42017-08-07 19:08:24 -0600503 sb_init_acpi_ports();
Aaron Durbin5a5e4d02020-08-14 16:22:11 -0600504
505 state = cbmem_add(CBMEM_ID_POWER_STATE, sizeof(*state));
506 if (state) {
507 acpi_fill_pm_gpe_state(state);
508 acpi_pm_gpe_add_events_print_events(state);
509 }
510
511 acpi_clear_pm_gpe_status();
Marc Jones24484842017-05-04 21:17:45 -0600512}
513
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600514static void set_sb_final_nvs(void)
515{
516 uintptr_t amdfw_rom;
517 uintptr_t xhci_fw;
518 uintptr_t fwaddr;
519 size_t fwsize;
Richard Spiegel41baf0c2018-10-22 13:57:18 -0700520 const struct device *sd, *sata;
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600521
Kyösti Mälkki0c1dd9c2020-06-17 23:37:49 +0300522 struct global_nvs *gnvs = acpi_get_gnvs();
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600523 if (gnvs == NULL)
524 return;
525
Felix Heldab0d85c2020-11-30 17:27:30 +0100526 gnvs->aoac.ic0e = is_aoac_device_enabled(FCH_AOAC_DEV_I2C0);
527 gnvs->aoac.ic1e = is_aoac_device_enabled(FCH_AOAC_DEV_I2C1);
528 gnvs->aoac.ic2e = is_aoac_device_enabled(FCH_AOAC_DEV_I2C2);
529 gnvs->aoac.ic3e = is_aoac_device_enabled(FCH_AOAC_DEV_I2C3);
530 gnvs->aoac.ut0e = is_aoac_device_enabled(FCH_AOAC_DEV_UART0);
531 gnvs->aoac.ut1e = is_aoac_device_enabled(FCH_AOAC_DEV_UART1);
532 gnvs->aoac.ehce = is_aoac_device_enabled(FCH_AOAC_DEV_USB2);
533 gnvs->aoac.xhce = is_aoac_device_enabled(FCH_AOAC_DEV_USB3);
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600534 /* Rely on these being in sync with devicetree */
Kyösti Mälkkie7377552018-06-21 16:20:55 +0300535 sd = pcidev_path_on_root(SD_DEVFN);
Marshall Dawson6d3b7e62019-04-18 17:01:01 -0600536 gnvs->aoac.sd_e = sd && sd->enabled ? 1 : 0;
Kyösti Mälkkie7377552018-06-21 16:20:55 +0300537 sata = pcidev_path_on_root(SATA_DEVFN);
Marshall Dawson6d3b7e62019-04-18 17:01:01 -0600538 gnvs->aoac.st_e = sata && sata->enabled ? 1 : 0;
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600539 gnvs->aoac.espi = 1;
540
541 amdfw_rom = 0x20000 - (0x80000 << CONFIG_AMD_FWM_POSITION_INDEX);
542 xhci_fw = read32((void *)(amdfw_rom + XHCI_FW_SIG_OFFSET));
543
544 fwaddr = 2 + read16((void *)(xhci_fw + XHCI_FW_ADDR_OFFSET
545 + XHCI_FW_BOOTRAM_SIZE));
546 fwsize = read16((void *)(xhci_fw + XHCI_FW_SIZE_OFFSET
547 + XHCI_FW_BOOTRAM_SIZE));
548 gnvs->fw00 = 0;
549 gnvs->fw01 = ((32 * KiB) << 16) + 0;
550 gnvs->fw02 = fwaddr + XHCI_FW_BOOTRAM_SIZE;
551 gnvs->fw03 = fwsize << 16;
552
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600553 gnvs->eh10 = pci_read_config32(SOC_EHCI1_DEV, PCI_BASE_ADDRESS_0)
554 & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
555}
556
Marc Jonesdfeb1c42017-08-07 19:08:24 -0600557void southbridge_final(void *chip_info)
Marc Jones24484842017-05-04 21:17:45 -0600558{
Richard Spiegel6a389142018-03-05 14:28:10 -0700559 uint8_t restored_power = PM_S5_AT_POWER_RECOVERY;
560
Julius Wernercd49cce2019-03-05 16:53:33 -0800561 if (CONFIG(MAINBOARD_POWER_RESTORE))
Richard Spiegel6a389142018-03-05 14:28:10 -0700562 restored_power = PM_RESTORE_S0_IF_PREV_S0;
563 pm_write8(PM_RTC_SHADOW, restored_power);
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600564
565 set_sb_final_nvs();
Marc Jones24484842017-05-04 21:17:45 -0600566}
Marshall Dawson8a906df2017-06-13 14:19:02 -0600567
568/*
569 * Update the PCI devices with a valid IRQ number
570 * that is set in the mainboard PCI_IRQ structures.
571 */
572static void set_pci_irqs(void *unused)
573{
574 /* Write PCI_INTR regs 0xC00/0xC01 */
575 write_pci_int_table();
576
577 /* Write IRQs for all devicetree enabled devices */
578 write_pci_cfg_irqs();
579}
580
581/*
582 * Hook this function into the PCI state machine
583 * on entry into BS_DEV_ENABLE.
584 */
585BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_ENTRY, set_pci_irqs, NULL);