aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/usb/phy.h
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-09-11 16:48:01 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-09-11 16:48:01 -0400
commitdcb9cf39c533a95be7dd0b2f7dfd73e04bf17c2d (patch)
tree7377bc0f6c36e94f17dafd93a003380186021d95 /include/linux/usb/phy.h
parent7135f08e47de094f8748507806efa8d7ba27a964 (diff)
parent363366cf61c544ea476f3d220f43a95cb03014f5 (diff)
Merge tag 'xceiv-for-v3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
usb: xceiv: patches for v3.7 merge window nop xceiv got its own header to avoid polluting otg.h. It has also learned to work as USB2 and USB3 phys so we can use it on USB3 controllers. Together with those two changes to nop xceiv, we're adding basic PHY support to dwc3 driver, this is to allow platforms which actually have a SW-controllable PHY talk to them through dwc3 driver. We're adding a new phy driver for the OMAP architecture. This driver is for the PHY found in OMAP4 SoCs, and a new phy driver for the marvell architecture. An extra phy driver - for Tegra SoCs - is now moving from arch/arm/mach-tegra* to drivers/usb/phy. Also here, there's the creation of <linux/usb/phy.h> which should be used from now on for PHY drivers, even those which don't support OTG.
Diffstat (limited to 'include/linux/usb/phy.h')
-rw-r--r--include/linux/usb/phy.h233
1 files changed, 233 insertions, 0 deletions
diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h
new file mode 100644
index 000000000000..06b5bae35b29
--- /dev/null
+++ b/include/linux/usb/phy.h
@@ -0,0 +1,233 @@
1/* USB OTG (On The Go) defines */
2/*
3 *
4 * These APIs may be used between USB controllers. USB device drivers
5 * (for either host or peripheral roles) don't use these calls; they
6 * continue to use just usb_device and usb_gadget.
7 */
8
9#ifndef __LINUX_USB_PHY_H
10#define __LINUX_USB_PHY_H
11
12#include <linux/notifier.h>
13
14enum usb_phy_events {
15 USB_EVENT_NONE, /* no events or cable disconnected */
16 USB_EVENT_VBUS, /* vbus valid event */
17 USB_EVENT_ID, /* id was grounded */
18 USB_EVENT_CHARGER, /* usb dedicated charger */
19 USB_EVENT_ENUMERATED, /* gadget driver enumerated */
20};
21
22/* associate a type with PHY */
23enum usb_phy_type {
24 USB_PHY_TYPE_UNDEFINED,
25 USB_PHY_TYPE_USB2,
26 USB_PHY_TYPE_USB3,
27};
28
29/* OTG defines lots of enumeration states before device reset */
30enum usb_otg_state {
31 OTG_STATE_UNDEFINED = 0,
32
33 /* single-role peripheral, and dual-role default-b */
34 OTG_STATE_B_IDLE,
35 OTG_STATE_B_SRP_INIT,
36 OTG_STATE_B_PERIPHERAL,
37
38 /* extra dual-role default-b states */
39 OTG_STATE_B_WAIT_ACON,
40 OTG_STATE_B_HOST,
41
42 /* dual-role default-a */
43 OTG_STATE_A_IDLE,
44 OTG_STATE_A_WAIT_VRISE,
45 OTG_STATE_A_WAIT_BCON,
46 OTG_STATE_A_HOST,
47 OTG_STATE_A_SUSPEND,
48 OTG_STATE_A_PERIPHERAL,
49 OTG_STATE_A_WAIT_VFALL,
50 OTG_STATE_A_VBUS_ERR,
51};
52
53struct usb_phy;
54struct usb_otg;
55
56/* for transceivers connected thru an ULPI interface, the user must
57 * provide access ops
58 */
59struct usb_phy_io_ops {
60 int (*read)(struct usb_phy *x, u32 reg);
61 int (*write)(struct usb_phy *x, u32 val, u32 reg);
62};
63
64struct usb_phy {
65 struct device *dev;
66 const char *label;
67 unsigned int flags;
68
69 enum usb_phy_type type;
70 enum usb_otg_state state;
71 enum usb_phy_events last_event;
72
73 struct usb_otg *otg;
74
75 struct device *io_dev;
76 struct usb_phy_io_ops *io_ops;
77 void __iomem *io_priv;
78
79 /* for notification of usb_phy_events */
80 struct atomic_notifier_head notifier;
81
82 /* to pass extra port status to the root hub */
83 u16 port_status;
84 u16 port_change;
85
86 /* to support controllers that have multiple transceivers */
87 struct list_head head;
88
89 /* initialize/shutdown the OTG controller */
90 int (*init)(struct usb_phy *x);
91 void (*shutdown)(struct usb_phy *x);
92
93 /* effective for B devices, ignored for A-peripheral */
94 int (*set_power)(struct usb_phy *x,
95 unsigned mA);
96
97 /* for non-OTG B devices: set transceiver into suspend mode */
98 int (*set_suspend)(struct usb_phy *x,
99 int suspend);
100
101 /* notify phy connect status change */
102 int (*notify_connect)(struct usb_phy *x, int port);
103 int (*notify_disconnect)(struct usb_phy *x, int port);
104};
105
106
107/* for board-specific init logic */
108extern int usb_add_phy(struct usb_phy *, enum usb_phy_type type);
109extern void usb_remove_phy(struct usb_phy *);
110
111/* helpers for direct access thru low-level io interface */
112static inline int usb_phy_io_read(struct usb_phy *x, u32 reg)
113{
114 if (x->io_ops && x->io_ops->read)
115 return x->io_ops->read(x, reg);
116
117 return -EINVAL;
118}
119
120static inline int usb_phy_io_write(struct usb_phy *x, u32 val, u32 reg)
121{
122 if (x->io_ops && x->io_ops->write)
123 return x->io_ops->write(x, val, reg);
124
125 return -EINVAL;
126}
127
128static inline int
129usb_phy_init(struct usb_phy *x)
130{
131 if (x->init)
132 return x->init(x);
133
134 return 0;
135}
136
137static inline void
138usb_phy_shutdown(struct usb_phy *x)
139{
140 if (x->shutdown)
141 x->shutdown(x);
142}
143
144/* for usb host and peripheral controller drivers */
145#ifdef CONFIG_USB_OTG_UTILS
146extern struct usb_phy *usb_get_phy(enum usb_phy_type type);
147extern struct usb_phy *devm_usb_get_phy(struct device *dev,
148 enum usb_phy_type type);
149extern void usb_put_phy(struct usb_phy *);
150extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x);
151#else
152static inline struct usb_phy *usb_get_phy(enum usb_phy_type type)
153{
154 return NULL;
155}
156
157static inline struct usb_phy *devm_usb_get_phy(struct device *dev,
158 enum usb_phy_type type)
159{
160 return NULL;
161}
162
163static inline void usb_put_phy(struct usb_phy *x)
164{
165}
166
167static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x)
168{
169}
170
171#endif
172
173static inline int
174usb_phy_set_power(struct usb_phy *x, unsigned mA)
175{
176 if (x && x->set_power)
177 return x->set_power(x, mA);
178 return 0;
179}
180
181/* Context: can sleep */
182static inline int
183usb_phy_set_suspend(struct usb_phy *x, int suspend)
184{
185 if (x->set_suspend != NULL)
186 return x->set_suspend(x, suspend);
187 else
188 return 0;
189}
190
191static inline int
192usb_phy_notify_connect(struct usb_phy *x, int port)
193{
194 if (x->notify_connect)
195 return x->notify_connect(x, port);
196 else
197 return 0;
198}
199
200static inline int
201usb_phy_notify_disconnect(struct usb_phy *x, int port)
202{
203 if (x->notify_disconnect)
204 return x->notify_disconnect(x, port);
205 else
206 return 0;
207}
208
209/* notifiers */
210static inline int
211usb_register_notifier(struct usb_phy *x, struct notifier_block *nb)
212{
213 return atomic_notifier_chain_register(&x->notifier, nb);
214}
215
216static inline void
217usb_unregister_notifier(struct usb_phy *x, struct notifier_block *nb)
218{
219 atomic_notifier_chain_unregister(&x->notifier, nb);
220}
221
222static inline const char *usb_phy_type_string(enum usb_phy_type type)
223{
224 switch (type) {
225 case USB_PHY_TYPE_USB2:
226 return "USB2 PHY";
227 case USB_PHY_TYPE_USB3:
228 return "USB3 PHY";
229 default:
230 return "UNKNOWN PHY TYPE";
231 }
232}
233#endif /* __LINUX_USB_PHY_H */