1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Motorola CPCAP PMIC USB PHY driver
4 * Copyright (C) 2017 Tony Lindgren <tony@atomide.com>
5 *
6 * Some parts based on earlier Motorola Linux kernel tree code in
7 * board-mapphone-usb.c and cpcap-usb-det.c:
8 * Copyright (C) 2007 - 2011 Motorola, Inc.
9 */
10
11#include <linux/atomic.h>
12#include <linux/clk.h>
13#include <linux/delay.h>
14#include <linux/err.h>
15#include <linux/io.h>
16#include <linux/module.h>
17#include <linux/of.h>
18#include <linux/iio/consumer.h>
19#include <linux/pinctrl/consumer.h>
20#include <linux/platform_device.h>
21#include <linux/regmap.h>
22#include <linux/slab.h>
23
24#include <linux/gpio/consumer.h>
25#include <linux/mfd/motorola-cpcap.h>
26#include <linux/phy/omap_usb.h>
27#include <linux/phy/phy.h>
28#include <linux/regulator/consumer.h>
29#include <linux/usb/musb.h>
30
31/* CPCAP_REG_USBC1 register bits */
32#define CPCAP_BIT_IDPULSE		BIT(15)
33#define CPCAP_BIT_ID100KPU		BIT(14)
34#define CPCAP_BIT_IDPUCNTRL		BIT(13)
35#define CPCAP_BIT_IDPU			BIT(12)
36#define CPCAP_BIT_IDPD			BIT(11)
37#define CPCAP_BIT_VBUSCHRGTMR3		BIT(10)
38#define CPCAP_BIT_VBUSCHRGTMR2		BIT(9)
39#define CPCAP_BIT_VBUSCHRGTMR1		BIT(8)
40#define CPCAP_BIT_VBUSCHRGTMR0		BIT(7)
41#define CPCAP_BIT_VBUSPU		BIT(6)
42#define CPCAP_BIT_VBUSPD		BIT(5)
43#define CPCAP_BIT_DMPD			BIT(4)
44#define CPCAP_BIT_DPPD			BIT(3)
45#define CPCAP_BIT_DM1K5PU		BIT(2)
46#define CPCAP_BIT_DP1K5PU		BIT(1)
47#define CPCAP_BIT_DP150KPU		BIT(0)
48
49/* CPCAP_REG_USBC2 register bits */
50#define CPCAP_BIT_ZHSDRV1		BIT(15)
51#define CPCAP_BIT_ZHSDRV0		BIT(14)
52#define CPCAP_BIT_DPLLCLKREQ		BIT(13)
53#define CPCAP_BIT_SE0CONN		BIT(12)
54#define CPCAP_BIT_UARTTXTRI		BIT(11)
55#define CPCAP_BIT_UARTSWAP		BIT(10)
56#define CPCAP_BIT_UARTMUX1		BIT(9)
57#define CPCAP_BIT_UARTMUX0		BIT(8)
58#define CPCAP_BIT_ULPISTPLOW		BIT(7)
59#define CPCAP_BIT_TXENPOL		BIT(6)
60#define CPCAP_BIT_USBXCVREN		BIT(5)
61#define CPCAP_BIT_USBCNTRL		BIT(4)
62#define CPCAP_BIT_USBSUSPEND		BIT(3)
63#define CPCAP_BIT_EMUMODE2		BIT(2)
64#define CPCAP_BIT_EMUMODE1		BIT(1)
65#define CPCAP_BIT_EMUMODE0		BIT(0)
66
67/* CPCAP_REG_USBC3 register bits */
68#define CPCAP_BIT_SPARE_898_15		BIT(15)
69#define CPCAP_BIT_IHSTX03		BIT(14)
70#define CPCAP_BIT_IHSTX02		BIT(13)
71#define CPCAP_BIT_IHSTX01		BIT(12)
72#define CPCAP_BIT_IHSTX0		BIT(11)
73#define CPCAP_BIT_IDPU_SPI		BIT(10)
74#define CPCAP_BIT_UNUSED_898_9		BIT(9)
75#define CPCAP_BIT_VBUSSTBY_EN		BIT(8)
76#define CPCAP_BIT_VBUSEN_SPI		BIT(7)
77#define CPCAP_BIT_VBUSPU_SPI		BIT(6)
78#define CPCAP_BIT_VBUSPD_SPI		BIT(5)
79#define CPCAP_BIT_DMPD_SPI		BIT(4)
80#define CPCAP_BIT_DPPD_SPI		BIT(3)
81#define CPCAP_BIT_SUSPEND_SPI		BIT(2)
82#define CPCAP_BIT_PU_SPI		BIT(1)
83#define CPCAP_BIT_ULPI_SPI_SEL		BIT(0)
84
85struct cpcap_usb_ints_state {
86	bool id_ground;
87	bool id_float;
88	bool chrg_det;
89	bool rvrs_chrg;
90	bool vbusov;
91
92	bool chrg_se1b;
93	bool se0conn;
94	bool rvrs_mode;
95	bool chrgcurr1;
96	bool vbusvld;
97	bool sessvld;
98	bool sessend;
99	bool se1;
100
101	bool battdetb;
102	bool dm;
103	bool dp;
104};
105
106enum cpcap_gpio_mode {
107	CPCAP_DM_DP,
108	CPCAP_MDM_RX_TX,
109	CPCAP_UNKNOWN_DISABLED,	/* Seems to disable USB lines */
110	CPCAP_OTG_DM_DP,
111};
112
113struct cpcap_phy_ddata {
114	struct regmap *reg;
115	struct device *dev;
116	struct usb_phy phy;
117	struct delayed_work detect_work;
118	struct pinctrl *pins;
119	struct pinctrl_state *pins_ulpi;
120	struct pinctrl_state *pins_utmi;
121	struct pinctrl_state *pins_uart;
122	struct gpio_desc *gpio[2];
123	struct iio_channel *vbus;
124	struct iio_channel *id;
125	struct regulator *vusb;
126	atomic_t active;
127	unsigned int vbus_provider:1;
128	unsigned int docked:1;
129};
130
131static bool cpcap_usb_vbus_valid(struct cpcap_phy_ddata *ddata)
132{
133	int error, value = 0;
134
135	error = iio_read_channel_processed(ddata->vbus, &value);
136	if (error >= 0)
137		return value > 3900;
138
139	dev_err(ddata->dev, "error reading VBUS: %i\n", error);
140
141	return false;
142}
143
144static int cpcap_usb_phy_set_host(struct usb_otg *otg, struct usb_bus *host)
145{
146	otg->host = host;
147	if (!host)
148		otg->state = OTG_STATE_UNDEFINED;
149
150	return 0;
151}
152
153static int cpcap_usb_phy_set_peripheral(struct usb_otg *otg,
154					struct usb_gadget *gadget)
155{
156	otg->gadget = gadget;
157	if (!gadget)
158		otg->state = OTG_STATE_UNDEFINED;
159
160	return 0;
161}
162
163static const struct phy_ops ops = {
164	.owner		= THIS_MODULE,
165};
166
167static int cpcap_phy_get_ints_state(struct cpcap_phy_ddata *ddata,
168				    struct cpcap_usb_ints_state *s)
169{
170	int val, error;
171
172	error = regmap_read(ddata->reg, CPCAP_REG_INTS1, &val);
173	if (error)
174		return error;
175
176	s->id_ground = val & BIT(15);
177	s->id_float = val & BIT(14);
178	s->vbusov = val & BIT(11);
179
180	error = regmap_read(ddata->reg, CPCAP_REG_INTS2, &val);
181	if (error)
182		return error;
183
184	s->vbusvld = val & BIT(3);
185	s->sessvld = val & BIT(2);
186	s->sessend = val & BIT(1);
187	s->se1 = val & BIT(0);
188
189	error = regmap_read(ddata->reg, CPCAP_REG_INTS4, &val);
190	if (error)
191		return error;
192
193	s->dm = val & BIT(1);
194	s->dp = val & BIT(0);
195
196	return 0;
197}
198
199static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata);
200static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata);
201
202static void cpcap_usb_try_musb_mailbox(struct cpcap_phy_ddata *ddata,
203				       enum musb_vbus_id_status status)
204{
205	int error;
206
207	error = musb_mailbox(status);
208	if (!error)
209		return;
210
211	dev_dbg(ddata->dev, "%s: musb_mailbox failed: %i\n",
212		__func__, error);
213}
214
215static void cpcap_usb_detect(struct work_struct *work)
216{
217	struct cpcap_phy_ddata *ddata;
218	struct cpcap_usb_ints_state s;
219	bool vbus = false;
220	int error;
221
222	ddata = container_of(work, struct cpcap_phy_ddata, detect_work.work);
223
224	error = cpcap_phy_get_ints_state(ddata, &s);
225	if (error)
226		return;
227
228	vbus = cpcap_usb_vbus_valid(ddata);
229
230	/* We need to kick the VBUS as USB A-host */
231	if (s.id_ground && ddata->vbus_provider) {
232		dev_dbg(ddata->dev, "still in USB A-host mode, kicking VBUS\n");
233
234		cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
235
236		error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
237					   CPCAP_BIT_VBUSSTBY_EN |
238					   CPCAP_BIT_VBUSEN_SPI,
239					   CPCAP_BIT_VBUSEN_SPI);
240		if (error)
241			goto out_err;
242
243		return;
244	}
245
246	if (vbus && s.id_ground && ddata->docked) {
247		dev_dbg(ddata->dev, "still docked as A-host, signal ID down\n");
248
249		cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
250
251		return;
252	}
253
254	/* No VBUS needed with docks */
255	if (vbus && s.id_ground && !ddata->vbus_provider) {
256		dev_dbg(ddata->dev, "connected to a dock\n");
257
258		ddata->docked = true;
259
260		error = cpcap_usb_set_usb_mode(ddata);
261		if (error)
262			goto out_err;
263
264		cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
265
266		/*
267		 * Force check state again after musb has reoriented,
268		 * otherwise devices won't enumerate after loading PHY
269		 * driver.
270		 */
271		schedule_delayed_work(&ddata->detect_work,
272				      msecs_to_jiffies(1000));
273
274		return;
275	}
276
277	if (s.id_ground && !ddata->docked) {
278		dev_dbg(ddata->dev, "id ground, USB host mode\n");
279
280		ddata->vbus_provider = true;
281
282		error = cpcap_usb_set_usb_mode(ddata);
283		if (error)
284			goto out_err;
285
286		cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
287
288		error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
289					   CPCAP_BIT_VBUSSTBY_EN |
290					   CPCAP_BIT_VBUSEN_SPI,
291					   CPCAP_BIT_VBUSEN_SPI);
292		if (error)
293			goto out_err;
294
295		return;
296	}
297
298	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
299				   CPCAP_BIT_VBUSSTBY_EN |
300				   CPCAP_BIT_VBUSEN_SPI, 0);
301	if (error)
302		goto out_err;
303
304	vbus = cpcap_usb_vbus_valid(ddata);
305
306	/* Otherwise assume we're connected to a USB host */
307	if (vbus) {
308		dev_dbg(ddata->dev, "connected to USB host\n");
309		error = cpcap_usb_set_usb_mode(ddata);
310		if (error)
311			goto out_err;
312		cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_VALID);
313
314		return;
315	}
316
317	ddata->vbus_provider = false;
318	ddata->docked = false;
319	cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_OFF);
320
321	/* Default to debug UART mode */
322	error = cpcap_usb_set_uart_mode(ddata);
323	if (error)
324		goto out_err;
325
326	dev_dbg(ddata->dev, "set UART mode\n");
327
328	return;
329
330out_err:
331	dev_err(ddata->dev, "error setting cable state: %i\n", error);
332}
333
334static irqreturn_t cpcap_phy_irq_thread(int irq, void *data)
335{
336	struct cpcap_phy_ddata *ddata = data;
337
338	if (!atomic_read(&ddata->active))
339		return IRQ_NONE;
340
341	schedule_delayed_work(&ddata->detect_work, msecs_to_jiffies(1));
342
343	return IRQ_HANDLED;
344}
345
346static int cpcap_usb_init_irq(struct platform_device *pdev,
347			      struct cpcap_phy_ddata *ddata,
348			      const char *name)
349{
350	int irq, error;
351
352	irq = platform_get_irq_byname(pdev, name);
353	if (irq < 0)
354		return -ENODEV;
355
356	error = devm_request_threaded_irq(ddata->dev, irq, NULL,
357					  cpcap_phy_irq_thread,
358					  IRQF_SHARED |
359					  IRQF_ONESHOT,
360					  name, ddata);
361	if (error) {
362		dev_err(ddata->dev, "could not get irq %s: %i\n",
363			name, error);
364
365		return error;
366	}
367
368	return 0;
369}
370
371static const char * const cpcap_phy_irqs[] = {
372	/* REG_INT_0 */
373	"id_ground", "id_float",
374
375	/* REG_INT1 */
376	"se0conn", "vbusvld", "sessvld", "sessend", "se1",
377
378	/* REG_INT_3 */
379	"dm", "dp",
380};
381
382static int cpcap_usb_init_interrupts(struct platform_device *pdev,
383				     struct cpcap_phy_ddata *ddata)
384{
385	int i, error;
386
387	for (i = 0; i < ARRAY_SIZE(cpcap_phy_irqs); i++) {
388		error = cpcap_usb_init_irq(pdev, ddata, cpcap_phy_irqs[i]);
389		if (error)
390			return error;
391	}
392
393	return 0;
394}
395
396/*
397 * Optional pins and modes. At least Motorola mapphone devices
398 * are using two GPIOs and dynamic pinctrl to multiplex PHY pins
399 * to UART, ULPI or UTMI mode.
400 */
401
402static int cpcap_usb_gpio_set_mode(struct cpcap_phy_ddata *ddata,
403				   enum cpcap_gpio_mode mode)
404{
405	if (!ddata->gpio[0] || !ddata->gpio[1])
406		return 0;
407
408	gpiod_set_value(ddata->gpio[0], mode & 1);
409	gpiod_set_value(ddata->gpio[1], mode >> 1);
410
411	return 0;
412}
413
414static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata)
415{
416	int error;
417
418	/* Disable lines to prevent glitches from waking up mdm6600 */
419	error = cpcap_usb_gpio_set_mode(ddata, CPCAP_UNKNOWN_DISABLED);
420	if (error)
421		goto out_err;
422
423	if (ddata->pins_uart) {
424		error = pinctrl_select_state(ddata->pins, ddata->pins_uart);
425		if (error)
426			goto out_err;
427	}
428
429	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC1,
430				   CPCAP_BIT_VBUSPD,
431				   CPCAP_BIT_VBUSPD);
432	if (error)
433		goto out_err;
434
435	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC2,
436				   0xffff, CPCAP_BIT_UARTMUX0 |
437				   CPCAP_BIT_EMUMODE0);
438	if (error)
439		goto out_err;
440
441	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3, 0x7fff,
442				   CPCAP_BIT_IDPU_SPI);
443	if (error)
444		goto out_err;
445
446	/* Enable UART mode */
447	error = cpcap_usb_gpio_set_mode(ddata, CPCAP_DM_DP);
448	if (error)
449		goto out_err;
450
451	return 0;
452
453out_err:
454	dev_err(ddata->dev, "%s failed with %i\n", __func__, error);
455
456	return error;
457}
458
459static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
460{
461	int error;
462
463	/* Disable lines to prevent glitches from waking up mdm6600 */
464	error = cpcap_usb_gpio_set_mode(ddata, CPCAP_UNKNOWN_DISABLED);
465	if (error)
466		return error;
467
468	if (ddata->pins_utmi) {
469		error = pinctrl_select_state(ddata->pins, ddata->pins_utmi);
470		if (error) {
471			dev_err(ddata->dev, "could not set usb mode: %i\n",
472				error);
473
474			return error;
475		}
476	}
477
478	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC1,
479				   CPCAP_BIT_VBUSPD, 0);
480	if (error)
481		goto out_err;
482
483	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
484				   CPCAP_BIT_PU_SPI |
485				   CPCAP_BIT_DMPD_SPI |
486				   CPCAP_BIT_DPPD_SPI |
487				   CPCAP_BIT_SUSPEND_SPI |
488				   CPCAP_BIT_ULPI_SPI_SEL, 0);
489	if (error)
490		goto out_err;
491
492	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC2,
493				   CPCAP_BIT_USBXCVREN,
494				   CPCAP_BIT_USBXCVREN);
495	if (error)
496		goto out_err;
497
498	/* Enable USB mode */
499	error = cpcap_usb_gpio_set_mode(ddata, CPCAP_OTG_DM_DP);
500	if (error)
501		goto out_err;
502
503	return 0;
504
505out_err:
506	dev_err(ddata->dev, "%s failed with %i\n", __func__, error);
507
508	return error;
509}
510
511static int cpcap_usb_init_optional_pins(struct cpcap_phy_ddata *ddata)
512{
513	ddata->pins = devm_pinctrl_get(ddata->dev);
514	if (IS_ERR(ddata->pins)) {
515		dev_info(ddata->dev, "default pins not configured: %ld\n",
516			 PTR_ERR(ddata->pins));
517		ddata->pins = NULL;
518
519		return 0;
520	}
521
522	ddata->pins_ulpi = pinctrl_lookup_state(ddata->pins, "ulpi");
523	if (IS_ERR(ddata->pins_ulpi)) {
524		dev_info(ddata->dev, "ulpi pins not configured\n");
525		ddata->pins_ulpi = NULL;
526	}
527
528	ddata->pins_utmi = pinctrl_lookup_state(ddata->pins, "utmi");
529	if (IS_ERR(ddata->pins_utmi)) {
530		dev_info(ddata->dev, "utmi pins not configured\n");
531		ddata->pins_utmi = NULL;
532	}
533
534	ddata->pins_uart = pinctrl_lookup_state(ddata->pins, "uart");
535	if (IS_ERR(ddata->pins_uart)) {
536		dev_info(ddata->dev, "uart pins not configured\n");
537		ddata->pins_uart = NULL;
538	}
539
540	if (ddata->pins_uart)
541		return pinctrl_select_state(ddata->pins, ddata->pins_uart);
542
543	return 0;
544}
545
546static void cpcap_usb_init_optional_gpios(struct cpcap_phy_ddata *ddata)
547{
548	int i;
549
550	for (i = 0; i < 2; i++) {
551		ddata->gpio[i] = devm_gpiod_get_index(ddata->dev, "mode",
552						      i, GPIOD_OUT_HIGH);
553		if (IS_ERR(ddata->gpio[i])) {
554			dev_info(ddata->dev, "no mode change GPIO%i: %li\n",
555				 i, PTR_ERR(ddata->gpio[i]));
556			ddata->gpio[i] = NULL;
557		}
558	}
559}
560
561static int cpcap_usb_init_iio(struct cpcap_phy_ddata *ddata)
562{
563	enum iio_chan_type type;
564	int error;
565
566	ddata->vbus = devm_iio_channel_get(ddata->dev, "vbus");
567	if (IS_ERR(ddata->vbus)) {
568		error = PTR_ERR(ddata->vbus);
569		goto out_err;
570	}
571
572	if (!ddata->vbus->indio_dev) {
573		error = -ENXIO;
574		goto out_err;
575	}
576
577	error = iio_get_channel_type(ddata->vbus, &type);
578	if (error < 0)
579		goto out_err;
580
581	if (type != IIO_VOLTAGE) {
582		error = -EINVAL;
583		goto out_err;
584	}
585
586	return 0;
587
588out_err:
589	dev_err(ddata->dev, "could not initialize VBUS or ID IIO: %i\n",
590		error);
591
592	return error;
593}
594
595#ifdef CONFIG_OF
596static const struct of_device_id cpcap_usb_phy_id_table[] = {
597	{
598		.compatible = "motorola,cpcap-usb-phy",
599	},
600	{
601		.compatible = "motorola,mapphone-cpcap-usb-phy",
602	},
603	{},
604};
605MODULE_DEVICE_TABLE(of, cpcap_usb_phy_id_table);
606#endif
607
608static int cpcap_usb_phy_probe(struct platform_device *pdev)
609{
610	struct cpcap_phy_ddata *ddata;
611	struct phy *generic_phy;
612	struct phy_provider *phy_provider;
613	struct usb_otg *otg;
614	int error;
615
616	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
617	if (!ddata)
618		return -ENOMEM;
619
620	ddata->reg = dev_get_regmap(pdev->dev.parent, NULL);
621	if (!ddata->reg)
622		return -ENODEV;
623
624	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
625	if (!otg)
626		return -ENOMEM;
627
628	ddata->dev = &pdev->dev;
629	ddata->phy.dev = ddata->dev;
630	ddata->phy.label = "cpcap_usb_phy";
631	ddata->phy.otg = otg;
632	ddata->phy.type = USB_PHY_TYPE_USB2;
633	otg->set_host = cpcap_usb_phy_set_host;
634	otg->set_peripheral = cpcap_usb_phy_set_peripheral;
635	otg->usb_phy = &ddata->phy;
636	INIT_DELAYED_WORK(&ddata->detect_work, cpcap_usb_detect);
637	platform_set_drvdata(pdev, ddata);
638
639	ddata->vusb = devm_regulator_get(&pdev->dev, "vusb");
640	if (IS_ERR(ddata->vusb))
641		return PTR_ERR(ddata->vusb);
642
643	error = regulator_enable(ddata->vusb);
644	if (error)
645		return error;
646
647	generic_phy = devm_phy_create(ddata->dev, NULL, &ops);
648	if (IS_ERR(generic_phy)) {
649		error = PTR_ERR(generic_phy);
650		goto out_reg_disable;
651	}
652
653	phy_set_drvdata(generic_phy, ddata);
654
655	phy_provider = devm_of_phy_provider_register(ddata->dev,
656						     of_phy_simple_xlate);
657	if (IS_ERR(phy_provider)) {
658		error = PTR_ERR(phy_provider);
659		goto out_reg_disable;
660	}
661
662	error = cpcap_usb_init_optional_pins(ddata);
663	if (error)
664		goto out_reg_disable;
665
666	cpcap_usb_init_optional_gpios(ddata);
667
668	error = cpcap_usb_init_iio(ddata);
669	if (error)
670		goto out_reg_disable;
671
672	error = cpcap_usb_init_interrupts(pdev, ddata);
673	if (error)
674		goto out_reg_disable;
675
676	usb_add_phy_dev(&ddata->phy);
677	atomic_set(&ddata->active, 1);
678	schedule_delayed_work(&ddata->detect_work, msecs_to_jiffies(1));
679
680	return 0;
681
682out_reg_disable:
683	regulator_disable(ddata->vusb);
684
685	return error;
686}
687
688static void cpcap_usb_phy_remove(struct platform_device *pdev)
689{
690	struct cpcap_phy_ddata *ddata = platform_get_drvdata(pdev);
691	int error;
692
693	atomic_set(&ddata->active, 0);
694	error = cpcap_usb_set_uart_mode(ddata);
695	if (error)
696		dev_err(ddata->dev, "could not set UART mode\n");
697
698	cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_OFF);
699
700	usb_remove_phy(&ddata->phy);
701	cancel_delayed_work_sync(&ddata->detect_work);
702	regulator_disable(ddata->vusb);
703}
704
705static struct platform_driver cpcap_usb_phy_driver = {
706	.probe		= cpcap_usb_phy_probe,
707	.remove_new	= cpcap_usb_phy_remove,
708	.driver		= {
709		.name	= "cpcap-usb-phy",
710		.of_match_table = of_match_ptr(cpcap_usb_phy_id_table),
711	},
712};
713
714module_platform_driver(cpcap_usb_phy_driver);
715
716MODULE_ALIAS("platform:cpcap_usb");
717MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
718MODULE_DESCRIPTION("CPCAP usb phy driver");
719MODULE_LICENSE("GPL v2");
720