blob: 84872abc4426ffe8c71c677a4fc1888d341079fc [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
Richard Spiegelb40e1932018-10-24 12:51:21 -0700335static void fch_smbus_init(void)
336{
Aaron Durbin5c0ef702020-01-28 10:56:46 -0700337 /* 400 kHz smbus speed. */
338 const uint8_t smbus_speed = (66000000 / (400000 * 4));
339
Richard Spiegelb40e1932018-10-24 12:51:21 -0700340 pm_write8(SMB_ASF_IO_BASE, SMB_BASE_ADDR >> 8);
Aaron Durbin5c0ef702020-01-28 10:56:46 -0700341 smbus_write8(SMBTIMING, smbus_speed);
Richard Spiegelb40e1932018-10-24 12:51:21 -0700342 /* Clear all SMBUS status bits */
Marshall Dawson753c2252019-05-05 14:08:59 -0600343 smbus_write8(SMBHSTSTAT, SMBHST_STAT_CLEAR);
344 smbus_write8(SMBSLVSTAT, SMBSLV_STAT_CLEAR);
345 asf_write8(SMBHSTSTAT, SMBHST_STAT_CLEAR);
346 asf_write8(SMBSLVSTAT, SMBSLV_STAT_CLEAR);
Richard Spiegelb40e1932018-10-24 12:51:21 -0700347}
348
Raul E Rangeld820f4b82018-08-13 10:39:03 -0600349/* Before console init */
Richard Spiegelbec44f22017-11-24 07:41:29 -0700350void bootblock_fch_early_init(void)
351{
Raul E Rangel79053412018-08-06 10:40:02 -0600352 int reboot = 0;
353
Marshall Dawson6ab5ed32019-05-29 09:24:18 -0600354 lpc_enable_rom();
355 sb_enable_lpc();
356 lpc_enable_port80();
Richard Spiegelbec44f22017-11-24 07:41:29 -0700357 sb_lpc_decode();
Marshall Dawson6ab5ed32019-05-29 09:24:18 -0600358 lpc_enable_spi_prefetch();
Marshall Dawsoneceaa972019-05-05 18:35:12 -0600359 sb_init_spi_base();
Marc Jonescfb16802018-04-20 16:27:41 -0600360 sb_disable_4dw_burst(); /* Must be disabled on CZ(ST) */
Michał Żygowski73a544d2019-11-24 14:16:34 +0100361 enable_acpimmio_decode_pm04();
Richard Spiegelb40e1932018-10-24 12:51:21 -0700362 fch_smbus_init();
Raul E Rangel5b058232018-06-28 16:31:45 -0600363 sb_enable_cf9_io();
Raul E Rangel79053412018-08-06 10:40:02 -0600364 setup_spread_spectrum(&reboot);
365 setup_misc(&reboot);
366
367 if (reboot)
Nico Huber73c11192018-10-06 18:20:47 +0200368 warm_reset();
Raul E Rangel79053412018-08-06 10:40:02 -0600369
Raul E Rangel9abc3fe2018-06-28 16:31:45 -0600370 sb_enable_legacy_io();
Richard Spiegel0e0e93c2018-03-13 10:19:51 -0700371 enable_aoac_devices();
Richard Spiegelbec44f22017-11-24 07:41:29 -0700372}
373
Edward Hillcc680342018-08-10 16:20:02 -0600374static void print_num_status_bits(int num_bits, uint32_t status,
375 const char *const bit_names[])
376{
377 int i;
378
379 if (!status)
380 return;
381
382 for (i = num_bits - 1; i >= 0; i--) {
383 if (status & (1 << i)) {
384 if (bit_names[i])
385 printk(BIOS_DEBUG, "%s ", bit_names[i]);
386 else
387 printk(BIOS_DEBUG, "BIT%d ", i);
388 }
389 }
390}
391
392static void sb_print_pmxc0_status(void)
393{
394 /* PMxC0 S5/Reset Status shows the source of previous reset. */
395 uint32_t pmxc0_status = pm_read32(PM_RST_STATUS);
396
Edward Hill917b4002018-10-02 14:17:19 -0600397 static const char *const pmxc0_status_bits[32] = {
Edward Hillcc680342018-08-10 16:20:02 -0600398 [0] = "ThermalTrip",
399 [1] = "FourSecondPwrBtn",
400 [2] = "Shutdown",
401 [3] = "ThermalTripFromTemp",
402 [4] = "RemotePowerDownFromASF",
403 [5] = "ShutDownFan0",
404 [16] = "UserRst",
405 [17] = "SoftPciRst",
406 [18] = "DoInit",
407 [19] = "DoReset",
408 [20] = "DoFullReset",
409 [21] = "SleepReset",
410 [22] = "KbReset",
411 [23] = "LtReset",
412 [24] = "FailBootRst",
413 [25] = "WatchdogIssueReset",
414 [26] = "RemoteResetFromASF",
415 [27] = "SyncFlood",
416 [28] = "HangReset",
417 [29] = "EcWatchdogRst",
Edward Hillcc680342018-08-10 16:20:02 -0600418 };
419
Edward Hill917b4002018-10-02 14:17:19 -0600420 printk(BIOS_DEBUG, "PMxC0 STATUS: 0x%x ", pmxc0_status);
Edward Hillcc680342018-08-10 16:20:02 -0600421 print_num_status_bits(ARRAY_SIZE(pmxc0_status_bits), pmxc0_status,
422 pmxc0_status_bits);
Edward Hill917b4002018-10-02 14:17:19 -0600423 printk(BIOS_DEBUG, "\n");
Edward Hillcc680342018-08-10 16:20:02 -0600424}
425
Raul E Rangeld820f4b82018-08-13 10:39:03 -0600426/* After console init */
Edward Hillcc680342018-08-10 16:20:02 -0600427void bootblock_fch_init(void)
428{
429 sb_print_pmxc0_status();
430}
Raul E Rangeld820f4b82018-08-13 10:39:03 -0600431
Elyes HAOUASc5ad2672018-12-05 10:58:34 +0100432void sb_enable(struct device *dev)
Marc Jones24484842017-05-04 21:17:45 -0600433{
Marc Jonesdfeb1c42017-08-07 19:08:24 -0600434 printk(BIOS_DEBUG, "%s\n", __func__);
Marc Jones24484842017-05-04 21:17:45 -0600435}
436
Marc Jonesdfeb1c42017-08-07 19:08:24 -0600437static void sb_init_acpi_ports(void)
Marc Jones24484842017-05-04 21:17:45 -0600438{
Marshall Dawson91b80412017-09-27 16:44:40 -0600439 u32 reg;
440
Marc Jones24484842017-05-04 21:17:45 -0600441 /* We use some of these ports in SMM regardless of whether or not
442 * ACPI tables are generated. Enable these ports indiscriminately.
443 */
444
445 pm_write16(PM_EVT_BLK, ACPI_PM_EVT_BLK);
446 pm_write16(PM1_CNT_BLK, ACPI_PM1_CNT_BLK);
447 pm_write16(PM_TMR_BLK, ACPI_PM_TMR_BLK);
448 pm_write16(PM_GPE0_BLK, ACPI_GPE0_BLK);
Michał Żygowski9550e972020-03-20 13:56:46 +0100449 /* CpuControl is in \_SB.CP00, 6 bytes */
Marc Jones24484842017-05-04 21:17:45 -0600450 pm_write16(PM_CPU_CTRL, ACPI_CPU_CONTROL);
451
Julius Wernercd49cce2019-03-05 16:53:33 -0800452 if (CONFIG(HAVE_SMI_HANDLER)) {
Marshall Dawsona05fdcb2017-09-27 15:01:37 -0600453 /* APMC - SMI Command Port */
Marshall Dawsone9b862e2017-09-22 15:14:46 -0600454 pm_write16(PM_ACPI_SMI_CMD, APM_CNT);
Marshall Dawsona05fdcb2017-09-27 15:01:37 -0600455 configure_smi(SMITYPE_SMI_CMD_PORT, SMI_MODE_SMI);
Marshall Dawson91b80412017-09-27 16:44:40 -0600456
457 /* SMI on SlpTyp requires sending SMI before completion
458 * response of the I/O write. The BKDG also specifies
459 * clearing ForceStpClkRetry for SMI trapping.
460 */
461 reg = pm_read32(PM_PCI_CTRL);
462 reg |= FORCE_SLPSTATE_RETRY;
463 reg &= ~FORCE_STPCLK_RETRY;
464 pm_write32(PM_PCI_CTRL, reg);
465
466 /* Disable SlpTyp feature */
467 reg = pm_read8(PM_RST_CTRL1);
468 reg &= ~SLPTYPE_CONTROL_EN;
469 pm_write8(PM_RST_CTRL1, reg);
470
471 configure_smi(SMITYPE_SLP_TYP, SMI_MODE_SMI);
Marc Jones24484842017-05-04 21:17:45 -0600472 } else {
473 pm_write16(PM_ACPI_SMI_CMD, 0);
474 }
475
Marshall Dawson5e2e74f2017-11-10 09:59:56 -0700476 /* Decode ACPI registers and enable standard features */
477 pm_write8(PM_ACPI_CONF, PM_ACPI_DECODE_STD |
478 PM_ACPI_GLOBAL_EN |
479 PM_ACPI_RTC_EN_EN |
480 PM_ACPI_TIMER_EN_EN);
Marc Jones24484842017-05-04 21:17:45 -0600481}
482
Richard Spiegeldbee8ae2018-05-09 17:34:04 -0700483static void set_nvs_sws(void *unused)
484{
Aaron Durbin5a5e4d02020-08-14 16:22:11 -0600485 struct acpi_pm_gpe_state *state;
Kyösti Mälkki0c1dd9c2020-06-17 23:37:49 +0300486 struct global_nvs *gnvs;
Richard Spiegeldbee8ae2018-05-09 17:34:04 -0700487
Aaron Durbin5a5e4d02020-08-14 16:22:11 -0600488 state = cbmem_find(CBMEM_ID_POWER_STATE);
489 if (state == NULL)
Richard Spiegel35282a02018-06-14 14:57:54 -0700490 return;
Kyösti Mälkki5daa1d32020-06-14 12:01:58 +0300491 gnvs = acpi_get_gnvs();
Richard Spiegeldbee8ae2018-05-09 17:34:04 -0700492 if (gnvs == NULL)
493 return;
494
Aaron Durbin5a5e4d02020-08-14 16:22:11 -0600495 acpi_fill_gnvs(gnvs, state);
Richard Spiegeldbee8ae2018-05-09 17:34:04 -0700496}
497
498BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, set_nvs_sws, NULL);
499
Marc Jonesdfeb1c42017-08-07 19:08:24 -0600500void southbridge_init(void *chip_info)
Marc Jones24484842017-05-04 21:17:45 -0600501{
Aaron Durbin5a5e4d02020-08-14 16:22:11 -0600502 struct acpi_pm_gpe_state *state;
503
Marc Jonesdfeb1c42017-08-07 19:08:24 -0600504 sb_init_acpi_ports();
Aaron Durbin5a5e4d02020-08-14 16:22:11 -0600505
506 state = cbmem_add(CBMEM_ID_POWER_STATE, sizeof(*state));
507 if (state) {
508 acpi_fill_pm_gpe_state(state);
509 acpi_pm_gpe_add_events_print_events(state);
510 }
511
512 acpi_clear_pm_gpe_status();
Marc Jones24484842017-05-04 21:17:45 -0600513}
514
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600515static void set_sb_final_nvs(void)
516{
517 uintptr_t amdfw_rom;
518 uintptr_t xhci_fw;
519 uintptr_t fwaddr;
520 size_t fwsize;
Richard Spiegel41baf0c2018-10-22 13:57:18 -0700521 const struct device *sd, *sata;
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600522
Kyösti Mälkki0c1dd9c2020-06-17 23:37:49 +0300523 struct global_nvs *gnvs = acpi_get_gnvs();
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600524 if (gnvs == NULL)
525 return;
526
Felix Heldab0d85c2020-11-30 17:27:30 +0100527 gnvs->aoac.ic0e = is_aoac_device_enabled(FCH_AOAC_DEV_I2C0);
528 gnvs->aoac.ic1e = is_aoac_device_enabled(FCH_AOAC_DEV_I2C1);
529 gnvs->aoac.ic2e = is_aoac_device_enabled(FCH_AOAC_DEV_I2C2);
530 gnvs->aoac.ic3e = is_aoac_device_enabled(FCH_AOAC_DEV_I2C3);
531 gnvs->aoac.ut0e = is_aoac_device_enabled(FCH_AOAC_DEV_UART0);
532 gnvs->aoac.ut1e = is_aoac_device_enabled(FCH_AOAC_DEV_UART1);
533 gnvs->aoac.ehce = is_aoac_device_enabled(FCH_AOAC_DEV_USB2);
534 gnvs->aoac.xhce = is_aoac_device_enabled(FCH_AOAC_DEV_USB3);
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600535 /* Rely on these being in sync with devicetree */
Kyösti Mälkkie7377552018-06-21 16:20:55 +0300536 sd = pcidev_path_on_root(SD_DEVFN);
Marshall Dawson6d3b7e62019-04-18 17:01:01 -0600537 gnvs->aoac.sd_e = sd && sd->enabled ? 1 : 0;
Kyösti Mälkkie7377552018-06-21 16:20:55 +0300538 sata = pcidev_path_on_root(SATA_DEVFN);
Marshall Dawson6d3b7e62019-04-18 17:01:01 -0600539 gnvs->aoac.st_e = sata && sata->enabled ? 1 : 0;
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600540 gnvs->aoac.espi = 1;
541
542 amdfw_rom = 0x20000 - (0x80000 << CONFIG_AMD_FWM_POSITION_INDEX);
543 xhci_fw = read32((void *)(amdfw_rom + XHCI_FW_SIG_OFFSET));
544
545 fwaddr = 2 + read16((void *)(xhci_fw + XHCI_FW_ADDR_OFFSET
546 + XHCI_FW_BOOTRAM_SIZE));
547 fwsize = read16((void *)(xhci_fw + XHCI_FW_SIZE_OFFSET
548 + XHCI_FW_BOOTRAM_SIZE));
549 gnvs->fw00 = 0;
550 gnvs->fw01 = ((32 * KiB) << 16) + 0;
551 gnvs->fw02 = fwaddr + XHCI_FW_BOOTRAM_SIZE;
552 gnvs->fw03 = fwsize << 16;
553
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600554 gnvs->eh10 = pci_read_config32(SOC_EHCI1_DEV, PCI_BASE_ADDRESS_0)
555 & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
556}
557
Marc Jonesdfeb1c42017-08-07 19:08:24 -0600558void southbridge_final(void *chip_info)
Marc Jones24484842017-05-04 21:17:45 -0600559{
Richard Spiegel6a389142018-03-05 14:28:10 -0700560 uint8_t restored_power = PM_S5_AT_POWER_RECOVERY;
561
Julius Wernercd49cce2019-03-05 16:53:33 -0800562 if (CONFIG(MAINBOARD_POWER_RESTORE))
Richard Spiegel6a389142018-03-05 14:28:10 -0700563 restored_power = PM_RESTORE_S0_IF_PREV_S0;
564 pm_write8(PM_RTC_SHADOW, restored_power);
Marshall Dawson1d9a46b2018-09-26 16:23:41 -0600565
566 set_sb_final_nvs();
Marc Jones24484842017-05-04 21:17:45 -0600567}
Marshall Dawson8a906df2017-06-13 14:19:02 -0600568
569/*
570 * Update the PCI devices with a valid IRQ number
571 * that is set in the mainboard PCI_IRQ structures.
572 */
573static void set_pci_irqs(void *unused)
574{
575 /* Write PCI_INTR regs 0xC00/0xC01 */
576 write_pci_int_table();
577
578 /* Write IRQs for all devicetree enabled devices */
579 write_pci_cfg_irqs();
580}
581
582/*
583 * Hook this function into the PCI state machine
584 * on entry into BS_DEV_ENABLE.
585 */
586BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_ENTRY, set_pci_irqs, NULL);