Add stage1 support for vt8237[RS] to v3.
Signed-off-by: Corey Osgood <corey.osgood@gmail.com> Acked-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> git-svn-id: svn://coreboot.org/repository/coreboot-v3@928 f3766cd6-281f-0410-b1cd-43a5c92072e9
This commit is contained in:
parent
1dcad4bdd2
commit
2dd3477242
3 changed files with 433 additions and 0 deletions
25
southbridge/via/vt8237/Makefile
Normal file
25
southbridge/via/vt8237/Makefile
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
##
|
||||
## This file is part of the coreboot project.
|
||||
##
|
||||
## Copyright (C) 2008 Corey Osgood <corey.osgood@gmail.com>
|
||||
##
|
||||
## 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 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
|
||||
##
|
||||
|
||||
ifeq ($(CONFIG_SOUTHBRIDGE_VIA_VT8237),y)
|
||||
|
||||
STAGE2_CHIPSET_SRC +=
|
||||
|
||||
endif
|
||||
318
southbridge/via/vt8237/stage1.c
Normal file
318
southbridge/via/vt8237/stage1.c
Normal file
|
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007-2008 Corey Osgood <corey.osgood@gmail.com>
|
||||
* Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
|
||||
*
|
||||
* 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 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
|
||||
*/
|
||||
|
||||
#include <types.h>
|
||||
#include <lib.h>
|
||||
#include <console.h>
|
||||
#include <device/pci.h>
|
||||
#include <io.h>
|
||||
#include <device/pci_ids.h>
|
||||
#include <spd.h>
|
||||
#include "vt8237.h"
|
||||
|
||||
/* TODO List:
|
||||
* * Merge the rest of the functions from v2, except smbus_fixup which doesn't
|
||||
* seem to be necessary any more (?)
|
||||
* * Clean up vt8237_early_network_init.
|
||||
* Comments in code indicate that it's broken?
|
||||
* * Figure out if the smbus actually needs to be reset after every transaction.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Print an error, should it occur. If no error, just exit.
|
||||
*
|
||||
* @param host_status The data returned on the host status register after
|
||||
* a transaction is processed.
|
||||
* @param loops The number of times a transaction was attempted.
|
||||
*/
|
||||
static void smbus_print_error(u8 host_status, int loops)
|
||||
{
|
||||
/* Check if there actually was an error. */
|
||||
if ((host_status == 0x00 || host_status == 0x40 ||
|
||||
host_status == 0x42) && (loops < SMBUS_TIMEOUT))
|
||||
{
|
||||
printk(BIOS_SPEW, "SMBus Ready/Completed Successfully\n");
|
||||
return;
|
||||
}
|
||||
if (loops >= SMBUS_TIMEOUT)
|
||||
printk(BIOS_ERR, "SMBus Timed out\n");
|
||||
if (host_status & (1 << 4))
|
||||
printk(BIOS_ERR, "Interrupt/SMI# was Failed Bus Transaction\n");
|
||||
if (host_status & (1 << 3))
|
||||
printk(BIOS_ERR, "Bus error\n");
|
||||
if (host_status & (1 << 2))
|
||||
printk(BIOS_ERR, "Device error\n");
|
||||
if (host_status & (1 << 1))
|
||||
printk(BIOS_SPEW, "Interrupt/SMI# completed successfully\n");
|
||||
if (host_status & (1 << 0))
|
||||
printk(BIOS_ERR, "Host busy\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset and take ownership of the SMBus.
|
||||
*/
|
||||
static void smbus_reset(u16 smbus_io_base)
|
||||
{
|
||||
outb(HOST_RESET, smbus_io_base + SMBHSTSTAT);
|
||||
|
||||
/* Datasheet says we have to read it to take ownership of SMBus. */
|
||||
smbus_print_error(inb(smbus_io_base + SMBHSTSTAT), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the SMBus to become ready to process the next transaction.
|
||||
*/
|
||||
static void smbus_wait_until_ready(u16 smbus_io_base)
|
||||
{
|
||||
int loops;
|
||||
|
||||
printk(BIOS_SPEW, "Waiting until SMBus ready\n");
|
||||
|
||||
loops = 0;
|
||||
while ((inb(smbus_io_base + SMBHSTSTAT) & 1) == 1 && loops <= SMBUS_TIMEOUT)
|
||||
++loops;
|
||||
|
||||
smbus_print_error(inb(smbus_io_base + SMBHSTSTAT), loops);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a byte from the SMBus.
|
||||
*
|
||||
* @param dimm The address location of the DIMM on the SMBus.
|
||||
* @param offset The offset the data is located at.
|
||||
*/
|
||||
u8 smbus_read_byte(u16 dimm, u8 offset, u16 smbus_io_base)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
printk(BIOS_SPEW, "SMBus Read from DIMM %d at address 0x%x\n",
|
||||
(int)dimm, offset);
|
||||
|
||||
smbus_reset(smbus_io_base);
|
||||
|
||||
/* Clear host data port. */
|
||||
outb(0x00, smbus_io_base + SMBHSTDAT0);
|
||||
/* Doesn't seem to be necessary...*/
|
||||
/* udelay(1); */
|
||||
smbus_wait_until_ready(smbus_io_base);
|
||||
|
||||
/* With this, addresses are 0x50, 0x51, etc. Without it,
|
||||
* addresses would be 0xa1, 0xa3, etc */
|
||||
dimm = (dimm << 1) | 1;
|
||||
|
||||
outb(dimm, smbus_io_base + SMBXMITADD);
|
||||
outb(offset, smbus_io_base + SMBHSTCMD);
|
||||
|
||||
/* Start transaction, byte data read. */
|
||||
outb(0x48, smbus_io_base + SMBHSTCTL);
|
||||
/* udelay(1); */
|
||||
smbus_wait_until_ready(smbus_io_base);
|
||||
|
||||
val = inb(smbus_io_base + SMBHSTDAT0);
|
||||
printk(BIOS_SPEW, "Read: 0x%x\n", val);
|
||||
|
||||
/* TODO: Is this necessary? */
|
||||
smbus_reset(smbus_io_base);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the smbus on vt8237-based systems
|
||||
*
|
||||
* @param smbus_io_base: The SMBus I/O base, usually 0x400
|
||||
*/
|
||||
void enable_smbus(u16 smbus_io_base)
|
||||
{
|
||||
u32 dev;
|
||||
|
||||
/* Power management controller */
|
||||
pci_conf1_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT8237R_LPC,
|
||||
&dev);
|
||||
|
||||
if (!dev) {
|
||||
/* Power management controller */
|
||||
pci_conf1_find_device(PCI_VENDOR_ID_VIA,
|
||||
PCI_DEVICE_ID_VIA_VT8237S_LPC, &dev);
|
||||
if (!dev)
|
||||
{
|
||||
printk(BIOS_ERR, "Power management controller not "
|
||||
"found! Using hardcoded default.\n");
|
||||
dev = PCI_BDF(0, 17, 0);
|
||||
} else {
|
||||
printk(BIOS_DEBUG, "VT8237S Power management "
|
||||
"controller found at 0x%x\n", dev);
|
||||
}
|
||||
} else {
|
||||
printk(BIOS_DEBUG, "VT8237R Power management controller found "
|
||||
"at 0x%x\n", dev);
|
||||
}
|
||||
|
||||
/* 7 = SMBus Clock from RTC 32.768KHz
|
||||
* 5 = Internal PLL reset from susp
|
||||
*/
|
||||
pci_conf1_write_config8(dev, VT8237R_POWER_WELL, 0xa0);
|
||||
|
||||
/* Enable SMBus. */
|
||||
pci_conf1_write_config16(dev, VT8237R_SMBUS_IO_BASE_REG,
|
||||
smbus_io_base | 0x1);
|
||||
|
||||
/* SMBus Host Configuration, enable. */
|
||||
pci_conf1_write_config8(dev, VT8237R_SMBUS_HOST_CONF, 0x01);
|
||||
|
||||
/* Make it work for I/O. */
|
||||
pci_conf1_write_config16(dev, PCI_COMMAND, PCI_COMMAND_IO);
|
||||
|
||||
/* reset smbus */
|
||||
smbus_reset(smbus_io_base);
|
||||
|
||||
/* Reset the internal pointer. */
|
||||
inb(smbus_io_base + SMBHSTCTL);
|
||||
}
|
||||
|
||||
/* TODO:
|
||||
* Magic numbers -> #defines
|
||||
* fix?
|
||||
* clean up
|
||||
*/
|
||||
|
||||
/* offset 0x58
|
||||
* 31:20 reserved
|
||||
* 19:16 4 bit position in shadow EEPROM
|
||||
* 15:0 data to write
|
||||
*
|
||||
* offset 0x5c
|
||||
* 31:28 reserved
|
||||
* 27 ERDBG - enable read from 0x5c
|
||||
* 26 reserved
|
||||
* 25 SEELD
|
||||
* 24 SEEPR - write 1 when done updating, wait until SEELD is set to 1, sticky
|
||||
* cleared by reset, if it is 1 writing is disabled
|
||||
* 19:16 4 bit position in shadow EEPROM
|
||||
* 15:0 data from shadow EEPROM
|
||||
*
|
||||
* after PCIRESET SEELD and SEEPR must be 1 and 1
|
||||
*/
|
||||
|
||||
/* 1 = needs PCI reset, 0 don't reset, network initialized */
|
||||
|
||||
/* fixme maybe close the debug register after use? */
|
||||
|
||||
#define LAN_TIMEOUT 0x7FFFFFFF
|
||||
|
||||
int vt8237_early_network_init(struct vt8237_network_rom *rom) {
|
||||
struct vt8237_network_rom n;
|
||||
int loops = 0;
|
||||
u32 dev;
|
||||
u32 tmp;
|
||||
u8 status;
|
||||
u16 *rom_write;
|
||||
unsigned int checksum;
|
||||
int i;
|
||||
|
||||
/* Network adapter */
|
||||
pci_conf1_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT8237_LAN,
|
||||
&dev);
|
||||
|
||||
if (!dev) {
|
||||
printk(BIOS_ERR, "Network is disabled, please enable\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
tmp = pci_conf1_read_config32(dev, 0x5c);
|
||||
/* enable ERDBG */
|
||||
tmp |= 0x08000000;
|
||||
pci_conf1_write_config32(dev, 0x5c, tmp);
|
||||
|
||||
status = ((pci_conf1_read_config32(dev, 0x5c) >> 24) & 0x3);
|
||||
|
||||
if (status == 3) {
|
||||
/* network controller OK, EEPROM loaded */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rom == NULL) {
|
||||
printk(BIOS_ERR, "No configuration data specified, using default MAC!\n");
|
||||
n.mac_address[0] = 0x0;
|
||||
n.mac_address[1] = 0x0;
|
||||
n.mac_address[2] = 0xde;
|
||||
n.mac_address[3] = 0xad;
|
||||
n.mac_address[4] = 0xbe;
|
||||
n.mac_address[5] = 0xef;
|
||||
n.phy_addr = 0x1;
|
||||
n.res1 = 0x0;
|
||||
n.sub_sid = 0x102;
|
||||
n.sub_vid = 0x1106;
|
||||
n.pid = 0x3065;
|
||||
n.vid = 0x1106;
|
||||
n.pmcc = 0x1f;
|
||||
n.data_sel = 0x10;
|
||||
n.pmu_data_reg = 0x0;
|
||||
n.aux_curr = 0x0;
|
||||
n.reserved = 0x0;
|
||||
n.min_gnt = 0x3;
|
||||
n.max_lat = 0x8;
|
||||
n.bcr0 = 0x9;
|
||||
n.bcr1 = 0xe;
|
||||
n.cfg_a = 0x3;
|
||||
n.cfg_b = 0x0;
|
||||
n.cfg_c = 0x40;
|
||||
n.cfg_d = 0x82;
|
||||
n.checksum = 0x0;
|
||||
rom = &n;
|
||||
}
|
||||
|
||||
rom_write = (u16 *) rom;
|
||||
checksum = 0;
|
||||
/* write all data except checksum and second to last byte */
|
||||
tmp &= 0xff000000; /* leave reserved bits in */
|
||||
for (i = 0; i < 15; i++) {
|
||||
pci_conf1_write_config32(dev, 0x58, tmp | (i << 16) | rom_write[i]);
|
||||
/* lame code fixme */
|
||||
checksum += rom_write[i] & 0xff;
|
||||
//checksum %= 256;
|
||||
checksum += (rom_write[i] >> 8) & 0xff;
|
||||
//checksum %= 256;
|
||||
}
|
||||
|
||||
checksum += (rom_write[15] & 0xff);
|
||||
checksum = ~(checksum & 0xff);
|
||||
tmp |= (((checksum & 0xff) << 8) | rom_write[15]);
|
||||
|
||||
/* write last byte and checksum */
|
||||
pci_conf1_write_config32(dev, 0x58, (15 << 16) | tmp);
|
||||
|
||||
tmp = pci_conf1_read_config32(dev, 0x5c);
|
||||
pci_conf1_write_config32(dev, 0x5c, tmp | 0x01000000); /* toggle SEEPR */
|
||||
|
||||
/* Yes, this is a mess, but it's the easiest way to do it. */
|
||||
while ( (((pci_conf1_read_config32(dev, 0x5c) >> 25) & 1) == 0)
|
||||
&& (loops < LAN_TIMEOUT))
|
||||
++loops;
|
||||
|
||||
if (loops >= LAN_TIMEOUT) {
|
||||
printk(BIOS_ERR, "Timout - LAN controller did not accept configuration\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* we are done, config will be used after PCIRST# */
|
||||
return 1;
|
||||
}
|
||||
90
southbridge/via/vt8237/vt8237.h
Normal file
90
southbridge/via/vt8237/vt8237.h
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License v2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef SOUTHBRIDGE_VIA_VT8237_VT8237_H
|
||||
#define SOUTHBRIDGE_VIA_VT8237_VT8237_H
|
||||
|
||||
#include <types.h>
|
||||
|
||||
/* Static resources for the VT8237R southbridge */
|
||||
|
||||
#define VT8237R_APIC_ID 0x2
|
||||
#define VT8237R_ACPI_IO_BASE 0x500
|
||||
/* 0x0 disabled, 0x2 reserved, 0xf = IRQ15 */
|
||||
#define VT8237R_ACPI_IRQ 0x9
|
||||
#define VT8237S_SPI_MEM_BASE 0xfed02000ULL
|
||||
#define VT8237R_HPET_ADDR 0xfed00000ULL
|
||||
#define VT8237R_APIC_BASE 0xfec00000ULL
|
||||
|
||||
/* IDE */
|
||||
#define IDE_CS 0x40
|
||||
#define IDE_CONF_I 0x41
|
||||
#define IDE_CONF_II 0x42
|
||||
#define IDE_CONF_FIFO 0x43
|
||||
#define IDE_MISC_I 0x44
|
||||
#define IDE_MISC_II 0x45
|
||||
#define IDE_UDMA 0x50
|
||||
|
||||
/* SMBus */
|
||||
#define VT8237R_POWER_WELL 0x94
|
||||
#define VT8237R_SMBUS_IO_BASE_REG 0xd0
|
||||
#define VT8237R_SMBUS_HOST_CONF 0xd2
|
||||
|
||||
#define SMBHSTSTAT 0x0
|
||||
#define SMBSLVSTAT 0x1
|
||||
#define SMBHSTCTL 0x2
|
||||
#define SMBHSTCMD 0x3
|
||||
#define SMBXMITADD 0x4
|
||||
#define SMBHSTDAT0 0x5
|
||||
|
||||
#define HOST_RESET 0xff
|
||||
/* 1 in the 0 bit of SMBHSTADD states to READ. */
|
||||
#define READ_CMD 0x01
|
||||
#define SMBUS_TIMEOUT (100 * 1000 * 10)
|
||||
#define I2C_TRANS_CMD 0x40
|
||||
#define CLOCK_SLAVE_ADDRESS 0x69
|
||||
|
||||
struct vt8237_network_rom {
|
||||
u8 mac_address[6];
|
||||
u8 phy_addr;
|
||||
u8 res1;
|
||||
u16 sub_sid;
|
||||
u16 sub_vid;
|
||||
u16 pid;
|
||||
u16 vid;
|
||||
u8 pmcc;
|
||||
u8 data_sel;
|
||||
u8 pmu_data_reg;
|
||||
u8 aux_curr;
|
||||
u16 reserved;
|
||||
u8 min_gnt;
|
||||
u8 max_lat;
|
||||
u8 bcr0;
|
||||
u8 bcr1;
|
||||
u8 cfg_a;
|
||||
u8 cfg_b;
|
||||
u8 cfg_c;
|
||||
u8 cfg_d;
|
||||
u8 checksum;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
void enable_smbus(u16);
|
||||
u8 smbus_read_byte(u16, u8, u16);
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue