This patch contains some significant updates to the i82801gx component and will
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
This commit is contained in:
parent
6df0c62b68
commit
a8e1168064
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
@ -22,7 +22,10 @@
|
|||
#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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -25,6 +25,12 @@
|
|||
|
||||
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 = {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -31,61 +31,63 @@
|
|||
#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;
|
||||
u32 reg32;
|
||||
|
||||
/* 1 */
|
||||
set_bits(base + 0x08, 1, 1);
|
||||
/* Set Bit0 to 0 to enter reset state (BAR + 0x8)[0] */
|
||||
if (set_bits(base + 0x08, 1, 0) == -1)
|
||||
goto no_codec;
|
||||
|
||||
/* 2 */
|
||||
dword = readl(base + 0x0e);
|
||||
dword |= 7;
|
||||
writel(dword, base + 0x0e);
|
||||
/* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
|
||||
if (set_bits(base + 0x08, 1, 1) == -1)
|
||||
goto no_codec;
|
||||
|
||||
/* 3 */
|
||||
/* 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) */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -26,31 +26,42 @@
|
|||
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);
|
||||
|
||||
/* disable parity error response */
|
||||
/* This device has no interrupt */
|
||||
pci_write_config8(dev, 0x3c, 0xff);
|
||||
|
||||
/* disable parity error response and SERR */
|
||||
reg16 = pci_read_config16(dev, 0x3e);
|
||||
reg16 &= ~(1 << 0);
|
||||
reg16 &= ~(1 << 1);
|
||||
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);
|
||||
/* 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;
|
||||
pci_write_config16(dev, 0x06, reg16);
|
||||
|
||||
reg16 = pci_read_config16(dev, 0x1e);
|
||||
// reg16 |= 0xf900;
|
||||
pci_write_config16(dev, 0x1e, reg16);
|
||||
}
|
||||
|
||||
#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 = {
|
||||
|
|
|
@ -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);
|
||||
/* Enable IO xAPIC on this PCIe port */
|
||||
reg32 = pci_read_config32(dev, 0xd8);
|
||||
reg32 |= (1 << 7);
|
||||
pci_write_config32(dev, 0xd8, reg32);
|
||||
|
||||
reg16 = pci_read_config16(dev, 0x1e);
|
||||
reg16 |= 0xf900;
|
||||
pci_write_config16(dev, 0x1e, reg16);
|
||||
/* 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 = {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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
|
||||
|
@ -18,27 +18,47 @@
|
|||
* 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) */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
@ -23,14 +23,23 @@
|
|||
#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,
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue