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