aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc3
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-03 14:36:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-03 14:36:27 -0400
commit1d1fdd95df681f0c065d90ffaafa215a0e8825e2 (patch)
tree19016e131bb5c7eb280a4cc8dff864ba36e53be4 /drivers/usb/dwc3
parentb3b49114c80e799af8b08c0c6d1ff886ea843f03 (diff)
parent3cc1f95283a125cf54ccf1e25065321d4385133b (diff)
Merge tag 'char-misc-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc patches from Greg KH: "Here is the big char/misc driver pull request for 3.12-rc1 Lots of driver updates all over the char/misc tree, full details in the shortlog" * tag 'char-misc-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (62 commits) drivers: uio: Kconfig: add MMU dependancy for UIO drivers: uio: Add driver for Humusoft MF624 DAQ PCI card drivers: uio_pdrv_genirq: use dev_get_platdata() drivers: uio_pruss: use dev_get_platdata() drivers: uio_dmem_genirq: use dev_get_platdata() drivers: parport: Kconfig: exclude h8300 for PARPORT_PC drivers: misc: ti-st: fix potential race if st_kim_start fails Drivers: hv: vmbus: Do not attempt to negoatiate a new version prematurely misc: vmw_balloon: Remove braces to fix build for clang. Drivers: hv: vmbus: Fix a bug in the handling of channel offers vme: vme_ca91cx42.c: fix to pass correct device identity to free_irq() VMCI: Add support for virtual IOMMU VMCI: Remove non-blocking/pinned queuepair support uio: uio_pruss: remove unnecessary platform_set_drvdata() parport: amiga: remove unnecessary platform_set_drvdata() vme: vme_vmivme7805.c: add missing __iomem annotation vme: vme_ca91cx42.c: add missing __iomem annotation vme: vme_tsi148.c: add missing __iomem annotation drivers/misc/hpilo: Correct panic when an AUX iLO is detected uio: drop unused vma_count member in uio_device struct ...
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r--drivers/usb/dwc3/Kconfig1
-rw-r--r--drivers/usb/dwc3/dwc3-omap.c125
2 files changed, 107 insertions, 19 deletions
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 3e225d5846f6..f969ea266acb 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -1,6 +1,7 @@
1config USB_DWC3 1config USB_DWC3
2 tristate "DesignWare USB3 DRD Core Support" 2 tristate "DesignWare USB3 DRD Core Support"
3 depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA 3 depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
4 depends on EXTCON
4 select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD 5 select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
5 help 6 help
6 Say Y or M here if your system has a Dual Role SuperSpeed 7 Say Y or M here if your system has a Dual Role SuperSpeed
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index ecd99451ee90..7f7ea62e961b 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -23,13 +23,15 @@
23#include <linux/spinlock.h> 23#include <linux/spinlock.h>
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25#include <linux/platform_data/dwc3-omap.h> 25#include <linux/platform_data/dwc3-omap.h>
26#include <linux/usb/dwc3-omap.h>
27#include <linux/pm_runtime.h> 26#include <linux/pm_runtime.h>
28#include <linux/dma-mapping.h> 27#include <linux/dma-mapping.h>
29#include <linux/ioport.h> 28#include <linux/ioport.h>
30#include <linux/io.h> 29#include <linux/io.h>
31#include <linux/of.h> 30#include <linux/of.h>
32#include <linux/of_platform.h> 31#include <linux/of_platform.h>
32#include <linux/extcon.h>
33#include <linux/extcon/of_extcon.h>
34#include <linux/regulator/consumer.h>
33 35
34#include <linux/usb/otg.h> 36#include <linux/usb/otg.h>
35 37
@@ -135,9 +137,21 @@ struct dwc3_omap {
135 u32 revision; 137 u32 revision;
136 138
137 u32 dma_status:1; 139 u32 dma_status:1;
140
141 struct extcon_specific_cable_nb extcon_vbus_dev;
142 struct extcon_specific_cable_nb extcon_id_dev;
143 struct notifier_block vbus_nb;
144 struct notifier_block id_nb;
145
146 struct regulator *vbus_reg;
138}; 147};
139 148
140static struct dwc3_omap *_omap; 149enum omap_dwc3_vbus_id_status {
150 OMAP_DWC3_ID_FLOAT,
151 OMAP_DWC3_ID_GROUND,
152 OMAP_DWC3_VBUS_OFF,
153 OMAP_DWC3_VBUS_VALID,
154};
141 155
142static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset) 156static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
143{ 157{
@@ -201,18 +215,24 @@ static void dwc3_omap_write_irq0_set(struct dwc3_omap *omap, u32 value)
201 omap->irq0_offset, value); 215 omap->irq0_offset, value);
202} 216}
203 217
204int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) 218static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
219 enum omap_dwc3_vbus_id_status status)
205{ 220{
206 u32 val; 221 int ret;
207 struct dwc3_omap *omap = _omap; 222 u32 val;
208
209 if (!omap)
210 return -EPROBE_DEFER;
211 223
212 switch (status) { 224 switch (status) {
213 case OMAP_DWC3_ID_GROUND: 225 case OMAP_DWC3_ID_GROUND:
214 dev_dbg(omap->dev, "ID GND\n"); 226 dev_dbg(omap->dev, "ID GND\n");
215 227
228 if (omap->vbus_reg) {
229 ret = regulator_enable(omap->vbus_reg);
230 if (ret) {
231 dev_dbg(omap->dev, "regulator enable failed\n");
232 return;
233 }
234 }
235
216 val = dwc3_omap_read_utmi_status(omap); 236 val = dwc3_omap_read_utmi_status(omap);
217 val &= ~(USBOTGSS_UTMI_OTG_STATUS_IDDIG 237 val &= ~(USBOTGSS_UTMI_OTG_STATUS_IDDIG
218 | USBOTGSS_UTMI_OTG_STATUS_VBUSVALID 238 | USBOTGSS_UTMI_OTG_STATUS_VBUSVALID
@@ -235,6 +255,9 @@ int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
235 break; 255 break;
236 256
237 case OMAP_DWC3_ID_FLOAT: 257 case OMAP_DWC3_ID_FLOAT:
258 if (omap->vbus_reg)
259 regulator_disable(omap->vbus_reg);
260
238 case OMAP_DWC3_VBUS_OFF: 261 case OMAP_DWC3_VBUS_OFF:
239 dev_dbg(omap->dev, "VBUS Disconnect\n"); 262 dev_dbg(omap->dev, "VBUS Disconnect\n");
240 263
@@ -248,12 +271,9 @@ int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
248 break; 271 break;
249 272
250 default: 273 default:
251 dev_dbg(omap->dev, "ID float\n"); 274 dev_dbg(omap->dev, "invalid state\n");
252 } 275 }
253
254 return 0;
255} 276}
256EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
257 277
258static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) 278static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
259{ 279{
@@ -346,6 +366,32 @@ static void dwc3_omap_disable_irqs(struct dwc3_omap *omap)
346 366
347static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32); 367static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32);
348 368
369static int dwc3_omap_id_notifier(struct notifier_block *nb,
370 unsigned long event, void *ptr)
371{
372 struct dwc3_omap *omap = container_of(nb, struct dwc3_omap, id_nb);
373
374 if (event)
375 dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
376 else
377 dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_FLOAT);
378
379 return NOTIFY_DONE;
380}
381
382static int dwc3_omap_vbus_notifier(struct notifier_block *nb,
383 unsigned long event, void *ptr)
384{
385 struct dwc3_omap *omap = container_of(nb, struct dwc3_omap, vbus_nb);
386
387 if (event)
388 dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
389 else
390 dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_OFF);
391
392 return NOTIFY_DONE;
393}
394
349static int dwc3_omap_probe(struct platform_device *pdev) 395static int dwc3_omap_probe(struct platform_device *pdev)
350{ 396{
351 struct device_node *node = pdev->dev.of_node; 397 struct device_node *node = pdev->dev.of_node;
@@ -353,6 +399,8 @@ static int dwc3_omap_probe(struct platform_device *pdev)
353 struct dwc3_omap *omap; 399 struct dwc3_omap *omap;
354 struct resource *res; 400 struct resource *res;
355 struct device *dev = &pdev->dev; 401 struct device *dev = &pdev->dev;
402 struct extcon_dev *edev;
403 struct regulator *vbus_reg = NULL;
356 404
357 int ret = -ENOMEM; 405 int ret = -ENOMEM;
358 int irq; 406 int irq;
@@ -393,19 +441,22 @@ static int dwc3_omap_probe(struct platform_device *pdev)
393 if (IS_ERR(base)) 441 if (IS_ERR(base))
394 return PTR_ERR(base); 442 return PTR_ERR(base);
395 443
444 if (of_property_read_bool(node, "vbus-supply")) {
445 vbus_reg = devm_regulator_get(dev, "vbus");
446 if (IS_ERR(vbus_reg)) {
447 dev_err(dev, "vbus init failed\n");
448 return PTR_ERR(vbus_reg);
449 }
450 }
451
396 spin_lock_init(&omap->lock); 452 spin_lock_init(&omap->lock);
397 453
398 omap->dev = dev; 454 omap->dev = dev;
399 omap->irq = irq; 455 omap->irq = irq;
400 omap->base = base; 456 omap->base = base;
457 omap->vbus_reg = vbus_reg;
401 dev->dma_mask = &dwc3_omap_dma_mask; 458 dev->dma_mask = &dwc3_omap_dma_mask;
402 459
403 /*
404 * REVISIT if we ever have two instances of the wrapper, we will be
405 * in big trouble
406 */
407 _omap = omap;
408
409 pm_runtime_enable(dev); 460 pm_runtime_enable(dev);
410 ret = pm_runtime_get_sync(dev); 461 ret = pm_runtime_get_sync(dev);
411 if (ret < 0) { 462 if (ret < 0) {
@@ -480,14 +531,46 @@ static int dwc3_omap_probe(struct platform_device *pdev)
480 531
481 dwc3_omap_enable_irqs(omap); 532 dwc3_omap_enable_irqs(omap);
482 533
534 if (of_property_read_bool(node, "extcon")) {
535 edev = of_extcon_get_extcon_dev(dev, 0);
536 if (IS_ERR(edev)) {
537 dev_vdbg(dev, "couldn't get extcon device\n");
538 ret = PTR_ERR(edev);
539 goto err2;
540 }
541
542 omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
543 ret = extcon_register_interest(&omap->extcon_vbus_dev,
544 edev->name, "USB", &omap->vbus_nb);
545 if (ret < 0)
546 dev_vdbg(dev, "failed to register notifier for USB\n");
547 omap->id_nb.notifier_call = dwc3_omap_id_notifier;
548 ret = extcon_register_interest(&omap->extcon_id_dev, edev->name,
549 "USB-HOST", &omap->id_nb);
550 if (ret < 0)
551 dev_vdbg(dev,
552 "failed to register notifier for USB-HOST\n");
553
554 if (extcon_get_cable_state(edev, "USB") == true)
555 dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
556 if (extcon_get_cable_state(edev, "USB-HOST") == true)
557 dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
558 }
559
483 ret = of_platform_populate(node, NULL, NULL, dev); 560 ret = of_platform_populate(node, NULL, NULL, dev);
484 if (ret) { 561 if (ret) {
485 dev_err(&pdev->dev, "failed to create dwc3 core\n"); 562 dev_err(&pdev->dev, "failed to create dwc3 core\n");
486 goto err2; 563 goto err3;
487 } 564 }
488 565
489 return 0; 566 return 0;
490 567
568err3:
569 if (omap->extcon_vbus_dev.edev)
570 extcon_unregister_interest(&omap->extcon_vbus_dev);
571 if (omap->extcon_id_dev.edev)
572 extcon_unregister_interest(&omap->extcon_id_dev);
573
491err2: 574err2:
492 dwc3_omap_disable_irqs(omap); 575 dwc3_omap_disable_irqs(omap);
493 576
@@ -504,6 +587,10 @@ static int dwc3_omap_remove(struct platform_device *pdev)
504{ 587{
505 struct dwc3_omap *omap = platform_get_drvdata(pdev); 588 struct dwc3_omap *omap = platform_get_drvdata(pdev);
506 589
590 if (omap->extcon_vbus_dev.edev)
591 extcon_unregister_interest(&omap->extcon_vbus_dev);
592 if (omap->extcon_id_dev.edev)
593 extcon_unregister_interest(&omap->extcon_id_dev);
507 dwc3_omap_disable_irqs(omap); 594 dwc3_omap_disable_irqs(omap);
508 pm_runtime_put_sync(&pdev->dev); 595 pm_runtime_put_sync(&pdev->dev);
509 pm_runtime_disable(&pdev->dev); 596 pm_runtime_disable(&pdev->dev);