Added smbus block read/write for amd8111
Signed-off-by: Oskar Enoksson <enok@lysator.liu.se> Change-Id: I86c80a27fd13c9a2be4034fdfb63be4ab2fadbfc Reviewed-on: http://review.coreboot.org/281 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
parent
07b4215e11
commit
9bfa1c8c68
|
@ -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);
|
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
|
#if CONFIG_GENERATE_ACPI_TABLES == 1
|
||||||
unsigned pm_base;
|
unsigned pm_base;
|
||||||
#endif
|
#endif
|
||||||
|
@ -191,6 +214,8 @@ static struct smbus_bus_operations lops_smbus_bus = {
|
||||||
.send_byte = lsmbus_send_byte,
|
.send_byte = lsmbus_send_byte,
|
||||||
.read_byte = lsmbus_read_byte,
|
.read_byte = lsmbus_read_byte,
|
||||||
.write_byte = lsmbus_write_byte,
|
.write_byte = lsmbus_write_byte,
|
||||||
|
.block_read = lsmbus_block_read,
|
||||||
|
.block_write= lsmbus_block_write,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pci_operations lops_pci = {
|
static struct pci_operations lops_pci = {
|
||||||
|
|
|
@ -222,3 +222,106 @@ static int do_smbus_write_byte(unsigned smbus_io_base, unsigned device, unsigned
|
||||||
return 0;
|
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;
|
||||||
|
u8 msglen;
|
||||||
|
|
||||||
|
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 */
|
||||||
|
msglen = 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<msglen && i<bytes; i++) {
|
||||||
|
buf[i] = inw(smbus_io_base + SMBHSTFIFO) & 0xff;
|
||||||
|
}
|
||||||
|
/* empty fifo */
|
||||||
|
while(bytes++<msglen) {
|
||||||
|
inw(smbus_io_base + SMBHSTFIFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
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);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue