aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/otg
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/otg')
-rw-r--r--drivers/usb/otg/Kconfig10
-rw-r--r--drivers/usb/otg/Makefile1
-rw-r--r--drivers/usb/otg/gpio_vbus.c1
-rw-r--r--drivers/usb/otg/isp1301_omap.c8
-rw-r--r--drivers/usb/otg/nop-usb-xceiv.c1
-rw-r--r--drivers/usb/otg/twl4030-usb.c86
-rw-r--r--drivers/usb/otg/ulpi.c137
7 files changed, 190 insertions, 54 deletions
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index aa884d072f0b..3d2d3e549bd1 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -41,6 +41,16 @@ config ISP1301_OMAP
41 This driver can also be built as a module. If so, the module 41 This driver can also be built as a module. If so, the module
42 will be called isp1301_omap. 42 will be called isp1301_omap.
43 43
44config USB_ULPI
45 bool "Generic ULPI Transceiver Driver"
46 depends on ARM
47 select USB_OTG_UTILS
48 help
49 Enable this to support ULPI connected USB OTG transceivers which
50 are likely found on embedded boards.
51
52 The only chip currently supported is NXP's ISP1504
53
44config TWL4030_USB 54config TWL4030_USB
45 tristate "TWL4030 USB Transceiver Driver" 55 tristate "TWL4030 USB Transceiver Driver"
46 depends on TWL4030_CORE && REGULATOR_TWL4030 56 depends on TWL4030_CORE && REGULATOR_TWL4030
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
index 208167856529..aeb49a8ec412 100644
--- a/drivers/usb/otg/Makefile
+++ b/drivers/usb/otg/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o
10obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o 10obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
11obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o 11obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o
12obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o 12obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o
13obj-$(CONFIG_USB_ULPI) += ulpi.o
13 14
14ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG 15ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG
15ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG 16ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG
diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c
index 1c26c94513e9..221c44444ec6 100644
--- a/drivers/usb/otg/gpio_vbus.c
+++ b/drivers/usb/otg/gpio_vbus.c
@@ -11,6 +11,7 @@
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/platform_device.h> 12#include <linux/platform_device.h>
13#include <linux/gpio.h> 13#include <linux/gpio.h>
14#include <linux/slab.h>
14#include <linux/interrupt.h> 15#include <linux/interrupt.h>
15#include <linux/usb.h> 16#include <linux/usb.h>
16#include <linux/workqueue.h> 17#include <linux/workqueue.h>
diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c
index 77a5f4188999..78a209709260 100644
--- a/drivers/usb/otg/isp1301_omap.c
+++ b/drivers/usb/otg/isp1301_omap.c
@@ -36,8 +36,8 @@
36#include <asm/irq.h> 36#include <asm/irq.h>
37#include <asm/mach-types.h> 37#include <asm/mach-types.h>
38 38
39#include <mach/usb.h> 39#include <plat/usb.h>
40#include <mach/mux.h> 40#include <plat/mux.h>
41 41
42 42
43#ifndef DEBUG 43#ifndef DEBUG
@@ -843,7 +843,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp)
843 843
844static struct platform_device *otg_dev; 844static struct platform_device *otg_dev;
845 845
846static int otg_init(struct isp1301 *isp) 846static int isp1301_otg_init(struct isp1301 *isp)
847{ 847{
848 u32 l; 848 u32 l;
849 849
@@ -1275,7 +1275,7 @@ static int __exit isp1301_remove(struct i2c_client *i2c)
1275static int isp1301_otg_enable(struct isp1301 *isp) 1275static int isp1301_otg_enable(struct isp1301 *isp)
1276{ 1276{
1277 power_up(isp); 1277 power_up(isp);
1278 otg_init(isp); 1278 isp1301_otg_init(isp);
1279 1279
1280 /* NOTE: since we don't change this, this provides 1280 /* NOTE: since we don't change this, this provides
1281 * a few more interrupts than are strictly needed. 1281 * a few more interrupts than are strictly needed.
diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
index af456b48985f..e70014ab0976 100644
--- a/drivers/usb/otg/nop-usb-xceiv.c
+++ b/drivers/usb/otg/nop-usb-xceiv.c
@@ -30,6 +30,7 @@
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/dma-mapping.h> 31#include <linux/dma-mapping.h>
32#include <linux/usb/otg.h> 32#include <linux/usb/otg.h>
33#include <linux/slab.h>
33 34
34struct nop_usb_xceiv { 35struct nop_usb_xceiv {
35 struct otg_transceiver otg; 36 struct otg_transceiver otg;
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index 9e3e7a5c258b..223cdf46ccb7 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -33,10 +33,11 @@
33#include <linux/io.h> 33#include <linux/io.h>
34#include <linux/delay.h> 34#include <linux/delay.h>
35#include <linux/usb/otg.h> 35#include <linux/usb/otg.h>
36#include <linux/i2c/twl4030.h> 36#include <linux/i2c/twl.h>
37#include <linux/regulator/consumer.h> 37#include <linux/regulator/consumer.h>
38#include <linux/err.h> 38#include <linux/err.h>
39 39#include <linux/notifier.h>
40#include <linux/slab.h>
40 41
41/* Register defines */ 42/* Register defines */
42 43
@@ -236,15 +237,6 @@
236#define PMBR1 0x0D 237#define PMBR1 0x0D
237#define GPIO_USB_4PIN_ULPI_2430C (3 << 0) 238#define GPIO_USB_4PIN_ULPI_2430C (3 << 0)
238 239
239
240
241enum linkstat {
242 USB_LINK_UNKNOWN = 0,
243 USB_LINK_NONE,
244 USB_LINK_VBUS,
245 USB_LINK_ID,
246};
247
248struct twl4030_usb { 240struct twl4030_usb {
249 struct otg_transceiver otg; 241 struct otg_transceiver otg;
250 struct device *dev; 242 struct device *dev;
@@ -276,16 +268,16 @@ static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl,
276{ 268{
277 u8 check; 269 u8 check;
278 270
279 if ((twl4030_i2c_write_u8(module, data, address) >= 0) && 271 if ((twl_i2c_write_u8(module, data, address) >= 0) &&
280 (twl4030_i2c_read_u8(module, &check, address) >= 0) && 272 (twl_i2c_read_u8(module, &check, address) >= 0) &&
281 (check == data)) 273 (check == data))
282 return 0; 274 return 0;
283 dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n", 275 dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n",
284 1, module, address, check, data); 276 1, module, address, check, data);
285 277
286 /* Failed once: Try again */ 278 /* Failed once: Try again */
287 if ((twl4030_i2c_write_u8(module, data, address) >= 0) && 279 if ((twl_i2c_write_u8(module, data, address) >= 0) &&
288 (twl4030_i2c_read_u8(module, &check, address) >= 0) && 280 (twl_i2c_read_u8(module, &check, address) >= 0) &&
289 (check == data)) 281 (check == data))
290 return 0; 282 return 0;
291 dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n", 283 dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n",
@@ -303,7 +295,7 @@ static inline int twl4030_usb_write(struct twl4030_usb *twl,
303{ 295{
304 int ret = 0; 296 int ret = 0;
305 297
306 ret = twl4030_i2c_write_u8(TWL4030_MODULE_USB, data, address); 298 ret = twl_i2c_write_u8(TWL4030_MODULE_USB, data, address);
307 if (ret < 0) 299 if (ret < 0)
308 dev_dbg(twl->dev, 300 dev_dbg(twl->dev,
309 "TWL4030:USB:Write[0x%x] Error %d\n", address, ret); 301 "TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
@@ -315,7 +307,7 @@ static inline int twl4030_readb(struct twl4030_usb *twl, u8 module, u8 address)
315 u8 data; 307 u8 data;
316 int ret = 0; 308 int ret = 0;
317 309
318 ret = twl4030_i2c_read_u8(module, &data, address); 310 ret = twl_i2c_read_u8(module, &data, address);
319 if (ret >= 0) 311 if (ret >= 0)
320 ret = data; 312 ret = data;
321 else 313 else
@@ -347,10 +339,10 @@ twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
347 339
348/*-------------------------------------------------------------------------*/ 340/*-------------------------------------------------------------------------*/
349 341
350static enum linkstat twl4030_usb_linkstat(struct twl4030_usb *twl) 342static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl)
351{ 343{
352 int status; 344 int status;
353 int linkstat = USB_LINK_UNKNOWN; 345 int linkstat = USB_EVENT_NONE;
354 346
355 /* 347 /*
356 * For ID/VBUS sensing, see manual section 15.4.8 ... 348 * For ID/VBUS sensing, see manual section 15.4.8 ...
@@ -368,11 +360,11 @@ static enum linkstat twl4030_usb_linkstat(struct twl4030_usb *twl)
368 dev_err(twl->dev, "USB link status err %d\n", status); 360 dev_err(twl->dev, "USB link status err %d\n", status);
369 else if (status & (BIT(7) | BIT(2))) { 361 else if (status & (BIT(7) | BIT(2))) {
370 if (status & BIT(2)) 362 if (status & BIT(2))
371 linkstat = USB_LINK_ID; 363 linkstat = USB_EVENT_ID;
372 else 364 else
373 linkstat = USB_LINK_VBUS; 365 linkstat = USB_EVENT_VBUS;
374 } else 366 } else
375 linkstat = USB_LINK_NONE; 367 linkstat = USB_EVENT_NONE;
376 368
377 dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", 369 dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
378 status, status, linkstat); 370 status, status, linkstat);
@@ -383,7 +375,7 @@ static enum linkstat twl4030_usb_linkstat(struct twl4030_usb *twl)
383 375
384 spin_lock_irq(&twl->lock); 376 spin_lock_irq(&twl->lock);
385 twl->linkstat = linkstat; 377 twl->linkstat = linkstat;
386 if (linkstat == USB_LINK_ID) { 378 if (linkstat == USB_EVENT_ID) {
387 twl->otg.default_a = true; 379 twl->otg.default_a = true;
388 twl->otg.state = OTG_STATE_A_IDLE; 380 twl->otg.state = OTG_STATE_A_IDLE;
389 } else { 381 } else {
@@ -462,7 +454,7 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on)
462 * SLEEP. We work around this by clearing the bit after usv3v1 454 * SLEEP. We work around this by clearing the bit after usv3v1
463 * is re-activated. This ensures that VUSB3V1 is really active. 455 * is re-activated. This ensures that VUSB3V1 is really active.
464 */ 456 */
465 twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, 457 twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0,
466 VUSB_DEDICATED2); 458 VUSB_DEDICATED2);
467 regulator_enable(twl->usb1v5); 459 regulator_enable(twl->usb1v5);
468 pwr &= ~PHY_PWR_PHYPWD; 460 pwr &= ~PHY_PWR_PHYPWD;
@@ -505,44 +497,44 @@ static void twl4030_phy_resume(struct twl4030_usb *twl)
505static int twl4030_usb_ldo_init(struct twl4030_usb *twl) 497static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
506{ 498{
507 /* Enable writing to power configuration registers */ 499 /* Enable writing to power configuration registers */
508 twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY); 500 twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY);
509 twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0x0C, PROTECT_KEY); 501 twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0x0C, PROTECT_KEY);
510 502
511 /* put VUSB3V1 LDO in active state */ 503 /* put VUSB3V1 LDO in active state */
512 twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); 504 twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);
513 505
514 /* input to VUSB3V1 LDO is from VBAT, not VBUS */ 506 /* input to VUSB3V1 LDO is from VBAT, not VBUS */
515 twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); 507 twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);
516 508
517 /* Initialize 3.1V regulator */ 509 /* Initialize 3.1V regulator */
518 twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP); 510 twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
519 511
520 twl->usb3v1 = regulator_get(twl->dev, "usb3v1"); 512 twl->usb3v1 = regulator_get(twl->dev, "usb3v1");
521 if (IS_ERR(twl->usb3v1)) 513 if (IS_ERR(twl->usb3v1))
522 return -ENODEV; 514 return -ENODEV;
523 515
524 twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE); 516 twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);
525 517
526 /* Initialize 1.5V regulator */ 518 /* Initialize 1.5V regulator */
527 twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP); 519 twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);
528 520
529 twl->usb1v5 = regulator_get(twl->dev, "usb1v5"); 521 twl->usb1v5 = regulator_get(twl->dev, "usb1v5");
530 if (IS_ERR(twl->usb1v5)) 522 if (IS_ERR(twl->usb1v5))
531 goto fail1; 523 goto fail1;
532 524
533 twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE); 525 twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);
534 526
535 /* Initialize 1.8V regulator */ 527 /* Initialize 1.8V regulator */
536 twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP); 528 twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP);
537 529
538 twl->usb1v8 = regulator_get(twl->dev, "usb1v8"); 530 twl->usb1v8 = regulator_get(twl->dev, "usb1v8");
539 if (IS_ERR(twl->usb1v8)) 531 if (IS_ERR(twl->usb1v8))
540 goto fail2; 532 goto fail2;
541 533
542 twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); 534 twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);
543 535
544 /* disable access to power configuration registers */ 536 /* disable access to power configuration registers */
545 twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY); 537 twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY);
546 538
547 return 0; 539 return 0;
548 540
@@ -564,7 +556,7 @@ static ssize_t twl4030_usb_vbus_show(struct device *dev,
564 556
565 spin_lock_irqsave(&twl->lock, flags); 557 spin_lock_irqsave(&twl->lock, flags);
566 ret = sprintf(buf, "%s\n", 558 ret = sprintf(buf, "%s\n",
567 (twl->linkstat == USB_LINK_VBUS) ? "on" : "off"); 559 (twl->linkstat == USB_EVENT_VBUS) ? "on" : "off");
568 spin_unlock_irqrestore(&twl->lock, flags); 560 spin_unlock_irqrestore(&twl->lock, flags);
569 561
570 return ret; 562 return ret;
@@ -576,17 +568,8 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
576 struct twl4030_usb *twl = _twl; 568 struct twl4030_usb *twl = _twl;
577 int status; 569 int status;
578 570
579#ifdef CONFIG_LOCKDEP
580 /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
581 * we don't want and can't tolerate. Although it might be
582 * friendlier not to borrow this thread context...
583 */
584 local_irq_enable();
585#endif
586
587 status = twl4030_usb_linkstat(twl); 571 status = twl4030_usb_linkstat(twl);
588 if (status != USB_LINK_UNKNOWN) { 572 if (status >= 0) {
589
590 /* FIXME add a set_power() method so that B-devices can 573 /* FIXME add a set_power() method so that B-devices can
591 * configure the charger appropriately. It's not always 574 * configure the charger appropriately. It's not always
592 * correct to consume VBUS power, and how much current to 575 * correct to consume VBUS power, and how much current to
@@ -598,12 +581,13 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
598 * USB_LINK_VBUS state. musb_hdrc won't care until it 581 * USB_LINK_VBUS state. musb_hdrc won't care until it
599 * starts to handle softconnect right. 582 * starts to handle softconnect right.
600 */ 583 */
601 twl4030charger_usb_en(status == USB_LINK_VBUS); 584 if (status == USB_EVENT_NONE)
602
603 if (status == USB_LINK_NONE)
604 twl4030_phy_suspend(twl, 0); 585 twl4030_phy_suspend(twl, 0);
605 else 586 else
606 twl4030_phy_resume(twl); 587 twl4030_phy_resume(twl);
588
589 blocking_notifier_call_chain(&twl->otg.notifier, status,
590 twl->otg.gadget);
607 } 591 }
608 sysfs_notify(&twl->dev->kobj, NULL, "vbus"); 592 sysfs_notify(&twl->dev->kobj, NULL, "vbus");
609 593
@@ -693,6 +677,8 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
693 if (device_create_file(&pdev->dev, &dev_attr_vbus)) 677 if (device_create_file(&pdev->dev, &dev_attr_vbus))
694 dev_warn(&pdev->dev, "could not create sysfs file\n"); 678 dev_warn(&pdev->dev, "could not create sysfs file\n");
695 679
680 BLOCKING_INIT_NOTIFIER_HEAD(&twl->otg.notifier);
681
696 /* Our job is to use irqs and status from the power module 682 /* Our job is to use irqs and status from the power module
697 * to keep the transceiver disabled when nothing's connected. 683 * to keep the transceiver disabled when nothing's connected.
698 * 684 *
@@ -702,7 +688,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
702 * need both handles, otherwise just one suffices. 688 * need both handles, otherwise just one suffices.
703 */ 689 */
704 twl->irq_enabled = true; 690 twl->irq_enabled = true;
705 status = request_irq(twl->irq, twl4030_usb_irq, 691 status = request_threaded_irq(twl->irq, NULL, twl4030_usb_irq,
706 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, 692 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
707 "twl4030_usb", twl); 693 "twl4030_usb", twl);
708 if (status < 0) { 694 if (status < 0) {
diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c
new file mode 100644
index 000000000000..9010225e0d06
--- /dev/null
+++ b/drivers/usb/otg/ulpi.c
@@ -0,0 +1,137 @@
1/*
2 * Generic ULPI USB transceiver support
3 *
4 * Copyright (C) 2009 Daniel Mack <daniel@caiaq.de>
5 *
6 * Based on sources from
7 *
8 * Sascha Hauer <s.hauer@pengutronix.de>
9 * Freescale Semiconductors
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26#include <linux/kernel.h>
27#include <linux/slab.h>
28#include <linux/usb.h>
29#include <linux/usb/otg.h>
30#include <linux/usb/ulpi.h>
31
32/* ULPI register addresses */
33#define ULPI_VID_LOW 0x00 /* Vendor ID low */
34#define ULPI_VID_HIGH 0x01 /* Vendor ID high */
35#define ULPI_PID_LOW 0x02 /* Product ID low */
36#define ULPI_PID_HIGH 0x03 /* Product ID high */
37#define ULPI_ITFCTL 0x07 /* Interface Control */
38#define ULPI_OTGCTL 0x0A /* OTG Control */
39
40/* add to above register address to access Set/Clear functions */
41#define ULPI_REG_SET 0x01
42#define ULPI_REG_CLEAR 0x02
43
44/* ULPI OTG Control Register bits */
45#define ID_PULL_UP (1 << 0) /* enable ID Pull Up */
46#define DP_PULL_DOWN (1 << 1) /* enable DP Pull Down */
47#define DM_PULL_DOWN (1 << 2) /* enable DM Pull Down */
48#define DISCHRG_VBUS (1 << 3) /* Discharge Vbus */
49#define CHRG_VBUS (1 << 4) /* Charge Vbus */
50#define DRV_VBUS (1 << 5) /* Drive Vbus */
51#define DRV_VBUS_EXT (1 << 6) /* Drive Vbus external */
52#define USE_EXT_VBUS_IND (1 << 7) /* Use ext. Vbus indicator */
53
54#define ULPI_ID(vendor, product) (((vendor) << 16) | (product))
55
56#define TR_FLAG(flags, a, b) (((flags) & a) ? b : 0)
57
58/* ULPI hardcoded IDs, used for probing */
59static unsigned int ulpi_ids[] = {
60 ULPI_ID(0x04cc, 0x1504), /* NXP ISP1504 */
61};
62
63static int ulpi_set_flags(struct otg_transceiver *otg)
64{
65 unsigned int flags = 0;
66
67 if (otg->flags & USB_OTG_PULLUP_ID)
68 flags |= ID_PULL_UP;
69
70 if (otg->flags & USB_OTG_PULLDOWN_DM)
71 flags |= DM_PULL_DOWN;
72
73 if (otg->flags & USB_OTG_PULLDOWN_DP)
74 flags |= DP_PULL_DOWN;
75
76 if (otg->flags & USB_OTG_EXT_VBUS_INDICATOR)
77 flags |= USE_EXT_VBUS_IND;
78
79 return otg_io_write(otg, flags, ULPI_OTGCTL + ULPI_REG_SET);
80}
81
82static int ulpi_init(struct otg_transceiver *otg)
83{
84 int i, vid, pid;
85
86 vid = (otg_io_read(otg, ULPI_VID_HIGH) << 8) |
87 otg_io_read(otg, ULPI_VID_LOW);
88 pid = (otg_io_read(otg, ULPI_PID_HIGH) << 8) |
89 otg_io_read(otg, ULPI_PID_LOW);
90
91 pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
92
93 for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++)
94 if (ulpi_ids[i] == ULPI_ID(vid, pid))
95 return ulpi_set_flags(otg);
96
97 pr_err("ULPI ID does not match any known transceiver.\n");
98 return -ENODEV;
99}
100
101static int ulpi_set_vbus(struct otg_transceiver *otg, bool on)
102{
103 unsigned int flags = otg_io_read(otg, ULPI_OTGCTL);
104
105 flags &= ~(DRV_VBUS | DRV_VBUS_EXT);
106
107 if (on) {
108 if (otg->flags & USB_OTG_DRV_VBUS)
109 flags |= DRV_VBUS;
110
111 if (otg->flags & USB_OTG_DRV_VBUS_EXT)
112 flags |= DRV_VBUS_EXT;
113 }
114
115 return otg_io_write(otg, flags, ULPI_OTGCTL + ULPI_REG_SET);
116}
117
118struct otg_transceiver *
119otg_ulpi_create(struct otg_io_access_ops *ops,
120 unsigned int flags)
121{
122 struct otg_transceiver *otg;
123
124 otg = kzalloc(sizeof(*otg), GFP_KERNEL);
125 if (!otg)
126 return NULL;
127
128 otg->label = "ULPI";
129 otg->flags = flags;
130 otg->io_ops = ops;
131 otg->init = ulpi_init;
132 otg->set_vbus = ulpi_set_vbus;
133
134 return otg;
135}
136EXPORT_SYMBOL_GPL(otg_ulpi_create);
137