Ronald G. Minnich | 4b8cf1d | 2006-04-10 23:32:23 +0000 | [diff] [blame] | 1 | #include <console/console.h> |
| 2 | #include <arch/io.h> |
| 3 | #include <stdint.h> |
| 4 | #include <device/device.h> |
| 5 | #include <device/pci.h> |
| 6 | #include <device/pci_ids.h> |
| 7 | #include <stdlib.h> |
| 8 | #include <string.h> |
| 9 | #include <bitops.h> |
| 10 | #include "chip.h" |
| 11 | #include "northbridge.h" |
| 12 | #include <cpu/amd/gx2def.h> |
| 13 | #include <cpu/x86/msr.h> |
| 14 | #include <cpu/x86/cache.h> |
| 15 | |
| 16 | |
| 17 | /* the structs in this file only set msr.lo. But ... that may not always be true */ |
| 18 | |
| 19 | struct msrinit { |
| 20 | unsigned long msrnum; |
| 21 | msr_t msr; |
| 22 | }; |
| 23 | |
| 24 | /* Master Configuration Register for Bus Masters.*/ |
| 25 | struct msrinit SB_MASTER_CONF_TABLE[] = { |
| 26 | {USB1_SB_GLD_MSR_CONF, {.hi=0,.lo=0x00008f000}}, /* NOTE: Must be 1st entry in table*/ |
| 27 | {USB2_SB_GLD_MSR_CONF, {.hi=0,.lo=0x00008f000}}, |
| 28 | {ATA_SB_GLD_MSR_CONF, {.hi=0,.lo=0x00048f000}}, |
| 29 | {AC97_SB_GLD_MSR_CONF, {.hi=0,.lo=0x00008f000}}, |
| 30 | {MDD_SB_GLD_MSR_CONF, {.hi=0,.lo=0x00000f000}}, |
| 31 | /* GLPCI_SB_GLD_MSR_CONF, 0x0FFFFFFFF*/ |
| 32 | /* GLCP_SB_GLD_MSR_CONF, 0x0FFFFFFFF*/ |
| 33 | /* GLIU_SB_GLD_MSR_CONF, 0x0*/ |
| 34 | {0,{0,0}} |
| 35 | }; |
| 36 | |
| 37 | /* 5535_A3 Clock Gating*/ |
| 38 | struct msrinit CS5535_CLOCK_GATING_TABLE[] = { |
| 39 | { USB1_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, |
| 40 | { USB2_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, |
| 41 | { GLIU_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000004}}, |
| 42 | { GLPCI_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, |
| 43 | { GLCP_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000004}}, |
| 44 | { MDD_SB_GLD_MSR_PM, {.hi=0,.lo=0x050554111}}, |
| 45 | { ATA_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, |
| 46 | { AC97_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, |
| 47 | {0,{0,0}} |
| 48 | }; |
| 49 | |
| 50 | /* 5536 Clock Gating*/ |
| 51 | struct msrinit CS5536_CLOCK_GATING_TABLE[] = { |
| 52 | /* MSR Setting*/ |
| 53 | { GLIU_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000004}}, |
| 54 | { GLPCI_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, |
| 55 | { GLCP_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000004}}, |
Ronald G. Minnich | fb93749 | 2006-06-10 22:57:15 +0000 | [diff] [blame] | 56 | { MDD_SB_GLD_MSR_PM, {.hi=0,.lo=0x050554111}}, /* SMBus clock gating errata (PBZ 2226 & SiBZ 3977)*/ |
Ronald G. Minnich | 4b8cf1d | 2006-04-10 23:32:23 +0000 | [diff] [blame] | 57 | { ATA_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, |
| 58 | { AC97_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, |
| 59 | {0,{0,0}} |
| 60 | }; |
| 61 | |
| 62 | struct acpiinit { |
| 63 | unsigned short ioreg; |
| 64 | unsigned long regdata; |
| 65 | unsigned short iolen; |
| 66 | }; |
| 67 | |
| 68 | struct acpiinit acpi_init_table[] = { |
| 69 | {ACPI_BASE+0x00, 0x01000000, 4}, |
| 70 | {ACPI_BASE+0x08, 0, 4}, |
| 71 | {ACPI_BASE+0x0C, 0, 4}, |
| 72 | {ACPI_BASE+0x1C, 0, 4}, |
| 73 | {ACPI_BASE+0x18, 0x0FFFFFFFF, 4}, |
| 74 | {ACPI_BASE+0x00, 0x0000FFFF, 4}, |
| 75 | |
| 76 | {PM_SCLK, 0x000000E00, 4}, |
| 77 | {PM_SED, 0x000004601, 4}, |
| 78 | {PM_SIDD, 0x000008C02, 4}, |
| 79 | {PM_WKD, 0x0000000A0, 4}, |
| 80 | {PM_WKXD, 0x0000000A0, 4}, |
| 81 | {0,0,0} |
| 82 | }; |
| 83 | |
| 84 | /* return 1 if we are a 5536-based system */ |
| 85 | static int is_5536(void){ |
| 86 | msr_t msr; |
| 87 | msr = rdmsr(GLIU_SB_GLD_MSR_CAP); |
| 88 | msr.lo >>= 20; |
| 89 | printk_debug("is_5536: msr.lo is 0x%x(==5 means 5536)\n", msr.lo&0xf); |
| 90 | return ((msr.lo&0xf) == 5); |
| 91 | } |
| 92 | /* ***************************************************************************/ |
| 93 | /* **/ |
| 94 | /* * pmChipsetInit*/ |
| 95 | /* **/ |
| 96 | /* * Program ACPI LBAR and initialize ACPI registers.*/ |
| 97 | /* * */ |
| 98 | /* **/ |
| 99 | /* * Entry:*/ |
| 100 | /* * None*/ |
| 101 | /* **/ |
| 102 | /* * Exit:*/ |
| 103 | /* * None*/ |
| 104 | /* **/ |
| 105 | /* * Destroys:*/ |
| 106 | /* * None*/ |
| 107 | /* **/ |
| 108 | /* ***************************************************************************/ |
| 109 | static void |
| 110 | pmChipsetInit(void) { |
| 111 | unsigned long val = 0; |
| 112 | unsigned short port; |
| 113 | |
| 114 | port = (PMLogic_BASE + 0x010); |
| 115 | val = 0x0E00 ; /* 1ms*/ |
| 116 | outl(val, port); |
| 117 | |
| 118 | /* PM_WKXD*/ |
| 119 | /* Make sure bits[3:0]=0000b to clear the*/ |
| 120 | /* saved Sx state*/ |
| 121 | port = (PMLogic_BASE + 0x034); |
| 122 | val = 0x0A0 ; /* 5ms*/ |
| 123 | outl(val, port); |
| 124 | |
| 125 | /* PM_WKD*/ |
| 126 | port = (PMLogic_BASE + 0x030); |
| 127 | outl(val, port); |
| 128 | |
| 129 | /* PM_SED*/ |
| 130 | port = (PMLogic_BASE + 0x014); |
| 131 | /* mov eax, 0x057642 ; 100ms, works*/ |
| 132 | val = 0x04601 ; /* 5ms*/ |
| 133 | outl(val, port); |
| 134 | |
| 135 | /* PM_SIDD*/ |
| 136 | port = (PMLogic_BASE + 0x020); |
| 137 | /* mov eax, 0x0AEC84 ; 200ms, works*/ |
| 138 | val = 0x08C02 ; /* 10ms*/ |
| 139 | outl(val, port); |
| 140 | |
| 141 | /* GPIO24 OUT_AUX1 function is the external signal for 5535's vsb_working_aux*/ |
| 142 | /* which is de-asserted when 5535 enters Standby(S3 or S5) state.*/ |
| 143 | /* On Hawk, GPIO24 controls all voltage rails except Vmem and Vstandby. This means*/ |
| 144 | /* GX2 will be fully de-powered if this control de-asserts in S3/S5.*/ |
| 145 | /* */ |
| 146 | /* GPIO24 is setup in preChipsetInit for two reasons*/ |
| 147 | /* 1. GPIO24 at reset defaults to disabled, since this signal is vsb_work_aux on*/ |
| 148 | /* Hawk it controls the FET's for all voltage rails except Vstanby & Vmem.*/ |
| 149 | /* BIOS needs to enable GPIO24 as OUT_AUX1 & OUTPUT_EN early so it is driven*/ |
| 150 | /* by 5535.*/ |
| 151 | /* 2. Non-PM builds will require GPIO24 enabled for instant-off power button*/ |
| 152 | /* */ |
| 153 | |
| 154 | /* GPIO11 OUT_AUX1 function is the external signal for 5535's slp_clk_n which is asserted*/ |
| 155 | /* when 5535 enters Sleep(S1) state.*/ |
| 156 | /* On Hawk, GPIO11 is connected to control input of external clock generator*/ |
| 157 | /* for 14MHz, PCI, USB & LPC clocks.*/ |
| 158 | /* Programming of GPIO11 will be done by VSA PM code. During VSA Init. BIOS writes*/ |
| 159 | /* PM Core Virual Register indicating if S1 Clocks should be On or Off. This is based*/ |
| 160 | /* on a Setup item. We do not want to leave GPIO11 enabled because of a Hawk board*/ |
| 161 | /* problem. With GPIO11 enabled in S3, something is back-driving GPIO11 causing it to*/ |
| 162 | /* float to 1.6-1.7V.*/ |
| 163 | |
| 164 | } |
| 165 | |
Ronald G. Minnich | da7ee9f | 2006-07-21 19:21:38 +0000 | [diff] [blame^] | 166 | struct FLASH_DEVICE { |
| 167 | unsigned char fType; /* Flash type: NOR or NAND */ |
| 168 | unsigned char fInterface; /* Flash interface: I/O or Memory */ |
| 169 | unsigned long fMask; /* Flash size/mask */ |
| 170 | }; |
Ronald G. Minnich | 4b8cf1d | 2006-04-10 23:32:23 +0000 | [diff] [blame] | 171 | |
Ronald G. Minnich | da7ee9f | 2006-07-21 19:21:38 +0000 | [diff] [blame^] | 172 | struct FLASH_DEVICE FlashInitTable[] = { |
| 173 | { FLASH_TYPE_NAND, FLASH_IF_MEM, FLASH_MEM_4K }, /* CS0, or Flash Device 0 */ |
| 174 | { FLASH_TYPE_NONE, 0, 0 }, /* CS1, or Flash Device 1 */ |
| 175 | { FLASH_TYPE_NONE, 0, 0 }, /* CS2, or Flash Device 2 */ |
| 176 | { FLASH_TYPE_NONE, 0, 0 }, /* CS3, or Flash Device 3 */ |
| 177 | }; |
| 178 | |
| 179 | #define FlashInitTableLen (sizeof(FlashInitTable)/sizeof(FlashInitTable[0])) |
| 180 | |
| 181 | uint32_t FlashPort[] = { |
| 182 | MDD_LBAR_FLSH0, |
| 183 | MDD_LBAR_FLSH1, |
| 184 | MDD_LBAR_FLSH2, |
| 185 | MDD_LBAR_FLSH3 |
| 186 | }; |
| 187 | |
| 188 | /*************************************************************************** |
| 189 | * |
| 190 | * ChipsetFlashSetup |
| 191 | * |
| 192 | * Flash LBARs need to be setup before VSA init so the PCI BARs have |
| 193 | * correct size info. Call this routine only if flash needs to be |
| 194 | * configured (don't call it if you want IDE). |
| 195 | * |
| 196 | * Entry: |
| 197 | * Exit: |
| 198 | * Destroys: |
| 199 | * |
| 200 | **************************************************************************/ |
| 201 | static void ChipsetFlashSetup(void) |
| 202 | { |
| 203 | msr_t msr; |
| 204 | int i; |
| 205 | int numEnabled = 0; |
| 206 | |
| 207 | printk_debug("ChipsetFlashSetup++\n"); |
| 208 | for (i = 0; i < FlashInitTableLen; i++) { |
| 209 | if (FlashInitTable[i].fType != FLASH_TYPE_NONE) { |
| 210 | printk_debug("Enable CS%d\n", i); |
| 211 | /* we need to configure the memory/IO mask */ |
| 212 | msr = rdmsr(FlashPort[i]); |
| 213 | msr.hi = 0; /* start with the "enabled" bit clear */ |
| 214 | if (FlashInitTable[i].fType == FLASH_TYPE_NAND) |
| 215 | msr.hi |= 0x00000002; |
| 216 | else |
| 217 | msr.hi &= ~0x00000002; |
| 218 | if (FlashInitTable[i].fInterface == FLASH_IF_MEM) |
| 219 | msr.hi |= 0x00000004; |
| 220 | else |
| 221 | msr.hi &= ~0x00000004; |
| 222 | msr.hi |= FlashInitTable[i].fMask; |
| 223 | printk_debug("WRMSR(0x%08X, %08X_%08X)\n", FlashPort[i], msr.hi, msr.lo); |
| 224 | wrmsr(FlashPort[i], msr); |
| 225 | |
| 226 | /* now write-enable the device */ |
| 227 | msr = rdmsr(MDD_NORF_CNTRL); |
| 228 | msr.lo |= (1 << i); |
| 229 | printk_debug("WRMSR(0x%08X, %08X_%08X)\n", MDD_NORF_CNTRL, msr.hi, msr.lo); |
| 230 | wrmsr(MDD_NORF_CNTRL, msr); |
| 231 | |
| 232 | /* update the number enabled */ |
| 233 | numEnabled++; |
| 234 | } |
| 235 | } |
| 236 | |
| 237 | /* enable the flash */ |
| 238 | if (0 != numEnabled) { |
| 239 | msr = rdmsr(MDD_PIN_OPT); |
| 240 | msr.lo &= ~1; /* PIN_OPT_IDE */ |
| 241 | printk_debug("WRMSR(0x%08X, %08X_%08X)\n", MDD_PIN_OPT, msr.hi, msr.lo); |
| 242 | wrmsr(MDD_PIN_OPT, msr); |
| 243 | } |
| 244 | printk_debug("ChipsetFlashSetup--\n"); |
| 245 | |
| 246 | } |
| 247 | |
| 248 | |
| 249 | |
Ronald G. Minnich | 4b8cf1d | 2006-04-10 23:32:23 +0000 | [diff] [blame] | 250 | /* ***************************************************************************/ |
| 251 | /* **/ |
| 252 | /* * ChipsetGeodeLinkInit*/ |
| 253 | /* * Handle chipset specific GeodeLink settings here. */ |
| 254 | /* * Called from GeodeLink init code.*/ |
| 255 | /* **/ |
| 256 | /* * Entry:*/ |
| 257 | /* * Exit:*/ |
| 258 | /* * Destroys: GS*/ |
| 259 | /* **/ |
| 260 | /* ***************************************************************************/ |
| 261 | static void |
| 262 | ChipsetGeodeLinkInit(void){ |
| 263 | msr_t msr; |
| 264 | unsigned long msrnum; |
| 265 | unsigned long totalmem; |
| 266 | |
| 267 | if (is_5536()) |
| 268 | return; |
| 269 | /* SWASIF for A1 DMA */ |
| 270 | /* Set all memory to "just above systop" PCI so DMA will work*/ |
| 271 | /* check A1*/ |
| 272 | msrnum = MSR_SB_GLCP + 0x17; |
| 273 | msr = rdmsr(msrnum); |
| 274 | if ((msr.lo&0xff) == 0x11) |
| 275 | return; |
| 276 | |
| 277 | totalmem = sizeram() << 20 - 1; |
| 278 | totalmem >>= 12; |
| 279 | totalmem = ~totalmem; |
| 280 | totalmem &= 0xfffff; |
| 281 | msr.lo = totalmem; |
| 282 | msr.hi = 0x20000000; /* Port 1 (PCI)*/ |
| 283 | msrnum = MSR_SB_GLIU + 0x20; /* */; |
| 284 | wrmsr(msrnum, msr); |
| 285 | } |
| 286 | |
| 287 | void |
Ronald G. Minnich | da7ee9f | 2006-07-21 19:21:38 +0000 | [diff] [blame^] | 288 | chipsetinit (struct northbridge_amd_gx2_config *nb){ |
Ronald G. Minnich | 4b8cf1d | 2006-04-10 23:32:23 +0000 | [diff] [blame] | 289 | msr_t msr; |
| 290 | struct msrinit *csi; |
| 291 | int i; |
| 292 | unsigned long msrnum; |
| 293 | |
| 294 | outb( P80_CHIPSET_INIT, 0x80); |
| 295 | ChipsetGeodeLinkInit(); |
Li-Ta Lo | d8d8fff | 2006-04-13 17:00:38 +0000 | [diff] [blame] | 296 | #if 0 |
Ronald G. Minnich | 4b8cf1d | 2006-04-10 23:32:23 +0000 | [diff] [blame] | 297 | /* we hope NEVER to be in linuxbios when S3 resumes |
| 298 | if (! IsS3Resume()) */ |
| 299 | { |
| 300 | struct acpiinit *aci = acpi_init_table; |
| 301 | while (aci->ioreg){ |
| 302 | if (aci->iolen == 2) { |
| 303 | outw(aci->regdata, aci->ioreg); |
| 304 | inw(aci->ioreg); |
| 305 | } else { |
| 306 | outl(aci->regdata, aci->ioreg); |
| 307 | inl(aci->ioreg); |
| 308 | } |
| 309 | } |
| 310 | |
| 311 | pmChipsetInit(); |
| 312 | } |
Li-Ta Lo | d8d8fff | 2006-04-13 17:00:38 +0000 | [diff] [blame] | 313 | #endif |
Ronald G. Minnich | 4b8cf1d | 2006-04-10 23:32:23 +0000 | [diff] [blame] | 314 | |
Ronald G. Minnich | 4b8cf1d | 2006-04-10 23:32:23 +0000 | [diff] [blame] | 315 | |
Ronald G. Minnich | fb93749 | 2006-06-10 22:57:15 +0000 | [diff] [blame] | 316 | if (!is_5536()) { |
| 317 | /* Setup USB. Need more details. #118.18*/ |
| 318 | msrnum = MSR_SB_USB1 + 8; |
| 319 | msr.lo = 0x00012090; |
| 320 | msr.hi = 0; |
| 321 | wrmsr(msrnum, msr); |
| 322 | msrnum = MSR_SB_USB2 + 8; |
| 323 | wrmsr(msrnum, msr); |
| 324 | } |
| 325 | |
Ronald G. Minnich | 4b8cf1d | 2006-04-10 23:32:23 +0000 | [diff] [blame] | 326 | /* set hd IRQ */ |
| 327 | outl (GPIOL_2_SET, GPIOL_INPUT_ENABLE); |
| 328 | outl (GPIOL_2_SET, GPIOL_IN_AUX1_SELECT); |
| 329 | |
| 330 | /* Allow IO read and writes during a ATA DMA operation.*/ |
| 331 | /* This could be done in the HD rom but do it here for easier debugging.*/ |
| 332 | |
| 333 | msrnum = ATA_SB_GLD_MSR_ERR; |
| 334 | msr = rdmsr(msrnum); |
| 335 | msr.lo &= ~0x100; |
| 336 | wrmsr(msrnum, msr); |
| 337 | |
Li-Ta Lo | d8d8fff | 2006-04-13 17:00:38 +0000 | [diff] [blame] | 338 | /* Enable Post Primary IDE.*/ |
Ronald G. Minnich | 4b8cf1d | 2006-04-10 23:32:23 +0000 | [diff] [blame] | 339 | msrnum = GLPCI_SB_CTRL; |
| 340 | msr = rdmsr(msrnum); |
| 341 | msr.lo |= GLPCI_CRTL_PPIDE_SET; |
| 342 | wrmsr(msrnum, msr); |
| 343 | |
| 344 | |
| 345 | /* Set up Master Configuration Register*/ |
| 346 | /* If 5536, use same master config settings as 5535, except for OHCI MSRs*/ |
| 347 | if (is_5536()) |
| 348 | i = 2; |
| 349 | else |
| 350 | i = 0; |
| 351 | |
| 352 | csi = &SB_MASTER_CONF_TABLE[i]; |
| 353 | for(; csi->msrnum; csi++){ |
| 354 | msr.lo = csi->msr.lo; |
| 355 | msr.hi = csi->msr.hi; |
Ronald G. Minnich | fb93749 | 2006-06-10 22:57:15 +0000 | [diff] [blame] | 356 | wrmsr(csi->msrnum, msr); // MSR - see table above |
Ronald G. Minnich | 4b8cf1d | 2006-04-10 23:32:23 +0000 | [diff] [blame] | 357 | } |
| 358 | |
| 359 | |
| 360 | /* Flash Setup*/ |
Ronald G. Minnich | da7ee9f | 2006-07-21 19:21:38 +0000 | [diff] [blame^] | 361 | printk_err("%sDOING ChipsetFlashSetup()!!!!!!!!!!!!!!!!!!\n", nb->setupflash? "NOT " : ""); |
| 362 | if (nb->setupflash) |
| 363 | ChipsetFlashSetup(); |
Ronald G. Minnich | 4b8cf1d | 2006-04-10 23:32:23 +0000 | [diff] [blame] | 364 | |
| 365 | |
| 366 | |
| 367 | /* */ |
| 368 | /* Set up Hardware Clock Gating*/ |
| 369 | /* */ |
| 370 | /* if (getnvram(TOKEN_SB_CLK_GATE) != TVALUE_DISABLE) */ |
| 371 | { |
| 372 | if (is_5536()) |
| 373 | csi = CS5536_CLOCK_GATING_TABLE; |
| 374 | else |
Ronald G. Minnich | fb93749 | 2006-06-10 22:57:15 +0000 | [diff] [blame] | 375 | csi = CS5535_CLOCK_GATING_TABLE; |
Ronald G. Minnich | 4b8cf1d | 2006-04-10 23:32:23 +0000 | [diff] [blame] | 376 | |
| 377 | for(; csi->msrnum; csi++){ |
| 378 | msr.lo = csi->msr.lo; |
| 379 | msr.hi = csi->msr.hi; |
Ronald G. Minnich | fb93749 | 2006-06-10 22:57:15 +0000 | [diff] [blame] | 380 | wrmsr(csi->msrnum, msr); // MSR - see table above |
Ronald G. Minnich | 4b8cf1d | 2006-04-10 23:32:23 +0000 | [diff] [blame] | 381 | } |
| 382 | } |
| 383 | |
| 384 | } |