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

source code of linux/drivers/phy/ti/phy-tusb1210.c