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