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
.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 = {
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;
+}
+
+