Commit a9b8676c authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'dwc3-for-v3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next

Felipe writes:
	usb: dwc3: patches for v3.9 merge window

	We're saving some extra memory now by being a lot
	more conservative when allocating our event buffers.

	Our default HIRD threshold value was mistakenly set
	as one of the unsupported which would cause undefined
	behavior. Turns out that it broke OMAP5 ES2.0, so we're
	fixing it now by setting the maximum allowed HIRD
	threshold (12).

	Quite a few fixes to Isochronous transfers and scatter/gather
	support from Pratyush.

	We're also starting to support devicetree-based probe with
	the latest changes from Kishon.

	The usual set of cleanups also available: converting debugfs
	regdump utility to regsets, better "compatible" strings for
	Exynos platforms and the removal of the dependency for
	Host and Gadget; now dwc3 can be compiled host-only, device-only,
	and/or Dual-Role.
parents 46823498 52758bcb
config USB_DWC3 config USB_DWC3
tristate "DesignWare USB3 DRD Core Support" tristate "DesignWare USB3 DRD Core Support"
depends on (USB && USB_GADGET) depends on (USB || USB_GADGET)
select USB_OTG_UTILS select USB_OTG_UTILS
select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
help help
...@@ -12,6 +12,35 @@ config USB_DWC3 ...@@ -12,6 +12,35 @@ config USB_DWC3
if USB_DWC3 if USB_DWC3
choice
bool "DWC3 Mode Selection"
default USB_DWC3_DUAL_ROLE if (USB && USB_GADGET)
default USB_DWC3_HOST if (USB && !USB_GADGET)
default USB_DWC3_GADGET if (!USB && USB_GADGET)
config USB_DWC3_HOST
bool "Host only mode"
depends on USB
help
Select this when you want to use DWC3 in host mode only,
thereby the gadget feature will be regressed.
config USB_DWC3_GADGET
bool "Gadget only mode"
depends on USB_GADGET
help
Select this when you want to use DWC3 in gadget mode only,
thereby the host feature will be regressed.
config USB_DWC3_DUAL_ROLE
bool "Dual Role mode"
depends on (USB && USB_GADGET)
help
This is the default mode of working of DWC3 controller where
both host and gadget features are enabled.
endchoice
config USB_DWC3_DEBUG config USB_DWC3_DEBUG
bool "Enable Debugging Messages" bool "Enable Debugging Messages"
help help
......
...@@ -4,8 +4,14 @@ ccflags-$(CONFIG_USB_DWC3_VERBOSE) += -DVERBOSE_DEBUG ...@@ -4,8 +4,14 @@ ccflags-$(CONFIG_USB_DWC3_VERBOSE) += -DVERBOSE_DEBUG
obj-$(CONFIG_USB_DWC3) += dwc3.o obj-$(CONFIG_USB_DWC3) += dwc3.o
dwc3-y := core.o dwc3-y := core.o
dwc3-y += host.o
dwc3-y += gadget.o ep0.o ifneq ($(filter y,$(CONFIG_USB_DWC3_HOST) $(CONFIG_USB_DWC3_DUAL_ROLE)),)
dwc3-y += host.o
endif
ifneq ($(filter y,$(CONFIG_USB_DWC3_GADGET) $(CONFIG_USB_DWC3_DUAL_ROLE)),)
dwc3-y += gadget.o ep0.o
endif
ifneq ($(CONFIG_DEBUG_FS),) ifneq ($(CONFIG_DEBUG_FS),)
dwc3-y += debugfs.o dwc3-y += debugfs.o
......
...@@ -432,6 +432,9 @@ static int dwc3_probe(struct platform_device *pdev) ...@@ -432,6 +432,9 @@ static int dwc3_probe(struct platform_device *pdev)
return -EPROBE_DEFER; return -EPROBE_DEFER;
} }
usb_phy_set_suspend(dwc->usb2_phy, 0);
usb_phy_set_suspend(dwc->usb3_phy, 0);
spin_lock_init(&dwc->lock); spin_lock_init(&dwc->lock);
platform_set_drvdata(pdev, dwc); platform_set_drvdata(pdev, dwc);
...@@ -550,9 +553,9 @@ static int dwc3_probe(struct platform_device *pdev) ...@@ -550,9 +553,9 @@ static int dwc3_probe(struct platform_device *pdev)
static int dwc3_remove(struct platform_device *pdev) static int dwc3_remove(struct platform_device *pdev)
{ {
struct dwc3 *dwc = platform_get_drvdata(pdev); struct dwc3 *dwc = platform_get_drvdata(pdev);
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); usb_phy_set_suspend(dwc->usb2_phy, 1);
usb_phy_set_suspend(dwc->usb3_phy, 1);
pm_runtime_put(&pdev->dev); pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
......
...@@ -55,7 +55,9 @@ ...@@ -55,7 +55,9 @@
#define DWC3_ENDPOINTS_NUM 32 #define DWC3_ENDPOINTS_NUM 32
#define DWC3_XHCI_RESOURCES_NUM 2 #define DWC3_XHCI_RESOURCES_NUM 2
#define DWC3_EVENT_BUFFERS_SIZE PAGE_SIZE #define DWC3_EVENT_SIZE 4 /* bytes */
#define DWC3_EVENT_MAX_NUM 64 /* 2 events/endpoint */
#define DWC3_EVENT_BUFFERS_SIZE (DWC3_EVENT_SIZE * DWC3_EVENT_MAX_NUM)
#define DWC3_EVENT_TYPE_MASK 0xfe #define DWC3_EVENT_TYPE_MASK 0xfe
#define DWC3_EVENT_TYPE_DEV 0 #define DWC3_EVENT_TYPE_DEV 0
...@@ -405,7 +407,6 @@ struct dwc3_event_buffer { ...@@ -405,7 +407,6 @@ struct dwc3_event_buffer {
* @number: endpoint number (1 - 15) * @number: endpoint number (1 - 15)
* @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK
* @resource_index: Resource transfer index * @resource_index: Resource transfer index
* @current_uf: Current uf received through last event parameter
* @interval: the intervall on which the ISOC transfer is started * @interval: the intervall on which the ISOC transfer is started
* @name: a human readable name e.g. ep1out-bulk * @name: a human readable name e.g. ep1out-bulk
* @direction: true for TX, false for RX * @direction: true for TX, false for RX
...@@ -439,7 +440,6 @@ struct dwc3_ep { ...@@ -439,7 +440,6 @@ struct dwc3_ep {
u8 number; u8 number;
u8 type; u8 type;
u8 resource_index; u8 resource_index;
u16 current_uf;
u32 interval; u32 interval;
char name[20]; char name[20];
...@@ -581,6 +581,7 @@ struct dwc3_request { ...@@ -581,6 +581,7 @@ struct dwc3_request {
struct usb_request request; struct usb_request request;
struct list_head list; struct list_head list;
struct dwc3_ep *dep; struct dwc3_ep *dep;
u32 start_slot;
u8 epnum; u8 epnum;
struct dwc3_trb *trb; struct dwc3_trb *trb;
...@@ -721,6 +722,7 @@ struct dwc3 { ...@@ -721,6 +722,7 @@ struct dwc3 {
struct dwc3_hwparams hwparams; struct dwc3_hwparams hwparams;
struct dentry *root; struct dentry *root;
struct debugfs_regset32 *regset;
u8 test_mode; u8 test_mode;
u8 test_mode_nr; u8 test_mode_nr;
...@@ -862,10 +864,24 @@ union dwc3_event { ...@@ -862,10 +864,24 @@ union dwc3_event {
void dwc3_set_mode(struct dwc3 *dwc, u32 mode); void dwc3_set_mode(struct dwc3 *dwc, u32 mode);
int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc); int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc);
#if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
int dwc3_host_init(struct dwc3 *dwc); int dwc3_host_init(struct dwc3 *dwc);
void dwc3_host_exit(struct dwc3 *dwc); void dwc3_host_exit(struct dwc3 *dwc);
#else
static inline int dwc3_host_init(struct dwc3 *dwc)
{ return 0; }
static inline void dwc3_host_exit(struct dwc3 *dwc)
{ }
#endif
#if IS_ENABLED(CONFIG_USB_DWC3_GADGET) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
int dwc3_gadget_init(struct dwc3 *dwc); int dwc3_gadget_init(struct dwc3 *dwc);
void dwc3_gadget_exit(struct dwc3 *dwc); void dwc3_gadget_exit(struct dwc3 *dwc);
#else
static inline int dwc3_gadget_init(struct dwc3 *dwc)
{ return 0; }
static inline void dwc3_gadget_exit(struct dwc3 *dwc)
{ }
#endif
#endif /* __DRIVERS_USB_DWC3_CORE_H */ #endif /* __DRIVERS_USB_DWC3_CORE_H */
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
.offset = DWC3_ ##nm - DWC3_GLOBALS_REGS_START, \ .offset = DWC3_ ##nm - DWC3_GLOBALS_REGS_START, \
} }
static const struct debugfs_reg32 dwc3_regs[] = { static struct debugfs_reg32 dwc3_regs[] = {
dump_register(GSBUSCFG0), dump_register(GSBUSCFG0),
dump_register(GSBUSCFG1), dump_register(GSBUSCFG1),
dump_register(GTXTHRCFG), dump_register(GTXTHRCFG),
...@@ -376,27 +376,6 @@ static const struct debugfs_reg32 dwc3_regs[] = { ...@@ -376,27 +376,6 @@ static const struct debugfs_reg32 dwc3_regs[] = {
dump_register(OSTS), dump_register(OSTS),
}; };
static int dwc3_regdump_show(struct seq_file *s, void *unused)
{
struct dwc3 *dwc = s->private;
seq_printf(s, "DesignWare USB3 Core Register Dump\n");
debugfs_print_regs32(s, dwc3_regs, ARRAY_SIZE(dwc3_regs),
dwc->regs, "");
return 0;
}
static int dwc3_regdump_open(struct inode *inode, struct file *file)
{
return single_open(file, dwc3_regdump_show, inode->i_private);
}
static const struct file_operations dwc3_regdump_fops = {
.open = dwc3_regdump_open,
.read = seq_read,
.release = single_release,
};
static int dwc3_mode_show(struct seq_file *s, void *unused) static int dwc3_mode_show(struct seq_file *s, void *unused)
{ {
struct dwc3 *dwc = s->private; struct dwc3 *dwc = s->private;
...@@ -666,13 +645,23 @@ int dwc3_debugfs_init(struct dwc3 *dwc) ...@@ -666,13 +645,23 @@ int dwc3_debugfs_init(struct dwc3 *dwc)
dwc->root = root; dwc->root = root;
file = debugfs_create_file("regdump", S_IRUGO, root, dwc, dwc->regset = kzalloc(sizeof(*dwc->regset), GFP_KERNEL);
&dwc3_regdump_fops); if (!dwc->regset) {
ret = -ENOMEM;
goto err1;
}
dwc->regset->regs = dwc3_regs;
dwc->regset->nregs = ARRAY_SIZE(dwc3_regs);
dwc->regset->base = dwc->regs;
file = debugfs_create_regset32("regdump", S_IRUGO, root, dwc->regset);
if (!file) { if (!file) {
ret = -ENOMEM; ret = -ENOMEM;
goto err1; goto err1;
} }
#if IS_ENABLED(CONFIG_USB_DWC3_GADGET)
file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root, file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root,
dwc, &dwc3_mode_fops); dwc, &dwc3_mode_fops);
if (!file) { if (!file) {
...@@ -693,6 +682,7 @@ int dwc3_debugfs_init(struct dwc3 *dwc) ...@@ -693,6 +682,7 @@ int dwc3_debugfs_init(struct dwc3 *dwc)
ret = -ENOMEM; ret = -ENOMEM;
goto err1; goto err1;
} }
#endif
return 0; return 0;
......
...@@ -42,7 +42,7 @@ static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos) ...@@ -42,7 +42,7 @@ static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
memset(&pdata, 0x00, sizeof(pdata)); memset(&pdata, 0x00, sizeof(pdata));
pdev = platform_device_alloc("nop_usb_xceiv", 0); pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
if (!pdev) if (!pdev)
return -ENOMEM; return -ENOMEM;
...@@ -53,7 +53,7 @@ static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos) ...@@ -53,7 +53,7 @@ static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
if (ret) if (ret)
goto err1; goto err1;
pdev = platform_device_alloc("nop_usb_xceiv", 1); pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
if (!pdev) { if (!pdev) {
ret = -ENOMEM; ret = -ENOMEM;
goto err1; goto err1;
...@@ -95,13 +95,14 @@ static int dwc3_exynos_probe(struct platform_device *pdev) ...@@ -95,13 +95,14 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
struct platform_device *dwc3; struct platform_device *dwc3;
struct dwc3_exynos *exynos; struct dwc3_exynos *exynos;
struct clk *clk; struct clk *clk;
struct device *dev = &pdev->dev;
int ret = -ENOMEM; int ret = -ENOMEM;
exynos = kzalloc(sizeof(*exynos), GFP_KERNEL); exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);
if (!exynos) { if (!exynos) {
dev_err(&pdev->dev, "not enough memory\n"); dev_err(dev, "not enough memory\n");
goto err0; return -ENOMEM;
} }
/* /*
...@@ -116,30 +117,30 @@ static int dwc3_exynos_probe(struct platform_device *pdev) ...@@ -116,30 +117,30 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
ret = dwc3_exynos_register_phys(exynos); ret = dwc3_exynos_register_phys(exynos);
if (ret) { if (ret) {
dev_err(&pdev->dev, "couldn't register PHYs\n"); dev_err(dev, "couldn't register PHYs\n");
goto err1; return ret;
} }
dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO); dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
if (!dwc3) { if (!dwc3) {
dev_err(&pdev->dev, "couldn't allocate dwc3 device\n"); dev_err(dev, "couldn't allocate dwc3 device\n");
goto err1; return -ENOMEM;
} }
clk = clk_get(&pdev->dev, "usbdrd30"); clk = devm_clk_get(dev, "usbdrd30");
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(&pdev->dev, "couldn't get clock\n"); dev_err(dev, "couldn't get clock\n");
ret = -EINVAL; ret = -EINVAL;
goto err3; goto err1;
} }
dma_set_coherent_mask(&dwc3->dev, pdev->dev.coherent_dma_mask); dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask);
dwc3->dev.parent = &pdev->dev; dwc3->dev.parent = dev;
dwc3->dev.dma_mask = pdev->dev.dma_mask; dwc3->dev.dma_mask = dev->dma_mask;
dwc3->dev.dma_parms = pdev->dev.dma_parms; dwc3->dev.dma_parms = dev->dma_parms;
exynos->dwc3 = dwc3; exynos->dwc3 = dwc3;
exynos->dev = &pdev->dev; exynos->dev = dev;
exynos->clk = clk; exynos->clk = clk;
clk_enable(exynos->clk); clk_enable(exynos->clk);
...@@ -147,26 +148,23 @@ static int dwc3_exynos_probe(struct platform_device *pdev) ...@@ -147,26 +148,23 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
ret = platform_device_add_resources(dwc3, pdev->resource, ret = platform_device_add_resources(dwc3, pdev->resource,
pdev->num_resources); pdev->num_resources);
if (ret) { if (ret) {
dev_err(&pdev->dev, "couldn't add resources to dwc3 device\n"); dev_err(dev, "couldn't add resources to dwc3 device\n");
goto err4; goto err2;
} }
ret = platform_device_add(dwc3); ret = platform_device_add(dwc3);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to register dwc3 device\n"); dev_err(dev, "failed to register dwc3 device\n");
goto err4; goto err2;
} }
return 0; return 0;
err4: err2:
clk_disable(clk); clk_disable(clk);
clk_put(clk);
err3:
platform_device_put(dwc3);
err1: err1:
kfree(exynos); platform_device_put(dwc3);
err0:
return ret; return ret;
} }
...@@ -179,16 +177,13 @@ static int dwc3_exynos_remove(struct platform_device *pdev) ...@@ -179,16 +177,13 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
platform_device_unregister(exynos->usb3_phy); platform_device_unregister(exynos->usb3_phy);
clk_disable(exynos->clk); clk_disable(exynos->clk);
clk_put(exynos->clk);
kfree(exynos);
return 0; return 0;
} }
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id exynos_dwc3_match[] = { static const struct of_device_id exynos_dwc3_match[] = {
{ .compatible = "samsung,exynos-dwc3" }, { .compatible = "samsung,exynos5250-dwusb3" },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, exynos_dwc3_match); MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
......
...@@ -43,10 +43,13 @@ ...@@ -43,10 +43,13 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/platform_data/dwc3-omap.h> #include <linux/platform_data/dwc3-omap.h>
#include <linux/usb/dwc3-omap.h>
#include <linux/pm_runtime.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/usb/otg.h> #include <linux/usb/otg.h>
#include <linux/usb/nop-usb-xceiv.h> #include <linux/usb/nop-usb-xceiv.h>
...@@ -78,23 +81,6 @@ ...@@ -78,23 +81,6 @@
/* SYSCONFIG REGISTER */ /* SYSCONFIG REGISTER */
#define USBOTGSS_SYSCONFIG_DMADISABLE (1 << 16) #define USBOTGSS_SYSCONFIG_DMADISABLE (1 << 16)
#define USBOTGSS_SYSCONFIG_STANDBYMODE(x) ((x) << 4)
#define USBOTGSS_STANDBYMODE_FORCE_STANDBY 0
#define USBOTGSS_STANDBYMODE_NO_STANDBY 1
#define USBOTGSS_STANDBYMODE_SMART_STANDBY 2
#define USBOTGSS_STANDBYMODE_SMART_WAKEUP 3
#define USBOTGSS_STANDBYMODE_MASK (0x03 << 4)
#define USBOTGSS_SYSCONFIG_IDLEMODE(x) ((x) << 2)
#define USBOTGSS_IDLEMODE_FORCE_IDLE 0
#define USBOTGSS_IDLEMODE_NO_IDLE 1
#define USBOTGSS_IDLEMODE_SMART_IDLE 2
#define USBOTGSS_IDLEMODE_SMART_WAKEUP 3
#define USBOTGSS_IDLEMODE_MASK (0x03 << 2)
/* IRQ_EOI REGISTER */ /* IRQ_EOI REGISTER */
#define USBOTGSS_IRQ_EOI_LINE_NUMBER (1 << 0) #define USBOTGSS_IRQ_EOI_LINE_NUMBER (1 << 0)
...@@ -133,7 +119,6 @@ struct dwc3_omap { ...@@ -133,7 +119,6 @@ struct dwc3_omap {
/* device lock */ /* device lock */
spinlock_t lock; spinlock_t lock;
struct platform_device *dwc3;
struct platform_device *usb2_phy; struct platform_device *usb2_phy;
struct platform_device *usb3_phy; struct platform_device *usb3_phy;
struct device *dev; struct device *dev;
...@@ -147,6 +132,8 @@ struct dwc3_omap { ...@@ -147,6 +132,8 @@ struct dwc3_omap {
u32 dma_status:1; u32 dma_status:1;
}; };
struct dwc3_omap *_omap;
static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset) static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
{ {
return readl(base + offset); return readl(base + offset);
...@@ -157,6 +144,57 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value) ...@@ -157,6 +144,57 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
writel(value, base + offset); writel(value, base + offset);
} }
void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
{
u32 val;
struct dwc3_omap *omap = _omap;
switch (status) {
case OMAP_DWC3_ID_GROUND:
dev_dbg(omap->dev, "ID GND\n");
val = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
val &= ~(USBOTGSS_UTMI_OTG_STATUS_IDDIG
| USBOTGSS_UTMI_OTG_STATUS_VBUSVALID
| USBOTGSS_UTMI_OTG_STATUS_SESSEND);
val |= USBOTGSS_UTMI_OTG_STATUS_SESSVALID
| USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT;
dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, val);
break;
case OMAP_DWC3_VBUS_VALID:
dev_dbg(omap->dev, "VBUS Connect\n");
val = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
val &= ~USBOTGSS_UTMI_OTG_STATUS_SESSEND;
val |= USBOTGSS_UTMI_OTG_STATUS_IDDIG
| USBOTGSS_UTMI_OTG_STATUS_VBUSVALID
| USBOTGSS_UTMI_OTG_STATUS_SESSVALID
| USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT;
dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, val);
break;
case OMAP_DWC3_ID_FLOAT:
case OMAP_DWC3_VBUS_OFF:
dev_dbg(omap->dev, "VBUS Disconnect\n");
val = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
val &= ~(USBOTGSS_UTMI_OTG_STATUS_SESSVALID
| USBOTGSS_UTMI_OTG_STATUS_VBUSVALID
| USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT);
val |= USBOTGSS_UTMI_OTG_STATUS_SESSEND
| USBOTGSS_UTMI_OTG_STATUS_IDDIG;
dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, val);
break;
default:
dev_dbg(omap->dev, "ID float\n");
}
return;
}
EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
static int dwc3_omap_register_phys(struct dwc3_omap *omap) static int dwc3_omap_register_phys(struct dwc3_omap *omap)
{ {
struct nop_usb_xceiv_platform_data pdata; struct nop_usb_xceiv_platform_data pdata;
...@@ -165,7 +203,7 @@ static int dwc3_omap_register_phys(struct dwc3_omap *omap) ...@@ -165,7 +203,7 @@ static int dwc3_omap_register_phys(struct dwc3_omap *omap)
memset(&pdata, 0x00, sizeof(pdata)); memset(&pdata, 0x00, sizeof(pdata));
pdev = platform_device_alloc("nop_usb_xceiv", 0); pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
if (!pdev) if (!pdev)
return -ENOMEM; return -ENOMEM;
...@@ -176,7 +214,7 @@ static int dwc3_omap_register_phys(struct dwc3_omap *omap) ...@@ -176,7 +214,7 @@ static int dwc3_omap_register_phys(struct dwc3_omap *omap)
if (ret) if (ret)
goto err1; goto err1;
pdev = platform_device_alloc("nop_usb_xceiv", 1); pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
if (!pdev) { if (!pdev) {
ret = -ENOMEM; ret = -ENOMEM;
goto err1; goto err1;
...@@ -262,12 +300,20 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) ...@@ -262,12 +300,20 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int dwc3_omap_remove_core(struct device *dev, void *c)
{
struct platform_device *pdev = to_platform_device(dev);
platform_device_unregister(pdev);
return 0;
}
static int dwc3_omap_probe(struct platform_device *pdev) static int dwc3_omap_probe(struct platform_device *pdev)
{ {
struct dwc3_omap_data *pdata = pdev->dev.platform_data; struct dwc3_omap_data *pdata = pdev->dev.platform_data;
struct device_node *node = pdev->dev.of_node; struct device_node *node = pdev->dev.of_node;
struct platform_device *dwc3;
struct dwc3_omap *omap; struct dwc3_omap *omap;
struct resource *res; struct resource *res;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
...@@ -314,30 +360,32 @@ static int dwc3_omap_probe(struct platform_device *pdev) ...@@ -314,30 +360,32 @@ static int dwc3_omap_probe(struct platform_device *pdev)
return ret; return ret;
} }
dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
if (!dwc3) {
dev_err(dev, "couldn't allocate dwc3 device\n");
return -ENOMEM;
}
context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL); context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL);
if (!context) { if (!context) {
dev_err(dev, "couldn't allocate dwc3 context memory\n"); dev_err(dev, "couldn't allocate dwc3 context memory\n");
goto err2; return -ENOMEM;
} }
spin_lock_init(&omap->lock); spin_lock_init(&omap->lock);
dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask);
dwc3->dev.parent = dev;
dwc3->dev.dma_mask = dev->dma_mask;
dwc3->dev.dma_parms = dev->dma_parms;
omap->resource_size = resource_size(res); omap->resource_size = resource_size(res);
omap->context = context; omap->context = context;
omap->dev = dev; omap->dev = dev;
omap->irq = irq; omap->irq = irq;
omap->base = base; omap->base = base;
omap->dwc3 = dwc3;
/*
* REVISIT if we ever have two instances of the wrapper, we will be
* in big trouble
*/
_omap = omap;
pm_runtime_enable(dev);
ret = pm_runtime_get_sync(dev);
if (ret < 0) {
dev_err(dev, "get_sync failed with err %d\n", ret);
return ret;
}
reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS); reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
...@@ -368,21 +416,12 @@ static int dwc3_omap_probe(struct platform_device *pdev) ...@@ -368,21 +416,12 @@ static int dwc3_omap_probe(struct platform_device *pdev)
reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG); reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE); omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE);
/* Set No-Idle and No-Standby */
reg &= ~(USBOTGSS_STANDBYMODE_MASK
| USBOTGSS_IDLEMODE_MASK);
reg |= (USBOTGSS_SYSCONFIG_STANDBYMODE(USBOTGSS_STANDBYMODE_NO_STANDBY)
| USBOTGSS_SYSCONFIG_IDLEMODE(USBOTGSS_IDLEMODE_NO_IDLE));
dwc3_omap_writel(omap->base, USBOTGSS_SYSCONFIG, reg);
ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0, ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0,
"dwc3-omap", omap); "dwc3-omap", omap);
if (ret) { if (ret) {
dev_err(dev, "failed to request IRQ #%d --> %d\n", dev_err(dev, "failed to request IRQ #%d --> %d\n",
omap->irq, ret); omap->irq, ret);
goto err2; return ret;
} }
/* enable all IRQs */ /* enable all IRQs */
...@@ -401,33 +440,28 @@ static int dwc3_omap_probe(struct platform_device *pdev) ...@@ -401,33 +440,28 @@ static int dwc3_omap_probe(struct platform_device *pdev)
dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg); dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);
ret = platform_device_add_resources(dwc3, pdev->resource, if (node) {
pdev->num_resources); ret = of_platform_populate(node, NULL, NULL, dev);
if (ret) { if (ret) {
dev_err(dev, "couldn't add resources to dwc3 device\n"); dev_err(&pdev->dev,
goto err2; "failed to add create dwc3 core\n");
} return ret;
}
ret = platform_device_add(dwc3);
if (ret) {
dev_err(dev, "failed to register dwc3 device\n");
goto err2;
} }
return 0; return 0;
err2:
platform_device_put(dwc3);
return ret;
} }
static int dwc3_omap_remove(struct platform_device *pdev) static int dwc3_omap_remove(struct platform_device *pdev)
{ {
struct dwc3_omap *omap = platform_get_drvdata(pdev); struct dwc3_omap *omap = platform_get_drvdata(pdev);
platform_device_unregister(omap->dwc3);
platform_device_unregister(omap->usb2_phy); platform_device_unregister(omap->usb2_phy);
platform_device_unregister(omap->usb3_phy); platform_device_unregister(omap->usb3_phy);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
return 0; return 0;
} }
......
This diff is collapsed.
...@@ -44,7 +44,7 @@ int dwc3_host_init(struct dwc3 *dwc) ...@@ -44,7 +44,7 @@ int dwc3_host_init(struct dwc3 *dwc)
struct platform_device *xhci; struct platform_device *xhci;
int ret; int ret;
xhci = platform_device_alloc("xhci-hcd", -1); xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO);
if (!xhci) { if (!xhci) {
dev_err(dwc->dev, "couldn't allocate xHCI device\n"); dev_err(dwc->dev, "couldn't allocate xHCI device\n");
ret = -ENOMEM; ret = -ENOMEM;
......
/*
* Copyright (C) 2013 by Texas Instruments
*
* The Inventra Controller Driver for Linux is free software; you
* can redistribute it and/or modify it under the terms of the GNU
* General Public License version 2 as published by the Free Software
* Foundation.
*/
#ifndef __DWC3_OMAP_H__
#define __DWC3_OMAP_H__
enum omap_dwc3_vbus_id_status {
OMAP_DWC3_UNKNOWN = 0,
OMAP_DWC3_ID_GROUND,
OMAP_DWC3_ID_FLOAT,
OMAP_DWC3_VBUS_VALID,
OMAP_DWC3_VBUS_OFF,
};
#if (defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_DWC3_MODULE))
extern void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status);
#else
static inline void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
{
return;
}
#endif
#endif /* __DWC3_OMAP_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment