• Home
  • Raw
  • Download

Lines Matching +full:multi +full:- +full:word

1 // SPDX-License-Identifier: GPL-2.0-only
3 * MCP2221A - Microchip USB to I2C Host Protocol Bridge
19 #include "hid-ids.h"
104 * want to set some other frequency (min 50 kHz - max 400 kHz).
117 return -ENOMEM; in mcp_send_report()
120 ret = hid_hw_output_report(mcp->hdev, buf, len); in mcp_send_report()
139 reinit_completion(&mcp->wait_in_report); in mcp_send_data_req_status()
145 t = wait_for_completion_timeout(&mcp->wait_in_report, in mcp_send_data_req_status()
148 return -ETIMEDOUT; in mcp_send_data_req_status()
150 return mcp->status; in mcp_send_data_req_status()
156 memset(mcp->txbuf, 0, 8); in mcp_chk_last_cmd_status()
157 mcp->txbuf[0] = MCP2221_I2C_PARAM_OR_STATUS; in mcp_chk_last_cmd_status()
159 return mcp_send_data_req_status(mcp, mcp->txbuf, 8); in mcp_chk_last_cmd_status()
165 memset(mcp->txbuf, 0, 8); in mcp_cancel_last_cmd()
166 mcp->txbuf[0] = MCP2221_I2C_PARAM_OR_STATUS; in mcp_cancel_last_cmd()
167 mcp->txbuf[2] = MCP2221_I2C_CANCEL; in mcp_cancel_last_cmd()
169 return mcp_send_data_req_status(mcp, mcp->txbuf, 8); in mcp_cancel_last_cmd()
176 memset(mcp->txbuf, 0, 8); in mcp_set_i2c_speed()
177 mcp->txbuf[0] = MCP2221_I2C_PARAM_OR_STATUS; in mcp_set_i2c_speed()
178 mcp->txbuf[3] = MCP2221_I2C_SET_SPEED; in mcp_set_i2c_speed()
179 mcp->txbuf[4] = mcp->cur_i2c_clk_div; in mcp_set_i2c_speed()
181 ret = mcp_send_data_req_status(mcp, mcp->txbuf, 8); in mcp_set_i2c_speed()
206 if (msg->len < 60) in mcp_i2c_write()
207 len = msg->len; in mcp_i2c_write()
212 mcp->txbuf[0] = type; in mcp_i2c_write()
213 mcp->txbuf[1] = msg->len & 0xff; in mcp_i2c_write()
214 mcp->txbuf[2] = msg->len >> 8; in mcp_i2c_write()
215 mcp->txbuf[3] = (u8)(msg->addr << 1); in mcp_i2c_write()
217 memcpy(&mcp->txbuf[4], &msg->buf[idx], len); in mcp_i2c_write()
219 ret = mcp_send_data_req_status(mcp, mcp->txbuf, len + 4); in mcp_i2c_write()
232 if (sent >= msg->len) in mcp_i2c_write()
236 if ((msg->len - sent) < 60) in mcp_i2c_write()
237 len = msg->len - sent; in mcp_i2c_write()
243 * otherwise next write fails on first-try from i2c core. in mcp_i2c_write()
253 * Device reads all data (0 - 65535 bytes) from i2c slave device and
264 mcp->txbuf[0] = type; in mcp_i2c_smbus_read()
266 mcp->txbuf[1] = msg->len & 0xff; in mcp_i2c_smbus_read()
267 mcp->txbuf[2] = msg->len >> 8; in mcp_i2c_smbus_read()
268 mcp->txbuf[3] = (u8)(msg->addr << 1); in mcp_i2c_smbus_read()
269 total_len = msg->len; in mcp_i2c_smbus_read()
270 mcp->rxbuf = msg->buf; in mcp_i2c_smbus_read()
272 mcp->txbuf[1] = smbus_len; in mcp_i2c_smbus_read()
273 mcp->txbuf[2] = 0; in mcp_i2c_smbus_read()
274 mcp->txbuf[3] = (u8)(smbus_addr << 1); in mcp_i2c_smbus_read()
276 mcp->rxbuf = smbus_buf; in mcp_i2c_smbus_read()
279 ret = mcp_send_data_req_status(mcp, mcp->txbuf, 4); in mcp_i2c_smbus_read()
283 mcp->rxbuf_idx = 0; in mcp_i2c_smbus_read()
286 memset(mcp->txbuf, 0, 4); in mcp_i2c_smbus_read()
287 mcp->txbuf[0] = MCP2221_I2C_GET_DATA; in mcp_i2c_smbus_read()
289 ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1); in mcp_i2c_smbus_read()
298 } while (mcp->rxbuf_idx < total_len); in mcp_i2c_smbus_read()
309 hid_hw_power(mcp->hdev, PM_HINT_FULLON); in mcp_i2c_xfer()
311 mutex_lock(&mcp->lock); in mcp_i2c_xfer()
319 if (msgs->flags & I2C_M_RD) { in mcp_i2c_xfer()
346 dev_err(&adapter->dev, in mcp_i2c_xfer()
347 "unsupported multi-msg i2c transaction\n"); in mcp_i2c_xfer()
348 ret = -EOPNOTSUPP; in mcp_i2c_xfer()
351 dev_err(&adapter->dev, in mcp_i2c_xfer()
352 "unsupported multi-msg i2c transaction\n"); in mcp_i2c_xfer()
353 ret = -EOPNOTSUPP; in mcp_i2c_xfer()
357 hid_hw_power(mcp->hdev, PM_HINT_NORMAL); in mcp_i2c_xfer()
358 mutex_unlock(&mcp->lock); in mcp_i2c_xfer()
368 mcp->txbuf[0] = type; in mcp_smbus_write()
369 mcp->txbuf[1] = len + 1; /* 1 is due to command byte itself */ in mcp_smbus_write()
370 mcp->txbuf[2] = 0; in mcp_smbus_write()
371 mcp->txbuf[3] = (u8)(addr << 1); in mcp_smbus_write()
372 mcp->txbuf[4] = command; in mcp_smbus_write()
379 mcp->txbuf[5] = buf[0]; in mcp_smbus_write()
383 mcp->txbuf[5] = buf[0]; in mcp_smbus_write()
384 mcp->txbuf[6] = buf[1]; in mcp_smbus_write()
388 memcpy(&mcp->txbuf[5], buf, len); in mcp_smbus_write()
392 ret = mcp_send_data_req_status(mcp, mcp->txbuf, data_len); in mcp_smbus_write()
415 hid_hw_power(mcp->hdev, PM_HINT_FULLON); in mcp_smbus_xfer()
417 mutex_lock(&mcp->lock); in mcp_smbus_xfer()
428 addr, 0, &data->byte); in mcp_smbus_xfer()
436 addr, 1, &data->byte); in mcp_smbus_xfer()
450 addr, 1, &data->byte); in mcp_smbus_xfer()
452 ret = mcp_smbus_write(mcp, addr, command, &data->byte, in mcp_smbus_xfer()
465 addr, 2, (u8 *)&data->word); in mcp_smbus_xfer()
468 (u8 *)&data->word, 2, in mcp_smbus_xfer()
479 mcp->rxbuf_idx = 0; in mcp_smbus_xfer()
480 mcp->rxbuf = data->block; in mcp_smbus_xfer()
481 mcp->txbuf[0] = MCP2221_I2C_GET_DATA; in mcp_smbus_xfer()
482 ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1); in mcp_smbus_xfer()
486 if (!data->block[0]) { in mcp_smbus_xfer()
487 ret = -EINVAL; in mcp_smbus_xfer()
490 ret = mcp_smbus_write(mcp, addr, command, data->block, in mcp_smbus_xfer()
491 data->block[0] + 1, in mcp_smbus_xfer()
502 mcp->rxbuf_idx = 0; in mcp_smbus_xfer()
503 mcp->rxbuf = data->block; in mcp_smbus_xfer()
504 mcp->txbuf[0] = MCP2221_I2C_GET_DATA; in mcp_smbus_xfer()
505 ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1); in mcp_smbus_xfer()
509 if (!data->block[0]) { in mcp_smbus_xfer()
510 ret = -EINVAL; in mcp_smbus_xfer()
514 &data->block[1], data->block[0], in mcp_smbus_xfer()
520 (u8 *)&data->word, in mcp_smbus_xfer()
527 addr, 2, (u8 *)&data->word); in mcp_smbus_xfer()
530 ret = mcp_smbus_write(mcp, addr, command, data->block, in mcp_smbus_xfer()
531 data->block[0] + 1, in mcp_smbus_xfer()
539 data->block); in mcp_smbus_xfer()
542 dev_err(&mcp->adapter.dev, in mcp_smbus_xfer()
544 ret = -EOPNOTSUPP; in mcp_smbus_xfer()
548 hid_hw_power(mcp->hdev, PM_HINT_NORMAL); in mcp_smbus_xfer()
549 mutex_unlock(&mcp->lock); in mcp_smbus_xfer()
573 mcp->txbuf[0] = MCP2221_GPIO_GET; in mcp_gpio_get()
575 mcp->gp_idx = offsetof(struct mcp_get_gpio, gpio[offset].value); in mcp_gpio_get()
577 mutex_lock(&mcp->lock); in mcp_gpio_get()
578 ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1); in mcp_gpio_get()
579 mutex_unlock(&mcp->lock); in mcp_gpio_get()
589 memset(mcp->txbuf, 0, 18); in mcp_gpio_set()
590 mcp->txbuf[0] = MCP2221_GPIO_SET; in mcp_gpio_set()
592 mcp->gp_idx = offsetof(struct mcp_set_gpio, gpio[offset].value); in mcp_gpio_set()
594 mcp->txbuf[mcp->gp_idx - 1] = 1; in mcp_gpio_set()
595 mcp->txbuf[mcp->gp_idx] = !!value; in mcp_gpio_set()
597 mutex_lock(&mcp->lock); in mcp_gpio_set()
598 mcp_send_data_req_status(mcp, mcp->txbuf, 18); in mcp_gpio_set()
599 mutex_unlock(&mcp->lock); in mcp_gpio_set()
605 memset(mcp->txbuf, 0, 18); in mcp_gpio_dir_set()
606 mcp->txbuf[0] = MCP2221_GPIO_SET; in mcp_gpio_dir_set()
608 mcp->gp_idx = offsetof(struct mcp_set_gpio, gpio[offset].direction); in mcp_gpio_dir_set()
610 mcp->txbuf[mcp->gp_idx - 1] = 1; in mcp_gpio_dir_set()
611 mcp->txbuf[mcp->gp_idx] = val; in mcp_gpio_dir_set()
613 return mcp_send_data_req_status(mcp, mcp->txbuf, 18); in mcp_gpio_dir_set()
622 mutex_lock(&mcp->lock); in mcp_gpio_direction_input()
624 mutex_unlock(&mcp->lock); in mcp_gpio_direction_input()
635 mutex_lock(&mcp->lock); in mcp_gpio_direction_output()
637 mutex_unlock(&mcp->lock); in mcp_gpio_direction_output()
654 mcp->txbuf[0] = MCP2221_GPIO_GET; in mcp_gpio_get_direction()
656 mcp->gp_idx = offsetof(struct mcp_get_gpio, gpio[offset].direction); in mcp_gpio_get_direction()
658 mutex_lock(&mcp->lock); in mcp_gpio_get_direction()
659 ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1); in mcp_gpio_get_direction()
660 mutex_unlock(&mcp->lock); in mcp_gpio_get_direction()
665 if (mcp->gpio_dir == MCP2221_DIR_IN) in mcp_gpio_get_direction()
680 ret = -ENXIO; in mcp_get_i2c_eng_state()
686 ret = -ETIMEDOUT; in mcp_get_i2c_eng_state()
689 ret = -EAGAIN; in mcp_get_i2c_eng_state()
695 ret = -EIO; in mcp_get_i2c_eng_state()
708 * results in timeout error and stray reponses results in -EIO.
724 mcp->status = 0; in mcp2221_raw_event()
727 mcp->status = mcp_get_i2c_eng_state(mcp, data, 2); in mcp2221_raw_event()
729 complete(&mcp->wait_in_report); in mcp2221_raw_event()
735 if ((mcp->txbuf[3] == MCP2221_I2C_SET_SPEED) && in mcp2221_raw_event()
737 mcp->status = -EAGAIN; in mcp2221_raw_event()
741 mcp->status = -ENXIO; in mcp2221_raw_event()
744 mcp->status = mcp_get_i2c_eng_state(mcp, data, 8); in mcp2221_raw_event()
747 mcp->status = -EIO; in mcp2221_raw_event()
749 complete(&mcp->wait_in_report); in mcp2221_raw_event()
756 mcp->status = -ENXIO; in mcp2221_raw_event()
761 mcp->status = 0; in mcp2221_raw_event()
765 mcp->status = -EIO; in mcp2221_raw_event()
769 buf = mcp->rxbuf; in mcp2221_raw_event()
770 memcpy(&buf[mcp->rxbuf_idx], &data[4], data[3]); in mcp2221_raw_event()
771 mcp->rxbuf_idx = mcp->rxbuf_idx + data[3]; in mcp2221_raw_event()
772 mcp->status = 0; in mcp2221_raw_event()
775 mcp->status = -EIO; in mcp2221_raw_event()
778 mcp->status = -EIO; in mcp2221_raw_event()
780 complete(&mcp->wait_in_report); in mcp2221_raw_event()
786 if ((data[mcp->gp_idx] == MCP2221_ALT_F_NOT_GPIOV) || in mcp2221_raw_event()
787 (data[mcp->gp_idx + 1] == MCP2221_ALT_F_NOT_GPIOD)) { in mcp2221_raw_event()
788 mcp->status = -ENOENT; in mcp2221_raw_event()
790 mcp->status = !!data[mcp->gp_idx]; in mcp2221_raw_event()
791 mcp->gpio_dir = data[mcp->gp_idx + 1]; in mcp2221_raw_event()
795 mcp->status = -EAGAIN; in mcp2221_raw_event()
797 complete(&mcp->wait_in_report); in mcp2221_raw_event()
803 if ((data[mcp->gp_idx] == MCP2221_ALT_F_NOT_GPIOV) || in mcp2221_raw_event()
804 (data[mcp->gp_idx - 1] == MCP2221_ALT_F_NOT_GPIOV)) { in mcp2221_raw_event()
805 mcp->status = -ENOENT; in mcp2221_raw_event()
807 mcp->status = 0; in mcp2221_raw_event()
811 mcp->status = -EAGAIN; in mcp2221_raw_event()
813 complete(&mcp->wait_in_report); in mcp2221_raw_event()
817 mcp->status = -EIO; in mcp2221_raw_event()
818 complete(&mcp->wait_in_report); in mcp2221_raw_event()
830 mcp = devm_kzalloc(&hdev->dev, sizeof(*mcp), GFP_KERNEL); in mcp2221_probe()
832 return -ENOMEM; in mcp2221_probe()
852 mutex_init(&mcp->lock); in mcp2221_probe()
853 init_completion(&mcp->wait_in_report); in mcp2221_probe()
855 mcp->hdev = hdev; in mcp2221_probe()
862 mcp->cur_i2c_clk_div = (12000000 / (i2c_clk_freq * 1000)) - 3; in mcp2221_probe()
864 mcp->adapter.owner = THIS_MODULE; in mcp2221_probe()
865 mcp->adapter.class = I2C_CLASS_HWMON; in mcp2221_probe()
866 mcp->adapter.algo = &mcp_i2c_algo; in mcp2221_probe()
867 mcp->adapter.retries = 1; in mcp2221_probe()
868 mcp->adapter.dev.parent = &hdev->dev; in mcp2221_probe()
869 snprintf(mcp->adapter.name, sizeof(mcp->adapter.name), in mcp2221_probe()
870 "MCP2221 usb-i2c bridge on hidraw%d", in mcp2221_probe()
871 ((struct hidraw *)hdev->hidraw)->minor); in mcp2221_probe()
873 ret = i2c_add_adapter(&mcp->adapter); in mcp2221_probe()
875 hid_err(hdev, "can't add usb-i2c adapter: %d\n", ret); in mcp2221_probe()
878 i2c_set_adapdata(&mcp->adapter, mcp); in mcp2221_probe()
881 mcp->gc = devm_kzalloc(&hdev->dev, sizeof(*mcp->gc), GFP_KERNEL); in mcp2221_probe()
882 if (!mcp->gc) { in mcp2221_probe()
883 ret = -ENOMEM; in mcp2221_probe()
887 mcp->gc->label = "mcp2221_gpio"; in mcp2221_probe()
888 mcp->gc->direction_input = mcp_gpio_direction_input; in mcp2221_probe()
889 mcp->gc->direction_output = mcp_gpio_direction_output; in mcp2221_probe()
890 mcp->gc->get_direction = mcp_gpio_get_direction; in mcp2221_probe()
891 mcp->gc->set = mcp_gpio_set; in mcp2221_probe()
892 mcp->gc->get = mcp_gpio_get; in mcp2221_probe()
893 mcp->gc->ngpio = MCP_NGPIO; in mcp2221_probe()
894 mcp->gc->base = -1; in mcp2221_probe()
895 mcp->gc->can_sleep = 1; in mcp2221_probe()
896 mcp->gc->parent = &hdev->dev; in mcp2221_probe()
898 ret = devm_gpiochip_add_data(&hdev->dev, mcp->gc, mcp); in mcp2221_probe()
905 i2c_del_adapter(&mcp->adapter); in mcp2221_probe()
907 hid_hw_close(mcp->hdev); in mcp2221_probe()
909 hid_hw_stop(mcp->hdev); in mcp2221_probe()
917 i2c_del_adapter(&mcp->adapter); in mcp2221_remove()
918 hid_hw_close(mcp->hdev); in mcp2221_remove()
919 hid_hw_stop(mcp->hdev); in mcp2221_remove()