This patch contains some significant updates to the i82801gx component and will
authorStefan Reinauer <stepan@coresystems.de>
Wed, 11 Mar 2009 14:54:18 +0000 (14:54 +0000)
committerStefan Reinauer <stepan@openbios.org>
Wed, 11 Mar 2009 14:54:18 +0000 (14:54 +0000)
be required for a series of later patches. Roughly it contains:

* fixed SMBus driver (was not compiled in before)
* fixed S-ATA/P-ATA combination
* Added warnings to drivers being called with a NULL dev->chip_info
* Set subsystem ids for those boards that have none specified in Options.lb
* Fix license headers. The code was originally released under GPL v2 but
  some files sneaked in with a v2 or later header.
* some attempts to fix azalia/Intel HDA.. not working yet
* clean up and fix pci bridge handling code
* Add Config based GPI handling to LPC driver
* Add HPET enable function
* Enable clock gating where appropriate
* first attempt at USB debug console support (not working yet)
* Add required options to kontron board
* many other minor changes

Signed-off-by: Stefan Reinauer <stepan@coresystems.de>
Acked-by: Myles Watson <mylesgw@gmail.com>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3991 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1

24 files changed:
src/mainboard/kontron/986lcd-m/Config.lb
src/mainboard/kontron/986lcd-m/Options.lb
src/southbridge/intel/i82801gx/Config.lb
src/southbridge/intel/i82801gx/IOMAP [deleted file]
src/southbridge/intel/i82801gx/chip.h
src/southbridge/intel/i82801gx/cmos_failover.c
src/southbridge/intel/i82801gx/i82801gx.c
src/southbridge/intel/i82801gx/i82801gx.h
src/southbridge/intel/i82801gx/i82801gx_ac97.c
src/southbridge/intel/i82801gx/i82801gx_azalia.c
src/southbridge/intel/i82801gx/i82801gx_early_smbus.c
src/southbridge/intel/i82801gx/i82801gx_ide.c
src/southbridge/intel/i82801gx/i82801gx_lpc.c
src/southbridge/intel/i82801gx/i82801gx_nic.c
src/southbridge/intel/i82801gx/i82801gx_pci.c
src/southbridge/intel/i82801gx/i82801gx_pcie.c
src/southbridge/intel/i82801gx/i82801gx_reset.c
src/southbridge/intel/i82801gx/i82801gx_sata.c
src/southbridge/intel/i82801gx/i82801gx_smbus.c
src/southbridge/intel/i82801gx/i82801gx_smbus.h
src/southbridge/intel/i82801gx/i82801gx_usb.c
src/southbridge/intel/i82801gx/i82801gx_usb_debug.c [new file with mode: 0644]
src/southbridge/intel/i82801gx/i82801gx_usb_ehci.c
src/southbridge/intel/i82801gx/i82801gx_watchdog.c

index 3e378273c2e5cecc89e63231fc161c32f3baa3a3..e5d110c130b1672f2048503758a852088df87194 100644 (file)
@@ -190,12 +190,18 @@ chip northbridge/intel/i945
                 chip southbridge/intel/i82801gx
                        register "pirqa_routing" = "0x05"
                        register "pirqb_routing" = "0x07"
-                       register "pirqc_routing" = "0x06"
+                       register "pirqc_routing" = "0x05"
                        register "pirqd_routing" = "0x07"
                        register "pirqe_routing" = "0x80"
                        register "pirqf_routing" = "0x80"
                        register "pirqg_routing" = "0x80"
-                       register "pirqh_routing" = "0x05"
+                       register "pirqh_routing" = "0x06"
+
+                       # GPI routing
+                       #  0 No effect (default)
+                       #  1 SMI# (if corresponding ALT_GPI_SMI_EN bit is also set)
+                       #  2 SCI (if corresponding GPIO_EN bit is also set)
+                       register "gpi13_routing" = "1"
 
                         register "ide_legacy_combined" = "0x1"
                         register "ide_enable_primary" = "0x1"
index 40a8a796fb76bf1a19ce7f95d5f7b209f1ae931f..d7749491009ff596625c061dcfa38b87375e07f4 100644 (file)
@@ -69,6 +69,9 @@ uses XIP_ROM_SIZE
 uses HAVE_HARD_RESET
 uses HAVE_SMI_HANDLER
 uses CONFIG_PCIE_CONFIGSPACE_HOLE
+uses MMCONF_SUPPORT
+uses MMCONF_BASE_ADDRESS
+uses CONFIG_GFXUMA
 #
 uses MAINBOARD
 uses MAINBOARD_PART_NUMBER
@@ -86,7 +89,9 @@ uses TTYS0_LCS
 uses DEFAULT_CONSOLE_LOGLEVEL
 uses MAXIMUM_CONSOLE_LOGLEVEL
 uses CONFIG_CONSOLE_VGA
+uses CONFIG_VGA_ROM_RUN
 uses CONFIG_PCI_ROM_RUN
+uses DEBUG
 # Toolchain
 uses CC
 uses HOSTCC
@@ -145,6 +150,13 @@ default HAVE_SMI_HANDLER=1
 ##
 
 default CONFIG_PCIE_CONFIGSPACE_HOLE=1
+default MMCONF_SUPPORT=1
+default MMCONF_BASE_ADDRESS=0xf0000000
+
+##
+## UMA
+##
+default CONFIG_GFXUMA=1
 
 ##
 ## Build code to export a programmable irq routing table
@@ -163,7 +175,7 @@ default HAVE_MP_TABLE=1
 ##
 default HAVE_ACPI_TABLES=1
 default HAVE_MAINBOARD_RESOURCES=1
-default HAVE_HIGH_TABLES=0
+default HAVE_HIGH_TABLES=1
 
 ##
 ## Build code to export a CMOS option table
@@ -179,7 +191,12 @@ default LB_CKS_LOC=123
 
 #VGA Console
 default CONFIG_CONSOLE_VGA=1
-default CONFIG_PCI_ROM_RUN=1
+# There are some network option roms that don't work with
+# coreboot's x86emu. Thus, we only execute the VGA option rom
+# for now:
+default CONFIG_VGA_ROM_RUN=1
+default CONFIG_PCI_ROM_RUN=0
+default DEBUG=0
 
 ##
 ## Build code for SMP support
index 6e5cba2338cd622f7d5348e8f9d9d41df28c06e7..53186ed293c1778ce738815ee32e4af6fa5c8aef 100644 (file)
@@ -5,8 +5,7 @@
 ##
 ## This program is free software; you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 2 of the License, or
-## (at your option) any later version.
+## the Free Software Foundation; version 2 of the License.
 ##
 ## This program is distributed in the hope that it will be useful,
 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -30,6 +29,7 @@ driver i82801gx_nic.o
 driver i82801gx_pci.o
 driver i82801gx_pcie.o
 driver i82801gx_sata.o
+driver i82801gx_smbus.o
 driver i82801gx_usb.o
 driver i82801gx_usb_ehci.o
 
