Loading drivers/hid/hid-mcp2221.c +50 −22 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ enum { MCP2221_I2C_MASK_ADDR_NACK = 0x40, MCP2221_I2C_WRADDRL_SEND = 0x21, MCP2221_I2C_ADDR_NACK = 0x25, MCP2221_I2C_READ_PARTIAL = 0x54, MCP2221_I2C_READ_COMPL = 0x55, MCP2221_ALT_F_NOT_GPIOV = 0xEE, MCP2221_ALT_F_NOT_GPIOD = 0xEF, Loading Loading @@ -187,6 +188,25 @@ static int mcp_cancel_last_cmd(struct mcp2221 *mcp) 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) { int ret; Loading Loading @@ -241,7 +261,7 @@ static int mcp_i2c_write(struct mcp2221 *mcp, usleep_range(980, 1000); if (last_status) { ret = mcp_chk_last_cmd_status(mcp); ret = mcp_chk_last_cmd_status_free_bus(mcp); if (ret) return ret; } Loading Loading @@ -278,6 +298,7 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp, { int ret; u16 total_len; int retries = 0; mcp->txbuf[0] = type; if (msg) { Loading @@ -301,19 +322,30 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp, mcp->rxbuf_idx = 0; do { /* Wait for the data to be read by the device */ usleep_range(980, 1000); memset(mcp->txbuf, 0, 4); mcp->txbuf[0] = MCP2221_I2C_GET_DATA; ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1); if (ret) return ret; ret = mcp_chk_last_cmd_status(mcp); if (ret) if (ret) { if (retries < 5) { /* The data wasn't ready to read. * Wait a bit longer and try again. */ usleep_range(90, 100); retries++; } else { return ret; } } else { retries = 0; } } while (mcp->rxbuf_idx < total_len); usleep_range(980, 1000); } while (mcp->rxbuf_idx < total_len); ret = mcp_chk_last_cmd_status_free_bus(mcp); return ret; } Loading @@ -328,11 +360,6 @@ static int mcp_i2c_xfer(struct i2c_adapter *adapter, 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 (msgs->flags & I2C_M_RD) { ret = mcp_i2c_smbus_read(mcp, msgs, MCP2221_I2C_RD_DATA, Loading Loading @@ -417,9 +444,7 @@ static int mcp_smbus_write(struct mcp2221 *mcp, u16 addr, if (last_status) { usleep_range(980, 1000); ret = mcp_chk_last_cmd_status(mcp); if (ret) return ret; ret = mcp_chk_last_cmd_status_free_bus(mcp); } return ret; Loading @@ -437,10 +462,6 @@ static int mcp_smbus_xfer(struct i2c_adapter *adapter, u16 addr, mutex_lock(&mcp->lock); ret = mcp_set_i2c_speed(mcp); if (ret) goto exit; switch (size) { case I2C_SMBUS_QUICK: Loading Loading @@ -791,7 +812,8 @@ static int mcp2221_raw_event(struct hid_device *hdev, mcp->status = -EIO; break; } if (data[2] == MCP2221_I2C_READ_COMPL) { if (data[2] == MCP2221_I2C_READ_COMPL || data[2] == MCP2221_I2C_READ_PARTIAL) { buf = mcp->rxbuf; memcpy(&buf[mcp->rxbuf_idx], &data[4], data[3]); mcp->rxbuf_idx = mcp->rxbuf_idx + data[3]; Loading Loading @@ -1150,12 +1172,18 @@ static int mcp2221_probe(struct hid_device *hdev, if (i2c_clk_freq < 50) i2c_clk_freq = 50; 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.class = I2C_CLASS_HWMON; mcp->adapter.algo = &mcp_i2c_algo; mcp->adapter.retries = 1; 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), "MCP2221 usb-i2c bridge"); Loading Loading
drivers/hid/hid-mcp2221.c +50 −22 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ enum { MCP2221_I2C_MASK_ADDR_NACK = 0x40, MCP2221_I2C_WRADDRL_SEND = 0x21, MCP2221_I2C_ADDR_NACK = 0x25, MCP2221_I2C_READ_PARTIAL = 0x54, MCP2221_I2C_READ_COMPL = 0x55, MCP2221_ALT_F_NOT_GPIOV = 0xEE, MCP2221_ALT_F_NOT_GPIOD = 0xEF, Loading Loading @@ -187,6 +188,25 @@ static int mcp_cancel_last_cmd(struct mcp2221 *mcp) 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) { int ret; Loading Loading @@ -241,7 +261,7 @@ static int mcp_i2c_write(struct mcp2221 *mcp, usleep_range(980, 1000); if (last_status) { ret = mcp_chk_last_cmd_status(mcp); ret = mcp_chk_last_cmd_status_free_bus(mcp); if (ret) return ret; } Loading Loading @@ -278,6 +298,7 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp, { int ret; u16 total_len; int retries = 0; mcp->txbuf[0] = type; if (msg) { Loading @@ -301,19 +322,30 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp, mcp->rxbuf_idx = 0; do { /* Wait for the data to be read by the device */ usleep_range(980, 1000); memset(mcp->txbuf, 0, 4); mcp->txbuf[0] = MCP2221_I2C_GET_DATA; ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1); if (ret) return ret; ret = mcp_chk_last_cmd_status(mcp); if (ret) if (ret) { if (retries < 5) { /* The data wasn't ready to read. * Wait a bit longer and try again. */ usleep_range(90, 100); retries++; } else { return ret; } } else { retries = 0; } } while (mcp->rxbuf_idx < total_len); usleep_range(980, 1000); } while (mcp->rxbuf_idx < total_len); ret = mcp_chk_last_cmd_status_free_bus(mcp); return ret; } Loading @@ -328,11 +360,6 @@ static int mcp_i2c_xfer(struct i2c_adapter *adapter, 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 (msgs->flags & I2C_M_RD) { ret = mcp_i2c_smbus_read(mcp, msgs, MCP2221_I2C_RD_DATA, Loading Loading @@ -417,9 +444,7 @@ static int mcp_smbus_write(struct mcp2221 *mcp, u16 addr, if (last_status) { usleep_range(980, 1000); ret = mcp_chk_last_cmd_status(mcp); if (ret) return ret; ret = mcp_chk_last_cmd_status_free_bus(mcp); } return ret; Loading @@ -437,10 +462,6 @@ static int mcp_smbus_xfer(struct i2c_adapter *adapter, u16 addr, mutex_lock(&mcp->lock); ret = mcp_set_i2c_speed(mcp); if (ret) goto exit; switch (size) { case I2C_SMBUS_QUICK: Loading Loading @@ -791,7 +812,8 @@ static int mcp2221_raw_event(struct hid_device *hdev, mcp->status = -EIO; break; } if (data[2] == MCP2221_I2C_READ_COMPL) { if (data[2] == MCP2221_I2C_READ_COMPL || data[2] == MCP2221_I2C_READ_PARTIAL) { buf = mcp->rxbuf; memcpy(&buf[mcp->rxbuf_idx], &data[4], data[3]); mcp->rxbuf_idx = mcp->rxbuf_idx + data[3]; Loading Loading @@ -1150,12 +1172,18 @@ static int mcp2221_probe(struct hid_device *hdev, if (i2c_clk_freq < 50) i2c_clk_freq = 50; 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.class = I2C_CLASS_HWMON; mcp->adapter.algo = &mcp_i2c_algo; mcp->adapter.retries = 1; 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), "MCP2221 usb-i2c bridge"); Loading