static int ismt_submit(struct ismt_softc *sc, struct ismt_desc *desc, uint8_t slave, uint8_t is_read) { uint32_t err, fmhp, val; desc->control |= ISMT_DESC_FAIR; if (sc->using_msi) desc->control |= ISMT_DESC_INT; desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(slave, is_read); desc->dptr_low = (sc->dma_buffer_bus_addr & 0xFFFFFFFFLL); desc->dptr_high = (sc->dma_buffer_bus_addr >> 32); wmb(); fmhp = sc->head << 16; val = bus_read_4(sc->mmio_res, ISMT_MSTR_MCTRL); val &= ~ISMT_MCTRL_FMHP; val |= fmhp; bus_write_4(sc->mmio_res, ISMT_MSTR_MCTRL, val); /* set the start bit */ val = bus_read_4(sc->mmio_res, ISMT_MSTR_MCTRL); val |= ISMT_MCTRL_SS; bus_write_4(sc->mmio_res, ISMT_MSTR_MCTRL, val); err = tsleep(sc, PWAIT, "ismt_wait", 5 * hz); if (err != 0) { ISMT_DEBUG(sc->pcidev, "%s timeout\n", __func__); return (SMB_ETIMEOUT); } ISMT_DEBUG(sc->pcidev, "%s status=0x%x\n", __func__, desc->status); if (desc->status & ISMT_DESC_SCS) return (SMB_ENOERR); if (desc->status & ISMT_DESC_NAK) return (SMB_ENOACK); if (desc->status & ISMT_DESC_CRC) return (SMB_EBUSERR); if (desc->status & ISMT_DESC_COL) return (SMB_ECOLLI); if (desc->status & ISMT_DESC_LPR) return (SMB_EINVAL); if (desc->status & (ISMT_DESC_DLTO | ISMT_DESC_CLTO)) return (SMB_ETIMEOUT); return (SMB_EBUSERR); }
/** * ismt_access() - process an SMBus command * @adap: the i2c host adapter * @addr: address of the i2c/SMBus target * @flags: command options * @read_write: read from or write to device * @command: the i2c/SMBus command to issue * @size: SMBus transaction type * @data: read/write data buffer */ static int ismt_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data) { int ret; dma_addr_t dma_addr = 0; /* address of the data buffer */ u8 dma_size = 0; enum dma_data_direction dma_direction = 0; struct ismt_desc *desc; struct ismt_priv *priv = i2c_get_adapdata(adap); struct device *dev = &priv->pci_dev->dev; desc = &priv->hw[priv->head]; /* Initialize the DMA buffer */ memset(priv->dma_buffer, 0, sizeof(priv->dma_buffer)); /* Initialize the descriptor */ memset(desc, 0, sizeof(struct ismt_desc)); desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, read_write); /* Initialize common control bits */ if (likely(priv->using_msi)) desc->control = ISMT_DESC_INT | ISMT_DESC_FAIR; else desc->control = ISMT_DESC_FAIR; if ((flags & I2C_CLIENT_PEC) && (size != I2C_SMBUS_QUICK) && (size != I2C_SMBUS_I2C_BLOCK_DATA)) desc->control |= ISMT_DESC_PEC; switch (size) { case I2C_SMBUS_QUICK: dev_dbg(dev, "I2C_SMBUS_QUICK\n"); break; case I2C_SMBUS_BYTE: if (read_write == I2C_SMBUS_WRITE) { /* * Send Byte * The command field contains the write data */ dev_dbg(dev, "I2C_SMBUS_BYTE: WRITE\n"); desc->control |= ISMT_DESC_CWRL; desc->wr_len_cmd = command; } else { /* Receive Byte */ dev_dbg(dev, "I2C_SMBUS_BYTE: READ\n"); dma_size = 1; dma_direction = DMA_FROM_DEVICE; desc->rd_len = 1; } break; case I2C_SMBUS_BYTE_DATA: if (read_write == I2C_SMBUS_WRITE) { /* * Write Byte * Command plus 1 data byte */ dev_dbg(dev, "I2C_SMBUS_BYTE_DATA: WRITE\n"); desc->wr_len_cmd = 2; dma_size = 2; dma_direction = DMA_TO_DEVICE; priv->dma_buffer[0] = command; priv->dma_buffer[1] = data->byte; } else { /* Read Byte */ dev_dbg(dev, "I2C_SMBUS_BYTE_DATA: READ\n"); desc->control |= ISMT_DESC_CWRL; desc->wr_len_cmd = command; desc->rd_len = 1; dma_size = 1; dma_direction = DMA_FROM_DEVICE; } break; case I2C_SMBUS_WORD_DATA: if (read_write == I2C_SMBUS_WRITE) { /* Write Word */ dev_dbg(dev, "I2C_SMBUS_WORD_DATA: WRITE\n"); desc->wr_len_cmd = 3; dma_size = 3; dma_direction = DMA_TO_DEVICE; priv->dma_buffer[0] = command; priv->dma_buffer[1] = data->word & 0xff; priv->dma_buffer[2] = data->word >> 8; } else {