switch (datalen) { case 1:
outb(*(data), addr); break; case 2:
outw(*((u16 *)data), addr); break; case 3:
outw(*((u16 *)data), addr);
outb(*(data + 2), addr + 2); break; case 4:
outl(*((u32 *)data), addr); break; default:
mlxcpld_i2c_lpc_write_buf(data, datalen, addr); break;
}
}
/* * Check validity of received i2c messages parameters. * Returns 0 if OK, other - in case of invalid parameters.
*/ staticint mlxcpld_i2c_check_msg_params(struct mlxcpld_i2c_priv *priv, struct i2c_msg *msgs, int num)
{ int i;
if (!num) {
dev_err(priv->dev, "Incorrect 0 num of messages\n"); return -EINVAL;
}
for (i = 0; i < num; ++i) { if (unlikely(!msgs[i].buf)) {
dev_err(priv->dev, "Invalid buf in msg[%d]\n",
i); return -EINVAL;
} if (unlikely(msgs[0].addr != msgs[i].addr)) {
dev_err(priv->dev, "Invalid addr in msg[%d]\n",
i); return -EINVAL;
}
}
return 0;
}
/* * Check if transfer is completed and status of operation. * Returns 0 - transfer completed (both ACK or NACK), * negative - transfer isn't finished.
*/ staticint mlxcpld_i2c_check_status(struct mlxcpld_i2c_priv *priv, int *status)
{
u8 val;
if (val & MLXCPLD_LPCI2C_TRANS_END) { if (val & MLXCPLD_LPCI2C_STATUS_NACK) /* * The target is unable to accept the data. No such * target, command not understood, or unable to accept * any more data.
*/
*status = MLXCPLD_LPCI2C_NACK_IND; else
*status = MLXCPLD_LPCI2C_ACK_IND; return 0;
}
*status = MLXCPLD_LPCI2C_NO_IND;
/* * All upper layers currently are never use transfer with more than * 2 messages. Actually, it's also not so relevant in Mellanox systems * because of HW limitation. Max size of transfer is not more than 32 * or 68 bytes in the current x86 LPCI2C bridge.
*/
priv->xfer.cmd = msgs[num - 1].flags & I2C_M_RD;
staticint mlxcpld_i2c_wait_for_free(struct mlxcpld_i2c_priv *priv)
{ int timeout = 0;
do { if (!mlxcpld_i2c_check_busy(priv)) break;
usleep_range(priv->polling_time / 2, priv->polling_time);
timeout += priv->polling_time;
} while (timeout <= MLXCPLD_I2C_XFER_TO);
if (timeout > MLXCPLD_I2C_XFER_TO) return -ETIMEDOUT;
return 0;
}
/* * Wait for transfer to complete. * It puts current process to sleep until we get interrupt or timeout expires. * Returns the number of transferred or read bytes or error (<0).
*/ staticint mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv)
{ int status, i, timeout = 0;
u8 datalen, val;
do {
usleep_range(priv->polling_time / 2, priv->polling_time); if (!mlxcpld_i2c_check_status(priv, &status)) break;
timeout += priv->polling_time;
} while (status == 0 && timeout < MLXCPLD_I2C_XFER_TO);
switch (status) { case MLXCPLD_LPCI2C_NO_IND: return -ETIMEDOUT;
case MLXCPLD_LPCI2C_ACK_IND: if (priv->xfer.cmd != I2C_M_RD) return (priv->xfer.addr_width + priv->xfer.data_len);
if (priv->xfer.msg_num == 1)
i = 0; else
i = 1;
if (!priv->xfer.msg[i].buf) return -EINVAL;
/* * Actual read data len will be always the same as * requested len. 0xff (line pull-up) will be returned * if target has no data to return. Thus don't read * MLXCPLD_LPCI2C_NUM_DAT_REG reg from CPLD. Only in case of * SMBus block read transaction data len can be different, * check this case.
*/
mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_NUM_ADDR_REG, &val,
1); if (priv->smbus_block && (val & MLXCPLD_I2C_SMBUS_BLK_BIT)) {
mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_NUM_DAT_REG,
&datalen, 1); if (unlikely(datalen > I2C_SMBUS_BLOCK_MAX)) {
dev_err(priv->dev, "Incorrect smbus block read message len\n"); return -EPROTO;
}
} else {
datalen = priv->xfer.data_len;
}
for (i = 0; i < priv->xfer.msg_num; i++) { if ((priv->xfer.msg[i].flags & I2C_M_RD) != I2C_M_RD) { /* Don't write to CPLD buffer in read transaction */
mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_DATA_REG +
len, priv->xfer.msg[i].buf,
priv->xfer.msg[i].len);
len += priv->xfer.msg[i].len;
}
}
/* * Set target address with command for transfer. * It should be latest executed function before CPLD transaction.
*/
cmd = (priv->xfer.msg[0].addr << 1) | priv->xfer.cmd;
mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_CMD_REG, &cmd, 1);
}
/* * Generic lpc-i2c transfer. * Returns the number of processed messages or error (<0).
*/ staticint mlxcpld_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{ struct mlxcpld_i2c_priv *priv = i2c_get_adapdata(adap);
u8 comm_len = 0; int i, err;
for (i = 0; i < num; ++i)
comm_len += msgs[i].len;
/* Check bus state */ if (mlxcpld_i2c_wait_for_free(priv)) {
dev_err(priv->dev, "LPCI2C bridge is busy\n");
/* * Usually it means something serious has happened. * We can not have unfinished previous transfer * so it doesn't make any sense to try to stop it. * Probably we were not able to recover from the * previous error. * The only reasonable thing - is soft reset.
*/
mlxcpld_i2c_reset(priv); if (mlxcpld_i2c_check_busy(priv)) {
dev_err(priv->dev, "LPCI2C bridge is busy after reset\n"); return -EIO;
}
}
/* Read frequency setting. */
data = item->data;
err = regmap_read(pdata->regmap, data->reg, ®val); if (err) return err;
/* Set frequency only if it is not 100KHz, which is default. */ switch ((regval & data->mask) >> data->bit) { case MLXCPLD_I2C_FREQ_1000KHZ:
freq = MLXCPLD_I2C_FREQ_1000KHZ_SET;
priv->polling_time /= 4; break; case MLXCPLD_I2C_FREQ_400KHZ:
freq = MLXCPLD_I2C_FREQ_400KHZ_SET;
priv->polling_time /= 4; break; default: return 0;
}
/* Set I2C bus frequency if platform data provides this info. */
pdata = dev_get_platdata(&pdev->dev); if (pdata) {
err = mlxcpld_i2c_set_frequency(priv, pdata); if (err) goto mlxcpld_i2_probe_failed;
}
/* Register with i2c layer */
mlxcpld_i2c_adapter.timeout = usecs_to_jiffies(MLXCPLD_I2C_XFER_TO); /* Read capability register */
mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_CPBLTY_REG, &val, 1); /* Check support for extended transaction length */ if ((val & MLXCPLD_I2C_DATA_SZ_MASK) == MLXCPLD_I2C_DATA_SZ_BIT)
mlxcpld_i2c_adapter.quirks = &mlxcpld_i2c_quirks_ext; elseif ((val & MLXCPLD_I2C_DATA_SZ_MASK) == MLXCPLD_I2C_DATA_EXT2_SZ_BIT)
mlxcpld_i2c_adapter.quirks = &mlxcpld_i2c_quirks_ext2; /* Check support for smbus block transaction */ if (val & MLXCPLD_I2C_SMBUS_BLK_BIT)
priv->smbus_block = true; if (pdev->id >= -1)
mlxcpld_i2c_adapter.nr = pdev->id;
priv->adap = mlxcpld_i2c_adapter;
priv->adap.dev.parent = &pdev->dev;
i2c_set_adapdata(&priv->adap, priv);
err = i2c_add_numbered_adapter(&priv->adap); if (err) goto mlxcpld_i2_probe_failed;
/* Notify caller when adapter is added. */ if (pdata && pdata->completion_notify)
pdata->completion_notify(pdata->handle, mlxcpld_i2c_adapter.nr);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.