Lines Matching +full:gpio +full:- +full:cfg
1 // SPDX-License-Identifier: GPL-2.0-only
3 * hid-cp2112.c - Silicon Labs HID USB to SMBus master bridge
10 * SMBus controller for talking to slave devices and 8 GPIO pins. The
16 …* https://www.silabs.com/documents/public/application-notes/an495-cp2112-interface-specification…
21 #include <linux/gpio/driver.h>
30 #include "hid-ids.h"
181 MODULE_PARM_DESC(gpio_push_pull, "GPIO push-pull configuration bitmask");
186 struct hid_device *hdev = dev->hdev; in cp2112_gpio_direction_input()
187 u8 *buf = dev->in_out_buffer; in cp2112_gpio_direction_input()
190 guard(mutex)(&dev->lock); in cp2112_gpio_direction_input()
196 hid_err(hdev, "error requesting GPIO config: %d\n", ret); in cp2112_gpio_direction_input()
198 ret = -EIO; in cp2112_gpio_direction_input()
209 hid_err(hdev, "error setting GPIO config: %d\n", ret); in cp2112_gpio_direction_input()
211 ret = -EIO; in cp2112_gpio_direction_input()
221 struct hid_device *hdev = dev->hdev; in cp2112_gpio_set_unlocked()
222 u8 *buf = dev->in_out_buffer; in cp2112_gpio_set_unlocked()
233 hid_err(hdev, "error setting GPIO values: %d\n", ret); in cp2112_gpio_set_unlocked()
234 return ret < 0 ? ret : -EIO; in cp2112_gpio_set_unlocked()
245 guard(mutex)(&dev->lock); in cp2112_gpio_set()
253 struct hid_device *hdev = dev->hdev; in cp2112_gpio_get_all()
254 u8 *buf = dev->in_out_buffer; in cp2112_gpio_get_all()
257 guard(mutex)(&dev->lock); in cp2112_gpio_get_all()
263 hid_err(hdev, "error requesting GPIO values: %d\n", ret); in cp2112_gpio_get_all()
264 return ret < 0 ? ret : -EIO; in cp2112_gpio_get_all()
285 struct hid_device *hdev = dev->hdev; in cp2112_gpio_direction_output()
286 u8 *buf = dev->in_out_buffer; in cp2112_gpio_direction_output()
289 guard(mutex)(&dev->lock); in cp2112_gpio_direction_output()
295 hid_err(hdev, "error requesting GPIO config: %d\n", ret); in cp2112_gpio_direction_output()
296 return ret < 0 ? ret : -EIO; in cp2112_gpio_direction_output()
306 hid_err(hdev, "error setting GPIO config: %d\n", ret); in cp2112_gpio_direction_output()
311 * Set gpio value when output direction is already set, in cp2112_gpio_direction_output()
325 return -ENOMEM; in cp2112_hid_get()
342 return -ENOMEM; in cp2112_hid_output()
366 ret = wait_event_interruptible_timeout(dev->wait, in cp2112_wait()
368 if (-ERESTARTSYS == ret) in cp2112_wait()
371 return -ETIMEDOUT; in cp2112_wait()
379 struct hid_device *hdev = dev->hdev; in cp2112_xfer_status()
385 atomic_set(&dev->xfer_avail, 0); in cp2112_xfer_status()
393 ret = cp2112_wait(dev, &dev->xfer_avail); in cp2112_xfer_status()
397 return dev->xfer_status; in cp2112_xfer_status()
402 struct hid_device *hdev = dev->hdev; in cp2112_read()
406 if (size > sizeof(dev->read_data)) in cp2112_read()
407 size = sizeof(dev->read_data); in cp2112_read()
411 atomic_set(&dev->read_avail, 0); in cp2112_read()
420 ret = cp2112_wait(dev, &dev->read_avail); in cp2112_read()
425 dev->read_length, size); in cp2112_read()
427 if (size > dev->read_length) in cp2112_read()
428 size = dev->read_length; in cp2112_read()
430 memcpy(data, dev->read_data, size); in cp2112_read()
431 return dev->read_length; in cp2112_read()
439 return -EINVAL; in cp2112_read_req()
441 report->report = CP2112_DATA_READ_REQUEST; in cp2112_read_req()
442 report->slave_address = slave_address << 1; in cp2112_read_req()
443 report->length = cpu_to_be16(length); in cp2112_read_req()
453 || data_length > sizeof(report->target_address) - 1) in cp2112_write_read_req()
454 return -EINVAL; in cp2112_write_read_req()
456 report->report = CP2112_DATA_WRITE_READ_REQUEST; in cp2112_write_read_req()
457 report->slave_address = slave_address << 1; in cp2112_write_read_req()
458 report->length = cpu_to_be16(length); in cp2112_write_read_req()
459 report->target_address_length = data_length + 1; in cp2112_write_read_req()
460 report->target_address[0] = command; in cp2112_write_read_req()
461 memcpy(&report->target_address[1], data, data_length); in cp2112_write_read_req()
470 if (data_length > sizeof(report->data) - 1) in cp2112_write_req()
471 return -EINVAL; in cp2112_write_req()
473 report->report = CP2112_DATA_WRITE_REQUEST; in cp2112_write_req()
474 report->slave_address = slave_address << 1; in cp2112_write_req()
475 report->length = data_length + 1; in cp2112_write_req()
476 report->data[0] = command; in cp2112_write_req()
477 memcpy(&report->data[1], data, data_length); in cp2112_write_req()
486 if (data_length > sizeof(report->data)) in cp2112_i2c_write_req()
487 return -EINVAL; in cp2112_i2c_write_req()
489 report->report = CP2112_DATA_WRITE_REQUEST; in cp2112_i2c_write_req()
490 report->slave_address = slave_address << 1; in cp2112_i2c_write_req()
491 report->length = data_length; in cp2112_i2c_write_req()
492 memcpy(report->data, data, data_length); in cp2112_i2c_write_req()
503 addr_length > sizeof(report->target_address)) in cp2112_i2c_write_read_req()
504 return -EINVAL; in cp2112_i2c_write_read_req()
506 report->report = CP2112_DATA_WRITE_READ_REQUEST; in cp2112_i2c_write_read_req()
507 report->slave_address = slave_address << 1; in cp2112_i2c_write_read_req()
508 report->length = cpu_to_be16(read_length); in cp2112_i2c_write_read_req()
509 report->target_address_length = addr_length; in cp2112_i2c_write_read_req()
510 memcpy(report->target_address, addr, addr_length); in cp2112_i2c_write_read_req()
517 struct cp2112_device *dev = (struct cp2112_device *)adap->algo_data; in cp2112_i2c_xfer()
518 struct hid_device *hdev = dev->hdev; in cp2112_i2c_xfer()
530 str_read_write(msgs->flags & I2C_M_RD), msgs->addr, msgs->len); in cp2112_i2c_xfer()
531 if (msgs->flags & I2C_M_RD) { in cp2112_i2c_xfer()
532 read_length = msgs->len; in cp2112_i2c_xfer()
533 read_buf = msgs->buf; in cp2112_i2c_xfer()
534 count = cp2112_read_req(buf, msgs->addr, msgs->len); in cp2112_i2c_xfer()
536 count = cp2112_i2c_write_req(buf, msgs->addr, in cp2112_i2c_xfer()
537 msgs->buf, msgs->len); in cp2112_i2c_xfer()
541 } else if (dev->hwversion > 1 && /* no repeated start in rev 1 */ in cp2112_i2c_xfer()
545 hid_dbg(hdev, "I2C write-read %#04x wlen %d rlen %d\n", in cp2112_i2c_xfer()
555 "Multi-message I2C transactions not supported\n"); in cp2112_i2c_xfer()
556 return -EOPNOTSUPP; in cp2112_i2c_xfer()
573 if (-EBUSY == ret) in cp2112_i2c_xfer()
590 ret = -ETIMEDOUT; in cp2112_i2c_xfer()
595 ret = cp2112_read(dev, read_buf + count, read_length - count); in cp2112_i2c_xfer()
600 ret = -EIO; in cp2112_i2c_xfer()
614 ret, read_length - count + ret); in cp2112_i2c_xfer()
615 ret = -EIO; in cp2112_i2c_xfer()
633 struct cp2112_device *dev = (struct cp2112_device *)adap->algo_data; in cp2112_xfer()
634 struct hid_device *hdev = dev->hdev; in cp2112_xfer()
664 &data->byte, 1); in cp2112_xfer()
668 word = cpu_to_le16(data->word); in cp2112_xfer()
681 word = cpu_to_le16(data->word); in cp2112_xfer()
688 read_length = data->block[0]; in cp2112_xfer()
692 /* Copy starts from data->block[1] so the length can in cp2112_xfer()
696 if (data->block[0] > I2C_SMBUS_BLOCK_MAX + 1) in cp2112_xfer()
697 count = -EINVAL; in cp2112_xfer()
700 data->block + 1, in cp2112_xfer()
701 data->block[0]); in cp2112_xfer()
710 /* data_length here is data->block[0] + 1 in cp2112_xfer()
711 * so make sure that the data->block[0] is in cp2112_xfer()
714 if (data->block[0] > I2C_SMBUS_BLOCK_MAX + 1) in cp2112_xfer()
715 count = -EINVAL; in cp2112_xfer()
718 data->block, in cp2112_xfer()
719 data->block[0] + 1); in cp2112_xfer()
726 /* data_length is data->block[0] + 1, so in cp2112_xfer()
727 * so data->block[0] should be less than or in cp2112_xfer()
730 if (data->block[0] > I2C_SMBUS_BLOCK_MAX + 1) in cp2112_xfer()
731 count = -EINVAL; in cp2112_xfer()
734 command, data->block, in cp2112_xfer()
735 data->block[0] + 1); in cp2112_xfer()
739 return -EOPNOTSUPP; in cp2112_xfer()
759 if (-EBUSY == ret) in cp2112_xfer()
776 ret = -ETIMEDOUT; in cp2112_xfer()
793 ret = -EIO; in cp2112_xfer()
800 data->byte = buf[0]; in cp2112_xfer()
803 data->word = le16_to_cpup((__le16 *)buf); in cp2112_xfer()
807 ret = -EINVAL; in cp2112_xfer()
811 memcpy(data->block + 1, buf, read_length); in cp2112_xfer()
815 ret = -EPROTO; in cp2112_xfer()
819 memcpy(data->block, buf, read_length); in cp2112_xfer()
849 struct cp2112_usb_config_report *cfg) in cp2112_get_usb_config() argument
853 ret = cp2112_hid_get(hdev, CP2112_USB_CONFIG, (u8 *)cfg, sizeof(*cfg), in cp2112_get_usb_config()
855 if (ret != sizeof(*cfg)) { in cp2112_get_usb_config()
859 return -EIO; in cp2112_get_usb_config()
866 struct cp2112_usb_config_report *cfg) in cp2112_set_usb_config() argument
870 if (WARN_ON(cfg->report != CP2112_USB_CONFIG)) in cp2112_set_usb_config()
871 return -EINVAL; in cp2112_set_usb_config()
873 ret = cp2112_hid_output(hdev, (u8 *)cfg, sizeof(*cfg), in cp2112_set_usb_config()
875 if (ret != sizeof(*cfg)) { in cp2112_set_usb_config()
879 return -EIO; in cp2112_set_usb_config()
893 struct cp2112_usb_config_report cfg; \
894 int ret = cp2112_get_usb_config(hdev, &cfg); \
898 ret = cp2112_set_usb_config(hdev, &cfg); \
908 struct cp2112_usb_config_report cfg; \
909 int ret = cp2112_get_usb_config(hdev, &cfg); \
920 return -EINVAL;
922 cfg.vid = cpu_to_le16(vid);
923 cfg.mask = 0x01;
924 }), "0x%04x\n", le16_to_cpu(cfg.vid));
930 return -EINVAL;
932 cfg.pid = cpu_to_le16(pid);
933 cfg.mask = 0x02;
934 }), "0x%04x\n", le16_to_cpu(cfg.pid));
940 return -EINVAL;
942 cfg.max_power = (mA + 1) / 2;
943 cfg.mask = 0x04;
944 }), "%u mA\n", cfg.max_power * 2);
947 if (sscanf(buf, "%hhi", &cfg.power_mode) != 1)
948 return -EINVAL;
950 cfg.mask = 0x08;
951 }), "%u\n", cfg.power_mode);
954 if (sscanf(buf, "%hhi.%hhi", &cfg.release_major, &cfg.release_minor)
956 return -EINVAL;
958 cfg.mask = 0x10;
959 }), "%u.%u\n", cfg.release_major, cfg.release_minor);
981 hid_err(hdev, "error writing %s string: %d\n", kattr->attr.name, in pstr_store()
985 return -EIO; in pstr_store()
1003 hid_err(hdev, "error reading %s string: %d\n", kattr->attr.name, in pstr_show()
1007 return -EIO; in pstr_show()
1012 kattr->attr.name, report.length); in pstr_show()
1013 return -EIO; in pstr_show()
1016 length = report.length > ret - 1 ? ret - 1 : report.length; in pstr_show()
1017 length = (length - 2) / sizeof(report.string[0]); in pstr_show()
1019 PAGE_SIZE - 1); in pstr_show()
1059 * already-programmed fields. This is why there is no sense in fixing this
1077 ret = sysfs_chmod_file(&hdev->dev.kobj, *attr, mode); in chmod_sysfs_attrs()
1080 (*attr)->name); in chmod_sysfs_attrs()
1095 __clear_bit(hwirq, &dev->irq_mask); in cp2112_gpio_irq_mask()
1106 __set_bit(hwirq, &dev->irq_mask); in cp2112_gpio_irq_unmask()
1117 ret = cp2112_gpio_get_all(&dev->gc); in cp2112_gpio_poll_callback()
1118 if (ret == -ENODEV) /* the hardware has been disconnected */ in cp2112_gpio_poll_callback()
1124 for_each_set_bit(virq, &dev->irq_mask, CP2112_GPIO_MAX_GPIO) { in cp2112_gpio_poll_callback()
1125 irq = irq_find_mapping(dev->gc.irq.domain, virq); in cp2112_gpio_poll_callback()
1140 !(dev->gpio_prev_state & BIT(virq))) in cp2112_gpio_poll_callback()
1149 (dev->gpio_prev_state & BIT(virq))) in cp2112_gpio_poll_callback()
1154 dev->gpio_prev_state = gpio_mask; in cp2112_gpio_poll_callback()
1157 if (dev->gpio_poll) in cp2112_gpio_poll_callback()
1158 schedule_delayed_work(&dev->gpio_poll_worker, 10); in cp2112_gpio_poll_callback()
1167 if (!dev->gpio_poll) { in cp2112_gpio_irq_startup()
1168 dev->gpio_poll = true; in cp2112_gpio_irq_startup()
1169 schedule_delayed_work(&dev->gpio_poll_worker, 0); in cp2112_gpio_irq_startup()
1183 if (!dev->irq_mask) { in cp2112_gpio_irq_shutdown()
1184 dev->gpio_poll = false; in cp2112_gpio_irq_shutdown()
1185 cancel_delayed_work_sync(&dev->gpio_poll_worker); in cp2112_gpio_irq_shutdown()
1195 .name = "cp2112-gpio",
1214 dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL); in cp2112_probe()
1216 return -ENOMEM; in cp2112_probe()
1218 dev->in_out_buffer = devm_kzalloc(&hdev->dev, CP2112_REPORT_MAX_LENGTH, in cp2112_probe()
1220 if (!dev->in_out_buffer) in cp2112_probe()
1221 return -ENOMEM; in cp2112_probe()
1223 ret = devm_mutex_init(&hdev->dev, &dev->lock); in cp2112_probe()
1258 ret = -EIO; in cp2112_probe()
1270 ret = -EIO; in cp2112_probe()
1281 ret = -EIO; in cp2112_probe()
1286 dev->hdev = hdev; in cp2112_probe()
1287 dev->adap.owner = THIS_MODULE; in cp2112_probe()
1288 dev->adap.class = I2C_CLASS_HWMON; in cp2112_probe()
1289 dev->adap.algo = &smbus_algorithm; in cp2112_probe()
1290 dev->adap.algo_data = dev; in cp2112_probe()
1291 dev->adap.dev.parent = &hdev->dev; in cp2112_probe()
1292 snprintf(dev->adap.name, sizeof(dev->adap.name), in cp2112_probe()
1294 ((struct hidraw *)hdev->hidraw)->minor); in cp2112_probe()
1295 dev->hwversion = buf[2]; in cp2112_probe()
1296 init_waitqueue_head(&dev->wait); in cp2112_probe()
1299 ret = i2c_add_adapter(&dev->adap); in cp2112_probe()
1309 dev->gc.label = "cp2112_gpio"; in cp2112_probe()
1310 dev->gc.direction_input = cp2112_gpio_direction_input; in cp2112_probe()
1311 dev->gc.direction_output = cp2112_gpio_direction_output; in cp2112_probe()
1312 dev->gc.set = cp2112_gpio_set; in cp2112_probe()
1313 dev->gc.get = cp2112_gpio_get; in cp2112_probe()
1314 dev->gc.base = -1; in cp2112_probe()
1315 dev->gc.ngpio = CP2112_GPIO_MAX_GPIO; in cp2112_probe()
1316 dev->gc.can_sleep = 1; in cp2112_probe()
1317 dev->gc.parent = &hdev->dev; in cp2112_probe()
1319 girq = &dev->gc.irq; in cp2112_probe()
1322 girq->parent_handler = NULL; in cp2112_probe()
1323 girq->num_parents = 0; in cp2112_probe()
1324 girq->parents = NULL; in cp2112_probe()
1325 girq->default_type = IRQ_TYPE_NONE; in cp2112_probe()
1326 girq->handler = handle_simple_irq; in cp2112_probe()
1327 girq->threaded = true; in cp2112_probe()
1329 INIT_DELAYED_WORK(&dev->gpio_poll_worker, cp2112_gpio_poll_callback); in cp2112_probe()
1331 ret = gpiochip_add_data(&dev->gc, dev); in cp2112_probe()
1333 hid_err(hdev, "error registering gpio chip\n"); in cp2112_probe()
1337 ret = sysfs_create_group(&hdev->dev.kobj, &cp2112_attr_group); in cp2112_probe()
1349 gpiochip_remove(&dev->gc); in cp2112_probe()
1351 i2c_del_adapter(&dev->adap); in cp2112_probe()
1365 sysfs_remove_group(&hdev->dev.kobj, &cp2112_attr_group); in cp2112_remove()
1366 i2c_del_adapter(&dev->adap); in cp2112_remove()
1368 if (dev->gpio_poll) { in cp2112_remove()
1369 dev->gpio_poll = false; in cp2112_remove()
1370 cancel_delayed_work_sync(&dev->gpio_poll_worker); in cp2112_remove()
1373 gpiochip_remove(&dev->gc); in cp2112_remove()
1377 * waited for device_unregister(&adap->dev) to complete. Therefore we in cp2112_remove()
1393 xfer->status0, xfer->status1, in cp2112_raw_event()
1394 be16_to_cpu(xfer->retries), be16_to_cpu(xfer->length)); in cp2112_raw_event()
1396 switch (xfer->status0) { in cp2112_raw_event()
1398 dev->xfer_status = -EAGAIN; in cp2112_raw_event()
1401 dev->xfer_status = -EBUSY; in cp2112_raw_event()
1404 dev->xfer_status = be16_to_cpu(xfer->length); in cp2112_raw_event()
1407 switch (xfer->status1) { in cp2112_raw_event()
1410 dev->xfer_status = -ETIMEDOUT; in cp2112_raw_event()
1413 dev->xfer_status = -EIO; in cp2112_raw_event()
1418 dev->xfer_status = -EINVAL; in cp2112_raw_event()
1422 atomic_set(&dev->xfer_avail, 1); in cp2112_raw_event()
1427 dev->read_length = data[2]; in cp2112_raw_event()
1428 if (dev->read_length > sizeof(dev->read_data)) in cp2112_raw_event()
1429 dev->read_length = sizeof(dev->read_data); in cp2112_raw_event()
1431 memcpy(dev->read_data, &data[3], dev->read_length); in cp2112_raw_event()
1432 atomic_set(&dev->read_avail, 1); in cp2112_raw_event()
1440 wake_up_interruptible(&dev->wait); in cp2112_raw_event()