From: Dinh Nguyen <[email protected]>
Hello,
This is version 7 of the patch series that combines the dwc2 gadget and host
driver into a single dual role driver. Here are the main differences from V6:
- patch 1/8: Addressed Felipe's comment on which variables should not be just
limited to gadget(phy, uphy, regulator_bulk_data_supplies, irq, clk,
debug_root, debug_file, and debug_fifo).
- patch 2/8: Move conversion to use dev_pm_ops API to separate patch.
- patch 3/8: Convert to use dev_pm_ops API
- patch 4/8: Rebased to s3c_hsotg_core_init is now
s3c_hsotg_core_init_disconnected(), followed by s3c_hsotg_core_connect().
- patch 5/8: Use IRQF_SHARED to have s3c_hsotg_irq handle gadget interrupts.
Had to remove paulz's Acked-by for this patch, as it is not quite the same
patch when his ack was given.
- patch 6/8: Assign clk=NULL if a clock is not provided.
- patch 7/8: Moved ahead of Kconfig/Makefile patch to avoid a build error when
patch 8 is applied to dual-role.
- patch 8/8: none
For v7, the series is rebased on top of Felipe Balbi's tree on -next
branch. I thought this might be appropriate as there are dwc2 patches already
on this branch.
As usual, tested on SOCFPGA(host, gadget, and dual-role) and on Rpi-B
(host mode only).
I have pushed this series to a git repo to make it more convenient for people
to test/review.
git://git.rocketboards.org/linux-socfpga-next.git dwc2_dual_role_v7
Thanks,
Dinh Nguyen (8):
usb: dwc2: Update the gadget driver to use common dwc2_hsotg structure
usb: dwc2: Move gadget probe function into platform code
usb: dwc2: convert to use dev_pm_ops API
usb: dwc2: Initialize the USB core for peripheral mode
usb: dwc2: Update common interrupt handler to call gadget interrupt
handler
usb: dwc2: gadget: Do not fail probe if there isn't a clock node
usb: dwc2: move usb_disabled() call to host driver only
usb: dwc2: Update Kconfig to support dual-role
drivers/usb/dwc2/Kconfig | 66 ++++++-----
drivers/usb/dwc2/Makefile | 32 ++---
drivers/usb/dwc2/core.c | 10 --
drivers/usb/dwc2/core.h | 192 ++++++++++++++++++------------
drivers/usb/dwc2/core_intr.c | 8 +-
drivers/usb/dwc2/gadget.c | 274 ++++++++++++++-----------------------------
drivers/usb/dwc2/hcd.c | 6 +-
drivers/usb/dwc2/hcd.h | 10 --
drivers/usb/dwc2/pci.c | 7 ++
drivers/usb/dwc2/platform.c | 42 ++++++-
10 files changed, 317 insertions(+), 330 deletions(-)
--
2.0.3
From: Dinh Nguyen <[email protected]>
Update suspend/resume to use dev_pm_ops API.
Signed-off-by: Dinh Nguyen <[email protected]>
---
drivers/usb/dwc2/platform.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index eeba8a4..b94867b 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -219,9 +219,9 @@ static int dwc2_driver_probe(struct platform_device *dev)
return retval;
}
-static int dwc2_suspend(struct platform_device *dev, pm_message_t state)
+static int dwc2_suspend(struct device *dev)
{
- struct dwc2_hsotg *dwc2 = platform_get_drvdata(dev);
+ struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
int ret = 0;
if (dwc2_is_device_mode(dwc2))
@@ -229,9 +229,9 @@ static int dwc2_suspend(struct platform_device *dev, pm_message_t state)
return ret;
}
-static int dwc2_resume(struct platform_device *dev)
+static int dwc2_resume(struct device *dev)
{
- struct dwc2_hsotg *dwc2 = platform_get_drvdata(dev);
+ struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
int ret = 0;
if (dwc2_is_device_mode(dwc2))
@@ -239,15 +239,18 @@ static int dwc2_resume(struct platform_device *dev)
return ret;
}
+static const struct dev_pm_ops dwc2_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(dwc2_suspend, dwc2_resume)
+};
+
static struct platform_driver dwc2_platform_driver = {
.driver = {
.name = dwc2_driver_name,
.of_match_table = dwc2_of_match_table,
+ .pm = &dwc2_dev_pm_ops,
},
.probe = dwc2_driver_probe,
.remove = dwc2_driver_remove,
- .suspend = dwc2_suspend,
- .resume = dwc2_resume,
};
module_platform_driver(dwc2_platform_driver);
--
2.0.3
From: Dinh Nguyen <[email protected]>
Since platform.c will get built for both Host and Gadget, if we leave the
usb_disabled() call in platform.c, it results in the following build error
when (!USB && USB_GADGET) condition is met.
ERROR: "usb_disabled" [drivers/usb/dwc2/dwc2_platform.ko] undefined!
Since usb_disabled() is mostly used to disable USB host functionality, move
the call the host portion for the DWC2 driver.
Signed-off-by: Dinh Nguyen <[email protected]>
---
drivers/usb/dwc2/hcd.c | 3 +++
drivers/usb/dwc2/platform.c | 3 ---
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index fa60f4a..755e16b 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2780,6 +2780,9 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
int i, num_channels;
int retval;
+ if (usb_disabled())
+ return -ENODEV;
+
dev_dbg(hsotg->dev, "DWC OTG HCD INIT\n");
/* Detect config values from hardware */
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index 3552602..57eb8a3 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -157,9 +157,6 @@ static int dwc2_driver_probe(struct platform_device *dev)
int retval;
int irq;
- if (usb_disabled())
- return -ENODEV;
-
match = of_match_device(dwc2_of_match_table, &dev->dev);
if (match && match->data) {
params = match->data;
--
2.0.3
From: Dinh Nguyen <[email protected]>
Update DWC2 kconfig and makefile to support dual-role mode. The platform
file will always get compiled for the case where the controller is directly
connected to the CPU. So for loadable modules, dwc2.ko is built for host,
peripheral, and dual-role mode. The PCI bus interface will be called
dwc2_pci.ko and the platform interface module will be called dwc2_platform.ko.
Signed-off-by: Dinh Nguyen <[email protected]>
Acked-by: Paul Zimmerman <[email protected]>
---
v7: None
v6: Correct notes for USB_DWC2_DUAL_ROLE and USB_DWC2_PERIPHERAL
Remove extra default for USB_DWC2_PLATFORM and make it a condition for
building dwc2_platform.ko. In addition USB_DWC2_PLATFORM and USB_DWC2_PCI
are now tristate.
v5: dwc2.ko for all modes along with dwc2_platform.ko and dwc2_pci.ko will
get built for kernel modules.
v3: Add USB_GADGET=y and USB_GADGET=USB_DWC2 for peripheral and dual-role
config options.
v2: Remove reference to dwc2_gadget
---
drivers/usb/dwc2/Kconfig | 66 ++++++++++++++++++++++++++++-------------------
drivers/usb/dwc2/Makefile | 32 +++++++++++------------
2 files changed, 55 insertions(+), 43 deletions(-)
diff --git a/drivers/usb/dwc2/Kconfig b/drivers/usb/dwc2/Kconfig
index 4d02718..b323c4c 100644
--- a/drivers/usb/dwc2/Kconfig
+++ b/drivers/usb/dwc2/Kconfig
@@ -1,5 +1,5 @@
config USB_DWC2
- bool "DesignWare USB2 DRD Core Support"
+ tristate "DesignWare USB2 DRD Core Support"
depends on USB || USB_GADGET
help
Say Y here if your system has a Dual Role Hi-Speed USB
@@ -10,49 +10,61 @@ config USB_DWC2
bus interface module (if you have a PCI bus system) will be
called dwc2_pci.ko, and the platform interface module (for
controllers directly connected to the CPU) will be called
- dwc2_platform.ko. For gadget mode, there will be a single
- module called dwc2_gadget.ko.
-
- NOTE: The s3c-hsotg driver is now renamed to dwc2_gadget. The
- host and gadget drivers are still currently separate drivers.
- There are plans to merge the dwc2_gadget driver with the dwc2
- host driver in the near future to create a dual-role driver.
+ dwc2_platform.ko. For all modes(host, gadget and dual-role), there
+ will be an additional module named dwc2.ko.
if USB_DWC2
+choice
+ bool "DWC2 Mode Selection"
+ default USB_DWC2_DUAL_ROLE if (USB && USB_GADGET)
+ default USB_DWC2_HOST if (USB && !USB_GADGET)
+ default USB_DWC2_PERIPHERAL if (!USB && USB_GADGET)
+
config USB_DWC2_HOST
- tristate "Host only mode"
+ bool "Host only mode"
depends on USB
help
The Designware USB2.0 high-speed host controller
- integrated into many SoCs.
+ integrated into many SoCs. Select this option if you want the
+ driver to operate in Host-only mode.
-config USB_DWC2_PLATFORM
- bool "DWC2 Platform"
- depends on USB_DWC2_HOST
- default USB_DWC2_HOST
+comment "Gadget/Dual-role mode requires USB Gadget support to be enabled"
+
+config USB_DWC2_PERIPHERAL
+ bool "Gadget only mode"
+ depends on USB_GADGET=y || USB_GADGET=USB_DWC2
+ help
+ The Designware USB2.0 high-speed gadget controller
+ integrated into many SoCs. Select this option if you want the
+ driver to operate in Peripheral-only mode. This option requires
+ USB_GADGET to be enabled.
+
+config USB_DWC2_DUAL_ROLE
+ bool "Dual Role mode"
+ depends on (USB=y || USB=USB_DWC2) && (USB_GADGET=y || USB_GADGET=USB_DWC2)
help
- The Designware USB2.0 platform interface module for
- controllers directly connected to the CPU. This is only
- used for host mode.
+ Select this option if you want the driver to work in a dual-role
+ mode. In this mode both host and gadget features are enabled, and
+ the role will be determined by the cable that gets plugged-in. This
+ option requires USB_GADGET to be enabled.
+endchoice
+
+config USB_DWC2_PLATFORM
+ tristate "DWC2 Platform"
+ default USB_DWC2_HOST || USB_DWC2_PERIPHERAL
+ help
+ The Designware USB2.0 platform interface module for
+ controllers directly connected to the CPU.
config USB_DWC2_PCI
- bool "DWC2 PCI"
+ tristate "DWC2 PCI"
depends on USB_DWC2_HOST && PCI
default USB_DWC2_HOST
help
The Designware USB2.0 PCI interface module for controllers
connected to a PCI bus. This is only used for host mode.
-comment "Gadget mode requires USB Gadget support to be enabled"
-
-config USB_DWC2_PERIPHERAL
- tristate "Gadget only mode"
- depends on USB_GADGET
- help
- The Designware USB2.0 high-speed gadget controller
- integrated into many SoCs.
-
config USB_DWC2_DEBUG
bool "Enable Debugging Messages"
help
diff --git a/drivers/usb/dwc2/Makefile b/drivers/usb/dwc2/Makefile
index b73d2a5..8f75267 100644
--- a/drivers/usb/dwc2/Makefile
+++ b/drivers/usb/dwc2/Makefile
@@ -1,28 +1,28 @@
ccflags-$(CONFIG_USB_DWC2_DEBUG) += -DDEBUG
ccflags-$(CONFIG_USB_DWC2_VERBOSE) += -DVERBOSE_DEBUG
-obj-$(CONFIG_USB_DWC2_HOST) += dwc2.o
+obj-$(CONFIG_USB_DWC2) += dwc2.o
dwc2-y := core.o core_intr.o
-dwc2-y += hcd.o hcd_intr.o
-dwc2-y += hcd_queue.o hcd_ddma.o
+
+ifneq ($(filter y,$(CONFIG_USB_DWC2_HOST) $(CONFIG_USB_DWC2_DUAL_ROLE)),)
+ dwc2-y += hcd.o hcd_intr.o
+ dwc2-y += hcd_queue.o hcd_ddma.o
+endif
+
+ifneq ($(filter y,$(CONFIG_USB_DWC2_PERIPHERAL) $(CONFIG_USB_DWC2_DUAL_ROLE)),)
+ dwc2-y += gadget.o
+endif
# NOTE: The previous s3c-hsotg peripheral mode only driver has been moved to
# this location and renamed gadget.c. When building for dynamically linked
-# modules, dwc2_gadget.ko will get built for peripheral mode. For host mode,
-# the core module will be dwc2.ko, the PCI bus interface module will called
-# dwc2_pci.ko and the platform interface module will be called dwc2_platform.ko.
-# At present the host and gadget driver will be separate drivers, but there
-# are plans in the near future to create a dual-role driver.
+# modules, dwc2.ko will get built for host mode, peripheral mode, and dual-role
+# mode. The PCI bus interface module will called dwc2_pci.ko and the platform
+# interface module will be called dwc2_platform.ko.
ifneq ($(CONFIG_USB_DWC2_PCI),)
- obj-$(CONFIG_USB_DWC2_HOST) += dwc2_pci.o
+ obj-$(CONFIG_USB_DWC2) += dwc2_pci.o
dwc2_pci-y := pci.o
endif
-ifneq ($(CONFIG_USB_DWC2_PLATFORM),)
- obj-$(CONFIG_USB_DWC2_HOST) += dwc2_platform.o
- dwc2_platform-y := platform.o
-endif
-
-obj-$(CONFIG_USB_DWC2_PERIPHERAL) += dwc2_gadget.o
-dwc2_gadget-y := gadget.o
+obj-$(CONFIG_USB_DWC2_PLATFORM) += dwc2_platform.o
+dwc2_platform-y := platform.o
--
2.0.3
From: Dinh Nguyen <[email protected]>
This patch will aggregate the probing of gadget/hcd driver into platform.c.
The gadget probe funtion is converted into gadget_init that is now only
responsible for gadget only initialization. All the gadget resources are now
handled by platform.c
Since the host workqueue will not get initialized if the driver is configured
for peripheral mode only. Thus we need to check for wq_otg before calling
queue_work().
Also, we move spin_lock_init to common location for both host and gadget that
is either in platform.c or pci.c.
We also move suspend/resume code to common platform code.
Lastly, move the "samsung,s3c6400-hsotg" binding into dwc2_of_match_table.
Signed-off-by: Dinh Nguyen <[email protected]>
Acked-by: Paul Zimmerman <[email protected]>
---
v7: Move the conversion to use pm_ops to a separate patch
v6: None
v5: Reworked by squashing the following commits into this one:
* [PATCHv4 02/12] usb: dwc2: move "samsung,s3c6400-hsotg" into common platform
* [PATCHv4 03/12] usb: dwc2: Update the gadget driver to use common dwc2_hsotg
structure
* [PATCHv4 09/12] usb: dwc2: initialize the spin_lock for both host and gadget
* [PATCHv4 10/12] usb: dwc2: Add suspend/resume for gadget
* [PATCHv4 11/12] usb: dwc2: check that the host work queue is valid
Also use IS_ENABLED instead of #if defined
---
drivers/usb/dwc2/core.h | 33 +++++++++++++++
drivers/usb/dwc2/core_intr.c | 8 ++--
drivers/usb/dwc2/gadget.c | 99 ++++++++++----------------------------------
drivers/usb/dwc2/hcd.c | 1 -
drivers/usb/dwc2/hcd.h | 10 -----
drivers/usb/dwc2/pci.c | 1 +
drivers/usb/dwc2/platform.c | 28 +++++++++++++
7 files changed, 88 insertions(+), 92 deletions(-)
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 7bcdc10..4905d88 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -960,4 +960,37 @@ extern void dwc2_dump_global_registers(struct dwc2_hsotg *hsotg);
*/
extern u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg);
+/* Gadget defines */
+#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
+extern int s3c_hsotg_remove(struct dwc2_hsotg *hsotg);
+extern int s3c_hsotg_suspend(struct dwc2_hsotg *dwc2);
+extern int s3c_hsotg_resume(struct dwc2_hsotg *dwc2);
+extern int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq);
+#else
+static inline int s3c_hsotg_remove(struct dwc2_hsotg *dwc2)
+{ return 0; }
+static inline int s3c_hsotg_suspend(struct dwc2_hsotg *dwc2)
+{ return 0; }
+static inline int s3c_hsotg_resume(struct dwc2_hsotg *dwc2)
+{ return 0; }
+static inline int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
+{ return 0; }
+#endif
+
+#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
+extern int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg);
+extern void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg);
+extern void dwc2_hcd_start(struct dwc2_hsotg *hsotg);
+#else
+static inline void dwc2_set_all_params(struct dwc2_core_params *params, int value) {}
+static inline int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg)
+{ return 0; }
+static inline void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg) {}
+static inline void dwc2_hcd_start(struct dwc2_hsotg *hsotg) {}
+static inline void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) {}
+static inline int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
+ const struct dwc2_core_params *params)
+{ return 0; }
+#endif
+
#endif /* __DWC2_CORE_H__ */
diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index c93918b..b176c2f 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -287,9 +287,11 @@ static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
* Release lock before scheduling workq as it holds spinlock during
* scheduling.
*/
- spin_unlock(&hsotg->lock);
- queue_work(hsotg->wq_otg, &hsotg->wf_otg);
- spin_lock(&hsotg->lock);
+ if (hsotg->wq_otg) {
+ spin_unlock(&hsotg->lock);
+ queue_work(hsotg->wq_otg, &hsotg->wf_otg);
+ spin_lock(&hsotg->lock);
+ }
/* Clear interrupt */
writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 5a24e95..9caea51 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3423,26 +3423,21 @@ static void s3c_hsotg_delete_debug(struct dwc2_hsotg *hsotg)
}
/**
- * s3c_hsotg_probe - probe function for hsotg driver
- * @pdev: The platform information for the driver
+ * dwc2_gadget_init - init function for gadget
+ * @dwc2: The data structure for the DWC2 driver.
+ * @irq: The IRQ number for the controller.
*/
-static int s3c_hsotg_probe(struct platform_device *pdev)
+int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
{
- struct s3c_hsotg_plat *plat = dev_get_platdata(&pdev->dev);
+ struct device *dev = hsotg->dev;
+ struct s3c_hsotg_plat *plat = dev->platform_data;
struct phy *phy;
struct usb_phy *uphy;
- struct device *dev = &pdev->dev;
struct s3c_hsotg_ep *eps;
- struct dwc2_hsotg *hsotg;
- struct resource *res;
int epnum;
int ret;
int i;
- hsotg = devm_kzalloc(&pdev->dev, sizeof(struct dwc2_hsotg), GFP_KERNEL);
- if (!hsotg)
- return -ENOMEM;
-
/* Set default UTMI width */
hsotg->phyif = GUSBCFG_PHYIF16;
@@ -3450,14 +3445,14 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
* Attempt to find a generic PHY, then look for an old style
* USB PHY, finally fall back to pdata
*/
- phy = devm_phy_get(&pdev->dev, "usb2-phy");
+ phy = devm_phy_get(dev, "usb2-phy");
if (IS_ERR(phy)) {
uphy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
if (IS_ERR(uphy)) {
/* Fallback for pdata */
- plat = dev_get_platdata(&pdev->dev);
+ plat = dev_get_platdata(dev);
if (!plat) {
- dev_err(&pdev->dev,
+ dev_err(dev,
"no platform data or transceiver defined\n");
return -EPROBE_DEFER;
}
@@ -3474,36 +3469,12 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
hsotg->phyif = GUSBCFG_PHYIF8;
}
- hsotg->dev = dev;
-
- hsotg->clk = devm_clk_get(&pdev->dev, "otg");
+ hsotg->clk = devm_clk_get(dev, "otg");
if (IS_ERR(hsotg->clk)) {
dev_err(dev, "cannot get otg clock\n");
return PTR_ERR(hsotg->clk);
}
- platform_set_drvdata(pdev, hsotg);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- hsotg->regs = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(hsotg->regs)) {
- ret = PTR_ERR(hsotg->regs);
- goto err_clk;
- }
-
- ret = platform_get_irq(pdev, 0);
- if (ret < 0) {
- dev_err(dev, "cannot find IRQ\n");
- goto err_clk;
- }
-
- spin_lock_init(&hsotg->lock);
-
- hsotg->irq = ret;
-
- dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq);
-
hsotg->gadget.max_speed = USB_SPEED_HIGH;
hsotg->gadget.ops = &s3c_hsotg_gadget_ops;
hsotg->gadget.name = dev_name(dev);
@@ -3520,7 +3491,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies),
hsotg->supplies);
if (ret) {
- dev_err(hsotg->dev, "failed to request supplies: %d\n", ret);
+ dev_err(dev, "failed to request supplies: %d\n", ret);
goto err_clk;
}
@@ -3539,7 +3510,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
s3c_hsotg_hw_cfg(hsotg);
s3c_hsotg_init(hsotg);
- ret = devm_request_irq(&pdev->dev, hsotg->irq, s3c_hsotg_irq, 0,
+ ret = devm_request_irq(dev, irq, s3c_hsotg_irq, 0,
dev_name(dev), hsotg);
if (ret < 0) {
s3c_hsotg_phy_disable(hsotg);
@@ -3592,11 +3563,11 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
hsotg->supplies);
if (ret) {
- dev_err(&pdev->dev, "failed to disable supplies: %d\n", ret);
+ dev_err(dev, "failed to disable supplies: %d\n", ret);
goto err_ep_mem;
}
- ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget);
+ ret = usb_add_gadget_udc(dev, &hsotg->gadget);
if (ret)
goto err_ep_mem;
@@ -3615,25 +3586,24 @@ err_clk:
return ret;
}
+EXPORT_SYMBOL_GPL(dwc2_gadget_init);
/**
* s3c_hsotg_remove - remove function for hsotg driver
* @pdev: The platform information for the driver
*/
-static int s3c_hsotg_remove(struct platform_device *pdev)
+int s3c_hsotg_remove(struct dwc2_hsotg *hsotg)
{
- struct dwc2_hsotg *hsotg = platform_get_drvdata(pdev);
-
usb_del_gadget_udc(&hsotg->gadget);
s3c_hsotg_delete_debug(hsotg);
clk_disable_unprepare(hsotg->clk);
return 0;
}
+EXPORT_SYMBOL_GPL(s3c_hsotg_remove);
-static int s3c_hsotg_suspend(struct platform_device *pdev, pm_message_t state)
+int s3c_hsotg_suspend(struct dwc2_hsotg *hsotg)
{
- struct dwc2_hsotg *hsotg = platform_get_drvdata(pdev);
unsigned long flags;
int ret = 0;
@@ -3661,10 +3631,10 @@ static int s3c_hsotg_suspend(struct platform_device *pdev, pm_message_t state)
return ret;
}
+EXPORT_SYMBOL_GPL(s3c_hsotg_suspend);
-static int s3c_hsotg_resume(struct platform_device *pdev)
+int s3c_hsotg_resume(struct dwc2_hsotg *hsotg)
{
- struct dwc2_hsotg *hsotg = platform_get_drvdata(pdev);
unsigned long flags;
int ret = 0;
@@ -3686,31 +3656,4 @@ static int s3c_hsotg_resume(struct platform_device *pdev)
return ret;
}
-
-#ifdef CONFIG_OF
-static const struct of_device_id s3c_hsotg_of_ids[] = {
- { .compatible = "samsung,s3c6400-hsotg", },
- { .compatible = "snps,dwc2", },
- { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, s3c_hsotg_of_ids);
-#endif
-
-static struct platform_driver s3c_hsotg_driver = {
- .driver = {
- .name = "s3c-hsotg",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(s3c_hsotg_of_ids),
- },
- .probe = s3c_hsotg_probe,
- .remove = s3c_hsotg_remove,
- .suspend = s3c_hsotg_suspend,
- .resume = s3c_hsotg_resume,
-};
-
-module_platform_driver(s3c_hsotg_driver);
-
-MODULE_DESCRIPTION("Samsung S3C USB High-speed/OtG device");
-MODULE_AUTHOR("Ben Dooks <[email protected]>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:s3c-hsotg");
+EXPORT_SYMBOL_GPL(s3c_hsotg_resume);
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 0a0e6f0..4a3cce0 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2839,7 +2839,6 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
hcd->has_tt = 1;
- spin_lock_init(&hsotg->lock);
((struct wrapper_priv_data *) &hcd->hcd_priv)->hsotg = hsotg;
hsotg->priv = hcd;
diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h
index a12bb15..e69a843 100644
--- a/drivers/usb/dwc2/hcd.h
+++ b/drivers/usb/dwc2/hcd.h
@@ -668,9 +668,6 @@ extern irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hsotg);
*/
extern void dwc2_hcd_stop(struct dwc2_hsotg *hsotg);
-extern void dwc2_hcd_start(struct dwc2_hsotg *hsotg);
-extern void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg);
-
/**
* dwc2_hcd_is_b_host() - Returns 1 if core currently is acting as B host,
* and 0 otherwise
@@ -680,13 +677,6 @@ extern void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg);
extern int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg);
/**
- * dwc2_hcd_get_frame_number() - Returns current frame number
- *
- * @hsotg: The DWC2 HCD
- */
-extern int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg);
-
-/**
* dwc2_hcd_dump_state() - Dumps hsotg state
*
* @hsotg: The DWC2 HCD
diff --git a/drivers/usb/dwc2/pci.c b/drivers/usb/dwc2/pci.c
index c291fca..6d33ecf 100644
--- a/drivers/usb/dwc2/pci.c
+++ b/drivers/usb/dwc2/pci.c
@@ -141,6 +141,7 @@ static int dwc2_driver_probe(struct pci_dev *dev,
pci_set_master(dev);
+ spin_lock_init(&hsotg->lock);
retval = dwc2_hcd_init(hsotg, dev->irq, &dwc2_module_params);
if (retval) {
pci_disable_device(dev);
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index 121dbda..eeba8a4 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -121,6 +121,7 @@ static int dwc2_driver_remove(struct platform_device *dev)
struct dwc2_hsotg *hsotg = platform_get_drvdata(dev);
dwc2_hcd_remove(hsotg);
+ s3c_hsotg_remove(hsotg);
return 0;
}
@@ -129,6 +130,7 @@ static const struct of_device_id dwc2_of_match_table[] = {
{ .compatible = "brcm,bcm2835-usb", .data = ¶ms_bcm2835 },
{ .compatible = "rockchip,rk3066-usb", .data = ¶ms_rk3066 },
{ .compatible = "snps,dwc2", .data = NULL },
+ { .compatible = "samsung,s3c6400-hsotg", .data = NULL},
{},
};
MODULE_DEVICE_TABLE(of, dwc2_of_match_table);
@@ -204,6 +206,10 @@ static int dwc2_driver_probe(struct platform_device *dev)
hsotg->dr_mode = of_usb_get_dr_mode(dev->dev.of_node);
+ spin_lock_init(&hsotg->lock);
+ retval = dwc2_gadget_init(hsotg, irq);
+ if (retval)
+ return retval;
retval = dwc2_hcd_init(hsotg, irq, params);
if (retval)
return retval;
@@ -213,6 +219,26 @@ static int dwc2_driver_probe(struct platform_device *dev)
return retval;
}
+static int dwc2_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct dwc2_hsotg *dwc2 = platform_get_drvdata(dev);
+ int ret = 0;
+
+ if (dwc2_is_device_mode(dwc2))
+ ret = s3c_hsotg_suspend(dwc2);
+ return ret;
+}
+
+static int dwc2_resume(struct platform_device *dev)
+{
+ struct dwc2_hsotg *dwc2 = platform_get_drvdata(dev);
+ int ret = 0;
+
+ if (dwc2_is_device_mode(dwc2))
+ ret = s3c_hsotg_resume(dwc2);
+ return ret;
+}
+
static struct platform_driver dwc2_platform_driver = {
.driver = {
.name = dwc2_driver_name,
@@ -220,6 +246,8 @@ static struct platform_driver dwc2_platform_driver = {
},
.probe = dwc2_driver_probe,
.remove = dwc2_driver_remove,
+ .suspend = dwc2_suspend,
+ .resume = dwc2_resume,
};
module_platform_driver(dwc2_platform_driver);
--
2.0.3
From: Dinh Nguyen <[email protected]>
Since the dwc2 hcd driver is currently not looking for a clock node during
init, we should not completely fail if there isn't a clock provided.
By assigning clk = NULL, this allows the driver, when configured for dual-role
mode, to be able to continue loading the host portion of the driver when
a clock node is not specified.
Signed-off-by: Dinh Nguyen <[email protected]>
---
v7: Reworked to use clk=NULL and remove the need to is IS_ERR(clk)
v6: none
v5: reworked to not access gadget functions from the hcd.
---
drivers/usb/dwc2/gadget.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 37c7916..367689b 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3431,6 +3431,7 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
hsotg->clk = devm_clk_get(dev, "otg");
if (IS_ERR(hsotg->clk)) {
+ hsotg->clk = NULL;
dev_err(dev, "cannot get otg clock\n");
return PTR_ERR(hsotg->clk);
}
--
2.0.3
From: Dinh Nguyen <[email protected]>
Make dwc2_handle_common_intr call the gadget interrupt function when operating
in peripheral mode. Remove the spinlock functions in s3c_hsotg_irq as
dwc2_handle_common_intr() already has the spinlocks.
Move the registeration of the IRQ to common code for platform and PCI.
Remove duplicate interrupt conditions that was in gadget, as those are handled
by dwc2 common interrupt handler.
Signed-off-by: Dinh Nguyen <[email protected]>
---
v7: Use IRQF_SHARED
v5: remove individual devm_request_irq from gadget and hcd, and place a
single devm_request_irq in platform and pci.
v2: Keep interrupt handler for host and peripheral modes separate
---
drivers/usb/dwc2/core.c | 10 ----------
drivers/usb/dwc2/gadget.c | 46 +++------------------------------------------
drivers/usb/dwc2/pci.c | 6 ++++++
drivers/usb/dwc2/platform.c | 8 ++++++++
4 files changed, 17 insertions(+), 53 deletions(-)
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index d926945..7605850b 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -458,16 +458,6 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq)
/* Clear the SRP success bit for FS-I2c */
hsotg->srp_success = 0;
- if (irq >= 0) {
- dev_dbg(hsotg->dev, "registering common handler for irq%d\n",
- irq);
- retval = devm_request_irq(hsotg->dev, irq,
- dwc2_handle_common_intr, IRQF_SHARED,
- dev_name(hsotg->dev), hsotg);
- if (retval)
- return retval;
- }
-
/* Enable common interrupts */
dwc2_enable_common_interrupts(hsotg);
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index ec85340..37c7916 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2285,33 +2285,12 @@ irq_retry:
gintsts &= gintmsk;
- if (gintsts & GINTSTS_OTGINT) {
- u32 otgint = readl(hsotg->regs + GOTGINT);
-
- dev_info(hsotg->dev, "OTGInt: %08x\n", otgint);
-
- writel(otgint, hsotg->regs + GOTGINT);
- }
-
- if (gintsts & GINTSTS_SESSREQINT) {
- dev_dbg(hsotg->dev, "%s: SessReqInt\n", __func__);
- writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
- }
-
if (gintsts & GINTSTS_ENUMDONE) {
writel(GINTSTS_ENUMDONE, hsotg->regs + GINTSTS);
s3c_hsotg_irq_enumdone(hsotg);
}
- if (gintsts & GINTSTS_CONIDSTSCHNG) {
- dev_dbg(hsotg->dev, "ConIDStsChg (DSTS=0x%08x, GOTCTL=%08x)\n",
- readl(hsotg->regs + DSTS),
- readl(hsotg->regs + GOTGCTL));
-
- writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
- }
-
if (gintsts & (GINTSTS_OEPINT | GINTSTS_IEPINT)) {
u32 daint = readl(hsotg->regs + DAINT);
u32 daintmsk = readl(hsotg->regs + DAINTMSK);
@@ -2392,25 +2371,6 @@ irq_retry:
s3c_hsotg_handle_rx(hsotg);
}
- if (gintsts & GINTSTS_MODEMIS) {
- dev_warn(hsotg->dev, "warning, mode mismatch triggered\n");
- writel(GINTSTS_MODEMIS, hsotg->regs + GINTSTS);
- }
-
- if (gintsts & GINTSTS_USBSUSP) {
- dev_info(hsotg->dev, "GINTSTS_USBSusp\n");
- writel(GINTSTS_USBSUSP, hsotg->regs + GINTSTS);
-
- call_gadget(hsotg, suspend);
- }
-
- if (gintsts & GINTSTS_WKUPINT) {
- dev_info(hsotg->dev, "GINTSTS_WkUpIn\n");
- writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS);
-
- call_gadget(hsotg, resume);
- }
-
if (gintsts & GINTSTS_ERLYSUSP) {
dev_dbg(hsotg->dev, "GINTSTS_ErlySusp\n");
writel(GINTSTS_ERLYSUSP, hsotg->regs + GINTSTS);
@@ -3510,14 +3470,14 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
s3c_hsotg_hw_cfg(hsotg);
s3c_hsotg_init(hsotg);
- ret = devm_request_irq(dev, irq, s3c_hsotg_irq, 0,
- dev_name(dev), hsotg);
+ ret = devm_request_irq(hsotg->dev, irq, s3c_hsotg_irq, IRQF_SHARED,
+ dev_name(hsotg->dev), hsotg);
if (ret < 0) {
s3c_hsotg_phy_disable(hsotg);
clk_disable_unprepare(hsotg->clk);
regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
hsotg->supplies);
- dev_err(dev, "cannot claim IRQ\n");
+ dev_err(dev, "cannot claim IRQ for gadget\n");
goto err_clk;
}
diff --git a/drivers/usb/dwc2/pci.c b/drivers/usb/dwc2/pci.c
index 6d33ecf..a4e724b 100644
--- a/drivers/usb/dwc2/pci.c
+++ b/drivers/usb/dwc2/pci.c
@@ -141,6 +141,12 @@ static int dwc2_driver_probe(struct pci_dev *dev,
pci_set_master(dev);
+ retval = devm_request_irq(hsotg->dev, dev->irq,
+ dwc2_handle_common_intr, IRQF_SHARED,
+ dev_name(hsotg->dev), hsotg);
+ if (retval)
+ return retval;
+
spin_lock_init(&hsotg->lock);
retval = dwc2_hcd_init(hsotg, dev->irq, &dwc2_module_params);
if (retval) {
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index b94867b..3552602 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -196,6 +196,14 @@ static int dwc2_driver_probe(struct platform_device *dev)
return irq;
}
+ dev_dbg(hsotg->dev, "registering common handler for irq%d\n",
+ irq);
+ retval = devm_request_irq(hsotg->dev, irq,
+ dwc2_handle_common_intr, IRQF_SHARED,
+ dev_name(hsotg->dev), hsotg);
+ if (retval)
+ return retval;
+
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
hsotg->regs = devm_ioremap_resource(&dev->dev, res);
if (IS_ERR(hsotg->regs))
--
2.0.3
From: Dinh Nguyen <[email protected]>
Initialize the USB driver to peripheral mode when a B-Device connector
is attached.
Signed-off-by: Dinh Nguyen <[email protected]>
Acked-by: Paul Zimmerman <[email protected]>
---
v7: s3c_hsotg_core_init became s3c_hsotg_core_init_disconnected
v5: move the export of s3c_hsotg_core_init into this patch
---
drivers/usb/dwc2/core.h | 4 ++++
drivers/usb/dwc2/gadget.c | 4 ++--
drivers/usb/dwc2/hcd.c | 2 ++
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 4905d88..4710935 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -966,6 +966,8 @@ extern int s3c_hsotg_remove(struct dwc2_hsotg *hsotg);
extern int s3c_hsotg_suspend(struct dwc2_hsotg *dwc2);
extern int s3c_hsotg_resume(struct dwc2_hsotg *dwc2);
extern int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq);
+extern void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2);
+extern void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg);
#else
static inline int s3c_hsotg_remove(struct dwc2_hsotg *dwc2)
{ return 0; }
@@ -975,6 +977,8 @@ static inline int s3c_hsotg_resume(struct dwc2_hsotg *dwc2)
{ return 0; }
static inline int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
{ return 0; }
+static inline void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2) {}
+static inline void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg) {}
#endif
#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 9caea51..ec85340 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2125,7 +2125,7 @@ static int s3c_hsotg_corereset(struct dwc2_hsotg *hsotg)
*
* Issue a soft reset to the core, and await the core finishing it.
*/
-static void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg)
+void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg)
{
s3c_hsotg_corereset(hsotg);
@@ -2257,7 +2257,7 @@ static void s3c_hsotg_core_disconnect(struct dwc2_hsotg *hsotg)
__orr32(hsotg->regs + DCTL, DCTL_SFTDISCON);
}
-static void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg)
+void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg)
{
/* remove the soft-disconnect and let's go */
__bic32(hsotg->regs + DCTL, DCTL_SFTDISCON);
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 4a3cce0..fa60f4a 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1371,6 +1371,8 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
hsotg->op_state = OTG_STATE_B_PERIPHERAL;
dwc2_core_init(hsotg, false, -1);
dwc2_enable_global_interrupts(hsotg);
+ s3c_hsotg_core_init_disconnected(hsotg);
+ s3c_hsotg_core_connect(hsotg);
} else {
/* A-Device connector (Host Mode) */
dev_dbg(hsotg->dev, "connId A\n");
--
2.0.3
From: Dinh Nguyen <[email protected]>
Adds the gadget data structure and appropriate data structure pointers
to the common dwc2_hsotg data structure. To keep the driver data
dereference code looking clean, the gadget variable declares are only available
for peripheral and dual-role mode. This is needed so that the dwc2_hsotg data
structure can be used by the hcd and gadget drivers.
Updates gadget.c to use the dwc2_hsotg data structure and gadget pointers
that have been moved into the common dwc2_hsotg structure.
Signed-off-by: Dinh Nguyen <[email protected]>
Signed-off-by: Paul Zimmerman <[email protected]>
---
v7: Addressed comments from Felipe Balbi on which variables should not be just
limited to gadget(phy, uphy, regulator_bulk_data_supplies, irq, clk,
debug_root, debug_file, and debug_fifo).
v6: None
v5: Keep the changes to mininum and maintain hcd and gadget driver to build
and work separately. Use IS_ENABLED() instead of #if defined
v3: Updated with paulz's suggestion to avoid double pointers.
v2: Left the function parameter name as 'hsotg' and just changed its type.
---
drivers/usb/dwc2/core.h | 155 ++++++++++++++++++++++++----------------------
drivers/usb/dwc2/gadget.c | 146 +++++++++++++++++++++----------------------
2 files changed, 153 insertions(+), 148 deletions(-)
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 55c90c5..7bcdc10 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -84,7 +84,7 @@ static const char * const s3c_hsotg_supply_names[] = {
*/
#define EP0_MPS_LIMIT 64
-struct s3c_hsotg;
+struct dwc2_hsotg;
struct s3c_hsotg_req;
/**
@@ -130,7 +130,7 @@ struct s3c_hsotg_req;
struct s3c_hsotg_ep {
struct usb_ep ep;
struct list_head queue;
- struct s3c_hsotg *parent;
+ struct dwc2_hsotg *parent;
struct s3c_hsotg_req *req;
struct dentry *debugfs;
@@ -155,67 +155,6 @@ struct s3c_hsotg_ep {
};
/**
- * struct s3c_hsotg - driver state.
- * @dev: The parent device supplied to the probe function
- * @driver: USB gadget driver
- * @phy: The otg phy transceiver structure for phy control.
- * @uphy: The otg phy transceiver structure for old USB phy control.
- * @plat: The platform specific configuration data. This can be removed once
- * all SoCs support usb transceiver.
- * @regs: The memory area mapped for accessing registers.
- * @irq: The IRQ number we are using
- * @supplies: Definition of USB power supplies
- * @phyif: PHY interface width
- * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos.
- * @num_of_eps: Number of available EPs (excluding EP0)
- * @debug_root: root directrory for debugfs.
- * @debug_file: main status file for debugfs.
- * @debug_fifo: FIFO status file for debugfs.
- * @ep0_reply: Request used for ep0 reply.
- * @ep0_buff: Buffer for EP0 reply data, if needed.
- * @ctrl_buff: Buffer for EP0 control requests.
- * @ctrl_req: Request for EP0 control packets.
- * @setup: NAK management for EP0 SETUP
- * @last_rst: Time of last reset
- * @eps: The endpoints being supplied to the gadget framework
- */
-struct s3c_hsotg {
- struct device *dev;
- struct usb_gadget_driver *driver;
- struct phy *phy;
- struct usb_phy *uphy;
- struct s3c_hsotg_plat *plat;
-
- spinlock_t lock;
-
- void __iomem *regs;
- int irq;
- struct clk *clk;
-
- struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsotg_supply_names)];
-
- u32 phyif;
- int fifo_mem;
- unsigned int dedicated_fifos:1;
- unsigned char num_of_eps;
- u32 fifo_map;
-
- struct dentry *debug_root;
- struct dentry *debug_file;
- struct dentry *debug_fifo;
-
- struct usb_request *ep0_reply;
- struct usb_request *ctrl_req;
- u8 ep0_buff[8];
- u8 ctrl_buff[8];
-
- struct usb_gadget gadget;
- unsigned int setup;
- unsigned long last_rst;
- struct s3c_hsotg_ep *eps;
-};
-
-/**
* struct s3c_hsotg_req - data transfer request
* @req: The USB gadget request
* @queue: The list of requests for the endpoint this is queued for.
@@ -229,6 +168,7 @@ struct s3c_hsotg_req {
unsigned char mapped;
};
+#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
#define call_gadget(_hs, _entry) \
do { \
if ((_hs)->gadget.speed != USB_SPEED_UNKNOWN && \
@@ -238,6 +178,9 @@ do { \
spin_lock(&_hs->lock); \
} \
} while (0)
+#else
+#define call_gadget(_hs, _entry) do {} while (0)
+#endif
struct dwc2_hsotg;
struct dwc2_host_chan;
@@ -495,11 +438,13 @@ struct dwc2_hw_params {
* struct dwc2_hsotg - Holds the state of the driver, including the non-periodic
* and periodic schedules
*
+ * These are common for both host and peripheral modes:
+ *
* @dev: The struct device pointer
* @regs: Pointer to controller regs
- * @core_params: Parameters that define how the core should be configured
* @hw_params: Parameters that were autodetected from the
* hardware registers
+ * @core_params: Parameters that define how the core should be configured
* @op_state: The operational State, during transitions (a_host=>
* a_peripheral and b_device=>b_host) this may not match
* the core, but allows the software to determine
@@ -508,6 +453,8 @@ struct dwc2_hw_params {
* - USB_DR_MODE_PERIPHERAL
* - USB_DR_MODE_HOST
* - USB_DR_MODE_OTG
+ * @lock: Spinlock that protects all the driver data structures
+ * @priv: Stores a pointer to the struct usb_hcd
* @queuing_high_bandwidth: True if multiple packets of a high-bandwidth
* transfer are in process of being queued
* @srp_success: Stores status of SRP request in the case of a FS PHY
@@ -517,6 +464,9 @@ struct dwc2_hw_params {
* interrupt
* @wkp_timer: Timer object for handling Wakeup Detected interrupt
* @lx_state: Lx state of connected device
+ *
+ * These are for host mode:
+ *
* @flags: Flags for handling root port state changes
* @non_periodic_sched_inactive: Inactive QHs in the non-periodic schedule.
* Transfers associated with these QHs are not currently
@@ -585,11 +535,31 @@ struct dwc2_hw_params {
* @status_buf_dma: DMA address for status_buf
* @start_work: Delayed work for handling host A-cable connection
* @reset_work: Delayed work for handling a port reset
- * @lock: Spinlock that protects all the driver data structures
- * @priv: Stores a pointer to the struct usb_hcd
* @otg_port: OTG port number
* @frame_list: Frame list
* @frame_list_dma: Frame list DMA address
+ *
+ * These are for peripheral mode:
+ *
+ * @driver: USB gadget driver
+ * @phy: The otg phy transceiver structure for phy control.
+ * @uphy: The otg phy transceiver structure for old USB phy control.
+ * @plat: The platform specific configuration data. This can be removed once
+ * all SoCs support usb transceiver.
+ * @supplies: Definition of USB power supplies
+ * @phyif: PHY interface width
+ * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos.
+ * @num_of_eps: Number of available EPs (excluding EP0)
+ * @debug_root: Root directrory for debugfs.
+ * @debug_file: Main status file for debugfs.
+ * @debug_fifo: FIFO status file for debugfs.
+ * @ep0_reply: Request used for ep0 reply.
+ * @ep0_buff: Buffer for EP0 reply data, if needed.
+ * @ctrl_buff: Buffer for EP0 control requests.
+ * @ctrl_req: Request for EP0 control packets.
+ * @setup: NAK management for EP0 SETUP
+ * @last_rst: Time of last reset
+ * @eps: The endpoints being supplied to the gadget framework
*/
struct dwc2_hsotg {
struct device *dev;
@@ -601,6 +571,15 @@ struct dwc2_hsotg {
enum usb_otg_state op_state;
enum usb_dr_mode dr_mode;
+ struct phy *phy;
+ struct usb_phy *uphy;
+ struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsotg_supply_names)];
+
+ spinlock_t lock;
+ void *priv;
+ int irq;
+ struct clk *clk;
+
unsigned int queuing_high_bandwidth:1;
unsigned int srp_success:1;
@@ -609,6 +588,18 @@ struct dwc2_hsotg {
struct timer_list wkp_timer;
enum dwc2_lx_state lx_state;
+ struct dentry *debug_root;
+ struct dentry *debug_file;
+ struct dentry *debug_fifo;
+
+ /* DWC OTG HW Release versions */
+#define DWC2_CORE_REV_2_71a 0x4f54271a
+#define DWC2_CORE_REV_2_90a 0x4f54290a
+#define DWC2_CORE_REV_2_92a 0x4f54292a
+#define DWC2_CORE_REV_2_94a 0x4f54294a
+#define DWC2_CORE_REV_3_00a 0x4f54300a
+
+#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
union dwc2_hcd_internal_flags {
u32 d32;
struct {
@@ -655,19 +646,10 @@ struct dwc2_hsotg {
struct delayed_work start_work;
struct delayed_work reset_work;
- spinlock_t lock;
- void *priv;
u8 otg_port;
u32 *frame_list;
dma_addr_t frame_list_dma;
- /* DWC OTG HW Release versions */
-#define DWC2_CORE_REV_2_71a 0x4f54271a
-#define DWC2_CORE_REV_2_90a 0x4f54290a
-#define DWC2_CORE_REV_2_92a 0x4f54292a
-#define DWC2_CORE_REV_2_94a 0x4f54294a
-#define DWC2_CORE_REV_3_00a 0x4f54300a
-
#ifdef DEBUG
u32 frrem_samples;
u64 frrem_accum;
@@ -686,6 +668,29 @@ struct dwc2_hsotg {
u32 hfnum_other_samples_b;
u64 hfnum_other_frrem_accum_b;
#endif
+#endif /* CONFIG_USB_DWC2_HOST || CONFIG_USB_DWC2_DUAL_ROLE */
+
+#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
+ /* Gadget structures */
+ struct usb_gadget_driver *driver;
+ struct s3c_hsotg_plat *plat;
+
+ u32 phyif;
+ int fifo_mem;
+ unsigned int dedicated_fifos:1;
+ unsigned char num_of_eps;
+ u32 fifo_map;
+
+ struct usb_request *ep0_reply;
+ struct usb_request *ctrl_req;
+ u8 ep0_buff[8];
+ u8 ctrl_buff[8];
+
+ struct usb_gadget gadget;
+ unsigned int setup;
+ unsigned long last_rst;
+ struct s3c_hsotg_ep *eps;
+#endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */
};
/* Reasons for halting a host channel */
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index fcd2bb5..5a24e95 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -36,6 +36,7 @@
#include <linux/platform_data/s3c-hsotg.h>
#include "core.h"
+#include "hw.h"
/* conversion functions */
static inline struct s3c_hsotg_req *our_req(struct usb_request *req)
@@ -48,9 +49,9 @@ static inline struct s3c_hsotg_ep *our_ep(struct usb_ep *ep)
return container_of(ep, struct s3c_hsotg_ep, ep);
}
-static inline struct s3c_hsotg *to_hsotg(struct usb_gadget *gadget)
+static inline struct dwc2_hsotg *to_hsotg(struct usb_gadget *gadget)
{
- return container_of(gadget, struct s3c_hsotg, gadget);
+ return container_of(gadget, struct dwc2_hsotg, gadget);
}
static inline void __orr32(void __iomem *ptr, u32 val)
@@ -64,7 +65,7 @@ static inline void __bic32(void __iomem *ptr, u32 val)
}
/* forward decleration of functions */
-static void s3c_hsotg_dump(struct s3c_hsotg *hsotg);
+static void s3c_hsotg_dump(struct dwc2_hsotg *hsotg);
/**
* using_dma - return the DMA status of the driver.
@@ -85,7 +86,7 @@ static void s3c_hsotg_dump(struct s3c_hsotg *hsotg);
*
* Until this issue is sorted out, we always return 'false'.
*/
-static inline bool using_dma(struct s3c_hsotg *hsotg)
+static inline bool using_dma(struct dwc2_hsotg *hsotg)
{
return false; /* support is not complete */
}
@@ -95,7 +96,7 @@ static inline bool using_dma(struct s3c_hsotg *hsotg)
* @hsotg: The device state
* @ints: A bitmask of the interrupts to enable
*/
-static void s3c_hsotg_en_gsint(struct s3c_hsotg *hsotg, u32 ints)
+static void s3c_hsotg_en_gsint(struct dwc2_hsotg *hsotg, u32 ints)
{
u32 gsintmsk = readl(hsotg->regs + GINTMSK);
u32 new_gsintmsk;
@@ -113,7 +114,7 @@ static void s3c_hsotg_en_gsint(struct s3c_hsotg *hsotg, u32 ints)
* @hsotg: The device state
* @ints: A bitmask of the interrupts to enable
*/
-static void s3c_hsotg_disable_gsint(struct s3c_hsotg *hsotg, u32 ints)
+static void s3c_hsotg_disable_gsint(struct dwc2_hsotg *hsotg, u32 ints)
{
u32 gsintmsk = readl(hsotg->regs + GINTMSK);
u32 new_gsintmsk;
@@ -134,7 +135,7 @@ static void s3c_hsotg_disable_gsint(struct s3c_hsotg *hsotg, u32 ints)
* Set or clear the mask for an individual endpoint's interrupt
* request.
*/
-static void s3c_hsotg_ctrl_epint(struct s3c_hsotg *hsotg,
+static void s3c_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg,
unsigned int ep, unsigned int dir_in,
unsigned int en)
{
@@ -159,7 +160,7 @@ static void s3c_hsotg_ctrl_epint(struct s3c_hsotg *hsotg,
* s3c_hsotg_init_fifo - initialise non-periodic FIFOs
* @hsotg: The device instance.
*/
-static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
{
unsigned int ep;
unsigned int addr;
@@ -283,7 +284,7 @@ static inline int is_ep_periodic(struct s3c_hsotg_ep *hs_ep)
* This is the reverse of s3c_hsotg_map_dma(), called for the completion
* of a request to ensure the buffer is ready for access by the caller.
*/
-static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg,
+static void s3c_hsotg_unmap_dma(struct dwc2_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep,
struct s3c_hsotg_req *hs_req)
{
@@ -312,7 +313,7 @@ static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg,
*
* This routine is only needed for PIO
*/
-static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
+static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep,
struct s3c_hsotg_req *hs_req)
{
@@ -517,7 +518,7 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep)
* Start the given request running by setting the endpoint registers
* appropriately, and writing any data to the FIFOs.
*/
-static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
+static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep,
struct s3c_hsotg_req *hs_req,
bool continuing)
@@ -707,7 +708,7 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
* DMA memory, then we map the memory and mark our request to allow us to
* cleanup on completion.
*/
-static int s3c_hsotg_map_dma(struct s3c_hsotg *hsotg,
+static int s3c_hsotg_map_dma(struct dwc2_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep,
struct usb_request *req)
{
@@ -736,7 +737,7 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
{
struct s3c_hsotg_req *hs_req = our_req(req);
struct s3c_hsotg_ep *hs_ep = our_ep(ep);
- struct s3c_hsotg *hs = hs_ep->parent;
+ struct dwc2_hsotg *hs = hs_ep->parent;
bool first;
dev_dbg(hs->dev, "%s: req %p: %d@%p, noi=%d, zero=%d, snok=%d\n",
@@ -768,7 +769,7 @@ static int s3c_hsotg_ep_queue_lock(struct usb_ep *ep, struct usb_request *req,
gfp_t gfp_flags)
{
struct s3c_hsotg_ep *hs_ep = our_ep(ep);
- struct s3c_hsotg *hs = hs_ep->parent;
+ struct dwc2_hsotg *hs = hs_ep->parent;
unsigned long flags = 0;
int ret = 0;
@@ -799,7 +800,7 @@ static void s3c_hsotg_complete_oursetup(struct usb_ep *ep,
struct usb_request *req)
{
struct s3c_hsotg_ep *hs_ep = our_ep(ep);
- struct s3c_hsotg *hsotg = hs_ep->parent;
+ struct dwc2_hsotg *hsotg = hs_ep->parent;
dev_dbg(hsotg->dev, "%s: ep %p, req %p\n", __func__, ep, req);
@@ -814,7 +815,7 @@ static void s3c_hsotg_complete_oursetup(struct usb_ep *ep,
* Convert the given wIndex into a pointer to an driver endpoint
* structure, or return NULL if it is not a valid endpoint.
*/
-static struct s3c_hsotg_ep *ep_from_windex(struct s3c_hsotg *hsotg,
+static struct s3c_hsotg_ep *ep_from_windex(struct dwc2_hsotg *hsotg,
u32 windex)
{
struct s3c_hsotg_ep *ep = &hsotg->eps[windex & 0x7F];
@@ -843,7 +844,7 @@ static struct s3c_hsotg_ep *ep_from_windex(struct s3c_hsotg *hsotg,
* Create a request and queue it on the given endpoint. This is useful as
* an internal method of sending replies to certain control requests, etc.
*/
-static int s3c_hsotg_send_reply(struct s3c_hsotg *hsotg,
+static int s3c_hsotg_send_reply(struct dwc2_hsotg *hsotg,
struct s3c_hsotg_ep *ep,
void *buff,
int length)
@@ -884,7 +885,7 @@ static int s3c_hsotg_send_reply(struct s3c_hsotg *hsotg,
* @hsotg: The device state
* @ctrl: USB control request
*/
-static int s3c_hsotg_process_req_status(struct s3c_hsotg *hsotg,
+static int s3c_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
struct usb_ctrlrequest *ctrl)
{
struct s3c_hsotg_ep *ep0 = &hsotg->eps[0];
@@ -955,7 +956,7 @@ static struct s3c_hsotg_req *get_ep_head(struct s3c_hsotg_ep *hs_ep)
* @hsotg: The device state
* @ctrl: USB control request
*/
-static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg,
+static int s3c_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
struct usb_ctrlrequest *ctrl)
{
struct s3c_hsotg_ep *ep0 = &hsotg->eps[0];
@@ -1028,8 +1029,8 @@ static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg,
return 1;
}
-static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg);
-static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg);
+static void s3c_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg);
+static void s3c_hsotg_disconnect(struct dwc2_hsotg *hsotg);
/**
* s3c_hsotg_stall_ep0 - stall ep0
@@ -1037,7 +1038,7 @@ static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg);
*
* Set stall for ep0 as response for setup request.
*/
-static void s3c_hsotg_stall_ep0(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_stall_ep0(struct dwc2_hsotg *hsotg)
{
struct s3c_hsotg_ep *ep0 = &hsotg->eps[0];
u32 reg;
@@ -1076,7 +1077,7 @@ static void s3c_hsotg_stall_ep0(struct s3c_hsotg *hsotg)
* needs to work out what to do next (and whether to pass it on to the
* gadget driver).
*/
-static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
+static void s3c_hsotg_process_control(struct dwc2_hsotg *hsotg,
struct usb_ctrlrequest *ctrl)
{
struct s3c_hsotg_ep *ep0 = &hsotg->eps[0];
@@ -1161,7 +1162,7 @@ static void s3c_hsotg_complete_setup(struct usb_ep *ep,
struct usb_request *req)
{
struct s3c_hsotg_ep *hs_ep = our_ep(ep);
- struct s3c_hsotg *hsotg = hs_ep->parent;
+ struct dwc2_hsotg *hsotg = hs_ep->parent;
if (req->status < 0) {
dev_dbg(hsotg->dev, "%s: failed %d\n", __func__, req->status);
@@ -1183,7 +1184,7 @@ static void s3c_hsotg_complete_setup(struct usb_ep *ep,
* Enqueue a request on EP0 if necessary to received any SETUP packets
* received from the host.
*/
-static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg)
{
struct usb_request *req = hsotg->ctrl_req;
struct s3c_hsotg_req *hs_req = our_req(req);
@@ -1226,7 +1227,7 @@ static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg)
*
* Note, expects the ep to already be locked as appropriate.
*/
-static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg,
+static void s3c_hsotg_complete_request(struct dwc2_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep,
struct s3c_hsotg_req *hs_req,
int result)
@@ -1291,7 +1292,7 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg,
* endpoint, so sort out whether we need to read the data into a request
* that has been made for that endpoint.
*/
-static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
+static void s3c_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
{
struct s3c_hsotg_ep *hs_ep = &hsotg->eps[ep_idx];
struct s3c_hsotg_req *hs_req = hs_ep->req;
@@ -1356,7 +1357,7 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
* currently believed that we do not need to wait for any space in
* the TxFIFO.
*/
-static void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg,
+static void s3c_hsotg_send_zlp(struct dwc2_hsotg *hsotg,
struct s3c_hsotg_req *req)
{
u32 ctrl;
@@ -1398,7 +1399,7 @@ static void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg,
* transfer for an OUT endpoint has been completed, either by a short
* packet or by the finish of a transfer.
*/
-static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
+static void s3c_hsotg_handle_outdone(struct dwc2_hsotg *hsotg,
int epnum, bool was_setup)
{
u32 epsize = readl(hsotg->regs + DOEPTSIZ(epnum));
@@ -1471,7 +1472,7 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
*
* Return the current frame number
*/
-static u32 s3c_hsotg_read_frameno(struct s3c_hsotg *hsotg)
+static u32 s3c_hsotg_read_frameno(struct dwc2_hsotg *hsotg)
{
u32 dsts;
@@ -1498,7 +1499,7 @@ static u32 s3c_hsotg_read_frameno(struct s3c_hsotg *hsotg)
* as the actual data should be sent to the memory directly and we turn
* on the completion interrupts to get notifications of transfer completion.
*/
-static void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_handle_rx(struct dwc2_hsotg *hsotg)
{
u32 grxstsr = readl(hsotg->regs + GRXSTSP);
u32 epnum, status, size;
@@ -1590,7 +1591,7 @@ static u32 s3c_hsotg_ep0_mps(unsigned int mps)
* Configure the maximum packet size for the given endpoint, updating
* the hardware control registers to reflect this.
*/
-static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg,
+static void s3c_hsotg_set_ep_maxpacket(struct dwc2_hsotg *hsotg,
unsigned int ep, unsigned int mps)
{
struct s3c_hsotg_ep *hs_ep = &hsotg->eps[ep];
@@ -1645,7 +1646,7 @@ bad_mps:
* @hsotg: The driver state
* @idx: The index for the endpoint (0..15)
*/
-static void s3c_hsotg_txfifo_flush(struct s3c_hsotg *hsotg, unsigned int idx)
+static void s3c_hsotg_txfifo_flush(struct dwc2_hsotg *hsotg, unsigned int idx)
{
int timeout;
int val;
@@ -1681,7 +1682,7 @@ static void s3c_hsotg_txfifo_flush(struct s3c_hsotg *hsotg, unsigned int idx)
* Check to see if there is a request that has data to send, and if so
* make an attempt to write data into the FIFO.
*/
-static int s3c_hsotg_trytx(struct s3c_hsotg *hsotg,
+static int s3c_hsotg_trytx(struct dwc2_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep)
{
struct s3c_hsotg_req *hs_req = hs_ep->req;
@@ -1714,7 +1715,7 @@ static int s3c_hsotg_trytx(struct s3c_hsotg *hsotg,
* An IN transfer has been completed, update the transfer's state and then
* call the relevant completion routines.
*/
-static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg,
+static void s3c_hsotg_complete_in(struct dwc2_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep)
{
struct s3c_hsotg_req *hs_req = hs_ep->req;
@@ -1791,7 +1792,7 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg,
*
* Process and clear any interrupt pending for an individual endpoint
*/
-static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
+static void s3c_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
int dir_in)
{
struct s3c_hsotg_ep *hs_ep = &hsotg->eps[idx];
@@ -1916,7 +1917,7 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
* Handle updating the device settings after the enumeration phase has
* been completed.
*/
-static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_irq_enumdone(struct dwc2_hsotg *hsotg)
{
u32 dsts = readl(hsotg->regs + DSTS);
int ep0_mps = 0, ep_mps = 8;
@@ -1993,7 +1994,7 @@ static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg)
* Go through the requests on the given endpoint and mark them
* completed with the given result code.
*/
-static void kill_all_requests(struct s3c_hsotg *hsotg,
+static void kill_all_requests(struct dwc2_hsotg *hsotg,
struct s3c_hsotg_ep *ep,
int result, bool force)
{
@@ -2027,7 +2028,7 @@ static void kill_all_requests(struct s3c_hsotg *hsotg,
* transactions and signal the gadget driver that this
* has happened.
*/
-static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_disconnect(struct dwc2_hsotg *hsotg)
{
unsigned ep;
@@ -2042,7 +2043,7 @@ static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg)
* @hsotg: The device state:
* @periodic: True if this is a periodic FIFO interrupt
*/
-static void s3c_hsotg_irq_fifoempty(struct s3c_hsotg *hsotg, bool periodic)
+static void s3c_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic)
{
struct s3c_hsotg_ep *ep;
int epno, ret;
@@ -2076,7 +2077,7 @@ static void s3c_hsotg_irq_fifoempty(struct s3c_hsotg *hsotg, bool periodic)
*
* Issue a soft reset to the core, and await the core finishing it.
*/
-static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg)
+static int s3c_hsotg_corereset(struct dwc2_hsotg *hsotg)
{
int timeout;
u32 grstctl;
@@ -2124,7 +2125,7 @@ static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg)
*
* Issue a soft reset to the core, and await the core finishing it.
*/
-static void s3c_hsotg_core_init_disconnected(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg)
{
s3c_hsotg_corereset(hsotg);
@@ -2250,13 +2251,13 @@ static void s3c_hsotg_core_init_disconnected(struct s3c_hsotg *hsotg)
hsotg->last_rst = jiffies;
}
-static void s3c_hsotg_core_disconnect(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_core_disconnect(struct dwc2_hsotg *hsotg)
{
/* set the soft-disconnect bit */
__orr32(hsotg->regs + DCTL, DCTL_SFTDISCON);
}
-static void s3c_hsotg_core_connect(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg)
{
/* remove the soft-disconnect and let's go */
__bic32(hsotg->regs + DCTL, DCTL_SFTDISCON);
@@ -2269,7 +2270,7 @@ static void s3c_hsotg_core_connect(struct s3c_hsotg *hsotg)
*/
static irqreturn_t s3c_hsotg_irq(int irq, void *pw)
{
- struct s3c_hsotg *hsotg = pw;
+ struct dwc2_hsotg *hsotg = pw;
int retry_count = 8;
u32 gintsts;
u32 gintmsk;
@@ -2461,7 +2462,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
const struct usb_endpoint_descriptor *desc)
{
struct s3c_hsotg_ep *hs_ep = our_ep(ep);
- struct s3c_hsotg *hsotg = hs_ep->parent;
+ struct dwc2_hsotg *hsotg = hs_ep->parent;
unsigned long flags;
int index = hs_ep->index;
u32 epctrl_reg;
@@ -2604,7 +2605,7 @@ error:
static int s3c_hsotg_ep_disable(struct usb_ep *ep)
{
struct s3c_hsotg_ep *hs_ep = our_ep(ep);
- struct s3c_hsotg *hsotg = hs_ep->parent;
+ struct dwc2_hsotg *hsotg = hs_ep->parent;
int dir_in = hs_ep->dir_in;
int index = hs_ep->index;
unsigned long flags;
@@ -2669,7 +2670,7 @@ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
{
struct s3c_hsotg_req *hs_req = our_req(req);
struct s3c_hsotg_ep *hs_ep = our_ep(ep);
- struct s3c_hsotg *hs = hs_ep->parent;
+ struct dwc2_hsotg *hs = hs_ep->parent;
unsigned long flags;
dev_dbg(hs->dev, "ep_dequeue(%p,%p)\n", ep, req);
@@ -2695,7 +2696,7 @@ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
{
struct s3c_hsotg_ep *hs_ep = our_ep(ep);
- struct s3c_hsotg *hs = hs_ep->parent;
+ struct dwc2_hsotg *hs = hs_ep->parent;
int index = hs_ep->index;
u32 epreg;
u32 epctl;
@@ -2759,7 +2760,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
static int s3c_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value)
{
struct s3c_hsotg_ep *hs_ep = our_ep(ep);
- struct s3c_hsotg *hs = hs_ep->parent;
+ struct dwc2_hsotg *hs = hs_ep->parent;
unsigned long flags = 0;
int ret = 0;
@@ -2788,7 +2789,7 @@ static struct usb_ep_ops s3c_hsotg_ep_ops = {
* A wrapper for platform code responsible for controlling
* low-level USB code
*/
-static void s3c_hsotg_phy_enable(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_phy_enable(struct dwc2_hsotg *hsotg)
{
struct platform_device *pdev = to_platform_device(hsotg->dev);
@@ -2811,7 +2812,7 @@ static void s3c_hsotg_phy_enable(struct s3c_hsotg *hsotg)
* A wrapper for platform code responsible for controlling
* low-level USB code
*/
-static void s3c_hsotg_phy_disable(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_phy_disable(struct dwc2_hsotg *hsotg)
{
struct platform_device *pdev = to_platform_device(hsotg->dev);
@@ -2829,7 +2830,7 @@ static void s3c_hsotg_phy_disable(struct s3c_hsotg *hsotg)
* s3c_hsotg_init - initalize the usb core
* @hsotg: The driver state
*/
-static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_init(struct dwc2_hsotg *hsotg)
{
/* unmask subset of endpoint interrupts */
@@ -2879,7 +2880,7 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
struct usb_gadget_driver *driver)
{
- struct s3c_hsotg *hsotg = to_hsotg(gadget);
+ struct dwc2_hsotg *hsotg = to_hsotg(gadget);
unsigned long flags;
int ret;
@@ -2942,7 +2943,7 @@ err:
*/
static int s3c_hsotg_udc_stop(struct usb_gadget *gadget)
{
- struct s3c_hsotg *hsotg = to_hsotg(gadget);
+ struct dwc2_hsotg *hsotg = to_hsotg(gadget);
unsigned long flags = 0;
int ep;
@@ -2989,7 +2990,7 @@ static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget)
*/
static int s3c_hsotg_pullup(struct usb_gadget *gadget, int is_on)
{
- struct s3c_hsotg *hsotg = to_hsotg(gadget);
+ struct dwc2_hsotg *hsotg = to_hsotg(gadget);
unsigned long flags = 0;
dev_dbg(hsotg->dev, "%s: is_on: %d\n", __func__, is_on);
@@ -3026,7 +3027,7 @@ static const struct usb_gadget_ops s3c_hsotg_gadget_ops = {
* creation) to give to the gadget driver. Setup the endpoint name, any
* direction information and other state that may be required.
*/
-static void s3c_hsotg_initep(struct s3c_hsotg *hsotg,
+static void s3c_hsotg_initep(struct dwc2_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep,
int epnum)
{
@@ -3075,7 +3076,7 @@ static void s3c_hsotg_initep(struct s3c_hsotg *hsotg,
*
* Read the USB core HW configuration registers
*/
-static void s3c_hsotg_hw_cfg(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_hw_cfg(struct dwc2_hsotg *hsotg)
{
u32 cfg2, cfg3, cfg4;
/* check hardware configuration */
@@ -3099,7 +3100,7 @@ static void s3c_hsotg_hw_cfg(struct s3c_hsotg *hsotg)
* s3c_hsotg_dump - dump state of the udc
* @param: The device state
*/
-static void s3c_hsotg_dump(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_dump(struct dwc2_hsotg *hsotg)
{
#ifdef DEBUG
struct device *dev = hsotg->dev;
@@ -3158,7 +3159,7 @@ static void s3c_hsotg_dump(struct s3c_hsotg *hsotg)
*/
static int state_show(struct seq_file *seq, void *v)
{
- struct s3c_hsotg *hsotg = seq->private;
+ struct dwc2_hsotg *hsotg = seq->private;
void __iomem *regs = hsotg->regs;
int idx;
@@ -3228,7 +3229,7 @@ static const struct file_operations state_fops = {
*/
static int fifo_show(struct seq_file *seq, void *v)
{
- struct s3c_hsotg *hsotg = seq->private;
+ struct dwc2_hsotg *hsotg = seq->private;
void __iomem *regs = hsotg->regs;
u32 val;
int idx;
@@ -3284,7 +3285,7 @@ static const char *decode_direction(int is_in)
static int ep_show(struct seq_file *seq, void *v)
{
struct s3c_hsotg_ep *ep = seq->private;
- struct s3c_hsotg *hsotg = ep->parent;
+ struct dwc2_hsotg *hsotg = ep->parent;
struct s3c_hsotg_req *req;
void __iomem *regs = hsotg->regs;
int index = ep->index;
@@ -3361,7 +3362,7 @@ static const struct file_operations ep_fops = {
* with the same name as the device itself, in case we end up
* with multiple blocks in future systems.
*/
-static void s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg)
{
struct dentry *root;
unsigned epidx;
@@ -3407,7 +3408,7 @@ static void s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)
*
* Cleanup (remove) the debugfs files for use on module exit.
*/
-static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_delete_debug(struct dwc2_hsotg *hsotg)
{
unsigned epidx;
@@ -3425,7 +3426,6 @@ static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
* s3c_hsotg_probe - probe function for hsotg driver
* @pdev: The platform information for the driver
*/
-
static int s3c_hsotg_probe(struct platform_device *pdev)
{
struct s3c_hsotg_plat *plat = dev_get_platdata(&pdev->dev);
@@ -3433,13 +3433,13 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
struct usb_phy *uphy;
struct device *dev = &pdev->dev;
struct s3c_hsotg_ep *eps;
- struct s3c_hsotg *hsotg;
+ struct dwc2_hsotg *hsotg;
struct resource *res;
int epnum;
int ret;
int i;
- hsotg = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsotg), GFP_KERNEL);
+ hsotg = devm_kzalloc(&pdev->dev, sizeof(struct dwc2_hsotg), GFP_KERNEL);
if (!hsotg)
return -ENOMEM;
@@ -3520,7 +3520,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies),
hsotg->supplies);
if (ret) {
- dev_err(dev, "failed to request supplies: %d\n", ret);
+ dev_err(hsotg->dev, "failed to request supplies: %d\n", ret);
goto err_clk;
}
@@ -3528,7 +3528,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
hsotg->supplies);
if (ret) {
- dev_err(hsotg->dev, "failed to enable supplies: %d\n", ret);
+ dev_err(dev, "failed to enable supplies: %d\n", ret);
goto err_supplies;
}
@@ -3592,7 +3592,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
hsotg->supplies);
if (ret) {
- dev_err(hsotg->dev, "failed to disable supplies: %d\n", ret);
+ dev_err(&pdev->dev, "failed to disable supplies: %d\n", ret);
goto err_ep_mem;
}
@@ -3622,7 +3622,7 @@ err_clk:
*/
static int s3c_hsotg_remove(struct platform_device *pdev)
{
- struct s3c_hsotg *hsotg = platform_get_drvdata(pdev);
+ struct dwc2_hsotg *hsotg = platform_get_drvdata(pdev);
usb_del_gadget_udc(&hsotg->gadget);
s3c_hsotg_delete_debug(hsotg);
@@ -3633,7 +3633,7 @@ static int s3c_hsotg_remove(struct platform_device *pdev)
static int s3c_hsotg_suspend(struct platform_device *pdev, pm_message_t state)
{
- struct s3c_hsotg *hsotg = platform_get_drvdata(pdev);
+ struct dwc2_hsotg *hsotg = platform_get_drvdata(pdev);
unsigned long flags;
int ret = 0;
@@ -3664,7 +3664,7 @@ static int s3c_hsotg_suspend(struct platform_device *pdev, pm_message_t state)
static int s3c_hsotg_resume(struct platform_device *pdev)
{
- struct s3c_hsotg *hsotg = platform_get_drvdata(pdev);
+ struct dwc2_hsotg *hsotg = platform_get_drvdata(pdev);
unsigned long flags;
int ret = 0;
--
2.0.3
> From: [email protected] [mailto:[email protected]]
> Sent: Tuesday, November 11, 2014 9:14 AM
>
> From: Dinh Nguyen <[email protected]>
>
> Update suspend/resume to use dev_pm_ops API.
>
> Signed-off-by: Dinh Nguyen <[email protected]>
> ---
> drivers/usb/dwc2/platform.c | 15 +++++++++------
> 1 file changed, 9 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
> index eeba8a4..b94867b 100644
> --- a/drivers/usb/dwc2/platform.c
> +++ b/drivers/usb/dwc2/platform.c
> @@ -219,9 +219,9 @@ static int dwc2_driver_probe(struct platform_device *dev)
> return retval;
> }
>
> -static int dwc2_suspend(struct platform_device *dev, pm_message_t state)
> +static int dwc2_suspend(struct device *dev)
> {
> - struct dwc2_hsotg *dwc2 = platform_get_drvdata(dev);
> + struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
> int ret = 0;
>
> if (dwc2_is_device_mode(dwc2))
> @@ -229,9 +229,9 @@ static int dwc2_suspend(struct platform_device *dev, pm_message_t state)
> return ret;
> }
>
> -static int dwc2_resume(struct platform_device *dev)
> +static int dwc2_resume(struct device *dev)
> {
> - struct dwc2_hsotg *dwc2 = platform_get_drvdata(dev);
> + struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
> int ret = 0;
>
> if (dwc2_is_device_mode(dwc2))
> @@ -239,15 +239,18 @@ static int dwc2_resume(struct platform_device *dev)
> return ret;
> }
>
> +static const struct dev_pm_ops dwc2_dev_pm_ops = {
> + SET_SYSTEM_SLEEP_PM_OPS(dwc2_suspend, dwc2_resume)
> +};
> +
> static struct platform_driver dwc2_platform_driver = {
> .driver = {
> .name = dwc2_driver_name,
> .of_match_table = dwc2_of_match_table,
> + .pm = &dwc2_dev_pm_ops,
> },
> .probe = dwc2_driver_probe,
> .remove = dwc2_driver_remove,
> - .suspend = dwc2_suspend,
> - .resume = dwc2_resume,
> };
>
> module_platform_driver(dwc2_platform_driver);
Acked-by: Paul Zimmerman <[email protected]>
> From: [email protected] [mailto:[email protected]]
> Sent: Tuesday, November 11, 2014 9:14 AM
>
> From: Dinh Nguyen <[email protected]>
>
> Make dwc2_handle_common_intr call the gadget interrupt function when operating
> in peripheral mode. Remove the spinlock functions in s3c_hsotg_irq as
> dwc2_handle_common_intr() already has the spinlocks.
>
> Move the registeration of the IRQ to common code for platform and PCI.
>
> Remove duplicate interrupt conditions that was in gadget, as those are handled
> by dwc2 common interrupt handler.
>
> Signed-off-by: Dinh Nguyen <[email protected]>
> ---
> v7: Use IRQF_SHARED
> v5: remove individual devm_request_irq from gadget and hcd, and place a
> single devm_request_irq in platform and pci.
> v2: Keep interrupt handler for host and peripheral modes separate
> ---
> drivers/usb/dwc2/core.c | 10 ----------
> drivers/usb/dwc2/gadget.c | 46 +++------------------------------------------
> drivers/usb/dwc2/pci.c | 6 ++++++
> drivers/usb/dwc2/platform.c | 8 ++++++++
> 4 files changed, 17 insertions(+), 53 deletions(-)
>
> diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
> index d926945..7605850b 100644
> --- a/drivers/usb/dwc2/core.c
> +++ b/drivers/usb/dwc2/core.c
> @@ -458,16 +458,6 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq)
> /* Clear the SRP success bit for FS-I2c */
> hsotg->srp_success = 0;
>
> - if (irq >= 0) {
> - dev_dbg(hsotg->dev, "registering common handler for irq%d\n",
> - irq);
> - retval = devm_request_irq(hsotg->dev, irq,
> - dwc2_handle_common_intr, IRQF_SHARED,
> - dev_name(hsotg->dev), hsotg);
> - if (retval)
> - return retval;
> - }
> -
> /* Enable common interrupts */
> dwc2_enable_common_interrupts(hsotg);
>
> diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
> index ec85340..37c7916 100644
> --- a/drivers/usb/dwc2/gadget.c
> +++ b/drivers/usb/dwc2/gadget.c
> @@ -2285,33 +2285,12 @@ irq_retry:
>
> gintsts &= gintmsk;
>
> - if (gintsts & GINTSTS_OTGINT) {
> - u32 otgint = readl(hsotg->regs + GOTGINT);
> -
> - dev_info(hsotg->dev, "OTGInt: %08x\n", otgint);
> -
> - writel(otgint, hsotg->regs + GOTGINT);
> - }
> -
> - if (gintsts & GINTSTS_SESSREQINT) {
> - dev_dbg(hsotg->dev, "%s: SessReqInt\n", __func__);
> - writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
> - }
> -
This hunk will clash with the patch that Marek has just submitted,
which uses the SESSREQINT in the gadget. But I guess you two and
Felipe can resolve that :)
> if (gintsts & GINTSTS_ENUMDONE) {
> writel(GINTSTS_ENUMDONE, hsotg->regs + GINTSTS);
>
> s3c_hsotg_irq_enumdone(hsotg);
> }
>
> - if (gintsts & GINTSTS_CONIDSTSCHNG) {
> - dev_dbg(hsotg->dev, "ConIDStsChg (DSTS=0x%08x, GOTCTL=%08x)\n",
> - readl(hsotg->regs + DSTS),
> - readl(hsotg->regs + GOTGCTL));
> -
> - writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
> - }
> -
> if (gintsts & (GINTSTS_OEPINT | GINTSTS_IEPINT)) {
> u32 daint = readl(hsotg->regs + DAINT);
> u32 daintmsk = readl(hsotg->regs + DAINTMSK);
> @@ -2392,25 +2371,6 @@ irq_retry:
> s3c_hsotg_handle_rx(hsotg);
> }
>
> - if (gintsts & GINTSTS_MODEMIS) {
> - dev_warn(hsotg->dev, "warning, mode mismatch triggered\n");
> - writel(GINTSTS_MODEMIS, hsotg->regs + GINTSTS);
> - }
> -
> - if (gintsts & GINTSTS_USBSUSP) {
> - dev_info(hsotg->dev, "GINTSTS_USBSusp\n");
> - writel(GINTSTS_USBSUSP, hsotg->regs + GINTSTS);
> -
> - call_gadget(hsotg, suspend);
> - }
> -
> - if (gintsts & GINTSTS_WKUPINT) {
> - dev_info(hsotg->dev, "GINTSTS_WkUpIn\n");
> - writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS);
> -
> - call_gadget(hsotg, resume);
> - }
> -
> if (gintsts & GINTSTS_ERLYSUSP) {
> dev_dbg(hsotg->dev, "GINTSTS_ErlySusp\n");
> writel(GINTSTS_ERLYSUSP, hsotg->regs + GINTSTS);
> @@ -3510,14 +3470,14 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
> s3c_hsotg_hw_cfg(hsotg);
> s3c_hsotg_init(hsotg);
>
> - ret = devm_request_irq(dev, irq, s3c_hsotg_irq, 0,
> - dev_name(dev), hsotg);
> + ret = devm_request_irq(hsotg->dev, irq, s3c_hsotg_irq, IRQF_SHARED,
> + dev_name(hsotg->dev), hsotg);
> if (ret < 0) {
> s3c_hsotg_phy_disable(hsotg);
> clk_disable_unprepare(hsotg->clk);
> regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
> hsotg->supplies);
> - dev_err(dev, "cannot claim IRQ\n");
> + dev_err(dev, "cannot claim IRQ for gadget\n");
> goto err_clk;
> }
>
> diff --git a/drivers/usb/dwc2/pci.c b/drivers/usb/dwc2/pci.c
> index 6d33ecf..a4e724b 100644
> --- a/drivers/usb/dwc2/pci.c
> +++ b/drivers/usb/dwc2/pci.c
> @@ -141,6 +141,12 @@ static int dwc2_driver_probe(struct pci_dev *dev,
>
> pci_set_master(dev);
>
> + retval = devm_request_irq(hsotg->dev, dev->irq,
> + dwc2_handle_common_intr, IRQF_SHARED,
> + dev_name(hsotg->dev), hsotg);
> + if (retval)
> + return retval;
> +
> spin_lock_init(&hsotg->lock);
> retval = dwc2_hcd_init(hsotg, dev->irq, &dwc2_module_params);
> if (retval) {
> diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
> index b94867b..3552602 100644
> --- a/drivers/usb/dwc2/platform.c
> +++ b/drivers/usb/dwc2/platform.c
> @@ -196,6 +196,14 @@ static int dwc2_driver_probe(struct platform_device *dev)
> return irq;
> }
>
> + dev_dbg(hsotg->dev, "registering common handler for irq%d\n",
> + irq);
> + retval = devm_request_irq(hsotg->dev, irq,
> + dwc2_handle_common_intr, IRQF_SHARED,
> + dev_name(hsotg->dev), hsotg);
> + if (retval)
> + return retval;
> +
> res = platform_get_resource(dev, IORESOURCE_MEM, 0);
> hsotg->regs = devm_ioremap_resource(&dev->dev, res);
> if (IS_ERR(hsotg->regs))
Acked-by: Paul Zimmerman <[email protected]>
> From: [email protected] [mailto:[email protected]]
> Sent: Tuesday, November 11, 2014 9:14 AM
>
> From: Dinh Nguyen <[email protected]>
>
> Since platform.c will get built for both Host and Gadget, if we leave the
> usb_disabled() call in platform.c, it results in the following build error
> when (!USB && USB_GADGET) condition is met.
>
> ERROR: "usb_disabled" [drivers/usb/dwc2/dwc2_platform.ko] undefined!
>
> Since usb_disabled() is mostly used to disable USB host functionality, move
> the call the host portion for the DWC2 driver.
>
> Signed-off-by: Dinh Nguyen <[email protected]>
> ---
> drivers/usb/dwc2/hcd.c | 3 +++
> drivers/usb/dwc2/platform.c | 3 ---
> 2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
> index fa60f4a..755e16b 100644
> --- a/drivers/usb/dwc2/hcd.c
> +++ b/drivers/usb/dwc2/hcd.c
> @@ -2780,6 +2780,9 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
> int i, num_channels;
> int retval;
>
> + if (usb_disabled())
> + return -ENODEV;
> +
> dev_dbg(hsotg->dev, "DWC OTG HCD INIT\n");
>
> /* Detect config values from hardware */
> diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
> index 3552602..57eb8a3 100644
> --- a/drivers/usb/dwc2/platform.c
> +++ b/drivers/usb/dwc2/platform.c
> @@ -157,9 +157,6 @@ static int dwc2_driver_probe(struct platform_device *dev)
> int retval;
> int irq;
>
> - if (usb_disabled())
> - return -ENODEV;
> -
> match = of_match_device(dwc2_of_match_table, &dev->dev);
> if (match && match->data) {
> params = match->data;
This patch also fixes a minor buglet, in that we were missing the
usb_disabled() check in pci.c.
Acked-by: Paul Zimmerman <[email protected]>
> From: [email protected] [mailto:[email protected]]
> Sent: Tuesday, November 11, 2014 9:14 AM
>
> From: Dinh Nguyen <[email protected]>
>
> Since the dwc2 hcd driver is currently not looking for a clock node during
> init, we should not completely fail if there isn't a clock provided.
> By assigning clk = NULL, this allows the driver, when configured for dual-role
> mode, to be able to continue loading the host portion of the driver when
> a clock node is not specified.
>
> Signed-off-by: Dinh Nguyen <[email protected]>
> ---
> v7: Reworked to use clk=NULL and remove the need to is IS_ERR(clk)
> v6: none
> v5: reworked to not access gadget functions from the hcd.
> ---
> drivers/usb/dwc2/gadget.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
> index 37c7916..367689b 100644
> --- a/drivers/usb/dwc2/gadget.c
> +++ b/drivers/usb/dwc2/gadget.c
> @@ -3431,6 +3431,7 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
>
> hsotg->clk = devm_clk_get(dev, "otg");
> if (IS_ERR(hsotg->clk)) {
> + hsotg->clk = NULL;
> dev_err(dev, "cannot get otg clock\n");
> return PTR_ERR(hsotg->clk);
> }
Whoops, you just broke the return value, since you NULL out
hsotg->clk and then call PTR_ERR() on it.
--
Paul
On Fri, Nov 14, 2014 at 09:01:49PM +0000, Paul Zimmerman wrote:
> > From: [email protected] [mailto:[email protected]]
> > Sent: Tuesday, November 11, 2014 9:14 AM
> >
> > From: Dinh Nguyen <[email protected]>
> >
> > Since the dwc2 hcd driver is currently not looking for a clock node during
> > init, we should not completely fail if there isn't a clock provided.
> > By assigning clk = NULL, this allows the driver, when configured for dual-role
> > mode, to be able to continue loading the host portion of the driver when
> > a clock node is not specified.
> >
> > Signed-off-by: Dinh Nguyen <[email protected]>
> > ---
> > v7: Reworked to use clk=NULL and remove the need to is IS_ERR(clk)
> > v6: none
> > v5: reworked to not access gadget functions from the hcd.
> > ---
> > drivers/usb/dwc2/gadget.c | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
> > index 37c7916..367689b 100644
> > --- a/drivers/usb/dwc2/gadget.c
> > +++ b/drivers/usb/dwc2/gadget.c
> > @@ -3431,6 +3431,7 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
> >
> > hsotg->clk = devm_clk_get(dev, "otg");
> > if (IS_ERR(hsotg->clk)) {
> > + hsotg->clk = NULL;
> > dev_err(dev, "cannot get otg clock\n");
> > return PTR_ERR(hsotg->clk);
> > }
>
> Whoops, you just broke the return value, since you NULL out
> hsotg->clk and then call PTR_ERR() on it.
yeah, the idea was to remove the early return too :-)
--
balbi
Hi Dinh:
On 2014/11/12 1:13, [email protected] wrote:
> From: Dinh Nguyen <[email protected]>
>
> Adds the gadget data structure and appropriate data structure pointers
> to the common dwc2_hsotg data structure. To keep the driver data
> dereference code looking clean, the gadget variable declares are only available
> for peripheral and dual-role mode. This is needed so that the dwc2_hsotg data
> structure can be used by the hcd and gadget drivers.
>
> Updates gadget.c to use the dwc2_hsotg data structure and gadget pointers
> that have been moved into the common dwc2_hsotg structure.
>
> Signed-off-by: Dinh Nguyen <[email protected]>
> Signed-off-by: Paul Zimmerman <[email protected]>
> ---
> v7: Addressed comments from Felipe Balbi on which variables should not be just
> limited to gadget(phy, uphy, regulator_bulk_data_supplies, irq, clk,
> debug_root, debug_file, and debug_fifo).
I hope your dual-roal patches could bring the intializtion code of
hsotg->clk and hsotg->phy out from dwc2_gadget_init() into
dwc2_driver_probe() like intializtion of irq and regs base address.
Because the host-only platforms may also need clk gating when enter
suspend for power saving.
> v6: None
> v5: Keep the changes to mininum and maintain hcd and gadget driver to build
> and work separately. Use IS_ENABLED() instead of #if defined
> v3: Updated with paulz's suggestion to avoid double pointers.
> v2: Left the function parameter name as 'hsotg' and just changed its type.
>
--
--------
Roy Li @ Rockchip