Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
466b1516 | 2 | /* |
1c14905e HK |
3 | * tusb1210.c - TUSB1210 USB ULPI PHY driver |
4 | * | |
5 | * Copyright (C) 2015 Intel Corporation | |
6 | * | |
7 | * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com> | |
1c14905e HK |
8 | */ |
9 | #include <linux/module.h> | |
eb445a15 | 10 | #include <linux/bitfield.h> |
df37c998 | 11 | #include <linux/delay.h> |
1c14905e | 12 | #include <linux/ulpi/driver.h> |
54fe3088 | 13 | #include <linux/ulpi/regs.h> |
1c14905e | 14 | #include <linux/gpio/consumer.h> |
858edde0 | 15 | #include <linux/phy/ulpi_phy.h> |
48969a56 SG |
16 | #include <linux/power_supply.h> |
17 | #include <linux/workqueue.h> | |
18 | ||
19 | #define TUSB1211_POWER_CONTROL 0x3d | |
20 | #define TUSB1211_POWER_CONTROL_SET 0x3e | |
21 | #define TUSB1211_POWER_CONTROL_CLEAR 0x3f | |
22 | #define TUSB1211_POWER_CONTROL_SW_CONTROL BIT(0) | |
23 | #define TUSB1211_POWER_CONTROL_DET_COMP BIT(1) | |
24 | #define TUSB1211_POWER_CONTROL_DP_VSRC_EN BIT(6) | |
25 | ||
26 | #define TUSB1210_VENDOR_SPECIFIC2 0x80 | |
27 | #define TUSB1210_VENDOR_SPECIFIC2_IHSTX_MASK GENMASK(3, 0) | |
28 | #define TUSB1210_VENDOR_SPECIFIC2_ZHSDRV_MASK GENMASK(5, 4) | |
29 | #define TUSB1210_VENDOR_SPECIFIC2_DP_MASK BIT(6) | |
30 | ||
31 | #define TUSB1211_VENDOR_SPECIFIC3 0x85 | |
32 | #define TUSB1211_VENDOR_SPECIFIC3_SET 0x86 | |
33 | #define TUSB1211_VENDOR_SPECIFIC3_CLEAR 0x87 | |
34 | #define TUSB1211_VENDOR_SPECIFIC3_SW_USB_DET BIT(4) | |
35 | #define TUSB1211_VENDOR_SPECIFIC3_CHGD_IDP_SRC_EN BIT(6) | |
36 | ||
37 | #define TUSB1210_RESET_TIME_MS 50 | |
38 | ||
39 | #define TUSB1210_CHG_DET_MAX_RETRIES 5 | |
40 | ||
41 | /* TUSB1210 charger detection work states */ | |
42 | enum tusb1210_chg_det_state { | |
43 | TUSB1210_CHG_DET_CONNECTING, | |
44 | TUSB1210_CHG_DET_START_DET, | |
45 | TUSB1210_CHG_DET_READ_DET, | |
46 | TUSB1210_CHG_DET_FINISH_DET, | |
47 | TUSB1210_CHG_DET_CONNECTED, | |
48 | TUSB1210_CHG_DET_DISCONNECTING, | |
49 | TUSB1210_CHG_DET_DISCONNECTING_DONE, | |
50 | TUSB1210_CHG_DET_DISCONNECTED, | |
51 | }; | |
df37c998 | 52 | |
1c14905e HK |
53 | struct tusb1210 { |
54 | struct ulpi *ulpi; | |
55 | struct phy *phy; | |
56 | struct gpio_desc *gpio_reset; | |
57 | struct gpio_desc *gpio_cs; | |
48969a56 | 58 | u8 otg_ctrl; |
1c14905e | 59 | u8 vendor_specific2; |
48969a56 SG |
60 | #ifdef CONFIG_POWER_SUPPLY |
61 | enum power_supply_usb_type chg_type; | |
62 | enum tusb1210_chg_det_state chg_det_state; | |
63 | int chg_det_retries; | |
64 | struct delayed_work chg_det_work; | |
65 | struct notifier_block psy_nb; | |
66 | struct power_supply *psy; | |
67 | struct power_supply *charger; | |
68 | #endif | |
1c14905e HK |
69 | }; |
70 | ||
09a35126 HG |
71 | static int tusb1210_ulpi_write(struct tusb1210 *tusb, u8 reg, u8 val) |
72 | { | |
73 | int ret; | |
74 | ||
75 | ret = ulpi_write(tusb->ulpi, reg, val); | |
76 | if (ret) | |
77 | dev_err(&tusb->ulpi->dev, "error %d writing val 0x%02x to reg 0x%02x\n", | |
78 | ret, val, reg); | |
79 | ||
80 | return ret; | |
81 | } | |
82 | ||
83 | static int tusb1210_ulpi_read(struct tusb1210 *tusb, u8 reg, u8 *val) | |
84 | { | |
85 | int ret; | |
86 | ||
87 | ret = ulpi_read(tusb->ulpi, reg); | |
88 | if (ret >= 0) { | |
89 | *val = ret; | |
90 | ret = 0; | |
91 | } else { | |
92 | dev_err(&tusb->ulpi->dev, "error %d reading reg 0x%02x\n", ret, reg); | |
93 | } | |
94 | ||
95 | return ret; | |
96 | } | |
97 | ||
1c14905e HK |
98 | static int tusb1210_power_on(struct phy *phy) |
99 | { | |
100 | struct tusb1210 *tusb = phy_get_drvdata(phy); | |
101 | ||
102 | gpiod_set_value_cansleep(tusb->gpio_reset, 1); | |
103 | gpiod_set_value_cansleep(tusb->gpio_cs, 1); | |
104 | ||
df37c998 HG |
105 | msleep(TUSB1210_RESET_TIME_MS); |
106 | ||
1c14905e | 107 | /* Restore the optional eye diagram optimization value */ |
cb7d21b4 HG |
108 | return tusb1210_ulpi_write(tusb, TUSB1210_VENDOR_SPECIFIC2, |
109 | tusb->vendor_specific2); | |
1c14905e HK |
110 | } |
111 | ||
112 | static int tusb1210_power_off(struct phy *phy) | |
113 | { | |
114 | struct tusb1210 *tusb = phy_get_drvdata(phy); | |
115 | ||
116 | gpiod_set_value_cansleep(tusb->gpio_reset, 0); | |
117 | gpiod_set_value_cansleep(tusb->gpio_cs, 0); | |
118 | ||
119 | return 0; | |
120 | } | |
121 | ||
79a5a18a | 122 | static int tusb1210_set_mode(struct phy *phy, enum phy_mode mode, int submode) |
54fe3088 FB |
123 | { |
124 | struct tusb1210 *tusb = phy_get_drvdata(phy); | |
125 | int ret; | |
09a35126 | 126 | u8 reg; |
54fe3088 | 127 | |
09a35126 | 128 | ret = tusb1210_ulpi_read(tusb, ULPI_OTG_CTRL, ®); |
54fe3088 FB |
129 | if (ret < 0) |
130 | return ret; | |
131 | ||
132 | switch (mode) { | |
133 | case PHY_MODE_USB_HOST: | |
09a35126 | 134 | reg |= (ULPI_OTG_CTRL_DRVVBUS_EXT |
54fe3088 FB |
135 | | ULPI_OTG_CTRL_ID_PULLUP |
136 | | ULPI_OTG_CTRL_DP_PULLDOWN | |
137 | | ULPI_OTG_CTRL_DM_PULLDOWN); | |
09a35126 HG |
138 | tusb1210_ulpi_write(tusb, ULPI_OTG_CTRL, reg); |
139 | reg |= ULPI_OTG_CTRL_DRVVBUS; | |
54fe3088 FB |
140 | break; |
141 | case PHY_MODE_USB_DEVICE: | |
09a35126 | 142 | reg &= ~(ULPI_OTG_CTRL_DRVVBUS |
54fe3088 FB |
143 | | ULPI_OTG_CTRL_DP_PULLDOWN |
144 | | ULPI_OTG_CTRL_DM_PULLDOWN); | |
09a35126 HG |
145 | tusb1210_ulpi_write(tusb, ULPI_OTG_CTRL, reg); |
146 | reg &= ~ULPI_OTG_CTRL_DRVVBUS_EXT; | |
54fe3088 FB |
147 | break; |
148 | default: | |
149 | /* nothing */ | |
150 | return 0; | |
151 | } | |
152 | ||
48969a56 | 153 | tusb->otg_ctrl = reg; |
09a35126 | 154 | return tusb1210_ulpi_write(tusb, ULPI_OTG_CTRL, reg); |
54fe3088 FB |
155 | } |
156 | ||
48969a56 | 157 | #ifdef CONFIG_POWER_SUPPLY |
b541f9e5 | 158 | static const char * const tusb1210_chg_det_states[] = { |
48969a56 SG |
159 | "CHG_DET_CONNECTING", |
160 | "CHG_DET_START_DET", | |
161 | "CHG_DET_READ_DET", | |
162 | "CHG_DET_FINISH_DET", | |
163 | "CHG_DET_CONNECTED", | |
164 | "CHG_DET_DISCONNECTING", | |
165 | "CHG_DET_DISCONNECTING_DONE", | |
166 | "CHG_DET_DISCONNECTED", | |
167 | }; | |
168 | ||
169 | static void tusb1210_reset(struct tusb1210 *tusb) | |
170 | { | |
171 | gpiod_set_value_cansleep(tusb->gpio_reset, 0); | |
172 | usleep_range(200, 500); | |
173 | gpiod_set_value_cansleep(tusb->gpio_reset, 1); | |
174 | } | |
175 | ||
176 | static void tusb1210_chg_det_set_type(struct tusb1210 *tusb, | |
177 | enum power_supply_usb_type type) | |
178 | { | |
179 | dev_dbg(&tusb->ulpi->dev, "charger type: %d\n", type); | |
180 | tusb->chg_type = type; | |
181 | tusb->chg_det_retries = 0; | |
182 | power_supply_changed(tusb->psy); | |
183 | } | |
184 | ||
185 | static void tusb1210_chg_det_set_state(struct tusb1210 *tusb, | |
186 | enum tusb1210_chg_det_state new_state, | |
187 | int delay_ms) | |
188 | { | |
189 | if (delay_ms) | |
190 | dev_dbg(&tusb->ulpi->dev, "chg_det new state %s in %d ms\n", | |
191 | tusb1210_chg_det_states[new_state], delay_ms); | |
192 | ||
193 | tusb->chg_det_state = new_state; | |
194 | mod_delayed_work(system_long_wq, &tusb->chg_det_work, | |
195 | msecs_to_jiffies(delay_ms)); | |
196 | } | |
197 | ||
198 | static void tusb1210_chg_det_handle_ulpi_error(struct tusb1210 *tusb) | |
199 | { | |
200 | tusb1210_reset(tusb); | |
201 | if (tusb->chg_det_retries < TUSB1210_CHG_DET_MAX_RETRIES) { | |
202 | tusb->chg_det_retries++; | |
203 | tusb1210_chg_det_set_state(tusb, TUSB1210_CHG_DET_START_DET, | |
204 | TUSB1210_RESET_TIME_MS); | |
205 | } else { | |
206 | tusb1210_chg_det_set_state(tusb, TUSB1210_CHG_DET_FINISH_DET, | |
207 | TUSB1210_RESET_TIME_MS); | |
208 | } | |
209 | } | |
210 | ||
211 | /* | |
212 | * Boards using a TUSB121x for charger-detection have 3 power_supply class devs: | |
213 | * | |
214 | * tusb1211-charger-detect(1) -> charger -> fuel-gauge | |
215 | * | |
216 | * To determine if an USB charger is connected to the board, the online prop of | |
217 | * the charger psy needs to be read. Since the tusb1211-charger-detect psy is | |
218 | * the start of the supplier -> supplied-to chain, power_supply_am_i_supplied() | |
219 | * cannot be used here. | |
220 | * | |
221 | * Instead, below is a list of the power_supply names of known chargers for | |
222 | * these boards and the charger psy is looked up by name from this list. | |
223 | * | |
224 | * (1) modelling the external USB charger | |
225 | */ | |
226 | static const char * const tusb1210_chargers[] = { | |
227 | "bq24190-charger", | |
228 | }; | |
229 | ||
230 | static bool tusb1210_get_online(struct tusb1210 *tusb) | |
231 | { | |
232 | union power_supply_propval val; | |
233 | int i; | |
234 | ||
235 | for (i = 0; i < ARRAY_SIZE(tusb1210_chargers) && !tusb->charger; i++) | |
236 | tusb->charger = power_supply_get_by_name(tusb1210_chargers[i]); | |
237 | ||
238 | if (!tusb->charger) | |
239 | return false; | |
240 | ||
241 | if (power_supply_get_property(tusb->charger, POWER_SUPPLY_PROP_ONLINE, &val)) | |
242 | return false; | |
243 | ||
244 | return val.intval; | |
245 | } | |
246 | ||
247 | static void tusb1210_chg_det_work(struct work_struct *work) | |
248 | { | |
249 | struct tusb1210 *tusb = container_of(work, struct tusb1210, chg_det_work.work); | |
250 | bool vbus_present = tusb1210_get_online(tusb); | |
251 | int ret; | |
252 | u8 val; | |
253 | ||
254 | dev_dbg(&tusb->ulpi->dev, "chg_det state %s vbus_present %d\n", | |
255 | tusb1210_chg_det_states[tusb->chg_det_state], vbus_present); | |
256 | ||
257 | switch (tusb->chg_det_state) { | |
258 | case TUSB1210_CHG_DET_CONNECTING: | |
259 | tusb->chg_type = POWER_SUPPLY_USB_TYPE_UNKNOWN; | |
260 | tusb->chg_det_retries = 0; | |
261 | /* Power on USB controller for ulpi_read()/_write() */ | |
262 | ret = pm_runtime_resume_and_get(tusb->ulpi->dev.parent); | |
263 | if (ret < 0) { | |
264 | dev_err(&tusb->ulpi->dev, "error %d runtime-resuming\n", ret); | |
265 | /* Should never happen, skip charger detection */ | |
266 | tusb1210_chg_det_set_state(tusb, TUSB1210_CHG_DET_CONNECTED, 0); | |
267 | return; | |
268 | } | |
269 | tusb1210_chg_det_set_state(tusb, TUSB1210_CHG_DET_START_DET, 0); | |
270 | break; | |
271 | case TUSB1210_CHG_DET_START_DET: | |
272 | /* | |
273 | * Use the builtin charger detection FSM to keep things simple. | |
274 | * This only detects DCP / SDP. This is good enough for the few | |
275 | * boards which actually rely on the phy for charger detection. | |
276 | */ | |
277 | mutex_lock(&tusb->phy->mutex); | |
278 | ret = tusb1210_ulpi_write(tusb, TUSB1211_VENDOR_SPECIFIC3_SET, | |
279 | TUSB1211_VENDOR_SPECIFIC3_SW_USB_DET); | |
280 | mutex_unlock(&tusb->phy->mutex); | |
281 | if (ret) { | |
282 | tusb1210_chg_det_handle_ulpi_error(tusb); | |
283 | break; | |
284 | } | |
285 | ||
286 | /* Wait 400 ms for the charger detection FSM to finish */ | |
287 | tusb1210_chg_det_set_state(tusb, TUSB1210_CHG_DET_READ_DET, 400); | |
288 | break; | |
289 | case TUSB1210_CHG_DET_READ_DET: | |
290 | mutex_lock(&tusb->phy->mutex); | |
291 | ret = tusb1210_ulpi_read(tusb, TUSB1211_POWER_CONTROL, &val); | |
292 | mutex_unlock(&tusb->phy->mutex); | |
293 | if (ret) { | |
294 | tusb1210_chg_det_handle_ulpi_error(tusb); | |
295 | break; | |
296 | } | |
297 | ||
298 | if (val & TUSB1211_POWER_CONTROL_DET_COMP) | |
299 | tusb1210_chg_det_set_type(tusb, POWER_SUPPLY_USB_TYPE_DCP); | |
300 | else | |
301 | tusb1210_chg_det_set_type(tusb, POWER_SUPPLY_USB_TYPE_SDP); | |
302 | ||
303 | tusb1210_chg_det_set_state(tusb, TUSB1210_CHG_DET_FINISH_DET, 0); | |
304 | break; | |
305 | case TUSB1210_CHG_DET_FINISH_DET: | |
306 | mutex_lock(&tusb->phy->mutex); | |
307 | ||
308 | /* Set SW_CONTROL to stop the charger-det FSM */ | |
309 | ret = tusb1210_ulpi_write(tusb, TUSB1211_POWER_CONTROL_SET, | |
310 | TUSB1211_POWER_CONTROL_SW_CONTROL); | |
311 | ||
312 | /* Clear DP_VSRC_EN which may have been enabled by the charger-det FSM */ | |
313 | ret |= tusb1210_ulpi_write(tusb, TUSB1211_POWER_CONTROL_CLEAR, | |
314 | TUSB1211_POWER_CONTROL_DP_VSRC_EN); | |
315 | ||
316 | /* Clear CHGD_IDP_SRC_EN (may have been enabled by the charger-det FSM) */ | |
317 | ret |= tusb1210_ulpi_write(tusb, TUSB1211_VENDOR_SPECIFIC3_CLEAR, | |
318 | TUSB1211_VENDOR_SPECIFIC3_CHGD_IDP_SRC_EN); | |
319 | ||
320 | /* If any of the above fails reset the phy */ | |
321 | if (ret) { | |
322 | tusb1210_reset(tusb); | |
323 | msleep(TUSB1210_RESET_TIME_MS); | |
324 | } | |
325 | ||
326 | /* Restore phy-parameters and OTG_CTRL register */ | |
327 | tusb1210_ulpi_write(tusb, ULPI_OTG_CTRL, tusb->otg_ctrl); | |
328 | tusb1210_ulpi_write(tusb, TUSB1210_VENDOR_SPECIFIC2, | |
329 | tusb->vendor_specific2); | |
330 | ||
331 | mutex_unlock(&tusb->phy->mutex); | |
332 | ||
333 | pm_runtime_put(tusb->ulpi->dev.parent); | |
334 | tusb1210_chg_det_set_state(tusb, TUSB1210_CHG_DET_CONNECTED, 0); | |
335 | break; | |
336 | case TUSB1210_CHG_DET_CONNECTED: | |
337 | if (!vbus_present) | |
338 | tusb1210_chg_det_set_state(tusb, TUSB1210_CHG_DET_DISCONNECTING, 0); | |
339 | break; | |
340 | case TUSB1210_CHG_DET_DISCONNECTING: | |
341 | /* | |
342 | * The phy seems to take approx. 600ms longer then the charger | |
343 | * chip (which is used to get vbus_present) to determine Vbus | |
344 | * session end. Wait 800ms to ensure the phy has detected and | |
345 | * signalled Vbus session end. | |
346 | */ | |
347 | tusb1210_chg_det_set_state(tusb, TUSB1210_CHG_DET_DISCONNECTING_DONE, 800); | |
348 | break; | |
349 | case TUSB1210_CHG_DET_DISCONNECTING_DONE: | |
350 | /* | |
351 | * The phy often stops reacting to ulpi_read()/_write requests | |
352 | * after a Vbus-session end. Reset it to work around this. | |
353 | */ | |
354 | tusb1210_reset(tusb); | |
355 | tusb1210_chg_det_set_type(tusb, POWER_SUPPLY_USB_TYPE_UNKNOWN); | |
356 | tusb1210_chg_det_set_state(tusb, TUSB1210_CHG_DET_DISCONNECTED, 0); | |
357 | break; | |
358 | case TUSB1210_CHG_DET_DISCONNECTED: | |
359 | if (vbus_present) | |
360 | tusb1210_chg_det_set_state(tusb, TUSB1210_CHG_DET_CONNECTING, 0); | |
361 | break; | |
362 | } | |
363 | } | |
364 | ||
365 | static int tusb1210_psy_notifier(struct notifier_block *nb, | |
366 | unsigned long event, void *ptr) | |
367 | { | |
368 | struct tusb1210 *tusb = container_of(nb, struct tusb1210, psy_nb); | |
369 | struct power_supply *psy = ptr; | |
370 | ||
371 | if (psy != tusb->psy && psy->desc->type == POWER_SUPPLY_TYPE_USB) | |
372 | queue_delayed_work(system_long_wq, &tusb->chg_det_work, 0); | |
373 | ||
374 | return NOTIFY_OK; | |
375 | } | |
376 | ||
377 | static int tusb1210_psy_get_prop(struct power_supply *psy, | |
378 | enum power_supply_property psp, | |
379 | union power_supply_propval *val) | |
380 | { | |
381 | struct tusb1210 *tusb = power_supply_get_drvdata(psy); | |
382 | ||
383 | switch (psp) { | |
384 | case POWER_SUPPLY_PROP_ONLINE: | |
385 | val->intval = tusb1210_get_online(tusb); | |
386 | break; | |
387 | case POWER_SUPPLY_PROP_USB_TYPE: | |
388 | val->intval = tusb->chg_type; | |
389 | break; | |
390 | case POWER_SUPPLY_PROP_CURRENT_MAX: | |
391 | if (tusb->chg_type == POWER_SUPPLY_USB_TYPE_DCP) | |
392 | val->intval = 2000000; | |
393 | else | |
394 | val->intval = 500000; | |
395 | break; | |
396 | default: | |
397 | return -EINVAL; | |
398 | } | |
399 | ||
400 | return 0; | |
401 | } | |
402 | ||
403 | static const enum power_supply_usb_type tusb1210_psy_usb_types[] = { | |
404 | POWER_SUPPLY_USB_TYPE_SDP, | |
405 | POWER_SUPPLY_USB_TYPE_DCP, | |
406 | POWER_SUPPLY_USB_TYPE_UNKNOWN, | |
407 | }; | |
408 | ||
409 | static const enum power_supply_property tusb1210_psy_props[] = { | |
410 | POWER_SUPPLY_PROP_ONLINE, | |
411 | POWER_SUPPLY_PROP_USB_TYPE, | |
412 | POWER_SUPPLY_PROP_CURRENT_MAX, | |
413 | }; | |
414 | ||
415 | static const struct power_supply_desc tusb1210_psy_desc = { | |
416 | .name = "tusb1211-charger-detect", | |
417 | .type = POWER_SUPPLY_TYPE_USB, | |
418 | .usb_types = tusb1210_psy_usb_types, | |
419 | .num_usb_types = ARRAY_SIZE(tusb1210_psy_usb_types), | |
420 | .properties = tusb1210_psy_props, | |
421 | .num_properties = ARRAY_SIZE(tusb1210_psy_props), | |
422 | .get_property = tusb1210_psy_get_prop, | |
423 | }; | |
424 | ||
425 | /* Setup charger detection if requested, on errors continue without chg-det */ | |
426 | static void tusb1210_probe_charger_detect(struct tusb1210 *tusb) | |
427 | { | |
428 | struct power_supply_config psy_cfg = { .drv_data = tusb }; | |
429 | struct device *dev = &tusb->ulpi->dev; | |
430 | int ret; | |
431 | ||
432 | if (!device_property_read_bool(dev->parent, "linux,phy_charger_detect")) | |
433 | return; | |
434 | ||
435 | if (tusb->ulpi->id.product != 0x1508) { | |
436 | dev_err(dev, "error charger detection is only supported on the TUSB1211\n"); | |
437 | return; | |
438 | } | |
439 | ||
440 | ret = tusb1210_ulpi_read(tusb, ULPI_OTG_CTRL, &tusb->otg_ctrl); | |
441 | if (ret) | |
442 | return; | |
443 | ||
444 | tusb->psy = power_supply_register(dev, &tusb1210_psy_desc, &psy_cfg); | |
445 | if (IS_ERR(tusb->psy)) | |
446 | return; | |
447 | ||
448 | /* | |
449 | * Delay initial run by 2 seconds to allow the charger driver, | |
450 | * which is used to determine vbus_present, to load. | |
451 | */ | |
452 | tusb->chg_det_state = TUSB1210_CHG_DET_DISCONNECTED; | |
453 | INIT_DELAYED_WORK(&tusb->chg_det_work, tusb1210_chg_det_work); | |
454 | queue_delayed_work(system_long_wq, &tusb->chg_det_work, 2 * HZ); | |
455 | ||
456 | tusb->psy_nb.notifier_call = tusb1210_psy_notifier; | |
457 | power_supply_reg_notifier(&tusb->psy_nb); | |
458 | } | |
459 | ||
460 | static void tusb1210_remove_charger_detect(struct tusb1210 *tusb) | |
461 | { | |
462 | ||
463 | if (!IS_ERR_OR_NULL(tusb->psy)) { | |
464 | power_supply_unreg_notifier(&tusb->psy_nb); | |
465 | cancel_delayed_work_sync(&tusb->chg_det_work); | |
466 | power_supply_unregister(tusb->psy); | |
467 | } | |
468 | ||
469 | if (tusb->charger) | |
470 | power_supply_put(tusb->charger); | |
471 | } | |
472 | #else | |
473 | static void tusb1210_probe_charger_detect(struct tusb1210 *tusb) { } | |
474 | static void tusb1210_remove_charger_detect(struct tusb1210 *tusb) { } | |
475 | #endif | |
476 | ||
4a9e5ca1 | 477 | static const struct phy_ops phy_ops = { |
1c14905e HK |
478 | .power_on = tusb1210_power_on, |
479 | .power_off = tusb1210_power_off, | |
54fe3088 | 480 | .set_mode = tusb1210_set_mode, |
1c14905e HK |
481 | .owner = THIS_MODULE, |
482 | }; | |
483 | ||
484 | static int tusb1210_probe(struct ulpi *ulpi) | |
485 | { | |
1c14905e HK |
486 | struct tusb1210 *tusb; |
487 | u8 val, reg; | |
09a35126 | 488 | int ret; |
1c14905e HK |
489 | |
490 | tusb = devm_kzalloc(&ulpi->dev, sizeof(*tusb), GFP_KERNEL); | |
491 | if (!tusb) | |
492 | return -ENOMEM; | |
493 | ||
09a35126 HG |
494 | tusb->ulpi = ulpi; |
495 | ||
8e71c680 UKK |
496 | tusb->gpio_reset = devm_gpiod_get_optional(&ulpi->dev, "reset", |
497 | GPIOD_OUT_LOW); | |
498 | if (IS_ERR(tusb->gpio_reset)) | |
499 | return PTR_ERR(tusb->gpio_reset); | |
500 | ||
501 | gpiod_set_value_cansleep(tusb->gpio_reset, 1); | |
502 | ||
503 | tusb->gpio_cs = devm_gpiod_get_optional(&ulpi->dev, "cs", | |
504 | GPIOD_OUT_LOW); | |
505 | if (IS_ERR(tusb->gpio_cs)) | |
506 | return PTR_ERR(tusb->gpio_cs); | |
507 | ||
508 | gpiod_set_value_cansleep(tusb->gpio_cs, 1); | |
1c14905e HK |
509 | |
510 | /* | |
511 | * VENDOR_SPECIFIC2 register in TUSB1210 can be used for configuring eye | |
512 | * diagram optimization and DP/DM swap. | |
513 | */ | |
514 | ||
09a35126 HG |
515 | ret = tusb1210_ulpi_read(tusb, TUSB1210_VENDOR_SPECIFIC2, ®); |
516 | if (ret) | |
517 | return ret; | |
eb445a15 | 518 | |
1c14905e | 519 | /* High speed output drive strength configuration */ |
eb445a15 LB |
520 | if (!device_property_read_u8(&ulpi->dev, "ihstx", &val)) |
521 | u8p_replace_bits(®, val, (u8)TUSB1210_VENDOR_SPECIFIC2_IHSTX_MASK); | |
1c14905e HK |
522 | |
523 | /* High speed output impedance configuration */ | |
eb445a15 LB |
524 | if (!device_property_read_u8(&ulpi->dev, "zhsdrv", &val)) |
525 | u8p_replace_bits(®, val, (u8)TUSB1210_VENDOR_SPECIFIC2_ZHSDRV_MASK); | |
1c14905e HK |
526 | |
527 | /* DP/DM swap control */ | |
eb445a15 LB |
528 | if (!device_property_read_u8(&ulpi->dev, "datapolarity", &val)) |
529 | u8p_replace_bits(®, val, (u8)TUSB1210_VENDOR_SPECIFIC2_DP_MASK); | |
1c14905e | 530 | |
09a35126 HG |
531 | ret = tusb1210_ulpi_write(tusb, TUSB1210_VENDOR_SPECIFIC2, reg); |
532 | if (ret) | |
533 | return ret; | |
534 | ||
eb445a15 | 535 | tusb->vendor_specific2 = reg; |
1c14905e | 536 | |
48969a56 SG |
537 | tusb1210_probe_charger_detect(tusb); |
538 | ||
1c14905e | 539 | tusb->phy = ulpi_phy_create(ulpi, &phy_ops); |
a9f17d0c CJ |
540 | if (IS_ERR(tusb->phy)) { |
541 | ret = PTR_ERR(tusb->phy); | |
542 | goto err_remove_charger; | |
543 | } | |
1c14905e | 544 | |
1c14905e HK |
545 | phy_set_drvdata(tusb->phy, tusb); |
546 | ulpi_set_drvdata(ulpi, tusb); | |
547 | return 0; | |
a9f17d0c CJ |
548 | |
549 | err_remove_charger: | |
550 | tusb1210_remove_charger_detect(tusb); | |
551 | return ret; | |
1c14905e HK |
552 | } |
553 | ||
554 | static void tusb1210_remove(struct ulpi *ulpi) | |
555 | { | |
556 | struct tusb1210 *tusb = ulpi_get_drvdata(ulpi); | |
557 | ||
558 | ulpi_phy_destroy(ulpi, tusb->phy); | |
48969a56 | 559 | tusb1210_remove_charger_detect(tusb); |
1c14905e HK |
560 | } |
561 | ||
562 | #define TI_VENDOR_ID 0x0451 | |
563 | ||
564 | static const struct ulpi_device_id tusb1210_ulpi_id[] = { | |
82d9d5e0 FB |
565 | { TI_VENDOR_ID, 0x1507, }, /* TUSB1210 */ |
566 | { TI_VENDOR_ID, 0x1508, }, /* TUSB1211 */ | |
1c14905e HK |
567 | { }, |
568 | }; | |
569 | MODULE_DEVICE_TABLE(ulpi, tusb1210_ulpi_id); | |
570 | ||
571 | static struct ulpi_driver tusb1210_driver = { | |
572 | .id_table = tusb1210_ulpi_id, | |
573 | .probe = tusb1210_probe, | |
574 | .remove = tusb1210_remove, | |
575 | .driver = { | |
576 | .name = "tusb1210", | |
577 | .owner = THIS_MODULE, | |
578 | }, | |
579 | }; | |
580 | ||
581 | module_ulpi_driver(tusb1210_driver); | |
582 | ||
583 | MODULE_AUTHOR("Intel Corporation"); | |
584 | MODULE_LICENSE("GPL v2"); | |
585 | MODULE_DESCRIPTION("TUSB1210 ULPI PHY driver"); |