diff --git a/src/southbridge/intel/i82801gx/IOMAP b/src/southbridge/intel/i82801gx/IOMAP
deleted file mode 100644 (file)
index 6c20f66..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-Non-automatic IO-Addresses
---------------------------
-
-The following dynamic IO BARs are used on the ICH7 for the Kontron Default BIOS:
-
-GPIOBASE       0x480 (64 bytes)
-PMBASE         0x800 (128 bytes)
-SMBASE         0x400 (32 bytes)
-HWMON          0xa00 (??)
-
-The following dynamic IO BARs are used on the ICH7 for the Getac Default BIOS:
-
-GPIOBASE       0x1180 (64 bytes)
-PMBASE         0x1000 (128 bytes)
-SMBASE         0x18e0 (32 bytes)
-
-The Getac also needs an IO Trapped area of 0x0C bytes (defaults to 0x800)
-
-coreboot:
-GPIOBASE       0x480 (64 bytes)
-PMBASE         0x500 (128 bytes)
-SMBASE         0x400 (32 bytes)
-HWMON          0xa00 (??)
-
-
-
-NOTE: Coreboot sets the SMBASE to 0xf00 in auto.c. But it gets relocated 
-in stage2 because its a "normal BAR" (to 0x2080 in one case here). 
-
-This is not unhealthy but at least confusing. We should provide a method to
-nail down certain resources for stage2. 
-
-For a list of static I/O space allocation look at 6.3.1 of the ICH7 Family
-Datasheet.
-
index 45c011a1c0c8049f470893280207e1dd6f988367..7fca7ca9f3527af819d734e2cfb1feb2a49d98be 100644 (file)
@@ -3,10 +3,10 @@
  *
  * Copyright (C) 2008-2009 coresystems GmbH
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 #define SOUTHBRIDGE_INTEL_I82801GX_CHIP_H
 
 struct southbridge_intel_i82801gx_config {
-       /* LPC configuration */
+       /**
+        * Interrupt Routing configuration
+        * If bit7 is 1, the interrupt is disabled.
+        */
        uint8_t pirqa_routing;
        uint8_t pirqb_routing;
        uint8_t pirqc_routing;
@@ -32,6 +35,32 @@ struct southbridge_intel_i82801gx_config {
        uint8_t pirqg_routing;
        uint8_t pirqh_routing;
 
+       /**
+        * GPI Routing configuration
+        *
+        * Only the lower two bits have a meaning:
+        * 00: No effect
+        * 01: SMI# (if corresponding ALT_GPI_SMI_EN bit is also set)
+        * 10: SCI (if corresponding GPIO_EN bit is also set)
+        * 11: reserved
+        */
+       uint8_t gpi0_routing;
+       uint8_t gpi1_routing;
+       uint8_t gpi2_routing;
+       uint8_t gpi3_routing;
+       uint8_t gpi4_routing;
+       uint8_t gpi5_routing;
+       uint8_t gpi6_routing;
+       uint8_t gpi7_routing;
+       uint8_t gpi8_routing;
+       uint8_t gpi9_routing;
+       uint8_t gpi10_routing;
+       uint8_t gpi11_routing;
+       uint8_t gpi12_routing;
+       uint8_t gpi13_routing;
+       uint8_t gpi14_routing;
+       uint8_t gpi15_routing;
+
        /* IDE configuration */
        uint32_t ide_legacy_combined;
        uint32_t ide_enable_primary;
@@ -39,7 +68,7 @@ struct southbridge_intel_i82801gx_config {
        uint32_t sata_ahci;
 
        /* Azalia Configuration */
-       unsigned long hda_viddid;
+       uint32_t hda_viddid;
 };
 
 extern struct chip_operations southbridge_intel_i82801gx_ops;
index ec5ec6a34b142090a5f370f27defd0cdf860321b..0765404ceba900559d71742e082142c08b2fe83e 100644 (file)
@@ -1,10 +1,12 @@
 /*
  * This file is part of the coreboot project.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * (C) 2008-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
index 9d504fbe0b118b5a51fc0c157f85346567d6277f..fb8e952eed3f76014580b354e42c0de0fbd55c09 100644 (file)
@@ -1,12 +1,12 @@
 /*
  * This file is part of the coreboot project.
  *
- * Copyright (C) 2008 coresystems GmbH
+ * Copyright (C) 2008-2009 coresystems GmbH
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 void i82801gx_enable(device_t dev)
 {
+       u32 reg32;
+
+       /* Enable SERR */
+       reg32 = pci_read_config32(dev, PCI_COMMAND);
+       reg32 |= PCI_COMMAND_SERR;
+       pci_write_config32(dev, PCI_COMMAND, reg32);
 }
 
 struct chip_operations southbridge_intel_i82801gx_ops = {
index 9ea0f1fee9dd1e0c522fd9f03e943008fcf29e67..a1771230fc8022eaf60a8d61853e700bcf069656 100644 (file)
@@ -1,12 +1,12 @@
 /*
  * This file is part of the coreboot project.
  *
- * Copyright (C) 2008 coresystems GmbH
+ * Copyright (C) 2008-2009 coresystems GmbH
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
index 4253284452ad5a83739a2f42181b9f48d0f3e0fb..e78b1eb28218290a8ff42a0c2df36e0e7ffdbe79 100644 (file)
@@ -3,10 +3,10 @@
  *
  * Copyright (C) 2008-2009 coresystems GmbH
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -119,7 +119,6 @@ static void program_sigid(struct device *dev, u32 id)
 
 static void ac97_audio_init(struct device *dev)
 {
-       u8 reg8;
        u16 reg16;
        u32 reg32;
        int i;
index 067d0f3980db4280df0a7086804ffa160c79e5c6..fba46bae7ce706f90f656be786f5f32fbadd1c58 100644 (file)
 #define   HDA_ICII_BUSY (1 << 0)
 #define   HDA_ICII_VALID  (1 << 1)
 
+typedef struct southbridge_intel_i82801gx_config config_t;
+
 static int set_bits(u8 * port, u32 mask, u32 val)
 {
-       u32 dword;
+       u32 reg32;
        int count;
 
+       /* Write (val & mask) to port */
        val &= mask;
-       dword = readl(port);
-       dword &= ~mask;
-       dword |= val;
-       writel(dword, port);
-
+       reg32 = readl(port);
+       reg32 &= ~mask;
+       reg32 |= val;
+       writel(reg32, port);
+
+       /* Wait for readback of register to 
+        * match what was just written to it 
+        */
        count = 50;
        do {
-               dword = readl(port);
-               dword &= mask;
-               udelay(100);
-       } while ((dword != val) && --count);
+               /* Wait 1ms based on BKDG wait time */
+               mdelay(1);
+               reg32 = readl(port);
+               reg32 &= mask;
+       } while ((reg32 != val) && --count);
 
+       /* Timeout occured */
        if (!count)
                return -1;
-
-       udelay(540);
        return 0;
 }
 
 static int codec_detect(u8 * base)
 {
-       u32 dword;
-
-       /* 1 */
-       set_bits(base + 0x08, 1, 1);
-
-       /* 2 */
-       dword = readl(base + 0x0e);
-       dword |= 7;
-       writel(dword, base + 0x0e);
-
-       /* 3 */
+       u32 reg32;
+
+       /* Set Bit0 to 0 to enter reset state (BAR + 0x8)[0] */
+       if (set_bits(base + 0x08, 1, 0) == -1) 
+               goto no_codec;
+
+       /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
+       if (set_bits(base + 0x08, 1, 1) == -1) 
+               goto no_codec;
+
+       /* Read in Codec location (BAR + 0xe)[2..0]*/
+       reg32 = readl(base + 0xe);
+       reg32 &= 0x0f;
+       if (!reg32)
+               goto no_codec;
+               
+       return reg32;
+
+no_codec:
+       /* Codec Not found */
+       /* Put HDA back in reset (BAR + 0x8) [0] */
        set_bits(base + 0x08, 1, 0);
-
-       /* 4 */
-       set_bits(base + 0x08, 1, 1);
-
-       /* 5 */
-       dword = readl(base + 0xe);
-       dword &= 7;
-
-       /* 6 */
-       if (!dword) {
-               set_bits(base + 0x08, 1, 0);
-               printk_debug("No codec!\n");
-               return 0;
-       }
-       return dword;
-
+       printk_debug("Azalia: No codec!\n");
+       return 0;
 }
 
 static u32 cim_verb_data[] = {
@@ -156,19 +158,24 @@ static u32 cim_verb_data[] = {
        0x01F71F41,
 };
 
-static unsigned find_verb(u32 viddid, u32 ** verb)
+static unsigned find_verb(struct device *dev, u32 viddid, u32 ** verb)
 {
-       device_t azalia_dev = dev_find_slot(0, PCI_DEVFN(0x14, 2));
-       struct southbridge_intel_i82801gx_config *cfg =
-           (struct southbridge_intel_i82801gx_config *)azalia_dev->chip_info;
-       printk_debug("Dev=%s\n", dev_path(azalia_dev));
-       printk_debug("Default viddid=%x\n", cfg->hda_viddid);
-       printk_debug("Reading viddid=%x\n", viddid);
-       if (!cfg)
+       config_t *config = dev->chip_info;
+       
+       if (config == NULL) {
+               printk_err("\ni82801gx_azalia: Not mentioned in mainboard's Config.lb!\n");
                return 0;
-       if (viddid != cfg->hda_viddid)
+       }
+
+       printk_debug("Azalia: dev=%s\n", dev_path(dev));
+       printk_debug("Azalia: Default viddid=%x\n", (u32)config->hda_viddid);
+       printk_debug("Azalia: Reading viddid=%x\n", viddid);
+
+       if (viddid != config->hda_viddid)
                return 0;
+
        *verb = (u32 *) cim_verb_data;
+
        return sizeof(cim_verb_data) / sizeof(u32);
 }
 
@@ -185,8 +192,8 @@ static int wait_for_ready(u8 *base)
        int timeout = 50;
 
        while(timeout--) {
-               u32 dword=readl(base +  HDA_ICII_REG);
-               if (!(dword & HDA_ICII_BUSY))
+               u32 reg32 = readl(base +  HDA_ICII_REG);
+               if (!(reg32 & HDA_ICII_BUSY))
                        return 0;
                udelay(1);
        }
@@ -207,8 +214,8 @@ static int wait_for_valid(u8 *base)
 
        int timeout = 50;
        while(timeout--) {
-               u32 dword = readl(base + HDA_ICII_REG);
-               if ((dword & (HDA_ICII_VALID | HDA_ICII_BUSY)) ==
+               u32 reg32 = readl(base + HDA_ICII_REG);
+               if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) ==
                        HDA_ICII_VALID)
                        return 0;
                udelay(1);
@@ -217,9 +224,9 @@ static int wait_for_valid(u8 *base)
        return 1;
 }
 
