[PATCH 6/7] usb: dwc2: Enable the dwc2/s3c-hsotg to be a single dual-role driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Dinh Nguyen <dinguyen@xxxxxxxxxx>

Similar to the DWC3 dual-role driver config, the default mode for the
dwc2/s3c-hsotg driver is a dual-role driver.

When the driver is built as a module the dwc2.ko and dwc2_platform.ko are
the two ko's that should be insmod for all operation modes of the driver.

Signed-off-by: Dinh Nguyen <dinguyen@xxxxxxxxxx>
Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
Cc: Paul Zimmerman <paulz@xxxxxxxxxxxx>
Cc: Felipe Balbi <balbi@xxxxxx>
Cc: Ben Dooks <ben-linux@xxxxxxxxx>
Cc: Matt Porter <mporter@xxxxxxxxxx>
Cc: Kukjin Kim <kgene.kim@xxxxxxxxxxx>
Cc: Stephen Warren <swarren@xxxxxxxxxxxxx>
Cc: Matthijs Kooijman <matthijs@xxxxxxxx>
Cc: Jingoo Han <jg1.han@xxxxxxxxxxx>
Cc: Sachin Kamat <sachin.kamat@xxxxxxxxxx>
Cc: Robert Baldyga <r.baldyga@xxxxxxxxxxx>
---
 drivers/usb/dwc2/Kconfig     |   43 +++++++++++++++++++++++++++---------------
 drivers/usb/dwc2/Makefile    |   13 +++++--------
 drivers/usb/dwc2/core.c      |    1 +
 drivers/usb/dwc2/core.h      |    2 +-
 drivers/usb/dwc2/hcd.c       |    7 +------
 drivers/usb/dwc2/platform.c  |   30 ++++++++++++++++++++++++-----
 drivers/usb/dwc2/s3c-hsotg.c |   18 ++++++++----------
 7 files changed, 69 insertions(+), 45 deletions(-)

diff --git a/drivers/usb/dwc2/Kconfig b/drivers/usb/dwc2/Kconfig
index ce14859..8c0df5d 100644
--- a/drivers/usb/dwc2/Kconfig
+++ b/drivers/usb/dwc2/Kconfig
@@ -20,21 +20,6 @@ config USB_DWC2
 
 if USB_DWC2
 
-config USB_DWC2_HOST
-	bool "Host only mode"
-	depends on USB=y || USB=USB_DWC2
-	default y
-	help
-	  Select this when you want to use DWC2 in host mode only,
-	  thereby the gadget feature will be regressed.
-
-config USB_S3C_HSOTG
-	depends on (ARM || USB_GADGET=y) && !USB_DWC2_HOST
-	tristate "Designware/S3C HS/OtG USB Device controller"
-	help
-	  The Designware USB2.0 high-speed gadget controller
-	  integrated into many SoCs.
-
 config USB_DWC2_DEBUG
 	bool "Enable Debugging Messages"
 	help
@@ -66,3 +51,31 @@ config USB_DWC2_DEBUG_PERIODIC
 	  incomplete. Note that this also disables some debug messages
 	  for which the transfer type cannot be deduced.
 endif
+
+choice
+	bool "DWC2 Mode Selection"
+	default USB_DWC2_DUAL_ROLE if (USB && USB_GADGET)
+	default USB_DWC2_HOST if (USB && !USB_GADGET)
+	default USB_S3C_HSOTG if (!USB && USB_GADGET)
+
+config USB_DWC2_HOST
+	bool "Host only mode"
+	depends on USB=y || USB=USB_DWC2
+	help
+	  Select this when you want to use DWC2 in host mode only,
+	  thereby the gadget feature will be regressed.
+
+config USB_S3C_HSOTG
+	depends on ARM || USB_GADGET=y
+	tristate "Designware/S3C HS/OtG USB Device controller"
+	help
+	  The Designware USB2.0 high-speed gadget controller
+	  integrated into many SoCs.
+
+config USB_DWC2_DUAL_ROLE
+	bool "Dual Role mode"
+	depends on ((USB=y || USB=USB_DWC2) && (USB_GADGET=y))
+	help
+	  This is the default mode of working of DWC2 controller where
+	  both host and gadget features are enabled.
+endchoice
diff --git a/drivers/usb/dwc2/Makefile b/drivers/usb/dwc2/Makefile
index 2cbbabf..eca1bd9 100644
--- a/drivers/usb/dwc2/Makefile
+++ b/drivers/usb/dwc2/Makefile
@@ -2,18 +2,15 @@ ccflags-$(CONFIG_USB_DWC2_DEBUG)	+= -DDEBUG
 ccflags-$(CONFIG_USB_DWC2_VERBOSE)	+= -DVERBOSE_DEBUG
 
 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
