Example #1
0
int do_smbus_recv_byte(u32 smbus_io_base, u32 device)
{
	u8 byte;

	if (smbus_wait_until_ready(smbus_io_base) < 0) {
        printk(BIOS_DEBUG, "SB800 - Smbus.c - do_smbus_recv_byte - smbus not ready.\n");
		return -2;	/* not ready */
	}

    printk(BIOS_DEBUG, "SB800 - Smbus.c - do_smbus_recv_byte - Start.\n");
	/* set the device I'm talking too */
	outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR);

	byte = inb(smbus_io_base + SMBHSTCTRL);
	byte &= 0xe3;		/* Clear [4:2] */
	byte |= (1 << 2) | (1 << 6);	/* Byte data read/write command, start the command */
	outb(byte, smbus_io_base + SMBHSTCTRL);

	/* poll for transaction completion */
	if (smbus_wait_until_done(smbus_io_base) < 0) {
		return -3;	/* timeout or error */
	}

	/* read results of transaction */
	byte = inb(smbus_io_base + SMBHSTCMD);

    printk(BIOS_DEBUG, "SB800 - Smbus.c - do_smbus_recv_byte - End.\n");
	return byte;
}
Example #2
0
static void smbus_write_byte(unsigned device, unsigned address, unsigned char val)
{
	if (smbus_wait_until_ready(SMBUS_IO_BASE) < 0) {
		return;
	}

	print_debug("Unimplemented smbus_write_byte() called.\n");

#if 0
	/* 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);
	outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
	/* set up for a byte data write */ /* FIXME */
	outw((inw(SMBUS_IO_BASE + SMBGCTL) & ~7) | (0x1), 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 data word...*/
	outw(val, SMBUS_IO_BASE + SMBHSTDAT);

	/* start the command */
	outw((inw(SMBUS_IO_BASE + SMBGCTL) | (1 << 3)), SMBUS_IO_BASE + SMBGCTL);

	/* poll for transaction completion */
	smbus_wait_until_done(SMBUS_IO_BASE);
#endif
	return;
}
Example #3
0
int do_smbus_write_byte(u32 smbus_io_base, u32 device, u32 address, u8 val)
{
	u8 byte;

	if (smbus_wait_until_ready(smbus_io_base) < 0) {
        printk(BIOS_DEBUG, "SB800 - Smbus.c - do_smbus_write_byte - smbus not ready.\n");
		return -2;	/* not ready */
	}

    printk(BIOS_DEBUG, "SB800 - Smbus.c - do_smbus_write_byte - Start.\n");
	/* set the command/address... */
	outb(address & 0xff, smbus_io_base + SMBHSTCMD);

	/* set the device I'm talking too */
	outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR);

	/* output value */
	outb(val, smbus_io_base + SMBHSTDAT0);

	byte = inb(smbus_io_base + SMBHSTCTRL);
	byte &= 0xe3;		/* Clear [4:2] */
	byte |= (1 << 3) | (1 << 6);	/* Byte data read/write command, start the command */
	outb(byte, smbus_io_base + SMBHSTCTRL);

	/* poll for transaction completion */
	if (smbus_wait_until_done(smbus_io_base) < 0) {
		return -3;	/* timeout or error */
	}

    printk(BIOS_DEBUG, "SB800 - Smbus.c - do_smbus_write_byte - End.\n");
	return 0;
}
Example #4
0
int do_smbus_read_byte(u32 smbus_io_base, u32 device, u32 address)
{
	u8 byte;

	if (smbus_wait_until_ready(smbus_io_base) < 0) {
		return -2;	/* not ready */
	}

	/* set the command/address... */
	outb(address & 0xff, smbus_io_base + SMBHSTCMD);

	/* set the device I'm talking too */
	outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR);

	byte = inb(smbus_io_base + SMBHSTCTRL);
	byte &= 0xe3;		/* Clear [4:2] */
	byte |= (1 << 3) | (1 << 6);	/* Byte data read/write command, start the command */
	outb(byte, smbus_io_base + SMBHSTCTRL);

	/* poll for transaction completion */
	if (smbus_wait_until_done(smbus_io_base) < 0) {
		return -3;	/* timeout or error */
	}

	/* read results of transaction */
	byte = inb(smbus_io_base + SMBHSTDAT0);

	return byte;
}
Example #5
0
int do_smbus_write_byte(u32 mmio, u8 device, u8 address, u8 val)
{
	u8 byte;

	if (smbus_wait_until_ready(mmio) < 0)
		return -2;	/* not ready */

	/* set the command/address... */
	smbus_write8(mmio, SMBHSTCMD, address & 0xff);

	/* set the device I'm talking to */
	smbus_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 0);

	/* output value */
	smbus_write8(mmio, SMBHSTDAT0, val);

	byte = smbus_read8(mmio, SMBHSTCTRL);
	byte &= ~SMBHST_CTRL_MODE_BITS;			/* Clear [4:2] */
	byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BDT_RW;	/* set mode, start */
	smbus_write8(mmio, SMBHSTCTRL, byte);

	/* poll for transaction completion */
	if (smbus_wait_until_done(mmio) < 0)
		return -3;	/* timeout or error */

	return 0;
}
Example #6
0
int do_smbus_send_byte(u32 smbus_io_base, u32 device, u8 val)
{
	u8 byte;

	if (smbus_wait_until_ready(smbus_io_base) < 0) {
		return -2;	/* not ready */
	}

	/* set the command... */
	outb(val, smbus_io_base + SMBHSTCMD);

	/* set the device I'm talking too */
	outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR);

	byte = inb(smbus_io_base + SMBHSTCTRL);
	byte &= 0xe3;		/* Clear [4:2] */
	byte |= (1 << 2) | (1 << 6);	/* Byte data read/write command, start the command */
	outb(byte, smbus_io_base + SMBHSTCTRL);

	/* poll for transaction completion */
	if (smbus_wait_until_done(smbus_io_base) < 0) {
		return -3;	/* timeout or error */
	}

	return 0;
}
Example #7
0
static int smbus_read_byte(unsigned device, unsigned address)
{
	unsigned char global_status_register;
	unsigned char byte;

	/* print_err("smbus_read_byte\n"); */
	if (smbus_wait_until_ready() < 0) {
		print_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) {
		print_err("SMBUS not active (-4)\n");
		return -4;
	}

	/* poll for transaction completion */
	if (smbus_wait_until_done() < 0) {
		print_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) {
		//print_spew("%s: no device (%02x, %02x)\n", __func__, device, address);
		return -1;
	}
	//print_debug("%s: %02x@%02x = %02x\n", __func__, device, address, byte);
	return byte;
}
/*
 * Copied from intel/i82801dbm early smbus code - suggested by rgm.
 * Modifications/check against i2c-viapro driver code from linux-2.4.22
 * and VT8231 Reference Docs - mw.
 */
