
Vladimir Serbinenko (phcoder@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/4776 -gerrit commit a941408963c73092699765edd06966d335875e97 Author: Vladimir Serbinenko <phcoder@gmail.com> Date: Wed Jan 22 01:29:54 2014 +0100 smbus: Define smbus_read/write_byte_main_bus. Those new functions are much easier to use with multiaddress devices. Change-Id: Iaea90044b1817c828210ba3b61208738ea74c5fd Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com> --- src/include/device/smbus.h | 4 +++ src/southbridge/intel/bd82x6x/smbus.c | 16 ++++++++++ src/southbridge/intel/bd82x6x/smbus.h | 43 +++++++++++++++++++++++++ src/southbridge/intel/i82801gx/smbus.c | 57 +++++++++------------------------- src/southbridge/intel/i82801gx/smbus.h | 41 ++++++++++++++++++++++++ src/southbridge/intel/ibexpeak/smbus.c | 16 ++++++++++ src/southbridge/intel/ibexpeak/smbus.h | 6 ++-- 7 files changed, 138 insertions(+), 45 deletions(-) diff --git a/src/include/device/smbus.h b/src/include/device/smbus.h index 073d7e2..7cd6da9 100644 --- a/src/include/device/smbus.h +++ b/src/include/device/smbus.h @@ -46,5 +46,9 @@ int smbus_write_word(device_t dev, u8 addr, u16 val); int smbus_process_call(device_t dev, u8 cmd, u16 data); int smbus_block_read(device_t dev, u8 cmd, u8 bytes, u8 *buffer); int smbus_block_write(device_t dev, u8 cmd, u8 bytes, const u8 *buffer); +/* Functions to access main bus simply by the address. Convenient for boards + which have only one bus. */ +int smbus_read_byte_main_bus(u8 dev, u8 addr); +int smbus_write_byte_main_bus(u8 dev, u8 addr, u8 val); #endif /* DEVICE_SMBUS_H */ diff --git a/src/southbridge/intel/bd82x6x/smbus.c b/src/southbridge/intel/bd82x6x/smbus.c index 4786d8b..e8e1aec 100644 --- a/src/southbridge/intel/bd82x6x/smbus.c +++ b/src/southbridge/intel/bd82x6x/smbus.c @@ -58,6 +58,22 @@ static int lsmbus_read_byte(device_t dev, u8 address) return do_smbus_read_byte(res->base, device, address); } +int smbus_read_byte_main_bus(u8 dev, u8 addr) +{ + device_t controller = dev_find_slot(0, PCI_DEVFN(0x1f, 3)); + struct resource *res = find_resource(controller, 0x20); + + return do_smbus_read_byte(res->base, dev, addr); +} + +int smbus_write_byte_main_bus(u8 dev, u8 addr, u8 val) +{ + device_t controller = dev_find_slot(0, PCI_DEVFN(0x1f, 3)); + struct resource *res = find_resource(controller, 0x20); + + return do_smbus_write_byte(res->base, dev, addr, val); +} + static struct smbus_bus_operations lops_smbus_bus = { .read_byte = lsmbus_read_byte, }; diff --git a/src/southbridge/intel/bd82x6x/smbus.h b/src/southbridge/intel/bd82x6x/smbus.h index 81e5949..9ea088d 100644 --- a/src/southbridge/intel/bd82x6x/smbus.h +++ b/src/southbridge/intel/bd82x6x/smbus.h @@ -98,3 +98,46 @@ static int do_smbus_read_byte(unsigned smbus_base, unsigned device, unsigned add return byte; } +static inline 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; +} + diff --git a/src/southbridge/intel/i82801gx/smbus.c b/src/southbridge/intel/i82801gx/smbus.c index 750da51..502184d 100644 --- a/src/southbridge/intel/i82801gx/smbus.c +++ b/src/southbridge/intel/i82801gx/smbus.c @@ -42,48 +42,6 @@ static int lsmbus_read_byte(device_t dev, u8 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 data) { u16 device; @@ -221,6 +179,21 @@ static int lsmbus_block_read(device_t dev, u8 cmd, u8 bytes, u8 *buf) return do_smbus_block_read(res->base, device, cmd, bytes, buf); } +int smbus_read_byte_main_bus(u8 dev, u8 addr) +{ + device_t controller = dev_find_slot(0, PCI_DEVFN(0x1f, 3)); + struct resource *res = find_resource(controller, 0x20); + + return do_smbus_read_byte(res->base, dev, addr); +} + +int smbus_write_byte_main_bus(u8 dev, u8 addr, u8 val) +{ + device_t controller = dev_find_slot(0, PCI_DEVFN(0x1f, 3)); + struct resource *res = find_resource(controller, 0x20); + + return do_smbus_write_byte(res->base, dev, addr, val); +} static struct smbus_bus_operations lops_smbus_bus = { .read_byte = lsmbus_read_byte, diff --git a/src/southbridge/intel/i82801gx/smbus.h b/src/southbridge/intel/i82801gx/smbus.h index 23b46ce..197727e 100644 --- a/src/southbridge/intel/i82801gx/smbus.h +++ b/src/southbridge/intel/i82801gx/smbus.h @@ -98,3 +98,44 @@ static int do_smbus_read_byte(unsigned smbus_base, unsigned device, unsigned add return byte; } +static inline 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; +} diff --git a/src/southbridge/intel/ibexpeak/smbus.c b/src/southbridge/intel/ibexpeak/smbus.c index ad7c8f9..29850be 100644 --- a/src/southbridge/intel/ibexpeak/smbus.c +++ b/src/southbridge/intel/ibexpeak/smbus.c @@ -62,6 +62,22 @@ static struct smbus_bus_operations lops_smbus_bus = { .read_byte = lsmbus_read_byte, }; +int smbus_read_byte_main_bus(u8 dev, u8 addr) +{ + device_t controller = dev_find_slot(0, PCI_DEVFN(0x1f, 3)); + struct resource *res = find_resource(controller, 0x20); + + return do_smbus_read_byte(res->base, dev, addr); +} + +int smbus_write_byte_main_bus(u8 dev, u8 addr, u8 val) +{ + device_t controller = dev_find_slot(0, PCI_DEVFN(0x1f, 3)); + struct resource *res = find_resource(controller, 0x20); + + return do_smbus_write_byte(res->base, dev, addr, val); +} + static void smbus_set_subsystem(device_t dev, unsigned vendor, unsigned device) { if (!vendor || !device) { diff --git a/src/southbridge/intel/ibexpeak/smbus.h b/src/southbridge/intel/ibexpeak/smbus.h index 6858e7d..5e03ada 100644 --- a/src/southbridge/intel/ibexpeak/smbus.h +++ b/src/southbridge/intel/ibexpeak/smbus.h @@ -99,9 +99,7 @@ static int do_smbus_read_byte(unsigned smbus_base, unsigned device, unsigned add return byte; } -#ifdef __PRE_RAM__ - -static int do_smbus_write_byte(unsigned smbus_base, unsigned device, unsigned address, unsigned data) +static inline int do_smbus_write_byte(unsigned smbus_base, unsigned device, unsigned address, unsigned data) { unsigned char global_status_register; @@ -144,6 +142,8 @@ static int do_smbus_write_byte(unsigned smbus_base, unsigned device, unsigned a return 0; } +#ifdef __PRE_RAM__ + static int do_smbus_block_write(unsigned smbus_base, unsigned device, unsigned cmd, unsigned bytes, const u8 *buf) {