Skip to content

Commit 02a4675

Browse files
Hamish MartinJiri Kosina
authored andcommitted
HID: mcp2221: Don't set bus speed on every transfer
Since the initial commit of this driver the I2C bus speed has been reconfigured for every single transfer. This is despite the fact that we never change the speed and it is never "lost" by the chip. Upon investigation we find that what was really happening was that the setting of the bus speed had the side effect of cancelling a previous failed command if there was one, thereby freeing the bus. This is the part that was actually required to keep the bus operational in the face of failed commands. Instead of always setting the speed, we now correctly cancel any failed commands as they are detected. This means we can just set the bus speed at probe time and remove the previous speed sets on each transfer. This has the effect of improving performance and reducing the number of commands required to complete transfers. Signed-off-by: Hamish Martin <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent d978615 commit 02a4675

File tree

1 file changed

+27
-14
lines changed

1 file changed

+27
-14
lines changed

drivers/hid/hid-mcp2221.c

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,25 @@ static int mcp_cancel_last_cmd(struct mcp2221 *mcp)
187187
return mcp_send_data_req_status(mcp, mcp->txbuf, 8);
188188
}
189189

190+
/* Check if the last command succeeded or failed and return the result.
191+
* If the command did fail, cancel that command which will free the i2c bus.
192+
*/
193+
static int mcp_chk_last_cmd_status_free_bus(struct mcp2221 *mcp)
194+
{
195+
int ret;
196+
197+
ret = mcp_chk_last_cmd_status(mcp);
198+
if (ret) {
199+
/* The last command was a failure.
200+
* Send a cancel which will also free the bus.
201+
*/
202+
usleep_range(980, 1000);
203+
mcp_cancel_last_cmd(mcp);
204+
}
205+
206+
return ret;
207+
}
208+
190209
static int mcp_set_i2c_speed(struct mcp2221 *mcp)
191210
{
192211
int ret;
@@ -241,7 +260,7 @@ static int mcp_i2c_write(struct mcp2221 *mcp,
241260
usleep_range(980, 1000);
242261

243262
if (last_status) {
244-
ret = mcp_chk_last_cmd_status(mcp);
263+
ret = mcp_chk_last_cmd_status_free_bus(mcp);
245264
if (ret)
246265
return ret;
247266
}
@@ -308,7 +327,7 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp,
308327
if (ret)
309328
return ret;
310329

311-
ret = mcp_chk_last_cmd_status(mcp);
330+
ret = mcp_chk_last_cmd_status_free_bus(mcp);
312331
if (ret)
313332
return ret;
314333

@@ -328,11 +347,6 @@ static int mcp_i2c_xfer(struct i2c_adapter *adapter,
328347

329348
mutex_lock(&mcp->lock);
330349

331-
/* Setting speed before every transaction is required for mcp2221 */
332-
ret = mcp_set_i2c_speed(mcp);
333-
if (ret)
334-
goto exit;
335-
336350
if (num == 1) {
337351
if (msgs->flags & I2C_M_RD) {
338352
ret = mcp_i2c_smbus_read(mcp, msgs, MCP2221_I2C_RD_DATA,
@@ -417,9 +431,7 @@ static int mcp_smbus_write(struct mcp2221 *mcp, u16 addr,
417431
if (last_status) {
418432
usleep_range(980, 1000);
419433

420-
ret = mcp_chk_last_cmd_status(mcp);
421-
if (ret)
422-
return ret;
434+
ret = mcp_chk_last_cmd_status_free_bus(mcp);
423435
}
424436

425437
return ret;
@@ -437,10 +449,6 @@ static int mcp_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
437449

438450
mutex_lock(&mcp->lock);
439451

440-
ret = mcp_set_i2c_speed(mcp);
441-
if (ret)
442-
goto exit;
443-
444452
switch (size) {
445453

446454
case I2C_SMBUS_QUICK:
@@ -1148,6 +1156,11 @@ static int mcp2221_probe(struct hid_device *hdev,
11481156
if (i2c_clk_freq < 50)
11491157
i2c_clk_freq = 50;
11501158
mcp->cur_i2c_clk_div = (12000000 / (i2c_clk_freq * 1000)) - 3;
1159+
ret = mcp_set_i2c_speed(mcp);
1160+
if (ret) {
1161+
hid_err(hdev, "can't set i2c speed: %d\n", ret);
1162+
return ret;
1163+
}
11511164

11521165
mcp->adapter.owner = THIS_MODULE;
11531166
mcp->adapter.class = I2C_CLASS_HWMON;

0 commit comments

Comments
 (0)