-static void codec_init(u8 * base, int addr)
+static void codec_init(struct device *dev, u8 * base, int addr)
 {
-       u32 dword;
+       u32 reg32;
        u32 *verb;
        u32 verb_size;
        int i;
@@ -228,24 +235,24 @@ static void codec_init(u8 * base, int addr)
        if (wait_for_ready(base) == -1)
                return;
 
-       dword = (addr << 28) | 0x000f0000;
-       writel(dword, base + 0x60);
+       reg32 = (addr << 28) | 0x000f0000;
+       writel(reg32, base + 0x60);
 
        if (wait_for_valid(base) == -1)
                return;
 
-       dword = readl(base + 0x64);
+       reg32 = readl(base + 0x64);
 
        /* 2 */
-       printk_debug("codec viddid: %08x\n", dword);
-       verb_size = find_verb(dword, &verb);
+       printk_debug("Azalia: codec viddid: %08x\n", reg32);
+       verb_size = find_verb(dev, reg32, &verb);
 
        if (!verb_size) {
-               printk_debug("No verb!\n");
+               printk_debug("Azalia: No verb!\n");
                return;
        }
 
-       printk_debug("verb_size: %d\n", verb_size);
+       printk_debug("Azalia: verb_size: %d\n", verb_size);
        /* 3 */
        for (i = 0; i < verb_size; i++) {
                if (wait_for_ready(base) == -1)
@@ -256,15 +263,15 @@ static void codec_init(u8 * base, int addr)
                if (wait_for_valid(base) == -1)
                        return;
        }
-       printk_debug("verb loaded!\n");
+       printk_debug("Azalia: verb loaded.\n");
 }
 
-static void codecs_init(u8 * base, u32 codec_mask)
+static void codecs_init(struct device *dev, u8 * base, u32 codec_mask)
 {
        int i;
        for (i = 2; i >= 0; i--) {
                if (codec_mask & (1 << i))
-                       codec_init(base, i);
+                       codec_init(dev, base, i);
        }
 }
 
@@ -273,7 +280,71 @@ static void azalia_init(struct device *dev)
        u8 *base;
        struct resource *res;
        u32 codec_mask;
-
+       u8 reg8;
+       u32 reg32;
+
+#if MMCONF_SUPPORT
+       // ESD
+       reg32 = pci_mmio_read_config32(dev, 0x134);
+       reg32 &= 0xff00ffff;
+       reg32 |= (2 << 16);
+       pci_mmio_write_config32(dev, 0x134, reg32);
+
+       // Link1 description
+       reg32 = pci_mmio_read_config32(dev, 0x140);
+       reg32 &= 0xff00ffff;
+       reg32 |= (2 << 16);
+       pci_mmio_write_config32(dev, 0x140, reg32);
+
+       // Port VC0 Resource Control Register
+       reg32 = pci_mmio_read_config32(dev, 0x114);
+       reg32 &= 0xffffff00;
+       reg32 |= 1;
+       pci_mmio_write_config32(dev, 0x114, reg32);
+
+       // VCi traffic class
+       reg8 = pci_mmio_read_config8(dev, 0x44);
+       reg8 |= (7 << 0); // TC7
+       pci_mmio_write_config8(dev, 0x44, reg8);
+
+       // VCi Resource Control
+       reg32 = pci_mmio_read_config32(dev, 0x120);
+       reg32 |= (1 << 31); 
+       reg32 |= (1 << 24); // VCi ID
+       reg32 |= (0x80 << 0); // VCi map
+       pci_mmio_write_config32(dev, 0x120, reg32);
+#else
+#error ICH7 Azalia required MMCONF_SUPPORT
+#endif
+
+       /* Set Bus Master */
+       reg32 = pci_read_config32(dev, PCI_COMMAND);
+       pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER);
+
+       pci_write_config8(dev, 0x3c, 0x0a); // unused?
+
+       // TODO Actually check if we're AC97 or HDA instead of hardcoding this
+       // here, in Config.lb and/or auto.c.
+       reg8 = pci_read_config8(dev, 0x40);
+       reg8 |= (1 << 3); // Clear Clock Detect Bit
+       pci_write_config8(dev, 0x40, reg8);
+       reg8 &= ~(1 << 3); // Keep CLKDETCLR from clearing the bit over and over
+       pci_write_config8(dev, 0x40, reg8);
+       reg8 |= (1 << 2); // Enable clock detection
+       pci_write_config8(dev, 0x40, reg8);
+       mdelay(1);
+       reg8 = pci_read_config8(dev, 0x40);
+       printk_debug("Azalia: codec type: %s\n", (reg8 & (1 << 1))?"Azalia":"AC97");
+
+       //
+       reg8 = pci_read_config8(dev, 0x40); // Audio Control
+       reg8 |= 1; // Select Azalia mode. This needs to be controlled via Config.lb
+       pci_write_config8(dev, 0x40, reg8);
+
+       reg8 = pci_read_config8(dev, 0x4d); // Docking Status
+       reg8 &= ~(1 << 7); // Docking not supported
+       pci_write_config8(dev, 0x4d, reg8);
+#if 0
        /* Set routing pin */
        pci_write_config32(dev, 0xf8, 0x0);
        pci_write_config8(dev, 0xfc, 0xAA);
@@ -283,21 +354,39 @@ static void azalia_init(struct device *dev)
 
        /* Enable azalia, disable ac97 */
        // pm_iowrite(0x59, 0xB);
+#endif
 
        res = find_resource(dev, 0x10);
        if (!res)
                return;
 
+       // NOTE this will break as soon as the Azalia get's a bar above
+       // 4G. Is there anything we can do about it?
        base = (u8 *) ((u32)res->base);
-       printk_debug("base = %08x\n", base);
+       printk_debug("Azalia: base = %08x\n", (u32)base);
        codec_mask = codec_detect(base);
 
        if (codec_mask) {
-               printk_debug("codec_mask = %02x\n", codec_mask);
-               codecs_init(base, codec_mask);
+               printk_debug("Azalia: codec_mask = %02x\n", codec_mask);
+               codecs_init(dev, base, codec_mask);
        }
 }
 
