From 5ea75095fe6d683900ccc674fcac375e7df68005 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 8 Jun 2015 08:20:05 +0200 Subject: usb: gadget: nokia: Add mass storage driver to g_nokia MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds removable mass storage support to g_nokia gadget (for N900). It means that at runtime block device can be exported or unexported. So it does not export anything by default and thus allows to use MyDocs partition as before... [ balbi@ti.com: make it build ] Signed-off-by: Pali Rohár Signed-off-by: Felipe Balbi --- drivers/usb/gadget/legacy/Kconfig | 1 + drivers/usb/gadget/legacy/nokia.c | 102 +++++++++++++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig index d5a7102de696..ddef41f6df3e 100644 --- a/drivers/usb/gadget/legacy/Kconfig +++ b/drivers/usb/gadget/legacy/Kconfig @@ -346,6 +346,7 @@ config USB_G_NOKIA select USB_F_OBEX select USB_F_PHONET select USB_F_ECM + select USB_F_MASS_STORAGE help The Nokia composite gadget provides support for acm, obex and phonet in only one composite gadget driver. diff --git a/drivers/usb/gadget/legacy/nokia.c b/drivers/usb/gadget/legacy/nokia.c index 4bb498a38a1c..e3791b919996 100644 --- a/drivers/usb/gadget/legacy/nokia.c +++ b/drivers/usb/gadget/legacy/nokia.c @@ -24,6 +24,7 @@ #include "u_phonet.h" #include "u_ecm.h" #include "gadget_chips.h" +#include "f_mass_storage.h" /* Defines */ @@ -34,6 +35,29 @@ USB_GADGET_COMPOSITE_OPTIONS(); USB_ETHERNET_MODULE_PARAMETERS(); +static struct fsg_module_parameters fsg_mod_data = { + .stall = 0, + .luns = 2, + .removable_count = 2, + .removable = { 1, 1, }, +}; + +#ifdef CONFIG_USB_GADGET_DEBUG_FILES + +static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS; + +#else + +/* + * Number of buffers we will use. + * 2 is usually enough for good buffering pipeline + */ +#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS + +#endif /* CONFIG_USB_DEBUG */ + +FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); + #define NOKIA_VENDOR_ID 0x0421 /* Nokia */ #define NOKIA_PRODUCT_ID 0x01c8 /* Nokia Gadget */ @@ -94,6 +118,8 @@ static struct usb_function *f_obex1_cfg2; static struct usb_function *f_obex2_cfg2; static struct usb_function *f_phonet_cfg1; static struct usb_function *f_phonet_cfg2; +static struct usb_function *f_msg_cfg1; +static struct usb_function *f_msg_cfg2; static struct usb_configuration nokia_config_500ma_driver = { @@ -117,6 +143,7 @@ static struct usb_function_instance *fi_ecm; static struct usb_function_instance *fi_obex1; static struct usb_function_instance *fi_obex2; static struct usb_function_instance *fi_phonet; +static struct usb_function_instance *fi_msg; static int nokia_bind_config(struct usb_configuration *c) { @@ -125,6 +152,8 @@ static int nokia_bind_config(struct usb_configuration *c) struct usb_function *f_obex1 = NULL; struct usb_function *f_ecm; struct usb_function *f_obex2 = NULL; + struct usb_function *f_msg; + struct fsg_opts *fsg_opts; int status = 0; int obex1_stat = -1; int obex2_stat = -1; @@ -160,6 +189,12 @@ static int nokia_bind_config(struct usb_configuration *c) goto err_get_ecm; } + f_msg = usb_get_function(fi_msg); + if (IS_ERR(f_msg)) { + status = PTR_ERR(f_msg); + goto err_get_msg; + } + if (!IS_ERR_OR_NULL(f_phonet)) { phonet_stat = usb_add_function(c, f_phonet); if (phonet_stat) @@ -187,21 +222,36 @@ static int nokia_bind_config(struct usb_configuration *c) pr_debug("could not bind ecm config %d\n", status); goto err_ecm; } + + fsg_opts = fsg_opts_from_func_inst(fi_msg); + + status = fsg_common_run_thread(fsg_opts->common); + if (status) + goto err_msg; + + status = usb_add_function(c, f_msg); + if (status) + goto err_msg; + if (c == &nokia_config_500ma_driver) { f_acm_cfg1 = f_acm; f_ecm_cfg1 = f_ecm; f_phonet_cfg1 = f_phonet; f_obex1_cfg1 = f_obex1; f_obex2_cfg1 = f_obex2; + f_msg_cfg1 = f_msg; } else { f_acm_cfg2 = f_acm; f_ecm_cfg2 = f_ecm; f_phonet_cfg2 = f_phonet; f_obex1_cfg2 = f_obex1; f_obex2_cfg2 = f_obex2; + f_msg_cfg2 = f_msg; } return status; +err_msg: + usb_remove_function(c, f_ecm); err_ecm: usb_remove_function(c, f_acm); err_conf: @@ -211,6 +261,8 @@ err_conf: usb_remove_function(c, f_obex1); if (!phonet_stat) usb_remove_function(c, f_phonet); + usb_put_function(f_msg); +err_get_msg: usb_put_function(f_ecm); err_get_ecm: usb_put_function(f_acm); @@ -227,6 +279,8 @@ err_get_acm: static int nokia_bind(struct usb_composite_dev *cdev) { struct usb_gadget *gadget = cdev->gadget; + struct fsg_opts *fsg_opts; + struct fsg_config fsg_config; int status; status = usb_string_ids_tab(cdev, strings_dev); @@ -267,11 +321,46 @@ static int nokia_bind(struct usb_composite_dev *cdev) goto err_acm_inst; } + fi_msg = usb_get_function_instance("mass_storage"); + if (IS_ERR(fi_msg)) { + status = PTR_ERR(fi_msg); + goto err_ecm_inst; + } + + /* set up mass storage function */ + fsg_config_from_params(&fsg_config, &fsg_mod_data, fsg_num_buffers); + fsg_config.vendor_name = "Nokia"; + fsg_config.product_name = "N900"; + + fsg_opts = fsg_opts_from_func_inst(fi_msg); + fsg_opts->no_configfs = true; + + status = fsg_common_set_num_buffers(fsg_opts->common, fsg_num_buffers); + if (status) + goto err_msg_inst; + + status = fsg_common_set_nluns(fsg_opts->common, fsg_config.nluns); + if (status) + goto err_msg_buf; + + status = fsg_common_set_cdev(fsg_opts->common, cdev, fsg_config.can_stall); + if (status) + goto err_msg_set_nluns; + + fsg_common_set_sysfs(fsg_opts->common, true); + + status = fsg_common_create_luns(fsg_opts->common, &fsg_config); + if (status) + goto err_msg_set_nluns; + + fsg_common_set_inquiry_string(fsg_opts->common, fsg_config.vendor_name, + fsg_config.product_name); + /* finally register the configuration */ status = usb_add_config(cdev, &nokia_config_500ma_driver, nokia_bind_config); if (status < 0) - goto err_ecm_inst; + goto err_msg_set_cdev; status = usb_add_config(cdev, &nokia_config_100ma_driver, nokia_bind_config); @@ -292,6 +381,14 @@ err_put_cfg1: if (!IS_ERR_OR_NULL(f_phonet_cfg1)) usb_put_function(f_phonet_cfg1); usb_put_function(f_ecm_cfg1); +err_msg_set_cdev: + fsg_common_remove_luns(fsg_opts->common); +err_msg_set_nluns: + fsg_common_free_luns(fsg_opts->common); +err_msg_buf: + fsg_common_free_buffers(fsg_opts->common); +err_msg_inst: + usb_put_function_instance(fi_msg); err_ecm_inst: usb_put_function_instance(fi_ecm); err_acm_inst: @@ -325,7 +422,10 @@ static int nokia_unbind(struct usb_composite_dev *cdev) usb_put_function(f_acm_cfg2); usb_put_function(f_ecm_cfg1); usb_put_function(f_ecm_cfg2); + usb_put_function(f_msg_cfg1); + usb_put_function(f_msg_cfg2); + usb_put_function_instance(fi_msg); usb_put_function_instance(fi_ecm); if (!IS_ERR(fi_obex2)) usb_put_function_instance(fi_obex2); -- cgit v1.2.3 From 5a350d53f4c4784cf6bb4d94e7b8d76ca4f96e9f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 29 Jun 2015 20:17:22 -0500 Subject: usb: dwc2: gadget: use | instead of + for bitmasks It's just a lot clearer to use | operator instead of + operator. Caught by coccicheck: " drivers/usb/dwc2/gadget.c:2883:26-27: WARNING: sum of probable bitmasks, consider | " Cc: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 4d47b7c09238..731b13dfc512 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -2880,7 +2880,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) epctl = readl(hs->regs + epreg); if (value) { - epctl |= DXEPCTL_STALL + DXEPCTL_SNAK; + epctl |= DXEPCTL_STALL | DXEPCTL_SNAK; if (epctl & DXEPCTL_EPENA) epctl |= DXEPCTL_EPDIS; } else { -- cgit v1.2.3 From e4f7566754675b2fd89ed32eee867d5f19bac934 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 30 Jun 2015 12:46:07 -0500 Subject: usb: dwc3: omap: drop dev_dbg() usage Some of the messages were plain unnecessary and some were actually errors. Fix it all up. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 43 ++++--------------------------------------- 1 file changed, 4 insertions(+), 39 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 6b486a36863c..e8a09a88eddd 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -225,12 +225,10 @@ static void dwc3_omap_set_mailbox(struct dwc3_omap *omap, switch (status) { case OMAP_DWC3_ID_GROUND: - dev_dbg(omap->dev, "ID GND\n"); - if (omap->vbus_reg) { ret = regulator_enable(omap->vbus_reg); if (ret) { - dev_dbg(omap->dev, "regulator enable failed\n"); + dev_err(omap->dev, "regulator enable failed\n"); return; } } @@ -245,8 +243,6 @@ static void dwc3_omap_set_mailbox(struct dwc3_omap *omap, break; case OMAP_DWC3_VBUS_VALID: - dev_dbg(omap->dev, "VBUS Connect\n"); - val = dwc3_omap_read_utmi_ctrl(omap); val &= ~USBOTGSS_UTMI_OTG_CTRL_SESSEND; val |= USBOTGSS_UTMI_OTG_CTRL_IDDIG @@ -261,8 +257,6 @@ static void dwc3_omap_set_mailbox(struct dwc3_omap *omap, regulator_disable(omap->vbus_reg); case OMAP_DWC3_VBUS_OFF: - dev_dbg(omap->dev, "VBUS Disconnect\n"); - val = dwc3_omap_read_utmi_ctrl(omap); val &= ~(USBOTGSS_UTMI_OTG_CTRL_SESSVALID | USBOTGSS_UTMI_OTG_CTRL_VBUSVALID @@ -273,7 +267,7 @@ static void dwc3_omap_set_mailbox(struct dwc3_omap *omap, break; default: - dev_dbg(omap->dev, "invalid state\n"); + dev_WARN(omap->dev, "invalid state\n"); } } @@ -284,37 +278,8 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) reg = dwc3_omap_read_irqmisc_status(omap); - if (reg & USBOTGSS_IRQMISC_DMADISABLECLR) { - dev_dbg(omap->dev, "DMA Disable was Cleared\n"); + if (reg & USBOTGSS_IRQMISC_DMADISABLECLR) omap->dma_status = false; - } - - if (reg & USBOTGSS_IRQMISC_OEVT) - dev_dbg(omap->dev, "OTG Event\n"); - - if (reg & USBOTGSS_IRQMISC_DRVVBUS_RISE) - dev_dbg(omap->dev, "DRVVBUS Rise\n"); - - if (reg & USBOTGSS_IRQMISC_CHRGVBUS_RISE) - dev_dbg(omap->dev, "CHRGVBUS Rise\n"); - - if (reg & USBOTGSS_IRQMISC_DISCHRGVBUS_RISE) - dev_dbg(omap->dev, "DISCHRGVBUS Rise\n"); - - if (reg & USBOTGSS_IRQMISC_IDPULLUP_RISE) - dev_dbg(omap->dev, "IDPULLUP Rise\n"); - - if (reg & USBOTGSS_IRQMISC_DRVVBUS_FALL) - dev_dbg(omap->dev, "DRVVBUS Fall\n"); - - if (reg & USBOTGSS_IRQMISC_CHRGVBUS_FALL) - dev_dbg(omap->dev, "CHRGVBUS Fall\n"); - - if (reg & USBOTGSS_IRQMISC_DISCHRGVBUS_FALL) - dev_dbg(omap->dev, "DISCHRGVBUS Fall\n"); - - if (reg & USBOTGSS_IRQMISC_IDPULLUP_FALL) - dev_dbg(omap->dev, "IDPULLUP Fall\n"); dwc3_omap_write_irqmisc_status(omap, reg); @@ -434,7 +399,7 @@ static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap) reg &= ~USBOTGSS_UTMI_OTG_CTRL_SW_MODE; break; default: - dev_dbg(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode); + dev_WARN(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode); } dwc3_omap_write_utmi_ctrl(omap, reg); -- cgit v1.2.3 From 9ff0fdca3b628d3f8719237cbc8f148379527108 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 30 Jun 2015 12:46:53 -0500 Subject: usb: dwc3: keystone: convert dev_dbg() to dev_err() that's an error condition, not a debugging message. Let's promote it appropriately. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-keystone.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/dwc3-keystone.c b/drivers/usb/dwc3/dwc3-keystone.c index fe3b9335a74e..2be268d2423d 100644 --- a/drivers/usb/dwc3/dwc3-keystone.c +++ b/drivers/usb/dwc3/dwc3-keystone.c @@ -115,7 +115,7 @@ static int kdwc3_probe(struct platform_device *pdev) error = clk_prepare_enable(kdwc->clk); if (error < 0) { - dev_dbg(kdwc->dev, "unable to enable usb clock, err %d\n", + dev_err(kdwc->dev, "unable to enable usb clock, error %d\n", error); return error; } -- cgit v1.2.3 From 42f69a02e7ab42f1ec75b91faf05b86e75de794a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 30 Jun 2015 12:47:45 -0500 Subject: usb: dwc3: exynos: switch dev_dbg() to dev_info() that message is informing that the clock is missing. However, that's a valid condition for some setups; driver even ignores the error and continues just fine. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-exynos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index 7bd0a95b2815..dd5cb5577dca 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -145,7 +145,7 @@ static int dwc3_exynos_probe(struct platform_device *pdev) exynos->susp_clk = devm_clk_get(dev, "usbdrd30_susp_clk"); if (IS_ERR(exynos->susp_clk)) { - dev_dbg(dev, "no suspend clk specified\n"); + dev_info(dev, "no suspend clk specified\n"); exynos->susp_clk = NULL; } clk_prepare_enable(exynos->susp_clk); -- cgit v1.2.3 From 2babd0d148a365728649addaaa09bfb690ce6b83 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 30 Jun 2015 12:48:58 -0500 Subject: usb: dwc3: qcom: switch dev_dbg() to dev_info() those two messages are informing that the clock doesn't exist; that, however, is a valid situation and driver continues just fine by ignoring the error. Reviewed-by: Andy Gross Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-qcom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index 8c2e8eec80c2..088026048f49 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -48,13 +48,13 @@ static int dwc3_qcom_probe(struct platform_device *pdev) qdwc->iface_clk = devm_clk_get(qdwc->dev, "iface"); if (IS_ERR(qdwc->iface_clk)) { - dev_dbg(qdwc->dev, "failed to get optional iface clock\n"); + dev_info(qdwc->dev, "failed to get optional iface clock\n"); qdwc->iface_clk = NULL; } qdwc->sleep_clk = devm_clk_get(qdwc->dev, "sleep"); if (IS_ERR(qdwc->sleep_clk)) { - dev_dbg(qdwc->dev, "failed to get optional sleep clock\n"); + dev_info(qdwc->dev, "failed to get optional sleep clock\n"); qdwc->sleep_clk = NULL; } -- cgit v1.2.3 From e746b06cc76afea568c7d53f83a834dc8d720da1 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 30 Jun 2015 12:50:46 -0500 Subject: usb: dwc3: st: remove two unnecessary messages the mode of operation is exposed through debugfs at all times. Because of that, we're removing the unnecessary messages. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-st.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c index 4a1a543deeda..de4d52f62517 100644 --- a/drivers/usb/dwc3/dwc3-st.c +++ b/drivers/usb/dwc3/dwc3-st.c @@ -135,8 +135,6 @@ static int st_dwc3_drd_init(struct st_dwc3 *dwc3_data) | USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2); val |= USB3_DEVICE_NOT_HOST; - - dev_dbg(dwc3_data->dev, "Configuring as Device\n"); break; case USB_DR_MODE_HOST: @@ -154,8 +152,6 @@ static int st_dwc3_drd_init(struct st_dwc3 *dwc3_data) */ val |= USB3_DELAY_VBUSVALID; - - dev_dbg(dwc3_data->dev, "Configuring as Host\n"); break; default: -- cgit v1.2.3 From 9fcfa463e17adc48865b1a4124d48d48e0b59556 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 30 Jun 2015 12:51:49 -0500 Subject: usb: dwc3: drop CONFIG_USB_DWC3_DEBUG now that we have no users of dev_dbg() in dwc3, we can safely remove CONFIG_USB_DWC3_DEBUG. If dev_dbg() is ever strictly necessary - and I don't see why it would, considering we want to rely on tracepoints for debug - we will depend on DYNAMIC_PRINTK to enable such messages. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/Kconfig | 7 ------- drivers/usb/dwc3/Makefile | 2 -- 2 files changed, 9 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index dede32e809b6..5a42c4590402 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -104,11 +104,4 @@ config USB_DWC3_QCOM Recent Qualcomm SoCs ship with one DesignWare Core USB3 IP inside, say 'Y' or 'M' if you have one such device. -comment "Debugging features" - -config USB_DWC3_DEBUG - bool "Enable Debugging Messages" - help - Say Y here to enable debugging messages on DWC3 Driver. - endif diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index c7076e37c4ed..acc951d46c27 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -1,8 +1,6 @@ # define_trace.h needs to know how to find our header CFLAGS_trace.o := -I$(src) -ccflags-$(CONFIG_USB_DWC3_DEBUG) := -DDEBUG - obj-$(CONFIG_USB_DWC3) += dwc3.o dwc3-y := core.o debug.o trace.o -- cgit v1.2.3 From e425be9304ce4da9cd231b55630ca941752635e9 Mon Sep 17 00:00:00 2001 From: Krzysztof Opasiak Date: Fri, 19 Jun 2015 12:05:05 +0200 Subject: usb: gadget: loopback: Remove out-of-date comment As loopback function has been reworked for ConfigFS composite gadget this comment is no longer valid. Signed-off-by: Krzysztof Opasiak Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_loopback.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_loopback.c b/drivers/usb/gadget/function/f_loopback.c index 39f49f1ad22f..6e2fe63b9267 100644 --- a/drivers/usb/gadget/function/f_loopback.c +++ b/drivers/usb/gadget/function/f_loopback.c @@ -28,11 +28,6 @@ * This takes messages of various sizes written OUT to a device, and loops * them back so they can be read IN from it. It has been used by certain * test applications. It supports limited testing of data queueing logic. - * - * - * This is currently packaged as a configuration driver, which can't be - * combined with other functions to make composite devices. However, it - * can be combined with other independent configurations. */ struct f_loopback { struct usb_function function; -- cgit v1.2.3 From d3c1ac4a69667300996ea76fe25c33434372a2a8 Mon Sep 17 00:00:00 2001 From: Krzysztof Opasiak Date: Fri, 19 Jun 2015 12:16:45 +0200 Subject: usb: gadget: SourceSink: Remove out-of-date comment As SourceSink function has been reworked for ConfigFS composite gadget this comment is no longer valid. Signed-off-by: Krzysztof Opasiak Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_sourcesink.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c index 3a5ae9900b1e..e6af1719d851 100644 --- a/drivers/usb/gadget/function/f_sourcesink.c +++ b/drivers/usb/gadget/function/f_sourcesink.c @@ -42,11 +42,6 @@ * queues are relatively independent, will receive a range of packet sizes, * and can often be made to run out completely. Those issues are important * when stress testing peripheral controller drivers. - * - * - * This is currently packaged as a configuration driver, which can't be - * combined with other functions to make composite devices. However, it - * can be combined with other independent configurations. */ struct f_sourcesink { struct usb_function function; -- cgit v1.2.3 From b8464bcf0a20970471e8f897fe4706fcc2702263 Mon Sep 17 00:00:00 2001 From: Vaishali Thakkar Date: Sat, 6 Jun 2015 07:02:53 +0530 Subject: usb: gadget: Convert use of __constant_cpu_to_le16 to cpu_to_le16 In big endian cases, macro cpu_to_le16 unfolds to __swab16 which provides special case for constants. In little endian cases, __constant_cpu_to_le16 and cpu_to_le16 expand directly to the same expression. So, replace __constant_cpu_to_le16 with cpu_to_le16 with the goal of getting rid of the definition of __constant_cpu_to_le16 completely. The semantic patch that performs this transformation is as follows: @@expression x;@@ - __constant_cpu_to_le16(x) + cpu_to_le16(x) Signed-off-by: Vaishali Thakkar Signed-off-by: Felipe Balbi --- drivers/usb/gadget/legacy/audio.c | 6 +++--- drivers/usb/gadget/legacy/dbgp.c | 10 +++++----- drivers/usb/gadget/legacy/gmidi.c | 6 +++--- drivers/usb/gadget/legacy/nokia.c | 6 +++--- 4 files changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/legacy/audio.c b/drivers/usb/gadget/legacy/audio.c index f289caf18a45..b8095bfe57b6 100644 --- a/drivers/usb/gadget/legacy/audio.c +++ b/drivers/usb/gadget/legacy/audio.c @@ -124,7 +124,7 @@ static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x200), + .bcdUSB = cpu_to_le16(0x200), #ifdef CONFIG_GADGET_UAC1 .bDeviceClass = USB_CLASS_PER_INTERFACE, @@ -141,8 +141,8 @@ static struct usb_device_descriptor device_desc = { * we support. (As does bNumConfigurations.) These values can * also be overridden by module parameters. */ - .idVendor = __constant_cpu_to_le16(AUDIO_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16(AUDIO_PRODUCT_NUM), + .idVendor = cpu_to_le16(AUDIO_VENDOR_NUM), + .idProduct = cpu_to_le16(AUDIO_PRODUCT_NUM), /* .bcdDevice = f(hardware) */ /* .iManufacturer = DYNAMIC */ /* .iProduct = DYNAMIC */ diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c index 204b10b1a7e7..5231a32aef55 100644 --- a/drivers/usb/gadget/legacy/dbgp.c +++ b/drivers/usb/gadget/legacy/dbgp.c @@ -35,10 +35,10 @@ static struct dbgp { static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_VENDOR_SPEC, - .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_ID), - .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_ID), + .idVendor = cpu_to_le16(DRIVER_VENDOR_ID), + .idProduct = cpu_to_le16(DRIVER_PRODUCT_ID), .bNumConfigurations = 1, }; @@ -251,7 +251,7 @@ static int dbgp_configure_endpoints(struct usb_gadget *gadget) dbgp.i_ep->driver_data = gadget; i_desc.wMaxPacketSize = - __constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE); + cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE); dbgp.o_ep = usb_ep_autoconfig(gadget, &o_desc); if (!dbgp.o_ep) { @@ -262,7 +262,7 @@ static int dbgp_configure_endpoints(struct usb_gadget *gadget) dbgp.o_ep->driver_data = gadget; o_desc.wMaxPacketSize = - __constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE); + cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE); dbg_desc.bDebugInEndpoint = i_desc.bEndpointAddress; dbg_desc.bDebugOutEndpoint = o_desc.bEndpointAddress; diff --git a/drivers/usb/gadget/legacy/gmidi.c b/drivers/usb/gadget/legacy/gmidi.c index da19c486b61e..650568de0de3 100644 --- a/drivers/usb/gadget/legacy/gmidi.c +++ b/drivers/usb/gadget/legacy/gmidi.c @@ -88,10 +88,10 @@ MODULE_PARM_DESC(out_ports, "Number of MIDI output ports"); static struct usb_device_descriptor device_desc = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_PER_INTERFACE, - .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_NUM), + .idVendor = cpu_to_le16(DRIVER_VENDOR_NUM), + .idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM), /* .iManufacturer = DYNAMIC */ /* .iProduct = DYNAMIC */ .bNumConfigurations = 1, diff --git a/drivers/usb/gadget/legacy/nokia.c b/drivers/usb/gadget/legacy/nokia.c index e3791b919996..8902f454b7bc 100644 --- a/drivers/usb/gadget/legacy/nokia.c +++ b/drivers/usb/gadget/legacy/nokia.c @@ -90,10 +90,10 @@ static struct usb_gadget_strings *dev_strings[] = { static struct usb_device_descriptor device_desc = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_COMM, - .idVendor = __constant_cpu_to_le16(NOKIA_VENDOR_ID), - .idProduct = __constant_cpu_to_le16(NOKIA_PRODUCT_ID), + .idVendor = cpu_to_le16(NOKIA_VENDOR_ID), + .idProduct = cpu_to_le16(NOKIA_PRODUCT_ID), .bcdDevice = cpu_to_le16(NOKIA_VERSION_NUM), /* .iManufacturer = DYNAMIC */ /* .iProduct = DYNAMIC */ -- cgit v1.2.3 From ad4676ab58ae38e5597a2d6bc0d12e9b5e0b0d18 Mon Sep 17 00:00:00 2001 From: Diego Viola Date: Sun, 31 May 2015 15:52:41 -0300 Subject: usb: gadget: composite.c: i18n is not an acronym I18N should be spelled as i18n because it's not an acronym Signed-off-by: Diego Viola Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 58b4657fc721..9ff3203b50e2 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -896,7 +896,7 @@ void usb_remove_config(struct usb_composite_dev *cdev, /* We support strings in multiple languages ... string descriptor zero * says which languages are supported. The typical case will be that - * only one language (probably English) is used, with I18N handled on + * only one language (probably English) is used, with i18n handled on * the host side. */ @@ -949,7 +949,7 @@ static int get_string(struct usb_composite_dev *cdev, struct usb_function *f; int len; - /* Yes, not only is USB's I18N support probably more than most + /* Yes, not only is USB's i18n support probably more than most * folk will ever care about ... also, it's all supported here. * (Except for UTF8 support for Unicode's "Astral Planes".) */ -- cgit v1.2.3 From b5c03bffa67727697252e913f64703e3404867ae Mon Sep 17 00:00:00 2001 From: Vaishali Thakkar Date: Wed, 10 Jun 2015 16:04:25 +0530 Subject: usb: udc: Convert use of __constant_cpu_to_leXX to cpu_to_leXX In big endian cases, the macro cpu_to_le{16,32} unfolds to __swab{16,32} which provides special case for constants. In little endian cases, __constant_cpu_to_le{16,32} and cpu_to_le{16,32} expand directly to the same expression. So, replace __constant_cpu_to_le{16,32} with cpu_to_le{16,32} with the goal of getting rid of the definition of __constant_cpu_to_le{16,32} completely. The semantic patch that performs this transformation is as follows: @@expression x;@@ ( - __constant_cpu_to_le16(x) + cpu_to_le16(x) | - __constant_cpu_to_le32(x) + cpu_to_le32(x) ) Signed-off-by: Vaishali Thakkar Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/net2272.c | 4 ++-- drivers/usb/gadget/udc/pch_udc.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c index 195baf3e1fcd..c2ed5daebb75 100644 --- a/drivers/usb/gadget/udc/net2272.c +++ b/drivers/usb/gadget/udc/net2272.c @@ -1826,9 +1826,9 @@ net2272_handle_stat0_irqs(struct net2272 *dev, u8 stat) if (!e || u.r.wLength > 2) goto do_stall; if (net2272_ep_read(e, EP_RSPSET) & (1 << ENDPOINT_HALT)) - status = __constant_cpu_to_le16(1); + status = cpu_to_le16(1); else - status = __constant_cpu_to_le16(0); + status = cpu_to_le16(0); /* don't bother with a request object! */ net2272_ep_write(&dev->ep[0], EP_IRQENB, 0); diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c index 613547f07828..dcf5defdb9e5 100644 --- a/drivers/usb/gadget/udc/pch_udc.c +++ b/drivers/usb/gadget/udc/pch_udc.c @@ -1793,7 +1793,7 @@ static struct usb_request *pch_udc_alloc_request(struct usb_ep *usbep, } /* prevent from using desc. - set HOST BUSY */ dma_desc->status |= PCH_UDC_BS_HST_BSY; - dma_desc->dataptr = __constant_cpu_to_le32(DMA_ADDR_INVALID); + dma_desc->dataptr = cpu_to_le32(DMA_ADDR_INVALID); req->td_data = dma_desc; req->td_data_last = dma_desc; req->chain_len = 1; -- cgit v1.2.3 From 5960387a2fb8314687351f6d8485cf62d7722b4e Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Wed, 1 Jul 2015 13:11:30 +0900 Subject: usb: dwc3: omap: Replace deprecated API of extcon This patch removes the deprecated notifier API of extcon framwork and then use the new extcon API with the unique id to indicate the each external connector (USB, USB-HOST). Alter deprecated API as following: - extcon_register_interest() -> extcon_register_notifier() - extcon_get_cable_state(*edev, char *) -> extcon_get_cable_state_(*edev, id) Cc: Felipe Balbi Cc: Greg Kroah-Hartman Signed-off-by: Chanwoo Choi Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index e8a09a88eddd..a5a1b7c45743 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -128,8 +128,7 @@ struct dwc3_omap { u32 dma_status:1; - struct extcon_specific_cable_nb extcon_vbus_dev; - struct extcon_specific_cable_nb extcon_id_dev; + struct extcon_dev *edev; struct notifier_block vbus_nb; struct notifier_block id_nb; @@ -419,23 +418,23 @@ static int dwc3_omap_extcon_register(struct dwc3_omap *omap) } omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier; - ret = extcon_register_interest(&omap->extcon_vbus_dev, - edev->name, "USB", - &omap->vbus_nb); + ret = extcon_register_notifier(edev, EXTCON_USB, + &omap->vbus_nb); if (ret < 0) dev_vdbg(omap->dev, "failed to register notifier for USB\n"); omap->id_nb.notifier_call = dwc3_omap_id_notifier; - ret = extcon_register_interest(&omap->extcon_id_dev, - edev->name, "USB-HOST", - &omap->id_nb); + ret = extcon_register_notifier(edev, EXTCON_USB_HOST, + &omap->id_nb); if (ret < 0) dev_vdbg(omap->dev, "failed to register notifier for USB-HOST\n"); - if (extcon_get_cable_state(edev, "USB") == true) + if (extcon_get_cable_state_(edev, EXTCON_USB) == true) dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID); - if (extcon_get_cable_state(edev, "USB-HOST") == true) + if (extcon_get_cable_state_(edev, EXTCON_USB_HOST) == true) dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND); + + omap->edev = edev; } return 0; @@ -530,11 +529,8 @@ static int dwc3_omap_probe(struct platform_device *pdev) return 0; err3: - if (omap->extcon_vbus_dev.edev) - extcon_unregister_interest(&omap->extcon_vbus_dev); - if (omap->extcon_id_dev.edev) - extcon_unregister_interest(&omap->extcon_id_dev); - + extcon_unregister_notifier(omap->edev, EXTCON_USB, &omap->vbus_nb); + extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb); err2: dwc3_omap_disable_irqs(omap); @@ -551,10 +547,8 @@ static int dwc3_omap_remove(struct platform_device *pdev) { struct dwc3_omap *omap = platform_get_drvdata(pdev); - if (omap->extcon_vbus_dev.edev) - extcon_unregister_interest(&omap->extcon_vbus_dev); - if (omap->extcon_id_dev.edev) - extcon_unregister_interest(&omap->extcon_id_dev); + extcon_unregister_notifier(omap->edev, EXTCON_USB, &omap->vbus_nb); + extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb); dwc3_omap_disable_irqs(omap); of_platform_depopulate(omap->dev); pm_runtime_put_sync(&pdev->dev); -- cgit v1.2.3 From a2fd2423240fe1abd7a154a1cc0fd1624c339bff Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Wed, 1 Jul 2015 13:11:31 +0900 Subject: usb: phy: omap-otg: Replace deprecated API of extcon This patch removes the deprecated notifier API of extcon framwork and then use the new extcon API with the unique id to indicate the each external connector (USB, USB-HOST). Alter deprecated API as following: - extcon_register_interest() -> extcon_register_notifier() - extcon_get_cable_state(*edev, char *) -> extcon_get_cable_state_(*edev, id) [ balbi@ti.com : fix build break ] Cc: Greg Kroah-Hartman Signed-off-by: Chanwoo Choi Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-omap-otg.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/phy/phy-omap-otg.c b/drivers/usb/phy/phy-omap-otg.c index 56ee7603034b..1270906ccb95 100644 --- a/drivers/usb/phy/phy-omap-otg.c +++ b/drivers/usb/phy/phy-omap-otg.c @@ -30,8 +30,7 @@ struct otg_device { void __iomem *base; bool id; bool vbus; - struct extcon_specific_cable_nb vbus_dev; - struct extcon_specific_cable_nb id_dev; + struct extcon_dev *extcon; struct notifier_block vbus_nb; struct notifier_block id_nb; }; @@ -106,6 +105,7 @@ static int omap_otg_probe(struct platform_device *pdev) extcon = extcon_get_extcon_dev(config->extcon); if (!extcon) return -EPROBE_DEFER; + otg_dev->extcon = extcon; otg_dev = devm_kzalloc(&pdev->dev, sizeof(*otg_dev), GFP_KERNEL); if (!otg_dev) @@ -118,20 +118,19 @@ static int omap_otg_probe(struct platform_device *pdev) otg_dev->id_nb.notifier_call = omap_otg_id_notifier; otg_dev->vbus_nb.notifier_call = omap_otg_vbus_notifier; - ret = extcon_register_interest(&otg_dev->id_dev, config->extcon, - "USB-HOST", &otg_dev->id_nb); + ret = extcon_register_notifier(extcon, EXTCON_USB_HOST, &otg_dev->id_nb); if (ret) return ret; - ret = extcon_register_interest(&otg_dev->vbus_dev, config->extcon, - "USB", &otg_dev->vbus_nb); + ret = extcon_register_notifier(extcon, EXTCON_USB, &otg_dev->vbus_nb); if (ret) { - extcon_unregister_interest(&otg_dev->id_dev); + extcon_unregister_notifier(extcon, EXTCON_USB_HOST, + &otg_dev->id_nb); return ret; } - otg_dev->id = extcon_get_cable_state(extcon, "USB-HOST"); - otg_dev->vbus = extcon_get_cable_state(extcon, "USB"); + otg_dev->id = extcon_get_cable_state_(extcon, EXTCON_USB_HOST); + otg_dev->vbus = extcon_get_cable_state_(extcon, EXTCON_USB); omap_otg_set_mode(otg_dev); rev = readl(otg_dev->base); @@ -147,9 +146,10 @@ static int omap_otg_probe(struct platform_device *pdev) static int omap_otg_remove(struct platform_device *pdev) { struct otg_device *otg_dev = platform_get_drvdata(pdev); + struct extcon_dev *edev = otg_dev->extcon; - extcon_unregister_interest(&otg_dev->id_dev); - extcon_unregister_interest(&otg_dev->vbus_dev); + extcon_unregister_notifier(edev, EXTCON_USB_HOST,&otg_dev->id_nb); + extcon_unregister_notifier(edev, EXTCON_USB, &otg_dev->vbus_nb); return 0; } -- cgit v1.2.3 From 860d2686fda7e4dceaa4e676e62adcdbfc7f7a2c Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Wed, 1 Jul 2015 13:11:32 +0900 Subject: usb: phy: tahvo: Use devm_extcon_dev_[allocate|register]() and replace deprecated API This patch uses the devm_extcon_dev_[allocate|register]() to manage the resource automatically and replace deprecated API as following: - extcon_[set|get]_cable_state(*edev, char *) -> extcon_[set|get]_cable_state_(*edev, id) Cc: Felipe Balbi Cc: Greg Kroah-Hartman Signed-off-by: Chanwoo Choi Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-tahvo.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c index b40d6a87d694..ab5d364f6e8c 100644 --- a/drivers/usb/phy/phy-tahvo.c +++ b/drivers/usb/phy/phy-tahvo.c @@ -57,7 +57,7 @@ struct tahvo_usb { struct clk *ick; int irq; int tahvo_mode; - struct extcon_dev extcon; + struct extcon_dev *extcon; }; static const unsigned int tahvo_cable[] = { @@ -121,7 +121,7 @@ static void check_vbus_state(struct tahvo_usb *tu) prev_state = tu->vbus_state; tu->vbus_state = reg & TAHVO_STAT_VBUS; if (prev_state != tu->vbus_state) { - extcon_set_cable_state(&tu->extcon, "USB", tu->vbus_state); + extcon_set_cable_state_(tu->extcon, EXTCON_USB, tu->vbus_state); sysfs_notify(&tu->pt_dev->dev.kobj, NULL, "vbus_state"); } } @@ -130,7 +130,7 @@ static void tahvo_usb_become_host(struct tahvo_usb *tu) { struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent); - extcon_set_cable_state(&tu->extcon, "USB-HOST", true); + extcon_set_cable_state_(tu->extcon, EXTCON_USB_HOST, true); /* Power up the transceiver in USB host mode */ retu_write(rdev, TAHVO_REG_USBR, USBR_REGOUT | USBR_NSUSPEND | @@ -149,7 +149,7 @@ static void tahvo_usb_become_peripheral(struct tahvo_usb *tu) { struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent); - extcon_set_cable_state(&tu->extcon, "USB-HOST", false); + extcon_set_cable_state_(tu->extcon, EXTCON_USB_HOST, false); /* Power up transceiver and set it in USB peripheral mode */ retu_write(rdev, TAHVO_REG_USBR, USBR_SLAVE_CONTROL | USBR_REGOUT | @@ -365,11 +365,13 @@ static int tahvo_usb_probe(struct platform_device *pdev) */ tu->vbus_state = retu_read(rdev, TAHVO_REG_IDSR) & TAHVO_STAT_VBUS; - tu->extcon.name = DRIVER_NAME; - tu->extcon.supported_cable = tahvo_cable; - tu->extcon.dev.parent = &pdev->dev; + tu->extcon = devm_extcon_dev_allocate(&pdev->dev, tahvo_cable); + if (IS_ERR(tu->extcon)) { + dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); + return -ENOMEM; + } - ret = extcon_dev_register(&tu->extcon); + ret = devm_extcon_dev_register(&pdev->dev, tu->extcon); if (ret) { dev_err(&pdev->dev, "could not register extcon device: %d\n", ret); @@ -377,9 +379,9 @@ static int tahvo_usb_probe(struct platform_device *pdev) } /* Set the initial cable state. */ - extcon_set_cable_state(&tu->extcon, "USB-HOST", + extcon_set_cable_state_(tu->extcon, EXTCON_USB_HOST, tu->tahvo_mode == TAHVO_MODE_HOST); - extcon_set_cable_state(&tu->extcon, "USB", tu->vbus_state); + extcon_set_cable_state_(tu->extcon, EXTCON_USB, tu->vbus_state); /* Create OTG interface */ tahvo_usb_power_off(tu); @@ -396,7 +398,7 @@ static int tahvo_usb_probe(struct platform_device *pdev) if (ret < 0) { dev_err(&pdev->dev, "cannot register USB transceiver: %d\n", ret); - goto err_extcon_unreg; + goto err_disable_clk; } dev_set_drvdata(&pdev->dev, tu); @@ -424,8 +426,6 @@ err_free_irq: free_irq(tu->irq, tu); err_remove_phy: usb_remove_phy(&tu->phy); -err_extcon_unreg: - extcon_dev_unregister(&tu->extcon); err_disable_clk: if (!IS_ERR(tu->ick)) clk_disable(tu->ick); @@ -440,7 +440,6 @@ static int tahvo_usb_remove(struct platform_device *pdev) sysfs_remove_group(&pdev->dev.kobj, &tahvo_attr_group); free_irq(tu->irq, tu); usb_remove_phy(&tu->phy); - extcon_dev_unregister(&tu->extcon); if (!IS_ERR(tu->ick)) clk_disable(tu->ick); -- cgit v1.2.3 From 50297b79b8fd426f678431a8e9dcee59afd33ec8 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Wed, 1 Jul 2015 13:11:33 +0900 Subject: usb: renesas_usbhs: Replace deprecated API of extcon This patch removes the deprecated API of extcon and then use the new extcon API with the unique id to indicate the each external connector (USB-HOST). - extcon_get_cable_state(*edev, char *) -> extcon_get_cable_state_(*edev, id) Cc: Greg Kroah-Hartman Cc: Felipe Balbi Cc: Yoshihiro Shimoda Cc: Sergei Shtylyov Cc: Yoshihiro Shimoda Cc: Peter Chen Cc: Varka Bhadram Cc: Takeshi Kihara Signed-off-by: Chanwoo Choi Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index e8bf40808b39..7b98e1d9194c 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -388,7 +388,7 @@ static void usbhsc_hotplug(struct usbhs_priv *priv) if (enable && !mod) { if (priv->edev) { - cable = extcon_get_cable_state(priv->edev, "USB-HOST"); + cable = extcon_get_cable_state_(priv->edev, EXTCON_USB_HOST); if ((cable > 0 && id != USBHS_HOST) || (!cable && id != USBHS_GADGET)) { dev_info(&pdev->dev, -- cgit v1.2.3 From 83b7b67c780500a1d5d87c44ee8963166154adfa Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Wed, 1 Jul 2015 13:11:34 +0900 Subject: usb: phy: msm-usb: Replace deprecated API of extcon This patch removes the deprecated notifier API of extcon framwork and then use the new extcon API with the unique id to indicate the each external connector (USB, USB-HOST). Alter deprecated API as following: - extcon_register_interest() -> extcon_register_notifier() - extcon_get_cable_state(*edev, char *) -> extcon_get_cable_state_(*edev, id) Cc: Felipe Balbi Cc: Greg Kroah-Hartman Signed-off-by: Chanwoo Choi Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-msm-usb.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 00c49bb1bd29..61d86d8bf5b7 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -1561,15 +1561,16 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) } if (!IS_ERR(ext_vbus)) { + motg->vbus.extcon = ext_vbus; motg->vbus.nb.notifier_call = msm_otg_vbus_notifier; - ret = extcon_register_interest(&motg->vbus.conn, ext_vbus->name, - "USB", &motg->vbus.nb); + ret = extcon_register_notifier(ext_vbus, EXTCON_USB, + &motg->vbus.nb); if (ret < 0) { dev_err(&pdev->dev, "register VBUS notifier failed\n"); return ret; } - ret = extcon_get_cable_state(ext_vbus, "USB"); + ret = extcon_get_cable_state_(ext_vbus, EXTCON_USB); if (ret) set_bit(B_SESS_VLD, &motg->inputs); else @@ -1577,15 +1578,16 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) } if (!IS_ERR(ext_id)) { + motg->id.extcon = ext_id; motg->id.nb.notifier_call = msm_otg_id_notifier; - ret = extcon_register_interest(&motg->id.conn, ext_id->name, - "USB-HOST", &motg->id.nb); + ret = extcon_register_notifier(ext_id, EXTCON_USB_HOST, + &motg->id.nb); if (ret < 0) { dev_err(&pdev->dev, "register ID notifier failed\n"); return ret; } - ret = extcon_get_cable_state(ext_id, "USB-HOST"); + ret = extcon_get_cable_state_(ext_id, EXTCON_USB_HOST); if (ret) clear_bit(ID, &motg->inputs); else @@ -1805,10 +1807,8 @@ static int msm_otg_remove(struct platform_device *pdev) if (phy->otg->host || phy->otg->gadget) return -EBUSY; - if (motg->id.conn.edev) - extcon_unregister_interest(&motg->id.conn); - if (motg->vbus.conn.edev) - extcon_unregister_interest(&motg->vbus.conn); + extcon_unregister_notifier(motg->id.extcon, EXTCON_USB_HOST, &motg->id.nb); + extcon_unregister_notifier(motg->vbus.extcon, EXTCON_USB, &motg->vbus.nb); msm_otg_debugfs_cleanup(); cancel_delayed_work_sync(&motg->chg_work); -- cgit v1.2.3 From 2df033ca39b56605725384bac1579cdd30e052a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 6 Jul 2015 11:09:48 +0200 Subject: usb: dwc3: pci: make better use of gpiod API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since 39b2bbe3d715 (gpio: add flags argument to gpiod_get*() functions) which appeared in v3.17-rc1, the gpiod_get* functions take an additional parameter that allows to specify direction and initial value for output. Use this additional parameter and the _optional variant to simplify the driver and improve error handling. Also expand the comment to explain why it's not sensible to switch to devm_gpiod_get and why the gpiod_put is also necessary. Furthermore this is one caller less that stops us making the flags argument to gpiod_get*() mandatory. Tested-by: Heikki Krogerus Signed-off-by: Uwe Kleine-König Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-pci.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 27e4fc896e9d..f62617999f3c 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -83,17 +83,23 @@ static int dwc3_pci_quirks(struct pci_dev *pdev) acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev), acpi_dwc3_byt_gpios); - /* These GPIOs will turn on the USB2 PHY */ - gpio = gpiod_get(&pdev->dev, "cs"); - if (!IS_ERR(gpio)) { - gpiod_direction_output(gpio, 0); - gpiod_set_value_cansleep(gpio, 1); - gpiod_put(gpio); - } + /* + * These GPIOs will turn on the USB2 PHY. Note that we have to + * put the gpio descriptors again here because the phy driver + * might want to grab them, too. + */ + gpio = gpiod_get_optional(&pdev->dev, "cs", GPIOD_OUT_LOW); + if (IS_ERR(gpio)) + return PTR_ERR(gpio); + + gpiod_set_value_cansleep(gpio, 1); + gpiod_put(gpio); + + gpio = gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(gpio)) + return PTR_ERR(gpio); - gpio = gpiod_get(&pdev->dev, "reset"); - if (!IS_ERR(gpio)) { - gpiod_direction_output(gpio, 0); + if (gpio) { gpiod_set_value_cansleep(gpio, 1); gpiod_put(gpio); usleep_range(10000, 11000); -- cgit v1.2.3 From 88167fc0b22aac0fe7b9c4fadf9c251a9f864f32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 6 Jul 2015 11:09:49 +0200 Subject: usb: pass flags parameter to gpiod_get functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since 39b2bbe3d715 (gpio: add flags argument to gpiod_get*() functions) which appeared in v3.17-rc1, the gpiod_get* functions take an additional parameter that allows to specify direction and initial value for output. Currently this parameter is made optional with the help of a cpp trick. To allow dropping this hack convert callers to explictly pass a value for flags. Acked-by: Felipe Balbi Acked-by: Robert Jarzmik Signed-off-by: Uwe Kleine-König Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/pxa27x_udc.c | 2 +- drivers/usb/phy/phy-generic.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c index b51226abade6..042f06b52677 100644 --- a/drivers/usb/gadget/udc/pxa27x_udc.c +++ b/drivers/usb/gadget/udc/pxa27x_udc.c @@ -2422,7 +2422,7 @@ static int pxa_udc_probe(struct platform_device *pdev) } udc->udc_command = mach->udc_command; } else { - udc->gpiod = devm_gpiod_get(&pdev->dev, NULL); + udc->gpiod = devm_gpiod_get(&pdev->dev, NULL, GPIOD_ASIS); } regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c index deee68eafb72..ec6ecd03269c 100644 --- a/drivers/usb/phy/phy-generic.c +++ b/drivers/usb/phy/phy-generic.c @@ -218,11 +218,13 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop, clk_rate = 0; needs_vcc = of_property_read_bool(node, "vcc-supply"); - nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset"); + nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset", + GPIOD_ASIS); err = PTR_ERR_OR_ZERO(nop->gpiod_reset); if (!err) { nop->gpiod_vbus = devm_gpiod_get_optional(dev, - "vbus-detect"); + "vbus-detect", + GPIOD_ASIS); err = PTR_ERR_OR_ZERO(nop->gpiod_vbus); } } else if (pdata) { -- cgit v1.2.3 From d9972f470bcb40947dd91af90f17f9cb01db1f41 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 7 Jul 2015 13:45:23 -0500 Subject: usb: dwc3: core: remove unnecessary dev_warn() When a SoC supports both PHY interfaces but doesn't define HSPHY in DT/pdata, we will get an unnecessary dev_warn() which can mislead users into thinking that they're missing something. Instead, let's just silently rely on a correct default. If the HW default is wrong, then HSPHY is required and USB won't work, this will be motivation enough for engineers to patch their way into a working setup. Reported-by: Murali Karicheri Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index ff5773c66b84..064123e44566 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -455,8 +455,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc) reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); } else { - dev_warn(dwc->dev, "HSPHY Interface not defined\n"); - /* Relying on default value. */ if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI)) break; -- cgit v1.2.3 From 7eaeac5c0e44921eb583d5b59b9c54741ecaa899 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 20 Jul 2015 14:46:15 -0500 Subject: usb: dwc3: gadget: add a trace when disabling EPs We have a "Enabling %s" trace when enabling an endpoint but that message felt lonely without a matching "Disabling %s". Add it. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 333a7c0078fc..1f8f730c7cc5 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -586,6 +586,8 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) struct dwc3 *dwc = dep->dwc; u32 reg; + dwc3_trace(trace_dwc3_gadget, "Disabling %s", dep->name); + dwc3_remove_requests(dwc, dep); /* make sure HW endpoint isn't stalled */ -- cgit v1.2.3 From aa7399744dd02537523b7bf9e3070600b6f79751 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 20 Jul 2015 14:48:13 -0500 Subject: usb: dwc3: gadget: defer endpoint name change We should only change endpoint names when we actually manage to enable/disable it. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 1f8f730c7cc5..d97fcfa8fe87 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -547,6 +547,23 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, trb_link->ctrl |= DWC3_TRB_CTRL_HWO; } + switch (usb_endpoint_type(desc)) { + case USB_ENDPOINT_XFER_CONTROL: + strlcat(dep->name, "-control", sizeof(dep->name)); + break; + case USB_ENDPOINT_XFER_ISOC: + strlcat(dep->name, "-isoc", sizeof(dep->name)); + break; + case USB_ENDPOINT_XFER_BULK: + strlcat(dep->name, "-bulk", sizeof(dep->name)); + break; + case USB_ENDPOINT_XFER_INT: + strlcat(dep->name, "-int", sizeof(dep->name)); + break; + default: + dev_err(dwc->dev, "invalid endpoint transfer type\n"); + } + return 0; } @@ -604,6 +621,10 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) dep->type = 0; dep->flags = 0; + snprintf(dep->name, sizeof(dep->name), "ep%d%s", + dep->number >> 1, + (dep->number & 1) ? "in" : "out"); + return 0; } @@ -649,23 +670,6 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep, return 0; } - switch (usb_endpoint_type(desc)) { - case USB_ENDPOINT_XFER_CONTROL: - strlcat(dep->name, "-control", sizeof(dep->name)); - break; - case USB_ENDPOINT_XFER_ISOC: - strlcat(dep->name, "-isoc", sizeof(dep->name)); - break; - case USB_ENDPOINT_XFER_BULK: - strlcat(dep->name, "-bulk", sizeof(dep->name)); - break; - case USB_ENDPOINT_XFER_INT: - strlcat(dep->name, "-int", sizeof(dep->name)); - break; - default: - dev_err(dwc->dev, "invalid endpoint transfer type\n"); - } - spin_lock_irqsave(&dwc->lock, flags); ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc, false, false); spin_unlock_irqrestore(&dwc->lock, flags); @@ -694,10 +698,6 @@ static int dwc3_gadget_ep_disable(struct usb_ep *ep) return 0; } - snprintf(dep->name, sizeof(dep->name), "ep%d%s", - dep->number >> 1, - (dep->number & 1) ? "in" : "out"); - spin_lock_irqsave(&dwc->lock, flags); ret = __dwc3_gadget_ep_disable(dep); spin_unlock_irqrestore(&dwc->lock, flags); -- cgit v1.2.3 From 903588a99c26ed6f103eaa0cfa4ccbe9cd779398 Mon Sep 17 00:00:00 2001 From: Krzysztof Opasiak Date: Mon, 20 Jul 2015 20:15:17 +0200 Subject: usb: gadget: mass_storage: Free buffers if create lun fails Creation of LUN 0 may fail (for example due to ENOMEM). As fsg_common_set_num_buffers() does some memory allocation we should free it before it becomes unavailable. Signed-off-by: Krzysztof Opasiak Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_mass_storage.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index f936268d26c6..f72102adc7ef 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -3524,6 +3524,9 @@ static struct usb_function_instance *fsg_alloc_inst(void) config.removable = true; rc = fsg_common_create_lun(opts->common, &config, 0, "lun.0", (const char **)&opts->func_inst.group.cg_item.ci_name); + if (rc) + goto release_buffers; + opts->lun0.lun = opts->common->luns[0]; opts->lun0.lun_id = 0; config_group_init_type_name(&opts->lun0.group, "lun.0", &fsg_lun_type); @@ -3534,6 +3537,8 @@ static struct usb_function_instance *fsg_alloc_inst(void) return &opts->func_inst; +release_buffers: + fsg_common_free_buffers(opts->common); release_luns: kfree(opts->common->luns); release_opts: -- cgit v1.2.3 From bab7a1f199fa617c7a0600c74ebbb514aed6dbe8 Mon Sep 17 00:00:00 2001 From: Krzysztof Opasiak Date: Mon, 20 Jul 2015 20:15:18 +0200 Subject: usb: gadget: mass_storage: Place EXPORT_SYMBOL_GPL() after func definition EXPORT_SYMBOL_GPL() is usually placed after function definition not before. Signed-off-by: Krzysztof Opasiak Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_mass_storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index f72102adc7ef..c3b62c7cb584 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -2761,12 +2761,12 @@ static void _fsg_common_remove_luns(struct fsg_common *common, int n) common->luns[i] = NULL; } } -EXPORT_SYMBOL_GPL(fsg_common_remove_luns); void fsg_common_remove_luns(struct fsg_common *common) { _fsg_common_remove_luns(common, common->nluns); } +EXPORT_SYMBOL_GPL(fsg_common_remove_luns); void fsg_common_free_luns(struct fsg_common *common) { -- cgit v1.2.3 From 75ddead2a77db61e818bc0cbe330a856a912f4d9 Mon Sep 17 00:00:00 2001 From: Krzysztof Opasiak Date: Mon, 20 Jul 2015 20:15:19 +0200 Subject: usb: gadget: storage-common: Set FSG_MAX_LUNS to 16 Mass storage spec allows up to 16 LUNs, so let's not add some more restrictive limits. Signed-off-by: Krzysztof Opasiak Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_mass_storage.c | 2 +- drivers/usb/gadget/function/storage_common.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index c3b62c7cb584..9e88e2b18d95 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -54,7 +54,7 @@ * following fields: * * nluns Number of LUNs function have (anywhere from 1 - * to FSG_MAX_LUNS which is 8). + * to FSG_MAX_LUNS). * luns An array of LUN configuration values. This * should be filled for each LUN that * function will include (ie. for "nluns" diff --git a/drivers/usb/gadget/function/storage_common.h b/drivers/usb/gadget/function/storage_common.h index 70c891469f57..c3544e61da66 100644 --- a/drivers/usb/gadget/function/storage_common.h +++ b/drivers/usb/gadget/function/storage_common.h @@ -123,7 +123,7 @@ static inline bool fsg_lun_is_open(struct fsg_lun *curlun) #define FSG_BUFLEN ((u32)16384) /* Maximal number of LUNs supported in mass storage function */ -#define FSG_MAX_LUNS 8 +#define FSG_MAX_LUNS 16 enum fsg_buffer_state { BUF_STATE_EMPTY = 0, -- cgit v1.2.3 From 351169933ea22592fb42b97c76c4c130fe287cca Mon Sep 17 00:00:00 2001 From: "Ivan T. Ivanov" Date: Wed, 8 Jul 2015 17:57:40 +0300 Subject: usb: phy: qcom: New APQ8016/MSM8916 USB transceiver driver Driver handles PHY initialization, clock management, power management and workarounds required after resetting the hardware. Signed-off-by: Ivan T. Ivanov Signed-off-by: Felipe Balbi --- drivers/usb/phy/Kconfig | 14 ++ drivers/usb/phy/Makefile | 1 + drivers/usb/phy/phy-qcom-8x16-usb.c | 436 ++++++++++++++++++++++++++++++++++++ 3 files changed, 451 insertions(+) create mode 100644 drivers/usb/phy/phy-qcom-8x16-usb.c (limited to 'drivers/usb') diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 869c0cfcad98..7d3beee2a587 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -152,6 +152,20 @@ config USB_MSM_OTG This driver is not supported on boards like trout which has an external PHY. +config USB_QCOM_8X16_PHY + tristate "Qualcomm APQ8016/MSM8916 on-chip USB PHY controller support" + depends on ARCH_QCOM || COMPILE_TEST + depends on RESET_CONTROLLER + select USB_PHY + select USB_ULPI_VIEWPORT + help + Enable this to support the USB transceiver on Qualcomm 8x16 chipsets. + It handles PHY initialization, clock management, power management, + and workarounds required after resetting the hardware. + + To compile this driver as a module, choose M here: the + module will be called phy-qcom-8x16-usb. + config USB_MV_OTG tristate "Marvell USB OTG support" depends on USB_EHCI_MV && USB_MV_UDC && PM diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index e36ab1d46d8b..19c0dccbb116 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_USB_EHCI_TEGRA) += phy-tegra-usb.o obj-$(CONFIG_USB_GPIO_VBUS) += phy-gpio-vbus-usb.o obj-$(CONFIG_USB_ISP1301) += phy-isp1301.o obj-$(CONFIG_USB_MSM_OTG) += phy-msm-usb.o +obj-$(CONFIG_USB_QCOM_8X16_PHY) += phy-qcom-8x16-usb.o obj-$(CONFIG_USB_MV_OTG) += phy-mv-usb.o obj-$(CONFIG_USB_MXS_PHY) += phy-mxs-usb.o obj-$(CONFIG_USB_RCAR_PHY) += phy-rcar-usb.o diff --git a/drivers/usb/phy/phy-qcom-8x16-usb.c b/drivers/usb/phy/phy-qcom-8x16-usb.c new file mode 100644 index 000000000000..5d357a94599e --- /dev/null +++ b/drivers/usb/phy/phy-qcom-8x16-usb.c @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2015, Linaro Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HSPHY_AHBBURST 0x0090 +#define HSPHY_AHBMODE 0x0098 +#define HSPHY_GENCONFIG 0x009c +#define HSPHY_GENCONFIG_2 0x00a0 + +#define HSPHY_USBCMD 0x0140 +#define HSPHY_ULPI_VIEWPORT 0x0170 +#define HSPHY_CTRL 0x0240 + +#define HSPHY_TXFIFO_IDLE_FORCE_DIS BIT(4) +#define HSPHY_SESS_VLD_CTRL_EN BIT(7) +#define HSPHY_POR_ASSERT BIT(0) +#define HSPHY_RETEN BIT(1) + +#define HSPHY_SESS_VLD_CTRL BIT(25) + +#define ULPI_PWR_CLK_MNG_REG 0x88 +#define ULPI_PWR_OTG_COMP_DISABLE BIT(0) + +#define ULPI_MISC_A 0x96 +#define ULPI_MISC_A_VBUSVLDEXTSEL BIT(1) +#define ULPI_MISC_A_VBUSVLDEXT BIT(0) + +#define HSPHY_3P3_MIN 3050000 /* uV */ +#define HSPHY_3P3_MAX 3300000 /* uV */ + +#define HSPHY_1P8_MIN 1800000 /* uV */ +#define HSPHY_1P8_MAX 1800000 /* uV */ + +#define HSPHY_VDD_MIN 5 +#define HSPHY_VDD_MAX 7 + +struct phy_8x16 { + struct usb_phy phy; + void __iomem *regs; + struct clk *core_clk; + struct clk *iface_clk; + struct regulator *v3p3; + struct regulator *v1p8; + struct regulator *vdd; + + struct reset_control *phy_reset; + + struct extcon_specific_cable_nb vbus_cable; + struct notifier_block vbus_notify; + + struct gpio_desc *switch_gpio; + struct notifier_block reboot_notify; +}; + +static int phy_8x16_regulators_enable(struct phy_8x16 *qphy) +{ + int ret; + + ret = regulator_set_voltage(qphy->vdd, HSPHY_VDD_MIN, HSPHY_VDD_MAX); + if (ret) + return ret; + + ret = regulator_enable(qphy->vdd); + if (ret) + return ret; + + ret = regulator_set_voltage(qphy->v3p3, HSPHY_3P3_MIN, HSPHY_3P3_MAX); + if (ret) + goto off_vdd; + + ret = regulator_enable(qphy->v3p3); + if (ret) + goto off_vdd; + + ret = regulator_set_voltage(qphy->v1p8, HSPHY_1P8_MIN, HSPHY_1P8_MAX); + if (ret) + goto off_3p3; + + ret = regulator_enable(qphy->v1p8); + if (ret) + goto off_3p3; + + return 0; + +off_3p3: + regulator_disable(qphy->v3p3); +off_vdd: + regulator_disable(qphy->vdd); + + return ret; +} + +static void phy_8x16_regulators_disable(struct phy_8x16 *qphy) +{ + regulator_disable(qphy->v1p8); + regulator_disable(qphy->v3p3); + regulator_disable(qphy->vdd); +} + +static int phy_8x16_notify_connect(struct usb_phy *phy, + enum usb_device_speed speed) +{ + struct phy_8x16 *qphy = container_of(phy, struct phy_8x16, phy); + u32 val; + + val = ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT; + usb_phy_io_write(&qphy->phy, val, ULPI_SET(ULPI_MISC_A)); + + val = readl(qphy->regs + HSPHY_USBCMD); + val |= HSPHY_SESS_VLD_CTRL; + writel(val, qphy->regs + HSPHY_USBCMD); + + return 0; +} + +static int phy_8x16_notify_disconnect(struct usb_phy *phy, + enum usb_device_speed speed) +{ + struct phy_8x16 *qphy = container_of(phy, struct phy_8x16, phy); + u32 val; + + val = ULPI_MISC_A_VBUSVLDEXT | ULPI_MISC_A_VBUSVLDEXTSEL; + usb_phy_io_write(&qphy->phy, val, ULPI_CLR(ULPI_MISC_A)); + + val = readl(qphy->regs + HSPHY_USBCMD); + val &= ~HSPHY_SESS_VLD_CTRL; + writel(val, qphy->regs + HSPHY_USBCMD); + + return 0; +} + +static int phy_8x16_vbus_on(struct phy_8x16 *qphy) +{ + phy_8x16_notify_connect(&qphy->phy, USB_SPEED_UNKNOWN); + + /* Switch D+/D- lines to Device connector */ + gpiod_set_value_cansleep(qphy->switch_gpio, 0); + + return 0; +} + +static int phy_8x16_vbus_off(struct phy_8x16 *qphy) +{ + phy_8x16_notify_disconnect(&qphy->phy, USB_SPEED_UNKNOWN); + + /* Switch D+/D- lines to USB HUB */ + gpiod_set_value_cansleep(qphy->switch_gpio, 1); + + return 0; +} + +static int phy_8x16_vbus_notify(struct notifier_block *nb, unsigned long event, + void *ptr) +{ + struct phy_8x16 *qphy = container_of(nb, struct phy_8x16, vbus_notify); + + if (event) + phy_8x16_vbus_on(qphy); + else + phy_8x16_vbus_off(qphy); + + return NOTIFY_DONE; +} + +static int phy_8x16_init(struct usb_phy *phy) +{ + struct phy_8x16 *qphy = container_of(phy, struct phy_8x16, phy); + u32 val, init[] = {0x44, 0x6B, 0x24, 0x13}; + u32 addr = ULPI_EXT_VENDOR_SPECIFIC; + int idx, state; + + for (idx = 0; idx < ARRAY_SIZE(init); idx++) + usb_phy_io_write(phy, init[idx], addr + idx); + + reset_control_reset(qphy->phy_reset); + + /* Assert USB HSPHY_POR */ + val = readl(qphy->regs + HSPHY_CTRL); + val |= HSPHY_POR_ASSERT; + writel(val, qphy->regs + HSPHY_CTRL); + + /* + * wait for minimum 10 microseconds as suggested in HPG. + * Use a slightly larger value since the exact value didn't + * work 100% of the time. + */ + usleep_range(12, 15); + + /* Deassert USB HSPHY_POR */ + val = readl(qphy->regs + HSPHY_CTRL); + val &= ~HSPHY_POR_ASSERT; + writel(val, qphy->regs + HSPHY_CTRL); + + usleep_range(10, 15); + + writel(0x00, qphy->regs + HSPHY_AHBBURST); + writel(0x08, qphy->regs + HSPHY_AHBMODE); + + /* workaround for rx buffer collision issue */ + val = readl(qphy->regs + HSPHY_GENCONFIG); + val &= ~HSPHY_TXFIFO_IDLE_FORCE_DIS; + writel(val, qphy->regs + HSPHY_GENCONFIG); + + val = readl(qphy->regs + HSPHY_GENCONFIG_2); + val |= HSPHY_SESS_VLD_CTRL_EN; + writel(val, qphy->regs + HSPHY_GENCONFIG_2); + + val = ULPI_PWR_OTG_COMP_DISABLE; + usb_phy_io_write(phy, val, ULPI_SET(ULPI_PWR_CLK_MNG_REG)); + + state = extcon_get_cable_state(qphy->vbus_cable.edev, "USB"); + if (state) + phy_8x16_vbus_on(qphy); + else + phy_8x16_vbus_off(qphy); + + val = usb_phy_io_read(&qphy->phy, ULPI_FUNC_CTRL); + val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; + val |= ULPI_FUNC_CTRL_OPMODE_NORMAL; + usb_phy_io_write(&qphy->phy, val, ULPI_FUNC_CTRL); + + return 0; +} + +static void phy_8x16_shutdown(struct usb_phy *phy) +{ + u32 val; + + /* Put the controller in non-driving mode */ + val = usb_phy_io_read(phy, ULPI_FUNC_CTRL); + val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; + val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; + usb_phy_io_write(phy, val, ULPI_FUNC_CTRL); +} + +static int phy_8x16_read_devicetree(struct phy_8x16 *qphy) +{ + struct regulator_bulk_data regs[3]; + struct device *dev = qphy->phy.dev; + int ret; + + qphy->core_clk = devm_clk_get(dev, "core"); + if (IS_ERR(qphy->core_clk)) + return PTR_ERR(qphy->core_clk); + + qphy->iface_clk = devm_clk_get(dev, "iface"); + if (IS_ERR(qphy->iface_clk)) + return PTR_ERR(qphy->iface_clk); + + regs[0].supply = "v3p3"; + regs[1].supply = "v1p8"; + regs[2].supply = "vddcx"; + + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(regs), regs); + if (ret) + return ret; + + qphy->v3p3 = regs[0].consumer; + qphy->v1p8 = regs[1].consumer; + qphy->vdd = regs[2].consumer; + + qphy->phy_reset = devm_reset_control_get(dev, "phy"); + if (IS_ERR(qphy->phy_reset)) + return PTR_ERR(qphy->phy_reset); + + qphy->switch_gpio = devm_gpiod_get_optional(dev, "switch", + GPIOD_OUT_LOW); + if (IS_ERR(qphy->switch_gpio)) + return PTR_ERR(qphy->switch_gpio); + + return 0; +} + +static int phy_8x16_reboot_notify(struct notifier_block *this, + unsigned long code, void *unused) +{ + struct phy_8x16 *qphy; + + qphy = container_of(this, struct phy_8x16, reboot_notify); + + /* + * Ensure that D+/D- lines are routed to uB connector, so + * we could load bootloader/kernel at next reboot_notify + */ + gpiod_set_value_cansleep(qphy->switch_gpio, 0); + return NOTIFY_DONE; +} + +static int phy_8x16_probe(struct platform_device *pdev) +{ + struct extcon_dev *edev; + struct phy_8x16 *qphy; + struct resource *res; + struct usb_phy *phy; + int ret; + + qphy = devm_kzalloc(&pdev->dev, sizeof(*qphy), GFP_KERNEL); + if (!qphy) + return -ENOMEM; + + platform_set_drvdata(pdev, qphy); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + + qphy->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (!qphy->regs) + return -ENOMEM; + + phy = &qphy->phy; + phy->dev = &pdev->dev; + phy->label = dev_name(&pdev->dev); + phy->init = phy_8x16_init; + phy->shutdown = phy_8x16_shutdown; + phy->notify_connect = phy_8x16_notify_connect; + phy->notify_disconnect = phy_8x16_notify_disconnect; + phy->io_priv = qphy->regs + HSPHY_ULPI_VIEWPORT; + phy->io_ops = &ulpi_viewport_access_ops; + phy->type = USB_PHY_TYPE_USB2; + + ret = phy_8x16_read_devicetree(qphy); + if (ret < 0) + return ret; + + edev = extcon_get_edev_by_phandle(phy->dev, 0); + if (IS_ERR(edev)) + return PTR_ERR(edev); + + ret = clk_set_rate(qphy->core_clk, INT_MAX); + if (ret < 0) + dev_dbg(phy->dev, "Can't boost core clock\n"); + + ret = clk_prepare_enable(qphy->core_clk); + if (ret < 0) + return ret; + + ret = clk_prepare_enable(qphy->iface_clk); + if (ret < 0) + goto off_core; + + ret = phy_8x16_regulators_enable(qphy); + if (0 && ret) + goto off_clks; + + qphy->vbus_notify.notifier_call = phy_8x16_vbus_notify; + ret = extcon_register_interest(&qphy->vbus_cable, edev->name, + "USB", &qphy->vbus_notify); + if (ret < 0) + goto off_power; + + ret = usb_add_phy_dev(&qphy->phy); + if (ret) + goto off_extcon; + + qphy->reboot_notify.notifier_call = phy_8x16_reboot_notify; + register_reboot_notifier(&qphy->reboot_notify); + + return 0; + +off_extcon: + extcon_unregister_interest(&qphy->vbus_cable); +off_power: + phy_8x16_regulators_disable(qphy); +off_clks: + clk_disable_unprepare(qphy->iface_clk); +off_core: + clk_disable_unprepare(qphy->core_clk); + return ret; +} + +static int phy_8x16_remove(struct platform_device *pdev) +{ + struct phy_8x16 *qphy = platform_get_drvdata(pdev); + + unregister_reboot_notifier(&qphy->reboot_notify); + extcon_unregister_interest(&qphy->vbus_cable); + + /* + * Ensure that D+/D- lines are routed to uB connector, so + * we could load bootloader/kernel at next reboot_notify + */ + gpiod_set_value_cansleep(qphy->switch_gpio, 0); + + usb_remove_phy(&qphy->phy); + + clk_disable_unprepare(qphy->iface_clk); + clk_disable_unprepare(qphy->core_clk); + phy_8x16_regulators_disable(qphy); + return 0; +} + +static const struct of_device_id phy_8x16_dt_match[] = { + { .compatible = "qcom,usb-8x16-phy" }, + { } +}; +MODULE_DEVICE_TABLE(of, phy_8x16_dt_match); + +static struct platform_driver phy_8x16_driver = { + .probe = phy_8x16_probe, + .remove = phy_8x16_remove, + .driver = { + .name = "phy-qcom-8x16-usb", + .of_match_table = phy_8x16_dt_match, + }, +}; +module_platform_driver(phy_8x16_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Qualcomm APQ8016/MSM8916 chipsets USB transceiver driver"); -- cgit v1.2.3 From 5601250bb1b4e736cf487d332f2d8d8833a84209 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 4 May 2015 14:55:12 +0200 Subject: usb: composite: fix usb_function_activate/deactivate functions Using usb_gadget_disconnect to make gadget temporarily invisible to host doesn't provide desired result, because gadget is connected immediately after binding regardless to previous usb_gadget_disconnect() calls. For this reason we use usb_gadget_deactivate() instead of usb_gadget_disconnect() to make it working as expected. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 9ff3203b50e2..86d4e8fdf8d3 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -279,7 +279,7 @@ int usb_function_deactivate(struct usb_function *function) spin_lock_irqsave(&cdev->lock, flags); if (cdev->deactivations == 0) - status = usb_gadget_disconnect(cdev->gadget); + status = usb_gadget_deactivate(cdev->gadget); if (status == 0) cdev->deactivations++; @@ -311,7 +311,7 @@ int usb_function_activate(struct usb_function *function) else { cdev->deactivations--; if (cdev->deactivations == 0) - status = usb_gadget_connect(cdev->gadget); + status = usb_gadget_activate(cdev->gadget); } spin_unlock_irqrestore(&cdev->lock, flags); -- cgit v1.2.3 From d5bb9b81dbfa35d117ecb58022ee6e7e41e4772d Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 4 May 2015 14:55:13 +0200 Subject: usb: composite: add bind_deactivated flag to usb_function This patch introduces 'bind_deactivated' flag in struct usb_function. Functions which don't want to be activated automatically after bind should set this flag, and when they start to be ready to work they should call usb_function_activate(). When USB function sets 'bind_deactivated' flag, initial deactivation counter is incremented automatically, so there is no need to call usb_function_deactivate() in function bind. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 86d4e8fdf8d3..36c6f47642f8 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -209,6 +209,12 @@ int usb_add_function(struct usb_configuration *config, function->config = config; list_add_tail(&function->list, &config->functions); + if (function->bind_deactivated) { + value = usb_function_deactivate(function); + if (value) + goto done; + } + /* REVISIT *require* function->bind? */ if (function->bind) { value = function->bind(config, function); -- cgit v1.2.3 From f277bf27cf5cd56bcd1c4b95ae140f61680a6e83 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 4 May 2015 14:55:14 +0200 Subject: usb: gadget: f_uvc: use bind_deactivated flag Use bind_deactivated flag instead of calling usb_function_deactivate() in function bind(). Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_uvc.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index cf0df8fbba89..743be34605dc 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -733,12 +733,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) uvc->control_req->complete = uvc_function_ep0_complete; uvc->control_req->context = uvc; - /* Avoid letting this gadget enumerate until the userspace server is - * active. - */ - if ((ret = usb_function_deactivate(f)) < 0) - goto error; - if (v4l2_device_register(&cdev->gadget->dev, &uvc->v4l2_dev)) { printk(KERN_INFO "v4l2_device_register failed\n"); goto error; @@ -949,6 +943,7 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi) uvc->func.disable = uvc_function_disable; uvc->func.setup = uvc_function_setup; uvc->func.free_func = uvc_free; + uvc->func.bind_deactivated = true; return &uvc->func; } -- cgit v1.2.3 From 4cfbd95232dd6194c04d432d1a8ac45cec269d8b Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 4 May 2015 14:55:15 +0200 Subject: usb: gadget: f_obex: use bind_deactivated flag Use bind_deactivated flag instead of calling usb_function_deactivate() in function bind(). Field 'can_activate' in struct f_obex is no longer needed as setting 'bind_deactivated' flag makes us sure, that the function will be binded only if deactivation can be performed successfully. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_obex.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_obex.c b/drivers/usb/gadget/function/f_obex.c index a1b79c53499c..5519f858904b 100644 --- a/drivers/usb/gadget/function/f_obex.c +++ b/drivers/usb/gadget/function/f_obex.c @@ -37,7 +37,6 @@ struct f_obex { u8 data_id; u8 cur_alt; u8 port_num; - u8 can_activate; }; static inline struct f_obex *func_to_obex(struct usb_function *f) @@ -268,9 +267,6 @@ static void obex_connect(struct gserial *g) struct usb_composite_dev *cdev = g->func.config->cdev; int status; - if (!obex->can_activate) - return; - status = usb_function_activate(&g->func); if (status) dev_dbg(&cdev->gadget->dev, @@ -284,9 +280,6 @@ static void obex_disconnect(struct gserial *g) struct usb_composite_dev *cdev = g->func.config->cdev; int status; - if (!obex->can_activate) - return; - status = usb_function_deactivate(&g->func); if (status) dev_dbg(&cdev->gadget->dev, @@ -378,17 +371,6 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f) if (status) goto fail; - /* Avoid letting this gadget enumerate until the userspace - * OBEX server is active. - */ - status = usb_function_deactivate(f); - if (status < 0) - WARNING(cdev, "obex ttyGS%d: can't prevent enumeration, %d\n", - obex->port_num, status); - else - obex->can_activate = true; - - dev_dbg(&cdev->gadget->dev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n", obex->port_num, gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", @@ -529,6 +511,7 @@ static struct usb_function *obex_alloc(struct usb_function_instance *fi) obex->port.func.get_alt = obex_get_alt; obex->port.func.disable = obex_disable; obex->port.func.free_func = obex_free; + obex->port.func.bind_deactivated = true; return &obex->port.func; } -- cgit v1.2.3 From 744543c599c420bcddca08cd2e2713b82a008328 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 8 Jul 2015 16:41:38 +0200 Subject: usb: musb: sunxi: Add support for the Allwinner sunxi musb controller This is based on initial code to get the Allwinner sunxi musb controller supported by Chen-Yu Tsai and Roman Byshko. This adds support for the Allwinner sunxi musb controller in both host only and otg mode. Peripheral only mode is not supported, as no boards use that. This has been tested on a cubietruck (A20 SoC) and an UTOO P66 tablet (A13 SoC) with a variety of devices in host mode and with the g_serial gadget driver in peripheral mode, plugging otg / host cables in/out a lot of times in all possible imaginable plug orders. Signed-off-by: Hans de Goede Signed-off-by: Felipe Balbi --- drivers/usb/musb/Kconfig | 13 +- drivers/usb/musb/Makefile | 1 + drivers/usb/musb/sunxi.c | 703 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 716 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/musb/sunxi.c (limited to 'drivers/usb') diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 39db8b603627..37081ed8f295 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -5,7 +5,7 @@ # (M)HDRC = (Multipoint) Highspeed Dual-Role Controller config USB_MUSB_HDRC - tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' + tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, AW, ...)' depends on (USB || USB_GADGET) help Say Y here if your system has a dual role high speed USB @@ -20,6 +20,8 @@ config USB_MUSB_HDRC Analog Devices parts using this IP include Blackfin BF54x, BF525 and BF527. + Allwinner SoCs using this IP include A10, A13, A20, ... + If you do not know what this is, please say N. To compile this driver as a module, choose M here; the @@ -60,6 +62,15 @@ endchoice comment "Platform Glue Layer" +config USB_MUSB_SUNXI + tristate "Allwinner (sunxi)" + depends on ARCH_SUNXI + depends on NOP_USB_XCEIV + depends on PHY_SUN4I_USB + depends on EXTCON + depends on GENERIC_PHY + select SUNXI_SRAM + config USB_MUSB_DAVINCI tristate "DaVinci" depends on ARCH_DAVINCI_DMx diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index ba495018b416..f95befe18cc1 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_USB_MUSB_DA8XX) += da8xx.o obj-$(CONFIG_USB_MUSB_BLACKFIN) += blackfin.o obj-$(CONFIG_USB_MUSB_UX500) += ux500.o obj-$(CONFIG_USB_MUSB_JZ4740) += jz4740.o +obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o obj-$(CONFIG_USB_MUSB_AM335X_CHILD) += musb_am335x.o diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c new file mode 100644 index 000000000000..00d7248a4840 --- /dev/null +++ b/drivers/usb/musb/sunxi.c @@ -0,0 +1,703 @@ +/* + * Allwinner sun4i MUSB Glue Layer + * + * Copyright (C) 2015 Hans de Goede + * + * Based on code from + * Allwinner Technology Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "musb_core.h" + +/* + * Register offsets, note sunxi musb has a different layout then most + * musb implementations, we translate the layout in musb_readb & friends. + */ +#define SUNXI_MUSB_POWER 0x0040 +#define SUNXI_MUSB_DEVCTL 0x0041 +#define SUNXI_MUSB_INDEX 0x0042 +#define SUNXI_MUSB_VEND0 0x0043 +#define SUNXI_MUSB_INTRTX 0x0044 +#define SUNXI_MUSB_INTRRX 0x0046 +#define SUNXI_MUSB_INTRTXE 0x0048 +#define SUNXI_MUSB_INTRRXE 0x004a +#define SUNXI_MUSB_INTRUSB 0x004c +#define SUNXI_MUSB_INTRUSBE 0x0050 +#define SUNXI_MUSB_FRAME 0x0054 +#define SUNXI_MUSB_TXFIFOSZ 0x0090 +#define SUNXI_MUSB_TXFIFOADD 0x0092 +#define SUNXI_MUSB_RXFIFOSZ 0x0094 +#define SUNXI_MUSB_RXFIFOADD 0x0096 +#define SUNXI_MUSB_FADDR 0x0098 +#define SUNXI_MUSB_TXFUNCADDR 0x0098 +#define SUNXI_MUSB_TXHUBADDR 0x009a +#define SUNXI_MUSB_TXHUBPORT 0x009b +#define SUNXI_MUSB_RXFUNCADDR 0x009c +#define SUNXI_MUSB_RXHUBADDR 0x009e +#define SUNXI_MUSB_RXHUBPORT 0x009f +#define SUNXI_MUSB_CONFIGDATA 0x00c0 + +/* VEND0 bits */ +#define SUNXI_MUSB_VEND0_PIO_MODE 0 + +/* flags */ +#define SUNXI_MUSB_FL_ENABLED 0 +#define SUNXI_MUSB_FL_HOSTMODE 1 +#define SUNXI_MUSB_FL_HOSTMODE_PEND 2 +#define SUNXI_MUSB_FL_VBUS_ON 3 +#define SUNXI_MUSB_FL_PHY_ON 4 + +/* Our read/write methods need access and do not get passed in a musb ref :| */ +static struct musb *sunxi_musb; + +struct sunxi_glue { + struct device *dev; + struct platform_device *musb; + struct clk *clk; + struct phy *phy; + struct platform_device *usb_phy; + struct usb_phy *xceiv; + unsigned long flags; + struct work_struct work; + struct extcon_dev *extcon; + struct notifier_block host_nb; +}; + +/* phy_power_on / off may sleep, so we use a workqueue */ +static void sunxi_musb_work(struct work_struct *work) +{ + struct sunxi_glue *glue = container_of(work, struct sunxi_glue, work); + bool vbus_on, phy_on; + + if (!test_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags)) + return; + + if (test_and_clear_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags)) { + struct musb *musb = platform_get_drvdata(glue->musb); + unsigned long flags; + u8 devctl; + + spin_lock_irqsave(&musb->lock, flags); + + devctl = readb(musb->mregs + SUNXI_MUSB_DEVCTL); + if (test_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags)) { + set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags); + musb->xceiv->otg->default_a = 1; + musb->xceiv->otg->state = OTG_STATE_A_IDLE; + MUSB_HST_MODE(musb); + devctl |= MUSB_DEVCTL_SESSION; + } else { + clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags); + musb->xceiv->otg->default_a = 0; + musb->xceiv->otg->state = OTG_STATE_B_IDLE; + MUSB_DEV_MODE(musb); + devctl &= ~MUSB_DEVCTL_SESSION; + } + writeb(devctl, musb->mregs + SUNXI_MUSB_DEVCTL); + + spin_unlock_irqrestore(&musb->lock, flags); + } + + vbus_on = test_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags); + phy_on = test_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags); + + if (phy_on != vbus_on) { + if (vbus_on) { + phy_power_on(glue->phy); + set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags); + } else { + phy_power_off(glue->phy); + clear_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags); + } + } +} + +static void sunxi_musb_set_vbus(struct musb *musb, int is_on) +{ + struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent); + + if (is_on) + set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags); + else + clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags); + + schedule_work(&glue->work); +} + +static void sunxi_musb_pre_root_reset_end(struct musb *musb) +{ + struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent); + + sun4i_usb_phy_set_squelch_detect(glue->phy, false); +} + +static void sunxi_musb_post_root_reset_end(struct musb *musb) +{ + struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent); + + sun4i_usb_phy_set_squelch_detect(glue->phy, true); +} + +static irqreturn_t sunxi_musb_interrupt(int irq, void *__hci) +{ + struct musb *musb = __hci; + unsigned long flags; + + spin_lock_irqsave(&musb->lock, flags); + + musb->int_usb = readb(musb->mregs + SUNXI_MUSB_INTRUSB); + if (musb->int_usb) + writeb(musb->int_usb, musb->mregs + SUNXI_MUSB_INTRUSB); + + /* + * sunxi musb often signals babble on low / full speed device + * disconnect, without ever raising MUSB_INTR_DISCONNECT, since + * normally babble never happens treat it as disconnect. + */ + if ((musb->int_usb & MUSB_INTR_BABBLE) && is_host_active(musb)) { + musb->int_usb &= ~MUSB_INTR_BABBLE; + musb->int_usb |= MUSB_INTR_DISCONNECT; + } + + if ((musb->int_usb & MUSB_INTR_RESET) && !is_host_active(musb)) { + /* ep0 FADDR must be 0 when (re)entering peripheral mode */ + musb_ep_select(musb->mregs, 0); + musb_writeb(musb->mregs, MUSB_FADDR, 0); + } + + musb->int_tx = readw(musb->mregs + SUNXI_MUSB_INTRTX); + if (musb->int_tx) + writew(musb->int_tx, musb->mregs + SUNXI_MUSB_INTRTX); + + musb->int_rx = readw(musb->mregs + SUNXI_MUSB_INTRRX); + if (musb->int_rx) + writew(musb->int_rx, musb->mregs + SUNXI_MUSB_INTRRX); + + musb_interrupt(musb); + + spin_unlock_irqrestore(&musb->lock, flags); + + return IRQ_HANDLED; +} + +static int sunxi_musb_host_notifier(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct sunxi_glue *glue = container_of(nb, struct sunxi_glue, host_nb); + + if (event) + set_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags); + else + clear_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags); + + set_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags); + schedule_work(&glue->work); + + return NOTIFY_DONE; +} + +static int sunxi_musb_init(struct musb *musb) +{ + struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent); + int ret; + + sunxi_musb = musb; + musb->phy = glue->phy; + musb->xceiv = glue->xceiv; + + ret = sunxi_sram_claim(musb->controller->parent); + if (ret) + return ret; + + ret = clk_prepare_enable(glue->clk); + if (ret) + goto error_sram_release; + + writeb(SUNXI_MUSB_VEND0_PIO_MODE, musb->mregs + SUNXI_MUSB_VEND0); + + /* Register notifier before calling phy_init() */ + if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) { + ret = extcon_register_notifier(glue->extcon, EXTCON_USB_HOST, + &glue->host_nb); + if (ret) + goto error_clk_disable; + } + + ret = phy_init(glue->phy); + if (ret) + goto error_unregister_notifier; + + if (musb->port_mode == MUSB_PORT_MODE_HOST) { + ret = phy_power_on(glue->phy); + if (ret) + goto error_phy_exit; + set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags); + /* Stop musb work from turning vbus off again */ + set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags); + } + + musb->isr = sunxi_musb_interrupt; + + /* Stop the musb-core from doing runtime pm (not supported on sunxi) */ + pm_runtime_get(musb->controller); + + return 0; + +error_phy_exit: + phy_exit(glue->phy); +error_unregister_notifier: + if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) + extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST, + &glue->host_nb); +error_clk_disable: + clk_disable_unprepare(glue->clk); +error_sram_release: + sunxi_sram_release(musb->controller->parent); + return ret; +} + +static int sunxi_musb_exit(struct musb *musb) +{ + struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent); + + pm_runtime_put(musb->controller); + + cancel_work_sync(&glue->work); + if (test_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags)) + phy_power_off(glue->phy); + + phy_exit(glue->phy); + + if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) + extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST, + &glue->host_nb); + + clk_disable_unprepare(glue->clk); + sunxi_sram_release(musb->controller->parent); + + return 0; +} + +static void sunxi_musb_enable(struct musb *musb) +{ + struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent); + + /* musb_core does not call us in a balanced manner */ + if (test_and_set_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags)) + return; + + schedule_work(&glue->work); +} + +static void sunxi_musb_disable(struct musb *musb) +{ + struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent); + + clear_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags); +} + +/* + * sunxi musb register layout + * 0x00 - 0x17 fifo regs, 1 long per fifo + * 0x40 - 0x57 generic control regs (power - frame) + * 0x80 - 0x8f ep control regs (addressed through hw_ep->regs, indexed) + * 0x90 - 0x97 fifo control regs (indexed) + * 0x98 - 0x9f multipoint / busctl regs (indexed) + * 0xc0 configdata reg + */ + +static u32 sunxi_musb_fifo_offset(u8 epnum) +{ + return (epnum * 4); +} + +static u32 sunxi_musb_ep_offset(u8 epnum, u16 offset) +{ + WARN_ONCE(offset != 0, + "sunxi_musb_ep_offset called with non 0 offset\n"); + + return 0x80; /* indexed, so ignore epnum */ +} + +static u32 sunxi_musb_busctl_offset(u8 epnum, u16 offset) +{ + return SUNXI_MUSB_TXFUNCADDR + offset; +} + +static u8 sunxi_musb_readb(const void __iomem *addr, unsigned offset) +{ + if (addr == sunxi_musb->mregs) { + /* generic control or fifo control reg access */ + switch (offset) { + case MUSB_FADDR: + return readb(addr + SUNXI_MUSB_FADDR); + case MUSB_POWER: + return readb(addr + SUNXI_MUSB_POWER); + case MUSB_INTRUSB: + return readb(addr + SUNXI_MUSB_INTRUSB); + case MUSB_INTRUSBE: + return readb(addr + SUNXI_MUSB_INTRUSBE); + case MUSB_INDEX: + return readb(addr + SUNXI_MUSB_INDEX); + case MUSB_TESTMODE: + return 0; /* No testmode on sunxi */ + case MUSB_DEVCTL: + return readb(addr + SUNXI_MUSB_DEVCTL); + case MUSB_TXFIFOSZ: + return readb(addr + SUNXI_MUSB_TXFIFOSZ); + case MUSB_RXFIFOSZ: + return readb(addr + SUNXI_MUSB_RXFIFOSZ); + case MUSB_CONFIGDATA + 0x10: /* See musb_read_configdata() */ + return readb(addr + SUNXI_MUSB_CONFIGDATA); + /* Offset for these is fixed by sunxi_musb_busctl_offset() */ + case SUNXI_MUSB_TXFUNCADDR: + case SUNXI_MUSB_TXHUBADDR: + case SUNXI_MUSB_TXHUBPORT: + case SUNXI_MUSB_RXFUNCADDR: + case SUNXI_MUSB_RXHUBADDR: + case SUNXI_MUSB_RXHUBPORT: + /* multipoint / busctl reg access */ + return readb(addr + offset); + default: + dev_err(sunxi_musb->controller->parent, + "Error unknown readb offset %u\n", offset); + return 0; + } + } else if (addr == (sunxi_musb->mregs + 0x80)) { + /* ep control reg access */ + /* sunxi has a 2 byte hole before the txtype register */ + if (offset >= MUSB_TXTYPE) + offset += 2; + return readb(addr + offset); + } + + dev_err(sunxi_musb->controller->parent, + "Error unknown readb at 0x%x bytes offset\n", + (int)(addr - sunxi_musb->mregs)); + return 0; +} + +static void sunxi_musb_writeb(void __iomem *addr, unsigned offset, u8 data) +{ + if (addr == sunxi_musb->mregs) { + /* generic control or fifo control reg access */ + switch (offset) { + case MUSB_FADDR: + return writeb(data, addr + SUNXI_MUSB_FADDR); + case MUSB_POWER: + return writeb(data, addr + SUNXI_MUSB_POWER); + case MUSB_INTRUSB: + return writeb(data, addr + SUNXI_MUSB_INTRUSB); + case MUSB_INTRUSBE: + return writeb(data, addr + SUNXI_MUSB_INTRUSBE); + case MUSB_INDEX: + return writeb(data, addr + SUNXI_MUSB_INDEX); + case MUSB_TESTMODE: + if (data) + dev_warn(sunxi_musb->controller->parent, + "sunxi-musb does not have testmode\n"); + return; + case MUSB_DEVCTL: + return writeb(data, addr + SUNXI_MUSB_DEVCTL); + case MUSB_TXFIFOSZ: + return writeb(data, addr + SUNXI_MUSB_TXFIFOSZ); + case MUSB_RXFIFOSZ: + return writeb(data, addr + SUNXI_MUSB_RXFIFOSZ); + /* Offset for these is fixed by sunxi_musb_busctl_offset() */ + case SUNXI_MUSB_TXFUNCADDR: + case SUNXI_MUSB_TXHUBADDR: + case SUNXI_MUSB_TXHUBPORT: + case SUNXI_MUSB_RXFUNCADDR: + case SUNXI_MUSB_RXHUBADDR: + case SUNXI_MUSB_RXHUBPORT: + /* multipoint / busctl reg access */ + return writeb(data, addr + offset); + default: + dev_err(sunxi_musb->controller->parent, + "Error unknown writeb offset %u\n", offset); + return; + } + } else if (addr == (sunxi_musb->mregs + 0x80)) { + /* ep control reg access */ + if (offset >= MUSB_TXTYPE) + offset += 2; + return writeb(data, addr + offset); + } + + dev_err(sunxi_musb->controller->parent, + "Error unknown writeb at 0x%x bytes offset\n", + (int)(addr - sunxi_musb->mregs)); +} + +static u16 sunxi_musb_readw(const void __iomem *addr, unsigned offset) +{ + if (addr == sunxi_musb->mregs) { + /* generic control or fifo control reg access */ + switch (offset) { + case MUSB_INTRTX: + return readw(addr + SUNXI_MUSB_INTRTX); + case MUSB_INTRRX: + return readw(addr + SUNXI_MUSB_INTRRX); + case MUSB_INTRTXE: + return readw(addr + SUNXI_MUSB_INTRTXE); + case MUSB_INTRRXE: + return readw(addr + SUNXI_MUSB_INTRRXE); + case MUSB_FRAME: + return readw(addr + SUNXI_MUSB_FRAME); + case MUSB_TXFIFOADD: + return readw(addr + SUNXI_MUSB_TXFIFOADD); + case MUSB_RXFIFOADD: + return readw(addr + SUNXI_MUSB_RXFIFOADD); + case MUSB_HWVERS: + return 0; /* sunxi musb version is not known */ + default: + dev_err(sunxi_musb->controller->parent, + "Error unknown readw offset %u\n", offset); + return 0; + } + } else if (addr == (sunxi_musb->mregs + 0x80)) { + /* ep control reg access */ + return readw(addr + offset); + } + + dev_err(sunxi_musb->controller->parent, + "Error unknown readw at 0x%x bytes offset\n", + (int)(addr - sunxi_musb->mregs)); + return 0; +} + +static void sunxi_musb_writew(void __iomem *addr, unsigned offset, u16 data) +{ + if (addr == sunxi_musb->mregs) { + /* generic control or fifo control reg access */ + switch (offset) { + case MUSB_INTRTX: + return writew(data, addr + SUNXI_MUSB_INTRTX); + case MUSB_INTRRX: + return writew(data, addr + SUNXI_MUSB_INTRRX); + case MUSB_INTRTXE: + return writew(data, addr + SUNXI_MUSB_INTRTXE); + case MUSB_INTRRXE: + return writew(data, addr + SUNXI_MUSB_INTRRXE); + case MUSB_FRAME: + return writew(data, addr + SUNXI_MUSB_FRAME); + case MUSB_TXFIFOADD: + return writew(data, addr + SUNXI_MUSB_TXFIFOADD); + case MUSB_RXFIFOADD: + return writew(data, addr + SUNXI_MUSB_RXFIFOADD); + default: + dev_err(sunxi_musb->controller->parent, + "Error unknown writew offset %u\n", offset); + return; + } + } else if (addr == (sunxi_musb->mregs + 0x80)) { + /* ep control reg access */ + return writew(data, addr + offset); + } + + dev_err(sunxi_musb->controller->parent, + "Error unknown writew at 0x%x bytes offset\n", + (int)(addr - sunxi_musb->mregs)); +} + +static const struct musb_platform_ops sunxi_musb_ops = { + .quirks = MUSB_INDEXED_EP, + .init = sunxi_musb_init, + .exit = sunxi_musb_exit, + .enable = sunxi_musb_enable, + .disable = sunxi_musb_disable, + .fifo_offset = sunxi_musb_fifo_offset, + .ep_offset = sunxi_musb_ep_offset, + .busctl_offset = sunxi_musb_busctl_offset, + .readb = sunxi_musb_readb, + .writeb = sunxi_musb_writeb, + .readw = sunxi_musb_readw, + .writew = sunxi_musb_writew, + .set_vbus = sunxi_musb_set_vbus, + .pre_root_reset_end = sunxi_musb_pre_root_reset_end, + .post_root_reset_end = sunxi_musb_post_root_reset_end, +}; + +/* Allwinner OTG supports up to 5 endpoints */ +#define SUNXI_MUSB_MAX_EP_NUM 6 +#define SUNXI_MUSB_RAM_BITS 11 + +static struct musb_fifo_cfg sunxi_musb_mode_cfg[] = { + MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512), + MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512), + MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512), + MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512), + MUSB_EP_FIFO_SINGLE(5, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(5, FIFO_RX, 512), +}; + +static struct musb_hdrc_config sunxi_musb_hdrc_config = { + .fifo_cfg = sunxi_musb_mode_cfg, + .fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg), + .multipoint = true, + .dyn_fifo = true, + .soft_con = true, + .num_eps = SUNXI_MUSB_MAX_EP_NUM, + .ram_bits = SUNXI_MUSB_RAM_BITS, + .dma = 0, +}; + +static int sunxi_musb_probe(struct platform_device *pdev) +{ + struct musb_hdrc_platform_data pdata; + struct platform_device_info pinfo; + struct sunxi_glue *glue; + struct device_node *np = pdev->dev.of_node; + int ret; + + if (!np) { + dev_err(&pdev->dev, "Error no device tree node found\n"); + return -EINVAL; + } + + glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL); + if (!glue) + return -ENOMEM; + + memset(&pdata, 0, sizeof(pdata)); + switch (of_usb_get_dr_mode(np)) { +#if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_HOST + case USB_DR_MODE_HOST: + pdata.mode = MUSB_PORT_MODE_HOST; + break; +#endif +#ifdef CONFIG_USB_MUSB_DUAL_ROLE + case USB_DR_MODE_OTG: + glue->extcon = extcon_get_edev_by_phandle(&pdev->dev, 0); + if (IS_ERR(glue->extcon)) { + if (PTR_ERR(glue->extcon) == -EPROBE_DEFER) + return -EPROBE_DEFER; + dev_err(&pdev->dev, "Invalid or missing extcon\n"); + return PTR_ERR(glue->extcon); + } + pdata.mode = MUSB_PORT_MODE_DUAL_ROLE; + break; +#endif + default: + dev_err(&pdev->dev, "Invalid or missing 'dr_mode' property\n"); + return -EINVAL; + } + pdata.platform_ops = &sunxi_musb_ops; + pdata.config = &sunxi_musb_hdrc_config; + + glue->dev = &pdev->dev; + INIT_WORK(&glue->work, sunxi_musb_work); + glue->host_nb.notifier_call = sunxi_musb_host_notifier; + + glue->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(glue->clk)) { + dev_err(&pdev->dev, "Error getting clock: %ld\n", + PTR_ERR(glue->clk)); + return PTR_ERR(glue->clk); + } + + glue->phy = devm_phy_get(&pdev->dev, "usb"); + if (IS_ERR(glue->phy)) { + if (PTR_ERR(glue->phy) == -EPROBE_DEFER) + return -EPROBE_DEFER; + dev_err(&pdev->dev, "Error getting phy %ld\n", + PTR_ERR(glue->phy)); + return PTR_ERR(glue->phy); + } + + glue->usb_phy = usb_phy_generic_register(); + if (IS_ERR(glue->usb_phy)) { + dev_err(&pdev->dev, "Error registering usb-phy %ld\n", + PTR_ERR(glue->usb_phy)); + return PTR_ERR(glue->usb_phy); + } + + glue->xceiv = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); + if (IS_ERR(glue->xceiv)) { + ret = PTR_ERR(glue->xceiv); + dev_err(&pdev->dev, "Error getting usb-phy %d\n", ret); + goto err_unregister_usb_phy; + } + + platform_set_drvdata(pdev, glue); + + memset(&pinfo, 0, sizeof(pinfo)); + pinfo.name = "musb-hdrc"; + pinfo.id = PLATFORM_DEVID_AUTO; + pinfo.parent = &pdev->dev; + pinfo.res = pdev->resource; + pinfo.num_res = pdev->num_resources; + pinfo.data = &pdata; + pinfo.size_data = sizeof(pdata); + + glue->musb = platform_device_register_full(&pinfo); + if (IS_ERR(glue->musb)) { + ret = PTR_ERR(glue->musb); + dev_err(&pdev->dev, "Error registering musb dev: %d\n", ret); + goto err_unregister_usb_phy; + } + + return 0; + +err_unregister_usb_phy: + usb_phy_generic_unregister(glue->usb_phy); + return ret; +} + +static int sunxi_musb_remove(struct platform_device *pdev) +{ + struct sunxi_glue *glue = platform_get_drvdata(pdev); + struct platform_device *usb_phy = glue->usb_phy; + + platform_device_unregister(glue->musb); /* Frees glue ! */ + usb_phy_generic_unregister(usb_phy); + + return 0; +} + +static const struct of_device_id sunxi_musb_match[] = { + { .compatible = "allwinner,sun4i-a10-musb", }, + {} +}; + +static struct platform_driver sunxi_musb_driver = { + .probe = sunxi_musb_probe, + .remove = sunxi_musb_remove, + .driver = { + .name = "musb-sunxi", + .of_match_table = sunxi_musb_match, + }, +}; +module_platform_driver(sunxi_musb_driver); + +MODULE_DESCRIPTION("Allwinner sunxi MUSB Glue Layer"); +MODULE_AUTHOR("Hans de Goede "); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 132e23775779cc895c37f7883c33a60a1a8a7cdd Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 8 Jul 2015 16:41:39 +0200 Subject: usb: musb: sunxi: Add support for musb controller in A31 SoC The A31 SoC uses the same musb controller as found in earlier SoCs, but it is hooked up slightly different. Its SRAM is private and no longer controlled through the SRAM controller, and its reset is controlled via a separate reset controller. This commit adds support for this setup. Signed-off-by: Hans de Goede Signed-off-by: Felipe Balbi --- drivers/usb/musb/sunxi.c | 50 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c index 00d7248a4840..df2f75eb9895 100644 --- a/drivers/usb/musb/sunxi.c +++ b/drivers/usb/musb/sunxi.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -70,6 +71,8 @@ #define SUNXI_MUSB_FL_HOSTMODE_PEND 2 #define SUNXI_MUSB_FL_VBUS_ON 3 #define SUNXI_MUSB_FL_PHY_ON 4 +#define SUNXI_MUSB_FL_HAS_SRAM 5 +#define SUNXI_MUSB_FL_HAS_RESET 6 /* Our read/write methods need access and do not get passed in a musb ref :| */ static struct musb *sunxi_musb; @@ -78,6 +81,7 @@ struct sunxi_glue { struct device *dev; struct platform_device *musb; struct clk *clk; + struct reset_control *rst; struct phy *phy; struct platform_device *usb_phy; struct usb_phy *xceiv; @@ -229,14 +233,22 @@ static int sunxi_musb_init(struct musb *musb) musb->phy = glue->phy; musb->xceiv = glue->xceiv; - ret = sunxi_sram_claim(musb->controller->parent); - if (ret) - return ret; + if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) { + ret = sunxi_sram_claim(musb->controller->parent); + if (ret) + return ret; + } ret = clk_prepare_enable(glue->clk); if (ret) goto error_sram_release; + if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) { + ret = reset_control_deassert(glue->rst); + if (ret) + goto error_clk_disable; + } + writeb(SUNXI_MUSB_VEND0_PIO_MODE, musb->mregs + SUNXI_MUSB_VEND0); /* Register notifier before calling phy_init() */ @@ -244,7 +256,7 @@ static int sunxi_musb_init(struct musb *musb) ret = extcon_register_notifier(glue->extcon, EXTCON_USB_HOST, &glue->host_nb); if (ret) - goto error_clk_disable; + goto error_reset_assert; } ret = phy_init(glue->phy); @@ -273,10 +285,14 @@ error_unregister_notifier: if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST, &glue->host_nb); +error_reset_assert: + if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) + reset_control_assert(glue->rst); error_clk_disable: clk_disable_unprepare(glue->clk); error_sram_release: - sunxi_sram_release(musb->controller->parent); + if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) + sunxi_sram_release(musb->controller->parent); return ret; } @@ -296,8 +312,12 @@ static int sunxi_musb_exit(struct musb *musb) extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST, &glue->host_nb); + if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) + reset_control_assert(glue->rst); + clk_disable_unprepare(glue->clk); - sunxi_sram_release(musb->controller->parent); + if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) + sunxi_sram_release(musb->controller->parent); return 0; } @@ -617,6 +637,12 @@ static int sunxi_musb_probe(struct platform_device *pdev) INIT_WORK(&glue->work, sunxi_musb_work); glue->host_nb.notifier_call = sunxi_musb_host_notifier; + if (of_device_is_compatible(np, "allwinner,sun4i-a10-musb")) + set_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags); + + if (of_device_is_compatible(np, "allwinner,sun6i-a31-musb")) + set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags); + glue->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(glue->clk)) { dev_err(&pdev->dev, "Error getting clock: %ld\n", @@ -624,6 +650,17 @@ static int sunxi_musb_probe(struct platform_device *pdev) return PTR_ERR(glue->clk); } + if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) { + glue->rst = devm_reset_control_get(&pdev->dev, NULL); + if (IS_ERR(glue->rst)) { + if (PTR_ERR(glue->rst) == -EPROBE_DEFER) + return -EPROBE_DEFER; + dev_err(&pdev->dev, "Error getting reset %ld\n", + PTR_ERR(glue->rst)); + return PTR_ERR(glue->rst); + } + } + glue->phy = devm_phy_get(&pdev->dev, "usb"); if (IS_ERR(glue->phy)) { if (PTR_ERR(glue->phy) == -EPROBE_DEFER) @@ -685,6 +722,7 @@ static int sunxi_musb_remove(struct platform_device *pdev) static const struct of_device_id sunxi_musb_match[] = { { .compatible = "allwinner,sun4i-a10-musb", }, + { .compatible = "allwinner,sun6i-a31-musb", }, {} }; -- cgit v1.2.3 From d91de093d94eca6e280e50c24b172ed598bb5724 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 8 Jul 2015 16:41:40 +0200 Subject: usb: musb: sunxi: Add support for musb controller in A33 SoC The A33 SoC uses the same musb controller as found on the A31 and later, but allwinner has removed the configdata register, this commit adds special handling for this. Signed-off-by: Hans de Goede Signed-off-by: Felipe Balbi --- drivers/usb/musb/sunxi.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c index df2f75eb9895..f9f6304ad854 100644 --- a/drivers/usb/musb/sunxi.c +++ b/drivers/usb/musb/sunxi.c @@ -73,6 +73,7 @@ #define SUNXI_MUSB_FL_PHY_ON 4 #define SUNXI_MUSB_FL_HAS_SRAM 5 #define SUNXI_MUSB_FL_HAS_RESET 6 +#define SUNXI_MUSB_FL_NO_CONFIGDATA 7 /* Our read/write methods need access and do not get passed in a musb ref :| */ static struct musb *sunxi_musb; @@ -370,6 +371,8 @@ static u32 sunxi_musb_busctl_offset(u8 epnum, u16 offset) static u8 sunxi_musb_readb(const void __iomem *addr, unsigned offset) { + struct sunxi_glue *glue; + if (addr == sunxi_musb->mregs) { /* generic control or fifo control reg access */ switch (offset) { @@ -392,6 +395,12 @@ static u8 sunxi_musb_readb(const void __iomem *addr, unsigned offset) case MUSB_RXFIFOSZ: return readb(addr + SUNXI_MUSB_RXFIFOSZ); case MUSB_CONFIGDATA + 0x10: /* See musb_read_configdata() */ + glue = dev_get_drvdata(sunxi_musb->controller->parent); + /* A33 saves a reg, and we get to hardcode this */ + if (test_bit(SUNXI_MUSB_FL_NO_CONFIGDATA, + &glue->flags)) + return 0xde; + return readb(addr + SUNXI_MUSB_CONFIGDATA); /* Offset for these is fixed by sunxi_musb_busctl_offset() */ case SUNXI_MUSB_TXFUNCADDR: @@ -643,6 +652,11 @@ static int sunxi_musb_probe(struct platform_device *pdev) if (of_device_is_compatible(np, "allwinner,sun6i-a31-musb")) set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags); + if (of_device_is_compatible(np, "allwinner,sun8i-a33-musb")) { + set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags); + set_bit(SUNXI_MUSB_FL_NO_CONFIGDATA, &glue->flags); + } + glue->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(glue->clk)) { dev_err(&pdev->dev, "Error getting clock: %ld\n", @@ -723,6 +737,7 @@ static int sunxi_musb_remove(struct platform_device *pdev) static const struct of_device_id sunxi_musb_match[] = { { .compatible = "allwinner,sun4i-a10-musb", }, { .compatible = "allwinner,sun6i-a31-musb", }, + { .compatible = "allwinner,sun8i-a33-musb", }, {} }; -- cgit v1.2.3 From 53e6242db8d60da0587d36951cc9434d1a1c21dd Mon Sep 17 00:00:00 2001 From: Macpaul Lin Date: Thu, 9 Jul 2015 15:18:42 +0800 Subject: usb: gadget: composite: add USB_DT_OTG request handling Copy usb_otg_descriptor from config's descriptor if host requests USB_DT_OTG. Signed-off-by: Macpaul Lin Signed-off-by: Li Jun Reviewed-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 36c6f47642f8..b474499839d3 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -19,6 +19,7 @@ #include #include +#include #include #include "u_os_desc.h" @@ -1540,6 +1541,32 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) value = min(w_length, (u16) value); } break; + case USB_DT_OTG: + if (gadget_is_otg(gadget)) { + struct usb_configuration *config; + int otg_desc_len = 0; + + if (cdev->config) + config = cdev->config; + else + config = list_first_entry( + &cdev->configs, + struct usb_configuration, list); + if (!config) + goto done; + + if (gadget->otg_caps && + (gadget->otg_caps->otg_rev >= 0x0200)) + otg_desc_len += sizeof( + struct usb_otg20_descriptor); + else + otg_desc_len += sizeof( + struct usb_otg_descriptor); + + value = min_t(int, w_length, otg_desc_len); + memcpy(req->buf, config->descriptors[0], value); + } + break; } break; -- cgit v1.2.3 From 929412d94f2b75fe2a662afa2977bfb6a233c1c3 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 9 Jul 2015 15:18:44 +0800 Subject: usb: common: add API to update usb otg capabilities by device tree Check property of usb hardware to update otg version and disable SRP, HNP and ADP if its disable flag is present. Reviewed-by: Roger Quadros Signed-off-by: Li Jun Signed-off-by: Felipe Balbi --- drivers/usb/common/common.c | 56 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c index b530fd403ffb..9e39286a4e5a 100644 --- a/drivers/usb/common/common.c +++ b/drivers/usb/common/common.c @@ -154,6 +154,62 @@ bool of_usb_host_tpl_support(struct device_node *np) return false; } EXPORT_SYMBOL_GPL(of_usb_host_tpl_support); + +/** + * of_usb_update_otg_caps - to update usb otg capabilities according to + * the passed properties in DT. + * @np: Pointer to the given device_node + * @otg_caps: Pointer to the target usb_otg_caps to be set + * + * The function updates the otg capabilities + */ +int of_usb_update_otg_caps(struct device_node *np, + struct usb_otg_caps *otg_caps) +{ + u32 otg_rev; + + if (!otg_caps) + return -EINVAL; + + if (!of_property_read_u32(np, "otg-rev", &otg_rev)) { + switch (otg_rev) { + case 0x0100: + case 0x0120: + case 0x0130: + case 0x0200: + /* Choose the lesser one if it's already been set */ + if (otg_caps->otg_rev) + otg_caps->otg_rev = min_t(u16, otg_rev, + otg_caps->otg_rev); + else + otg_caps->otg_rev = otg_rev; + break; + default: + pr_err("%s: unsupported otg-rev: 0x%x\n", + np->full_name, otg_rev); + return -EINVAL; + } + } else { + /* + * otg-rev is mandatory for otg properties, if not passed + * we set it to be 0 and assume it's a legacy otg device. + * Non-dt platform can set it afterwards. + */ + otg_caps->otg_rev = 0; + } + + if (of_find_property(np, "hnp-disable", NULL)) + otg_caps->hnp_support = false; + if (of_find_property(np, "srp-disable", NULL)) + otg_caps->srp_support = false; + if (of_find_property(np, "adp-disable", NULL) || + (otg_caps->otg_rev < 0x0200)) + otg_caps->adp_support = false; + + return 0; +} +EXPORT_SYMBOL_GPL(of_usb_update_otg_caps); + #endif MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 79742351c89b76ebcf82b73103aed50f98ac2ee4 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 9 Jul 2015 15:18:45 +0800 Subject: usb: chipidea: set usb otg capabilities Init and update otg capabilities by DT, set gadget's otg capabilities accordingly. Acked-by: Peter Chen Reviewed-by: Roger Quadros Signed-off-by: Li Jun Signed-off-by: Felipe Balbi --- drivers/usb/chipidea/core.c | 15 +++++++++++++++ drivers/usb/chipidea/udc.c | 7 ++++++- 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 74fea4fa41b1..1e6d5f0c18f2 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -560,6 +560,8 @@ static irqreturn_t ci_irq(int irq, void *data) static int ci_get_platdata(struct device *dev, struct ci_hdrc_platform_data *platdata) { + int ret; + if (!platdata->phy_mode) platdata->phy_mode = of_usb_get_phy_mode(dev->of_node); @@ -588,6 +590,19 @@ static int ci_get_platdata(struct device *dev, of_usb_host_tpl_support(dev->of_node); } + if (platdata->dr_mode == USB_DR_MODE_OTG) { + /* We can support HNP and SRP of OTG 2.0 */ + platdata->ci_otg_caps.otg_rev = 0x0200; + platdata->ci_otg_caps.hnp_support = true; + platdata->ci_otg_caps.srp_support = true; + + /* Update otg capabilities by DT properties */ + ret = of_usb_update_otg_caps(dev->of_node, + &platdata->ci_otg_caps); + if (ret) + return ret; + } + if (of_usb_get_maximum_speed(dev->of_node) == USB_SPEED_FULL) platdata->flags |= CI_HDRC_FORCE_FULLSPEED; diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 764f668d45a9..b7cca3e597bf 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1827,6 +1827,7 @@ static irqreturn_t udc_irq(struct ci_hdrc *ci) static int udc_start(struct ci_hdrc *ci) { struct device *dev = ci->dev; + struct usb_otg_caps *otg_caps = &ci->platdata->ci_otg_caps; int retval = 0; spin_lock_init(&ci->lock); @@ -1834,8 +1835,12 @@ static int udc_start(struct ci_hdrc *ci) ci->gadget.ops = &usb_gadget_ops; ci->gadget.speed = USB_SPEED_UNKNOWN; ci->gadget.max_speed = USB_SPEED_HIGH; - ci->gadget.is_otg = ci->is_otg ? 1 : 0; ci->gadget.name = ci->platdata->name; + ci->gadget.otg_caps = otg_caps; + + if (otg_caps->hnp_support || otg_caps->srp_support || + otg_caps->adp_support) + ci->gadget.is_otg = 1; INIT_LIST_HEAD(&ci->gadget.ep_list); -- cgit v1.2.3 From b0930d4cafb487a663ac6780a0369d1a0f461bc2 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 9 Jul 2015 15:18:46 +0800 Subject: usb: chipidea: update ci_otg_is_fsm_mode conditions After introduce usb otg properties, update ci_otg_is_fsm_mode conditions to be depending on both usb hardware properties and usb driver config, also resolve a compile issue in debug.c after the API change. Acked-by: Peter Chen Signed-off-by: Li Jun Signed-off-by: Felipe Balbi --- drivers/usb/chipidea/ci.h | 5 ++++- drivers/usb/chipidea/debug.c | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index 6d6200e37b71..f243f0b431c3 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -406,8 +406,11 @@ static inline u32 hw_test_and_write(struct ci_hdrc *ci, enum ci_hw_regs reg, static inline bool ci_otg_is_fsm_mode(struct ci_hdrc *ci) { #ifdef CONFIG_USB_OTG_FSM + struct usb_otg_caps *otg_caps = &ci->platdata->ci_otg_caps; + return ci->is_otg && ci->roles[CI_ROLE_HOST] && - ci->roles[CI_ROLE_GADGET]; + ci->roles[CI_ROLE_GADGET] && (otg_caps->srp_support || + otg_caps->hnp_support || otg_caps->adp_support); #else return false; #endif diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index 5b7061a33103..3869c6d75515 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "ci.h" #include "udc.h" -- cgit v1.2.3 From d1606dfb98e59221332704c05f5908d9116456ab Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 9 Jul 2015 15:18:47 +0800 Subject: usb: gadget: add usb otg descriptor allocate and init interface Allocate usb otg descriptor and initialize it according to gadget's otg capabilities, if usb_otg_caps is not set, keep settings as current gadget drivers. With this 2 new interfaces, gadget can use usb_otg_descriptor for OTG 1.x, and usb_otg20_descriptor for OTG 2.0 or above, and otg features can be decided by the combination of usb hardware property and driver config. Signed-off-by: Li Jun Reviewed-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/gadget/config.c | 56 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c index 34e12fc52c23..0fafa7a1b6f6 100644 --- a/drivers/usb/gadget/config.c +++ b/drivers/usb/gadget/config.c @@ -20,6 +20,7 @@ #include #include #include +#include /** * usb_descriptor_fillbuf - fill buffer with descriptors @@ -195,3 +196,58 @@ void usb_free_all_descriptors(struct usb_function *f) usb_free_descriptors(f->ss_descriptors); } EXPORT_SYMBOL_GPL(usb_free_all_descriptors); + +struct usb_descriptor_header *usb_otg_descriptor_alloc( + struct usb_gadget *gadget) +{ + struct usb_descriptor_header *otg_desc; + unsigned length = 0; + + if (gadget->otg_caps && (gadget->otg_caps->otg_rev >= 0x0200)) + length = sizeof(struct usb_otg20_descriptor); + else + length = sizeof(struct usb_otg_descriptor); + + otg_desc = kzalloc(length, GFP_KERNEL); + return otg_desc; +} +EXPORT_SYMBOL_GPL(usb_otg_descriptor_alloc); + +int usb_otg_descriptor_init(struct usb_gadget *gadget, + struct usb_descriptor_header *otg_desc) +{ + struct usb_otg_descriptor *otg1x_desc; + struct usb_otg20_descriptor *otg20_desc; + struct usb_otg_caps *otg_caps = gadget->otg_caps; + u8 otg_attributes = 0; + + if (!otg_desc) + return -EINVAL; + + if (otg_caps && otg_caps->otg_rev) { + if (otg_caps->hnp_support) + otg_attributes |= USB_OTG_HNP; + if (otg_caps->srp_support) + otg_attributes |= USB_OTG_SRP; + if (otg_caps->adp_support && (otg_caps->otg_rev >= 0x0200)) + otg_attributes |= USB_OTG_ADP; + } else { + otg_attributes = USB_OTG_SRP | USB_OTG_HNP; + } + + if (otg_caps && (otg_caps->otg_rev >= 0x0200)) { + otg20_desc = (struct usb_otg20_descriptor *)otg_desc; + otg20_desc->bLength = sizeof(struct usb_otg20_descriptor); + otg20_desc->bDescriptorType = USB_DT_OTG; + otg20_desc->bmAttributes = otg_attributes; + otg20_desc->bcdOTG = cpu_to_le16(otg_caps->otg_rev); + } else { + otg1x_desc = (struct usb_otg_descriptor *)otg_desc; + otg1x_desc->bLength = sizeof(struct usb_otg_descriptor); + otg1x_desc->bDescriptorType = USB_DT_OTG; + otg1x_desc->bmAttributes = otg_attributes; + } + + return 0; +} +EXPORT_SYMBOL_GPL(usb_otg_descriptor_init); -- cgit v1.2.3 From 41ce84c86d0a04ef70a9608bd744afb122b6d103 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 9 Jul 2015 15:18:48 +0800 Subject: usb: gadget: configfs: allocate and init otg descriptor by otg capabilities Allocate and initialize usb otg descriptor according to gadget otg capabilities, add it for each usb configurations, free it while composite unbind. If otg capability is not defined, keep its otg descriptor unchanged. Signed-off-by: Li Jun Reviewed-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/gadget/configfs.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 289e20119fea..294eb74fb078 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -41,6 +41,8 @@ int check_user_usb_string(const char *name, #define MAX_NAME_LEN 40 #define MAX_USB_STRING_LANGS 2 +static const struct usb_descriptor_header *otg_desc[2]; + struct gadget_info { struct config_group group; struct config_group functions_group; @@ -55,9 +57,6 @@ struct gadget_info { struct list_head available_func; const char *udc_name; -#ifdef CONFIG_USB_OTG - struct usb_otg_descriptor otg; -#endif struct usb_composite_driver composite; struct usb_composite_dev cdev; bool use_os_desc; @@ -1376,6 +1375,19 @@ static int configfs_composite_bind(struct usb_gadget *gadget, memcpy(cdev->qw_sign, gi->qw_sign, OS_STRING_QW_SIGN_LEN); } + if (gadget_is_otg(gadget) && !otg_desc[0]) { + struct usb_descriptor_header *usb_desc; + + usb_desc = usb_otg_descriptor_alloc(gadget); + if (!usb_desc) { + ret = -ENOMEM; + goto err_comp_cleanup; + } + usb_otg_descriptor_init(gadget, usb_desc); + otg_desc[0] = usb_desc; + otg_desc[1] = NULL; + } + /* Go through all configs, attach all functions */ list_for_each_entry(c, &gi->cdev.configs, list) { struct config_usb_cfg *cfg; @@ -1383,6 +1395,9 @@ static int configfs_composite_bind(struct usb_gadget *gadget, struct usb_function *tmp; struct gadget_config_name *cn; + if (gadget_is_otg(gadget)) + c->descriptors = otg_desc; + cfg = container_of(c, struct config_usb_cfg, c); if (!list_empty(&cfg->string_list)) { i = 0; @@ -1437,6 +1452,8 @@ static void configfs_composite_unbind(struct usb_gadget *gadget) cdev = get_gadget_data(gadget); gi = container_of(cdev, struct gadget_info, cdev); + kfree(otg_desc[0]); + otg_desc[0] = NULL; purge_configs_funcs(gi); composite_dev_cleanup(cdev); usb_ep_autoconfig_reset(cdev->gadget); @@ -1510,12 +1527,6 @@ static struct config_group *gadgets_make( if (!gi->composite.gadget_driver.function) goto err; -#ifdef CONFIG_USB_OTG - gi->otg.bLength = sizeof(struct usb_otg_descriptor); - gi->otg.bDescriptorType = USB_DT_OTG; - gi->otg.bmAttributes = USB_OTG_SRP | USB_OTG_HNP; -#endif - config_group_init_type_name(&gi->group, name, &gadget_root_type); return &gi->group; -- cgit v1.2.3 From 9b95236eebdbdf2ff68517cc32390683f4114a37 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 9 Jul 2015 15:18:49 +0800 Subject: usb: gadget: ether: allocate and init otg descriptor by otg capabilities Allocate and initialize usb otg descriptor according to gadget otg capabilities, add it for each usb configurations, free it while ether unbind. If otg capability is not defined, keep its otg descriptor unchanged. Signed-off-by: Li Jun Reviewed-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/gadget/legacy/ether.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/legacy/ether.c b/drivers/usb/gadget/legacy/ether.c index a3323dca218f..31e9160223e9 100644 --- a/drivers/usb/gadget/legacy/ether.c +++ b/drivers/usb/gadget/legacy/ether.c @@ -171,20 +171,7 @@ static struct usb_device_descriptor device_desc = { .bNumConfigurations = 1, }; -static struct usb_otg_descriptor otg_descriptor = { - .bLength = sizeof otg_descriptor, - .bDescriptorType = USB_DT_OTG, - - /* REVISIT SRP-only hardware is possible, although - * it would not be called "OTG" ... - */ - .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, -}; - -static const struct usb_descriptor_header *otg_desc[] = { - (struct usb_descriptor_header *) &otg_descriptor, - NULL, -}; +static const struct usb_descriptor_header *otg_desc[2]; static struct usb_string strings_dev[] = { [USB_GADGET_MANUFACTURER_IDX].s = "", @@ -416,17 +403,28 @@ static int eth_bind(struct usb_composite_dev *cdev) device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; + if (gadget_is_otg(gadget) && !otg_desc[0]) { + struct usb_descriptor_header *usb_desc; + + usb_desc = usb_otg_descriptor_alloc(gadget); + if (!usb_desc) + goto fail1; + usb_otg_descriptor_init(gadget, usb_desc); + otg_desc[0] = usb_desc; + otg_desc[1] = NULL; + } + /* register our configuration(s); RNDIS first, if it's used */ if (has_rndis()) { status = usb_add_config(cdev, &rndis_config_driver, rndis_do_config); if (status < 0) - goto fail1; + goto fail2; } status = usb_add_config(cdev, ð_config_driver, eth_do_config); if (status < 0) - goto fail1; + goto fail2; usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n", @@ -434,6 +432,9 @@ static int eth_bind(struct usb_composite_dev *cdev) return 0; +fail2: + kfree(otg_desc[0]); + otg_desc[0] = NULL; fail1: if (has_rndis()) usb_put_function_instance(fi_rndis); @@ -463,6 +464,9 @@ static int eth_unbind(struct usb_composite_dev *cdev) usb_put_function(f_geth); usb_put_function_instance(fi_geth); } + kfree(otg_desc[0]); + otg_desc[0] = NULL; + return 0; } -- cgit v1.2.3 From 578aa8a2b12cb4cc3cfdb6ccd56af9f5f0dd6118 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 9 Jul 2015 15:18:50 +0800 Subject: usb: gadget: acm_ms: allocate and init otg descriptor by otg capabilities Allocate and initialize usb otg descriptor according to gadget otg capabilities, add it for each usb configurations. If otg capability is not defined, keep its original otg descriptor unchanged. Signed-off-by: Li Jun Reviewed-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/gadget/legacy/acm_ms.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/legacy/acm_ms.c b/drivers/usb/gadget/legacy/acm_ms.c index 1194b09ae746..4d8adb48b8a7 100644 --- a/drivers/usb/gadget/legacy/acm_ms.c +++ b/drivers/usb/gadget/legacy/acm_ms.c @@ -58,21 +58,7 @@ static struct usb_device_descriptor device_desc = { /*.bNumConfigurations = DYNAMIC*/ }; -static struct usb_otg_descriptor otg_descriptor = { - .bLength = sizeof otg_descriptor, - .bDescriptorType = USB_DT_OTG, - - /* - * REVISIT SRP-only hardware is possible, although - * it would not be called "OTG" ... - */ - .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, -}; - -static const struct usb_descriptor_header *otg_desc[] = { - (struct usb_descriptor_header *) &otg_descriptor, - NULL, -}; +static const struct usb_descriptor_header *otg_desc[2]; /* string IDs are assigned dynamically */ static struct usb_string strings_dev[] = { @@ -225,10 +211,21 @@ static int acm_ms_bind(struct usb_composite_dev *cdev) device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; + if (gadget_is_otg(gadget) && !otg_desc[0]) { + struct usb_descriptor_header *usb_desc; + + usb_desc = usb_otg_descriptor_alloc(gadget); + if (!usb_desc) + goto fail_string_ids; + usb_otg_descriptor_init(gadget, usb_desc); + otg_desc[0] = usb_desc; + otg_desc[1] = NULL; + } + /* register our configuration */ status = usb_add_config(cdev, &acm_ms_config_driver, acm_ms_do_config); if (status < 0) - goto fail_string_ids; + goto fail_otg_desc; usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n", @@ -236,6 +233,9 @@ static int acm_ms_bind(struct usb_composite_dev *cdev) return 0; /* error recovery */ +fail_otg_desc: + kfree(otg_desc[0]); + otg_desc[0] = NULL; fail_string_ids: fsg_common_remove_luns(opts->common); fail_set_cdev: @@ -255,6 +255,9 @@ static int acm_ms_unbind(struct usb_composite_dev *cdev) usb_put_function_instance(fi_msg); usb_put_function(f_acm); usb_put_function_instance(f_acm_inst); + kfree(otg_desc[0]); + otg_desc[0] = NULL; + return 0; } -- cgit v1.2.3 From 56023ce0fd7025154494d139b2c9891d75fee622 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 9 Jul 2015 15:18:51 +0800 Subject: usb: gadget: audio: allocate and init otg descriptor by otg capabilities Allocate and initialize usb otg descriptor according to gadget otg capabilities, add it for each usb configurations. If otg capability is not defined, keep its original otg descriptor unchanged. Signed-off-by: Li Jun Reviewed-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/gadget/legacy/audio.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/legacy/audio.c b/drivers/usb/gadget/legacy/audio.c index b8095bfe57b6..9b2c1c68746b 100644 --- a/drivers/usb/gadget/legacy/audio.c +++ b/drivers/usb/gadget/legacy/audio.c @@ -150,20 +150,7 @@ static struct usb_device_descriptor device_desc = { .bNumConfigurations = 1, }; -static struct usb_otg_descriptor otg_descriptor = { - .bLength = sizeof otg_descriptor, - .bDescriptorType = USB_DT_OTG, - - /* REVISIT SRP-only hardware is possible, although - * it would not be called "OTG" ... - */ - .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, -}; - -static const struct usb_descriptor_header *otg_desc[] = { - (struct usb_descriptor_header *) &otg_descriptor, - NULL, -}; +static const struct usb_descriptor_header *otg_desc[2]; /*-------------------------------------------------------------------------*/ @@ -259,14 +246,28 @@ static int audio_bind(struct usb_composite_dev *cdev) device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; + if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) { + struct usb_descriptor_header *usb_desc; + + usb_desc = usb_otg_descriptor_alloc(cdev->gadget); + if (!usb_desc) + goto fail; + usb_otg_descriptor_init(cdev->gadget, usb_desc); + otg_desc[0] = usb_desc; + otg_desc[1] = NULL; + } + status = usb_add_config(cdev, &audio_config_driver, audio_do_config); if (status < 0) - goto fail; + goto fail_otg_desc; usb_composite_overwrite_options(cdev, &coverwrite); INFO(cdev, "%s, version: %s\n", DRIVER_DESC, DRIVER_VERSION); return 0; +fail_otg_desc: + kfree(otg_desc[0]); + otg_desc[0] = NULL; fail: #ifndef CONFIG_GADGET_UAC1 usb_put_function_instance(fi_uac2); @@ -289,6 +290,9 @@ static int audio_unbind(struct usb_composite_dev *cdev) if (!IS_ERR_OR_NULL(fi_uac2)) usb_put_function_instance(fi_uac2); #endif + kfree(otg_desc[0]); + otg_desc[0] = NULL; + return 0; } -- cgit v1.2.3 From ab6796ae98330389754b82d37bed89029d1dab51 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 9 Jul 2015 15:18:52 +0800 Subject: usb: gadget: cdc2: allocate and init otg descriptor by otg capabilities Allocate and initialize usb otg descriptor according to gadget otg capabilities, add it for each usb configurations. If otg capability is not defined, keep its original otg descriptor unchanged. Signed-off-by: Li Jun Reviewed-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/gadget/legacy/cdc2.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/legacy/cdc2.c b/drivers/usb/gadget/legacy/cdc2.c index afd3e37921a7..ecd8c8d62f2e 100644 --- a/drivers/usb/gadget/legacy/cdc2.c +++ b/drivers/usb/gadget/legacy/cdc2.c @@ -60,21 +60,7 @@ static struct usb_device_descriptor device_desc = { .bNumConfigurations = 1, }; -static struct usb_otg_descriptor otg_descriptor = { - .bLength = sizeof otg_descriptor, - .bDescriptorType = USB_DT_OTG, - - /* REVISIT SRP-only hardware is possible, although - * it would not be called "OTG" ... - */ - .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, -}; - -static const struct usb_descriptor_header *otg_desc[] = { - (struct usb_descriptor_header *) &otg_descriptor, - NULL, -}; - +static const struct usb_descriptor_header *otg_desc[2]; /* string IDs are assigned dynamically */ static struct usb_string strings_dev[] = { @@ -193,10 +179,21 @@ static int cdc_bind(struct usb_composite_dev *cdev) device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; + if (gadget_is_otg(gadget) && !otg_desc[0]) { + struct usb_descriptor_header *usb_desc; + + usb_desc = usb_otg_descriptor_alloc(gadget); + if (!usb_desc) + goto fail1; + usb_otg_descriptor_init(gadget, usb_desc); + otg_desc[0] = usb_desc; + otg_desc[1] = NULL; + } + /* register our configuration */ status = usb_add_config(cdev, &cdc_config_driver, cdc_do_config); if (status < 0) - goto fail1; + goto fail2; usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n", @@ -204,6 +201,9 @@ static int cdc_bind(struct usb_composite_dev *cdev) return 0; +fail2: + kfree(otg_desc[0]); + otg_desc[0] = NULL; fail1: usb_put_function_instance(fi_serial); fail: @@ -219,6 +219,9 @@ static int cdc_unbind(struct usb_composite_dev *cdev) usb_put_function(f_ecm); if (!IS_ERR_OR_NULL(fi_ecm)) usb_put_function_instance(fi_ecm); + kfree(otg_desc[0]); + otg_desc[0] = NULL; + return 0; } -- cgit v1.2.3 From 75c9310a050b77a6788addf8060b533ab2d9de00 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 9 Jul 2015 15:18:53 +0800 Subject: usb: gadget: g_ffs: allocate and init otg descriptor by otg capabilities Allocate and initialize usb otg descriptor according to gadget otg capabilities, add it for each usb configurations. If otg capability is not defined, keep its original otg descriptor unchanged. Signed-off-by: Li Jun Reviewed-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/gadget/legacy/g_ffs.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/legacy/g_ffs.c b/drivers/usb/gadget/legacy/g_ffs.c index e821931c965c..320a81b2baa6 100644 --- a/drivers/usb/gadget/legacy/g_ffs.c +++ b/drivers/usb/gadget/legacy/g_ffs.c @@ -88,21 +88,7 @@ MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol"); module_param_array_named(functions, func_names, charp, &func_num, 0); MODULE_PARM_DESC(functions, "USB Functions list"); -static const struct usb_descriptor_header *gfs_otg_desc[] = { - (const struct usb_descriptor_header *) - &(const struct usb_otg_descriptor) { - .bLength = sizeof(struct usb_otg_descriptor), - .bDescriptorType = USB_DT_OTG, - - /* - * REVISIT SRP-only hardware is possible, although - * it would not be called "OTG" ... - */ - .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, - }, - - NULL -}; +static const struct usb_descriptor_header *gfs_otg_desc[2]; /* String IDs are assigned dynamically */ static struct usb_string gfs_strings[] = { @@ -412,6 +398,17 @@ static int gfs_bind(struct usb_composite_dev *cdev) goto error_rndis; gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id; + if (gadget_is_otg(cdev->gadget) && !gfs_otg_desc[0]) { + struct usb_descriptor_header *usb_desc; + + usb_desc = usb_otg_descriptor_alloc(cdev->gadget); + if (!usb_desc) + goto error_rndis; + usb_otg_descriptor_init(cdev->gadget, usb_desc); + gfs_otg_desc[0] = usb_desc; + gfs_otg_desc[1] = NULL; + } + for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) { struct gfs_configuration *c = gfs_configurations + i; int sid = USB_GADGET_FIRST_AVAIL_IDX + i; @@ -432,6 +429,8 @@ static int gfs_bind(struct usb_composite_dev *cdev) /* TODO */ error_unbind: + kfree(gfs_otg_desc[0]); + gfs_otg_desc[0] = NULL; error_rndis: #ifdef CONFIG_USB_FUNCTIONFS_RNDIS usb_put_function_instance(fi_rndis); @@ -473,6 +472,9 @@ static int gfs_unbind(struct usb_composite_dev *cdev) for (i = 0; i < N_CONF * func_num; ++i) usb_put_function(*(f_ffs[0] + i)); + kfree(gfs_otg_desc[0]); + gfs_otg_desc[0] = NULL; + return 0; } -- cgit v1.2.3 From d9e1867917ccf43ebe6f0e43e19958cbdeb0d8f2 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 9 Jul 2015 15:18:54 +0800 Subject: usb: gadget: hid: allocate and init otg descriptor by otg capabilities Allocate and initialize usb otg descriptor according to gadget otg capabilities, add it for each usb configurations. If otg capability is not defined, keep its original otg descriptor unchanged. Signed-off-by: Li Jun Reviewed-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/gadget/legacy/hid.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/legacy/hid.c b/drivers/usb/gadget/legacy/hid.c index 2baa572686c6..e4874d3183dc 100644 --- a/drivers/usb/gadget/legacy/hid.c +++ b/drivers/usb/gadget/legacy/hid.c @@ -68,21 +68,7 @@ static struct usb_device_descriptor device_desc = { .bNumConfigurations = 1, }; -static struct usb_otg_descriptor otg_descriptor = { - .bLength = sizeof otg_descriptor, - .bDescriptorType = USB_DT_OTG, - - /* REVISIT SRP-only hardware is possible, although - * it would not be called "OTG" ... - */ - .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, -}; - -static const struct usb_descriptor_header *otg_desc[] = { - (struct usb_descriptor_header *) &otg_descriptor, - NULL, -}; - +static const struct usb_descriptor_header *otg_desc[2]; /* string IDs are assigned dynamically */ static struct usb_string strings_dev[] = { @@ -186,16 +172,30 @@ static int hid_bind(struct usb_composite_dev *cdev) device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; + if (gadget_is_otg(gadget) && !otg_desc[0]) { + struct usb_descriptor_header *usb_desc; + + usb_desc = usb_otg_descriptor_alloc(gadget); + if (!usb_desc) + goto put; + usb_otg_descriptor_init(gadget, usb_desc); + otg_desc[0] = usb_desc; + otg_desc[1] = NULL; + } + /* register our configuration */ status = usb_add_config(cdev, &config_driver, do_config); if (status < 0) - goto put; + goto free_otg_desc; usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); return 0; +free_otg_desc: + kfree(otg_desc[0]); + otg_desc[0] = NULL; put: list_for_each_entry(m, &hidg_func_list, node) { if (m == n) @@ -213,6 +213,10 @@ static int hid_unbind(struct usb_composite_dev *cdev) usb_put_function(n->f); usb_put_function_instance(n->fi); } + + kfree(otg_desc[0]); + otg_desc[0] = NULL; + return 0; } -- cgit v1.2.3 From d867889797615761975e693881a12283ebc92b0f Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 9 Jul 2015 15:18:55 +0800 Subject: usb: gadget: mass_storage: allocate and init otg descriptor by otg capabilities Allocate and initialize usb otg descriptor according to gadget otg capabilities, add it for each usb configurations. If otg capability is not defined, keep its original otg descriptor unchanged. Signed-off-by: Li Jun Reviewed-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/gadget/legacy/mass_storage.c | 35 +++++++++++++++++--------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/legacy/mass_storage.c b/drivers/usb/gadget/legacy/mass_storage.c index e7bfb081f111..ab1a42ce75d2 100644 --- a/drivers/usb/gadget/legacy/mass_storage.c +++ b/drivers/usb/gadget/legacy/mass_storage.c @@ -64,21 +64,7 @@ static struct usb_device_descriptor msg_device_desc = { .bNumConfigurations = 1, }; -static struct usb_otg_descriptor otg_descriptor = { - .bLength = sizeof otg_descriptor, - .bDescriptorType = USB_DT_OTG, - - /* - * REVISIT SRP-only hardware is possible, although - * it would not be called "OTG" ... - */ - .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, -}; - -static const struct usb_descriptor_header *otg_desc[] = { - (struct usb_descriptor_header *) &otg_descriptor, - NULL, -}; +static const struct usb_descriptor_header *otg_desc[2]; static struct usb_string strings_dev[] = { [USB_GADGET_MANUFACTURER_IDX].s = "", @@ -214,9 +200,20 @@ static int msg_bind(struct usb_composite_dev *cdev) goto fail_string_ids; msg_device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; + if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) { + struct usb_descriptor_header *usb_desc; + + usb_desc = usb_otg_descriptor_alloc(cdev->gadget); + if (!usb_desc) + goto fail_string_ids; + usb_otg_descriptor_init(cdev->gadget, usb_desc); + otg_desc[0] = usb_desc; + otg_desc[1] = NULL; + } + status = usb_add_config(cdev, &msg_config_driver, msg_do_config); if (status < 0) - goto fail_string_ids; + goto fail_otg_desc; usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&cdev->gadget->dev, @@ -224,6 +221,9 @@ static int msg_bind(struct usb_composite_dev *cdev) set_bit(0, &msg_registered); return 0; +fail_otg_desc: + kfree(otg_desc[0]); + otg_desc[0] = NULL; fail_string_ids: fsg_common_remove_luns(opts->common); fail_set_cdev: @@ -243,6 +243,9 @@ static int msg_unbind(struct usb_composite_dev *cdev) if (!IS_ERR(fi_msg)) usb_put_function_instance(fi_msg); + kfree(otg_desc[0]); + otg_desc[0] = NULL; + return 0; } -- cgit v1.2.3 From 21ddc2a860ca69eb92ab0c48c05187f89aa6a39a Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 9 Jul 2015 15:18:56 +0800 Subject: usb: gadget: multi: allocate and init otg descriptor by otg capabilities Allocate and initialize usb otg descriptor according to gadget otg capabilities, add it for each usb configurations. If otg capability is not defined, keep its original otg descriptor unchanged. Signed-off-by: Li Jun Reviewed-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/gadget/legacy/multi.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/legacy/multi.c b/drivers/usb/gadget/legacy/multi.c index b21b51f0c9fa..c38ead1d67a4 100644 --- a/drivers/usb/gadget/legacy/multi.c +++ b/drivers/usb/gadget/legacy/multi.c @@ -78,21 +78,7 @@ static struct usb_device_descriptor device_desc = { .idProduct = cpu_to_le16(MULTI_PRODUCT_NUM), }; - -static const struct usb_descriptor_header *otg_desc[] = { - (struct usb_descriptor_header *) &(struct usb_otg_descriptor){ - .bLength = sizeof(struct usb_otg_descriptor), - .bDescriptorType = USB_DT_OTG, - - /* - * REVISIT SRP-only hardware is possible, although - * it would not be called "OTG" ... - */ - .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, - }, - NULL, -}; - +static const struct usb_descriptor_header *otg_desc[2]; enum { MULTI_STRING_RNDIS_CONFIG_IDX = USB_GADGET_FIRST_AVAIL_IDX, @@ -429,14 +415,25 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) goto fail_string_ids; device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; + if (gadget_is_otg(gadget) && !otg_desc[0]) { + struct usb_descriptor_header *usb_desc; + + usb_desc = usb_otg_descriptor_alloc(gadget); + if (!usb_desc) + goto fail_string_ids; + usb_otg_descriptor_init(gadget, usb_desc); + otg_desc[0] = usb_desc; + otg_desc[1] = NULL; + } + /* register configurations */ status = rndis_config_register(cdev); if (unlikely(status < 0)) - goto fail_string_ids; + goto fail_otg_desc; status = cdc_config_register(cdev); if (unlikely(status < 0)) - goto fail_string_ids; + goto fail_otg_desc; usb_composite_overwrite_options(cdev, &coverwrite); /* we're done */ @@ -445,6 +442,9 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) /* error recovery */ +fail_otg_desc: + kfree(otg_desc[0]); + otg_desc[0] = NULL; fail_string_ids: fsg_common_remove_luns(fsg_opts->common); fail_set_cdev: @@ -490,6 +490,9 @@ static int multi_unbind(struct usb_composite_dev *cdev) usb_put_function(f_ecm); usb_put_function_instance(fi_ecm); #endif + kfree(otg_desc[0]); + otg_desc[0] = NULL; + return 0; } -- cgit v1.2.3 From 1156e91dd7cc3a579544286d07fd46f0162e3ec6 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 9 Jul 2015 15:18:57 +0800 Subject: usb: gadget: ncm: allocate and init otg descriptor by otg capabilities Allocate and initialize usb otg descriptor according to gadget otg capabilities, add it for each usb configurations. If otg capability is not defined, keep its original otg descriptor unchanged. Signed-off-by: Li Jun Reviewed-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/gadget/legacy/ncm.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/legacy/ncm.c b/drivers/usb/gadget/legacy/ncm.c index 6ce7421412e9..2bae4381332d 100644 --- a/drivers/usb/gadget/legacy/ncm.c +++ b/drivers/usb/gadget/legacy/ncm.c @@ -69,20 +69,7 @@ static struct usb_device_descriptor device_desc = { .bNumConfigurations = 1, }; -static struct usb_otg_descriptor otg_descriptor = { - .bLength = sizeof otg_descriptor, - .bDescriptorType = USB_DT_OTG, - - /* REVISIT SRP-only hardware is possible, although - * it would not be called "OTG" ... - */ - .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, -}; - -static const struct usb_descriptor_header *otg_desc[] = { - (struct usb_descriptor_header *) &otg_descriptor, - NULL, -}; +static const struct usb_descriptor_header *otg_desc[2]; /* string IDs are assigned dynamically */ static struct usb_string strings_dev[] = { @@ -171,16 +158,30 @@ static int gncm_bind(struct usb_composite_dev *cdev) device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; + if (gadget_is_otg(gadget) && !otg_desc[0]) { + struct usb_descriptor_header *usb_desc; + + usb_desc = usb_otg_descriptor_alloc(gadget); + if (!usb_desc) + goto fail; + usb_otg_descriptor_init(gadget, usb_desc); + otg_desc[0] = usb_desc; + otg_desc[1] = NULL; + } + status = usb_add_config(cdev, &ncm_config_driver, ncm_do_config); if (status < 0) - goto fail; + goto fail1; usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&gadget->dev, "%s\n", DRIVER_DESC); return 0; +fail1: + kfree(otg_desc[0]); + otg_desc[0] = NULL; fail: usb_put_function_instance(f_ncm_inst); return status; @@ -192,6 +193,9 @@ static int gncm_unbind(struct usb_composite_dev *cdev) usb_put_function(f_ncm); if (!IS_ERR_OR_NULL(f_ncm_inst)) usb_put_function_instance(f_ncm_inst); + kfree(otg_desc[0]); + otg_desc[0] = NULL; + return 0; } -- cgit v1.2.3 From 93d39afdb8f99a11d1cbd04f4670226494bf03da Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 9 Jul 2015 15:18:58 +0800 Subject: usb: gadget: printer: allocate and init otg descriptor by otg capabilities Allocate and initialize usb otg descriptor according to gadget otg capabilities, add it for each usb configurations. If otg capability is not defined, keep its original otg descriptor unchanged. Reviewed-by: Roger Quadros Signed-off-by: Li Jun Signed-off-by: Felipe Balbi --- drivers/usb/gadget/legacy/printer.c | 49 +++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 19 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/legacy/printer.c b/drivers/usb/gadget/legacy/printer.c index 1ce7df1060a5..0c1fc0622d09 100644 --- a/drivers/usb/gadget/legacy/printer.c +++ b/drivers/usb/gadget/legacy/printer.c @@ -82,16 +82,7 @@ static struct usb_device_descriptor device_desc = { .bNumConfigurations = 1 }; -static struct usb_otg_descriptor otg_descriptor = { - .bLength = sizeof otg_descriptor, - .bDescriptorType = USB_DT_OTG, - .bmAttributes = USB_OTG_SRP, -}; - -static const struct usb_descriptor_header *otg_desc[] = { - (struct usb_descriptor_header *) &otg_descriptor, - NULL, -}; +static const struct usb_descriptor_header *otg_desc[2]; /*-------------------------------------------------------------------------*/ @@ -136,7 +127,6 @@ static int printer_do_config(struct usb_configuration *c) usb_gadget_set_selfpowered(gadget); if (gadget_is_otg(gadget)) { - otg_descriptor.bmAttributes |= USB_OTG_HNP; printer_cfg_driver.descriptors = otg_desc; printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; } @@ -174,21 +164,39 @@ static int printer_bind(struct usb_composite_dev *cdev) opts->q_len = QLEN; ret = usb_string_ids_tab(cdev, strings); - if (ret < 0) { - usb_put_function_instance(fi_printer); - return ret; - } + if (ret < 0) + goto fail_put_func_inst; + device_desc.iManufacturer = strings[USB_GADGET_MANUFACTURER_IDX].id; device_desc.iProduct = strings[USB_GADGET_PRODUCT_IDX].id; device_desc.iSerialNumber = strings[USB_GADGET_SERIAL_IDX].id; - ret = usb_add_config(cdev, &printer_cfg_driver, printer_do_config); - if (ret) { - usb_put_function_instance(fi_printer); - return ret; + if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) { + struct usb_descriptor_header *usb_desc; + + usb_desc = usb_otg_descriptor_alloc(cdev->gadget); + if (!usb_desc) { + ret = -ENOMEM; + goto fail_put_func_inst; + } + usb_otg_descriptor_init(cdev->gadget, usb_desc); + otg_desc[0] = usb_desc; + otg_desc[1] = NULL; } + + ret = usb_add_config(cdev, &printer_cfg_driver, printer_do_config); + if (ret) + goto fail_free_otg_desc; + usb_composite_overwrite_options(cdev, &coverwrite); return ret; + +fail_free_otg_desc: + kfree(otg_desc[0]); + otg_desc[0] = NULL; +fail_put_func_inst: + usb_put_function_instance(fi_printer); + return ret; } static int printer_unbind(struct usb_composite_dev *cdev) @@ -196,6 +204,9 @@ static int printer_unbind(struct usb_composite_dev *cdev) usb_put_function(f_printer); usb_put_function_instance(fi_printer); + kfree(otg_desc[0]); + otg_desc[0] = NULL; + return 0; } -- cgit v1.2.3 From 3dcc7053087fb58c799cd964a00a5396bec3bc9e Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 9 Jul 2015 15:18:59 +0800 Subject: usb: gadget: serial: allocate and init otg descriptor by otg capabilities Allocate and initialize usb otg descriptor according to gadget otg capabilities, add it for each usb configurations. If otg capability is not defined, keep its original otg descriptor unchanged. Reviewed-by: Roger Quadros Signed-off-by: Li Jun Signed-off-by: Felipe Balbi --- drivers/usb/gadget/legacy/serial.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/legacy/serial.c b/drivers/usb/gadget/legacy/serial.c index 8b7528f9b78e..9836d164469a 100644 --- a/drivers/usb/gadget/legacy/serial.c +++ b/drivers/usb/gadget/legacy/serial.c @@ -79,20 +79,7 @@ static struct usb_device_descriptor device_desc = { .bNumConfigurations = 1, }; -static struct usb_otg_descriptor otg_descriptor = { - .bLength = sizeof otg_descriptor, - .bDescriptorType = USB_DT_OTG, - - /* REVISIT SRP-only hardware is possible, although - * it would not be called "OTG" ... - */ - .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, -}; - -static const struct usb_descriptor_header *otg_desc[] = { - (struct usb_descriptor_header *) &otg_descriptor, - NULL, -}; +static const struct usb_descriptor_header *otg_desc[2]; /*-------------------------------------------------------------------------*/ @@ -191,6 +178,18 @@ static int gs_bind(struct usb_composite_dev *cdev) serial_config_driver.iConfiguration = status; if (gadget_is_otg(cdev->gadget)) { + if (!otg_desc[0]) { + struct usb_descriptor_header *usb_desc; + + usb_desc = usb_otg_descriptor_alloc(cdev->gadget); + if (!usb_desc) { + status = -ENOMEM; + goto fail; + } + usb_otg_descriptor_init(cdev->gadget, usb_desc); + otg_desc[0] = usb_desc; + otg_desc[1] = NULL; + } serial_config_driver.descriptors = otg_desc; serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; } @@ -208,13 +207,15 @@ static int gs_bind(struct usb_composite_dev *cdev) "gser"); } if (status < 0) - goto fail; + goto fail1; usb_composite_overwrite_options(cdev, &coverwrite); INFO(cdev, "%s\n", GS_VERSION_NAME); return 0; - +fail1: + kfree(otg_desc[0]); + otg_desc[0] = NULL; fail: return status; } @@ -227,6 +228,10 @@ static int gs_unbind(struct usb_composite_dev *cdev) usb_put_function(f_serial[i]); usb_put_function_instance(fi_serial[i]); } + + kfree(otg_desc[0]); + otg_desc[0] = NULL; + return 0; } -- cgit v1.2.3 From 9e832bf7c011965b378bd963955e315bd0c23aa4 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 9 Jul 2015 15:19:00 +0800 Subject: usb: gadget: zero: allocate and init otg descriptor by otg capabilities Allocate and initialize usb otg descriptor according to gadget otg capabilities, add it for each usb configurations. If otg capability is not defined, keep its original otg descriptor unchanged. Reviewed-by: Roger Quadros Signed-off-by: Li Jun Signed-off-by: Felipe Balbi --- drivers/usb/gadget/legacy/zero.c | 41 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/legacy/zero.c b/drivers/usb/gadget/legacy/zero.c index c986e8addb90..37a410056fed 100644 --- a/drivers/usb/gadget/legacy/zero.c +++ b/drivers/usb/gadget/legacy/zero.c @@ -121,24 +121,7 @@ static struct usb_device_descriptor device_desc = { .bNumConfigurations = 2, }; -#ifdef CONFIG_USB_OTG -static struct usb_otg_descriptor otg_descriptor = { - .bLength = sizeof otg_descriptor, - .bDescriptorType = USB_DT_OTG, - - /* REVISIT SRP-only hardware is possible, although - * it would not be called "OTG" ... - */ - .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, -}; - -static const struct usb_descriptor_header *otg_desc[] = { - (struct usb_descriptor_header *) &otg_descriptor, - NULL, -}; -#else -#define otg_desc NULL -#endif +static const struct usb_descriptor_header *otg_desc[2]; /* string IDs are assigned dynamically */ /* default serial number takes at least two packets */ @@ -341,6 +324,18 @@ static int zero_bind(struct usb_composite_dev *cdev) /* support OTG systems */ if (gadget_is_otg(cdev->gadget)) { + if (!otg_desc[0]) { + struct usb_descriptor_header *usb_desc; + + usb_desc = usb_otg_descriptor_alloc(cdev->gadget); + if (!usb_desc) { + status = -ENOMEM; + goto err_conf_flb; + } + usb_otg_descriptor_init(cdev->gadget, usb_desc); + otg_desc[0] = usb_desc; + otg_desc[1] = NULL; + } sourcesink_driver.descriptors = otg_desc; sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; loopback_driver.descriptors = otg_desc; @@ -359,12 +354,12 @@ static int zero_bind(struct usb_composite_dev *cdev) } status = usb_add_function(&sourcesink_driver, func_ss); if (status) - goto err_conf_flb; + goto err_free_otg_desc; usb_ep_autoconfig_reset(cdev->gadget); status = usb_add_function(&loopback_driver, func_lb); if (status) - goto err_conf_flb; + goto err_free_otg_desc; usb_ep_autoconfig_reset(cdev->gadget); usb_composite_overwrite_options(cdev, &coverwrite); @@ -373,6 +368,9 @@ static int zero_bind(struct usb_composite_dev *cdev) return 0; +err_free_otg_desc: + kfree(otg_desc[0]); + otg_desc[0] = NULL; err_conf_flb: usb_put_function(func_lb); func_lb = NULL; @@ -397,6 +395,9 @@ static int zero_unbind(struct usb_composite_dev *cdev) if (!IS_ERR_OR_NULL(func_lb)) usb_put_function(func_lb); usb_put_function_instance(func_inst_lb); + kfree(otg_desc[0]); + otg_desc[0] = NULL; + return 0; } -- cgit v1.2.3 From b5a2875605cac14a7d7744ec8254547a26c02612 Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Mon, 13 Jul 2015 16:30:18 +0100 Subject: usb: renesas_usbhs: Allow an OTG PHY driver to provide VBUS These changes allow a PHY driver to trigger a VBUS interrupt and to provide the value of VBUS. Reviewed-by: Laurent Pinchart Signed-off-by: Phil Edworthy Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/mod_gadget.c | 62 ++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index dc2aa3261202..494dfe06bb27 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "common.h" /* @@ -50,6 +51,8 @@ struct usbhsg_gpriv { int uep_size; struct usb_gadget_driver *driver; + struct usb_phy *transceiver; + bool vbus_active; u32 status; #define USBHSG_STATUS_STARTED (1 << 0) @@ -872,6 +875,27 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) return 0; } +/* + * VBUS provided by the PHY + */ +static int usbhsm_phy_get_vbus(struct platform_device *pdev) +{ + struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); + struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); + + return gpriv->vbus_active; +} + +static void usbhs_mod_phy_mode(struct usbhs_priv *priv) +{ + struct usbhs_mod_info *info = &priv->mod_info; + + info->irq_vbus = NULL; + priv->pfunc.get_vbus = usbhsm_phy_get_vbus; + + usbhs_irq_callback_update(priv, NULL); +} + /* * * linux usb function @@ -882,12 +906,28 @@ static int usbhsg_gadget_start(struct usb_gadget *gadget, { struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); + struct device *dev = usbhs_priv_to_dev(priv); + int ret; if (!driver || !driver->setup || driver->max_speed < USB_SPEED_FULL) return -EINVAL; + /* connect to bus through transceiver */ + if (!IS_ERR_OR_NULL(gpriv->transceiver)) { + ret = otg_set_peripheral(gpriv->transceiver->otg, + &gpriv->gadget); + if (ret) { + dev_err(dev, "%s: can't bind to transceiver\n", + gpriv->gadget.name); + return ret; + } + + /* get vbus using phy versions */ + usbhs_mod_phy_mode(priv); + } + /* first hook up the driver ... */ gpriv->driver = driver; @@ -900,6 +940,10 @@ static int usbhsg_gadget_stop(struct usb_gadget *gadget) struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); usbhsg_try_stop(priv, USBHSG_STATUS_REGISTERD); + + if (!IS_ERR_OR_NULL(gpriv->transceiver)) + otg_set_peripheral(gpriv->transceiver->otg, NULL); + gpriv->driver = NULL; return 0; @@ -947,12 +991,26 @@ static int usbhsg_set_selfpowered(struct usb_gadget *gadget, int is_self) return 0; } +static int usbhsg_vbus_session(struct usb_gadget *gadget, int is_active) +{ + struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); + struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); + struct platform_device *pdev = usbhs_priv_to_pdev(priv); + + gpriv->vbus_active = !!is_active; + + renesas_usbhs_call_notify_hotplug(pdev); + + return 0; +} + static const struct usb_gadget_ops usbhsg_gadget_ops = { .get_frame = usbhsg_get_frame, .set_selfpowered = usbhsg_set_selfpowered, .udc_start = usbhsg_gadget_start, .udc_stop = usbhsg_gadget_stop, .pullup = usbhsg_pullup, + .vbus_session = usbhsg_vbus_session, }; static int usbhsg_start(struct usbhs_priv *priv) @@ -994,6 +1052,10 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) goto usbhs_mod_gadget_probe_err_gpriv; } + gpriv->transceiver = usb_get_phy(USB_PHY_TYPE_UNDEFINED); + dev_info(dev, "%stransceiver found\n", + gpriv->transceiver ? "" : "no "); + /* * CAUTION * -- cgit v1.2.3 From b2fb5b1a0f50d3ebc12342c8d8dead245e9c9d4e Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Mon, 27 Jul 2015 12:25:27 +0530 Subject: usb: dwc3: ep0: Fix mem corruption on OUT transfers of more than 512 bytes DWC3 uses bounce buffer to handle non max packet aligned OUT transfers and the size of bounce buffer is 512 bytes. However if the host initiates OUT transfers of size more than 512 bytes (and non max packet aligned), the driver throws a WARN dump but still programs the TRB to receive more than 512 bytes. This will cause bounce buffer to overflow and corrupt the adjacent memory locations which can be fatal. Fix it by programming the TRB to receive a maximum of DWC3_EP0_BOUNCE_SIZE (512) bytes. Cc: # 3.4+ Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 69e769c35cf5..06ecd1e6871c 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -820,6 +820,11 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, unsigned maxp = ep0->endpoint.maxpacket; transfer_size += (maxp - (transfer_size % maxp)); + + /* Maximum of DWC3_EP0_BOUNCE_SIZE can only be received */ + if (transfer_size > DWC3_EP0_BOUNCE_SIZE) + transfer_size = DWC3_EP0_BOUNCE_SIZE; + transferred = min_t(u32, ur->length, transfer_size - length); memcpy(ur->buf, dwc->ep0_bounce, transferred); @@ -941,11 +946,14 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, return; } - WARN_ON(req->request.length > DWC3_EP0_BOUNCE_SIZE); - maxpacket = dep->endpoint.maxpacket; transfer_size = roundup(req->request.length, maxpacket); + if (transfer_size > DWC3_EP0_BOUNCE_SIZE) { + dev_WARN(dwc->dev, "bounce buf can't handle req len\n"); + transfer_size = DWC3_EP0_BOUNCE_SIZE; + } + dwc->ep0_bounced = true; /* -- cgit v1.2.3 From 2e5464da4e7dc55e1751d2beb3e6e78f35020756 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Mon, 27 Jul 2015 12:25:28 +0530 Subject: usb: dwc3: ep0: use _roundup_ to calculate the transfer size No functional change. Used _roundup_ macro to calculate the transfer size aligned to maxpacket in dwc3_ep0_complete_data. It also makes it similar to how transfer size is calculated in __dwc3_ep0_do_control_data. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 06ecd1e6871c..672d55a6d598 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -816,10 +816,8 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, length = trb->size & DWC3_TRB_SIZE_MASK; if (dwc->ep0_bounced) { - unsigned transfer_size = ur->length; unsigned maxp = ep0->endpoint.maxpacket; - - transfer_size += (maxp - (transfer_size % maxp)); + unsigned transfer_size = roundup(ur->length, maxp); /* Maximum of DWC3_EP0_BOUNCE_SIZE can only be received */ if (transfer_size > DWC3_EP0_BOUNCE_SIZE) -- cgit v1.2.3 From 8a3442205630d52b1b1777efe07c80832aa5ee73 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Mon, 27 Jul 2015 12:25:29 +0530 Subject: usb: dwc3: ep0: preparation for handling non maxpacket aligned transfers > 512 No functional change. This is in preparation for handling non maxpacket aligned transfers greater than bounce buffer size. This is basically to avoid code duplication when using chained TRB transfers to handle non maxpacket aligned transfers greater than bounce buffer size. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 672d55a6d598..396c2af00fed 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -783,7 +783,11 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, struct usb_request *ur; struct dwc3_trb *trb; struct dwc3_ep *ep0; - u32 transferred; + unsigned transfer_size = 0; + unsigned maxp; + unsigned remaining_ur_length; + void *buf; + u32 transferred = 0; u32 status; u32 length; u8 epnum; @@ -812,20 +816,24 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, } ur = &r->request; + buf = ur->buf; + remaining_ur_length = ur->length; length = trb->size & DWC3_TRB_SIZE_MASK; + maxp = ep0->endpoint.maxpacket; + if (dwc->ep0_bounced) { - unsigned maxp = ep0->endpoint.maxpacket; - unsigned transfer_size = roundup(ur->length, maxp); + transfer_size = roundup((ur->length - transfer_size), + maxp); /* Maximum of DWC3_EP0_BOUNCE_SIZE can only be received */ if (transfer_size > DWC3_EP0_BOUNCE_SIZE) transfer_size = DWC3_EP0_BOUNCE_SIZE; - transferred = min_t(u32, ur->length, - transfer_size - length); - memcpy(ur->buf, dwc->ep0_bounce, transferred); + transferred = min_t(u32, remaining_ur_length, + transfer_size - length); + memcpy(buf, dwc->ep0_bounce, transferred); } else { transferred = ur->length - length; } @@ -934,7 +942,7 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, DWC3_TRBCTL_CONTROL_DATA); } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) && (dep->number == 0)) { - u32 transfer_size; + u32 transfer_size = 0; u32 maxpacket; ret = usb_gadget_map_request(&dwc->gadget, &req->request, @@ -945,7 +953,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, } maxpacket = dep->endpoint.maxpacket; - transfer_size = roundup(req->request.length, maxpacket); + transfer_size = roundup((req->request.length - transfer_size), + maxpacket); if (transfer_size > DWC3_EP0_BOUNCE_SIZE) { dev_WARN(dwc->dev, "bounce buf can't handle req len\n"); -- cgit v1.2.3 From 368ca113ca0a41bbf60be6886bbbd238523c6fba Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Mon, 27 Jul 2015 12:25:30 +0530 Subject: usb: dwc3; ep0: Modify _dwc3_ep0_start_trans_ API to take 'chain' parameter No functional change. Added a new parameter in _dwc3_ep0_start_trans_ to indicate whether the TRB is a chained TRB or last TRB. This is in preparation for adding chained TRB support for ep0. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 396c2af00fed..3f709a3ef31a 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -56,7 +56,7 @@ static const char *dwc3_ep0_state_string(enum dwc3_ep0_state state) } static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, - u32 len, u32 type) + u32 len, u32 type, bool chain) { struct dwc3_gadget_ep_cmd_params params; struct dwc3_trb *trb; @@ -302,7 +302,7 @@ void dwc3_ep0_out_start(struct dwc3 *dwc) int ret; ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8, - DWC3_TRBCTL_CONTROL_SETUP); + DWC3_TRBCTL_CONTROL_SETUP, false); WARN_ON(ret < 0); } @@ -855,7 +855,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, ret = dwc3_ep0_start_trans(dwc, epnum, dwc->ctrl_req_addr, 0, - DWC3_TRBCTL_CONTROL_DATA); + DWC3_TRBCTL_CONTROL_DATA, false); WARN_ON(ret < 0); } } @@ -939,7 +939,7 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, if (req->request.length == 0) { ret = dwc3_ep0_start_trans(dwc, dep->number, dwc->ctrl_req_addr, 0, - DWC3_TRBCTL_CONTROL_DATA); + DWC3_TRBCTL_CONTROL_DATA, false); } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) && (dep->number == 0)) { u32 transfer_size = 0; @@ -970,7 +970,7 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, */ ret = dwc3_ep0_start_trans(dwc, dep->number, dwc->ep0_bounce_addr, transfer_size, - DWC3_TRBCTL_CONTROL_DATA); + DWC3_TRBCTL_CONTROL_DATA, false); } else { ret = usb_gadget_map_request(&dwc->gadget, &req->request, dep->number); @@ -980,7 +980,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, } ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma, - req->request.length, DWC3_TRBCTL_CONTROL_DATA); + req->request.length, DWC3_TRBCTL_CONTROL_DATA, + false); } WARN_ON(ret < 0); @@ -995,7 +996,7 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep) : DWC3_TRBCTL_CONTROL_STATUS2; return dwc3_ep0_start_trans(dwc, dep->number, - dwc->ctrl_req_addr, 0, type); + dwc->ctrl_req_addr, 0, type, false); } static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep) -- cgit v1.2.3 From 2abd9d5fa60f90cd99801687904f528156d31e18 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Mon, 27 Jul 2015 12:25:31 +0530 Subject: usb: dwc3: ep0: Add chained TRB support Add chained TRB support to ep0. Now TRB's can be chained just by invoking _dwc3_ep0_start_trans_ with 'chain' parameter set to true. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 16 +++++++++++++--- drivers/usb/dwc3/gadget.c | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 3f709a3ef31a..ebf2621fae5d 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -70,7 +70,10 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, return 0; } - trb = dwc->ep0_trb; + trb = &dwc->ep0_trb[dep->free_slot]; + + if (chain) + dep->free_slot++; trb->bpl = lower_32_bits(buf_dma); trb->bph = upper_32_bits(buf_dma); @@ -78,10 +81,17 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, trb->ctrl = type; trb->ctrl |= (DWC3_TRB_CTRL_HWO - | DWC3_TRB_CTRL_LST - | DWC3_TRB_CTRL_IOC | DWC3_TRB_CTRL_ISP_IMI); + if (chain) + trb->ctrl |= DWC3_TRB_CTRL_CHN; + else + trb->ctrl |= (DWC3_TRB_CTRL_IOC + | DWC3_TRB_CTRL_LST); + + if (chain) + return 0; + memset(¶ms, 0, sizeof(params)); params.param0 = upper_32_bits(dwc->ep0_trb_addr); params.param1 = lower_32_bits(dwc->ep0_trb_addr); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index d97fcfa8fe87..2feed9e03583 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2687,7 +2687,7 @@ int dwc3_gadget_init(struct dwc3 *dwc) goto err0; } - dwc->ep0_trb = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ep0_trb), + dwc->ep0_trb = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ep0_trb) * 2, &dwc->ep0_trb_addr, GFP_KERNEL); if (!dwc->ep0_trb) { dev_err(dwc->dev, "failed to allocate ep0 trb\n"); -- cgit v1.2.3 From c0bd5456a470223e331a9e9e93b4a7425ecfaabb Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Mon, 27 Jul 2015 12:25:32 +0530 Subject: usb: dwc3: ep0: handle non maxpacket aligned transfers > 512 Use chained TRB mechanism to handle non maxpacket aligned transfers greater than bounce buffer size. With this the first TRB will be programmed to receive 'ALIGN(ur->length - maxp, maxp)' data and the second TRB will be programmed to receive the remaining data using bounce buffer. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index ebf2621fae5d..5320e939e090 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -834,13 +834,26 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, maxp = ep0->endpoint.maxpacket; if (dwc->ep0_bounced) { + /* + * Handle the first TRB before handling the bounce buffer if + * the request length is greater than the bounce buffer size + */ + if (ur->length > DWC3_EP0_BOUNCE_SIZE) { + transfer_size = ALIGN(ur->length - maxp, maxp); + transferred = transfer_size - length; + buf = (u8 *)buf + transferred; + ur->actual += transferred; + remaining_ur_length -= transferred; + + trb++; + length = trb->size & DWC3_TRB_SIZE_MASK; + + ep0->free_slot = 0; + } + transfer_size = roundup((ur->length - transfer_size), maxp); - /* Maximum of DWC3_EP0_BOUNCE_SIZE can only be received */ - if (transfer_size > DWC3_EP0_BOUNCE_SIZE) - transfer_size = DWC3_EP0_BOUNCE_SIZE; - transferred = min_t(u32, remaining_ur_length, transfer_size - length); memcpy(buf, dwc->ep0_bounce, transferred); @@ -963,21 +976,22 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, } maxpacket = dep->endpoint.maxpacket; - transfer_size = roundup((req->request.length - transfer_size), - maxpacket); - if (transfer_size > DWC3_EP0_BOUNCE_SIZE) { - dev_WARN(dwc->dev, "bounce buf can't handle req len\n"); - transfer_size = DWC3_EP0_BOUNCE_SIZE; + if (req->request.length > DWC3_EP0_BOUNCE_SIZE) { + transfer_size = ALIGN(req->request.length - maxpacket, + maxpacket); + ret = dwc3_ep0_start_trans(dwc, dep->number, + req->request.dma, + transfer_size, + DWC3_TRBCTL_CONTROL_DATA, + true); } + transfer_size = roundup((req->request.length - transfer_size), + maxpacket); + dwc->ep0_bounced = true; - /* - * REVISIT in case request length is bigger than - * DWC3_EP0_BOUNCE_SIZE we will need two chained - * TRBs to handle the transfer. - */ ret = dwc3_ep0_start_trans(dwc, dep->number, dwc->ep0_bounce_addr, transfer_size, DWC3_TRBCTL_CONTROL_DATA, false); -- cgit v1.2.3 From ffd9a0fcbbed300b55f84e8397e96c2edd06cbdf Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Tue, 28 Jul 2015 07:19:58 +0200 Subject: usb: gadget: add 'quirk_altset_not_supp' to usb_gadget Due to some UDC controllers may not support altsettings, usb gadget layer needs to provide a generic way to inform gadget functions about non-standard hardware limitations. This patch adds 'quirk_altset_not_supp' field to struct usb_gadget and helper function gadget_is_altset_supported(). It also sets 'quirk_altset_not_supp' to 1 in pxa25x_udc and pxa27x_udc drivers, which have such limitation. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/pxa25x_udc.c | 1 + drivers/usb/gadget/udc/pxa27x_udc.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c index f6cbe667ce39..27f944231477 100644 --- a/drivers/usb/gadget/udc/pxa25x_udc.c +++ b/drivers/usb/gadget/udc/pxa25x_udc.c @@ -1176,6 +1176,7 @@ static void udc_reinit(struct pxa25x_udc *dev) INIT_LIST_HEAD (&dev->gadget.ep_list); INIT_LIST_HEAD (&dev->gadget.ep0->ep_list); dev->ep0state = EP0_IDLE; + dev->gadget.quirk_altset_not_supp = 1; /* basic endpoint records init */ for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) { diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c index 042f06b52677..670ac0b12f00 100644 --- a/drivers/usb/gadget/udc/pxa27x_udc.c +++ b/drivers/usb/gadget/udc/pxa27x_udc.c @@ -1710,6 +1710,7 @@ static void udc_init_data(struct pxa_udc *dev) INIT_LIST_HEAD(&dev->gadget.ep_list); INIT_LIST_HEAD(&dev->gadget.ep0->ep_list); dev->udc_usb_ep[0].pxa_ep = &dev->pxa_ep[0]; + dev->gadget.quirk_altset_not_supp = 1; ep0_idle(dev); /* PXA endpoints init */ -- cgit v1.2.3 From 02ded1b0d8e73dad7d2626c960ef20fb7dc30753 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Tue, 28 Jul 2015 07:19:59 +0200 Subject: usb: gadget: add 'quirk_stall_not_supp' to usb_gadget Due to some UDC controllers may not support stalling, usb gadget layer needs to provide a generic way to inform gadget functions about non-standard hardware limitations. This patch adds 'quirk_stall_not_supp' field to struct usb_gadget and helper function gadget_is_stall_supported(). It also sets 'quirk_stall_not_supp' to 1 in at91_udc driver, which has such limitation. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/at91_udc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c index fc4226462f8f..32f50a7944dd 100644 --- a/drivers/usb/gadget/udc/at91_udc.c +++ b/drivers/usb/gadget/udc/at91_udc.c @@ -825,6 +825,7 @@ static void udc_reinit(struct at91_udc *udc) INIT_LIST_HEAD(&udc->gadget.ep_list); INIT_LIST_HEAD(&udc->gadget.ep0->ep_list); + udc->gadget.quirk_stall_not_supp = 1; for (i = 0; i < NUM_ENDPOINTS; i++) { struct at91_ep *ep = &udc->ep[i]; -- cgit v1.2.3 From ca1023c81dd10f76a5d0a8be2fdbe724fe7a126a Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Tue, 28 Jul 2015 07:20:00 +0200 Subject: usb: gadget: add 'quirk_zlp_not_supp' to usb_gadget Due to some UDC controllers may not support zlp, usb gadget layer needs to provide a generic way to inform gadget functions about non-standard hardware limitations. This patch adds 'quirk_zlp_not_supp' field to struct usb_gadget and helper function gadget_is_zlp_supported(). It also sets 'quirk_zlp_not_supp' to 1 in musb UDC driver, which has such limitation. [ balbi@ti.com : make it build ] Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 625d482f1a97..9e18178f1d45 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -2075,6 +2075,7 @@ __acquires(musb->lock) musb->g.b_hnp_enable = 0; musb->g.a_alt_hnp_support = 0; musb->g.a_hnp_support = 0; + musb->g.quirk_zlp_not_supp = 1; /* Normal reset, as B-Device; * or else after HNP, as A-Device -- cgit v1.2.3 From a4cc42157f3f8c3dd5562b91c7430376912c6fb8 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Tue, 28 Jul 2015 07:20:01 +0200 Subject: usb: gadget: f_mass_storage: check quirk instead of UDC name Use generic mechanism to check if UDC controller supports stalling. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_mass_storage.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 9e88e2b18d95..a2291946ca7e 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -2836,7 +2836,8 @@ int fsg_common_set_cdev(struct fsg_common *common, * halt bulk endpoints correctly. If one of them is present, * disable stalls. */ - common->can_stall = can_stall && !(gadget_is_at91(common->gadget)); + common->can_stall = can_stall && + gadget_is_stall_supported(common->gadget); return 0; } -- cgit v1.2.3 From 7a896d40525349e7d52307fb957882696e09466c Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Tue, 28 Jul 2015 07:20:02 +0200 Subject: usb: gadget: f_ecm/f_ncm: check quirk instead of UDC name Use generic mechanism to check if UDC controller supports zlp. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_ecm.c | 4 ++-- drivers/usb/gadget/function/f_ncm.c | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_ecm.c b/drivers/usb/gadget/function/f_ecm.c index 798760fa7e70..7b7424f10ddd 100644 --- a/drivers/usb/gadget/function/f_ecm.c +++ b/drivers/usb/gadget/function/f_ecm.c @@ -585,8 +585,8 @@ static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) /* Enable zlps by default for ECM conformance; * override for musb_hdrc (avoids txdma ovhead). */ - ecm->port.is_zlp_ok = !(gadget_is_musbhdrc(cdev->gadget) - ); + ecm->port.is_zlp_ok = + gadget_is_zlp_supported(cdev->gadget); ecm->port.cdc_filter = DEFAULT_FILTER; DBG(cdev, "activate ecm\n"); net = gether_connect(&ecm->port); diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index bdcda9f5148e..3f05c6bd57f0 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -853,9 +853,8 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) /* Enable zlps by default for NCM conformance; * override for musb_hdrc (avoids txdma ovhead) */ - ncm->port.is_zlp_ok = !( - gadget_is_musbhdrc(cdev->gadget) - ); + ncm->port.is_zlp_ok = + gadget_is_zlp_supported(cdev->gadget); ncm->port.cdc_filter = DEFAULT_FILTER; DBG(cdev, "activate ncm\n"); net = gether_connect(&ncm->port); -- cgit v1.2.3 From 736d093b5985c1f6583460c8eea1be3c9ee5635e Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Tue, 28 Jul 2015 07:20:03 +0200 Subject: usb: gadget: apply generic altsetting support check mechanism Replace calls of gadget_supports_altsettings() function (which check altset support by comparing UDC controller name with hardcoded names) with gadget_is_altset_supported() which checks generic quirk bitfield. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_obex.c | 2 +- drivers/usb/gadget/function/u_ether.h | 2 +- drivers/usb/gadget/legacy/nokia.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_obex.c b/drivers/usb/gadget/function/f_obex.c index 5519f858904b..2682d59f5675 100644 --- a/drivers/usb/gadget/function/f_obex.c +++ b/drivers/usb/gadget/function/f_obex.c @@ -297,7 +297,7 @@ static inline bool can_support_obex(struct usb_configuration *c) * * Altsettings are mandatory, however... */ - if (!gadget_supports_altsettings(c->cdev->gadget)) + if (!gadget_is_altset_supported(c->cdev->gadget)) return false; /* everything else is *probably* fine ... */ diff --git a/drivers/usb/gadget/function/u_ether.h b/drivers/usb/gadget/function/u_ether.h index 334b38947916..1384f000bd80 100644 --- a/drivers/usb/gadget/function/u_ether.h +++ b/drivers/usb/gadget/function/u_ether.h @@ -259,7 +259,7 @@ void gether_disconnect(struct gether *); /* Some controllers can't support CDC Ethernet (ECM) ... */ static inline bool can_support_ecm(struct usb_gadget *gadget) { - if (!gadget_supports_altsettings(gadget)) + if (!gadget_is_altset_supported(gadget)) return false; /* Everything else is *presumably* fine ... but this is a bit diff --git a/drivers/usb/gadget/legacy/nokia.c b/drivers/usb/gadget/legacy/nokia.c index 8902f454b7bc..264c97e15478 100644 --- a/drivers/usb/gadget/legacy/nokia.c +++ b/drivers/usb/gadget/legacy/nokia.c @@ -292,7 +292,7 @@ static int nokia_bind(struct usb_composite_dev *cdev) nokia_config_500ma_driver.iConfiguration = status; nokia_config_100ma_driver.iConfiguration = status; - if (!gadget_supports_altsettings(gadget)) { + if (!gadget_is_altset_supported(gadget)) { status = -ENODEV; goto err_usb; } -- cgit v1.2.3 From 6f98f545b0b4effdf67e83e214a4eb13cd41fba2 Mon Sep 17 00:00:00 2001 From: "Ivan T. Ivanov" Date: Tue, 28 Jul 2015 11:10:22 +0300 Subject: usb: phy: msm: Add D+/D- lines route control apq8016-sbc board is using Dual SPDT USB Switch (TC7USB40MU), witch is controlled by GPIO to de/multiplex D+/D- USB lines to USB2513B Hub and uB connector. Add support for this. Signed-off-by: Ivan T. Ivanov Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-msm-usb.c | 47 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 61d86d8bf5b7..c58c3c0dbe35 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -32,6 +33,7 @@ #include #include #include +#include #include #include @@ -1471,6 +1473,14 @@ static int msm_otg_vbus_notifier(struct notifier_block *nb, unsigned long event, else clear_bit(B_SESS_VLD, &motg->inputs); + if (test_bit(B_SESS_VLD, &motg->inputs)) { + /* Switch D+/D- lines to Device connector */ + gpiod_set_value_cansleep(motg->switch_gpio, 0); + } else { + /* Switch D+/D- lines to Hub */ + gpiod_set_value_cansleep(motg->switch_gpio, 1); + } + schedule_work(&motg->sm_work); return NOTIFY_DONE; @@ -1546,6 +1556,11 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) motg->manual_pullup = of_property_read_bool(node, "qcom,manual-pullup"); + motg->switch_gpio = devm_gpiod_get_optional(&pdev->dev, "switch", + GPIOD_OUT_LOW); + if (IS_ERR(motg->switch_gpio)) + return PTR_ERR(motg->switch_gpio); + ext_id = ERR_PTR(-ENODEV); ext_vbus = ERR_PTR(-ENODEV); if (of_property_read_bool(node, "extcon")) { @@ -1617,6 +1632,19 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) return 0; } +static int msm_otg_reboot_notify(struct notifier_block *this, + unsigned long code, void *unused) +{ + struct msm_otg *motg = container_of(this, struct msm_otg, reboot); + + /* + * Ensure that D+/D- lines are routed to uB connector, so + * we could load bootloader/kernel at next reboot + */ + gpiod_set_value_cansleep(motg->switch_gpio, 0); + return NOTIFY_DONE; +} + static int msm_otg_probe(struct platform_device *pdev) { struct regulator_bulk_data regs[3]; @@ -1781,6 +1809,17 @@ static int msm_otg_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "Can not create mode change file\n"); } + if (test_bit(B_SESS_VLD, &motg->inputs)) { + /* Switch D+/D- lines to Device connector */ + gpiod_set_value_cansleep(motg->switch_gpio, 0); + } else { + /* Switch D+/D- lines to Hub */ + gpiod_set_value_cansleep(motg->switch_gpio, 1); + } + + motg->reboot.notifier_call = msm_otg_reboot_notify; + register_reboot_notifier(&motg->reboot); + pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); @@ -1807,6 +1846,14 @@ static int msm_otg_remove(struct platform_device *pdev) if (phy->otg->host || phy->otg->gadget) return -EBUSY; + unregister_reboot_notifier(&motg->reboot); + + /* + * Ensure that D+/D- lines are routed to uB connector, so + * we could load bootloader/kernel at next reboot + */ + gpiod_set_value_cansleep(motg->switch_gpio, 0); + extcon_unregister_notifier(motg->id.extcon, EXTCON_USB_HOST, &motg->id.nb); extcon_unregister_notifier(motg->vbus.extcon, EXTCON_USB, &motg->vbus.nb); -- cgit v1.2.3 From 1c99cabfc95d3b08fbf06d558ebfa76b5303710c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 30 Jul 2015 00:29:23 +0300 Subject: usb: gadget: fotg210-udc: remove duplicate conditions We handle the "if (!req->req.length)" condition at the start of the function and return. We can delete this dead code. Signed-off-by: Dan Carpenter Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/fotg210-udc.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c index 1137e3384218..a99ed6d80e9a 100644 --- a/drivers/usb/gadget/udc/fotg210-udc.c +++ b/drivers/usb/gadget/udc/fotg210-udc.c @@ -384,25 +384,15 @@ static void fotg210_ep0_queue(struct fotg210_ep *ep, return; } if (ep->dir_in) { /* if IN */ - if (req->req.length) { - fotg210_start_dma(ep, req); - } else { - pr_err("%s : req->req.length = 0x%x\n", - __func__, req->req.length); - } + fotg210_start_dma(ep, req); if ((req->req.length == req->req.actual) || (req->req.actual < ep->ep.maxpacket)) fotg210_done(ep, req, 0); } else { /* OUT */ - if (!req->req.length) { - fotg210_done(ep, req, 0); - } else { - u32 value = ioread32(ep->fotg210->reg + - FOTG210_DMISGR0); + u32 value = ioread32(ep->fotg210->reg + FOTG210_DMISGR0); - value &= ~DMISGR0_MCX_OUT_INT; - iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR0); - } + value &= ~DMISGR0_MCX_OUT_INT; + iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR0); } } -- cgit v1.2.3 From 5feb5d2003499b1094d898c010a7604d7afddc4c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 30 Jul 2015 00:30:58 +0300 Subject: usb: gadget: m66592-udc: forever loop in set_feature() There is an "&&" vs "||" typo here so this loops 3000 times or if we get unlucky it could loop forever. Fixes: ceaa0a6eeadf ('usb: gadget: m66592-udc: add support for TEST_MODE') Signed-off-by: Dan Carpenter Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/m66592-udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/m66592-udc.c b/drivers/usb/gadget/udc/m66592-udc.c index 309706fe4bf0..9704053dfe05 100644 --- a/drivers/usb/gadget/udc/m66592-udc.c +++ b/drivers/usb/gadget/udc/m66592-udc.c @@ -1052,7 +1052,7 @@ static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl) tmp = m66592_read(m66592, M66592_INTSTS0) & M66592_CTSQ; udelay(1); - } while (tmp != M66592_CS_IDST || timeout-- > 0); + } while (tmp != M66592_CS_IDST && timeout-- > 0); if (tmp == M66592_CS_IDST) m66592_bset(m66592, -- cgit v1.2.3 From 8078f314b8c8012cf36e5decc75378b803bfba4d Mon Sep 17 00:00:00 2001 From: Sanjay Singh Rawat Date: Wed, 22 Jul 2015 16:29:46 +0530 Subject: usb: gadget: f_mass_storage: stop thread in bind failure case After the worker thread is launched, bind function is doing further configuration. In case of failure stop the thread. Acked-by: Michal Nazarewicz Signed-off-by: Sanjay Singh Rawat Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_mass_storage.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index a2291946ca7e..f94a8e2e9b60 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -3081,7 +3081,7 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) /* New interface */ i = usb_interface_id(c, f); if (i < 0) - return i; + goto fail; fsg_intf_desc.bInterfaceNumber = i; fsg->interface_number = i; @@ -3124,7 +3124,14 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) autoconf_fail: ERROR(fsg, "unable to autoconfigure all endpoints\n"); - return -ENOTSUPP; + i = -ENOTSUPP; +fail: + /* terminate the thread */ + if (fsg->common->state != FSG_STATE_TERMINATED) { + raise_exception(fsg->common, FSG_STATE_EXIT); + wait_for_completion(&fsg->common->thread_notifier); + } + return i; } /****************************** ALLOCATE FUNCTION *************************/ -- cgit v1.2.3 From 913e4a90b6f9687ac0f543e7b632753e4f51c441 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Thu, 30 Jul 2015 13:13:03 +0800 Subject: usb: gadget: f_uac2: finalize wMaxPacketSize according to bandwidth According to USB Audio Device 2.0 Spec, Ch4.10.1.1: wMaxPacketSize is defined as follows: Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. This is determined by the audio bandwidth constraints of the endpoint. In current code, the wMaxPacketSize is defined as the maximum packet size for ISO endpoint, and it will let the host reserve much more space than it really needs, so that we can't let more endpoints work together at one frame. We find this issue when we try to let 4 f_uac2 gadgets work together [1] at FS connection. [1]http://www.spinics.net/lists/linux-usb/msg123478.html Acked-by: Daniel Mack Cc: andrzej.p@samsung.com Cc: Daniel Mack Cc: tiwai@suse.de Cc: #v3.18+ Cc: Alan Stern Signed-off-by: Peter Chen Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_uac2.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 6d3eb8b00a48..b5680246d6aa 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -975,6 +975,29 @@ free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep) "%s:%d Error!\n", __func__, __LINE__); } +static void set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts, + struct usb_endpoint_descriptor *ep_desc, + unsigned int factor, bool is_playback) +{ + int chmask, srate, ssize; + u16 max_packet_size; + + if (is_playback) { + chmask = uac2_opts->p_chmask; + srate = uac2_opts->p_srate; + ssize = uac2_opts->p_ssize; + } else { + chmask = uac2_opts->c_chmask; + srate = uac2_opts->c_srate; + ssize = uac2_opts->c_ssize; + } + + max_packet_size = num_channels(chmask) * ssize * + DIV_ROUND_UP(srate, factor / (1 << (ep_desc->bInterval - 1))); + ep_desc->wMaxPacketSize = cpu_to_le16(min(max_packet_size, + le16_to_cpu(ep_desc->wMaxPacketSize))); +} + static int afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) { @@ -1070,10 +1093,14 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) uac2->p_prm.uac2 = uac2; uac2->c_prm.uac2 = uac2; + /* Calculate wMaxPacketSize according to audio bandwidth */ + set_ep_max_packet_size(uac2_opts, &fs_epin_desc, 1000, true); + set_ep_max_packet_size(uac2_opts, &fs_epout_desc, 1000, false); + set_ep_max_packet_size(uac2_opts, &hs_epin_desc, 8000, true); + set_ep_max_packet_size(uac2_opts, &hs_epout_desc, 8000, false); + hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; - hs_epout_desc.wMaxPacketSize = fs_epout_desc.wMaxPacketSize; hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; - hs_epin_desc.wMaxPacketSize = fs_epin_desc.wMaxPacketSize; ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL); if (ret) -- cgit v1.2.3 From 55d811211b139ed097ddaf40d173c258f133c130 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 13 Jul 2015 11:03:50 +0200 Subject: usb: gadget: ffs: call functionfs_unbind() if _ffs_func_bind() fails Function ffs_do_functionfs_bind() calls functionfs_bind() which allocates usb request and increments refcounts. These things needs to be cleaned up by if further steps of initialization fail by calling functionfs_unbind(). Signed-off-by: Robert Baldyga Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_fs.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 6e7be91e6097..adc6d52efa46 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -2897,11 +2897,17 @@ static int ffs_func_bind(struct usb_configuration *c, struct usb_function *f) { struct f_fs_opts *ffs_opts = ffs_do_functionfs_bind(f, c); + struct ffs_function *func = ffs_func_from_usb(f); + int ret; if (IS_ERR(ffs_opts)) return PTR_ERR(ffs_opts); - return _ffs_func_bind(c, f); + ret = _ffs_func_bind(c, f); + if (ret && !--ffs_opts->refcnt) + functionfs_unbind(func->ffs); + + return ret; } -- cgit v1.2.3 From 4ef7a4a1f097b2c17f4f2873a1595aa0aca9f6b4 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 13 Jul 2015 11:03:51 +0200 Subject: usb: gadget: midi: avoid redundant f_midi_set_alt() call Function midi registers two interfaces with single set_alt() function which means that f_midi_set_alt() is called twice when configuration is set. That means that endpoint initialization and ep request allocation is done two times. To avoid this problem we do such things only once, for interface number 1 (MIDI Streaming interface). Signed-off-by: Robert Baldyga Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_midi.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index ad50a67c1465..a287a4829273 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -329,6 +329,10 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt) unsigned i; int err; + /* For Control Device interface we do nothing */ + if (intf == 0) + return 0; + err = f_midi_start_ep(midi, f, midi->in_ep); if (err) return err; -- cgit v1.2.3 From 6fd82b69796cc8f313f160ac55bfd24cedc60fed Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 13 Jul 2015 11:03:52 +0200 Subject: usb: isp1760: udc: add missing usb_ep_set_maxpacket_limit() Since maxpacket_limit was introduced all UDC drivers should use usb_ep_set_maxpacket_limit() function instead of setting maxpacket value manually. ep.maxpacket_limit contains actual maximum maxpacket value supported by hardware which is needed by epautoconf. Signed-off-by: Robert Baldyga Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/isp1760/isp1760-udc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/isp1760/isp1760-udc.c b/drivers/usb/isp1760/isp1760-udc.c index 18ebf5b1f256..3699962987b2 100644 --- a/drivers/usb/isp1760/isp1760-udc.c +++ b/drivers/usb/isp1760/isp1760-udc.c @@ -1382,11 +1382,11 @@ static void isp1760_udc_init_eps(struct isp1760_udc *udc) * This fits in the 8kB FIFO without double-buffering. */ if (ep_num == 0) { - ep->ep.maxpacket = 64; + usb_ep_set_maxpacket_limit(&ep->ep, 64); ep->maxpacket = 64; udc->gadget.ep0 = &ep->ep; } else { - ep->ep.maxpacket = 512; + usb_ep_set_maxpacket_limit(&ep->ep, 512); ep->maxpacket = 0; list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); } -- cgit v1.2.3 From 7674cba55ad66b2565f8abe8d081a6ea4269bfb6 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 13 Jul 2015 11:03:54 +0200 Subject: usb: gadget: atmel_usba_udc: add missing ret value check Add missing return value check. In case of error print debug message and return error code. Signed-off-by: Robert Baldyga Acked-by: Nicolas Ferre Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/atmel_usba_udc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 4095cce05e6a..37d414ec2d69 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -1989,6 +1989,10 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc"); ret = of_property_read_string(pp, "name", &name); + if (ret) { + dev_err(&pdev->dev, "of_probe: name error(%d)\n", ret); + goto err; + } ep->ep.name = name; ep->ep_regs = udc->regs + USBA_EPT_BASE(i); -- cgit v1.2.3 From 5542f58c95aef67bc9016855f7c0bd6117b43100 Mon Sep 17 00:00:00 2001 From: Krzysztof Opasiak Date: Fri, 31 Jul 2015 13:37:45 +0200 Subject: usb: gadget: mass_storage: Fix freeing luns sysfs implementation Use device_is_registered() instad of sysfs flag to determine if we should free sysfs representation of particular LUN. sysfs flag in fsg common determines if luns attributes should be exposed using sysfs. This flag is used when creating and freeing luns. Unfortunately there is no guarantee that this flag will not be changed between creation and removal of particular LUN. Especially because of lun.0 which is created during allocating instance of function. This may lead to resource leak or NULL pointer dereference: [ 62.539925] Unable to handle kernel NULL pointer dereference at virtual address 00000044 [ 62.548014] pgd = ec994000 [ 62.550679] [00000044] *pgd=6d7be831, *pte=00000000, *ppte=00000000 [ 62.556933] Internal error: Oops: 17 [#1] PREEMPT SMP ARM [ 62.562310] Modules linked in: g_mass_storage(+) [ 62.566916] CPU: 2 PID: 613 Comm: insmod Not tainted 4.2.0-rc4-00077-ge29ee91-dirty #125 [ 62.574984] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree) [ 62.581061] task: eca56e80 ti: eca76000 task.ti: eca76000 [ 62.586450] PC is at kernfs_find_ns+0x8/0xe8 [ 62.590698] LR is at kernfs_find_and_get_ns+0x30/0x48 [ 62.595732] pc : [] lr : [] psr: 40010053 [ 62.595732] sp : eca77c40 ip : eca77c38 fp : 000008c1 [ 62.607187] r10: 00000001 r9 : c0082f38 r8 : ed41ce40 [ 62.612395] r7 : c05c1484 r6 : 00000000 r5 : 00000000 r4 : c0814488 [ 62.618904] r3 : 00000000 r2 : 00000000 r1 : c05c1484 r0 : 00000000 [ 62.625417] Flags: nZcv IRQs on FIQs off Mode SVC_32 ISA ARM Segment user [ 62.632620] Control: 10c5387d Table: 6c99404a DAC: 00000015 [ 62.638348] Process insmod (pid: 613, stack limit = 0xeca76210) [ 62.644251] Stack: (0xeca77c40 to 0xeca78000) [ 62.648594] 7c40: c0814488 00000000 00000000 c05c1484 ed41ce40 c0127b88 00000000 c0824888 [ 62.656753] 7c60: ed41d038 ed41d030 ed41d000 c012af4c 00000000 c0824858 ed41d038 c02e3314 [ 62.664912] 7c80: ed41d030 00000000 ed41ce04 c02d9e8c c070eda8 eca77cb4 000008c1 c058317c [ 62.673071] 7ca0: 000008c1 ed41d030 ed41ce00 ed41ce04 ed41d000 c02da044 ed41cf48 c0375870 [ 62.681230] 7cc0: ed9d3c04 ed9d3c00 ed52df80 bf000940 fffffff0 c03758f4 c03758c0 00000000 [ 62.689389] 7ce0: bf000564 c03614e0 ed9d3c04 bf000194 c0082f38 00000001 00000000 c0000100 [ 62.697548] 7d00: c0814488 c0814488 c086b1dc c05893a8 00000000 ed7e8320 00000000 c0128b88 [ 62.705707] 7d20: ed8a6b40 00000000 00000000 ed410500 ed8a6b40 c0594818 ed7e8320 00000000 [ 62.713867] 7d40: 00000000 c0129f20 00000000 c082c444 ed8a6b40 c012a684 00001000 00000000 [ 62.722026] 7d60: c0594818 c082c444 00000000 00000000 ed52df80 ed52df80 00000000 00000000 [ 62.730185] 7d80: 00000000 00000000 00000001 00000002 ed8e9b70 ed52df80 bf0006d0 00000000 [ 62.738345] 7da0: ed8e9b70 ed410500 ed618340 c036129c ed8c1c00 bf0006d0 c080b158 ed8c1c00 [ 62.746504] 7dc0: bf0006d0 c080b158 ed8c1c08 ed410500 c0082f38 ed618340 000008c1 c03640ac [ 62.754663] 7de0: 00000000 bf0006d0 c082c8dc c080b158 c080b158 c03642d4 00000000 bf003000 [ 62.762822] 7e00: 00000000 c0009784 00000000 00000001 00000000 c05849b0 00000002 ee7ab780 [ 62.770981] 7e20: 00000002 ed4105c0 0000c53e 000000d0 c0808600 eca77e5c 00000004 00000000 [ 62.779140] 7e40: bf000000 c0095680 c08075a0 ee001f00 ed4105c0 c00cadc0 ed52df80 bf000780 [ 62.787300] 7e60: ed4105c0 bf000780 00000001 bf0007c8 c0082f38 ed618340 000008c1 c0083e24 [ 62.795459] 7e80: 00000001 bf000780 00000001 eca77f58 00000001 bf000780 00000001 c00857f4 [ 62.803618] 7ea0: bf00078c 00007fff 00000000 c00835b4 eca77f58 00000000 c0082fac eca77f58 [ 62.811777] 7ec0: f05038c0 0003b008 bf000904 00000000 00000000 bf00078c 6e72656b 00006c65 [ 62.819936] 7ee0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 62.828095] 7f00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 62.836255] 7f20: 00000000 00000000 00000000 00000000 00000000 00000000 00000003 0003b008 [ 62.844414] 7f40: 0000017b c000f5c8 eca76000 00000000 0003b008 c0085df8 f04ef000 0001b8a9 [ 62.852573] 7f60: f0503258 f05030c2 f0509fe8 00000968 00000dc8 00000000 00000000 00000000 [ 62.860732] 7f80: 00000029 0000002a 00000011 00000000 0000000a 00000000 33f6eb00 0003b008 [ 62.868892] 7fa0: bef01cac c000f400 33f6eb00 0003b008 00000003 0003b008 00000000 00000003 [ 62.877051] 7fc0: 33f6eb00 0003b008 bef01cac 0000017b 00000000 0003b008 0000000b 0003b008 [ 62.885210] 7fe0: bef01ae0 bef01ad0 0001dc23 b6e8c162 800b0070 00000003 c0c0c0c0 c0c0c0c0 [ 62.893380] [] (kernfs_find_ns) from [] (pm_qos_latency_tolerance_attr_group+0x0/0x10) [ 62.903005] Code: e28dd00c e8bd80f0 e92d41f0 e2923000 (e1d0e4b4) [ 62.909115] ---[ end trace 02fb4373ef095c7b ]--- Acked-by: Michal Nazarewicz Signed-off-by: Krzysztof Opasiak Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_mass_storage.c | 12 ++++++------ drivers/usb/gadget/function/f_mass_storage.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index f94a8e2e9b60..9870913e34bf 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -2742,9 +2742,9 @@ error_release: } EXPORT_SYMBOL_GPL(fsg_common_set_num_buffers); -void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs) +void fsg_common_remove_lun(struct fsg_lun *lun) { - if (sysfs) + if (device_is_registered(&lun->dev)) device_unregister(&lun->dev); fsg_lun_close(lun); kfree(lun); @@ -2757,7 +2757,7 @@ static void _fsg_common_remove_luns(struct fsg_common *common, int n) for (i = 0; i < n; ++i) if (common->luns[i]) { - fsg_common_remove_lun(common->luns[i], common->sysfs); + fsg_common_remove_lun(common->luns[i]); common->luns[i] = NULL; } } @@ -2950,7 +2950,7 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, return 0; error_lun: - if (common->sysfs) + if (device_is_registered(&lun->dev)) device_unregister(&lun->dev); fsg_lun_close(lun); common->luns[id] = NULL; @@ -3038,7 +3038,7 @@ static void fsg_common_release(struct kref *ref) if (!lun) continue; fsg_lun_close(lun); - if (common->sysfs) + if (device_is_registered(&lun->dev)) device_unregister(&lun->dev); kfree(lun); } @@ -3363,7 +3363,7 @@ static void fsg_lun_drop(struct config_group *group, struct config_item *item) unregister_gadget_item(gadget); } - fsg_common_remove_lun(lun_opts->lun, fsg_opts->common->sysfs); + fsg_common_remove_lun(lun_opts->lun); fsg_opts->common->luns[lun_opts->lun_id] = NULL; lun_opts->lun_id = 0; mutex_unlock(&fsg_opts->lock); diff --git a/drivers/usb/gadget/function/f_mass_storage.h b/drivers/usb/gadget/function/f_mass_storage.h index b4866fcef30b..37bc94cbb7f3 100644 --- a/drivers/usb/gadget/function/f_mass_storage.h +++ b/drivers/usb/gadget/function/f_mass_storage.h @@ -137,7 +137,7 @@ void fsg_common_free_buffers(struct fsg_common *common); int fsg_common_set_cdev(struct fsg_common *common, struct usb_composite_dev *cdev, bool can_stall); -void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs); +void fsg_common_remove_lun(struct fsg_lun *lun); void fsg_common_remove_luns(struct fsg_common *common); -- cgit v1.2.3 From dd02ea5a33059e4a753ae8bb877b698c54ee2907 Mon Sep 17 00:00:00 2001 From: Krzysztof Opasiak Date: Fri, 31 Jul 2015 13:46:07 +0200 Subject: usb: gadget: mass_storage: Use static array for luns This patch replace dynamicly allocated luns array with static one. This simplifies the code of mass storage function and modules. Signed-off-by: Krzysztof Opasiak Acked-by: Michal Nazarewicz --- drivers/usb/gadget/function/f_mass_storage.c | 127 ++++++++++----------------- drivers/usb/gadget/function/f_mass_storage.h | 4 - drivers/usb/gadget/legacy/acm_ms.c | 6 -- drivers/usb/gadget/legacy/mass_storage.c | 6 -- drivers/usb/gadget/legacy/multi.c | 6 -- drivers/usb/gadget/legacy/nokia.c | 14 +-- 6 files changed, 50 insertions(+), 113 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 9870913e34bf..04c3bb6e9dcd 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -279,9 +279,8 @@ struct fsg_common { int cmnd_size; u8 cmnd[MAX_COMMAND_SIZE]; - unsigned int nluns; unsigned int lun; - struct fsg_lun **luns; + struct fsg_lun *luns[FSG_MAX_LUNS]; struct fsg_lun *curlun; unsigned int bulk_out_maxpacket; @@ -490,6 +489,16 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) spin_unlock(&common->lock); } +static int _fsg_common_get_max_lun(struct fsg_common *common) +{ + int i = ARRAY_SIZE(common->luns) - 1; + + while (i >= 0 && !common->luns[i]) + --i; + + return i; +} + static int fsg_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) { @@ -533,7 +542,7 @@ static int fsg_setup(struct usb_function *f, w_length != 1) return -EDOM; VDBG(fsg, "get max LUN\n"); - *(u8 *)req->buf = fsg->common->nluns - 1; + *(u8 *)req->buf = _fsg_common_get_max_lun(fsg->common); /* Respond with data/status */ req->length = min((u16)1, w_length); @@ -2131,8 +2140,9 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) } /* Is the CBW meaningful? */ - if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN || - cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { + if (cbw->Lun >= ARRAY_SIZE(common->luns) || + cbw->Flags & ~US_BULK_FLAG_IN || cbw->Length <= 0 || + cbw->Length > MAX_COMMAND_SIZE) { DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " "cmdlen %u\n", cbw->Lun, cbw->Flags, cbw->Length); @@ -2159,7 +2169,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) if (common->data_size == 0) common->data_dir = DATA_DIR_NONE; common->lun = cbw->Lun; - if (common->lun < common->nluns) + if (common->lun < ARRAY_SIZE(common->luns)) common->curlun = common->luns[common->lun]; else common->curlun = NULL; @@ -2307,7 +2317,7 @@ reset: } common->running = 1; - for (i = 0; i < common->nluns; ++i) + for (i = 0; i < ARRAY_SIZE(common->luns); ++i) if (common->luns[i]) common->luns[i]->unit_attention_data = SS_RESET_OCCURRED; @@ -2409,7 +2419,7 @@ static void handle_exception(struct fsg_common *common) if (old_state == FSG_STATE_ABORT_BULK_OUT) common->state = FSG_STATE_STATUS_PHASE; else { - for (i = 0; i < common->nluns; ++i) { + for (i = 0; i < ARRAY_SIZE(common->luns); ++i) { curlun = common->luns[i]; if (!curlun) continue; @@ -2453,7 +2463,7 @@ static void handle_exception(struct fsg_common *common) * a waste of time. Ditto for the INTERFACE_CHANGE and * CONFIG_CHANGE cases. */ - /* for (i = 0; i < common->nluns; ++i) */ + /* for (i = 0; i < common->ARRAY_SIZE(common->luns); ++i) */ /* if (common->luns[i]) */ /* common->luns[i]->unit_attention_data = */ /* SS_RESET_OCCURRED; */ @@ -2552,12 +2562,11 @@ static int fsg_main_thread(void *common_) if (!common->ops || !common->ops->thread_exits || common->ops->thread_exits(common) < 0) { - struct fsg_lun **curlun_it = common->luns; - unsigned i = common->nluns; + int i; down_write(&common->filesem); - for (; i--; ++curlun_it) { - struct fsg_lun *curlun = *curlun_it; + for (i = 0; i < ARRAY_SIZE(common->luns); --i) { + struct fsg_lun *curlun = common->luns[i]; if (!curlun || !fsg_lun_is_open(curlun)) continue; @@ -2676,6 +2685,7 @@ static struct fsg_common *fsg_common_setup(struct fsg_common *common) init_completion(&common->thread_notifier); init_waitqueue_head(&common->fsg_wait); common->state = FSG_STATE_TERMINATED; + memset(common->luns, 0, sizeof(common->luns)); return common; } @@ -2764,42 +2774,10 @@ static void _fsg_common_remove_luns(struct fsg_common *common, int n) void fsg_common_remove_luns(struct fsg_common *common) { - _fsg_common_remove_luns(common, common->nluns); + _fsg_common_remove_luns(common, ARRAY_SIZE(common->luns)); } EXPORT_SYMBOL_GPL(fsg_common_remove_luns); -void fsg_common_free_luns(struct fsg_common *common) -{ - fsg_common_remove_luns(common); - kfree(common->luns); - common->luns = NULL; -} -EXPORT_SYMBOL_GPL(fsg_common_free_luns); - -int fsg_common_set_nluns(struct fsg_common *common, int nluns) -{ - struct fsg_lun **curlun; - - /* Find out how many LUNs there should be */ - if (nluns < 1 || nluns > FSG_MAX_LUNS) { - pr_err("invalid number of LUNs: %u\n", nluns); - return -EINVAL; - } - - curlun = kcalloc(FSG_MAX_LUNS, sizeof(*curlun), GFP_KERNEL); - if (unlikely(!curlun)) - return -ENOMEM; - - if (common->luns) - fsg_common_free_luns(common); - - common->luns = curlun; - common->nluns = nluns; - - return 0; -} -EXPORT_SYMBOL_GPL(fsg_common_set_nluns); - void fsg_common_set_ops(struct fsg_common *common, const struct fsg_operations *ops) { @@ -2881,7 +2859,7 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, char *pathbuf, *p; int rc = -ENOMEM; - if (!common->nluns || !common->luns) + if (id >= ARRAY_SIZE(common->luns)) return -ENODEV; if (common->luns[id]) @@ -2965,14 +2943,16 @@ int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg) char buf[8]; /* enough for 100000000 different numbers, decimal */ int i, rc; - for (i = 0; i < common->nluns; ++i) { + fsg_common_remove_luns(common); + + for (i = 0; i < cfg->nluns; ++i) { snprintf(buf, sizeof(buf), "lun%d", i); rc = fsg_common_create_lun(common, &cfg->luns[i], i, buf, NULL); if (rc) goto fail; } - pr_info("Number of LUNs=%d\n", common->nluns); + pr_info("Number of LUNs=%d\n", cfg->nluns); return 0; @@ -3021,6 +3001,7 @@ EXPORT_SYMBOL_GPL(fsg_common_run_thread); static void fsg_common_release(struct kref *ref) { struct fsg_common *common = container_of(ref, struct fsg_common, ref); + int i; /* If the thread isn't already dead, tell it to exit now */ if (common->state != FSG_STATE_TERMINATED) { @@ -3028,22 +3009,14 @@ static void fsg_common_release(struct kref *ref) wait_for_completion(&common->thread_notifier); } - if (likely(common->luns)) { - struct fsg_lun **lun_it = common->luns; - unsigned i = common->nluns; - - /* In error recovery common->nluns may be zero. */ - for (; i; --i, ++lun_it) { - struct fsg_lun *lun = *lun_it; - if (!lun) - continue; - fsg_lun_close(lun); + for (i = 0; i < ARRAY_SIZE(common->luns); ++i) { + struct fsg_lun *lun = common->luns[i]; + if (!lun) + continue; + fsg_lun_close(lun); if (device_is_registered(&lun->dev)) - device_unregister(&lun->dev); - kfree(lun); - } - - kfree(common->luns); + device_unregister(&lun->dev); + kfree(lun); } _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers); @@ -3057,6 +3030,7 @@ static void fsg_common_release(struct kref *ref) static int fsg_bind(struct usb_configuration *c, struct usb_function *f) { struct fsg_dev *fsg = fsg_from_func(f); + struct fsg_common *common = fsg->common; struct usb_gadget *gadget = c->cdev->gadget; int i; struct usb_ep *ep; @@ -3064,6 +3038,13 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) int ret; struct fsg_opts *opts; + /* Don't allow to bind if we don't have at least one LUN */ + ret = _fsg_common_get_max_lun(common); + if (ret < 0) { + pr_err("There should be at least one LUN.\n"); + return -EINVAL; + } + opts = fsg_opts_from_func_inst(f->fi); if (!opts->no_configfs) { ret = fsg_common_set_cdev(fsg->common, c->cdev, @@ -3517,14 +3498,11 @@ static struct usb_function_instance *fsg_alloc_inst(void) rc = PTR_ERR(opts->common); goto release_opts; } - rc = fsg_common_set_nluns(opts->common, FSG_MAX_LUNS); - if (rc) - goto release_opts; rc = fsg_common_set_num_buffers(opts->common, CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS); if (rc) - goto release_luns; + goto release_opts; pr_info(FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n"); @@ -3547,8 +3525,6 @@ static struct usb_function_instance *fsg_alloc_inst(void) release_buffers: fsg_common_free_buffers(opts->common); -release_luns: - kfree(opts->common->luns); release_opts: kfree(opts); return ERR_PTR(rc); @@ -3574,23 +3550,12 @@ static struct usb_function *fsg_alloc(struct usb_function_instance *fi) struct fsg_opts *opts = fsg_opts_from_func_inst(fi); struct fsg_common *common = opts->common; struct fsg_dev *fsg; - unsigned nluns, i; fsg = kzalloc(sizeof(*fsg), GFP_KERNEL); if (unlikely(!fsg)) return ERR_PTR(-ENOMEM); mutex_lock(&opts->lock); - if (!opts->refcnt) { - for (nluns = i = 0; i < FSG_MAX_LUNS; ++i) - if (common->luns[i]) - nluns = i + 1; - if (!nluns) - pr_warn("No LUNS defined, continuing anyway\n"); - else - common->nluns = nluns; - pr_info("Number of LUNs=%u\n", common->nluns); - } opts->refcnt++; mutex_unlock(&opts->lock); diff --git a/drivers/usb/gadget/function/f_mass_storage.h b/drivers/usb/gadget/function/f_mass_storage.h index 37bc94cbb7f3..445df6775609 100644 --- a/drivers/usb/gadget/function/f_mass_storage.h +++ b/drivers/usb/gadget/function/f_mass_storage.h @@ -141,10 +141,6 @@ void fsg_common_remove_lun(struct fsg_lun *lun); void fsg_common_remove_luns(struct fsg_common *common); -void fsg_common_free_luns(struct fsg_common *common); - -int fsg_common_set_nluns(struct fsg_common *common, int nluns); - void fsg_common_set_ops(struct fsg_common *common, const struct fsg_operations *ops); diff --git a/drivers/usb/gadget/legacy/acm_ms.c b/drivers/usb/gadget/legacy/acm_ms.c index 4d8adb48b8a7..4b158e2d1e57 100644 --- a/drivers/usb/gadget/legacy/acm_ms.c +++ b/drivers/usb/gadget/legacy/acm_ms.c @@ -186,10 +186,6 @@ static int acm_ms_bind(struct usb_composite_dev *cdev) if (status) goto fail; - status = fsg_common_set_nluns(opts->common, config.nluns); - if (status) - goto fail_set_nluns; - status = fsg_common_set_cdev(opts->common, cdev, config.can_stall); if (status) goto fail_set_cdev; @@ -239,8 +235,6 @@ fail_otg_desc: fail_string_ids: fsg_common_remove_luns(opts->common); fail_set_cdev: - fsg_common_free_luns(opts->common); -fail_set_nluns: fsg_common_free_buffers(opts->common); fail: usb_put_function_instance(fi_msg); diff --git a/drivers/usb/gadget/legacy/mass_storage.c b/drivers/usb/gadget/legacy/mass_storage.c index ab1a42ce75d2..bda3c519110f 100644 --- a/drivers/usb/gadget/legacy/mass_storage.c +++ b/drivers/usb/gadget/legacy/mass_storage.c @@ -177,10 +177,6 @@ static int msg_bind(struct usb_composite_dev *cdev) if (status) goto fail; - status = fsg_common_set_nluns(opts->common, config.nluns); - if (status) - goto fail_set_nluns; - fsg_common_set_ops(opts->common, &ops); status = fsg_common_set_cdev(opts->common, cdev, config.can_stall); @@ -227,8 +223,6 @@ fail_otg_desc: fail_string_ids: fsg_common_remove_luns(opts->common); fail_set_cdev: - fsg_common_free_luns(opts->common); -fail_set_nluns: fsg_common_free_buffers(opts->common); fail: usb_put_function_instance(fi_msg); diff --git a/drivers/usb/gadget/legacy/multi.c b/drivers/usb/gadget/legacy/multi.c index c38ead1d67a4..4fe794ddcd49 100644 --- a/drivers/usb/gadget/legacy/multi.c +++ b/drivers/usb/gadget/legacy/multi.c @@ -393,10 +393,6 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) if (status) goto fail2; - status = fsg_common_set_nluns(fsg_opts->common, config.nluns); - if (status) - goto fail_set_nluns; - status = fsg_common_set_cdev(fsg_opts->common, cdev, config.can_stall); if (status) goto fail_set_cdev; @@ -448,8 +444,6 @@ fail_otg_desc: fail_string_ids: fsg_common_remove_luns(fsg_opts->common); fail_set_cdev: - fsg_common_free_luns(fsg_opts->common); -fail_set_nluns: fsg_common_free_buffers(fsg_opts->common); fail2: usb_put_function_instance(fi_msg); diff --git a/drivers/usb/gadget/legacy/nokia.c b/drivers/usb/gadget/legacy/nokia.c index 264c97e15478..c20f3b58f126 100644 --- a/drivers/usb/gadget/legacy/nokia.c +++ b/drivers/usb/gadget/legacy/nokia.c @@ -339,19 +339,15 @@ static int nokia_bind(struct usb_composite_dev *cdev) if (status) goto err_msg_inst; - status = fsg_common_set_nluns(fsg_opts->common, fsg_config.nluns); - if (status) - goto err_msg_buf; - status = fsg_common_set_cdev(fsg_opts->common, cdev, fsg_config.can_stall); if (status) - goto err_msg_set_nluns; + goto err_msg_buf; fsg_common_set_sysfs(fsg_opts->common, true); status = fsg_common_create_luns(fsg_opts->common, &fsg_config); if (status) - goto err_msg_set_nluns; + goto err_msg_buf; fsg_common_set_inquiry_string(fsg_opts->common, fsg_config.vendor_name, fsg_config.product_name); @@ -360,7 +356,7 @@ static int nokia_bind(struct usb_composite_dev *cdev) status = usb_add_config(cdev, &nokia_config_500ma_driver, nokia_bind_config); if (status < 0) - goto err_msg_set_cdev; + goto err_msg_luns; status = usb_add_config(cdev, &nokia_config_100ma_driver, nokia_bind_config); @@ -381,10 +377,8 @@ err_put_cfg1: if (!IS_ERR_OR_NULL(f_phonet_cfg1)) usb_put_function(f_phonet_cfg1); usb_put_function(f_ecm_cfg1); -err_msg_set_cdev: +err_msg_luns: fsg_common_remove_luns(fsg_opts->common); -err_msg_set_nluns: - fsg_common_free_luns(fsg_opts->common); err_msg_buf: fsg_common_free_buffers(fsg_opts->common); err_msg_inst: -- cgit v1.2.3 From d3cb25a12138a09bc948c0091d3d42e519980659 Mon Sep 17 00:00:00 2001 From: Pengyu Ma Date: Mon, 3 Aug 2015 11:28:24 +0800 Subject: usb: gadget: udc: fix spin_lock in pch_udc When remove module g_serial on quark platform, the following Warning on: Modules linked in: usb_f_acm u_serial g_serial(-) pch_udc libcomposite configfs udc_core ad7298 industrialio_triggered_buffer kfifo_buf tpm_i2c_infineon indus CPU: 0 PID: 369 Comm: modprobe Not tainted 3.14.29ltsi-WR7.0.0.0_standard #6 Hardware name: Intel Corp. QUARK/CrossHill, BIOS 0x010100F5 01/01/2014 f641df0c f641df0c f641dec8 c15ac7fa f641defc c103084f c16c2356 f641df28 00000171 c16b855c 000009dd c15b2d6f 000009dd c15b2d6f f6bd2000 faae5480 00000000 f641df14 c10308a3 00000009 f641df0c c16c2356 f641df28 f641df2c Call Trace: [] dump_stack+0x16/0x18 [] warn_slowpath_common+0x7f/0xa0 [] ? preempt_count_sub+0x6f/0xc0 [] ? preempt_count_sub+0x6f/0xc0 [] warn_slowpath_fmt+0x33/0x40 [] preempt_count_sub+0x6f/0xc0 [] pch_udc_pcd_pullup+0x32/0xa0 [pch_udc] [] usb_gadget_remove_driver+0x29/0x60 [udc_core] [] usb_gadget_unregister_driver+0x59/0x80 [udc_core] [] usb_composite_unregister+0x10/0x20 [libcomposite] [] cleanup+0xd/0xf [g_serial] [] SyS_delete_module+0xf7/0x150 [] ? ____fput+0xd/0x10 [] ? task_work_run+0x6e/0xa0 [] syscall_call+0x7/0x7 g_serial module on quark is depended on pch_udc module, ttyGSX cann't recieve data and warning on when remove g_serial. It was unlocked before the modification of the structure it was protecting, fix it as "lock -> unlock" to resolve this. Signed-off-by: Pengyu Ma Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/pch_udc.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c index dcf5defdb9e5..e071c62d7f24 100644 --- a/drivers/usb/gadget/udc/pch_udc.c +++ b/drivers/usb/gadget/udc/pch_udc.c @@ -620,9 +620,9 @@ static inline void pch_udc_vbus_session(struct pch_udc_dev *dev, dev->vbus_session = 1; } else { if (dev->driver && dev->driver->disconnect) { - spin_unlock(&dev->lock); - dev->driver->disconnect(&dev->gadget); spin_lock(&dev->lock); + dev->driver->disconnect(&dev->gadget); + spin_unlock(&dev->lock); } pch_udc_set_disconnect(dev); dev->vbus_session = 0; @@ -1191,9 +1191,9 @@ static int pch_udc_pcd_pullup(struct usb_gadget *gadget, int is_on) pch_udc_reconnect(dev); } else { if (dev->driver && dev->driver->disconnect) { - spin_unlock(&dev->lock); - dev->driver->disconnect(&dev->gadget); spin_lock(&dev->lock); + dev->driver->disconnect(&dev->gadget); + spin_unlock(&dev->lock); } pch_udc_set_disconnect(dev); } @@ -1488,11 +1488,11 @@ static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req, req->dma_mapped = 0; } ep->halted = 1; - spin_unlock(&dev->lock); + spin_lock(&dev->lock); if (!ep->in) pch_udc_ep_clear_rrdy(ep); usb_gadget_giveback_request(&ep->ep, &req->req); - spin_lock(&dev->lock); + spin_unlock(&dev->lock); ep->halted = halted; } @@ -2414,7 +2414,7 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev) dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IDX].ep; else /* OUT */ dev->gadget.ep0 = &ep->ep; - spin_unlock(&dev->lock); + spin_lock(&dev->lock); /* If Mass storage Reset */ if ((dev->setup_data.bRequestType == 0x21) && (dev->setup_data.bRequest == 0xFF)) @@ -2422,7 +2422,7 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev) /* call gadget with setup data received */ setup_supported = dev->driver->setup(&dev->gadget, &dev->setup_data); - spin_lock(&dev->lock); + spin_unlock(&dev->lock); if (dev->setup_data.bRequestType & USB_DIR_IN) { ep->td_data->status = (ep->td_data->status & @@ -2594,9 +2594,9 @@ static void pch_udc_svc_ur_interrupt(struct pch_udc_dev *dev) empty_req_queue(ep); } if (dev->driver) { - spin_unlock(&dev->lock); - usb_gadget_udc_reset(&dev->gadget, dev->driver); spin_lock(&dev->lock); + usb_gadget_udc_reset(&dev->gadget, dev->driver); + spin_unlock(&dev->lock); } } @@ -2675,9 +2675,9 @@ static void pch_udc_svc_intf_interrupt(struct pch_udc_dev *dev) dev->ep[i].halted = 0; } dev->stall = 0; - spin_unlock(&dev->lock); - ret = dev->driver->setup(&dev->gadget, &dev->setup_data); spin_lock(&dev->lock); + ret = dev->driver->setup(&dev->gadget, &dev->setup_data); + spin_unlock(&dev->lock); } /** @@ -2712,9 +2712,9 @@ static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev) dev->stall = 0; /* call gadget zero with setup data received */ - spin_unlock(&dev->lock); - ret = dev->driver->setup(&dev->gadget, &dev->setup_data); spin_lock(&dev->lock); + ret = dev->driver->setup(&dev->gadget, &dev->setup_data); + spin_unlock(&dev->lock); } /** @@ -2747,18 +2747,18 @@ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr) if (dev_intr & UDC_DEVINT_US) { if (dev->driver && dev->driver->suspend) { - spin_unlock(&dev->lock); - dev->driver->suspend(&dev->gadget); spin_lock(&dev->lock); + dev->driver->suspend(&dev->gadget); + spin_unlock(&dev->lock); } vbus = pch_vbus_gpio_get_value(dev); if ((dev->vbus_session == 0) && (vbus != 1)) { if (dev->driver && dev->driver->disconnect) { - spin_unlock(&dev->lock); - dev->driver->disconnect(&dev->gadget); spin_lock(&dev->lock); + dev->driver->disconnect(&dev->gadget); + spin_unlock(&dev->lock); } pch_udc_reconnect(dev); } else if ((dev->vbus_session == 0) -- cgit v1.2.3 From 2f0bb2a0e7f5161e83615fb1283c5079566ed6a7 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 3 Aug 2015 05:37:10 -0700 Subject: usb: musb: Allow building in all the DMA code With recent changes to MUSB code, we can now now get rid of the Kconfig choise for the DMA code and allow building in any of the desired DMA code. This makes life easier for distros. Signed-off-by: Tony Lindgren Signed-off-by: Felipe Balbi --- drivers/usb/musb/Kconfig | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 37081ed8f295..1f2037bbeb0d 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -124,19 +124,20 @@ config USB_MUSB_JZ4740 config USB_MUSB_AM335X_CHILD tristate -choice - prompt 'MUSB DMA mode' - default MUSB_PIO_ONLY if ARCH_MULTIPLATFORM || USB_MUSB_JZ4740 - default USB_UX500_DMA if USB_MUSB_UX500 - default USB_INVENTRA_DMA if USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN - default USB_TI_CPPI_DMA if USB_MUSB_DAVINCI - default USB_TUSB_OMAP_DMA if USB_MUSB_TUSB6010 - default MUSB_PIO_ONLY if USB_MUSB_TUSB6010 || USB_MUSB_DA8XX || USB_MUSB_AM35X \ - || USB_MUSB_DSPS +comment "MUSB DMA mode" + +config MUSB_PIO_ONLY + bool 'Disable DMA (always use PIO)' help - Unfortunately, only one option can be enabled here. Ideally one - should be able to build all these drivers into one kernel to - allow using DMA on multiplatform kernels. + All data is copied between memory and FIFO by the CPU. + DMA controllers are ignored. + + Do not choose this unless DMA support for your SOC or board + is unavailable (or unstable). When DMA is enabled at compile time, + you can still disable it at run time using the "use_dma=n" module + parameter. + +if !MUSB_PIO_ONLY config USB_UX500_DMA bool 'ST Ericsson Ux500' @@ -168,17 +169,6 @@ config USB_TUSB_OMAP_DMA help Enable DMA transfers on TUSB 6010 when OMAP DMA is available. -config MUSB_PIO_ONLY - bool 'Disable DMA (always use PIO)' - help - All data is copied between memory and FIFO by the CPU. - DMA controllers are ignored. - - Do not choose this unless DMA support for your SOC or board - is unavailable (or unstable). When DMA is enabled at compile time, - you can still disable it at run time using the "use_dma=n" module - parameter. - -endchoice +endif # !MUSB_PIO_ONLY endif # USB_MUSB_HDRC -- cgit v1.2.3 From a24b071bb4ac37ef51a0ed4765f89be05a617677 Mon Sep 17 00:00:00 2001 From: Fupan Li Date: Mon, 3 Aug 2015 19:19:43 +0800 Subject: usb: gadget: f_printer: fix deadlock caused by nested spinlock Function printer_func_disable() has called spinlock on printer_dev->lock, and it'll call function chain of printer_reset_interface() | +---dwc3_gadget_ep_disable() | +---__dwc3_gadget_ep_disable() | +---dwc3_remove_requests() | +---dwc3_gadget_giveback() | +---rx_complete() in the protected block. However, rx_complete() in f_printer.c calls spinlock on printer_dev->lock again, which will cause system hang. The following steps can reproduce this hang: 1. Build the test program from Documentation/usb/gadget_printer.txt as g_printer 2. Plug in the USB device to a host(such as Ubuntu). 3. on the USB device system run: #modprobe g_printer.ko #./g_printer -read_data 4. Unplug the USB device from the host The system will hang later. In order to avoid this deadlock, moving the spinlock from printer_func_disable() into printer_reset_interface() and excluding the block of calling dwc3_gadget_ep_disable(), in which the critical resource will be protected by its spinlock in rx_complete(). This commit will fix the system hang with the following calltrace: INFO: rcu_preempt detected stalls on CPUs/tasks: { 3} (detected by 0, t=21006 jiffies, g=524, c=523, q=2) sending NMI to all CPUs: NMI backtrace for cpu 3 CPU: 3 PID: 718 Comm: irq/22-dwc3 Not tainted 3.10.38-ltsi-WR6.0.0.11_standard #2 Hardware name: Intel Corp. VALLEYVIEW B3 PLATFORM/NOTEBOOK, BIOS BYTICRB1.86C.0092.R32.1410021707 10/02/2014 task: f44f4c20 ti: f40f6000 task.ti: f40f6000 EIP: 0060:[] EFLAGS: 00000097 CPU: 3 EIP is at _raw_spin_lock_irqsave+0x35/0x40 EAX: 00000076 EBX: f80fad00 ECX: 00000076 EDX: 00000075 ESI: 00000096 EDI: ffffff94 EBP: f40f7e20 ESP: f40f7e18 DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 CR0: 8005003b CR2: b77ac000 CR3: 01c30000 CR4: 001007f0 DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 DR6: ffff0ff0 DR7: 00000400 Stack: f474a720 f80fad00 f40f7e3c f80f93cc c135d486 00000000 f474a720 f468fb00 f4bea894 f40f7e54 f7e35f19 ffffff00 f468fb00 f468fb24 00000086 f40f7e64 f7e36577 f468fb00 f4bea810 f40f7e74 f7e365a8 f468fb00 f4bea894 f40f7e9c Call Trace: [] rx_complete+0x1c/0xb0 [g_printer] [] ? vsnprintf+0x166/0x390 [] dwc3_gadget_giveback+0xc9/0xf0 [dwc3] [] dwc3_remove_requests+0x57/0x70 [dwc3] [] __dwc3_gadget_ep_disable+0x18/0x60 [dwc3] [] dwc3_gadget_ep_disable+0x89/0xf0 [dwc3] [] printer_reset_interface+0x31/0x50 [g_printer] [] printer_func_disable+0x20/0x30 [g_printer] [] composite_disconnect+0x4b/0x90 [libcomposite] [] dwc3_disconnect_gadget+0x38/0x43 [dwc3] [] dwc3_gadget_disconnect_interrupt+0x3e/0x5a [dwc3] [] dwc3_thread_interrupt+0x5c8/0x610 [dwc3] [] irq_thread_fn+0x18/0x30 [] irq_thread+0x100/0x130 [] ? irq_finalize_oneshot.part.29+0xb0/0xb0 [] ? wake_threads_waitq+0x40/0x40 [] ? irq_thread_dtor+0xb0/0xb0 [] kthread+0x94/0xa0 [] ret_from_kernel_thread+0x1b/0x28 [] ? kthread_create_on_node+0xc0/0xc0 Signed-off-by: Fupan Li Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_printer.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index 44173df27273..a91c18a585b5 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c @@ -804,6 +804,8 @@ done: static void printer_reset_interface(struct printer_dev *dev) { + unsigned long flags; + if (dev->interface < 0) return; @@ -815,9 +817,11 @@ static void printer_reset_interface(struct printer_dev *dev) if (dev->out_ep->desc) usb_ep_disable(dev->out_ep); + spin_lock_irqsave(&dev->lock, flags); dev->in_ep->desc = NULL; dev->out_ep->desc = NULL; dev->interface = -1; + spin_unlock_irqrestore(&dev->lock, flags); } /* Change our operational Interface. */ @@ -1131,13 +1135,10 @@ static int printer_func_set_alt(struct usb_function *f, static void printer_func_disable(struct usb_function *f) { struct printer_dev *dev = func_to_printer(f); - unsigned long flags; DBG(dev, "%s\n", __func__); - spin_lock_irqsave(&dev->lock, flags); printer_reset_interface(dev); - spin_unlock_irqrestore(&dev->lock, flags); } static inline struct f_printer_opts -- cgit v1.2.3 From 3f217e9e96daa3d7741bab705fe9c7798d9951a9 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Fri, 31 Jul 2015 10:41:00 +0800 Subject: usb: chipidea: add ci->is_otg condition for otg judgement Since some chipidea based controller is not otg capable, add ci->is_otg condition when setting is_otg flag for gadget. Signed-off-by: Li Jun Reviewed-by: Roger Quadros Acked-by: Peter Chen Signed-off-by: Felipe Balbi --- drivers/usb/chipidea/udc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index b7cca3e597bf..f5fbe78e8e6a 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1838,8 +1838,8 @@ static int udc_start(struct ci_hdrc *ci) ci->gadget.name = ci->platdata->name; ci->gadget.otg_caps = otg_caps; - if (otg_caps->hnp_support || otg_caps->srp_support || - otg_caps->adp_support) + if (ci->is_otg && (otg_caps->hnp_support || otg_caps->srp_support || + otg_caps->adp_support)) ci->gadget.is_otg = 1; INIT_LIST_HEAD(&ci->gadget.ep_list); -- cgit v1.2.3 From 4b68b50fd45e2f429da574c74d9a3788a861434f Mon Sep 17 00:00:00 2001 From: Saurabh Karajgaonkar Date: Tue, 4 Aug 2015 14:01:31 +0000 Subject: usb: phy: phy-mxs-usb: Simplify return statement Replace redundant variable use in return statement. Signed-off-by: Saurabh Karajgaonkar Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-mxs-usb.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index 3fcc0483a081..4d863ebc117c 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -506,11 +506,7 @@ static int mxs_phy_probe(struct platform_device *pdev) device_set_wakeup_capable(&pdev->dev, true); - ret = usb_add_phy_dev(&mxs_phy->phy); - if (ret) - return ret; - - return 0; + return usb_add_phy_dev(&mxs_phy->phy); } static int mxs_phy_remove(struct platform_device *pdev) -- cgit v1.2.3 From c5673f5ce4c0faa97df419877bcdebbd76d43151 Mon Sep 17 00:00:00 2001 From: Saurabh Karajgaonkar Date: Tue, 4 Aug 2015 14:02:03 +0000 Subject: usb: phy: phy-keystone: Simplify return statement Replace redundant variable use in return statement. Signed-off-by: Saurabh Karajgaonkar Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-keystone.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/phy/phy-keystone.c b/drivers/usb/phy/phy-keystone.c index e0556f7832b5..01d4e4cdbc79 100644 --- a/drivers/usb/phy/phy-keystone.c +++ b/drivers/usb/phy/phy-keystone.c @@ -96,11 +96,7 @@ static int keystone_usbphy_probe(struct platform_device *pdev) platform_set_drvdata(pdev, k_phy); - ret = usb_add_phy_dev(&k_phy->usb_phy_gen.phy); - if (ret) - return ret; - - return 0; + return usb_add_phy_dev(&k_phy->usb_phy_gen.phy); } static int keystone_usbphy_remove(struct platform_device *pdev) -- cgit v1.2.3 From 7f352964852ede9e95d18fd3825c5200fb48b3a5 Mon Sep 17 00:00:00 2001 From: Saurabh Karajgaonkar Date: Tue, 4 Aug 2015 14:02:28 +0000 Subject: usb: musb: musb_dsps: Simplify return statement Replace redundant variable use in return statement. Signed-off-by: Saurabh Karajgaonkar Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_dsps.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 1334a3de31b8..a0cfead6150f 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -482,11 +482,7 @@ static int dsps_musb_init(struct musb *musb) dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val); } - ret = dsps_musb_dbg_init(musb, glue); - if (ret) - return ret; - - return 0; + return dsps_musb_dbg_init(musb, glue); } static int dsps_musb_exit(struct musb *musb) -- cgit v1.2.3 From 0f4315a8f1a73f130bbc5dde134b704ea6dda56c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 4 Aug 2015 11:02:45 -0500 Subject: usb: gadget: f_uac2: fix build warning commit 913e4a90b6f9 ("usb: gadget: f_uac2: finalize wMaxPacketSize according to bandwidth") added a possible build warning when calling min(). In order to fix the warning, we just make sure to call min_t() and tell that its arguments should be u16. Cc: Peter Chen Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_uac2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index b5680246d6aa..c35a2a1157d5 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -994,7 +994,7 @@ static void set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts, max_packet_size = num_channels(chmask) * ssize * DIV_ROUND_UP(srate, factor / (1 << (ep_desc->bInterval - 1))); - ep_desc->wMaxPacketSize = cpu_to_le16(min(max_packet_size, + ep_desc->wMaxPacketSize = cpu_to_le16(min_t(u16, max_packet_size, le16_to_cpu(ep_desc->wMaxPacketSize))); } -- cgit v1.2.3 From cc476b42a39d5a66d94f46cade972dcb8ee278df Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:13 +0200 Subject: usb: gadget: encapsulate endpoint claiming mechanism So far it was necessary for usb functions to set ep->driver_data in endpoint obtained from autoconfig to non-null value, to indicate that endpoint is claimed by function (in autoconfig it was checked if endpoint has set this field to non-null value, and if it has, it was assumed that it is claimed). It could cause bugs because if some function doesn't set this field autoconfig could return the same endpoint more than one time. To help to avoid such bugs this patch adds claimed flag to struct usb_ep, and encapsulates endpoint claiming mechanism inside usb_ep_autoconfig_ss() and usb_ep_autoconfig_reset(), so now usb functions don't need to perform any additional actions to mark endpoint obtained from autoconfig as claimed. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/epautoconf.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 919cdfdda78b..8e00ca765549 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -53,7 +53,7 @@ ep_matches ( int num_req_streams = 0; /* endpoint already claimed? */ - if (NULL != ep->driver_data) + if (ep->claimed) return 0; /* only support ep0 for portable CONTROL traffic */ @@ -240,7 +240,7 @@ find_ep (struct usb_gadget *gadget, const char *name) * updated with the assigned number of streams if it is * different from the original value. To prevent the endpoint * from being returned by a later autoconfig call, claim it by - * assigning ep->driver_data to some non-null value. + * assigning ep->claimed to true. * * On failure, this returns a null endpoint descriptor. */ @@ -323,6 +323,7 @@ struct usb_ep *usb_ep_autoconfig_ss( found_ep: ep->desc = NULL; ep->comp_desc = NULL; + ep->claimed = true; return ep; } EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss); @@ -354,7 +355,7 @@ EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss); * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value * is initialized as if the endpoint were used at full speed. To prevent * the endpoint from being returned by a later autoconfig call, claim it - * by assigning ep->driver_data to some non-null value. + * by assigning ep->claimed to true. * * On failure, this returns a null endpoint descriptor. */ @@ -373,7 +374,7 @@ EXPORT_SYMBOL_GPL(usb_ep_autoconfig); * * Use this for devices where one configuration may need to assign * endpoint resources very differently from the next one. It clears - * state such as ep->driver_data and the record of assigned endpoints + * state such as ep->claimed and the record of assigned endpoints * used by usb_ep_autoconfig(). */ void usb_ep_autoconfig_reset (struct usb_gadget *gadget) @@ -381,7 +382,7 @@ void usb_ep_autoconfig_reset (struct usb_gadget *gadget) struct usb_ep *ep; list_for_each_entry (ep, &gadget->ep_list, ep_list) { - ep->driver_data = NULL; + ep->claimed = false; } gadget->in_epnum = 0; gadget->out_epnum = 0; -- cgit v1.2.3 From a7e3f1410855db6b67ec29a386e74be2df3cc311 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:17 +0200 Subject: usb: chipidea: udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/chipidea/udc.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index f5fbe78e8e6a..c592b6f0fe21 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1624,6 +1624,20 @@ static int init_eps(struct ci_hdrc *ci) hwep->ep.name = hwep->name; hwep->ep.ops = &usb_ep_ops; + + if (i == 0) { + hwep->ep.caps.type_control = true; + } else { + hwep->ep.caps.type_iso = true; + hwep->ep.caps.type_bulk = true; + hwep->ep.caps.type_int = true; + } + + if (j == TX) + hwep->ep.caps.dir_in = true; + else + hwep->ep.caps.dir_out = true; + /* * for ep0: maxP defined in desc, for other * eps, maxP is set by epautoconfig() called -- cgit v1.2.3 From 2954522f135246287c36524bc96e9dae8c40f8a9 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:18 +0200 Subject: usb: dwc2: gadget: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 731b13dfc512..3ee5b4c77a1f 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -3289,6 +3289,19 @@ static void s3c_hsotg_initep(struct dwc2_hsotg *hsotg, usb_ep_set_maxpacket_limit(&hs_ep->ep, epnum ? 1024 : EP0_MPS_LIMIT); hs_ep->ep.ops = &s3c_hsotg_ep_ops; + if (epnum == 0) { + hs_ep->ep.caps.type_control = true; + } else { + hs_ep->ep.caps.type_iso = true; + hs_ep->ep.caps.type_bulk = true; + hs_ep->ep.caps.type_int = true; + } + + if (dir_in) + hs_ep->ep.caps.dir_in = true; + else + hs_ep->ep.caps.dir_out = true; + /* * if we're using dma, we need to set the next-endpoint pointer * to be something valid. -- cgit v1.2.3 From a474d3b73ba7f22844e672ac004f01cd9b8be159 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:19 +0200 Subject: usb: dwc3: gadget: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 2feed9e03583..0c25704dcb6b 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1715,6 +1715,17 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, return ret; } + if (epnum == 0 || epnum == 1) { + dep->endpoint.caps.type_control = true; + } else { + dep->endpoint.caps.type_iso = true; + dep->endpoint.caps.type_bulk = true; + dep->endpoint.caps.type_int = true; + } + + dep->endpoint.caps.dir_in = !!direction; + dep->endpoint.caps.dir_out = !direction; + INIT_LIST_HEAD(&dep->request_list); INIT_LIST_HEAD(&dep->req_queued); } -- cgit v1.2.3 From 6f02ac5ac9bba538593e4359dd5e83c4d42822fe Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:20 +0200 Subject: usb: gadget: amd5536udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/amd5536udc.c | 88 ++++++++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 10 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/amd5536udc.c b/drivers/usb/gadget/udc/amd5536udc.c index de7e5e2ccf1c..fdacddb18c00 100644 --- a/drivers/usb/gadget/udc/amd5536udc.c +++ b/drivers/usb/gadget/udc/amd5536udc.c @@ -138,15 +138,82 @@ static DECLARE_TASKLET(disconnect_tasklet, udc_tasklet_disconnect, /* endpoint names used for print */ static const char ep0_string[] = "ep0in"; -static const char *const ep_string[] = { - ep0_string, - "ep1in-int", "ep2in-bulk", "ep3in-bulk", "ep4in-bulk", "ep5in-bulk", - "ep6in-bulk", "ep7in-bulk", "ep8in-bulk", "ep9in-bulk", "ep10in-bulk", - "ep11in-bulk", "ep12in-bulk", "ep13in-bulk", "ep14in-bulk", - "ep15in-bulk", "ep0out", "ep1out-bulk", "ep2out-bulk", "ep3out-bulk", - "ep4out-bulk", "ep5out-bulk", "ep6out-bulk", "ep7out-bulk", - "ep8out-bulk", "ep9out-bulk", "ep10out-bulk", "ep11out-bulk", - "ep12out-bulk", "ep13out-bulk", "ep14out-bulk", "ep15out-bulk" +static const struct { + const char *name; + const struct usb_ep_caps caps; +} ep_info[] = { +#define EP_INFO(_name, _caps) \ + { \ + .name = _name, \ + .caps = _caps, \ + } + + EP_INFO(ep0_string, + USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep1in-int", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep2in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep3in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep4in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep5in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep6in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep7in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep8in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep9in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep10in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep11in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep12in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep13in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep14in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep15in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep0out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep1out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep2out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep3out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep4out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep5out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep6out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep7out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep8out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep9out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep10out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep11out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep12out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep13out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep14out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep15out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + +#undef EP_INFO }; /* DMA usage flag */ @@ -1517,7 +1584,8 @@ static void udc_setup_endpoints(struct udc *dev) for (tmp = 0; tmp < UDC_EP_NUM; tmp++) { ep = &dev->ep[tmp]; ep->dev = dev; - ep->ep.name = ep_string[tmp]; + ep->ep.name = ep_info[tmp].name; + ep->ep.caps = ep_info[tmp].caps; ep->num = tmp; /* txfifo size is calculated at enable time */ ep->txfifo = dev->txfifo; -- cgit v1.2.3 From b9ed96d7d579416a8fd2e1cef66541bfdad2720f Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:21 +0200 Subject: usb: gadget: at91_udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/at91_udc.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c index 32f50a7944dd..d0d18947f58b 100644 --- a/drivers/usb/gadget/udc/at91_udc.c +++ b/drivers/usb/gadget/udc/at91_udc.c @@ -59,15 +59,34 @@ #define DRIVER_VERSION "3 May 2006" static const char driver_name [] = "at91_udc"; -static const char * const ep_names[] = { - "ep0", - "ep1", - "ep2", - "ep3-int", - "ep4", - "ep5", + +static const struct { + const char *name; + const struct usb_ep_caps caps; +} ep_info[] = { +#define EP_INFO(_name, _caps) \ + { \ + .name = _name, \ + .caps = _caps, \ + } + + EP_INFO("ep0", + USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep1", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep2", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep3-int", + USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep4", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep5", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + +#undef EP_INFO }; -#define ep0name ep_names[0] + +#define ep0name ep_info[0].name #define VBUS_POLL_TIMEOUT msecs_to_jiffies(1000) @@ -1831,7 +1850,8 @@ static int at91udc_probe(struct platform_device *pdev) for (i = 0; i < NUM_ENDPOINTS; i++) { ep = &udc->ep[i]; - ep->ep.name = ep_names[i]; + ep->ep.name = ep_info[i].name; + ep->ep.caps = ep_info[i].caps; ep->ep.ops = &at91_ep_ops; ep->udc = udc; ep->int_mask = BIT(i); -- cgit v1.2.3 From 1b0ba527702268992a62227dde4911477f057ca5 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:22 +0200 Subject: usb: gadget: bcm63xx_udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/bcm63xx_udc.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/bcm63xx_udc.c b/drivers/usb/gadget/udc/bcm63xx_udc.c index 9db968ba39f5..8cbb00325824 100644 --- a/drivers/usb/gadget/udc/bcm63xx_udc.c +++ b/drivers/usb/gadget/udc/bcm63xx_udc.c @@ -44,9 +44,29 @@ #define DRV_MODULE_NAME "bcm63xx_udc" static const char bcm63xx_ep0name[] = "ep0"; -static const char *const bcm63xx_ep_name[] = { - bcm63xx_ep0name, - "ep1in-bulk", "ep2out-bulk", "ep3in-int", "ep4out-int", + +static const struct { + const char *name; + const struct usb_ep_caps caps; +} bcm63xx_ep_info[] = { +#define EP_INFO(_name, _caps) \ + { \ + .name = _name, \ + .caps = _caps, \ + } + + EP_INFO(bcm63xx_ep0name, + USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep1in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep2out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep3in-int", + USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep4out-int", + USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_OUT)), + +#undef EP_INFO }; static bool use_fullspeed; @@ -943,7 +963,8 @@ static int bcm63xx_init_udc_hw(struct bcm63xx_udc *udc) for (i = 0; i < BCM63XX_NUM_EP; i++) { struct bcm63xx_ep *bep = &udc->bep[i]; - bep->ep.name = bcm63xx_ep_name[i]; + bep->ep.name = bcm63xx_ep_info[i].name; + bep->ep.caps = bcm63xx_ep_info[i].caps; bep->ep_num = i; bep->ep.ops = &bcm63xx_udc_ep_ops; list_add_tail(&bep->ep.ep_list, &udc->gadget.ep_list); -- cgit v1.2.3 From b079dd6156a6544e0383642a9ec97d17485aa244 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:23 +0200 Subject: usb: gadget: bdc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/bdc/bdc_ep.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/bdc/bdc_ep.c b/drivers/usb/gadget/udc/bdc/bdc_ep.c index b04980cf6dc4..f9a8f57620e2 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_ep.c +++ b/drivers/usb/gadget/udc/bdc/bdc_ep.c @@ -1952,12 +1952,18 @@ static int init_ep(struct bdc *bdc, u32 epnum, u32 dir) ep->bdc = bdc; ep->dir = dir; + if (dir) + ep->usb_ep.caps.dir_in = true; + else + ep->usb_ep.caps.dir_out = true; + /* ep->ep_num is the index inside bdc_ep */ if (epnum == 1) { ep->ep_num = 1; bdc->bdc_ep_array[ep->ep_num] = ep; snprintf(ep->name, sizeof(ep->name), "ep%d", epnum - 1); usb_ep_set_maxpacket_limit(&ep->usb_ep, EP0_MAX_PKT_SIZE); + ep->usb_ep.caps.type_control = true; ep->comp_desc = NULL; bdc->gadget.ep0 = &ep->usb_ep; } else { @@ -1971,6 +1977,9 @@ static int init_ep(struct bdc *bdc, u32 epnum, u32 dir) dir & 1 ? "in" : "out"); usb_ep_set_maxpacket_limit(&ep->usb_ep, 1024); + ep->usb_ep.caps.type_iso = true; + ep->usb_ep.caps.type_bulk = true; + ep->usb_ep.caps.type_int = true; ep->usb_ep.max_streams = 0; list_add_tail(&ep->usb_ep.ep_list, &bdc->gadget.ep_list); } -- cgit v1.2.3 From 7a3b8e7098946b44c014f3df0ceef27fb273c142 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:24 +0200 Subject: usb: gadget: dummy-hcd: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/dummy_hcd.c | 95 ++++++++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 15 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index 181112c88f43..1379ad40d864 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c @@ -127,23 +127,87 @@ static inline struct dummy_request *usb_request_to_dummy_request static const char ep0name[] = "ep0"; -static const char *const ep_name[] = { - ep0name, /* everyone has ep0 */ +static const struct { + const char *name; + const struct usb_ep_caps caps; +} ep_info[] = { +#define EP_INFO(_name, _caps) \ + { \ + .name = _name, \ + .caps = _caps, \ + } + /* everyone has ep0 */ + EP_INFO(ep0name, + USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)), /* act like a pxa250: fifteen fixed function endpoints */ - "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int", - "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int", - "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso", - "ep15in-int", - + EP_INFO("ep1in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep2out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep3in-iso", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep4out-iso", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep5in-int", + USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep6in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep7out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep8in-iso", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep9out-iso", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep10in-int", + USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep11in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep12out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep13in-iso", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep14out-iso", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep15in-int", + USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)), /* or like sa1100: two fixed function endpoints */ - "ep1out-bulk", "ep2in-bulk", - + EP_INFO("ep1out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep2in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), /* and now some generic EPs so we have enough in multi config */ - "ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in", - "ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out", + EP_INFO("ep3out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep4in", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep5out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep6out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep7in", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep8out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep9in", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep10out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep11out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep12in", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep13out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep14in", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep15out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + +#undef EP_INFO }; -#define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name) + +#define DUMMY_ENDPOINTS ARRAY_SIZE(ep_info) /*-------------------------------------------------------------------------*/ @@ -938,9 +1002,10 @@ static void init_dummy_udc_hw(struct dummy *dum) for (i = 0; i < DUMMY_ENDPOINTS; i++) { struct dummy_ep *ep = &dum->ep[i]; - if (!ep_name[i]) + if (!ep_info[i].name) break; - ep->ep.name = ep_name[i]; + ep->ep.name = ep_info[i].name; + ep->ep.caps = ep_info[i].caps; ep->ep.ops = &dummy_ep_ops; list_add_tail(&ep->ep.ep_list, &dum->gadget.ep_list); ep->halted = ep->wedged = ep->already_seen = @@ -1684,7 +1749,7 @@ static void dummy_timer(unsigned long _dum_hcd) } for (i = 0; i < DUMMY_ENDPOINTS; i++) { - if (!ep_name[i]) + if (!ep_info[i].name) break; dum->ep[i].already_seen = 0; } -- cgit v1.2.3 From 8d29237a436dc8e2b5c44dd0ca662a680f16deb5 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:25 +0200 Subject: usb: gadget: fotg210-udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/fotg210-udc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c index a99ed6d80e9a..6ba122cc7490 100644 --- a/drivers/usb/gadget/udc/fotg210-udc.c +++ b/drivers/usb/gadget/udc/fotg210-udc.c @@ -1143,6 +1143,17 @@ static int fotg210_udc_probe(struct platform_device *pdev) ep->ep.name = fotg210_ep_name[i]; ep->ep.ops = &fotg210_ep_ops; usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0); + + if (i == 0) { + ep->ep.caps.type_control = true; + } else { + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + } + + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; } usb_ep_set_maxpacket_limit(&fotg210->ep[0]->ep, 0x40); fotg210->gadget.ep0 = &fotg210->ep[0]->ep; -- cgit v1.2.3 From e8fc42f6a19af320d7a4718c05c3f249bf5d3151 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:26 +0200 Subject: usb: gadget: fsl_qe_udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/fsl_qe_udc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c index e0822f1b6639..5fb6f8b4f0b4 100644 --- a/drivers/usb/gadget/udc/fsl_qe_udc.c +++ b/drivers/usb/gadget/udc/fsl_qe_udc.c @@ -2417,6 +2417,17 @@ static int qe_ep_config(struct qe_udc *udc, unsigned char pipe_num) strcpy(ep->name, ep_name[pipe_num]); ep->ep.name = ep_name[pipe_num]; + if (pipe_num == 0) { + ep->ep.caps.type_control = true; + } else { + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + } + + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; + ep->ep.ops = &qe_ep_ops; ep->stopped = 1; usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0); -- cgit v1.2.3 From 60a28c63712f190b45e9d8f0ca593c927970fd51 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:27 +0200 Subject: usb: gadget: fsl_udc_core: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/fsl_udc_core.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index c60022b46a48..aab5221d6c2e 100644 --- a/drivers/usb/gadget/udc/fsl_udc_core.c +++ b/drivers/usb/gadget/udc/fsl_udc_core.c @@ -2313,6 +2313,19 @@ static int struct_ep_setup(struct fsl_udc *udc, unsigned char index, ep->ep.ops = &fsl_ep_ops; ep->stopped = 0; + if (index == 0) { + ep->ep.caps.type_control = true; + } else { + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + } + + if (index & 1) + ep->ep.caps.dir_in = true; + else + ep->ep.caps.dir_out = true; + /* for ep0: maxP defined in desc * for other eps, maxP is set by epautoconfig() called by gadget layer */ -- cgit v1.2.3 From 455d11c93582c4167f55af0969b83821450be120 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:28 +0200 Subject: usb: gadget: fusb300_udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/fusb300_udc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/fusb300_udc.c b/drivers/usb/gadget/udc/fusb300_udc.c index 3970f453de49..948845c90e47 100644 --- a/drivers/usb/gadget/udc/fusb300_udc.c +++ b/drivers/usb/gadget/udc/fusb300_udc.c @@ -1450,6 +1450,17 @@ static int fusb300_probe(struct platform_device *pdev) ep->ep.name = fusb300_ep_name[i]; ep->ep.ops = &fusb300_ep_ops; usb_ep_set_maxpacket_limit(&ep->ep, HS_BULK_MAX_PACKET_SIZE); + + if (i == 0) { + ep->ep.caps.type_control = true; + } else { + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + } + + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; } usb_ep_set_maxpacket_limit(&fusb300->ep[0]->ep, HS_CTL_MAX_PACKET_SIZE); fusb300->ep[0]->epnum = 0; -- cgit v1.2.3 From b0bf5fbfbd30ffbb9e45169f78412f0596e16412 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:29 +0200 Subject: usb: gadget: goku_udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/goku_udc.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/goku_udc.c b/drivers/usb/gadget/udc/goku_udc.c index 9e8d842e8c08..46b8d14998cf 100644 --- a/drivers/usb/gadget/udc/goku_udc.c +++ b/drivers/usb/gadget/udc/goku_udc.c @@ -1257,6 +1257,14 @@ static void udc_reinit (struct goku_udc *dev) INIT_LIST_HEAD (&ep->queue); ep_reset(NULL, ep); + + if (i == 0) + ep->ep.caps.type_control = true; + else + ep->ep.caps.type_bulk = true; + + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; } dev->ep[0].reg_mode = NULL; -- cgit v1.2.3 From 892269925991b449ae47dcc0debb324ae451022e Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:30 +0200 Subject: usb: gadget: gr_udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/gr_udc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/gr_udc.c b/drivers/usb/gadget/udc/gr_udc.c index c8868870e217..8aa2593c2c36 100644 --- a/drivers/usb/gadget/udc/gr_udc.c +++ b/drivers/usb/gadget/udc/gr_udc.c @@ -2018,12 +2018,23 @@ static int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit) usb_ep_set_maxpacket_limit(&ep->ep, MAX_CTRL_PL_SIZE); ep->bytes_per_buffer = MAX_CTRL_PL_SIZE; + + ep->ep.caps.type_control = true; } else { usb_ep_set_maxpacket_limit(&ep->ep, (u16)maxplimit); list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list); + + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; } list_add_tail(&ep->ep_list, &dev->ep_list); + if (is_in) + ep->ep.caps.dir_in = true; + else + ep->ep.caps.dir_out = true; + ep->tailbuf = dma_alloc_coherent(dev->dev, ep->ep.maxpacket_limit, &ep->tailbuf_paddr, GFP_ATOMIC); if (!ep->tailbuf) -- cgit v1.2.3 From 4d75c8bd613c5ba99ee02cfe38610c82e7fe8362 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:31 +0200 Subject: usb: gadget: lpc32xx_udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/lpc32xx_udc.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c index 3b6a7852822d..00b5006baf15 100644 --- a/drivers/usb/gadget/udc/lpc32xx_udc.c +++ b/drivers/usb/gadget/udc/lpc32xx_udc.c @@ -2575,6 +2575,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep0", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 0, @@ -2586,6 +2588,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep1-int", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 2, @@ -2597,6 +2601,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep2-bulk", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 4, @@ -2608,6 +2614,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep3-iso", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 1023, .hwep_num_base = 6, @@ -2619,6 +2627,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep4-int", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 8, @@ -2630,6 +2640,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep5-bulk", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 10, @@ -2641,6 +2653,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep6-iso", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 1023, .hwep_num_base = 12, @@ -2652,6 +2666,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep7-int", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 14, @@ -2663,6 +2679,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep8-bulk", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 16, @@ -2674,6 +2692,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep9-iso", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 1023, .hwep_num_base = 18, @@ -2685,6 +2705,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep10-int", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 20, @@ -2696,6 +2718,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep11-bulk", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 22, @@ -2707,6 +2731,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep12-iso", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 1023, .hwep_num_base = 24, @@ -2718,6 +2744,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep13-int", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 26, @@ -2729,6 +2757,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep14-bulk", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 28, @@ -2740,6 +2770,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep15-bulk", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 1023, .hwep_num_base = 30, -- cgit v1.2.3 From 8ddbf94fd5b536b3adf5ffa631c5951718e7301d Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:32 +0200 Subject: usb: gadget: m66592-udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/m66592-udc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/m66592-udc.c b/drivers/usb/gadget/udc/m66592-udc.c index 9704053dfe05..b1cfa96cc88f 100644 --- a/drivers/usb/gadget/udc/m66592-udc.c +++ b/drivers/usb/gadget/udc/m66592-udc.c @@ -1644,6 +1644,17 @@ static int m66592_probe(struct platform_device *pdev) ep->ep.name = m66592_ep_name[i]; ep->ep.ops = &m66592_ep_ops; usb_ep_set_maxpacket_limit(&ep->ep, 512); + + if (i == 0) { + ep->ep.caps.type_control = true; + } else { + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + } + + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; } usb_ep_set_maxpacket_limit(&m66592->ep[0].ep, 64); m66592->ep[0].pipenum = 0; -- cgit v1.2.3 From c12a30629f8b5fe8c2aba42c3128df702bbc9e83 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:33 +0200 Subject: usb: gadget: mv_u3d_core: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/mv_u3d_core.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/mv_u3d_core.c b/drivers/usb/gadget/udc/mv_u3d_core.c index ea35a248c898..4c489692745e 100644 --- a/drivers/usb/gadget/udc/mv_u3d_core.c +++ b/drivers/usb/gadget/udc/mv_u3d_core.c @@ -1324,6 +1324,9 @@ static int mv_u3d_eps_init(struct mv_u3d *u3d) ep->ep.ops = &mv_u3d_ep_ops; ep->wedge = 0; usb_ep_set_maxpacket_limit(&ep->ep, MV_U3D_EP0_MAX_PKT_SIZE); + ep->ep.caps.type_control = true; + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; ep->ep_num = 0; ep->ep.desc = &mv_u3d_ep0_desc; INIT_LIST_HEAD(&ep->queue); @@ -1339,14 +1342,20 @@ static int mv_u3d_eps_init(struct mv_u3d *u3d) if (i & 1) { snprintf(name, sizeof(name), "ep%din", i >> 1); ep->direction = MV_U3D_EP_DIR_IN; + ep->ep.caps.dir_in = true; } else { snprintf(name, sizeof(name), "ep%dout", i >> 1); ep->direction = MV_U3D_EP_DIR_OUT; + ep->ep.caps.dir_out = true; } ep->u3d = u3d; strncpy(ep->name, name, sizeof(ep->name)); ep->ep.name = ep->name; + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + ep->ep.ops = &mv_u3d_ep_ops; usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0); ep->ep_num = i / 2; -- cgit v1.2.3 From 43710a8dba9ae607decdeaf7a56a51dd5b42184e Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:34 +0200 Subject: usb: gadget: mv_udc_core: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/mv_udc_core.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c index 5da37c957b53..339af51df57d 100644 --- a/drivers/usb/gadget/udc/mv_udc_core.c +++ b/drivers/usb/gadget/udc/mv_udc_core.c @@ -1257,6 +1257,9 @@ static int eps_init(struct mv_udc *udc) ep->wedge = 0; ep->stopped = 0; usb_ep_set_maxpacket_limit(&ep->ep, EP0_MAX_PKT_SIZE); + ep->ep.caps.type_control = true; + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; ep->ep_num = 0; ep->ep.desc = &mv_ep0_desc; INIT_LIST_HEAD(&ep->queue); @@ -1269,14 +1272,20 @@ static int eps_init(struct mv_udc *udc) if (i % 2) { snprintf(name, sizeof(name), "ep%din", i / 2); ep->direction = EP_DIR_IN; + ep->ep.caps.dir_in = true; } else { snprintf(name, sizeof(name), "ep%dout", i / 2); ep->direction = EP_DIR_OUT; + ep->ep.caps.dir_out = true; } ep->udc = udc; strncpy(ep->name, name, sizeof(ep->name)); ep->ep.name = ep->name; + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + ep->ep.ops = &mv_ep_ops; ep->stopped = 0; usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0); -- cgit v1.2.3 From f95aec51da16250841a4254db36f9771446cdbb6 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:35 +0200 Subject: usb: gadget: net2272: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/net2272.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c index c2ed5daebb75..18f5ebd447b8 100644 --- a/drivers/usb/gadget/udc/net2272.c +++ b/drivers/usb/gadget/udc/net2272.c @@ -1404,6 +1404,17 @@ net2272_usb_reinit(struct net2272 *dev) else ep->fifo_size = 64; net2272_ep_reset(ep); + + if (i == 0) { + ep->ep.caps.type_control = true; + } else { + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + } + + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; } usb_ep_set_maxpacket_limit(&dev->ep[0].ep, 64); -- cgit v1.2.3 From c23c3c3c3059f3dc47268cd7a28b96b9efdbc1ea Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:36 +0200 Subject: usb: gadget: net2280: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/net2280.c | 67 +++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 12 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c index 2bee912ca65b..872ca257cfa4 100644 --- a/drivers/usb/gadget/udc/net2280.c +++ b/drivers/usb/gadget/udc/net2280.c @@ -74,19 +74,58 @@ static const char driver_desc[] = DRIVER_DESC; static const u32 ep_bit[9] = { 0, 17, 2, 19, 4, 1, 18, 3, 20 }; static const char ep0name[] = "ep0"; -static const char *const ep_name[] = { - ep0name, - "ep-a", "ep-b", "ep-c", "ep-d", - "ep-e", "ep-f", "ep-g", "ep-h", -}; -/* Endpoint names for usb3380 advance mode */ -static const char *const ep_name_adv[] = { - ep0name, - "ep1in", "ep2out", "ep3in", "ep4out", - "ep1out", "ep2in", "ep3out", "ep4in", +#define EP_INFO(_name, _caps) \ + { \ + .name = _name, \ + .caps = _caps, \ + } + +static const struct { + const char *name; + const struct usb_ep_caps caps; +} ep_info_dft[] = { /* Default endpoint configuration */ + EP_INFO(ep0name, + USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep-a", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep-b", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep-c", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep-d", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep-e", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep-f", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep-g", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep-h", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), +}, ep_info_adv[] = { /* Endpoints for usb3380 advance mode */ + EP_INFO(ep0name, + USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep1in", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep2out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep3in", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep4out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep1out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep2in", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep3out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep4in", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), }; +#undef EP_INFO + /* mode 0 == ep-{a,b,c,d} 1K fifo each * mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable * mode 2 == ep-a 2K fifo, ep-{b,c} 1K each, ep-d unavailable @@ -2055,7 +2094,8 @@ static void usb_reinit_228x(struct net2280 *dev) for (tmp = 0; tmp < 7; tmp++) { struct net2280_ep *ep = &dev->ep[tmp]; - ep->ep.name = ep_name[tmp]; + ep->ep.name = ep_info_dft[tmp].name; + ep->ep.caps = ep_info_dft[tmp].caps; ep->dev = dev; ep->num = tmp; @@ -2095,7 +2135,10 @@ static void usb_reinit_338x(struct net2280 *dev) for (i = 0; i < dev->n_ep; i++) { struct net2280_ep *ep = &dev->ep[i]; - ep->ep.name = dev->enhanced_mode ? ep_name_adv[i] : ep_name[i]; + ep->ep.name = dev->enhanced_mode ? ep_info_adv[i].name : + ep_info_dft[i].name; + ep->ep.caps = dev->enhanced_mode ? ep_info_adv[i].caps : + ep_info_dft[i].caps; ep->dev = dev; ep->num = i; -- cgit v1.2.3 From 7d4ba80d3a91222de577b652a8936f935de8b409 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:37 +0200 Subject: usb: gadget: omap_udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/omap_udc.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c index e2fcdb8e5596..9b7d39484ed3 100644 --- a/drivers/usb/gadget/udc/omap_udc.c +++ b/drivers/usb/gadget/udc/omap_udc.c @@ -2579,6 +2579,28 @@ omap_ep_setup(char *name, u8 addr, u8 type, ep->double_buf = dbuf; ep->udc = udc; + switch (type) { + case USB_ENDPOINT_XFER_CONTROL: + ep->ep.caps.type_control = true; + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; + break; + case USB_ENDPOINT_XFER_ISOC: + ep->ep.caps.type_iso = true; + break; + case USB_ENDPOINT_XFER_BULK: + ep->ep.caps.type_bulk = true; + break; + case USB_ENDPOINT_XFER_INT: + ep->ep.caps.type_int = true; + break; + }; + + if (addr & USB_DIR_IN) + ep->ep.caps.dir_in = true; + else + ep->ep.caps.dir_out = true; + ep->ep.name = ep->name; ep->ep.ops = &omap_ep_ops; ep->maxpacket = maxp; -- cgit v1.2.3 From 85a4ed003b39f70ba478e613a9be2c334f1079e7 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:38 +0200 Subject: usb: gadget: pch_udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/pch_udc.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c index e071c62d7f24..e5f4c5274298 100644 --- a/drivers/usb/gadget/udc/pch_udc.c +++ b/drivers/usb/gadget/udc/pch_udc.c @@ -2895,11 +2895,21 @@ static void pch_udc_pcd_reinit(struct pch_udc_dev *dev) ep->in = ~i & 1; ep->ep.name = ep_string[i]; ep->ep.ops = &pch_udc_ep_ops; - if (ep->in) + if (ep->in) { ep->offset_addr = ep->num * UDC_EP_REG_SHIFT; - else + ep->ep.caps.dir_in = true; + } else { ep->offset_addr = (UDC_EPINT_OUT_SHIFT + ep->num) * UDC_EP_REG_SHIFT; + ep->ep.caps.dir_out = true; + } + if (i == UDC_EP0IN_IDX || i == UDC_EP0OUT_IDX) { + ep->ep.caps.type_control = true; + } else { + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + } /* need to set ep->ep.maxpacket and set Default Configuration?*/ usb_ep_set_maxpacket_limit(&ep->ep, UDC_BULK_MAX_PKT_SIZE); list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list); -- cgit v1.2.3 From 36411b6b042d350a43fe1e0d3ce78fbda30f4f02 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:39 +0200 Subject: usb: gadget: pxa25x_udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/pxa25x_udc.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c index 27f944231477..b4d25dc4cb72 100644 --- a/drivers/usb/gadget/udc/pxa25x_udc.c +++ b/drivers/usb/gadget/udc/pxa25x_udc.c @@ -1822,6 +1822,8 @@ static struct pxa25x_udc memory = { .name = ep0name, .ops = &pxa25x_ep_ops, .maxpacket = EP0_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, + USB_EP_CAPS_DIR_ALL), }, .dev = &memory, .reg_udccs = &UDCCS0, @@ -1834,6 +1836,8 @@ static struct pxa25x_udc memory = { .name = "ep1in-bulk", .ops = &pxa25x_ep_ops, .maxpacket = BULK_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_IN), }, .dev = &memory, .fifo_size = BULK_FIFO_SIZE, @@ -1847,6 +1851,8 @@ static struct pxa25x_udc memory = { .name = "ep2out-bulk", .ops = &pxa25x_ep_ops, .maxpacket = BULK_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_OUT), }, .dev = &memory, .fifo_size = BULK_FIFO_SIZE, @@ -1862,6 +1868,8 @@ static struct pxa25x_udc memory = { .name = "ep3in-iso", .ops = &pxa25x_ep_ops, .maxpacket = ISO_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_IN), }, .dev = &memory, .fifo_size = ISO_FIFO_SIZE, @@ -1875,6 +1883,8 @@ static struct pxa25x_udc memory = { .name = "ep4out-iso", .ops = &pxa25x_ep_ops, .maxpacket = ISO_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_OUT), }, .dev = &memory, .fifo_size = ISO_FIFO_SIZE, @@ -1889,6 +1899,8 @@ static struct pxa25x_udc memory = { .name = "ep5in-int", .ops = &pxa25x_ep_ops, .maxpacket = INT_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, + USB_EP_CAPS_DIR_IN), }, .dev = &memory, .fifo_size = INT_FIFO_SIZE, @@ -1904,6 +1916,8 @@ static struct pxa25x_udc memory = { .name = "ep6in-bulk", .ops = &pxa25x_ep_ops, .maxpacket = BULK_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_IN), }, .dev = &memory, .fifo_size = BULK_FIFO_SIZE, @@ -1917,6 +1931,8 @@ static struct pxa25x_udc memory = { .name = "ep7out-bulk", .ops = &pxa25x_ep_ops, .maxpacket = BULK_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_OUT), }, .dev = &memory, .fifo_size = BULK_FIFO_SIZE, @@ -1931,6 +1947,8 @@ static struct pxa25x_udc memory = { .name = "ep8in-iso", .ops = &pxa25x_ep_ops, .maxpacket = ISO_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_IN), }, .dev = &memory, .fifo_size = ISO_FIFO_SIZE, @@ -1944,6 +1962,8 @@ static struct pxa25x_udc memory = { .name = "ep9out-iso", .ops = &pxa25x_ep_ops, .maxpacket = ISO_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_OUT), }, .dev = &memory, .fifo_size = ISO_FIFO_SIZE, @@ -1958,6 +1978,8 @@ static struct pxa25x_udc memory = { .name = "ep10in-int", .ops = &pxa25x_ep_ops, .maxpacket = INT_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, + USB_EP_CAPS_DIR_IN), }, .dev = &memory, .fifo_size = INT_FIFO_SIZE, @@ -1973,6 +1995,8 @@ static struct pxa25x_udc memory = { .name = "ep11in-bulk", .ops = &pxa25x_ep_ops, .maxpacket = BULK_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_IN), }, .dev = &memory, .fifo_size = BULK_FIFO_SIZE, @@ -1986,6 +2010,8 @@ static struct pxa25x_udc memory = { .name = "ep12out-bulk", .ops = &pxa25x_ep_ops, .maxpacket = BULK_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_OUT), }, .dev = &memory, .fifo_size = BULK_FIFO_SIZE, @@ -2000,6 +2026,8 @@ static struct pxa25x_udc memory = { .name = "ep13in-iso", .ops = &pxa25x_ep_ops, .maxpacket = ISO_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_IN), }, .dev = &memory, .fifo_size = ISO_FIFO_SIZE, @@ -2013,6 +2041,8 @@ static struct pxa25x_udc memory = { .name = "ep14out-iso", .ops = &pxa25x_ep_ops, .maxpacket = ISO_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_OUT), }, .dev = &memory, .fifo_size = ISO_FIFO_SIZE, @@ -2027,6 +2057,8 @@ static struct pxa25x_udc memory = { .name = "ep15in-int", .ops = &pxa25x_ep_ops, .maxpacket = INT_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, + USB_EP_CAPS_DIR_IN), }, .dev = &memory, .fifo_size = INT_FIFO_SIZE, -- cgit v1.2.3 From a180e3da97a323510071b2b5e42b5dc07df239da Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:40 +0200 Subject: usb: gadget: pxa27x_udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/pxa27x_udc.h | 40 +++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 15 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/pxa27x_udc.h b/drivers/usb/gadget/udc/pxa27x_udc.h index 11e14232794b..cea2cb79b30c 100644 --- a/drivers/usb/gadget/udc/pxa27x_udc.h +++ b/drivers/usb/gadget/udc/pxa27x_udc.h @@ -234,25 +234,35 @@ /* * Endpoint definition helpers */ -#define USB_EP_DEF(addr, bname, dir, type, maxpkt) \ -{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, }, \ +#define USB_EP_DEF(addr, bname, dir, type, maxpkt, ctype, cdir) \ +{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, \ + .caps = USB_EP_CAPS(ctype, cdir), }, \ .desc = { .bEndpointAddress = addr | (dir ? USB_DIR_IN : 0), \ - .bmAttributes = type, \ + .bmAttributes = USB_ENDPOINT_XFER_ ## type, \ .wMaxPacketSize = maxpkt, }, \ .dev = &memory \ } -#define USB_EP_BULK(addr, bname, dir) \ - USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE) -#define USB_EP_ISO(addr, bname, dir) \ - USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE) -#define USB_EP_INT(addr, bname, dir) \ - USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE) -#define USB_EP_IN_BULK(n) USB_EP_BULK(n, "ep" #n "in-bulk", 1) -#define USB_EP_OUT_BULK(n) USB_EP_BULK(n, "ep" #n "out-bulk", 0) -#define USB_EP_IN_ISO(n) USB_EP_ISO(n, "ep" #n "in-iso", 1) -#define USB_EP_OUT_ISO(n) USB_EP_ISO(n, "ep" #n "out-iso", 0) -#define USB_EP_IN_INT(n) USB_EP_INT(n, "ep" #n "in-int", 1) -#define USB_EP_CTRL USB_EP_DEF(0, "ep0", 0, 0, EP0_FIFO_SIZE) +#define USB_EP_BULK(addr, bname, dir, cdir) \ + USB_EP_DEF(addr, bname, dir, BULK, BULK_FIFO_SIZE, \ + USB_EP_CAPS_TYPE_BULK, cdir) +#define USB_EP_ISO(addr, bname, dir, cdir) \ + USB_EP_DEF(addr, bname, dir, ISOC, ISO_FIFO_SIZE, \ + USB_EP_CAPS_TYPE_ISO, cdir) +#define USB_EP_INT(addr, bname, dir, cdir) \ + USB_EP_DEF(addr, bname, dir, INT, INT_FIFO_SIZE, \ + USB_EP_CAPS_TYPE_INT, cdir) +#define USB_EP_IN_BULK(n) USB_EP_BULK(n, "ep" #n "in-bulk", 1, \ + USB_EP_CAPS_DIR_IN) +#define USB_EP_OUT_BULK(n) USB_EP_BULK(n, "ep" #n "out-bulk", 0, \ + USB_EP_CAPS_DIR_OUT) +#define USB_EP_IN_ISO(n) USB_EP_ISO(n, "ep" #n "in-iso", 1, \ + USB_EP_CAPS_DIR_IN) +#define USB_EP_OUT_ISO(n) USB_EP_ISO(n, "ep" #n "out-iso", 0, \ + USB_EP_CAPS_DIR_OUT) +#define USB_EP_IN_INT(n) USB_EP_INT(n, "ep" #n "in-int", 1, \ + USB_EP_CAPS_DIR_IN) +#define USB_EP_CTRL USB_EP_DEF(0, "ep0", 0, CONTROL, EP0_FIFO_SIZE, \ + USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL) #define PXA_EP_DEF(_idx, _addr, dir, _type, maxpkt, _config, iface, altset) \ { \ -- cgit v1.2.3 From 0ec8026d7afee625f52631708d84435ea4735da6 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:41 +0200 Subject: usb: gadget: r8a66597-udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/r8a66597-udc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c index 0293f7169dee..baa0609a429d 100644 --- a/drivers/usb/gadget/udc/r8a66597-udc.c +++ b/drivers/usb/gadget/udc/r8a66597-udc.c @@ -1935,6 +1935,16 @@ static int r8a66597_probe(struct platform_device *pdev) ep->ep.name = r8a66597_ep_name[i]; ep->ep.ops = &r8a66597_ep_ops; usb_ep_set_maxpacket_limit(&ep->ep, 512); + + if (i == 0) { + ep->ep.caps.type_control = true; + } else { + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + } + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; } usb_ep_set_maxpacket_limit(&r8a66597->ep[0].ep, 64); r8a66597->ep[0].pipenum = 0; -- cgit v1.2.3 From bc1b9f300ae06c64fcd056fb959b3d709ad2ef33 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:42 +0200 Subject: usb: gadget: s3c-hsudc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/s3c-hsudc.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/s3c-hsudc.c b/drivers/usb/gadget/udc/s3c-hsudc.c index 85a712a03343..e9def42ce50d 100644 --- a/drivers/usb/gadget/udc/s3c-hsudc.c +++ b/drivers/usb/gadget/udc/s3c-hsudc.c @@ -1005,6 +1005,21 @@ static void s3c_hsudc_initep(struct s3c_hsudc *hsudc, hsep->stopped = 0; hsep->wedge = 0; + if (epnum == 0) { + hsep->ep.caps.type_control = true; + hsep->ep.caps.dir_in = true; + hsep->ep.caps.dir_out = true; + } else { + hsep->ep.caps.type_iso = true; + hsep->ep.caps.type_bulk = true; + hsep->ep.caps.type_int = true; + } + + if (epnum & 1) + hsep->ep.caps.dir_in = true; + else + hsep->ep.caps.dir_out = true; + set_index(hsudc, epnum); writel(hsep->ep.maxpacket, hsudc->regs + S3C_MPR); } -- cgit v1.2.3 From 0648772d51c0ff3949397cb0cbcf2435ee32c550 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:43 +0200 Subject: usb: gadget: s3c2410_udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/s3c2410_udc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c index 5d9aa81969b4..eb3571ee59e3 100644 --- a/drivers/usb/gadget/udc/s3c2410_udc.c +++ b/drivers/usb/gadget/udc/s3c2410_udc.c @@ -1691,6 +1691,8 @@ static struct s3c2410_udc memory = { .name = ep0name, .ops = &s3c2410_ep_ops, .maxpacket = EP0_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, + USB_EP_CAPS_DIR_ALL), }, .dev = &memory, }, @@ -1702,6 +1704,8 @@ static struct s3c2410_udc memory = { .name = "ep1-bulk", .ops = &s3c2410_ep_ops, .maxpacket = EP_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .dev = &memory, .fifo_size = EP_FIFO_SIZE, @@ -1714,6 +1718,8 @@ static struct s3c2410_udc memory = { .name = "ep2-bulk", .ops = &s3c2410_ep_ops, .maxpacket = EP_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .dev = &memory, .fifo_size = EP_FIFO_SIZE, @@ -1726,6 +1732,8 @@ static struct s3c2410_udc memory = { .name = "ep3-bulk", .ops = &s3c2410_ep_ops, .maxpacket = EP_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .dev = &memory, .fifo_size = EP_FIFO_SIZE, @@ -1738,6 +1746,8 @@ static struct s3c2410_udc memory = { .name = "ep4-bulk", .ops = &s3c2410_ep_ops, .maxpacket = EP_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .dev = &memory, .fifo_size = EP_FIFO_SIZE, -- cgit v1.2.3 From 927d9f77fe3d5f9261eeb465e2b60768e400ffc9 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:44 +0200 Subject: usb: gadget: udc-xilinx: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/udc-xilinx.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c index 1f24274477ab..1cbb0ac6b182 100644 --- a/drivers/usb/gadget/udc/udc-xilinx.c +++ b/drivers/usb/gadget/udc/udc-xilinx.c @@ -1317,12 +1317,21 @@ static void xudc_eps_init(struct xusb_udc *udc) snprintf(ep->name, EPNAME_SIZE, "ep%d", ep_number); ep->ep_usb.name = ep->name; ep->ep_usb.ops = &xusb_ep_ops; + + ep->ep_usb.caps.type_iso = true; + ep->ep_usb.caps.type_bulk = true; + ep->ep_usb.caps.type_int = true; } else { ep->ep_usb.name = ep0name; usb_ep_set_maxpacket_limit(&ep->ep_usb, EP0_MAX_PACKET); ep->ep_usb.ops = &xusb_ep0_ops; + + ep->ep_usb.caps.type_control = true; } + ep->ep_usb.caps.dir_in = true; + ep->ep_usb.caps.dir_out = true; + ep->udc = udc; ep->epnumber = ep_number; ep->desc = NULL; -- cgit v1.2.3 From eb4cbc19526d62657b838d6f0b694a000e5b4c81 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:45 +0200 Subject: usb: isp1760: udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/isp1760/isp1760-udc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/isp1760/isp1760-udc.c b/drivers/usb/isp1760/isp1760-udc.c index 3699962987b2..1c3d0fd658fa 100644 --- a/drivers/usb/isp1760/isp1760-udc.c +++ b/drivers/usb/isp1760/isp1760-udc.c @@ -1383,13 +1383,24 @@ static void isp1760_udc_init_eps(struct isp1760_udc *udc) */ if (ep_num == 0) { usb_ep_set_maxpacket_limit(&ep->ep, 64); + ep->ep.caps.type_control = true; + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; ep->maxpacket = 64; udc->gadget.ep0 = &ep->ep; } else { usb_ep_set_maxpacket_limit(&ep->ep, 512); + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; ep->maxpacket = 0; list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); } + + if (is_in) + ep->ep.caps.dir_in = true; + else + ep->ep.caps.dir_out = true; } } -- cgit v1.2.3 From 8501955e888662ca56775eec2eb804e7bc7fce0d Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:46 +0200 Subject: usb: musb: gadget: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 9e18178f1d45..4150bafe6bf5 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1729,6 +1729,7 @@ init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in) INIT_LIST_HEAD(&ep->end_point.ep_list); if (!epnum) { usb_ep_set_maxpacket_limit(&ep->end_point, 64); + ep->end_point.caps.type_control = true; ep->end_point.ops = &musb_g_ep0_ops; musb->g.ep0 = &ep->end_point; } else { @@ -1736,9 +1737,20 @@ init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in) usb_ep_set_maxpacket_limit(&ep->end_point, hw_ep->max_packet_sz_tx); else usb_ep_set_maxpacket_limit(&ep->end_point, hw_ep->max_packet_sz_rx); + ep->end_point.caps.type_iso = true; + ep->end_point.caps.type_bulk = true; + ep->end_point.caps.type_int = true; ep->end_point.ops = &musb_ep_ops; list_add_tail(&ep->end_point.ep_list, &musb->g.ep_list); } + + if (!epnum || hw_ep->is_shared_fifo) { + ep->end_point.caps.dir_in = true; + ep->end_point.caps.dir_out = true; + } else if (is_in) + ep->end_point.caps.dir_in = true; + else + ep->end_point.caps.dir_out = true; } /* -- cgit v1.2.3 From 916f7ac5dbc312969a90bc35a5f4fcbfc2965d60 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:47 +0200 Subject: usb: renesas: gadget: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/mod_gadget.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 494dfe06bb27..de4f97d84a82 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -1103,12 +1103,18 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) if (usbhsg_is_dcp(uep)) { gpriv->gadget.ep0 = &uep->ep; usb_ep_set_maxpacket_limit(&uep->ep, 64); + uep->ep.caps.type_control = true; } /* init normal pipe */ else { usb_ep_set_maxpacket_limit(&uep->ep, 512); + uep->ep.caps.type_iso = true; + uep->ep.caps.type_bulk = true; + uep->ep.caps.type_int = true; list_add_tail(&uep->ep.ep_list, &gpriv->gadget.ep_list); } + uep->ep.caps.dir_in = true; + uep->ep.caps.dir_out = true; } ret = usb_add_gadget_udc(dev, &gpriv->gadget); -- cgit v1.2.3 From 47bef386511517449e2f24a89a41084af53616f8 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:48 +0200 Subject: usb: gadget: atmel_usba_udc: add ep capabilities support Convert endpoint configuration to new capabilities model. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/atmel_usba_udc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 37d414ec2d69..267d84f838e1 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -2067,6 +2067,17 @@ static struct usba_ep * usba_udc_pdata(struct platform_device *pdev, ep->can_dma = pdata->ep[i].can_dma; ep->can_isoc = pdata->ep[i].can_isoc; + if (i == 0) { + ep->ep.caps.type_control = true; + } else { + ep->ep.caps.type_iso = ep->can_isoc; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + } + + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; + if (i) list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); } -- cgit v1.2.3 From b86f33a3a371a4c3aa8dbb2f4125634a4e0d09dc Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:49 +0200 Subject: usb: gadget: epautoconf: add endpoint capabilities flags verification Introduce endpoint matching mechanism basing on endpoint capabilities flags. We check if endpoint supports transfer type and direction requested in ep descriptor. Since we have this new endpoint matching mechanism there is no need to have old code guessing endpoint capabilities basing on its name, so we are getting rid of it. Remove also the obsolete comment. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/epautoconf.c | 96 +++++++++++++---------------------------- 1 file changed, 30 insertions(+), 66 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 8e00ca765549..af4b10a9068e 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -22,22 +22,6 @@ #include "gadget_chips.h" -/* - * This should work with endpoints from controller drivers sharing the - * same endpoint naming convention. By example: - * - * - ep1, ep2, ... address is fixed, not direction or type - * - ep1in, ep2out, ... address and direction are fixed, not type - * - ep1-bulk, ep2-bulk, ... address and type are fixed, not direction - * - ep1in-bulk, ep2out-iso, ... all three are fixed - * - ep-* ... no functionality restrictions - * - * Type suffixes are "-bulk", "-iso", or "-int". Numbers are decimal. - * Less common restrictions are implied by gadget_is_*(). - * - * NOTE: each endpoint is unidirectional, as specified by its USB - * descriptor; and isn't specific to a configuration or altsetting. - */ static int ep_matches ( struct usb_gadget *gadget, @@ -47,7 +31,6 @@ ep_matches ( ) { u8 type; - const char *tmp; u16 max; int num_req_streams = 0; @@ -56,58 +39,39 @@ ep_matches ( if (ep->claimed) return 0; - /* only support ep0 for portable CONTROL traffic */ type = usb_endpoint_type(desc); - if (USB_ENDPOINT_XFER_CONTROL == type) - return 0; - - /* some other naming convention */ - if ('e' != ep->name[0]) + switch (type) { + case USB_ENDPOINT_XFER_CONTROL: + /* only support ep0 for portable CONTROL traffic */ return 0; + case USB_ENDPOINT_XFER_ISOC: + if (!ep->caps.type_iso) + return 0; + break; + case USB_ENDPOINT_XFER_BULK: + if (!ep->caps.type_bulk) + return 0; + break; + case USB_ENDPOINT_XFER_INT: + /* bulk endpoints handle interrupt transfers, + * except the toggle-quirky iso-synch kind + */ + if (!ep->caps.type_int && !ep->caps.type_bulk) + return 0; + /* for now, avoid PXA "interrupt-in"; + * it's documented as never using DATA1. + */ + if (gadget_is_pxa(gadget) && ep->caps.type_int) + return 0; + break; + } - /* type-restriction: "-iso", "-bulk", or "-int". - * direction-restriction: "in", "out". - */ - if ('-' != ep->name[2]) { - tmp = strrchr (ep->name, '-'); - if (tmp) { - switch (type) { - case USB_ENDPOINT_XFER_INT: - /* bulk endpoints handle interrupt transfers, - * except the toggle-quirky iso-synch kind - */ - if ('s' == tmp[2]) // == "-iso" - return 0; - /* for now, avoid PXA "interrupt-in"; - * it's documented as never using DATA1. - */ - if (gadget_is_pxa (gadget) - && 'i' == tmp [1]) - return 0; - break; - case USB_ENDPOINT_XFER_BULK: - if ('b' != tmp[1]) // != "-bulk" - return 0; - break; - case USB_ENDPOINT_XFER_ISOC: - if ('s' != tmp[2]) // != "-iso" - return 0; - } - } else { - tmp = ep->name + strlen (ep->name); - } - - /* direction-restriction: "..in-..", "out-.." */ - tmp--; - if (!isdigit (*tmp)) { - if (desc->bEndpointAddress & USB_DIR_IN) { - if ('n' != *tmp) - return 0; - } else { - if ('t' != *tmp) - return 0; - } - } + if (usb_endpoint_dir_in(desc)) { + if (!ep->caps.dir_in) + return 0; + } else { + if (!ep->caps.dir_out) + return 0; } /* -- cgit v1.2.3 From b58713d53a8f41d57b24c93de0b1c7e9550ba70f Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:50 +0200 Subject: usb: gadget: epautoconf: remove pxa quirk from ep_matches() The same effect can be achieved by using capabilities flags, so now we can get rid of handling of hardware specific limitations in generic code. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/epautoconf.c | 5 ----- drivers/usb/gadget/udc/pxa25x_udc.c | 9 +++------ 2 files changed, 3 insertions(+), 11 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index af4b10a9068e..4f66e9d733cd 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -58,11 +58,6 @@ ep_matches ( */ if (!ep->caps.type_int && !ep->caps.type_bulk) return 0; - /* for now, avoid PXA "interrupt-in"; - * it's documented as never using DATA1. - */ - if (gadget_is_pxa(gadget) && ep->caps.type_int) - return 0; break; } diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c index b4d25dc4cb72..b82cb14850b6 100644 --- a/drivers/usb/gadget/udc/pxa25x_udc.c +++ b/drivers/usb/gadget/udc/pxa25x_udc.c @@ -1899,8 +1899,7 @@ static struct pxa25x_udc memory = { .name = "ep5in-int", .ops = &pxa25x_ep_ops, .maxpacket = INT_FIFO_SIZE, - .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, - USB_EP_CAPS_DIR_IN), + .caps = USB_EP_CAPS(0, 0), }, .dev = &memory, .fifo_size = INT_FIFO_SIZE, @@ -1978,8 +1977,7 @@ static struct pxa25x_udc memory = { .name = "ep10in-int", .ops = &pxa25x_ep_ops, .maxpacket = INT_FIFO_SIZE, - .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, - USB_EP_CAPS_DIR_IN), + .caps = USB_EP_CAPS(0, 0), }, .dev = &memory, .fifo_size = INT_FIFO_SIZE, @@ -2057,8 +2055,7 @@ static struct pxa25x_udc memory = { .name = "ep15in-int", .ops = &pxa25x_ep_ops, .maxpacket = INT_FIFO_SIZE, - .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, - USB_EP_CAPS_DIR_IN), + .caps = USB_EP_CAPS(0, 0), }, .dev = &memory, .fifo_size = INT_FIFO_SIZE, -- cgit v1.2.3 From 5dbe135a153837ce9367bdfacf7aabfc6fb76f4b Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 31 Jul 2015 16:00:51 +0200 Subject: usb: gadget: epautoconf: remove ep and desc configuration from ep_matches() As function ep_matches() is used to match endpoint with usb descriptor it's highly unintuitive that it modifies endpoint and descriptor structures fields. This patch moves code configuring ep and desc from ep_matches() to usb_ep_autoconfig_ss(), so now function ep_matches() does nothing more than its name suggests. [ balbi@ti.com : fix build warning ] Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/epautoconf.c | 66 +++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 32 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 4f66e9d733cd..52658fe761d4 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -82,13 +82,6 @@ ep_matches ( } - /* - * If the protocol driver hasn't yet decided on wMaxPacketSize - * and wants to know the maximum possible, provide the info. - */ - if (desc->wMaxPacketSize == 0) - desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit); - /* endpoint maxpacket size is an input parameter, except for bulk * where it's an output parameter representing the full speed limit. * the usb spec fixes high speed bulk maxpacket at 512 bytes. @@ -119,31 +112,6 @@ ep_matches ( /* MATCH!! */ - /* report address */ - desc->bEndpointAddress &= USB_DIR_IN; - if (isdigit (ep->name [2])) { - u8 num = simple_strtoul (&ep->name [2], NULL, 10); - desc->bEndpointAddress |= num; - } else if (desc->bEndpointAddress & USB_DIR_IN) { - if (++gadget->in_epnum > 15) - return 0; - desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum; - } else { - if (++gadget->out_epnum > 15) - return 0; - desc->bEndpointAddress |= gadget->out_epnum; - } - - /* report (variable) full speed bulk maxpacket */ - if ((USB_ENDPOINT_XFER_BULK == type) && !ep_comp) { - int size = ep->maxpacket_limit; - - /* min() doesn't work on bitfields with gcc-3.5 */ - if (size > 64) - size = 64; - desc->wMaxPacketSize = cpu_to_le16(size); - } - ep->address = desc->bEndpointAddress; return 1; } @@ -280,6 +248,40 @@ struct usb_ep *usb_ep_autoconfig_ss( /* Fail */ return NULL; found_ep: + + /* + * If the protocol driver hasn't yet decided on wMaxPacketSize + * and wants to know the maximum possible, provide the info. + */ + if (desc->wMaxPacketSize == 0) + desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit); + + /* report address */ + desc->bEndpointAddress &= USB_DIR_IN; + if (isdigit(ep->name[2])) { + u8 num = simple_strtoul(&ep->name[2], NULL, 10); + desc->bEndpointAddress |= num; + } else if (desc->bEndpointAddress & USB_DIR_IN) { + if (++gadget->in_epnum > 15) + return NULL; + desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum; + } else { + if (++gadget->out_epnum > 15) + return NULL; + desc->bEndpointAddress |= gadget->out_epnum; + } + + /* report (variable) full speed bulk maxpacket */ + if ((type == USB_ENDPOINT_XFER_BULK) && !ep_comp) { + int size = ep->maxpacket_limit; + + /* min() doesn't work on bitfields with gcc-3.5 */ + if (size > 64) + size = 64; + desc->wMaxPacketSize = cpu_to_le16(size); + } + + ep->address = desc->bEndpointAddress; ep->desc = NULL; ep->comp_desc = NULL; ep->claimed = true; -- cgit v1.2.3 From 26bf956aa9952a8141a12f314df70dcd020572d6 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Thu, 6 Aug 2015 14:11:09 +0200 Subject: usb: gadget: epautoconf: rework ep_matches() function Rework ep_matches() function to make it shorter and more readable. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/epautoconf.c | 81 ++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 49 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 52658fe761d4..95e12759af4d 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -32,7 +32,6 @@ ep_matches ( { u8 type; u16 max; - int num_req_streams = 0; /* endpoint already claimed? */ @@ -40,6 +39,20 @@ ep_matches ( return 0; type = usb_endpoint_type(desc); + max = 0x7ff & usb_endpoint_maxp(desc); + + if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in) + return 0; + if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out) + return 0; + + if (max > ep->maxpacket_limit) + return 0; + + /* "high bandwidth" works only at high speed */ + if (!gadget_is_dualspeed(gadget) && usb_endpoint_maxp(desc) & (3<<11)) + return 0; + switch (type) { case USB_ENDPOINT_XFER_CONTROL: /* only support ep0 for portable CONTROL traffic */ @@ -47,66 +60,36 @@ ep_matches ( case USB_ENDPOINT_XFER_ISOC: if (!ep->caps.type_iso) return 0; + /* ISO: limit 1023 bytes full speed, + * 1024 high/super speed + */ + if (!gadget_is_dualspeed(gadget) && max > 1023) + return 0; break; case USB_ENDPOINT_XFER_BULK: if (!ep->caps.type_bulk) return 0; + if (ep_comp && gadget_is_superspeed(gadget)) { + /* Get the number of required streams from the + * EP companion descriptor and see if the EP + * matches it + */ + num_req_streams = ep_comp->bmAttributes & 0x1f; + if (num_req_streams > ep->max_streams) + return 0; + } break; case USB_ENDPOINT_XFER_INT: - /* bulk endpoints handle interrupt transfers, + /* Bulk endpoints handle interrupt transfers, * except the toggle-quirky iso-synch kind */ if (!ep->caps.type_int && !ep->caps.type_bulk) return 0; - break; - } - - if (usb_endpoint_dir_in(desc)) { - if (!ep->caps.dir_in) - return 0; - } else { - if (!ep->caps.dir_out) - return 0; - } - - /* - * Get the number of required streams from the EP companion - * descriptor and see if the EP matches it - */ - if (usb_endpoint_xfer_bulk(desc)) { - if (ep_comp && gadget->max_speed >= USB_SPEED_SUPER) { - num_req_streams = ep_comp->bmAttributes & 0x1f; - if (num_req_streams > ep->max_streams) - return 0; - } - - } - - /* endpoint maxpacket size is an input parameter, except for bulk - * where it's an output parameter representing the full speed limit. - * the usb spec fixes high speed bulk maxpacket at 512 bytes. - */ - max = 0x7ff & usb_endpoint_maxp(desc); - switch (type) { - case USB_ENDPOINT_XFER_INT: - /* INT: limit 64 bytes full speed, 1024 high/super speed */ + /* INT: limit 64 bytes full speed, + * 1024 high/super speed + */ if (!gadget_is_dualspeed(gadget) && max > 64) return 0; - /* FALLTHROUGH */ - - case USB_ENDPOINT_XFER_ISOC: - /* ISO: limit 1023 bytes full speed, 1024 high/super speed */ - if (ep->maxpacket_limit < max) - return 0; - if (!gadget_is_dualspeed(gadget) && max > 1023) - return 0; - - /* BOTH: "high bandwidth" works only at high speed */ - if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) { - if (!gadget_is_dualspeed(gadget)) - return 0; - /* configure your hardware with enough buffering!! */ - } break; } -- cgit v1.2.3 From 596c154d62330ea0bb4e3c3e50afa3682e50b617 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Thu, 6 Aug 2015 14:11:10 +0200 Subject: usb: gadget: add 'ep_match' callback to usb_gadget_ops Add callback that is called by epautoconf to allow UDC driver match the best endpoint for specific descriptor. It's intended to supply mechanism which allows to get rid of chip-specific endpoint matching code from epautoconf. If gadget has set 'ep_match' callback we prefer to call it first, and if it fails to find matching endpoint, then we try to use default matching algorithm. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/epautoconf.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 95e12759af4d..f000c73319f4 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -165,6 +165,12 @@ struct usb_ep *usb_ep_autoconfig_ss( type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (gadget->ops->match_ep) { + ep = gadget->ops->match_ep(gadget, desc, ep_comp); + if (ep) + goto found_ep; + } + /* First, apply chip-specific "best usage" knowledge. * This might make a good usb_gadget_ops hook ... */ -- cgit v1.2.3 From 4278c687f697b651ab0c771114564da5ed006f22 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Thu, 6 Aug 2015 14:11:11 +0200 Subject: usb: gadget: move ep_matches() from epautoconf to udc-core Move ep_matches() function to udc-core and rename it to usb_gadget_ep_match_desc(). This function can be used by UDC drivers in 'match_ep' callback to avoid writing lots of repetitive code. Replace all calls of ep_matches() with usb_gadget_ep_match_desc(). Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/epautoconf.c | 95 +++++---------------------------------- drivers/usb/gadget/udc/udc-core.c | 69 ++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 84 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index f000c73319f4..d49af4fc8667 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -22,82 +22,6 @@ #include "gadget_chips.h" -static int -ep_matches ( - struct usb_gadget *gadget, - struct usb_ep *ep, - struct usb_endpoint_descriptor *desc, - struct usb_ss_ep_comp_descriptor *ep_comp -) -{ - u8 type; - u16 max; - int num_req_streams = 0; - - /* endpoint already claimed? */ - if (ep->claimed) - return 0; - - type = usb_endpoint_type(desc); - max = 0x7ff & usb_endpoint_maxp(desc); - - if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in) - return 0; - if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out) - return 0; - - if (max > ep->maxpacket_limit) - return 0; - - /* "high bandwidth" works only at high speed */ - if (!gadget_is_dualspeed(gadget) && usb_endpoint_maxp(desc) & (3<<11)) - return 0; - - switch (type) { - case USB_ENDPOINT_XFER_CONTROL: - /* only support ep0 for portable CONTROL traffic */ - return 0; - case USB_ENDPOINT_XFER_ISOC: - if (!ep->caps.type_iso) - return 0; - /* ISO: limit 1023 bytes full speed, - * 1024 high/super speed - */ - if (!gadget_is_dualspeed(gadget) && max > 1023) - return 0; - break; - case USB_ENDPOINT_XFER_BULK: - if (!ep->caps.type_bulk) - return 0; - if (ep_comp && gadget_is_superspeed(gadget)) { - /* Get the number of required streams from the - * EP companion descriptor and see if the EP - * matches it - */ - num_req_streams = ep_comp->bmAttributes & 0x1f; - if (num_req_streams > ep->max_streams) - return 0; - } - break; - case USB_ENDPOINT_XFER_INT: - /* Bulk endpoints handle interrupt transfers, - * except the toggle-quirky iso-synch kind - */ - if (!ep->caps.type_int && !ep->caps.type_bulk) - return 0; - /* INT: limit 64 bytes full speed, - * 1024 high/super speed - */ - if (!gadget_is_dualspeed(gadget) && max > 64) - return 0; - break; - } - - /* MATCH!! */ - - return 1; -} - static struct usb_ep * find_ep (struct usb_gadget *gadget, const char *name) { @@ -180,10 +104,12 @@ struct usb_ep *usb_ep_autoconfig_ss( if (type == USB_ENDPOINT_XFER_INT) { /* ep-e, ep-f are PIO with only 64 byte fifos */ ep = find_ep(gadget, "ep-e"); - if (ep && ep_matches(gadget, ep, desc, ep_comp)) + if (ep && usb_gadget_ep_match_desc(gadget, + ep, desc, ep_comp)) goto found_ep; ep = find_ep(gadget, "ep-f"); - if (ep && ep_matches(gadget, ep, desc, ep_comp)) + if (ep && usb_gadget_ep_match_desc(gadget, + ep, desc, ep_comp)) goto found_ep; } @@ -191,20 +117,21 @@ struct usb_ep *usb_ep_autoconfig_ss( snprintf(name, sizeof(name), "ep%d%s", usb_endpoint_num(desc), usb_endpoint_dir_in(desc) ? "in" : "out"); ep = find_ep(gadget, name); - if (ep && ep_matches(gadget, ep, desc, ep_comp)) + if (ep && usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp)) goto found_ep; } else if (gadget_is_goku (gadget)) { if (USB_ENDPOINT_XFER_INT == type) { /* single buffering is enough */ ep = find_ep(gadget, "ep3-bulk"); - if (ep && ep_matches(gadget, ep, desc, ep_comp)) + if (ep && usb_gadget_ep_match_desc(gadget, + ep, desc, ep_comp)) goto found_ep; } else if (USB_ENDPOINT_XFER_BULK == type && (USB_DIR_IN & desc->bEndpointAddress)) { /* DMA may be available */ ep = find_ep(gadget, "ep2-bulk"); - if (ep && ep_matches(gadget, ep, desc, - ep_comp)) + if (ep && usb_gadget_ep_match_desc(gadget, + ep, desc, ep_comp)) goto found_ep; } @@ -223,14 +150,14 @@ struct usb_ep *usb_ep_autoconfig_ss( ep = find_ep(gadget, "ep2out"); } else ep = NULL; - if (ep && ep_matches(gadget, ep, desc, ep_comp)) + if (ep && usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp)) goto found_ep; #endif } /* Second, look at endpoints until an unclaimed one looks usable */ list_for_each_entry (ep, &gadget->ep_list, ep_list) { - if (ep_matches(gadget, ep, desc, ep_comp)) + if (usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp)) goto found_ep; } diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c index 362ee8af5fce..b6427d1e9a6c 100644 --- a/drivers/usb/gadget/udc/udc-core.c +++ b/drivers/usb/gadget/udc/udc-core.c @@ -131,6 +131,75 @@ EXPORT_SYMBOL_GPL(usb_gadget_giveback_request); /* ------------------------------------------------------------------------- */ +int usb_gadget_ep_match_desc(struct usb_gadget *gadget, + struct usb_ep *ep, struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *ep_comp) +{ + u8 type; + u16 max; + int num_req_streams = 0; + + /* endpoint already claimed? */ + if (ep->claimed) + return 0; + + type = usb_endpoint_type(desc); + max = 0x7ff & usb_endpoint_maxp(desc); + + if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in) + return 0; + if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out) + return 0; + + if (max > ep->maxpacket_limit) + return 0; + + /* "high bandwidth" works only at high speed */ + if (!gadget_is_dualspeed(gadget) && usb_endpoint_maxp(desc) & (3<<11)) + return 0; + + switch (type) { + case USB_ENDPOINT_XFER_CONTROL: + /* only support ep0 for portable CONTROL traffic */ + return 0; + case USB_ENDPOINT_XFER_ISOC: + if (!ep->caps.type_iso) + return 0; + /* ISO: limit 1023 bytes full speed, 1024 high/super speed */ + if (!gadget_is_dualspeed(gadget) && max > 1023) + return 0; + break; + case USB_ENDPOINT_XFER_BULK: + if (!ep->caps.type_bulk) + return 0; + if (ep_comp && gadget_is_superspeed(gadget)) { + /* Get the number of required streams from the + * EP companion descriptor and see if the EP + * matches it + */ + num_req_streams = ep_comp->bmAttributes & 0x1f; + if (num_req_streams > ep->max_streams) + return 0; + } + break; + case USB_ENDPOINT_XFER_INT: + /* Bulk endpoints handle interrupt transfers, + * except the toggle-quirky iso-synch kind + */ + if (!ep->caps.type_int && !ep->caps.type_bulk) + return 0; + /* INT: limit 64 bytes full speed, 1024 high/super speed */ + if (!gadget_is_dualspeed(gadget) && max > 64) + return 0; + break; + } + + return 1; +} +EXPORT_SYMBOL_GPL(usb_gadget_ep_match_desc); + +/* ------------------------------------------------------------------------- */ + static void usb_gadget_state_work(struct work_struct *work) { struct usb_gadget *gadget = work_to_gadget(work); -- cgit v1.2.3 From b0aea0037c8896b8e69cad3f6e828782789c1edf Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Thu, 6 Aug 2015 14:11:12 +0200 Subject: usb: gadget: move find_ep() from epautoconf to udc-core Move find_ep() to udc-core and rename it to gadget_find_ep_by_name(). It can be used in UDC drivers, especially in 'match_ep' callback after moving chip-specific endpoint matching logic from epautoconf to UDC drivers. Replace all calls of find_ep() function with gadget_find_ep_by_name(). Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/epautoconf.c | 30 +++++++++--------------------- drivers/usb/gadget/udc/udc-core.c | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 21 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index d49af4fc8667..a39ca033b9ce 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -22,18 +22,6 @@ #include "gadget_chips.h" -static struct usb_ep * -find_ep (struct usb_gadget *gadget, const char *name) -{ - struct usb_ep *ep; - - list_for_each_entry (ep, &gadget->ep_list, ep_list) { - if (0 == strcmp (ep->name, name)) - return ep; - } - return NULL; -} - /** * usb_ep_autoconfig_ss() - choose an endpoint matching the ep * descriptor and ep companion descriptor @@ -103,11 +91,11 @@ struct usb_ep *usb_ep_autoconfig_ss( if (type == USB_ENDPOINT_XFER_INT) { /* ep-e, ep-f are PIO with only 64 byte fifos */ - ep = find_ep(gadget, "ep-e"); + ep = gadget_find_ep_by_name(gadget, "ep-e"); if (ep && usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp)) goto found_ep; - ep = find_ep(gadget, "ep-f"); + ep = gadget_find_ep_by_name(gadget, "ep-f"); if (ep && usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp)) goto found_ep; @@ -116,20 +104,20 @@ struct usb_ep *usb_ep_autoconfig_ss( /* USB3380: use same address for usb and hardware endpoints */ snprintf(name, sizeof(name), "ep%d%s", usb_endpoint_num(desc), usb_endpoint_dir_in(desc) ? "in" : "out"); - ep = find_ep(gadget, name); + ep = gadget_find_ep_by_name(gadget, name); if (ep && usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp)) goto found_ep; } else if (gadget_is_goku (gadget)) { if (USB_ENDPOINT_XFER_INT == type) { /* single buffering is enough */ - ep = find_ep(gadget, "ep3-bulk"); + ep = gadget_find_ep_by_name(gadget, "ep3-bulk"); if (ep && usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp)) goto found_ep; } else if (USB_ENDPOINT_XFER_BULK == type && (USB_DIR_IN & desc->bEndpointAddress)) { /* DMA may be available */ - ep = find_ep(gadget, "ep2-bulk"); + ep = gadget_find_ep_by_name(gadget, "ep2-bulk"); if (ep && usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp)) goto found_ep; @@ -140,14 +128,14 @@ struct usb_ep *usb_ep_autoconfig_ss( if ((USB_ENDPOINT_XFER_BULK == type) || (USB_ENDPOINT_XFER_ISOC == type)) { if (USB_DIR_IN & desc->bEndpointAddress) - ep = find_ep (gadget, "ep5in"); + ep = gadget_find_ep_by_name(gadget, "ep5in"); else - ep = find_ep (gadget, "ep6out"); + ep = gadget_find_ep_by_name(gadget, "ep6out"); } else if (USB_ENDPOINT_XFER_INT == type) { if (USB_DIR_IN & desc->bEndpointAddress) - ep = find_ep(gadget, "ep1in"); + ep = gadget_find_ep_by_name(gadget, "ep1in"); else - ep = find_ep(gadget, "ep2out"); + ep = gadget_find_ep_by_name(gadget, "ep2out"); } else ep = NULL; if (ep && usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp)) diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c index b6427d1e9a6c..3c954b5fe4f3 100644 --- a/drivers/usb/gadget/udc/udc-core.c +++ b/drivers/usb/gadget/udc/udc-core.c @@ -131,6 +131,27 @@ EXPORT_SYMBOL_GPL(usb_gadget_giveback_request); /* ------------------------------------------------------------------------- */ +/** + * gadget_find_ep_by_name - returns ep whose name is the same as sting passed + * in second parameter or NULL if searched endpoint not found + * @g: controller to check for quirk + * @name: name of searched endpoint + */ +struct usb_ep *gadget_find_ep_by_name(struct usb_gadget *g, const char *name) +{ + struct usb_ep *ep; + + gadget_for_each_ep(ep, g) { + if (!strcmp(ep->name, name)) + return ep; + } + + return NULL; +} +EXPORT_SYMBOL_GPL(gadget_find_ep_by_name); + +/* ------------------------------------------------------------------------- */ + int usb_gadget_ep_match_desc(struct usb_gadget *gadget, struct usb_ep *ep, struct usb_endpoint_descriptor *desc, struct usb_ss_ep_comp_descriptor *ep_comp) -- cgit v1.2.3 From 3e8b231818c25a250c36f8bfb944aa1fd2b13396 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Thu, 6 Aug 2015 14:11:13 +0200 Subject: usb: gadget: net2280: add net2280_match_ep() function Add 'match_ep' callback to utilize chip-specific knowledge in endpoint matching process. Function does the same that was done by chip-specific code inside of epautoconf. Now this code can be removed from there to separate generic code from platform specific logic. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/epautoconf.c | 23 +---------------------- drivers/usb/gadget/udc/net2280.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 22 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index a39ca033b9ce..0ff513400ecf 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -86,28 +86,7 @@ struct usb_ep *usb_ep_autoconfig_ss( /* First, apply chip-specific "best usage" knowledge. * This might make a good usb_gadget_ops hook ... */ - if (gadget_is_net2280(gadget)) { - char name[8]; - - if (type == USB_ENDPOINT_XFER_INT) { - /* ep-e, ep-f are PIO with only 64 byte fifos */ - ep = gadget_find_ep_by_name(gadget, "ep-e"); - if (ep && usb_gadget_ep_match_desc(gadget, - ep, desc, ep_comp)) - goto found_ep; - ep = gadget_find_ep_by_name(gadget, "ep-f"); - if (ep && usb_gadget_ep_match_desc(gadget, - ep, desc, ep_comp)) - goto found_ep; - } - - /* USB3380: use same address for usb and hardware endpoints */ - snprintf(name, sizeof(name), "ep%d%s", usb_endpoint_num(desc), - usb_endpoint_dir_in(desc) ? "in" : "out"); - ep = gadget_find_ep_by_name(gadget, name); - if (ep && usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp)) - goto found_ep; - } else if (gadget_is_goku (gadget)) { + if (gadget_is_goku(gadget)) { if (USB_ENDPOINT_XFER_INT == type) { /* single buffering is enough */ ep = gadget_find_ep_by_name(gadget, "ep3-bulk"); diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c index 872ca257cfa4..cf0ed42f5591 100644 --- a/drivers/usb/gadget/udc/net2280.c +++ b/drivers/usb/gadget/udc/net2280.c @@ -1550,6 +1550,33 @@ static int net2280_pullup(struct usb_gadget *_gadget, int is_on) return 0; } +static struct usb_ep *net2280_match_ep(struct usb_gadget *_gadget, + struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *ep_comp) +{ + char name[8]; + struct usb_ep *ep; + + if (usb_endpoint_type(desc) == USB_ENDPOINT_XFER_INT) { + /* ep-e, ep-f are PIO with only 64 byte fifos */ + ep = gadget_find_ep_by_name(_gadget, "ep-e"); + if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp)) + return ep; + ep = gadget_find_ep_by_name(_gadget, "ep-f"); + if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp)) + return ep; + } + + /* USB3380: use same address for usb and hardware endpoints */ + snprintf(name, sizeof(name), "ep%d%s", usb_endpoint_num(desc), + usb_endpoint_dir_in(desc) ? "in" : "out"); + ep = gadget_find_ep_by_name(_gadget, name); + if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp)) + return ep; + + return NULL; +} + static int net2280_start(struct usb_gadget *_gadget, struct usb_gadget_driver *driver); static int net2280_stop(struct usb_gadget *_gadget); @@ -1561,6 +1588,7 @@ static const struct usb_gadget_ops net2280_ops = { .pullup = net2280_pullup, .udc_start = net2280_start, .udc_stop = net2280_stop, + .match_ep = net2280_match_ep, }; /*-------------------------------------------------------------------------*/ -- cgit v1.2.3 From 8cc67b7bff2fc1adfd080233d35aacba4411cf87 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Thu, 6 Aug 2015 14:11:14 +0200 Subject: usb: gadget: goku_udc: add goku_match_ep() function Add 'match_ep' callback to utilize chip-specific knowledge in endpoint matching process. Function does the same that was done by chip-specific code inside of epautoconf. Now this code can be removed from there to separate generic code from platform specific logic. [ balbi@ti.com : fix build breakage ] Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/epautoconf.c | 20 ++------------------ drivers/usb/gadget/udc/goku_udc.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 18 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 0ff513400ecf..574b6a4df646 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -86,24 +86,8 @@ struct usb_ep *usb_ep_autoconfig_ss( /* First, apply chip-specific "best usage" knowledge. * This might make a good usb_gadget_ops hook ... */ - if (gadget_is_goku(gadget)) { - if (USB_ENDPOINT_XFER_INT == type) { - /* single buffering is enough */ - ep = gadget_find_ep_by_name(gadget, "ep3-bulk"); - if (ep && usb_gadget_ep_match_desc(gadget, - ep, desc, ep_comp)) - goto found_ep; - } else if (USB_ENDPOINT_XFER_BULK == type - && (USB_DIR_IN & desc->bEndpointAddress)) { - /* DMA may be available */ - ep = gadget_find_ep_by_name(gadget, "ep2-bulk"); - if (ep && usb_gadget_ep_match_desc(gadget, - ep, desc, ep_comp)) - goto found_ep; - } - #ifdef CONFIG_BLACKFIN - } else if (gadget_is_musbhdrc(gadget)) { + if (gadget_is_musbhdrc(gadget)) { if ((USB_ENDPOINT_XFER_BULK == type) || (USB_ENDPOINT_XFER_ISOC == type)) { if (USB_DIR_IN & desc->bEndpointAddress) @@ -119,8 +103,8 @@ struct usb_ep *usb_ep_autoconfig_ss( ep = NULL; if (ep && usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp)) goto found_ep; -#endif } +#endif /* Second, look at endpoints until an unclaimed one looks usable */ list_for_each_entry (ep, &gadget->ep_list, ep_list) { diff --git a/drivers/usb/gadget/udc/goku_udc.c b/drivers/usb/gadget/udc/goku_udc.c index 46b8d14998cf..1fdfec14a3ba 100644 --- a/drivers/usb/gadget/udc/goku_udc.c +++ b/drivers/usb/gadget/udc/goku_udc.c @@ -990,6 +990,35 @@ static int goku_get_frame(struct usb_gadget *_gadget) return -EOPNOTSUPP; } +static struct usb_ep *goku_match_ep(struct usb_gadget *g, + struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *ep_comp) +{ + struct goku_udc *dev = to_goku_udc(g); + struct usb_ep *ep; + + switch (usb_endpoint_type(desc)) { + case USB_ENDPOINT_XFER_INT: + /* single buffering is enough */ + ep = &dev->ep[3].ep; + if (usb_gadget_ep_match_desc(g, ep, desc, ep_comp)) + return ep; + break; + case USB_ENDPOINT_XFER_BULK: + if (usb_endpoint_dir_in(desc)) { + /* DMA may be available */ + ep = &dev->ep[2].ep; + if (usb_gadget_ep_match_desc(g, ep, desc, ep_comp)) + return ep; + } + break; + default: + /* nothing */ ; + } + + return NULL; +} + static int goku_udc_start(struct usb_gadget *g, struct usb_gadget_driver *driver); static int goku_udc_stop(struct usb_gadget *g); @@ -998,6 +1027,7 @@ static const struct usb_gadget_ops goku_ops = { .get_frame = goku_get_frame, .udc_start = goku_udc_start, .udc_stop = goku_udc_stop, + .match_ep = goku_match_ep, // no remote wakeup // not selfpowered }; -- cgit v1.2.3 From 26b8aa458c7d99181ceb07f27da9bd7d94185e35 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Thu, 6 Aug 2015 14:11:15 +0200 Subject: usb: musb: gadget: add musb_match_ep() function Add 'match_ep' callback to utilize chip-specific knowledge in endpoint matching process. Function does the same that was done by chip-specific code inside of epautoconf. Now this code can be removed from there to separate generic code from platform specific logic. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/epautoconf.c | 23 ----------------------- drivers/usb/musb/musb_gadget.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 23 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 574b6a4df646..16c1cc90c406 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -83,29 +83,6 @@ struct usb_ep *usb_ep_autoconfig_ss( goto found_ep; } - /* First, apply chip-specific "best usage" knowledge. - * This might make a good usb_gadget_ops hook ... - */ -#ifdef CONFIG_BLACKFIN - if (gadget_is_musbhdrc(gadget)) { - if ((USB_ENDPOINT_XFER_BULK == type) || - (USB_ENDPOINT_XFER_ISOC == type)) { - if (USB_DIR_IN & desc->bEndpointAddress) - ep = gadget_find_ep_by_name(gadget, "ep5in"); - else - ep = gadget_find_ep_by_name(gadget, "ep6out"); - } else if (USB_ENDPOINT_XFER_INT == type) { - if (USB_DIR_IN & desc->bEndpointAddress) - ep = gadget_find_ep_by_name(gadget, "ep1in"); - else - ep = gadget_find_ep_by_name(gadget, "ep2out"); - } else - ep = NULL; - if (ep && usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp)) - goto found_ep; - } -#endif - /* Second, look at endpoints until an unclaimed one looks usable */ list_for_each_entry (ep, &gadget->ep_list, ep_list) { if (usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp)) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 4150bafe6bf5..5f52bcb4bf78 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1684,6 +1684,39 @@ static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on) return 0; } +#ifdef CONFIG_BLACKFIN +static struct usb_ep *musb_match_ep(struct usb_gadget *g, + struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *ep_comp) +{ + struct usb_ep *ep = NULL; + + switch (usb_endpoint_type(desc)) { + case USB_ENDPOINT_XFER_ISOC: + case USB_ENDPOINT_XFER_BULK: + if (usb_endpoint_dir_in(desc)) + ep = gadget_find_ep_by_name(g, "ep5in"); + else + ep = gadget_find_ep_by_name(g, "ep6out"); + break; + case USB_ENDPOINT_XFER_INT: + if (usb_endpoint_dir_in(desc)) + ep = gadget_find_ep_by_name(g, "ep1in"); + else + ep = gadget_find_ep_by_name(g, "ep2out"); + break; + default: + } + + if (ep && usb_gadget_ep_match_desc(g, ep, desc, ep_comp)) + return ep; + + return NULL; +} +#else +#define musb_match_ep NULL +#endif + static int musb_gadget_start(struct usb_gadget *g, struct usb_gadget_driver *driver); static int musb_gadget_stop(struct usb_gadget *g); @@ -1697,6 +1730,7 @@ static const struct usb_gadget_ops musb_gadget_operations = { .pullup = musb_gadget_pullup, .udc_start = musb_gadget_start, .udc_stop = musb_gadget_stop, + .match_ep = musb_match_ep, }; /* ----------------------------------------------------------------------- */ -- cgit v1.2.3 From adab43396ed4830c7cee29837e8cedcddb2b5315 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Thu, 6 Aug 2015 14:11:16 +0200 Subject: usb: gadget: remove gadget_chips.h This header file contains helpers for quirks based on UDC controller name. Since we have generic quirk bitfields in usb_gadget structure for all of these quirks we don't need to have this header any longer. This patch removes gadget_chips.h file and makes sure that it's no longer included anywhere in kernel sources. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/epautoconf.c | 2 - drivers/usb/gadget/function/f_acm.c | 1 - drivers/usb/gadget/function/f_mass_storage.c | 1 - drivers/usb/gadget/function/f_obex.c | 1 - drivers/usb/gadget/function/f_serial.c | 1 - drivers/usb/gadget/function/f_sourcesink.c | 1 - drivers/usb/gadget/function/u_ether.h | 2 - drivers/usb/gadget/function/u_uac1.h | 2 - drivers/usb/gadget/legacy/audio.c | 1 - drivers/usb/gadget/legacy/gmidi.c | 2 - drivers/usb/gadget/legacy/hid.c | 1 - drivers/usb/gadget/legacy/nokia.c | 1 - drivers/usb/gadget/legacy/printer.c | 2 - drivers/usb/gadget/legacy/serial.c | 1 - drivers/usb/gadget/udc/gadget_chips.h | 55 ---------------------------- 15 files changed, 74 deletions(-) delete mode 100644 drivers/usb/gadget/udc/gadget_chips.h (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 16c1cc90c406..978435a51038 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -20,8 +20,6 @@ #include #include -#include "gadget_chips.h" - /** * usb_ep_autoconfig_ss() - choose an endpoint matching the ep * descriptor and ep companion descriptor diff --git a/drivers/usb/gadget/function/f_acm.c b/drivers/usb/gadget/function/f_acm.c index aad8165e98ef..be9df09fde26 100644 --- a/drivers/usb/gadget/function/f_acm.c +++ b/drivers/usb/gadget/function/f_acm.c @@ -21,7 +21,6 @@ #include #include "u_serial.h" -#include "gadget_chips.h" /* diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 04c3bb6e9dcd..11a7f5aa955b 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -219,7 +219,6 @@ #include #include -#include "gadget_chips.h" #include "configfs.h" diff --git a/drivers/usb/gadget/function/f_obex.c b/drivers/usb/gadget/function/f_obex.c index 2682d59f5675..5460426057eb 100644 --- a/drivers/usb/gadget/function/f_obex.c +++ b/drivers/usb/gadget/function/f_obex.c @@ -20,7 +20,6 @@ #include #include "u_serial.h" -#include "gadget_chips.h" /* diff --git a/drivers/usb/gadget/function/f_serial.c b/drivers/usb/gadget/function/f_serial.c index 2e02dfabc7ae..1d162e200e83 100644 --- a/drivers/usb/gadget/function/f_serial.c +++ b/drivers/usb/gadget/function/f_serial.c @@ -16,7 +16,6 @@ #include #include "u_serial.h" -#include "gadget_chips.h" /* diff --git a/drivers/usb/gadget/function/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c index e6af1719d851..cbfaf86fe456 100644 --- a/drivers/usb/gadget/function/f_sourcesink.c +++ b/drivers/usb/gadget/function/f_sourcesink.c @@ -20,7 +20,6 @@ #include #include "g_zero.h" -#include "gadget_chips.h" #include "u_f.h" /* diff --git a/drivers/usb/gadget/function/u_ether.h b/drivers/usb/gadget/function/u_ether.h index 1384f000bd80..c77145bd6b5b 100644 --- a/drivers/usb/gadget/function/u_ether.h +++ b/drivers/usb/gadget/function/u_ether.h @@ -20,8 +20,6 @@ #include #include -#include "gadget_chips.h" - #define QMULT_DEFAULT 5 /* diff --git a/drivers/usb/gadget/function/u_uac1.h b/drivers/usb/gadget/function/u_uac1.h index fe386df6dd3e..5c2ac8e8456d 100644 --- a/drivers/usb/gadget/function/u_uac1.h +++ b/drivers/usb/gadget/function/u_uac1.h @@ -21,8 +21,6 @@ #include #include -#include "gadget_chips.h" - #define FILE_PCM_PLAYBACK "/dev/snd/pcmC0D0p" #define FILE_PCM_CAPTURE "/dev/snd/pcmC0D0c" #define FILE_CONTROL "/dev/snd/controlC0" diff --git a/drivers/usb/gadget/legacy/audio.c b/drivers/usb/gadget/legacy/audio.c index 9b2c1c68746b..685cf3b4b78f 100644 --- a/drivers/usb/gadget/legacy/audio.c +++ b/drivers/usb/gadget/legacy/audio.c @@ -15,7 +15,6 @@ #include #include -#include "gadget_chips.h" #define DRIVER_DESC "Linux USB Audio Gadget" #define DRIVER_VERSION "Feb 2, 2012" diff --git a/drivers/usb/gadget/legacy/gmidi.c b/drivers/usb/gadget/legacy/gmidi.c index 650568de0de3..8a18348ae86e 100644 --- a/drivers/usb/gadget/legacy/gmidi.c +++ b/drivers/usb/gadget/legacy/gmidi.c @@ -35,8 +35,6 @@ #include #include -#include "gadget_chips.h" - #include "u_midi.h" /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/legacy/hid.c b/drivers/usb/gadget/legacy/hid.c index e4874d3183dc..7e5d2c48476e 100644 --- a/drivers/usb/gadget/legacy/hid.c +++ b/drivers/usb/gadget/legacy/hid.c @@ -19,7 +19,6 @@ #include #include -#include "gadget_chips.h" #define DRIVER_DESC "HID Gadget" #define DRIVER_VERSION "2010/03/16" diff --git a/drivers/usb/gadget/legacy/nokia.c b/drivers/usb/gadget/legacy/nokia.c index c20f3b58f126..8b3f6fb1825d 100644 --- a/drivers/usb/gadget/legacy/nokia.c +++ b/drivers/usb/gadget/legacy/nokia.c @@ -23,7 +23,6 @@ #include "u_ether.h" #include "u_phonet.h" #include "u_ecm.h" -#include "gadget_chips.h" #include "f_mass_storage.h" /* Defines */ diff --git a/drivers/usb/gadget/legacy/printer.c b/drivers/usb/gadget/legacy/printer.c index 0c1fc0622d09..a22d30a4def1 100644 --- a/drivers/usb/gadget/legacy/printer.c +++ b/drivers/usb/gadget/legacy/printer.c @@ -19,8 +19,6 @@ #include #include -#include "gadget_chips.h" - USB_GADGET_COMPOSITE_OPTIONS(); #define DRIVER_DESC "Printer Gadget" diff --git a/drivers/usb/gadget/legacy/serial.c b/drivers/usb/gadget/legacy/serial.c index 9836d164469a..c5d42e0347a9 100644 --- a/drivers/usb/gadget/legacy/serial.c +++ b/drivers/usb/gadget/legacy/serial.c @@ -17,7 +17,6 @@ #include #include "u_serial.h" -#include "gadget_chips.h" /* Defines */ diff --git a/drivers/usb/gadget/udc/gadget_chips.h b/drivers/usb/gadget/udc/gadget_chips.h deleted file mode 100644 index bcd04bc66b98..000000000000 --- a/drivers/usb/gadget/udc/gadget_chips.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * USB device controllers have lots of quirks. Use these macros in - * gadget drivers or other code that needs to deal with them, and which - * autoconfigures instead of using early binding to the hardware. - * - * This SHOULD eventually work like the ARM mach_is_*() stuff, driven by - * some config file that gets updated as new hardware is supported. - * (And avoiding all runtime comparisons in typical one-choice configs!) - * - * NOTE: some of these controller drivers may not be available yet. - * Some are available on 2.4 kernels; several are available, but not - * yet pushed in the 2.6 mainline tree. - */ - -#ifndef __GADGET_CHIPS_H -#define __GADGET_CHIPS_H - -#include - -/* - * NOTICE: the entries below are alphabetical and should be kept - * that way. - * - * Always be sure to add new entries to the correct position or - * accept the bashing later. - * - * If you have forgotten the alphabetical order let VIM/EMACS - * do that for you. - */ -#define gadget_is_at91(g) (!strcmp("at91_udc", (g)->name)) -#define gadget_is_goku(g) (!strcmp("goku_udc", (g)->name)) -#define gadget_is_musbhdrc(g) (!strcmp("musb-hdrc", (g)->name)) -#define gadget_is_net2280(g) (!strcmp("net2280", (g)->name)) -#define gadget_is_pxa(g) (!strcmp("pxa25x_udc", (g)->name)) -#define gadget_is_pxa27x(g) (!strcmp("pxa27x_udc", (g)->name)) - -/** - * gadget_supports_altsettings - return true if altsettings work - * @gadget: the gadget in question - */ -static inline bool gadget_supports_altsettings(struct usb_gadget *gadget) -{ - /* PXA 21x/25x/26x has no altsettings at all */ - if (gadget_is_pxa(gadget)) - return false; - - /* PXA 27x and 3xx have *broken* altsetting support */ - if (gadget_is_pxa27x(gadget)) - return false; - - /* Everything else is *presumably* fine ... */ - return true; -} - -#endif /* __GADGET_CHIPS_H */ -- cgit v1.2.3 From 03840fad004ce8a56bc8b3bb60a2df10f6f9481e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 6 Aug 2015 10:47:16 -0500 Subject: usb: musb: gadget: remove remaining DMA ifdeferry Commit fb91cddc54e7 ("usb: musb: Remove DMA ifdef for musb_gadget.c short_packet") tried to remove DMA ifdeferry from musb_gadget.c but ended up leaving some around. Remove them so that when building kernels with all DMA engines enabled, we don't end up trying to allocte channels twice. Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 5f52bcb4bf78..cc503591b634 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -313,8 +313,7 @@ static void txstate(struct musb *musb, struct musb_request *req) /* MUSB_TXCSR_P_ISO is still set correctly */ -#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA) - { + if (musb_dma_inventra(musb) || musb_dma_ux500(musb)) { if (request_size < musb_ep->packet_sz) musb_ep->dma->desired_mode = 0; else @@ -365,7 +364,6 @@ static void txstate(struct musb *musb, struct musb_request *req) } } -#endif if (is_cppi_enabled(musb)) { /* program endpoint CSR first, then setup DMA */ csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY); @@ -641,8 +639,10 @@ static void rxstate(struct musb *musb, struct musb_request *req) use_mode_1 = 0; if (request->actual < request->length) { -#ifdef CONFIG_USB_INVENTRA_DMA - if (is_buffer_mapped(req)) { + if (!is_buffer_mapped(req)) + goto buffer_aint_mapped; + + if (musb_dma_inventra(musb)) { struct dma_controller *c; struct dma_channel *channel; int use_dma = 0; @@ -716,8 +716,8 @@ static void rxstate(struct musb *musb, struct musb_request *req) if (use_dma) return; } -#elif defined(CONFIG_USB_UX500_DMA) - if ((is_buffer_mapped(req)) && + + if ((musb_dma_ux500(musb)) && (request->actual < request->length)) { struct dma_controller *c; @@ -765,7 +765,6 @@ static void rxstate(struct musb *musb, struct musb_request *req) return; } -#endif /* Mentor's DMA */ len = request->length - request->actual; dev_dbg(musb->controller, "%s OUT/RX pio fifo %d/%d, maxpacket %d\n", @@ -775,8 +774,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) fifo_count = min_t(unsigned, len, fifo_count); -#ifdef CONFIG_USB_TUSB_OMAP_DMA - if (tusb_dma_omap(musb) && is_buffer_mapped(req)) { + if (tusb_dma_omap(musb)) { struct dma_controller *c = musb->dma_controller; struct dma_channel *channel = musb_ep->dma; u32 dma_addr = request->dma + request->actual; @@ -790,23 +788,22 @@ static void rxstate(struct musb *musb, struct musb_request *req) if (ret) return; } -#endif + /* * Unmap the dma buffer back to cpu if dma channel * programming fails. This buffer is mapped if the * channel allocation is successful */ - if (is_buffer_mapped(req)) { - unmap_dma_buffer(req, musb); - - /* - * Clear DMAENAB and AUTOCLEAR for the - * PIO mode transfer - */ - csr &= ~(MUSB_RXCSR_DMAENAB | MUSB_RXCSR_AUTOCLEAR); - musb_writew(epio, MUSB_RXCSR, csr); - } + unmap_dma_buffer(req, musb); + + /* + * Clear DMAENAB and AUTOCLEAR for the + * PIO mode transfer + */ + csr &= ~(MUSB_RXCSR_DMAENAB | MUSB_RXCSR_AUTOCLEAR); + musb_writew(epio, MUSB_RXCSR, csr); +buffer_aint_mapped: musb_read_fifo(musb_ep->hw_ep, fifo_count, (u8 *) (request->buf + request->actual)); request->actual += fifo_count; -- cgit v1.2.3 From b0a688ddcc5015eb26000c63841db7c46cfb380a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 6 Aug 2015 10:51:29 -0500 Subject: usb: musb: cppi41: allow it to work again since commit 33c300cb90a6 ("usb: musb: dsps: don't fake of_node to musb core") we have been preventing CPPI 4.1 from probing due to NULL of_node. We can't revert said commit otherwise a different regression would show up, so the fix is to look for the parent device's (glue layer's) of_node instead, since that's the thing which is actually described in DTS. Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_cppi41.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c index 4d1b44c232ee..d07cafb7d5f5 100644 --- a/drivers/usb/musb/musb_cppi41.c +++ b/drivers/usb/musb/musb_cppi41.c @@ -614,7 +614,7 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller) { struct musb *musb = controller->musb; struct device *dev = musb->controller; - struct device_node *np = dev->of_node; + struct device_node *np = dev->parent->of_node; struct cppi41_dma_channel *cppi41_channel; int count; int i; @@ -664,7 +664,7 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller) musb_dma->status = MUSB_DMA_STATUS_FREE; musb_dma->max_len = SZ_4M; - dc = dma_request_slave_channel(dev, str); + dc = dma_request_slave_channel(dev->parent, str); if (!dc) { dev_err(dev, "Failed to request %s.\n", str); ret = -EPROBE_DEFER; @@ -695,7 +695,7 @@ cppi41_dma_controller_create(struct musb *musb, void __iomem *base) struct cppi41_dma_controller *controller; int ret = 0; - if (!musb->controller->of_node) { + if (!musb->controller->parent->of_node) { dev_err(musb->controller, "Need DT for the DMA engine.\n"); return NULL; } -- cgit v1.2.3 From 4a1e9211809d4130fe23cad1bea222222d6e94f4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 6 Aug 2015 11:23:32 -0500 Subject: usb: gadget: f_mass_storage: add mising was originally being pulled indirectly through some other header, however it's not anymore, so we need to include it directly Reported-by: Jim Davis Suggested-by: Alan Stern Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_mass_storage.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 11a7f5aa955b..a6eb537d7768 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -214,6 +214,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From 2e8328fb87d02569511c4808a1b3f44f67bd83fd Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 6 Aug 2015 11:29:19 -0500 Subject: usb: gadget: legacy: nokia: add CONFIG_BLOCK dependency g_nokia now has mass_storage function, so it should depend on CONFIG_BLOCK. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/legacy/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig index ddef41f6df3e..4d682ad7bf23 100644 --- a/drivers/usb/gadget/legacy/Kconfig +++ b/drivers/usb/gadget/legacy/Kconfig @@ -339,6 +339,7 @@ config USB_CDC_COMPOSITE config USB_G_NOKIA tristate "Nokia composite gadget" depends on PHONET + depends on BLOCK select USB_LIBCOMPOSITE select USB_U_SERIAL select USB_U_ETHER -- cgit v1.2.3 From 2f3cc24f07b8bfe8302a46ceb1ed58cde62cbd09 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Fri, 7 Aug 2015 14:13:34 +0200 Subject: usb: musb: gadget: fix build break by adding missing 'break' Add missing break after 'default' label to fix compilation error. Signed-off-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index cc503591b634..67ad630c86c9 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1703,6 +1703,7 @@ static struct usb_ep *musb_match_ep(struct usb_gadget *g, ep = gadget_find_ep_by_name(g, "ep2out"); break; default: + break; } if (ep && usb_gadget_ep_match_desc(g, ep, desc, ep_comp)) -- cgit v1.2.3