static int smbus_read_byte(unsigned device, unsigned address)
{
	unsigned char global_status_register;
	unsigned char byte;

	if (smbus_wait_until_ready() < 0) {
		outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
		if (smbus_wait_until_ready() < 0) {
			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) {
		return -4;
	}

	/* poll for transaction completion */
	if (smbus_wait_until_done() < 0) {
		return -3;
	}

	/* Ignore the Host Busy & Command Complete ? */
	global_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT) & ~((1 << 1) | (1 << 0));

	/* read results of transaction */
	byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);

	if (global_status_register != 0) {
		return -1;
	}
	return byte;
}
Example #9
0
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;
}
Example #10
0
int smbus_read_byte(unsigned device, unsigned address, unsigned char *result)
{
	unsigned char host_status_register;
	unsigned char byte;

	reset();

	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 + 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 */
	smbus_wait_until_done();

	host_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT);

	/* Ignore the In Use Status... */
	host_status_register &= ~(1 << 6);

	/* read results of transaction */
	byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);
	smbus_print_error(byte);

	*result = byte;
	return host_status_register != 0x02;
}
Example #11
0
static int smbus_block_write(u32 base, u8 dev, u8 *buffer,
			     int offset, int len)
{
	int i;

	debug("%s (%d): dev=0x%x offs=0x%x len=0x%x\n",
	      __func__, __LINE__, dev, offset, len);
	if (smbus_wait_until_ready(base) < 0)
		return -ETIMEDOUT;

	/* Setup transaction */
	/* Set the device I'm talking too */
	outb(((dev & 0x7f) << 1) & ~0x01, base + SMBXMITADD);
	/* Set the command/address... */
	outb(offset, base + SMBHSTCMD);
	/* Set up for a block write */
	outb((inb(base + SMBHSTCTL) & (~(0x7) << 2)) | (0x5 << 2),
	     (base + SMBHSTCTL));
	/* Clear any lingering errors, so the transaction will run */
	outb(inb(base + SMBHSTSTAT), base + SMBHSTSTAT);

	/* Write count in DAT0 register */
	outb(len, base + SMBHSTDAT0);

	/* Write data bytes... */
	for (i = 0; i < len; i++)
		outb(*buffer++, base + SMBBLKDAT);

	/* Start the command */
	outb((inb(base + SMBHSTCTL) | SMBHSTCNT_START), base + SMBHSTCTL);

	/* Poll for transaction completion */
	if (smbus_wait_until_done(base) < 0) {
		printf("SMBUS write transaction timeout (dev=0x%x)\n", dev);
		return -ETIMEDOUT;
	}

	/* Return results of transaction */
	if (!(inb(base + SMBHSTSTAT) & SMBHSTSTS_INTR))
		return -EIO;

	return 0;
}
Example #12
0
/** \brief generic smbus helper function to read & write to the smbus
 *
 * \details Configures the SMBus for the transaction, sets up the address
 *          and data bytes, starts the command, waits for the command to
 *          finish, and returns data if the command is a read.
 *
 * \param device The 8-bit device address, with the read / write bit set-up.
 *
 * \param addr_dat For full reads/writes, this contains the address within
 *                 the device of the byte being read/written. For quick writes,
 *                 this contains the data to write.
 *
 * \param data For full writes, this contains the Data to write to the
 *             device.  For all other transactions, this is ignored.
 *
 * \param command Contains the command for a full read/write (0x48) or the
 *                command for a quick read/write (0x44)
 *
 * \return Data read from the device, or -1 if there was an error
 */
