Commit e9d29f4f authored by Jiri Kosina's avatar Jiri Kosina

Merge branch 'for-6.8/mcp2221' into for-linus

- several assorted functional fixes for mcp2221 driver (Hamish Martin)
parents 4dc8c87a 26824686
...@@ -49,6 +49,7 @@ enum { ...@@ -49,6 +49,7 @@ enum {
MCP2221_I2C_MASK_ADDR_NACK = 0x40, MCP2221_I2C_MASK_ADDR_NACK = 0x40,
MCP2221_I2C_WRADDRL_SEND = 0x21, MCP2221_I2C_WRADDRL_SEND = 0x21,
MCP2221_I2C_ADDR_NACK = 0x25, MCP2221_I2C_ADDR_NACK = 0x25,
MCP2221_I2C_READ_PARTIAL = 0x54,
MCP2221_I2C_READ_COMPL = 0x55, MCP2221_I2C_READ_COMPL = 0x55,
MCP2221_ALT_F_NOT_GPIOV = 0xEE, MCP2221_ALT_F_NOT_GPIOV = 0xEE,
MCP2221_ALT_F_NOT_GPIOD = 0xEF, MCP2221_ALT_F_NOT_GPIOD = 0xEF,
...@@ -187,6 +188,25 @@ static int mcp_cancel_last_cmd(struct mcp2221 *mcp) ...@@ -187,6 +188,25 @@ static int mcp_cancel_last_cmd(struct mcp2221 *mcp)
return mcp_send_data_req_status(mcp, mcp->txbuf, 8); return mcp_send_data_req_status(mcp, mcp->txbuf, 8);
} }
/* Check if the last command succeeded or failed and return the result.
* If the command did fail, cancel that command which will free the i2c bus.
*/
static int mcp_chk_last_cmd_status_free_bus(struct mcp2221 *mcp)
{
int ret;
ret = mcp_chk_last_cmd_status(mcp);
if (ret) {
/* The last command was a failure.
* Send a cancel which will also free the bus.
*/
usleep_range(980, 1000);
mcp_cancel_last_cmd(mcp);
}
return ret;
}
static int mcp_set_i2c_speed(struct mcp2221 *mcp) static int mcp_set_i2c_speed(struct mcp2221 *mcp)
{ {
int ret; int ret;
...@@ -241,7 +261,7 @@ static int mcp_i2c_write(struct mcp2221 *mcp, ...@@ -241,7 +261,7 @@ static int mcp_i2c_write(struct mcp2221 *mcp,
usleep_range(980, 1000); usleep_range(980, 1000);
if (last_status) { if (last_status) {
ret = mcp_chk_last_cmd_status(mcp); ret = mcp_chk_last_cmd_status_free_bus(mcp);
if (ret) if (ret)
return ret; return ret;
} }
...@@ -278,6 +298,7 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp, ...@@ -278,6 +298,7 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp,
{ {
int ret; int ret;
u16 total_len; u16 total_len;
int retries = 0;
mcp->txbuf[0] = type; mcp->txbuf[0] = type;
if (msg) { if (msg) {
...@@ -301,19 +322,30 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp, ...@@ -301,19 +322,30 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp,
mcp->rxbuf_idx = 0; mcp->rxbuf_idx = 0;
do { do {
/* Wait for the data to be read by the device */
usleep_range(980, 1000);
memset(mcp->txbuf, 0, 4); memset(mcp->txbuf, 0, 4);
mcp->txbuf[0] = MCP2221_I2C_GET_DATA; mcp->txbuf[0] = MCP2221_I2C_GET_DATA;
ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1); ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1);
if (ret) if (ret) {
return ret; if (retries < 5) {
/* The data wasn't ready to read.
ret = mcp_chk_last_cmd_status(mcp); * Wait a bit longer and try again.
if (ret) */
usleep_range(90, 100);
retries++;
} else {
return ret; return ret;
}
} else {
retries = 0;
}
} while (mcp->rxbuf_idx < total_len);
usleep_range(980, 1000); usleep_range(980, 1000);
} while (mcp->rxbuf_idx < total_len); ret = mcp_chk_last_cmd_status_free_bus(mcp);
return ret; return ret;
} }
...@@ -328,11 +360,6 @@ static int mcp_i2c_xfer(struct i2c_adapter *adapter, ...@@ -328,11 +360,6 @@ static int mcp_i2c_xfer(struct i2c_adapter *adapter,
mutex_lock(&mcp->lock); mutex_lock(&mcp->lock);
/* Setting speed before every transaction is required for mcp2221 */
ret = mcp_set_i2c_speed(mcp);
if (ret)
goto exit;
if (num == 1) { if (num == 1) {
if (msgs->flags & I2C_M_RD) { if (msgs->flags & I2C_M_RD) {
ret = mcp_i2c_smbus_read(mcp, msgs, MCP2221_I2C_RD_DATA, ret = mcp_i2c_smbus_read(mcp, msgs, MCP2221_I2C_RD_DATA,
...@@ -417,9 +444,7 @@ static int mcp_smbus_write(struct mcp2221 *mcp, u16 addr, ...@@ -417,9 +444,7 @@ static int mcp_smbus_write(struct mcp2221 *mcp, u16 addr,
if (last_status) { if (last_status) {
usleep_range(980, 1000); usleep_range(980, 1000);
ret = mcp_chk_last_cmd_status(mcp); ret = mcp_chk_last_cmd_status_free_bus(mcp);
if (ret)
return ret;
} }
return ret; return ret;
...@@ -437,10 +462,6 @@ static int mcp_smbus_xfer(struct i2c_adapter *adapter, u16 addr, ...@@ -437,10 +462,6 @@ static int mcp_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
mutex_lock(&mcp->lock); mutex_lock(&mcp->lock);
ret = mcp_set_i2c_speed(mcp);
if (ret)
goto exit;
switch (size) { switch (size) {
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
...@@ -791,7 +812,8 @@ static int mcp2221_raw_event(struct hid_device *hdev, ...@@ -791,7 +812,8 @@ static int mcp2221_raw_event(struct hid_device *hdev,
mcp->status = -EIO; mcp->status = -EIO;
break; break;
} }
if (data[2] == MCP2221_I2C_READ_COMPL) { if (data[2] == MCP2221_I2C_READ_COMPL ||
data[2] == MCP2221_I2C_READ_PARTIAL) {
buf = mcp->rxbuf; buf = mcp->rxbuf;
memcpy(&buf[mcp->rxbuf_idx], &data[4], data[3]); memcpy(&buf[mcp->rxbuf_idx], &data[4], data[3]);
mcp->rxbuf_idx = mcp->rxbuf_idx + data[3]; mcp->rxbuf_idx = mcp->rxbuf_idx + data[3];
...@@ -1150,12 +1172,18 @@ static int mcp2221_probe(struct hid_device *hdev, ...@@ -1150,12 +1172,18 @@ static int mcp2221_probe(struct hid_device *hdev,
if (i2c_clk_freq < 50) if (i2c_clk_freq < 50)
i2c_clk_freq = 50; i2c_clk_freq = 50;
mcp->cur_i2c_clk_div = (12000000 / (i2c_clk_freq * 1000)) - 3; mcp->cur_i2c_clk_div = (12000000 / (i2c_clk_freq * 1000)) - 3;
ret = mcp_set_i2c_speed(mcp);
if (ret) {
hid_err(hdev, "can't set i2c speed: %d\n", ret);
return ret;
}
mcp->adapter.owner = THIS_MODULE; mcp->adapter.owner = THIS_MODULE;
mcp->adapter.class = I2C_CLASS_HWMON; mcp->adapter.class = I2C_CLASS_HWMON;
mcp->adapter.algo = &mcp_i2c_algo; mcp->adapter.algo = &mcp_i2c_algo;
mcp->adapter.retries = 1; mcp->adapter.retries = 1;
mcp->adapter.dev.parent = &hdev->dev; mcp->adapter.dev.parent = &hdev->dev;
ACPI_COMPANION_SET(&mcp->adapter.dev, ACPI_COMPANION(hdev->dev.parent));
snprintf(mcp->adapter.name, sizeof(mcp->adapter.name), snprintf(mcp->adapter.name, sizeof(mcp->adapter.name),
"MCP2221 usb-i2c bridge"); "MCP2221 usb-i2c bridge");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment