coreboot-v3/southbridge/amd/cs5536/stage1.c
<<
>>
Prefs
   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
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.