12f98382dSKuninori Morimoto /* 22f98382dSKuninori Morimoto * Renesas USB driver 32f98382dSKuninori Morimoto * 42f98382dSKuninori Morimoto * Copyright (C) 2011 Renesas Solutions Corp. 52f98382dSKuninori Morimoto * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 62f98382dSKuninori Morimoto * 72f98382dSKuninori Morimoto * This program is distributed in the hope that it will be useful, 82f98382dSKuninori Morimoto * but WITHOUT ANY WARRANTY; without even the implied warranty of 92f98382dSKuninori Morimoto * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 102f98382dSKuninori Morimoto * GNU General Public License for more details. 112f98382dSKuninori Morimoto * 122f98382dSKuninori Morimoto * You should have received a copy of the GNU General Public License 132f98382dSKuninori Morimoto * along with this program; if not, write to the Free Software 142f98382dSKuninori Morimoto * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 152f98382dSKuninori Morimoto * 162f98382dSKuninori Morimoto */ 17dfbb7f4fSKuninori Morimoto #include <linux/delay.h> 18d128a259SKuninori Morimoto #include <linux/dma-mapping.h> 192f98382dSKuninori Morimoto #include <linux/io.h> 202f98382dSKuninori Morimoto #include <linux/module.h> 212f98382dSKuninori Morimoto #include <linux/platform_device.h> 222f98382dSKuninori Morimoto #include <linux/usb/ch9.h> 232f98382dSKuninori Morimoto #include <linux/usb/gadget.h> 242f98382dSKuninori Morimoto #include "common.h" 252f98382dSKuninori Morimoto 262f98382dSKuninori Morimoto /* 272f98382dSKuninori Morimoto * struct 282f98382dSKuninori Morimoto */ 292f98382dSKuninori Morimoto struct usbhsg_request { 302f98382dSKuninori Morimoto struct usb_request req; 314bd04811SKuninori Morimoto struct usbhs_pkt pkt; 322f98382dSKuninori Morimoto }; 332f98382dSKuninori Morimoto 342f98382dSKuninori Morimoto #define EP_NAME_SIZE 8 352f98382dSKuninori Morimoto struct usbhsg_gpriv; 362f98382dSKuninori Morimoto struct usbhsg_uep { 372f98382dSKuninori Morimoto struct usb_ep ep; 382f98382dSKuninori Morimoto struct usbhs_pipe *pipe; 392f98382dSKuninori Morimoto 402f98382dSKuninori Morimoto char ep_name[EP_NAME_SIZE]; 412f98382dSKuninori Morimoto 422f98382dSKuninori Morimoto struct usbhsg_gpriv *gpriv; 432f98382dSKuninori Morimoto }; 442f98382dSKuninori Morimoto 452f98382dSKuninori Morimoto struct usbhsg_gpriv { 462f98382dSKuninori Morimoto struct usb_gadget gadget; 472f98382dSKuninori Morimoto struct usbhs_mod mod; 482f98382dSKuninori Morimoto 492f98382dSKuninori Morimoto struct usbhsg_uep *uep; 502f98382dSKuninori Morimoto int uep_size; 512f98382dSKuninori Morimoto 522f98382dSKuninori Morimoto struct usb_gadget_driver *driver; 532f98382dSKuninori Morimoto 542f98382dSKuninori Morimoto u32 status; 552f98382dSKuninori Morimoto #define USBHSG_STATUS_STARTED (1 << 0) 562f98382dSKuninori Morimoto #define USBHSG_STATUS_REGISTERD (1 << 1) 572f98382dSKuninori Morimoto #define USBHSG_STATUS_WEDGE (1 << 2) 58cac402ddSShimoda, Yoshihiro #define USBHSG_STATUS_SELF_POWERED (1 << 3) 5904a5def3STakeshi Kihara #define USBHSG_STATUS_SOFT_CONNECT (1 << 4) 602f98382dSKuninori Morimoto }; 612f98382dSKuninori Morimoto 622f98382dSKuninori Morimoto struct usbhsg_recip_handle { 632f98382dSKuninori Morimoto char *name; 642f98382dSKuninori Morimoto int (*device)(struct usbhs_priv *priv, struct usbhsg_uep *uep, 652f98382dSKuninori Morimoto struct usb_ctrlrequest *ctrl); 662f98382dSKuninori Morimoto int (*interface)(struct usbhs_priv *priv, struct usbhsg_uep *uep, 672f98382dSKuninori Morimoto struct usb_ctrlrequest *ctrl); 682f98382dSKuninori Morimoto int (*endpoint)(struct usbhs_priv *priv, struct usbhsg_uep *uep, 692f98382dSKuninori Morimoto struct usb_ctrlrequest *ctrl); 702f98382dSKuninori Morimoto }; 712f98382dSKuninori Morimoto 722f98382dSKuninori Morimoto /* 732f98382dSKuninori Morimoto * macro 742f98382dSKuninori Morimoto */ 752f98382dSKuninori Morimoto #define usbhsg_priv_to_gpriv(priv) \ 762f98382dSKuninori Morimoto container_of( \ 772f98382dSKuninori Morimoto usbhs_mod_get(priv, USBHS_GADGET), \ 782f98382dSKuninori Morimoto struct usbhsg_gpriv, mod) 792f98382dSKuninori Morimoto 802f98382dSKuninori Morimoto #define __usbhsg_for_each_uep(start, pos, g, i) \ 81925403f4SKuninori Morimoto for ((i) = start; \ 82925403f4SKuninori Morimoto ((i) < (g)->uep_size) && ((pos) = (g)->uep + (i)); \ 83925403f4SKuninori Morimoto (i)++) 842f98382dSKuninori Morimoto 852f98382dSKuninori Morimoto #define usbhsg_for_each_uep(pos, gpriv, i) \ 862f98382dSKuninori Morimoto __usbhsg_for_each_uep(1, pos, gpriv, i) 872f98382dSKuninori Morimoto 882f98382dSKuninori Morimoto #define usbhsg_for_each_uep_with_dcp(pos, gpriv, i) \ 892f98382dSKuninori Morimoto __usbhsg_for_each_uep(0, pos, gpriv, i) 902f98382dSKuninori Morimoto 912f98382dSKuninori Morimoto #define usbhsg_gadget_to_gpriv(g)\ 922f98382dSKuninori Morimoto container_of(g, struct usbhsg_gpriv, gadget) 932f98382dSKuninori Morimoto 942f98382dSKuninori Morimoto #define usbhsg_req_to_ureq(r)\ 952f98382dSKuninori Morimoto container_of(r, struct usbhsg_request, req) 962f98382dSKuninori Morimoto 972f98382dSKuninori Morimoto #define usbhsg_ep_to_uep(e) container_of(e, struct usbhsg_uep, ep) 982f98382dSKuninori Morimoto #define usbhsg_gpriv_to_dev(gp) usbhs_priv_to_dev((gp)->mod.priv) 992f98382dSKuninori Morimoto #define usbhsg_gpriv_to_priv(gp) ((gp)->mod.priv) 1002f98382dSKuninori Morimoto #define usbhsg_gpriv_to_dcp(gp) ((gp)->uep) 1012f98382dSKuninori Morimoto #define usbhsg_gpriv_to_nth_uep(gp, i) ((gp)->uep + i) 1022f98382dSKuninori Morimoto #define usbhsg_uep_to_gpriv(u) ((u)->gpriv) 1032f98382dSKuninori Morimoto #define usbhsg_uep_to_pipe(u) ((u)->pipe) 1042f98382dSKuninori Morimoto #define usbhsg_pipe_to_uep(p) ((p)->mod_private) 1052f98382dSKuninori Morimoto #define usbhsg_is_dcp(u) ((u) == usbhsg_gpriv_to_dcp((u)->gpriv)) 1062f98382dSKuninori Morimoto 1074bd04811SKuninori Morimoto #define usbhsg_ureq_to_pkt(u) (&(u)->pkt) 1084bd04811SKuninori Morimoto #define usbhsg_pkt_to_ureq(i) \ 1094bd04811SKuninori Morimoto container_of(i, struct usbhsg_request, pkt) 1104bd04811SKuninori Morimoto 1112f98382dSKuninori Morimoto #define usbhsg_is_not_connected(gp) ((gp)->gadget.speed == USB_SPEED_UNKNOWN) 1122f98382dSKuninori Morimoto 1132f98382dSKuninori Morimoto /* status */ 1142f98382dSKuninori Morimoto #define usbhsg_status_init(gp) do {(gp)->status = 0; } while (0) 1152f98382dSKuninori Morimoto #define usbhsg_status_set(gp, b) (gp->status |= b) 1162f98382dSKuninori Morimoto #define usbhsg_status_clr(gp, b) (gp->status &= ~b) 1172f98382dSKuninori Morimoto #define usbhsg_status_has(gp, b) (gp->status & b) 1182f98382dSKuninori Morimoto 1192f98382dSKuninori Morimoto /* 120233f519dSKuninori Morimoto * queue push/pop 1212f98382dSKuninori Morimoto */ 1222f98382dSKuninori Morimoto static void usbhsg_queue_pop(struct usbhsg_uep *uep, 1232f98382dSKuninori Morimoto struct usbhsg_request *ureq, 1242f98382dSKuninori Morimoto int status) 1252f98382dSKuninori Morimoto { 1262f98382dSKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); 1272f98382dSKuninori Morimoto struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); 1282f98382dSKuninori Morimoto struct device *dev = usbhsg_gpriv_to_dev(gpriv); 1292f98382dSKuninori Morimoto 1302f98382dSKuninori Morimoto dev_dbg(dev, "pipe %d : queue pop\n", usbhs_pipe_number(pipe)); 1312f98382dSKuninori Morimoto 1322f98382dSKuninori Morimoto ureq->req.status = status; 133304f7e5eSMichal Sojka usb_gadget_giveback_request(&uep->ep, &ureq->req); 1342f98382dSKuninori Morimoto } 1352f98382dSKuninori Morimoto 1362cc97197SKuninori Morimoto static void usbhsg_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt) 1372f98382dSKuninori Morimoto { 1384bd04811SKuninori Morimoto struct usbhs_pipe *pipe = pkt->pipe; 1394bd04811SKuninori Morimoto struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe); 1404bd04811SKuninori Morimoto struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt); 1414bd04811SKuninori Morimoto 142659d4954SKuninori Morimoto ureq->req.actual = pkt->actual; 1432f98382dSKuninori Morimoto 1442f98382dSKuninori Morimoto usbhsg_queue_pop(uep, ureq, 0); 1452f98382dSKuninori Morimoto } 1464bd04811SKuninori Morimoto 147b331872bSKuninori Morimoto static void usbhsg_queue_push(struct usbhsg_uep *uep, 148b331872bSKuninori Morimoto struct usbhsg_request *ureq) 149b331872bSKuninori Morimoto { 150b331872bSKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); 151b331872bSKuninori Morimoto struct device *dev = usbhsg_gpriv_to_dev(gpriv); 152b331872bSKuninori Morimoto struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); 153b331872bSKuninori Morimoto struct usbhs_pkt *pkt = usbhsg_ureq_to_pkt(ureq); 154b331872bSKuninori Morimoto struct usb_request *req = &ureq->req; 155b331872bSKuninori Morimoto 156b331872bSKuninori Morimoto req->actual = 0; 157b331872bSKuninori Morimoto req->status = -EINPROGRESS; 158b331872bSKuninori Morimoto usbhs_pkt_push(pipe, pkt, usbhsg_queue_done, 1593edeee38SKuninori Morimoto req->buf, req->length, req->zero, -1); 160654c35abSKuninori Morimoto usbhs_pkt_start(pipe); 161b331872bSKuninori Morimoto 162b331872bSKuninori Morimoto dev_dbg(dev, "pipe %d : queue push (%d)\n", 163b331872bSKuninori Morimoto usbhs_pipe_number(pipe), 164b331872bSKuninori Morimoto req->length); 165b331872bSKuninori Morimoto } 166b331872bSKuninori Morimoto 167233f519dSKuninori Morimoto /* 168233f519dSKuninori Morimoto * dma map/unmap 169233f519dSKuninori Morimoto */ 170e73a9891SKuninori Morimoto static int usbhsg_dma_map_ctrl(struct usbhs_pkt *pkt, int map) 171e73a9891SKuninori Morimoto { 172ade78f9fSFelipe Balbi struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt); 173ade78f9fSFelipe Balbi struct usb_request *req = &ureq->req; 174e73a9891SKuninori Morimoto struct usbhs_pipe *pipe = pkt->pipe; 175e73a9891SKuninori Morimoto struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe); 176e73a9891SKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); 177e73a9891SKuninori Morimoto enum dma_data_direction dir; 178ade78f9fSFelipe Balbi int ret = 0; 179e73a9891SKuninori Morimoto 180ade78f9fSFelipe Balbi dir = usbhs_pipe_is_dir_host(pipe); 181e73a9891SKuninori Morimoto 182ade78f9fSFelipe Balbi if (map) { 183ade78f9fSFelipe Balbi /* it can not use scatter/gather */ 184ade78f9fSFelipe Balbi WARN_ON(req->num_sgs); 185ade78f9fSFelipe Balbi 186ade78f9fSFelipe Balbi ret = usb_gadget_map_request(&gpriv->gadget, req, dir); 187ade78f9fSFelipe Balbi if (ret < 0) 188ade78f9fSFelipe Balbi return ret; 189ade78f9fSFelipe Balbi 190ade78f9fSFelipe Balbi pkt->dma = req->dma; 191ade78f9fSFelipe Balbi } else { 192ade78f9fSFelipe Balbi usb_gadget_unmap_request(&gpriv->gadget, req, dir); 193ade78f9fSFelipe Balbi } 194ade78f9fSFelipe Balbi 195ade78f9fSFelipe Balbi return ret; 196e73a9891SKuninori Morimoto } 197e73a9891SKuninori Morimoto 1982f98382dSKuninori Morimoto /* 1992f98382dSKuninori Morimoto * USB_TYPE_STANDARD / clear feature functions 2002f98382dSKuninori Morimoto */ 2012f98382dSKuninori Morimoto static int usbhsg_recip_handler_std_control_done(struct usbhs_priv *priv, 2022f98382dSKuninori Morimoto struct usbhsg_uep *uep, 2032f98382dSKuninori Morimoto struct usb_ctrlrequest *ctrl) 2042f98382dSKuninori Morimoto { 2052f98382dSKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); 2062f98382dSKuninori Morimoto struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); 2072f98382dSKuninori Morimoto struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(dcp); 2082f98382dSKuninori Morimoto 2092f98382dSKuninori Morimoto usbhs_dcp_control_transfer_done(pipe); 2102f98382dSKuninori Morimoto 2112f98382dSKuninori Morimoto return 0; 2122f98382dSKuninori Morimoto } 2132f98382dSKuninori Morimoto 2142f98382dSKuninori Morimoto static int usbhsg_recip_handler_std_clear_endpoint(struct usbhs_priv *priv, 2152f98382dSKuninori Morimoto struct usbhsg_uep *uep, 2162f98382dSKuninori Morimoto struct usb_ctrlrequest *ctrl) 2172f98382dSKuninori Morimoto { 2182f98382dSKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); 2192f98382dSKuninori Morimoto struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); 2202f98382dSKuninori Morimoto 2212f98382dSKuninori Morimoto if (!usbhsg_status_has(gpriv, USBHSG_STATUS_WEDGE)) { 222e8d548d5SKuninori Morimoto usbhs_pipe_disable(pipe); 2236e6db82bSKuninori Morimoto usbhs_pipe_sequence_data0(pipe); 224e8d548d5SKuninori Morimoto usbhs_pipe_enable(pipe); 2252f98382dSKuninori Morimoto } 2262f98382dSKuninori Morimoto 2272f98382dSKuninori Morimoto usbhsg_recip_handler_std_control_done(priv, uep, ctrl); 2282f98382dSKuninori Morimoto 22925fa7079SKuninori Morimoto usbhs_pkt_start(pipe); 23025fa7079SKuninori Morimoto 2312f98382dSKuninori Morimoto return 0; 2322f98382dSKuninori Morimoto } 2332f98382dSKuninori Morimoto 234225da3e3SKuninori Morimoto static struct usbhsg_recip_handle req_clear_feature = { 2352f98382dSKuninori Morimoto .name = "clear feature", 2362f98382dSKuninori Morimoto .device = usbhsg_recip_handler_std_control_done, 2372f98382dSKuninori Morimoto .interface = usbhsg_recip_handler_std_control_done, 2382f98382dSKuninori Morimoto .endpoint = usbhsg_recip_handler_std_clear_endpoint, 2392f98382dSKuninori Morimoto }; 2402f98382dSKuninori Morimoto 2412f98382dSKuninori Morimoto /* 242ced6e09eSKuninori Morimoto * USB_TYPE_STANDARD / set feature functions 243ced6e09eSKuninori Morimoto */ 244dfbb7f4fSKuninori Morimoto static int usbhsg_recip_handler_std_set_device(struct usbhs_priv *priv, 245dfbb7f4fSKuninori Morimoto struct usbhsg_uep *uep, 246dfbb7f4fSKuninori Morimoto struct usb_ctrlrequest *ctrl) 247dfbb7f4fSKuninori Morimoto { 248dfbb7f4fSKuninori Morimoto switch (le16_to_cpu(ctrl->wValue)) { 249dfbb7f4fSKuninori Morimoto case USB_DEVICE_TEST_MODE: 250dfbb7f4fSKuninori Morimoto usbhsg_recip_handler_std_control_done(priv, uep, ctrl); 251dfbb7f4fSKuninori Morimoto udelay(100); 252dfbb7f4fSKuninori Morimoto usbhs_sys_set_test_mode(priv, le16_to_cpu(ctrl->wIndex >> 8)); 253dfbb7f4fSKuninori Morimoto break; 254dfbb7f4fSKuninori Morimoto default: 255dfbb7f4fSKuninori Morimoto usbhsg_recip_handler_std_control_done(priv, uep, ctrl); 256dfbb7f4fSKuninori Morimoto break; 257dfbb7f4fSKuninori Morimoto } 258dfbb7f4fSKuninori Morimoto 259dfbb7f4fSKuninori Morimoto return 0; 260dfbb7f4fSKuninori Morimoto } 261dfbb7f4fSKuninori Morimoto 262ced6e09eSKuninori Morimoto static int usbhsg_recip_handler_std_set_endpoint(struct usbhs_priv *priv, 263ced6e09eSKuninori Morimoto struct usbhsg_uep *uep, 264ced6e09eSKuninori Morimoto struct usb_ctrlrequest *ctrl) 265ced6e09eSKuninori Morimoto { 266ced6e09eSKuninori Morimoto struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); 267ced6e09eSKuninori Morimoto 268ced6e09eSKuninori Morimoto usbhs_pipe_stall(pipe); 269ced6e09eSKuninori Morimoto 270ced6e09eSKuninori Morimoto usbhsg_recip_handler_std_control_done(priv, uep, ctrl); 271ced6e09eSKuninori Morimoto 272ced6e09eSKuninori Morimoto return 0; 273ced6e09eSKuninori Morimoto } 274ced6e09eSKuninori Morimoto 275225da3e3SKuninori Morimoto static struct usbhsg_recip_handle req_set_feature = { 276ced6e09eSKuninori Morimoto .name = "set feature", 277dfbb7f4fSKuninori Morimoto .device = usbhsg_recip_handler_std_set_device, 278ced6e09eSKuninori Morimoto .interface = usbhsg_recip_handler_std_control_done, 279ced6e09eSKuninori Morimoto .endpoint = usbhsg_recip_handler_std_set_endpoint, 280ced6e09eSKuninori Morimoto }; 281ced6e09eSKuninori Morimoto 282ced6e09eSKuninori Morimoto /* 28317f7f769SKuninori Morimoto * USB_TYPE_STANDARD / get status functions 28417f7f769SKuninori Morimoto */ 28517f7f769SKuninori Morimoto static void __usbhsg_recip_send_complete(struct usb_ep *ep, 28617f7f769SKuninori Morimoto struct usb_request *req) 28717f7f769SKuninori Morimoto { 28817f7f769SKuninori Morimoto struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); 28917f7f769SKuninori Morimoto 29017f7f769SKuninori Morimoto /* free allocated recip-buffer/usb_request */ 29117f7f769SKuninori Morimoto kfree(ureq->pkt.buf); 29217f7f769SKuninori Morimoto usb_ep_free_request(ep, req); 29317f7f769SKuninori Morimoto } 29417f7f769SKuninori Morimoto 29517f7f769SKuninori Morimoto static void __usbhsg_recip_send_status(struct usbhsg_gpriv *gpriv, 29617f7f769SKuninori Morimoto unsigned short status) 29717f7f769SKuninori Morimoto { 29817f7f769SKuninori Morimoto struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); 29917f7f769SKuninori Morimoto struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(dcp); 30017f7f769SKuninori Morimoto struct device *dev = usbhsg_gpriv_to_dev(gpriv); 30117f7f769SKuninori Morimoto struct usb_request *req; 30217f7f769SKuninori Morimoto unsigned short *buf; 30317f7f769SKuninori Morimoto 30417f7f769SKuninori Morimoto /* alloc new usb_request for recip */ 30517f7f769SKuninori Morimoto req = usb_ep_alloc_request(&dcp->ep, GFP_ATOMIC); 30617f7f769SKuninori Morimoto if (!req) { 30717f7f769SKuninori Morimoto dev_err(dev, "recip request allocation fail\n"); 30817f7f769SKuninori Morimoto return; 30917f7f769SKuninori Morimoto } 31017f7f769SKuninori Morimoto 31117f7f769SKuninori Morimoto /* alloc recip data buffer */ 31217f7f769SKuninori Morimoto buf = kmalloc(sizeof(*buf), GFP_ATOMIC); 31317f7f769SKuninori Morimoto if (!buf) { 31417f7f769SKuninori Morimoto usb_ep_free_request(&dcp->ep, req); 31517f7f769SKuninori Morimoto dev_err(dev, "recip data allocation fail\n"); 31617f7f769SKuninori Morimoto return; 31717f7f769SKuninori Morimoto } 31817f7f769SKuninori Morimoto 31917f7f769SKuninori Morimoto /* recip data is status */ 32017f7f769SKuninori Morimoto *buf = cpu_to_le16(status); 32117f7f769SKuninori Morimoto 32217f7f769SKuninori Morimoto /* allocated usb_request/buffer will be freed */ 32317f7f769SKuninori Morimoto req->complete = __usbhsg_recip_send_complete; 32417f7f769SKuninori Morimoto req->buf = buf; 32517f7f769SKuninori Morimoto req->length = sizeof(*buf); 32617f7f769SKuninori Morimoto req->zero = 0; 32717f7f769SKuninori Morimoto 32817f7f769SKuninori Morimoto /* push packet */ 32917f7f769SKuninori Morimoto pipe->handler = &usbhs_fifo_pio_push_handler; 33017f7f769SKuninori Morimoto usbhsg_queue_push(dcp, usbhsg_req_to_ureq(req)); 33117f7f769SKuninori Morimoto } 33217f7f769SKuninori Morimoto 33317f7f769SKuninori Morimoto static int usbhsg_recip_handler_std_get_device(struct usbhs_priv *priv, 33417f7f769SKuninori Morimoto struct usbhsg_uep *uep, 33517f7f769SKuninori Morimoto struct usb_ctrlrequest *ctrl) 33617f7f769SKuninori Morimoto { 33717f7f769SKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); 338cac402ddSShimoda, Yoshihiro unsigned short status = 0; 339cac402ddSShimoda, Yoshihiro 340cac402ddSShimoda, Yoshihiro if (usbhsg_status_has(gpriv, USBHSG_STATUS_SELF_POWERED)) 341cac402ddSShimoda, Yoshihiro status = 1 << USB_DEVICE_SELF_POWERED; 34217f7f769SKuninori Morimoto 34317f7f769SKuninori Morimoto __usbhsg_recip_send_status(gpriv, status); 34417f7f769SKuninori Morimoto 34517f7f769SKuninori Morimoto return 0; 34617f7f769SKuninori Morimoto } 34717f7f769SKuninori Morimoto 34817f7f769SKuninori Morimoto static int usbhsg_recip_handler_std_get_interface(struct usbhs_priv *priv, 34917f7f769SKuninori Morimoto struct usbhsg_uep *uep, 35017f7f769SKuninori Morimoto struct usb_ctrlrequest *ctrl) 35117f7f769SKuninori Morimoto { 35217f7f769SKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); 35317f7f769SKuninori Morimoto unsigned short status = 0; 35417f7f769SKuninori Morimoto 35517f7f769SKuninori Morimoto __usbhsg_recip_send_status(gpriv, status); 35617f7f769SKuninori Morimoto 35717f7f769SKuninori Morimoto return 0; 35817f7f769SKuninori Morimoto } 35917f7f769SKuninori Morimoto 36017f7f769SKuninori Morimoto static int usbhsg_recip_handler_std_get_endpoint(struct usbhs_priv *priv, 36117f7f769SKuninori Morimoto struct usbhsg_uep *uep, 36217f7f769SKuninori Morimoto struct usb_ctrlrequest *ctrl) 36317f7f769SKuninori Morimoto { 36417f7f769SKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); 36517f7f769SKuninori Morimoto struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); 36617f7f769SKuninori Morimoto unsigned short status = 0; 36717f7f769SKuninori Morimoto 36817f7f769SKuninori Morimoto if (usbhs_pipe_is_stall(pipe)) 36917f7f769SKuninori Morimoto status = 1 << USB_ENDPOINT_HALT; 37017f7f769SKuninori Morimoto 37117f7f769SKuninori Morimoto __usbhsg_recip_send_status(gpriv, status); 37217f7f769SKuninori Morimoto 37317f7f769SKuninori Morimoto return 0; 37417f7f769SKuninori Morimoto } 37517f7f769SKuninori Morimoto 376225da3e3SKuninori Morimoto static struct usbhsg_recip_handle req_get_status = { 37717f7f769SKuninori Morimoto .name = "get status", 37817f7f769SKuninori Morimoto .device = usbhsg_recip_handler_std_get_device, 37917f7f769SKuninori Morimoto .interface = usbhsg_recip_handler_std_get_interface, 38017f7f769SKuninori Morimoto .endpoint = usbhsg_recip_handler_std_get_endpoint, 38117f7f769SKuninori Morimoto }; 38217f7f769SKuninori Morimoto 38317f7f769SKuninori Morimoto /* 3842f98382dSKuninori Morimoto * USB_TYPE handler 3852f98382dSKuninori Morimoto */ 3862f98382dSKuninori Morimoto static int usbhsg_recip_run_handle(struct usbhs_priv *priv, 3872f98382dSKuninori Morimoto struct usbhsg_recip_handle *handler, 3882f98382dSKuninori Morimoto struct usb_ctrlrequest *ctrl) 3892f98382dSKuninori Morimoto { 3902f98382dSKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); 3912f98382dSKuninori Morimoto struct device *dev = usbhsg_gpriv_to_dev(gpriv); 3922f98382dSKuninori Morimoto struct usbhsg_uep *uep; 3930432eed0SKuninori Morimoto struct usbhs_pipe *pipe; 3942f98382dSKuninori Morimoto int recip = ctrl->bRequestType & USB_RECIP_MASK; 3952f98382dSKuninori Morimoto int nth = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK; 3967983bc74SJesper Juhl int ret = 0; 3972f98382dSKuninori Morimoto int (*func)(struct usbhs_priv *priv, struct usbhsg_uep *uep, 3982f98382dSKuninori Morimoto struct usb_ctrlrequest *ctrl); 3992f98382dSKuninori Morimoto char *msg; 4002f98382dSKuninori Morimoto 4012f98382dSKuninori Morimoto uep = usbhsg_gpriv_to_nth_uep(gpriv, nth); 4020432eed0SKuninori Morimoto pipe = usbhsg_uep_to_pipe(uep); 4030432eed0SKuninori Morimoto if (!pipe) { 4049a28b7bdSKuninori Morimoto dev_err(dev, "wrong recip request\n"); 40525fa7079SKuninori Morimoto return -EINVAL; 4069a28b7bdSKuninori Morimoto } 4072f98382dSKuninori Morimoto 4082f98382dSKuninori Morimoto switch (recip) { 4092f98382dSKuninori Morimoto case USB_RECIP_DEVICE: 4102f98382dSKuninori Morimoto msg = "DEVICE"; 4112f98382dSKuninori Morimoto func = handler->device; 4122f98382dSKuninori Morimoto break; 4132f98382dSKuninori Morimoto case USB_RECIP_INTERFACE: 4142f98382dSKuninori Morimoto msg = "INTERFACE"; 4152f98382dSKuninori Morimoto func = handler->interface; 4162f98382dSKuninori Morimoto break; 4172f98382dSKuninori Morimoto case USB_RECIP_ENDPOINT: 4182f98382dSKuninori Morimoto msg = "ENDPOINT"; 4192f98382dSKuninori Morimoto func = handler->endpoint; 4202f98382dSKuninori Morimoto break; 4212f98382dSKuninori Morimoto default: 4222f98382dSKuninori Morimoto dev_warn(dev, "unsupported RECIP(%d)\n", recip); 4232f98382dSKuninori Morimoto func = NULL; 4242f98382dSKuninori Morimoto ret = -EINVAL; 4252f98382dSKuninori Morimoto } 4262f98382dSKuninori Morimoto 4272f98382dSKuninori Morimoto if (func) { 4282f98382dSKuninori Morimoto dev_dbg(dev, "%s (pipe %d :%s)\n", handler->name, nth, msg); 4292f98382dSKuninori Morimoto ret = func(priv, uep, ctrl); 4302f98382dSKuninori Morimoto } 4312f98382dSKuninori Morimoto 4322f98382dSKuninori Morimoto return ret; 4332f98382dSKuninori Morimoto } 4342f98382dSKuninori Morimoto 4352f98382dSKuninori Morimoto /* 4362f98382dSKuninori Morimoto * irq functions 4372f98382dSKuninori Morimoto * 4382f98382dSKuninori Morimoto * it will be called from usbhs_interrupt 4392f98382dSKuninori Morimoto */ 4402f98382dSKuninori Morimoto static int usbhsg_irq_dev_state(struct usbhs_priv *priv, 4412f98382dSKuninori Morimoto struct usbhs_irq_state *irq_state) 4422f98382dSKuninori Morimoto { 4432f98382dSKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); 4442f98382dSKuninori Morimoto struct device *dev = usbhsg_gpriv_to_dev(gpriv); 4452f98382dSKuninori Morimoto 44675587f52SKuninori Morimoto gpriv->gadget.speed = usbhs_bus_get_speed(priv); 4472f98382dSKuninori Morimoto 4482f98382dSKuninori Morimoto dev_dbg(dev, "state = %x : speed : %d\n", 4492f98382dSKuninori Morimoto usbhs_status_get_device_state(irq_state), 4502f98382dSKuninori Morimoto gpriv->gadget.speed); 4512f98382dSKuninori Morimoto 4522f98382dSKuninori Morimoto return 0; 4532f98382dSKuninori Morimoto } 4542f98382dSKuninori Morimoto 4552f98382dSKuninori Morimoto static int usbhsg_irq_ctrl_stage(struct usbhs_priv *priv, 4562f98382dSKuninori Morimoto struct usbhs_irq_state *irq_state) 4572f98382dSKuninori Morimoto { 4582f98382dSKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); 4592f98382dSKuninori Morimoto struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); 4602f98382dSKuninori Morimoto struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(dcp); 4612f98382dSKuninori Morimoto struct device *dev = usbhsg_gpriv_to_dev(gpriv); 4622f98382dSKuninori Morimoto struct usb_ctrlrequest ctrl; 4632f98382dSKuninori Morimoto struct usbhsg_recip_handle *recip_handler = NULL; 4642f98382dSKuninori Morimoto int stage = usbhs_status_get_ctrl_stage(irq_state); 4652f98382dSKuninori Morimoto int ret = 0; 4662f98382dSKuninori Morimoto 4672f98382dSKuninori Morimoto dev_dbg(dev, "stage = %d\n", stage); 4682f98382dSKuninori Morimoto 4692f98382dSKuninori Morimoto /* 4702f98382dSKuninori Morimoto * see Manual 4712f98382dSKuninori Morimoto * 4722f98382dSKuninori Morimoto * "Operation" 4732f98382dSKuninori Morimoto * - "Interrupt Function" 4742f98382dSKuninori Morimoto * - "Control Transfer Stage Transition Interrupt" 4752f98382dSKuninori Morimoto * - Fig. "Control Transfer Stage Transitions" 4762f98382dSKuninori Morimoto */ 4772f98382dSKuninori Morimoto 4782f98382dSKuninori Morimoto switch (stage) { 4792f98382dSKuninori Morimoto case READ_DATA_STAGE: 4800c6ef985SKuninori Morimoto pipe->handler = &usbhs_fifo_pio_push_handler; 4812f98382dSKuninori Morimoto break; 4822f98382dSKuninori Morimoto case WRITE_DATA_STAGE: 4830c6ef985SKuninori Morimoto pipe->handler = &usbhs_fifo_pio_pop_handler; 4842f98382dSKuninori Morimoto break; 4852f98382dSKuninori Morimoto case NODATA_STATUS_STAGE: 4860c6ef985SKuninori Morimoto pipe->handler = &usbhs_ctrl_stage_end_handler; 4872f98382dSKuninori Morimoto break; 4884ef35b10SYoshihiro Shimoda case READ_STATUS_STAGE: 4894ef35b10SYoshihiro Shimoda case WRITE_STATUS_STAGE: 4904ef35b10SYoshihiro Shimoda usbhs_dcp_control_transfer_done(pipe); 4912f98382dSKuninori Morimoto default: 4922f98382dSKuninori Morimoto return ret; 4932f98382dSKuninori Morimoto } 4942f98382dSKuninori Morimoto 4952f98382dSKuninori Morimoto /* 4962f98382dSKuninori Morimoto * get usb request 4972f98382dSKuninori Morimoto */ 4982f98382dSKuninori Morimoto usbhs_usbreq_get_val(priv, &ctrl); 4992f98382dSKuninori Morimoto 5002f98382dSKuninori Morimoto switch (ctrl.bRequestType & USB_TYPE_MASK) { 5012f98382dSKuninori Morimoto case USB_TYPE_STANDARD: 5022f98382dSKuninori Morimoto switch (ctrl.bRequest) { 5032f98382dSKuninori Morimoto case USB_REQ_CLEAR_FEATURE: 5042f98382dSKuninori Morimoto recip_handler = &req_clear_feature; 5052f98382dSKuninori Morimoto break; 506ced6e09eSKuninori Morimoto case USB_REQ_SET_FEATURE: 507ced6e09eSKuninori Morimoto recip_handler = &req_set_feature; 508ced6e09eSKuninori Morimoto break; 50917f7f769SKuninori Morimoto case USB_REQ_GET_STATUS: 51017f7f769SKuninori Morimoto recip_handler = &req_get_status; 51117f7f769SKuninori Morimoto break; 5122f98382dSKuninori Morimoto } 5132f98382dSKuninori Morimoto } 5142f98382dSKuninori Morimoto 5152f98382dSKuninori Morimoto /* 5162f98382dSKuninori Morimoto * setup stage / run recip 5172f98382dSKuninori Morimoto */ 5182f98382dSKuninori Morimoto if (recip_handler) 5192f98382dSKuninori Morimoto ret = usbhsg_recip_run_handle(priv, recip_handler, &ctrl); 5202f98382dSKuninori Morimoto else 5212f98382dSKuninori Morimoto ret = gpriv->driver->setup(&gpriv->gadget, &ctrl); 5222f98382dSKuninori Morimoto 5232f98382dSKuninori Morimoto if (ret < 0) 524e8d548d5SKuninori Morimoto usbhs_pipe_stall(pipe); 5252f98382dSKuninori Morimoto 5262f98382dSKuninori Morimoto return ret; 5272f98382dSKuninori Morimoto } 5282f98382dSKuninori Morimoto 5292f98382dSKuninori Morimoto /* 5302f98382dSKuninori Morimoto * 5312f98382dSKuninori Morimoto * usb_dcp_ops 5322f98382dSKuninori Morimoto * 5332f98382dSKuninori Morimoto */ 5342f98382dSKuninori Morimoto static int usbhsg_pipe_disable(struct usbhsg_uep *uep) 5352f98382dSKuninori Morimoto { 5362f98382dSKuninori Morimoto struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); 5378a2c225dSKuninori Morimoto struct usbhs_pkt *pkt; 5382f98382dSKuninori Morimoto 5392f98382dSKuninori Morimoto while (1) { 54097664a20SKuninori Morimoto pkt = usbhs_pkt_pop(pipe, NULL); 5418a2c225dSKuninori Morimoto if (!pkt) 5422f98382dSKuninori Morimoto break; 54391b158f4SKuninori Morimoto 54491b158f4SKuninori Morimoto usbhsg_queue_pop(uep, usbhsg_pkt_to_ureq(pkt), -ECONNRESET); 5452f98382dSKuninori Morimoto } 5462f98382dSKuninori Morimoto 54791b158f4SKuninori Morimoto usbhs_pipe_disable(pipe); 54891b158f4SKuninori Morimoto 5492f98382dSKuninori Morimoto return 0; 5502f98382dSKuninori Morimoto } 5512f98382dSKuninori Morimoto 5522f98382dSKuninori Morimoto /* 5532f98382dSKuninori Morimoto * 5542f98382dSKuninori Morimoto * usb_ep_ops 5552f98382dSKuninori Morimoto * 5562f98382dSKuninori Morimoto */ 5572f98382dSKuninori Morimoto static int usbhsg_ep_enable(struct usb_ep *ep, 5582f98382dSKuninori Morimoto const struct usb_endpoint_descriptor *desc) 5592f98382dSKuninori Morimoto { 5602f98382dSKuninori Morimoto struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); 5612f98382dSKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); 5622f98382dSKuninori Morimoto struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); 5632f98382dSKuninori Morimoto struct usbhs_pipe *pipe; 5642f98382dSKuninori Morimoto int ret = -EIO; 5652f98382dSKuninori Morimoto 566409ba9e7SKuninori Morimoto /* 567409ba9e7SKuninori Morimoto * if it already have pipe, 568409ba9e7SKuninori Morimoto * nothing to do 569409ba9e7SKuninori Morimoto */ 57008e6c611SKuninori Morimoto if (uep->pipe) { 57108e6c611SKuninori Morimoto usbhs_pipe_clear(uep->pipe); 5726e6db82bSKuninori Morimoto usbhs_pipe_sequence_data0(uep->pipe); 573409ba9e7SKuninori Morimoto return 0; 57408e6c611SKuninori Morimoto } 575409ba9e7SKuninori Morimoto 576f5aa889fSKuninori Morimoto pipe = usbhs_pipe_malloc(priv, 577f5aa889fSKuninori Morimoto usb_endpoint_type(desc), 578f5aa889fSKuninori Morimoto usb_endpoint_dir_in(desc)); 5792f98382dSKuninori Morimoto if (pipe) { 5802f98382dSKuninori Morimoto uep->pipe = pipe; 5812f98382dSKuninori Morimoto pipe->mod_private = uep; 5822f98382dSKuninori Morimoto 583f5aa889fSKuninori Morimoto /* set epnum / maxp */ 584bc6fbf59SKuninori Morimoto usbhs_pipe_config_update(pipe, 0, 585f5aa889fSKuninori Morimoto usb_endpoint_num(desc), 586f5aa889fSKuninori Morimoto usb_endpoint_maxp(desc)); 587f5aa889fSKuninori Morimoto 588233f519dSKuninori Morimoto /* 589233f519dSKuninori Morimoto * usbhs_fifo_dma_push/pop_handler try to 590233f519dSKuninori Morimoto * use dmaengine if possible. 591233f519dSKuninori Morimoto * It will use pio handler if impossible. 592233f519dSKuninori Morimoto */ 5932f98382dSKuninori Morimoto if (usb_endpoint_dir_in(desc)) 5940c6ef985SKuninori Morimoto pipe->handler = &usbhs_fifo_dma_push_handler; 5952f98382dSKuninori Morimoto else 5960c6ef985SKuninori Morimoto pipe->handler = &usbhs_fifo_dma_pop_handler; 5972f98382dSKuninori Morimoto 5982f98382dSKuninori Morimoto ret = 0; 5992f98382dSKuninori Morimoto } 600cb96632cSKuninori Morimoto 6012f98382dSKuninori Morimoto return ret; 6022f98382dSKuninori Morimoto } 6032f98382dSKuninori Morimoto 6042f98382dSKuninori Morimoto static int usbhsg_ep_disable(struct usb_ep *ep) 6052f98382dSKuninori Morimoto { 6062f98382dSKuninori Morimoto struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); 607dfb87b8bSYoshihiro Shimoda struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); 6082f98382dSKuninori Morimoto 60911432050SKazuya Mizuguchi if (!pipe) 61011432050SKazuya Mizuguchi return -EINVAL; 61111432050SKazuya Mizuguchi 612d9fa298fSKuninori Morimoto usbhsg_pipe_disable(uep); 613dfb87b8bSYoshihiro Shimoda usbhs_pipe_free(pipe); 614d9fa298fSKuninori Morimoto 615d9fa298fSKuninori Morimoto uep->pipe->mod_private = NULL; 616d9fa298fSKuninori Morimoto uep->pipe = NULL; 617d9fa298fSKuninori Morimoto 618d9fa298fSKuninori Morimoto return 0; 6192f98382dSKuninori Morimoto } 6202f98382dSKuninori Morimoto 6212f98382dSKuninori Morimoto static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep, 6222f98382dSKuninori Morimoto gfp_t gfp_flags) 6232f98382dSKuninori Morimoto { 6242f98382dSKuninori Morimoto struct usbhsg_request *ureq; 6252f98382dSKuninori Morimoto 6262f98382dSKuninori Morimoto ureq = kzalloc(sizeof *ureq, gfp_flags); 6272f98382dSKuninori Morimoto if (!ureq) 6282f98382dSKuninori Morimoto return NULL; 6292f98382dSKuninori Morimoto 6306acb95d4SKuninori Morimoto usbhs_pkt_init(usbhsg_ureq_to_pkt(ureq)); 6316acb95d4SKuninori Morimoto 6322f98382dSKuninori Morimoto return &ureq->req; 6332f98382dSKuninori Morimoto } 6342f98382dSKuninori Morimoto 6352f98382dSKuninori Morimoto static void usbhsg_ep_free_request(struct usb_ep *ep, 6362f98382dSKuninori Morimoto struct usb_request *req) 6372f98382dSKuninori Morimoto { 6382f98382dSKuninori Morimoto struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); 6392f98382dSKuninori Morimoto 6406acb95d4SKuninori Morimoto WARN_ON(!list_empty(&ureq->pkt.node)); 6412f98382dSKuninori Morimoto kfree(ureq); 6422f98382dSKuninori Morimoto } 6432f98382dSKuninori Morimoto 6442f98382dSKuninori Morimoto static int usbhsg_ep_queue(struct usb_ep *ep, struct usb_request *req, 6452f98382dSKuninori Morimoto gfp_t gfp_flags) 6462f98382dSKuninori Morimoto { 6472f98382dSKuninori Morimoto struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); 6482f98382dSKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); 6492f98382dSKuninori Morimoto struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); 6502f98382dSKuninori Morimoto struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); 6512f98382dSKuninori Morimoto 6522f98382dSKuninori Morimoto /* param check */ 6532f98382dSKuninori Morimoto if (usbhsg_is_not_connected(gpriv) || 6542f98382dSKuninori Morimoto unlikely(!gpriv->driver) || 6552f98382dSKuninori Morimoto unlikely(!pipe)) 65697664a20SKuninori Morimoto return -ESHUTDOWN; 65797664a20SKuninori Morimoto 6582f98382dSKuninori Morimoto usbhsg_queue_push(uep, ureq); 6592f98382dSKuninori Morimoto 66097664a20SKuninori Morimoto return 0; 6612f98382dSKuninori Morimoto } 6622f98382dSKuninori Morimoto 6632f98382dSKuninori Morimoto static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) 6642f98382dSKuninori Morimoto { 6652f98382dSKuninori Morimoto struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); 6662f98382dSKuninori Morimoto struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); 66797664a20SKuninori Morimoto struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); 6682f98382dSKuninori Morimoto 66997664a20SKuninori Morimoto usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq)); 6702f98382dSKuninori Morimoto usbhsg_queue_pop(uep, ureq, -ECONNRESET); 6712f98382dSKuninori Morimoto 6722f98382dSKuninori Morimoto return 0; 6732f98382dSKuninori Morimoto } 6742f98382dSKuninori Morimoto 6752f98382dSKuninori Morimoto static int __usbhsg_ep_set_halt_wedge(struct usb_ep *ep, int halt, int wedge) 6762f98382dSKuninori Morimoto { 6772f98382dSKuninori Morimoto struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); 6782f98382dSKuninori Morimoto struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); 6792f98382dSKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); 68097664a20SKuninori Morimoto struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); 6812f98382dSKuninori Morimoto struct device *dev = usbhsg_gpriv_to_dev(gpriv); 6822f98382dSKuninori Morimoto unsigned long flags; 6832f98382dSKuninori Morimoto 68497664a20SKuninori Morimoto usbhsg_pipe_disable(uep); 6852f98382dSKuninori Morimoto 6862f98382dSKuninori Morimoto dev_dbg(dev, "set halt %d (pipe %d)\n", 6872f98382dSKuninori Morimoto halt, usbhs_pipe_number(pipe)); 6882f98382dSKuninori Morimoto 68997664a20SKuninori Morimoto /******************** spin lock ********************/ 69097664a20SKuninori Morimoto usbhs_lock(priv, flags); 69197664a20SKuninori Morimoto 6922f98382dSKuninori Morimoto if (halt) 693e8d548d5SKuninori Morimoto usbhs_pipe_stall(pipe); 6942f98382dSKuninori Morimoto else 695e8d548d5SKuninori Morimoto usbhs_pipe_disable(pipe); 6962f98382dSKuninori Morimoto 6972f98382dSKuninori Morimoto if (halt && wedge) 6982f98382dSKuninori Morimoto usbhsg_status_set(gpriv, USBHSG_STATUS_WEDGE); 6992f98382dSKuninori Morimoto else 7002f98382dSKuninori Morimoto usbhsg_status_clr(gpriv, USBHSG_STATUS_WEDGE); 7012f98382dSKuninori Morimoto 70297664a20SKuninori Morimoto usbhs_unlock(priv, flags); 7032f98382dSKuninori Morimoto /******************** spin unlock ******************/ 7042f98382dSKuninori Morimoto 70597664a20SKuninori Morimoto return 0; 7062f98382dSKuninori Morimoto } 7072f98382dSKuninori Morimoto 7082f98382dSKuninori Morimoto static int usbhsg_ep_set_halt(struct usb_ep *ep, int value) 7092f98382dSKuninori Morimoto { 7102f98382dSKuninori Morimoto return __usbhsg_ep_set_halt_wedge(ep, value, 0); 7112f98382dSKuninori Morimoto } 7122f98382dSKuninori Morimoto 7132f98382dSKuninori Morimoto static int usbhsg_ep_set_wedge(struct usb_ep *ep) 7142f98382dSKuninori Morimoto { 7152f98382dSKuninori Morimoto return __usbhsg_ep_set_halt_wedge(ep, 1, 1); 7162f98382dSKuninori Morimoto } 7172f98382dSKuninori Morimoto 7182f98382dSKuninori Morimoto static struct usb_ep_ops usbhsg_ep_ops = { 7192f98382dSKuninori Morimoto .enable = usbhsg_ep_enable, 7202f98382dSKuninori Morimoto .disable = usbhsg_ep_disable, 7212f98382dSKuninori Morimoto 7222f98382dSKuninori Morimoto .alloc_request = usbhsg_ep_alloc_request, 7232f98382dSKuninori Morimoto .free_request = usbhsg_ep_free_request, 7242f98382dSKuninori Morimoto 7252f98382dSKuninori Morimoto .queue = usbhsg_ep_queue, 7262f98382dSKuninori Morimoto .dequeue = usbhsg_ep_dequeue, 7272f98382dSKuninori Morimoto 7282f98382dSKuninori Morimoto .set_halt = usbhsg_ep_set_halt, 7292f98382dSKuninori Morimoto .set_wedge = usbhsg_ep_set_wedge, 7302f98382dSKuninori Morimoto }; 7312f98382dSKuninori Morimoto 7322f98382dSKuninori Morimoto /* 73304a5def3STakeshi Kihara * pullup control 73404a5def3STakeshi Kihara */ 73504a5def3STakeshi Kihara static int usbhsg_can_pullup(struct usbhs_priv *priv) 73604a5def3STakeshi Kihara { 73704a5def3STakeshi Kihara struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); 73804a5def3STakeshi Kihara 73904a5def3STakeshi Kihara return gpriv->driver && 74004a5def3STakeshi Kihara usbhsg_status_has(gpriv, USBHSG_STATUS_SOFT_CONNECT); 74104a5def3STakeshi Kihara } 74204a5def3STakeshi Kihara 74304a5def3STakeshi Kihara static void usbhsg_update_pullup(struct usbhs_priv *priv) 74404a5def3STakeshi Kihara { 74504a5def3STakeshi Kihara if (usbhsg_can_pullup(priv)) 74604a5def3STakeshi Kihara usbhs_sys_function_pullup(priv, 1); 74704a5def3STakeshi Kihara else 74804a5def3STakeshi Kihara usbhs_sys_function_pullup(priv, 0); 74904a5def3STakeshi Kihara } 75004a5def3STakeshi Kihara 75104a5def3STakeshi Kihara /* 7522f98382dSKuninori Morimoto * usb module start/end 7532f98382dSKuninori Morimoto */ 7542f98382dSKuninori Morimoto static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) 7552f98382dSKuninori Morimoto { 7562f98382dSKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); 7572f98382dSKuninori Morimoto struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); 7582f98382dSKuninori Morimoto struct usbhs_mod *mod = usbhs_mod_get_current(priv); 7592f98382dSKuninori Morimoto struct device *dev = usbhs_priv_to_dev(priv); 7602f98382dSKuninori Morimoto unsigned long flags; 76197664a20SKuninori Morimoto int ret = 0; 7622f98382dSKuninori Morimoto 7632f98382dSKuninori Morimoto /******************** spin lock ********************/ 76497664a20SKuninori Morimoto usbhs_lock(priv, flags); 76597664a20SKuninori Morimoto 76697664a20SKuninori Morimoto usbhsg_status_set(gpriv, status); 76797664a20SKuninori Morimoto if (!(usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && 76897664a20SKuninori Morimoto usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD))) 76997664a20SKuninori Morimoto ret = -1; /* not ready */ 77097664a20SKuninori Morimoto 77197664a20SKuninori Morimoto usbhs_unlock(priv, flags); 77297664a20SKuninori Morimoto /******************** spin unlock ********************/ 77397664a20SKuninori Morimoto 77497664a20SKuninori Morimoto if (ret < 0) 77597664a20SKuninori Morimoto return 0; /* not ready is not error */ 7762f98382dSKuninori Morimoto 7772f98382dSKuninori Morimoto /* 7782f98382dSKuninori Morimoto * enable interrupt and systems if ready 7792f98382dSKuninori Morimoto */ 7802f98382dSKuninori Morimoto dev_dbg(dev, "start gadget\n"); 7812f98382dSKuninori Morimoto 7822f98382dSKuninori Morimoto /* 7832f98382dSKuninori Morimoto * pipe initialize and enable DCP 7842f98382dSKuninori Morimoto */ 785*cdeb7943SYoshihiro Shimoda usbhs_fifo_init(priv); 7864bd04811SKuninori Morimoto usbhs_pipe_init(priv, 787e73a9891SKuninori Morimoto usbhsg_dma_map_ctrl); 78897664a20SKuninori Morimoto 789d9fa298fSKuninori Morimoto /* dcp init instead of usbhsg_ep_enable() */ 79097664a20SKuninori Morimoto dcp->pipe = usbhs_dcp_malloc(priv); 79197664a20SKuninori Morimoto dcp->pipe->mod_private = dcp; 792bc6fbf59SKuninori Morimoto usbhs_pipe_config_update(dcp->pipe, 0, 0, 64); 7932f98382dSKuninori Morimoto 7942f98382dSKuninori Morimoto /* 7952f98382dSKuninori Morimoto * system config enble 7962f98382dSKuninori Morimoto * - HI speed 7972f98382dSKuninori Morimoto * - function 7982f98382dSKuninori Morimoto * - usb module 7992f98382dSKuninori Morimoto */ 8002f98382dSKuninori Morimoto usbhs_sys_function_ctrl(priv, 1); 80104a5def3STakeshi Kihara usbhsg_update_pullup(priv); 8022f98382dSKuninori Morimoto 8032f98382dSKuninori Morimoto /* 8042f98382dSKuninori Morimoto * enable irq callback 8052f98382dSKuninori Morimoto */ 8062f98382dSKuninori Morimoto mod->irq_dev_state = usbhsg_irq_dev_state; 8072f98382dSKuninori Morimoto mod->irq_ctrl_stage = usbhsg_irq_ctrl_stage; 8082f98382dSKuninori Morimoto usbhs_irq_callback_update(priv, mod); 8092f98382dSKuninori Morimoto 8102f98382dSKuninori Morimoto return 0; 8112f98382dSKuninori Morimoto } 8122f98382dSKuninori Morimoto 8132f98382dSKuninori Morimoto static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) 8142f98382dSKuninori Morimoto { 8152f98382dSKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); 8162f98382dSKuninori Morimoto struct usbhs_mod *mod = usbhs_mod_get_current(priv); 8172f98382dSKuninori Morimoto struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); 8182f98382dSKuninori Morimoto struct device *dev = usbhs_priv_to_dev(priv); 8192f98382dSKuninori Morimoto unsigned long flags; 82097664a20SKuninori Morimoto int ret = 0; 8212f98382dSKuninori Morimoto 8222f98382dSKuninori Morimoto /******************** spin lock ********************/ 82397664a20SKuninori Morimoto usbhs_lock(priv, flags); 82497664a20SKuninori Morimoto 82597664a20SKuninori Morimoto usbhsg_status_clr(gpriv, status); 82697664a20SKuninori Morimoto if (!usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && 82797664a20SKuninori Morimoto !usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD)) 82897664a20SKuninori Morimoto ret = -1; /* already done */ 82997664a20SKuninori Morimoto 83097664a20SKuninori Morimoto usbhs_unlock(priv, flags); 83197664a20SKuninori Morimoto /******************** spin unlock ********************/ 83297664a20SKuninori Morimoto 83397664a20SKuninori Morimoto if (ret < 0) 83497664a20SKuninori Morimoto return 0; /* already done is not error */ 8352f98382dSKuninori Morimoto 8362f98382dSKuninori Morimoto /* 8372f98382dSKuninori Morimoto * disable interrupt and systems if 1st try 8382f98382dSKuninori Morimoto */ 839dad67397SKuninori Morimoto usbhs_fifo_quit(priv); 840dad67397SKuninori Morimoto 8412f98382dSKuninori Morimoto /* disable all irq */ 8422f98382dSKuninori Morimoto mod->irq_dev_state = NULL; 8432f98382dSKuninori Morimoto mod->irq_ctrl_stage = NULL; 8442f98382dSKuninori Morimoto usbhs_irq_callback_update(priv, mod); 8452f98382dSKuninori Morimoto 8462f98382dSKuninori Morimoto gpriv->gadget.speed = USB_SPEED_UNKNOWN; 8472f98382dSKuninori Morimoto 8482f98382dSKuninori Morimoto /* disable sys */ 849dfbb7f4fSKuninori Morimoto usbhs_sys_set_test_mode(priv, 0); 8502f98382dSKuninori Morimoto usbhs_sys_function_ctrl(priv, 0); 8512f98382dSKuninori Morimoto 852d9fa298fSKuninori Morimoto usbhsg_ep_disable(&dcp->ep); 8532f98382dSKuninori Morimoto 8542f98382dSKuninori Morimoto dev_dbg(dev, "stop gadget\n"); 8552f98382dSKuninori Morimoto 8562f98382dSKuninori Morimoto return 0; 8572f98382dSKuninori Morimoto } 8582f98382dSKuninori Morimoto 8592f98382dSKuninori Morimoto /* 8602f98382dSKuninori Morimoto * 8612f98382dSKuninori Morimoto * linux usb function 8622f98382dSKuninori Morimoto * 8632f98382dSKuninori Morimoto */ 864af1d7056SFelipe Balbi static int usbhsg_gadget_start(struct usb_gadget *gadget, 865af1d7056SFelipe Balbi struct usb_gadget_driver *driver) 8662f98382dSKuninori Morimoto { 867af1d7056SFelipe Balbi struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); 868f8eff0a0SKuninori Morimoto struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); 8692f98382dSKuninori Morimoto 870af1d7056SFelipe Balbi if (!driver || 8712f98382dSKuninori Morimoto !driver->setup || 8727177aed4SMichal Nazarewicz driver->max_speed < USB_SPEED_FULL) 8732f98382dSKuninori Morimoto return -EINVAL; 8743b872188SKuninori Morimoto 8752f98382dSKuninori Morimoto /* first hook up the driver ... */ 8762f98382dSKuninori Morimoto gpriv->driver = driver; 8772f98382dSKuninori Morimoto 8782f98382dSKuninori Morimoto return usbhsg_try_start(priv, USBHSG_STATUS_REGISTERD); 8792f98382dSKuninori Morimoto } 8802f98382dSKuninori Morimoto 88122835b80SFelipe Balbi static int usbhsg_gadget_stop(struct usb_gadget *gadget) 8822f98382dSKuninori Morimoto { 883af1d7056SFelipe Balbi struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); 884f8eff0a0SKuninori Morimoto struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); 8852f98382dSKuninori Morimoto 8862f98382dSKuninori Morimoto usbhsg_try_stop(priv, USBHSG_STATUS_REGISTERD); 8872f98382dSKuninori Morimoto gpriv->driver = NULL; 8882f98382dSKuninori Morimoto 8892f98382dSKuninori Morimoto return 0; 8902f98382dSKuninori Morimoto } 8912f98382dSKuninori Morimoto 8922f98382dSKuninori Morimoto /* 8932f98382dSKuninori Morimoto * usb gadget ops 8942f98382dSKuninori Morimoto */ 8952f98382dSKuninori Morimoto static int usbhsg_get_frame(struct usb_gadget *gadget) 8962f98382dSKuninori Morimoto { 8972f98382dSKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); 8982f98382dSKuninori Morimoto struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); 8992f98382dSKuninori Morimoto 9002f98382dSKuninori Morimoto return usbhs_frame_get_num(priv); 9012f98382dSKuninori Morimoto } 9022f98382dSKuninori Morimoto 9034cd2f599Skuninori.morimoto.gx@renesas.com static int usbhsg_pullup(struct usb_gadget *gadget, int is_on) 9044cd2f599Skuninori.morimoto.gx@renesas.com { 9054cd2f599Skuninori.morimoto.gx@renesas.com struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); 9064cd2f599Skuninori.morimoto.gx@renesas.com struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); 90704a5def3STakeshi Kihara unsigned long flags; 9084cd2f599Skuninori.morimoto.gx@renesas.com 90904a5def3STakeshi Kihara usbhs_lock(priv, flags); 91004a5def3STakeshi Kihara if (is_on) 91104a5def3STakeshi Kihara usbhsg_status_set(gpriv, USBHSG_STATUS_SOFT_CONNECT); 91204a5def3STakeshi Kihara else 91304a5def3STakeshi Kihara usbhsg_status_clr(gpriv, USBHSG_STATUS_SOFT_CONNECT); 91404a5def3STakeshi Kihara usbhsg_update_pullup(priv); 91504a5def3STakeshi Kihara usbhs_unlock(priv, flags); 9164cd2f599Skuninori.morimoto.gx@renesas.com 9174cd2f599Skuninori.morimoto.gx@renesas.com return 0; 9184cd2f599Skuninori.morimoto.gx@renesas.com } 9194cd2f599Skuninori.morimoto.gx@renesas.com 920cac402ddSShimoda, Yoshihiro static int usbhsg_set_selfpowered(struct usb_gadget *gadget, int is_self) 921cac402ddSShimoda, Yoshihiro { 922cac402ddSShimoda, Yoshihiro struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); 923cac402ddSShimoda, Yoshihiro 924cac402ddSShimoda, Yoshihiro if (is_self) 925cac402ddSShimoda, Yoshihiro usbhsg_status_set(gpriv, USBHSG_STATUS_SELF_POWERED); 926cac402ddSShimoda, Yoshihiro else 927cac402ddSShimoda, Yoshihiro usbhsg_status_clr(gpriv, USBHSG_STATUS_SELF_POWERED); 928cac402ddSShimoda, Yoshihiro 929cac402ddSShimoda, Yoshihiro return 0; 930cac402ddSShimoda, Yoshihiro } 931cac402ddSShimoda, Yoshihiro 932eeef4587SFelipe Balbi static const struct usb_gadget_ops usbhsg_gadget_ops = { 9332f98382dSKuninori Morimoto .get_frame = usbhsg_get_frame, 934cac402ddSShimoda, Yoshihiro .set_selfpowered = usbhsg_set_selfpowered, 935af1d7056SFelipe Balbi .udc_start = usbhsg_gadget_start, 936af1d7056SFelipe Balbi .udc_stop = usbhsg_gadget_stop, 9374cd2f599Skuninori.morimoto.gx@renesas.com .pullup = usbhsg_pullup, 9382f98382dSKuninori Morimoto }; 9392f98382dSKuninori Morimoto 9402f98382dSKuninori Morimoto static int usbhsg_start(struct usbhs_priv *priv) 9412f98382dSKuninori Morimoto { 9422f98382dSKuninori Morimoto return usbhsg_try_start(priv, USBHSG_STATUS_STARTED); 9432f98382dSKuninori Morimoto } 9442f98382dSKuninori Morimoto 9452f98382dSKuninori Morimoto static int usbhsg_stop(struct usbhs_priv *priv) 9462f98382dSKuninori Morimoto { 9478885a897SKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); 9488885a897SKuninori Morimoto 9498885a897SKuninori Morimoto /* cable disconnect */ 9508885a897SKuninori Morimoto if (gpriv->driver && 9518885a897SKuninori Morimoto gpriv->driver->disconnect) 9528885a897SKuninori Morimoto gpriv->driver->disconnect(&gpriv->gadget); 9538885a897SKuninori Morimoto 9542f98382dSKuninori Morimoto return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED); 9552f98382dSKuninori Morimoto } 9562f98382dSKuninori Morimoto 957b7a8d17dSKuninori Morimoto int usbhs_mod_gadget_probe(struct usbhs_priv *priv) 9582f98382dSKuninori Morimoto { 9592f98382dSKuninori Morimoto struct usbhsg_gpriv *gpriv; 9602f98382dSKuninori Morimoto struct usbhsg_uep *uep; 9612f98382dSKuninori Morimoto struct device *dev = usbhs_priv_to_dev(priv); 9622f98382dSKuninori Morimoto int pipe_size = usbhs_get_dparam(priv, pipe_size); 9632f98382dSKuninori Morimoto int i; 9640f91349bSSebastian Andrzej Siewior int ret; 9652f98382dSKuninori Morimoto 9662f98382dSKuninori Morimoto gpriv = kzalloc(sizeof(struct usbhsg_gpriv), GFP_KERNEL); 9672f98382dSKuninori Morimoto if (!gpriv) { 9682f98382dSKuninori Morimoto dev_err(dev, "Could not allocate gadget priv\n"); 9692f98382dSKuninori Morimoto return -ENOMEM; 9702f98382dSKuninori Morimoto } 9712f98382dSKuninori Morimoto 9722f98382dSKuninori Morimoto uep = kzalloc(sizeof(struct usbhsg_uep) * pipe_size, GFP_KERNEL); 9732f98382dSKuninori Morimoto if (!uep) { 9742f98382dSKuninori Morimoto dev_err(dev, "Could not allocate ep\n"); 9750f91349bSSebastian Andrzej Siewior ret = -ENOMEM; 9762f98382dSKuninori Morimoto goto usbhs_mod_gadget_probe_err_gpriv; 9772f98382dSKuninori Morimoto } 9782f98382dSKuninori Morimoto 9792f98382dSKuninori Morimoto /* 9802f98382dSKuninori Morimoto * CAUTION 9812f98382dSKuninori Morimoto * 9822f98382dSKuninori Morimoto * There is no guarantee that it is possible to access usb module here. 9832f98382dSKuninori Morimoto * Don't accesses to it. 9842f98382dSKuninori Morimoto * The accesse will be enable after "usbhsg_start" 9852f98382dSKuninori Morimoto */ 9862f98382dSKuninori Morimoto 9872f98382dSKuninori Morimoto /* 9882f98382dSKuninori Morimoto * register itself 9892f98382dSKuninori Morimoto */ 9902f98382dSKuninori Morimoto usbhs_mod_register(priv, &gpriv->mod, USBHS_GADGET); 9912f98382dSKuninori Morimoto 9922f98382dSKuninori Morimoto /* init gpriv */ 9932f98382dSKuninori Morimoto gpriv->mod.name = "gadget"; 9942f98382dSKuninori Morimoto gpriv->mod.start = usbhsg_start; 9952f98382dSKuninori Morimoto gpriv->mod.stop = usbhsg_stop; 9962f98382dSKuninori Morimoto gpriv->uep = uep; 9972f98382dSKuninori Morimoto gpriv->uep_size = pipe_size; 9982f98382dSKuninori Morimoto usbhsg_status_init(gpriv); 9992f98382dSKuninori Morimoto 10002f98382dSKuninori Morimoto /* 10012f98382dSKuninori Morimoto * init gadget 10022f98382dSKuninori Morimoto */ 10032f98382dSKuninori Morimoto gpriv->gadget.dev.parent = dev; 10042f98382dSKuninori Morimoto gpriv->gadget.name = "renesas_usbhs_udc"; 10052f98382dSKuninori Morimoto gpriv->gadget.ops = &usbhsg_gadget_ops; 1006d327ab5bSMichal Nazarewicz gpriv->gadget.max_speed = USB_SPEED_HIGH; 10072f98382dSKuninori Morimoto 10082f98382dSKuninori Morimoto INIT_LIST_HEAD(&gpriv->gadget.ep_list); 10092f98382dSKuninori Morimoto 10102f98382dSKuninori Morimoto /* 10112f98382dSKuninori Morimoto * init usb_ep 10122f98382dSKuninori Morimoto */ 10132f98382dSKuninori Morimoto usbhsg_for_each_uep_with_dcp(uep, gpriv, i) { 10142f98382dSKuninori Morimoto uep->gpriv = gpriv; 101558482945SKuninori Morimoto uep->pipe = NULL; 10162f98382dSKuninori Morimoto snprintf(uep->ep_name, EP_NAME_SIZE, "ep%d", i); 10172f98382dSKuninori Morimoto 10182f98382dSKuninori Morimoto uep->ep.name = uep->ep_name; 10192f98382dSKuninori Morimoto uep->ep.ops = &usbhsg_ep_ops; 10202f98382dSKuninori Morimoto INIT_LIST_HEAD(&uep->ep.ep_list); 10212f98382dSKuninori Morimoto 10222f98382dSKuninori Morimoto /* init DCP */ 10232f98382dSKuninori Morimoto if (usbhsg_is_dcp(uep)) { 10242f98382dSKuninori Morimoto gpriv->gadget.ep0 = &uep->ep; 1025e117e742SRobert Baldyga usb_ep_set_maxpacket_limit(&uep->ep, 64); 10262f98382dSKuninori Morimoto } 10272f98382dSKuninori Morimoto /* init normal pipe */ 10282f98382dSKuninori Morimoto else { 1029e117e742SRobert Baldyga usb_ep_set_maxpacket_limit(&uep->ep, 512); 10302f98382dSKuninori Morimoto list_add_tail(&uep->ep.ep_list, &gpriv->gadget.ep_list); 10312f98382dSKuninori Morimoto } 10322f98382dSKuninori Morimoto } 10332f98382dSKuninori Morimoto 10340f91349bSSebastian Andrzej Siewior ret = usb_add_gadget_udc(dev, &gpriv->gadget); 10350f91349bSSebastian Andrzej Siewior if (ret) 10360972ef71SFelipe Balbi goto err_add_udc; 10370f91349bSSebastian Andrzej Siewior 10380f91349bSSebastian Andrzej Siewior 10392f98382dSKuninori Morimoto dev_info(dev, "gadget probed\n"); 10402f98382dSKuninori Morimoto 10412f98382dSKuninori Morimoto return 0; 1042f8eff0a0SKuninori Morimoto 10430f91349bSSebastian Andrzej Siewior err_add_udc: 10440f91349bSSebastian Andrzej Siewior kfree(gpriv->uep); 10452f98382dSKuninori Morimoto 10462f98382dSKuninori Morimoto usbhs_mod_gadget_probe_err_gpriv: 10472f98382dSKuninori Morimoto kfree(gpriv); 10482f98382dSKuninori Morimoto 10490f91349bSSebastian Andrzej Siewior return ret; 10502f98382dSKuninori Morimoto } 10512f98382dSKuninori Morimoto 1052b7a8d17dSKuninori Morimoto void usbhs_mod_gadget_remove(struct usbhs_priv *priv) 10532f98382dSKuninori Morimoto { 10542f98382dSKuninori Morimoto struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); 10552f98382dSKuninori Morimoto 10560f91349bSSebastian Andrzej Siewior usb_del_gadget_udc(&gpriv->gadget); 10573b872188SKuninori Morimoto 10583af51ac9SSebastian Andrzej Siewior kfree(gpriv->uep); 10592f98382dSKuninori Morimoto kfree(gpriv); 10602f98382dSKuninori Morimoto } 1061