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