+static void azalia_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+       if (!vendor || !device) {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               pci_read_config32(dev, PCI_VENDOR_ID));
+       } else {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
+}
+
+static struct pci_operations azalia_pci_ops = {
+       .set_subsystem    = azalia_set_subsystem,
+};
+
 static struct device_operations azalia_ops = {
        .read_resources         = pci_dev_read_resources,
        .set_resources          = pci_dev_set_resources,
@@ -305,6 +394,7 @@ static struct device_operations azalia_ops = {
        .init                   = azalia_init,
        .scan_bus               = 0,
        .enable                 = i82801gx_enable,
+       .ops_pci                = &azalia_pci_ops,
 };
 
 /* 82801GB/GR/GDH/GBM/GHM (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH) */
index 5fe1daa279750db1450f01557ea5dc4fc5d3d896..7c0d97d2c8c913dbc83bb6d9e1899beb21b522c6 100644 (file)
@@ -1,12 +1,12 @@
 /*
  * This file is part of the coreboot project.
  *
- * Copyright (C) 2008 coresystems GmbH
+ * Copyright (C) 2008-2009 coresystems GmbH
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -54,6 +54,6 @@ static void enable_smbus(void)
 
 static inline int smbus_read_byte(unsigned device, unsigned address)
 {
-       return do_smbus_read_byte(device, address);
+       return do_smbus_read_byte(SMBUS_IO_BASE, device, address);
 }
 
index 0074cc7b2af27d8f19dd936cd9baa527ac3fd137..c29e678a69cd7f039c96ecd2b321c50366993c00 100644 (file)
@@ -1,12 +1,12 @@
 /*
  * This file is part of the coreboot project.
  *
- * Copyright (C) 2008 coresystems GmbH
+ * Copyright (C) 2008-2009 coresystems GmbH
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -30,12 +30,20 @@ static void ide_init(struct device *dev)
 {
        u16 ideTimingConfig;
        u32 reg32;
+       u32 enable_primary, enable_secondary;
 
        /* Get the chip configuration */
        config_t *config = dev->chip_info;
 
-       int enable_primary = config->ide_enable_primary;
-       int enable_secondary = config->ide_enable_secondary;
+       printk_debug("i82801gx_ide: initializing... ");
+       if (config == NULL) {
+               printk_err("\ni82801gx_ide: Not mentioned in mainboard's Config.lb!\n");
+               // Trying to set somewhat save defaults instead of bailing out.
+               enable_primary = enable_secondary = 1;
+       } else {
+               enable_primary = config->ide_enable_primary;
+               enable_secondary = config->ide_enable_secondary;
+       }
 
        reg32 = pci_read_config32(dev, PCI_COMMAND);
        pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_IO | PCI_COMMAND_MASTER);
@@ -81,8 +89,25 @@ static void ide_init(struct device *dev)
        /* Set Interrupt Line */
        /* Interrupt Pin is set by D31IP.PIP */
        pci_write_config32(dev, INTR_LN, 0xff); /* Int 15 */
+
+       printk_debug("\n");
+}
+
+static void ide_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+       if (!vendor || !device) {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               pci_read_config32(dev, PCI_VENDOR_ID));
+       } else {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
 }
 
+static struct pci_operations ide_pci_ops = {
+       .set_subsystem    = ide_set_subsystem,
+};
+
 static struct device_operations ide_ops = {
        .read_resources         = pci_dev_read_resources,
        .set_resources          = pci_dev_set_resources,
@@ -90,6 +115,7 @@ static struct device_operations ide_ops = {
        .init                   = ide_init,
        .scan_bus               = 0,
        .enable                 = i82801gx_enable,
+       .ops_pci                = &ide_pci_ops,
 };
 
 /* 82801GB/GR/GDH/GBM/GHM/GU (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH/ICH7-U) */
index 78c4efe3b040d731daaa3c7ba556e647347b5bae..241d610bdda7e472125f02d346e93b86259734ec 100644 (file)
@@ -3,10 +3,10 @@
  *
  * Copyright (C) 2008-2009 coresystems GmbH
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -151,6 +151,35 @@ static void i82801gx_pirq_init(device_t dev)
        }
 }
 
+static void i82801gx_gpi_routing(device_t dev)
+{
+       /* Get the chip configuration */
+       config_t *config = dev->chip_info;
+       u32 reg32 = 0;
+
+       /* An array would be much nicer here, or some
+        * other method of doing this.
+        */
+       reg32 |= (config->gpi0_routing & 0x03) << 0;
+       reg32 |= (config->gpi1_routing & 0x03) << 2;
+       reg32 |= (config->gpi2_routing & 0x03) << 4;
+       reg32 |= (config->gpi3_routing & 0x03) << 6;
+       reg32 |= (config->gpi4_routing & 0x03) << 8;
+       reg32 |= (config->gpi5_routing & 0x03) << 10;
+       reg32 |= (config->gpi6_routing & 0x03) << 12;
+       reg32 |= (config->gpi7_routing & 0x03) << 14;
+       reg32 |= (config->gpi8_routing & 0x03) << 16;
+       reg32 |= (config->gpi9_routing & 0x03) << 18;
+       reg32 |= (config->gpi10_routing & 0x03) << 20;
+       reg32 |= (config->gpi11_routing & 0x03) << 22;
+       reg32 |= (config->gpi12_routing & 0x03) << 24;
+       reg32 |= (config->gpi13_routing & 0x03) << 26;
+       reg32 |= (config->gpi14_routing & 0x03) << 28;
+       reg32 |= (config->gpi15_routing & 0x03) << 30;
+
+       pci_write_config32(dev, 0xb8, reg32);
+}
+
 static void i82801gx_power_options(device_t dev)
 {
        u8 reg8;
@@ -172,6 +201,7 @@ static void i82801gx_power_options(device_t dev)
                reg8 |= 1;
        }
        reg8 |= (3 << 4);       /* avoid #S4 assertions */
+       reg8 &= ~(1 << 3);      /* minimum asssertion is 1 to 2 RTCCLK */
 
        pci_write_config8(dev, GEN_PMCON_3, reg8);
        printk_info("Set power %s after power failure.\n", pwr_on ? "on" : "off");
@@ -198,19 +228,34 @@ static void i82801gx_power_options(device_t dev)
 
        // Enable CPU_SLP# and Intel Speedstep, set SMI# rate down
        reg16 = pci_read_config16(dev, GEN_PMCON_1);
-       reg16 &= ~3;
-       reg16 |= (1 << 3) | (1 << 5) | (1 << 10);
+       reg16 &= ~((3 << 0) | (1 << 10));
+       reg16 |= (1 << 3) | (1 << 5);
+       reg16 |= (1 << 2); // CLKRUN_EN
        pci_write_config16(dev, GEN_PMCON_1, reg16);
 
-       // Set GPIO13 to SCI (?)
-       // This might be board specific
-       pci_write_config32(dev, 0xb8, 0x08000000);
+       // Set the board's GPI routing.
+       i82801gx_gpi_routing(dev);
 }
 
-void i82801gx_rtc_init(struct device *dev)
+static void i82801gx_configure_cstates(device_t dev)
+{
+       u8 reg8;
+       
+       reg8 = pci_read_config8(dev, 0xa9); // Cx state configuration
+       reg8 |= (1 << 4) | (1 << 3) | (1 << 2); // Enable Popup & Popdown
+       pci_write_config8(dev, 0xa9, reg8);
+
+       // Set Deeper Sleep configuration to recommended values
+       reg8 = pci_read_config8(dev, 0xaa);
+       reg8 &= 0xf0;
+       reg8 |= (2 << 2);       // Deeper Sleep to Stop CPU: 34-40us
+       reg8 |= (2 << 0);       // Deeper Sleep to Sleep: 15us
+       pci_write_config8(dev, 0xaa, reg8);
+}
+
+static void i82801gx_rtc_init(struct device *dev)
 {
        u8 reg8;
-       u32 reg32;
        int rtc_failed;
 
        reg8 = pci_read_config8(dev, GEN_PMCON_3);
@@ -224,17 +269,40 @@ void i82801gx_rtc_init(struct device *dev)
        rtc_init(rtc_failed);
 }
 
-static void enable_hpet(struct device *dev)
+static void enable_hpet(void)
 {
-       /* TODO */
+       u32 reg32;
+       
+       /* Leave HPET at default address, but enable it */
+       reg32 = RCBA32(0x3404);
+       reg32 |= (1 << 7); // HPET Address Enable
+       RCBA32(0x3404) = reg32;
 }
 
