From d9f29c8e5e3f37335a9b737361acc286df5248f0 Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Fri, 5 Sep 2008 18:20:57 +0000 Subject: [PATCH] This patch adds support for the VIA VT8237S south bridge. The VT8237R programming remains unchanged (tested on mine desktop) except of reverting the small change introduced by Bari (gpio/inta setup reg 0x5b). This should go for some board specific file. The change would broke at least mine board. But seems to be needed for jakllsch. Signed-off-by: Rudolf Marek Acked-by: Bari Ari git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3567 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/include/device/pci_ids.h | 3 + src/southbridge/via/vt8237r/Config.lb | 1 + src/southbridge/via/vt8237r/vt8237_ctrl.c | 186 +++++++++++++ src/southbridge/via/vt8237r/vt8237r.h | 27 ++ .../via/vt8237r/vt8237r_early_smbus.c | 253 +++++++++++++++++- src/southbridge/via/vt8237r/vt8237r_lpc.c | 118 ++++++-- src/southbridge/via/vt8237r/vt8237r_sata.c | 75 +++++- 7 files changed, 622 insertions(+), 41 deletions(-) create mode 100644 src/southbridge/via/vt8237r/vt8237_ctrl.c diff --git a/src/include/device/pci_ids.h b/src/include/device/pci_ids.h index 2331f3b4fe..da01fba2a5 100644 --- a/src/include/device/pci_ids.h +++ b/src/include/device/pci_ids.h @@ -1160,6 +1160,9 @@ #define PCI_DEVICE_ID_VIA_K8T890CE_BR 0xb188 #define PCI_DEVICE_ID_VIA_VT6420_SATA 0x3149 #define PCI_DEVICE_ID_VIA_VT8237R_LPC 0x3227 +#define PCI_DEVICE_ID_VIA_VT8237S_LPC 0x3372 +#define PCI_DEVICE_ID_VIA_VT8237_SATA 0x5372 +#define PCI_DEVICE_ID_VIA_VT8237_VLINK 0x287e #define PCI_DEVICE_ID_VIA_CN700_AGP 0x0314 #define PCI_DEVICE_ID_VIA_CN700_ERR 0x1314 #define PCI_DEVICE_ID_VIA_CN700_HOST 0x2314 diff --git a/src/southbridge/via/vt8237r/Config.lb b/src/southbridge/via/vt8237r/Config.lb index 90feb0f9ef..2c01d41a2e 100644 --- a/src/southbridge/via/vt8237r/Config.lb +++ b/src/southbridge/via/vt8237r/Config.lb @@ -20,6 +20,7 @@ config chip.h driver vt8237r.o +driver vt8237_ctrl.o driver vt8237r_ide.o driver vt8237r_lpc.o driver vt8237r_sata.o diff --git a/src/southbridge/via/vt8237r/vt8237_ctrl.c b/src/southbridge/via/vt8237r/vt8237_ctrl.c new file mode 100644 index 0000000000..666fbcf68c --- /dev/null +++ b/src/southbridge/via/vt8237r/vt8237_ctrl.c @@ -0,0 +1,186 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 Rudolf Marek + * + * 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 + */ + +#include +#include +#include +#include +#include + +/* We support here K8M890/K8T890 and VT8237/S/A PCI1/Vlink */ + +static void vt8237_cfg(struct device *dev) +{ + u8 regm, regm2, regm3; + + device_t devfun3; + + devfun3 = dev_find_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_K8T890CE_3, 0); + + if (!devfun3) + devfun3 = dev_find_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_K8M890CE_3, 0); + + if (!devfun3) + die("Unknown NB"); + + /* CPU to PCI Flow Control 1 & 2, just fill in recommended */ + pci_write_config8(dev, 0x70, 0xc2); + pci_write_config8(dev, 0x71, 0xc8); + + /* PCI Control */ + pci_write_config8(dev, 0x72, 0xee); + pci_write_config8(dev, 0x73, 0x01); + pci_write_config8(dev, 0x74, 0x3c); + pci_write_config8(dev, 0x75, 0x0f); + pci_write_config8(dev, 0x76, 0x50); + pci_write_config8(dev, 0x77, 0x48); + pci_write_config8(dev, 0x78, 0x01); + /* APIC on HT */ + pci_write_config8(dev, 0x7c, 0x77); //maybe Enable LDT APIC Mode bit3 set to 1 + + /* WARNING: Need to copy some registers from NB (D0F3) to SB (D11F7). */ + + regm = pci_read_config8(devfun3, 0x88); /* Shadow mem CTRL */ + pci_write_config8(dev, 0x57, regm); + + regm = pci_read_config8(devfun3, 0x80); /* Shadow page C */ + pci_write_config8(dev, 0x61, regm); + + regm = pci_read_config8(devfun3, 0x81); /* Shadow page D */ + pci_write_config8(dev, 0x62, regm); + + /* Shadow page F + memhole copy */ + regm = pci_read_config8(devfun3, 0x83); + pci_write_config8(dev, 0x63, regm); + + regm3 = pci_read_config8(devfun3, 0x82);/* Shadow page E */ + pci_write_config8(dev, 0x64, regm); + + regm = pci_read_config8(devfun3, 0x86); /* SMM and APIC decoding */ + pci_write_config8(dev, 0xe6, regm); +} + +/** + * Example of setup: Setup the V-Link for VT8237R, 8X mode. + * + * For K8T890CF VIA recommends what is in VIA column, AW is award 8X: + * + * REG DEF AW VIA-8X VIA-4X + * ----------------------------- + * NB V-Link Manual Driving Control strobe 0xb5 0x46 0x46 0x88 0x88 + * NB V-Link Manual Driving Control - Data 0xb6 0x46 0x46 0x88 0x88 + * NB V-Link Receiving Strobe Delay 0xb7 0x02 0x02 0x61 0x01 + * NB V-Link Compensation Control bit4,0 (b5,b6) 0xb4 0x10 0x10 0x11 0x11 + * SB V-Link Strobe Drive Control 0xb9 0x00 0xa5 0x98 0x98 + * SB V-Link Data drive Control???? 0xba 0x00 0xbb 0x77 0x77 + * SB V-Link Receive Strobe Delay???? 0xbb 0x04 0x11 0x11 0x11 + * SB V-Link Compensation Control bit0 (use b9) 0xb8 0x00 0x01 0x01 0x01 + * V-Link CKG Control 0xb0 0x05 0x05 0x06 0x03 + * V-Link CKG Control 0xb1 0x05 0x05 0x01 0x03 + */ + +static void vt8237s_vlink_init(struct device *dev) +{ + u8 reg; + + device_t devfun7; + + devfun7 = dev_find_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_K8T890CE_7, 0); + + if (!devfun7) + devfun7 = dev_find_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_K8M890CE_7, 0); + + /* no pairing NB found */ + if (!devfun7) + return; + + /* + * This init code is valid only for the VT8237S! For different + * sounthbridges (e.g. VT8237A, VT8237S, VT8237R (without plus R) + * and VT8251) a different init code is required. + */ + + pci_write_config8(devfun7, 0xb5, 0x66); + pci_write_config8(devfun7, 0xb6, 0x66); + pci_write_config8(devfun7, 0xb7, 0x65); + + reg = pci_read_config8(devfun7, 0xb4); + reg |= 0x1; + pci_write_config8(devfun7, 0xb4, reg); + + pci_write_config8(dev, 0xb9, 0x68); + pci_write_config8(dev, 0xba, 0x88); + pci_write_config8(dev, 0xbb, 0x89); + + + reg = pci_read_config8(dev, 0xbd); + reg |= 0x3; + pci_write_config8(dev, 0xbd, reg); + + /* Program V-link 8X 8bit full duplex, parity disabled FIXME */ + pci_write_config8(dev, 0x48, 0x13); +} + +static void ctrl_enable(struct device *dev) { + + /* enable the 0:13 and 0:13.1 */ + /* FIXME */ + pci_write_config8(dev, 0x4f, 0x43); +} + + +extern void dump_south(device_t dev); + +static void ctrl_init(struct device *dev) { + + /* TODO: Fix some ordering issue fo V-link set Rx77[6] and PCI1_Rx4F[0] + should to 1 FIXME DO you need?*/ + + /* VT8237R specific configuration other SB are done in their own directories */ + /* add A version */ + device_t devsb = dev_find_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_VT8237S_LPC, 0); + if (devsb) { + /* FIXME: Skip v-link setup for now */ +// vt8237s_vlink_init(dev); + } + + /* configure PCI1 and copy mirror registers from D0F3 */ + vt8237_cfg(dev); + dump_south(dev); +} + +static const struct device_operations ctrl_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = ctrl_init, + .enable = ctrl_enable, + .ops_pci = 0, +}; + +static const struct pci_driver northbridge_driver_t __pci_driver = { + .ops = &ctrl_ops, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_VT8237_VLINK, +}; diff --git a/src/southbridge/via/vt8237r/vt8237r.h b/src/southbridge/via/vt8237r/vt8237r.h index 444500b82a..231553bc11 100644 --- a/src/southbridge/via/vt8237r/vt8237r.h +++ b/src/southbridge/via/vt8237r/vt8237r.h @@ -20,6 +20,8 @@ #ifndef SOUTHBRIDGE_VIA_VT8237R_VT8237R_H #define SOUTHBRIDGE_VIA_VT8237R_VT8237R_H +#include + /* Static resources for the VT8237R southbridge */ #define VT8237R_APIC_ID 0x2 @@ -27,6 +29,7 @@ #define VT8237R_SMBUS_IO_BASE 0x400 /* 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 @@ -68,4 +71,28 @@ #define SMBUS_DELAY() inb(0x80) +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)); + #endif diff --git a/src/southbridge/via/vt8237r/vt8237r_early_smbus.c b/src/southbridge/via/vt8237r/vt8237r_early_smbus.c index 5e62f39e4d..5b865d3814 100644 --- a/src/southbridge/via/vt8237r/vt8237r_early_smbus.c +++ b/src/southbridge/via/vt8237r/vt8237r_early_smbus.c @@ -128,7 +128,6 @@ u8 smbus_read_byte(u8 dimm, u8 offset) return val; } - /** * Enable the smbus on vt8237r-based systems */ @@ -137,11 +136,17 @@ void enable_smbus(void) device_t dev; /* Power management controller */ + dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT8237R_LPC), 0); - if (dev == PCI_DEV_INVALID) - die("Power management controller not found\r\n"); + if (dev == PCI_DEV_INVALID) { + /* Power management controller */ + dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_VT8237S_LPC), 0); + if (dev == PCI_DEV_INVALID) + die("Power management controller not found\r\n"); + } /* 7 = SMBus Clock from RTC 32.768KHz * 5 = Internal PLL reset from susp @@ -213,17 +218,253 @@ void smbus_fixup(const struct mem_controller *ctrl) PRINT_DEBUG("Done\r\n"); } +/* fixme better separate the NB and SB, will done once it works */ + +void vt8237_sb_enable_fid_vid(void) { + device_t dev; + device_t devctl; + + /* Power management controller */ + dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_VT8237R_LPC), 0); + + if (dev == PCI_DEV_INVALID) { + /* Power management controller */ + dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_VT8237S_LPC), 0); + if (dev == PCI_DEV_INVALID) + return; + + devctl = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_VT8237_VLINK), 0); + if (devctl == PCI_DEV_INVALID) + return; + + { + u8 tmp; + tmp = pci_read_config8(devctl, 0xec); + print_debug("EC is "); + print_debug_hex8(tmp); + print_debug(" E5 is "); + tmp = pci_read_config8(dev, 0xe5); + print_debug_hex8(tmp); + + } + /* Set ACPI base address to I/O VT8237R_ACPI_IO_BASE. */ + pci_write_config16(dev, 0x88, VT8237R_ACPI_IO_BASE | 0x1); + /* Enable ACPI accessm RTC signal gated with PSON. */ + pci_write_config8(dev, 0x81, 0x84); + /* Allow SLP# signal to assert LDTSTOP_L. + * Will work for C3 and for FID/VID change. + */ + + /* fixme */ + outb(0xff, VT8237R_ACPI_IO_BASE + 0x50); //fixme maybe not needed + +// outb(0x4, VT8237R_ACPI_IO_BASE + 0x50); //fixme maybe not needed + + /* it seems for AMD LDTSTP is connected not to SLP anymore */ + /* enable 0: DPSLP# / DPRSTP# / VRDSLP */ + + /* Enable SATA LED, VR timer = 100us + * Enable DPSLP# / DPRSTP# / VRDSLP - WARNING LDTSTP connetcs to some of those pins! (and not to SLP as on R ver) + */ + //fixme + pci_write_config8(dev, 0xe5, 0x69); + + /* REQ5 as PCI request input - should be together with INTE-INTH. + * Fast VR timer disable - need for LDTSTP signal + */ + pci_write_config8(dev, 0xe4, 0xa5); + + /* reduce further the STPCLK/LDTSTP signal to 5us */ + + pci_write_config8(dev, 0xec, 0x4); + /* Host Bus Power Management Control, maybe not needed */ + pci_write_config8(dev, 0x8c, 0x5); + + /* so the chip knows we are on AMD */ + pci_write_config8(devctl, 0x7c, 0x77); + + devctl = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA, + 0x2336), 0); + if (devctl == PCI_DEV_INVALID) + return; + /* Enable C2NOW delay to PSTATECTL VID / FID Change Delay to P-State Control */ + pci_write_config8(devctl, 0xa6, 0x83); + + //return; //FIXME fall through some revs have it old way + } + /* Set ACPI base address to I/O VT8237R_ACPI_IO_BASE. */ + pci_write_config16(dev, 0x88, VT8237R_ACPI_IO_BASE | 0x1); + /* Enable ACPI accessm RTC signal gated with PSON. */ + pci_write_config8(dev, 0x81, 0x84); + /* Allow SLP# signal to assert LDTSTOP_L. + * Will work for C3 and for FID/VID change. + */ + outb(0x1, VT8237R_ACPI_IO_BASE + 0x11); +} + void enable_rom_decode(void) { device_t dev; - /* Bus Control and Power Management */ + /* Power management controller */ dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT8237R_LPC), 0); - if (dev == PCI_DEV_INVALID) - die("SB not found\r\n"); + if (dev == PCI_DEV_INVALID) { + /* Power management controller */ + dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_VT8237S_LPC), 0); + if (dev == PCI_DEV_INVALID) + return; + } /* ROM decode last 1MB FFC00000 - FFFFFFFF */ pci_write_config8(dev, 0x41, 0x7f); } + +void vt8237_early_spi_init(void) { + device_t dev; + volatile u16 *spireg; + u32 tmp; + + /* Bus Control and Power Management */ + dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_VT8237S_LPC), 0); + + if (dev == PCI_DEV_INVALID) + die("SB not found\r\n"); + + /* put SPI base 20 d0 fe */ + tmp = pci_read_config32(dev, 0xbc); + pci_write_config32(dev, 0xbc, (VT8237S_SPI_MEM_BASE >> 8) | (tmp & 0xFF000000)); + + /* set SPI clock to 33MHz */ + spireg = (u16 *) (VT8237S_SPI_MEM_BASE + 0x6c); + (*spireg) &= 0xff00; +} + +/* 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; + device_t dev; + u32 tmp; + u8 status; + u16 *rom_write; + unsigned int checksum; + int i; + + /* Network adapter */ + dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_8233_7), 0); + + if (dev == PCI_DEV_INVALID) { + print_err("Network is disabled, please enable\n"); + return 0; + } + + tmp = pci_read_config32(dev, 0x5c); + /* enable ERDBG */ + tmp |= 0x08000000; + pci_write_config32(dev, 0x5c, tmp); + + status = ((pci_read_config32(dev, 0x5c) >> 24) & 0x3); + + if (status == 3) { + /* network controller OK, EEPROM loaded */ + return 0; + } + + if (rom == NULL) { + print_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_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_write_config32(dev, 0x58, (15 << 16) | tmp); + + tmp = pci_read_config32(dev, 0x5c); + pci_write_config32(dev, 0x5c, tmp | 0x01000000); /* toggle SEEPR */ + + /* Yes, this is a mess, but it's the easiest way to do it. */ + while ( (((pci_read_config32(dev, 0x5c) >> 25) & 1) == 0) + && (loops < LAN_TIMEOUT)) + ++loops; + + if (loops >= LAN_TIMEOUT) { + print_err("Timout - LAN controller did not accept configuration\n"); + return 0; + } + + /* we are done, config will be used after PCIRST# */ + return 1; +} diff --git a/src/southbridge/via/vt8237r/vt8237r_lpc.c b/src/southbridge/via/vt8237r/vt8237r_lpc.c index d4721a23f3..4d24e6161d 100644 --- a/src/southbridge/via/vt8237r/vt8237r_lpc.c +++ b/src/southbridge/via/vt8237r/vt8237r_lpc.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2007 Rudolf Marek + * Copyright (C) 2007, 2008 Rudolf Marek * * 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 @@ -116,6 +116,8 @@ static void setup_ioapic(u32 ioapic_base) } } +static void southbridge_init_common(struct device *dev); + /** Set up PCI IRQ routing, route everything through APIC. */ static void pci_routing_fixup(struct device *dev) { @@ -173,6 +175,7 @@ static void setup_pm(device_t dev) /* 7 = stp to sust delay 1msec * 6 = SUSST# Deasserted Before PWRGD for STD + * 4 = PWRGOOD reset on VT8237A/S * 3 = GPO26/GPO27 is GPO * 2 = Disable Alert on Lan */ @@ -181,14 +184,6 @@ static void setup_pm(device_t dev) /* Disable GP3 timer. */ pci_write_config8(dev, 0x98, 0); - /* Enable SATA LED, disable special CPU Frequency Change - - * GPIO28 GPIO22 GPIO29 GPIO23 are GPIOs. - */ - pci_write_config8(dev, 0xe5, 0x9); - - /* REQ5 as PCI request input - should be together with INTE-INTH. */ - pci_write_config8(dev, 0xe4, 0x4); - /* Enable ACPI accessm RTC signal gated with PSON. */ pci_write_config8(dev, 0x81, 0x84); @@ -222,6 +217,30 @@ static void setup_pm(device_t dev) /* SCI is generated for RTC/pwrBtn/slpBtn. */ outw(0x001, VT8237R_ACPI_IO_BASE + 0x04); +} + + +static void vt8237r_init(struct device *dev) { + u8 enables; + + /* Enable SATA LED, disable special CPU Frequency Change - + * GPIO28 GPIO22 GPIO29 GPIO23 are GPIOs. + */ + pci_write_config8(dev, 0xe5, 0x9); + + /* REQ5 as PCI request input - should be together with INTE-INTH. */ + pci_write_config8(dev, 0xe4, 0x4); + + /* Set bit 3 of 0x4f (use INIT# as CPU reset). */ + enables = pci_read_config8(dev, 0x4f); + enables |= 0x08; + pci_write_config8(dev, 0x4f, enables); + + /* Set Read Pass Write Control Enable (force A2 from APIC FSB to low). */ + pci_write_config8(dev, 0x48, 0x8c); + + southbridge_init_common(dev); + /* FIXME: Intel needs more bit set for C2/C3. */ /* Allow SLP# signal to assert LDTSTOP_L. @@ -230,7 +249,44 @@ static void setup_pm(device_t dev) outb(0x1, VT8237R_ACPI_IO_BASE + 0x11); } -static void vt8237r_init(struct device *dev) +static void vt8237s_init(struct device *dev) +{ + u32 tmp; + + /* put SPI base VT8237S_SPI_MEM_BASE */ + tmp = pci_read_config32(dev, 0xbc); + pci_write_config32(dev, 0xbc, (VT8237S_SPI_MEM_BASE >> 8) | (tmp & 0xFF000000)); + + /* Enable SATA LED, VR timer = 100us, VR timer should be fixed */ + + pci_write_config8(dev, 0xe5, 0x69); + + /* REQ5 as PCI request input - should be together with INTE-INTH. + * Fast VR timer disable - need for LDTSTOP_L signal + */ + pci_write_config8(dev, 0xe4, 0xa5); + + /* reduce further the STPCLK/LDTSTP signal to 5us */ + + pci_write_config8(dev, 0xec, 0x4); + + /* Host Bus Power Management Control, maybe not needed */ + pci_write_config8(dev, 0x8c, 0x5); + + /* Enable HPET at VT8237R_HPET_ADDR., does not work correctly on R */ + pci_write_config32(dev, 0x68, (VT8237R_HPET_ADDR | 0x80)); + + southbridge_init_common(dev); + + /* FIXME: Intel needs more bit set for C2/C3. */ + + /* Allow SLP# signal to assert LDTSTOP_L. + * Will work for C3 and for FID/VID change. FIXME FIXME, pre rev A2 + */ + outb(0xff, VT8237R_ACPI_IO_BASE + 0x50); + dump_south(dev); +} +static void vt8237_common_init(struct device *dev) { u8 enables, byte; @@ -275,7 +331,7 @@ static void vt8237r_init(struct device *dev) /* Delay transaction control */ pci_write_config8(dev, 0x43, 0xb); - /* I/O recovery time */ + /* I/O recovery time, default IDE routing */ pci_write_config8(dev, 0x4c, 0x44); /* ROM memory cycles go to LPC. */ @@ -288,25 +344,14 @@ static void vt8237r_init(struct device *dev) * bit 1=1 works for Aaron at VIA, bit 1=0 works for jakllsch * 0 Dynamic Clock Gating Main Switch (1=Enable) */ - pci_write_config8(dev, 0x5b, 0x9); - - /* Set Read Pass Write Control Enable (force A2 from APIC FSB to low). */ - pci_write_config8(dev, 0x48, 0x8c); + pci_write_config8(dev, 0x5b, 0xb); /* Set 0x58 to 0x43 APIC and RTC. */ pci_write_config8(dev, 0x58, 0x43); - /* Set bit 3 of 0x4f (use INIT# as CPU reset). */ - enables = pci_read_config8(dev, 0x4f); - enables |= 0x08; - pci_write_config8(dev, 0x4f, enables); - /* Enable serial IRQ, 6PCI clocks. */ pci_write_config8(dev, 0x52, 0x9); - /* Enable HPET at VT8237R_HPET_ADDR. */ - pci_write_config32(dev, 0x68, (VT8237R_HPET_ADDR | 0x80)); - /* Power management setup */ setup_pm(dev); @@ -348,25 +393,40 @@ static void init_keyboard(struct device *dev) init_pc_keyboard(0x60, 0x64, 0); } -static void southbridge_init(struct device *dev) +static void southbridge_init_common(struct device *dev) { - vt8237r_init(dev); + vt8237_common_init(dev); pci_routing_fixup(dev); setup_ioapic(VT8237R_APIC_BASE); setup_i8259(); init_keyboard(dev); } -static const struct device_operations vt8237r_lpc_ops = { +static const struct device_operations vt8237r_lpc_ops_s = { .read_resources = vt8237r_read_resources, .set_resources = pci_dev_set_resources, .enable_resources = vt8237r_enable_resources, - .init = &southbridge_init, + .init = &vt8237s_init, .scan_bus = scan_static_bus, }; -static const struct pci_driver lpc_driver __pci_driver = { - .ops = &vt8237r_lpc_ops, + +static const struct device_operations vt8237r_lpc_ops_r = { + .read_resources = vt8237r_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = vt8237r_enable_resources, + .init = &vt8237r_init, + .scan_bus = scan_static_bus, +}; + +static const struct pci_driver lpc_driver_r __pci_driver = { + .ops = &vt8237r_lpc_ops_r, .vendor = PCI_VENDOR_ID_VIA, .device = PCI_DEVICE_ID_VIA_VT8237R_LPC, }; + +static const struct pci_driver lpc_driver_s __pci_driver = { + .ops = &vt8237r_lpc_ops_s, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_VT8237S_LPC, +}; diff --git a/src/southbridge/via/vt8237r/vt8237r_sata.c b/src/southbridge/via/vt8237r/vt8237r_sata.c index ecdafdfd88..77d7b0c3e2 100644 --- a/src/southbridge/via/vt8237r/vt8237r_sata.c +++ b/src/southbridge/via/vt8237r/vt8237r_sata.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2007 Rudolf Marek + * Copyright (C) 2007, 2008 Rudolf Marek * * 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 @@ -24,7 +24,7 @@ #define SATA_MISC_CTRL 0x45 -static void sata_init(struct device *dev) +static void sata_i_init(struct device *dev) { u8 reg; @@ -39,19 +39,82 @@ static void sata_init(struct device *dev) pci_write_config8(dev, PCI_CLASS_DEVICE, 0x1); reg |= 0x80; /* Sub Class Write Protect on */ pci_write_config8(dev, SATA_MISC_CTRL, reg); + + return; } -static const struct device_operations sata_ops = { +static void sata_ii_init(struct device *dev) { + u8 reg; + + sata_i_init(dev); + + /* analog black magic, you may or may not need to adjust 0x60-0x6f, depends on PCB */ + + /* Analog PHY - gen1 + * CDR bandwidth [6:5] = 3 + * Squelch Window Select [4:3] = 1 + * CDR Charge Pump [2:0] = 1 + */ + + pci_write_config8(dev, 0x64, 0x49); + + /* adjust driver current source value to 9 */ + reg = pci_read_config8(dev, 0x65); + reg &= 0xf0; + reg |= 0x9; + pci_write_config8(dev, 0x65, reg); + + /* set all manual termination 50ohm bits [2:0] and enable [4] */ + reg = pci_read_config8(dev, 0x6a); + reg |= 0xf; + pci_write_config8(dev, 0x6a, reg); + + /* Analog PHY - gen2 + * CDR bandwidth [5:4] = 2 + * Pre / De-emphasis Level [7:6] controls bits [3:2], rest in 0x6e + * CDR Charge Pump [2:0] = 1 + */ + + reg = pci_read_config8(dev, 0x6f); + reg &= 0x08; + reg |= 0x61; + pci_write_config8(dev, 0x6f, reg); + + /* check if staggered spinup is supported */ + reg = pci_read_config8(dev, 0x83); + if ((reg & 0x8) == 0) { + /* start OOB sequence on both drives */ + reg |= 0x30; + pci_write_config8(dev, 0x83, reg); + } +} + +static const struct device_operations sata_i_ops = { .read_resources = pci_dev_read_resources, .set_resources = pci_dev_set_resources, .enable_resources = pci_dev_enable_resources, - .init = sata_init, + .init = sata_i_init, .enable = 0, .ops_pci = 0, }; -static const struct pci_driver northbridge_driver __pci_driver = { - .ops = &sata_ops, +static const struct device_operations sata_ii_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = sata_ii_init, + .enable = 0, + .ops_pci = 0, +}; + +static const struct pci_driver northbridge_driver_ii __pci_driver = { + .ops = &sata_ii_ops, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_VT8237_SATA, +}; + +static const struct pci_driver northbridge_driver_i __pci_driver = { + .ops = &sata_i_ops, .vendor = PCI_VENDOR_ID_VIA, .device = PCI_DEVICE_ID_VIA_VT6420_SATA, };