-endif
-obj-$(CONFIG_USB_S3C_HSOTG)             += s3c-hsotg.o
+dwc2-y					+= core.o core_intr.o
+dwc2-y					+= hcd.o hcd_intr.o
+dwc2-y					+= hcd_queue.o hcd_ddma.o
+dwc2-y					+= s3c-hsotg.o
 
 ifneq ($(CONFIG_PCI),)
 	obj-$(CONFIG_USB_DWC2)		+= dwc2_pci.o
 endif
-ifneq ($(CONFIG_USB_DWC2_HOST),)
-	obj-$(CONFIG_USB_DWC2)			+= dwc2_platform.o
-endif
+obj-$(CONFIG_USB_DWC2)			+= dwc2_platform.o
 
 dwc2_pci-y				+= pci.o
 dwc2_platform-y				+= platform.o
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 1d12988..12e9465 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -467,6 +467,7 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(dwc2_core_init);
 
 /**
  * dwc2_enable_host_interrupts() - Enables the Host mode interrupts
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index dd5c496..9bbbe53 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -737,7 +737,7 @@ extern void dwc2_read_packet(struct dwc2_hsotg *hsotg, u8 *dest, u16 bytes);
 extern void dwc2_flush_tx_fifo(struct dwc2_hsotg *hsotg, const int num);
 extern void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg);
 
-extern int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq);
+int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq);
 extern void dwc2_enable_global_interrupts(struct dwc2_hsotg *hcd);
 extern void dwc2_disable_global_interrupts(struct dwc2_hsotg *hcd);
 
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index f59484d..2e949ef 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1355,6 +1355,7 @@ 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(hsotg);
 	} else {
 		/* A-Device connector (Host Mode) */
 		dev_dbg(hsotg->dev, "connId A\n");
@@ -2798,11 +2799,6 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
 		goto error1;
 	hsotg->last_frame_num = HFNUM_MAX_FRNUM;
 #endif
-
-	hsotg->core_params = kzalloc(sizeof(*hsotg->core_params), GFP_KERNEL);
-	if (!hsotg->core_params)
-		goto error1;
-
 	dwc2_set_all_params(hsotg->core_params, -1);
 
 	/* Validate parameter values */
@@ -2834,7 +2830,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/platform.c b/drivers/usb/dwc2/platform.c
index c6fb4f2..85f706d 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -42,11 +42,12 @@
 #include <linux/dma-mapping.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
+#include <linux/usb/otg.h>
 
 #include "core.h"
 #include "hcd.h"
 
-static const char dwc2_driver_name[] = "dwc2";
+static const char dwc2_driver_name[] = "dwc2/s3c-hsotg";
 
 static const struct dwc2_core_params params_bcm2835 = {
 	.otg_cap			= 0,	/* HNP/SRP capable */
@@ -93,8 +94,13 @@ static int dwc2_driver_remove(struct platform_device *dev)
 
 	if (IS_ENABLED(CONFIG_USB_DWC2_HOST))
 		dwc2_hcd_remove(hsotg);
-	else /* s3c-hsotg gadget */
+	else if (IS_ENABLED(CONFIG_USB_S3C_HSOTG))
 		s3c_hsotg_remove(hsotg);
+	else {/* dual-role */
+		s3c_hsotg_remove(hsotg);
+		dwc2_hcd_remove(hsotg);
+	}
+	clk_disable_unprepare(hsotg->clk);
 
 	return 0;
 }
@@ -134,8 +140,7 @@ static int dwc2_driver_probe(struct platform_device *dev)
 		params = match->data;
 	} else {
 		/* Default all params to autodetect */
-		if (IS_ENABLED(CONFIG_USB_DWC2_HOST))
-			dwc2_set_all_params(&defparams, -1);
+		dwc2_set_all_params(&defparams, -1);
 		params = &defparams;
 	}
 