+static void enable_clock_gating(void)
+{
+       u32 reg32;
+       
+       /* Enable Clock Gating for most devices */
+       reg32 = RCBA32(0x341c);
+       reg32 |= (1 << 31);     // LPC clock gating
+       reg32 |= (1 << 30);     // PATA clock gating
+       // SATA clock gating
+       reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
+       reg32 |= (1 << 23);     // AC97 clock gating
+       reg32 |= (1 << 20) | (1 << 19); // USB EHCI clock gating
+       reg32 |= (1 << 3) | (1 << 1);   // DMI clock gating
+       reg32 |= (1 << 2);      // PCIe clock gating;
+       RCBA32(0x341c) = reg32;
+}
 
 #if HAVE_SMI_HANDLER
 static void i82801gx_lock_smm(struct device *dev)
 {
        void smm_lock(void);
+#if TEST_SMM_FLASH_LOCKDOWN
        u8 reg8;
+#endif
 
 #if ENABLE_ACPI_MODE_IN_COREBOOT
        printk_debug("Enabling ACPI via APMC:\n");
@@ -279,6 +347,22 @@ static void i82801gx_lock_smm(struct device *dev)
 }
 #endif
 
+#define SPIBASE 0x3020
+static void i82801gx_spi_init(void)
+{
+       u16 spicontrol;
+
+       spicontrol = RCBA16(SPIBASE + 2);
+       spicontrol &= ~(1 << 0); // SPI Access Request
+       RCBA16(SPIBASE + 2) = spicontrol;
+}
+
+static void i82801gx_fixups(void)
+{
+       /* This needs to happen after PCI enumeration */
+       RCBA32(0x1d40) |= 1;
+}
+
 static void lpc_init(struct device *dev)
 {
        printk_debug("i82801gx: lpc_init\n");
@@ -297,6 +381,9 @@ static void lpc_init(struct device *dev)
        /* Setup power options. */
        i82801gx_power_options(dev);
 
+       /* Configure Cx state registers */
+       i82801gx_configure_cstates(dev);
+
        /* Set the state of the GPIO lines. */
        //gpio_init(dev);
 
@@ -307,13 +394,20 @@ static void lpc_init(struct device *dev)
        isa_dma_init();
 
        /* Initialize the High Precision Event Timers, if present. */
-       enable_hpet(dev);
+       enable_hpet();
+
+       /* Initialize Clock Gating */
+       enable_clock_gating();
 
        setup_i8259();
 
 #if HAVE_SMI_HANDLER
        i82801gx_lock_smm(dev);
 #endif
+
+       i82801gx_spi_init();
+
+       i82801gx_fixups();
 }
 
 static void i82801gx_lpc_read_resources(device_t dev)
@@ -341,9 +435,13 @@ static void i82801gx_lpc_enable_resources(device_t dev)
 
 static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
 {
-       printk_debug("Setting LPC bridge subsystem ID\n");
-       pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
-                       pci_read_config32(dev, 0));
+       if (!vendor || !device) {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               pci_read_config32(dev, PCI_VENDOR_ID));
+       } else {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
 }
 
 static struct pci_operations pci_ops = {
index 9790dac85f8f5b16e47d3e32a85f830e0818ad51..0405294cb7dc32c49446eda2efedf1dc8d1557d9 100644 (file)
@@ -1,12 +1,12 @@
 /*
  * This file is part of the coreboot project.
  *
- * Copyright (C) 2008 coresystems GmbH
+ * Copyright (C) 2008-2009 coresystems GmbH
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
index b2e4ce55611104ff3ee0bc321c49169f6c11e8d7..2bf228b135e3442eccacc652784754f86bad255a 100644 (file)
@@ -3,10 +3,10 @@
  *
  * Copyright (C) 2008-2009 coresystems GmbH
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 static void pci_init(struct device *dev)
 {
        u16 reg16;
+       u8 reg8;
 
-#if 0
-       /* Commented out for now because it will break on some machines. */
-       /* Set latency timer to 32. */
-       pci_write_config16(dev, 0x1b, 0x20);
-#endif
+       /* Enable Bus Master */
+       reg16 = pci_read_config16(dev, PCI_COMMAND);
+       reg16 |= PCI_COMMAND_MASTER;
+       pci_write_config16(dev, PCI_COMMAND, reg16);
+
+       /* This device has no interrupt */
+       pci_write_config8(dev, 0x3c, 0xff);
 
-       /* disable parity error response */
+       /* disable parity error response and SERR */
        reg16 = pci_read_config16(dev, 0x3e);
        reg16 &= ~(1 << 0);
+       reg16 &= ~(1 << 1);
        pci_write_config16(dev, 0x3e, reg16);
 
+       /* Master Latency Count must be set to 0x04! */
+       reg8 = pci_read_config8(dev, 0x1b);
+       reg8 &= 0x07;
+       reg8 |= (0x04 << 3);
+       pci_write_config8(dev, 0x1b, reg8);
+
+       /* Will this improve throughput of bus masters? */
+       pci_write_config8(dev, PCI_MIN_GNT, 0x06);
+
        /* Clear errors in status registers */
        reg16 = pci_read_config16(dev, 0x06);
-       reg16 |= 0xf900;
+       //reg16 |= 0xf900;
        pci_write_config16(dev, 0x06, reg16);
 
        reg16 = pci_read_config16(dev, 0x1e);
-       reg16 |= 0xf900;
+       // reg16 |= 0xf900;
        pci_write_config16(dev, 0x1e, reg16);
-
-       /* Will this improve throughput of bus masters? */
-       pci_write_config8(dev, PCI_MIN_GNT, 0x06);
 }
 
+#undef PCI_BRIDGE_UPDATE_COMMAND
 static void ich_pci_dev_enable_resources(struct device *dev)
 {
        const struct pci_operations *ops;
@@ -68,15 +79,17 @@ static void ich_pci_dev_enable_resources(struct device *dev)
                        MAINBOARD_PCI_SUBSYSTEM_DEVICE_ID);
        }
 
-#if 0
+       command = pci_read_config16(dev, PCI_COMMAND);
+       command |= dev->command;
+#if PCI_BRIDGE_UPDATE_COMMAND
        /* If we write to PCI_COMMAND, on some systems 
         * this will cause the ROM and APICs not being visible
         * anymore.
         */
-       command = pci_read_config16(dev, PCI_COMMAND);
-       command |= dev->command;
        printk_debug("%s cmd <- %02x\n", dev_path(dev), command);
        pci_write_config16(dev, PCI_COMMAND, command);
+#else
+       printk_debug("%s cmd <- %02x (NOT WRITTEN!)\n", dev_path(dev), command);
 #endif
 }
 
