diff options
author | Stefan Reinauer <stepan@coresystems.de> | 2009-03-11 14:54:18 +0000 |
---|---|---|
committer | Stefan Reinauer <stepan@openbios.org> | 2009-03-11 14:54:18 +0000 |
commit | a8e1168064b34b46494b58480411a11bc98340f6 (patch) | |
tree | 7d8c27e67ed67a3b96356581bad604b496f7cdd5 /src/southbridge/intel/i82801gx/i82801gx_smbus.h | |
parent | 6df0c62b688d1c4157bc151f98a2feeeca79fee8 (diff) |
This patch contains some significant updates to the i82801gx component and will
be required for a series of later patches. Roughly it contains:
* fixed SMBus driver (was not compiled in before)
* fixed S-ATA/P-ATA combination
* Added warnings to drivers being called with a NULL dev->chip_info
* Set subsystem ids for those boards that have none specified in Options.lb
* Fix license headers. The code was originally released under GPL v2 but
some files sneaked in with a v2 or later header.
* some attempts to fix azalia/Intel HDA.. not working yet
* clean up and fix pci bridge handling code
* Add Config based GPI handling to LPC driver
* Add HPET enable function
* Enable clock gating where appropriate
* first attempt at USB debug console support (not working yet)
* Add required options to kontron board
* many other minor changes
Signed-off-by: Stefan Reinauer <stepan@coresystems.de>
Acked-by: Myles Watson <mylesgw@gmail.com>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3991 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/southbridge/intel/i82801gx/i82801gx_smbus.h')
-rw-r--r-- | src/southbridge/intel/i82801gx/i82801gx_smbus.h | 133 |
1 files changed, 23 insertions, 110 deletions
diff --git a/src/southbridge/intel/i82801gx/i82801gx_smbus.h b/src/southbridge/intel/i82801gx/i82801gx_smbus.h index 13272cb552..ac327783ef 100644 --- a/src/southbridge/intel/i82801gx/i82801gx_smbus.h +++ b/src/southbridge/intel/i82801gx/i82801gx_smbus.h @@ -2,11 +2,12 @@ * This file is part of the coreboot project. * * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com> + * Copyright (C) 2009 coresystems GmbH * - * 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 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; version 2 of + * the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -25,7 +26,7 @@ static void smbus_delay(void) inb(0x80); } -static int smbus_wait_until_ready(void) +static int smbus_wait_until_ready(u16 smbus_base) { unsigned loops = SMBUS_TIMEOUT; unsigned char byte; @@ -33,12 +34,12 @@ static int smbus_wait_until_ready(void) smbus_delay(); if (--loops == 0) break; - byte = inb(SMBUS_IO_BASE + SMBHSTSTAT); + byte = inb(smbus_base + SMBHSTSTAT); } while (byte & 1); return loops ? 0 : -1; } -static int smbus_wait_until_done(void) +static int smbus_wait_until_done(u16 smbus_base) { unsigned loops = SMBUS_TIMEOUT; unsigned char byte; @@ -46,142 +47,54 @@ static int smbus_wait_until_done(void) smbus_delay(); if (--loops == 0) break; - byte = inb(SMBUS_IO_BASE + SMBHSTSTAT); + byte = inb(smbus_base + SMBHSTSTAT); } while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0); return loops ? 0 : -1; } -static int smbus_wait_until_blk_done(void) -{ - unsigned loops = SMBUS_TIMEOUT; - unsigned char byte; - do { - smbus_delay(); - if (--loops == 0) - break; - byte = inb(SMBUS_IO_BASE + SMBHSTSTAT); - } while ((byte & (1 << 7)) == 0); - return loops ? 0 : -1; -} - -static int do_smbus_read_byte(unsigned device, unsigned address) +static int do_smbus_read_byte(unsigned smbus_base, unsigned device, unsigned address) { unsigned char global_status_register; unsigned char byte; - if (smbus_wait_until_ready() < 0) { + if (smbus_wait_until_ready(smbus_base) < 0) { return SMBUS_WAIT_UNTIL_READY_TIMEOUT; } /* Setup transaction */ /* Disable interrupts */ - outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL); + outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL); /* Set the device I'm talking too */ - outb(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBXMITADD); + outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD); /* Set the command/address... */ - outb(address & 0xff, SMBUS_IO_BASE + SMBHSTCMD); + outb(address & 0xff, smbus_base + SMBHSTCMD); /* Set up for a byte data read */ - outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xe3) | (0x2 << 2), - (SMBUS_IO_BASE + SMBHSTCTL)); + outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2), + (smbus_base + SMBHSTCTL)); /* Clear any lingering errors, so the transaction will run */ - outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); + outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT); /* Clear the data byte... */ - outb(0, SMBUS_IO_BASE + SMBHSTDAT0); + outb(0, smbus_base + SMBHSTDAT0); /* Start the command */ - outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40), - SMBUS_IO_BASE + SMBHSTCTL); + outb((inb(smbus_base + SMBHSTCTL) | 0x40), + smbus_base + SMBHSTCTL); /* Poll for transaction completion */ - if (smbus_wait_until_done() < 0) { + if (smbus_wait_until_done(smbus_base) < 0) { return SMBUS_WAIT_UNTIL_DONE_TIMEOUT; } - global_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT); + global_status_register = inb(smbus_base + SMBHSTSTAT); /* Ignore the "In Use" status... */ global_status_register &= ~(3 << 5); /* Read results of transaction */ - byte = inb(SMBUS_IO_BASE + SMBHSTDAT0); + byte = inb(smbus_base + SMBHSTDAT0); if (global_status_register != (1 << 1)) { return SMBUS_ERROR; } return byte; } -/* This function is neither used nor tested by me (Corey Osgood), the author -(Yinghai) probably tested/used it on i82801er */ -static int do_smbus_write_block(unsigned device, unsigned length, unsigned cmd, - unsigned data1, unsigned data2) -{ - unsigned char byte; - unsigned char stat; - int i; - -#if CONFIG_USE_PRINTK_IN_CAR - printk_err("Untested smbus_write_block called\r\n"); -#else - print_err("Untested smbus_write_block called\r\n"); -#endif - - /* Clear the PM timeout flags, SECOND_TO_STS */ - outw(inw(0x0400 + 0x66), 0x0400 + 0x66); - - if (smbus_wait_until_ready() < 0) { - return -2; - } - - /* Setup transaction */ - /* Obtain ownership */ - outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); - for (stat = 0; (stat & 0x40) == 0;) { - stat = inb(SMBUS_IO_BASE + SMBHSTSTAT); - } - /* Clear the done bit */ - outb(0x80, SMBUS_IO_BASE + SMBHSTSTAT); - /* Disable interrupts */ - outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL); - - /* Set the device I'm talking too */ - outb(((device & 0x7f) << 1), SMBUS_IO_BASE + SMBXMITADD); - - /* Set the command address */ - outb(cmd & 0xff, SMBUS_IO_BASE + SMBHSTCMD); - - /* Set the block length */ - outb(length & 0xff, SMBUS_IO_BASE + SMBHSTDAT0); - - /* Try sending out the first byte of data here */ - byte = (data1 >> (0)) & 0x0ff; - outb(byte, SMBUS_IO_BASE + SMBBLKDAT); - /* Issue a block write command */ - outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xe3) | (0x5 << 2) | 0x40, - SMBUS_IO_BASE + SMBHSTCTL); - - for (i = 0; i < length; i++) { - - /* Poll for transaction completion */ - if (smbus_wait_until_blk_done() < 0) { - return -3; - } - - /* Load the next byte */ - if (i > 3) - byte = (data2 >> (i % 4)) & 0x0ff; - else - byte = (data1 >> (i)) & 0x0ff; - outb(byte, SMBUS_IO_BASE + SMBBLKDAT); - - /* Clear the done bit */ - outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), - SMBUS_IO_BASE + SMBHSTSTAT); - } - -#if CONFIG_USE_PRINTK_IN_CAR - printk_debug("SMBUS Block complete\r\n"); -#else - print_debug("SMBUS Block complete\r\n"); -#endif - return 0; -} |