From f6281af9d62e128aa6efad29cf7265062af114f2 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sat, 19 Dec 2015 00:34:33 +0800 Subject: usb: gadget: rndis: use list_for_each_entry_safe Use list_for_each_entry_safe() instead of list_for_each_safe() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/rndis.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c index 70d3917cc003..34a76db2c8fd 100644 --- a/drivers/usb/gadget/function/rndis.c +++ b/drivers/usb/gadget/function/rndis.c @@ -914,7 +914,7 @@ struct rndis_params *rndis_register(void (*resp_avail)(void *v), void *v) params->media_state = RNDIS_MEDIA_STATE_DISCONNECTED; params->resp_avail = resp_avail; params->v = v; - INIT_LIST_HEAD(&(params->resp_queue)); + INIT_LIST_HEAD(¶ms->resp_queue); pr_debug("%s: configNr = %d\n", __func__, i); return params; @@ -1006,12 +1006,9 @@ EXPORT_SYMBOL_GPL(rndis_add_hdr); void rndis_free_response(struct rndis_params *params, u8 *buf) { - rndis_resp_t *r; - struct list_head *act, *tmp; + rndis_resp_t *r, *n; - list_for_each_safe(act, tmp, &(params->resp_queue)) - { - r = list_entry(act, rndis_resp_t, list); + list_for_each_entry_safe(r, n, ¶ms->resp_queue, list) { if (r && r->buf == buf) { list_del(&r->list); kfree(r); @@ -1022,14 +1019,11 @@ EXPORT_SYMBOL_GPL(rndis_free_response); u8 *rndis_get_next_response(struct rndis_params *params, u32 *length) { - rndis_resp_t *r; - struct list_head *act, *tmp; + rndis_resp_t *r, *n; if (!length) return NULL; - list_for_each_safe(act, tmp, &(params->resp_queue)) - { - r = list_entry(act, rndis_resp_t, list); + list_for_each_entry_safe(r, n, ¶ms->resp_queue, list) { if (!r->send) { r->send = 1; *length = r->length; @@ -1053,7 +1047,7 @@ static rndis_resp_t *rndis_add_response(struct rndis_params *params, u32 length) r->length = length; r->send = 0; - list_add_tail(&r->list, &(params->resp_queue)); + list_add_tail(&r->list, ¶ms->resp_queue); return r; } -- cgit v1.2.3-70-g09d2 From 1c17a353c5a8346b1ce128c60ffb862d156f7e7e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 25 Jan 2016 16:21:54 +0100 Subject: usb: gadget: rndis: fix itnull.cocci warnings The index variable of list_for_each_entry_safe is an offset from a list pointer, and thus should not be NULL. Generated by: scripts/coccinelle/iterators/itnull.cocci CC: Geliang Tang Signed-off-by: Fengguang Wu Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/rndis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c index 34a76db2c8fd..943c21aafd3b 100644 --- a/drivers/usb/gadget/function/rndis.c +++ b/drivers/usb/gadget/function/rndis.c @@ -1009,7 +1009,7 @@ void rndis_free_response(struct rndis_params *params, u8 *buf) rndis_resp_t *r, *n; list_for_each_entry_safe(r, n, ¶ms->resp_queue, list) { - if (r && r->buf == buf) { + if (r->buf == buf) { list_del(&r->list); kfree(r); } -- cgit v1.2.3-70-g09d2 From 7562b75b214ce86215fc028183edd50df130042f Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:37 +0100 Subject: usb: add HAS_IOMEM dependency to USB_NET2272 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/usb/gadget/udc/net2272.c: In function ‘net2272_remove’: drivers/usb/gadget/udc/net2272.c:2232:2: error: implicit declaration of function ‘iounmap’ [-Werror=implicit-function-declaration] iounmap(dev->base_addr); ^ drivers/usb/gadget/udc/net2272.c: In function ‘net2272_plat_probe’: drivers/usb/gadget/udc/net2272.c:2650:2: error: implicit declaration of function ‘ioremap_nocache’ [-Werror=implicit-function-declaration] dev->base_addr = ioremap_nocache(base, len); ^ drivers/usb/gadget/udc/net2272.c:2650:17: warning: assignment makes pointer from integer without a cast [enabled by default] dev->base_addr = ioremap_nocache(base, len); ^ Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/udc/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index 753c29bd11ad..ca19f6f3197a 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig @@ -287,6 +287,7 @@ config USB_FSL_QE dynamically linked module called "fsl_qe_udc". config USB_NET2272 + depends on HAS_IOMEM tristate "PLX NET2272" help PLX NET2272 is a USB peripheral controller which supports -- cgit v1.2.3-70-g09d2 From be6708e6f2d13b26bfdc416b5bf31c942ccff72c Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:38 +0100 Subject: usb: Add HAS_IOMEM dependency to USB_M66592 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/usb/gadget/udc/m66592-udc.c: In function ‘m66592_remove’: drivers/usb/gadget/udc/m66592-udc.c:1538:2: error: implicit declaration of function ‘iounmap’ [-Werror=implicit-function-declaration] iounmap(m66592->reg); ^ drivers/usb/gadget/udc/m66592-udc.c: In function ‘m66592_probe’: drivers/usb/gadget/udc/m66592-udc.c:1577:2: error: implicit declaration of function ‘ioremap’ [-Werror=implicit-function-declaration] reg = ioremap(res->start, resource_size(res)); ^ drivers/usb/gadget/udc/m66592-udc.c:1577:6: warning: assignment makes pointer from integer without a cast [enabled by default] reg = ioremap(res->start, resource_size(res)); ^ Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/udc/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index ca19f6f3197a..e06efa3c3033 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig @@ -244,6 +244,7 @@ config USB_MV_U3D config USB_M66592 tristate "Renesas M66592 USB Peripheral Controller" + depends on HAS_IOMEM help M66592 is a discrete USB peripheral controller chip that supports both full and high speed USB 2.0 data transfers. -- cgit v1.2.3-70-g09d2 From 1b4ea40bbd87d963c9c6328b304aec4106ac8e89 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:49 +0100 Subject: usb: add HAS_IOMEM dependency to USB_PXA25X drivers/built-in.o: In function `pxa_udc_probe': /home/vegard/linux/drivers/usb/gadget/udc/pxa27x_udc.c:2430: undefined reference to `devm_ioremap_resource' Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/udc/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index e06efa3c3033..70feaf2a012d 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig @@ -128,6 +128,7 @@ config USB_OMAP config USB_PXA25X tristate "PXA 25x or IXP 4xx" depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX + depends on HAS_IOMEM help Intel's PXA 25x series XScale ARM-5TE processors include an integrated full speed USB 1.1 device controller. The -- cgit v1.2.3-70-g09d2 From c470ba38097b2e2adf695e4cfb8e5f6fa362e125 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:52 +0100 Subject: usb: add HAS_IOMEM dependency to USB_PXA27X drivers/built-in.o: In function `pxa_udc_probe': /home/vegard/linux/drivers/usb/gadget/udc/pxa27x_udc.c:2430: undefined reference to `devm_ioremap_resource' Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/udc/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index 70feaf2a012d..d6ad7e6c978c 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig @@ -188,6 +188,7 @@ config USB_RENESAS_USB3 config USB_PXA27X tristate "PXA 27x" + depends on HAS_IOMEM help Intel's PXA 27x series XScale ARM v5TE processors include an integrated full speed USB 1.1 device controller. -- cgit v1.2.3-70-g09d2 From 1a85329171094951956a37acc8abb7e51c1e742e Mon Sep 17 00:00:00 2001 From: John Youn Date: Fri, 5 Feb 2016 17:05:40 -0800 Subject: usb: gadget: composite: Return bcdUSB 0x0310 The USB 3.1 specification replaces the USB 3.0 specification and all new devices that are running at SuperSpeed or higher speeds must report a bcdUSB of 0x0310. Refer to USB 3.1 Specification, Revision 1.0, Section 9.6. Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 8b14c2a13ac5..ce5dbc59311d 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1499,7 +1499,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) cdev->gadget->ep0->maxpacket; if (gadget_is_superspeed(gadget)) { if (gadget->speed >= USB_SPEED_SUPER) { - cdev->desc.bcdUSB = cpu_to_le16(0x0300); + cdev->desc.bcdUSB = cpu_to_le16(0x0310); cdev->desc.bMaxPacketSize0 = 9; } else { cdev->desc.bcdUSB = cpu_to_le16(0x0210); -- cgit v1.2.3-70-g09d2 From f228a8de242a85659d9c86f2b9ff862775f015c2 Mon Sep 17 00:00:00 2001 From: John Youn Date: Fri, 5 Feb 2016 17:05:53 -0800 Subject: usb: gadget: composite: Return SSP Dev Cap descriptor If a gadget supports SuperSpeedPlus or higher speeds, return a SuperSpeedPlus USB Device Capability descriptor. Currently this implementation returns a fixed descriptor with typical values set. Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index ce5dbc59311d..11d243349ebf 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -597,6 +597,48 @@ static int bos_desc(struct usb_composite_dev *cdev) ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat; ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat; + /* The SuperSpeedPlus USB Device Capability descriptor */ + if (gadget_is_superspeed_plus(cdev->gadget)) { + struct usb_ssp_cap_descriptor *ssp_cap; + + ssp_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength); + bos->bNumDeviceCaps++; + + /* + * Report typical values. + */ + + le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SSP_CAP_SIZE(1)); + ssp_cap->bLength = USB_DT_USB_SSP_CAP_SIZE(1); + ssp_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY; + ssp_cap->bDevCapabilityType = USB_SSP_CAP_TYPE; + + /* SSAC = 1 (2 attributes) */ + ssp_cap->bmAttributes = cpu_to_le32(1); + + /* Min RX/TX Lane Count = 1 */ + ssp_cap->wFunctionalitySupport = (1 << 8) | (1 << 12); + + /* + * bmSublinkSpeedAttr[0]: + * ST = Symmetric, RX + * LSE = 3 (Gbps) + * LP = 1 (SuperSpeedPlus) + * LSM = 10 (10 Gbps) + */ + ssp_cap->bmSublinkSpeedAttr[0] = + (3 << 4) | (1 << 14) | (0xa << 16); + /* + * bmSublinkSpeedAttr[1] = + * ST = Symmetric, TX + * LSE = 3 (Gbps) + * LP = 1 (SuperSpeedPlus) + * LSM = 10 (10 Gbps) + */ + ssp_cap->bmSublinkSpeedAttr[1] = + (3 << 4) | (1 << 14) | (0xa << 16) | (1 << 7); + } + return le16_to_cpu(bos->wTotalLength); } -- cgit v1.2.3-70-g09d2 From eaef50c760576bca70b87fdc26eb87a3660529f8 Mon Sep 17 00:00:00 2001 From: John Youn Date: Fri, 5 Feb 2016 17:06:07 -0800 Subject: usb: gadget: Update usb_assign_descriptors for SuperSpeedPlus Add the 'ssp_descriptors' parameter to the usb_assign_descriptors() function. This allows a function driver to add descriptors for SuperSpeedPlus speeds if it supports it. Also update all uses of this function in the gadget subsystem so that they pass NULL for the ssp_descriptors parameters. Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/gadget/config.c | 3 ++- drivers/usb/gadget/function/f_acm.c | 2 +- drivers/usb/gadget/function/f_ecm.c | 2 +- drivers/usb/gadget/function/f_eem.c | 2 +- drivers/usb/gadget/function/f_hid.c | 2 +- drivers/usb/gadget/function/f_loopback.c | 2 +- drivers/usb/gadget/function/f_mass_storage.c | 2 +- drivers/usb/gadget/function/f_ncm.c | 2 +- drivers/usb/gadget/function/f_obex.c | 3 ++- drivers/usb/gadget/function/f_phonet.c | 2 +- drivers/usb/gadget/function/f_printer.c | 2 +- drivers/usb/gadget/function/f_rndis.c | 2 +- drivers/usb/gadget/function/f_serial.c | 2 +- drivers/usb/gadget/function/f_sourcesink.c | 2 +- drivers/usb/gadget/function/f_subset.c | 2 +- drivers/usb/gadget/function/f_tcm.c | 2 +- drivers/usb/gadget/function/f_uac1.c | 3 ++- drivers/usb/gadget/function/f_uac2.c | 3 ++- include/linux/usb/gadget.h | 3 ++- 19 files changed, 24 insertions(+), 19 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c index 0fafa7a1b6f6..62ba4c1b69ec 100644 --- a/drivers/usb/gadget/config.c +++ b/drivers/usb/gadget/config.c @@ -163,7 +163,8 @@ EXPORT_SYMBOL_GPL(usb_copy_descriptors); int usb_assign_descriptors(struct usb_function *f, struct usb_descriptor_header **fs, struct usb_descriptor_header **hs, - struct usb_descriptor_header **ss) + struct usb_descriptor_header **ss, + struct usb_descriptor_header **ssp) { struct usb_gadget *g = f->config->cdev->gadget; diff --git a/drivers/usb/gadget/function/f_acm.c b/drivers/usb/gadget/function/f_acm.c index 2fa1e80a3ce7..dc13b280db28 100644 --- a/drivers/usb/gadget/function/f_acm.c +++ b/drivers/usb/gadget/function/f_acm.c @@ -685,7 +685,7 @@ acm_bind(struct usb_configuration *c, struct usb_function *f) acm_ss_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress; status = usb_assign_descriptors(f, acm_fs_function, acm_hs_function, - acm_ss_function); + acm_ss_function, NULL); if (status) goto fail; diff --git a/drivers/usb/gadget/function/f_ecm.c b/drivers/usb/gadget/function/f_ecm.c index 7ad60ee41914..4c488d15b6f6 100644 --- a/drivers/usb/gadget/function/f_ecm.c +++ b/drivers/usb/gadget/function/f_ecm.c @@ -786,7 +786,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f) fs_ecm_notify_desc.bEndpointAddress; status = usb_assign_descriptors(f, ecm_fs_function, ecm_hs_function, - ecm_ss_function); + ecm_ss_function, NULL); if (status) goto fail; diff --git a/drivers/usb/gadget/function/f_eem.c b/drivers/usb/gadget/function/f_eem.c index cad35a502d3f..d58bfc32be9e 100644 --- a/drivers/usb/gadget/function/f_eem.c +++ b/drivers/usb/gadget/function/f_eem.c @@ -309,7 +309,7 @@ static int eem_bind(struct usb_configuration *c, struct usb_function *f) eem_ss_out_desc.bEndpointAddress = eem_fs_out_desc.bEndpointAddress; status = usb_assign_descriptors(f, eem_fs_function, eem_hs_function, - eem_ss_function); + eem_ss_function, NULL); if (status) goto fail; diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index 99285b416308..51980c50546d 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -646,7 +646,7 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) hidg_fs_out_ep_desc.bEndpointAddress; status = usb_assign_descriptors(f, hidg_fs_descriptors, - hidg_hs_descriptors, NULL); + hidg_hs_descriptors, NULL, NULL); if (status) goto fail; diff --git a/drivers/usb/gadget/function/f_loopback.c b/drivers/usb/gadget/function/f_loopback.c index ddc3aad886b7..3a9f8f9c77bd 100644 --- a/drivers/usb/gadget/function/f_loopback.c +++ b/drivers/usb/gadget/function/f_loopback.c @@ -211,7 +211,7 @@ autoconf_fail: ss_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress; ret = usb_assign_descriptors(f, fs_loopback_descs, hs_loopback_descs, - ss_loopback_descs); + ss_loopback_descs, NULL); if (ret) return ret; diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 223ccf89d226..321a6315c696 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -3093,7 +3093,7 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst; ret = usb_assign_descriptors(f, fsg_fs_function, fsg_hs_function, - fsg_ss_function); + fsg_ss_function, NULL); if (ret) goto autoconf_fail; diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index 7ad798ace1e5..97f0a9bc84df 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -1432,7 +1432,7 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f) fs_ncm_notify_desc.bEndpointAddress; status = usb_assign_descriptors(f, ncm_fs_function, ncm_hs_function, - NULL); + NULL, NULL); if (status) goto fail; diff --git a/drivers/usb/gadget/function/f_obex.c b/drivers/usb/gadget/function/f_obex.c index d6396e0909ee..d43e86cea74f 100644 --- a/drivers/usb/gadget/function/f_obex.c +++ b/drivers/usb/gadget/function/f_obex.c @@ -364,7 +364,8 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f) obex_hs_ep_out_desc.bEndpointAddress = obex_fs_ep_out_desc.bEndpointAddress; - status = usb_assign_descriptors(f, fs_function, hs_function, NULL); + status = usb_assign_descriptors(f, fs_function, hs_function, NULL, + NULL); if (status) goto fail; diff --git a/drivers/usb/gadget/function/f_phonet.c b/drivers/usb/gadget/function/f_phonet.c index 157441dbfeba..0473d619d5bf 100644 --- a/drivers/usb/gadget/function/f_phonet.c +++ b/drivers/usb/gadget/function/f_phonet.c @@ -541,7 +541,7 @@ static int pn_bind(struct usb_configuration *c, struct usb_function *f) /* Do not try to bind Phonet twice... */ status = usb_assign_descriptors(f, fs_pn_function, hs_pn_function, - NULL); + NULL, NULL); if (status) goto err; diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index 26ccad5d8680..c45104e3a64b 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c @@ -1051,7 +1051,7 @@ autoconf_fail: ss_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress; ret = usb_assign_descriptors(f, fs_printer_function, - hs_printer_function, ss_printer_function); + hs_printer_function, ss_printer_function, NULL); if (ret) return ret; diff --git a/drivers/usb/gadget/function/f_rndis.c b/drivers/usb/gadget/function/f_rndis.c index e587767e374c..d99dd9542048 100644 --- a/drivers/usb/gadget/function/f_rndis.c +++ b/drivers/usb/gadget/function/f_rndis.c @@ -783,7 +783,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) ss_notify_desc.bEndpointAddress = fs_notify_desc.bEndpointAddress; status = usb_assign_descriptors(f, eth_fs_function, eth_hs_function, - eth_ss_function); + eth_ss_function, NULL); if (status) goto fail; diff --git a/drivers/usb/gadget/function/f_serial.c b/drivers/usb/gadget/function/f_serial.c index 6bb44d613bab..cb00ada21d9c 100644 --- a/drivers/usb/gadget/function/f_serial.c +++ b/drivers/usb/gadget/function/f_serial.c @@ -236,7 +236,7 @@ static int gser_bind(struct usb_configuration *c, struct usb_function *f) gser_ss_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress; status = usb_assign_descriptors(f, gser_fs_function, gser_hs_function, - gser_ss_function); + gser_ss_function, NULL); if (status) goto fail; dev_dbg(&cdev->gadget->dev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n", diff --git a/drivers/usb/gadget/function/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c index 242ba5caffe5..df0189ddfdd5 100644 --- a/drivers/usb/gadget/function/f_sourcesink.c +++ b/drivers/usb/gadget/function/f_sourcesink.c @@ -437,7 +437,7 @@ no_iso: ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress; ret = usb_assign_descriptors(f, fs_source_sink_descs, - hs_source_sink_descs, ss_source_sink_descs); + hs_source_sink_descs, ss_source_sink_descs, NULL); if (ret) return ret; diff --git a/drivers/usb/gadget/function/f_subset.c b/drivers/usb/gadget/function/f_subset.c index 829c78de9eba..434b983f3b4c 100644 --- a/drivers/usb/gadget/function/f_subset.c +++ b/drivers/usb/gadget/function/f_subset.c @@ -362,7 +362,7 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) fs_subset_out_desc.bEndpointAddress; status = usb_assign_descriptors(f, fs_eth_function, hs_eth_function, - ss_eth_function); + ss_eth_function, NULL); if (status) goto fail; diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c index bad007b5a190..dfb733047a4c 100644 --- a/drivers/usb/gadget/function/f_tcm.c +++ b/drivers/usb/gadget/function/f_tcm.c @@ -2098,7 +2098,7 @@ static int tcm_bind(struct usb_configuration *c, struct usb_function *f) uasp_fs_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress; ret = usb_assign_descriptors(f, uasp_fs_function_desc, - uasp_hs_function_desc, uasp_ss_function_desc); + uasp_hs_function_desc, uasp_ss_function_desc, NULL); if (ret) goto ep_fail; diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c index 6a2346b99f55..f2ac0cbc29a4 100644 --- a/drivers/usb/gadget/function/f_uac1.c +++ b/drivers/usb/gadget/function/f_uac1.c @@ -721,7 +721,8 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f) status = -ENOMEM; /* copy descriptors, and track endpoint copies */ - status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL); + status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL, + NULL); if (status) goto fail; return 0; diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 044ca79d3cb5..186d4b162524 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -1100,7 +1100,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; - ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL); + ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL, + NULL); if (ret) goto err; diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index d6a1bdaf11c1..42527297f218 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -1204,7 +1204,8 @@ struct usb_function; int usb_assign_descriptors(struct usb_function *f, struct usb_descriptor_header **fs, struct usb_descriptor_header **hs, - struct usb_descriptor_header **ss); + struct usb_descriptor_header **ss, + struct usb_descriptor_header **ssp); void usb_free_all_descriptors(struct usb_function *f); struct usb_descriptor_header *usb_otg_descriptor_alloc( -- cgit v1.2.3-70-g09d2 From f5c61225cf29c4f97e544ad7bd088256303acf97 Mon Sep 17 00:00:00 2001 From: John Youn Date: Fri, 5 Feb 2016 17:06:21 -0800 Subject: usb: gadget: Update function for SuperSpeedPlus Add a ssp_descriptors member to struct usb_function and handle the initialization and cleanup of it. This holds the SuperSpeedPlus descriptors for a function that supports SuperSpeedPlus. This is added by usb_assign_descriptors(). Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/gadget/config.c | 6 ++++++ include/linux/usb/composite.h | 5 +++++ 2 files changed, 11 insertions(+) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c index 62ba4c1b69ec..e6c0542a063b 100644 --- a/drivers/usb/gadget/config.c +++ b/drivers/usb/gadget/config.c @@ -183,6 +183,11 @@ int usb_assign_descriptors(struct usb_function *f, if (!f->ss_descriptors) goto err; } + if (ssp && gadget_is_superspeed_plus(g)) { + f->ssp_descriptors = usb_copy_descriptors(ssp); + if (!f->ssp_descriptors) + goto err; + } return 0; err: usb_free_all_descriptors(f); @@ -195,6 +200,7 @@ void usb_free_all_descriptors(struct usb_function *f) usb_free_descriptors(f->fs_descriptors); usb_free_descriptors(f->hs_descriptors); usb_free_descriptors(f->ss_descriptors); + usb_free_descriptors(f->ssp_descriptors); } EXPORT_SYMBOL_GPL(usb_free_all_descriptors); diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 1074b8921a5d..9ff1e465d307 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -126,6 +126,10 @@ struct usb_os_desc_table { * string identifiers assigned during @bind(). If this * pointer is null after initiation, the function will not * be available at super speed. + * @ssp_descriptors: Table of super speed plus descriptors, using + * interface and string identifiers assigned during @bind(). If + * this pointer is null after initiation, the function will not + * be available at super speed plus. * @config: assigned when @usb_add_function() is called; this is the * configuration with which this function is associated. * @os_desc_table: Table of (interface id, os descriptors) pairs. The function @@ -186,6 +190,7 @@ struct usb_function { struct usb_descriptor_header **fs_descriptors; struct usb_descriptor_header **hs_descriptors; struct usb_descriptor_header **ss_descriptors; + struct usb_descriptor_header **ssp_descriptors; struct usb_configuration *config; -- cgit v1.2.3-70-g09d2 From 554eead5436401ae3cfdb7d79fca24c14ebab143 Mon Sep 17 00:00:00 2001 From: John Youn Date: Fri, 5 Feb 2016 17:06:35 -0800 Subject: usb: gadget: Update config for SuperSpeedPlus When a function is added to a configuration with usb_add_function(), the configuration speed flags are updated. These flags indicate for which speeds the configuration is valid for. This patch adds a flag in the configuration for SuperSpeedPlus and also updates this based on the existence of ssp_descriptors. Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 2 ++ drivers/usb/gadget/configfs.c | 1 + include/linux/usb/composite.h | 1 + 3 files changed, 4 insertions(+) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 11d243349ebf..560330f5457c 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -237,6 +237,8 @@ int usb_add_function(struct usb_configuration *config, config->highspeed = true; if (!config->superspeed && function->ss_descriptors) config->superspeed = true; + if (!config->superspeed_plus && function->ssp_descriptors) + config->superspeed_plus = true; done: if (value) diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 590c44989e5e..c6cc15ebeed6 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -1229,6 +1229,7 @@ static void purge_configs_funcs(struct gadget_info *gi) } c->next_interface_id = 0; memset(c->interface, 0, sizeof(c->interface)); + c->superspeed_plus = 0; c->superspeed = 0; c->highspeed = 0; c->fullspeed = 0; diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 9ff1e465d307..2b81b24eb5aa 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -322,6 +322,7 @@ struct usb_configuration { unsigned superspeed:1; unsigned highspeed:1; unsigned fullspeed:1; + unsigned superspeed_plus:1; struct usb_function *interface[MAX_CONFIG_INTERFACES]; }; -- cgit v1.2.3-70-g09d2 From a4afd012f400b5b41e2db2b0bf7e384f738411ae Mon Sep 17 00:00:00 2001 From: John Youn Date: Fri, 5 Feb 2016 17:06:49 -0800 Subject: usb: gadget: composite: Count configs for SuperSpeedPlus If enumerated in SuperSpeedPlus, count the configurations that support it. Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 560330f5457c..44ad7aa6f8f1 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -511,18 +511,24 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type) unsigned count = 0; int hs = 0; int ss = 0; + int ssp = 0; if (gadget_is_dualspeed(gadget)) { if (gadget->speed == USB_SPEED_HIGH) hs = 1; if (gadget->speed == USB_SPEED_SUPER) ss = 1; + if (gadget->speed == USB_SPEED_SUPER_PLUS) + ssp = 1; if (type == USB_DT_DEVICE_QUALIFIER) hs = !hs; } list_for_each_entry(c, &cdev->configs, list) { /* ignore configs that won't work at this speed */ - if (ss) { + if (ssp) { + if (!c->superspeed_plus) + continue; + } else if (ss) { if (!c->superspeed) continue; } else if (hs) { -- cgit v1.2.3-70-g09d2 From f3bdbe36682631d5e13ef933670ef0b47d9aaa87 Mon Sep 17 00:00:00 2001 From: John Youn Date: Fri, 5 Feb 2016 17:07:03 -0800 Subject: usb: gadget: composite: Add function to get descriptors There are a couple places in the code that get the function descriptors based on the speed. Move this lookup into a function call and add support to handle the SuperSpeedPlus descriptors as well. Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 53 +++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 21 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 44ad7aa6f8f1..1d4f324e4bac 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -53,6 +53,36 @@ static struct usb_gadget_strings **get_containers_gs( return (struct usb_gadget_strings **)uc->stash; } +/** + * function_descriptors() - get function descriptors for speed + * @f: the function + * @speed: the speed + * + * Returns the descriptors or NULL if not set. + */ +static struct usb_descriptor_header ** +function_descriptors(struct usb_function *f, + enum usb_device_speed speed) +{ + struct usb_descriptor_header **descriptors; + + switch (speed) { + case USB_SPEED_SUPER_PLUS: + descriptors = f->ssp_descriptors; + break; + case USB_SPEED_SUPER: + descriptors = f->ss_descriptors; + break; + case USB_SPEED_HIGH: + descriptors = f->hs_descriptors; + break; + default: + descriptors = f->fs_descriptors; + } + + return descriptors; +} + /** * next_ep_desc() - advance to the next EP descriptor * @t: currect pointer within descriptor array @@ -419,17 +449,7 @@ static int config_buf(struct usb_configuration *config, list_for_each_entry(f, &config->functions, list) { struct usb_descriptor_header **descriptors; - switch (speed) { - case USB_SPEED_SUPER: - descriptors = f->ss_descriptors; - break; - case USB_SPEED_HIGH: - descriptors = f->hs_descriptors; - break; - default: - descriptors = f->fs_descriptors; - } - + descriptors = function_descriptors(f, speed); if (!descriptors) continue; status = usb_descriptor_fillbuf(next, len, @@ -740,16 +760,7 @@ static int set_config(struct usb_composite_dev *cdev, * function's setup callback instead of the current * configuration's setup callback. */ - switch (gadget->speed) { - case USB_SPEED_SUPER: - descriptors = f->ss_descriptors; - break; - case USB_SPEED_HIGH: - descriptors = f->hs_descriptors; - break; - default: - descriptors = f->fs_descriptors; - } + descriptors = function_descriptors(f, gadget->speed); for (; *descriptors; ++descriptors) { struct usb_endpoint_descriptor *ep; -- cgit v1.2.3-70-g09d2 From eae5820b852f2b434fc7734b5b1226bcc4ae9b92 Mon Sep 17 00:00:00 2001 From: John Youn Date: Fri, 5 Feb 2016 17:07:17 -0800 Subject: usb: gadget: composite: Write SuperSpeedPlus config descriptors Enable writing of SuperSpeedPlus descriptors for any SuperSpeedPlus capable configuration when connected in SuperSpeedPlus. Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 1d4f324e4bac..b938fcfee235 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -473,7 +473,7 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value) u8 type = w_value >> 8; enum usb_device_speed speed = USB_SPEED_UNKNOWN; - if (gadget->speed == USB_SPEED_SUPER) + if (gadget->speed >= USB_SPEED_SUPER) speed = gadget->speed; else if (gadget_is_dualspeed(gadget)) { int hs = 0; @@ -504,6 +504,10 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value) check_config: /* ignore configs that won't work at this speed */ switch (speed) { + case USB_SPEED_SUPER_PLUS: + if (!c->superspeed_plus) + continue; + break; case USB_SPEED_SUPER: if (!c->superspeed) continue; -- cgit v1.2.3-70-g09d2 From 4eb8e32dabef701e481ae18d7f5a4a6b850cccc9 Mon Sep 17 00:00:00 2001 From: John Youn Date: Fri, 5 Feb 2016 17:07:30 -0800 Subject: usb: gadget: composite: Configure the usb_ep for SuperSpeedPlus Configure the usb_ep using the SuperSpeedPlus descriptors if connected in SuperSpeedPlus. Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index b938fcfee235..60b6e4b4c7e5 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -148,6 +148,13 @@ int config_ep_by_speed(struct usb_gadget *g, /* select desired speed */ switch (g->speed) { + case USB_SPEED_SUPER_PLUS: + if (gadget_is_superspeed_plus(g)) { + speed_desc = f->ssp_descriptors; + want_comp_desc = 1; + break; + } + /* else: Fall trough */ case USB_SPEED_SUPER: if (gadget_is_superspeed(g)) { speed_desc = f->ss_descriptors; @@ -191,7 +198,7 @@ ep_found: (comp_desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP)) return -EIO; _ep->comp_desc = comp_desc; - if (g->speed == USB_SPEED_SUPER) { + if (g->speed >= USB_SPEED_SUPER) { switch (usb_endpoint_type(_ep->desc)) { case USB_ENDPOINT_XFER_ISOC: /* mult: bits 1:0 of bmAttributes */ -- cgit v1.2.3-70-g09d2 From cd69cbeb6977bbe5747b99b380007d7ec28f8095 Mon Sep 17 00:00:00 2001 From: John Youn Date: Fri, 5 Feb 2016 17:07:44 -0800 Subject: usb: gadget: composite: Update debug message for SuperSpeedPlus Update the debug message reporting the speeds that a configuration supports for SuperSpeedPlus. Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 60b6e4b4c7e5..64ad1bebb0fa 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -891,8 +891,9 @@ int usb_add_config(struct usb_composite_dev *cdev, } else { unsigned i; - DBG(cdev, "cfg %d/%p speeds:%s%s%s\n", + DBG(cdev, "cfg %d/%p speeds:%s%s%s%s\n", config->bConfigurationValue, config, + config->superspeed_plus ? " superplus" : "", config->superspeed ? " super" : "", config->highspeed ? " high" : "", config->fullspeed -- cgit v1.2.3-70-g09d2 From 59a3cedf910da4f73296172481f72c6f292b2b3a Mon Sep 17 00:00:00 2001 From: John Youn Date: Fri, 5 Feb 2016 17:07:58 -0800 Subject: usb: gadget: f_mass_storage: Enable SuperSpeedPlus Enable superspeed plus configuration for the mass storage gadget. The mass storage function doesn't do anything special for SuperSpeedPlus. Just pass in the same SuperSpeed descriptors for SuperSpeedPlus. Signed-off-by: John Youn 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/gadget') diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 321a6315c696..ee9390b07c17 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -3093,7 +3093,7 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst; ret = usb_assign_descriptors(f, fsg_fs_function, fsg_hs_function, - fsg_ss_function, NULL); + fsg_ss_function, fsg_ss_function); if (ret) goto autoconf_fail; -- cgit v1.2.3-70-g09d2 From c5418a0b98c1ff7ae6f3d0b248d9120368156f4a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 28 Jan 2016 17:17:02 +0100 Subject: usb: gadget: pxa25x_udc: move register definitions from arch ixp4xx and pxa25x both use this driver and provide a slightly different set of register definitions for it. Aside from that, the definition in the ixp4xx-regs.h header conflicts with the on in the pxa27x device driver when compile-testing that: In file included from ../drivers/usb/gadget/udc/pxa27x_udc.c:37:0: ../drivers/usb/gadget/udc/pxa27x_udc.h:26:0: warning: "UDCCR" redefined #define UDCCR 0x0000 /* UDC Control Register */ ^ In file included from ../arch/arm/mach-ixp4xx/include/mach/hardware.h:27:0, from ../arch/arm/mach-ixp4xx/include/mach/io.h:18, from ../arch/arm/include/asm/io.h:194, from ../include/linux/io.h:25, from ../include/linux/irq.h:24, from ../drivers/usb/gadget/udc/pxa27x_udc.c:23: ../arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h:415:0: note: this is the location of the previous definition #define UDCCR IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0000) This addresses both issues by moving all the definitions into the pxa25x_udc driver itself. It turns out the only difference between them was 'UDCCS_IO_ROF', and that could well be a mistake when it was incorrectly copied from pxa25x to ixp4xx. Acked-by: Krzysztof Halasa Acked-by: Robert Jarzmik Signed-off-by: Arnd Bergmann Signed-off-by: Felipe Balbi --- arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h | 198 ------------------------ arch/arm/mach-pxa/include/mach/pxa25x-udc.h | 163 ------------------- drivers/usb/gadget/udc/pxa25x_udc.c | 161 ++++++++++++++++++- 3 files changed, 155 insertions(+), 367 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h index c5bae9c035d5..b7ddd27419c2 100644 --- a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h +++ b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h @@ -395,204 +395,6 @@ #define CRP_AD_CBE_BESL 20 #define CRP_AD_CBE_WRITE 0x00010000 - -/* - * USB Device Controller - * - * These are used by the USB gadget driver, so they don't follow the - * IXP4XX_ naming convetions. - * - */ -# define IXP4XX_USB_REG(x) (*((volatile u32 *)(x))) - -/* UDC Undocumented - Reserved1 */ -#define UDC_RES1 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0004) -/* UDC Undocumented - Reserved2 */ -#define UDC_RES2 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0008) -/* UDC Undocumented - Reserved3 */ -#define UDC_RES3 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x000C) -/* UDC Control Register */ -#define UDCCR IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0000) -/* UDC Endpoint 0 Control/Status Register */ -#define UDCCS0 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0010) -/* UDC Endpoint 1 (IN) Control/Status Register */ -#define UDCCS1 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0014) -/* UDC Endpoint 2 (OUT) Control/Status Register */ -#define UDCCS2 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0018) -/* UDC Endpoint 3 (IN) Control/Status Register */ -#define UDCCS3 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x001C) -/* UDC Endpoint 4 (OUT) Control/Status Register */ -#define UDCCS4 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0020) -/* UDC Endpoint 5 (Interrupt) Control/Status Register */ -#define UDCCS5 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0024) -/* UDC Endpoint 6 (IN) Control/Status Register */ -#define UDCCS6 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0028) -/* UDC Endpoint 7 (OUT) Control/Status Register */ -#define UDCCS7 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x002C) -/* UDC Endpoint 8 (IN) Control/Status Register */ -#define UDCCS8 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0030) -/* UDC Endpoint 9 (OUT) Control/Status Register */ -#define UDCCS9 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0034) -/* UDC Endpoint 10 (Interrupt) Control/Status Register */ -#define UDCCS10 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0038) -/* UDC Endpoint 11 (IN) Control/Status Register */ -#define UDCCS11 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x003C) -/* UDC Endpoint 12 (OUT) Control/Status Register */ -#define UDCCS12 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0040) -/* UDC Endpoint 13 (IN) Control/Status Register */ -#define UDCCS13 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0044) -/* UDC Endpoint 14 (OUT) Control/Status Register */ -#define UDCCS14 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0048) -/* UDC Endpoint 15 (Interrupt) Control/Status Register */ -#define UDCCS15 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x004C) -/* UDC Frame Number Register High */ -#define UFNRH IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0060) -/* UDC Frame Number Register Low */ -#define UFNRL IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0064) -/* UDC Byte Count Reg 2 */ -#define UBCR2 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0068) -/* UDC Byte Count Reg 4 */ -#define UBCR4 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x006c) -/* UDC Byte Count Reg 7 */ -#define UBCR7 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0070) -/* UDC Byte Count Reg 9 */ -#define UBCR9 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0074) -/* UDC Byte Count Reg 12 */ -#define UBCR12 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0078) -/* UDC Byte Count Reg 14 */ -#define UBCR14 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x007c) -/* UDC Endpoint 0 Data Register */ -#define UDDR0 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0080) -/* UDC Endpoint 1 Data Register */ -#define UDDR1 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0100) -/* UDC Endpoint 2 Data Register */ -#define UDDR2 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0180) -/* UDC Endpoint 3 Data Register */ -#define UDDR3 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0200) -/* UDC Endpoint 4 Data Register */ -#define UDDR4 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0400) -/* UDC Endpoint 5 Data Register */ -#define UDDR5 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x00A0) -/* UDC Endpoint 6 Data Register */ -#define UDDR6 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0600) -/* UDC Endpoint 7 Data Register */ -#define UDDR7 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0680) -/* UDC Endpoint 8 Data Register */ -#define UDDR8 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0700) -/* UDC Endpoint 9 Data Register */ -#define UDDR9 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0900) -/* UDC Endpoint 10 Data Register */ -#define UDDR10 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x00C0) -/* UDC Endpoint 11 Data Register */ -#define UDDR11 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0B00) -/* UDC Endpoint 12 Data Register */ -#define UDDR12 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0B80) -/* UDC Endpoint 13 Data Register */ -#define UDDR13 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0C00) -/* UDC Endpoint 14 Data Register */ -#define UDDR14 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0E00) -/* UDC Endpoint 15 Data Register */ -#define UDDR15 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x00E0) -/* UDC Interrupt Control Register 0 */ -#define UICR0 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0050) -/* UDC Interrupt Control Register 1 */ -#define UICR1 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0054) -/* UDC Status Interrupt Register 0 */ -#define USIR0 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0058) -/* UDC Status Interrupt Register 1 */ -#define USIR1 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x005C) - -#define UDCCR_UDE (1 << 0) /* UDC enable */ -#define UDCCR_UDA (1 << 1) /* UDC active */ -#define UDCCR_RSM (1 << 2) /* Device resume */ -#define UDCCR_RESIR (1 << 3) /* Resume interrupt request */ -#define UDCCR_SUSIR (1 << 4) /* Suspend interrupt request */ -#define UDCCR_SRM (1 << 5) /* Suspend/resume interrupt mask */ -#define UDCCR_RSTIR (1 << 6) /* Reset interrupt request */ -#define UDCCR_REM (1 << 7) /* Reset interrupt mask */ - -#define UDCCS0_OPR (1 << 0) /* OUT packet ready */ -#define UDCCS0_IPR (1 << 1) /* IN packet ready */ -#define UDCCS0_FTF (1 << 2) /* Flush Tx FIFO */ -#define UDCCS0_DRWF (1 << 3) /* Device remote wakeup feature */ -#define UDCCS0_SST (1 << 4) /* Sent stall */ -#define UDCCS0_FST (1 << 5) /* Force stall */ -#define UDCCS0_RNE (1 << 6) /* Receive FIFO no empty */ -#define UDCCS0_SA (1 << 7) /* Setup active */ - -#define UDCCS_BI_TFS (1 << 0) /* Transmit FIFO service */ -#define UDCCS_BI_TPC (1 << 1) /* Transmit packet complete */ -#define UDCCS_BI_FTF (1 << 2) /* Flush Tx FIFO */ -#define UDCCS_BI_TUR (1 << 3) /* Transmit FIFO underrun */ -#define UDCCS_BI_SST (1 << 4) /* Sent stall */ -#define UDCCS_BI_FST (1 << 5) /* Force stall */ -#define UDCCS_BI_TSP (1 << 7) /* Transmit short packet */ - -#define UDCCS_BO_RFS (1 << 0) /* Receive FIFO service */ -#define UDCCS_BO_RPC (1 << 1) /* Receive packet complete */ -#define UDCCS_BO_DME (1 << 3) /* DMA enable */ -#define UDCCS_BO_SST (1 << 4) /* Sent stall */ -#define UDCCS_BO_FST (1 << 5) /* Force stall */ -#define UDCCS_BO_RNE (1 << 6) /* Receive FIFO not empty */ -#define UDCCS_BO_RSP (1 << 7) /* Receive short packet */ - -#define UDCCS_II_TFS (1 << 0) /* Transmit FIFO service */ -#define UDCCS_II_TPC (1 << 1) /* Transmit packet complete */ -#define UDCCS_II_FTF (1 << 2) /* Flush Tx FIFO */ -#define UDCCS_II_TUR (1 << 3) /* Transmit FIFO underrun */ -#define UDCCS_II_TSP (1 << 7) /* Transmit short packet */ - -#define UDCCS_IO_RFS (1 << 0) /* Receive FIFO service */ -#define UDCCS_IO_RPC (1 << 1) /* Receive packet complete */ -#define UDCCS_IO_ROF (1 << 3) /* Receive overflow */ -#define UDCCS_IO_DME (1 << 3) /* DMA enable */ -#define UDCCS_IO_RNE (1 << 6) /* Receive FIFO not empty */ -#define UDCCS_IO_RSP (1 << 7) /* Receive short packet */ - -#define UDCCS_INT_TFS (1 << 0) /* Transmit FIFO service */ -#define UDCCS_INT_TPC (1 << 1) /* Transmit packet complete */ -#define UDCCS_INT_FTF (1 << 2) /* Flush Tx FIFO */ -#define UDCCS_INT_TUR (1 << 3) /* Transmit FIFO underrun */ -#define UDCCS_INT_SST (1 << 4) /* Sent stall */ -#define UDCCS_INT_FST (1 << 5) /* Force stall */ -#define UDCCS_INT_TSP (1 << 7) /* Transmit short packet */ - -#define UICR0_IM0 (1 << 0) /* Interrupt mask ep 0 */ -#define UICR0_IM1 (1 << 1) /* Interrupt mask ep 1 */ -#define UICR0_IM2 (1 << 2) /* Interrupt mask ep 2 */ -#define UICR0_IM3 (1 << 3) /* Interrupt mask ep 3 */ -#define UICR0_IM4 (1 << 4) /* Interrupt mask ep 4 */ -#define UICR0_IM5 (1 << 5) /* Interrupt mask ep 5 */ -#define UICR0_IM6 (1 << 6) /* Interrupt mask ep 6 */ -#define UICR0_IM7 (1 << 7) /* Interrupt mask ep 7 */ - -#define UICR1_IM8 (1 << 0) /* Interrupt mask ep 8 */ -#define UICR1_IM9 (1 << 1) /* Interrupt mask ep 9 */ -#define UICR1_IM10 (1 << 2) /* Interrupt mask ep 10 */ -#define UICR1_IM11 (1 << 3) /* Interrupt mask ep 11 */ -#define UICR1_IM12 (1 << 4) /* Interrupt mask ep 12 */ -#define UICR1_IM13 (1 << 5) /* Interrupt mask ep 13 */ -#define UICR1_IM14 (1 << 6) /* Interrupt mask ep 14 */ -#define UICR1_IM15 (1 << 7) /* Interrupt mask ep 15 */ - -#define USIR0_IR0 (1 << 0) /* Interrupt request ep 0 */ -#define USIR0_IR1 (1 << 1) /* Interrupt request ep 1 */ -#define USIR0_IR2 (1 << 2) /* Interrupt request ep 2 */ -#define USIR0_IR3 (1 << 3) /* Interrupt request ep 3 */ -#define USIR0_IR4 (1 << 4) /* Interrupt request ep 4 */ -#define USIR0_IR5 (1 << 5) /* Interrupt request ep 5 */ -#define USIR0_IR6 (1 << 6) /* Interrupt request ep 6 */ -#define USIR0_IR7 (1 << 7) /* Interrupt request ep 7 */ - -#define USIR1_IR8 (1 << 0) /* Interrupt request ep 8 */ -#define USIR1_IR9 (1 << 1) /* Interrupt request ep 9 */ -#define USIR1_IR10 (1 << 2) /* Interrupt request ep 10 */ -#define USIR1_IR11 (1 << 3) /* Interrupt request ep 11 */ -#define USIR1_IR12 (1 << 4) /* Interrupt request ep 12 */ -#define USIR1_IR13 (1 << 5) /* Interrupt request ep 13 */ -#define USIR1_IR14 (1 << 6) /* Interrupt request ep 14 */ -#define USIR1_IR15 (1 << 7) /* Interrupt request ep 15 */ - #define DCMD_LENGTH 0x01fff /* length mask (max = 8K - 1) */ /* "fuse" bits of IXP_EXP_CFG2 */ diff --git a/arch/arm/mach-pxa/include/mach/pxa25x-udc.h b/arch/arm/mach-pxa/include/mach/pxa25x-udc.h index 1b80a4805a60..e69de29bb2d1 100644 --- a/arch/arm/mach-pxa/include/mach/pxa25x-udc.h +++ b/arch/arm/mach-pxa/include/mach/pxa25x-udc.h @@ -1,163 +0,0 @@ -#ifndef _ASM_ARCH_PXA25X_UDC_H -#define _ASM_ARCH_PXA25X_UDC_H - -#ifdef _ASM_ARCH_PXA27X_UDC_H -#error "You can't include both PXA25x and PXA27x UDC support" -#endif - -#define UDC_RES1 __REG(0x40600004) /* UDC Undocumented - Reserved1 */ -#define UDC_RES2 __REG(0x40600008) /* UDC Undocumented - Reserved2 */ -#define UDC_RES3 __REG(0x4060000C) /* UDC Undocumented - Reserved3 */ - -#define UDCCR __REG(0x40600000) /* UDC Control Register */ -#define UDCCR_UDE (1 << 0) /* UDC enable */ -#define UDCCR_UDA (1 << 1) /* UDC active */ -#define UDCCR_RSM (1 << 2) /* Device resume */ -#define UDCCR_RESIR (1 << 3) /* Resume interrupt request */ -#define UDCCR_SUSIR (1 << 4) /* Suspend interrupt request */ -#define UDCCR_SRM (1 << 5) /* Suspend/resume interrupt mask */ -#define UDCCR_RSTIR (1 << 6) /* Reset interrupt request */ -#define UDCCR_REM (1 << 7) /* Reset interrupt mask */ - -#define UDCCS0 __REG(0x40600010) /* UDC Endpoint 0 Control/Status Register */ -#define UDCCS0_OPR (1 << 0) /* OUT packet ready */ -#define UDCCS0_IPR (1 << 1) /* IN packet ready */ -#define UDCCS0_FTF (1 << 2) /* Flush Tx FIFO */ -#define UDCCS0_DRWF (1 << 3) /* Device remote wakeup feature */ -#define UDCCS0_SST (1 << 4) /* Sent stall */ -#define UDCCS0_FST (1 << 5) /* Force stall */ -#define UDCCS0_RNE (1 << 6) /* Receive FIFO no empty */ -#define UDCCS0_SA (1 << 7) /* Setup active */ - -/* Bulk IN - Endpoint 1,6,11 */ -#define UDCCS1 __REG(0x40600014) /* UDC Endpoint 1 (IN) Control/Status Register */ -#define UDCCS6 __REG(0x40600028) /* UDC Endpoint 6 (IN) Control/Status Register */ -#define UDCCS11 __REG(0x4060003C) /* UDC Endpoint 11 (IN) Control/Status Register */ - -#define UDCCS_BI_TFS (1 << 0) /* Transmit FIFO service */ -#define UDCCS_BI_TPC (1 << 1) /* Transmit packet complete */ -#define UDCCS_BI_FTF (1 << 2) /* Flush Tx FIFO */ -#define UDCCS_BI_TUR (1 << 3) /* Transmit FIFO underrun */ -#define UDCCS_BI_SST (1 << 4) /* Sent stall */ -#define UDCCS_BI_FST (1 << 5) /* Force stall */ -#define UDCCS_BI_TSP (1 << 7) /* Transmit short packet */ - -/* Bulk OUT - Endpoint 2,7,12 */ -#define UDCCS2 __REG(0x40600018) /* UDC Endpoint 2 (OUT) Control/Status Register */ -#define UDCCS7 __REG(0x4060002C) /* UDC Endpoint 7 (OUT) Control/Status Register */ -#define UDCCS12 __REG(0x40600040) /* UDC Endpoint 12 (OUT) Control/Status Register */ - -#define UDCCS_BO_RFS (1 << 0) /* Receive FIFO service */ -#define UDCCS_BO_RPC (1 << 1) /* Receive packet complete */ -#define UDCCS_BO_DME (1 << 3) /* DMA enable */ -#define UDCCS_BO_SST (1 << 4) /* Sent stall */ -#define UDCCS_BO_FST (1 << 5) /* Force stall */ -#define UDCCS_BO_RNE (1 << 6) /* Receive FIFO not empty */ -#define UDCCS_BO_RSP (1 << 7) /* Receive short packet */ - -/* Isochronous IN - Endpoint 3,8,13 */ -#define UDCCS3 __REG(0x4060001C) /* UDC Endpoint 3 (IN) Control/Status Register */ -#define UDCCS8 __REG(0x40600030) /* UDC Endpoint 8 (IN) Control/Status Register */ -#define UDCCS13 __REG(0x40600044) /* UDC Endpoint 13 (IN) Control/Status Register */ - -#define UDCCS_II_TFS (1 << 0) /* Transmit FIFO service */ -#define UDCCS_II_TPC (1 << 1) /* Transmit packet complete */ -#define UDCCS_II_FTF (1 << 2) /* Flush Tx FIFO */ -#define UDCCS_II_TUR (1 << 3) /* Transmit FIFO underrun */ -#define UDCCS_II_TSP (1 << 7) /* Transmit short packet */ - -/* Isochronous OUT - Endpoint 4,9,14 */ -#define UDCCS4 __REG(0x40600020) /* UDC Endpoint 4 (OUT) Control/Status Register */ -#define UDCCS9 __REG(0x40600034) /* UDC Endpoint 9 (OUT) Control/Status Register */ -#define UDCCS14 __REG(0x40600048) /* UDC Endpoint 14 (OUT) Control/Status Register */ - -#define UDCCS_IO_RFS (1 << 0) /* Receive FIFO service */ -#define UDCCS_IO_RPC (1 << 1) /* Receive packet complete */ -#define UDCCS_IO_ROF (1 << 2) /* Receive overflow */ -#define UDCCS_IO_DME (1 << 3) /* DMA enable */ -#define UDCCS_IO_RNE (1 << 6) /* Receive FIFO not empty */ -#define UDCCS_IO_RSP (1 << 7) /* Receive short packet */ - -/* Interrupt IN - Endpoint 5,10,15 */ -#define UDCCS5 __REG(0x40600024) /* UDC Endpoint 5 (Interrupt) Control/Status Register */ -#define UDCCS10 __REG(0x40600038) /* UDC Endpoint 10 (Interrupt) Control/Status Register */ -#define UDCCS15 __REG(0x4060004C) /* UDC Endpoint 15 (Interrupt) Control/Status Register */ - -#define UDCCS_INT_TFS (1 << 0) /* Transmit FIFO service */ -#define UDCCS_INT_TPC (1 << 1) /* Transmit packet complete */ -#define UDCCS_INT_FTF (1 << 2) /* Flush Tx FIFO */ -#define UDCCS_INT_TUR (1 << 3) /* Transmit FIFO underrun */ -#define UDCCS_INT_SST (1 << 4) /* Sent stall */ -#define UDCCS_INT_FST (1 << 5) /* Force stall */ -#define UDCCS_INT_TSP (1 << 7) /* Transmit short packet */ - -#define UFNRH __REG(0x40600060) /* UDC Frame Number Register High */ -#define UFNRL __REG(0x40600064) /* UDC Frame Number Register Low */ -#define UBCR2 __REG(0x40600068) /* UDC Byte Count Reg 2 */ -#define UBCR4 __REG(0x4060006c) /* UDC Byte Count Reg 4 */ -#define UBCR7 __REG(0x40600070) /* UDC Byte Count Reg 7 */ -#define UBCR9 __REG(0x40600074) /* UDC Byte Count Reg 9 */ -#define UBCR12 __REG(0x40600078) /* UDC Byte Count Reg 12 */ -#define UBCR14 __REG(0x4060007c) /* UDC Byte Count Reg 14 */ -#define UDDR0 __REG(0x40600080) /* UDC Endpoint 0 Data Register */ -#define UDDR1 __REG(0x40600100) /* UDC Endpoint 1 Data Register */ -#define UDDR2 __REG(0x40600180) /* UDC Endpoint 2 Data Register */ -#define UDDR3 __REG(0x40600200) /* UDC Endpoint 3 Data Register */ -#define UDDR4 __REG(0x40600400) /* UDC Endpoint 4 Data Register */ -#define UDDR5 __REG(0x406000A0) /* UDC Endpoint 5 Data Register */ -#define UDDR6 __REG(0x40600600) /* UDC Endpoint 6 Data Register */ -#define UDDR7 __REG(0x40600680) /* UDC Endpoint 7 Data Register */ -#define UDDR8 __REG(0x40600700) /* UDC Endpoint 8 Data Register */ -#define UDDR9 __REG(0x40600900) /* UDC Endpoint 9 Data Register */ -#define UDDR10 __REG(0x406000C0) /* UDC Endpoint 10 Data Register */ -#define UDDR11 __REG(0x40600B00) /* UDC Endpoint 11 Data Register */ -#define UDDR12 __REG(0x40600B80) /* UDC Endpoint 12 Data Register */ -#define UDDR13 __REG(0x40600C00) /* UDC Endpoint 13 Data Register */ -#define UDDR14 __REG(0x40600E00) /* UDC Endpoint 14 Data Register */ -#define UDDR15 __REG(0x406000E0) /* UDC Endpoint 15 Data Register */ - -#define UICR0 __REG(0x40600050) /* UDC Interrupt Control Register 0 */ - -#define UICR0_IM0 (1 << 0) /* Interrupt mask ep 0 */ -#define UICR0_IM1 (1 << 1) /* Interrupt mask ep 1 */ -#define UICR0_IM2 (1 << 2) /* Interrupt mask ep 2 */ -#define UICR0_IM3 (1 << 3) /* Interrupt mask ep 3 */ -#define UICR0_IM4 (1 << 4) /* Interrupt mask ep 4 */ -#define UICR0_IM5 (1 << 5) /* Interrupt mask ep 5 */ -#define UICR0_IM6 (1 << 6) /* Interrupt mask ep 6 */ -#define UICR0_IM7 (1 << 7) /* Interrupt mask ep 7 */ - -#define UICR1 __REG(0x40600054) /* UDC Interrupt Control Register 1 */ - -#define UICR1_IM8 (1 << 0) /* Interrupt mask ep 8 */ -#define UICR1_IM9 (1 << 1) /* Interrupt mask ep 9 */ -#define UICR1_IM10 (1 << 2) /* Interrupt mask ep 10 */ -#define UICR1_IM11 (1 << 3) /* Interrupt mask ep 11 */ -#define UICR1_IM12 (1 << 4) /* Interrupt mask ep 12 */ -#define UICR1_IM13 (1 << 5) /* Interrupt mask ep 13 */ -#define UICR1_IM14 (1 << 6) /* Interrupt mask ep 14 */ -#define UICR1_IM15 (1 << 7) /* Interrupt mask ep 15 */ - -#define USIR0 __REG(0x40600058) /* UDC Status Interrupt Register 0 */ - -#define USIR0_IR0 (1 << 0) /* Interrupt request ep 0 */ -#define USIR0_IR1 (1 << 1) /* Interrupt request ep 1 */ -#define USIR0_IR2 (1 << 2) /* Interrupt request ep 2 */ -#define USIR0_IR3 (1 << 3) /* Interrupt request ep 3 */ -#define USIR0_IR4 (1 << 4) /* Interrupt request ep 4 */ -#define USIR0_IR5 (1 << 5) /* Interrupt request ep 5 */ -#define USIR0_IR6 (1 << 6) /* Interrupt request ep 6 */ -#define USIR0_IR7 (1 << 7) /* Interrupt request ep 7 */ - -#define USIR1 __REG(0x4060005C) /* UDC Status Interrupt Register 1 */ - -#define USIR1_IR8 (1 << 0) /* Interrupt request ep 8 */ -#define USIR1_IR9 (1 << 1) /* Interrupt request ep 9 */ -#define USIR1_IR10 (1 << 2) /* Interrupt request ep 10 */ -#define USIR1_IR11 (1 << 3) /* Interrupt request ep 11 */ -#define USIR1_IR12 (1 << 4) /* Interrupt request ep 12 */ -#define USIR1_IR13 (1 << 5) /* Interrupt request ep 13 */ -#define USIR1_IR14 (1 << 6) /* Interrupt request ep 14 */ -#define USIR1_IR15 (1 << 7) /* Interrupt request ep 15 */ - -#endif diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c index b82cb14850b6..26537f50374d 100644 --- a/drivers/usb/gadget/udc/pxa25x_udc.c +++ b/drivers/usb/gadget/udc/pxa25x_udc.c @@ -48,18 +48,167 @@ #include #include -/* - * This driver is PXA25x only. Grab the right register definitions. - */ -#ifdef CONFIG_ARCH_PXA -#include #include -#endif #ifdef CONFIG_ARCH_LUBBOCK #include #endif +#ifdef CONFIG_ARCH_IXP4XX +#define __UDC_REG(x) (*((volatile u32 *)(IXP4XX_USB_BASE_VIRT + (x)))) +#endif + +#ifdef CONFIG_ARCH_PXA +#define __UDC_REG(x) __REG(0x40600000 + (x)) +#endif + +#define UDCCR __UDC_REG(0x0000) /* UDC Control Register */ +#define UDC_RES1 __UDC_REG(0x0004) /* UDC Undocumented - Reserved1 */ +#define UDC_RES2 __UDC_REG(0x0008) /* UDC Undocumented - Reserved2 */ +#define UDC_RES3 __UDC_REG(0x000C) /* UDC Undocumented - Reserved3 */ +#define UDCCS0 __UDC_REG(0x0010) /* UDC Endpoint 0 Control/Status Register */ +#define UDCCS1 __UDC_REG(0x0014) /* UDC Endpoint 1 (IN) Control/Status Register */ +#define UDCCS2 __UDC_REG(0x0018) /* UDC Endpoint 2 (OUT) Control/Status Register */ +#define UDCCS3 __UDC_REG(0x001C) /* UDC Endpoint 3 (IN) Control/Status Register */ +#define UDCCS4 __UDC_REG(0x0020) /* UDC Endpoint 4 (OUT) Control/Status Register */ +#define UDCCS5 __UDC_REG(0x0024) /* UDC Endpoint 5 (Interrupt) Control/Status Register */ +#define UDCCS6 __UDC_REG(0x0028) /* UDC Endpoint 6 (IN) Control/Status Register */ +#define UDCCS7 __UDC_REG(0x002C) /* UDC Endpoint 7 (OUT) Control/Status Register */ +#define UDCCS8 __UDC_REG(0x0030) /* UDC Endpoint 8 (IN) Control/Status Register */ +#define UDCCS9 __UDC_REG(0x0034) /* UDC Endpoint 9 (OUT) Control/Status Register */ +#define UDCCS10 __UDC_REG(0x0038) /* UDC Endpoint 10 (Interrupt) Control/Status Register */ +#define UDCCS11 __UDC_REG(0x003C) /* UDC Endpoint 11 (IN) Control/Status Register */ +#define UDCCS12 __UDC_REG(0x0040) /* UDC Endpoint 12 (OUT) Control/Status Register */ +#define UDCCS13 __UDC_REG(0x0044) /* UDC Endpoint 13 (IN) Control/Status Register */ +#define UDCCS14 __UDC_REG(0x0048) /* UDC Endpoint 14 (OUT) Control/Status Register */ +#define UDCCS15 __UDC_REG(0x004C) /* UDC Endpoint 15 (Interrupt) Control/Status Register */ +#define UFNRH __UDC_REG(0x0060) /* UDC Frame Number Register High */ +#define UFNRL __UDC_REG(0x0064) /* UDC Frame Number Register Low */ +#define UBCR2 __UDC_REG(0x0068) /* UDC Byte Count Reg 2 */ +#define UBCR4 __UDC_REG(0x006c) /* UDC Byte Count Reg 4 */ +#define UBCR7 __UDC_REG(0x0070) /* UDC Byte Count Reg 7 */ +#define UBCR9 __UDC_REG(0x0074) /* UDC Byte Count Reg 9 */ +#define UBCR12 __UDC_REG(0x0078) /* UDC Byte Count Reg 12 */ +#define UBCR14 __UDC_REG(0x007c) /* UDC Byte Count Reg 14 */ +#define UDDR0 __UDC_REG(0x0080) /* UDC Endpoint 0 Data Register */ +#define UDDR1 __UDC_REG(0x0100) /* UDC Endpoint 1 Data Register */ +#define UDDR2 __UDC_REG(0x0180) /* UDC Endpoint 2 Data Register */ +#define UDDR3 __UDC_REG(0x0200) /* UDC Endpoint 3 Data Register */ +#define UDDR4 __UDC_REG(0x0400) /* UDC Endpoint 4 Data Register */ +#define UDDR5 __UDC_REG(0x00A0) /* UDC Endpoint 5 Data Register */ +#define UDDR6 __UDC_REG(0x0600) /* UDC Endpoint 6 Data Register */ +#define UDDR7 __UDC_REG(0x0680) /* UDC Endpoint 7 Data Register */ +#define UDDR8 __UDC_REG(0x0700) /* UDC Endpoint 8 Data Register */ +#define UDDR9 __UDC_REG(0x0900) /* UDC Endpoint 9 Data Register */ +#define UDDR10 __UDC_REG(0x00C0) /* UDC Endpoint 10 Data Register */ +#define UDDR11 __UDC_REG(0x0B00) /* UDC Endpoint 11 Data Register */ +#define UDDR12 __UDC_REG(0x0B80) /* UDC Endpoint 12 Data Register */ +#define UDDR13 __UDC_REG(0x0C00) /* UDC Endpoint 13 Data Register */ +#define UDDR14 __UDC_REG(0x0E00) /* UDC Endpoint 14 Data Register */ +#define UDDR15 __UDC_REG(0x00E0) /* UDC Endpoint 15 Data Register */ + +#define UICR0 __UDC_REG(0x0050) /* UDC Interrupt Control Register 0 */ +#define UICR1 __UDC_REG(0x0054) /* UDC Interrupt Control Register 1 */ + +#define USIR0 __UDC_REG(0x0058) /* UDC Status Interrupt Register 0 */ +#define USIR1 __UDC_REG(0x005C) /* UDC Status Interrupt Register 1 */ + +#define UDCCR_UDE (1 << 0) /* UDC enable */ +#define UDCCR_UDA (1 << 1) /* UDC active */ +#define UDCCR_RSM (1 << 2) /* Device resume */ +#define UDCCR_RESIR (1 << 3) /* Resume interrupt request */ +#define UDCCR_SUSIR (1 << 4) /* Suspend interrupt request */ +#define UDCCR_SRM (1 << 5) /* Suspend/resume interrupt mask */ +#define UDCCR_RSTIR (1 << 6) /* Reset interrupt request */ +#define UDCCR_REM (1 << 7) /* Reset interrupt mask */ + +#define UDCCS0_OPR (1 << 0) /* OUT packet ready */ +#define UDCCS0_IPR (1 << 1) /* IN packet ready */ +#define UDCCS0_FTF (1 << 2) /* Flush Tx FIFO */ +#define UDCCS0_DRWF (1 << 3) /* Device remote wakeup feature */ +#define UDCCS0_SST (1 << 4) /* Sent stall */ +#define UDCCS0_FST (1 << 5) /* Force stall */ +#define UDCCS0_RNE (1 << 6) /* Receive FIFO no empty */ +#define UDCCS0_SA (1 << 7) /* Setup active */ + +#define UDCCS_BI_TFS (1 << 0) /* Transmit FIFO service */ +#define UDCCS_BI_TPC (1 << 1) /* Transmit packet complete */ +#define UDCCS_BI_FTF (1 << 2) /* Flush Tx FIFO */ +#define UDCCS_BI_TUR (1 << 3) /* Transmit FIFO underrun */ +#define UDCCS_BI_SST (1 << 4) /* Sent stall */ +#define UDCCS_BI_FST (1 << 5) /* Force stall */ +#define UDCCS_BI_TSP (1 << 7) /* Transmit short packet */ + +#define UDCCS_BO_RFS (1 << 0) /* Receive FIFO service */ +#define UDCCS_BO_RPC (1 << 1) /* Receive packet complete */ +#define UDCCS_BO_DME (1 << 3) /* DMA enable */ +#define UDCCS_BO_SST (1 << 4) /* Sent stall */ +#define UDCCS_BO_FST (1 << 5) /* Force stall */ +#define UDCCS_BO_RNE (1 << 6) /* Receive FIFO not empty */ +#define UDCCS_BO_RSP (1 << 7) /* Receive short packet */ + +#define UDCCS_II_TFS (1 << 0) /* Transmit FIFO service */ +#define UDCCS_II_TPC (1 << 1) /* Transmit packet complete */ +#define UDCCS_II_FTF (1 << 2) /* Flush Tx FIFO */ +#define UDCCS_II_TUR (1 << 3) /* Transmit FIFO underrun */ +#define UDCCS_II_TSP (1 << 7) /* Transmit short packet */ + +#define UDCCS_IO_RFS (1 << 0) /* Receive FIFO service */ +#define UDCCS_IO_RPC (1 << 1) /* Receive packet complete */ +#ifdef CONFIG_ARCH_IXP4XX /* FIXME: is this right?, datasheed says '2' */ +#define UDCCS_IO_ROF (1 << 3) /* Receive overflow */ +#endif +#ifdef CONFIG_ARCH_PXA +#define UDCCS_IO_ROF (1 << 2) /* Receive overflow */ +#endif +#define UDCCS_IO_DME (1 << 3) /* DMA enable */ +#define UDCCS_IO_RNE (1 << 6) /* Receive FIFO not empty */ +#define UDCCS_IO_RSP (1 << 7) /* Receive short packet */ + +#define UDCCS_INT_TFS (1 << 0) /* Transmit FIFO service */ +#define UDCCS_INT_TPC (1 << 1) /* Transmit packet complete */ +#define UDCCS_INT_FTF (1 << 2) /* Flush Tx FIFO */ +#define UDCCS_INT_TUR (1 << 3) /* Transmit FIFO underrun */ +#define UDCCS_INT_SST (1 << 4) /* Sent stall */ +#define UDCCS_INT_FST (1 << 5) /* Force stall */ +#define UDCCS_INT_TSP (1 << 7) /* Transmit short packet */ + +#define UICR0_IM0 (1 << 0) /* Interrupt mask ep 0 */ +#define UICR0_IM1 (1 << 1) /* Interrupt mask ep 1 */ +#define UICR0_IM2 (1 << 2) /* Interrupt mask ep 2 */ +#define UICR0_IM3 (1 << 3) /* Interrupt mask ep 3 */ +#define UICR0_IM4 (1 << 4) /* Interrupt mask ep 4 */ +#define UICR0_IM5 (1 << 5) /* Interrupt mask ep 5 */ +#define UICR0_IM6 (1 << 6) /* Interrupt mask ep 6 */ +#define UICR0_IM7 (1 << 7) /* Interrupt mask ep 7 */ + +#define UICR1_IM8 (1 << 0) /* Interrupt mask ep 8 */ +#define UICR1_IM9 (1 << 1) /* Interrupt mask ep 9 */ +#define UICR1_IM10 (1 << 2) /* Interrupt mask ep 10 */ +#define UICR1_IM11 (1 << 3) /* Interrupt mask ep 11 */ +#define UICR1_IM12 (1 << 4) /* Interrupt mask ep 12 */ +#define UICR1_IM13 (1 << 5) /* Interrupt mask ep 13 */ +#define UICR1_IM14 (1 << 6) /* Interrupt mask ep 14 */ +#define UICR1_IM15 (1 << 7) /* Interrupt mask ep 15 */ + +#define USIR0_IR0 (1 << 0) /* Interrupt request ep 0 */ +#define USIR0_IR1 (1 << 1) /* Interrupt request ep 1 */ +#define USIR0_IR2 (1 << 2) /* Interrupt request ep 2 */ +#define USIR0_IR3 (1 << 3) /* Interrupt request ep 3 */ +#define USIR0_IR4 (1 << 4) /* Interrupt request ep 4 */ +#define USIR0_IR5 (1 << 5) /* Interrupt request ep 5 */ +#define USIR0_IR6 (1 << 6) /* Interrupt request ep 6 */ +#define USIR0_IR7 (1 << 7) /* Interrupt request ep 7 */ + +#define USIR1_IR8 (1 << 0) /* Interrupt request ep 8 */ +#define USIR1_IR9 (1 << 1) /* Interrupt request ep 9 */ +#define USIR1_IR10 (1 << 2) /* Interrupt request ep 10 */ +#define USIR1_IR11 (1 << 3) /* Interrupt request ep 11 */ +#define USIR1_IR12 (1 << 4) /* Interrupt request ep 12 */ +#define USIR1_IR13 (1 << 5) /* Interrupt request ep 13 */ +#define USIR1_IR14 (1 << 6) /* Interrupt request ep 14 */ +#define USIR1_IR15 (1 << 7) /* Interrupt request ep 15 */ + /* * This driver handles the USB Device Controller (UDC) in Intel's PXA 25x * series processors. The UDC for the IXP 4xx series is very similar. -- cgit v1.2.3-70-g09d2 From a77af20e9e67caf79bd961c3d12938051b2c560e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 28 Jan 2016 17:17:03 +0100 Subject: usb: gadget: pxa25x_udc cleanup This removes the dependency on the mach/hardware.h header file from the pxa25x_udc driver after the register definitions were already unified in the previous patch. Following the model of pxa27x_udc (and basically all other drivers in the kernel), we define the register numbers as offsets from the register base address and use accessor functions to read/write them. For the moment, this still leaves the direct pointer dereference in place, instead of using readl/writel, so this patch should not be changing the behavior of the driver, other than using ioremap() on the platform resource to replace the hardcoded virtual address pointers. Acked-by: Robert Jarzmik Signed-off-by: Arnd Bergmann Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/pxa25x_udc.c | 468 +++++++++++++++++++++--------------- drivers/usb/gadget/udc/pxa25x_udc.h | 10 +- 2 files changed, 275 insertions(+), 203 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c index 26537f50374d..5db429f3cfb2 100644 --- a/drivers/usb/gadget/udc/pxa25x_udc.c +++ b/drivers/usb/gadget/udc/pxa25x_udc.c @@ -48,70 +48,63 @@ #include #include -#include - #ifdef CONFIG_ARCH_LUBBOCK #include #endif -#ifdef CONFIG_ARCH_IXP4XX -#define __UDC_REG(x) (*((volatile u32 *)(IXP4XX_USB_BASE_VIRT + (x)))) -#endif - -#ifdef CONFIG_ARCH_PXA -#define __UDC_REG(x) __REG(0x40600000 + (x)) -#endif - -#define UDCCR __UDC_REG(0x0000) /* UDC Control Register */ -#define UDC_RES1 __UDC_REG(0x0004) /* UDC Undocumented - Reserved1 */ -#define UDC_RES2 __UDC_REG(0x0008) /* UDC Undocumented - Reserved2 */ -#define UDC_RES3 __UDC_REG(0x000C) /* UDC Undocumented - Reserved3 */ -#define UDCCS0 __UDC_REG(0x0010) /* UDC Endpoint 0 Control/Status Register */ -#define UDCCS1 __UDC_REG(0x0014) /* UDC Endpoint 1 (IN) Control/Status Register */ -#define UDCCS2 __UDC_REG(0x0018) /* UDC Endpoint 2 (OUT) Control/Status Register */ -#define UDCCS3 __UDC_REG(0x001C) /* UDC Endpoint 3 (IN) Control/Status Register */ -#define UDCCS4 __UDC_REG(0x0020) /* UDC Endpoint 4 (OUT) Control/Status Register */ -#define UDCCS5 __UDC_REG(0x0024) /* UDC Endpoint 5 (Interrupt) Control/Status Register */ -#define UDCCS6 __UDC_REG(0x0028) /* UDC Endpoint 6 (IN) Control/Status Register */ -#define UDCCS7 __UDC_REG(0x002C) /* UDC Endpoint 7 (OUT) Control/Status Register */ -#define UDCCS8 __UDC_REG(0x0030) /* UDC Endpoint 8 (IN) Control/Status Register */ -#define UDCCS9 __UDC_REG(0x0034) /* UDC Endpoint 9 (OUT) Control/Status Register */ -#define UDCCS10 __UDC_REG(0x0038) /* UDC Endpoint 10 (Interrupt) Control/Status Register */ -#define UDCCS11 __UDC_REG(0x003C) /* UDC Endpoint 11 (IN) Control/Status Register */ -#define UDCCS12 __UDC_REG(0x0040) /* UDC Endpoint 12 (OUT) Control/Status Register */ -#define UDCCS13 __UDC_REG(0x0044) /* UDC Endpoint 13 (IN) Control/Status Register */ -#define UDCCS14 __UDC_REG(0x0048) /* UDC Endpoint 14 (OUT) Control/Status Register */ -#define UDCCS15 __UDC_REG(0x004C) /* UDC Endpoint 15 (Interrupt) Control/Status Register */ -#define UFNRH __UDC_REG(0x0060) /* UDC Frame Number Register High */ -#define UFNRL __UDC_REG(0x0064) /* UDC Frame Number Register Low */ -#define UBCR2 __UDC_REG(0x0068) /* UDC Byte Count Reg 2 */ -#define UBCR4 __UDC_REG(0x006c) /* UDC Byte Count Reg 4 */ -#define UBCR7 __UDC_REG(0x0070) /* UDC Byte Count Reg 7 */ -#define UBCR9 __UDC_REG(0x0074) /* UDC Byte Count Reg 9 */ -#define UBCR12 __UDC_REG(0x0078) /* UDC Byte Count Reg 12 */ -#define UBCR14 __UDC_REG(0x007c) /* UDC Byte Count Reg 14 */ -#define UDDR0 __UDC_REG(0x0080) /* UDC Endpoint 0 Data Register */ -#define UDDR1 __UDC_REG(0x0100) /* UDC Endpoint 1 Data Register */ -#define UDDR2 __UDC_REG(0x0180) /* UDC Endpoint 2 Data Register */ -#define UDDR3 __UDC_REG(0x0200) /* UDC Endpoint 3 Data Register */ -#define UDDR4 __UDC_REG(0x0400) /* UDC Endpoint 4 Data Register */ -#define UDDR5 __UDC_REG(0x00A0) /* UDC Endpoint 5 Data Register */ -#define UDDR6 __UDC_REG(0x0600) /* UDC Endpoint 6 Data Register */ -#define UDDR7 __UDC_REG(0x0680) /* UDC Endpoint 7 Data Register */ -#define UDDR8 __UDC_REG(0x0700) /* UDC Endpoint 8 Data Register */ -#define UDDR9 __UDC_REG(0x0900) /* UDC Endpoint 9 Data Register */ -#define UDDR10 __UDC_REG(0x00C0) /* UDC Endpoint 10 Data Register */ -#define UDDR11 __UDC_REG(0x0B00) /* UDC Endpoint 11 Data Register */ -#define UDDR12 __UDC_REG(0x0B80) /* UDC Endpoint 12 Data Register */ -#define UDDR13 __UDC_REG(0x0C00) /* UDC Endpoint 13 Data Register */ -#define UDDR14 __UDC_REG(0x0E00) /* UDC Endpoint 14 Data Register */ -#define UDDR15 __UDC_REG(0x00E0) /* UDC Endpoint 15 Data Register */ - -#define UICR0 __UDC_REG(0x0050) /* UDC Interrupt Control Register 0 */ -#define UICR1 __UDC_REG(0x0054) /* UDC Interrupt Control Register 1 */ - -#define USIR0 __UDC_REG(0x0058) /* UDC Status Interrupt Register 0 */ -#define USIR1 __UDC_REG(0x005C) /* UDC Status Interrupt Register 1 */ +static void __iomem *pxa25x_udc_reg_base; +#define __UDC_REG(x) (*((volatile u32 *)(pxa25x_udc_reg_base + (x)))) + +#define UDCCR 0x0000 /* UDC Control Register */ +#define UDC_RES1 0x0004 /* UDC Undocumented - Reserved1 */ +#define UDC_RES2 0x0008 /* UDC Undocumented - Reserved2 */ +#define UDC_RES3 0x000C /* UDC Undocumented - Reserved3 */ +#define UDCCS0 0x0010 /* UDC Endpoint 0 Control/Status Register */ +#define UDCCS1 0x0014 /* UDC Endpoint 1 (IN) Control/Status Register */ +#define UDCCS2 0x0018 /* UDC Endpoint 2 (OUT) Control/Status Register */ +#define UDCCS3 0x001C /* UDC Endpoint 3 (IN) Control/Status Register */ +#define UDCCS4 0x0020 /* UDC Endpoint 4 (OUT) Control/Status Register */ +#define UDCCS5 0x0024 /* UDC Endpoint 5 (Interrupt) Control/Status Register */ +#define UDCCS6 0x0028 /* UDC Endpoint 6 (IN) Control/Status Register */ +#define UDCCS7 0x002C /* UDC Endpoint 7 (OUT) Control/Status Register */ +#define UDCCS8 0x0030 /* UDC Endpoint 8 (IN) Control/Status Register */ +#define UDCCS9 0x0034 /* UDC Endpoint 9 (OUT) Control/Status Register */ +#define UDCCS10 0x0038 /* UDC Endpoint 10 (Interrupt) Control/Status Register */ +#define UDCCS11 0x003C /* UDC Endpoint 11 (IN) Control/Status Register */ +#define UDCCS12 0x0040 /* UDC Endpoint 12 (OUT) Control/Status Register */ +#define UDCCS13 0x0044 /* UDC Endpoint 13 (IN) Control/Status Register */ +#define UDCCS14 0x0048 /* UDC Endpoint 14 (OUT) Control/Status Register */ +#define UDCCS15 0x004C /* UDC Endpoint 15 (Interrupt) Control/Status Register */ +#define UFNRH 0x0060 /* UDC Frame Number Register High */ +#define UFNRL 0x0064 /* UDC Frame Number Register Low */ +#define UBCR2 0x0068 /* UDC Byte Count Reg 2 */ +#define UBCR4 0x006c /* UDC Byte Count Reg 4 */ +#define UBCR7 0x0070 /* UDC Byte Count Reg 7 */ +#define UBCR9 0x0074 /* UDC Byte Count Reg 9 */ +#define UBCR12 0x0078 /* UDC Byte Count Reg 12 */ +#define UBCR14 0x007c /* UDC Byte Count Reg 14 */ +#define UDDR0 0x0080 /* UDC Endpoint 0 Data Register */ +#define UDDR1 0x0100 /* UDC Endpoint 1 Data Register */ +#define UDDR2 0x0180 /* UDC Endpoint 2 Data Register */ +#define UDDR3 0x0200 /* UDC Endpoint 3 Data Register */ +#define UDDR4 0x0400 /* UDC Endpoint 4 Data Register */ +#define UDDR5 0x00A0 /* UDC Endpoint 5 Data Register */ +#define UDDR6 0x0600 /* UDC Endpoint 6 Data Register */ +#define UDDR7 0x0680 /* UDC Endpoint 7 Data Register */ +#define UDDR8 0x0700 /* UDC Endpoint 8 Data Register */ +#define UDDR9 0x0900 /* UDC Endpoint 9 Data Register */ +#define UDDR10 0x00C0 /* UDC Endpoint 10 Data Register */ +#define UDDR11 0x0B00 /* UDC Endpoint 11 Data Register */ +#define UDDR12 0x0B80 /* UDC Endpoint 12 Data Register */ +#define UDDR13 0x0C00 /* UDC Endpoint 13 Data Register */ +#define UDDR14 0x0E00 /* UDC Endpoint 14 Data Register */ +#define UDDR15 0x00E0 /* UDC Endpoint 15 Data Register */ + +#define UICR0 0x0050 /* UDC Interrupt Control Register 0 */ +#define UICR1 0x0054 /* UDC Interrupt Control Register 1 */ + +#define USIR0 0x0058 /* UDC Status Interrupt Register 0 */ +#define USIR1 0x005C /* UDC Status Interrupt Register 1 */ #define UDCCR_UDE (1 << 0) /* UDC enable */ #define UDCCR_UDA (1 << 1) /* UDC active */ @@ -299,25 +292,41 @@ static void pullup_on(void) mach->udc_command(PXA2XX_UDC_CMD_CONNECT); } -static void pio_irq_enable(int bEndpointAddress) +static inline void udc_set_reg(struct pxa25x_udc *dev, u32 reg, u32 uicr) +{ + __UDC_REG(reg) = uicr; +} + +static inline u32 udc_get_reg(struct pxa25x_udc *dev, u32 reg) { - bEndpointAddress &= 0xf; + return __UDC_REG(reg); +} + +static void pio_irq_enable(struct pxa25x_ep *ep) +{ + u32 bEndpointAddress = ep->bEndpointAddress & 0xf; + if (bEndpointAddress < 8) - UICR0 &= ~(1 << bEndpointAddress); + udc_set_reg(ep->dev, UICR0, udc_get_reg(ep->dev, UICR0) & + ~(1 << bEndpointAddress)); else { bEndpointAddress -= 8; - UICR1 &= ~(1 << bEndpointAddress); + udc_set_reg(ep->dev, UICR1, udc_get_reg(ep->dev, UICR1) & + ~(1 << bEndpointAddress)); } } -static void pio_irq_disable(int bEndpointAddress) +static void pio_irq_disable(struct pxa25x_ep *ep) { - bEndpointAddress &= 0xf; + u32 bEndpointAddress = ep->bEndpointAddress & 0xf; + if (bEndpointAddress < 8) - UICR0 |= 1 << bEndpointAddress; + udc_set_reg(ep->dev, UICR0, udc_get_reg(ep->dev, UICR0) | + (1 << bEndpointAddress)); else { bEndpointAddress -= 8; - UICR1 |= 1 << bEndpointAddress; + udc_set_reg(ep->dev, UICR1, udc_get_reg(ep->dev, UICR1) | + (1 << bEndpointAddress)); } } @@ -326,22 +335,61 @@ static void pio_irq_disable(int bEndpointAddress) */ #define UDCCR_MASK_BITS (UDCCR_REM | UDCCR_SRM | UDCCR_UDE) -static inline void udc_set_mask_UDCCR(int mask) +static inline void udc_set_mask_UDCCR(struct pxa25x_udc *dev, int mask) { - UDCCR = (UDCCR & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS); + u32 udccr = __UDC_REG(UDCCR); + + __UDC_REG(UDCCR) = (udccr & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS); } -static inline void udc_clear_mask_UDCCR(int mask) +static inline void udc_clear_mask_UDCCR(struct pxa25x_udc *dev, int mask) { - UDCCR = (UDCCR & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS); + u32 udccr = __UDC_REG(UDCCR); + + __UDC_REG(UDCCR) = (udccr & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS); } -static inline void udc_ack_int_UDCCR(int mask) +static inline void udc_ack_int_UDCCR(struct pxa25x_udc *dev, int mask) { /* udccr contains the bits we dont want to change */ - __u32 udccr = UDCCR & UDCCR_MASK_BITS; + u32 udccr = __UDC_REG(UDCCR) & UDCCR_MASK_BITS; - UDCCR = udccr | (mask & ~UDCCR_MASK_BITS); + __UDC_REG(UDCCR) = udccr | (mask & ~UDCCR_MASK_BITS); +} + +static inline u32 udc_ep_get_UDCCS(struct pxa25x_ep *ep) +{ + return __UDC_REG(ep->regoff_udccs); +} + +static inline void udc_ep_set_UDCCS(struct pxa25x_ep *ep, u32 data) +{ + __UDC_REG(ep->regoff_udccs) = data; +} + +static inline u32 udc_ep0_get_UDCCS(struct pxa25x_udc *dev) +{ + return __UDC_REG(UDCCS0); +} + +static inline void udc_ep0_set_UDCCS(struct pxa25x_udc *dev, u32 data) +{ + __UDC_REG(UDCCS0) = data; +} + +static inline u32 udc_ep_get_UDDR(struct pxa25x_ep *ep) +{ + return __UDC_REG(ep->regoff_uddr); +} + +static inline void udc_ep_set_UDDR(struct pxa25x_ep *ep, u32 data) +{ + __UDC_REG(ep->regoff_uddr) = data; +} + +static inline u32 udc_ep_get_UBCR(struct pxa25x_ep *ep) +{ + return __UDC_REG(ep->regoff_ubcr); } /* @@ -507,7 +555,7 @@ static inline void ep0_idle (struct pxa25x_udc *dev) } static int -write_packet(volatile u32 *uddr, struct pxa25x_request *req, unsigned max) +write_packet(struct pxa25x_ep *ep, struct pxa25x_request *req, unsigned max) { u8 *buf; unsigned length, count; @@ -521,7 +569,7 @@ write_packet(volatile u32 *uddr, struct pxa25x_request *req, unsigned max) count = length; while (likely(count--)) - *uddr = *buf++; + udc_ep_set_UDDR(ep, *buf++); return length; } @@ -541,7 +589,7 @@ write_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) unsigned count; int is_last, is_short; - count = write_packet(ep->reg_uddr, req, max); + count = write_packet(ep, req, max); /* last packet is usually short (or a zlp) */ if (unlikely (count != max)) @@ -565,15 +613,15 @@ write_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) * double buffering might work. TSP, TPC, and TFS * bit values are the same for all normal IN endpoints. */ - *ep->reg_udccs = UDCCS_BI_TPC; + udc_ep_set_UDCCS(ep, UDCCS_BI_TPC); if (is_short) - *ep->reg_udccs = UDCCS_BI_TSP; + udc_ep_set_UDCCS(ep, UDCCS_BI_TSP); /* requests complete when all IN data is in the FIFO */ if (is_last) { done (ep, req, 0); if (list_empty(&ep->queue)) - pio_irq_disable (ep->bEndpointAddress); + pio_irq_disable(ep); return 1; } @@ -581,7 +629,7 @@ write_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) // double buffering is off in the default fifo mode, which // prevents TFS from being set here. - } while (*ep->reg_udccs & UDCCS_BI_TFS); + } while (udc_ep_get_UDCCS(ep) & UDCCS_BI_TFS); return 0; } @@ -591,20 +639,21 @@ write_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) static inline void ep0start(struct pxa25x_udc *dev, u32 flags, const char *tag) { - UDCCS0 = flags|UDCCS0_SA|UDCCS0_OPR; - USIR0 = USIR0_IR0; + udc_ep0_set_UDCCS(dev, flags|UDCCS0_SA|UDCCS0_OPR); + udc_set_reg(dev, USIR0, USIR0_IR0); dev->req_pending = 0; DBG(DBG_VERY_NOISY, "%s %s, %02x/%02x\n", - __func__, tag, UDCCS0, flags); + __func__, tag, udc_ep0_get_UDCCS(dev), flags); } static int write_ep0_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) { + struct pxa25x_udc *dev = ep->dev; unsigned count; int is_short; - count = write_packet(&UDDR0, req, EP0_FIFO_SIZE); + count = write_packet(&dev->ep[0], req, EP0_FIFO_SIZE); ep->dev->stats.write.bytes += count; /* last packet "must be" short (or a zlp) */ @@ -617,7 +666,7 @@ write_ep0_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) if (ep->dev->req_pending) ep0start(ep->dev, UDCCS0_IPR, "short IN"); else - UDCCS0 = UDCCS0_IPR; + udc_ep0_set_UDCCS(dev, UDCCS0_IPR); count = req->req.length; done (ep, req, 0); @@ -633,9 +682,9 @@ write_ep0_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) if (count >= EP0_FIFO_SIZE) { count = 100; do { - if ((UDCCS0 & UDCCS0_OPR) != 0) { + if ((udc_ep0_get_UDCCS(dev) & UDCCS0_OPR) != 0) { /* clear OPR, generate ack */ - UDCCS0 = UDCCS0_OPR; + udc_ep0_set_UDCCS(dev, UDCCS0_OPR); break; } count--; @@ -670,7 +719,7 @@ read_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) * UDCCS_{BO,IO}_RPC are all the same bit value. * UDCCS_{BO,IO}_RNE are all the same bit value. */ - udccs = *ep->reg_udccs; + udccs = udc_ep_get_UDCCS(ep); if (unlikely ((udccs & UDCCS_BO_RPC) == 0)) break; buf = req->req.buf + req->req.actual; @@ -679,7 +728,7 @@ read_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) /* read all bytes from this packet */ if (likely (udccs & UDCCS_BO_RNE)) { - count = 1 + (0x0ff & *ep->reg_ubcr); + count = 1 + (0x0ff & udc_ep_get_UBCR(ep)); req->req.actual += min (count, bufferspace); } else /* zlp */ count = 0; @@ -689,7 +738,7 @@ read_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) is_short ? "/S" : "", req, req->req.actual, req->req.length); while (likely (count-- != 0)) { - u8 byte = (u8) *ep->reg_uddr; + u8 byte = (u8) udc_ep_get_UDDR(ep); if (unlikely (bufferspace == 0)) { /* this happens when the driver's buffer @@ -705,7 +754,7 @@ read_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) bufferspace--; } } - *ep->reg_udccs = UDCCS_BO_RPC; + udc_ep_set_UDCCS(ep, UDCCS_BO_RPC); /* RPC/RSP/RNE could now reflect the other packet buffer */ /* iso is one request per packet */ @@ -720,7 +769,7 @@ read_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) if (is_short || req->req.actual == req->req.length) { done (ep, req, 0); if (list_empty(&ep->queue)) - pio_irq_disable (ep->bEndpointAddress); + pio_irq_disable(ep); return 1; } @@ -744,7 +793,7 @@ read_ep0_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) buf = req->req.buf + req->req.actual; bufferspace = req->req.length - req->req.actual; - while (UDCCS0 & UDCCS0_RNE) { + while (udc_ep_get_UDCCS(ep) & UDCCS0_RNE) { byte = (u8) UDDR0; if (unlikely (bufferspace == 0)) { @@ -762,7 +811,7 @@ read_ep0_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) } } - UDCCS0 = UDCCS0_OPR | UDCCS0_IPR; + udc_ep_set_UDCCS(ep, UDCCS0_OPR | UDCCS0_IPR); /* completion */ if (req->req.actual >= req->req.length) @@ -836,8 +885,8 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) DBG(DBG_VERBOSE, "ep0 config ack%s\n", dev->has_cfr ? "" : " raced"); if (dev->has_cfr) - UDCCFR = UDCCFR_AREN|UDCCFR_ACM - |UDCCFR_MB1; + udc_set_reg(dev, UDCCFR, UDCCFR_AREN | + UDCCFR_ACM | UDCCFR_MB1); done(ep, req, 0); dev->ep0state = EP0_END_XFER; local_irq_restore (flags); @@ -845,7 +894,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) } if (dev->req_pending) ep0start(dev, UDCCS0_IPR, "OUT"); - if (length == 0 || ((UDCCS0 & UDCCS0_RNE) != 0 + if (length == 0 || ((udc_ep0_get_UDCCS(dev) & UDCCS0_RNE) != 0 && read_ep0_fifo(ep, req))) { ep0_idle(dev); done(ep, req, 0); @@ -860,16 +909,16 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) } /* can the FIFO can satisfy the request immediately? */ } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) { - if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0 + if ((udc_ep_get_UDCCS(ep) & UDCCS_BI_TFS) != 0 && write_fifo(ep, req)) req = NULL; - } else if ((*ep->reg_udccs & UDCCS_BO_RFS) != 0 + } else if ((udc_ep_get_UDCCS(ep) & UDCCS_BO_RFS) != 0 && read_fifo(ep, req)) { req = NULL; } if (likely(req && ep->ep.desc)) - pio_irq_enable(ep->bEndpointAddress); + pio_irq_enable(ep); } /* pio or dma irq handler advances the queue. */ @@ -896,7 +945,7 @@ static void nuke(struct pxa25x_ep *ep, int status) done(ep, req, status); } if (ep->ep.desc) - pio_irq_disable (ep->bEndpointAddress); + pio_irq_disable(ep); } @@ -956,14 +1005,14 @@ static int pxa25x_ep_set_halt(struct usb_ep *_ep, int value) local_irq_save(flags); if ((ep->bEndpointAddress & USB_DIR_IN) != 0 - && ((*ep->reg_udccs & UDCCS_BI_TFS) == 0 + && ((udc_ep_get_UDCCS(ep) & UDCCS_BI_TFS) == 0 || !list_empty(&ep->queue))) { local_irq_restore(flags); return -EAGAIN; } /* FST bit is the same for control, bulk in, bulk out, interrupt in */ - *ep->reg_udccs = UDCCS_BI_FST|UDCCS_BI_FTF; + udc_ep_set_UDCCS(ep, UDCCS_BI_FST|UDCCS_BI_FTF); /* ep0 needs special care */ if (!ep->ep.desc) { @@ -975,7 +1024,7 @@ static int pxa25x_ep_set_halt(struct usb_ep *_ep, int value) } else { unsigned i; for (i = 0; i < 1000; i += 20) { - if (*ep->reg_udccs & UDCCS_BI_SST) + if (udc_ep_get_UDCCS(ep) & UDCCS_BI_SST) break; udelay(20); } @@ -999,10 +1048,10 @@ static int pxa25x_ep_fifo_status(struct usb_ep *_ep) if ((ep->bEndpointAddress & USB_DIR_IN) != 0) return -EOPNOTSUPP; if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN - || (*ep->reg_udccs & UDCCS_BO_RFS) == 0) + || (udc_ep_get_UDCCS(ep) & UDCCS_BO_RFS) == 0) return 0; else - return (*ep->reg_ubcr & 0xfff) + 1; + return (udc_ep_get_UBCR(ep) & 0xfff) + 1; } static void pxa25x_ep_fifo_flush(struct usb_ep *_ep) @@ -1019,15 +1068,15 @@ static void pxa25x_ep_fifo_flush(struct usb_ep *_ep) /* for OUT, just read and discard the FIFO contents. */ if ((ep->bEndpointAddress & USB_DIR_IN) == 0) { - while (((*ep->reg_udccs) & UDCCS_BO_RNE) != 0) - (void) *ep->reg_uddr; + while (((udc_ep_get_UDCCS(ep)) & UDCCS_BO_RNE) != 0) + (void)udc_ep_get_UDDR(ep); return; } /* most IN status is the same, but ISO can't stall */ - *ep->reg_udccs = UDCCS_BI_TPC|UDCCS_BI_FTF|UDCCS_BI_TUR + udc_ep_set_UDCCS(ep, UDCCS_BI_TPC|UDCCS_BI_FTF|UDCCS_BI_TUR | (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC - ? 0 : UDCCS_BI_SST); + ? 0 : UDCCS_BI_SST)); } @@ -1054,15 +1103,23 @@ static struct usb_ep_ops pxa25x_ep_ops = { static int pxa25x_udc_get_frame(struct usb_gadget *_gadget) { - return ((UFNRH & 0x07) << 8) | (UFNRL & 0xff); + struct pxa25x_udc *dev; + + dev = container_of(_gadget, struct pxa25x_udc, gadget); + return ((udc_get_reg(dev, UFNRH) & 0x07) << 8) | + (udc_get_reg(dev, UFNRL) & 0xff); } static int pxa25x_udc_wakeup(struct usb_gadget *_gadget) { + struct pxa25x_udc *udc; + + udc = container_of(_gadget, struct pxa25x_udc, gadget); + /* host may not have enabled remote wakeup */ - if ((UDCCS0 & UDCCS0_DRWF) == 0) + if ((udc_ep0_get_UDCCS(udc) & UDCCS0_DRWF) == 0) return -EHOSTUNREACH; - udc_set_mask_UDCCR(UDCCR_RSM); + udc_set_mask_UDCCR(udc, UDCCR_RSM); return 0; } @@ -1183,9 +1240,11 @@ udc_seq_show(struct seq_file *m, void *_d) /* registers for device and ep0 */ seq_printf(m, "uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n", - UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL); + udc_get_reg(dev, UICR1), udc_get_reg(dev, UICR0), + udc_get_reg(dev, USIR1), udc_get_reg(dev, USIR0), + udc_get_reg(dev, UFNRH), udc_get_reg(dev, UFNRL)); - tmp = UDCCR; + tmp = udc_get_reg(dev, UDCCR); seq_printf(m, "udccr %02X =%s%s%s%s%s%s%s%s\n", tmp, (tmp & UDCCR_REM) ? " rem" : "", @@ -1197,7 +1256,7 @@ udc_seq_show(struct seq_file *m, void *_d) (tmp & UDCCR_UDA) ? " uda" : "", (tmp & UDCCR_UDE) ? " ude" : ""); - tmp = UDCCS0; + tmp = udc_ep0_get_UDCCS(dev); seq_printf(m, "udccs0 %02X =%s%s%s%s%s%s%s%s\n", tmp, (tmp & UDCCS0_SA) ? " sa" : "", @@ -1210,7 +1269,7 @@ udc_seq_show(struct seq_file *m, void *_d) (tmp & UDCCS0_OPR) ? " opr" : ""); if (dev->has_cfr) { - tmp = UDCCFR; + tmp = udc_get_reg(dev, UDCCFR); seq_printf(m, "udccfr %02X =%s%s\n", tmp, (tmp & UDCCFR_AREN) ? " aren" : "", @@ -1236,7 +1295,7 @@ udc_seq_show(struct seq_file *m, void *_d) desc = ep->ep.desc; if (!desc) continue; - tmp = *dev->ep [i].reg_udccs; + tmp = udc_ep_get_UDCCS(&dev->ep[i]); seq_printf(m, "%s max %d %s udccs %02x irqs %lu\n", ep->ep.name, usb_endpoint_maxp(desc), @@ -1300,14 +1359,15 @@ static const struct file_operations debug_fops = { static void udc_disable(struct pxa25x_udc *dev) { /* block all irqs */ - udc_set_mask_UDCCR(UDCCR_SRM|UDCCR_REM); - UICR0 = UICR1 = 0xff; - UFNRH = UFNRH_SIM; + udc_set_mask_UDCCR(dev, UDCCR_SRM|UDCCR_REM); + udc_set_reg(dev, UICR0, 0xff); + udc_set_reg(dev, UICR1, 0xff); + udc_set_reg(dev, UFNRH, UFNRH_SIM); /* if hardware supports it, disconnect from usb */ pullup_off(); - udc_clear_mask_UDCCR(UDCCR_UDE); + udc_clear_mask_UDCCR(dev, UDCCR_UDE); ep0_idle (dev); dev->gadget.speed = USB_SPEED_UNKNOWN; @@ -1349,10 +1409,10 @@ static void udc_reinit(struct pxa25x_udc *dev) */ static void udc_enable (struct pxa25x_udc *dev) { - udc_clear_mask_UDCCR(UDCCR_UDE); + udc_clear_mask_UDCCR(dev, UDCCR_UDE); /* try to clear these bits before we enable the udc */ - udc_ack_int_UDCCR(UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR); + udc_ack_int_UDCCR(dev, UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR); ep0_idle(dev); dev->gadget.speed = USB_SPEED_UNKNOWN; @@ -1364,15 +1424,15 @@ static void udc_enable (struct pxa25x_udc *dev) * - if RESET is already in progress, ack interrupt * - unmask reset interrupt */ - udc_set_mask_UDCCR(UDCCR_UDE); - if (!(UDCCR & UDCCR_UDA)) - udc_ack_int_UDCCR(UDCCR_RSTIR); + udc_set_mask_UDCCR(dev, UDCCR_UDE); + if (!(udc_get_reg(dev, UDCCR) & UDCCR_UDA)) + udc_ack_int_UDCCR(dev, UDCCR_RSTIR); if (dev->has_cfr /* UDC_RES2 is defined */) { /* pxa255 (a0+) can avoid a set_config race that could * prevent gadget drivers from configuring correctly */ - UDCCFR = UDCCFR_ACM | UDCCFR_MB1; + udc_set_reg(dev, UDCCFR, UDCCFR_ACM | UDCCFR_MB1); } else { /* "USB test mode" for pxa250 errata 40-42 (stepping a0, a1) * which could result in missing packets and interrupts. @@ -1380,15 +1440,15 @@ static void udc_enable (struct pxa25x_udc *dev) * double buffers or not; ACM/AREN bits fit into the holes. * zero bits (like USIR0_IRx) disable double buffering. */ - UDC_RES1 = 0x00; - UDC_RES2 = 0x00; + udc_set_reg(dev, UDC_RES1, 0x00); + udc_set_reg(dev, UDC_RES2, 0x00); } /* enable suspend/resume and reset irqs */ - udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM); + udc_clear_mask_UDCCR(dev, UDCCR_SRM | UDCCR_REM); /* enable ep0 irqs */ - UICR0 &= ~UICR0_IM0; + udc_set_reg(dev, UICR0, udc_get_reg(dev, UICR0) & ~UICR0_IM0); /* if hardware supports it, pullup D+ and wait for reset */ pullup_on(); @@ -1557,9 +1617,9 @@ static void udc_watchdog(unsigned long _dev) local_irq_disable(); if (dev->ep0state == EP0_STALL - && (UDCCS0 & UDCCS0_FST) == 0 - && (UDCCS0 & UDCCS0_SST) == 0) { - UDCCS0 = UDCCS0_FST|UDCCS0_FTF; + && (udc_ep0_get_UDCCS(dev) & UDCCS0_FST) == 0 + && (udc_ep0_get_UDCCS(dev) & UDCCS0_SST) == 0) { + udc_ep0_set_UDCCS(dev, UDCCS0_FST|UDCCS0_FTF); DBG(DBG_VERBOSE, "ep0 re-stall\n"); start_watchdog(dev); } @@ -1568,7 +1628,7 @@ static void udc_watchdog(unsigned long _dev) static void handle_ep0 (struct pxa25x_udc *dev) { - u32 udccs0 = UDCCS0; + u32 udccs0 = udc_ep0_get_UDCCS(dev); struct pxa25x_ep *ep = &dev->ep [0]; struct pxa25x_request *req; union { @@ -1585,7 +1645,7 @@ static void handle_ep0 (struct pxa25x_udc *dev) /* clear stall status */ if (udccs0 & UDCCS0_SST) { nuke(ep, -EPIPE); - UDCCS0 = UDCCS0_SST; + udc_ep0_set_UDCCS(dev, UDCCS0_SST); del_timer(&dev->timer); ep0_idle(dev); } @@ -1600,7 +1660,7 @@ static void handle_ep0 (struct pxa25x_udc *dev) switch (dev->ep0state) { case EP0_IDLE: /* late-breaking status? */ - udccs0 = UDCCS0; + udccs0 = udc_ep0_get_UDCCS(dev); /* start control request? */ if (likely((udccs0 & (UDCCS0_OPR|UDCCS0_SA|UDCCS0_RNE)) @@ -1611,14 +1671,14 @@ static void handle_ep0 (struct pxa25x_udc *dev) /* read SETUP packet */ for (i = 0; i < 8; i++) { - if (unlikely(!(UDCCS0 & UDCCS0_RNE))) { + if (unlikely(!(udc_ep0_get_UDCCS(dev) & UDCCS0_RNE))) { bad_setup: DMSG("SETUP %d!\n", i); goto stall; } u.raw [i] = (u8) UDDR0; } - if (unlikely((UDCCS0 & UDCCS0_RNE) != 0)) + if (unlikely((udc_ep0_get_UDCCS(dev) & UDCCS0_RNE) != 0)) goto bad_setup; got_setup: @@ -1694,7 +1754,7 @@ config_change: */ } DBG(DBG_VERBOSE, "protocol STALL, " - "%02x err %d\n", UDCCS0, i); + "%02x err %d\n", udc_ep0_get_UDCCS(dev), i); stall: /* the watchdog timer helps deal with cases * where udc seems to clear FST wrongly, and @@ -1741,12 +1801,12 @@ stall: * - IPR cleared * - OPR got set, without SA (likely status stage) */ - UDCCS0 = udccs0 & (UDCCS0_SA|UDCCS0_OPR); + udc_ep0_set_UDCCS(dev, udccs0 & (UDCCS0_SA|UDCCS0_OPR)); } break; case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR etc */ if (udccs0 & UDCCS0_OPR) { - UDCCS0 = UDCCS0_OPR|UDCCS0_FTF; + udc_ep0_set_UDCCS(dev, UDCCS0_OPR|UDCCS0_FTF); DBG(DBG_VERBOSE, "ep0in premature status\n"); if (req) done(ep, req, 0); @@ -1780,14 +1840,14 @@ stall: * also appears after some config change events. */ if (udccs0 & UDCCS0_OPR) - UDCCS0 = UDCCS0_OPR; + udc_ep0_set_UDCCS(dev, UDCCS0_OPR); ep0_idle(dev); break; case EP0_STALL: - UDCCS0 = UDCCS0_FST; + udc_ep0_set_UDCCS(dev, UDCCS0_FST); break; } - USIR0 = USIR0_IR0; + udc_set_reg(dev, USIR0, USIR0_IR0); } static void handle_ep(struct pxa25x_ep *ep) @@ -1807,14 +1867,14 @@ static void handle_ep(struct pxa25x_ep *ep) // TODO check FST handling - udccs = *ep->reg_udccs; + udccs = udc_ep_get_UDCCS(ep); if (unlikely(is_in)) { /* irq from TPC, SST, or (ISO) TUR */ tmp = UDCCS_BI_TUR; if (likely(ep->bmAttributes == USB_ENDPOINT_XFER_BULK)) tmp |= UDCCS_BI_SST; tmp &= udccs; if (likely (tmp)) - *ep->reg_udccs = tmp; + udc_ep_set_UDCCS(ep, tmp); if (req && likely ((udccs & UDCCS_BI_TFS) != 0)) completed = write_fifo(ep, req); @@ -1825,13 +1885,13 @@ static void handle_ep(struct pxa25x_ep *ep) tmp = UDCCS_IO_ROF | UDCCS_IO_DME; tmp &= udccs; if (likely(tmp)) - *ep->reg_udccs = tmp; + udc_ep_set_UDCCS(ep, tmp); /* fifos can hold packets, ready for reading... */ if (likely(req)) { completed = read_fifo(ep, req); } else - pio_irq_disable (ep->bEndpointAddress); + pio_irq_disable(ep); } ep->pio_irqs++; } while (completed); @@ -1852,13 +1912,13 @@ pxa25x_udc_irq(int irq, void *_dev) dev->stats.irqs++; do { - u32 udccr = UDCCR; + u32 udccr = udc_get_reg(dev, UDCCR); handled = 0; /* SUSpend Interrupt Request */ if (unlikely(udccr & UDCCR_SUSIR)) { - udc_ack_int_UDCCR(UDCCR_SUSIR); + udc_ack_int_UDCCR(dev, UDCCR_SUSIR); handled = 1; DBG(DBG_VERBOSE, "USB suspend\n"); @@ -1871,7 +1931,7 @@ pxa25x_udc_irq(int irq, void *_dev) /* RESume Interrupt Request */ if (unlikely(udccr & UDCCR_RESIR)) { - udc_ack_int_UDCCR(UDCCR_RESIR); + udc_ack_int_UDCCR(dev, UDCCR_RESIR); handled = 1; DBG(DBG_VERBOSE, "USB resume\n"); @@ -1883,10 +1943,10 @@ pxa25x_udc_irq(int irq, void *_dev) /* ReSeT Interrupt Request - USB reset */ if (unlikely(udccr & UDCCR_RSTIR)) { - udc_ack_int_UDCCR(UDCCR_RSTIR); + udc_ack_int_UDCCR(dev, UDCCR_RSTIR); handled = 1; - if ((UDCCR & UDCCR_UDA) == 0) { + if ((udc_get_reg(dev, UDCCR) & UDCCR_UDA) == 0) { DBG(DBG_VERBOSE, "USB reset start\n"); /* reset driver and endpoints, @@ -1902,8 +1962,10 @@ pxa25x_udc_irq(int irq, void *_dev) } } else { - u32 usir0 = USIR0 & ~UICR0; - u32 usir1 = USIR1 & ~UICR1; + u32 usir0 = udc_get_reg(dev, USIR0) & + ~udc_get_reg(dev, UICR0); + u32 usir1 = udc_get_reg(dev, USIR1) & + ~udc_get_reg(dev, UICR1); int i; if (unlikely (!usir0 && !usir1)) @@ -1924,13 +1986,15 @@ pxa25x_udc_irq(int irq, void *_dev) if (i && (usir0 & tmp)) { handle_ep(&dev->ep[i]); - USIR0 |= tmp; + udc_set_reg(dev, USIR0, + udc_get_reg(dev, USIR0) | tmp); handled = 1; } #ifndef CONFIG_USB_PXA25X_SMALL if (usir1 & tmp) { handle_ep(&dev->ep[i+8]); - USIR1 |= tmp; + udc_set_reg(dev, USIR1, + udc_get_reg(dev, USIR1) | tmp); handled = 1; } #endif @@ -1975,8 +2039,8 @@ static struct pxa25x_udc memory = { USB_EP_CAPS_DIR_ALL), }, .dev = &memory, - .reg_udccs = &UDCCS0, - .reg_uddr = &UDDR0, + .regoff_udccs = UDCCS0, + .regoff_uddr = UDDR0, }, /* first group of endpoints */ @@ -1992,8 +2056,8 @@ static struct pxa25x_udc memory = { .fifo_size = BULK_FIFO_SIZE, .bEndpointAddress = USB_DIR_IN | 1, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .reg_udccs = &UDCCS1, - .reg_uddr = &UDDR1, + .regoff_udccs = UDCCS1, + .regoff_uddr = UDDR1, }, .ep[2] = { .ep = { @@ -2007,9 +2071,9 @@ static struct pxa25x_udc memory = { .fifo_size = BULK_FIFO_SIZE, .bEndpointAddress = 2, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .reg_udccs = &UDCCS2, - .reg_ubcr = &UBCR2, - .reg_uddr = &UDDR2, + .regoff_udccs = UDCCS2, + .regoff_ubcr = UBCR2, + .regoff_uddr = UDDR2, }, #ifndef CONFIG_USB_PXA25X_SMALL .ep[3] = { @@ -2024,8 +2088,8 @@ static struct pxa25x_udc memory = { .fifo_size = ISO_FIFO_SIZE, .bEndpointAddress = USB_DIR_IN | 3, .bmAttributes = USB_ENDPOINT_XFER_ISOC, - .reg_udccs = &UDCCS3, - .reg_uddr = &UDDR3, + .regoff_udccs = UDCCS3, + .regoff_uddr = UDDR3, }, .ep[4] = { .ep = { @@ -2039,9 +2103,9 @@ static struct pxa25x_udc memory = { .fifo_size = ISO_FIFO_SIZE, .bEndpointAddress = 4, .bmAttributes = USB_ENDPOINT_XFER_ISOC, - .reg_udccs = &UDCCS4, - .reg_ubcr = &UBCR4, - .reg_uddr = &UDDR4, + .regoff_udccs = UDCCS4, + .regoff_ubcr = UBCR4, + .regoff_uddr = UDDR4, }, .ep[5] = { .ep = { @@ -2054,8 +2118,8 @@ static struct pxa25x_udc memory = { .fifo_size = INT_FIFO_SIZE, .bEndpointAddress = USB_DIR_IN | 5, .bmAttributes = USB_ENDPOINT_XFER_INT, - .reg_udccs = &UDCCS5, - .reg_uddr = &UDDR5, + .regoff_udccs = UDCCS5, + .regoff_uddr = UDDR5, }, /* second group of endpoints */ @@ -2071,8 +2135,8 @@ static struct pxa25x_udc memory = { .fifo_size = BULK_FIFO_SIZE, .bEndpointAddress = USB_DIR_IN | 6, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .reg_udccs = &UDCCS6, - .reg_uddr = &UDDR6, + .regoff_udccs = UDCCS6, + .regoff_uddr = UDDR6, }, .ep[7] = { .ep = { @@ -2086,9 +2150,9 @@ static struct pxa25x_udc memory = { .fifo_size = BULK_FIFO_SIZE, .bEndpointAddress = 7, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .reg_udccs = &UDCCS7, - .reg_ubcr = &UBCR7, - .reg_uddr = &UDDR7, + .regoff_udccs = UDCCS7, + .regoff_ubcr = UBCR7, + .regoff_uddr = UDDR7, }, .ep[8] = { .ep = { @@ -2102,8 +2166,8 @@ static struct pxa25x_udc memory = { .fifo_size = ISO_FIFO_SIZE, .bEndpointAddress = USB_DIR_IN | 8, .bmAttributes = USB_ENDPOINT_XFER_ISOC, - .reg_udccs = &UDCCS8, - .reg_uddr = &UDDR8, + .regoff_udccs = UDCCS8, + .regoff_uddr = UDDR8, }, .ep[9] = { .ep = { @@ -2117,9 +2181,9 @@ static struct pxa25x_udc memory = { .fifo_size = ISO_FIFO_SIZE, .bEndpointAddress = 9, .bmAttributes = USB_ENDPOINT_XFER_ISOC, - .reg_udccs = &UDCCS9, - .reg_ubcr = &UBCR9, - .reg_uddr = &UDDR9, + .regoff_udccs = UDCCS9, + .regoff_ubcr = UBCR9, + .regoff_uddr = UDDR9, }, .ep[10] = { .ep = { @@ -2132,8 +2196,8 @@ static struct pxa25x_udc memory = { .fifo_size = INT_FIFO_SIZE, .bEndpointAddress = USB_DIR_IN | 10, .bmAttributes = USB_ENDPOINT_XFER_INT, - .reg_udccs = &UDCCS10, - .reg_uddr = &UDDR10, + .regoff_udccs = UDCCS10, + .regoff_uddr = UDDR10, }, /* third group of endpoints */ @@ -2149,8 +2213,8 @@ static struct pxa25x_udc memory = { .fifo_size = BULK_FIFO_SIZE, .bEndpointAddress = USB_DIR_IN | 11, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .reg_udccs = &UDCCS11, - .reg_uddr = &UDDR11, + .regoff_udccs = UDCCS11, + .regoff_uddr = UDDR11, }, .ep[12] = { .ep = { @@ -2164,9 +2228,9 @@ static struct pxa25x_udc memory = { .fifo_size = BULK_FIFO_SIZE, .bEndpointAddress = 12, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .reg_udccs = &UDCCS12, - .reg_ubcr = &UBCR12, - .reg_uddr = &UDDR12, + .regoff_udccs = UDCCS12, + .regoff_ubcr = UBCR12, + .regoff_uddr = UDDR12, }, .ep[13] = { .ep = { @@ -2180,8 +2244,8 @@ static struct pxa25x_udc memory = { .fifo_size = ISO_FIFO_SIZE, .bEndpointAddress = USB_DIR_IN | 13, .bmAttributes = USB_ENDPOINT_XFER_ISOC, - .reg_udccs = &UDCCS13, - .reg_uddr = &UDDR13, + .regoff_udccs = UDCCS13, + .regoff_uddr = UDDR13, }, .ep[14] = { .ep = { @@ -2195,9 +2259,9 @@ static struct pxa25x_udc memory = { .fifo_size = ISO_FIFO_SIZE, .bEndpointAddress = 14, .bmAttributes = USB_ENDPOINT_XFER_ISOC, - .reg_udccs = &UDCCS14, - .reg_ubcr = &UBCR14, - .reg_uddr = &UDDR14, + .regoff_udccs = UDCCS14, + .regoff_ubcr = UBCR14, + .regoff_uddr = UDDR14, }, .ep[15] = { .ep = { @@ -2210,8 +2274,8 @@ static struct pxa25x_udc memory = { .fifo_size = INT_FIFO_SIZE, .bEndpointAddress = USB_DIR_IN | 15, .bmAttributes = USB_ENDPOINT_XFER_INT, - .reg_udccs = &UDCCS15, - .reg_uddr = &UDDR15, + .regoff_udccs = UDCCS15, + .regoff_uddr = UDDR15, }, #endif /* !CONFIG_USB_PXA25X_SMALL */ }; @@ -2258,6 +2322,7 @@ static int pxa25x_udc_probe(struct platform_device *pdev) struct pxa25x_udc *dev = &memory; int retval, irq; u32 chiprev; + struct resource *res; pr_info("%s: version %s\n", driver_name, DRIVER_VERSION); @@ -2303,6 +2368,11 @@ static int pxa25x_udc_probe(struct platform_device *pdev) if (irq < 0) return -ENODEV; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pxa25x_udc_reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(pxa25x_udc_reg_base)) + return PTR_ERR(pxa25x_udc_reg_base); + dev->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(dev->clk)) return PTR_ERR(dev->clk); diff --git a/drivers/usb/gadget/udc/pxa25x_udc.h b/drivers/usb/gadget/udc/pxa25x_udc.h index 3fe5931dc21a..f884513f7390 100644 --- a/drivers/usb/gadget/udc/pxa25x_udc.h +++ b/drivers/usb/gadget/udc/pxa25x_udc.h @@ -56,9 +56,9 @@ struct pxa25x_ep { * UDDR = UDC Endpoint Data Register (the fifo) * DRCM = DMA Request Channel Map */ - volatile u32 *reg_udccs; - volatile u32 *reg_ubcr; - volatile u32 *reg_uddr; + u32 regoff_udccs; + u32 regoff_ubcr; + u32 regoff_uddr; }; struct pxa25x_request { @@ -197,6 +197,8 @@ dump_udccs0(const char *label) (udccs0 & UDCCS0_OPR) ? " opr" : ""); } +static inline u32 udc_ep_get_UDCCS(struct pxa25x_ep *); + static void __maybe_unused dump_state(struct pxa25x_udc *dev) { @@ -228,7 +230,7 @@ dump_state(struct pxa25x_udc *dev) for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++) { if (dev->ep[i].ep.desc == NULL) continue; - DMSG ("udccs%d = %02x\n", i, *dev->ep->reg_udccs); + DMSG ("udccs%d = %02x\n", i, udc_ep_get_UDCCS(&dev->ep[i])); } } -- cgit v1.2.3-70-g09d2 From 65bc0fba4ed6e2ea7d89539985feb576ae2f84b9 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 28 Jan 2016 17:17:04 +0100 Subject: usb: gadget: pxa25x_udc: use readl/writel for mmio This converts the pxa25x udc driver to use readl/writel as normal driver should do, rather than dereferencing __iomem pointers themselves. Based on the earlier preparation work, we can now also pass the register start in the device pointer so we no longer need the global variable. The unclear part here is for IXP4xx, which supports both big-endian and little-endian configurations. So far, the driver has done no byteswap in either case. I suspect that is wrong and it would actually need to swap in one or the other case, but I don't know which. It's also possible that there is some magic setting in the chip that makes the endianess of the MMIO register match the CPU, and in that case, the code actually does the right thing for all configurations, both before and after this patch. Acked-by: Robert Jarzmik Signed-off-by: Arnd Bergmann Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/pxa25x_udc.c | 61 ++++++++++++++++++++++++------------- drivers/usb/gadget/udc/pxa25x_udc.h | 1 + 2 files changed, 40 insertions(+), 22 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c index 5db429f3cfb2..6d3acbf3b311 100644 --- a/drivers/usb/gadget/udc/pxa25x_udc.c +++ b/drivers/usb/gadget/udc/pxa25x_udc.c @@ -52,9 +52,6 @@ #include #endif -static void __iomem *pxa25x_udc_reg_base; -#define __UDC_REG(x) (*((volatile u32 *)(pxa25x_udc_reg_base + (x)))) - #define UDCCR 0x0000 /* UDC Control Register */ #define UDC_RES1 0x0004 /* UDC Undocumented - Reserved1 */ #define UDC_RES2 0x0008 /* UDC Undocumented - Reserved2 */ @@ -292,16 +289,36 @@ static void pullup_on(void) mach->udc_command(PXA2XX_UDC_CMD_CONNECT); } -static inline void udc_set_reg(struct pxa25x_udc *dev, u32 reg, u32 uicr) +#if defined(CONFIG_ARCH_IXP4XX) && defined(CONFIG_CPU_BIG_ENDIAN) +/* + * not sure if this is the correct behavior on ixp4xx in both + * bit-endian and little-endian modes, but it's what the driver + * has always done using direct pointer dereferences: + * We assume that there is a byteswap done in hardware at the + * MMIO register that matches what the CPU setting is, so we + * never swap in software. + */ +static inline void udc_set_reg(struct pxa25x_udc *dev, u32 reg, u32 val) { - __UDC_REG(reg) = uicr; + iowrite32be(val, dev->regs + reg); } static inline u32 udc_get_reg(struct pxa25x_udc *dev, u32 reg) { - return __UDC_REG(reg); + return ioread32be(dev->regs + reg); +} +#else +static inline void udc_set_reg(struct pxa25x_udc *dev, u32 reg, u32 val) +{ + writel(val, dev->regs + reg); } +static inline u32 udc_get_reg(struct pxa25x_udc *dev, u32 reg) +{ + return readl(dev->regs + reg); +} +#endif + static void pio_irq_enable(struct pxa25x_ep *ep) { u32 bEndpointAddress = ep->bEndpointAddress & 0xf; @@ -337,59 +354,59 @@ static void pio_irq_disable(struct pxa25x_ep *ep) static inline void udc_set_mask_UDCCR(struct pxa25x_udc *dev, int mask) { - u32 udccr = __UDC_REG(UDCCR); + u32 udccr = udc_get_reg(dev, UDCCR); - __UDC_REG(UDCCR) = (udccr & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS); + udc_set_reg(dev, (udccr & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS), UDCCR); } static inline void udc_clear_mask_UDCCR(struct pxa25x_udc *dev, int mask) { - u32 udccr = __UDC_REG(UDCCR); + u32 udccr = udc_get_reg(dev, UDCCR); - __UDC_REG(UDCCR) = (udccr & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS); + udc_set_reg(dev, (udccr & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS), UDCCR); } static inline void udc_ack_int_UDCCR(struct pxa25x_udc *dev, int mask) { /* udccr contains the bits we dont want to change */ - u32 udccr = __UDC_REG(UDCCR) & UDCCR_MASK_BITS; + u32 udccr = udc_get_reg(dev, UDCCR) & UDCCR_MASK_BITS; - __UDC_REG(UDCCR) = udccr | (mask & ~UDCCR_MASK_BITS); + udc_set_reg(dev, udccr | (mask & ~UDCCR_MASK_BITS), UDCCR); } static inline u32 udc_ep_get_UDCCS(struct pxa25x_ep *ep) { - return __UDC_REG(ep->regoff_udccs); + return udc_get_reg(ep->dev, ep->regoff_udccs); } static inline void udc_ep_set_UDCCS(struct pxa25x_ep *ep, u32 data) { - __UDC_REG(ep->regoff_udccs) = data; + udc_set_reg(ep->dev, data, ep->regoff_udccs); } static inline u32 udc_ep0_get_UDCCS(struct pxa25x_udc *dev) { - return __UDC_REG(UDCCS0); + return udc_get_reg(dev, UDCCS0); } static inline void udc_ep0_set_UDCCS(struct pxa25x_udc *dev, u32 data) { - __UDC_REG(UDCCS0) = data; + udc_set_reg(dev, data, UDCCS0); } static inline u32 udc_ep_get_UDDR(struct pxa25x_ep *ep) { - return __UDC_REG(ep->regoff_uddr); + return udc_get_reg(ep->dev, ep->regoff_uddr); } static inline void udc_ep_set_UDDR(struct pxa25x_ep *ep, u32 data) { - __UDC_REG(ep->regoff_uddr) = data; + udc_set_reg(ep->dev, data, ep->regoff_uddr); } static inline u32 udc_ep_get_UBCR(struct pxa25x_ep *ep) { - return __UDC_REG(ep->regoff_ubcr); + return udc_get_reg(ep->dev, ep->regoff_ubcr); } /* @@ -2369,9 +2386,9 @@ static int pxa25x_udc_probe(struct platform_device *pdev) return -ENODEV; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pxa25x_udc_reg_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(pxa25x_udc_reg_base)) - return PTR_ERR(pxa25x_udc_reg_base); + dev->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(dev->regs)) + return PTR_ERR(dev->regs); dev->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(dev->clk)) diff --git a/drivers/usb/gadget/udc/pxa25x_udc.h b/drivers/usb/gadget/udc/pxa25x_udc.h index f884513f7390..4b8b72d7ab37 100644 --- a/drivers/usb/gadget/udc/pxa25x_udc.h +++ b/drivers/usb/gadget/udc/pxa25x_udc.h @@ -125,6 +125,7 @@ struct pxa25x_udc { #ifdef CONFIG_USB_GADGET_DEBUG_FS struct dentry *debugfs_udc; #endif + void __iomem *regs; }; #define to_pxa25x(g) (container_of((g), struct pxa25x_udc, gadget)) -- cgit v1.2.3-70-g09d2 From d0fc35bc0889c7157527ed5758f54101ec015839 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 28 Jan 2016 17:20:54 +0100 Subject: usb: fsl: drop USB_FSL_MPH_DR_OF Kconfig symbol The USB_FSL_MPH_DR_OF symbol is used to ensure the code that interprets the DR device node is built whenever one of the two drivers (EHCI or UDC) for the platform is enabled. However, if CONFIG_USB is disabled and we only support gadget mode, this causes a Kconfig warning: warning: (USB_FSL_USB2) selects USB_FSL_MPH_DR_OF which has unmet direct dependencies (USB_SUPPORT && USB) We can avoid this warning by simply no longer using the symbol, and making sure we enter the drivers/usb/host/ directory when the UDC driver is enabled that needs the file, and then we use Makefile syntax to ensure the file is built-in if needed. There is currently a dependency on CONFIG_OF, but this is redundant, as we already know that this is set unconditionally for the platforms that use this driver. Signed-off-by: Arnd Bergmann Signed-off-by: Felipe Balbi --- drivers/usb/Makefile | 2 +- drivers/usb/gadget/udc/Kconfig | 1 - drivers/usb/host/Kconfig | 4 ---- drivers/usb/host/Makefile | 3 ++- 4 files changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index d5c57f1e98fd..dca78565eb55 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -26,7 +26,7 @@ obj-$(CONFIG_USB_U132_HCD) += host/ obj-$(CONFIG_USB_R8A66597_HCD) += host/ obj-$(CONFIG_USB_HWA_HCD) += host/ obj-$(CONFIG_USB_IMX21_HCD) += host/ -obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/ +obj-$(CONFIG_USB_FSL_USB2) += host/ obj-$(CONFIG_USB_FOTG210_HCD) += host/ obj-$(CONFIG_USB_MAX3421_HCD) += host/ diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index d6ad7e6c978c..ff4f8a6735d6 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig @@ -74,7 +74,6 @@ config USB_BCM63XX_UDC config USB_FSL_USB2 tristate "Freescale Highspeed USB DR Peripheral Controller" depends on FSL_SOC || ARCH_MXC - select USB_FSL_MPH_DR_OF if OF help Some of Freescale PowerPC and i.MX processors have a High Speed Dual-Role(DR) USB controller, which supports device mode. diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index ed9a90f601e8..8c20ebbc049c 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -125,9 +125,6 @@ config USB_EHCI_TT_NEWSCHED If unsure, say Y. -config USB_FSL_MPH_DR_OF - tristate - if USB_EHCI_HCD config USB_EHCI_PCI @@ -160,7 +157,6 @@ config USB_EHCI_FSL tristate "Support for Freescale PPC on-chip EHCI USB controller" depends on FSL_SOC select USB_EHCI_ROOT_HUB_TT - select USB_FSL_MPH_DR_OF if OF ---help--- Variation of ARC USB block used in some Freescale chips. diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 65a06b4382bf..a9ddd3c9ec94 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -74,7 +74,8 @@ obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o -obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o +obj-$(CONFIG_USB_FSL_USB2) += fsl-mph-dr-of.o +obj-$(CONFIG_USB_EHCI_FSL) += fsl-mph-dr-of.o obj-$(CONFIG_USB_EHCI_FSL) += ehci-fsl.o obj-$(CONFIG_USB_HCD_BCMA) += bcma-hcd.o obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o -- cgit v1.2.3-70-g09d2 From a9458a3b33ea1a00fc9d1beb3c0bb1c2d18855c9 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 17 Feb 2016 16:51:40 +0100 Subject: usb: gadget: pxa25x_udc: document endianess better MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When I wrote the cleanup patch series, it was not clear how exactly big-endian mode works on ixp4xx, and whether the driver was doing this correctly. After discussing with Krzysztof Hałasa, this has been clarified, so I can update the comment let pxa25x big-endian (which we don't support) work the same way as ixp4xx. Signed-off-by: Arnd Bergmann Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/pxa25x_udc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c index 6d3acbf3b311..a238da906115 100644 --- a/drivers/usb/gadget/udc/pxa25x_udc.c +++ b/drivers/usb/gadget/udc/pxa25x_udc.c @@ -289,14 +289,14 @@ static void pullup_on(void) mach->udc_command(PXA2XX_UDC_CMD_CONNECT); } -#if defined(CONFIG_ARCH_IXP4XX) && defined(CONFIG_CPU_BIG_ENDIAN) +#if defined(CONFIG_CPU_BIG_ENDIAN) /* - * not sure if this is the correct behavior on ixp4xx in both - * bit-endian and little-endian modes, but it's what the driver - * has always done using direct pointer dereferences: - * We assume that there is a byteswap done in hardware at the - * MMIO register that matches what the CPU setting is, so we - * never swap in software. + * IXP4xx has its buses wired up in a way that relies on never doing any + * byte swaps, independent of whether it runs in big-endian or little-endian + * mode, as explained by Krzysztof Hałasa. + * + * We only support pxa25x in little-endian mode, but it is very likely + * that it works the same way. */ static inline void udc_set_reg(struct pxa25x_udc *dev, u32 reg, u32 val) { -- cgit v1.2.3-70-g09d2 From 3de4e20568171f542adb8d54a47c46ff025ca942 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Mon, 4 Jan 2016 20:42:43 +0100 Subject: usb: f_fs: fix memory leak when ep changes during transfer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the ffs_epfile_io function, data buffer is allocated for non-halt requests. Later, after grabing a mutex, the function checks that epfile->ep is still ep and if it’s not, it set ret to -ESHUTDOWN and follow a path including spin_unlock_irq (just after ‘ret = -ESHUTDOWN’), mutex_unlock (after if-else-if-else chain) and returns ret. Noticeably, this does not include freeing of the data buffer. Fix by introducing a goto which moves control flow to the the end of the function where spin_unlock_irq, mutex_unlock and kfree are all called. Signed-off-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index cf43e9e18368..d1a4a8645620 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -763,7 +763,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) if (epfile->ep != ep) { /* In the meantime, endpoint got disabled or changed. */ ret = -ESHUTDOWN; - spin_unlock_irq(&epfile->ffs->eps_lock); + goto error_lock; } else if (halt) { /* Halt */ if (likely(epfile->ep == ep) && !WARN_ON(!ep->ep)) -- cgit v1.2.3-70-g09d2 From 3163c79efa653ea9832acb8efe55efd34a5f4ae6 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Mon, 4 Jan 2016 21:28:34 +0100 Subject: usb: f_fs: fix ffs_epfile_io returning success on req alloc failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the AIO path, if allocating of a request failse, the function simply goes to the error_lock path whose end result is returning value of ret. However, at this point ret’s value is zero (assigned as return value from ffs_mutex_lock). Fix by adding ‘ret = -ENOMEM’ statement. Signed-off-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_fs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index d1a4a8645620..13842205b849 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -793,8 +793,10 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) if (io_data->aio) { req = usb_ep_alloc_request(ep->ep, GFP_KERNEL); - if (unlikely(!req)) + if (unlikely(!req)) { + ret = -ENOMEM; goto error_lock; + } req->buf = data; req->length = data_len; -- cgit v1.2.3-70-g09d2 From b3591f67b9f9607fea5d854f9d481f44696d8ddc Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Mon, 4 Jan 2016 20:58:12 +0100 Subject: usb: f_fs: replace unnecessary goto with a return MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In ffs_epfile_io error label points to a return path which includes a kfree(data) call. However, at the beginning of the function data is always NULL so some of the early ‘goto error’ can safely be replaced with a trivial return statement. Signed-off-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_fs.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 13842205b849..c4e6395c1271 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -690,32 +690,24 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) int halt; /* Are we still active? */ - if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) { - ret = -ENODEV; - goto error; - } + if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) + return -ENODEV; /* Wait for endpoint to be enabled */ ep = epfile->ep; if (!ep) { - if (file->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - goto error; - } + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; ret = wait_event_interruptible(epfile->wait, (ep = epfile->ep)); - if (ret) { - ret = -EINTR; - goto error; - } + if (ret) + return -EINTR; } /* Do we halt? */ halt = (!io_data->read == !epfile->in); - if (halt && epfile->isoc) { - ret = -EINVAL; - goto error; - } + if (halt && epfile->isoc) + return -EINVAL; /* Allocate & copy */ if (!halt) { -- cgit v1.2.3-70-g09d2 From ae76e13477d8de0065cddbb6714e6b027562eaec Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Mon, 4 Jan 2016 21:05:59 +0100 Subject: usb: f_fs: refactor ffs_epfile_io MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Eliminate one of the return paths by using a ‘goto error_mutex’ and rearrange some if-bodies which results in reduction of the indention level and thus hopefully makes the function easier to read and reason about. Signed-off-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_fs.c | 127 +++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 69 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index c4e6395c1271..63fe6931b17b 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -684,6 +684,7 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep, static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) { struct ffs_epfile *epfile = file->private_data; + struct usb_request *req; struct ffs_ep *ep; char *data = NULL; ssize_t ret, data_len = -EINVAL; @@ -713,7 +714,8 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) if (!halt) { /* * if we _do_ wait above, the epfile->ffs->gadget might be NULL - * before the waiting completes, so do not assign to 'gadget' earlier + * before the waiting completes, so do not assign to 'gadget' + * earlier */ struct usb_gadget *gadget = epfile->ffs->gadget; size_t copied; @@ -755,17 +757,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) if (epfile->ep != ep) { /* In the meantime, endpoint got disabled or changed. */ ret = -ESHUTDOWN; - goto error_lock; } else if (halt) { /* Halt */ if (likely(epfile->ep == ep) && !WARN_ON(!ep->ep)) usb_ep_set_halt(ep->ep); - spin_unlock_irq(&epfile->ffs->eps_lock); ret = -EBADMSG; - } else { - /* Fire the request */ - struct usb_request *req; - + } else if (unlikely(data_len == -EINVAL)) { /* * Sanity Check: even though data_len can't be used * uninitialized at the time I write this comment, some @@ -777,82 +774,74 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) * For such reason, we're adding this redundant sanity check * here. */ - if (unlikely(data_len == -EINVAL)) { - WARN(1, "%s: data_len == -EINVAL\n", __func__); - ret = -EINVAL; - goto error_lock; - } - - if (io_data->aio) { - req = usb_ep_alloc_request(ep->ep, GFP_KERNEL); - if (unlikely(!req)) { - ret = -ENOMEM; - goto error_lock; - } - - req->buf = data; - req->length = data_len; + WARN(1, "%s: data_len == -EINVAL\n", __func__); + ret = -EINVAL; + } else if (!io_data->aio) { + DECLARE_COMPLETION_ONSTACK(done); - io_data->buf = data; - io_data->ep = ep->ep; - io_data->req = req; - io_data->ffs = epfile->ffs; + req = ep->req; + req->buf = data; + req->length = data_len; - req->context = io_data; - req->complete = ffs_epfile_async_io_complete; + req->context = &done; + req->complete = ffs_epfile_io_complete; - ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC); - if (unlikely(ret)) { - usb_ep_free_request(ep->ep, req); - goto error_lock; - } - ret = -EIOCBQUEUED; + ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC); + if (unlikely(ret < 0)) + goto error_lock; - spin_unlock_irq(&epfile->ffs->eps_lock); - } else { - DECLARE_COMPLETION_ONSTACK(done); + spin_unlock_irq(&epfile->ffs->eps_lock); - req = ep->req; - req->buf = data; - req->length = data_len; + if (unlikely(wait_for_completion_interruptible(&done))) { + ret = -EINTR; + usb_ep_dequeue(ep->ep, req); + goto error_mutex; + } - req->context = &done; - req->complete = ffs_epfile_io_complete; + /* + * XXX We may end up silently droping data here. Since data_len + * (i.e. req->length) may be bigger than len (after being + * rounded up to maxpacketsize), we may end up with more data + * then user space has space for. + */ + ret = ep->status; + if (io_data->read && ret > 0) { + ret = copy_to_iter(data, ret, &io_data->data); + if (!ret) + ret = -EFAULT; + } + goto error_mutex; + } else if (!(req = usb_ep_alloc_request(ep->ep, GFP_KERNEL))) { + ret = -ENOMEM; + } else { + req->buf = data; + req->length = data_len; - ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC); + io_data->buf = data; + io_data->ep = ep->ep; + io_data->req = req; + io_data->ffs = epfile->ffs; - spin_unlock_irq(&epfile->ffs->eps_lock); + req->context = io_data; + req->complete = ffs_epfile_async_io_complete; - if (unlikely(ret < 0)) { - /* nop */ - } else if (unlikely( - wait_for_completion_interruptible(&done))) { - ret = -EINTR; - usb_ep_dequeue(ep->ep, req); - } else { - /* - * XXX We may end up silently droping data - * here. Since data_len (i.e. req->length) may - * be bigger than len (after being rounded up - * to maxpacketsize), we may end up with more - * data then user space has space for. - */ - ret = ep->status; - if (io_data->read && ret > 0) { - ret = copy_to_iter(data, ret, &io_data->data); - if (!ret) - ret = -EFAULT; - } - } - kfree(data); + ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC); + if (unlikely(ret)) { + usb_ep_free_request(ep->ep, req); + goto error_lock; } - } - mutex_unlock(&epfile->mutex); - return ret; + ret = -EIOCBQUEUED; + /* + * Do not kfree the buffer in this function. It will be freed + * by ffs_user_copy_worker. + */ + data = NULL; + } error_lock: spin_unlock_irq(&epfile->ffs->eps_lock); +error_mutex: mutex_unlock(&epfile->mutex); error: kfree(data); -- cgit v1.2.3-70-g09d2 From ef15088440e2b34441a6c99e44405b05171792a7 Mon Sep 17 00:00:00 2001 From: "Du, Changbin" Date: Tue, 29 Dec 2015 14:36:58 +0800 Subject: usb: f_fs: avoid race condition with ffs_epfile_io_complete ffs_epfile_io and ffs_epfile_io_complete runs in different context, but there is no synchronization between them. consider the following scenario: 1) ffs_epfile_io interrupted by sigal while wait_for_completion_interruptible 2) then ffs_epfile_io set ret to -EINTR 3) just before or during usb_ep_dequeue, the request completed 4) ffs_epfile_io return with -EINTR In this case, ffs_epfile_io tell caller no transfer success but actually it may has been done. This break the caller's pipe. Below script can help test it (adbd is the process which lies on f_fs). while true do pkill -19 adbd #SIGSTOP pkill -18 adbd #SIGCONT sleep 0.1 done To avoid this, just dequeue the request first. After usb_ep_dequeue, the request must be done or canceled. With this change, we can ensure no race condition in f_fs driver. But actually I found some of the udc driver has analogical issue in its dequeue implementation. For example, 1) the dequeue function hold the controller's lock. 2) before driver request controller to stop transfer, a request completed. 3) the controller trigger a interrupt, but its irq handler need wait dequeue function to release the lock. 4) dequeue function give back the request with negative status, and release lock. 5) irq handler get lock but the request has already been given back. So, the dequeue implementation should take care of this case. IMO, it can be done as below steps to dequeue a already started request, 1) request controller to stop transfer on the given ep. HW know the actual transfer status. 2) after hw stop transfer, driver scan if there are any completed one. 3) if found, process it with real status. if no, the request can canceled. Signed-off-by: "Du, Changbin" [mina86@mina86.com: rebased on top of refactoring commits] Signed-off-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_fs.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 63fe6931b17b..8cfce105c7ee 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -778,6 +778,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) ret = -EINVAL; } else if (!io_data->aio) { DECLARE_COMPLETION_ONSTACK(done); + bool interrupted = false; req = ep->req; req->buf = data; @@ -793,9 +794,14 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) spin_unlock_irq(&epfile->ffs->eps_lock); if (unlikely(wait_for_completion_interruptible(&done))) { - ret = -EINTR; + /* + * To avoid race condition with ffs_epfile_io_complete, + * dequeue the request first then check + * status. usb_ep_dequeue API should guarantee no race + * condition with req->complete callback. + */ usb_ep_dequeue(ep->ep, req); - goto error_mutex; + interrupted = ep->status < 0; } /* @@ -804,7 +810,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) * rounded up to maxpacketsize), we may end up with more data * then user space has space for. */ - ret = ep->status; + ret = interrupted ? -EINTR : ep->status; if (io_data->read && ret > 0) { ret = copy_to_iter(data, ret, &io_data->data); if (!ret) -- cgit v1.2.3-70-g09d2 From f297e86c7f017430816b27e6cf29bf81246d897e Mon Sep 17 00:00:00 2001 From: "Felipe F. Tonello" Date: Tue, 26 Jan 2016 14:52:36 +0100 Subject: usb: gadget: f_midi: remove useless midi reference from port struct remove a field which is unnecessary. No functional changes. Signed-off-by: Felipe F. Tonello Signed-off-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_midi.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index fb1fe96d3215..cd160e79b777 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -56,7 +56,6 @@ static const char f_midi_longname[] = "MIDI Gadget"; * USB <- IN endpoint <- rawmidi */ struct gmidi_in_port { - struct f_midi *midi; int active; uint8_t cable; uint8_t state; @@ -1192,7 +1191,6 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) goto setup_fail; } - port->midi = midi; port->active = 0; port->cable = i; midi->in_port[i] = port; -- cgit v1.2.3-70-g09d2 From 9a71eb563441a42effe11d9a8cc1e6be068b7446 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Mon, 18 Jan 2016 17:54:14 +0100 Subject: usb: gadget: f_midi: move some of f_midi_transmit to separate func Move some of the f_midi_transmit to a separate f_midi_do_transmit function so the massive indention levels are not so jarring. This introduces no changes in behaviour. Signed-off-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_midi.c | 137 +++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 61 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index cd160e79b777..75853a3272d2 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -531,84 +531,99 @@ static void f_midi_drop_out_substreams(struct f_midi *midi) } } -static void f_midi_transmit(struct f_midi *midi) +static int f_midi_do_transmit(struct f_midi *midi, struct usb_ep *ep) { - struct usb_ep *ep = midi->in_ep; - bool active; + struct usb_request *req = NULL; + unsigned int len, i; + bool active = false; + int err; - /* We only care about USB requests if IN endpoint is enabled */ - if (!ep || !ep->enabled) - goto drop_out; + /* + * We peek the request in order to reuse it if it fails to enqueue on + * its endpoint + */ + len = kfifo_peek(&midi->in_req_fifo, &req); + if (len != 1) { + ERROR(midi, "%s: Couldn't get usb request\n", __func__); + return -1; + } - do { - struct usb_request *req = NULL; - unsigned int len, i; + /* + * If buffer overrun, then we ignore this transmission. + * IMPORTANT: This will cause the user-space rawmidi device to block + * until a) usb requests have been completed or b) snd_rawmidi_write() + * times out. + */ + if (req->length > 0) + return 0; - active = false; + for (i = midi->in_last_port; i < MAX_PORTS; i++) { + struct gmidi_in_port *port = midi->in_port[i]; + struct snd_rawmidi_substream *substream = midi->in_substream[i]; - /* We peek the request in order to reuse it if it fails - * to enqueue on its endpoint */ - len = kfifo_peek(&midi->in_req_fifo, &req); - if (len != 1) { - ERROR(midi, "%s: Couldn't get usb request\n", __func__); - goto drop_out; + if (!port) { + /* Reset counter when we reach the last available port */ + midi->in_last_port = 0; + break; } - /* If buffer overrun, then we ignore this transmission. - * IMPORTANT: This will cause the user-space rawmidi device to block until a) usb - * requests have been completed or b) snd_rawmidi_write() times out. */ - if (req->length > 0) - return; + if (!port->active || !substream) + continue; - for (i = midi->in_last_port; i < MAX_PORTS; i++) { - struct gmidi_in_port *port = midi->in_port[i]; - struct snd_rawmidi_substream *substream = midi->in_substream[i]; + while (req->length + 3 < midi->buflen) { + uint8_t b; - if (!port) { - /* Reset counter when we reach the last available port */ - midi->in_last_port = 0; + if (snd_rawmidi_transmit(substream, &b, 1) != 1) { + port->active = 0; break; } + f_midi_transmit_byte(req, port, b); + } + + active = !!port->active; + /* + * Check if last port is still active, which means that there is + * still data on that substream but this current request run out + * of space. + */ + if (active) { + midi->in_last_port = i; + /* There is no need to re-iterate though midi ports. */ + break; + } + } - if (!port->active || !substream) - continue; + if (req->length <= 0) + return active; - while (req->length + 3 < midi->buflen) { - uint8_t b; + err = usb_ep_queue(ep, req, GFP_ATOMIC); + if (err < 0) { + ERROR(midi, "%s failed to queue req: %d\n", + midi->in_ep->name, err); + req->length = 0; /* Re-use request next time. */ + } else { + /* Upon success, put request at the back of the queue. */ + kfifo_skip(&midi->in_req_fifo); + kfifo_put(&midi->in_req_fifo, req); + } - if (snd_rawmidi_transmit(substream, &b, 1) != 1) { - port->active = 0; - break; - } - f_midi_transmit_byte(req, port, b); - } + return active; +} - active = !!port->active; - /* Check if last port is still active, which means that - * there is still data on that substream but this current - * request run out of space. */ - if (active) { - midi->in_last_port = i; - /* There is no need to re-iterate though midi ports. */ - break; - } - } +static void f_midi_transmit(struct f_midi *midi) +{ + struct usb_ep *ep = midi->in_ep; + int ret; - if (req->length > 0) { - int err; + /* We only care about USB requests if IN endpoint is enabled */ + if (!ep || !ep->enabled) + goto drop_out; - err = usb_ep_queue(ep, req, GFP_ATOMIC); - if (err < 0) { - ERROR(midi, "%s failed to queue req: %d\n", - midi->in_ep->name, err); - req->length = 0; /* Re-use request next time. */ - } else { - /* Upon success, put request at the back of the queue. */ - kfifo_skip(&midi->in_req_fifo); - kfifo_put(&midi->in_req_fifo, req); - } - } - } while (active); + do { + ret = f_midi_do_transmit(midi, ep); + if (ret < 0) + goto drop_out; + } while (ret); return; -- cgit v1.2.3-70-g09d2 From 06cd928b0cfc79e9e17e0d36e39329e20238b185 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Mon, 18 Jan 2016 18:30:15 +0100 Subject: usb: gadget: f_midi: fix in_last_port looping logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In general case, all of midi->in_port pointers may be non-NULL which implies that the ‘if (\!port)’ condition will never execute thus never zeroing midi->in_last_port. Fix by rewriting the loop such that the field is set to zero if \!port or end of loop has been reached. Signed-off-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_midi.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index 75853a3272d2..896f02cdadbe 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -534,6 +534,7 @@ static void f_midi_drop_out_substreams(struct f_midi *midi) static int f_midi_do_transmit(struct f_midi *midi, struct usb_ep *ep) { struct usb_request *req = NULL; + struct gmidi_in_port *port; unsigned int len, i; bool active = false; int err; @@ -557,16 +558,9 @@ static int f_midi_do_transmit(struct f_midi *midi, struct usb_ep *ep) if (req->length > 0) return 0; - for (i = midi->in_last_port; i < MAX_PORTS; i++) { - struct gmidi_in_port *port = midi->in_port[i]; + i = midi->in_last_port; + for (; i < MAX_PORTS && (port = midi->in_port[i]); ++i) { struct snd_rawmidi_substream *substream = midi->in_substream[i]; - - if (!port) { - /* Reset counter when we reach the last available port */ - midi->in_last_port = 0; - break; - } - if (!port->active || !substream) continue; @@ -581,20 +575,13 @@ static int f_midi_do_transmit(struct f_midi *midi, struct usb_ep *ep) } active = !!port->active; - /* - * Check if last port is still active, which means that there is - * still data on that substream but this current request run out - * of space. - */ - if (active) { - midi->in_last_port = i; - /* There is no need to re-iterate though midi ports. */ + if (active) break; - } } + midi->in_last_port = active ? i : 0; if (req->length <= 0) - return active; + goto done; err = usb_ep_queue(ep, req, GFP_ATOMIC); if (err < 0) { @@ -607,6 +594,7 @@ static int f_midi_do_transmit(struct f_midi *midi, struct usb_ep *ep) kfifo_put(&midi->in_req_fifo, req); } +done: return active; } -- cgit v1.2.3-70-g09d2 From bf0028f8cb44a65ddc57b805ef43bd37dfa8a6ce Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Tue, 5 Jan 2016 14:43:42 +0100 Subject: usb: gadget: f_midi: use flexible array member for gmidi_in_port elements Reduce number of allocations, simplify memory management and reduce memory usage by stacking the gmidi_in_port elements at the end of the f_midi structure using a flexible array. Signed-off-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_midi.c | 55 ++++++++++++------------------------ 1 file changed, 18 insertions(+), 37 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index 896f02cdadbe..8a3c8c45bf0d 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -79,7 +79,6 @@ struct f_midi { struct snd_rawmidi_substream *in_substream[MAX_PORTS]; struct snd_rawmidi_substream *out_substream[MAX_PORTS]; - struct gmidi_in_port *in_port[MAX_PORTS]; unsigned long out_triggered; struct tasklet_struct tasklet; @@ -91,6 +90,8 @@ struct f_midi { /* This fifo is used as a buffer ring for pre-allocated IN usb_requests */ DECLARE_KFIFO_PTR(in_req_fifo, struct usb_request *); unsigned int in_last_port; + + struct gmidi_in_port in_ports_array[/* in_ports */]; }; static inline struct f_midi *func_to_midi(struct usb_function *f) @@ -517,24 +518,17 @@ static void f_midi_drop_out_substreams(struct f_midi *midi) { unsigned int i; - for (i = 0; i < MAX_PORTS; i++) { - struct gmidi_in_port *port = midi->in_port[i]; + for (i = 0; i < midi->in_ports; i++) { + struct gmidi_in_port *port = midi->in_ports_array + i; struct snd_rawmidi_substream *substream = midi->in_substream[i]; - - if (!port) - break; - - if (!port->active || !substream) - continue; - - snd_rawmidi_drop_output(substream); + if (port->active && substream) + snd_rawmidi_drop_output(substream); } } static int f_midi_do_transmit(struct f_midi *midi, struct usb_ep *ep) { struct usb_request *req = NULL; - struct gmidi_in_port *port; unsigned int len, i; bool active = false; int err; @@ -558,9 +552,10 @@ static int f_midi_do_transmit(struct f_midi *midi, struct usb_ep *ep) if (req->length > 0) return 0; - i = midi->in_last_port; - for (; i < MAX_PORTS && (port = midi->in_port[i]); ++i) { + for (i = midi->in_last_port; i < midi->in_ports; ++i) { + struct gmidi_in_port *port = midi->in_ports_array + i; struct snd_rawmidi_substream *substream = midi->in_substream[i]; + if (!port->active || !substream) continue; @@ -629,12 +624,12 @@ static int f_midi_in_open(struct snd_rawmidi_substream *substream) { struct f_midi *midi = substream->rmidi->private_data; - if (!midi->in_port[substream->number]) + if (substream->number >= midi->in_ports) return -EINVAL; VDBG(midi, "%s()\n", __func__); midi->in_substream[substream->number] = substream; - midi->in_port[substream->number]->state = STATE_UNKNOWN; + midi->in_ports_array[substream->number].state = STATE_UNKNOWN; return 0; } @@ -650,11 +645,11 @@ static void f_midi_in_trigger(struct snd_rawmidi_substream *substream, int up) { struct f_midi *midi = substream->rmidi->private_data; - if (!midi->in_port[substream->number]) + if (substream->number >= midi->in_ports) return; VDBG(midi, "%s() %d\n", __func__, up); - midi->in_port[substream->number]->active = up; + midi->in_ports_array[substream->number].active = up; if (up) tasklet_hi_schedule(&midi->tasklet); } @@ -1130,14 +1125,11 @@ static void f_midi_free(struct usb_function *f) { struct f_midi *midi; struct f_midi_opts *opts; - int i; midi = func_to_midi(f); opts = container_of(f->fi, struct f_midi_opts, func_inst); kfree(midi->id); mutex_lock(&opts->lock); - for (i = opts->in_ports - 1; i >= 0; --i) - kfree(midi->in_port[i]); kfifo_free(&midi->in_req_fifo); kfree(midi); --opts->refcnt; @@ -1179,25 +1171,16 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) } /* allocate and initialize one new instance */ - midi = kzalloc(sizeof(*midi), GFP_KERNEL); + midi = kzalloc( + sizeof(*midi) + opts->in_ports * sizeof(*midi->in_ports_array), + GFP_KERNEL); if (!midi) { mutex_unlock(&opts->lock); return ERR_PTR(-ENOMEM); } - for (i = 0; i < opts->in_ports; i++) { - struct gmidi_in_port *port = kzalloc(sizeof(*port), GFP_KERNEL); - - if (!port) { - status = -ENOMEM; - mutex_unlock(&opts->lock); - goto setup_fail; - } - - port->active = 0; - port->cable = i; - midi->in_port[i] = port; - } + for (i = 0; i < opts->in_ports; i++) + midi->in_ports_array[i].cable = i; /* set up ALSA midi devices */ midi->id = kstrdup(opts->id, GFP_KERNEL); @@ -1230,8 +1213,6 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) return &midi->func; setup_fail: - for (--i; i >= 0; i--) - kfree(midi->in_port[i]); kfree(midi); return ERR_PTR(status); } -- cgit v1.2.3-70-g09d2 From 413489c8337bf86b7787248484b1e845111809be Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 5 Jan 2016 13:28:09 +0300 Subject: usb: gadget: f_midi: missing unlock on error path We added a new error path to this function and we forgot to drop the lock. Fixes: e1e3d7ec5da3 ('usb: gadget: f_midi: pre-allocate IN requests') Signed-off-by: Dan Carpenter [mina86@mina86.com: rebased on top of refactoring commit] Signed-off-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_midi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index 8a3c8c45bf0d..0e411bffa4ab 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -1157,7 +1157,7 @@ static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f) static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) { - struct f_midi *midi; + struct f_midi *midi = NULL; struct f_midi_opts *opts; int status, i; @@ -1166,8 +1166,8 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) mutex_lock(&opts->lock); /* sanity check */ if (opts->in_ports > MAX_PORTS || opts->out_ports > MAX_PORTS) { - mutex_unlock(&opts->lock); - return ERR_PTR(-EINVAL); + status = -EINVAL; + goto setup_fail; } /* allocate and initialize one new instance */ @@ -1175,8 +1175,8 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) sizeof(*midi) + opts->in_ports * sizeof(*midi->in_ports_array), GFP_KERNEL); if (!midi) { - mutex_unlock(&opts->lock); - return ERR_PTR(-ENOMEM); + status = -ENOMEM; + goto setup_fail; } for (i = 0; i < opts->in_ports; i++) @@ -1186,7 +1186,6 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) midi->id = kstrdup(opts->id, GFP_KERNEL); if (opts->id && !midi->id) { status = -ENOMEM; - mutex_unlock(&opts->lock); goto setup_fail; } midi->in_ports = opts->in_ports; @@ -1213,6 +1212,7 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) return &midi->func; setup_fail: + mutex_unlock(&opts->lock); kfree(midi); return ERR_PTR(status); } -- cgit v1.2.3-70-g09d2 From 4111d4943a369136b3d9f7ddaff1359f187cf94a Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Sat, 9 Jan 2016 04:20:37 +0100 Subject: usb: gadget: f_midi: stash substream in gmidi_in_port structure For every in_substream, there must be a corresponding gmidi_in_port structure so it is perfectly viable and some might argue sensible to stash pointer to the input substream in the gmidi_in_port structure. This has an added benefit that if in_ports < MAX_PORTS, the whole f_midi structure takes up less space because only in_ports number of pointers for in_substream are allocated instead of MAX_PORTS lots of them. Signed-off-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_midi.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index 0e411bffa4ab..84c0ee5ebd1e 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -56,6 +56,7 @@ static const char f_midi_longname[] = "MIDI Gadget"; * USB <- IN endpoint <- rawmidi */ struct gmidi_in_port { + struct snd_rawmidi_substream *substream; int active; uint8_t cable; uint8_t state; @@ -77,7 +78,6 @@ struct f_midi { struct snd_rawmidi *rmidi; u8 ms_id; - struct snd_rawmidi_substream *in_substream[MAX_PORTS]; struct snd_rawmidi_substream *out_substream[MAX_PORTS]; unsigned long out_triggered; @@ -520,7 +520,7 @@ static void f_midi_drop_out_substreams(struct f_midi *midi) for (i = 0; i < midi->in_ports; i++) { struct gmidi_in_port *port = midi->in_ports_array + i; - struct snd_rawmidi_substream *substream = midi->in_substream[i]; + struct snd_rawmidi_substream *substream = port->substream; if (port->active && substream) snd_rawmidi_drop_output(substream); } @@ -554,7 +554,7 @@ static int f_midi_do_transmit(struct f_midi *midi, struct usb_ep *ep) for (i = midi->in_last_port; i < midi->in_ports; ++i) { struct gmidi_in_port *port = midi->in_ports_array + i; - struct snd_rawmidi_substream *substream = midi->in_substream[i]; + struct snd_rawmidi_substream *substream = port->substream; if (!port->active || !substream) continue; @@ -623,13 +623,15 @@ static void f_midi_in_tasklet(unsigned long data) static int f_midi_in_open(struct snd_rawmidi_substream *substream) { struct f_midi *midi = substream->rmidi->private_data; + struct gmidi_in_port *port; if (substream->number >= midi->in_ports) return -EINVAL; VDBG(midi, "%s()\n", __func__); - midi->in_substream[substream->number] = substream; - midi->in_ports_array[substream->number].state = STATE_UNKNOWN; + port = midi->in_ports_array + substream->number; + port->substream = substream; + port->state = STATE_UNKNOWN; return 0; } -- cgit v1.2.3-70-g09d2 From 175f712119c57c0f2a9b553211d3edcfc460b484 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 18 Feb 2016 11:34:43 +0100 Subject: usb: gadget: provide interface for legacy gadgets to get UDC name Since commit 855ed04a3758b205e84b269f92d26ab36ed8e2f7 ("usb: gadget: udc-core: independent registration of gadgets and gadget drivers") gadget drivers can not assume that UDC drivers are already available on their initialization. This broke the HACK, which was used in gadgetfs driver, to get UDC controller name. This patch removes this hack and replaces it by additional function in the UDC core (which is usefully only for legacy drivers, please don't use it in the new code). Reported-by: Vegard Nossum Signed-off-by: Marek Szyprowski Tested-by: Vegard Nossum Signed-off-by: Felipe Balbi --- drivers/usb/gadget/legacy/inode.c | 28 +++------------------------- drivers/usb/gadget/udc/udc-core.c | 30 ++++++++++++++++++++++++++++++ include/linux/usb/gadget.h | 1 + 3 files changed, 34 insertions(+), 25 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 87fb0fd6aaab..5cdaf0150a4e 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -1699,28 +1699,6 @@ static struct usb_gadget_driver gadgetfs_driver = { }; /*----------------------------------------------------------------------*/ - -static void gadgetfs_nop(struct usb_gadget *arg) { } - -static int gadgetfs_probe(struct usb_gadget *gadget, - struct usb_gadget_driver *driver) -{ - CHIP = gadget->name; - return -EISNAM; -} - -static struct usb_gadget_driver probe_driver = { - .max_speed = USB_SPEED_HIGH, - .bind = gadgetfs_probe, - .unbind = gadgetfs_nop, - .setup = (void *)gadgetfs_nop, - .disconnect = gadgetfs_nop, - .driver = { - .name = "nop", - }, -}; - - /* DEVICE INITIALIZATION * * fd = open ("/dev/gadget/$CHIP", O_RDWR) @@ -1971,9 +1949,7 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent) if (the_device) return -ESRCH; - /* fake probe to determine $CHIP */ - CHIP = NULL; - usb_gadget_probe_driver(&probe_driver); + CHIP = usb_get_gadget_udc_name(); if (!CHIP) return -ENODEV; @@ -2034,6 +2010,8 @@ gadgetfs_kill_sb (struct super_block *sb) put_dev (the_device); the_device = NULL; } + kfree(CHIP); + CHIP = NULL; } /*----------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c index b86a6f03592e..4151597e9d28 100644 --- a/drivers/usb/gadget/udc/udc-core.c +++ b/drivers/usb/gadget/udc/udc-core.c @@ -442,6 +442,36 @@ err1: } EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release); +/** + * usb_get_gadget_udc_name - get the name of the first UDC controller + * This functions returns the name of the first UDC controller in the system. + * Please note that this interface is usefull only for legacy drivers which + * assume that there is only one UDC controller in the system and they need to + * get its name before initialization. There is no guarantee that the UDC + * of the returned name will be still available, when gadget driver registers + * itself. + * + * Returns pointer to string with UDC controller name on success, NULL + * otherwise. Caller should kfree() returned string. + */ +char *usb_get_gadget_udc_name(void) +{ + struct usb_udc *udc; + char *name = NULL; + + /* For now we take the first available UDC */ + mutex_lock(&udc_lock); + list_for_each_entry(udc, &udc_list, list) { + if (!udc->driver) { + name = kstrdup(udc->gadget->name, GFP_KERNEL); + break; + } + } + mutex_unlock(&udc_lock); + return name; +} +EXPORT_SYMBOL_GPL(usb_get_gadget_udc_name); + /** * usb_add_gadget_udc - adds a new gadget to the udc class driver list * @parent: the parent device to this udc. Usually the controller diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 42527297f218..dd7c53279e6a 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -1136,6 +1136,7 @@ extern int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, void (*release)(struct device *dev)); extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget); extern void usb_del_gadget_udc(struct usb_gadget *gadget); +extern char *usb_get_gadget_udc_name(void); /*-------------------------------------------------------------------------*/ -- cgit v1.2.3-70-g09d2 From c5348b621bd8a61fab3de9f69bf14c8545d7d642 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Fri, 19 Feb 2016 10:04:44 +0800 Subject: usb: gadget: composite: handle otg status selector request from OTG host If gadget with HNP polling support receives GetStatus request of otg status selector, it feedback to host with host request flag to indicate if it wants to take host role. Acked-by: Peter Chen Signed-off-by: Li Jun Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 64ad1bebb0fa..a5c62093c26c 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1707,15 +1707,24 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) *((u8 *)req->buf) = value; value = min(w_length, (u16) 1); break; - - /* - * USB 3.0 additions: - * Function driver should handle get_status request. If such cb - * wasn't supplied we respond with default value = 0 - * Note: function driver should supply such cb only for the first - * interface of the function - */ case USB_REQ_GET_STATUS: + if (gadget_is_otg(gadget) && gadget->hnp_polling_support && + (w_index == OTG_STS_SELECTOR)) { + if (ctrl->bRequestType != (USB_DIR_IN | + USB_RECIP_DEVICE)) + goto unknown; + *((u8 *)req->buf) = gadget->host_request_flag; + value = 1; + break; + } + + /* + * USB 3.0 additions: + * Function driver should handle get_status request. If such cb + * wasn't supplied we respond with default value = 0 + * Note: function driver should supply such cb only for the + * first interface of the function + */ if (!gadget_is_superspeed(gadget)) goto unknown; if (ctrl->bRequestType != (USB_DIR_IN | USB_RECIP_INTERFACE)) -- cgit v1.2.3-70-g09d2 From cff5638ef7852196879f9687e70d49ea291bbb33 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Sat, 27 Feb 2016 01:33:14 +0300 Subject: usb: gadget: bdc_udc: fix race condition in bdc_udc_exit() bdc_ep_disable() expects to be called with bdc->lock held. The assumption is met in all the cases except for call from bdc_udc_exit(), that is called from bdc_remove(). As a result a race can happen or unheld bdc->lock can be unlocked in bdc_req_complete(). The patch proposes to acquire-release bdc->lock around bdc_ep_disable() in bdc_udc_exit(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/bdc/bdc_udc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/udc/bdc/bdc_udc.c b/drivers/usb/gadget/udc/bdc/bdc_udc.c index 7f77db5d1278..aae7458d8986 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_udc.c +++ b/drivers/usb/gadget/udc/bdc/bdc_udc.c @@ -581,8 +581,13 @@ err0: void bdc_udc_exit(struct bdc *bdc) { + unsigned long flags; + dev_dbg(bdc->dev, "%s()\n", __func__); + spin_lock_irqsave(&bdc->lock, flags); bdc_ep_disable(bdc->bdc_ep_array[1]); + spin_unlock_irqrestore(&bdc->lock, flags); + usb_del_gadget_udc(&bdc->gadget); bdc_free_ep(bdc); } -- cgit v1.2.3-70-g09d2 From dd9fee67985882fd05fcf252fb4500265cb3fdcb Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 2 Mar 2016 11:17:17 +0900 Subject: usb: gadget: renesas_usb3: Use ARCH_RENESAS Make use of ARCH_RENESAS in place of ARCH_SHMOBILE. This is part of an ongoing process to migrate from ARCH_SHMOBILE to ARCH_RENESAS the motivation for which being that RENESAS seems to be a more appropriate name than SHMOBILE for the majority of Renesas ARM based SoCs. Acked-by: Geert Uytterhoeven Acked-by: Yoshihiro Shimoda Signed-off-by: Simon Horman Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index ff4f8a6735d6..7c289416f87d 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig @@ -176,7 +176,7 @@ config USB_RENESAS_USBHS_UDC config USB_RENESAS_USB3 tristate 'Renesas USB3.0 Peripheral controller' - depends on ARCH_SHMOBILE || COMPILE_TEST + depends on ARCH_RENESAS || COMPILE_TEST help Renesas USB3.0 Peripheral controller is a USB peripheral controller that supports super, high, and full speed USB 3.0 data transfers. -- cgit v1.2.3-70-g09d2 From 68726e772d3d2a65a4ea593a6cbde21a9700985a Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Thu, 3 Mar 2016 06:52:57 +0200 Subject: usb: udc: lpc32xx: switch to clock prepare/unprepare model The driver requires to prepare/unprepare clocks to work properly on a platform with enabled common clock framework, otherwise unprepared clocks are not enabled: WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:728 clk_core_enable+0x2c/0xf0() Modules linked in: CPU: 0 PID: 1 Comm: swapper Not tainted 4.3.0-rc2+ #284 Hardware name: LPC32XX SoC (Flattened Device Tree) Backtrace: [<>] (dump_backtrace) from [<>] (show_stack+0x18/0x1c) [<>] (show_stack) from [<>] (dump_stack+0x20/0x28) [<>] (dump_stack) from [<>] (warn_slowpath_common+0x90/0xb8) [<>] (warn_slowpath_common) from [<>] (warn_slowpath_null+0x24/0x2c) [<>] (warn_slowpath_null) from [<>] (clk_core_enable+0x2c/0xf0) [<>] (clk_core_enable) from [<>] (clk_enable+0x24/0x38) [<>] (clk_enable) from [<>] (lpc32xx_udc_probe+0x284/0x924) [<>] (lpc32xx_udc_probe) from [<>] (platform_drv_probe+0x50/0xa0) [<>] (platform_drv_probe) from [<>] (driver_probe_device+0x18c/0x408) [<>] (driver_probe_device) from [<>] (__driver_attach+0x70/0x94) [<>] (__driver_attach) from [<>] (bus_for_each_dev+0x74/0x98) [<>] (bus_for_each_dev) from [<>] (driver_attach+0x20/0x28) [<>] (driver_attach) from [<>] (bus_add_driver+0x11c/0x248) [<>] (bus_add_driver) from [<>] (driver_register+0xa4/0xe8) [<>] (driver_register) from [<>] (__platform_driver_register+0x50/0x64) [<>] (__platform_driver_register) from [<>] (__platform_driver_probe+0x54/0x100) [<>] (__platform_driver_probe) from [<>] (lpc32xx_udc_driver_init+0x1c/0x28) [<>] (lpc32xx_udc_driver_init) from [<>] (do_one_initcall+0x11c/0x1dc) [<>] (do_one_initcall) from [<>] (kernel_init_freeable+0x10c/0x1d4) [<>] (kernel_init_freeable) from [<>] (kernel_init+0x10/0xec) [<>] (kernel_init) from [<>] (ret_from_fork+0x14/0x24) Signed-off-by: Vladimir Zapolskiy Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/lpc32xx_udc.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c index 79fe6b77ee44..bb8737ad2c87 100644 --- a/drivers/usb/gadget/udc/lpc32xx_udc.c +++ b/drivers/usb/gadget/udc/lpc32xx_udc.c @@ -982,13 +982,13 @@ static void udc_clk_set(struct lpc32xx_udc *udc, int enable) udc->clocked = 1; /* 48MHz PLL up */ - clk_enable(udc->usb_pll_clk); + clk_prepare_enable(udc->usb_pll_clk); /* Enable the USB device clock */ writel(readl(USB_CTRL) | USB_DEV_NEED_CLK_EN, USB_CTRL); - clk_enable(udc->usb_otg_clk); + clk_prepare_enable(udc->usb_otg_clk); } else { if (!udc->clocked) return; @@ -998,13 +998,13 @@ static void udc_clk_set(struct lpc32xx_udc *udc, int enable) /* Never disable the USB_HCLK during normal operation */ /* 48MHz PLL dpwn */ - clk_disable(udc->usb_pll_clk); + clk_disable_unprepare(udc->usb_pll_clk); /* Disable the USB device clock */ writel(readl(USB_CTRL) & ~USB_DEV_NEED_CLK_EN, USB_CTRL); - clk_disable(udc->usb_otg_clk); + clk_disable_unprepare(udc->usb_otg_clk); } } @@ -3149,7 +3149,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) } /* Setup PLL clock to 48MHz */ - retval = clk_enable(udc->usb_pll_clk); + retval = clk_prepare_enable(udc->usb_pll_clk); if (retval < 0) { dev_err(udc->dev, "failed to start USB PLL\n"); goto pll_enable_fail; @@ -3164,14 +3164,14 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) writel(readl(USB_CTRL) | USB_DEV_NEED_CLK_EN, USB_CTRL); /* Enable USB device clock */ - retval = clk_enable(udc->usb_slv_clk); + retval = clk_prepare_enable(udc->usb_slv_clk); if (retval < 0) { dev_err(udc->dev, "failed to start USB device clock\n"); goto usb_clk_enable_fail; } /* Enable USB OTG clock */ - retval = clk_enable(udc->usb_otg_clk); + retval = clk_prepare_enable(udc->usb_otg_clk); if (retval < 0) { dev_err(udc->dev, "failed to start USB otg clock\n"); goto usb_otg_clk_enable_fail; @@ -3287,12 +3287,12 @@ dma_alloc_fail: dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE, udc->udca_v_base, udc->udca_p_base); i2c_fail: - clk_disable(udc->usb_otg_clk); + clk_disable_unprepare(udc->usb_otg_clk); usb_otg_clk_enable_fail: - clk_disable(udc->usb_slv_clk); + clk_disable_unprepare(udc->usb_slv_clk); usb_clk_enable_fail: pll_set_fail: - clk_disable(udc->usb_pll_clk); + clk_disable_unprepare(udc->usb_pll_clk); pll_enable_fail: clk_put(udc->usb_otg_clk); usb_otg_clk_get_fail: @@ -3336,11 +3336,11 @@ static int lpc32xx_udc_remove(struct platform_device *pdev) free_irq(udc->udp_irq[IRQ_USB_HP], udc); free_irq(udc->udp_irq[IRQ_USB_LP], udc); - clk_disable(udc->usb_otg_clk); + clk_disable_unprepare(udc->usb_otg_clk); clk_put(udc->usb_otg_clk); - clk_disable(udc->usb_slv_clk); + clk_disable_unprepare(udc->usb_slv_clk); clk_put(udc->usb_slv_clk); - clk_disable(udc->usb_pll_clk); + clk_disable_unprepare(udc->usb_pll_clk); clk_put(udc->usb_pll_clk); iounmap(udc->udp_baseaddr); release_mem_region(udc->io_p_start, udc->io_p_size); @@ -3367,7 +3367,7 @@ static int lpc32xx_udc_suspend(struct platform_device *pdev, pm_message_t mesg) udc->clocked = 1; /* Kill global USB clock */ - clk_disable(udc->usb_slv_clk); + clk_disable_unprepare(udc->usb_slv_clk); } return 0; @@ -3379,7 +3379,7 @@ static int lpc32xx_udc_resume(struct platform_device *pdev) if (udc->clocked) { /* Enable global USB clock */ - clk_enable(udc->usb_slv_clk); + clk_prepare_enable(udc->usb_slv_clk); /* Enable clocking */ udc_clk_set(udc, 1); -- cgit v1.2.3-70-g09d2 From c9083dd34a9f0b39ee343d6f3d115b42e2034bfe Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Thu, 3 Mar 2016 06:52:58 +0200 Subject: usb: udc: lpc32xx: remove direct access to clock controller registers Direct access to clock control registers can be safely removed, the task of clock management is done by platform clock driver based on common clock framework. Signed-off-by: Vladimir Zapolskiy Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/lpc32xx_udc.c | 29 ----------------------------- 1 file changed, 29 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c index bb8737ad2c87..2b8f21f5b5b5 100644 --- a/drivers/usb/gadget/udc/lpc32xx_udc.c +++ b/drivers/usb/gadget/udc/lpc32xx_udc.c @@ -49,7 +49,6 @@ #endif #include -#include /* * USB device configuration structure @@ -210,16 +209,6 @@ static inline struct lpc32xx_udc *to_udc(struct usb_gadget *g) #define UDCA_BUFF_SIZE (128) -/* TODO: When the clock framework is introduced in LPC32xx, IO_ADDRESS will - * be replaced with an inremap()ed pointer - * */ -#define USB_CTRL IO_ADDRESS(LPC32XX_CLK_PM_BASE + 0x64) - -/* USB_CTRL bit defines */ -#define USB_SLAVE_HCLK_EN (1 << 24) -#define USB_HOST_NEED_CLK_EN (1 << 21) -#define USB_DEV_NEED_CLK_EN (1 << 22) - /********************************************************************** * USB device controller register offsets **********************************************************************/ @@ -639,9 +628,6 @@ static void isp1301_udc_configure(struct lpc32xx_udc *udc) i2c_smbus_write_byte_data(udc->isp1301_i2c_client, ISP1301_I2C_INTERRUPT_RISING, INT_VBUS_VLD); - /* Enable usb_need_clk clock after transceiver is initialized */ - writel((readl(USB_CTRL) | USB_DEV_NEED_CLK_EN), USB_CTRL); - dev_info(udc->dev, "ISP1301 Vendor ID : 0x%04x\n", i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x00)); dev_info(udc->dev, "ISP1301 Product ID : 0x%04x\n", @@ -983,11 +969,6 @@ static void udc_clk_set(struct lpc32xx_udc *udc, int enable) /* 48MHz PLL up */ clk_prepare_enable(udc->usb_pll_clk); - - /* Enable the USB device clock */ - writel(readl(USB_CTRL) | USB_DEV_NEED_CLK_EN, - USB_CTRL); - clk_prepare_enable(udc->usb_otg_clk); } else { if (!udc->clocked) @@ -999,11 +980,6 @@ static void udc_clk_set(struct lpc32xx_udc *udc, int enable) /* 48MHz PLL dpwn */ clk_disable_unprepare(udc->usb_pll_clk); - - /* Disable the USB device clock */ - writel(readl(USB_CTRL) & ~USB_DEV_NEED_CLK_EN, - USB_CTRL); - clk_disable_unprepare(udc->usb_otg_clk); } } @@ -3125,9 +3101,6 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) goto io_map_fail; } - /* Enable AHB slave USB clock, needed for further USB clock control */ - writel(USB_SLAVE_HCLK_EN | (1 << 19), USB_CTRL); - /* Get required clocks */ udc->usb_pll_clk = clk_get(&pdev->dev, "ck_pll5"); if (IS_ERR(udc->usb_pll_clk)) { @@ -3161,8 +3134,6 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) goto pll_set_fail; } - writel(readl(USB_CTRL) | USB_DEV_NEED_CLK_EN, USB_CTRL); - /* Enable USB device clock */ retval = clk_prepare_enable(udc->usb_slv_clk); if (retval < 0) { -- cgit v1.2.3-70-g09d2 From 59e052727e8fc197f344d4d5ec10814247049972 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Thu, 3 Mar 2016 06:52:59 +0200 Subject: usb: udc: lpc32xx: remove USB PLL and USB OTG clock management LPC32xx common clock framework driver correctly manages parent clocks of USB device clock, so there is no need to manually enable and disable them from the driver, which now depends only on a single USB device clock. Signed-off-by: Vladimir Zapolskiy Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/lpc32xx_udc.c | 64 +++--------------------------------- 1 file changed, 5 insertions(+), 59 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c index 2b8f21f5b5b5..8f32b5ee7734 100644 --- a/drivers/usb/gadget/udc/lpc32xx_udc.c +++ b/drivers/usb/gadget/udc/lpc32xx_udc.c @@ -146,9 +146,7 @@ struct lpc32xx_udc { u32 io_p_size; void __iomem *udp_baseaddr; int udp_irq[4]; - struct clk *usb_pll_clk; struct clk *usb_slv_clk; - struct clk *usb_otg_clk; /* DMA support */ u32 *udca_v_base; @@ -966,21 +964,13 @@ static void udc_clk_set(struct lpc32xx_udc *udc, int enable) return; udc->clocked = 1; - - /* 48MHz PLL up */ - clk_prepare_enable(udc->usb_pll_clk); - clk_prepare_enable(udc->usb_otg_clk); + clk_prepare_enable(udc->usb_slv_clk); } else { if (!udc->clocked) return; udc->clocked = 0; - - /* Never disable the USB_HCLK during normal operation */ - - /* 48MHz PLL dpwn */ - clk_disable_unprepare(udc->usb_pll_clk); - clk_disable_unprepare(udc->usb_otg_clk); + clk_disable_unprepare(udc->usb_slv_clk); } } @@ -3101,38 +3091,13 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) goto io_map_fail; } - /* Get required clocks */ - udc->usb_pll_clk = clk_get(&pdev->dev, "ck_pll5"); - if (IS_ERR(udc->usb_pll_clk)) { - dev_err(udc->dev, "failed to acquire USB PLL\n"); - retval = PTR_ERR(udc->usb_pll_clk); - goto pll_get_fail; - } - udc->usb_slv_clk = clk_get(&pdev->dev, "ck_usbd"); + /* Get USB device clock */ + udc->usb_slv_clk = clk_get(&pdev->dev, NULL); if (IS_ERR(udc->usb_slv_clk)) { dev_err(udc->dev, "failed to acquire USB device clock\n"); retval = PTR_ERR(udc->usb_slv_clk); goto usb_clk_get_fail; } - udc->usb_otg_clk = clk_get(&pdev->dev, "ck_usb_otg"); - if (IS_ERR(udc->usb_otg_clk)) { - dev_err(udc->dev, "failed to acquire USB otg clock\n"); - retval = PTR_ERR(udc->usb_otg_clk); - goto usb_otg_clk_get_fail; - } - - /* Setup PLL clock to 48MHz */ - retval = clk_prepare_enable(udc->usb_pll_clk); - if (retval < 0) { - dev_err(udc->dev, "failed to start USB PLL\n"); - goto pll_enable_fail; - } - - retval = clk_set_rate(udc->usb_pll_clk, 48000); - if (retval < 0) { - dev_err(udc->dev, "failed to set USB clock rate\n"); - goto pll_set_fail; - } /* Enable USB device clock */ retval = clk_prepare_enable(udc->usb_slv_clk); @@ -3141,13 +3106,6 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) goto usb_clk_enable_fail; } - /* Enable USB OTG clock */ - retval = clk_prepare_enable(udc->usb_otg_clk); - if (retval < 0) { - dev_err(udc->dev, "failed to start USB otg clock\n"); - goto usb_otg_clk_enable_fail; - } - /* Setup deferred workqueue data */ udc->poweron = udc->pullup = 0; INIT_WORK(&udc->pullup_job, pullup_work); @@ -3258,19 +3216,10 @@ dma_alloc_fail: dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE, udc->udca_v_base, udc->udca_p_base); i2c_fail: - clk_disable_unprepare(udc->usb_otg_clk); -usb_otg_clk_enable_fail: clk_disable_unprepare(udc->usb_slv_clk); usb_clk_enable_fail: -pll_set_fail: - clk_disable_unprepare(udc->usb_pll_clk); -pll_enable_fail: - clk_put(udc->usb_otg_clk); -usb_otg_clk_get_fail: clk_put(udc->usb_slv_clk); usb_clk_get_fail: - clk_put(udc->usb_pll_clk); -pll_get_fail: iounmap(udc->udp_baseaddr); io_map_fail: release_mem_region(udc->io_p_start, udc->io_p_size); @@ -3307,12 +3256,9 @@ static int lpc32xx_udc_remove(struct platform_device *pdev) free_irq(udc->udp_irq[IRQ_USB_HP], udc); free_irq(udc->udp_irq[IRQ_USB_LP], udc); - clk_disable_unprepare(udc->usb_otg_clk); - clk_put(udc->usb_otg_clk); clk_disable_unprepare(udc->usb_slv_clk); clk_put(udc->usb_slv_clk); - clk_disable_unprepare(udc->usb_pll_clk); - clk_put(udc->usb_pll_clk); + iounmap(udc->udp_baseaddr); release_mem_region(udc->io_p_start, udc->io_p_size); kfree(udc); -- cgit v1.2.3-70-g09d2 From 0561f77e2db9e72dc32e4f82b56fca8ba6b31171 Mon Sep 17 00:00:00 2001 From: Krzysztof Opasiak Date: Tue, 1 Mar 2016 12:47:11 +0100 Subject: usb: gadget: f_acm: Fix configfs attr name Correct attribute name is port_num not num. Fixes: ea6bd6b ("usb-gadget/f_acm: use per-attribute show and store methods") Reviewed-by: Christoph Hellwig Signed-off-by: Krzysztof Opasiak Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_acm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/function/f_acm.c b/drivers/usb/gadget/function/f_acm.c index dc13b280db28..a30766ca4226 100644 --- a/drivers/usb/gadget/function/f_acm.c +++ b/drivers/usb/gadget/function/f_acm.c @@ -777,10 +777,10 @@ static ssize_t f_acm_port_num_show(struct config_item *item, char *page) return sprintf(page, "%u\n", to_f_serial_opts(item)->port_num); } -CONFIGFS_ATTR_RO(f_acm_port_, num); +CONFIGFS_ATTR_RO(f_acm_, port_num); static struct configfs_attribute *acm_attrs[] = { - &f_acm_port_attr_num, + &f_acm_attr_port_num, NULL, }; -- cgit v1.2.3-70-g09d2