diff --git a/southbridge/nvidia/mcp55/stage1.c b/southbridge/nvidia/mcp55/stage1.c index aa7651d268..fcae494f48 100644 --- a/southbridge/nvidia/mcp55/stage1.c +++ b/southbridge/nvidia/mcp55/stage1.c @@ -26,20 +26,20 @@ #include #include #include "mcp55.h" -#define pci_read_config32(bus, dev, where) pci_cf8_conf1.read32(NULL, bus, dev, where) -#define pci_write_config32(bus, dev, where, what) pci_cf8_conf1.write32(NULL, bus, dev, where, what) +#include "stage1.h" #warning fix disgusting define of MCP55_NUM it is mainboard dependent #define MCP55_NUM 1 -static int set_ht_link_mcp55(u8 ht_c_num) +int set_ht_link_mcp55(u8 ht_c_num) { + int set_ht_link_buffer_counts_chain(u8 ht_c_num, unsigned vendorid, unsigned val); unsigned vendorid = 0x10de; unsigned val = 0x01610109; /* Nvidia mcp55 hardcode, hw can not set it automatically */ return set_ht_link_buffer_counts_chain(ht_c_num, vendorid, val); } -static void setup_ss_table(unsigned index, unsigned where, unsigned control, const unsigned int *register_values, int max) +void setup_ss_table(unsigned index, unsigned where, unsigned control, const unsigned int *register_values, int max) { int i; @@ -138,14 +138,6 @@ static void mcp55_early_clear_port(unsigned mcp55_num, unsigned *busn, unsigned } -} -static void delayx(u8 value) { -#if 1 - int i; - for(i=0;i<0x8000;i++) { - outb(value, 0x80); - } -#endif } static void mcp55_early_pcie_setup(unsigned busnx, unsigned devnx, unsigned anactrl_io_base, unsigned pci_e_x) @@ -154,11 +146,10 @@ static void mcp55_early_pcie_setup(unsigned busnx, unsigned devnx, unsigned anac u32 pll_ctrl; u32 dword; int i; - u32 dev; - // dev = PCI_BDF(busnx, devnx+1, 1); - dword = pci_read_config32(busnx, (devnx+1)<<3 | 1, 0xe4); + u32 bdf = PCI_BDF(busnx, devnx+1, 1); + dword = pci_read_config32(bdf, 0xe4); dword |= 0x3f0; // disable it at first - pci_write_config32(busnx, (devnx+1)<<3 | 1, 0xe4, dword); + pci_write_config32(bdf, 0xe4, dword); for(i=0; i<3; i++) { tgio_ctrl = inl(anactrl_io_base + 0xcc); @@ -178,14 +169,14 @@ static void mcp55_early_pcie_setup(unsigned busnx, unsigned devnx, unsigned anac outl(tgio_ctrl, anactrl_io_base + 0xcc); // wait 100us - delayx(1); + udelay(100); - dword = pci_read_config32(busnx, (devnx+1)<<3 | 1, 0xe4); + dword = pci_read_config32(bdf, 0xe4); dword &= ~(0x3f0); // enable - pci_write_config32(busnx, (devnx+1)<<3 | 1, 0xe4, dword); + pci_write_config32(bdf, 0xe4, dword); // need to wait 100ms - delayx(1000); + udelay(100000); } static void mcp55_early_setup(unsigned mcp55_num, unsigned *busn, unsigned *devn, unsigned *io_base, unsigned *pci_e_x) @@ -380,7 +371,7 @@ static void mcp55_early_setup(unsigned mcp55_num, unsigned *busn, unsigned *devn #endif -static int mcp55_early_setup_x(void) +int mcp55_early_setup_x(void) { /*find out how many mcp55 we have */ unsigned busn[HT_CHAIN_NUM_MAX]; @@ -403,8 +394,9 @@ static int mcp55_early_setup_x(void) busnx = ht_c_index * HT_CHAIN_BUSN_D; for(devnx=0;devnx<0x20;devnx++) { u32 id; - // dev = PCI_BDF(busnx, devnx, 0); - id = pci_read_config32(busnx, devnx<<3, PCI_VENDOR_ID); + u32 bdf; + bdf = PCI_BDF(busnx, devnx, 0); + id = pci_read_config32(bdf, PCI_VENDOR_ID); if(id == 0x036910de) { busn[mcp55_num] = busnx; devn[mcp55_num] = devnx; @@ -431,4 +423,49 @@ out: } +/* this was in separate file but I am trying to gather the utility junk + * into one file. + */ + +unsigned int get_sbdn(unsigned int bus) +{ +#warning bus ignore in get_sbdn; do we care + /* Find the device. + */ + u32 bdf; + if (!pci_locate_device(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP55_HT, &bdf)) { + die("PCI_DEVICE_ID_NVIDIA_MCP55_HT not found\r\n"); + } + + return (bdf>>15) & 0x1f; + +} + +void hard_reset(void) +{ +#warning what is set_bios_reset +// set_bios_reset(); + + /* full reset */ + outb(0x0a, 0x0cf9); + outb(0x0e, 0x0cf9); +} + +void enable_fid_change_on_sb(unsigned sbbusn, unsigned sbdn) +{ +/* default value for mcp55 is good */ + /* set VFSMAF ( VID/FID System Management Action Field) to 2 */ + +} + +void soft_reset(void) +{ +#warning what is set_bios_reset +// set_bios_reset(); +#if 1 + /* link reset */ + outb(0x02, 0x0cf9); + outb(0x06, 0x0cf9); +#endif +} diff --git a/southbridge/nvidia/mcp55/stage1.h b/southbridge/nvidia/mcp55/stage1.h new file mode 100644 index 0000000000..5d0c056fba --- /dev/null +++ b/southbridge/nvidia/mcp55/stage1.h @@ -0,0 +1,24 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 Ronald G. Minnich + * + * 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 + */ +#define pci_read_config32(bdf, where) pci_cf8_conf1.read32(bdf, where) +#define pci_write_config32(bdf, where, what) pci_cf8_conf1.write32(bdf, where, what) +#define pci_read_config16(bdf, where) pci_cf8_conf1.read32(bdf, where) +#define pci_write_config16(bdf, where, what) pci_cf8_conf1.write32(bdf, where, what) +#define pci_locate_device(vid, did, slot) pci_cf8_conf1.find(vid, did, slot) diff --git a/southbridge/nvidia/mcp55/stage1_smbus.c b/southbridge/nvidia/mcp55/stage1_smbus.c index 21bf464561..13dcf09376 100644 --- a/southbridge/nvidia/mcp55/stage1_smbus.c +++ b/southbridge/nvidia/mcp55/stage1_smbus.c @@ -5,6 +5,7 @@ * Written by Yinghai Lu for Tyan Computer. * Copyright (C) 2006,2007 AMD * Written by Yinghai Lu for AMD. + * Copyright (C) 2008 Ronald G. Minnich (for v3) * * 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 @@ -26,73 +27,222 @@ #include #include #include "mcp55.h" -#define pci_read_config32(bus, dev, where) pci_cf8_conf1.read32(NULL, bus, dev, where) -#define pci_write_config32(bus, dev, where, what) pci_cf8_conf1.write32(NULL, bus, dev, where, what) -#define pci_read_config16(bus, dev, where) pci_cf8_conf1.read32(NULL, bus, dev, where) -#define pci_write_config16(bus, dev, where, what) pci_cf8_conf1.write32(NULL, bus, dev, where, what) +#include "stage1.h" #include "mcp55_smbus.h" #define SMBUS0_IO_BASE 0x1000 #define SMBUS1_IO_BASE (0x1000+(1<<8)) /*SIZE 0x40 */ -static void enable_smbus(void) +int smbus_wait_until_ready(u16 smbus_io_base) { - u32 dev; - dev = pci_locate_device(PCI_ID(0x10de, 0x0368), 0); -#if 0 - if (dev == PCI_DEV_INVALID) { + unsigned long loops; + loops = SMBUS_TIMEOUT; + do { + unsigned char val; + smbus_delay(); + val = inb(smbus_io_base + SMBHSTSTAT); + val &= 0x1f; + if (val == 0) { + return 0; + } + outb(val,smbus_io_base + SMBHSTSTAT); + } while(--loops); + return -2; +} + +int smbus_wait_until_done(u16 smbus_io_base) +{ + unsigned long loops; + loops = SMBUS_TIMEOUT; + do { + unsigned char val; + smbus_delay(); + + val = inb(smbus_io_base + SMBHSTSTAT); + if ( (val & 0xff) != 0) { + return 0; + } + } while(--loops); + return -3; +} + +int do_smbus_recv_byte(u16 smbus_io_base, u8 device) +{ + u8 global_status_register; + u8 byte; + + /* set the device I'm talking too */ + outb(((device & 0x7f) << 1)|1 , smbus_io_base + SMBXMITADD); + smbus_delay(); + + /* byte data recv */ + outb(0x05, smbus_io_base + SMBHSTPRTCL); + smbus_delay(); + + /* poll for transaction completion */ + if (smbus_wait_until_done(smbus_io_base) < 0) { + return -3; + } + + global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80; /* lose check */ + + /* read results of transaction */ + byte = inb(smbus_io_base + SMBHSTCMD); + + if (global_status_register != 0x80) { // loose check, otherwise it should be 0 + return -1; + } + return byte; +} + +int do_smbus_send_byte(u16 smbus_io_base, u8 device, u8 val) +{ + u8 global_status_register; + + outb(val, smbus_io_base + SMBHSTDAT0); + smbus_delay(); + + /* set the command... */ + outb(val, smbus_io_base + SMBHSTCMD); + smbus_delay(); + + /* set the device I'm talking too */ + outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBXMITADD); + smbus_delay(); + + /* set up for a byte data write */ + outb(0x04, smbus_io_base + SMBHSTPRTCL); + smbus_delay(); + + /* poll for transaction completion */ + if (smbus_wait_until_done(smbus_io_base) < 0) { + return -3; + } + global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80; /* lose check */; + + if (global_status_register != 0x80) { + return -1; + } + return 0; +} + +int do_smbus_read_byte(u16 smbus_io_base, u8 device, u8 address) +{ + u8 global_status_register; + u8 byte; + + /* set the device I'm talking too */ + outb(((device & 0x7f) << 1)|1 , smbus_io_base + SMBXMITADD); + smbus_delay(); + /* set the command/address... */ + outb(address & 0xff, smbus_io_base + SMBHSTCMD); + smbus_delay(); + /* byte data read */ + outb(0x07, smbus_io_base + SMBHSTPRTCL); + smbus_delay(); + + /* poll for transaction completion */ + if (smbus_wait_until_done(smbus_io_base) < 0) { + return -3; + } + + global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80; /* lose check */ + + /* read results of transaction */ + byte = inb(smbus_io_base + SMBHSTDAT0); + + if (global_status_register != 0x80) { // lose check, otherwise it should be 0 + return -1; + } + return byte; +} + +int do_smbus_write_byte(u16 smbus_io_base, u8 device, u8 address, u8 val) +{ + u8 global_status_register; + + outb(val, smbus_io_base + SMBHSTDAT0); + smbus_delay(); + + /* set the device I'm talking too */ + outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBXMITADD); + smbus_delay(); + + outb(address & 0xff, smbus_io_base + SMBHSTCMD); + smbus_delay(); + + /* set up for a byte data write */ + outb(0x06, smbus_io_base + SMBHSTPRTCL); + smbus_delay(); + + /* poll for transaction completion */ + if (smbus_wait_until_done(smbus_io_base) < 0) { + return -3; + } + global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80; /* lose check */; + + if (global_status_register != 0x80) { + return -1; + } + return 0; +} + + +void enable_smbus(void) +{ + u32 bdf; + if (!pci_locate_device(0x10de, 0x0368, &bdf)) { die("SMBUS controller not found\r\n"); } - printk(BIOS_DEBUG, "SMBus controller enabled\r\n"); -#endif + printk(BIOS_DEBUG, "SMBus controller enabled\n"); /* set smbus iobase */ - pci_write_config32(0, dev, 0x20, SMBUS0_IO_BASE | 1); - pci_write_config32(0, dev, 0x24, SMBUS1_IO_BASE | 1); + pci_write_config32(bdf, 0x20, SMBUS0_IO_BASE | 1); + pci_write_config32(bdf, 0x24, SMBUS1_IO_BASE | 1); /* Set smbus iospace enable */ - pci_write_config16(0, dev, 0x4, 0x01); + pci_write_config16(bdf, 0x4, 0x01); /* clear any lingering errors, so the transaction will run */ outb(inb(SMBUS0_IO_BASE + SMBHSTSTAT), SMBUS0_IO_BASE + SMBHSTSTAT); outb(inb(SMBUS1_IO_BASE + SMBHSTSTAT), SMBUS1_IO_BASE + SMBHSTSTAT); } -static u8 smbus_recv_byte(u8 device) +u8 smbus_recv_byte(u8 device) { return do_smbus_recv_byte(SMBUS0_IO_BASE, device); } -static u8 smbus_send_byte(u8 device,u8 val) +u8 smbus_send_byte(u8 device,u8 val) { return do_smbus_send_byte(SMBUS0_IO_BASE, device, val); } -static u8 smbus_read_byte(u8 device, u8 address) +u8 smbus_read_byte(u8 device, u8 address) { return do_smbus_read_byte(SMBUS0_IO_BASE, device, address); } -static u8 smbus_write_byte(u8 device, u8 address, u8 val) +u8 smbus_write_byte(u8 device, u8 address, u8 val) { return do_smbus_write_byte(SMBUS0_IO_BASE, device, address, val); } -static u8 smbusx_recv_byte(u8 smb_index, u8 device) +u8 smbusx_recv_byte(u8 smb_index, u8 device) { return do_smbus_recv_byte(SMBUS0_IO_BASE + (smb_index<<8), device); } -static u8 smbusx_send_byte(u8 smb_index, u8 device, u8 val) +u8 smbusx_send_byte(u8 smb_index, u8 device, u8 val) { return do_smbus_send_byte(SMBUS0_IO_BASE + (smb_index<<8), device, val); } -static u8 smbusx_read_byte(u8 smb_index, u8 device, u8 address) +u8 smbusx_read_byte(u8 smb_index, u8 device, u8 address) { return do_smbus_read_byte(SMBUS0_IO_BASE + (smb_index<<8), device, address); } -static u8 smbusx_write_byte(u8 smb_index, u8 device, u8 address, u8 val) +u8 smbusx_write_byte(u8 smb_index, u8 device, u8 address, u8 val) { return do_smbus_write_byte(SMBUS0_IO_BASE + (smb_index<<8), device, address, val); } diff --git a/southbridge/nvidia/mcp55/stage1_usbdebug.c b/southbridge/nvidia/mcp55/stage1_usbdebug.c new file mode 100644 index 0000000000..eee383841d --- /dev/null +++ b/southbridge/nvidia/mcp55/stage1_usbdebug.c @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2004 Tyan Computer + * Written by Yinghai Lu for Tyan Computer. + * Copyright (C) 2006,2007 AMD + * Written by Yinghai Lu for AMD. + * + * 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 + */ + +/* This should probably be a config variable. */ +#if HT_CHAIN_END_UNITID_BASE != 0x20 + #define MCP55_DEVN_BASE HT_CHAIN_END_UNITID_BASE +#else + #define MCP55_DEVN_BASE HT_CHAIN_UNITID_BASE +#endif + +#define EHCI_BAR_INDEX 0x10 +#define EHCI_BAR 0xFEF00000 +#define EHCI_DEBUG_OFFSET 0x98 + +#include "pci.h" +#include "stage1.h" +static void set_debug_port(unsigned port) +{ + u32 dword; + u32 bdf = PCI_BDF(0, MCP55_DEVN_BASE+2, 1); + dword = pci_read_config32(bdf, 0x74); + dword &= ~(0xf<<12); + dword |= (port<<12); + pci_write_config32(bdf, 0x74, dword); + +} + +static void mcp55_enable_usbdebug_direct(unsigned port) +{ + u32 bdf = PCI_BDF(0, MCP55_DEVN_BASE+2, 1); + set_debug_port(port); + pci_write_config32(bdf, EHCI_BAR_INDEX, EHCI_BAR); + pci_write_config8(bdf, 0x04, 0x2); // mem space enable +} +