Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[sfrench/cifs-2.6.git] / drivers / usb / gadget / udc / aspeed-vhub / ep0.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * aspeed-vhub -- Driver for Aspeed SoC "vHub" USB gadget
4  *
5  * ep0.c - Endpoint 0 handling
6  *
7  * Copyright 2017 IBM Corporation
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  */
14
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/platform_device.h>
18 #include <linux/delay.h>
19 #include <linux/ioport.h>
20 #include <linux/slab.h>
21 #include <linux/errno.h>
22 #include <linux/list.h>
23 #include <linux/interrupt.h>
24 #include <linux/proc_fs.h>
25 #include <linux/prefetch.h>
26 #include <linux/clk.h>
27 #include <linux/usb/gadget.h>
28 #include <linux/of.h>
29 #include <linux/of_gpio.h>
30 #include <linux/regmap.h>
31 #include <linux/dma-mapping.h>
32
33 #include "vhub.h"
34
35 int ast_vhub_reply(struct ast_vhub_ep *ep, char *ptr, int len)
36 {
37         struct usb_request *req = &ep->ep0.req.req;
38         int rc;
39
40         if (WARN_ON(ep->d_idx != 0))
41                 return std_req_stall;
42         if (WARN_ON(!ep->ep0.dir_in))
43                 return std_req_stall;
44         if (WARN_ON(len > AST_VHUB_EP0_MAX_PACKET))
45                 return std_req_stall;
46         if (WARN_ON(req->status == -EINPROGRESS))
47                 return std_req_stall;
48
49         req->buf = ptr;
50         req->length = len;
51         req->complete = NULL;
52         req->zero = true;
53
54         /*
55          * Call internal queue directly after dropping the lock. This is
56          * safe to do as the reply is always the last thing done when
57          * processing a SETUP packet, usually as a tail call
58          */
59         spin_unlock(&ep->vhub->lock);
60         if (ep->ep.ops->queue(&ep->ep, req, GFP_ATOMIC))
61                 rc = std_req_stall;
62         else
63                 rc = std_req_data;
64         spin_lock(&ep->vhub->lock);
65         return rc;
66 }
67
68 int __ast_vhub_simple_reply(struct ast_vhub_ep *ep, int len, ...)
69 {
70         u8 *buffer = ep->buf;
71         unsigned int i;
72         va_list args;
73
74         va_start(args, len);
75
76         /* Copy data directly into EP buffer */
77         for (i = 0; i < len; i++)
78                 buffer[i] = va_arg(args, int);
79         va_end(args);
80
81         /* req->buf NULL means data is already there */
82         return ast_vhub_reply(ep, NULL, len);
83 }
84
85 void ast_vhub_ep0_handle_setup(struct ast_vhub_ep *ep)
86 {
87         struct usb_ctrlrequest crq;
88         enum std_req_rc std_req_rc;
89         int rc = -ENODEV;
90
91         if (WARN_ON(ep->d_idx != 0))
92                 return;
93
94         /*
95          * Grab the setup packet from the chip and byteswap
96          * interesting fields
97          */
98         memcpy_fromio(&crq, ep->ep0.setup, sizeof(crq));
99
100         EPDBG(ep, "SETUP packet %02x/%02x/%04x/%04x/%04x [%s] st=%d\n",
101               crq.bRequestType, crq.bRequest,
102                le16_to_cpu(crq.wValue),
103                le16_to_cpu(crq.wIndex),
104                le16_to_cpu(crq.wLength),
105                (crq.bRequestType & USB_DIR_IN) ? "in" : "out",
106                ep->ep0.state);
107
108         /* Check our state, cancel pending requests if needed */
109         if (ep->ep0.state != ep0_state_token) {
110                 EPDBG(ep, "wrong state\n");
111                 ast_vhub_nuke(ep, 0);
112                 goto stall;
113         }
114
115         /* Calculate next state for EP0 */
116         ep->ep0.state = ep0_state_data;
117         ep->ep0.dir_in = !!(crq.bRequestType & USB_DIR_IN);
118
119         /* If this is the vHub, we handle requests differently */
120         std_req_rc = std_req_driver;
121         if (ep->dev == NULL) {
122                 if ((crq.bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD)
123                         std_req_rc = ast_vhub_std_hub_request(ep, &crq);
124                 else if ((crq.bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS)
125                         std_req_rc = ast_vhub_class_hub_request(ep, &crq);
126                 else
127                         std_req_rc = std_req_stall;
128         } else if ((crq.bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD)
129                 std_req_rc = ast_vhub_std_dev_request(ep, &crq);
130
131         /* Act upon result */
132         switch(std_req_rc) {
133         case std_req_complete:
134                 goto complete;
135         case std_req_stall:
136                 goto stall;
137         case std_req_driver:
138                 break;
139         case std_req_data:
140                 return;
141         }
142
143         /* Pass request up to the gadget driver */
144         if (WARN_ON(!ep->dev))
145                 goto stall;
146         if (ep->dev->driver) {
147                 EPDBG(ep, "forwarding to gadget...\n");
148                 spin_unlock(&ep->vhub->lock);
149                 rc = ep->dev->driver->setup(&ep->dev->gadget, &crq);
150                 spin_lock(&ep->vhub->lock);
151                 EPDBG(ep, "driver returned %d\n", rc);
152         } else {
153                 EPDBG(ep, "no gadget for request !\n");
154         }
155         if (rc >= 0)
156                 return;
157
158  stall:
159         EPDBG(ep, "stalling\n");
160         writel(VHUB_EP0_CTRL_STALL, ep->ep0.ctlstat);
161         ep->ep0.state = ep0_state_status;
162         ep->ep0.dir_in = false;
163         return;
164
165  complete:
166         EPVDBG(ep, "sending [in] status with no data\n");
167         writel(VHUB_EP0_TX_BUFF_RDY, ep->ep0.ctlstat);
168         ep->ep0.state = ep0_state_status;
169         ep->ep0.dir_in = false;
170 }
171
172
173 static void ast_vhub_ep0_do_send(struct ast_vhub_ep *ep,
174                                  struct ast_vhub_req *req)
175 {
176         unsigned int chunk;
177         u32 reg;
178
179         /* If this is a 0-length request, it's the gadget trying to
180          * send a status on our behalf. We take it from here.
181          */
182         if (req->req.length == 0)
183                 req->last_desc = 1;
184
185         /* Are we done ? Complete request, otherwise wait for next interrupt */
186         if (req->last_desc >= 0) {
187                 EPVDBG(ep, "complete send %d/%d\n",
188                        req->req.actual, req->req.length);
189                 ep->ep0.state = ep0_state_status;
190                 writel(VHUB_EP0_RX_BUFF_RDY, ep->ep0.ctlstat);
191                 ast_vhub_done(ep, req, 0);
192                 return;
193         }
194
195         /*
196          * Next chunk cropped to max packet size. Also check if this
197          * is the last packet
198          */
199         chunk = req->req.length - req->req.actual;
200         if (chunk > ep->ep.maxpacket)
201                 chunk = ep->ep.maxpacket;
202         else if ((chunk < ep->ep.maxpacket) || !req->req.zero)
203                 req->last_desc = 1;
204
205         EPVDBG(ep, "send chunk=%d last=%d, req->act=%d mp=%d\n",
206                chunk, req->last_desc, req->req.actual, ep->ep.maxpacket);
207
208         /*
209          * Copy data if any (internal requests already have data
210          * in the EP buffer)
211          */
212         if (chunk && req->req.buf)
213                 memcpy(ep->buf, req->req.buf + req->req.actual, chunk);
214
215         /* Remember chunk size and trigger send */
216         reg = VHUB_EP0_SET_TX_LEN(chunk);
217         writel(reg, ep->ep0.ctlstat);
218         writel(reg | VHUB_EP0_TX_BUFF_RDY, ep->ep0.ctlstat);
219         req->req.actual += chunk;
220 }
221
222 static void ast_vhub_ep0_rx_prime(struct ast_vhub_ep *ep)
223 {
224         EPVDBG(ep, "rx prime\n");
225
226         /* Prime endpoint for receiving data */
227         writel(VHUB_EP0_RX_BUFF_RDY, ep->ep0.ctlstat + AST_VHUB_EP0_CTRL);
228 }
229
230 static void ast_vhub_ep0_do_receive(struct ast_vhub_ep *ep, struct ast_vhub_req *req,
231                                     unsigned int len)
232 {
233         unsigned int remain;
234         int rc = 0;
235
236         /* We are receiving... grab request */
237         remain = req->req.length - req->req.actual;
238
239         EPVDBG(ep, "receive got=%d remain=%d\n", len, remain);
240
241         /* Are we getting more than asked ? */
242         if (len > remain) {
243                 EPDBG(ep, "receiving too much (ovf: %d) !\n",
244                       len - remain);
245                 len = remain;
246                 rc = -EOVERFLOW;
247         }
248         if (len && req->req.buf)
249                 memcpy(req->req.buf + req->req.actual, ep->buf, len);
250         req->req.actual += len;
251
252         /* Done ? */
253         if (len < ep->ep.maxpacket || len == remain) {
254                 ep->ep0.state = ep0_state_status;
255                 writel(VHUB_EP0_TX_BUFF_RDY, ep->ep0.ctlstat);
256                 ast_vhub_done(ep, req, rc);
257         } else
258                 ast_vhub_ep0_rx_prime(ep);
259 }
260
261 void ast_vhub_ep0_handle_ack(struct ast_vhub_ep *ep, bool in_ack)
262 {
263         struct ast_vhub_req *req;
264         struct ast_vhub *vhub = ep->vhub;
265         struct device *dev = &vhub->pdev->dev;
266         bool stall = false;
267         u32 stat;
268
269         /* Read EP0 status */
270         stat = readl(ep->ep0.ctlstat);
271
272         /* Grab current request if any */
273         req = list_first_entry_or_null(&ep->queue, struct ast_vhub_req, queue);
274
275         EPVDBG(ep, "ACK status=%08x,state=%d is_in=%d in_ack=%d req=%p\n",
276                 stat, ep->ep0.state, ep->ep0.dir_in, in_ack, req);
277
278         switch(ep->ep0.state) {
279         case ep0_state_token:
280                 /* There should be no request queued in that state... */
281                 if (req) {
282                         dev_warn(dev, "request present while in TOKEN state\n");
283                         ast_vhub_nuke(ep, -EINVAL);
284                 }
285                 dev_warn(dev, "ack while in TOKEN state\n");
286                 stall = true;
287                 break;
288         case ep0_state_data:
289                 /* Check the state bits corresponding to our direction */
290                 if ((ep->ep0.dir_in && (stat & VHUB_EP0_TX_BUFF_RDY)) ||
291                     (!ep->ep0.dir_in && (stat & VHUB_EP0_RX_BUFF_RDY)) ||
292                     (ep->ep0.dir_in != in_ack)) {
293                         dev_warn(dev, "irq state mismatch");
294                         stall = true;
295                         break;
296                 }
297                 /*
298                  * We are in data phase and there's no request, something is
299                  * wrong, stall
300                  */
301                 if (!req) {
302                         dev_warn(dev, "data phase, no request\n");
303                         stall = true;
304                         break;
305                 }
306
307                 /* We have a request, handle data transfers */
308                 if (ep->ep0.dir_in)
309                         ast_vhub_ep0_do_send(ep, req);
310                 else
311                         ast_vhub_ep0_do_receive(ep, req, VHUB_EP0_RX_LEN(stat));
312                 return;
313         case ep0_state_status:
314                 /* Nuke stale requests */
315                 if (req) {
316                         dev_warn(dev, "request present while in STATUS state\n");
317                         ast_vhub_nuke(ep, -EINVAL);
318                 }
319
320                 /*
321                  * If the status phase completes with the wrong ack, stall
322                  * the endpoint just in case, to abort whatever the host
323                  * was doing.
324                  */
325                 if (ep->ep0.dir_in == in_ack) {
326                         dev_warn(dev, "status direction mismatch\n");
327                         stall = true;
328                 }
329         }
330
331         /* Reset to token state */
332         ep->ep0.state = ep0_state_token;
333         if (stall)
334                 writel(VHUB_EP0_CTRL_STALL, ep->ep0.ctlstat);
335 }
336
337 static int ast_vhub_ep0_queue(struct usb_ep* u_ep, struct usb_request *u_req,
338                               gfp_t gfp_flags)
339 {
340         struct ast_vhub_req *req = to_ast_req(u_req);
341         struct ast_vhub_ep *ep = to_ast_ep(u_ep);
342         struct ast_vhub *vhub = ep->vhub;
343         struct device *dev = &vhub->pdev->dev;
344         unsigned long flags;
345
346         /* Paranoid cheks */
347         if (!u_req || (!u_req->complete && !req->internal)) {
348                 dev_warn(dev, "Bogus EP0 request ! u_req=%p\n", u_req);
349                 if (u_req) {
350                         dev_warn(dev, "complete=%p internal=%d\n",
351                                  u_req->complete, req->internal);
352                 }
353                 return -EINVAL;
354         }
355
356         /* Not endpoint 0 ? */
357         if (WARN_ON(ep->d_idx != 0))
358                 return -EINVAL;
359
360         /* Disabled device */
361         if (ep->dev && (!ep->dev->enabled || ep->dev->suspended))
362                 return -ESHUTDOWN;
363
364         /* Data, no buffer and not internal ? */
365         if (u_req->length && !u_req->buf && !req->internal) {
366                 dev_warn(dev, "Request with no buffer !\n");
367                 return -EINVAL;
368         }
369
370         EPVDBG(ep, "enqueue req @%p\n", req);
371         EPVDBG(ep, "  l=%d zero=%d noshort=%d is_in=%d\n",
372                u_req->length, u_req->zero,
373                u_req->short_not_ok, ep->ep0.dir_in);
374
375         /* Initialize request progress fields */
376         u_req->status = -EINPROGRESS;
377         u_req->actual = 0;
378         req->last_desc = -1;
379         req->active = false;
380
381         spin_lock_irqsave(&vhub->lock, flags);
382
383         /* EP0 can only support a single request at a time */
384         if (!list_empty(&ep->queue) || ep->ep0.state == ep0_state_token) {
385                 dev_warn(dev, "EP0: Request in wrong state\n");
386                 spin_unlock_irqrestore(&vhub->lock, flags);
387                 return -EBUSY;
388         }
389
390         /* Add request to list and kick processing if empty */
391         list_add_tail(&req->queue, &ep->queue);
392
393         if (ep->ep0.dir_in) {
394                 /* IN request, send data */
395                 ast_vhub_ep0_do_send(ep, req);
396         } else if (u_req->length == 0) {
397                 /* 0-len request, send completion as rx */
398                 EPVDBG(ep, "0-length rx completion\n");
399                 ep->ep0.state = ep0_state_status;
400                 writel(VHUB_EP0_TX_BUFF_RDY, ep->ep0.ctlstat);
401                 ast_vhub_done(ep, req, 0);
402         } else {
403                 /* OUT request, start receiver */
404                 ast_vhub_ep0_rx_prime(ep);
405         }
406
407         spin_unlock_irqrestore(&vhub->lock, flags);
408
409         return 0;
410 }
411
412 static int ast_vhub_ep0_dequeue(struct usb_ep* u_ep, struct usb_request *u_req)
413 {
414         struct ast_vhub_ep *ep = to_ast_ep(u_ep);
415         struct ast_vhub *vhub = ep->vhub;
416         struct ast_vhub_req *req;
417         unsigned long flags;
418         int rc = -EINVAL;
419
420         spin_lock_irqsave(&vhub->lock, flags);
421
422         /* Only one request can be in the queue */
423         req = list_first_entry_or_null(&ep->queue, struct ast_vhub_req, queue);
424
425         /* Is it ours ? */
426         if (req && u_req == &req->req) {
427                 EPVDBG(ep, "dequeue req @%p\n", req);
428
429                 /*
430                  * We don't have to deal with "active" as all
431                  * DMAs go to the EP buffers, not the request.
432                  */
433                 ast_vhub_done(ep, req, -ECONNRESET);
434
435                 /* We do stall the EP to clean things up in HW */
436                 writel(VHUB_EP0_CTRL_STALL, ep->ep0.ctlstat);
437                 ep->ep0.state = ep0_state_status;
438                 ep->ep0.dir_in = false;
439                 rc = 0;
440         }
441         spin_unlock_irqrestore(&vhub->lock, flags);
442         return rc;
443 }
444
445
446 static const struct usb_ep_ops ast_vhub_ep0_ops = {
447         .queue          = ast_vhub_ep0_queue,
448         .dequeue        = ast_vhub_ep0_dequeue,
449         .alloc_request  = ast_vhub_alloc_request,
450         .free_request   = ast_vhub_free_request,
451 };
452
453 void ast_vhub_init_ep0(struct ast_vhub *vhub, struct ast_vhub_ep *ep,
454                        struct ast_vhub_dev *dev)
455 {
456         memset(ep, 0, sizeof(*ep));
457
458         INIT_LIST_HEAD(&ep->ep.ep_list);
459         INIT_LIST_HEAD(&ep->queue);
460         ep->ep.ops = &ast_vhub_ep0_ops;
461         ep->ep.name = "ep0";
462         ep->ep.caps.type_control = true;
463         usb_ep_set_maxpacket_limit(&ep->ep, AST_VHUB_EP0_MAX_PACKET);
464         ep->d_idx = 0;
465         ep->dev = dev;
466         ep->vhub = vhub;
467         ep->ep0.state = ep0_state_token;
468         INIT_LIST_HEAD(&ep->ep0.req.queue);
469         ep->ep0.req.internal = true;
470
471         /* Small difference between vHub and devices */
472         if (dev) {
473                 ep->ep0.ctlstat = dev->regs + AST_VHUB_DEV_EP0_CTRL;
474                 ep->ep0.setup = vhub->regs +
475                         AST_VHUB_SETUP0 + 8 * (dev->index + 1);
476                 ep->buf = vhub->ep0_bufs +
477                         AST_VHUB_EP0_MAX_PACKET * (dev->index + 1);
478                 ep->buf_dma = vhub->ep0_bufs_dma +
479                         AST_VHUB_EP0_MAX_PACKET * (dev->index + 1);
480         } else {
481                 ep->ep0.ctlstat = vhub->regs + AST_VHUB_EP0_CTRL;
482                 ep->ep0.setup = vhub->regs + AST_VHUB_SETUP0;
483                 ep->buf = vhub->ep0_bufs;
484                 ep->buf_dma = vhub->ep0_bufs_dma;
485         }
486 }