coreboot/src/southbridge/intel/i82801gx/lpc.c
<<
>>
Prefs
   1/*
   2 * This file is part of the coreboot project.
   3 *
   4 * Copyright (C) 2008-2009 coresystems GmbH
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License as
   8 * published by the Free Software Foundation; version 2 of
   9 * 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.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  19 */
  20
  21#include <console/console.h>
  22#include <device/device.h>
  23#include <device/pci.h>
  24#include <device/pci_ids.h>
  25#include <pc80/mc146818rtc.h>
  26#include <pc80/isa-dma.h>
  27#include <pc80/i8259.h>
  28#include <arch/io.h>
  29#include <arch/ioapic.h>
  30#include <cpu/cpu.h>
  31#include "i82801gx.h"
  32
  33#define NMI_OFF 0
  34
  35#define ENABLE_ACPI_MODE_IN_COREBOOT    0
  36#define TEST_SMM_FLASH_LOCKDOWN         0
  37
  38typedef struct southbridge_intel_i82801gx_config config_t;
  39
  40static void i82801gx_enable_apic(struct device *dev)
  41{
  42        int i;
  43        u32 reg32;
  44        volatile u32 *ioapic_index = (volatile u32 *)(IO_APIC_ADDR);
  45        volatile u32 *ioapic_data = (volatile u32 *)(IO_APIC_ADDR + 0x10);
  46
  47        /* Enable ACPI I/O and power management.
  48         * Set SCI IRQ to IRQ9
  49         */
  50        pci_write_config8(dev, ACPI_CNTL, 0x80);
  51
  52        *ioapic_index = 0;
  53        *ioapic_data = (1 << 25);
  54
  55        *ioapic_index = 0;
  56        reg32 = *ioapic_data;
  57        printk(BIOS_DEBUG, "Southbridge APIC ID = %x\n", (reg32 >> 24) & 0x0f);
  58        if (reg32 != (1 << 25))
  59                die("APIC Error\n");
  60
  61        printk(BIOS_SPEW, "Dumping IOAPIC registers\n");
  62        for (i=0; i<3; i++) {
  63                *ioapic_index = i;
  64                printk(BIOS_SPEW, "  reg 0x%04x:", i);
  65                reg32 = *ioapic_data;
  66                printk(BIOS_SPEW, " 0x%08x\n", reg32);
  67        }
  68
  69        *ioapic_index = 3; /* Select Boot Configuration register. */
  70        *ioapic_data = 1; /* Use Processor System Bus to deliver interrupts. */
  71}
  72
  73static void i82801gx_enable_serial_irqs(struct device *dev)
  74{
  75        /* Set packet length and toggle silent mode bit for one frame. */
  76        pci_write_config8(dev, SERIRQ_CNTL,
  77                          (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
  78}
  79
  80/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
  81 * 0x00 - 0000 = Reserved
  82 * 0x01 - 0001 = Reserved
  83 * 0x02 - 0010 = Reserved
  84 * 0x03 - 0011 = IRQ3
  85 * 0x04 - 0100 = IRQ4
  86 * 0x05 - 0101 = IRQ5
  87 * 0x06 - 0110 = IRQ6
  88 * 0x07 - 0111 = IRQ7
  89 * 0x08 - 1000 = Reserved
  90 * 0x09 - 1001 = IRQ9
  91 * 0x0A - 1010 = IRQ10
  92 * 0x0B - 1011 = IRQ11
  93 * 0x0C - 1100 = IRQ12
  94 * 0x0D - 1101 = Reserved
  95 * 0x0E - 1110 = IRQ14
  96 * 0x0F - 1111 = IRQ15
  97 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
  98 * 0x80 - The PIRQ is not routed.
  99 */
 100
 101static void i82801gx_pirq_init(device_t dev)
 102{
 103        device_t irq_dev;
 104        /* Get the chip configuration */
 105        config_t *config = dev->chip_info;
 106
 107        pci_write_config8(dev, PIRQA_ROUT, config->pirqa_routing);
 108        pci_write_config8(dev, PIRQB_ROUT, config->pirqb_routing);
 109        pci_write_config8(dev, PIRQC_ROUT, config->pirqc_routing);
 110        pci_write_config8(dev, PIRQD_ROUT, config->pirqd_routing);
 111
 112        pci_write_config8(dev, PIRQE_ROUT, config->pirqe_routing);
 113        pci_write_config8(dev, PIRQF_ROUT, config->pirqf_routing);
 114        pci_write_config8(dev, PIRQG_ROUT, config->pirqg_routing);
 115        pci_write_config8(dev, PIRQH_ROUT, config->pirqh_routing);
 116
 117        /* Eric Biederman once said we should let the OS do this.
 118         * I am not so sure anymore he was right.
 119         */
 120
 121        for(irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
 122                u8 int_pin=0, int_line=0;
 123
 124                if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
 125                        continue;
 126
 127                int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
 128
 129                switch (int_pin) {
 130                case 1: /* INTA# */ int_line = config->pirqa_routing; break;
 131                case 2: /* INTB# */ int_line = config->pirqb_routing; break;
 132                case 3: /* INTC# */ int_line = config->pirqc_routing; break;
 133                case 4: /* INTD# */ int_line = config->pirqd_routing; break;
 134                }
 135
 136                if (!int_line)
 137                        continue;
 138
 139                pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, int_line);
 140        }
 141}
 142
 143static void i82801gx_gpi_routing(device_t dev)
 144{
 145        /* Get the chip configuration */
 146        config_t *config = dev->chip_info;
 147        u32 reg32 = 0;
 148
 149        /* An array would be much nicer here, or some
 150         * other method of doing this.
 151         */
 152        reg32 |= (config->gpi0_routing & 0x03) << 0;
 153        reg32 |= (config->gpi1_routing & 0x03) << 2;
 154        reg32 |= (config->gpi2_routing & 0x03) << 4;
 155        reg32 |= (config->gpi3_routing & 0x03) << 6;
 156        reg32 |= (config->gpi4_routing & 0x03) << 8;
 157        reg32 |= (config->gpi5_routing & 0x03) << 10;
 158        reg32 |= (config->gpi6_routing & 0x03) << 12;
 159        reg32 |= (config->gpi7_routing & 0x03) << 14;
 160        reg32 |= (config->gpi8_routing & 0x03) << 16;
 161        reg32 |= (config->gpi9_routing & 0x03) << 18;
 162        reg32 |= (config->gpi10_routing & 0x03) << 20;
 163        reg32 |= (config->gpi11_routing & 0x03) << 22;
 164        reg32 |= (config->gpi12_routing & 0x03) << 24;
 165        reg32 |= (config->gpi13_routing & 0x03) << 26;
 166        reg32 |= (config->gpi14_routing & 0x03) << 28;
 167        reg32 |= (config->gpi15_routing & 0x03) << 30;
 168
 169        pci_write_config32(dev, 0xb8, reg32);
 170}
 171
 172extern u8 acpi_slp_type;
 173
 174static void i82801gx_power_options(device_t dev)
 175{
 176        u8 reg8;
 177        u16 reg16, pmbase;
 178        u32 reg32;
 179        const char *state;
 180        /* Get the chip configuration */
 181        config_t *config = dev->chip_info;
 182
 183        int pwr_on=CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
 184        int nmi_option;
 185
 186        /* Which state do we want to goto after g3 (power restored)?
 187         * 0 == S0 Full On
 188         * 1 == S5 Soft Off
 189         *
 190         * If the option is not existent (Laptops), use MAINBOARD_POWER_ON.
 191         */
 192        if (get_option(&pwr_on, "power_on_after_fail") < 0)
 193                pwr_on = MAINBOARD_POWER_ON;
 194
 195        reg8 = pci_read_config8(dev, GEN_PMCON_3);
 196        reg8 &= 0xfe;
 197        switch (pwr_on) {
 198        case MAINBOARD_POWER_OFF:
 199                reg8 |= 1;
 200                state = "off";
 201                break;
 202        case MAINBOARD_POWER_ON:
 203                reg8 &= ~1;
 204                state = "on";
 205                break;
 206        case MAINBOARD_POWER_KEEP:
 207                reg8 &= ~1;
 208                state = "state keep";
 209                break;
 210        default:
 211                state = "undefined";
 212        }
 213
 214        reg8 |= (3 << 4);       /* avoid #S4 assertions */
 215        reg8 &= ~(1 << 3);      /* minimum asssertion is 1 to 2 RTCCLK */
 216
 217        pci_write_config8(dev, GEN_PMCON_3, reg8);
 218        printk(BIOS_INFO, "Set power %s after power failure.\n", state);
 219
 220        /* Set up NMI on errors. */
 221        reg8 = inb(0x61);
 222        reg8 &= 0x0f;           /* Higher Nibble must be 0 */
 223        reg8 &= ~(1 << 3);      /* IOCHK# NMI Enable */
 224        // reg8 &= ~(1 << 2);   /* PCI SERR# Enable */
 225        reg8 |= (1 << 2); /* PCI SERR# Disable for now */
 226        outb(reg8, 0x61);
 227
 228        reg8 = inb(0x70);
 229        nmi_option = NMI_OFF;
 230        get_option(&nmi_option, "nmi");
 231        if (nmi_option) {
 232                printk(BIOS_INFO, "NMI sources enabled.\n");
 233                reg8 &= ~(1 << 7);      /* Set NMI. */
 234        } else {
 235                printk(BIOS_INFO, "NMI sources disabled.\n");
 236                reg8 |= ( 1 << 7);      /* Can't mask NMI from PCI-E and NMI_NOW */
 237        }
 238        outb(reg8, 0x70);
 239
 240        /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
 241        reg16 = pci_read_config16(dev, GEN_PMCON_1);
 242        reg16 &= ~(3 << 0);     // SMI# rate 1 minute
 243        reg16 |= (1 << 2);      // CLKRUN_EN - Mobile/Ultra only
 244        reg16 |= (1 << 3);      // Speedstep Enable - Mobile/Ultra only
 245        reg16 |= (1 << 5);      // CPUSLP_EN Desktop only
 246        // another laptop wants this?
 247        // reg16 &= ~(1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
 248        reg16 |= (1 << 10);     // BIOS_PCI_EXP_EN - Desktop/Mobile only
 249#if DEBUG_PERIODIC_SMIS
 250        /* Set DEBUG_PERIODIC_SMIS in i82801gx.h to debug using
 251         * periodic SMIs.
 252         */
 253        reg16 |= (3 << 0); // Periodic SMI every 8s
 254#endif
 255        pci_write_config16(dev, GEN_PMCON_1, reg16);
 256
 257        // Set the board's GPI routing.
 258        i82801gx_gpi_routing(dev);
 259
 260        pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
 261
 262        outl(config->gpe0_en, pmbase + GPE0_EN);
 263        outw(config->alt_gp_smi_en, pmbase + ALT_GP_SMI_EN);
 264
 265        /* Set up power management block and determine sleep mode */
 266        reg32 = inl(pmbase + 0x04); // PM1_CNT
 267
 268        reg32 &= ~(7 << 10);    // SLP_TYP
 269        reg32 |= (1 << 1);      // enable C3->C0 transition on bus master
 270        reg32 |= (1 << 0);      // SCI_EN
 271        outl(reg32, pmbase + 0x04);
 272}
 273
 274static void i82801gx_configure_cstates(device_t dev)
 275{
 276        u8 reg8;
 277
 278        reg8 = pci_read_config8(dev, 0xa9); // Cx state configuration
 279        reg8 |= (1 << 4) | (1 << 3) | (1 << 2); // Enable Popup & Popdown
 280        pci_write_config8(dev, 0xa9, reg8);
 281
 282        // Set Deeper Sleep configuration to recommended values
 283        reg8 = pci_read_config8(dev, 0xaa);
 284        reg8 &= 0xf0;
 285        reg8 |= (2 << 2);       // Deeper Sleep to Stop CPU: 34-40us
 286        reg8 |= (2 << 0);       // Deeper Sleep to Sleep: 15us
 287        pci_write_config8(dev, 0xaa, reg8);
 288}
 289
 290static void i82801gx_rtc_init(struct device *dev)
 291{
 292        u8 reg8;
 293        int rtc_failed;
 294
 295        reg8 = pci_read_config8(dev, GEN_PMCON_3);
 296        rtc_failed = reg8 & RTC_BATTERY_DEAD;
 297        if (rtc_failed) {
 298                reg8 &= ~RTC_BATTERY_DEAD;
 299                pci_write_config8(dev, GEN_PMCON_3, reg8);
 300        }
 301        printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
 302
 303        rtc_init(rtc_failed);
 304}
 305
 306static void enable_hpet(void)
 307{
 308        u32 reg32;
 309
 310        /* Move HPET to default address 0xfed00000 and enable it */
 311        reg32 = RCBA32(HPTC);
 312        reg32 |= (1 << 7); // HPET Address Enable
 313        reg32 &= ~(3 << 0);
 314        RCBA32(HPTC) = reg32;
 315}
 316
 317static void enable_clock_gating(void)
 318{
 319        u32 reg32;
 320
 321        /* Enable Clock Gating for most devices */
 322        reg32 = RCBA32(CG);
 323        reg32 |= (1 << 31);     // LPC clock gating
 324        reg32 |= (1 << 30);     // PATA clock gating
 325        // SATA clock gating
 326        reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
 327        reg32 |= (1 << 23);     // AC97 clock gating
 328        reg32 |= (1 << 19);     // USB EHCI clock gating
 329        reg32 |= (1 << 3) | (1 << 1);   // DMI clock gating
 330        reg32 |= (1 << 2);      // PCIe clock gating;
 331        reg32 &= ~(1 << 20); // No static clock gating for USB
 332        reg32 &= ~( (1 << 29) | (1 << 28) ); // Disable UHCI clock gating
 333        RCBA32(CG) = reg32;
 334}
 335
 336#if CONFIG_HAVE_SMI_HANDLER
 337static void i82801gx_lock_smm(struct device *dev)
 338{
 339#if TEST_SMM_FLASH_LOCKDOWN
 340        u8 reg8;
 341#endif
 342
 343#if ENABLE_ACPI_MODE_IN_COREBOOT
 344        printk(BIOS_DEBUG, "Enabling ACPI via APMC:\n");
 345        outb(0xe1, 0xb2); // Enable ACPI mode
 346        printk(BIOS_DEBUG, "done.\n");
 347#else
 348        printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
 349        outb(0x1e, 0xb2); // Disable ACPI mode
 350        printk(BIOS_DEBUG, "done.\n");
 351#endif
 352        /* Don't allow evil boot loaders, kernels, or
 353         * userspace applications to deceive us:
 354         */
 355        smm_lock();
 356
 357#if TEST_SMM_FLASH_LOCKDOWN
 358        /* Now try this: */
 359        printk(BIOS_DEBUG, "Locking BIOS to RO... ");
 360        reg8 = pci_read_config8(dev, 0xdc);     /* BIOS_CNTL */
 361        printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
 362                        (reg8&1)?"rw":"ro");
 363        reg8 &= ~(1 << 0);                      /* clear BIOSWE */
 364        pci_write_config8(dev, 0xdc, reg8);
 365        reg8 |= (1 << 1);                       /* set BLE */
 366        pci_write_config8(dev, 0xdc, reg8);
 367        printk(BIOS_DEBUG, "ok.\n");
 368        reg8 = pci_read_config8(dev, 0xdc);     /* BIOS_CNTL */
 369        printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
 370                        (reg8&1)?"rw":"ro");
 371
 372        printk(BIOS_DEBUG, "Writing:\n");
 373        *(volatile u8 *)0xfff00000 = 0x00;
 374        printk(BIOS_DEBUG, "Testing:\n");
 375        reg8 |= (1 << 0);                       /* set BIOSWE */
 376        pci_write_config8(dev, 0xdc, reg8);
 377
 378        reg8 = pci_read_config8(dev, 0xdc);     /* BIOS_CNTL */
 379        printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
 380                        (reg8&1)?"rw":"ro");
 381        printk(BIOS_DEBUG, "Done.\n");
 382#endif
 383}
 384#endif
 385
 386#define SPIBASE 0x3020
 387static void i82801gx_spi_init(void)
 388{
 389        u16 spicontrol;
 390
 391        spicontrol = RCBA16(SPIBASE + 2);
 392        spicontrol &= ~(1 << 0); // SPI Access Request
 393        RCBA16(SPIBASE + 2) = spicontrol;
 394}
 395
 396static void i82801gx_fixups(struct device *dev)
 397{
 398        /* This needs to happen after PCI enumeration */
 399        RCBA32(0x1d40) |= 1;
 400
 401        /* USB Transient Disconnect Detect:
 402         * Prevent a SE0 condition on the USB ports from being
 403         * interpreted by the UHCI controller as a disconnect
 404         */
 405        pci_write_config8(dev, 0xad, 0x3);
 406}
 407
 408static void lpc_init(struct device *dev)
 409{
 410        printk(BIOS_DEBUG, "i82801gx: lpc_init\n");
 411
 412        /* Set the value for PCI command register. */
 413        pci_write_config16(dev, PCI_COMMAND, 0x000f);
 414
 415        /* IO APIC initialization. */
 416        i82801gx_enable_apic(dev);
 417
 418        i82801gx_enable_serial_irqs(dev);
 419
 420        /* Setup the PIRQ. */
 421        i82801gx_pirq_init(dev);
 422
 423        /* Setup power options. */
 424        i82801gx_power_options(dev);
 425
 426        /* Configure Cx state registers */
 427        i82801gx_configure_cstates(dev);
 428
 429        /* Set the state of the GPIO lines. */
 430        //gpio_init(dev);
 431
 432        /* Initialize the real time clock. */
 433        i82801gx_rtc_init(dev);
 434
 435        /* Initialize ISA DMA. */
 436        isa_dma_init();
 437
 438        /* Initialize the High Precision Event Timers, if present. */
 439        enable_hpet();
 440
 441        /* Initialize Clock Gating */
 442        enable_clock_gating();
 443
 444        setup_i8259();
 445
 446        /* The OS should do this? */
 447        /* Interrupt 9 should be level triggered (SCI) */
 448        i8259_configure_irq_trigger(9, 1);
 449
 450#if CONFIG_HAVE_SMI_HANDLER
 451        i82801gx_lock_smm(dev);
 452#endif
 453
 454        i82801gx_spi_init();
 455
 456        i82801gx_fixups(dev);
 457}
 458
 459static void i82801gx_lpc_read_resources(device_t dev)
 460{
 461        struct resource *res;
 462
 463        /* Get the normal PCI resources of this device. */
 464        pci_dev_read_resources(dev);
 465
 466        /* Add an extra subtractive resource for both memory and I/O. */
 467        res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
 468        res->base = 0;
 469        res->size = 0x1000;
 470        res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
 471                     IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
 472
 473        res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
 474        res->base = 0xff800000;
 475        res->size = 0x00800000; /* 8 MB for flash */
 476        res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
 477                     IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
 478
 479        res = new_resource(dev, 3); /* IOAPIC */
 480        res->base = IO_APIC_ADDR;
 481        res->size = 0x00001000;
 482        res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
 483}
 484
 485static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
 486{
 487        if (!vendor || !device) {
 488                pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
 489                                pci_read_config32(dev, PCI_VENDOR_ID));
 490        } else {
 491                pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
 492                                ((device & 0xffff) << 16) | (vendor & 0xffff));
 493        }
 494}
 495
 496static struct pci_operations pci_ops = {
 497        .set_subsystem = set_subsystem,
 498};
 499
 500static struct device_operations device_ops = {
 501        .read_resources         = i82801gx_lpc_read_resources,
 502        .set_resources          = pci_dev_set_resources,
 503        .enable_resources       = pci_dev_enable_resources,
 504        .init                   = lpc_init,
 505        .scan_bus               = scan_static_bus,
 506        .enable                 = i82801gx_enable,
 507        .ops_pci                = &pci_ops,
 508};
 509
 510/* 82801GH (ICH7 DH) */
 511static const struct pci_driver ich7_dh_lpc __pci_driver = {
 512        .ops    = &device_ops,
 513        .vendor = PCI_VENDOR_ID_INTEL,
 514        .device = 0x27b0,
 515};
 516
 517/* 82801GB/GR (ICH7/ICH7R) */
 518static const struct pci_driver ich7_ich7r_lpc __pci_driver = {
 519        .ops    = &device_ops,
 520        .vendor = PCI_VENDOR_ID_INTEL,
 521        .device = 0x27b8,
 522};
 523
 524/* 82801GBM/GU (ICH7-M/ICH7-U) */
 525static const struct pci_driver ich7m_ich7u_lpc __pci_driver = {
 526        .ops    = &device_ops,
 527        .vendor = PCI_VENDOR_ID_INTEL,
 528        .device = 0x27b9,
 529};
 530
 531/* 82801GHM (ICH7-M DH) */
 532static const struct pci_driver ich7m_dh_lpc __pci_driver = {
 533        .ops    = &device_ops,
 534        .vendor = PCI_VENDOR_ID_INTEL,
 535        .device = 0x27bd,
 536};
 537
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.