Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
/**
 * 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 {