[coreboot] New patch to review for coreboot: 437e073 Added block smbus block operations for amd8111 Fixed bug in one function prototype also: smbus_block_read should pass pointer to block length, not value. Makes no sense to me to pass a value.

Oskar Enoksson (enok@lysator.liu.se) gerrit at coreboot.org
Sat Oct 15 13:33:01 CEST 2011


Oskar Enoksson (enok at lysator.liu.se) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/281

-gerrit

commit 437e07301e3239e50f842aa95fcbaf5525f1ae92
Author: Oskar Enoksson <enok at lysator.liu.se>
Date:   Fri Oct 14 02:16:48 2011 +0200

    Added block smbus block operations for amd8111
    Fixed bug in one function prototype also: smbus_block_read should
    pass pointer to block length, not value. Makes no sense to me to
    pass a value.
    
    Signed-off-by: Oskar Enoksson <enok at lysator.liu.se>
    Change-Id: I86c80a27fd13c9a2be4034fdfb63be4ab2fadbfc
---
 src/devices/smbus_ops.c                     |    2 +-
 src/include/device/smbus.h                  |    4 +-
 src/southbridge/amd/amd8111/acpi.c          |   25 +++++++
 src/southbridge/amd/amd8111/amd8111_smbus.h |   98 +++++++++++++++++++++++++++
 src/southbridge/amd/amd8111/early_smbus.c   |    9 +++
 5 files changed, 135 insertions(+), 3 deletions(-)

diff --git a/src/devices/smbus_ops.c b/src/devices/smbus_ops.c
index 75ca42b..d0e226f 100644
--- a/src/devices/smbus_ops.c
+++ b/src/devices/smbus_ops.c
@@ -124,7 +124,7 @@ int smbus_process_call(device_t dev, u8 cmd, u16 data)
 	return ops_smbus_bus(get_pbus_smbus(dev))->process_call(dev, cmd, data);
 }
 
-int smbus_block_read(device_t dev, u8 cmd, u8 bytes, u8 *buffer)
+int smbus_block_read(device_t dev, u8 cmd, u8 *bytes, u8 *buffer)
 {
 	return ops_smbus_bus(get_pbus_smbus(dev))->block_read(dev, cmd,
 							      bytes, buffer);
diff --git a/src/include/device/smbus.h b/src/include/device/smbus.h
index 073d7e2..bd8f8ce 100644
--- a/src/include/device/smbus.h
+++ b/src/include/device/smbus.h
@@ -17,7 +17,7 @@ struct smbus_bus_operations {
 	int (*read_word)   (device_t dev, u8 addr);
 	int (*write_word)  (device_t dev, u8 addr, u16 value);
 	int (*process_call)(device_t dev, u8 cmd, u16 data);
-	int (*block_read)  (device_t dev, u8 cmd, u8 bytes, u8 *buffer);
+	int (*block_read)  (device_t dev, u8 cmd, u8 *bytes, u8 *buffer);
 	int (*block_write) (device_t dev, u8 cmd, u8 bytes, const u8 *buffer);
 };
 
@@ -44,7 +44,7 @@ int smbus_write_byte(device_t dev, u8 addr, u8 val);
 int smbus_read_word(device_t dev, u8 addr);
 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_read(device_t dev, u8 cmd, u8 *bytes, u8 *buffer);
 int smbus_block_write(device_t dev, u8 cmd, u8 bytes, const u8 *buffer);
 
 #endif /* DEVICE_SMBUS_H */
diff --git a/src/southbridge/amd/amd8111/acpi.c b/src/southbridge/amd/amd8111/acpi.c
index 2ad54b7..0c78b91 100644
--- a/src/southbridge/amd/amd8111/acpi.c
+++ b/src/southbridge/amd/amd8111/acpi.c
@@ -66,6 +66,29 @@ static int lsmbus_write_byte(device_t dev, uint8_t address, uint8_t val)
 	return do_smbus_write_byte(res->base, device, address, val);
 }
 
+static int lsmbus_block_read(device_t dev, uint8_t cmd, u8 *bytes, u8 *buffer)
+{
+	unsigned device;
+	struct resource *res;
+
+	device = dev->path.i2c.device;
+	res = find_resource(get_pbus_smbus(dev)->dev, 0x58);
+
+	return do_smbus_block_read(res->base, device, cmd, bytes, buffer);
+}
+
+static int lsmbus_block_write(device_t dev, uint8_t cmd, u8 bytes, const u8 *buffer)
+{
+	unsigned device;
+	struct resource *res;
+
+	device = dev->path.i2c.device;
+	res = find_resource(get_pbus_smbus(dev)->dev, 0x58);
+
+	return do_smbus_block_write(res->base, device, cmd, bytes, buffer);
+}
+
+
 #if CONFIG_GENERATE_ACPI_TABLES == 1
 unsigned pm_base;
 #endif