@@ -102,16 +115,14 @@ static void ich_pci_bus_enable_resources(struct device *dev)
 
 static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
 {
-#if 0
-       /* Currently disabled because it causes a "BAR 9" memory resource
-        * conflict:
-        */
-       u32 pci_id;
-
-       printk_debug("Setting PCI bridge subsystem ID\n");
-       pci_id = pci_read_config32(dev, 0);
-       pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, pci_id );
-#endif
+       /* NOTE: This is not the default position! */
+       if (!vendor || !device) {
+               pci_write_config32(dev, 0x54,
+                               pci_read_config32(dev, PCI_VENDOR_ID));
+       } else {
+               pci_write_config32(dev, 0x54,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
 }
 
 static struct pci_operations pci_ops = {
index 882c3e4a78165a6cc292fdb9f4cf87fc07fead92..6965b309725d19babe88090d09977ec0527023a0 100644 (file)
@@ -3,10 +3,10 @@
  *
  * Copyright (C) 2008-2009 coresystems GmbH
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -29,29 +29,53 @@ static void pci_init(struct device *dev)
        u32 reg32;
 
        printk_debug("Initializing ICH7 PCIe bridge.\n");
-#if 0
-       // When the latency of the PCIe(!) bridge is set to 0x20
-       // all devices on the secondary bus of the PCI(!) bridge
-       // suddenly vanish. If you know why, please explain here.
+       
+       /* Enable Bus Master */
+       reg32 = pci_read_config32(dev, PCI_COMMAND);
+       reg32 |= PCI_COMMAND_MASTER;
+       pci_write_config32(dev, PCI_COMMAND, reg32);
 
-       /* Set latency timer to 32. */
-       pci_write_config16(dev, 0x1b, 0x20);
-#endif
+       /* Set Cache Line Size to 0x10 */
+       // This has no effect but the OS might expect it
+       pci_write_config8(dev, 0x0c, 0x10);
 
-       /* disable parity error response */
        reg16 = pci_read_config16(dev, 0x3e);
-       reg16 &= ~(1 << 0);
+       reg16 &= ~(1 << 0); /* disable parity error response */
+       // reg16 &= ~(1 << 1); /* disable SERR */
+       reg16 |= (1 << 2); /* ISA enable */
        pci_write_config16(dev, 0x3e, reg16);
 
-       /* Clear errors in status registers */
-       reg16 = pci_read_config16(dev, 0x06);
-       reg16 |= 0xf900;
-       pci_write_config16(dev, 0x06, reg16);
-
-       reg16 = pci_read_config16(dev, 0x1e);
-       reg16 |= 0xf900;
-       pci_write_config16(dev, 0x1e, reg16);
+       /* Enable IO xAPIC on this PCIe port */
+       reg32 = pci_read_config32(dev, 0xd8);
+       reg32 |= (1 << 7);
+       pci_write_config32(dev, 0xd8, reg32);
+
+       /* Enable Backbone Clock Gating */
+       reg32 = pci_read_config32(dev, 0xe1);
+       reg32 |= (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0);
+       pci_write_config32(dev, 0xe1, reg32);
+
+#if MMCONF_SUPPORT
+       /* Set VC0 transaction class */
+       reg32 = pci_mmio_read_config32(dev, 0x114);
+       reg32 &= 0xffffff00;
+       reg32 |= 1;
+       pci_mmio_write_config32(dev, 0x114, reg32);
+
+       /* Mask completion timeouts */
+       reg32 = pci_mmio_read_config32(dev, 0x148);
+       reg32 |= (1 << 14);
+       pci_mmio_write_config32(dev, 0x148, reg32);
+#else
+#error "MMIO needed for ICH7 PCIe"
+#endif
+       /* Enable common clock configuration */
+       // Are there cases when we don't want that?
+       reg16 = pci_read_config16(dev, 0x50);
+       reg16 |= (1 << 6);
+       pci_write_config16(dev, 0x50, reg16);
 
+#if EVEN_MORE_DEBUG
        reg32 = pci_read_config32(dev, 0x20);
        printk_spew("    MBL    = 0x%08x\n", reg32);
        reg32 = pci_read_config32(dev, 0x24);
@@ -60,19 +84,32 @@ static void pci_init(struct device *dev)
        printk_spew("    PMBU32 = 0x%08x\n", reg32);
        reg32 = pci_read_config32(dev, 0x2c);
        printk_spew("    PMLU32 = 0x%08x\n", reg32);
+#endif
+
+       /* Clear errors in status registers */
+       reg16 = pci_read_config16(dev, 0x06);
+       //reg16 |= 0xf900;
+       pci_write_config16(dev, 0x06, reg16);
+
+       reg16 = pci_read_config16(dev, 0x1e);
+       //reg16 |= 0xf900;
+       pci_write_config16(dev, 0x1e, reg16);
 }
 
-static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
+static void pcie_set_subsystem(device_t dev, unsigned vendor, unsigned device)
 {
-       u32 pci_id;
-
-       printk_debug("Setting PCIe bridge subsystem ID.\n");
-       pci_id = pci_read_config32(dev, 0);
-       pci_write_config32(dev, 0x94, pci_id );
+       /* NOTE: This is not the default position! */
+       if (!vendor || !device) {
+               pci_write_config32(dev, 0x94,
+                               pci_read_config32(dev, 0));
+       } else {
+               pci_write_config32(dev, 0x94,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
 }
 
 static struct pci_operations pci_ops = {
-       .set_subsystem = set_subsystem,
+       .set_subsystem = pcie_set_subsystem,
 };
 
 static struct device_operations device_ops = {
index 5ebb75607fa91760ad6f2506f534270f7e0b7dc0..1facb0810590db46e33db701587e884d1a6f551d 100644 (file)
@@ -1,12 +1,12 @@
 /*
  * This file is part of the coreboot project.
  *
- * Copyright (C) 2008 coresystems GmbH
+ * Copyright (C) 2008-2009 coresystems GmbH
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
index 7f17b73b0ac4070f1fd77c7c88611f17af2206b6..0f092e9204e03e26c4613f0566d994512ffeb131 100644 (file)
@@ -3,10 +3,10 @@
  *
  * Copyright (C) 2008-2009 coresystems GmbH
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -29,16 +29,29 @@ typedef struct southbridge_intel_i82801gx_config config_t;
 static void sata_init(struct device *dev)
 {
        u32 reg32;
+       u16 reg16;
        /* Get the chip configuration */
        config_t *config = dev->chip_info;
 
        printk_debug("i82801gx_sata: initializing...\n");
+
+       if (config == NULL)
+               printk_err("i82801gx_sata: error: device not in Config.lb!\n");
+
        /* SATA configuration */
 
        /* Enable BARs */
-       pci_write_config16(dev, 0x04, 0x0007);
+       pci_write_config16(dev, PCI_COMMAND, 0x0007);
 
        if (config->ide_legacy_combined) {
+               printk_debug("SATA controller in combined mode.\n");
+               /* No AHCI: clear AHCI base */
+               pci_write_config32(dev, 0x24, 0x00000000);
+               /* And without AHCI BAR no memory decoding */
+               reg16 = pci_read_config16(dev, PCI_COMMAND);
+               reg16 &= ~PCI_COMMAND_MEMORY;
+               pci_write_config16(dev, PCI_COMMAND, reg16);
+
                pci_write_config8(dev, 0x09, 0x80);
 
                /* Set timings */
@@ -49,6 +62,10 @@ static void sata_init(struct device *dev)
                pci_write_config16(dev, 0x48, 0x0004);
                pci_write_config16(dev, 0x4a, 0x0200);
 
+               /* Set IDE I/O Configuration */
+               reg32 = SIG_MODE_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0;
+               pci_write_config32(dev, IDE_CONFIG, reg32);
+
                /* Combine IDE - SATA configuration */
                pci_write_config8(dev, 0x90, 0x02);
 
@@ -56,8 +73,9 @@ static void sata_init(struct device *dev)
                pci_write_config8(dev, 0x92, 0x0f);
 
                /* SATA Initialization register */
-               pci_write_config32(dev, 0x94, 0x40000180);
+               pci_write_config32(dev, 0x94, 0x5a000180);
        } else if(config->sata_ahci) {
+               printk_debug("SATA controller in AHCI mode.\n");
                /* Allow both Legacy and Native mode */
                pci_write_config8(dev, 0x09, 0x8f);
 
@@ -86,6 +104,18 @@ static void sata_init(struct device *dev)
                /* SATA Initialization register */
                pci_write_config32(dev, 0x94, 0x1a000180);
        } else {
+               printk_debug("SATA controller in plain mode.\n");
+               /* Set Sata Controller Mode. No Mapping(?) */
+               pci_write_config8(dev, 0x90, 0x00);
+
+               /* No AHCI: clear AHCI base */
+               pci_write_config32(dev, 0x24, 0x00000000);
+
+               /* And without AHCI BAR no memory decoding */
+               reg16 = pci_read_config16(dev, PCI_COMMAND);
+               reg16 &= ~PCI_COMMAND_MEMORY;
+               pci_write_config16(dev, PCI_COMMAND, reg16);
+
                /* Native mode capable on both primary and secondary (0xa)
                 * or'ed with enabled (0x50) = 0xf
                 */
@@ -107,9 +137,6 @@ static void sata_init(struct device *dev)
                reg32 = SIG_MODE_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0;
                pci_write_config32(dev, IDE_CONFIG, reg32);
        
-               /* Set Sata Controller Mode. */
-               pci_write_config8(dev, 0x90, 0x02);
-       
                /* Port 0 & 1 enable XXX */
                pci_write_config8(dev, 0x92, 0x15);
        
@@ -135,8 +162,28 @@ static void sata_init(struct device *dev)
        pci_write_config8(dev, 0xa0, 0x00);
 
        pci_write_config8(dev, PCI_INTERRUPT_LINE, 0);
+
+       /* Sata Initialization Register */
+       reg32 = pci_read_config32(dev, 0x94);
+       reg32 |= (1 << 30); // due to some bug
+       pci_write_config32(dev, 0x94, reg32);
+}
+
+static void sata_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+       if (!vendor || !device) {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               pci_read_config32(dev, PCI_VENDOR_ID));
+       } else {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
 }
 
+static struct pci_operations sata_pci_ops = {
+       .set_subsystem    = sata_set_subsystem,
+};
+
 static struct device_operations sata_ops = {
        .read_resources         = pci_dev_read_resources,
        .set_resources          = pci_dev_set_resources,
@@ -144,6 +191,7 @@ static struct device_operations sata_ops = {
        .init                   = sata_init,
        .scan_bus               = 0,
        .enable                 = i82801gx_enable,
+       .ops_pci                = &sata_pci_ops,
 };
 
 /* Desktop Non-AHCI and Non-RAID Mode */
@@ -154,6 +202,15 @@ static const struct pci_driver i82801gx_sata_normal_driver __pci_driver = {
        .device = 0x27c0,
 };
 
+/* Mobile Non-AHCI and Non-RAID Mode */
+/* 82801GBM/GHM (ICH7-M/ICH7-M DH) */
+static const struct pci_driver i82801gx_sata_mobile_normal_driver __pci_driver = {
+       .ops    = &sata_ops,
+       .vendor = PCI_VENDOR_ID_INTEL,
+       .device = 0x27c4,
+};
+
+
 /* NOTE: Any of the below are not properly supported yet. */
 
 /* Desktop AHCI Mode */
@@ -172,14 +229,6 @@ static const struct pci_driver i82801gx_sata_raid_driver __pci_driver = {
        .device = 0x27c3,
 };
 
-/* Mobile Non-AHCI and Non-RAID Mode */
-/* 82801GBM/GHM (ICH7-M/ICH7-M DH) */
-static const struct pci_driver i82801gx_sata_mobile_normal_driver __pci_driver = {
-       .ops    = &sata_ops,
-       .vendor = PCI_VENDOR_ID_INTEL,
-       .device = 0x27c4,
-};
-
 /* Mobile AHCI Mode */
 /* 82801GBM/GHM (ICH7-M/ICH7-M DH) */
 static const struct pci_driver i82801gx_sata_mobile_ahci_driver __pci_driver = {
index bc14cc39f207bad128a04b63004f82f833756456..e9f9c7d9186a5c9c6d7bcb0e4dafb0329f68f5c8 100644 (file)
@@ -1,12 +1,12 @@
 /*
  * This file is part of the coreboot project.
  *
- * Copyright (C) 2008 coresystems GmbH
+ * Copyright (C) 2008-2009 coresystems GmbH
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
-#include <stdint.h>
-#include <smbus.h>
-#include <pci.h>
-#include <pci_ids.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/path.h>
+#include <device/smbus.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
 #include <arch/io.h>
 #include "i82801gx.h"
-#include "i82801_smbus.h"
-
-static int smbus_read_byte(struct bus *bus, device_t dev, u8 address)
+#include "i82801gx_smbus.h"
+static int lsmbus_read_byte(device_t dev, u8 address)
 {
        u16 device;
        struct resource *res;
+       struct bus *pbus;
 
        device = dev->path.i2c.device;
-       res = find_resource(bus->dev, 0x20);
+       pbus = get_pbus_smbus(dev);
+       res = find_resource(pbus->dev, 0x20);
 
        return do_smbus_read_byte(res->base, device, address);
 }
 
 static struct smbus_bus_operations lops_smbus_bus = {
-       .read_byte      = smbus_read_byte,
+       .read_byte      = lsmbus_read_byte,
+};
+
+static void smbus_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+       if (!vendor || !device) {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               pci_read_config32(dev, PCI_VENDOR_ID));
+       } else {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
+}
+
+static struct pci_operations smbus_pci_ops = {
+       .set_subsystem    = smbus_set_subsystem,
 };
 
 static struct device_operations smbus_ops = {
@@ -49,6 +69,7 @@ static struct device_operations smbus_ops = {
        .scan_bus               = scan_static_bus,
        .enable                 = i82801gx_enable,
        .ops_smbus_bus          = &lops_smbus_bus,
+       .ops_pci                = &smbus_pci_ops,
 };
 
 /* 82801GB/GR/GDH/GBM/GHM/GU (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH/ICH7-U) */
index 13272cb5526124eda21b4b9424ddd6c1cdb2c79e..ac327783ef8c061612b04c039e4e8436d7d5b5ea 100644 (file)
@@ -2,11 +2,12 @@
  * This file is part of the coreboot project.
  *
  * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
+ * Copyright (C) 2009 coresystems GmbH
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -25,7 +26,7 @@ static void smbus_delay(void)
        inb(0x80);
 }
 
-static int smbus_wait_until_ready(void)
+static int smbus_wait_until_ready(u16 smbus_base)
 {
        unsigned loops = SMBUS_TIMEOUT;
        unsigned char byte;
@@ -33,12 +34,12 @@ static int smbus_wait_until_ready(void)
                smbus_delay();
                if (--loops == 0)
                        break;
-               byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+               byte = inb(smbus_base + SMBHSTSTAT);
        } while (byte & 1);
        return loops ? 0 : -1;
 }
 
-static int smbus_wait_until_done(void)
+static int smbus_wait_until_done(u16 smbus_base)
 {
        unsigned loops = SMBUS_TIMEOUT;
        unsigned char byte;
@@ -46,142 +47,54 @@ static int smbus_wait_until_done(void)
                smbus_delay();
                if (--loops == 0)
                        break;
-               byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+               byte = inb(smbus_base + SMBHSTSTAT);
        } while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
        return loops ? 0 : -1;
 }
 
-static int smbus_wait_until_blk_done(void)
-{
-       unsigned loops = SMBUS_TIMEOUT;
-       unsigned char byte;
-       do {
-               smbus_delay();
-               if (--loops == 0)
-                       break;
-               byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
-       } while ((byte & (1 << 7)) == 0);
-       return loops ? 0 : -1;
-}
-
-static int do_smbus_read_byte(unsigned device, unsigned address)
+static int do_smbus_read_byte(unsigned smbus_base, unsigned device, unsigned address)
 {
        unsigned char global_status_register;
        unsigned char byte;
 
-       if (smbus_wait_until_ready() < 0) {
+       if (smbus_wait_until_ready(smbus_base) < 0) {
                return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
        }
        /* Setup transaction */
        /* Disable interrupts */
-       outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
+       outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
        /* Set the device I'm talking too */
-       outb(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBXMITADD);
+       outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
        /* Set the command/address... */
-       outb(address & 0xff, SMBUS_IO_BASE + SMBHSTCMD);
+       outb(address & 0xff, smbus_base + SMBHSTCMD);
        /* Set up for a byte data read */
-       outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xe3) | (0x2 << 2),
-            (SMBUS_IO_BASE + SMBHSTCTL));
+       outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
+            (smbus_base + SMBHSTCTL));
        /* Clear any lingering errors, so the transaction will run */
-       outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
+       outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
 
        /* Clear the data byte... */
-       outb(0, SMBUS_IO_BASE + SMBHSTDAT0);
+       outb(0, smbus_base + SMBHSTDAT0);
 
        /* Start the command */
-       outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40),
-            SMBUS_IO_BASE + SMBHSTCTL);
+       outb((inb(smbus_base + SMBHSTCTL) | 0x40),
+            smbus_base + SMBHSTCTL);
 
        /* Poll for transaction completion */
