1 // SPDX-License-Identifier: GPL-2.0+
3 * Generic ULPI USB transceiver support
5 * Copyright (C) 2009 Daniel Mack <daniel@caiaq.de>
7 * Based on sources from
9 * Sascha Hauer <s.hauer@pengutronix.de>
10 * Freescale Semiconductors
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>
26 #define ULPI_ID(vendor, product) (((vendor) << 16) | (product))
27 #define ULPI_INFO(_id, _name) \
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"),
42 static int ulpi_set_otg_flags(struct usb_phy
*phy
)
44 unsigned int flags
= ULPI_OTG_CTRL_DP_PULLDOWN
|
45 ULPI_OTG_CTRL_DM_PULLDOWN
;
47 if (phy
->flags
& ULPI_OTG_ID_PULLUP
)
48 flags
|= ULPI_OTG_CTRL_ID_PULLUP
;
51 * ULPI Specification rev.1.1 default
52 * for Dp/DmPulldown is enabled.
54 if (phy
->flags
& ULPI_OTG_DP_PULLDOWN_DIS
)
55 flags
&= ~ULPI_OTG_CTRL_DP_PULLDOWN
;
57 if (phy
->flags
& ULPI_OTG_DM_PULLDOWN_DIS
)
58 flags
&= ~ULPI_OTG_CTRL_DM_PULLDOWN
;
60 if (phy
->flags
& ULPI_OTG_EXTVBUSIND
)
61 flags
|= ULPI_OTG_CTRL_EXTVBUSIND
;
63 return usb_phy_io_write(phy
, flags
, ULPI_OTG_CTRL
);
66 static int ulpi_set_fc_flags(struct usb_phy
*phy
)
68 unsigned int flags
= 0;
71 * ULPI Specification rev.1.1 default
72 * for XcvrSelect is Full Speed.
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
;
81 flags
|= ULPI_FUNC_CTRL_FULL_SPEED
;
83 if (phy
->flags
& ULPI_FC_TERMSEL
)
84 flags
|= ULPI_FUNC_CTRL_TERMSELECT
;
87 * ULPI Specification rev.1.1 default
88 * for OpMode is Normal Operation.
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
;
97 flags
|= ULPI_FUNC_CTRL_OPMODE_NORMAL
;
100 * ULPI Specification rev.1.1 default
101 * for SuspendM is Powered.
103 flags
|= ULPI_FUNC_CTRL_SUSPENDM
;
105 return usb_phy_io_write(phy
, flags
, ULPI_FUNC_CTRL
);
108 static int ulpi_set_ic_flags(struct usb_phy
*phy
)
110 unsigned int flags
= 0;
112 if (phy
->flags
& ULPI_IC_AUTORESUME
)
113 flags
|= ULPI_IFC_CTRL_AUTORESUME
;
115 if (phy
->flags
& ULPI_IC_EXTVBUS_INDINV
)
116 flags
|= ULPI_IFC_CTRL_EXTERNAL_VBUS
;
118 if (phy
->flags
& ULPI_IC_IND_PASSTHRU
)
119 flags
|= ULPI_IFC_CTRL_PASSTHRU
;
121 if (phy
->flags
& ULPI_IC_PROTECT_DIS
)
122 flags
|= ULPI_IFC_CTRL_PROTECT_IFC_DISABLE
;
124 return usb_phy_io_write(phy
, flags
, ULPI_IFC_CTRL
);
127 static int ulpi_set_flags(struct usb_phy
*phy
)
131 ret
= ulpi_set_otg_flags(phy
);
135 ret
= ulpi_set_ic_flags(phy
);
139 return ulpi_set_fc_flags(phy
);
142 static int ulpi_check_integrity(struct usb_phy
*phy
)
145 unsigned int val
= 0x55;
147 for (i
= 0; i
< 2; i
++) {
148 ret
= usb_phy_io_write(phy
, val
, ULPI_SCRATCH
);
152 ret
= usb_phy_io_read(phy
, ULPI_SCRATCH
);
157 pr_err("ULPI integrity check: failed!");
163 pr_info("ULPI integrity check: passed.\n");
168 static int ulpi_init(struct usb_phy
*phy
)
170 int i
, vid
, pid
, ret
;
173 for (i
= 0; i
< 4; i
++) {
174 ret
= usb_phy_io_read(phy
, ULPI_PRODUCT_ID_HIGH
- i
);
177 ulpi_id
= (ulpi_id
<< 8) | ret
;
179 vid
= ulpi_id
& 0xffff;
182 pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid
, pid
);
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",
192 ret
= ulpi_check_integrity(phy
);
196 return ulpi_set_flags(phy
);
199 static int ulpi_set_host(struct usb_otg
*otg
, struct usb_bus
*host
)
201 struct usb_phy
*phy
= otg
->usb_phy
;
202 unsigned int flags
= usb_phy_io_read(phy
, ULPI_IFC_CTRL
);
211 flags
&= ~(ULPI_IFC_CTRL_6_PIN_SERIAL_MODE
|
212 ULPI_IFC_CTRL_3_PIN_SERIAL_MODE
|
213 ULPI_IFC_CTRL_CARKITMODE
);
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
;
222 return usb_phy_io_write(phy
, flags
, ULPI_IFC_CTRL
);
225 static int ulpi_set_vbus(struct usb_otg
*otg
, bool on
)
227 struct usb_phy
*phy
= otg
->usb_phy
;
228 unsigned int flags
= usb_phy_io_read(phy
, ULPI_OTG_CTRL
);
230 flags
&= ~(ULPI_OTG_CTRL_DRVVBUS
| ULPI_OTG_CTRL_DRVVBUS_EXT
);
233 if (phy
->flags
& ULPI_OTG_DRVVBUS
)
234 flags
|= ULPI_OTG_CTRL_DRVVBUS
;
236 if (phy
->flags
& ULPI_OTG_DRVVBUS_EXT
)
237 flags
|= ULPI_OTG_CTRL_DRVVBUS_EXT
;
240 return usb_phy_io_write(phy
, flags
, ULPI_OTG_CTRL
);
244 otg_ulpi_create(struct usb_phy_io_ops
*ops
,
250 phy
= kzalloc(sizeof(*phy
), GFP_KERNEL
);
254 otg
= kzalloc(sizeof(*otg
), GFP_KERNEL
);
264 phy
->init
= ulpi_init
;
267 otg
->set_host
= ulpi_set_host
;
268 otg
->set_vbus
= ulpi_set_vbus
;
272 EXPORT_SYMBOL_GPL(otg_ulpi_create
);