Lines Matching +full:otg +full:- +full:id
1 // SPDX-License-Identifier: GPL-2.0
3 * drd.c - DesignWare USB3 DRD Controller Dual-role support
5 * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com
20 u32 reg = dwc3_readl(dwc->regs, DWC3_OEVTEN); in dwc3_otg_disable_events()
23 dwc3_writel(dwc->regs, DWC3_OEVTEN, reg); in dwc3_otg_disable_events()
28 u32 reg = dwc3_readl(dwc->regs, DWC3_OEVTEN); in dwc3_otg_enable_events()
31 dwc3_writel(dwc->regs, DWC3_OEVTEN, reg); in dwc3_otg_enable_events()
36 u32 reg = dwc3_readl(dwc->regs, DWC3_OEVT); in dwc3_otg_clear_events()
38 dwc3_writel(dwc->regs, DWC3_OEVTEN, reg); in dwc3_otg_clear_events()
55 spin_lock(&dwc->lock); in dwc3_otg_thread_irq()
56 if (dwc->otg_restart_host) { in dwc3_otg_thread_irq()
58 dwc->otg_restart_host = 0; in dwc3_otg_thread_irq()
61 spin_unlock(&dwc->lock); in dwc3_otg_thread_irq()
74 reg = dwc3_readl(dwc->regs, DWC3_OEVT); in dwc3_otg_irq()
76 /* ignore non OTG events, we can't disable them in OEVTEN */ in dwc3_otg_irq()
78 dwc3_writel(dwc->regs, DWC3_OEVT, reg); in dwc3_otg_irq()
82 if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST && in dwc3_otg_irq()
84 dwc->otg_restart_host = 1; in dwc3_otg_irq()
85 dwc3_writel(dwc->regs, DWC3_OEVT, reg); in dwc3_otg_irq()
97 * Prevent host/device reset from resetting OTG core. in dwc3_otgregs_init()
99 * the signal outputs sent to the PHY, the OTG FSM logic of the in dwc3_otgregs_init()
102 reg = dwc3_readl(dwc->regs, DWC3_OCFG); in dwc3_otgregs_init()
104 dwc3_writel(dwc->regs, DWC3_OCFG, reg); in dwc3_otgregs_init()
107 reg = dwc3_readl(dwc->regs, DWC3_GCTL); in dwc3_otgregs_init()
109 dwc3_writel(dwc->regs, DWC3_GCTL, reg); in dwc3_otgregs_init()
112 * Initialize OTG registers as per in dwc3_otgregs_init()
113 * Figure 11-4 OTG Driver Overall Programming Flow in dwc3_otgregs_init()
116 reg = dwc3_readl(dwc->regs, DWC3_OCFG); in dwc3_otgregs_init()
118 dwc3_writel(dwc->regs, DWC3_OCFG, reg); in dwc3_otgregs_init()
129 reg = dwc3_readl(dwc->regs, DWC3_OCTL); in dwc3_otgregs_init()
133 dwc3_writel(dwc->regs, DWC3_OCTL, reg); in dwc3_otgregs_init()
138 struct platform_device *dwc3_pdev = to_platform_device(dwc->dev); in dwc3_otg_get_irq()
141 irq = platform_get_irq_byname(dwc3_pdev, "otg"); in dwc3_otg_get_irq()
145 if (irq == -EPROBE_DEFER) in dwc3_otg_get_irq()
152 if (irq == -EPROBE_DEFER) in dwc3_otg_get_irq()
159 if (irq != -EPROBE_DEFER) in dwc3_otg_get_irq()
160 dev_err(dwc->dev, "missing OTG IRQ\n"); in dwc3_otg_get_irq()
163 irq = -EINVAL; in dwc3_otg_get_irq()
174 * As per Figure 11-4 OTG Driver Overall Programming Flow, in dwc3_otg_init()
175 * block "Initialize GCTL for OTG operation". in dwc3_otg_init()
180 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); in dwc3_otg_init()
182 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); in dwc3_otg_init()
184 /* Initialize OTG registers */ in dwc3_otg_init()
190 /* disable all OTG IRQs */ in dwc3_otg_exit()
201 /* As per Figure 11-10 A-Device Flow Diagram */ in dwc3_otg_host_init()
208 reg = dwc3_readl(dwc->regs, DWC3_OCTL); in dwc3_otg_host_init()
211 dwc3_writel(dwc->regs, DWC3_OCTL, reg); in dwc3_otg_host_init()
216 reg = dwc3_readl(dwc->regs, DWC3_OCFG); in dwc3_otg_host_init()
218 dwc3_writel(dwc->regs, DWC3_OCFG, reg); in dwc3_otg_host_init()
222 * We don't want SRP/HNP for simple dual-role so leave in dwc3_otg_host_init()
229 * We don't want HNP/role-swap so leave these disabled. in dwc3_otg_host_init()
233 if (!dwc->dis_u2_susphy_quirk) { in dwc3_otg_host_init()
234 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); in dwc3_otg_host_init()
236 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); in dwc3_otg_host_init()
240 reg = dwc3_readl(dwc->regs, DWC3_OCTL); in dwc3_otg_host_init()
242 dwc3_writel(dwc->regs, DWC3_OCTL, reg); in dwc3_otg_host_init()
251 * Exit from A-device flow as per in dwc3_otg_host_exit()
252 * Figure 11-4 OTG Driver Overall Programming Flow in dwc3_otg_host_exit()
259 * But we don't disable any OTG events in dwc3_otg_host_exit()
263 reg = dwc3_readl(dwc->regs, DWC3_OCTL); in dwc3_otg_host_exit()
265 dwc3_writel(dwc->regs, DWC3_OCTL, reg); in dwc3_otg_host_exit()
273 /* As per Figure 11-20 B-Device Flow Diagram */ in dwc3_otg_device_init()
277 * but we keep them 0 for simple dual-role operation. in dwc3_otg_device_init()
279 reg = dwc3_readl(dwc->regs, DWC3_OCFG); in dwc3_otg_device_init()
282 dwc3_writel(dwc->regs, DWC3_OCFG, reg); in dwc3_otg_device_init()
288 reg = dwc3_readl(dwc->regs, DWC3_OCTL); in dwc3_otg_device_init()
292 dwc3_writel(dwc->regs, DWC3_OCTL, reg); in dwc3_otg_device_init()
296 if (!dwc->dis_u2_susphy_quirk) { in dwc3_otg_device_init()
297 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); in dwc3_otg_device_init()
299 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); in dwc3_otg_device_init()
310 * Exit from B-device flow as per in dwc3_otg_device_exit()
311 * Figure 11-4 OTG Driver Overall Programming Flow in dwc3_otg_device_exit()
324 reg = dwc3_readl(dwc->regs, DWC3_OCTL); in dwc3_otg_device_exit()
327 dwc3_writel(dwc->regs, DWC3_OCTL, reg); in dwc3_otg_device_exit()
334 int id; in dwc3_otg_update() local
337 if (dwc->dr_mode != USB_DR_MODE_OTG) in dwc3_otg_update()
340 /* don't do anything if debug user changed role to not OTG */ in dwc3_otg_update()
341 if (dwc->current_dr_role != DWC3_GCTL_PRTCAP_OTG) in dwc3_otg_update()
345 reg = dwc3_readl(dwc->regs, DWC3_OSTS); in dwc3_otg_update()
346 id = !!(reg & DWC3_OSTS_CONIDSTS); in dwc3_otg_update()
348 dwc->desired_otg_role = id ? DWC3_OTG_ROLE_DEVICE : in dwc3_otg_update()
352 if (dwc->desired_otg_role == dwc->current_otg_role) in dwc3_otg_update()
355 switch (dwc->current_otg_role) { in dwc3_otg_update()
358 spin_lock_irqsave(&dwc->lock, flags); in dwc3_otg_update()
360 spin_unlock_irqrestore(&dwc->lock, flags); in dwc3_otg_update()
364 spin_lock_irqsave(&dwc->lock, flags); in dwc3_otg_update()
367 spin_unlock_irqrestore(&dwc->lock, flags); in dwc3_otg_update()
373 spin_lock_irqsave(&dwc->lock, flags); in dwc3_otg_update()
375 dwc->current_otg_role = dwc->desired_otg_role; in dwc3_otg_update()
377 spin_unlock_irqrestore(&dwc->lock, flags); in dwc3_otg_update()
379 switch (dwc->desired_otg_role) { in dwc3_otg_update()
381 spin_lock_irqsave(&dwc->lock, flags); in dwc3_otg_update()
384 spin_unlock_irqrestore(&dwc->lock, flags); in dwc3_otg_update()
387 dev_err(dwc->dev, "failed to initialize host\n"); in dwc3_otg_update()
389 if (dwc->usb2_phy) in dwc3_otg_update()
390 otg_set_vbus(dwc->usb2_phy->otg, true); in dwc3_otg_update()
391 if (dwc->usb2_generic_phy) in dwc3_otg_update()
392 phy_set_mode(dwc->usb2_generic_phy, in dwc3_otg_update()
397 spin_lock_irqsave(&dwc->lock, flags); in dwc3_otg_update()
401 spin_unlock_irqrestore(&dwc->lock, flags); in dwc3_otg_update()
403 if (dwc->usb2_phy) in dwc3_otg_update()
404 otg_set_vbus(dwc->usb2_phy->otg, false); in dwc3_otg_update()
405 if (dwc->usb2_generic_phy) in dwc3_otg_update()
406 phy_set_mode(dwc->usb2_generic_phy, in dwc3_otg_update()
410 dev_err(dwc->dev, "failed to initialize peripheral\n"); in dwc3_otg_update()
419 int id; in dwc3_drd_update() local
421 if (dwc->edev) { in dwc3_drd_update()
422 id = extcon_get_state(dwc->edev, EXTCON_USB_HOST); in dwc3_drd_update()
423 if (id < 0) in dwc3_drd_update()
424 id = 0; in dwc3_drd_update()
425 dwc3_set_mode(dwc, id ? in dwc3_drd_update()
445 struct device *dev = dwc->dev; in dwc3_get_extcon()
449 if (of_property_read_bool(dev->of_node, "extcon")) in dwc3_get_extcon()
450 return extcon_get_edev_by_phandle(dwc->dev, 0); in dwc3_get_extcon()
452 np_phy = of_parse_phandle(dev->of_node, "phys", 0); in dwc3_get_extcon()
453 np_conn = of_graph_get_remote_node(np_phy, -1, -1); in dwc3_get_extcon()
470 dwc->edev = dwc3_get_extcon(dwc); in dwc3_drd_init()
471 if (IS_ERR(dwc->edev)) in dwc3_drd_init()
472 return PTR_ERR(dwc->edev); in dwc3_drd_init()
474 if (dwc->edev) { in dwc3_drd_init()
475 dwc->edev_nb.notifier_call = dwc3_drd_notifier; in dwc3_drd_init()
476 ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST, in dwc3_drd_init()
477 &dwc->edev_nb); in dwc3_drd_init()
479 dev_err(dwc->dev, "couldn't register cable notifier\n"); in dwc3_drd_init()
486 dwc->current_dr_role = DWC3_GCTL_PRTCAP_OTG; in dwc3_drd_init()
488 /* use OTG block to get ID event */ in dwc3_drd_init()
493 dwc->otg_irq = irq; in dwc3_drd_init()
495 /* disable all OTG IRQs */ in dwc3_drd_init()
500 ret = request_threaded_irq(dwc->otg_irq, dwc3_otg_irq, in dwc3_drd_init()
502 IRQF_SHARED, "dwc3-otg", dwc); in dwc3_drd_init()
504 dev_err(dwc->dev, "failed to request irq #%d --> %d\n", in dwc3_drd_init()
505 dwc->otg_irq, ret); in dwc3_drd_init()
506 ret = -ENODEV; in dwc3_drd_init()
521 if (dwc->edev) in dwc3_drd_exit()
522 extcon_unregister_notifier(dwc->edev, EXTCON_USB_HOST, in dwc3_drd_exit()
523 &dwc->edev_nb); in dwc3_drd_exit()
525 cancel_work_sync(&dwc->drd_work); in dwc3_drd_exit()
528 switch (dwc->current_dr_role) { in dwc3_drd_exit()
538 spin_lock_irqsave(&dwc->lock, flags); in dwc3_drd_exit()
539 dwc->desired_otg_role = DWC3_OTG_ROLE_IDLE; in dwc3_drd_exit()
540 spin_unlock_irqrestore(&dwc->lock, flags); in dwc3_drd_exit()
547 if (!dwc->edev) in dwc3_drd_exit()
548 free_irq(dwc->otg_irq, dwc); in dwc3_drd_exit()