cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

phy-cpcap-usb.c (17085B)


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