@@ -191,6 +214,8 @@ static struct smbus_bus_operations lops_smbus_bus = {
 	.send_byte  = lsmbus_send_byte,
 	.read_byte  = lsmbus_read_byte,
 	.write_byte = lsmbus_write_byte,
+	.block_read = lsmbus_block_read,
+	.block_write= lsmbus_block_write,
 };
 
 static struct pci_operations lops_pci = {
diff --git a/src/southbridge/amd/amd8111/amd8111_smbus.h b/src/southbridge/amd/amd8111/amd8111_smbus.h
index fe9b3bf..f07893d 100644
--- a/src/southbridge/amd/amd8111/amd8111_smbus.h
+++ b/src/southbridge/amd/amd8111/amd8111_smbus.h
@@ -222,3 +222,101 @@ static int do_smbus_write_byte(unsigned smbus_io_base, unsigned device, unsigned
 	return 0;
 }
 
+static int do_smbus_block_read(unsigned smbus_io_base, unsigned device, unsigned cmd, u8 *bytes, u8 *buf)
+{
+	unsigned global_status_register;
+	unsigned i;
+
+	if (smbus_wait_until_ready(smbus_io_base) < 0) {
+		return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
+	}
+
+	/* setup transaction */
+	/* disable interrupts */
+	outw(inw(smbus_io_base + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), smbus_io_base + SMBGCTL);
+	/* set the device I'm talking too */
+	outw(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR);
+	/* set the command/address... */
+	outb(cmd & 0xFF, smbus_io_base + SMBHSTCMD);
+	/* set up for a block data read */
+	outw((inw(smbus_io_base + SMBGCTL) & ~7) | (0x5), smbus_io_base + SMBGCTL);
+
+	/* clear any lingering errors, so the transaction will run */
+	/* Do I need to write the bits to a 1 to clear an error? */
+	outw(inw(smbus_io_base + SMBGSTATUS), smbus_io_base + SMBGSTATUS);
+
+	/* clear the length word...*/
+	outw(0, smbus_io_base + SMBHSTDAT);
+
+	/* start the command */
+	outw((inw(smbus_io_base + SMBGCTL) | (1 << 3)), smbus_io_base + SMBGCTL);
+
+	/* poll for transaction completion */
+	if (smbus_wait_until_done(smbus_io_base) < 0) {
+		return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
+	}
+
+	global_status_register = inw(smbus_io_base + SMBGSTATUS);
+
+	/* read results of transaction */
+	*bytes = inw(smbus_io_base + SMBHSTDAT) & 0x3f;
+
+	if ((global_status_register & SMBUS_STATUS_MASK) != (1 << 4)) {
+		return SMBUS_ERROR;
+	}
+
+	/* read data block */
+	for(i=0; i<*bytes; i++) {
+		buf[i] = inw(smbus_io_base + SMBHSTFIFO) & 0xff;
+	}
+
+	return 0;
+}
+
+static int do_smbus_block_write(unsigned smbus_io_base, unsigned device, unsigned cmd, u8 bytes, const u8 *buf)
+{
+	unsigned global_status_register;
+	unsigned i;
+
+	if (smbus_wait_until_ready(smbus_io_base) < 0) {
+		return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
+	}
+
+	/* setup transaction */
+	/* disable interrupts */
+	outw(inw(smbus_io_base + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), smbus_io_base + SMBGCTL);
+	/* set the device I'm talking too */
+	outw(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR);
+	/* set the command/address... */
+	outb(cmd & 0xFF, smbus_io_base + SMBHSTCMD);
+	/* set up for a block data write */
+	outw((inw(smbus_io_base + SMBGCTL) & ~7) | (0x5), smbus_io_base + SMBGCTL);
+
+	/* clear any lingering errors, so the transaction will run */
+	/* Do I need to write the bits to a 1 to clear an error? */
+	outw(inw(smbus_io_base + SMBGSTATUS), smbus_io_base + SMBGSTATUS);
+
+	/* set the length word...*/
+	outw(bytes, smbus_io_base + SMBHSTDAT);
+
+	/* set the data block */
+	for(i=0; i<bytes; i++) {
+		outw(buf[i], smbus_io_base + SMBHSTFIFO);
+	}
+
+	/* start the command */
+	outw((inw(smbus_io_base + SMBGCTL) | (1 << 3)), smbus_io_base + SMBGCTL);
+
+	/* poll for transaction completion */
+	if (smbus_wait_until_done(smbus_io_base) < 0) {
+		return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
+	}
+	global_status_register = inw(smbus_io_base + SMBGSTATUS);
+
+	if ((global_status_register & SMBUS_STATUS_MASK) != (1 << 4)) {
+		return SMBUS_ERROR;
+	}
+	return 0;
+}
+
+
diff --git a/src/southbridge/amd/amd8111/early_smbus.c b/src/southbridge/amd/amd8111/early_smbus.c
index e6d7084..9a58a99 100644
--- a/src/southbridge/amd/amd8111/early_smbus.c
+++ b/src/southbridge/amd/amd8111/early_smbus.c
@@ -46,3 +46,12 @@ static inline int smbus_write_byte(unsigned device, unsigned address, unsigned c
 	return do_smbus_write_byte(SMBUS_IO_BASE, device, address, val);
 }
 
+static inline int smbus_block_read(unsigned device, unsigned cmd, u8 *bytes, u8 *buf)
+{
+	return do_smbus_block_read(SMBUS_IO_BASE, device, cmd, bytes, buf);
+}
+
+static inline int smbus_block_write(unsigned device, unsigned cmd, u8 bytes, const u8 *buf)
+{
+	return do_smbus_block_write(SMBUS_IO_BASE, device, cmd, bytes, buf);
+}




More information about the coreboot mailing list