Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Generic ULPI USB transceiver support
0004  *
0005  * Copyright (C) 2009 Daniel Mack <daniel@caiaq.de>
0006  *
0007  * Based on sources from
0008  *
0009  *   Sascha Hauer <s.hauer@pengutronix.de>
0010  *   Freescale Semiconductors
0011  */
0012 
0013 #include <linux/kernel.h>
0014 #include <linux/slab.h>
0015 #include <linux/export.h>
0016 #include <linux/usb.h>
0017 #include <linux/usb/otg.h>
0018 #include <linux/usb/ulpi.h>
0019 
0020 
0021 struct ulpi_info {
0022     unsigned int    id;
0023     char        *name;
0024 };
0025 
0026 #define ULPI_ID(vendor, product) (((vendor) << 16) | (product))
0027 #define ULPI_INFO(_id, _name)       \
0028     {               \
0029         .id = (_id),    \
0030         .name   = (_name),  \
0031     }
0032 
0033 /* ULPI hardcoded IDs, used for probing */
0034 static struct ulpi_info ulpi_ids[] = {
0035     ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"),
0036     ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"),
0037     ULPI_INFO(ULPI_ID(0x0424, 0x0007), "SMSC USB3320"),
0038     ULPI_INFO(ULPI_ID(0x0424, 0x0009), "SMSC USB334x"),
0039     ULPI_INFO(ULPI_ID(0x0451, 0x1507), "TI TUSB1210"),
0040 };
0041 
0042 static int ulpi_set_otg_flags(struct usb_phy *phy)
0043 {
0044     unsigned int flags = ULPI_OTG_CTRL_DP_PULLDOWN |
0045                  ULPI_OTG_CTRL_DM_PULLDOWN;
0046 
0047     if (phy->flags & ULPI_OTG_ID_PULLUP)
0048         flags |= ULPI_OTG_CTRL_ID_PULLUP;
0049 
0050     /*
0051      * ULPI Specification rev.1.1 default
0052      * for Dp/DmPulldown is enabled.
0053      */
0054     if (phy->flags & ULPI_OTG_DP_PULLDOWN_DIS)
0055         flags &= ~ULPI_OTG_CTRL_DP_PULLDOWN;
0056 
0057     if (phy->flags & ULPI_OTG_DM_PULLDOWN_DIS)
0058         flags &= ~ULPI_OTG_CTRL_DM_PULLDOWN;
0059 
0060     if (phy->flags & ULPI_OTG_EXTVBUSIND)
0061         flags |= ULPI_OTG_CTRL_EXTVBUSIND;
0062 
0063     return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
0064 }
0065 
0066 static int ulpi_set_fc_flags(struct usb_phy *phy)
0067 {
0068     unsigned int flags = 0;
0069 
0070     /*
0071      * ULPI Specification rev.1.1 default
0072      * for XcvrSelect is Full Speed.
0073      */
0074     if (phy->flags & ULPI_FC_HS)
0075         flags |= ULPI_FUNC_CTRL_HIGH_SPEED;
0076     else if (phy->flags & ULPI_FC_LS)
0077         flags |= ULPI_FUNC_CTRL_LOW_SPEED;
0078     else if (phy->flags & ULPI_FC_FS4LS)
0079         flags |= ULPI_FUNC_CTRL_FS4LS;
0080     else
0081         flags |= ULPI_FUNC_CTRL_FULL_SPEED;
0082 
0083     if (phy->flags & ULPI_FC_TERMSEL)
0084         flags |= ULPI_FUNC_CTRL_TERMSELECT;
0085 
0086     /*
0087      * ULPI Specification rev.1.1 default
0088      * for OpMode is Normal Operation.
0089      */
0090     if (phy->flags & ULPI_FC_OP_NODRV)
0091         flags |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
0092     else if (phy->flags & ULPI_FC_OP_DIS_NRZI)
0093         flags |= ULPI_FUNC_CTRL_OPMODE_DISABLE_NRZI;
0094     else if (phy->flags & ULPI_FC_OP_NSYNC_NEOP)
0095         flags |= ULPI_FUNC_CTRL_OPMODE_NOSYNC_NOEOP;
0096     else
0097         flags |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
0098 
0099     /*
0100      * ULPI Specification rev.1.1 default
0101      * for SuspendM is Powered.
0102      */
0103     flags |= ULPI_FUNC_CTRL_SUSPENDM;
0104 
0105     return usb_phy_io_write(phy, flags, ULPI_FUNC_CTRL);
0106 }
0107 
0108 static int ulpi_set_ic_flags(struct usb_phy *phy)
0109 {
0110     unsigned int flags = 0;
0111 
0112     if (phy->flags & ULPI_IC_AUTORESUME)
0113         flags |= ULPI_IFC_CTRL_AUTORESUME;
0114 
0115     if (phy->flags & ULPI_IC_EXTVBUS_INDINV)
0116         flags |= ULPI_IFC_CTRL_EXTERNAL_VBUS;
0117 
0118     if (phy->flags & ULPI_IC_IND_PASSTHRU)
0119         flags |= ULPI_IFC_CTRL_PASSTHRU;
0120 
0121     if (phy->flags & ULPI_IC_PROTECT_DIS)
0122         flags |= ULPI_IFC_CTRL_PROTECT_IFC_DISABLE;
0123 
0124     return usb_phy_io_write(phy, flags, ULPI_IFC_CTRL);
0125 }
0126 
0127 static int ulpi_set_flags(struct usb_phy *phy)
0128 {
0129     int ret;
0130 
0131     ret = ulpi_set_otg_flags(phy);
0132     if (ret)
0133         return ret;
0134 
0135     ret = ulpi_set_ic_flags(phy);
0136     if (ret)
0137         return ret;
0138 
0139     return ulpi_set_fc_flags(phy);
0140 }
0141 
0142 static int ulpi_check_integrity(struct usb_phy *phy)
0143 {
0144     int ret, i;
0145     unsigned int val = 0x55;
0146 
0147     for (i = 0; i < 2; i++) {
0148         ret = usb_phy_io_write(phy, val, ULPI_SCRATCH);
0149         if (ret < 0)
0150             return ret;
0151 
0152         ret = usb_phy_io_read(phy, ULPI_SCRATCH);
0153         if (ret < 0)
0154             return ret;
0155 
0156         if (ret != val) {
0157             pr_err("ULPI integrity check: failed!");
0158             return -ENODEV;
0159         }
0160         val = val << 1;
0161     }
0162 
0163     pr_info("ULPI integrity check: passed.\n");
0164 
0165     return 0;
0166 }
0167 
0168 static int ulpi_init(struct usb_phy *phy)
0169 {
0170     int i, vid, pid, ret;
0171     u32 ulpi_id = 0;
0172 
0173     for (i = 0; i < 4; i++) {
0174         ret = usb_phy_io_read(phy, ULPI_PRODUCT_ID_HIGH - i);
0175         if (ret < 0)
0176             return ret;
0177         ulpi_id = (ulpi_id << 8) | ret;
0178     }
0179     vid = ulpi_id & 0xffff;
0180     pid = ulpi_id >> 16;
0181 
0182     pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
0183 
0184     for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++) {
0185         if (ulpi_ids[i].id == ULPI_ID(vid, pid)) {
0186             pr_info("Found %s ULPI transceiver.\n",
0187                 ulpi_ids[i].name);
0188             break;
0189         }
0190     }
0191 
0192     ret = ulpi_check_integrity(phy);
0193     if (ret)
0194         return ret;
0195 
0196     return ulpi_set_flags(phy);
0197 }
0198 
0199 static int ulpi_set_host(struct usb_otg *otg, struct usb_bus *host)
0200 {
0201     struct usb_phy *phy = otg->usb_phy;
0202     unsigned int flags = usb_phy_io_read(phy, ULPI_IFC_CTRL);
0203 
0204     if (!host) {
0205         otg->host = NULL;
0206         return 0;
0207     }
0208 
0209     otg->host = host;
0210 
0211     flags &= ~(ULPI_IFC_CTRL_6_PIN_SERIAL_MODE |
0212            ULPI_IFC_CTRL_3_PIN_SERIAL_MODE |
0213            ULPI_IFC_CTRL_CARKITMODE);
0214 
0215     if (phy->flags & ULPI_IC_6PIN_SERIAL)
0216         flags |= ULPI_IFC_CTRL_6_PIN_SERIAL_MODE;
0217     else if (phy->flags & ULPI_IC_3PIN_SERIAL)
0218         flags |= ULPI_IFC_CTRL_3_PIN_SERIAL_MODE;
0219     else if (phy->flags & ULPI_IC_CARKIT)
0220         flags |= ULPI_IFC_CTRL_CARKITMODE;
0221 
0222     return usb_phy_io_write(phy, flags, ULPI_IFC_CTRL);
0223 }
0224 
0225 static int ulpi_set_vbus(struct usb_otg *otg, bool on)
0226 {
0227     struct usb_phy *phy = otg->usb_phy;
0228     unsigned int flags = usb_phy_io_read(phy, ULPI_OTG_CTRL);
0229 
0230     flags &= ~(ULPI_OTG_CTRL_DRVVBUS | ULPI_OTG_CTRL_DRVVBUS_EXT);
0231 
0232     if (on) {
0233         if (phy->flags & ULPI_OTG_DRVVBUS)
0234             flags |= ULPI_OTG_CTRL_DRVVBUS;
0235 
0236         if (phy->flags & ULPI_OTG_DRVVBUS_EXT)
0237             flags |= ULPI_OTG_CTRL_DRVVBUS_EXT;
0238     }
0239 
0240     return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
0241 }
0242 
0243 static void otg_ulpi_init(struct usb_phy *phy, struct usb_otg *otg,
0244               struct usb_phy_io_ops *ops,
0245               unsigned int flags)
0246 {
0247     phy->label  = "ULPI";
0248     phy->flags  = flags;
0249     phy->io_ops = ops;
0250     phy->otg    = otg;
0251     phy->init   = ulpi_init;
0252 
0253     otg->usb_phy    = phy;
0254     otg->set_host   = ulpi_set_host;
0255     otg->set_vbus   = ulpi_set_vbus;
0256 }
0257 
0258 struct usb_phy *
0259 otg_ulpi_create(struct usb_phy_io_ops *ops,
0260         unsigned int flags)
0261 {
0262     struct usb_phy *phy;
0263     struct usb_otg *otg;
0264 
0265     phy = kzalloc(sizeof(*phy), GFP_KERNEL);
0266     if (!phy)
0267         return NULL;
0268 
0269     otg = kzalloc(sizeof(*otg), GFP_KERNEL);
0270     if (!otg) {
0271         kfree(phy);
0272         return NULL;
0273     }
0274 
0275     otg_ulpi_init(phy, otg, ops, flags);
0276 
0277     return phy;
0278 }
0279 EXPORT_SYMBOL_GPL(otg_ulpi_create);
0280 
0281 struct usb_phy *
0282 devm_otg_ulpi_create(struct device *dev,
0283              struct usb_phy_io_ops *ops,
0284              unsigned int flags)
0285 {
0286     struct usb_phy *phy;
0287     struct usb_otg *otg;
0288 
0289     phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
0290     if (!phy)
0291         return NULL;
0292 
0293     otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL);
0294     if (!otg) {
0295         devm_kfree(dev, phy);
0296         return NULL;
0297     }
0298 
0299     otg_ulpi_init(phy, otg, ops, flags);
0300 
0301     return phy;
0302 }
0303 EXPORT_SYMBOL_GPL(devm_otg_ulpi_create);