-       if (smbus_wait_until_done() < 0) {
+       if (smbus_wait_until_done(smbus_base) < 0) {
                return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
        }
 
-       global_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+       global_status_register = inb(smbus_base + SMBHSTSTAT);
 
        /* Ignore the "In Use" status... */
        global_status_register &= ~(3 << 5);
 
        /* Read results of transaction */
-       byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);
+       byte = inb(smbus_base + SMBHSTDAT0);
        if (global_status_register != (1 << 1)) {
                return SMBUS_ERROR;
        }
        return byte;
 }
 
-/* This function is neither used nor tested by me (Corey Osgood), the author 
-(Yinghai) probably tested/used it on i82801er */
-static int do_smbus_write_block(unsigned device, unsigned length, unsigned cmd,
-                               unsigned data1, unsigned data2)
-{
-       unsigned char byte;
-       unsigned char stat;
-       int i;
-
-#if CONFIG_USE_PRINTK_IN_CAR
-       printk_err("Untested smbus_write_block called\r\n");
-#else
-       print_err("Untested smbus_write_block called\r\n");
-#endif
-
-       /* Clear the PM timeout flags, SECOND_TO_STS */
-       outw(inw(0x0400 + 0x66), 0x0400 + 0x66);
-
-       if (smbus_wait_until_ready() < 0) {
-               return -2;
-       }
-
-       /* Setup transaction */
-       /* Obtain ownership */
-       outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
-       for (stat = 0; (stat & 0x40) == 0;) {
-               stat = inb(SMBUS_IO_BASE + SMBHSTSTAT);
-       }
-       /* Clear the done bit */
-       outb(0x80, SMBUS_IO_BASE + SMBHSTSTAT);
-       /* Disable interrupts */
-       outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
-
-       /* Set the device I'm talking too */
-       outb(((device & 0x7f) << 1), SMBUS_IO_BASE + SMBXMITADD);
-
-       /* Set the command address */
-       outb(cmd & 0xff, SMBUS_IO_BASE + SMBHSTCMD);
-
-       /* Set the block length */
-       outb(length & 0xff, SMBUS_IO_BASE + SMBHSTDAT0);
-
-       /* Try sending out the first byte of data here */
-       byte = (data1 >> (0)) & 0x0ff;
-       outb(byte, SMBUS_IO_BASE + SMBBLKDAT);
-       /* Issue a block write command */
-       outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xe3) | (0x5 << 2) | 0x40,
-            SMBUS_IO_BASE + SMBHSTCTL);
-
-       for (i = 0; i < length; i++) {
-
-               /* Poll for transaction completion */
-               if (smbus_wait_until_blk_done() < 0) {
-                       return -3;
-               }
-
-               /* Load the next byte */
-               if (i > 3)
-                       byte = (data2 >> (i % 4)) & 0x0ff;
-               else
-                       byte = (data1 >> (i)) & 0x0ff;
-               outb(byte, SMBUS_IO_BASE + SMBBLKDAT);
-
-               /* Clear the done bit */
-               outb(inb(SMBUS_IO_BASE + SMBHSTSTAT),
-                    SMBUS_IO_BASE + SMBHSTSTAT);
-       }
-
-#if CONFIG_USE_PRINTK_IN_CAR
-       printk_debug("SMBUS Block complete\r\n");
-#else
-       print_debug("SMBUS Block complete\r\n");
-#endif
-       return 0;
-}
index 22aad92a4eacd24d4d95c4adb997a13a031ad4fd..a753202f72cec5e4a60cf3d71662b449f34b45e8 100644 (file)
@@ -1,12 +1,12 @@
 /*
  * This file is part of the coreboot project.
  *
- * Copyright (C) 2008 coresystems GmbH
+ * Copyright (C) 2008-2009 coresystems GmbH
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -42,6 +42,21 @@ static void usb_init(struct device *dev)
        printk_debug("done.\n");
 }
 
+static void usb_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+       if (!vendor || !device) {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               pci_read_config32(dev, PCI_VENDOR_ID));
+       } else {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
+}
+
+static struct pci_operations usb_pci_ops = {
+       .set_subsystem    = usb_set_subsystem,
+};
+
 static struct device_operations usb_ops = {
        .read_resources         = pci_dev_read_resources,
        .set_resources          = pci_dev_set_resources,
@@ -49,6 +64,7 @@ static struct device_operations usb_ops = {
        .init                   = usb_init,
        .scan_bus               = 0,
        .enable                 = i82801gx_enable,
+       .ops_pci                = &usb_pci_ops,
 };
 
 /* 82801GB/GR/GDH/GBM/GHM/GU (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH/ICH7-U) */
