linux/include/linux/usb/phy.h
<<
>>
Prefs
   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#include <linux/usb.h>
  14
  15enum usb_phy_interface {
  16        USBPHY_INTERFACE_MODE_UNKNOWN,
  17        USBPHY_INTERFACE_MODE_UTMI,
  18        USBPHY_INTERFACE_MODE_UTMIW,
  19        USBPHY_INTERFACE_MODE_ULPI,
  20        USBPHY_INTERFACE_MODE_SERIAL,
  21        USBPHY_INTERFACE_MODE_HSIC,
  22};
  23
  24enum usb_phy_events {
  25        USB_EVENT_NONE,         /* no events or cable disconnected */
  26        USB_EVENT_VBUS,         /* vbus valid event */
  27        USB_EVENT_ID,           /* id was grounded */
  28        USB_EVENT_CHARGER,      /* usb dedicated charger */
  29        USB_EVENT_ENUMERATED,   /* gadget driver enumerated */
  30};
  31
  32/* associate a type with PHY */
  33enum usb_phy_type {
  34        USB_PHY_TYPE_UNDEFINED,
  35        USB_PHY_TYPE_USB2,
  36        USB_PHY_TYPE_USB3,
  37};
  38
  39/* OTG defines lots of enumeration states before device reset */
  40enum usb_otg_state {
  41        OTG_STATE_UNDEFINED = 0,
  42
  43        /* single-role peripheral, and dual-role default-b */
  44        OTG_STATE_B_IDLE,
  45        OTG_STATE_B_SRP_INIT,
  46        OTG_STATE_B_PERIPHERAL,
  47
  48        /* extra dual-role default-b states */
  49        OTG_STATE_B_WAIT_ACON,
  50        OTG_STATE_B_HOST,
  51
  52        /* dual-role default-a */
  53        OTG_STATE_A_IDLE,
  54        OTG_STATE_A_WAIT_VRISE,
  55        OTG_STATE_A_WAIT_BCON,
  56        OTG_STATE_A_HOST,
  57        OTG_STATE_A_SUSPEND,
  58        OTG_STATE_A_PERIPHERAL,
  59        OTG_STATE_A_WAIT_VFALL,
  60        OTG_STATE_A_VBUS_ERR,
  61};
  62
  63struct usb_phy;
  64struct usb_otg;
  65
  66/* for transceivers connected thru an ULPI interface, the user must
  67 * provide access ops
  68 */
  69struct usb_phy_io_ops {
  70        int (*read)(struct usb_phy *x, u32 reg);
  71        int (*write)(struct usb_phy *x, u32 val, u32 reg);
  72};
  73
  74struct usb_phy {
  75        struct device           *dev;
  76        const char              *label;
  77        unsigned int             flags;
  78
  79        enum usb_phy_type       type;
  80        enum usb_otg_state      state;
  81        enum usb_phy_events     last_event;
  82
  83        struct usb_otg          *otg;
  84
  85        struct device           *io_dev;
  86        struct usb_phy_io_ops   *io_ops;
  87        void __iomem            *io_priv;
  88
  89        /* for notification of usb_phy_events */
  90        struct atomic_notifier_head     notifier;
  91
  92        /* to pass extra port status to the root hub */
  93        u16                     port_status;
  94        u16                     port_change;
  95
  96        /* to support controllers that have multiple transceivers */
  97        struct list_head        head;
  98
  99        /* initialize/shutdown the OTG controller */
 100        int     (*init)(struct usb_phy *x);
 101        void    (*shutdown)(struct usb_phy *x);
 102
 103        /* enable/disable VBUS */
 104        int     (*set_vbus)(struct usb_phy *x, int on);
 105
 106        /* effective for B devices, ignored for A-peripheral */
 107        int     (*set_power)(struct usb_phy *x,
 108                                unsigned mA);
 109
 110        /* for non-OTG B devices: set transceiver into suspend mode */
 111        int     (*set_suspend)(struct usb_phy *x,
 112                                int suspend);
 113
 114        /*
 115         * Set wakeup enable for PHY, in that case, the PHY can be
 116         * woken up from suspend status due to external events,
 117         * like vbus change, dp/dm change and id.
 118         */
 119        int     (*set_wakeup)(struct usb_phy *x, bool enabled);
 120
 121        /* notify phy connect status change */
 122        int     (*notify_connect)(struct usb_phy *x,
 123                        enum usb_device_speed speed);
 124        int     (*notify_disconnect)(struct usb_phy *x,
 125                        enum usb_device_speed speed);
 126};
 127
 128/**
 129 * struct usb_phy_bind - represent the binding for the phy
 130 * @dev_name: the device name of the device that will bind to the phy
 131 * @phy_dev_name: the device name of the phy
 132 * @index: used if a single controller uses multiple phys
 133 * @phy: reference to the phy
 134 * @list: to maintain a linked list of the binding information
 135 */
 136struct usb_phy_bind {
 137        const char      *dev_name;
 138        const char      *phy_dev_name;
 139        u8              index;
 140        struct usb_phy  *phy;
 141        struct list_head list;
 142};
 143
 144/* for board-specific init logic */
 145extern int usb_add_phy(struct usb_phy *, enum usb_phy_type type);
 146extern int usb_add_phy_dev(struct usb_phy *);
 147extern void usb_remove_phy(struct usb_phy *);
 148
 149/* helpers for direct access thru low-level io interface */
 150static inline int usb_phy_io_read(struct usb_phy *x, u32 reg)
 151{
 152        if (x && x->io_ops && x->io_ops->read)
 153                return x->io_ops->read(x, reg);
 154
 155        return -EINVAL;
 156}
 157
 158static inline int usb_phy_io_write(struct usb_phy *x, u32 val, u32 reg)
 159{
 160        if (x && x->io_ops && x->io_ops->write)
 161                return x->io_ops->write(x, val, reg);
 162
 163        return -EINVAL;
 164}
 165
 166static inline int
 167usb_phy_init(struct usb_phy *x)
 168{
 169        if (x && x->init)
 170                return x->init(x);
 171
 172        return 0;
 173}
 174
 175static inline void
 176usb_phy_shutdown(struct usb_phy *x)
 177{
 178        if (x && x->shutdown)
 179                x->shutdown(x);
 180}
 181
 182static inline int
 183usb_phy_vbus_on(struct usb_phy *x)
 184{
 185        if (!x || !x->set_vbus)
 186                return 0;
 187
 188        return x->set_vbus(x, true);
 189}
 190
 191static inline int
 192usb_phy_vbus_off(struct usb_phy *x)
 193{
 194        if (!x || !x->set_vbus)
 195                return 0;
 196
 197        return x->set_vbus(x, false);
 198}
 199
 200/* for usb host and peripheral controller drivers */
 201#if IS_ENABLED(CONFIG_USB_PHY)
 202extern struct usb_phy *usb_get_phy(enum usb_phy_type type);
 203extern struct usb_phy *devm_usb_get_phy(struct device *dev,
 204        enum usb_phy_type type);
 205extern struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index);
 206extern struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index);
 207extern struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
 208        const char *phandle, u8 index);
 209extern void usb_put_phy(struct usb_phy *);
 210extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x);
 211extern int usb_bind_phy(const char *dev_name, u8 index,
 212                                const char *phy_dev_name);
 213#else
 214static inline struct usb_phy *usb_get_phy(enum usb_phy_type type)
 215{
 216        return ERR_PTR(-ENXIO);
 217}
 218
 219static inline struct usb_phy *devm_usb_get_phy(struct device *dev,
 220        enum usb_phy_type type)
 221{
 222        return ERR_PTR(-ENXIO);
 223}
 224
 225static inline struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index)
 226{
 227        return ERR_PTR(-ENXIO);
 228}
 229
 230static inline struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index)
 231{
 232        return ERR_PTR(-ENXIO);
 233}
 234
 235static inline struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
 236        const char *phandle, u8 index)
 237{
 238        return ERR_PTR(-ENXIO);
 239}
 240
 241static inline void usb_put_phy(struct usb_phy *x)
 242{
 243}
 244
 245static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x)
 246{
 247}
 248
 249static inline int usb_bind_phy(const char *dev_name, u8 index,
 250                                const char *phy_dev_name)
 251{
 252        return -EOPNOTSUPP;
 253}
 254#endif
 255
 256static inline int
 257usb_phy_set_power(struct usb_phy *x, unsigned mA)
 258{
 259        if (x && x->set_power)
 260                return x->set_power(x, mA);
 261        return 0;
 262}
 263
 264/* Context: can sleep */
 265static inline int
 266usb_phy_set_suspend(struct usb_phy *x, int suspend)
 267{
 268        if (x && x->set_suspend != NULL)
 269                return x->set_suspend(x, suspend);
 270        else
 271                return 0;
 272}
 273
 274static inline int
 275usb_phy_set_wakeup(struct usb_phy *x, bool enabled)
 276{
 277        if (x && x->set_wakeup)
 278                return x->set_wakeup(x, enabled);
 279        else
 280                return 0;
 281}
 282
 283static inline int
 284usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed)
 285{
 286        if (x && x->notify_connect)
 287                return x->notify_connect(x, speed);
 288        else
 289                return 0;
 290}
 291
 292static inline int
 293usb_phy_notify_disconnect(struct usb_phy *x, enum usb_device_speed speed)
 294{
 295        if (x && x->notify_disconnect)
 296                return x->notify_disconnect(x, speed);
 297        else
 298                return 0;
 299}
 300
 301/* notifiers */
 302static inline int
 303usb_register_notifier(struct usb_phy *x, struct notifier_block *nb)
 304{
 305        return atomic_notifier_chain_register(&x->notifier, nb);
 306}
 307
 308static inline void
 309usb_unregister_notifier(struct usb_phy *x, struct notifier_block *nb)
 310{
 311        atomic_notifier_chain_unregister(&x->notifier, nb);
 312}
 313
 314static inline const char *usb_phy_type_string(enum usb_phy_type type)
 315{
 316        switch (type) {
 317        case USB_PHY_TYPE_USB2:
 318                return "USB2 PHY";
 319        case USB_PHY_TYPE_USB3:
 320                return "USB3 PHY";
 321        default:
 322                return "UNKNOWN PHY TYPE";
 323        }
 324}
 325#endif /* __LINUX_USB_PHY_H */
 326