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(x: phy, val: 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(x: phy, val: 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(x: phy, val: 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(x: phy, val, ULPI_SCRATCH); |
149 | if (ret < 0) |
150 | return ret; |
151 | |
152 | ret = usb_phy_io_read(x: 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(x: 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(x: 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(x: phy, val: 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(x: 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(x: phy, val: flags, ULPI_OTG_CTRL); |
241 | } |
242 | |
243 | static void otg_ulpi_init(struct usb_phy *phy, struct usb_otg *otg, |
244 | struct usb_phy_io_ops *ops, |
245 | unsigned int flags) |
246 | { |
247 | phy->label = "ULPI" ; |
248 | phy->flags = flags; |
249 | phy->io_ops = ops; |
250 | phy->otg = otg; |
251 | phy->init = ulpi_init; |
252 | |
253 | otg->usb_phy = phy; |
254 | otg->set_host = ulpi_set_host; |
255 | otg->set_vbus = ulpi_set_vbus; |
256 | } |
257 | |
258 | struct usb_phy * |
259 | otg_ulpi_create(struct usb_phy_io_ops *ops, |
260 | unsigned int flags) |
261 | { |
262 | struct usb_phy *phy; |
263 | struct usb_otg *otg; |
264 | |
265 | phy = kzalloc(size: sizeof(*phy), GFP_KERNEL); |
266 | if (!phy) |
267 | return NULL; |
268 | |
269 | otg = kzalloc(size: sizeof(*otg), GFP_KERNEL); |
270 | if (!otg) { |
271 | kfree(objp: phy); |
272 | return NULL; |
273 | } |
274 | |
275 | otg_ulpi_init(phy, otg, ops, flags); |
276 | |
277 | return phy; |
278 | } |
279 | EXPORT_SYMBOL_GPL(otg_ulpi_create); |
280 | |
281 | struct usb_phy * |
282 | devm_otg_ulpi_create(struct device *dev, |
283 | struct usb_phy_io_ops *ops, |
284 | unsigned int flags) |
285 | { |
286 | struct usb_phy *phy; |
287 | struct usb_otg *otg; |
288 | |
289 | phy = devm_kzalloc(dev, size: sizeof(*phy), GFP_KERNEL); |
290 | if (!phy) |
291 | return NULL; |
292 | |
293 | otg = devm_kzalloc(dev, size: sizeof(*otg), GFP_KERNEL); |
294 | if (!otg) { |
295 | devm_kfree(dev, p: phy); |
296 | return NULL; |
297 | } |
298 | |
299 | otg_ulpi_init(phy, otg, ops, flags); |
300 | |
301 | return phy; |
302 | } |
303 | EXPORT_SYMBOL_GPL(devm_otg_ulpi_create); |
304 | |