@@ -143,6 +148,10 @@ static int dwc2_driver_probe(struct platform_device *dev)
 	if (!hsotg)
 		return -ENOMEM;
 
+	hsotg->core_params = kzalloc(sizeof(*hsotg->core_params), GFP_KERNEL);
+	if (!hsotg->core_params)
+		return -ENOMEM;
+
 	hsotg->dev = &dev->dev;
 
 	/*
@@ -180,11 +189,22 @@ static int dwc2_driver_probe(struct platform_device *dev)
 		retval = dwc2_hcd_init(hsotg, irq, params);
 		if (retval)
 			return retval;
-	} else {/* Enable s3c_hsotg gadget driver */
+	} else if (IS_ENABLED(CONFIG_USB_S3C_HSOTG)) {
 		retval = dwc2_gadget_init(hsotg, irq);
 		if (retval)
 			return retval;
+		retval = dwc2_core_init(hsotg, true, irq);
+		if (retval)
+			return retval;
+	} else {/* Enable dwc2/3c_hsotg dual-role driver */
+		retval = dwc2_gadget_init(hsotg, irq);
+		if (retval)
+			return retval;
+		retval = dwc2_hcd_init(hsotg, irq, params);
+		if (retval)
+			return retval;
 	}
+	spin_lock_init(&hsotg->lock);
 
 	platform_set_drvdata(dev, hsotg);
 
diff --git a/drivers/usb/dwc2/s3c-hsotg.c b/drivers/usb/dwc2/s3c-hsotg.c
index 6c0aba8..6f5d7e4 100644
--- a/drivers/usb/dwc2/s3c-hsotg.c
+++ b/drivers/usb/dwc2/s3c-hsotg.c
@@ -2097,6 +2097,7 @@ static int s3c_hsotg_corereset(struct dwc2_hsotg *dwc2)
  *
  * Issue a soft reset to the core, and await the core finishing it.
  */
+#if defined(CONFIG_USB_DWC2_DUAL_ROLE) || defined(CONFIG_USB_S3C_HSOTG)
 void s3c_hsotg_core_init(struct dwc2_hsotg *dwc2)
 {
 	s3c_hsotg_corereset(dwc2);
@@ -2223,6 +2224,11 @@ void s3c_hsotg_core_init(struct dwc2_hsotg *dwc2)
 	/* remove the soft-disconnect and let's go */
 	__bic32(dwc2->regs + DCTL, DCTL_SFTDISCON);
 }
+#else
+void s3c_hsotg_core_init(struct dwc2_hsotg *dwc2)
+{
+}
+#endif
 
 /**
  * s3c_hsotg_ep_enable - enable the given endpoint
@@ -3210,15 +3216,6 @@ int dwc2_gadget_init(struct dwc2_hsotg *dwc2, int irq)
 	} else
 		dwc2->s3c_hsotg->phy = phy;
 
-	spin_lock_init(&dwc2->lock);
-
-	ret = devm_request_irq(dwc2->dev, irq, dwc2_handle_common_intr, 0,
-			dev_name(dev), dwc2);
-	if (ret < 0) {
-		dev_err(dev, "cannot claim IRQ\n");
-		return ret;
-	}
-
 	dwc2->gadget.max_speed = USB_SPEED_HIGH;
 	dwc2->gadget.ops = &s3c_hsotg_gadget_ops;
 	dwc2->gadget.name = dev_name(dev);
@@ -3328,6 +3325,7 @@ err_supplies:
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(dwc2_gadget_init);
 
 /**
  * s3c_hsotg_remove - remove function for hsotg driver
@@ -3347,8 +3345,8 @@ void s3c_hsotg_remove(struct dwc2_hsotg *dwc2)
 	s3c_hsotg_phy_disable(dwc2);
 	if (dwc2->s3c_hsotg->phy)
 		phy_exit(dwc2->s3c_hsotg->phy);
-	clk_disable_unprepare(dwc2->clk);
 }
+EXPORT_SYMBOL_GPL(s3c_hsotg_remove);
 
 #define s3c_hsotg_suspend NULL
 #define s3c_hsotg_resume NULL
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux