Lines Matching +full:i2c +full:- +full:hid

1 // SPDX-License-Identifier: GPL-2.0-only
3 * hid-ft260.c - FTDI FT260 USB HID to I2C host bridge
11 #include "hid-ids.h"
13 #include <linux/i2c.h>
32 #define FT260_I2C_DATA_REPORT_ID(len) (FT260_I2C_REPORT_MIN + (len - 1) / 4)
39 * reports. To achieve better performance with the multi-report read data
41 * With a 100 kHz I2C clock, one 240 bytes read takes about 1/27 second,
43 * or optoe limit the i2c reads to 128 bytes. To not block other drivers out
44 * of I2C for potentially troublesome amounts of time, we select the maximum
53 * First implementes USB HID to I2C bridge function and
54 * second - USB HID to UART bridge function.
113 /* Response codes in I2C status report */
125 /* I2C Conditions flags */
147 u8 chip_mode; /* DCNF0 and DCNF1 status, bits 0-1 */
148 u8 clock_ctl; /* 0 - 12MHz, 1 - 24MHz, 2 - 48MHz */
149 u8 suspend_status; /* 0 - not suspended, 1 - suspended */
150 u8 pwren_status; /* 0 - FT260 is not ready, 1 - ready */
151 u8 i2c_enable; /* 0 - disabled, 1 - enabled */
152 u8 uart_mode; /* 0 - OFF; 1 - RTS_CTS, 2 - DTR_DSR, */
153 /* 3 - XON_XOFF, 4 - No flow control */
154 u8 hid_over_i2c_en; /* 0 - disabled, 1 - enabled */
155 u8 gpio2_function; /* 0 - GPIO, 1 - SUSPOUT, */
156 /* 2 - PWREN, 4 - TX_LED */
157 u8 gpioA_function; /* 0 - GPIO, 3 - TX_ACTIVE, 4 - TX_LED */
158 u8 gpioG_function; /* 0 - GPIO, 2 - PWREN, */
159 /* 5 - RX_LED, 6 - BCD_DET */
160 u8 suspend_out_pol; /* 0 - active-high, 1 - active-low */
161 u8 enable_wakeup_int; /* 0 - disabled, 1 - enabled */
163 u8 power_saving_en; /* 0 - disabled, 1 - enabled */
169 u8 bus_status; /* I2C bus status */
170 __le16 clock; /* I2C bus clock in range 60-3400 KHz */
179 u8 clock_ctl; /* 0 - 12MHz, 1 - 24MHz, 2 - 48MHz */
185 u8 i2c_enable; /* 0 - disabled, 1 - enabled */
191 u8 uart_mode; /* 0 - OFF; 1 - RTS_CTS, 2 - DTR_DSR, */
192 /* 3 - XON_XOFF, 4 - No flow control */
203 __le16 clock; /* I2C bus clock in range 60-3400 KHz */
210 u8 address; /* 7-bit I2C address */
211 u8 flag; /* I2C transaction condition */
218 u8 address; /* 7-bit I2C address */
219 u8 flag; /* I2C transaction condition */
234 MODULE_DEVICE_TABLE(hid, ft260_devices);
258 return -ENOMEM; in ft260_hid_feature_report_get()
265 ret = -EIO; in ft260_hid_feature_report_get()
278 return -ENOMEM; in ft260_hid_feature_report_set()
298 hid_err(hdev, "failed to reset I2C controller: %d\n", ret); in ft260_i2c_reset()
308 struct hid_device *hdev = dev->hdev; in ft260_xfer_status()
312 if (time_is_before_jiffies(dev->need_wakeup_at)) { in ft260_xfer_status()
319 dev->need_wakeup_at = jiffies + in ft260_xfer_status()
333 dev->clock = le16_to_cpu(report.clock); in ft260_xfer_status()
335 dev->clock); in ft260_xfer_status()
338 return -EAGAIN; in ft260_xfer_status()
346 hid_err(hdev, "i2c bus error: %#02x\n", report.bus_status); in ft260_xfer_status()
347 return -EIO; in ft260_xfer_status()
361 return -ENOMEM; in ft260_hid_output_report()
374 struct hid_device *hdev = dev->hdev; in ft260_hid_output_report_check_status()
387 usec = len * 9000 / dev->clock; in ft260_hid_output_report_check_status()
389 usec -= 1500; in ft260_hid_output_report_check_status()
399 if (rep->flag == FT260_FLAG_START) in ft260_hid_output_report_check_status()
406 if (ret != -EAGAIN) in ft260_hid_output_report_check_status()
408 } while (--try); in ft260_hid_output_report_check_status()
414 return -EIO; in ft260_hid_output_report_check_status()
421 struct hid_device *hdev = dev->hdev; in ft260_i2c_write()
423 (struct ft260_i2c_write_request_report *)dev->write_buf; in ft260_i2c_write()
426 return -EINVAL; in ft260_i2c_write()
428 rep->flag = FT260_FLAG_START; in ft260_i2c_write()
434 rep->flag |= FT260_FLAG_STOP; in ft260_i2c_write()
439 rep->report = FT260_I2C_DATA_REPORT_ID(wr_len); in ft260_i2c_write()
440 rep->address = addr; in ft260_i2c_write()
441 rep->length = wr_len; in ft260_i2c_write()
443 memcpy(rep->data, &data[idx], wr_len); in ft260_i2c_write()
446 rep->report, addr, idx, len, wr_len, in ft260_i2c_write()
447 rep->flag, data[0]); in ft260_i2c_write()
456 len -= wr_len; in ft260_i2c_write()
458 rep->flag = 0; in ft260_i2c_write()
472 (struct ft260_i2c_write_request_report *)dev->write_buf; in ft260_smbus_write()
474 if (data_len >= sizeof(rep->data)) in ft260_smbus_write()
475 return -EINVAL; in ft260_smbus_write()
477 rep->address = addr; in ft260_smbus_write()
478 rep->data[0] = cmd; in ft260_smbus_write()
479 rep->length = data_len + 1; in ft260_smbus_write()
480 rep->flag = flag; in ft260_smbus_write()
481 len += rep->length; in ft260_smbus_write()
483 rep->report = FT260_I2C_DATA_REPORT_ID(len); in ft260_smbus_write()
486 memcpy(&rep->data[1], data, data_len); in ft260_smbus_write()
489 rep->report, addr, cmd, rep->length, len); in ft260_smbus_write()
503 struct hid_device *hdev = dev->hdev; in ft260_i2c_read()
527 reinit_completion(&dev->wait); in ft260_i2c_read()
529 dev->read_idx = 0; in ft260_i2c_read()
530 dev->read_buf = data; in ft260_i2c_read()
531 dev->read_len = rd_len; in ft260_i2c_read()
540 if (!wait_for_completion_timeout(&dev->wait, timeout)) { in ft260_i2c_read()
541 ret = -ETIMEDOUT; in ft260_i2c_read()
546 dev->read_buf = NULL; in ft260_i2c_read()
553 ret = -EIO; in ft260_i2c_read()
558 len -= rd_len; in ft260_i2c_read()
565 dev->read_buf = NULL; in ft260_i2c_read()
580 struct hid_device *hdev = dev->hdev; in ft260_i2c_write_read()
586 return -EOPNOTSUPP; in ft260_i2c_write_read()
617 struct hid_device *hdev = dev->hdev; in ft260_i2c_xfer()
619 mutex_lock(&dev->lock); in ft260_i2c_xfer()
624 mutex_unlock(&dev->lock); in ft260_i2c_xfer()
629 if (msgs->flags & I2C_M_RD) in ft260_i2c_xfer()
630 ret = ft260_i2c_read(dev, msgs->addr, msgs->buf, in ft260_i2c_xfer()
631 msgs->len, FT260_FLAG_START_STOP); in ft260_i2c_xfer()
633 ret = ft260_i2c_write(dev, msgs->addr, msgs->buf, in ft260_i2c_xfer()
634 msgs->len, FT260_FLAG_START_STOP); in ft260_i2c_xfer()
648 mutex_unlock(&dev->lock); in ft260_i2c_xfer()
658 struct hid_device *hdev = dev->hdev; in ft260_smbus_xfer()
662 mutex_lock(&dev->lock); in ft260_smbus_xfer()
667 mutex_unlock(&dev->lock); in ft260_smbus_xfer()
674 ret = ft260_i2c_read(dev, addr, &data->byte, 1, in ft260_smbus_xfer()
687 ret = ft260_i2c_read(dev, addr, &data->byte, 1, in ft260_smbus_xfer()
690 ret = ft260_smbus_write(dev, addr, cmd, &data->byte, 1, in ft260_smbus_xfer()
701 ret = ft260_i2c_read(dev, addr, (u8 *)&data->word, 2, in ft260_smbus_xfer()
705 (u8 *)&data->word, 2, in ft260_smbus_xfer()
716 ret = ft260_i2c_read(dev, addr, data->block, in ft260_smbus_xfer()
717 data->block[0] + 1, in ft260_smbus_xfer()
720 ret = ft260_smbus_write(dev, addr, cmd, data->block, in ft260_smbus_xfer()
721 data->block[0] + 1, in ft260_smbus_xfer()
732 ret = ft260_i2c_read(dev, addr, data->block + 1, in ft260_smbus_xfer()
733 data->block[0], in ft260_smbus_xfer()
736 ret = ft260_smbus_write(dev, addr, cmd, data->block + 1, in ft260_smbus_xfer()
737 data->block[0], in ft260_smbus_xfer()
743 ret = -EOPNOTSUPP; in ft260_smbus_xfer()
748 mutex_unlock(&dev->lock); in ft260_smbus_xfer()
788 struct usb_interface *usbif = to_usb_interface(hdev->dev.parent); in ft260_is_interface_enabled()
789 int interface = usbif->cur_altsetting->desc.bInterfaceNumber; in ft260_is_interface_enabled()
883 ret = -EINVAL; \
967 return -EINVAL; in ft260_probe()
969 dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL); in ft260_probe()
971 return -ENOMEM; in ft260_probe()
975 hid_err(hdev, "failed to parse HID\n"); in ft260_probe()
981 hid_err(hdev, "failed to start HID HW\n"); in ft260_probe()
987 hid_err(hdev, "failed to open HID HW\n"); in ft260_probe()
1006 hid_info(hdev, "USB HID v%x.%02x Device [%s] on %s\n", in ft260_probe()
1007 hdev->version >> 8, hdev->version & 0xff, hdev->name, in ft260_probe()
1008 hdev->phys); in ft260_probe()
1011 dev->hdev = hdev; in ft260_probe()
1012 dev->adap.owner = THIS_MODULE; in ft260_probe()
1013 dev->adap.class = I2C_CLASS_HWMON; in ft260_probe()
1014 dev->adap.algo = &ft260_i2c_algo; in ft260_probe()
1015 dev->adap.quirks = &ft260_i2c_quirks; in ft260_probe()
1016 dev->adap.dev.parent = &hdev->dev; in ft260_probe()
1017 snprintf(dev->adap.name, sizeof(dev->adap.name), in ft260_probe()
1018 "FT260 usb-i2c bridge"); in ft260_probe()
1020 mutex_init(&dev->lock); in ft260_probe()
1021 init_completion(&dev->wait); in ft260_probe()
1027 i2c_set_adapdata(&dev->adap, dev); in ft260_probe()
1028 ret = i2c_add_adapter(&dev->adap); in ft260_probe()
1030 hid_err(hdev, "failed to add i2c adapter\n"); in ft260_probe()
1034 ret = sysfs_create_group(&hdev->dev.kobj, &ft260_attr_group); in ft260_probe()
1043 i2c_del_adapter(&dev->adap); in ft260_probe()
1058 sysfs_remove_group(&hdev->dev.kobj, &ft260_attr_group); in ft260_remove()
1059 i2c_del_adapter(&dev->adap); in ft260_remove()
1071 if (xfer->report >= FT260_I2C_REPORT_MIN && in ft260_raw_event()
1072 xfer->report <= FT260_I2C_REPORT_MAX) { in ft260_raw_event()
1073 ft260_dbg("i2c resp: rep %#02x len %d\n", xfer->report, in ft260_raw_event()
1074 xfer->length); in ft260_raw_event()
1076 if ((dev->read_buf == NULL) || in ft260_raw_event()
1077 (xfer->length > dev->read_len - dev->read_idx)) { in ft260_raw_event()
1079 xfer->report, xfer->length); in ft260_raw_event()
1080 return -1; in ft260_raw_event()
1083 memcpy(&dev->read_buf[dev->read_idx], &xfer->data, in ft260_raw_event()
1084 xfer->length); in ft260_raw_event()
1085 dev->read_idx += xfer->length; in ft260_raw_event()
1087 if (dev->read_idx == dev->read_len) in ft260_raw_event()
1088 complete(&dev->wait); in ft260_raw_event()
1091 hid_err(hdev, "unhandled report %#02x\n", xfer->report); in ft260_raw_event()
1105 MODULE_DESCRIPTION("FTDI FT260 USB HID to I2C host bridge");