Lines Matching +full:try +full:- +full:power +full:- +full:role

1 // SPDX-License-Identifier: GPL-2.0
3 * drd.c - DesignWare USB3 DRD Controller Dual-role support
5 * Copyright (C) 2017 Texas Instruments Incorporated - https://www.ti.com
21 u32 reg = dwc3_readl(dwc->regs, DWC3_OEVTEN); in dwc3_otg_disable_events()
24 dwc3_writel(dwc->regs, DWC3_OEVTEN, reg); in dwc3_otg_disable_events()
29 u32 reg = dwc3_readl(dwc->regs, DWC3_OEVTEN); in dwc3_otg_enable_events()
32 dwc3_writel(dwc->regs, DWC3_OEVTEN, reg); in dwc3_otg_enable_events()
37 u32 reg = dwc3_readl(dwc->regs, DWC3_OEVT); in dwc3_otg_clear_events()
39 dwc3_writel(dwc->regs, DWC3_OEVTEN, reg); in dwc3_otg_clear_events()
56 spin_lock(&dwc->lock); in dwc3_otg_thread_irq()
57 if (dwc->otg_restart_host) { in dwc3_otg_thread_irq()
59 dwc->otg_restart_host = false; in dwc3_otg_thread_irq()
62 spin_unlock(&dwc->lock); in dwc3_otg_thread_irq()
75 reg = dwc3_readl(dwc->regs, DWC3_OEVT); in dwc3_otg_irq()
79 dwc3_writel(dwc->regs, DWC3_OEVT, reg); in dwc3_otg_irq()
83 if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST && in dwc3_otg_irq()
85 dwc->otg_restart_host = true; in dwc3_otg_irq()
86 dwc3_writel(dwc->regs, DWC3_OEVT, reg); in dwc3_otg_irq()
103 reg = dwc3_readl(dwc->regs, DWC3_OCFG); in dwc3_otgregs_init()
105 dwc3_writel(dwc->regs, DWC3_OCFG, reg); in dwc3_otgregs_init()
108 reg = dwc3_readl(dwc->regs, DWC3_GCTL); in dwc3_otgregs_init()
110 dwc3_writel(dwc->regs, DWC3_GCTL, reg); in dwc3_otgregs_init()
114 * Figure 11-4 OTG Driver Overall Programming Flow in dwc3_otgregs_init()
117 reg = dwc3_readl(dwc->regs, DWC3_OCFG); in dwc3_otgregs_init()
119 dwc3_writel(dwc->regs, DWC3_OCFG, reg); in dwc3_otgregs_init()
130 reg = dwc3_readl(dwc->regs, DWC3_OCTL); in dwc3_otgregs_init()
134 dwc3_writel(dwc->regs, DWC3_OCTL, reg); in dwc3_otgregs_init()
139 struct platform_device *dwc3_pdev = to_platform_device(dwc->dev); in dwc3_otg_get_irq()
146 if (irq == -EPROBE_DEFER) in dwc3_otg_get_irq()
153 if (irq == -EPROBE_DEFER) in dwc3_otg_get_irq()
161 irq = -EINVAL; in dwc3_otg_get_irq()
172 * As per Figure 11-4 OTG Driver Overall Programming Flow, in dwc3_otg_init()
178 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); in dwc3_otg_init()
180 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); in dwc3_otg_init()
199 /* As per Figure 11-10 A-Device Flow Diagram */ in dwc3_otg_host_init()
206 reg = dwc3_readl(dwc->regs, DWC3_OCTL); in dwc3_otg_host_init()
209 dwc3_writel(dwc->regs, DWC3_OCTL, reg); in dwc3_otg_host_init()
214 reg = dwc3_readl(dwc->regs, DWC3_OCFG); in dwc3_otg_host_init()
216 dwc3_writel(dwc->regs, DWC3_OCFG, reg); in dwc3_otg_host_init()
220 * We don't want SRP/HNP for simple dual-role so leave in dwc3_otg_host_init()
227 * We don't want HNP/role-swap so leave these disabled. in dwc3_otg_host_init()
231 if (!dwc->dis_u2_susphy_quirk) { in dwc3_otg_host_init()
232 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); in dwc3_otg_host_init()
234 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); in dwc3_otg_host_init()
237 /* Set Port Power to enable VBUS: OCTL.PrtPwrCtl = 1 */ in dwc3_otg_host_init()
238 reg = dwc3_readl(dwc->regs, DWC3_OCTL); in dwc3_otg_host_init()
240 dwc3_writel(dwc->regs, DWC3_OCTL, reg); in dwc3_otg_host_init()
249 * Exit from A-device flow as per in dwc3_otg_host_exit()
250 * Figure 11-4 OTG Driver Overall Programming Flow in dwc3_otg_host_exit()
261 reg = dwc3_readl(dwc->regs, DWC3_OCTL); in dwc3_otg_host_exit()
263 dwc3_writel(dwc->regs, DWC3_OCTL, reg); in dwc3_otg_host_exit()
271 /* As per Figure 11-20 B-Device Flow Diagram */ in dwc3_otg_device_init()
275 * but we keep them 0 for simple dual-role operation. in dwc3_otg_device_init()
277 reg = dwc3_readl(dwc->regs, DWC3_OCFG); in dwc3_otg_device_init()
280 dwc3_writel(dwc->regs, DWC3_OCFG, reg); in dwc3_otg_device_init()
286 reg = dwc3_readl(dwc->regs, DWC3_OCTL); in dwc3_otg_device_init()
290 dwc3_writel(dwc->regs, DWC3_OCTL, reg); in dwc3_otg_device_init()
294 if (!dwc->dis_u2_susphy_quirk) { in dwc3_otg_device_init()
295 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); in dwc3_otg_device_init()
297 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); in dwc3_otg_device_init()
308 * Exit from B-device flow as per in dwc3_otg_device_exit()
309 * Figure 11-4 OTG Driver Overall Programming Flow in dwc3_otg_device_exit()
322 reg = dwc3_readl(dwc->regs, DWC3_OCTL); in dwc3_otg_device_exit()
325 dwc3_writel(dwc->regs, DWC3_OCTL, reg); in dwc3_otg_device_exit()
335 if (dwc->dr_mode != USB_DR_MODE_OTG) in dwc3_otg_update()
338 /* don't do anything if debug user changed role to not OTG */ in dwc3_otg_update()
339 if (dwc->current_dr_role != DWC3_GCTL_PRTCAP_OTG) in dwc3_otg_update()
343 reg = dwc3_readl(dwc->regs, DWC3_OSTS); in dwc3_otg_update()
346 dwc->desired_otg_role = id ? DWC3_OTG_ROLE_DEVICE : in dwc3_otg_update()
350 if (dwc->desired_otg_role == dwc->current_otg_role) in dwc3_otg_update()
353 switch (dwc->current_otg_role) { in dwc3_otg_update()
356 spin_lock_irqsave(&dwc->lock, flags); in dwc3_otg_update()
358 spin_unlock_irqrestore(&dwc->lock, flags); in dwc3_otg_update()
362 spin_lock_irqsave(&dwc->lock, flags); in dwc3_otg_update()
365 spin_unlock_irqrestore(&dwc->lock, flags); in dwc3_otg_update()
371 spin_lock_irqsave(&dwc->lock, flags); in dwc3_otg_update()
373 dwc->current_otg_role = dwc->desired_otg_role; in dwc3_otg_update()
375 spin_unlock_irqrestore(&dwc->lock, flags); in dwc3_otg_update()
377 switch (dwc->desired_otg_role) { in dwc3_otg_update()
379 spin_lock_irqsave(&dwc->lock, flags); in dwc3_otg_update()
382 spin_unlock_irqrestore(&dwc->lock, flags); in dwc3_otg_update()
385 dev_err(dwc->dev, "failed to initialize host\n"); in dwc3_otg_update()
387 if (dwc->usb2_phy) in dwc3_otg_update()
388 otg_set_vbus(dwc->usb2_phy->otg, true); in dwc3_otg_update()
389 if (dwc->usb2_generic_phy) in dwc3_otg_update()
390 phy_set_mode(dwc->usb2_generic_phy, in dwc3_otg_update()
395 spin_lock_irqsave(&dwc->lock, flags); in dwc3_otg_update()
399 spin_unlock_irqrestore(&dwc->lock, flags); in dwc3_otg_update()
401 if (dwc->usb2_phy) in dwc3_otg_update()
402 otg_set_vbus(dwc->usb2_phy->otg, false); in dwc3_otg_update()
403 if (dwc->usb2_generic_phy) in dwc3_otg_update()
404 phy_set_mode(dwc->usb2_generic_phy, in dwc3_otg_update()
408 dev_err(dwc->dev, "failed to initialize peripheral\n"); in dwc3_otg_update()
419 if (dwc->edev) { in dwc3_drd_update()
420 id = extcon_get_state(dwc->edev, EXTCON_USB_HOST); in dwc3_drd_update()
443 struct device *dev = dwc->dev; in dwc3_get_extcon()
457 if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) { in dwc3_get_extcon()
460 return ERR_PTR(-EPROBE_DEFER); in dwc3_get_extcon()
466 * Try to get an extcon device from the USB PHY controller's "port" in dwc3_get_extcon()
469 * device (and "port" node) may be missing in case of "usb-role-switch" in dwc3_get_extcon()
472 np_phy = of_parse_phandle(dev->of_node, "phys", 0); in dwc3_get_extcon()
476 np_conn = of_graph_get_remote_node(np_phy, -1, -1); in dwc3_get_extcon()
489 enum usb_role role) in dwc3_usb_role_switch_set() argument
494 switch (role) { in dwc3_usb_role_switch_set()
502 if (dwc->role_switch_default_mode == USB_DR_MODE_HOST) in dwc3_usb_role_switch_set()
517 enum usb_role role; in dwc3_usb_role_switch_get() local
519 spin_lock_irqsave(&dwc->lock, flags); in dwc3_usb_role_switch_get()
520 switch (dwc->current_dr_role) { in dwc3_usb_role_switch_get()
522 role = USB_ROLE_HOST; in dwc3_usb_role_switch_get()
525 role = USB_ROLE_DEVICE; in dwc3_usb_role_switch_get()
528 role = dwc->current_otg_role; in dwc3_usb_role_switch_get()
531 if (dwc->role_switch_default_mode == USB_DR_MODE_HOST) in dwc3_usb_role_switch_get()
532 role = USB_ROLE_HOST; in dwc3_usb_role_switch_get()
534 role = USB_ROLE_DEVICE; in dwc3_usb_role_switch_get()
537 spin_unlock_irqrestore(&dwc->lock, flags); in dwc3_usb_role_switch_get()
538 return role; in dwc3_usb_role_switch_get()
546 dwc->role_switch_default_mode = usb_get_role_switch_default_mode(dwc->dev); in dwc3_setup_role_switch()
547 if (dwc->role_switch_default_mode == USB_DR_MODE_HOST) { in dwc3_setup_role_switch()
550 dwc->role_switch_default_mode = USB_DR_MODE_PERIPHERAL; in dwc3_setup_role_switch()
554 dwc3_role_switch.fwnode = dev_fwnode(dwc->dev); in dwc3_setup_role_switch()
558 dwc->role_sw = usb_role_switch_register(dwc->dev, &dwc3_role_switch); in dwc3_setup_role_switch()
559 if (IS_ERR(dwc->role_sw)) in dwc3_setup_role_switch()
560 return PTR_ERR(dwc->role_sw); in dwc3_setup_role_switch()
574 dwc->edev = dwc3_get_extcon(dwc); in dwc3_drd_init()
575 if (IS_ERR(dwc->edev)) in dwc3_drd_init()
576 return PTR_ERR(dwc->edev); in dwc3_drd_init()
579 device_property_read_bool(dwc->dev, "usb-role-switch")) { in dwc3_drd_init()
583 } else if (dwc->edev) { in dwc3_drd_init()
584 dwc->edev_nb.notifier_call = dwc3_drd_notifier; in dwc3_drd_init()
585 ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST, in dwc3_drd_init()
586 &dwc->edev_nb); in dwc3_drd_init()
588 dev_err(dwc->dev, "couldn't register cable notifier\n"); in dwc3_drd_init()
601 dwc->otg_irq = irq; in dwc3_drd_init()
608 ret = request_threaded_irq(dwc->otg_irq, dwc3_otg_irq, in dwc3_drd_init()
610 IRQF_SHARED, "dwc3-otg", dwc); in dwc3_drd_init()
612 dev_err(dwc->dev, "failed to request irq #%d --> %d\n", in dwc3_drd_init()
613 dwc->otg_irq, ret); in dwc3_drd_init()
614 ret = -ENODEV; in dwc3_drd_init()
629 if (dwc->role_sw) in dwc3_drd_exit()
630 usb_role_switch_unregister(dwc->role_sw); in dwc3_drd_exit()
632 if (dwc->edev) in dwc3_drd_exit()
633 extcon_unregister_notifier(dwc->edev, EXTCON_USB_HOST, in dwc3_drd_exit()
634 &dwc->edev_nb); in dwc3_drd_exit()
636 cancel_work_sync(&dwc->drd_work); in dwc3_drd_exit()
638 /* debug user might have changed role, clean based on current role */ in dwc3_drd_exit()
639 switch (dwc->current_dr_role) { in dwc3_drd_exit()
649 spin_lock_irqsave(&dwc->lock, flags); in dwc3_drd_exit()
650 dwc->desired_otg_role = DWC3_OTG_ROLE_IDLE; in dwc3_drd_exit()
651 spin_unlock_irqrestore(&dwc->lock, flags); in dwc3_drd_exit()
658 if (dwc->otg_irq) in dwc3_drd_exit()
659 free_irq(dwc->otg_irq, dwc); in dwc3_drd_exit()