Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 1 | /* |
| 2 | * This file is part of the coreboot project. |
| 3 | * |
| 4 | * Copyright (C) 2010 Advanced Micro Devices, Inc. |
Timothy Pearson | 056e454 | 2016-04-06 13:18:52 -0500 | [diff] [blame] | 5 | * Copyright (C) 2015 - 2016 Raptor Engineering, LLC |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation; version 2 of the License. |
| 10 | * |
| 11 | * This program is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * GNU General Public License for more details. |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 15 | */ |
| 16 | |
Uwe Hermann | ff492b1 | 2010-09-24 23:37:25 +0000 | [diff] [blame] | 17 | #ifndef _SB700_EARLY_SETUP_C_ |
| 18 | #define _SB700_EARLY_SETUP_C_ |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 19 | |
efdesign98 | 00c8c4a | 2011-07-20 12:37:58 -0600 | [diff] [blame] | 20 | #include <stdint.h> |
Timothy Pearson | 1b70865 | 2015-11-10 20:14:52 -0600 | [diff] [blame] | 21 | #include <option.h> |
efdesign98 | 00c8c4a | 2011-07-20 12:37:58 -0600 | [diff] [blame] | 22 | #include <arch/io.h> |
Kyösti Mälkki | f1b58b7 | 2019-03-01 13:43:02 +0200 | [diff] [blame] | 23 | #include <device/pci_ops.h> |
efdesign98 | 00c8c4a | 2011-07-20 12:37:58 -0600 | [diff] [blame] | 24 | #include <console/console.h> |
| 25 | #include <cpu/x86/msr.h> |
Kyösti Mälkki | 8a41f4b | 2019-02-08 18:14:34 +0200 | [diff] [blame] | 26 | #include <device/pci.h> |
efdesign98 | 00c8c4a | 2011-07-20 12:37:58 -0600 | [diff] [blame] | 27 | |
Stefan Reinauer | 6a445e8 | 2010-04-09 11:34:59 +0000 | [diff] [blame] | 28 | #include <reset.h> |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 29 | #include "sb700.h" |
efdesign98 | 00c8c4a | 2011-07-20 12:37:58 -0600 | [diff] [blame] | 30 | #include "smbus.h" |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 31 | |
Damien Zammit | 75a3d1f | 2016-11-28 00:29:10 +1100 | [diff] [blame] | 32 | u32 get_sbdn(u32 bus); |
| 33 | |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 34 | static void pmio_write(u8 reg, u8 value) |
| 35 | { |
| 36 | outb(reg, PM_INDEX); |
| 37 | outb(value, PM_INDEX + 1); |
| 38 | } |
| 39 | |
| 40 | static u8 pmio_read(u8 reg) |
| 41 | { |
| 42 | outb(reg, PM_INDEX); |
| 43 | return inb(PM_INDEX + 1); |
| 44 | } |
| 45 | |
Zheng Bao | a5c949e | 2011-01-27 03:31:50 +0000 | [diff] [blame] | 46 | static void sb700_acpi_init(void) |
| 47 | { |
Zheng Bao | c342223 | 2011-03-28 03:33:10 +0000 | [diff] [blame] | 48 | u16 word; |
Rudolf Marek | c436953 | 2010-12-13 19:59:13 +0000 | [diff] [blame] | 49 | pmio_write(0x20, ACPI_PM_EVT_BLK & 0xFF); |
| 50 | pmio_write(0x21, ACPI_PM_EVT_BLK >> 8); |
| 51 | pmio_write(0x22, ACPI_PM1_CNT_BLK & 0xFF); |
| 52 | pmio_write(0x23, ACPI_PM1_CNT_BLK >> 8); |
| 53 | pmio_write(0x24, ACPI_PM_TMR_BLK & 0xFF); |
| 54 | pmio_write(0x25, ACPI_PM_TMR_BLK >> 8); |
| 55 | pmio_write(0x28, ACPI_GPE0_BLK & 0xFF); |
| 56 | pmio_write(0x29, ACPI_GPE0_BLK >> 8); |
| 57 | |
Timothy Pearson | 033bb4b | 2015-02-10 22:21:39 -0600 | [diff] [blame] | 58 | /* CpuControl is in \_PR.CP00, 6 bytes */ |
Rudolf Marek | c436953 | 2010-12-13 19:59:13 +0000 | [diff] [blame] | 59 | pmio_write(0x26, ACPI_CPU_CONTROL & 0xFF); |
| 60 | pmio_write(0x27, ACPI_CPU_CONTROL >> 8); |
| 61 | |
| 62 | pmio_write(0x2A, 0); /* AcpiSmiCmdLo */ |
| 63 | pmio_write(0x2B, 0); /* AcpiSmiCmdHi */ |
| 64 | |
| 65 | pmio_write(0x2C, ACPI_PMA_CNT_BLK & 0xFF); |
| 66 | pmio_write(0x2D, ACPI_PMA_CNT_BLK >> 8); |
| 67 | |
| 68 | pmio_write(0x0E, 1<<3 | 0<<2); /* AcpiDecodeEnable, When set, SB uses |
| 69 | * the contents of the PM registers at |
| 70 | * index 20-2B to decode ACPI I/O address. |
| 71 | * AcpiSmiEn & SmiCmdEn*/ |
| 72 | pmio_write(0x10, 1<<1 | 1<<3| 1<<5); /* RTC_En_En, TMR_En_En, GBL_EN_EN */ |
Zheng Bao | c342223 | 2011-03-28 03:33:10 +0000 | [diff] [blame] | 73 | word = inl(ACPI_PM1_CNT_BLK); |
| 74 | word |= 1; |
| 75 | outl(word, ACPI_PM1_CNT_BLK); /* set SCI_EN */ |
Rudolf Marek | c436953 | 2010-12-13 19:59:13 +0000 | [diff] [blame] | 76 | } |
| 77 | |
Uwe Hermann | ff492b1 | 2010-09-24 23:37:25 +0000 | [diff] [blame] | 78 | /* RPR 2.28: Get SB ASIC Revision. */ |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 79 | static u8 set_sb700_revision(void) |
| 80 | { |
Antonello Dettori | 6cf4415 | 2016-09-03 10:45:33 +0200 | [diff] [blame] | 81 | pci_devfn_t dev; |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 82 | u8 rev_id, enable_14Mhz, byte; |
| 83 | u8 rev = 0; |
| 84 | |
| 85 | /* if (rev != 0) return rev; */ |
| 86 | |
| 87 | dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); |
| 88 | |
| 89 | if (dev == PCI_DEV_INVALID) { |
Stefan Reinauer | 64ed2b7 | 2010-03-31 14:47:43 +0000 | [diff] [blame] | 90 | die("SMBUS controller not found\n"); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 91 | /* NOT REACHED */ |
| 92 | } |
| 93 | rev_id = pci_read_config8(dev, 0x08); |
| 94 | |
| 95 | if (rev_id == 0x39) { |
| 96 | enable_14Mhz = (pmio_read(0x53) >> 6) & 1; |
| 97 | if (enable_14Mhz == 0x0) |
| 98 | rev = 0x11; /* A11 */ |
| 99 | else if (enable_14Mhz == 0x1) { |
| 100 | /* This happens, if does, only once. So later if we need to get |
Zheng Bao | 2a5101a | 2010-10-10 15:18:53 +0000 | [diff] [blame] | 101 | * the revision ID, we don't have to make such a big function. |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 102 | * We just get reg 0x8 in smbus dev. 0x39 is A11, 0x3A is A12. */ |
| 103 | rev = 0x12; |
| 104 | byte = pci_read_config8(dev, 0x40); |
| 105 | byte |= 1 << 0; |
| 106 | pci_write_config8(dev, 0x40, byte); |
| 107 | |
| 108 | pci_write_config8(dev, 0x08, 0x3A); /* Change 0x39 to 0x3A. */ |
| 109 | |
| 110 | byte &= ~(1 << 0); |
| 111 | pci_write_config8(dev, 0x40, byte); |
| 112 | } |
| 113 | } else if (rev_id == 0x3A) { /* A12 will be 0x3A after BIOS is initialized */ |
| 114 | rev = 0x12; |
| 115 | } else if (rev_id == 0x3C) { |
| 116 | rev = 0x14; |
| 117 | } else if (rev_id == 0x3D) { |
| 118 | rev = 0x15; |
| 119 | } else |
Stefan Reinauer | 64ed2b7 | 2010-03-31 14:47:43 +0000 | [diff] [blame] | 120 | die("It is not SB700 or SB710\n"); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 121 | |
| 122 | return rev; |
| 123 | } |
| 124 | |
| 125 | /*************************************** |
| 126 | * Legacy devices are mapped to LPC space. |
| 127 | * Serial port 0 |
| 128 | * KBC Port |
| 129 | * ACPI Micro-controller port |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 130 | * This function does not change port 0x80 decoding. |
| 131 | * Console output through any port besides 0x3f8 is unsupported. |
| 132 | * If you use FWH ROMs, you have to setup IDSEL. |
| 133 | ***************************************/ |
efdesign98 | 00c8c4a | 2011-07-20 12:37:58 -0600 | [diff] [blame] | 134 | void sb7xx_51xx_lpc_init(void) |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 135 | { |
| 136 | u8 reg8; |
| 137 | u32 reg32; |
Antonello Dettori | 6cf4415 | 2016-09-03 10:45:33 +0200 | [diff] [blame] | 138 | pci_devfn_t dev; |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 139 | |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 140 | dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); /* SMBUS controller */ |
Zheng Bao | d4e77df | 2010-03-17 03:10:39 +0000 | [diff] [blame] | 141 | /* NOTE: Set BootTimerDisable, otherwise it would keep rebooting!! |
| 142 | * This bit has no meaning if debug strap is not enabled. So if the |
| 143 | * board keeps rebooting and the code fails to reach here, we could |
| 144 | * disable the debug strap first. */ |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 145 | reg32 = pci_read_config32(dev, 0x4C); |
| 146 | reg32 |= 1 << 31; |
| 147 | pci_write_config32(dev, 0x4C, reg32); |
| 148 | |
| 149 | /* Enable lpc controller */ |
| 150 | reg32 = pci_read_config32(dev, 0x64); |
| 151 | reg32 |= 1 << 20; |
| 152 | pci_write_config32(dev, 0x64, reg32); |
| 153 | |
Martin Roth | 083504b | 2017-06-24 21:30:14 -0600 | [diff] [blame] | 154 | #if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SUBTYPE_SP5100) |
Zheng Bao | c342223 | 2011-03-28 03:33:10 +0000 | [diff] [blame] | 155 | post_code(0x66); |
| 156 | dev = pci_locate_device(PCI_ID(0x1002, 0x439d), 0); /* LPC Controller */ |
| 157 | reg8 = pci_read_config8(dev, 0xBB); |
| 158 | reg8 |= 1 << 2 | 1 << 3 | 1 << 6 | 1 << 7; |
| 159 | reg8 &= ~(1 << 1); |
| 160 | pci_write_config8(dev, 0xBB, reg8); |
| 161 | #endif |
| 162 | |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 163 | dev = pci_locate_device(PCI_ID(0x1002, 0x439d), 0); /* LPC Controller */ |
| 164 | /* Decode port 0x3f8-0x3ff (Serial 0) */ |
Stefan Reinauer | 29ceae2 | 2010-04-20 11:03:41 +0000 | [diff] [blame] | 165 | // XXX Serial port decode on LPC is hardcoded to 0x3f8 |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 166 | reg8 = pci_read_config8(dev, 0x44); |
| 167 | reg8 |= 1 << 6; |
Martin Roth | 083504b | 2017-06-24 21:30:14 -0600 | [diff] [blame] | 168 | #if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SUBTYPE_SP5100) |
Zheng Bao | c342223 | 2011-03-28 03:33:10 +0000 | [diff] [blame] | 169 | #if CONFIG_TTYS0_BASE == 0x2f8 |
| 170 | reg8 |= 1 << 7; |
| 171 | #endif |
| 172 | #endif |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 173 | pci_write_config8(dev, 0x44, reg8); |
| 174 | |
| 175 | /* Decode port 0x60 & 0x64 (PS/2 keyboard) and port 0x62 & 0x66 (ACPI)*/ |
| 176 | reg8 = pci_read_config8(dev, 0x47); |
| 177 | reg8 |= (1 << 5) | (1 << 6); |
| 178 | pci_write_config8(dev, 0x47, reg8); |
| 179 | |
Scott Duplichan | d7acdfb | 2010-10-18 04:01:12 +0000 | [diff] [blame] | 180 | /* Enable PrefetchEnSPIFromHost to speed up SPI flash read (does not affect LPC) */ |
| 181 | reg8 = pci_read_config8(dev, 0xbb); |
| 182 | reg8 |= 1 << 0; |
| 183 | pci_write_config8(dev, 0xbb, reg8); |
| 184 | |
Uwe Hermann | 6e7efb7 | 2010-12-10 09:02:50 +0000 | [diff] [blame] | 185 | /* Super I/O, RTC */ |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 186 | reg8 = pci_read_config8(dev, 0x48); |
| 187 | /* Decode ports 0x2e-0x2f, 0x4e-0x4f (SuperI/O configuration) */ |
| 188 | reg8 |= (1 << 1) | (1 << 0); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 189 | /* Decode port 0x70-0x73 (RTC) */ |
Uwe Hermann | 6e7efb7 | 2010-12-10 09:02:50 +0000 | [diff] [blame] | 190 | reg8 |= (1 << 6); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 191 | pci_write_config8(dev, 0x48, reg8); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 192 | } |
| 193 | |
Zheng Bao | c342223 | 2011-03-28 03:33:10 +0000 | [diff] [blame] | 194 | void sb7xx_51xx_enable_wideio(u8 wio_index, u16 base) |
| 195 | { |
| 196 | /* TODO: Now assume wio_index=0 */ |
Antonello Dettori | 6cf4415 | 2016-09-03 10:45:33 +0200 | [diff] [blame] | 197 | pci_devfn_t dev; |
Zheng Bao | c342223 | 2011-03-28 03:33:10 +0000 | [diff] [blame] | 198 | u8 reg8; |
| 199 | |
| 200 | dev = pci_locate_device(PCI_ID(0x1002, 0x439d), 0); /* LPC Controller */ |
| 201 | pci_write_config32(dev, 0x64, base); |
| 202 | reg8 = pci_read_config8(dev, 0x48); |
| 203 | reg8 |= 1 << 2; |
| 204 | pci_write_config8(dev, 0x48, reg8); |
| 205 | } |
| 206 | |
| 207 | void sb7xx_51xx_disable_wideio(u8 wio_index) |
| 208 | { |
| 209 | /* TODO: Now assume wio_index=0 */ |
Antonello Dettori | 6cf4415 | 2016-09-03 10:45:33 +0200 | [diff] [blame] | 210 | pci_devfn_t dev; |
Zheng Bao | c342223 | 2011-03-28 03:33:10 +0000 | [diff] [blame] | 211 | u8 reg8; |
| 212 | |
| 213 | dev = pci_locate_device(PCI_ID(0x1002, 0x439d), 0); /* LPC Controller */ |
| 214 | pci_write_config32(dev, 0x64, 0); |
| 215 | reg8 = pci_read_config8(dev, 0x48); |
| 216 | reg8 &= ~(1 << 2); |
| 217 | pci_write_config8(dev, 0x48, reg8); |
| 218 | } |
| 219 | |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 220 | /* what is its usage? */ |
Vladimir Serbinenko | 1765fd2 | 2014-11-09 16:33:25 +0100 | [diff] [blame] | 221 | u32 get_sbdn(u32 bus) |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 222 | { |
Antonello Dettori | 6cf4415 | 2016-09-03 10:45:33 +0200 | [diff] [blame] | 223 | pci_devfn_t dev; |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 224 | |
| 225 | /* Find the device. */ |
| 226 | dev = pci_locate_device_on_bus(PCI_ID(0x1002, 0x4385), bus); |
| 227 | return (dev >> 15) & 0x1f; |
| 228 | } |
| 229 | |
| 230 | static u8 dual_core(void) |
| 231 | { |
| 232 | return (pci_read_config32(PCI_DEV(0, 0x18, 3), 0xE8) & (0x3<<12)) != 0; |
| 233 | } |
| 234 | |
| 235 | /* |
| 236 | * RPR 2.4 C-state and VID/FID change for the K8 platform. |
| 237 | */ |
Vladimir Serbinenko | 1526b9f | 2014-11-09 16:36:03 +0100 | [diff] [blame] | 238 | void enable_fid_change_on_sb(u32 sbbusn, u32 sbdn) |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 239 | { |
| 240 | u8 byte; |
| 241 | byte = pmio_read(0x9a); |
| 242 | byte &= ~0x34; |
| 243 | if (dual_core()) |
| 244 | byte |= 0x34; |
| 245 | else |
| 246 | byte |= 0x04; |
| 247 | pmio_write(0x9a, byte); |
| 248 | |
| 249 | byte = pmio_read(0x8f); |
| 250 | byte &= ~0x30; |
| 251 | byte |= 0x20; |
| 252 | pmio_write(0x8f, byte); |
| 253 | |
Martin Roth | dcf253c | 2014-12-16 20:51:31 -0700 | [diff] [blame] | 254 | pmio_write(0x8b, 0x01); /* TODO: if the HT Link is 200 MHz, it is 0x0A. It doesn't often happen. */ |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 255 | pmio_write(0x8a, 0x90); |
| 256 | |
| 257 | pmio_write(0x88, 0x10); |
| 258 | |
| 259 | byte = pmio_read(0x7c); |
| 260 | byte |= 0x03; |
| 261 | pmio_write(0x7c, byte); |
| 262 | |
Uwe Hermann | ff492b1 | 2010-09-24 23:37:25 +0000 | [diff] [blame] | 263 | /* Must be 0 for K8 platform. */ |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 264 | byte = pmio_read(0x68); |
| 265 | byte &= ~0x01; |
| 266 | pmio_write(0x68, byte); |
Uwe Hermann | ff492b1 | 2010-09-24 23:37:25 +0000 | [diff] [blame] | 267 | /* Must be 0 for K8 platform. */ |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 268 | byte = pmio_read(0x8d); |
| 269 | byte &= ~(1<<6); |
| 270 | pmio_write(0x8d, byte); |
| 271 | |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 272 | byte = pmio_read(0x42); |
| 273 | byte &= ~0x04; |
| 274 | pmio_write(0x42, byte); |
| 275 | |
| 276 | pmio_write(0x89, 0x10); |
Rudolf Marek | 199c694 | 2011-02-26 13:34:01 +0000 | [diff] [blame] | 277 | |
| 278 | /* Toggle the LDT_STOP# during FID/VID Change, this bit is documented |
| 279 | only in SB600! |
| 280 | While here, enable C states too |
| 281 | */ |
| 282 | pmio_write(0x67, 0x6); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 283 | } |
| 284 | |
Zheng Bao | c342223 | 2011-03-28 03:33:10 +0000 | [diff] [blame] | 285 | void sb7xx_51xx_pci_port80(void) |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 286 | { |
| 287 | u8 byte; |
Antonello Dettori | 6cf4415 | 2016-09-03 10:45:33 +0200 | [diff] [blame] | 288 | pci_devfn_t dev; |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 289 | |
| 290 | /* P2P Bridge */ |
| 291 | dev = pci_locate_device(PCI_ID(0x1002, 0x4384), 0); |
| 292 | |
| 293 | /* Chip Control: Enable subtractive decoding */ |
| 294 | byte = pci_read_config8(dev, 0x40); |
| 295 | byte |= 1 << 5; |
| 296 | pci_write_config8(dev, 0x40, byte); |
| 297 | |
| 298 | /* Misc Control: Enable subtractive decoding if 0x40 bit 5 is set */ |
| 299 | byte = pci_read_config8(dev, 0x4B); |
| 300 | byte |= 1 << 7; |
| 301 | pci_write_config8(dev, 0x4B, byte); |
| 302 | |
| 303 | /* The same IO Base and IO Limit here is meaningful because we set the |
| 304 | * bridge to be subtractive. During early setup stage, we have to make |
| 305 | * sure that data can go through port 0x80. |
| 306 | */ |
| 307 | /* IO Base: 0xf000 */ |
| 308 | byte = pci_read_config8(dev, 0x1C); |
| 309 | byte |= 0xF << 4; |
| 310 | pci_write_config8(dev, 0x1C, byte); |
| 311 | |
| 312 | /* IO Limit: 0xf000 */ |
| 313 | byte = pci_read_config8(dev, 0x1D); |
| 314 | byte |= 0xF << 4; |
| 315 | pci_write_config8(dev, 0x1D, byte); |
| 316 | |
| 317 | /* PCI Command: Enable IO response */ |
| 318 | byte = pci_read_config8(dev, 0x04); |
| 319 | byte |= 1 << 0; |
| 320 | pci_write_config8(dev, 0x04, byte); |
| 321 | |
| 322 | /* LPC controller */ |
| 323 | dev = pci_locate_device(PCI_ID(0x1002, 0x439D), 0); |
| 324 | |
| 325 | byte = pci_read_config8(dev, 0x4A); |
| 326 | byte &= ~(1 << 5); /* disable lpc port 80 */ |
| 327 | pci_write_config8(dev, 0x4A, byte); |
| 328 | } |
| 329 | |
Zheng Bao | c342223 | 2011-03-28 03:33:10 +0000 | [diff] [blame] | 330 | void sb7xx_51xx_lpc_port80(void) |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 331 | { |
| 332 | u8 byte; |
Antonello Dettori | 6cf4415 | 2016-09-03 10:45:33 +0200 | [diff] [blame] | 333 | pci_devfn_t dev; |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 334 | u32 reg32; |
| 335 | |
| 336 | /* Enable LPC controller */ |
| 337 | dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); |
| 338 | reg32 = pci_read_config32(dev, 0x64); |
| 339 | reg32 |= 0x00100000; /* lpcEnable */ |
| 340 | pci_write_config32(dev, 0x64, reg32); |
| 341 | |
| 342 | /* Enable port 80 LPC decode in pci function 3 configuration space. */ |
| 343 | dev = pci_locate_device(PCI_ID(0x1002, 0x439d), 0); |
| 344 | byte = pci_read_config8(dev, 0x4a); |
| 345 | byte |= 1 << 5; /* enable port 80 */ |
| 346 | pci_write_config8(dev, 0x4a, byte); |
| 347 | } |
| 348 | |
| 349 | /* sbDevicesPorInitTable */ |
| 350 | static void sb700_devices_por_init(void) |
| 351 | { |
Antonello Dettori | 6cf4415 | 2016-09-03 10:45:33 +0200 | [diff] [blame] | 352 | pci_devfn_t dev; |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 353 | u8 byte; |
Timothy Pearson | 5d7dc55 | 2015-06-09 18:09:50 -0500 | [diff] [blame] | 354 | uint32_t dword; |
| 355 | uint8_t nvram; |
| 356 | uint8_t sata_ahci_mode; |
| 357 | |
| 358 | sata_ahci_mode = 0; |
| 359 | if (get_option(&nvram, "sata_ahci_mode") == CB_SUCCESS) |
| 360 | sata_ahci_mode = !!nvram; |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 361 | |
Stefan Reinauer | c02b4fc | 2010-03-22 11:42:32 +0000 | [diff] [blame] | 362 | printk(BIOS_INFO, "sb700_devices_por_init()\n"); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 363 | /* SMBus Device, BDF:0-20-0 */ |
Stefan Reinauer | c02b4fc | 2010-03-22 11:42:32 +0000 | [diff] [blame] | 364 | printk(BIOS_INFO, "sb700_devices_por_init(): SMBus Device, BDF:0-20-0\n"); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 365 | dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); |
| 366 | |
| 367 | if (dev == PCI_DEV_INVALID) { |
Stefan Reinauer | 64ed2b7 | 2010-03-31 14:47:43 +0000 | [diff] [blame] | 368 | die("SMBUS controller not found\n"); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 369 | /* NOT REACHED */ |
| 370 | } |
Stefan Reinauer | 64ed2b7 | 2010-03-31 14:47:43 +0000 | [diff] [blame] | 371 | printk(BIOS_INFO, "SMBus controller enabled, sb revision is A%x\n", |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 372 | set_sb700_revision()); |
| 373 | |
| 374 | /* sbPorAtStartOfTblCfg */ |
| 375 | /* Set A-Link bridge access address. This address is set at device 14h, function 0, register 0xf0. |
Martin Roth | dcf253c | 2014-12-16 20:51:31 -0700 | [diff] [blame] | 376 | * This is an I/O address. The I/O address must be on 16-byte boundary. */ |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 377 | pci_write_config32(dev, 0xf0, AB_INDX); |
| 378 | |
| 379 | /* To enable AB/BIF DMA access, a specific register inside the BIF register space needs to be configured first. */ |
| 380 | /* 4.3:Enables the SB700 to send transactions upstream over A-Link Express interface. */ |
| 381 | axcfg_reg(0x04, 1 << 2, 1 << 2); |
| 382 | axindxc_reg(0x21, 0xff, 0); |
| 383 | |
| 384 | /* 2.5:Enabling Non-Posted Memory Write for the K8 Platform */ |
| 385 | axindxc_reg(0x10, 1 << 9, 1 << 9); |
| 386 | /* END of sbPorAtStartOfTblCfg */ |
| 387 | |
| 388 | /* sbDevicesPorInitTables */ |
| 389 | /* set smbus iobase */ |
| 390 | pci_write_config32(dev, 0x90, SMBUS_IO_BASE | 1); |
| 391 | |
| 392 | /* enable smbus controller interface */ |
| 393 | byte = pci_read_config8(dev, 0xd2); |
| 394 | byte |= (1 << 0); |
| 395 | pci_write_config8(dev, 0xd2, byte); |
| 396 | |
Timothy Pearson | ee3ec8e | 2015-10-23 22:28:26 -0500 | [diff] [blame] | 397 | /* set auxiliary smbus iobase and enable controller */ |
| 398 | pci_write_config32(dev, 0x58, SMBUS_AUX_IO_BASE | 1); |
| 399 | |
| 400 | if (inb(SMBUS_IO_BASE) == 0xff) |
| 401 | printk(BIOS_INFO, "%s: Primary SMBUS controller I/O not found\n", __func__); |
| 402 | |
Timothy Pearson | 796e77e | 2016-04-10 15:45:17 -0500 | [diff] [blame] | 403 | if (inb(SMBUS_AUX_IO_BASE) == 0xff) { |
Timothy Pearson | ee3ec8e | 2015-10-23 22:28:26 -0500 | [diff] [blame] | 404 | printk(BIOS_INFO, "%s: Secondary SMBUS controller I/O not found\n", __func__); |
Timothy Pearson | 796e77e | 2016-04-10 15:45:17 -0500 | [diff] [blame] | 405 | } |
| 406 | else { |
| 407 | if (IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SUBTYPE_SP5100)) { |
| 408 | /* Disable legacy sensor support / reset ASF Slave state machine per RPR 2.27 step 3 */ |
| 409 | outb(0x40, SMBUS_AUX_IO_BASE + SMBSLVMISC); |
| 410 | } |
| 411 | } |
Timothy Pearson | ee3ec8e | 2015-10-23 22:28:26 -0500 | [diff] [blame] | 412 | |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 413 | /* KB2RstEnable */ |
| 414 | pci_write_config8(dev, 0x40, 0x44); |
| 415 | |
| 416 | /* Enable ISA Address 0-960K decoding */ |
| 417 | pci_write_config8(dev, 0x48, 0x0f); |
| 418 | |
| 419 | /* Enable ISA Address 0xC0000-0xDFFFF decode */ |
| 420 | pci_write_config8(dev, 0x49, 0xff); |
| 421 | |
| 422 | /* Enable decode cycles to IO C50, C51, C52 GPM controls. */ |
| 423 | byte = pci_read_config8(dev, 0x41); |
| 424 | byte &= 0x80; |
| 425 | byte |= 0x33; |
| 426 | pci_write_config8(dev, 0x41, byte); |
| 427 | |
| 428 | /* Legacy DMA Prefetch Enhancement, CIM masked it. */ |
| 429 | /* pci_write_config8(dev, 0x43, 0x1); */ |
| 430 | |
Timothy Pearson | 8274acc | 2015-11-24 14:11:56 -0600 | [diff] [blame] | 431 | /* Enable DMA verify bugfix */ |
| 432 | byte = pci_read_config8(dev, 0x67); |
| 433 | byte |= 0x1 << 1; |
| 434 | pci_write_config8(dev, 0x67, byte); |
| 435 | |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 436 | /* Disabling Legacy USB Fast SMI# */ |
| 437 | byte = pci_read_config8(dev, 0x62); |
| 438 | byte |= 0x24; |
| 439 | pci_write_config8(dev, 0x62, byte); |
| 440 | |
Dave Frodin | 3780597 | 2012-08-21 16:51:33 -0600 | [diff] [blame] | 441 | /* Configure HPET Counter CLK period */ |
| 442 | byte = pci_read_config8(dev, 0x43); |
Timothy Pearson | 905507c | 2015-08-28 15:31:31 -0500 | [diff] [blame] | 443 | byte &= 0xF7; /* Unhide HPET regs */ |
Dave Frodin | 3780597 | 2012-08-21 16:51:33 -0600 | [diff] [blame] | 444 | pci_write_config8(dev, 0x43, byte); |
Timothy Pearson | 905507c | 2015-08-28 15:31:31 -0500 | [diff] [blame] | 445 | pci_write_config32(dev, 0x34, 0x0429b17e); /* Counter CLK period */ |
| 446 | byte |= 0x08; /* Hide HPET regs */ |
Dave Frodin | 3780597 | 2012-08-21 16:51:33 -0600 | [diff] [blame] | 447 | pci_write_config8(dev, 0x43, byte); |
| 448 | |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 449 | /* Features Enable */ |
| 450 | pci_write_config32(dev, 0x64, 0x829E79BF); /* bit10: Enables the HPET interrupt. */ |
| 451 | |
| 452 | /* SerialIrq Control */ |
| 453 | pci_write_config8(dev, 0x69, 0x90); |
| 454 | |
| 455 | /* Test Mode, PCIB_SReset_En Mask is set. */ |
| 456 | pci_write_config8(dev, 0x6c, 0x20); |
| 457 | |
| 458 | /* IO Address Enable, CIM set 0x78 only and masked 0x79. */ |
| 459 | /*pci_write_config8(dev, 0x79, 0x4F); */ |
| 460 | pci_write_config8(dev, 0x78, 0xFF); |
| 461 | |
Timothy Pearson | 70f2736 | 2015-09-05 17:46:15 -0500 | [diff] [blame] | 462 | if (IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700_DISABLE_ISA_DMA)) { |
| 463 | printk(BIOS_DEBUG, "%s: Disabling ISA DMA support\n", __func__); |
| 464 | /* Disable LPC ISA DMA Capability */ |
| 465 | byte = pci_read_config8(dev, 0x78); |
| 466 | byte &= ~(1 << 0); |
| 467 | pci_write_config8(dev, 0x78, byte); |
| 468 | } |
| 469 | |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 470 | /* Set smbus iospace enable, I don't know why write 0x04 into reg5 that is reserved */ |
| 471 | pci_write_config16(dev, 0x4, 0x0407); |
| 472 | |
| 473 | /* clear any lingering errors, so the transaction will run */ |
| 474 | outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); |
| 475 | |
| 476 | /* IDE Device, BDF:0-20-1 */ |
Stefan Reinauer | c02b4fc | 2010-03-22 11:42:32 +0000 | [diff] [blame] | 477 | printk(BIOS_INFO, "sb700_devices_por_init(): IDE Device, BDF:0-20-1\n"); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 478 | dev = pci_locate_device(PCI_ID(0x1002, 0x439C), 0); |
| 479 | /* Disable prefetch */ |
| 480 | byte = pci_read_config8(dev, 0x63); |
| 481 | byte |= 0x1; |
| 482 | pci_write_config8(dev, 0x63, byte); |
| 483 | |
| 484 | /* LPC Device, BDF:0-20-3 */ |
Stefan Reinauer | c02b4fc | 2010-03-22 11:42:32 +0000 | [diff] [blame] | 485 | printk(BIOS_INFO, "sb700_devices_por_init(): LPC Device, BDF:0-20-3\n"); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 486 | dev = pci_locate_device(PCI_ID(0x1002, 0x439D), 0); |
Timothy Pearson | 85c39a4 | 2015-09-05 18:14:25 -0500 | [diff] [blame] | 487 | if (!IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700_DISABLE_ISA_DMA)) { |
| 488 | /* DMA enable */ |
| 489 | pci_write_config8(dev, 0x40, 0x04); |
| 490 | } |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 491 | |
Zheng Bao | c342223 | 2011-03-28 03:33:10 +0000 | [diff] [blame] | 492 | /* IO Port Decode Enable */ |
| 493 | pci_write_config8(dev, 0x44, 0xFF); |
| 494 | pci_write_config8(dev, 0x45, 0xFF); |
| 495 | pci_write_config8(dev, 0x46, 0xC3); |
| 496 | pci_write_config8(dev, 0x47, 0xFF); |
| 497 | |
| 498 | // TODO: This has already been done(?) |
| 499 | /* IO/Mem Port Decode Enable, I don't know why CIM disable some ports. |
| 500 | * Disable LPC TimeOut counter, enable SuperIO Configuration Port (2e/2f), |
| 501 | * Alternate Super I/O Configuration Port (4e/4f), Wide Generic IO Port (64/65). */ |
| 502 | byte = pci_read_config8(dev, 0x48); |
| 503 | byte |= (1 << 1) | (1 << 0); /* enable Super IO config port 2e-2h, 4e-4f */ |
| 504 | byte |= 1 << 6; /* enable for RTC I/O range */ |
| 505 | pci_write_config8(dev, 0x48, byte); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 506 | pci_write_config8(dev, 0x49, 0xFF); |
Zheng Bao | c342223 | 2011-03-28 03:33:10 +0000 | [diff] [blame] | 507 | /* Enable 0x480-0x4bf, 0x4700-0x470B */ |
| 508 | byte = pci_read_config8(dev, 0x4A); |
Martin Roth | dcf253c | 2014-12-16 20:51:31 -0700 | [diff] [blame] | 509 | byte |= ((1 << 1) + (1 << 6)); /*0x42, save the configuration for port 0x80. */ |
Zheng Bao | c342223 | 2011-03-28 03:33:10 +0000 | [diff] [blame] | 510 | pci_write_config8(dev, 0x4A, byte); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 511 | |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 512 | /* Enable Tpm12_en and Tpm_legacy. I don't know what is its usage and copied from CIM. */ |
| 513 | pci_write_config8(dev, 0x7C, 0x05); |
| 514 | |
| 515 | /* P2P Bridge, BDF:0-20-4, the configuration of the registers in this dev are copied from CIM, |
| 516 | */ |
Stefan Reinauer | c02b4fc | 2010-03-22 11:42:32 +0000 | [diff] [blame] | 517 | printk(BIOS_INFO, "sb700_devices_por_init(): P2P Bridge, BDF:0-20-4\n"); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 518 | dev = pci_locate_device(PCI_ID(0x1002, 0x4384), 0); |
| 519 | |
| 520 | /* Arbiter enable. */ |
| 521 | pci_write_config8(dev, 0x43, 0xff); |
| 522 | |
Martin Roth | dcf253c | 2014-12-16 20:51:31 -0700 | [diff] [blame] | 523 | /* Set PCDMA request into height priority list. */ |
Elyes HAOUAS | 18cd8a6 | 2016-10-03 20:41:04 +0200 | [diff] [blame] | 524 | /* pci_write_config8(dev, 0x49, 0x1); */ |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 525 | |
| 526 | pci_write_config8(dev, 0x40, 0x26); |
| 527 | |
| 528 | pci_write_config8(dev, 0x0d, 0x40); |
| 529 | pci_write_config8(dev, 0x1b, 0x40); |
| 530 | /* Enable PCIB_DUAL_EN_UP will fix potential problem with PCI cards. */ |
| 531 | pci_write_config8(dev, 0x50, 0x01); |
| 532 | |
Timothy Pearson | 5d7dc55 | 2015-06-09 18:09:50 -0500 | [diff] [blame] | 533 | if (!sata_ahci_mode){ |
Martin Roth | 083504b | 2017-06-24 21:30:14 -0600 | [diff] [blame] | 534 | #if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SUBTYPE_SP5100) |
Timothy Pearson | 5d7dc55 | 2015-06-09 18:09:50 -0500 | [diff] [blame] | 535 | /* SP5100 default SATA mode is RAID5 MODE */ |
Timothy Pearson | 1a38374 | 2015-10-25 18:58:24 -0500 | [diff] [blame] | 536 | dev = pci_locate_device(PCI_ID(0x1002, 0x4392), 0); |
Zheng Bao | c342223 | 2011-03-28 03:33:10 +0000 | [diff] [blame] | 537 | |
Timothy Pearson | 1a38374 | 2015-10-25 18:58:24 -0500 | [diff] [blame] | 538 | if (dev != PCI_DEV_INVALID) { |
| 539 | /* Set SATA Operation Mode, Set to IDE mode */ |
| 540 | byte = pci_read_config8(dev, 0x40); |
| 541 | byte |= (1 << 0); |
| 542 | pci_write_config8(dev, 0x40, byte); |
Zheng Bao | c342223 | 2011-03-28 03:33:10 +0000 | [diff] [blame] | 543 | |
Timothy Pearson | 1a38374 | 2015-10-25 18:58:24 -0500 | [diff] [blame] | 544 | dword = 0x01018f00; |
| 545 | pci_write_config32(dev, 0x8, dword); |
Zheng Bao | c342223 | 2011-03-28 03:33:10 +0000 | [diff] [blame] | 546 | |
Timothy Pearson | 1a38374 | 2015-10-25 18:58:24 -0500 | [diff] [blame] | 547 | /* set SATA Device ID writable */ |
| 548 | dword = pci_read_config32(dev, 0x40); |
| 549 | dword &= ~(1 << 24); |
| 550 | pci_write_config32(dev, 0x40, dword); |
Zheng Bao | c342223 | 2011-03-28 03:33:10 +0000 | [diff] [blame] | 551 | |
Timothy Pearson | 1a38374 | 2015-10-25 18:58:24 -0500 | [diff] [blame] | 552 | /* set Device ID consistent with IDE emulation mode configuration */ |
| 553 | pci_write_config32(dev, 0x0, 0x43901002); |
Timothy Pearson | 1a38374 | 2015-10-25 18:58:24 -0500 | [diff] [blame] | 554 | } |
Zheng Bao | c342223 | 2011-03-28 03:33:10 +0000 | [diff] [blame] | 555 | #endif |
Timothy Pearson | 5d7dc55 | 2015-06-09 18:09:50 -0500 | [diff] [blame] | 556 | } |
Zheng Bao | c342223 | 2011-03-28 03:33:10 +0000 | [diff] [blame] | 557 | |
Timothy Pearson | 2268e0d | 2016-04-05 23:10:48 -0500 | [diff] [blame] | 558 | /* rpr v2.13 4.17 Reset CPU on Sync Flood */ |
| 559 | abcfg_reg(0x10050, 1 << 2, 1 << 2); |
| 560 | |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 561 | /* SATA Device, BDF:0-17-0, Non-Raid-5 SATA controller */ |
Timothy Pearson | 5d7dc55 | 2015-06-09 18:09:50 -0500 | [diff] [blame] | 562 | printk(BIOS_INFO, "sb700_devices_por_init(): SATA Device, BDF:0-17-0\n"); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 563 | dev = pci_locate_device(PCI_ID(0x1002, 0x4390), 0); |
| 564 | |
Timothy Pearson | 5d7dc55 | 2015-06-09 18:09:50 -0500 | [diff] [blame] | 565 | if (sata_ahci_mode) { |
| 566 | /* Switch to AHCI mode (AMD inbox) */ |
| 567 | dword = pci_read_config32(dev, 0x40); |
| 568 | dword |= (0x1 << 24); /* Lock Flash Device ID = 1 */ |
| 569 | pci_write_config32(dev, 0x40, dword); |
| 570 | |
| 571 | /* Deactivate Sub-Class Code write protection */ |
| 572 | byte = pci_read_config8(dev, 0x40); |
| 573 | byte |= (1 << 0); |
| 574 | pci_write_config8(dev, 0x40, byte); |
| 575 | |
| 576 | dword = pci_read_config32(dev, 0x08); |
| 577 | dword &= ~(0xff << 16); /* Sub-Class Code = 0x6 */ |
| 578 | dword |= (0x6 << 16); |
| 579 | dword &= ~(0xff << 8); /* Operating Mode Selection = 0x1 */ |
| 580 | dword |= (0x1 << 8); |
| 581 | pci_write_config32(dev, 0x08, dword); |
| 582 | } |
| 583 | |
| 584 | /* PHY Global Control */ |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 585 | pci_write_config16(dev, 0x86, 0x2C00); |
| 586 | } |
| 587 | |
| 588 | /* sbPmioPorInitTable, Pre-initializing PMIO register space |
| 589 | * The power management (PM) block is resident in the PCI/LPC/ISA bridge. |
| 590 | * The PM regs are accessed via IO mapped regs 0xcd6 and 0xcd7. |
| 591 | * The index address is first programmed into IO reg 0xcd6. |
| 592 | * Read or write values are accessed through IO reg 0xcd7. |
| 593 | */ |
| 594 | static void sb700_pmio_por_init(void) |
| 595 | { |
| 596 | u8 byte; |
Timothy Pearson | 83abd81 | 2015-06-08 19:35:06 -0500 | [diff] [blame] | 597 | uint8_t enable_c_states; |
| 598 | |
| 599 | enable_c_states = 0; |
| 600 | #if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES) |
| 601 | if (get_option(&byte, "cpu_c_states") == CB_SUCCESS) |
| 602 | enable_c_states = !!byte; |
| 603 | #endif |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 604 | |
Stefan Reinauer | c02b4fc | 2010-03-22 11:42:32 +0000 | [diff] [blame] | 605 | printk(BIOS_INFO, "sb700_pmio_por_init()\n"); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 606 | /* K8KbRstEn, KB_RST# control for K8 system. */ |
| 607 | byte = pmio_read(0x66); |
| 608 | byte |= 0x20; |
| 609 | pmio_write(0x66, byte); |
| 610 | |
Timothy Pearson | c13866f | 2016-04-10 16:02:42 -0500 | [diff] [blame] | 611 | if (IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SUBTYPE_SP5100)) { |
| 612 | /* RPR 2.11 Sx State Settings */ |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 613 | byte = pmio_read(0x65); |
Timothy Pearson | c13866f | 2016-04-10 16:02:42 -0500 | [diff] [blame] | 614 | byte &= ~(1 << 7); /* SpecialFunc = 0 */ |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 615 | pmio_write(0x65, byte); |
| 616 | |
Timothy Pearson | c13866f | 2016-04-10 16:02:42 -0500 | [diff] [blame] | 617 | byte = pmio_read(0x68); |
| 618 | byte |= 1 << 2; /* MaskApicEn = 1 */ |
| 619 | pmio_write(0x68, byte); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 620 | } else { |
Timothy Pearson | c13866f | 2016-04-10 16:02:42 -0500 | [diff] [blame] | 621 | /* RPR2.31 PM_TURN_OFF_MSG during ASF Shutdown. */ |
| 622 | if (get_sb700_revision(pci_locate_device(PCI_ID(0x1002, 0x4385), 0)) <= 0x12) { |
| 623 | byte = pmio_read(0x65); |
| 624 | byte &= ~(1 << 7); |
| 625 | pmio_write(0x65, byte); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 626 | |
Timothy Pearson | c13866f | 2016-04-10 16:02:42 -0500 | [diff] [blame] | 627 | byte = pmio_read(0x75); |
| 628 | byte &= 0xc0; |
| 629 | byte |= 0x05; |
| 630 | pmio_write(0x75, byte); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 631 | |
Timothy Pearson | c13866f | 2016-04-10 16:02:42 -0500 | [diff] [blame] | 632 | byte = pmio_read(0x52); |
| 633 | byte &= 0xc0; |
| 634 | byte |= 0x08; |
| 635 | pmio_write(0x52, byte); |
| 636 | } else { |
| 637 | byte = pmio_read(0xD7); |
| 638 | byte |= 1 << 0; |
| 639 | pmio_write(0xD7, byte); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 640 | |
Timothy Pearson | c13866f | 2016-04-10 16:02:42 -0500 | [diff] [blame] | 641 | byte = pmio_read(0x65); |
| 642 | byte |= 1 << 7; |
| 643 | pmio_write(0x65, byte); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 644 | |
Timothy Pearson | c13866f | 2016-04-10 16:02:42 -0500 | [diff] [blame] | 645 | byte = pmio_read(0x75); |
| 646 | byte &= 0xc0; |
| 647 | byte |= 0x01; |
| 648 | pmio_write(0x75, byte); |
| 649 | |
| 650 | byte = pmio_read(0x52); |
| 651 | byte &= 0xc0; |
| 652 | byte |= 0x02; |
| 653 | pmio_write(0x52, byte); |
| 654 | } |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 655 | } |
| 656 | |
| 657 | /* Watch Dog Timer Control |
| 658 | * Set watchdog time base to 0xfec000f0 to avoid SCSI card boot failure. |
| 659 | * But I don't find WDT is enabled in SMBUS 0x41 bit3 in CIM. |
| 660 | */ |
| 661 | pmio_write(0x6c, 0xf0); |
| 662 | pmio_write(0x6d, 0x00); |
| 663 | pmio_write(0x6e, 0xc0); |
| 664 | pmio_write(0x6f, 0xfe); |
| 665 | |
| 666 | /* rpr2.15: Enabling Spread Spectrum */ |
| 667 | byte = pmio_read(0x42); |
| 668 | byte |= 1 << 7; |
| 669 | pmio_write(0x42, byte); |
| 670 | /* TODO: Check if it is necessary. IDE reset */ |
| 671 | byte = pmio_read(0xB2); |
| 672 | byte |= 1 << 0; |
| 673 | pmio_write(0xB2, byte); |
Timothy Pearson | 85c39a4 | 2015-09-05 18:14:25 -0500 | [diff] [blame] | 674 | |
Timothy Pearson | 83abd81 | 2015-06-08 19:35:06 -0500 | [diff] [blame] | 675 | /* Set up IOAPIC and BM_STS monitoring */ |
| 676 | byte = pmio_read(0x61); |
| 677 | if (enable_c_states) |
| 678 | byte |= 0x4; |
| 679 | else |
| 680 | byte &= ~0x04; |
| 681 | pmio_write(0x61, byte); |
| 682 | |
Martin Roth | eabce72 | 2015-10-27 14:10:22 -0600 | [diff] [blame] | 683 | /* NOTE: Enabling automatic C1e state switch caused failures when initializing processors */ |
Timothy Pearson | 85c39a4 | 2015-09-05 18:14:25 -0500 | [diff] [blame] | 684 | |
| 685 | /* Enable precision HPET clock and automatic C state switch */ |
| 686 | byte = pmio_read(0xbb); |
| 687 | byte |= 0xc0; |
| 688 | pmio_write(0xbb, byte); |
Timothy Pearson | 905507c | 2015-08-28 15:31:31 -0500 | [diff] [blame] | 689 | |
Martin Roth | 083504b | 2017-06-24 21:30:14 -0600 | [diff] [blame] | 690 | #if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SUBTYPE_SP5100) |
Timothy Pearson | d1b6ff8 | 2016-04-10 15:52:47 -0500 | [diff] [blame] | 691 | /* RPR 2.26 Alter CPU reset timing */ |
| 692 | byte = pmio_read(0xb2); |
| 693 | byte |= 0x1 << 2; /* Enable CPU reset timing option */ |
| 694 | pmio_write(0xb2, byte); |
| 695 | |
Timothy Pearson | 905507c | 2015-08-28 15:31:31 -0500 | [diff] [blame] | 696 | /* Work around system clock drift issues */ |
| 697 | byte = pmio_read(0xd4); |
| 698 | byte |= 0x1 << 6; /* Enable alternate 14MHz clock source */ |
| 699 | byte |= 0x1 << 7; /* Disable 25MHz oscillator buffer */ |
| 700 | pmio_write(0xd4, byte); |
| 701 | #endif |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 702 | } |
| 703 | |
| 704 | /* |
| 705 | * Add any south bridge setting. |
| 706 | */ |
| 707 | static void sb700_pci_cfg(void) |
| 708 | { |
Antonello Dettori | 6cf4415 | 2016-09-03 10:45:33 +0200 | [diff] [blame] | 709 | pci_devfn_t dev; |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 710 | u8 byte; |
Timothy Pearson | 22dfccf | 2015-06-09 19:12:35 -0500 | [diff] [blame] | 711 | uint8_t acpi_s1_supported = 1; |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 712 | |
| 713 | /* SMBus Device, BDF:0-20-0 */ |
| 714 | dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); |
Timothy Pearson | 0a105cd | 2015-12-08 12:09:06 -0600 | [diff] [blame] | 715 | |
| 716 | /* Enable watchdog timer decode */ |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 717 | byte = pci_read_config8(dev, 0x41); |
| 718 | byte |= (1 << 3); |
| 719 | pci_write_config8(dev, 0x41, byte); |
| 720 | |
| 721 | /* Set to 1 to reset USB on the software (such as IO-64 or IO-CF9 cycles) |
| 722 | * generated PCIRST#. */ |
| 723 | byte = pmio_read(0x65); |
| 724 | byte |= (1 << 4); |
| 725 | pmio_write(0x65, byte); |
| 726 | |
| 727 | /* IDE Device, BDF:0-20-1 */ |
| 728 | dev = pci_locate_device(PCI_ID(0x1002, 0x439C), 0); |
| 729 | /* Enable IDE Explicit prefetch, 0x63[0] clear */ |
| 730 | byte = pci_read_config8(dev, 0x63); |
| 731 | byte &= 0xfe; |
| 732 | pci_write_config8(dev, 0x63, byte); |
| 733 | |
| 734 | /* LPC Device, BDF:0-20-3 */ |
| 735 | /* The code below is ported from old chipset. It is not |
Zheng Bao | 2a5101a | 2010-10-10 15:18:53 +0000 | [diff] [blame] | 736 | * mentioned in RPR. But I keep them. The registers and the |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 737 | * comments are compatible. */ |
| 738 | dev = pci_locate_device(PCI_ID(0x1002, 0x439D), 0); |
Timothy Pearson | 85c39a4 | 2015-09-05 18:14:25 -0500 | [diff] [blame] | 739 | if (!IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700_DISABLE_ISA_DMA)) { |
| 740 | /* Enabling LPC DMA function. */ |
| 741 | byte = pci_read_config8(dev, 0x40); |
| 742 | byte |= (1 << 2); |
| 743 | pci_write_config8(dev, 0x40, byte); |
| 744 | } |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 745 | /* Disabling LPC TimeOut. 0x48[7] clear. */ |
| 746 | byte = pci_read_config8(dev, 0x48); |
| 747 | byte &= 0x7f; |
| 748 | pci_write_config8(dev, 0x48, byte); |
| 749 | /* Disabling LPC MSI Capability, 0x78[1] clear. */ |
| 750 | byte = pci_read_config8(dev, 0x78); |
| 751 | byte &= 0xfd; |
| 752 | pci_write_config8(dev, 0x78, byte); |
| 753 | |
| 754 | /* SATA Device, BDF:0-17-0, Non-Raid-5 SATA controller */ |
| 755 | dev = pci_locate_device(PCI_ID(0x1002, 0x4390), 0); |
Timothy Pearson | 5d7dc55 | 2015-06-09 18:09:50 -0500 | [diff] [blame] | 756 | if (dev == PCI_DEV_INVALID) |
| 757 | dev = pci_locate_device(PCI_ID(0x1002, 0x4391), 0); |
| 758 | if (dev == PCI_DEV_INVALID) |
| 759 | dev = pci_locate_device(PCI_ID(0x1002, 0x4394), 0); |
| 760 | |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 761 | /* rpr7.12 SATA MSI and D3 Power State Capability. */ |
| 762 | byte = pci_read_config8(dev, 0x40); |
| 763 | byte |= 1 << 0; |
| 764 | pci_write_config8(dev, 0x40, byte); |
Timothy Pearson | 22dfccf | 2015-06-09 19:12:35 -0500 | [diff] [blame] | 765 | if (acpi_s1_supported) |
| 766 | pci_write_config8(dev, 0x34, 0x70); /* Hide D3 power state and MSI capabilities */ |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 767 | else |
Timothy Pearson | 22dfccf | 2015-06-09 19:12:35 -0500 | [diff] [blame] | 768 | pci_write_config8(dev, 0x61, 0x70); /* Hide MSI capability */ |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 769 | byte &= ~(1 << 0); |
| 770 | pci_write_config8(dev, 0x40, byte); |
| 771 | } |
| 772 | |
| 773 | /* |
| 774 | */ |
| 775 | static void sb700_por_init(void) |
| 776 | { |
| 777 | /* sbDevicesPorInitTable + sbK8PorInitTable */ |
| 778 | sb700_devices_por_init(); |
| 779 | |
| 780 | /* sbPmioPorInitTable + sbK8PmioPorInitTable */ |
| 781 | sb700_pmio_por_init(); |
| 782 | } |
| 783 | |
Timothy Pearson | 056e454 | 2016-04-06 13:18:52 -0500 | [diff] [blame] | 784 | uint16_t sb7xx_51xx_decode_last_reset(void) { |
| 785 | uint16_t reset_status = 0; |
| 786 | reset_status |= pmio_read(0x44); |
| 787 | reset_status |= (pmio_read(0x45) << 8); |
| 788 | printk(BIOS_INFO, "sb700 reset flags: %04x\n", reset_status); |
| 789 | if (reset_status & (0x1 << 10)) |
| 790 | printk(BIOS_WARNING, "WARNING: Last reset was caused by fatal error / sync flood!\n"); |
| 791 | |
| 792 | return reset_status; |
| 793 | } |
| 794 | |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 795 | /* |
| 796 | * It should be called during early POST after memory detection and BIOS shadowing but before PCI bus enumeration. |
| 797 | */ |
efdesign98 | 00c8c4a | 2011-07-20 12:37:58 -0600 | [diff] [blame] | 798 | void sb7xx_51xx_before_pci_init(void) |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 799 | { |
| 800 | sb700_pci_cfg(); |
| 801 | } |
| 802 | |
| 803 | /* |
| 804 | * This function should be called after enable_sb700_smbus(). |
| 805 | */ |
efdesign98 | 00c8c4a | 2011-07-20 12:37:58 -0600 | [diff] [blame] | 806 | void sb7xx_51xx_early_setup(void) |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 807 | { |
Stefan Reinauer | c02b4fc | 2010-03-22 11:42:32 +0000 | [diff] [blame] | 808 | printk(BIOS_INFO, "sb700_early_setup()\n"); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 809 | sb700_por_init(); |
Rudolf Marek | c436953 | 2010-12-13 19:59:13 +0000 | [diff] [blame] | 810 | sb700_acpi_init(); |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 811 | } |
| 812 | |
Zheng Bao | a5c949e | 2011-01-27 03:31:50 +0000 | [diff] [blame] | 813 | int s3_save_nvram_early(u32 dword, int size, int nvram_pos) |
| 814 | { |
Rudolf Marek | c436953 | 2010-12-13 19:59:13 +0000 | [diff] [blame] | 815 | int i; |
| 816 | printk(BIOS_DEBUG, "Writing %x of size %d to nvram pos: %d\n", dword, size, nvram_pos); |
| 817 | |
Elyes HAOUAS | c021ffe | 2016-09-18 19:18:56 +0200 | [diff] [blame] | 818 | for (i = 0; i < size; i++) { |
Rudolf Marek | c436953 | 2010-12-13 19:59:13 +0000 | [diff] [blame] | 819 | outb(nvram_pos, BIOSRAM_INDEX); |
Elyes HAOUAS | a342f39 | 2018-10-17 10:56:26 +0200 | [diff] [blame] | 820 | outb((dword >> (8 * i)) & 0xff, BIOSRAM_DATA); |
Rudolf Marek | c436953 | 2010-12-13 19:59:13 +0000 | [diff] [blame] | 821 | nvram_pos++; |
| 822 | } |
| 823 | |
| 824 | return nvram_pos; |
| 825 | } |
| 826 | |
Zheng Bao | a5c949e | 2011-01-27 03:31:50 +0000 | [diff] [blame] | 827 | int s3_load_nvram_early(int size, u32 *old_dword, int nvram_pos) |
| 828 | { |
Rudolf Marek | c436953 | 2010-12-13 19:59:13 +0000 | [diff] [blame] | 829 | u32 data = *old_dword; |
| 830 | int i; |
Elyes HAOUAS | c021ffe | 2016-09-18 19:18:56 +0200 | [diff] [blame] | 831 | for (i = 0; i < size; i++) { |
Rudolf Marek | c436953 | 2010-12-13 19:59:13 +0000 | [diff] [blame] | 832 | outb(nvram_pos, BIOSRAM_INDEX); |
| 833 | data &= ~(0xff << (i * 8)); |
| 834 | data |= inb(BIOSRAM_DATA) << (i *8); |
| 835 | nvram_pos++; |
| 836 | } |
| 837 | *old_dword = data; |
| 838 | printk(BIOS_DEBUG, "Loading %x of size %d to nvram pos:%d\n", *old_dword, size, |
| 839 | nvram_pos-size); |
| 840 | return nvram_pos; |
| 841 | } |
| 842 | |
Timothy Pearson | 85c39a4 | 2015-09-05 18:14:25 -0500 | [diff] [blame] | 843 | void set_lpc_sticky_ctl(bool enable) |
| 844 | { |
| 845 | uint8_t byte; |
| 846 | |
| 847 | byte = pmio_read(0xbb); |
| 848 | if (enable) |
| 849 | byte |= 0x20; |
| 850 | else |
| 851 | byte &= ~0x20; |
| 852 | pmio_write(0xbb, byte); |
| 853 | } |
| 854 | |
Zheng Bao | eff2ffd | 2010-03-16 01:38:54 +0000 | [diff] [blame] | 855 | #endif |