Lines Matching +full:scl +full:- +full:open +full:- +full:drain

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
31 * - CP2112 Datasheet
32 * https://www.silabs.com/documents/public/data-sheets/cp2112-datasheet.pdf
33 * - AN495: CP2112 Interface Specification
34 * https://www.silabs.com/documents/public/application-notes/an495-cp2112-interface-specification.pdf
35 * - CP2112 Errata
36 * https://www.silabs.com/documents/public/errata/cp2112-errata.pdf
66 #define SIZEOF_FIELD(_s, _f) sizeof(((struct _s *)NULL)->_f)
68 #define CP2112GPIO_LOCK(sc) sx_xlock(&sc->gpio_lock)
69 #define CP2112GPIO_UNLOCK(sc) sx_xunlock(&sc->gpio_lock)
70 #define CP2112GPIO_LOCKED(sc) sx_assert(&sc->gpio_lock, SX_XLOCKED)
199 uint16_t write_timeout; /* 0-1000 ms, 0 ~ no timeout */
200 uint16_t read_timeout; /* 0-1000 ms, 0 ~ no timeout */
202 uint16_t retry_count; /* 1-1000, 0 ~ forever */
270 err = usbd_req_get_report(sc->sc_udev, NULL, data,
271 len, sc->sc_iface_index, UHID_FEATURE_REPORT, id);
283 err = usbd_req_set_report(sc->sc_udev, NULL, data,
284 len, sc->sc_iface_index, UHID_FEATURE_REPORT, id);
294 if (uaa->usb_mode != USB_MODE_HOST)
296 if (uaa->info.bInterfaceClass != UICLASS_HID)
317 sc->sc_udev = uaa->device;
318 sc->sc_iface_index = uaa->info.bIfaceIndex;
329 sc->sc_version = vdata.version;
330 sc->sc_gpio_dev = device_add_child(dev, "gpio", DEVICE_UNIT_ANY);
331 if (sc->sc_gpio_dev != NULL) {
332 err = device_probe_and_attach(sc->sc_gpio_dev);
340 sc->sc_iic_dev = device_add_child(dev, "iichb", DEVICE_UNIT_ANY);
341 if (sc->sc_iic_dev != NULL) {
342 err = device_probe_and_attach(sc->sc_iic_dev);
473 return (sc->busdev);
480 *maxpin = CP2112_GPIO_COUNT - 1;
551 *caps = sc->gpio_caps;
567 *flags = sc->pins[pin_num].gp_flags;
583 memcpy(name, sc->pins[pin_num].gp_name, GPIOMAXNAME);
601 if ((flags & sc->gpio_caps) != flags)
620 * If neither push-pull or open-drain is explicitly requested, then
632 pin = &sc->pins[pin_num];
637 * If neither open-drain or push-pull was requested, then see
650 pin->gp_flags = flags;
676 sx_init(&sc->gpio_lock, "cp2112 lock");
678 sc->gpio_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN |
690 pin = &sc->pins[i];
691 pin->gp_flags = 0;
693 snprintf(pin->gp_name, GPIOMAXNAME, "GPIO%u", i);
694 pin->gp_name[GPIOMAXNAME - 1] = '\0';
701 pin->gp_flags |= GPIO_PIN_OUTPUT;
703 pin->gp_flags |= GPIO_PIN_PUSHPULL;
705 pin->gp_flags |= GPIO_PIN_OPENDRAIN;
707 pin->gp_flags |= GPIO_PIN_INPUT;
711 sc->busdev = gpiobus_attach_bus(dev);
712 if (sc->busdev == NULL) {
729 if (sc->busdev != NULL)
731 sx_destroy(&sc->gpio_lock);
743 mtx_assert(&sc->io.lock, MA_OWNED);
748 usbd_copy_in(pc, 0, sc->io.out.data, sc->io.out.len);
749 usbd_xfer_set_frame_len(xfer, 0, sc->io.out.len);
754 sc->io.out.error = 0;
755 sc->io.out.done = 1;
756 cv_signal(&sc->io.cv);
759 device_printf(sc->dev, "write intr state %d error %d\n",
761 sc->io.out.error = IIC_EBUSERR;
762 cv_signal(&sc->io.cv);
778 mtx_assert(&sc->io.lock, MA_OWNED);
783 if (sc->io.in.done) {
784 device_printf(sc->dev,
786 } else if (sc->io.in.len == 0) {
791 * zero-length Read Response during hardware
795 if (device_is_attached(sc->dev)) {
796 device_printf(sc->dev,
802 device_printf(sc->dev, "data: %*D\n",
810 device_printf(sc->dev,
818 usbd_copy_out(pc, 0, sc->io.in.data, sc->io.in.len);
819 sc->io.in.error = 0;
820 sc->io.in.done = 1;
822 device_printf(sc->dev,
824 sc->io.in.error = IIC_EBUSERR;
825 sc->io.in.done = 1;
827 cv_signal(&sc->io.cv);
835 device_printf(sc->dev, "read intr state %d error %d\n",
838 sc->io.in.error = IIC_EBUSERR;
839 sc->io.in.done = 1;
840 cv_signal(&sc->io.cv);
875 mtx_assert(&sc->io.lock, MA_OWNED);
876 KASSERT(sc->io.out.done == 0, ("%s: conflicting request", __func__));
878 sc->io.out.data = data;
879 sc->io.out.len = len;
883 usbd_transfer_start(sc->xfers[CP2112_INTR_OUT]);
885 while (!sc->io.out.done)
886 cv_wait(&sc->io.cv, &sc->io.lock);
888 usbd_transfer_stop(sc->xfers[CP2112_INTR_OUT]);
890 sc->io.out.done = 0;
891 sc->io.out.data = NULL;
892 sc->io.out.len = 0;
893 err = sc->io.out.error;
895 device_printf(sc->dev, "output report 0x%02x failed: %d\n",
907 mtx_assert(&sc->io.lock, MA_OWNED);
913 KASSERT(sc->io.in.done == 0, ("%s: conflicting request", __func__));
914 sc->io.in.len = resp_len;
915 sc->io.in.data = resp_data;
919 sc->io.in.len = 0;
920 sc->io.in.data = NULL;
924 while (!sc->io.in.done)
925 cv_wait(&sc->io.cv, &sc->io.lock);
927 err = sc->io.in.error;
928 sc->io.in.done = 0;
929 sc->io.in.error = 0;
930 sc->io.in.len = 0;
931 sc->io.in.data = NULL;
942 mtx_assert(&sc->io.lock, MA_OWNED);
952 device_printf(sc->dev,
969 err = ERESTART; /* non-I2C, special handling */
986 device_printf(sc->dev,
994 device_printf(sc->dev,
1014 mtx_assert(&sc->io.lock, MA_OWNED);
1032 device_printf(sc->dev,
1053 device_printf(sc->dev, "device returns more data than asked\n");
1092 if (i == nmsgs - 1 && (msgs[i].flags & IIC_M_NOSTOP) != 0) {
1120 psc->sc_version < CP2112_IIC_REPSTART_VER) {
1130 if ((msgs[i - 1].flags & IIC_M_NOSTOP) != 0 &&
1131 msgs[i].slave != msgs[i - 1].slave) {
1135 if ((msgs[i - 1].flags & IIC_M_NOSTOP) != 0 &&
1149 mtx_lock(&sc->io.lock);
1212 to_read -= act_read;
1218 mtx_unlock(&sc->io.lock);
1233 if (sc->iicbus_dev == NULL)
1236 busfreq = IICBUS_GET_FREQUENCY(sc->iicbus_dev, speed);
1252 * - read and write timeouts (no timeout by default),
1253 * - SCL low timeout (disabled by default),
1270 device_printf(dev, "write timeout %d ms (0 - disabled)\n",
1272 device_printf(dev, "read timeout %d ms (0 - disabled)\n",
1274 device_printf(dev, "scl low timeout %s\n",
1276 device_printf(dev, "retry count %d (0 - no limit)\n",
1304 sc->dev = dev;
1308 mtx_init(&sc->io.lock, "cp2112iic lock", NULL, MTX_DEF | MTX_RECURSE);
1309 cv_init(&sc->io.cv, "cp2112iic cv");
1311 err = usbd_transfer_setup(psc->sc_udev,
1312 &psc->sc_iface_index, sc->xfers, cp2112iic_config,
1313 nitems(cp2112iic_config), sc, &sc->io.lock);
1320 mtx_lock(&sc->io.lock);
1321 usbd_transfer_start(sc->xfers[CP2112_INTR_IN]);
1322 mtx_unlock(&sc->io.lock);
1324 sc->iicbus_dev = device_add_child(dev, "iicbus", DEVICE_UNIT_ANY);
1325 if (sc->iicbus_dev == NULL) {
1349 mtx_lock(&sc->io.lock);
1350 usbd_transfer_stop(sc->xfers[CP2112_INTR_IN]);
1351 mtx_unlock(&sc->io.lock);
1352 usbd_transfer_unsetup(sc->xfers, nitems(cp2112iic_config));
1354 cv_destroy(&sc->io.cv);
1355 mtx_destroy(&sc->io.lock);