]> Git Repo - linux.git/blob - drivers/usb/dwc3/drd.c
Merge tag 'acpi-fix-4.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[linux.git] / drivers / usb / dwc3 / drd.c
1 // SPDX-License-Identifier: GPL-2.0
2 /**
3  * drd.c - DesignWare USB3 DRD Controller Dual-role support
4  *
5  * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com
6  *
7  * Authors: Roger Quadros <[email protected]>
8  */
9
10 #include <linux/extcon.h>
11
12 #include "debug.h"
13 #include "core.h"
14 #include "gadget.h"
15
16 static void dwc3_drd_update(struct dwc3 *dwc)
17 {
18         int id;
19
20         id = extcon_get_state(dwc->edev, EXTCON_USB_HOST);
21         if (id < 0)
22                 id = 0;
23
24         dwc3_set_mode(dwc, id ?
25                       DWC3_GCTL_PRTCAP_HOST :
26                       DWC3_GCTL_PRTCAP_DEVICE);
27 }
28
29 static int dwc3_drd_notifier(struct notifier_block *nb,
30                              unsigned long event, void *ptr)
31 {
32         struct dwc3 *dwc = container_of(nb, struct dwc3, edev_nb);
33
34         dwc3_set_mode(dwc, event ?
35                       DWC3_GCTL_PRTCAP_HOST :
36                       DWC3_GCTL_PRTCAP_DEVICE);
37
38         return NOTIFY_DONE;
39 }
40
41 int dwc3_drd_init(struct dwc3 *dwc)
42 {
43         int ret;
44
45         if (dwc->dev->of_node) {
46                 if (of_property_read_bool(dwc->dev->of_node, "extcon"))
47                         dwc->edev = extcon_get_edev_by_phandle(dwc->dev, 0);
48
49                 if (IS_ERR(dwc->edev))
50                         return PTR_ERR(dwc->edev);
51
52                 dwc->edev_nb.notifier_call = dwc3_drd_notifier;
53                 ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST,
54                                                &dwc->edev_nb);
55                 if (ret < 0) {
56                         dev_err(dwc->dev, "couldn't register cable notifier\n");
57                         return ret;
58                 }
59         }
60
61         dwc3_drd_update(dwc);
62
63         return 0;
64 }
65
66 void dwc3_drd_exit(struct dwc3 *dwc)
67 {
68         extcon_unregister_notifier(dwc->edev, EXTCON_USB_HOST,
69                                    &dwc->edev_nb);
70
71         dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
72         flush_work(&dwc->drd_work);
73         dwc3_gadget_exit(dwc);
74 }
This page took 0.035608 seconds and 4 git commands to generate.