Skip to content

Commit e9d29f4

Browse files
author
Jiri Kosina
committed
Merge branch 'for-6.8/mcp2221' into for-linus
- several assorted functional fixes for mcp2221 driver (Hamish Martin)
2 parents 4dc8c87 + 2682468 commit e9d29f4

File tree

1 file changed

+50
-22
lines changed

1 file changed

+50
-22
lines changed

drivers/hid/hid-mcp2221.c

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ enum {
4949
MCP2221_I2C_MASK_ADDR_NACK = 0x40,
5050
MCP2221_I2C_WRADDRL_SEND = 0x21,
5151
MCP2221_I2C_ADDR_NACK = 0x25,
52+
MCP2221_I2C_READ_PARTIAL = 0x54,
5253
MCP2221_I2C_READ_COMPL = 0x55,
5354
MCP2221_ALT_F_NOT_GPIOV = 0xEE,
5455
MCP2221_ALT_F_NOT_GPIOD = 0xEF,
@@ -187,6 +188,25 @@ static int mcp_cancel_last_cmd(struct mcp2221 *mcp)
187188
return mcp_send_data_req_status(mcp, mcp->txbuf, 8);
188189
}
189190

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

243263
if (last_status) {
244-
ret = mcp_chk_last_cmd_status(mcp);
264+
ret = mcp_chk_last_cmd_status_free_bus(mcp);
245265
if (ret)
246266
return ret;
247267
}
@@ -278,6 +298,7 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp,
278298
{
279299
int ret;
280300
u16 total_len;
301+
int retries = 0;
281302

282303
mcp->txbuf[0] = type;
283304
if (msg) {
@@ -301,20 +322,31 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp,
301322
mcp->rxbuf_idx = 0;
302323

303324
do {
325+
/* Wait for the data to be read by the device */
326+
usleep_range(980, 1000);
327+
304328
memset(mcp->txbuf, 0, 4);
305329
mcp->txbuf[0] = MCP2221_I2C_GET_DATA;
306330

307331
ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1);
308-
if (ret)
309-
return ret;
310-
311-
ret = mcp_chk_last_cmd_status(mcp);
312-
if (ret)
313-
return ret;
314-
315-
usleep_range(980, 1000);
332+
if (ret) {
333+
if (retries < 5) {
334+
/* The data wasn't ready to read.
335+
* Wait a bit longer and try again.
336+
*/
337+
usleep_range(90, 100);
338+
retries++;
339+
} else {
340+
return ret;
341+
}
342+
} else {
343+
retries = 0;
344+
}
316345
} while (mcp->rxbuf_idx < total_len);
317346

347+
usleep_range(980, 1000);
348+
ret = mcp_chk_last_cmd_status_free_bus(mcp);
349+
318350
return ret;
319351
}
320352

@@ -328,11 +360,6 @@ static int mcp_i2c_xfer(struct i2c_adapter *adapter,
328360

329361
mutex_lock(&mcp->lock);
330362

331-
/* Setting speed before every transaction is required for mcp2221 */
332-
ret = mcp_set_i2c_speed(mcp);
333-
if (ret)
334-
goto exit;
335-
336363
if (num == 1) {
337364
if (msgs->flags & I2C_M_RD) {
338365
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,
417444
if (last_status) {
418445
usleep_range(980, 1000);
419446

420-
ret = mcp_chk_last_cmd_status(mcp);
421-
if (ret)
422-
return ret;
447+
ret = mcp_chk_last_cmd_status_free_bus(mcp);
423448
}
424449

425450
return ret;
@@ -437,10 +462,6 @@ static int mcp_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
437462

438463
mutex_lock(&mcp->lock);
439464

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

446467
case I2C_SMBUS_QUICK:
@@ -791,7 +812,8 @@ static int mcp2221_raw_event(struct hid_device *hdev,
791812
mcp->status = -EIO;
792813
break;
793814
}
794-
if (data[2] == MCP2221_I2C_READ_COMPL) {
815+
if (data[2] == MCP2221_I2C_READ_COMPL ||
816+
data[2] == MCP2221_I2C_READ_PARTIAL) {
795817
buf = mcp->rxbuf;
796818
memcpy(&buf[mcp->rxbuf_idx], &data[4], data[3]);
797819
mcp->rxbuf_idx = mcp->rxbuf_idx + data[3];
@@ -1150,12 +1172,18 @@ static int mcp2221_probe(struct hid_device *hdev,
11501172
if (i2c_clk_freq < 50)
11511173
i2c_clk_freq = 50;
11521174
mcp->cur_i2c_clk_div = (12000000 / (i2c_clk_freq * 1000)) - 3;
1175+
ret = mcp_set_i2c_speed(mcp);
1176+
if (ret) {
1177+
hid_err(hdev, "can't set i2c speed: %d\n", ret);
1178+
return ret;
1179+
}
11531180

11541181
mcp->adapter.owner = THIS_MODULE;
11551182
mcp->adapter.class = I2C_CLASS_HWMON;
11561183
mcp->adapter.algo = &mcp_i2c_algo;
11571184
mcp->adapter.retries = 1;
11581185
mcp->adapter.dev.parent = &hdev->dev;
1186+
ACPI_COMPANION_SET(&mcp->adapter.dev, ACPI_COMPANION(hdev->dev.parent));
11591187
snprintf(mcp->adapter.name, sizeof(mcp->adapter.name),
11601188
"MCP2221 usb-i2c bridge");
11611189

0 commit comments

Comments
 (0)