Author: rminnich Date: 2008-08-07 01:31:35 +0200 (Thu, 07 Aug 2008) New Revision: 724
Added: coreboot-v3/southbridge/nvidia/mcp55/mcp55_smbus.h coreboot-v3/southbridge/nvidia/mcp55/stage1_smbus.c Modified: coreboot-v3/mainboard/gigabyte/m57sli/Makefile Log: SMBUS support for mcp55 and v3. Signed-off-by: Ronald G. Minnich rminnich@gmail.com Acked-by: Peter Stuge peter@stuge.se
Modified: coreboot-v3/mainboard/gigabyte/m57sli/Makefile =================================================================== --- coreboot-v3/mainboard/gigabyte/m57sli/Makefile 2008-08-05 02:59:00 UTC (rev 723) +++ coreboot-v3/mainboard/gigabyte/m57sli/Makefile 2008-08-06 23:31:35 UTC (rev 724) @@ -20,7 +20,8 @@ ##
STAGE0_MAINBOARD_OBJ := $(obj)/mainboard/$(MAINBOARDDIR)/stage1.o \ - $(obj)/mainboard/$(MAINBOARDDIR)/option_table.c + $(obj)/mainboard/$(MAINBOARDDIR)/option_table.c \ + $(obj)/southbridge/nvidia/mcp55/stage1_smbus.o
INITRAM_SRC = $(src)/mainboard/$(MAINBOARDDIR)/initram.c
Added: coreboot-v3/southbridge/nvidia/mcp55/mcp55_smbus.h =================================================================== --- coreboot-v3/southbridge/nvidia/mcp55/mcp55_smbus.h (rev 0) +++ coreboot-v3/southbridge/nvidia/mcp55/mcp55_smbus.h 2008-08-06 23:31:35 UTC (rev 724) @@ -0,0 +1,197 @@ +/* + * 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 + */ + +#include <device/smbus_def.h> + +#define SMBHSTSTAT 0x1 +#define SMBHSTPRTCL 0x0 +#define SMBHSTCMD 0x3 +#define SMBXMITADD 0x2 +#define SMBHSTDAT0 0x4 +#define SMBHSTDAT1 0x5 + +/* Between 1-10 seconds, We should never timeout normally + * Longer than this is just painful when a timeout condition occurs. + */ +#define SMBUS_TIMEOUT (100*1000*10) + +static inline void smbus_delay(void) +{ + /* let's hope this is not optimized out */ + (void) intb(0x80); +} + +static int smbus_wait_until_ready(u16 smbus_io_base) +{ + 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; +} + +static 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; +} + +static int do_smbus_recv_byte(u16 smbus_io_base, unsigned u8) +{ + 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; +} + +static 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; +} + +static 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; +} + +static 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; +} +
Added: coreboot-v3/southbridge/nvidia/mcp55/stage1_smbus.c =================================================================== --- coreboot-v3/southbridge/nvidia/mcp55/stage1_smbus.c (rev 0) +++ coreboot-v3/southbridge/nvidia/mcp55/stage1_smbus.c 2008-08-06 23:31:35 UTC (rev 724) @@ -0,0 +1,99 @@ +/* + * 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 + */ + +#include <console.h> +#include <io.h> +#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 "mcp55_smbus.h" + +#define SMBUS0_IO_BASE 0x1000 +#define SMBUS1_IO_BASE (0x1000+(1<<8)) +/*SIZE 0x40 */ + +static void enable_smbus(void) +{ + u32 dev; + dev = pci_locate_device(PCI_ID(0x10de, 0x0368), 0); +#if 0 + if (dev == PCI_DEV_INVALID) { + die("SMBUS controller not found\r\n"); + } + + printk(BIOS_DEBUG, "SMBus controller enabled\r\n"); +#endif + /* set smbus iobase */ + pci_write_config32(0, dev, 0x20, SMBUS0_IO_BASE | 1); + pci_write_config32(0, dev, 0x24, SMBUS1_IO_BASE | 1); + /* Set smbus iospace enable */ + pci_write_config16(0, dev, 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) +{ + return do_smbus_recv_byte(SMBUS0_IO_BASE, device); +} + +static 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) +{ + return do_smbus_read_byte(SMBUS0_IO_BASE, device, address); +} + +static u8 smbus_write_byte(u8 device, u8 address, u8 char val) +{ + return do_smbus_write_byte(SMBUS0_IO_BASE, device, address, val); +} + +static 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 char 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) +{ + 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 char val) +{ + return do_smbus_write_byte(SMBUS0_IO_BASE + (smb_index<<8), device, address, val); +} +