sb/intel/*: Use common SMBus functions

All Intel southbridges implement the same SMBus functions.
This patch replaces all these similar and mostly identical
implementations with a common file.

This also makes i2c block read available to all those southbridges.
If the northbridge has to read a lot of SPD bytes sequentially, using
this function can reduce the time being spent to read SPD five-fold.

Change-Id: I93bb186e04e8c32dff04fc1abe4b5ecbc4c9c962
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/19258
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
This commit is contained in:
Arthur Heymans 2017-04-12 17:01:31 +02:00 committed by Martin Roth
parent 12d010306b
commit 16fe79048f
68 changed files with 471 additions and 2162 deletions

View File

@ -5,5 +5,6 @@
#define SMBUS_ERROR -1 #define SMBUS_ERROR -1
#define SMBUS_WAIT_UNTIL_READY_TIMEOUT -2 #define SMBUS_WAIT_UNTIL_READY_TIMEOUT -2
#define SMBUS_WAIT_UNTIL_DONE_TIMEOUT -3 #define SMBUS_WAIT_UNTIL_DONE_TIMEOUT -3
#define SMBUS_WAIT_UNTIL_ACTIVE_TIMEOUT -4
#endif /* DEVICE_SMBUS_DEF_H */ #endif /* DEVICE_SMBUS_DEF_H */

View File

@ -25,7 +25,7 @@
#include <timestamp.h> #include <timestamp.h>
#include <northbridge/intel/common/mrc_cache.h> #include <northbridge/intel/common/mrc_cache.h>
#include <southbridge/intel/bd82x6x/me.h> #include <southbridge/intel/bd82x6x/me.h>
#include <southbridge/intel/bd82x6x/smbus.h> #include <southbridge/intel/common/smbus.h>
#include <cpu/x86/msr.h> #include <cpu/x86/msr.h>
#include <delay.h> #include <delay.h>
#include <smbios.h> #include <smbios.h>

View File

@ -25,6 +25,7 @@ config SOUTH_BRIDGE_OPTIONS # dummy
def_bool y def_bool y
select ACPI_INTEL_HARDWARE_SLEEP_VALUES select ACPI_INTEL_HARDWARE_SLEEP_VALUES
select SOUTHBRIDGE_INTEL_COMMON select SOUTHBRIDGE_INTEL_COMMON
select SOUTHBRIDGE_INTEL_COMMON_SMBUS
select IOAPIC select IOAPIC
select HAVE_HARD_RESET select HAVE_HARD_RESET
select HAVE_USBDEBUG_OPTIONS select HAVE_USBDEBUG_OPTIONS

View File

@ -18,8 +18,8 @@
#include <console/console.h> #include <console/console.h>
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/pci_def.h> #include <device/pci_def.h>
#include <southbridge/intel/common/smbus.h>
#include "pch.h" #include "pch.h"
#include "smbus.h"
void enable_smbus(void) void enable_smbus(void)
{ {

View File

@ -265,22 +265,6 @@ early_usb_init (const struct southbridge_usb_port *portmap);
#define SMB_SMI_EN (1 << 1) #define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0) #define HST_EN (1 << 0)
/* SMBus I/O bits. */
#define SMBHSTSTAT 0x0
#define SMBHSTCTL 0x2
#define SMBHSTCMD 0x3
#define SMBXMITADD 0x4
#define SMBHSTDAT0 0x5
#define SMBHSTDAT1 0x6
#define SMBBLKDAT 0x7
#define SMBTRNSADD 0x9
#define SMBSLVDATA 0xa
#define SMLINK_PIN_CTL 0xe
#define SMBUS_PIN_CTL 0xf
#define SMBUS_TIMEOUT (10 * 1000 * 100)
/* Southbridge IO BARs */ /* Southbridge IO BARs */
#define GPIOBASE 0x48 #define GPIOBASE 0x48

View File

@ -22,8 +22,8 @@
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/pci_ops.h> #include <device/pci_ops.h>
#include <arch/io.h> #include <arch/io.h>
#include <southbridge/intel/common/smbus.h>
#include "pch.h" #include "pch.h"
#include "smbus.h"
static void pch_smbus_init(device_t dev) static void pch_smbus_init(device_t dev)
{ {
@ -54,49 +54,6 @@ static int lsmbus_read_byte(device_t dev, u8 address)
return do_smbus_read_byte(res->base, device, address); return do_smbus_read_byte(res->base, device, address);
} }
static int do_smbus_write_byte(unsigned smbus_base, unsigned device, unsigned address, unsigned data)
{
unsigned char global_status_register;
if (smbus_wait_until_ready(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Clear the data byte... */
outb(data, smbus_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
global_status_register = inb(smbus_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
global_status_register &= ~(3 << 5);
/* Read results of transaction */
if (global_status_register != (1 << 1))
return SMBUS_ERROR;
return 0;
}
static int lsmbus_write_byte(device_t dev, u8 address, u8 val) static int lsmbus_write_byte(device_t dev, u8 address, u8 val)
{ {
u16 device; u16 device;

View File

@ -1,95 +0,0 @@
/*
* 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; 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <device/smbus_def.h>
#include "pch.h"
static void smbus_delay(void)
{
inb(0x80);
}
static int smbus_wait_until_ready(u16 smbus_base)
{
unsigned loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_base + SMBHSTSTAT);
} while (byte & 1);
return loops ? 0 : -1;
}
static int smbus_wait_until_done(u16 smbus_base)
{
unsigned loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_base + SMBHSTSTAT);
} while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
return loops ? 0 : -1;
}
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(smbus_base) < 0) {
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
}
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Clear the data byte... */
outb(0, smbus_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_base) < 0) {
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
}
global_status_register = inb(smbus_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
global_status_register &= ~(3 << 5);
/* Read results of transaction */
byte = inb(smbus_base + SMBHSTDAT0);
if (global_status_register != (1 << 1)) {
return SMBUS_ERROR;
}
return byte;
}

View File

@ -2,3 +2,5 @@ config SOUTHBRIDGE_INTEL_COMMON
def_bool n def_bool n
config SOUTHBRIDGE_INTEL_COMMON_GPIO config SOUTHBRIDGE_INTEL_COMMON_GPIO
def_bool n def_bool n
config SOUTHBRIDGE_INTEL_COMMON_SMBUS
def_bool n

View File

@ -24,4 +24,8 @@ ramstage-$(CONFIG_USBDEBUG) += usb_debug.c
romstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_GPIO) += gpio.c romstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_GPIO) += gpio.c
ramstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_GPIO) += gpio.c ramstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_GPIO) += gpio.c
smm-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_GPIO) += gpio.c smm-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_GPIO) += gpio.c
romstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SMBUS) += smbus.c
ramstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SMBUS) += smbus.c
endif endif

View File

@ -0,0 +1,365 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
* Copyright (C) 2009 coresystems GmbH
* Copyright (C) 2013 Vladimir Serbinenko
*
* 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <arch/io.h>
#include <device/smbus_def.h>
#include "smbus.h"
/* I801 command constants */
#define I801_QUICK (0 << 2)
#define I801_BYTE (1 << 2)
#define I801_BYTE_DATA (2 << 2)
#define I801_WORD_DATA (3 << 2)
#define I801_BLOCK_DATA (5 << 2)
#define I801_I2C_BLOCK_DATA (6 << 2) /* ICH5 and later */
/* I801 Host Control register bits */
#define SMBHSTCNT_INTREN (1 << 0)
#define SMBHSTCNT_KILL (1 << 1)
#define SMBHSTCNT_LAST_BYTE (1 << 5)
#define SMBHSTCNT_START (1 << 6)
#define SMBHSTCNT_PEC_EN (1 << 7) /* ICH3 and later */
/* I801 Hosts Status register bits */
#define SMBHSTSTS_BYTE_DONE (1 << 7)
#define SMBHSTSTS_INUSE_STS (1 << 6)
#define SMBHSTSTS_SMBALERT_STS (1 << 5)
#define SMBHSTSTS_FAILED (1 << 4)
#define SMBHSTSTS_BUS_ERR (1 << 3)
#define SMBHSTSTS_DEV_ERR (1 << 2)
#define SMBHSTSTS_INTR (1 << 1)
#define SMBHSTSTS_HOST_BUSY (1 << 0)
#define SMBUS_TIMEOUT (10 * 1000 * 100)
static void smbus_delay(void)
{
inb(0x80);
}
static int smbus_wait_until_ready(u16 smbus_base)
{
unsigned int loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_base + SMBHSTSTAT);
} while (byte & SMBHSTSTS_HOST_BUSY);
return loops ? 0 : -1;
}
static int smbus_wait_until_done(u16 smbus_base)
{
unsigned int loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_base + SMBHSTSTAT);
} while ((byte & SMBHSTSTS_HOST_BUSY)
|| (byte & ~(SMBHSTSTS_INUSE_STS | SMBHSTSTS_HOST_BUSY)) == 0);
return loops ? 0 : -1;
}
static int smbus_wait_until_active(u16 smbus_base)
{
unsigned long loops;
loops = SMBUS_TIMEOUT;
do {
unsigned char val;
smbus_delay();
val = inb(smbus_base + SMBHSTSTAT);
if ((val & SMBHSTSTS_HOST_BUSY)) {
break;
}
} while (--loops);
return loops ? 0 : -1;
}
int do_smbus_read_byte(unsigned int smbus_base, u8 device,
unsigned int address)
{
unsigned char status;
unsigned char byte;
if (smbus_wait_until_ready(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
/* Set up transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & ~SMBHSTCNT_INTREN,
smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | I801_BYTE_DATA,
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Clear the data byte... */
outb(0, smbus_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | SMBHSTCNT_START),
smbus_base + SMBHSTCTL);
/* poll for it to start */
if (smbus_wait_until_active(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_ACTIVE_TIMEOUT;
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
status = inb(smbus_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
status &= ~(SMBHSTSTS_SMBALERT_STS | SMBHSTSTS_INUSE_STS);
/* Read results of transaction */
byte = inb(smbus_base + SMBHSTDAT0);
if (status != SMBHSTSTS_INTR)
return SMBUS_ERROR;
return byte;
}
int do_smbus_write_byte(unsigned int smbus_base, u8 device,
unsigned int address, unsigned int data)
{
unsigned char status;
if (smbus_wait_until_ready(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
/* Set up transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & ~SMBHSTCNT_INTREN,
smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | I801_BYTE_DATA,
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Clear the data byte... */
outb(data, smbus_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | SMBHSTCNT_START),
smbus_base + SMBHSTCTL);
/* poll for it to start */
if (smbus_wait_until_active(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_ACTIVE_TIMEOUT;
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
status = inb(smbus_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
status &= ~(SMBHSTSTS_SMBALERT_STS | SMBHSTSTS_INUSE_STS);
/* Read results of transaction */
if (status != SMBHSTSTS_INTR)
return SMBUS_ERROR;
return 0;
}
int do_smbus_block_read(unsigned int smbus_base, u8 device, u8 cmd,
unsigned int bytes, u8 *buf)
{
u8 status;
int bytes_read = 0;
unsigned int loops = SMBUS_TIMEOUT;
if (smbus_wait_until_ready(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
/* Set up transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & ~SMBHSTCNT_INTREN,
smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(cmd & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a block data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | I801_BLOCK_DATA,
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | SMBHSTCNT_START),
smbus_base + SMBHSTCTL);
/* poll for it to start */
if (smbus_wait_until_active(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_ACTIVE_TIMEOUT;
/* Poll for transaction completion */
do {
loops--;
status = inb(smbus_base + SMBHSTSTAT);
if (status & (SMBHSTSTS_FAILED | /* FAILED */
SMBHSTSTS_BUS_ERR | /* BUS ERR */
SMBHSTSTS_DEV_ERR)) /* DEV ERR */
return SMBUS_ERROR;
if (status & SMBHSTSTS_BYTE_DONE) { /* Byte done */
*buf = inb(smbus_base + SMBBLKDAT);
buf++;
bytes_read++;
if (--bytes == 1) {
/* indicate that next byte is the last one */
outb(inb(smbus_base + SMBHSTCTL)
| SMBHSTCNT_LAST_BYTE,
smbus_base + SMBHSTCTL);
}
outb(status, smbus_base + SMBHSTSTAT);
}
} while ((status & SMBHSTSTS_HOST_BUSY) && loops);
return bytes_read;
}
int do_smbus_block_write(unsigned int smbus_base, u8 device, u8 cmd,
unsigned int bytes, const u8 *buf)
{
u8 status;
unsigned int loops = SMBUS_TIMEOUT;
if (smbus_wait_until_ready(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
/* Set up transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & ~SMBHSTCNT_INTREN,
smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(cmd & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a block data write */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | I801_BLOCK_DATA,
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* set number of bytes to transfer */
outb(bytes, smbus_base + SMBHSTDAT0);
outb(*buf++, smbus_base + SMBBLKDAT);
bytes--;
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | SMBHSTCNT_START),
smbus_base + SMBHSTCTL);
/* poll for it to start */
if (smbus_wait_until_active(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_ACTIVE_TIMEOUT;
/* Poll for transaction completion */
do {
loops--;
status = inb(smbus_base + SMBHSTSTAT);
if (status & (SMBHSTSTS_FAILED | /* FAILED */
SMBHSTSTS_BUS_ERR | /* BUS ERR */
SMBHSTSTS_DEV_ERR)) /* DEV ERR */
return SMBUS_ERROR;
if (status & SMBHSTSTS_BYTE_DONE) {
outb(*buf++, smbus_base + SMBBLKDAT);
outb(status, smbus_base + SMBHSTSTAT);
}
} while ((status & SMBHSTSTS_HOST_BUSY) && loops);
return 0;
}
/* Only since ICH5 */
int do_i2c_block_read(unsigned int smbus_base, u8 device,
unsigned int offset, u32 bytes, u8 *buf)
{
u8 status;
int bytes_read = 0;
unsigned int loops = SMBUS_TIMEOUT;
if (smbus_wait_until_ready(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
/* Set upp transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & SMBHSTCNT_INTREN,
smbus_base + SMBHSTCTL);
/* Set the device I'm talking to */
outb((device & 0x7f) << 1, smbus_base + SMBXMITADD);
/* device offset */
outb(offset, smbus_base + SMBHSTDAT1);
/* Set up for a i2c block data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xc3) | I801_I2C_BLOCK_DATA,
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | SMBHSTCNT_START),
smbus_base + SMBHSTCTL);
/* poll for it to start */
if (smbus_wait_until_active(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_ACTIVE_TIMEOUT;
/* Poll for transaction completion */
do {
loops--;
status = inb(smbus_base + SMBHSTSTAT);
if (status & (SMBHSTSTS_FAILED | /* FAILED */
SMBHSTSTS_BUS_ERR | /* BUS ERR */
SMBHSTSTS_DEV_ERR)) /* DEV ERR */
return SMBUS_ERROR;
if (status & SMBHSTSTS_BYTE_DONE) {
*buf = inb(smbus_base + SMBBLKDAT);
buf++;
bytes_read++;
if (--bytes == 1) {
/* indicate that next byte is the last one */
outb(inb(smbus_base + SMBHSTCTL)
| SMBHSTCNT_LAST_BYTE,
smbus_base + SMBHSTCTL);
}
outb(status, smbus_base + SMBHSTSTAT);
}
} while ((status & SMBHSTSTS_HOST_BUSY) && loops);
return bytes_read;
}

View File

@ -0,0 +1,46 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
* Copyright (C) 2009 coresystems GmbH
* Copyright (C) 2013 Vladimir Serbinenko
*
* 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef INTEL_COMMON_SMBUS_H
#define INTEL_COMMON_SMBUS_H
/* SMBus register offsets. */
#define SMBHSTSTAT 0x0
#define SMBHSTCTL 0x2
#define SMBHSTCMD 0x3
#define SMBXMITADD 0x4
#define SMBHSTDAT0 0x5
#define SMBHSTDAT1 0x6
#define SMBBLKDAT 0x7
#define SMBTRNSADD 0x9
#define SMBSLVDATA 0xa
#define SMLINK_PIN_CTL 0xe
#define SMBUS_PIN_CTL 0xf
#define SMBSLVCMD 0x11
int do_smbus_read_byte(unsigned int smbus_base, u8 device,
unsigned int address);
int do_smbus_write_byte(unsigned int smbus_base, u8 device,
unsigned int address, unsigned int data);
int do_smbus_block_read(unsigned int smbus_base, u8 device,
u8 cmd, unsigned int bytes, u8 *buf);
int do_smbus_block_write(unsigned int smbus_base, u8 device,
u8 cmd, unsigned int bytes, const u8 *buf);
/* Only since ICH5 */
int do_i2c_block_read(unsigned int smbus_base, u8 device,
unsigned int offset, u32 bytes, u8 *buf);
#endif

View File

@ -31,6 +31,8 @@ config SOUTH_BRIDGE_OPTIONS # dummy
select SPI_FLASH select SPI_FLASH
select COMMON_FADT select COMMON_FADT
select HAVE_INTEL_FIRMWARE select HAVE_INTEL_FIRMWARE
select SOUTHBRIDGE_INTEL_COMMON
select SOUTHBRIDGE_INTEL_COMMON_SMBUS
config EHCI_BAR config EHCI_BAR
hex hex

View File

@ -32,6 +32,8 @@ config SOUTH_BRIDGE_OPTIONS # dummy
select COMMON_FADT select COMMON_FADT
select HAVE_INTEL_FIRMWARE select HAVE_INTEL_FIRMWARE
select NO_EARLY_BOOTBLOCK_POSTCODES select NO_EARLY_BOOTBLOCK_POSTCODES
select SOUTHBRIDGE_INTEL_COMMON
select SOUTHBRIDGE_INTEL_COMMON_SMBUS
config EHCI_BAR config EHCI_BAR
hex hex

View File

@ -19,8 +19,8 @@
#include <console/console.h> #include <console/console.h>
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/pci_def.h> #include <device/pci_def.h>
#include <southbridge/intel/common/smbus.h>
#include "pch.h" #include "pch.h"
#include "smbus.h"
void enable_smbus(void) void enable_smbus(void)
{ {

View File

@ -174,22 +174,6 @@ void early_pch_init(void);
#define SMB_SMI_EN (1 << 1) #define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0) #define HST_EN (1 << 0)
/* SMBus I/O bits. */
#define SMBHSTSTAT 0x0
#define SMBHSTCTL 0x2
#define SMBHSTCMD 0x3
#define SMBXMITADD 0x4
#define SMBHSTDAT0 0x5
#define SMBHSTDAT1 0x6
#define SMBBLKDAT 0x7
#define SMBTRNSADD 0x9
#define SMBSLVDATA 0xa
#define SMLINK_PIN_CTL 0xe
#define SMBUS_PIN_CTL 0xf
#define SMBUS_TIMEOUT (10 * 1000 * 100)
/* Southbridge IO BARs */ /* Southbridge IO BARs */
#define GPIOBASE 0x48 #define GPIOBASE 0x48

View File

@ -1,91 +0,0 @@
/*
* 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; 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <device/smbus_def.h>
#include "pch.h"
#include <delay.h>
static int smbus_wait_until_ready(u16 smbus_base)
{
unsigned loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
udelay(1);
if (--loops == 0)
break;
byte = inb(smbus_base + SMBHSTSTAT);
} while (byte & 1);
return loops ? 0 : -1;
}
static int smbus_wait_until_done(u16 smbus_base)
{
unsigned loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
udelay(1);
if (--loops == 0)
break;
byte = inb(smbus_base + SMBHSTSTAT);
} while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
return loops ? 0 : -1;
}
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(smbus_base) < 0) {
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
}
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Clear the data byte... */
outb(0, smbus_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_base) < 0) {
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
}
global_status_register = inb(smbus_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
global_status_register &= ~(3 << 5);
/* Read results of transaction */
byte = inb(smbus_base + SMBHSTDAT0);
if (global_status_register != (1 << 1)) {
return SMBUS_ERROR;
}
return byte;
}

View File

@ -30,6 +30,8 @@ config SOUTH_BRIDGE_OPTIONS # dummy
select PCIEXP_COMMON_CLOCK select PCIEXP_COMMON_CLOCK
select SPI_FLASH select SPI_FLASH
select HAVE_INTEL_FIRMWARE select HAVE_INTEL_FIRMWARE
select SOUTHBRIDGE_INTEL_COMMON
select SOUTHBRIDGE_INTEL_COMMON_SMBUS
config EHCI_BAR config EHCI_BAR
hex hex

View File

@ -18,8 +18,8 @@
#include <console/console.h> #include <console/console.h>
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/pci_def.h> #include <device/pci_def.h>
#include <southbridge/intel/common/smbus.h>
#include "soc.h" #include "soc.h"
#include "smbus.h"
void enable_smbus(void) void enable_smbus(void)
{ {

View File

@ -22,8 +22,8 @@
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/pci_ops.h> #include <device/pci_ops.h>
#include <arch/io.h> #include <arch/io.h>
#include <southbridge/intel/common/smbus.h>
#include "soc.h" #include "soc.h"
#include "smbus.h"
static int lsmbus_read_byte(device_t dev, u8 address) static int lsmbus_read_byte(device_t dev, u8 address)
{ {

View File

@ -1,95 +0,0 @@
/*
* 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; 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <device/smbus_def.h>
#include "soc.h"
static void smbus_delay(void)
{
inb(0x80);
}
static int smbus_wait_until_ready(u16 smbus_base)
{
unsigned loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_base + SMBHSTSTAT);
} while (byte & 1);
return loops ? 0 : -1;
}
static int smbus_wait_until_done(u16 smbus_base)
{
unsigned loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_base + SMBHSTSTAT);
} while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
return loops ? 0 : -1;
}
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(smbus_base) < 0) {
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
}
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Clear the data byte... */
outb(0, smbus_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_base) < 0) {
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
}
global_status_register = inb(smbus_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
global_status_register &= ~(3 << 5);
/* Read results of transaction */
byte = inb(smbus_base + SMBHSTDAT0);
if (global_status_register != (1 << 1)) {
return SMBUS_ERROR;
}
return byte;
}

View File

@ -176,21 +176,6 @@ void rangeley_sb_early_initialization(void);
#define SMB_SMI_EN (1 << 1) #define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0) #define HST_EN (1 << 0)
/* SMBus I/O bits. */
#define SMBHSTSTAT 0x0
#define SMBHSTCTL 0x2
#define SMBHSTCMD 0x3
#define SMBXMITADD 0x4
#define SMBHSTDAT0 0x5
#define SMBHSTDAT1 0x6
#define SMBBLKDAT 0x7
#define SMBTRNSADD 0x9
#define SMBSLVDATA 0xa
#define SMLINK_PIN_CTL 0xe
#define SMBUS_PIN_CTL 0xf
#define SMBUS_TIMEOUT (10 * 1000 * 100)
/* Root Complex Register Block */ /* Root Complex Register Block */
#define RCBA 0xf0 #define RCBA 0xf0
#define RCBA_ENABLE 0x01 #define RCBA_ENABLE 0x01

View File

@ -2,6 +2,8 @@ config SOUTHBRIDGE_INTEL_I3100
bool bool
select IOAPIC select IOAPIC
select HAVE_HARD_RESET select HAVE_HARD_RESET
select SOUTHBRIDGE_INTEL_COMMON
select SOUTHBRIDGE_INTEL_COMMON_SMBUS
if SOUTHBRIDGE_INTEL_I3100 if SOUTHBRIDGE_INTEL_I3100

View File

@ -14,7 +14,7 @@
* *
*/ */
#include "smbus.h" #include <southbridge/intel/common/smbus.h>
#define SMBUS_IO_BASE 0x0f00 #define SMBUS_IO_BASE 0x0f00

View File

@ -21,8 +21,8 @@
#include <device/pci_ops.h> #include <device/pci_ops.h>
#include <device/smbus.h> #include <device/smbus.h>
#include <arch/io.h> #include <arch/io.h>
#include <southbridge/intel/common/smbus.h>
#include "i3100.h" #include "i3100.h"
#include "smbus.h"
static int lsmbus_read_byte(device_t dev, u8 address) static int lsmbus_read_byte(device_t dev, u8 address)
{ {

View File

@ -1,151 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008 Arastra, Inc.
*
* 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/* This code is based on src/southbridge/intel/esb6300/esb6300_smbus.h */
#include <device/smbus_def.h>
#define SMBHSTSTAT 0x0
#define SMBHSTCTL 0x2
#define SMBHSTCMD 0x3
#define SMBXMITADD 0x4
#define SMBHSTDAT0 0x5
#define SMBHSTDAT1 0x6
#define SMBBLKDAT 0x7
#define SMBTRNSADD 0x9
#define SMBSLVDATA 0xa
#define SMLINK_PIN_CTL 0xe
#define SMBUS_PIN_CTL 0xf
#define SMBSLVCMD 0x11
#define SMBUS_TIMEOUT (100*1000*10)
static void smbus_delay(void)
{
outb(0x80, 0x80);
}
static int smbus_wait_until_ready(u32 smbus_io_base)
{
u32 loops = SMBUS_TIMEOUT;
u8 byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_io_base + SMBHSTSTAT);
} while (byte & 1);
return loops ? 0 : -1;
}
static int smbus_wait_until_done(u32 smbus_io_base)
{
u32 loops = SMBUS_TIMEOUT;
u8 byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_io_base + SMBHSTSTAT);
} while ((byte & 1) || (byte & ~((1 << 6)|(1 << 0))) == 0);
return loops ? 0 : -1;
}
static int do_smbus_read_byte(u32 smbus_io_base, u16 device, u8 address)
{
u8 global_status_register;
u8 byte;
if (smbus_wait_until_ready(smbus_io_base) < 0) {
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
}
/* setup transaction */
/* disable interrupts */
outb(inb(smbus_io_base + SMBHSTCTL) & (~1), smbus_io_base + SMBHSTCTL);
/* set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBXMITADD);
/* set the command/address... */
outb(address & 0xFF, smbus_io_base + SMBHSTCMD);
/* set up for a byte data read */
outb((inb(smbus_io_base + SMBHSTCTL) & 0xE3) | (0x2 << 2), smbus_io_base + SMBHSTCTL);
/* clear any lingering errors, so the transaction will run */
outb(inb(smbus_io_base + SMBHSTSTAT), smbus_io_base + SMBHSTSTAT);
/* clear the data byte...*/
outb(0, smbus_io_base + SMBHSTDAT0);
/* start the command */
outb((inb(smbus_io_base + SMBHSTCTL) | 0x40), smbus_io_base + SMBHSTCTL);
/* poll for transaction completion */
if (smbus_wait_until_done(smbus_io_base) < 0) {
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
}
global_status_register = inb(smbus_io_base + SMBHSTSTAT);
/* Ignore the In Use Status... */
global_status_register &= ~(3 << 5);
/* read results of transaction */
byte = inb(smbus_io_base + SMBHSTDAT0);
if (global_status_register != (1 << 1)) {
return SMBUS_ERROR;
}
return byte;
}
static int do_smbus_write_byte(unsigned smbus_base, unsigned device, unsigned address, unsigned data)
{
unsigned char global_status_register;
if (smbus_wait_until_ready(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Clear the data byte... */
outb(data, smbus_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
global_status_register = inb(smbus_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
global_status_register &= ~(3 << 5);
/* Read results of transaction */
if (global_status_register != (1 << 1))
return SMBUS_ERROR;
return 0;
}

View File

@ -1,4 +1,6 @@
config SOUTHBRIDGE_INTEL_I82371EB config SOUTHBRIDGE_INTEL_I82371EB
select SOUTHBRIDGE_INTEL_COMMON
select SOUTHBRIDGE_INTEL_COMMON_SMBUS
bool bool
config BOOTBLOCK_SOUTHBRIDGE_INIT config BOOTBLOCK_SOUTHBRIDGE_INIT

View File

@ -19,8 +19,8 @@
#include <console/console.h> #include <console/console.h>
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/pci_def.h> #include <device/pci_def.h>
#include <southbridge/intel/common/smbus.h>
#include "i82371eb.h" #include "i82371eb.h"
#include "smbus.h"
void enable_smbus(void) void enable_smbus(void)
{ {
@ -46,7 +46,7 @@ void enable_smbus(void)
pci_write_config16(dev, PCI_COMMAND, reg16); pci_write_config16(dev, PCI_COMMAND, reg16);
/* Clear any lingering errors, so the transaction will run. */ /* Clear any lingering errors, so the transaction will run. */
outb(inb(SMBUS_IO_BASE + SMBHST_STATUS), SMBUS_IO_BASE + SMBHST_STATUS); outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
} }
int smbus_read_byte(u8 device, u8 address) int smbus_read_byte(u8 device, u8 address)

View File

@ -24,8 +24,8 @@
#include <device/pci.h> #include <device/pci.h>
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/smbus.h> #include <device/smbus.h>
#include <southbridge/intel/common/smbus.h>
#include "i82371eb.h" #include "i82371eb.h"
#include "smbus.h"
static void pwrmgt_enable(struct device *dev) static void pwrmgt_enable(struct device *dev)
{ {

View File

@ -1,112 +0,0 @@
#include <device/smbus_def.h>
#include "i82371eb.h"
#define SMBHST_STATUS 0x0
#define SMBHST_CTL 0x2
#define SMBHST_CMD 0x3
#define SMBHST_ADDR 0x4
#define SMBHST_DAT 0x5
#define SMBUS_TIMEOUT (100*1000*10)
#define SMBUS_STATUS_MASK 0x1e
#define SMBUS_ERROR_FLAG (1<<2)
int do_smbus_read_byte(unsigned smbus_io_base, unsigned device, unsigned address);
static inline void smbus_delay(void)
{
outb(0x80, 0x80);
outb(0x80, 0x80);
outb(0x80, 0x80);
outb(0x80, 0x80);
outb(0x80, 0x80);
outb(0x80, 0x80);
}
static int smbus_wait_until_ready(unsigned smbus_io_base)
{
unsigned long loops;
loops = SMBUS_TIMEOUT;
do {
unsigned char val;
smbus_delay();
val = inb(smbus_io_base + SMBHST_STATUS);
if ((val & 0x1) == 0) {
break;
}
#if 0
if (loops == (SMBUS_TIMEOUT / 2)) {
outw(inw(smbus_io_base + SMBHST_STATUS),
smbus_io_base + SMBHST_STATUS);
}
#endif
} while (--loops);
return loops?0:SMBUS_WAIT_UNTIL_READY_TIMEOUT;
}
static int smbus_wait_until_done(unsigned smbus_io_base)
{
unsigned long loops;
loops = SMBUS_TIMEOUT;
do {
unsigned short val;
smbus_delay();
val = inb(smbus_io_base + SMBHST_STATUS);
// Make sure the command is done
if ((val & 0x1) != 0) {
continue;
}
// Don't break out until one of the interrupt
// flags is set.
if (val & 0xfe) {
break;
}
} while (--loops);
return loops?0:SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
}
int do_smbus_read_byte(unsigned smbus_io_base, unsigned device, unsigned address)
{
unsigned status_register;
unsigned byte;
if (smbus_wait_until_ready(smbus_io_base) < 0) {
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
}
/* setup transaction */
/* clear any lingering errors, so the transaction will run */
outb(0x1e, smbus_io_base + SMBHST_STATUS);
/* set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHST_ADDR);
/* set the command/address... */
outb(address & 0xff, smbus_io_base + SMBHST_CMD);
/* clear the data word...*/
outb(0, smbus_io_base + SMBHST_DAT);
/* start a byte read with interrupts disabled */
outb( (0x02 << 2)|(1<<6), smbus_io_base + SMBHST_CTL);
/* poll for transaction completion */
if (smbus_wait_until_done(smbus_io_base) < 0) {
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
}
status_register = inw(smbus_io_base + SMBHST_STATUS);
/* read results of transaction */
byte = inw(smbus_io_base + SMBHST_DAT) & 0xff;
if (status_register & 0x04) {
#if 0
printk(BIOS_DEBUG, "Read fail %04x\n", status_register);
#endif
return SMBUS_ERROR;
}
return byte;
}

View File

@ -18,3 +18,5 @@ config SOUTHBRIDGE_INTEL_I82801AX
select IOAPIC select IOAPIC
select HAVE_HARD_RESET select HAVE_HARD_RESET
select USE_WATCHDOG_ON_BOOT select USE_WATCHDOG_ON_BOOT
select SOUTHBRIDGE_INTEL_COMMON
select SOUTHBRIDGE_INTEL_COMMON_SMBUS

View File

@ -20,8 +20,8 @@
#include <console/console.h> #include <console/console.h>
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/pci_def.h> #include <device/pci_def.h>
#include <southbridge/intel/common/smbus.h>
#include "i82801ax.h" #include "i82801ax.h"
#include "smbus.h"
void enable_smbus(void) void enable_smbus(void)
{ {

View File

@ -90,15 +90,4 @@ int smbus_read_byte(u8 device, u8 address);
#define SMB_SMI_EN (1 << 1) #define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0) #define HST_EN (1 << 0)
/* SMBus I/O registers. */
#define SMBHSTSTAT 0x0
#define SMBHSTCTL 0x2
#define SMBHSTCMD 0x3
#define SMBXMITADD 0x4
#define SMBHSTDAT0 0x5
#define SMBHSTDAT1 0x6
#define SMBBLKDAT 0x7
#define SMBUS_TIMEOUT (10 * 1000 * 100)
#endif #endif

View File

@ -19,8 +19,8 @@
#include <device/pci.h> #include <device/pci.h>
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <arch/io.h> #include <arch/io.h>
#include <southbridge/intel/common/smbus.h>
#include "i82801ax.h" #include "i82801ax.h"
#include "smbus.h"
static int lsmbus_read_byte(device_t dev, u8 address) static int lsmbus_read_byte(device_t dev, u8 address)
{ {

View File

@ -1,97 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
*
* 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.
*/
#include <device/smbus_def.h>
#include "i82801ax.h"
int do_smbus_read_byte(u16 smbus_io_base, u8 device, u8 address);
static void smbus_delay(void)
{
inb(0x80);
}
static int smbus_wait_until_ready(u16 smbus_io_base)
{
unsigned loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_io_base + SMBHSTSTAT);
} while (byte & 1);
return loops ? 0 : -1;
}
static int smbus_wait_until_done(u16 smbus_io_base)
{
unsigned loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_io_base + SMBHSTSTAT);
} while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
return loops ? 0 : -1;
}
int do_smbus_read_byte(u16 smbus_io_base, u8 device, u8 address)
{
unsigned char global_status_register;
unsigned char byte;
if (smbus_wait_until_ready(smbus_io_base) < 0) {
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
}
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_io_base + SMBHSTCTL) & (~1), smbus_io_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_io_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_io_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
(smbus_io_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_io_base + SMBHSTSTAT), smbus_io_base + SMBHSTSTAT);
/* Clear the data byte... */
outb(0, smbus_io_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_io_base + SMBHSTCTL) | 0x40),
smbus_io_base + SMBHSTCTL);
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_io_base) < 0) {
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
}
global_status_register = inb(smbus_io_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
global_status_register &= ~(3 << 5);
/* Read results of transaction */
byte = inb(smbus_io_base + SMBHSTDAT0);
if (global_status_register != (1 << 1)) {
return SMBUS_ERROR;
}
return byte;
}

View File

@ -18,3 +18,5 @@ config SOUTHBRIDGE_INTEL_I82801BX
select IOAPIC select IOAPIC
select HAVE_HARD_RESET select HAVE_HARD_RESET
select USE_WATCHDOG_ON_BOOT select USE_WATCHDOG_ON_BOOT
select SOUTHBRIDGE_INTEL_COMMON
select SOUTHBRIDGE_INTEL_COMMON_SMBUS

View File

@ -20,8 +20,8 @@
#include <console/console.h> #include <console/console.h>
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/pci_def.h> #include <device/pci_def.h>
#include <southbridge/intel/common/smbus.h>
#include "i82801bx.h" #include "i82801bx.h"
#include "smbus.h"
void enable_smbus(void) void enable_smbus(void)
{ {

View File

@ -99,19 +99,4 @@ int smbus_read_byte(u8 device, u8 address);
#define SMB_SMI_EN (1 << 1) #define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0) #define HST_EN (1 << 0)
/* SMBus I/O registers. */
#define SMBHSTSTAT 0x0
#define SMBHSTCTL 0x2
#define SMBHSTCMD 0x3
#define SMBXMITADD 0x4
#define SMBHSTDAT0 0x5
#define SMBHSTDAT1 0x6
#define SMBBLKDAT 0x7
#define SMBTRNSADD 0x9
#define SMBSLVDATA 0xa
#define SMLINK_PIN_CTL 0xe
#define SMBUS_PIN_CTL 0xf
#define SMBUS_TIMEOUT (10 * 1000 * 100)
#endif /* SOUTHBRIDGE_INTEL_I82801BX_I82801BX_H */ #endif /* SOUTHBRIDGE_INTEL_I82801BX_I82801BX_H */

View File

@ -19,8 +19,8 @@
#include <device/pci.h> #include <device/pci.h>
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <arch/io.h> #include <arch/io.h>
#include <southbridge/intel/common/smbus.h>
#include "i82801bx.h" #include "i82801bx.h"
#include "smbus.h"
static int lsmbus_read_byte(device_t dev, u8 address) static int lsmbus_read_byte(device_t dev, u8 address)
{ {

View File

@ -1,94 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
*
* 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.
*/
#include <device/smbus_def.h>
static void smbus_delay(void)
{
inb(0x80);
}
static int smbus_wait_until_ready(u16 smbus_io_base)
{
unsigned loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_io_base + SMBHSTSTAT);
} while (byte & 1);
return loops ? 0 : -1;
}
static int smbus_wait_until_done(u16 smbus_io_base)
{
unsigned loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_io_base + SMBHSTSTAT);
} while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
return loops ? 0 : -1;
}
static int do_smbus_read_byte(u16 smbus_io_base, u8 device, u8 address)
{
unsigned char global_status_register;
unsigned char byte;
if (smbus_wait_until_ready(smbus_io_base) < 0) {
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
}
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_io_base + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_io_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_io_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
(smbus_io_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_io_base + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
/* Clear the data byte... */
outb(0, smbus_io_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_io_base + SMBHSTCTL) | 0x40),
smbus_io_base + SMBHSTCTL);
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_io_base) < 0) {
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
}
global_status_register = inb(smbus_io_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
global_status_register &= ~(3 << 5);
/* Read results of transaction */
byte = inb(smbus_io_base + SMBHSTDAT0);
if (global_status_register != (1 << 1)) {
return SMBUS_ERROR;
}
return byte;
}

View File

@ -22,6 +22,8 @@ config SOUTHBRIDGE_INTEL_I82801DX
select HAVE_HARD_RESET select HAVE_HARD_RESET
select HAVE_SMI_HANDLER select HAVE_SMI_HANDLER
select HAVE_USBDEBUG select HAVE_USBDEBUG
select SOUTHBRIDGE_INTEL_COMMON
select SOUTHBRIDGE_INTEL_COMMON_SMBUS
if SOUTHBRIDGE_INTEL_I82801DX if SOUTHBRIDGE_INTEL_I82801DX

View File

@ -17,6 +17,7 @@
#include <arch/io.h> #include <arch/io.h>
#include <device/pci_def.h> #include <device/pci_def.h>
#include <console/console.h> #include <console/console.h>
#include <southbridge/intel/common/smbus.h>
#include "i82801dx.h" #include "i82801dx.h"
@ -37,143 +38,7 @@ void enable_smbus(void)
outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
} }
static inline void smbus_delay(void) int smbus_read_byte(unsigned int device, unsigned int address)
{ {
outb(0x80, 0x80); return do_smbus_read_byte(SMBUS_IO_BASE, device, address);
} }
static int smbus_wait_until_active(void)
{
unsigned long loops;
loops = SMBUS_TIMEOUT;
do {
unsigned char val;
smbus_delay();
val = inb(SMBUS_IO_BASE + SMBHSTSTAT);
if ((val & 1)) {
break;
}
} while (--loops);
return loops ? 0 : -4;
}
static int smbus_wait_until_ready(void)
{
unsigned long loops;
loops = SMBUS_TIMEOUT;
do {
unsigned char val;
smbus_delay();
val = inb(SMBUS_IO_BASE + SMBHSTSTAT);
if ((val & 1) == 0) {
break;
}
if (loops == (SMBUS_TIMEOUT / 2)) {
outb(inb(SMBUS_IO_BASE + SMBHSTSTAT),
SMBUS_IO_BASE + SMBHSTSTAT);
}
} while (--loops);
return loops ? 0 : -2;
}
static int smbus_wait_until_done(void)
{
unsigned long loops;
loops = SMBUS_TIMEOUT;
do {
unsigned char val;
smbus_delay();
val = inb(SMBUS_IO_BASE + SMBHSTSTAT);
if ((val & 1) == 0) {
break;
}
if ((val & ~((1 << 6) | (1 << 0))) != 0) {
break;
}
} while (--loops);
return loops ? 0 : -3;
}
int smbus_read_byte(unsigned device, unsigned address)
{
unsigned char global_status_register;
unsigned char byte;
/* printk(BIOS_ERR, "smbus_read_byte\n"); */
if (smbus_wait_until_ready() < 0) {
printk(BIOS_ERR, "SMBUS not ready (-2)\n");
return -2;
}
/* setup transaction */
/* disable interrupts */
outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xfe, SMBUS_IO_BASE + SMBHSTCTL);
/* set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBXMITADD);
/* set the command/address... */
outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
/* set up for a byte data read */
outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xe3) | (0x2 << 2),
SMBUS_IO_BASE + SMBHSTCTL);
/* clear any lingering errors, so the transaction will run */
outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
/* clear the data byte... */
outb(0, SMBUS_IO_BASE + SMBHSTDAT0);
/* start a byte read, with interrupts disabled */
outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40),
SMBUS_IO_BASE + SMBHSTCTL);
/* poll for it to start */
if (smbus_wait_until_active() < 0) {
printk(BIOS_ERR, "SMBUS not active (-4)\n");
return -4;
}
/* poll for transaction completion */
if (smbus_wait_until_done() < 0) {
printk(BIOS_ERR, "SMBUS not completed (-3)\n");
return -3;
}
global_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT) & ~(1 << 6); /* Ignore the In Use Status... */
/* read results of transaction */
byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);
if (global_status_register != 2) {
//printk(BIOS_SPEW, "%s: no device (%02x, %02x)\n", __func__, device, address);
return -1;
}
//printk(BIOS_DEBUG, "%s: %02x@%02x = %02x\n", __func__, device, address, byte);
return byte;
}
#if 0
static void smbus_write_byte(unsigned device, unsigned address,
unsigned char val)
{
if (smbus_wait_until_ready() < 0) {
return;
}
/* by LYH */
outb(0x37, SMBUS_IO_BASE + SMBHSTSTAT);
/* set the device I'm talking too */
outw(((device & 0x7f) << 1) | 0, SMBUS_IO_BASE + SMBHSTADDR);
/* data to send */
outb(val, SMBUS_IO_BASE + SMBHSTDAT);
outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
/* start the command */
outb(0xa, SMBUS_IO_BASE + SMBHSTCTL);
/* poll for transaction completion */
smbus_wait_until_done();
return;
}
#endif

View File

@ -116,23 +116,6 @@ int smbus_read_byte(unsigned device, unsigned address);
#define SMBUS_IO_BASE 0x1000 #define SMBUS_IO_BASE 0x1000
#define SMBHSTSTAT 0x0
#define SMBHSTCTL 0x2
#define SMBHSTCMD 0x3
#define SMBXMITADD 0x4
#define SMBHSTDAT0 0x5
#define SMBHSTDAT1 0x6
#define SMBBLKDAT 0x7
#define SMBTRNSADD 0x9
#define SMBSLVDATA 0xa
#define SMLINK_PIN_CTL 0xe
#define SMBUS_PIN_CTL 0xf
/* 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)
#define PM1_STS 0x00 #define PM1_STS 0x00
#define WAK_STS (1 << 15) #define WAK_STS (1 << 15)
#define PCIEXPWAK_STS (1 << 14) #define PCIEXPWAK_STS (1 << 14)

View File

@ -1,101 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2004 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; 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "i82801dx.h"
#include <smbus.h>
#include <pci.h>
#include <arch/io.h>
#define PM_BUS 0
#define PM_DEVFN PCI_DEVFN(0x1f,3)
void smbus_enable(void)
{
unsigned char byte;
/* iobase addr */
pcibios_write_config_dword(PM_BUS, PM_DEVFN, 0x20, SMBUS_IO_BASE | 1);
/* smbus enable */
pcibios_write_config_byte(PM_BUS, PM_DEVFN, 0x40, 1);
/* iospace enable */
pcibios_write_config_word(PM_BUS, PM_DEVFN, 0x4, 1);
/* Disable interrupt generation */
outb(0, SMBUS_IO_BASE + SMBHSTCTL);
}
void smbus_setup(void)
{
outb(0, SMBUS_IO_BASE + SMBHSTSTAT);
}
static void smbus_wait_until_ready(void)
{
while ((inb(SMBUS_IO_BASE + SMBHSTSTAT) & 1) == 1) {
/* nop */
}
}
static void smbus_wait_until_done(void)
{
unsigned char byte;
do {
byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
}
while ((byte & 1) == 1);
while ((byte & ~1) == 0) {
byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
}
}
int smbus_read_byte(unsigned device, unsigned address, unsigned char *result)
{
unsigned char host_status_register;
unsigned char byte;
smbus_wait_until_ready();
/* setup transaction */
/* disable interrupts */
outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
/* set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBHSTADD);
/* set the command/address... */
outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
/* set up for a byte data read */
outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xE3) | (0x2 << 2),
SMBUS_IO_BASE + SMBHSTCTL);
/* clear any lingering errors, so the transaction will run */
outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
/* clear the data byte... */
outb(0, SMBUS_IO_BASE + SMBHSTDAT0);
/* start the command */
outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40),
SMBUS_IO_BASE + SMBHSTCTL);
/* poll for transaction completion */
smbus_wait_until_done();
host_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT);
/* read results of transaction */
byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);
*result = byte;
return host_status_register != 0x02;
}

View File

@ -24,6 +24,7 @@ config SOUTHBRIDGE_INTEL_I82801GX
select HAVE_SMI_HANDLER select HAVE_SMI_HANDLER
select COMMON_FADT select COMMON_FADT
select SOUTHBRIDGE_INTEL_COMMON_GPIO select SOUTHBRIDGE_INTEL_COMMON_GPIO
select SOUTHBRIDGE_INTEL_COMMON_SMBUS
if SOUTHBRIDGE_INTEL_I82801GX if SOUTHBRIDGE_INTEL_I82801GX

View File

@ -18,8 +18,8 @@
#include <console/console.h> #include <console/console.h>
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/pci_def.h> #include <device/pci_def.h>
#include <southbridge/intel/common/smbus.h>
#include "i82801gx.h" #include "i82801gx.h"
#include "smbus.h"
void enable_smbus(void) void enable_smbus(void)
{ {
@ -57,52 +57,5 @@ int smbus_read_byte(unsigned int device, unsigned int address)
int i2c_block_read(unsigned int device, unsigned int offset, u32 bytes, u8 *buf) int i2c_block_read(unsigned int device, unsigned int offset, u32 bytes, u8 *buf)
{ {
u8 status; return do_i2c_block_read(SMBUS_IO_BASE, device, offset, bytes, buf);
int bytes_read = 0;
if (smbus_wait_until_ready(SMBUS_IO_BASE) < 0)
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
/* Setup transaction */
/* Disable interrupts */
outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
/* Set the device I'm talking to */
outb((device & 0x7f) << 1, SMBUS_IO_BASE + SMBXMITADD);
/* SPD offset */
outb(offset, SMBUS_IO_BASE + SMBHSTDAT1);
/* Set up for a i2c block data read */
outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xc3) | (0x6 << 2),
(SMBUS_IO_BASE + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
/* Start the command */
outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40),
SMBUS_IO_BASE + SMBHSTCTL);
while (!(inb(SMBUS_IO_BASE + SMBHSTSTAT) & 1))
;
/* Poll for transaction completion */
do {
status = inb(SMBUS_IO_BASE + SMBHSTSTAT);
if (status & ((1 << 4) | /* FAILED */
(1 << 3) | /* BUS ERR */
(1 << 2))) /* DEV ERR */
return SMBUS_ERROR;
if (status & 0x80) { /* Byte done */
*buf = inb(SMBUS_IO_BASE + SMBBLKDAT);
buf++;
bytes_read++;
if (--bytes == 1) {
/* indicate that next byte is the last one */
outb(inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x20,
SMBUS_IO_BASE + SMBHSTCTL);
}
outb(status, SMBUS_IO_BASE + SMBHSTSTAT);
}
} while (status & 0x01);
return bytes_read;
} }

View File

@ -177,22 +177,6 @@ int southbridge_detect_s3_resume(void);
#define SMB_SMI_EN (1 << 1) #define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0) #define HST_EN (1 << 0)
/* SMBus I/O bits. */
#define SMBHSTSTAT 0x0
#define SMBHSTCTL 0x2
#define SMBHSTCMD 0x3
#define SMBXMITADD 0x4
#define SMBHSTDAT0 0x5
#define SMBHSTDAT1 0x6
#define SMBBLKDAT 0x7
#define SMBTRNSADD 0x9
#define SMBSLVDATA 0xa
#define SMLINK_PIN_CTL 0xe
#define SMBUS_PIN_CTL 0xf
#define SMBUS_TIMEOUT (10 * 1000 * 100)
/* Southbridge IO BARs */ /* Southbridge IO BARs */
#define GPIOBASE 0x48 #define GPIOBASE 0x48

View File

@ -22,8 +22,8 @@
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/pci_ops.h> #include <device/pci_ops.h>
#include <arch/io.h> #include <arch/io.h>
#include <southbridge/intel/common/smbus.h>
#include "i82801gx.h" #include "i82801gx.h"
#include "smbus.h"
static int lsmbus_read_byte(device_t dev, u8 address) static int lsmbus_read_byte(device_t dev, u8 address)
{ {
@ -38,49 +38,6 @@ static int lsmbus_read_byte(device_t dev, u8 address)
return do_smbus_read_byte(res->base, device, address); return do_smbus_read_byte(res->base, device, address);
} }
static int do_smbus_write_byte(unsigned int smbus_base, unsigned int device,
unsigned int address, unsigned int data)
{
unsigned char global_status_register;
if (smbus_wait_until_ready(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Clear the data byte... */
outb(data, smbus_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
global_status_register = inb(smbus_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
global_status_register &= ~(3 << 5);
/* Read results of transaction */
if (global_status_register != (1 << 1))
return SMBUS_ERROR;
return 0;
}
static int lsmbus_write_byte(device_t dev, u8 address, u8 data) static int lsmbus_write_byte(device_t dev, u8 address, u8 data)
{ {
u16 device; u16 device;
@ -93,58 +50,6 @@ static int lsmbus_write_byte(device_t dev, u8 address, u8 data)
return do_smbus_write_byte(res->base, device, address, data); return do_smbus_write_byte(res->base, device, address, data);
} }
static int do_smbus_block_write(unsigned int smbus_base, unsigned int device,
unsigned int cmd, unsigned int bytes, const u8 *buf)
{
u8 status;
if (smbus_wait_until_ready(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(cmd & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a block data write */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x5 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* set number of bytes to transfer */
outb(bytes, smbus_base + SMBHSTDAT0);
outb(*buf++, smbus_base + SMBBLKDAT);
bytes--;
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
while (!(inb(smbus_base + SMBHSTSTAT) & 1))
;
/* Poll for transaction completion */
do {
status = inb(smbus_base + SMBHSTSTAT);
if (status & ((1 << 4) | /* FAILED */
(1 << 3) | /* BUS ERR */
(1 << 2))) /* DEV ERR */
return SMBUS_ERROR;
if (status & 0x80) { /* Byte done */
outb(*buf++, smbus_base + SMBBLKDAT);
outb(status, smbus_base + SMBHSTSTAT);
}
} while (status & 0x01);
return 0;
}
static int lsmbus_block_write(device_t dev, u8 cmd, u8 bytes, const u8 *buf) static int lsmbus_block_write(device_t dev, u8 cmd, u8 bytes, const u8 *buf)
{ {
u16 device; u16 device;
@ -157,57 +62,6 @@ static int lsmbus_block_write(device_t dev, u8 cmd, u8 bytes, const u8 *buf)
return do_smbus_block_write(res->base, device, cmd, bytes, buf); return do_smbus_block_write(res->base, device, cmd, bytes, buf);
} }
static int do_smbus_block_read(unsigned int smbus_base, unsigned int device,
unsigned int cmd, unsigned int bytes, u8 *buf)
{
u8 status;
int bytes_read = 0;
if (smbus_wait_until_ready(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(cmd & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a block data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x5 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
while (!(inb(smbus_base + SMBHSTSTAT) & 1))
;
/* Poll for transaction completion */
do {
status = inb(smbus_base + SMBHSTSTAT);
if (status & ((1 << 4) | /* FAILED */
(1 << 3) | /* BUS ERR */
(1 << 2))) /* DEV ERR */
return SMBUS_ERROR;
if (status & 0x80) { /* Byte done */
*buf = inb(smbus_base + SMBBLKDAT);
buf++;
bytes_read++;
outb(status, smbus_base + SMBHSTSTAT);
if (--bytes == 1) {
/* indicate that next byte is the last one */
outb(inb(smbus_base + SMBHSTCTL) | 0x20,
smbus_base + SMBHSTCTL);
}
}
} while (status & 0x01);
return bytes_read;
}
static int lsmbus_block_read(device_t dev, u8 cmd, u8 bytes, u8 *buf) static int lsmbus_block_read(device_t dev, u8 cmd, u8 bytes, u8 *buf)
{ {
u16 device; u16 device;

View File

@ -1,92 +0,0 @@
/*
* 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; 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <device/smbus_def.h>
#include "i82801gx.h"
static void smbus_delay(void)
{
inb(0x80);
}
static int smbus_wait_until_ready(u16 smbus_base)
{
unsigned int loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_base + SMBHSTSTAT);
} while (byte & 1);
return loops ? 0 : -1;
}
static int smbus_wait_until_done(u16 smbus_base)
{
unsigned int loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_base + SMBHSTSTAT);
} while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
return loops ? 0 : -1;
}
static int do_smbus_read_byte(unsigned int smbus_base, unsigned int device, unsigned int address)
{
unsigned char global_status_register;
unsigned char byte;
if (smbus_wait_until_ready(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Clear the data byte... */
outb(0, smbus_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
global_status_register = inb(smbus_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
global_status_register &= ~(3 << 5);
/* Read results of transaction */
byte = inb(smbus_base + SMBHSTDAT0);
if (global_status_register != (1 << 1))
return SMBUS_ERROR;
return byte;
}

View File

@ -17,6 +17,7 @@
config SOUTHBRIDGE_INTEL_I82801IX config SOUTHBRIDGE_INTEL_I82801IX
bool bool
select SOUTHBRIDGE_INTEL_COMMON select SOUTHBRIDGE_INTEL_COMMON
select SOUTHBRIDGE_INTEL_COMMON_SMBUS
select IOAPIC select IOAPIC
select HAVE_USBDEBUG select HAVE_USBDEBUG
select HAVE_HARD_RESET select HAVE_HARD_RESET

View File

@ -19,8 +19,8 @@
#include <console/console.h> #include <console/console.h>
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/pci_def.h> #include <device/pci_def.h>
#include <southbridge/intel/common/smbus.h>
#include "i82801ix.h" #include "i82801ix.h"
#include "smbus.h"
void enable_smbus(void) void enable_smbus(void)
{ {

View File

@ -154,22 +154,6 @@
#define SMB_SMI_EN (1 << 1) #define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0) #define HST_EN (1 << 0)
/* SMBus I/O bits. */
#define SMBHSTSTAT 0x0
#define SMBHSTCTL 0x2
#define SMBHSTCMD 0x3
#define SMBXMITADD 0x4
#define SMBHSTDAT0 0x5
#define SMBHSTDAT1 0x6
#define SMBBLKDAT 0x7
#define SMBTRNSADD 0x9
#define SMBSLVDATA 0xa
#define SMLINK_PIN_CTL 0xe
#define SMBUS_PIN_CTL 0xf
#define SMBUS_TIMEOUT (10 * 1000 * 100)
#define RCBA8(x) *((volatile u8 *)(DEFAULT_RCBA + x)) #define RCBA8(x) *((volatile u8 *)(DEFAULT_RCBA + x))
#define RCBA16(x) *((volatile u16 *)(DEFAULT_RCBA + x)) #define RCBA16(x) *((volatile u16 *)(DEFAULT_RCBA + x))
#define RCBA32(x) *((volatile u32 *)(DEFAULT_RCBA + x)) #define RCBA32(x) *((volatile u32 *)(DEFAULT_RCBA + x))

View File

@ -22,7 +22,8 @@
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/pci_ops.h> #include <device/pci_ops.h>
#include <arch/io.h> #include <arch/io.h>
#include "smbus.h" #include <southbridge/intel/common/smbus.h>
#include "i82801ix.h"
static void pch_smbus_init(device_t dev) static void pch_smbus_init(device_t dev)
{ {

View File

@ -1,140 +0,0 @@
/*
* 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; 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <device/smbus_def.h>
#include "i82801ix.h"
static void smbus_delay(void)
{
inb(0x80);
}
static int smbus_wait_until_ready(u16 smbus_base)
{
unsigned loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_base + SMBHSTSTAT);
} while (byte & 1);
return loops ? 0 : -1;
}
static int smbus_wait_until_done(u16 smbus_base)
{
unsigned loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_base + SMBHSTSTAT);
} while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
return loops ? 0 : -1;
}
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(smbus_base) < 0) {
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
}
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Clear the data byte... */
outb(0, smbus_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_base) < 0) {
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
}
global_status_register = inb(smbus_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
global_status_register &= ~(3 << 5);
/* Read results of transaction */
byte = inb(smbus_base + SMBHSTDAT0);
if (global_status_register != (1 << 1)) {
return SMBUS_ERROR;
}
return byte;
}
#ifndef __PRE_RAM__
static int do_smbus_write_byte(unsigned smbus_base, unsigned device, unsigned address, unsigned data)
{
unsigned char global_status_register;
if (smbus_wait_until_ready(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Clear the data byte... */
outb(data, smbus_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
global_status_register = inb(smbus_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
global_status_register &= ~(3 << 5);
/* Read results of transaction */
if (global_status_register != (1 << 1))
return SMBUS_ERROR;
return 0;
}
#endif

View File

@ -17,6 +17,7 @@
config SOUTHBRIDGE_INTEL_I82801JX config SOUTHBRIDGE_INTEL_I82801JX
bool bool
select SOUTHBRIDGE_INTEL_COMMON select SOUTHBRIDGE_INTEL_COMMON
select SOUTHBRIDGE_INTEL_COMMON_SMBUS
select IOAPIC select IOAPIC
select HAVE_USBDEBUG select HAVE_USBDEBUG
select HAVE_HARD_RESET select HAVE_HARD_RESET

View File

@ -19,8 +19,8 @@
#include <console/console.h> #include <console/console.h>
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/pci_def.h> #include <device/pci_def.h>
#include <southbridge/intel/common/smbus.h>
#include "i82801jx.h" #include "i82801jx.h"
#include "smbus.h"
void enable_smbus(void) void enable_smbus(void)
{ {

View File

@ -147,22 +147,6 @@
#define SMB_SMI_EN (1 << 1) #define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0) #define HST_EN (1 << 0)
/* SMBus I/O bits. */
#define SMBHSTSTAT 0x0
#define SMBHSTCTL 0x2
#define SMBHSTCMD 0x3
#define SMBXMITADD 0x4
#define SMBHSTDAT0 0x5
#define SMBHSTDAT1 0x6
#define SMBBLKDAT 0x7
#define SMBTRNSADD 0x9
#define SMBSLVDATA 0xa
#define SMLINK_PIN_CTL 0xe
#define SMBUS_PIN_CTL 0xf
#define SMBUS_TIMEOUT (10 * 1000 * 100)
#define RCBA8(x) *((volatile u8 *)(DEFAULT_RCBA + x)) #define RCBA8(x) *((volatile u8 *)(DEFAULT_RCBA + x))
#define RCBA16(x) *((volatile u16 *)(DEFAULT_RCBA + x)) #define RCBA16(x) *((volatile u16 *)(DEFAULT_RCBA + x))
#define RCBA32(x) *((volatile u32 *)(DEFAULT_RCBA + x)) #define RCBA32(x) *((volatile u32 *)(DEFAULT_RCBA + x))

View File

@ -22,7 +22,8 @@
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/pci_ops.h> #include <device/pci_ops.h>
#include <arch/io.h> #include <arch/io.h>
#include "smbus.h" #include <southbridge/intel/common/smbus.h>
#include "i82801jx.h"
static void pch_smbus_init(device_t dev) static void pch_smbus_init(device_t dev)
{ {

View File

@ -1,140 +0,0 @@
/*
* 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; 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <device/smbus_def.h>
#include "i82801jx.h"
static void smbus_delay(void)
{
inb(0x80);
}
static int smbus_wait_until_ready(u16 smbus_base)
{
unsigned loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_base + SMBHSTSTAT);
} while (byte & 1);
return loops ? 0 : -1;
}
static int smbus_wait_until_done(u16 smbus_base)
{
unsigned loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_base + SMBHSTSTAT);
} while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
return loops ? 0 : -1;
}
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(smbus_base) < 0) {
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
}
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Clear the data byte... */
outb(0, smbus_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_base) < 0) {
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
}
global_status_register = inb(smbus_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
global_status_register &= ~(3 << 5);
/* Read results of transaction */
byte = inb(smbus_base + SMBHSTDAT0);
if (global_status_register != (1 << 1)) {
return SMBUS_ERROR;
}
return byte;
}
#ifndef __PRE_RAM__
static int do_smbus_write_byte(unsigned smbus_base, unsigned device, unsigned address, unsigned data)
{
unsigned char global_status_register;
if (smbus_wait_until_ready(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Clear the data byte... */
outb(data, smbus_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
global_status_register = inb(smbus_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
global_status_register &= ~(3 << 5);
/* Read results of transaction */
if (global_status_register != (1 << 1))
return SMBUS_ERROR;
return 0;
}
#endif

View File

@ -30,6 +30,7 @@ config SOUTH_BRIDGE_OPTIONS # dummy
select PCIEXP_COMMON_CLOCK select PCIEXP_COMMON_CLOCK
select SPI_FLASH select SPI_FLASH
select SOUTHBRIDGE_INTEL_COMMON select SOUTHBRIDGE_INTEL_COMMON
select SOUTHBRIDGE_INTEL_COMMON_SMBUS
select HAVE_USBDEBUG_OPTIONS select HAVE_USBDEBUG_OPTIONS
select COMMON_FADT select COMMON_FADT
select ACPI_SATA_GENERATOR select ACPI_SATA_GENERATOR

View File

@ -18,8 +18,8 @@
#include <console/console.h> #include <console/console.h>
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/pci_def.h> #include <device/pci_def.h>
#include <southbridge/intel/common/smbus.h>
#include "pch.h" #include "pch.h"
#include "smbus.h"
void enable_smbus(void) void enable_smbus(void)
{ {

View File

@ -233,22 +233,6 @@ void southbridge_configure_default_intmap(void);
#define SMB_SMI_EN (1 << 1) #define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0) #define HST_EN (1 << 0)
/* SMBus I/O bits. */
#define SMBHSTSTAT 0x0
#define SMBHSTCTL 0x2
#define SMBHSTCMD 0x3
#define SMBXMITADD 0x4
#define SMBHSTDAT0 0x5
#define SMBHSTDAT1 0x6
#define SMBBLKDAT 0x7
#define SMBTRNSADD 0x9
#define SMBSLVDATA 0xa
#define SMLINK_PIN_CTL 0xe
#define SMBUS_PIN_CTL 0xf
#define SMBUS_TIMEOUT (10 * 1000 * 100)
/* Southbridge IO BARs */ /* Southbridge IO BARs */
#define GPIOBASE 0x48 #define GPIOBASE 0x48

View File

@ -22,8 +22,8 @@
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/pci_ops.h> #include <device/pci_ops.h>
#include <arch/io.h> #include <arch/io.h>
#include <southbridge/intel/common/smbus.h>
#include "pch.h" #include "pch.h"
#include "smbus.h"
static void pch_smbus_init(device_t dev) static void pch_smbus_init(device_t dev)
{ {

View File

@ -1,241 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
* Copyright (C) 2009 coresystems GmbH
* Copyright (C) 2013 Vladimir Serbinenko
*
* 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <device/smbus_def.h>
#include "pch.h"
static void smbus_delay(void)
{
inb(0x80);
}
static int smbus_wait_until_ready(u16 smbus_base)
{
unsigned loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_base + SMBHSTSTAT);
} while (byte & 1);
return loops ? 0 : -1;
}
static int smbus_wait_until_done(u16 smbus_base)
{
unsigned loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_base + SMBHSTSTAT);
} while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
return loops ? 0 : -1;
}
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(smbus_base) < 0) {
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
}
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Clear the data byte... */
outb(0, smbus_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_base) < 0) {
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
}
global_status_register = inb(smbus_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
global_status_register &= ~(3 << 5);
/* Read results of transaction */
byte = inb(smbus_base + SMBHSTDAT0);
if (global_status_register != (1 << 1)) {
return SMBUS_ERROR;
}
return byte;
}
static int do_smbus_write_byte(unsigned smbus_base, unsigned device, unsigned address, unsigned data)
{
unsigned char global_status_register;
if (smbus_wait_until_ready(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Clear the data byte... */
outb(data, smbus_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
global_status_register = inb(smbus_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
global_status_register &= ~(3 << 5);
/* Read results of transaction */
if (global_status_register != (1 << 1))
return SMBUS_ERROR;
return 0;
}
#ifdef __PRE_RAM__
static int do_smbus_block_write(unsigned smbus_base, unsigned device,
unsigned cmd, unsigned bytes, const u8 *buf)
{
u8 status;
if (smbus_wait_until_ready(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(cmd & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a block data write */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x5 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* set number of bytes to transfer */
outb(bytes, smbus_base + SMBHSTDAT0);
outb(*buf++, smbus_base + SMBBLKDAT);
bytes--;
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
while (!(inb(smbus_base + SMBHSTSTAT) & 1));
/* Poll for transaction completion */
do {
status = inb(smbus_base + SMBHSTSTAT);
if (status & ((1 << 4) | /* FAILED */
(1 << 3) | /* BUS ERR */
(1 << 2))) /* DEV ERR */
return SMBUS_ERROR;
if (status & 0x80) { /* Byte done */
outb(*buf++, smbus_base + SMBBLKDAT);
outb(status, smbus_base + SMBHSTSTAT);
}
} while (status & 0x01);
return 0;
}
static int do_smbus_block_read(unsigned smbus_base, unsigned device,
unsigned cmd, unsigned bytes, u8 *buf)
{
u8 status;
int bytes_read = 0;
if (smbus_wait_until_ready(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(cmd & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a block data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x5 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
while (!(inb(smbus_base + SMBHSTSTAT) & 1));
/* Poll for transaction completion */
do {
status = inb(smbus_base + SMBHSTSTAT);
if (status & ((1 << 4) | /* FAILED */
(1 << 3) | /* BUS ERR */
(1 << 2))) /* DEV ERR */
return SMBUS_ERROR;
if (status & 0x80) { /* Byte done */
*buf = inb(smbus_base + SMBBLKDAT);
buf++;
bytes_read++;
outb(status, smbus_base + SMBHSTSTAT);
if (--bytes == 1) {
/* indicate that next byte is the last one */
outb(inb(smbus_base + SMBHSTCTL) | 0x20,
smbus_base + SMBHSTCTL);
}
}
} while (status & 0x01);
return bytes_read;
}
#endif

View File

@ -22,6 +22,7 @@ config SOUTH_BRIDGE_OPTIONS # dummy
def_bool y def_bool y
select ACPI_INTEL_HARDWARE_SLEEP_VALUES select ACPI_INTEL_HARDWARE_SLEEP_VALUES
select SOUTHBRIDGE_INTEL_COMMON select SOUTHBRIDGE_INTEL_COMMON
select SOUTHBRIDGE_INTEL_COMMON_SMBUS
select IOAPIC select IOAPIC
select HAVE_HARD_RESET select HAVE_HARD_RESET
select HAVE_USBDEBUG_OPTIONS select HAVE_USBDEBUG_OPTIONS

View File

@ -18,8 +18,8 @@
#include <console/console.h> #include <console/console.h>
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/pci_def.h> #include <device/pci_def.h>
#include <southbridge/intel/common/smbus.h>
#include "pch.h" #include "pch.h"
#include "smbus.h"
void enable_smbus(void) void enable_smbus(void)
{ {

View File

@ -473,22 +473,6 @@ void pch_enable_lpc(void);
#define SMB_SMI_EN (1 << 1) #define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0) #define HST_EN (1 << 0)
/* SMBus I/O bits. */
#define SMBHSTSTAT 0x0
#define SMBHSTCTL 0x2
#define SMBHSTCMD 0x3
#define SMBXMITADD 0x4
#define SMBHSTDAT0 0x5
#define SMBHSTDAT1 0x6
#define SMBBLKDAT 0x7
#define SMBTRNSADD 0x9
#define SMBSLVDATA 0xa
#define SMLINK_PIN_CTL 0xe
#define SMBUS_PIN_CTL 0xf
#define SMBUS_TIMEOUT (10 * 1000 * 100)
/* Southbridge IO BARs */ /* Southbridge IO BARs */
#define GPIOBASE 0x48 #define GPIOBASE 0x48

View File

@ -22,8 +22,8 @@
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <device/pci_ops.h> #include <device/pci_ops.h>
#include <arch/io.h> #include <arch/io.h>
#include <southbridge/intel/common/smbus.h>
#include "pch.h" #include "pch.h"
#include "smbus.h"
static void pch_smbus_init(device_t dev) static void pch_smbus_init(device_t dev)
{ {
@ -54,54 +54,6 @@ static int lsmbus_read_byte(device_t dev, u8 address)
return do_smbus_read_byte(res->base, device, address); return do_smbus_read_byte(res->base, device, address);
} }
static int do_smbus_write_byte(unsigned smbus_base, unsigned device,
unsigned address, unsigned data)
{
unsigned char global_status_register;
if (smbus_wait_until_ready(smbus_base) < 0)
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Clear the data byte... */
outb(data, smbus_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_base) < 0) {
printk(BIOS_ERR, "SMBUS transaction timeout\n");
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
}
global_status_register = inb(smbus_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
global_status_register &= ~(3 << 5);
/* Read results of transaction */
if (global_status_register != (1 << 1)) {
printk(BIOS_ERR, "SMBUS transaction error\n");
return SMBUS_ERROR;
}
return 0;
}
static int lsmbus_write_byte(device_t dev, u8 address, u8 data) static int lsmbus_write_byte(device_t dev, u8 address, u8 data)
{ {
u16 device; u16 device;

View File

@ -1,95 +0,0 @@
/*
* 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; 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <device/smbus_def.h>
#include "pch.h"
static void smbus_delay(void)
{
inb(0x80);
}
static int smbus_wait_until_ready(u16 smbus_base)
{
unsigned loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_base + SMBHSTSTAT);
} while (byte & 1);
return loops ? 0 : -1;
}
static int smbus_wait_until_done(u16 smbus_base)
{
unsigned loops = SMBUS_TIMEOUT;
unsigned char byte;
do {
smbus_delay();
if (--loops == 0)
break;
byte = inb(smbus_base + SMBHSTSTAT);
} while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
return loops ? 0 : -1;
}
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(smbus_base) < 0) {
return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
}
/* Setup transaction */
/* Disable interrupts */
outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
/* Set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
/* Set the command/address... */
outb(address & 0xff, smbus_base + SMBHSTCMD);
/* Set up for a byte data read */
outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
(smbus_base + SMBHSTCTL));
/* Clear any lingering errors, so the transaction will run */
outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
/* Clear the data byte... */
outb(0, smbus_base + SMBHSTDAT0);
/* Start the command */
outb((inb(smbus_base + SMBHSTCTL) | 0x40),
smbus_base + SMBHSTCTL);
/* Poll for transaction completion */
if (smbus_wait_until_done(smbus_base) < 0) {
return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
}
global_status_register = inb(smbus_base + SMBHSTSTAT);
/* Ignore the "In Use" status... */
global_status_register &= ~(3 << 5);
/* Read results of transaction */
byte = inb(smbus_base + SMBHSTDAT0);
if (global_status_register != (1 << 1)) {
return SMBUS_ERROR;
}
return byte;
}