linux/include/linux/usb/phy.h
<<
>>
Prefs
   1/*
   2 * USB PHY defines
   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 phys 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_phy_events     last_event;
  81
  82        struct usb_otg          *otg;
  83
  84        struct device           *io_dev;
  85        struct usb_phy_io_ops   *io_ops;
  86        void __iomem            *io_priv;
  87
  88        /* for notification of usb_phy_events */
  89        struct atomic_notifier_head     notifier;
  90
  91        /* to pass extra port status to the root hub */
  92        u16                     port_status;
  93        u16                     port_change;
  94
  95        /* to support controllers that have multiple phys */
  96        struct list_head        head;
  97
  98        /* initialize/shutdown the phy */
  99        int     (*init)(struct usb_phy *x);
 100        void    (*shutdown)(struct usb_phy *x);
 101
 102        /* enable/disable VBUS */
 103        int     (*set_vbus)(struct usb_phy *x, int on);
 104
 105        /* effective for B devices, ignored for A-peripheral */
 106        int     (*set_power)(struct usb_phy *x,
 107                                unsigned mA);
 108
 109        /* Set phy into suspend mode */
 110        int     (*set_suspend)(struct usb_phy *x,
 111                                int suspend);
 112
 113        /*
 114         * Set wakeup enable for PHY, in that case, the PHY can be
 115         * woken up from suspend status due to external events,
 116         * like vbus change, dp/dm change and id.
 117         */
 118        int     (*set_wakeup)(struct usb_phy *x, bool enabled);
 119
 120        /* notify phy connect status change */
 121        int     (*notify_connect)(struct usb_phy *x,
 122                        enum usb_device_speed speed);
 123        int     (*notify_disconnect)(struct usb_phy *x,
 124                        enum usb_device_speed speed);
 125};
 126
 127/**
 128 * struct usb_phy_bind - represent the binding for the phy
 129 * @dev_name: the device name of the device that will bind to the phy
 130 * @phy_dev_name: the device name of the phy
 131 * @index: used if a single controller uses multiple phys
 132 * @phy: reference to the phy
 133 * @list: to maintain a linked list of the binding information
 134 */
 135struct usb_phy_bind {
 136        const char      *dev_name;
 137        const char      *phy_dev_name;
 138        u8              index;
 139        struct usb_phy  *phy;
 140        struct list_head list;
 141};
 142
 143/* for board-specific init logic */
 144extern int usb_add_phy(struct usb_phy *, enum usb_phy_type type);
 145extern int usb_add_phy_dev(struct usb_phy *);
 146extern void usb_remove_phy(struct usb_phy *);
 147
 148/* helpers for direct access thru low-level io interface */
 149static inline int usb_phy_io_read(struct usb_phy *x, u32 reg)
 150{
 151        if (x && x->io_ops && x->io_ops->read)
 152                return x->io_ops->read(x, reg);
 153
 154        return -EINVAL;
 155}
 156
 157static inline int usb_phy_io_write(struct usb_phy *x, u32 val, u32 reg)
 158{
 159        if (x && x->io_ops && x->io_ops->write)
 160                return x->io_ops->write(x, val, reg);
 161
 162        return -EINVAL;
 163}
 164
 165static inline int
 166usb_phy_init(struct usb_phy *x)
 167{
 168        if (x && x->init)
 169                return x->init(x);
 170
 171        return 0;
 172}
 173
 174static inline void
 175usb_phy_shutdown(struct usb_phy *x)
 176{
 177        if (x && x->shutdown)
 178                x->shutdown(x);
 179}
 180
 181static inline int
 182usb_phy_vbus_on(struct usb_phy *x)
 183{
 184        if (!x || !x->set_vbus)
 185                return 0;
 186
 187        return x->set_vbus(x, true);
 188}
 189
 190static inline int
 191usb_phy_vbus_off(struct usb_phy *x)
 192{
 193        if (!x || !x->set_vbus)
 194                return 0;
 195
 196        return x->set_vbus(x, false);
 197}
 198
 199/* for usb host and peripheral controller drivers */
 200#if IS_ENABLED(CONFIG_USB_PHY)
 201extern struct usb_phy *usb_get_phy(enum usb_phy_type type);
 202extern struct usb_phy *devm_usb_get_phy(struct device *dev,
 203        enum usb_phy_type type);
 204extern struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index);
 205extern struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index);
 206extern struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
 207        const char *phandle, u8 index);
 208extern struct usb_phy *devm_usb_get_phy_by_node(struct device *dev,
 209        struct device_node *node, struct notifier_block *nb);
 210extern void usb_put_phy(struct usb_phy *);
 211extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x);
 212extern int usb_bind_phy(const char *dev_name, u8 index,
 213                                const char *phy_dev_name);
 214extern void usb_phy_set_event(struct usb_phy *x, unsigned long event);
 215#else
 216static inline struct usb_phy *usb_get_phy(enum usb_phy_type type)
 217{
 218        return ERR_PTR(-ENXIO);
 219}
 220
 221static inline struct usb_phy *devm_usb_get_phy(struct device *dev,
 222        enum usb_phy_type type)
 223{
 224        return ERR_PTR(-ENXIO);
 225}
 226
 227static inline struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index)
 228{
 229        return ERR_PTR(-ENXIO);
 230}
 231
 232static inline struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index)
 233{
 234        return ERR_PTR(-ENXIO);
 235}
 236
 237static inline struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
 238        const char *phandle, u8 index)
 239{
 240        return ERR_PTR(-ENXIO);
 241}
 242
 243static inline struct usb_phy *devm_usb_get_phy_by_node(struct device *dev,
 244        struct device_node *node, struct notifier_block *nb)
 245{
 246        return ERR_PTR(-ENXIO);
 247}
 248
 249static inline void usb_put_phy(struct usb_phy *x)
 250{
 251}
 252
 253static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x)
 254{
 255}
 256
 257static inline int usb_bind_phy(const char *dev_name, u8 index,
 258                                const char *phy_dev_name)
 259{
 260        return -EOPNOTSUPP;
 261}
 262
 263static inline void usb_phy_set_event(struct usb_phy *x, unsigned long event)
 264{
 265}
 266#endif
 267
 268static inline int
 269usb_phy_set_power(struct usb_phy *x, unsigned mA)
 270{
 271        if (x && x->set_power)
 272                return x->set_power(x, mA);
 273        return 0;
 274}
 275
 276/* Context: can sleep */
 277static inline int
 278usb_phy_set_suspend(struct usb_phy *x, int suspend)
 279{
 280        if (x && x->set_suspend != NULL)
 281                return x->set_suspend(x, suspend);
 282        else
 283                return 0;
 284}
 285
 286static inline int
 287usb_phy_set_wakeup(struct usb_phy *x, bool enabled)
 288{
 289        if (x && x->set_wakeup)
 290                return x->set_wakeup(x, enabled);
 291        else
 292                return 0;
 293}
 294
 295static inline int
 296usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed)
 297{
 298        if (x && x->notify_connect)
 299                return x->notify_connect(x, speed);
 300        else
 301                return 0;
 302}
 303
 304static inline int
 305usb_phy_notify_disconnect(struct usb_phy *x, enum usb_device_speed speed)
 306{
 307        if (x && x->notify_disconnect)
 308                return x->notify_disconnect(x, speed);
 309        else
 310                return 0;
 311}
 312
 313/* notifiers */
 314static inline int
 315usb_register_notifier(struct usb_phy *x, struct notifier_block *nb)
 316{
 317        return atomic_notifier_chain_register(&x->notifier, nb);
 318}
 319
 320static inline void
 321usb_unregister_notifier(struct usb_phy *x, struct notifier_block *nb)
 322{
 323        atomic_notifier_chain_unregister(&x->notifier, nb);
 324}
 325
 326static inline const char *usb_phy_type_string(enum usb_phy_type type)
 327{
 328        switch (type) {
 329        case USB_PHY_TYPE_USB2:
 330                return "USB2 PHY";
 331        case USB_PHY_TYPE_USB3:
 332                return "USB3 PHY";
 333        default:
 334                return "UNKNOWN PHY TYPE";
 335        }
 336}
 337#endif /* __LINUX_USB_PHY_H */
 338