static s16 smbus_rw_byte(u8 device, u8 addr_dat, u8 data, u8 command)
{
	u8 global_status_register;

	if (smbus_wait_until_ready(SMBUS_IO_BASE) < 0)
		return SMBUS_WAIT_UNTIL_READY_TIMEOUT;

	/*** Set up transaction ***/

	/* Disable interrupts */
	outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);

	/* Set the device being talked to using supplied device address*/
	outb(device, SMBUS_IO_BASE + SMBXMITADD);

	/* Set the address and data byte */
	outb(addr_dat, SMBUS_IO_BASE + SMBHSTCMD);
	outb(data, SMBUS_IO_BASE + SMBHSTDAT0);

	/* Clear any lingering errors, so the transaction will run */
	outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);

	/* Start the command */
	outb(command, 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 &= ~(HSTSTS_SMBALERT_STS | HSTSTS_INUSE_STS);

	/* Read results - INTR gets set when a command is completed successfully */
	data = inb(SMBUS_IO_BASE + SMBHSTDAT0);
	if (global_status_register != HSTSTS_INTR)
		return SMBUS_ERROR;

	return data;
}
Example #13
0
int smbus_read_byte(unsigned device, unsigned address)
{
    unsigned char host_status_register;
    int result;

    smbus_wait_until_ready();

    /* setup transaction */
    /* disable interrupts */
    outb(inb(SMBUS_IO_HSTCTL) & (~1), SMBUS_IO_HSTCTL);
    /* set the device I'm talking too */
    outb(((device & 0x7f) << 1) | 1, SMBUS_IO_HSTADD);
    /* set the command/address... */
    outb(address & 0xFF, SMBUS_IO_HSTCMD);
    /* set up for a byte data read */
    outb((inb(SMBUS_IO_HSTCTL) & 0xE3) | 8, SMBUS_IO_HSTCTL);

    /* clear any lingering errors, so the transaction will run */
    outb(inb(SMBUS_IO_HSTSTAT), SMBUS_IO_HSTSTAT);

    /* clear the data byte...*/
    outb(0, SMBUS_IO_HSTDAT0);

    /* start the command */
    outb((inb(SMBUS_IO_HSTCTL) | 0x40), SMBUS_IO_HSTCTL);

    /* poll for transaction completion */
    smbus_wait_until_done();

    host_status_register = inb(SMBUS_IO_HSTSTAT);

    /* read results of transaction */
    result = inb(SMBUS_IO_HSTDAT0);

    if (host_status_register != 0x02) {
        result = -1;
    }
    return result;
}
Example #14
0
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 to read from the specified device  */
	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;		// return true if !SUCCESS
}
Example #15
0
int do_smbus_recv_byte(u32 mmio, u8 device)
{
	u8 byte;

	if (smbus_wait_until_ready(mmio) < 0)
		return -2;	/* not ready */

	/* set the device I'm talking to */
	smbus_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 1);

	byte = smbus_read8(mmio, SMBHSTCTRL);
	byte &= ~SMBHST_CTRL_MODE_BITS;			/* Clear [4:2] */
	byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BTE_RW;	/* set mode, start */
	smbus_write8(mmio, SMBHSTCTRL, byte);

	/* poll for transaction completion */
	if (smbus_wait_until_done(mmio) < 0)
		return -3;	/* timeout or error */

	/* read results of transaction */
	byte = smbus_read8(mmio, SMBHSTDAT0);

	return byte;
}
Example #16
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;
}
Example #17
0
static int smbus_block_read(u32 base, u8 dev, u8 *buffer,
			    int offset, int len)
{
	u8 buf_temp[32];
	int count;
	int i;

	debug("%s (%d): dev=0x%x offs=0x%x len=0x%x\n",
	      __func__, __LINE__, dev, offset, len);
	if (smbus_wait_until_ready(base) < 0)
		return -ETIMEDOUT;

	/* Setup transaction */

	/* Reset the data buffer index */
	inb(base + SMBHSTCTL);

	/* Set the device I'm talking too */
	outb(((dev & 0x7f) << 1) | 1, base + SMBXMITADD);
	/* Set the command/address... */
	outb(offset & 0xff, base + SMBHSTCMD);
	/* Set up for a block read */
	outb((inb(base + SMBHSTCTL) & (~(0x7) << 2)) | (0x5 << 2),
	     (base + SMBHSTCTL));
	/* Clear any lingering errors, so the transaction will run */
	outb(inb(base + SMBHSTSTAT), base + SMBHSTSTAT);

	/* Start the command */
	outb((inb(base + SMBHSTCTL) | SMBHSTCNT_START), base + SMBHSTCTL);

	/* Poll for transaction completion */
	if (smbus_wait_until_done(base) < 0) {
		printf("SMBUS read transaction timeout (dev=0x%x)\n", dev);
		return -ETIMEDOUT;
	}

	count = inb(base + SMBHSTDAT0);
	debug("%s (%d): count=%d (len=%d)\n", __func__, __LINE__, count, len);
	if (count == 0) {
		debug("ERROR: len=0 on read\n");
		return -EIO;
	}

	if (count < len) {
		debug("ERROR: too few bytes read\n");
		return -EIO;
	}

	if (count > 32) {
		debug("ERROR: count=%d too high\n", count);
		return -EIO;
	}

	/* Read all available bytes from buffer */
	for (i = 0; i < count; i++)
		buf_temp[i] = inb(base + SMBBLKDAT);

	memcpy(buffer, buf_temp, len);

	/* Return results of transaction */
	if (!(inb(base + SMBHSTSTAT) & SMBHSTSTS_INTR))
		return -EIO;

	return 0;
}