1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-18 10:35:55 +00:00

Allow multi-byte reads in the private CHELSIO_T4_GET_I2C ioctl. The

firmware allows up to 48B to be read this way but the driver limits
itself to 8B at a time to remain compatible with old cxgbetool
binaries.

MFC after:	1 week
This commit is contained in:
Navdeep Parhar 2014-07-15 01:03:29 +00:00
parent ad15140ee7
commit 44eb893659
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=268640
3 changed files with 92 additions and 37 deletions

View File

@ -585,12 +585,18 @@ int t4_enable_vi_ns(struct adapter *adap, unsigned int mbox, unsigned int viid,
bool rx_en, bool tx_en);
int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid,
unsigned int nblinks);
int t4_i2c_rd(struct adapter *adap, unsigned int mbox, unsigned int port_id,
u8 dev_addr, u8 offset, u8 *valp);
int t4_mdio_rd(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
unsigned int mmd, unsigned int reg, unsigned int *valp);
int t4_mdio_wr(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
unsigned int mmd, unsigned int reg, unsigned int val);
int t4_i2c_rd(struct adapter *adap, unsigned int mbox,
int port, unsigned int devid,
unsigned int offset, unsigned int len,
u8 *buf);
int t4_i2c_wr(struct adapter *adap, unsigned int mbox,
int port, unsigned int devid,
unsigned int offset, unsigned int len,
u8 *buf);
int t4_iq_start_stop(struct adapter *adap, unsigned int mbox, bool start,
unsigned int pf, unsigned int vf, unsigned int iqid,
unsigned int fl0id, unsigned int fl1id);

View File

@ -4147,36 +4147,6 @@ int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox, u32 addr, u32
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
/**
* t4_i2c_rd - read a byte from an i2c addressable device
* @adap: the adapter
* @mbox: mailbox to use for the FW command
* @port_id: the port id
* @dev_addr: the i2c device address
* @offset: the byte offset to read from
* @valp: where to store the value
*/
int t4_i2c_rd(struct adapter *adap, unsigned int mbox, unsigned int port_id,
u8 dev_addr, u8 offset, u8 *valp)
{
int ret;
struct fw_ldst_cmd c;
memset(&c, 0, sizeof(c));
c.op_to_addrspace = htonl(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST |
F_FW_CMD_READ |
V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FUNC_I2C));
c.cycles_to_len16 = htonl(FW_LEN16(c));
c.u.i2c_deprecated.pid_pkd = V_FW_LDST_CMD_PID(port_id);
c.u.i2c_deprecated.base = dev_addr;
c.u.i2c_deprecated.boffset = offset;
ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
if (ret == 0)
*valp = c.u.i2c_deprecated.data;
return ret;
}
/**
* t4_mdio_rd - read a PHY register through MDIO
* @adap: the adapter
@ -4236,6 +4206,87 @@ int t4_mdio_wr(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
/**
* t4_i2c_rd - read I2C data from adapter
* @adap: the adapter
* @port: Port number if per-port device; <0 if not
* @devid: per-port device ID or absolute device ID
* @offset: byte offset into device I2C space
* @len: byte length of I2C space data
* @buf: buffer in which to return I2C data
*
* Reads the I2C data from the indicated device and location.
*/
int t4_i2c_rd(struct adapter *adap, unsigned int mbox,
int port, unsigned int devid,
unsigned int offset, unsigned int len,
u8 *buf)
{
struct fw_ldst_cmd ldst;
int ret;
if (port >= 4 ||
devid >= 256 ||
offset >= 256 ||
len > sizeof ldst.u.i2c.data)
return -EINVAL;
memset(&ldst, 0, sizeof ldst);
ldst.op_to_addrspace =
cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
F_FW_CMD_REQUEST |
F_FW_CMD_READ |
V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_I2C));
ldst.cycles_to_len16 = cpu_to_be32(FW_LEN16(ldst));
ldst.u.i2c.pid = (port < 0 ? 0xff : port);
ldst.u.i2c.did = devid;
ldst.u.i2c.boffset = offset;
ldst.u.i2c.blen = len;
ret = t4_wr_mbox(adap, mbox, &ldst, sizeof ldst, &ldst);
if (!ret)
memcpy(buf, ldst.u.i2c.data, len);
return ret;
}
/**
* t4_i2c_wr - write I2C data to adapter
* @adap: the adapter
* @port: Port number if per-port device; <0 if not
* @devid: per-port device ID or absolute device ID
* @offset: byte offset into device I2C space
* @len: byte length of I2C space data
* @buf: buffer containing new I2C data
*
* Write the I2C data to the indicated device and location.
*/
int t4_i2c_wr(struct adapter *adap, unsigned int mbox,
int port, unsigned int devid,
unsigned int offset, unsigned int len,
u8 *buf)
{
struct fw_ldst_cmd ldst;
if (port >= 4 ||
devid >= 256 ||
offset >= 256 ||
len > sizeof ldst.u.i2c.data)
return -EINVAL;
memset(&ldst, 0, sizeof ldst);
ldst.op_to_addrspace =
cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
F_FW_CMD_REQUEST |
F_FW_CMD_WRITE |
V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_I2C));
ldst.cycles_to_len16 = cpu_to_be32(FW_LEN16(ldst));
ldst.u.i2c.pid = (port < 0 ? 0xff : port);
ldst.u.i2c.did = devid;
ldst.u.i2c.boffset = offset;
ldst.u.i2c.blen = len;
memcpy(ldst.u.i2c.data, buf, len);
return t4_wr_mbox(adap, mbox, &ldst, sizeof ldst, &ldst);
}
/**
* t4_sge_ctxt_flush - flush the SGE context cache
* @adap: the adapter

View File

@ -7535,16 +7535,14 @@ read_i2c(struct adapter *sc, struct t4_i2c_data *i2cd)
if (i2cd->len == 0 || i2cd->port_id >= sc->params.nports)
return (EINVAL);
if (i2cd->len > 1) {
/* XXX: need fw support for longer reads in one go */
return (ENOTSUP);
}
if (i2cd->len > sizeof(i2cd->data))
return (EFBIG);
rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4i2crd");
if (rc)
return (rc);
rc = -t4_i2c_rd(sc, sc->mbox, i2cd->port_id, i2cd->dev_addr,
i2cd->offset, &i2cd->data[0]);
i2cd->offset, i2cd->len, &i2cd->data[0]);
end_synchronized_op(sc, 0);
return (rc);