diff --git a/src/southbridge/intel/i82801gx/i82801gx_usb_debug.c b/src/southbridge/intel/i82801gx/i82801gx_usb_debug.c
new file mode 100644 (file)
index 0000000..be524ca
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+// An arbitrary address for the BAR
+#define EHCI_BAR               0xFEF00000
+// These could be read from DEBUG_BASE (0:1d.7 R 0x5A 16bit)
+#define EHCI_BAR_INDEX         0x10
+#define EHCI_DEBUG_OFFSET      0xA0
+
+static void set_debug_port(unsigned port)
+{
+       // Nothing for now?
+}
+
+static void i82801gx_enable_usbdebug_direct(unsigned port)
+{
+       pci_write_config32(PCI_DEV(0, 0x1d, 7), EHCI_BAR_INDEX, EHCI_BAR);
+       pci_write_config8(PCI_DEV(0, 0x1d, 7), 0x04, 0x2); // Memory Space Enable
+}
+
index 5ac7a1a97c4211123aebea298b51f1e30b2e8fa3..39a5799ed9ed47e6466f46fddfddc07879bcbb94 100644 (file)
@@ -1,12 +1,12 @@
 /*
  * This file is part of the coreboot project.
  *
- * Copyright (C) 2008 coresystems GmbH
+ * Copyright (C) 2008-2009 coresystems GmbH
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 #include <device/pci.h>
 #include <device/pci_ids.h>
 #include "i82801gx.h"
+#if CONFIG_USBDEBUG_DIRECT
+#include <usbdebug_direct.h>
+#endif
+#include <arch/io.h>
 
 static void usb_ehci_init(struct device *dev)
 {
+       struct resource *res;
+       u8 *base;
        u32 reg32;
+       u8 reg8;
 
        printk_debug("EHCI: Setting up controller.. ");
        reg32 = pci_read_config32(dev, PCI_COMMAND);
-       pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER);
+       reg32 |= PCI_COMMAND_MASTER;
+       reg32 |= PCI_COMMAND_SERR;
+       pci_write_config32(dev, PCI_COMMAND, reg32);
 
        reg32 = pci_read_config32(dev, 0xdc);
        reg32 |= (1 << 31) | (1 << 27);
@@ -41,11 +50,21 @@ static void usb_ehci_init(struct device *dev)
        reg32 |= (2 << 2) | (1 << 29) | (1 << 17);
        pci_write_config32(dev, 0xfc, reg32);
 
+       /* Clear any pending port changes */
+       res = find_resource(dev, 0x10);
+       base =(u8 *)res->base;
+       reg32 = readl(base + 0x24) | (1 << 2);
+       writel(base + 0x24, reg32);
+
+       /* workaround */
+       reg8 = pci_read_config8(dev, 0x84);
+       reg8 |= (1 << 4);
+       pci_write_config8(dev, 0x84, reg8);
+
        printk_debug("done.\n");
 }
 
-static void usb_ehci_set_subsystem(device_t dev, unsigned vendor,
-                                  unsigned device)
+static void usb_ehci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
 {
        u8 access_cntl;
 
@@ -54,14 +73,42 @@ static void usb_ehci_set_subsystem(device_t dev, unsigned vendor,
        /* Enable writes to protected registers. */
        pci_write_config8(dev, 0x80, access_cntl | 1);
 
-       /* Write the subsystem vendor and device ID. */
-       pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
-                          ((device & 0xffff) << 16) | (vendor & 0xffff));
+       if (!vendor || !device) {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               pci_read_config32(dev, PCI_VENDOR_ID));
+       } else {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
 
        /* Restore protection. */
        pci_write_config8(dev, 0x80, access_cntl);
 }
 
+static void usb_ehci_set_resources(struct device *dev)
+{
+#if CONFIG_USBDEBUG_DIRECT
+       struct resource *res;
+       u32 base;
+       u32 usb_debug;
+
+       usb_debug = get_ehci_debug();
+       set_ehci_debug(0);
+#endif
+       pci_dev_set_resources(dev);
+
+#if CONFIG_USBDEBUG_DIRECT
+       res = find_resource(dev, 0x10);
+       set_ehci_debug(usb_debug);
+       if (!res) return;
+       base = res->base;
+       set_ehci_base(base);
+       report_resource_stored(dev, res, "");
+#endif
+}
+
+
+
 static struct pci_operations lops_pci = {
        .set_subsystem  = &usb_ehci_set_subsystem,
 };
index 474a2d7cb3896c182fdfcf50836894a17125f8a8..9304ffc705fcf92a76534e4558a2a73411fd63ab 100644 (file)
@@ -1,12 +1,12 @@
 /*
  * This file is part of the coreboot project.
  *
- * Copyright (C) 2008 coresystems GmbH
+ * Copyright (C) 2008-2009 coresystems GmbH
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of