root/drivers/usb/phy/phy-ulpi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ulpi_set_otg_flags
  2. ulpi_set_fc_flags
  3. ulpi_set_ic_flags
  4. ulpi_set_flags
  5. ulpi_check_integrity
  6. ulpi_init
  7. ulpi_set_host
  8. ulpi_set_vbus
  9. otg_ulpi_create

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Generic ULPI USB transceiver support
   4  *
   5  * Copyright (C) 2009 Daniel Mack <daniel@caiaq.de>
   6  *
   7  * Based on sources from
   8  *
   9  *   Sascha Hauer <s.hauer@pengutronix.de>
  10  *   Freescale Semiconductors
  11  */
  12 
  13 #include <linux/kernel.h>
  14 #include <linux/slab.h>
  15 #include <linux/export.h>
  16 #include <linux/usb.h>
  17 #include <linux/usb/otg.h>
  18 #include <linux/usb/ulpi.h>
  19 
  20 
  21 struct ulpi_info {
  22         unsigned int    id;
  23         char            *name;
  24 };
  25 
  26 #define ULPI_ID(vendor, product) (((vendor) << 16) | (product))
  27 #define ULPI_INFO(_id, _name)           \
  28         {                               \
  29                 .id     = (_id),        \
  30                 .name   = (_name),      \
  31         }
  32 
  33 /* ULPI hardcoded IDs, used for probing */
  34 static struct ulpi_info ulpi_ids[] = {
  35         ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"),
  36         ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"),
  37         ULPI_INFO(ULPI_ID(0x0424, 0x0007), "SMSC USB3320"),
  38         ULPI_INFO(ULPI_ID(0x0424, 0x0009), "SMSC USB334x"),
  39         ULPI_INFO(ULPI_ID(0x0451, 0x1507), "TI TUSB1210"),
  40 };
  41 
  42 static int ulpi_set_otg_flags(struct usb_phy *phy)
  43 {
  44         unsigned int flags = ULPI_OTG_CTRL_DP_PULLDOWN |
  45                              ULPI_OTG_CTRL_DM_PULLDOWN;
  46 
  47         if (phy->flags & ULPI_OTG_ID_PULLUP)
  48                 flags |= ULPI_OTG_CTRL_ID_PULLUP;
  49 
  50         /*
  51          * ULPI Specification rev.1.1 default
  52          * for Dp/DmPulldown is enabled.
  53          */
  54         if (phy->flags & ULPI_OTG_DP_PULLDOWN_DIS)
  55                 flags &= ~ULPI_OTG_CTRL_DP_PULLDOWN;
  56 
  57         if (phy->flags & ULPI_OTG_DM_PULLDOWN_DIS)
  58                 flags &= ~ULPI_OTG_CTRL_DM_PULLDOWN;
  59 
  60         if (phy->flags & ULPI_OTG_EXTVBUSIND)
  61                 flags |= ULPI_OTG_CTRL_EXTVBUSIND;
  62 
  63         return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
  64 }
  65 
  66 static int ulpi_set_fc_flags(struct usb_phy *phy)
  67 {
  68         unsigned int flags = 0;
  69 
  70         /*
  71          * ULPI Specification rev.1.1 default
  72          * for XcvrSelect is Full Speed.
  73          */
  74         if (phy->flags & ULPI_FC_HS)
  75                 flags |= ULPI_FUNC_CTRL_HIGH_SPEED;
  76         else if (phy->flags & ULPI_FC_LS)
  77                 flags |= ULPI_FUNC_CTRL_LOW_SPEED;
  78         else if (phy->flags & ULPI_FC_FS4LS)
  79                 flags |= ULPI_FUNC_CTRL_FS4LS;
  80         else
  81                 flags |= ULPI_FUNC_CTRL_FULL_SPEED;
  82 
  83         if (phy->flags & ULPI_FC_TERMSEL)
  84                 flags |= ULPI_FUNC_CTRL_TERMSELECT;
  85 
  86         /*
  87          * ULPI Specification rev.1.1 default
  88          * for OpMode is Normal Operation.
  89          */
  90         if (phy->flags & ULPI_FC_OP_NODRV)
  91                 flags |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
  92         else if (phy->flags & ULPI_FC_OP_DIS_NRZI)
  93                 flags |= ULPI_FUNC_CTRL_OPMODE_DISABLE_NRZI;
  94         else if (phy->flags & ULPI_FC_OP_NSYNC_NEOP)
  95                 flags |= ULPI_FUNC_CTRL_OPMODE_NOSYNC_NOEOP;
  96         else
  97                 flags |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
  98 
  99         /*
 100          * ULPI Specification rev.1.1 default
 101          * for SuspendM is Powered.
 102          */
 103         flags |= ULPI_FUNC_CTRL_SUSPENDM;
 104 
 105         return usb_phy_io_write(phy, flags, ULPI_FUNC_CTRL);
 106 }
 107 
 108 static int ulpi_set_ic_flags(struct usb_phy *phy)
 109 {
 110         unsigned int flags = 0;
 111 
 112         if (phy->flags & ULPI_IC_AUTORESUME)
 113                 flags |= ULPI_IFC_CTRL_AUTORESUME;
 114 
 115         if (phy->flags & ULPI_IC_EXTVBUS_INDINV)
 116                 flags |= ULPI_IFC_CTRL_EXTERNAL_VBUS;
 117 
 118         if (phy->flags & ULPI_IC_IND_PASSTHRU)
 119                 flags |= ULPI_IFC_CTRL_PASSTHRU;
 120 
 121         if (phy->flags & ULPI_IC_PROTECT_DIS)
 122                 flags |= ULPI_IFC_CTRL_PROTECT_IFC_DISABLE;
 123 
 124         return usb_phy_io_write(phy, flags, ULPI_IFC_CTRL);
 125 }
 126 
 127 static int ulpi_set_flags(struct usb_phy *phy)
 128 {
 129         int ret;
 130 
 131         ret = ulpi_set_otg_flags(phy);
 132         if (ret)
 133                 return ret;
 134 
 135         ret = ulpi_set_ic_flags(phy);
 136         if (ret)
 137                 return ret;
 138 
 139         return ulpi_set_fc_flags(phy);
 140 }
 141 
 142 static int ulpi_check_integrity(struct usb_phy *phy)
 143 {
 144         int ret, i;
 145         unsigned int val = 0x55;
 146 
 147         for (i = 0; i < 2; i++) {
 148                 ret = usb_phy_io_write(phy, val, ULPI_SCRATCH);
 149                 if (ret < 0)
 150                         return ret;
 151 
 152                 ret = usb_phy_io_read(phy, ULPI_SCRATCH);
 153                 if (ret < 0)
 154                         return ret;
 155 
 156                 if (ret != val) {
 157                         pr_err("ULPI integrity check: failed!");
 158                         return -ENODEV;
 159                 }
 160                 val = val << 1;
 161         }
 162 
 163         pr_info("ULPI integrity check: passed.\n");
 164 
 165         return 0;
 166 }
 167 
 168 static int ulpi_init(struct usb_phy *phy)
 169 {
 170         int i, vid, pid, ret;
 171         u32 ulpi_id = 0;
 172 
 173         for (i = 0; i < 4; i++) {
 174                 ret = usb_phy_io_read(phy, ULPI_PRODUCT_ID_HIGH - i);
 175                 if (ret < 0)
 176                         return ret;
 177                 ulpi_id = (ulpi_id << 8) | ret;
 178         }
 179         vid = ulpi_id & 0xffff;
 180         pid = ulpi_id >> 16;
 181 
 182         pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
 183 
 184         for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++) {
 185                 if (ulpi_ids[i].id == ULPI_ID(vid, pid)) {
 186                         pr_info("Found %s ULPI transceiver.\n",
 187                                 ulpi_ids[i].name);
 188                         break;
 189                 }
 190         }
 191 
 192         ret = ulpi_check_integrity(phy);
 193         if (ret)
 194                 return ret;
 195 
 196         return ulpi_set_flags(phy);
 197 }
 198 
 199 static int ulpi_set_host(struct usb_otg *otg, struct usb_bus *host)
 200 {
 201         struct usb_phy *phy = otg->usb_phy;
 202         unsigned int flags = usb_phy_io_read(phy, ULPI_IFC_CTRL);
 203 
 204         if (!host) {
 205                 otg->host = NULL;
 206                 return 0;
 207         }
 208 
 209         otg->host = host;
 210 
 211         flags &= ~(ULPI_IFC_CTRL_6_PIN_SERIAL_MODE |
 212                    ULPI_IFC_CTRL_3_PIN_SERIAL_MODE |
 213                    ULPI_IFC_CTRL_CARKITMODE);
 214 
 215         if (phy->flags & ULPI_IC_6PIN_SERIAL)
 216                 flags |= ULPI_IFC_CTRL_6_PIN_SERIAL_MODE;
 217         else if (phy->flags & ULPI_IC_3PIN_SERIAL)
 218                 flags |= ULPI_IFC_CTRL_3_PIN_SERIAL_MODE;
 219         else if (phy->flags & ULPI_IC_CARKIT)
 220                 flags |= ULPI_IFC_CTRL_CARKITMODE;
 221 
 222         return usb_phy_io_write(phy, flags, ULPI_IFC_CTRL);
 223 }
 224 
 225 static int ulpi_set_vbus(struct usb_otg *otg, bool on)
 226 {
 227         struct usb_phy *phy = otg->usb_phy;
 228         unsigned int flags = usb_phy_io_read(phy, ULPI_OTG_CTRL);
 229 
 230         flags &= ~(ULPI_OTG_CTRL_DRVVBUS | ULPI_OTG_CTRL_DRVVBUS_EXT);
 231 
 232         if (on) {
 233                 if (phy->flags & ULPI_OTG_DRVVBUS)
 234                         flags |= ULPI_OTG_CTRL_DRVVBUS;
 235 
 236                 if (phy->flags & ULPI_OTG_DRVVBUS_EXT)
 237                         flags |= ULPI_OTG_CTRL_DRVVBUS_EXT;
 238         }
 239 
 240         return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
 241 }
 242 
 243 struct usb_phy *
 244 otg_ulpi_create(struct usb_phy_io_ops *ops,
 245                 unsigned int flags)
 246 {
 247         struct usb_phy *phy;
 248         struct usb_otg *otg;
 249 
 250         phy = kzalloc(sizeof(*phy), GFP_KERNEL);
 251         if (!phy)
 252                 return NULL;
 253 
 254         otg = kzalloc(sizeof(*otg), GFP_KERNEL);
 255         if (!otg) {
 256                 kfree(phy);
 257                 return NULL;
 258         }
 259 
 260         phy->label      = "ULPI";
 261         phy->flags      = flags;
 262         phy->io_ops     = ops;
 263         phy->otg        = otg;
 264         phy->init       = ulpi_init;
 265 
 266         otg->usb_phy    = phy;
 267         otg->set_host   = ulpi_set_host;
 268         otg->set_vbus   = ulpi_set_vbus;
 269 
 270         return phy;
 271 }
 272 EXPORT_SYMBOL_GPL(otg_ulpi_create);
 273 

/* [<][>][^][v][top][bottom][index][help] */