1/* 2 * This file is part of the coreboot project. 3 * 4 * Copyright (C) 2007 Advanced Micro Devices, Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20#include <types.h> 21#include <console.h> 22#include <msr.h> 23#include <lib.h> 24#include <amd_geodelx.h> 25#include "cs5536.h" 26 27/* 28 * Early chipset initialization for the AMD CS5536 Companion Device. 29 * 30 * This code is needed for setting up RAM, since we need SMBus working as 31 * well as a serial port. 32 * 33 * This file implements the initialization sequence documented in section 4.2 34 * of AMD Geode GX Processor CS5536 Companion Device GoedeROM Porting Guide. 35 */ 36 37/** 38 * Set up GLINK routing for this part. 39 * 40 * The routing is controlled by an MSR. This appears to be the same on 41 * all boards. 42 */ 43static void cs5536_setup_extmsr(void) 44{ 45 struct msr msr; 46 47 /* Forward MSR access to CS5536_GLINK_PORT_NUM to CS5536_DEV_NUM. */ 48 msr.hi = msr.lo = 0; 49 50 /* TODO: unsigned char -> u8? */ 51#if CS5536_GLINK_PORT_NUM <= 4 52 msr.lo = CS5536_DEV_NUM << 53 (unsigned char) ((CS5536_GLINK_PORT_NUM - 1) * 8); 54#else 55 msr.hi = CS5536_DEV_NUM << 56 (unsigned char) ((CS5536_GLINK_PORT_NUM - 5) * 8); 57#endif 58 59 wrmsr(GLPCI_ExtMSR, msr); 60} 61 62/** 63 * Setup PCI IDSEL for CS5536. There is a Magic Register that must be 64 * written so that the chip appears at the expected place in the PCI tree. 65 */ 66static void cs5536_setup_idsel(void) 67{ 68 /* Write IDSEL to the write once register at address 0x0000. */ 69 outl(0x1 << (CS5536_DEV_NUM + 10), 0); 70} 71 72/** 73 * Magic Bits for undocumented register. You don't need to see those papers. 74 * These are not the bits you're looking for. You can go about your business. 75 * Move along, move along. 76 */ 77static void cs5536_usb_swapsif(void) 78{ 79 struct msr msr; 80 81 msr = rdmsr(USB1_SB_GLD_MSR_CAP + 0x5); 82 83 /* USB Serial short detect bit. */ 84 if (msr.hi & 0x10) { 85 /* We need to preserve bits 32,33,35 and not clear any BIST 86 * error, but clear the SERSHRT error bit. 87 */ 88 msr.hi &= 0xFFFFFFFB; 89 wrmsr(USB1_SB_GLD_MSR_CAP + 0x5, msr); 90 } 91} 92 93static const struct msrinit msr_table[] = { 94 {MDD_LBAR_SMB, {.hi = 0x0000f001,.lo = SMBUS_IO_BASE}}, 95 {MDD_LBAR_GPIO, {.hi = 0x0000f001,.lo = GPIO_IO_BASE}}, 96 {MDD_LBAR_MFGPT, {.hi = 0x0000f001,.lo = MFGPT_IO_BASE}}, 97 {MDD_LBAR_ACPI, {.hi = 0x0000f001,.lo = ACPI_IO_BASE}}, 98 {MDD_LBAR_PMS, {.hi = 0x0000f001,.lo = PMS_IO_BASE}}, 99}; 100 101/** 102 * Set up I/O bases for SMBus, GPIO, MFGPT, ACPI, and PM. 103 * 104 * These can be changed by Linux later. We set some initial value so that 105 * the resources are there as needed. The values are hardcoded because, 106 * this early in the process, fancy allocation can do more harm than good. 107 */ 108static void cs5536_setup_iobase(void) 109{ 110 int i; 111 112 for (i = 0; i < ARRAY_SIZE(msr_table); i++) 113 wrmsr(msr_table[i].msrnum, msr_table[i].msr); 114} 115 116/** 117 * Set the various GPIOs. 118 * 119 * An unknown question at this point is how general this is to all mainboards. 120 * At the same time, many boards seem to follow this particular reference spec. 121 */ 122static void cs5536_setup_smbus_gpio(void) 123{ 124 u32 val; 125 126 /* Setup GPIO pins 14/15 for SDA/SCL. */ 127 val = GPIOL_15_SET | GPIOL_14_SET; 128 129 /* Output AUX1 + enable */ 130 outl(val, GPIO_IO_BASE + GPIOL_OUT_AUX1_SELECT); 131 outl(val, GPIO_IO_BASE + GPIOL_OUTPUT_ENABLE); 132 133 /* Input AUX1 + enable */ 134 outl(val, GPIO_IO_BASE + GPIOL_IN_AUX1_SELECT); 135 outl(val, GPIO_IO_BASE + GPIOL_INPUT_ENABLE); 136} 137 138/** 139 * Disable the internal UART. 140 * 141 * Different boards have different UARTs for COM1. 142 */ 143void cs5536_disable_internal_uart(void) 144{ 145 struct msr msr; 146 147 /* The UARTs default to enabled. 148 * Disable and reset them and configure them later (SIO init). 149 */ 150 msr = rdmsr(MDD_UART1_CONF); 151 msr.lo = 1; /* Reset */ 152 wrmsr(MDD_UART1_CONF, msr); 153 msr.lo = 0; /* Disable */ 154 wrmsr(MDD_UART1_CONF, msr); 155 156 msr = rdmsr(MDD_UART2_CONF); 157 msr.lo = 1; /* Reset */ 158 wrmsr(MDD_UART2_CONF, msr); 159 msr.lo = 0; /* Disable */ 160 wrmsr(MDD_UART2_CONF, msr); 161} 162 163/** 164 * Set up the CS5536 CIS interface to CPU interface to match modes. 165 * 166 * The CIS is related to the interrupt system. It is important to match 167 * the southbridge and the CPU chips. At the same time, they always seem 168 * to use mode B. 169 */ 170static void cs5536_setup_cis_mode(void) 171{ 172 struct msr msr; 173 174 /* Setup CPU interface serial to mode B to match CPU. */ 175 msr = rdmsr(GLPCI_SB_CTRL); 176 msr.lo &= ~0x18; 177 msr.lo |= 0x10; 178 wrmsr(GLPCI_SB_CTRL, msr); 179} 180 181/** 182 * Enable the on-chip UART. 183 * 184 * See page 412 of the AMD Geode CS5536 Companion Device data book. 185 */ 186void cs5536_setup_onchipuart1(void) 187{ 188 struct msr msr; 189 190 /* Setup early for polling only mode. 191 * 1. Enable GPIO 8 to OUT_AUX1, 9 to IN_AUX1. 192 * GPIO LBAR + 0x04, LBAR + 0x10, LBAR + 0x20, LBAR + 34 193 * 2. Enable UART I/O space in MDD. 194 * MSR 0x51400014 bit 18:16 195 * 3. Enable UART controller. 196 * MSR 0x5140003A bit 0, 1 197 */ 198 199 /* GPIO8 - UART1_TX */ 200 /* Set: Output Enable (0x4) */ 201 outl(GPIOL_8_SET, GPIO_IO_BASE + GPIOL_OUTPUT_ENABLE); 202 /* Set: OUTAUX1 Select (0x10) */ 203 outl(GPIOL_8_SET, GPIO_IO_BASE + GPIOL_OUT_AUX1_SELECT); 204 205 /* GPIO9 - UART1_RX */ 206 /* Set: Input Enable (0x20) */ 207 outl(GPIOL_9_SET, GPIO_IO_BASE + GPIOL_INPUT_ENABLE); 208 /* Set: INAUX1 Select (0x34) */ 209 outl(GPIOL_9_SET, GPIO_IO_BASE + GPIOL_IN_AUX1_SELECT); 210 211 /* Set address to 0x3F8. */ 212 msr = rdmsr(MDD_LEG_IO); 213 msr.lo |= 0x7 << 16; 214 wrmsr(MDD_LEG_IO, msr); 215 216 /* Bit 1 = DEVEN (device enable) 217 * Bit 4 = EN_BANKS (allow access to the upper banks) 218 */ 219 msr.lo = (1 << 4) | (1 << 1); 220 msr.hi = 0; 221 222 /* Enable COM1. */ 223 wrmsr(MDD_UART1_CONF, msr); 224} 225 226void cs5536_setup_onchipuart2(void) 227{ 228 struct msr msr; 229 230 /* GPIO4 - UART2_TX */ 231 /* Set: Output Enable (0x4) */ 232 outl(GPIOL_4_SET, GPIO_IO_BASE + GPIOL_OUTPUT_ENABLE); 233 /* Set: OUTAUX1 Select (0x10) */ 234 outl(GPIOL_4_SET, GPIO_IO_BASE + GPIOL_OUT_AUX1_SELECT); 235 /* GPIO4 - UART2_RX */ 236 /* Set: Input Enable (0x20) */ 237 outl(GPIOL_3_SET, GPIO_IO_BASE + GPIOL_INPUT_ENABLE); 238 /* Set: INAUX1 Select (0x34) */ 239 outl(GPIOL_3_SET, GPIO_IO_BASE + GPIOL_IN_AUX1_SELECT); 240 241 /* Set: GPIO 3 + 3 Pull Up (0x18) */ 242 outl(GPIOL_3_SET | GPIOL_4_SET, 243 GPIO_IO_BASE + GPIOL_PULLUP_ENABLE); 244 245 /* set address to 3F8 */ 246 msr = rdmsr(MDD_LEG_IO); 247 msr.lo |= 0x7 << 20; 248 wrmsr(MDD_LEG_IO, msr); 249 250 /* Bit 1 = DEVEN (device enable) 251 * Bit 4 = EN_BANKS (allow access to the upper banks 252 */ 253 msr.lo = (1 << 4) | (1 << 1); 254 msr.hi = 0; 255 256 /* enable COM2 */ 257 wrmsr(MDD_UART2_CONF, msr); 258} 259 260void cs5536_setup_onchipuart(int uart) 261{ 262 switch (uart) { 263 case 1: 264 cs5536_setup_onchipuart1(); 265 break; 266 case 2: 267 cs5536_setup_onchipuart2(); 268 break; 269 } 270} 271 272 273/** 274 * Board setup. 275 * 276 * Known to work on the AMD Norwich and Advanced Digital Logic boards. 277 * 278 * The extmsr and cis_mode are common for sure. The RSTPLL check is mandatory. 279 * IDSEL of course is required, so the chip appears in PCI config space, 280 * and the swapsif covers a necessary chip fix. 281 * 282 * Finally, the iobase is needed for DRAM, the GPIOs are likely common to all 283 * boards, and the power button seems to be the same on all. At the same time, 284 * we may need to move GPIO and power button out as developments demand. 285 * 286 * Note we do NOT do any UART setup here -- this is done later by the 287 * mainboard setup, since UART usage is not universal. 288 * 289 * See also a comment from Marc Jones: 290 * http://www.linuxbios.org/pipermail/linuxbios/2007-June/021958.html 291 */ 292void cs5536_stage1(void) 293{ 294 struct msr msr; 295 296 /* Note: you can't do prints in here in most cases, and we don't want 297 * to hang on serial, so they are commented out. 298 */ 299 cs5536_setup_extmsr(); 300 cs5536_setup_cis_mode(); 301 302 msr = rdmsr(GLCP_SYS_RSTPLL); 303 if (msr.lo & (0x3f << 26)) { 304 /* PLL is already set and we are reboot from PLL reset. */ 305 return; 306 } 307 308 cs5536_setup_idsel(); 309 cs5536_usb_swapsif(); 310 cs5536_setup_iobase(); 311 cs5536_setup_smbus_gpio(); 312 /* cs5536_enable_smbus(); -- Leave this out for now. */ 313} 314

