xref: /linux/drivers/usb/phy/phy-ulpi.c (revision 6eb2fb3170549737207974c2c6ad34bcc2f3025e)
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 };
51 
52 static int ulpi_set_otg_flags(struct usb_phy *phy)
53 {
54 	unsigned int flags = ULPI_OTG_CTRL_DP_PULLDOWN |
55 			     ULPI_OTG_CTRL_DM_PULLDOWN;
56 
57 	if (phy->flags & ULPI_OTG_ID_PULLUP)
58 		flags |= ULPI_OTG_CTRL_ID_PULLUP;
59 
60 	/*
61 	 * ULPI Specification rev.1.1 default
62 	 * for Dp/DmPulldown is enabled.
63 	 */
64 	if (phy->flags & ULPI_OTG_DP_PULLDOWN_DIS)
65 		flags &= ~ULPI_OTG_CTRL_DP_PULLDOWN;
66 
67 	if (phy->flags & ULPI_OTG_DM_PULLDOWN_DIS)
68 		flags &= ~ULPI_OTG_CTRL_DM_PULLDOWN;
69 
70 	if (phy->flags & ULPI_OTG_EXTVBUSIND)
71 		flags |= ULPI_OTG_CTRL_EXTVBUSIND;
72 
73 	return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
74 }
75 
76 static int ulpi_set_fc_flags(struct usb_phy *phy)
77 {
78 	unsigned int flags = 0;
79 
80 	/*
81 	 * ULPI Specification rev.1.1 default
82 	 * for XcvrSelect is Full Speed.
83 	 */
84 	if (phy->flags & ULPI_FC_HS)
85 		flags |= ULPI_FUNC_CTRL_HIGH_SPEED;
86 	else if (phy->flags & ULPI_FC_LS)
87 		flags |= ULPI_FUNC_CTRL_LOW_SPEED;
88 	else if (phy->flags & ULPI_FC_FS4LS)
89 		flags |= ULPI_FUNC_CTRL_FS4LS;
90 	else
91 		flags |= ULPI_FUNC_CTRL_FULL_SPEED;
92 
93 	if (phy->flags & ULPI_FC_TERMSEL)
94 		flags |= ULPI_FUNC_CTRL_TERMSELECT;
95 
96 	/*
97 	 * ULPI Specification rev.1.1 default
98 	 * for OpMode is Normal Operation.
99 	 */
100 	if (phy->flags & ULPI_FC_OP_NODRV)
101 		flags |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
102 	else if (phy->flags & ULPI_FC_OP_DIS_NRZI)
103 		flags |= ULPI_FUNC_CTRL_OPMODE_DISABLE_NRZI;
104 	else if (phy->flags & ULPI_FC_OP_NSYNC_NEOP)
105 		flags |= ULPI_FUNC_CTRL_OPMODE_NOSYNC_NOEOP;
106 	else
107 		flags |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
108 
109 	/*
110 	 * ULPI Specification rev.1.1 default
111 	 * for SuspendM is Powered.
112 	 */
113 	flags |= ULPI_FUNC_CTRL_SUSPENDM;
114 
115 	return usb_phy_io_write(phy, flags, ULPI_FUNC_CTRL);
116 }
117 
118 static int ulpi_set_ic_flags(struct usb_phy *phy)
119 {
120 	unsigned int flags = 0;
121 
122 	if (phy->flags & ULPI_IC_AUTORESUME)
123 		flags |= ULPI_IFC_CTRL_AUTORESUME;
124 
125 	if (phy->flags & ULPI_IC_EXTVBUS_INDINV)
126 		flags |= ULPI_IFC_CTRL_EXTERNAL_VBUS;
127 
128 	if (phy->flags & ULPI_IC_IND_PASSTHRU)
129 		flags |= ULPI_IFC_CTRL_PASSTHRU;
130 
131 	if (phy->flags & ULPI_IC_PROTECT_DIS)
132 		flags |= ULPI_IFC_CTRL_PROTECT_IFC_DISABLE;
133 
134 	return usb_phy_io_write(phy, flags, ULPI_IFC_CTRL);
135 }
136 
137 static int ulpi_set_flags(struct usb_phy *phy)
138 {
139 	int ret;
140 
141 	ret = ulpi_set_otg_flags(phy);
142 	if (ret)
143 		return ret;
144 
145 	ret = ulpi_set_ic_flags(phy);
146 	if (ret)
147 		return ret;
148 
149 	return ulpi_set_fc_flags(phy);
150 }
151 
152 static int ulpi_check_integrity(struct usb_phy *phy)
153 {
154 	int ret, i;
155 	unsigned int val = 0x55;
156 
157 	for (i = 0; i < 2; i++) {
158 		ret = usb_phy_io_write(phy, val, ULPI_SCRATCH);
159 		if (ret < 0)
160 			return ret;
161 
162 		ret = usb_phy_io_read(phy, ULPI_SCRATCH);
163 		if (ret < 0)
164 			return ret;
165 
166 		if (ret != val) {
167 			pr_err("ULPI integrity check: failed!");
168 			return -ENODEV;
169 		}
170 		val = val << 1;
171 	}
172 
173 	pr_info("ULPI integrity check: passed.\n");
174 
175 	return 0;
176 }
177 
178 static int ulpi_init(struct usb_phy *phy)
179 {
180 	int i, vid, pid, ret;
181 	u32 ulpi_id = 0;
182 
183 	for (i = 0; i < 4; i++) {
184 		ret = usb_phy_io_read(phy, ULPI_PRODUCT_ID_HIGH - i);
185 		if (ret < 0)
186 			return ret;
187 		ulpi_id = (ulpi_id << 8) | ret;
188 	}
189 	vid = ulpi_id & 0xffff;
190 	pid = ulpi_id >> 16;
191 
192 	pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
193 
194 	for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++) {
195 		if (ulpi_ids[i].id == ULPI_ID(vid, pid)) {
196 			pr_info("Found %s ULPI transceiver.\n",
197 				ulpi_ids[i].name);
198 			break;
199 		}
200 	}
201 
202 	ret = ulpi_check_integrity(phy);
203 	if (ret)
204 		return ret;
205 
206 	return ulpi_set_flags(phy);
207 }
208 
209 static int ulpi_set_host(struct usb_otg *otg, struct usb_bus *host)
210 {
211 	struct usb_phy *phy = otg->phy;
212 	unsigned int flags = usb_phy_io_read(phy, ULPI_IFC_CTRL);
213 
214 	if (!host) {
215 		otg->host = NULL;
216 		return 0;
217 	}
218 
219 	otg->host = host;
220 
221 	flags &= ~(ULPI_IFC_CTRL_6_PIN_SERIAL_MODE |
222 		   ULPI_IFC_CTRL_3_PIN_SERIAL_MODE |
223 		   ULPI_IFC_CTRL_CARKITMODE);
224 
225 	if (phy->flags & ULPI_IC_6PIN_SERIAL)
226 		flags |= ULPI_IFC_CTRL_6_PIN_SERIAL_MODE;
227 	else if (phy->flags & ULPI_IC_3PIN_SERIAL)
228 		flags |= ULPI_IFC_CTRL_3_PIN_SERIAL_MODE;
229 	else if (phy->flags & ULPI_IC_CARKIT)
230 		flags |= ULPI_IFC_CTRL_CARKITMODE;
231 
232 	return usb_phy_io_write(phy, flags, ULPI_IFC_CTRL);
233 }
234 
235 static int ulpi_set_vbus(struct usb_otg *otg, bool on)
236 {
237 	struct usb_phy *phy = otg->phy;
238 	unsigned int flags = usb_phy_io_read(phy, ULPI_OTG_CTRL);
239 
240 	flags &= ~(ULPI_OTG_CTRL_DRVVBUS | ULPI_OTG_CTRL_DRVVBUS_EXT);
241 
242 	if (on) {
243 		if (phy->flags & ULPI_OTG_DRVVBUS)
244 			flags |= ULPI_OTG_CTRL_DRVVBUS;
245 
246 		if (phy->flags & ULPI_OTG_DRVVBUS_EXT)
247 			flags |= ULPI_OTG_CTRL_DRVVBUS_EXT;
248 	}
249 
250 	return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
251 }
252 
253 struct usb_phy *
254 otg_ulpi_create(struct usb_phy_io_ops *ops,
255 		unsigned int flags)
256 {
257 	struct usb_phy *phy;
258 	struct usb_otg *otg;
259 
260 	phy = kzalloc(sizeof(*phy), GFP_KERNEL);
261 	if (!phy)
262 		return NULL;
263 
264 	otg = kzalloc(sizeof(*otg), GFP_KERNEL);
265 	if (!otg) {
266 		kfree(phy);
267 		return NULL;
268 	}
269 
270 	phy->label	= "ULPI";
271 	phy->flags	= flags;
272 	phy->io_ops	= ops;
273 	phy->otg	= otg;
274 	phy->init	= ulpi_init;
275 
276 	otg->phy	= phy;
277 	otg->set_host	= ulpi_set_host;
278 	otg->set_vbus	= ulpi_set_vbus;
279 
280 	return phy;
281 }
282 EXPORT_SYMBOL_GPL(otg_ulpi_create);
283 
284