/* check ID and VBUS and update cable state */
id = info->id_gpiod ?
gpiod_get_value_cansleep(info->id_gpiod) : 1;
vbus = info->vbus_gpiod ?
gpiod_get_value_cansleep(info->vbus_gpiod) : id;
/* at first we clean states which are no longer active */ if (id)
extcon_set_state_sync(info->edev, EXTCON_USB_HOST, false); if (!vbus)
extcon_set_state_sync(info->edev, EXTCON_USB, false);
if (!id) {
extcon_set_state_sync(info->edev, EXTCON_USB_HOST, true);
} else { if (vbus)
extcon_set_state_sync(info->edev, EXTCON_USB, true);
}
}
if (!info->id_gpiod && !info->vbus_gpiod) {
dev_err(dev, "failed to get gpios\n"); return -ENODEV;
}
if (IS_ERR(info->id_gpiod)) return PTR_ERR(info->id_gpiod);
if (IS_ERR(info->vbus_gpiod)) return PTR_ERR(info->vbus_gpiod);
info->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable); if (IS_ERR(info->edev)) {
dev_err(dev, "failed to allocate extcon device\n"); return -ENOMEM;
}
ret = devm_extcon_dev_register(dev, info->edev); if (ret < 0) {
dev_err(dev, "failed to register extcon device\n"); return ret;
}
if (info->id_gpiod)
ret = gpiod_set_debounce(info->id_gpiod,
USB_GPIO_DEBOUNCE_MS * 1000); if (!ret && info->vbus_gpiod)
ret = gpiod_set_debounce(info->vbus_gpiod,
USB_GPIO_DEBOUNCE_MS * 1000);
if (ret < 0)
info->debounce_jiffies = msecs_to_jiffies(USB_GPIO_DEBOUNCE_MS);
if (info->id_gpiod) {
info->id_irq = gpiod_to_irq(info->id_gpiod); if (info->id_irq < 0) {
dev_err(dev, "failed to get ID IRQ\n"); return info->id_irq;
}
ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
usb_irq_handler,
IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
pdev->name, info); if (ret < 0) {
dev_err(dev, "failed to request handler for ID IRQ\n"); return ret;
}
}
if (info->vbus_gpiod) {
info->vbus_irq = gpiod_to_irq(info->vbus_gpiod); if (info->vbus_irq < 0) {
dev_err(dev, "failed to get VBUS IRQ\n"); return info->vbus_irq;
}
ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,
usb_irq_handler,
IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
pdev->name, info); if (ret < 0) {
dev_err(dev, "failed to request handler for VBUS IRQ\n"); return ret;
}
}
#ifdef CONFIG_PM_SLEEP staticint usb_extcon_suspend(struct device *dev)
{ struct usb_extcon_info *info = dev_get_drvdata(dev); int ret = 0;
if (device_may_wakeup(dev)) { if (info->id_gpiod) {
ret = enable_irq_wake(info->id_irq); if (ret) return ret;
} if (info->vbus_gpiod) {
ret = enable_irq_wake(info->vbus_irq); if (ret) { if (info->id_gpiod)
disable_irq_wake(info->id_irq);
return ret;
}
}
}
if (!device_may_wakeup(dev))
pinctrl_pm_select_sleep_state(dev);
return ret;
}
staticint usb_extcon_resume(struct device *dev)
{ struct usb_extcon_info *info = dev_get_drvdata(dev); int ret = 0;
if (!device_may_wakeup(dev))
pinctrl_pm_select_default_state(dev);
if (device_may_wakeup(dev)) { if (info->id_gpiod) {
ret = disable_irq_wake(info->id_irq); if (ret) return ret;
} if (info->vbus_gpiod) {
ret = disable_irq_wake(info->vbus_irq); if (ret) { if (info->id_gpiod)
enable_irq_wake(info->id_irq);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.