static int do_smbus_block_write(unsigned smbus_base, unsigned device, unsigned cmd, unsigned bytes, const u8 *buf) { u8 status; 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(cmd & 0xff, smbus_base + SMBHSTCMD); /* Set up for a block data write */ outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x5 << 2), (smbus_base + SMBHSTCTL)); /* Clear any lingering errors, so the transaction will run */ outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT); /* set number of bytes to transfer */ outb(bytes, smbus_base + SMBHSTDAT0); outb(*buf++, smbus_base + SMBBLKDAT); bytes--; /* Start the command */ outb((inb(smbus_base + SMBHSTCTL) | 0x40), smbus_base + SMBHSTCTL); while(!(inb(smbus_base + SMBHSTSTAT) & 1)); /* Poll for transaction completion */ do { status = inb(smbus_base + SMBHSTSTAT); if (status & ((1 << 4) | /* FAILED */ (1 << 3) | /* BUS ERR */ (1 << 2))) /* DEV ERR */ return SMBUS_ERROR; if (status & 0x80) { /* Byte done */ outb(*buf++, smbus_base + SMBBLKDAT); outb(status, smbus_base + SMBHSTSTAT); } } while(status & 0x01); return 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; }
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; }
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; }
/** \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; }
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; }
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 }
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; }
int do_smbus_send_byte(u32 mmio, u8 device, u8 val) { u8 byte; if (smbus_wait_until_ready(mmio) < 0) return -2; /* not ready */ /* set the command... */ smbus_write8(mmio, SMBHSTDAT0, val); /* set the device I'm talking to */ smbus_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 0); 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 */ return 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; }