1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * USB PHY defines
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * These APIs may be used between USB controllers. USB device drivers
6*4882a593Smuzhiyun * (for either host or peripheral roles) don't use these calls; they
7*4882a593Smuzhiyun * continue to use just usb_device and usb_gadget.
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #ifndef __LINUX_USB_PHY_H
11*4882a593Smuzhiyun #define __LINUX_USB_PHY_H
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #include <linux/extcon.h>
14*4882a593Smuzhiyun #include <linux/notifier.h>
15*4882a593Smuzhiyun #include <linux/usb.h>
16*4882a593Smuzhiyun #include <linux/android_kabi.h>
17*4882a593Smuzhiyun #include <uapi/linux/usb/charger.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun enum usb_phy_interface {
20*4882a593Smuzhiyun USBPHY_INTERFACE_MODE_UNKNOWN,
21*4882a593Smuzhiyun USBPHY_INTERFACE_MODE_UTMI,
22*4882a593Smuzhiyun USBPHY_INTERFACE_MODE_UTMIW,
23*4882a593Smuzhiyun USBPHY_INTERFACE_MODE_ULPI,
24*4882a593Smuzhiyun USBPHY_INTERFACE_MODE_SERIAL,
25*4882a593Smuzhiyun USBPHY_INTERFACE_MODE_HSIC,
26*4882a593Smuzhiyun };
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun enum usb_phy_events {
29*4882a593Smuzhiyun USB_EVENT_NONE, /* no events or cable disconnected */
30*4882a593Smuzhiyun USB_EVENT_VBUS, /* vbus valid event */
31*4882a593Smuzhiyun USB_EVENT_ID, /* id was grounded */
32*4882a593Smuzhiyun USB_EVENT_CHARGER, /* usb dedicated charger */
33*4882a593Smuzhiyun USB_EVENT_ENUMERATED, /* gadget driver enumerated */
34*4882a593Smuzhiyun };
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun /* associate a type with PHY */
37*4882a593Smuzhiyun enum usb_phy_type {
38*4882a593Smuzhiyun USB_PHY_TYPE_UNDEFINED,
39*4882a593Smuzhiyun USB_PHY_TYPE_USB2,
40*4882a593Smuzhiyun USB_PHY_TYPE_USB3,
41*4882a593Smuzhiyun };
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun /* OTG defines lots of enumeration states before device reset */
44*4882a593Smuzhiyun enum usb_otg_state {
45*4882a593Smuzhiyun OTG_STATE_UNDEFINED = 0,
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun /* single-role peripheral, and dual-role default-b */
48*4882a593Smuzhiyun OTG_STATE_B_IDLE,
49*4882a593Smuzhiyun OTG_STATE_B_SRP_INIT,
50*4882a593Smuzhiyun OTG_STATE_B_PERIPHERAL,
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun /* extra dual-role default-b states */
53*4882a593Smuzhiyun OTG_STATE_B_WAIT_ACON,
54*4882a593Smuzhiyun OTG_STATE_B_HOST,
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /* dual-role default-a */
57*4882a593Smuzhiyun OTG_STATE_A_IDLE,
58*4882a593Smuzhiyun OTG_STATE_A_WAIT_VRISE,
59*4882a593Smuzhiyun OTG_STATE_A_WAIT_BCON,
60*4882a593Smuzhiyun OTG_STATE_A_HOST,
61*4882a593Smuzhiyun OTG_STATE_A_SUSPEND,
62*4882a593Smuzhiyun OTG_STATE_A_PERIPHERAL,
63*4882a593Smuzhiyun OTG_STATE_A_WAIT_VFALL,
64*4882a593Smuzhiyun OTG_STATE_A_VBUS_ERR,
65*4882a593Smuzhiyun };
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun struct usb_phy;
68*4882a593Smuzhiyun struct usb_otg;
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /* for phys connected thru an ULPI interface, the user must
71*4882a593Smuzhiyun * provide access ops
72*4882a593Smuzhiyun */
73*4882a593Smuzhiyun struct usb_phy_io_ops {
74*4882a593Smuzhiyun int (*read)(struct usb_phy *x, u32 reg);
75*4882a593Smuzhiyun int (*write)(struct usb_phy *x, u32 val, u32 reg);
76*4882a593Smuzhiyun };
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun struct usb_charger_current {
79*4882a593Smuzhiyun unsigned int sdp_min;
80*4882a593Smuzhiyun unsigned int sdp_max;
81*4882a593Smuzhiyun unsigned int dcp_min;
82*4882a593Smuzhiyun unsigned int dcp_max;
83*4882a593Smuzhiyun unsigned int cdp_min;
84*4882a593Smuzhiyun unsigned int cdp_max;
85*4882a593Smuzhiyun unsigned int aca_min;
86*4882a593Smuzhiyun unsigned int aca_max;
87*4882a593Smuzhiyun };
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun struct usb_phy {
90*4882a593Smuzhiyun struct device *dev;
91*4882a593Smuzhiyun const char *label;
92*4882a593Smuzhiyun unsigned int flags;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun enum usb_phy_type type;
95*4882a593Smuzhiyun enum usb_phy_events last_event;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun struct usb_otg *otg;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun struct device *io_dev;
100*4882a593Smuzhiyun struct usb_phy_io_ops *io_ops;
101*4882a593Smuzhiyun void __iomem *io_priv;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun /* to support extcon device */
104*4882a593Smuzhiyun struct extcon_dev *edev;
105*4882a593Smuzhiyun struct extcon_dev *id_edev;
106*4882a593Smuzhiyun struct notifier_block vbus_nb;
107*4882a593Smuzhiyun struct notifier_block id_nb;
108*4882a593Smuzhiyun struct notifier_block type_nb;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun /* Support USB charger */
111*4882a593Smuzhiyun enum usb_charger_type chg_type;
112*4882a593Smuzhiyun enum usb_charger_state chg_state;
113*4882a593Smuzhiyun struct usb_charger_current chg_cur;
114*4882a593Smuzhiyun struct work_struct chg_work;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun /* for notification of usb_phy_events */
117*4882a593Smuzhiyun struct atomic_notifier_head notifier;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun /* to pass extra port status to the root hub */
120*4882a593Smuzhiyun u16 port_status;
121*4882a593Smuzhiyun u16 port_change;
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun /* to support controllers that have multiple phys */
124*4882a593Smuzhiyun struct list_head head;
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun /* initialize/shutdown the phy */
127*4882a593Smuzhiyun int (*init)(struct usb_phy *x);
128*4882a593Smuzhiyun void (*shutdown)(struct usb_phy *x);
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun /* enable/disable VBUS */
131*4882a593Smuzhiyun int (*set_vbus)(struct usb_phy *x, int on);
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun /* effective for B devices, ignored for A-peripheral */
134*4882a593Smuzhiyun int (*set_power)(struct usb_phy *x,
135*4882a593Smuzhiyun unsigned mA);
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun /* Set phy into suspend mode */
138*4882a593Smuzhiyun int (*set_suspend)(struct usb_phy *x,
139*4882a593Smuzhiyun int suspend);
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun /*
142*4882a593Smuzhiyun * Set wakeup enable for PHY, in that case, the PHY can be
143*4882a593Smuzhiyun * woken up from suspend status due to external events,
144*4882a593Smuzhiyun * like vbus change, dp/dm change and id.
145*4882a593Smuzhiyun */
146*4882a593Smuzhiyun int (*set_wakeup)(struct usb_phy *x, bool enabled);
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun /* notify phy connect status change */
149*4882a593Smuzhiyun int (*notify_connect)(struct usb_phy *x,
150*4882a593Smuzhiyun enum usb_device_speed speed);
151*4882a593Smuzhiyun int (*notify_disconnect)(struct usb_phy *x,
152*4882a593Smuzhiyun enum usb_device_speed speed);
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun /*
155*4882a593Smuzhiyun * Charger detection method can be implemented if you need to
156*4882a593Smuzhiyun * manually detect the charger type.
157*4882a593Smuzhiyun */
158*4882a593Smuzhiyun enum usb_charger_type (*charger_detect)(struct usb_phy *x);
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun ANDROID_KABI_RESERVE(1);
161*4882a593Smuzhiyun };
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun /* for board-specific init logic */
164*4882a593Smuzhiyun extern int usb_add_phy(struct usb_phy *, enum usb_phy_type type);
165*4882a593Smuzhiyun extern int usb_add_phy_dev(struct usb_phy *);
166*4882a593Smuzhiyun extern void usb_remove_phy(struct usb_phy *);
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun /* helpers for direct access thru low-level io interface */
usb_phy_io_read(struct usb_phy * x,u32 reg)169*4882a593Smuzhiyun static inline int usb_phy_io_read(struct usb_phy *x, u32 reg)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun if (x && x->io_ops && x->io_ops->read)
172*4882a593Smuzhiyun return x->io_ops->read(x, reg);
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun return -EINVAL;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
usb_phy_io_write(struct usb_phy * x,u32 val,u32 reg)177*4882a593Smuzhiyun static inline int usb_phy_io_write(struct usb_phy *x, u32 val, u32 reg)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun if (x && x->io_ops && x->io_ops->write)
180*4882a593Smuzhiyun return x->io_ops->write(x, val, reg);
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun return -EINVAL;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun static inline int
usb_phy_init(struct usb_phy * x)186*4882a593Smuzhiyun usb_phy_init(struct usb_phy *x)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun if (x && x->init)
189*4882a593Smuzhiyun return x->init(x);
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun return 0;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun static inline void
usb_phy_shutdown(struct usb_phy * x)195*4882a593Smuzhiyun usb_phy_shutdown(struct usb_phy *x)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun if (x && x->shutdown)
198*4882a593Smuzhiyun x->shutdown(x);
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun static inline int
usb_phy_vbus_on(struct usb_phy * x)202*4882a593Smuzhiyun usb_phy_vbus_on(struct usb_phy *x)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun if (!x || !x->set_vbus)
205*4882a593Smuzhiyun return 0;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun return x->set_vbus(x, true);
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun static inline int
usb_phy_vbus_off(struct usb_phy * x)211*4882a593Smuzhiyun usb_phy_vbus_off(struct usb_phy *x)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun if (!x || !x->set_vbus)
214*4882a593Smuzhiyun return 0;
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun return x->set_vbus(x, false);
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun /* for usb host and peripheral controller drivers */
220*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_USB_PHY)
221*4882a593Smuzhiyun extern struct usb_phy *usb_get_phy(enum usb_phy_type type);
222*4882a593Smuzhiyun extern struct usb_phy *devm_usb_get_phy(struct device *dev,
223*4882a593Smuzhiyun enum usb_phy_type type);
224*4882a593Smuzhiyun extern struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
225*4882a593Smuzhiyun const char *phandle, u8 index);
226*4882a593Smuzhiyun extern struct usb_phy *devm_usb_get_phy_by_node(struct device *dev,
227*4882a593Smuzhiyun struct device_node *node, struct notifier_block *nb);
228*4882a593Smuzhiyun extern void usb_put_phy(struct usb_phy *);
229*4882a593Smuzhiyun extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x);
230*4882a593Smuzhiyun extern void usb_phy_set_event(struct usb_phy *x, unsigned long event);
231*4882a593Smuzhiyun extern void usb_phy_set_charger_current(struct usb_phy *usb_phy,
232*4882a593Smuzhiyun unsigned int mA);
233*4882a593Smuzhiyun extern void usb_phy_get_charger_current(struct usb_phy *usb_phy,
234*4882a593Smuzhiyun unsigned int *min, unsigned int *max);
235*4882a593Smuzhiyun extern void usb_phy_set_charger_state(struct usb_phy *usb_phy,
236*4882a593Smuzhiyun enum usb_charger_state state);
237*4882a593Smuzhiyun #else
usb_get_phy(enum usb_phy_type type)238*4882a593Smuzhiyun static inline struct usb_phy *usb_get_phy(enum usb_phy_type type)
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun return ERR_PTR(-ENXIO);
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun
devm_usb_get_phy(struct device * dev,enum usb_phy_type type)243*4882a593Smuzhiyun static inline struct usb_phy *devm_usb_get_phy(struct device *dev,
244*4882a593Smuzhiyun enum usb_phy_type type)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun return ERR_PTR(-ENXIO);
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
devm_usb_get_phy_by_phandle(struct device * dev,const char * phandle,u8 index)249*4882a593Smuzhiyun static inline struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
250*4882a593Smuzhiyun const char *phandle, u8 index)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun return ERR_PTR(-ENXIO);
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun
devm_usb_get_phy_by_node(struct device * dev,struct device_node * node,struct notifier_block * nb)255*4882a593Smuzhiyun static inline struct usb_phy *devm_usb_get_phy_by_node(struct device *dev,
256*4882a593Smuzhiyun struct device_node *node, struct notifier_block *nb)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun return ERR_PTR(-ENXIO);
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
usb_put_phy(struct usb_phy * x)261*4882a593Smuzhiyun static inline void usb_put_phy(struct usb_phy *x)
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun
devm_usb_put_phy(struct device * dev,struct usb_phy * x)265*4882a593Smuzhiyun static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun
usb_phy_set_event(struct usb_phy * x,unsigned long event)269*4882a593Smuzhiyun static inline void usb_phy_set_event(struct usb_phy *x, unsigned long event)
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
usb_phy_set_charger_current(struct usb_phy * usb_phy,unsigned int mA)273*4882a593Smuzhiyun static inline void usb_phy_set_charger_current(struct usb_phy *usb_phy,
274*4882a593Smuzhiyun unsigned int mA)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
usb_phy_get_charger_current(struct usb_phy * usb_phy,unsigned int * min,unsigned int * max)278*4882a593Smuzhiyun static inline void usb_phy_get_charger_current(struct usb_phy *usb_phy,
279*4882a593Smuzhiyun unsigned int *min,
280*4882a593Smuzhiyun unsigned int *max)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun
usb_phy_set_charger_state(struct usb_phy * usb_phy,enum usb_charger_state state)284*4882a593Smuzhiyun static inline void usb_phy_set_charger_state(struct usb_phy *usb_phy,
285*4882a593Smuzhiyun enum usb_charger_state state)
286*4882a593Smuzhiyun {
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun #endif
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun static inline int
usb_phy_set_power(struct usb_phy * x,unsigned mA)291*4882a593Smuzhiyun usb_phy_set_power(struct usb_phy *x, unsigned mA)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun if (!x)
294*4882a593Smuzhiyun return 0;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun usb_phy_set_charger_current(x, mA);
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun if (x->set_power)
299*4882a593Smuzhiyun return x->set_power(x, mA);
300*4882a593Smuzhiyun return 0;
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun /* Context: can sleep */
304*4882a593Smuzhiyun static inline int
usb_phy_set_suspend(struct usb_phy * x,int suspend)305*4882a593Smuzhiyun usb_phy_set_suspend(struct usb_phy *x, int suspend)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun if (x && x->set_suspend != NULL)
308*4882a593Smuzhiyun return x->set_suspend(x, suspend);
309*4882a593Smuzhiyun else
310*4882a593Smuzhiyun return 0;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun static inline int
usb_phy_set_wakeup(struct usb_phy * x,bool enabled)314*4882a593Smuzhiyun usb_phy_set_wakeup(struct usb_phy *x, bool enabled)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun if (x && x->set_wakeup)
317*4882a593Smuzhiyun return x->set_wakeup(x, enabled);
318*4882a593Smuzhiyun else
319*4882a593Smuzhiyun return 0;
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun static inline int
usb_phy_notify_connect(struct usb_phy * x,enum usb_device_speed speed)323*4882a593Smuzhiyun usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed)
324*4882a593Smuzhiyun {
325*4882a593Smuzhiyun if (x && x->notify_connect)
326*4882a593Smuzhiyun return x->notify_connect(x, speed);
327*4882a593Smuzhiyun else
328*4882a593Smuzhiyun return 0;
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun static inline int
usb_phy_notify_disconnect(struct usb_phy * x,enum usb_device_speed speed)332*4882a593Smuzhiyun usb_phy_notify_disconnect(struct usb_phy *x, enum usb_device_speed speed)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun if (x && x->notify_disconnect)
335*4882a593Smuzhiyun return x->notify_disconnect(x, speed);
336*4882a593Smuzhiyun else
337*4882a593Smuzhiyun return 0;
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun /* notifiers */
341*4882a593Smuzhiyun static inline int
usb_register_notifier(struct usb_phy * x,struct notifier_block * nb)342*4882a593Smuzhiyun usb_register_notifier(struct usb_phy *x, struct notifier_block *nb)
343*4882a593Smuzhiyun {
344*4882a593Smuzhiyun return atomic_notifier_chain_register(&x->notifier, nb);
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun static inline void
usb_unregister_notifier(struct usb_phy * x,struct notifier_block * nb)348*4882a593Smuzhiyun usb_unregister_notifier(struct usb_phy *x, struct notifier_block *nb)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun atomic_notifier_chain_unregister(&x->notifier, nb);
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun
usb_phy_type_string(enum usb_phy_type type)353*4882a593Smuzhiyun static inline const char *usb_phy_type_string(enum usb_phy_type type)
354*4882a593Smuzhiyun {
355*4882a593Smuzhiyun switch (type) {
356*4882a593Smuzhiyun case USB_PHY_TYPE_USB2:
357*4882a593Smuzhiyun return "USB2 PHY";
358*4882a593Smuzhiyun case USB_PHY_TYPE_USB3:
359*4882a593Smuzhiyun return "USB3 PHY";
360*4882a593Smuzhiyun default:
361*4882a593Smuzhiyun return "UNKNOWN PHY TYPE";
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun #endif /* __LINUX_USB_PHY_H */
365