/** * \brief Read a byte from the SMBus. * * @param smbus_dev The base SMBus IO port * @param addr The address location of the DIMM on the SMBus. * @param offset The offset the data is located at. */ u8 smbus_read_byte(u32 smbus_dev, u8 addr, u8 offset) { u8 val; /* Initialize SMBus sequence */ smbus_reset(smbus_dev); /* Clear host data port. */ outb(0x00, SMBHSTDAT0(smbus_dev)); smbus_wait_until_ready(smbus_dev); /* Actual addr to reg format. */ addr = (addr << 1); addr |= 1; /* read command */ outb(addr, SMBXMITADD(smbus_dev)); outb(offset, SMBHSTCMD(smbus_dev)); /* Start transaction, byte data read. */ outb(0x48, SMBHSTCTL(smbus_dev)); smbus_wait_until_ready(smbus_dev); val = inb(SMBHSTDAT0(smbus_dev)); return val; }
/* Return negative errno on error. */ static s32 i801_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data) { int hwpec; int block = 0; int ret = 0, xact = 0; struct i801_priv *priv = i2c_get_adapdata(adap); mutex_lock(&priv->acpi_lock); if (priv->acpi_reserved) { mutex_unlock(&priv->acpi_lock); return -EBUSY; } hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA; switch (size) { case I2C_SMBUS_QUICK: outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv)); xact = I801_QUICK; break; case I2C_SMBUS_BYTE: outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv)); if (read_write == I2C_SMBUS_WRITE) outb_p(command, SMBHSTCMD(priv)); xact = I801_BYTE; break; case I2C_SMBUS_BYTE_DATA: outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv)); outb_p(command, SMBHSTCMD(priv)); if (read_write == I2C_SMBUS_WRITE) outb_p(data->byte, SMBHSTDAT0(priv)); xact = I801_BYTE_DATA; break; case I2C_SMBUS_WORD_DATA: outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv)); outb_p(command, SMBHSTCMD(priv)); if (read_write == I2C_SMBUS_WRITE) { outb_p(data->word & 0xff, SMBHSTDAT0(priv)); outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv)); } xact = I801_WORD_DATA; break; case I2C_SMBUS_BLOCK_DATA: outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv)); outb_p(command, SMBHSTCMD(priv)); block = 1; break; case I2C_SMBUS_I2C_BLOCK_DATA: /* NB: page 240 of ICH5 datasheet shows that the R/#W * bit should be cleared here, even when reading */ outb_p((addr & 0x7f) << 1, SMBHSTADD(priv)); if (read_write == I2C_SMBUS_READ) { /* NB: page 240 of ICH5 datasheet also shows * that DATA1 is the cmd field when reading */ outb_p(command, SMBHSTDAT1(priv)); } else outb_p(command, SMBHSTCMD(priv)); block = 1; break; default: dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n", size); ret = -EOPNOTSUPP; goto out; }