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…
19 #include <linux/gpio/consumer.h>
20 #include <linux/gpio/machine.h>
21 #include <linux/gpio/driver.h>
28 #include "hid-ids.h"
179 MODULE_PARM_DESC(gpio_push_pull, "GPIO push-pull configuration bitmask");
184 struct hid_device *hdev = dev->hdev; in cp2112_gpio_direction_input()
185 u8 *buf = dev->in_out_buffer; in cp2112_gpio_direction_input()
188 mutex_lock(&dev->lock); in cp2112_gpio_direction_input()
194 hid_err(hdev, "error requesting GPIO config: %d\n", ret); in cp2112_gpio_direction_input()
196 ret = -EIO; in cp2112_gpio_direction_input()
207 hid_err(hdev, "error setting GPIO config: %d\n", ret); in cp2112_gpio_direction_input()
209 ret = -EIO; in cp2112_gpio_direction_input()
216 mutex_unlock(&dev->lock); in cp2112_gpio_direction_input()
223 struct hid_device *hdev = dev->hdev; in cp2112_gpio_set()
224 u8 *buf = dev->in_out_buffer; in cp2112_gpio_set()
227 mutex_lock(&dev->lock); in cp2112_gpio_set()
237 hid_err(hdev, "error setting GPIO values: %d\n", ret); in cp2112_gpio_set()
239 mutex_unlock(&dev->lock); in cp2112_gpio_set()
245 struct hid_device *hdev = dev->hdev; in cp2112_gpio_get_all()
246 u8 *buf = dev->in_out_buffer; in cp2112_gpio_get_all()
249 mutex_lock(&dev->lock); in cp2112_gpio_get_all()
255 hid_err(hdev, "error requesting GPIO values: %d\n", ret); in cp2112_gpio_get_all()
256 ret = ret < 0 ? ret : -EIO; in cp2112_gpio_get_all()
263 mutex_unlock(&dev->lock); in cp2112_gpio_get_all()
283 struct hid_device *hdev = dev->hdev; in cp2112_gpio_direction_output()
284 u8 *buf = dev->in_out_buffer; in cp2112_gpio_direction_output()
287 mutex_lock(&dev->lock); in cp2112_gpio_direction_output()
293 hid_err(hdev, "error requesting GPIO config: %d\n", ret); in cp2112_gpio_direction_output()
304 hid_err(hdev, "error setting GPIO config: %d\n", ret); in cp2112_gpio_direction_output()
308 mutex_unlock(&dev->lock); in cp2112_gpio_direction_output()
311 * Set gpio value when output direction is already set, in cp2112_gpio_direction_output()
319 mutex_unlock(&dev->lock); in cp2112_gpio_direction_output()
320 return ret < 0 ? ret : -EIO; in cp2112_gpio_direction_output()
331 return -ENOMEM; in cp2112_hid_get()
348 return -ENOMEM; in cp2112_hid_output()
372 ret = wait_event_interruptible_timeout(dev->wait, in cp2112_wait()
374 if (-ERESTARTSYS == ret) in cp2112_wait()
377 return -ETIMEDOUT; in cp2112_wait()
385 struct hid_device *hdev = dev->hdev; in cp2112_xfer_status()
391 atomic_set(&dev->xfer_avail, 0); in cp2112_xfer_status()
399 ret = cp2112_wait(dev, &dev->xfer_avail); in cp2112_xfer_status()
403 return dev->xfer_status; in cp2112_xfer_status()
408 struct hid_device *hdev = dev->hdev; in cp2112_read()
412 if (size > sizeof(dev->read_data)) in cp2112_read()
413 size = sizeof(dev->read_data); in cp2112_read()
417 atomic_set(&dev->read_avail, 0); in cp2112_read()
426 ret = cp2112_wait(dev, &dev->read_avail); in cp2112_read()
431 dev->read_length, size); in cp2112_read()
433 if (size > dev->read_length) in cp2112_read()
434 size = dev->read_length; in cp2112_read()
436 memcpy(data, dev->read_data, size); in cp2112_read()
437 return dev->read_length; in cp2112_read()
445 return -EINVAL; in cp2112_read_req()
447 report->report = CP2112_DATA_READ_REQUEST; in cp2112_read_req()
448 report->slave_address = slave_address << 1; in cp2112_read_req()
449 report->length = cpu_to_be16(length); in cp2112_read_req()
459 || data_length > sizeof(report->target_address) - 1) in cp2112_write_read_req()
460 return -EINVAL; in cp2112_write_read_req()
462 report->report = CP2112_DATA_WRITE_READ_REQUEST; in cp2112_write_read_req()
463 report->slave_address = slave_address << 1; in cp2112_write_read_req()
464 report->length = cpu_to_be16(length); in cp2112_write_read_req()
465 report->target_address_length = data_length + 1; in cp2112_write_read_req()
466 report->target_address[0] = command; in cp2112_write_read_req()
467 memcpy(&report->target_address[1], data, data_length); in cp2112_write_read_req()
476 if (data_length > sizeof(report->data) - 1) in cp2112_write_req()
477 return -EINVAL; in cp2112_write_req()
479 report->report = CP2112_DATA_WRITE_REQUEST; in cp2112_write_req()
480 report->slave_address = slave_address << 1; in cp2112_write_req()
481 report->length = data_length + 1; in cp2112_write_req()
482 report->data[0] = command; in cp2112_write_req()
483 memcpy(&report->data[1], data, data_length); in cp2112_write_req()
492 if (data_length > sizeof(report->data)) in cp2112_i2c_write_req()
493 return -EINVAL; in cp2112_i2c_write_req()
495 report->report = CP2112_DATA_WRITE_REQUEST; in cp2112_i2c_write_req()
496 report->slave_address = slave_address << 1; in cp2112_i2c_write_req()
497 report->length = data_length; in cp2112_i2c_write_req()
498 memcpy(report->data, data, data_length); in cp2112_i2c_write_req()
509 addr_length > sizeof(report->target_address)) in cp2112_i2c_write_read_req()
510 return -EINVAL; in cp2112_i2c_write_read_req()
512 report->report = CP2112_DATA_WRITE_READ_REQUEST; in cp2112_i2c_write_read_req()
513 report->slave_address = slave_address << 1; in cp2112_i2c_write_read_req()
514 report->length = cpu_to_be16(read_length); in cp2112_i2c_write_read_req()
515 report->target_address_length = addr_length; in cp2112_i2c_write_read_req()
516 memcpy(report->target_address, addr, addr_length); in cp2112_i2c_write_read_req()
523 struct cp2112_device *dev = (struct cp2112_device *)adap->algo_data; in cp2112_i2c_xfer()
524 struct hid_device *hdev = dev->hdev; in cp2112_i2c_xfer()
535 if (msgs->flags & I2C_M_RD) { in cp2112_i2c_xfer()
537 msgs->addr, msgs->len); in cp2112_i2c_xfer()
538 read_length = msgs->len; in cp2112_i2c_xfer()
539 read_buf = msgs->buf; in cp2112_i2c_xfer()
540 count = cp2112_read_req(buf, msgs->addr, msgs->len); in cp2112_i2c_xfer()
543 msgs->addr, msgs->len); in cp2112_i2c_xfer()
544 count = cp2112_i2c_write_req(buf, msgs->addr, in cp2112_i2c_xfer()
545 msgs->buf, msgs->len); in cp2112_i2c_xfer()
549 } else if (dev->hwversion > 1 && /* no repeated start in rev 1 */ in cp2112_i2c_xfer()
553 hid_dbg(hdev, "I2C write-read %#04x wlen %d rlen %d\n", in cp2112_i2c_xfer()
563 "Multi-message I2C transactions not supported\n"); in cp2112_i2c_xfer()
564 return -EOPNOTSUPP; in cp2112_i2c_xfer()
581 if (-EBUSY == ret) in cp2112_i2c_xfer()
598 ret = -ETIMEDOUT; in cp2112_i2c_xfer()
603 ret = cp2112_read(dev, read_buf + count, read_length - count); in cp2112_i2c_xfer()
608 ret = -EIO; in cp2112_i2c_xfer()
622 ret, read_length - count + ret); in cp2112_i2c_xfer()
623 ret = -EIO; in cp2112_i2c_xfer()
641 struct cp2112_device *dev = (struct cp2112_device *)adap->algo_data; in cp2112_xfer()
642 struct hid_device *hdev = dev->hdev; in cp2112_xfer()
672 &data->byte, 1); in cp2112_xfer()
676 word = cpu_to_le16(data->word); in cp2112_xfer()
689 word = cpu_to_le16(data->word); in cp2112_xfer()
696 read_length = data->block[0]; in cp2112_xfer()
701 data->block + 1, in cp2112_xfer()
702 data->block[0]); in cp2112_xfer()
712 data->block, in cp2112_xfer()
713 data->block[0] + 1); in cp2112_xfer()
721 command, data->block, in cp2112_xfer()
722 data->block[0] + 1); in cp2112_xfer()
726 return -EOPNOTSUPP; in cp2112_xfer()
746 if (-EBUSY == ret) in cp2112_xfer()
763 ret = -ETIMEDOUT; in cp2112_xfer()
780 ret = -EIO; in cp2112_xfer()
787 data->byte = buf[0]; in cp2112_xfer()
790 data->word = le16_to_cpup((__le16 *)buf); in cp2112_xfer()
794 ret = -EINVAL; in cp2112_xfer()
798 memcpy(data->block + 1, buf, read_length); in cp2112_xfer()
802 ret = -EPROTO; in cp2112_xfer()
806 memcpy(data->block, buf, read_length); in cp2112_xfer()
836 struct cp2112_usb_config_report *cfg) in cp2112_get_usb_config() argument
840 ret = cp2112_hid_get(hdev, CP2112_USB_CONFIG, (u8 *)cfg, sizeof(*cfg), in cp2112_get_usb_config()
842 if (ret != sizeof(*cfg)) { in cp2112_get_usb_config()
846 return -EIO; in cp2112_get_usb_config()
853 struct cp2112_usb_config_report *cfg) in cp2112_set_usb_config() argument
857 BUG_ON(cfg->report != CP2112_USB_CONFIG); in cp2112_set_usb_config()
859 ret = cp2112_hid_output(hdev, (u8 *)cfg, sizeof(*cfg), in cp2112_set_usb_config()
861 if (ret != sizeof(*cfg)) { in cp2112_set_usb_config()
865 return -EIO; in cp2112_set_usb_config()
879 struct cp2112_usb_config_report cfg; \
880 int ret = cp2112_get_usb_config(hdev, &cfg); \
884 ret = cp2112_set_usb_config(hdev, &cfg); \
894 struct cp2112_usb_config_report cfg; \
895 int ret = cp2112_get_usb_config(hdev, &cfg); \
906 return -EINVAL;
908 cfg.vid = cpu_to_le16(vid);
909 cfg.mask = 0x01;
910 }), "0x%04x\n", le16_to_cpu(cfg.vid));
916 return -EINVAL;
918 cfg.pid = cpu_to_le16(pid);
919 cfg.mask = 0x02;
920 }), "0x%04x\n", le16_to_cpu(cfg.pid));
926 return -EINVAL;
928 cfg.max_power = (mA + 1) / 2;
929 cfg.mask = 0x04;
930 }), "%u mA\n", cfg.max_power * 2);
933 if (sscanf(buf, "%hhi", &cfg.power_mode) != 1)
934 return -EINVAL;
936 cfg.mask = 0x08;
937 }), "%u\n", cfg.power_mode);
940 if (sscanf(buf, "%hhi.%hhi", &cfg.release_major, &cfg.release_minor)
942 return -EINVAL;
944 cfg.mask = 0x10;
945 }), "%u.%u\n", cfg.release_major, cfg.release_minor);
968 report.report = attr->report; in pstr_store()
975 hid_err(hdev, "error writing %s string: %d\n", kattr->attr.name, in pstr_store()
979 return -EIO; in pstr_store()
996 ret = cp2112_hid_get(hdev, attr->report, (u8 *)&report.contents, in pstr_show()
999 hid_err(hdev, "error reading %s string: %d\n", kattr->attr.name, in pstr_show()
1003 return -EIO; in pstr_show()
1008 kattr->attr.name, report.length); in pstr_show()
1009 return -EIO; in pstr_show()
1012 length = report.length > ret - 1 ? ret - 1 : report.length; in pstr_show()
1013 length = (length - 2) / sizeof(report.string[0]); in pstr_show()
1015 PAGE_SIZE - 1); in pstr_show()
1049 * already-programmed fields. This is why there is no sense in fixing this
1067 ret = sysfs_chmod_file(&hdev->dev.kobj, *attr, mode); in chmod_sysfs_attrs()
1070 (*attr)->name); in chmod_sysfs_attrs()
1084 __clear_bit(d->hwirq, &dev->irq_mask); in cp2112_gpio_irq_mask()
1092 __set_bit(d->hwirq, &dev->irq_mask); in cp2112_gpio_irq_unmask()
1101 u8 virqs = (u8)dev->irq_mask; in cp2112_gpio_poll_callback()
1105 ret = cp2112_gpio_get_all(&dev->gc); in cp2112_gpio_poll_callback()
1106 if (ret == -ENODEV) /* the hardware has been disconnected */ in cp2112_gpio_poll_callback()
1114 virq = ffs(virqs) - 1; in cp2112_gpio_poll_callback()
1117 if (!dev->gc.to_irq) in cp2112_gpio_poll_callback()
1120 irq = dev->gc.to_irq(&dev->gc, virq); in cp2112_gpio_poll_callback()
1135 !(dev->gpio_prev_state & BIT(virq))) in cp2112_gpio_poll_callback()
1144 (dev->gpio_prev_state & BIT(virq))) in cp2112_gpio_poll_callback()
1149 dev->gpio_prev_state = gpio_mask; in cp2112_gpio_poll_callback()
1152 if (dev->gpio_poll) in cp2112_gpio_poll_callback()
1153 schedule_delayed_work(&dev->gpio_poll_worker, 10); in cp2112_gpio_poll_callback()
1162 INIT_DELAYED_WORK(&dev->gpio_poll_worker, cp2112_gpio_poll_callback); in cp2112_gpio_irq_startup()
1164 if (!dev->gpio_poll) { in cp2112_gpio_irq_startup()
1165 dev->gpio_poll = true; in cp2112_gpio_irq_startup()
1166 schedule_delayed_work(&dev->gpio_poll_worker, 0); in cp2112_gpio_irq_startup()
1178 cancel_delayed_work_sync(&dev->gpio_poll_worker); in cp2112_gpio_irq_shutdown()
1191 if (dev->desc[pin]) in cp2112_allocate_irq()
1192 return -EINVAL; in cp2112_allocate_irq()
1194 dev->desc[pin] = gpiochip_request_own_desc(&dev->gc, pin, in cp2112_allocate_irq()
1198 if (IS_ERR(dev->desc[pin])) { in cp2112_allocate_irq()
1199 dev_err(dev->gc.parent, "Failed to request GPIO\n"); in cp2112_allocate_irq()
1200 return PTR_ERR(dev->desc[pin]); in cp2112_allocate_irq()
1203 ret = cp2112_gpio_direction_input(&dev->gc, pin); in cp2112_allocate_irq()
1205 dev_err(dev->gc.parent, "Failed to set GPIO to input dir\n"); in cp2112_allocate_irq()
1209 ret = gpiochip_lock_as_irq(&dev->gc, pin); in cp2112_allocate_irq()
1211 dev_err(dev->gc.parent, "Failed to lock GPIO as interrupt\n"); in cp2112_allocate_irq()
1215 ret = gpiod_to_irq(dev->desc[pin]); in cp2112_allocate_irq()
1217 dev_err(dev->gc.parent, "Failed to translate GPIO to IRQ\n"); in cp2112_allocate_irq()
1224 gpiochip_unlock_as_irq(&dev->gc, pin); in cp2112_allocate_irq()
1226 gpiochip_free_own_desc(dev->desc[pin]); in cp2112_allocate_irq()
1227 dev->desc[pin] = NULL; in cp2112_allocate_irq()
1239 dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL); in cp2112_probe()
1241 return -ENOMEM; in cp2112_probe()
1243 dev->in_out_buffer = devm_kzalloc(&hdev->dev, CP2112_REPORT_MAX_LENGTH, in cp2112_probe()
1245 if (!dev->in_out_buffer) in cp2112_probe()
1246 return -ENOMEM; in cp2112_probe()
1248 mutex_init(&dev->lock); in cp2112_probe()
1279 ret = -EIO; in cp2112_probe()
1291 ret = -EIO; in cp2112_probe()
1302 ret = -EIO; in cp2112_probe()
1307 dev->hdev = hdev; in cp2112_probe()
1308 dev->adap.owner = THIS_MODULE; in cp2112_probe()
1309 dev->adap.class = I2C_CLASS_HWMON; in cp2112_probe()
1310 dev->adap.algo = &smbus_algorithm; in cp2112_probe()
1311 dev->adap.algo_data = dev; in cp2112_probe()
1312 dev->adap.dev.parent = &hdev->dev; in cp2112_probe()
1313 snprintf(dev->adap.name, sizeof(dev->adap.name), in cp2112_probe()
1315 ((struct hidraw *)hdev->hidraw)->minor); in cp2112_probe()
1316 dev->hwversion = buf[2]; in cp2112_probe()
1317 init_waitqueue_head(&dev->wait); in cp2112_probe()
1320 ret = i2c_add_adapter(&dev->adap); in cp2112_probe()
1330 dev->gc.label = "cp2112_gpio"; in cp2112_probe()
1331 dev->gc.direction_input = cp2112_gpio_direction_input; in cp2112_probe()
1332 dev->gc.direction_output = cp2112_gpio_direction_output; in cp2112_probe()
1333 dev->gc.set = cp2112_gpio_set; in cp2112_probe()
1334 dev->gc.get = cp2112_gpio_get; in cp2112_probe()
1335 dev->gc.base = -1; in cp2112_probe()
1336 dev->gc.ngpio = 8; in cp2112_probe()
1337 dev->gc.can_sleep = 1; in cp2112_probe()
1338 dev->gc.parent = &hdev->dev; in cp2112_probe()
1340 dev->irq.name = "cp2112-gpio"; in cp2112_probe()
1341 dev->irq.irq_startup = cp2112_gpio_irq_startup; in cp2112_probe()
1342 dev->irq.irq_shutdown = cp2112_gpio_irq_shutdown; in cp2112_probe()
1343 dev->irq.irq_ack = cp2112_gpio_irq_ack; in cp2112_probe()
1344 dev->irq.irq_mask = cp2112_gpio_irq_mask; in cp2112_probe()
1345 dev->irq.irq_unmask = cp2112_gpio_irq_unmask; in cp2112_probe()
1346 dev->irq.irq_set_type = cp2112_gpio_irq_type; in cp2112_probe()
1347 dev->irq.flags = IRQCHIP_MASK_ON_SUSPEND; in cp2112_probe()
1349 girq = &dev->gc.irq; in cp2112_probe()
1350 girq->chip = &dev->irq; in cp2112_probe()
1352 girq->parent_handler = NULL; in cp2112_probe()
1353 girq->num_parents = 0; in cp2112_probe()
1354 girq->parents = NULL; in cp2112_probe()
1355 girq->default_type = IRQ_TYPE_NONE; in cp2112_probe()
1356 girq->handler = handle_simple_irq; in cp2112_probe()
1358 ret = gpiochip_add_data(&dev->gc, dev); in cp2112_probe()
1360 hid_err(hdev, "error registering gpio chip\n"); in cp2112_probe()
1364 ret = sysfs_create_group(&hdev->dev.kobj, &cp2112_attr_group); in cp2112_probe()
1376 gpiochip_remove(&dev->gc); in cp2112_probe()
1378 i2c_del_adapter(&dev->adap); in cp2112_probe()
1393 sysfs_remove_group(&hdev->dev.kobj, &cp2112_attr_group); in cp2112_remove()
1394 i2c_del_adapter(&dev->adap); in cp2112_remove()
1396 if (dev->gpio_poll) { in cp2112_remove()
1397 dev->gpio_poll = false; in cp2112_remove()
1398 cancel_delayed_work_sync(&dev->gpio_poll_worker); in cp2112_remove()
1401 for (i = 0; i < ARRAY_SIZE(dev->desc); i++) { in cp2112_remove()
1402 gpiochip_unlock_as_irq(&dev->gc, i); in cp2112_remove()
1403 gpiochip_free_own_desc(dev->desc[i]); in cp2112_remove()
1406 gpiochip_remove(&dev->gc); in cp2112_remove()
1410 * waited for device_unregister(&adap->dev) to complete. Therefore we in cp2112_remove()
1426 xfer->status0, xfer->status1, in cp2112_raw_event()
1427 be16_to_cpu(xfer->retries), be16_to_cpu(xfer->length)); in cp2112_raw_event()
1429 switch (xfer->status0) { in cp2112_raw_event()
1431 dev->xfer_status = -EAGAIN; in cp2112_raw_event()
1434 dev->xfer_status = -EBUSY; in cp2112_raw_event()
1437 dev->xfer_status = be16_to_cpu(xfer->length); in cp2112_raw_event()
1440 switch (xfer->status1) { in cp2112_raw_event()
1443 dev->xfer_status = -ETIMEDOUT; in cp2112_raw_event()
1446 dev->xfer_status = -EIO; in cp2112_raw_event()
1451 dev->xfer_status = -EINVAL; in cp2112_raw_event()
1455 atomic_set(&dev->xfer_avail, 1); in cp2112_raw_event()
1460 dev->read_length = data[2]; in cp2112_raw_event()
1461 if (dev->read_length > sizeof(dev->read_data)) in cp2112_raw_event()
1462 dev->read_length = sizeof(dev->read_data); in cp2112_raw_event()
1464 memcpy(dev->read_data, &data[3], dev->read_length); in cp2112_raw_event()
1465 atomic_set(&dev->read_avail, 1); in cp2112_raw_event()
1473 wake_up_interruptible(&dev->wait); in cp2112_raw_event()