Author: rminnich Date: 2008-08-10 23:20:46 +0200 (Sun, 10 Aug 2008) New Revision: 731
Added: coreboot-v3/southbridge/nvidia/mcp55/stage1.h coreboot-v3/southbridge/nvidia/mcp55/stage1_usbdebug.c Modified: coreboot-v3/southbridge/nvidia/mcp55/stage1.c coreboot-v3/southbridge/nvidia/mcp55/stage1_smbus.c Log: Add stage1.h to the files for standard defines used by all stage1 functions.
Modify all functions to use the new v3 pci operations calling conventions. use udelay for delays.
Add the USB debug support function. This is compiling pretty well for me save for the missing hypertransport function.
Signed-off-by: Ronald G. Minnich rminnich@gmail.com Acked-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Modified: coreboot-v3/southbridge/nvidia/mcp55/stage1.c =================================================================== --- coreboot-v3/southbridge/nvidia/mcp55/stage1.c 2008-08-10 00:20:24 UTC (rev 730) +++ coreboot-v3/southbridge/nvidia/mcp55/stage1.c 2008-08-10 21:20:46 UTC (rev 731) @@ -26,20 +26,20 @@ #include <cpu.h> #include <amd/k8/k8.h> #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;
@@ -139,14 +139,6 @@
} -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 @@ 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 @@ 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 @@
#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 @@ 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 @@ }
+/* 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 +} +
Added: coreboot-v3/southbridge/nvidia/mcp55/stage1.h =================================================================== --- coreboot-v3/southbridge/nvidia/mcp55/stage1.h (rev 0) +++ coreboot-v3/southbridge/nvidia/mcp55/stage1.h 2008-08-10 21:20:46 UTC (rev 731) @@ -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)
Modified: coreboot-v3/southbridge/nvidia/mcp55/stage1_smbus.c =================================================================== --- coreboot-v3/southbridge/nvidia/mcp55/stage1_smbus.c 2008-08-10 00:20:24 UTC (rev 730) +++ coreboot-v3/southbridge/nvidia/mcp55/stage1_smbus.c 2008-08-10 21:20:46 UTC (rev 731) @@ -5,6 +5,7 @@ * Written by Yinghai Lu yhlu@tyan.com for Tyan Computer. * Copyright (C) 2006,2007 AMD * Written by Yinghai Lu yinghai.lu@amd.com 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 <device/device.h> #include <device/pci.h> #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); }
Added: coreboot-v3/southbridge/nvidia/mcp55/stage1_usbdebug.c =================================================================== --- coreboot-v3/southbridge/nvidia/mcp55/stage1_usbdebug.c (rev 0) +++ coreboot-v3/southbridge/nvidia/mcp55/stage1_usbdebug.c 2008-08-10 21:20:46 UTC (rev 731) @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2004 Tyan Computer + * Written by Yinghai Lu yhlu@tyan.com for Tyan Computer. + * Copyright (C) 2006,2007 AMD + * Written by Yinghai Lu yinghai.lu@amd.com 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 +} +