blob: f62636462fe46e297a321f0188c0a781f0ffe978 [file] [log] [blame]
Magnus Damm33aa8d42014-06-06 19:44:17 +09001/*
2 * drivers/usb/gadget/emxx_udc.c
3 * EMXX FCD (Function Controller Driver) for USB.
4 *
5 * Copyright (C) 2010 Renesas Electronics Corporation
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2
9 * as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Magnus Damm33aa8d42014-06-06 19:44:17 +090015 */
16
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/platform_device.h>
20#include <linux/delay.h>
21#include <linux/ioport.h>
22#include <linux/slab.h>
23#include <linux/errno.h>
24#include <linux/init.h>
25#include <linux/list.h>
26#include <linux/interrupt.h>
27#include <linux/proc_fs.h>
28#include <linux/clk.h>
29#include <linux/ctype.h>
30#include <linux/string.h>
31#include <linux/dma-mapping.h>
32#include <linux/workqueue.h>
Sachin Kamata790ebc2014-06-23 11:43:08 +053033#include <linux/device.h>
Magnus Damm33aa8d42014-06-06 19:44:17 +090034
35#include <linux/usb/ch9.h>
36#include <linux/usb/gadget.h>
37
38#include <linux/irq.h>
39#include <linux/gpio.h>
40
41#include "emxx_udc.h"
42
43#define DRIVER_DESC "EMXX UDC driver"
44#define DMA_ADDR_INVALID (~(dma_addr_t)0)
45
46static const char driver_name[] = "emxx_udc";
47static const char driver_desc[] = DRIVER_DESC;
48
49/*===========================================================================*/
50/* Prototype */
51static void _nbu2ss_ep_dma_abort(struct nbu2ss_udc *, struct nbu2ss_ep *);
52static void _nbu2ss_ep0_enable(struct nbu2ss_udc *);
53/*static void _nbu2ss_ep0_disable(struct nbu2ss_udc *);*/
54static void _nbu2ss_ep_done(struct nbu2ss_ep *, struct nbu2ss_req *, int);
55static void _nbu2ss_set_test_mode(struct nbu2ss_udc *, u32 mode);
56static void _nbu2ss_endpoint_toggle_reset(struct nbu2ss_udc *udc, u8 ep_adrs);
57
58static int _nbu2ss_pullup(struct nbu2ss_udc *, int);
59static void _nbu2ss_fifo_flush(struct nbu2ss_udc *, struct nbu2ss_ep *);
60
61/*===========================================================================*/
62/* Macro */
63#define _nbu2ss_zero_len_pkt(udc, epnum) \
64 _nbu2ss_ep_in_end(udc, epnum, 0, 0)
65
Magnus Damm33aa8d42014-06-06 19:44:17 +090066/*===========================================================================*/
67/* Global */
68struct nbu2ss_udc udc_controller;
69
Magnus Damm33aa8d42014-06-06 19:44:17 +090070/*-------------------------------------------------------------------------*/
71/* Read */
72static inline u32 _nbu2ss_readl(void *address)
73{
Andrew Plummerce1e3eb2014-08-30 19:43:02 +010074 return __raw_readl(address);
Magnus Damm33aa8d42014-06-06 19:44:17 +090075}
76
77/*-------------------------------------------------------------------------*/
78/* Write */
79static inline void _nbu2ss_writel(void *address, u32 udata)
80{
Andrew Plummerce1e3eb2014-08-30 19:43:02 +010081 __raw_writel(udata, address);
Magnus Damm33aa8d42014-06-06 19:44:17 +090082}
83
84/*-------------------------------------------------------------------------*/
85/* Set Bit */
86static inline void _nbu2ss_bitset(void *address, u32 udata)
87{
88 u32 reg_dt = __raw_readl(address) | (udata);
Vincenzo Scotti7f39ae02014-09-09 23:06:25 +020089
Andrew Plummerce1e3eb2014-08-30 19:43:02 +010090 __raw_writel(reg_dt, address);
Magnus Damm33aa8d42014-06-06 19:44:17 +090091}
92
93/*-------------------------------------------------------------------------*/
94/* Clear Bit */
95static inline void _nbu2ss_bitclr(void *address, u32 udata)
96{
97 u32 reg_dt = __raw_readl(address) & ~(udata);
Vincenzo Scotti7f39ae02014-09-09 23:06:25 +020098
Andrew Plummerce1e3eb2014-08-30 19:43:02 +010099 __raw_writel(reg_dt, address);
Magnus Damm33aa8d42014-06-06 19:44:17 +0900100}
101
102#ifdef UDC_DEBUG_DUMP
103/*-------------------------------------------------------------------------*/
104static void _nbu2ss_dump_register(struct nbu2ss_udc *udc)
105{
106 int i;
107 u32 reg_data;
108
109 pr_info("=== %s()\n", __func__);
110
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +0530111 if (!udc) {
Haneen Mohammed88689272015-03-02 21:37:38 +0300112 pr_err("%s udc == NULL\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +0900113 return;
114 }
115
116 spin_unlock(&udc->lock);
117
Ebru Akagunduzfb71d242014-10-02 23:32:06 +0300118 dev_dbg(&udc->dev, "\n-USB REG-\n");
Magnus Damm33aa8d42014-06-06 19:44:17 +0900119 for (i = 0x0 ; i < USB_BASE_SIZE ; i += 16) {
120 reg_data = _nbu2ss_readl(
121 (u32 *)IO_ADDRESS(USB_BASE_ADDRESS + i));
Ebru Akagunduzfb71d242014-10-02 23:32:06 +0300122 dev_dbg(&udc->dev, "USB%04x =%08x", i, (int)reg_data);
Magnus Damm33aa8d42014-06-06 19:44:17 +0900123
124 reg_data = _nbu2ss_readl(
125 (u32 *)IO_ADDRESS(USB_BASE_ADDRESS + i + 4));
Ebru Akagunduzfb71d242014-10-02 23:32:06 +0300126 dev_dbg(&udc->dev, " %08x", (int)reg_data);
Magnus Damm33aa8d42014-06-06 19:44:17 +0900127
128 reg_data = _nbu2ss_readl(
129 (u32 *)IO_ADDRESS(USB_BASE_ADDRESS + i + 8));
Ebru Akagunduzfb71d242014-10-02 23:32:06 +0300130 dev_dbg(&udc->dev, " %08x", (int)reg_data);
Magnus Damm33aa8d42014-06-06 19:44:17 +0900131
132 reg_data = _nbu2ss_readl(
133 (u32 *)IO_ADDRESS(USB_BASE_ADDRESS + i + 12));
Ebru Akagunduzfb71d242014-10-02 23:32:06 +0300134 dev_dbg(&udc->dev, " %08x\n", (int)reg_data);
Magnus Damm33aa8d42014-06-06 19:44:17 +0900135
136 }
137
138 spin_lock(&udc->lock);
139}
140#endif /* UDC_DEBUG_DUMP */
141
142/*-------------------------------------------------------------------------*/
143/* Endpoint 0 Callback (Complete) */
144static void _nbu2ss_ep0_complete(struct usb_ep *_ep, struct usb_request *_req)
145{
146 u8 recipient;
147 u16 selector;
148 u32 test_mode;
149 struct usb_ctrlrequest *p_ctrl;
150 struct nbu2ss_udc *udc;
151
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +0530152 if ((!_ep) || (!_req))
Magnus Damm33aa8d42014-06-06 19:44:17 +0900153 return;
154
155 udc = (struct nbu2ss_udc *)_req->context;
156 p_ctrl = &udc->ctrl;
157 if ((p_ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
158
159 if (p_ctrl->bRequest == USB_REQ_SET_FEATURE) {
160 /*-------------------------------------------------*/
161 /* SET_FEATURE */
162 recipient = (u8)(p_ctrl->bRequestType & USB_RECIP_MASK);
163 selector = p_ctrl->wValue;
164 if ((recipient == USB_RECIP_DEVICE) &&
165 (selector == USB_DEVICE_TEST_MODE)) {
166 test_mode = (u32)(p_ctrl->wIndex >> 8);
167 _nbu2ss_set_test_mode(udc, test_mode);
168 }
169 }
170 }
171}
172
173/*-------------------------------------------------------------------------*/
174/* Initialization usb_request */
175static void _nbu2ss_create_ep0_packet(
176 struct nbu2ss_udc *udc,
177 void *p_buf,
178 unsigned length
179)
180{
181 udc->ep0_req.req.buf = p_buf;
182 udc->ep0_req.req.length = length;
183 udc->ep0_req.req.dma = 0;
184 udc->ep0_req.req.zero = TRUE;
185 udc->ep0_req.req.complete = _nbu2ss_ep0_complete;
186 udc->ep0_req.req.status = -EINPROGRESS;
187 udc->ep0_req.req.context = udc;
188 udc->ep0_req.req.actual = 0;
189}
190
191/*-------------------------------------------------------------------------*/
192/* Acquisition of the first address of RAM(FIFO) */
193static u32 _nbu2ss_get_begin_ram_address(struct nbu2ss_udc *udc)
194{
195 u32 num, buf_type;
196 u32 data, last_ram_adr, use_ram_size;
197
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +0300198 struct ep_regs *p_ep_regs;
Magnus Damm33aa8d42014-06-06 19:44:17 +0900199
200 last_ram_adr = (D_RAM_SIZE_CTRL / sizeof(u32)) * 2;
201 use_ram_size = 0;
202
203 for (num = 0; num < NUM_ENDPOINTS - 1; num++) {
204 p_ep_regs = &udc->p_regs->EP_REGS[num];
205 data = _nbu2ss_readl(&p_ep_regs->EP_PCKT_ADRS);
206 buf_type = _nbu2ss_readl(&p_ep_regs->EP_CONTROL) & EPn_BUF_TYPE;
207 if (buf_type == 0) {
208 /* Single Buffer */
209 use_ram_size += (data & EPn_MPKT) / sizeof(u32);
210 } else {
211 /* Double Buffer */
212 use_ram_size += ((data & EPn_MPKT) / sizeof(u32)) * 2;
213 }
214
215 if ((data >> 16) > last_ram_adr)
216 last_ram_adr = data>>16;
217 }
218
219 return last_ram_adr + use_ram_size;
220}
221
222/*-------------------------------------------------------------------------*/
223/* Construction of Endpoint */
224static int _nbu2ss_ep_init(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
225{
226 u32 num;
227 u32 data;
228 u32 begin_adrs;
229
230 if (ep->epnum == 0)
231 return -EINVAL;
232
233 num = ep->epnum - 1;
234
235 /*-------------------------------------------------------------*/
236 /* RAM Transfer Address */
237 begin_adrs = _nbu2ss_get_begin_ram_address(udc);
238 data = (begin_adrs << 16) | ep->ep.maxpacket;
239 _nbu2ss_writel(&udc->p_regs->EP_REGS[num].EP_PCKT_ADRS, data);
240
241 /*-------------------------------------------------------------*/
242 /* Interrupt Enable */
243 data = 1 << (ep->epnum + 8);
244 _nbu2ss_bitset(&udc->p_regs->USB_INT_ENA, data);
245
246 /*-------------------------------------------------------------*/
247 /* Endpoint Type(Mode) */
248 /* Bulk, Interrupt, ISO */
249 switch (ep->ep_type) {
250 case USB_ENDPOINT_XFER_BULK:
251 data = EPn_BULK;
252 break;
253
254 case USB_ENDPOINT_XFER_INT:
255 data = EPn_BUF_SINGLE | EPn_INTERRUPT;
256 break;
257
258 case USB_ENDPOINT_XFER_ISOC:
259 data = EPn_ISO;
260 break;
261
262 default:
263 data = 0;
264 break;
265 }
266
267 _nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
268 _nbu2ss_endpoint_toggle_reset(udc, (ep->epnum|ep->direct));
269
270 if (ep->direct == USB_DIR_OUT) {
271 /*---------------------------------------------------------*/
272 /* OUT */
273 data = EPn_EN | EPn_BCLR | EPn_DIR0;
274 _nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
275
276 data = (EPn_ONAK | EPn_OSTL_EN | EPn_OSTL);
277 _nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
278
279 data = (EPn_OUT_EN | EPn_OUT_END_EN);
280 _nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_INT_ENA, data);
281 } else {
282 /*---------------------------------------------------------*/
283 /* IN */
284 data = (EPn_EN | EPn_BCLR | EPn_AUTO);
285 _nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
286
287 data = (EPn_ISTL);
288 _nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
289
290 data = (EPn_IN_EN | EPn_IN_END_EN);
291 _nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_INT_ENA, data);
292 }
293
294 return 0;
295}
296
297/*-------------------------------------------------------------------------*/
298/* Release of Endpoint */
299static int _nbu2ss_epn_exit(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
300{
301 u32 num;
302 u32 data;
303
304 if ((ep->epnum == 0) || (udc->vbus_active == 0))
305 return -EINVAL;
306
307 num = ep->epnum - 1;
308
309 /*-------------------------------------------------------------*/
310 /* RAM Transfer Address */
311 _nbu2ss_writel(&udc->p_regs->EP_REGS[num].EP_PCKT_ADRS, 0);
312
313 /*-------------------------------------------------------------*/
314 /* Interrupt Disable */
315 data = 1 << (ep->epnum + 8);
316 _nbu2ss_bitclr(&udc->p_regs->USB_INT_ENA, data);
317
318 if (ep->direct == USB_DIR_OUT) {
319 /*---------------------------------------------------------*/
320 /* OUT */
321 data = EPn_ONAK | EPn_BCLR;
322 _nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
323
324 data = EPn_EN | EPn_DIR0;
325 _nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
326
327 data = EPn_OUT_EN | EPn_OUT_END_EN;
328 _nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_INT_ENA, data);
329 } else {
330 /*---------------------------------------------------------*/
331 /* IN */
332 data = EPn_BCLR;
333 _nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
334
335 data = EPn_EN | EPn_AUTO;
336 _nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
337
338 data = EPn_IN_EN | EPn_IN_END_EN;
339 _nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_INT_ENA, data);
340 }
341
342 return 0;
343}
344
345/*-------------------------------------------------------------------------*/
346/* DMA setting (without Endpoint 0) */
347static void _nbu2ss_ep_dma_init(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
348{
349 u32 num;
350 u32 data;
351
352 data = _nbu2ss_readl(&udc->p_regs->USBSSCONF);
353 if (((ep->epnum == 0) || (data & (1 << ep->epnum)) == 0))
354 return; /* Not Support DMA */
355
356 num = ep->epnum - 1;
357
358 if (ep->direct == USB_DIR_OUT) {
359 /*---------------------------------------------------------*/
360 /* OUT */
361 data = ep->ep.maxpacket;
362 _nbu2ss_writel(&udc->p_regs->EP_DCR[num].EP_DCR2, data);
363
364 /*---------------------------------------------------------*/
365 /* Transfer Direct */
366 data = DCR1_EPn_DIR0;
367 _nbu2ss_bitset(&udc->p_regs->EP_DCR[num].EP_DCR1, data);
368
369 /*---------------------------------------------------------*/
370 /* DMA Mode etc. */
371 data = EPn_STOP_MODE | EPn_STOP_SET | EPn_DMAMODE0;
372 _nbu2ss_writel(&udc->p_regs->EP_REGS[num].EP_DMA_CTRL, data);
373 } else {
374 /*---------------------------------------------------------*/
375 /* IN */
376 _nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, EPn_AUTO);
377
378 /*---------------------------------------------------------*/
379 /* DMA Mode etc. */
380 data = EPn_BURST_SET | EPn_DMAMODE0;
381 _nbu2ss_writel(&udc->p_regs->EP_REGS[num].EP_DMA_CTRL, data);
382 }
383}
384
385/*-------------------------------------------------------------------------*/
386/* DMA setting release */
387static void _nbu2ss_ep_dma_exit(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
388{
389 u32 num;
390 u32 data;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +0300391 struct fc_regs *preg = udc->p_regs;
Magnus Damm33aa8d42014-06-06 19:44:17 +0900392
393 if (udc->vbus_active == 0)
394 return; /* VBUS OFF */
395
396 data = _nbu2ss_readl(&preg->USBSSCONF);
397 if ((ep->epnum == 0) || ((data & (1 << ep->epnum)) == 0))
398 return; /* Not Support DMA */
399
400 num = ep->epnum - 1;
401
402 _nbu2ss_ep_dma_abort(udc, ep);
403
404 if (ep->direct == USB_DIR_OUT) {
405 /*---------------------------------------------------------*/
406 /* OUT */
407 _nbu2ss_writel(&preg->EP_DCR[num].EP_DCR2, 0);
408 _nbu2ss_bitclr(&preg->EP_DCR[num].EP_DCR1, DCR1_EPn_DIR0);
409 _nbu2ss_writel(&preg->EP_REGS[num].EP_DMA_CTRL, 0);
410 } else {
411 /*---------------------------------------------------------*/
412 /* IN */
413 _nbu2ss_bitclr(&preg->EP_REGS[num].EP_CONTROL, EPn_AUTO);
414 _nbu2ss_writel(&preg->EP_REGS[num].EP_DMA_CTRL, 0);
415 }
416}
417
418/*-------------------------------------------------------------------------*/
419/* Abort DMA */
420static void _nbu2ss_ep_dma_abort(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
421{
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +0300422 struct fc_regs *preg = udc->p_regs;
Magnus Damm33aa8d42014-06-06 19:44:17 +0900423
424 _nbu2ss_bitclr(&preg->EP_DCR[ep->epnum-1].EP_DCR1, DCR1_EPn_REQEN);
425 mdelay(DMA_DISABLE_TIME); /* DCR1_EPn_REQEN Clear */
426 _nbu2ss_bitclr(&preg->EP_REGS[ep->epnum-1].EP_DMA_CTRL, EPn_DMA_EN);
427}
428
429/*-------------------------------------------------------------------------*/
430/* Start IN Transfer */
431static void _nbu2ss_ep_in_end(
432 struct nbu2ss_udc *udc,
433 u32 epnum,
434 u32 data32,
435 u32 length
436)
437{
438 u32 data;
439 u32 num;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +0300440 struct fc_regs *preg = udc->p_regs;
Magnus Damm33aa8d42014-06-06 19:44:17 +0900441
442 if (length >= sizeof(u32))
443 return;
444
445 if (epnum == 0) {
446 _nbu2ss_bitclr(&preg->EP0_CONTROL, EP0_AUTO);
447
448 /* Writing of 1-4 bytes */
449 if (length)
450 _nbu2ss_writel(&preg->EP0_WRITE, data32);
451
452 data = ((length << 5) & EP0_DW) | EP0_DEND;
453 _nbu2ss_writel(&preg->EP0_CONTROL, data);
454
455 _nbu2ss_bitset(&preg->EP0_CONTROL, EP0_AUTO);
456 } else {
457 num = epnum - 1;
458
459 _nbu2ss_bitclr(&preg->EP_REGS[num].EP_CONTROL, EPn_AUTO);
460
461 /* Writing of 1-4 bytes */
462 if (length)
463 _nbu2ss_writel(&preg->EP_REGS[num].EP_WRITE, data32);
464
465 data = (((((u32)length) << 5) & EPn_DW) | EPn_DEND);
466 _nbu2ss_bitset(&preg->EP_REGS[num].EP_CONTROL, data);
467
468 _nbu2ss_bitset(&preg->EP_REGS[num].EP_CONTROL, EPn_AUTO);
469 }
Magnus Damm33aa8d42014-06-06 19:44:17 +0900470}
471
472#ifdef USE_DMA
473/*-------------------------------------------------------------------------*/
474static void _nbu2ss_dma_map_single(
475 struct nbu2ss_udc *udc,
476 struct nbu2ss_ep *ep,
477 struct nbu2ss_req *req,
478 u8 direct
479)
480{
481 if (req->req.dma == DMA_ADDR_INVALID) {
482 if (req->unaligned)
483 req->req.dma = ep->phys_buf;
484 else {
485 req->req.dma = dma_map_single(
486 udc->gadget.dev.parent,
487 req->req.buf,
488 req->req.length,
489 (direct == USB_DIR_IN)
490 ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
491 }
492 req->mapped = 1;
493 } else {
494 if (!req->unaligned)
495 dma_sync_single_for_device(
496 udc->gadget.dev.parent,
497 req->req.dma,
498 req->req.length,
499 (direct == USB_DIR_IN)
500 ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
501
502 req->mapped = 0;
503 }
504}
505
506/*-------------------------------------------------------------------------*/
507static void _nbu2ss_dma_unmap_single(
508 struct nbu2ss_udc *udc,
509 struct nbu2ss_ep *ep,
510 struct nbu2ss_req *req,
511 u8 direct
512)
513{
514 u8 data[4];
515 u8 *p;
516 u32 count = 0;
517
518 if (direct == USB_DIR_OUT) {
519 count = req->req.actual % 4;
520 if (count) {
521 p = req->req.buf;
522 p += (req->req.actual - count);
523 memcpy(data, p, count);
524 }
525 }
526
527 if (req->mapped) {
528 if (req->unaligned) {
529 if (direct == USB_DIR_OUT)
530 memcpy(req->req.buf, ep->virt_buf,
531 req->req.actual & 0xfffffffc);
532 } else
533 dma_unmap_single(udc->gadget.dev.parent,
534 req->req.dma, req->req.length,
535 (direct == USB_DIR_IN)
536 ? DMA_TO_DEVICE
537 : DMA_FROM_DEVICE);
538 req->req.dma = DMA_ADDR_INVALID;
539 req->mapped = 0;
540 } else {
541 if (!req->unaligned)
542 dma_sync_single_for_cpu(udc->gadget.dev.parent,
543 req->req.dma, req->req.length,
544 (direct == USB_DIR_IN)
545 ? DMA_TO_DEVICE
546 : DMA_FROM_DEVICE);
547 }
548
549 if (count) {
550 p = req->req.buf;
551 p += (req->req.actual - count);
552 memcpy(p, data, count);
553 }
554}
555#endif
556
557/*-------------------------------------------------------------------------*/
558/* Endpoint 0 OUT Transfer (PIO) */
KANG Yuxuana2c14e92014-07-16 10:45:01 +0800559static int EP0_out_PIO(struct nbu2ss_udc *udc, u8 *pBuf, u32 length)
Magnus Damm33aa8d42014-06-06 19:44:17 +0900560{
561 u32 i;
562 int nret = 0;
563 u32 iWordLength = 0;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +0300564 union usb_reg_access *pBuf32 = (union usb_reg_access *)pBuf;
Magnus Damm33aa8d42014-06-06 19:44:17 +0900565
566 /*------------------------------------------------------------*/
567 /* Read Length */
568 iWordLength = length / sizeof(u32);
569
570 /*------------------------------------------------------------*/
571 /* PIO Read */
572 if (iWordLength) {
573 for (i = 0; i < iWordLength; i++) {
574 pBuf32->dw = _nbu2ss_readl(&udc->p_regs->EP0_READ);
575 pBuf32++;
576 }
577 nret = iWordLength * sizeof(u32);
578 }
579
580 return nret;
581}
582
583/*-------------------------------------------------------------------------*/
584/* Endpoint 0 OUT Transfer (PIO, OverBytes) */
KANG Yuxuana2c14e92014-07-16 10:45:01 +0800585static int EP0_out_OverBytes(struct nbu2ss_udc *udc, u8 *pBuf, u32 length)
Magnus Damm33aa8d42014-06-06 19:44:17 +0900586{
587 u32 i;
588 u32 iReadSize = 0;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +0300589 union usb_reg_access Temp32;
590 union usb_reg_access *pBuf32 = (union usb_reg_access *)pBuf;
Magnus Damm33aa8d42014-06-06 19:44:17 +0900591
Cristina Moraru28669142015-09-29 14:47:25 -0700592 if ((length > 0) && (length < sizeof(u32))) {
Magnus Damm33aa8d42014-06-06 19:44:17 +0900593 Temp32.dw = _nbu2ss_readl(&udc->p_regs->EP0_READ);
594 for (i = 0 ; i < length ; i++)
595 pBuf32->byte.DATA[i] = Temp32.byte.DATA[i];
596 iReadSize += length;
597 }
598
599 return iReadSize;
600}
601
602/*-------------------------------------------------------------------------*/
603/* Endpoint 0 IN Transfer (PIO) */
604static int EP0_in_PIO(struct nbu2ss_udc *udc, u8 *pBuf, u32 length)
605{
606 u32 i;
607 u32 iMaxLength = EP0_PACKETSIZE;
608 u32 iWordLength = 0;
609 u32 iWriteLength = 0;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +0300610 union usb_reg_access *pBuf32 = (union usb_reg_access *)pBuf;
Magnus Damm33aa8d42014-06-06 19:44:17 +0900611
612 /*------------------------------------------------------------*/
613 /* Transfer Length */
614 if (iMaxLength < length)
615 iWordLength = iMaxLength / sizeof(u32);
616 else
617 iWordLength = length / sizeof(u32);
618
619 /*------------------------------------------------------------*/
620 /* PIO */
621 for (i = 0; i < iWordLength; i++) {
622 _nbu2ss_writel(&udc->p_regs->EP0_WRITE, pBuf32->dw);
623 pBuf32++;
624 iWriteLength += sizeof(u32);
625 }
626
627 return iWriteLength;
628}
629
630/*-------------------------------------------------------------------------*/
631/* Endpoint 0 IN Transfer (PIO, OverBytes) */
632static int EP0_in_OverBytes(struct nbu2ss_udc *udc, u8 *pBuf, u32 iRemainSize)
633{
634 u32 i;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +0300635 union usb_reg_access Temp32;
636 union usb_reg_access *pBuf32 = (union usb_reg_access *)pBuf;
Magnus Damm33aa8d42014-06-06 19:44:17 +0900637
Cristina Moraru28669142015-09-29 14:47:25 -0700638 if ((iRemainSize > 0) && (iRemainSize < sizeof(u32))) {
Magnus Damm33aa8d42014-06-06 19:44:17 +0900639 for (i = 0 ; i < iRemainSize ; i++)
640 Temp32.byte.DATA[i] = pBuf32->byte.DATA[i];
641 _nbu2ss_ep_in_end(udc, 0, Temp32.dw, iRemainSize);
642
643 return iRemainSize;
644 }
645
646 return 0;
647}
648
649/*-------------------------------------------------------------------------*/
650/* Transfer NULL Packet (Epndoint 0) */
651static int EP0_send_NULL(struct nbu2ss_udc *udc, bool pid_flag)
652{
653 u32 data;
654
655 data = _nbu2ss_readl(&udc->p_regs->EP0_CONTROL);
656 data &= ~(u32)EP0_INAK;
657
658 if (pid_flag)
659 data |= (EP0_INAK_EN | EP0_PIDCLR | EP0_DEND);
660 else
661 data |= (EP0_INAK_EN | EP0_DEND);
662
663 _nbu2ss_writel(&udc->p_regs->EP0_CONTROL, data);
664
665 return 0;
666}
667
668/*-------------------------------------------------------------------------*/
669/* Receive NULL Packet (Endpoint 0) */
670static int EP0_receive_NULL(struct nbu2ss_udc *udc, bool pid_flag)
671{
672 u32 data;
673
674 data = _nbu2ss_readl(&udc->p_regs->EP0_CONTROL);
675 data &= ~(u32)EP0_ONAK;
676
677 if (pid_flag)
678 data |= EP0_PIDCLR;
679
680 _nbu2ss_writel(&udc->p_regs->EP0_CONTROL, data);
681
682 return 0;
683}
684
685/*-------------------------------------------------------------------------*/
686static int _nbu2ss_ep0_in_transfer(
687 struct nbu2ss_udc *udc,
Magnus Damm33aa8d42014-06-06 19:44:17 +0900688 struct nbu2ss_req *req
689)
690{
691 u8 *pBuffer; /* IN Data Buffer */
692 u32 data;
693 u32 iRemainSize = 0;
694 int result = 0;
695
696 /*-------------------------------------------------------------*/
697 /* End confirmation */
698 if (req->req.actual == req->req.length) {
699 if ((req->req.actual % EP0_PACKETSIZE) == 0) {
700 if (req->zero) {
Roberta Dobrescu666e9082014-09-23 11:37:02 +0300701 req->zero = false;
Magnus Damm33aa8d42014-06-06 19:44:17 +0900702 EP0_send_NULL(udc, FALSE);
703 return 1;
704 }
705 }
706
707 return 0; /* Transfer End */
708 }
709
710 /*-------------------------------------------------------------*/
711 /* NAK release */
712 data = _nbu2ss_readl(&udc->p_regs->EP0_CONTROL);
713 data |= EP0_INAK_EN;
714 data &= ~(u32)EP0_INAK;
715 _nbu2ss_writel(&udc->p_regs->EP0_CONTROL, data);
716
717 iRemainSize = req->req.length - req->req.actual;
718 pBuffer = (u8 *)req->req.buf;
719 pBuffer += req->req.actual;
720
721 /*-------------------------------------------------------------*/
722 /* Data transfer */
723 result = EP0_in_PIO(udc, pBuffer, iRemainSize);
724
725 req->div_len = result;
726 iRemainSize -= result;
727
728 if (iRemainSize == 0) {
729 EP0_send_NULL(udc, FALSE);
730 return result;
731 }
732
733 if ((iRemainSize < sizeof(u32)) && (result != EP0_PACKETSIZE)) {
734 pBuffer += result;
735 result += EP0_in_OverBytes(udc, pBuffer, iRemainSize);
736 req->div_len = result;
737 }
738
739 return result;
740}
741
742/*-------------------------------------------------------------------------*/
743static int _nbu2ss_ep0_out_transfer(
744 struct nbu2ss_udc *udc,
Magnus Damm33aa8d42014-06-06 19:44:17 +0900745 struct nbu2ss_req *req
746)
747{
748 u8 *pBuffer;
749 u32 iRemainSize;
750 u32 iRecvLength;
751 int result = 0;
752 int fRcvZero;
753
754 /*-------------------------------------------------------------*/
755 /* Receive data confirmation */
756 iRecvLength = _nbu2ss_readl(&udc->p_regs->EP0_LENGTH) & EP0_LDATA;
757 if (iRecvLength != 0) {
758
759 fRcvZero = 0;
760
761 iRemainSize = req->req.length - req->req.actual;
762 pBuffer = (u8 *)req->req.buf;
763 pBuffer += req->req.actual;
764
765 result = EP0_out_PIO(udc, pBuffer
766 , min(iRemainSize, iRecvLength));
767 if (result < 0)
768 return result;
769
770 req->req.actual += result;
771 iRecvLength -= result;
772
Cristina Moraru28669142015-09-29 14:47:25 -0700773 if ((iRecvLength > 0) && (iRecvLength < sizeof(u32))) {
Magnus Damm33aa8d42014-06-06 19:44:17 +0900774 pBuffer += result;
775 iRemainSize -= result;
776
777 result = EP0_out_OverBytes(udc, pBuffer
778 , min(iRemainSize, iRecvLength));
779 req->req.actual += result;
780 }
781 } else {
782 fRcvZero = 1;
783 }
784
785 /*-------------------------------------------------------------*/
786 /* End confirmation */
787 if (req->req.actual == req->req.length) {
788 if ((req->req.actual % EP0_PACKETSIZE) == 0) {
789 if (req->zero) {
Roberta Dobrescu666e9082014-09-23 11:37:02 +0300790 req->zero = false;
Magnus Damm33aa8d42014-06-06 19:44:17 +0900791 EP0_receive_NULL(udc, FALSE);
792 return 1;
793 }
794 }
795
796 return 0; /* Transfer End */
797 }
798
799 if ((req->req.actual % EP0_PACKETSIZE) != 0)
800 return 0; /* Short Packet Transfer End */
801
802 if (req->req.actual > req->req.length) {
Haneen Mohammed88689272015-03-02 21:37:38 +0300803 dev_err(udc->dev, " *** Overrun Error\n");
Magnus Damm33aa8d42014-06-06 19:44:17 +0900804 return -EOVERFLOW;
805 }
806
807 if (fRcvZero != 0) {
808 iRemainSize = _nbu2ss_readl(&udc->p_regs->EP0_CONTROL);
809 if (iRemainSize & EP0_ONAK) {
810 /*---------------------------------------------------*/
811 /* NACK release */
812 _nbu2ss_bitclr(&udc->p_regs->EP0_CONTROL, EP0_ONAK);
813 }
814 result = 1;
815 }
816
817 return result;
818}
819
820/*-------------------------------------------------------------------------*/
821static int _nbu2ss_out_dma(
822 struct nbu2ss_udc *udc,
823 struct nbu2ss_req *req,
824 u32 num,
825 u32 length
826)
827{
828 u8 *pBuffer;
829 u32 mpkt;
830 u32 lmpkt;
831 u32 dmacnt;
832 u32 burst = 1;
833 u32 data;
834 int result = -EINVAL;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +0300835 struct fc_regs *preg = udc->p_regs;
Magnus Damm33aa8d42014-06-06 19:44:17 +0900836
837 if (req->dma_flag)
838 return 1; /* DMA is forwarded */
839
840 req->dma_flag = TRUE;
841 pBuffer = (u8 *)req->req.dma;
842 pBuffer += req->req.actual;
843
844 /* DMA Address */
845 _nbu2ss_writel(&preg->EP_DCR[num].EP_TADR, (u32)pBuffer);
846
847 /* Number of transfer packets */
848 mpkt = _nbu2ss_readl(&preg->EP_REGS[num].EP_PCKT_ADRS) & EPn_MPKT;
849 dmacnt = (length / mpkt);
850 lmpkt = (length % mpkt) & ~(u32)0x03;
851
Cristina Moraru28669142015-09-29 14:47:25 -0700852 if (dmacnt > DMA_MAX_COUNT) {
Magnus Damm33aa8d42014-06-06 19:44:17 +0900853 dmacnt = DMA_MAX_COUNT;
854 lmpkt = 0;
Cristina Moraru28669142015-09-29 14:47:25 -0700855 } else if (lmpkt != 0) {
856 if (dmacnt == 0)
Magnus Damm33aa8d42014-06-06 19:44:17 +0900857 burst = 0; /* Burst OFF */
858 dmacnt++;
859 }
860
861 data = mpkt | (lmpkt << 16);
862 _nbu2ss_writel(&preg->EP_DCR[num].EP_DCR2, data);
863
864 data = ((dmacnt & 0xff) << 16) | DCR1_EPn_DIR0 | DCR1_EPn_REQEN;
865 _nbu2ss_writel(&preg->EP_DCR[num].EP_DCR1, data);
866
Cristina Moraru28669142015-09-29 14:47:25 -0700867 if (burst == 0) {
Magnus Damm33aa8d42014-06-06 19:44:17 +0900868 _nbu2ss_writel(&preg->EP_REGS[num].EP_LEN_DCNT, 0);
869 _nbu2ss_bitclr(&preg->EP_REGS[num].EP_DMA_CTRL, EPn_BURST_SET);
870 } else {
871 _nbu2ss_writel(&preg->EP_REGS[num].EP_LEN_DCNT
872 , (dmacnt << 16));
873 _nbu2ss_bitset(&preg->EP_REGS[num].EP_DMA_CTRL, EPn_BURST_SET);
874 }
875 _nbu2ss_bitset(&preg->EP_REGS[num].EP_DMA_CTRL, EPn_DMA_EN);
876
877 result = length & ~(u32)0x03;
878 req->div_len = result;
879
880 return result;
881}
882
883/*-------------------------------------------------------------------------*/
884static int _nbu2ss_epn_out_pio(
885 struct nbu2ss_udc *udc,
886 struct nbu2ss_ep *ep,
887 struct nbu2ss_req *req,
888 u32 length
889)
890{
891 u8 *pBuffer;
892 u32 i;
893 u32 data;
894 u32 iWordLength;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +0300895 union usb_reg_access Temp32;
896 union usb_reg_access *pBuf32;
Magnus Damm33aa8d42014-06-06 19:44:17 +0900897 int result = 0;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +0300898 struct fc_regs *preg = udc->p_regs;
Magnus Damm33aa8d42014-06-06 19:44:17 +0900899
900 if (req->dma_flag)
901 return 1; /* DMA is forwarded */
902
903 if (length == 0)
904 return 0;
905
906 pBuffer = (u8 *)req->req.buf;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +0300907 pBuf32 = (union usb_reg_access *)(pBuffer + req->req.actual);
Magnus Damm33aa8d42014-06-06 19:44:17 +0900908
909 iWordLength = length / sizeof(u32);
910 if (iWordLength > 0) {
911 /*---------------------------------------------------------*/
912 /* Copy of every four bytes */
913 for (i = 0; i < iWordLength; i++) {
914 pBuf32->dw =
915 _nbu2ss_readl(&preg->EP_REGS[ep->epnum-1].EP_READ);
916 pBuf32++;
917 }
918 result = iWordLength * sizeof(u32);
919 }
920
921 data = length - result;
922 if (data > 0) {
923 /*---------------------------------------------------------*/
924 /* Copy of fraction byte */
925 Temp32.dw = _nbu2ss_readl(&preg->EP_REGS[ep->epnum-1].EP_READ);
926 for (i = 0 ; i < data ; i++)
927 pBuf32->byte.DATA[i] = Temp32.byte.DATA[i];
928 result += data;
929 }
930
931 req->req.actual += result;
932
933 if ((req->req.actual == req->req.length)
934 || ((req->req.actual % ep->ep.maxpacket) != 0)) {
935
936 result = 0;
937 }
938
939 return result;
940}
941
942/*-------------------------------------------------------------------------*/
943static int _nbu2ss_epn_out_data(
944 struct nbu2ss_udc *udc,
945 struct nbu2ss_ep *ep,
946 struct nbu2ss_req *req,
947 u32 data_size
948)
949{
950 u32 num;
951 u32 iBufSize;
952 int nret = 1;
953
954 if (ep->epnum == 0)
955 return -EINVAL;
956
957 num = ep->epnum - 1;
958
959 iBufSize = min((req->req.length - req->req.actual), data_size);
960
961 if ((ep->ep_type != USB_ENDPOINT_XFER_INT)
962 && (req->req.dma != 0)
963 && (iBufSize >= sizeof(u32))) {
964 nret = _nbu2ss_out_dma(udc, req, num, iBufSize);
965 } else {
Ebru Akagunduz77d966f2014-10-02 23:32:07 +0300966 iBufSize = min_t(u32, iBufSize, ep->ep.maxpacket);
Magnus Damm33aa8d42014-06-06 19:44:17 +0900967 nret = _nbu2ss_epn_out_pio(udc, ep, req, iBufSize);
968 }
969
970 return nret;
971}
972
973/*-------------------------------------------------------------------------*/
974static int _nbu2ss_epn_out_transfer(
975 struct nbu2ss_udc *udc,
976 struct nbu2ss_ep *ep,
977 struct nbu2ss_req *req
978)
979{
980 u32 num;
981 u32 iRecvLength;
982 int result = 1;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +0300983 struct fc_regs *preg = udc->p_regs;
Magnus Damm33aa8d42014-06-06 19:44:17 +0900984
985 if (ep->epnum == 0)
986 return -EINVAL;
987
988 num = ep->epnum - 1;
989
990 /*-------------------------------------------------------------*/
991 /* Receive Length */
992 iRecvLength
993 = _nbu2ss_readl(&preg->EP_REGS[num].EP_LEN_DCNT) & EPn_LDATA;
994
995 if (iRecvLength != 0) {
996 result = _nbu2ss_epn_out_data(udc, ep, req, iRecvLength);
997 if (iRecvLength < ep->ep.maxpacket) {
998 if (iRecvLength == result) {
999 req->req.actual += result;
1000 result = 0;
1001 }
1002 }
1003 } else {
1004 if ((req->req.actual == req->req.length)
1005 || ((req->req.actual % ep->ep.maxpacket) != 0)) {
1006
1007 result = 0;
1008 }
1009 }
1010
1011 if (result == 0) {
1012 if ((req->req.actual % ep->ep.maxpacket) == 0) {
1013 if (req->zero) {
Roberta Dobrescu666e9082014-09-23 11:37:02 +03001014 req->zero = false;
Magnus Damm33aa8d42014-06-06 19:44:17 +09001015 return 1;
1016 }
1017 }
1018 }
1019
1020 if (req->req.actual > req->req.length) {
Haneen Mohammed88689272015-03-02 21:37:38 +03001021 dev_err(udc->dev, " Overrun Error\n");
1022 dev_err(udc->dev, " actual = %d, length = %d\n",
Magnus Damm33aa8d42014-06-06 19:44:17 +09001023 req->req.actual, req->req.length);
1024 result = -EOVERFLOW;
1025 }
1026
1027 return result;
1028}
1029
1030/*-------------------------------------------------------------------------*/
1031static int _nbu2ss_in_dma(
1032 struct nbu2ss_udc *udc,
1033 struct nbu2ss_ep *ep,
1034 struct nbu2ss_req *req,
1035 u32 num,
1036 u32 length
1037)
1038{
1039 u8 *pBuffer;
1040 u32 mpkt; /* MaxPacketSize */
1041 u32 lmpkt; /* Last Packet Data Size */
1042 u32 dmacnt; /* IN Data Size */
1043 u32 iWriteLength;
1044 u32 data;
1045 int result = -EINVAL;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +03001046 struct fc_regs *preg = udc->p_regs;
Magnus Damm33aa8d42014-06-06 19:44:17 +09001047
1048 if (req->dma_flag)
1049 return 1; /* DMA is forwarded */
1050
1051#ifdef USE_DMA
1052 if (req->req.actual == 0)
1053 _nbu2ss_dma_map_single(udc, ep, req, USB_DIR_IN);
1054#endif
1055 req->dma_flag = TRUE;
1056
1057 /* MAX Packet Size */
1058 mpkt = _nbu2ss_readl(&preg->EP_REGS[num].EP_PCKT_ADRS) & EPn_MPKT;
1059
1060 if ((DMA_MAX_COUNT * mpkt) < length)
1061 iWriteLength = DMA_MAX_COUNT * mpkt;
1062 else
1063 iWriteLength = length;
1064
1065 /*------------------------------------------------------------*/
1066 /* Number of transmission packets */
1067 if (mpkt < iWriteLength) {
1068 dmacnt = iWriteLength / mpkt;
1069 lmpkt = (iWriteLength % mpkt) & ~(u32)0x3;
1070 if (lmpkt != 0)
1071 dmacnt++;
1072 else
1073 lmpkt = mpkt & ~(u32)0x3;
1074
1075 } else {
1076 dmacnt = 1;
1077 lmpkt = iWriteLength & ~(u32)0x3;
1078 }
1079
1080 /* Packet setting */
1081 data = mpkt | (lmpkt << 16);
1082 _nbu2ss_writel(&preg->EP_DCR[num].EP_DCR2, data);
1083
1084 /* Address setting */
1085 pBuffer = (u8 *)req->req.dma;
1086 pBuffer += req->req.actual;
1087 _nbu2ss_writel(&preg->EP_DCR[num].EP_TADR, (u32)pBuffer);
1088
1089 /* Packet and DMA setting */
1090 data = ((dmacnt & 0xff) << 16) | DCR1_EPn_REQEN;
1091 _nbu2ss_writel(&preg->EP_DCR[num].EP_DCR1, data);
1092
1093 /* Packet setting of EPC */
1094 data = dmacnt << 16;
1095 _nbu2ss_writel(&preg->EP_REGS[num].EP_LEN_DCNT, data);
1096
1097 /*DMA setting of EPC */
1098 _nbu2ss_bitset(&preg->EP_REGS[num].EP_DMA_CTRL, EPn_DMA_EN);
1099
1100 result = iWriteLength & ~(u32)0x3;
1101 req->div_len = result;
1102
1103 return result;
1104}
1105
1106/*-------------------------------------------------------------------------*/
1107static int _nbu2ss_epn_in_pio(
1108 struct nbu2ss_udc *udc,
1109 struct nbu2ss_ep *ep,
1110 struct nbu2ss_req *req,
1111 u32 length
1112)
1113{
1114 u8 *pBuffer;
1115 u32 i;
1116 u32 data;
1117 u32 iWordLength;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +03001118 union usb_reg_access Temp32;
1119 union usb_reg_access *pBuf32 = NULL;
Magnus Damm33aa8d42014-06-06 19:44:17 +09001120 int result = 0;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +03001121 struct fc_regs *preg = udc->p_regs;
Magnus Damm33aa8d42014-06-06 19:44:17 +09001122
1123 if (req->dma_flag)
1124 return 1; /* DMA is forwarded */
1125
1126 if (length > 0) {
1127 pBuffer = (u8 *)req->req.buf;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +03001128 pBuf32 = (union usb_reg_access *)(pBuffer + req->req.actual);
Magnus Damm33aa8d42014-06-06 19:44:17 +09001129
1130 iWordLength = length / sizeof(u32);
1131 if (iWordLength > 0) {
1132 for (i = 0; i < iWordLength; i++) {
1133 _nbu2ss_writel(
1134 &preg->EP_REGS[ep->epnum-1].EP_WRITE
1135 , pBuf32->dw
1136 );
1137
1138 pBuf32++;
1139 }
1140 result = iWordLength * sizeof(u32);
1141 }
1142 }
1143
1144 if (result != ep->ep.maxpacket) {
1145 data = length - result;
1146 Temp32.dw = 0;
1147 for (i = 0 ; i < data ; i++)
1148 Temp32.byte.DATA[i] = pBuf32->byte.DATA[i];
1149
1150 _nbu2ss_ep_in_end(udc, ep->epnum, Temp32.dw, data);
1151 result += data;
1152 }
1153
1154 req->div_len = result;
1155
1156 return result;
1157}
1158
1159/*-------------------------------------------------------------------------*/
1160static int _nbu2ss_epn_in_data(
1161 struct nbu2ss_udc *udc,
1162 struct nbu2ss_ep *ep,
1163 struct nbu2ss_req *req,
1164 u32 data_size
1165)
1166{
1167 u32 num;
1168 int nret = 1;
1169
1170 if (ep->epnum == 0)
1171 return -EINVAL;
1172
1173 num = ep->epnum - 1;
1174
1175 if ((ep->ep_type != USB_ENDPOINT_XFER_INT)
1176 && (req->req.dma != 0)
1177 && (data_size >= sizeof(u32))) {
1178 nret = _nbu2ss_in_dma(udc, ep, req, num, data_size);
1179 } else {
Ebru Akagunduz77d966f2014-10-02 23:32:07 +03001180 data_size = min_t(u32, data_size, ep->ep.maxpacket);
Magnus Damm33aa8d42014-06-06 19:44:17 +09001181 nret = _nbu2ss_epn_in_pio(udc, ep, req, data_size);
1182 }
1183
1184 return nret;
1185}
1186
1187/*-------------------------------------------------------------------------*/
1188static int _nbu2ss_epn_in_transfer(
1189 struct nbu2ss_udc *udc,
1190 struct nbu2ss_ep *ep,
1191 struct nbu2ss_req *req
1192)
1193{
1194 u32 num;
1195 u32 iBufSize;
1196 int result = 0;
1197 u32 status;
1198
1199 if (ep->epnum == 0)
1200 return -EINVAL;
1201
1202 num = ep->epnum - 1;
1203
1204 status = _nbu2ss_readl(&udc->p_regs->EP_REGS[num].EP_STATUS);
1205
1206 /*-------------------------------------------------------------*/
1207 /* State confirmation of FIFO */
1208 if (req->req.actual == 0) {
1209 if ((status & EPn_IN_EMPTY) == 0)
1210 return 1; /* Not Empty */
1211
1212 } else {
1213 if ((status & EPn_IN_FULL) != 0)
1214 return 1; /* Not Empty */
1215 }
1216
1217 /*-------------------------------------------------------------*/
Carlos E. Garcia69e98df2015-04-24 09:40:42 -04001218 /* Start transfer */
Magnus Damm33aa8d42014-06-06 19:44:17 +09001219 iBufSize = req->req.length - req->req.actual;
1220 if (iBufSize > 0)
1221 result = _nbu2ss_epn_in_data(udc, ep, req, iBufSize);
1222 else if (req->req.length == 0)
1223 _nbu2ss_zero_len_pkt(udc, ep->epnum);
1224
1225 return result;
1226}
1227
1228/*-------------------------------------------------------------------------*/
1229static int _nbu2ss_start_transfer(
1230 struct nbu2ss_udc *udc,
1231 struct nbu2ss_ep *ep,
1232 struct nbu2ss_req *req,
1233 bool bflag)
1234{
1235 int nret = -EINVAL;
1236
1237 req->dma_flag = FALSE;
1238 req->div_len = 0;
1239
1240 if (req->req.length == 0)
Roberta Dobrescu666e9082014-09-23 11:37:02 +03001241 req->zero = false;
Magnus Damm33aa8d42014-06-06 19:44:17 +09001242 else {
1243 if ((req->req.length % ep->ep.maxpacket) == 0)
1244 req->zero = req->req.zero;
1245 else
Roberta Dobrescu666e9082014-09-23 11:37:02 +03001246 req->zero = false;
Magnus Damm33aa8d42014-06-06 19:44:17 +09001247 }
1248
1249 if (ep->epnum == 0) {
1250 /* EP0 */
1251 switch (udc->ep0state) {
1252 case EP0_IN_DATA_PHASE:
Ravi Teja Darbhaf2b29162015-09-08 21:18:51 +05301253 nret = _nbu2ss_ep0_in_transfer(udc, req);
Magnus Damm33aa8d42014-06-06 19:44:17 +09001254 break;
1255
1256 case EP0_OUT_DATA_PHASE:
Ravi Teja Darbhaf2b29162015-09-08 21:18:51 +05301257 nret = _nbu2ss_ep0_out_transfer(udc, req);
Magnus Damm33aa8d42014-06-06 19:44:17 +09001258 break;
1259
1260 case EP0_IN_STATUS_PHASE:
1261 nret = EP0_send_NULL(udc, TRUE);
1262 break;
1263
1264 default:
1265 break;
1266 }
1267
1268 } else {
1269 /* EPn */
1270 if (ep->direct == USB_DIR_OUT) {
1271 /* OUT */
1272 if (bflag == FALSE)
1273 nret = _nbu2ss_epn_out_transfer(udc, ep, req);
1274 } else {
1275 /* IN */
1276 nret = _nbu2ss_epn_in_transfer(udc, ep, req);
1277 }
1278 }
1279
1280 return nret;
1281}
1282
1283/*-------------------------------------------------------------------------*/
1284static void _nbu2ss_restert_transfer(struct nbu2ss_ep *ep)
1285{
1286 u32 length;
1287 bool bflag = FALSE;
1288 struct nbu2ss_req *req;
1289
1290 if (list_empty(&ep->queue))
1291 req = NULL;
1292 else
1293 req = list_entry(ep->queue.next, struct nbu2ss_req, queue);
1294
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05301295 if (!req)
Magnus Damm33aa8d42014-06-06 19:44:17 +09001296 return;
1297
1298 if (ep->epnum > 0) {
1299 length = _nbu2ss_readl(
1300 &ep->udc->p_regs->EP_REGS[ep->epnum-1].EP_LEN_DCNT);
1301
1302 length &= EPn_LDATA;
1303 if (length < ep->ep.maxpacket)
1304 bflag = TRUE;
1305 }
1306
1307 _nbu2ss_start_transfer(ep->udc, ep, req, bflag);
1308}
1309
1310/*-------------------------------------------------------------------------*/
1311/* Endpoint Toggle Reset */
1312static void _nbu2ss_endpoint_toggle_reset(
1313 struct nbu2ss_udc *udc,
1314 u8 ep_adrs)
1315{
1316 u8 num;
1317 u32 data;
1318
1319 if ((ep_adrs == 0) || (ep_adrs == 0x80))
1320 return;
1321
1322 num = (ep_adrs & 0x7F) - 1;
1323
1324 if (ep_adrs & USB_DIR_IN)
1325 data = EPn_IPIDCLR;
1326 else
1327 data = EPn_BCLR | EPn_OPIDCLR;
1328
1329 _nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data);
1330}
1331
1332/*-------------------------------------------------------------------------*/
1333/* Endpoint STALL set */
1334static void _nbu2ss_set_endpoint_stall(
1335 struct nbu2ss_udc *udc,
1336 u8 ep_adrs,
1337 bool bstall)
1338{
1339 u8 num, epnum;
1340 u32 data;
1341 struct nbu2ss_ep *ep;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +03001342 struct fc_regs *preg = udc->p_regs;
Magnus Damm33aa8d42014-06-06 19:44:17 +09001343
1344 if ((ep_adrs == 0) || (ep_adrs == 0x80)) {
1345 if (bstall) {
1346 /* Set STALL */
1347 _nbu2ss_bitset(&preg->EP0_CONTROL, EP0_STL);
1348 } else {
1349 /* Clear STALL */
1350 _nbu2ss_bitclr(&preg->EP0_CONTROL, EP0_STL);
1351 }
1352 } else {
1353 epnum = ep_adrs & USB_ENDPOINT_NUMBER_MASK;
1354 num = epnum - 1;
1355 ep = &udc->ep[epnum];
1356
1357 if (bstall) {
1358 /* Set STALL */
1359 ep->halted = TRUE;
1360
1361 if (ep_adrs & USB_DIR_IN)
1362 data = EPn_BCLR | EPn_ISTL;
1363 else
1364 data = EPn_OSTL_EN | EPn_OSTL;
1365
1366 _nbu2ss_bitset(&preg->EP_REGS[num].EP_CONTROL, data);
1367 } else {
1368 /* Clear STALL */
1369 ep->stalled = FALSE;
1370 if (ep_adrs & USB_DIR_IN) {
1371 _nbu2ss_bitclr(&preg->EP_REGS[num].EP_CONTROL
1372 , EPn_ISTL);
1373 } else {
1374 data =
1375 _nbu2ss_readl(&preg->EP_REGS[num].EP_CONTROL);
1376
1377 data &= ~EPn_OSTL;
1378 data |= EPn_OSTL_EN;
1379
1380 _nbu2ss_writel(&preg->EP_REGS[num].EP_CONTROL
1381 , data);
1382 }
1383
1384 ep->stalled = FALSE;
1385 if (ep->halted) {
1386 ep->halted = FALSE;
1387 _nbu2ss_restert_transfer(ep);
1388 }
1389 }
1390 }
Magnus Damm33aa8d42014-06-06 19:44:17 +09001391}
1392
Magnus Damm33aa8d42014-06-06 19:44:17 +09001393/*-------------------------------------------------------------------------*/
1394/* Device Descriptor */
1395static struct usb_device_descriptor device_desc = {
1396 .bLength = sizeof(device_desc),
1397 .bDescriptorType = USB_DT_DEVICE,
Roberta Dobrescu1ff99b32014-09-19 23:34:36 +03001398 .bcdUSB = cpu_to_le16(0x0200),
Magnus Damm33aa8d42014-06-06 19:44:17 +09001399 .bDeviceClass = USB_CLASS_VENDOR_SPEC,
1400 .bDeviceSubClass = 0x00,
1401 .bDeviceProtocol = 0x00,
1402 .bMaxPacketSize0 = 64,
Roberta Dobrescu1ff99b32014-09-19 23:34:36 +03001403 .idVendor = cpu_to_le16(0x0409),
1404 .idProduct = cpu_to_le16(0xfff0),
Magnus Damm33aa8d42014-06-06 19:44:17 +09001405 .bcdDevice = 0xffff,
1406 .iManufacturer = 0x00,
1407 .iProduct = 0x00,
1408 .iSerialNumber = 0x00,
1409 .bNumConfigurations = 0x01,
1410};
1411
1412/*-------------------------------------------------------------------------*/
1413static void _nbu2ss_set_test_mode(struct nbu2ss_udc *udc, u32 mode)
1414{
1415 u32 data;
1416
1417 if (mode > MAX_TEST_MODE_NUM)
1418 return;
1419
Haneen Mohammed93275c82015-03-16 01:26:37 +03001420 dev_info(udc->dev, "SET FEATURE : test mode = %d\n", mode);
Magnus Damm33aa8d42014-06-06 19:44:17 +09001421
1422 data = _nbu2ss_readl(&udc->p_regs->USB_CONTROL);
1423 data &= ~TEST_FORCE_ENABLE;
1424 data |= mode << TEST_MODE_SHIFT;
1425
1426 _nbu2ss_writel(&udc->p_regs->USB_CONTROL, data);
1427 _nbu2ss_bitset(&udc->p_regs->TEST_CONTROL, CS_TESTMODEEN);
1428}
1429
1430/*-------------------------------------------------------------------------*/
1431static int _nbu2ss_set_feature_device(
1432 struct nbu2ss_udc *udc,
1433 u16 selector,
1434 u16 wIndex
1435)
1436{
1437 int result = -EOPNOTSUPP;
1438
1439 switch (selector) {
1440 case USB_DEVICE_REMOTE_WAKEUP:
Cristina Moraru28669142015-09-29 14:47:25 -07001441 if (wIndex == 0x0000) {
Magnus Damm33aa8d42014-06-06 19:44:17 +09001442 udc->remote_wakeup = U2F_ENABLE;
1443 result = 0;
1444 }
1445 break;
1446
1447 case USB_DEVICE_TEST_MODE:
Aya Mahfouz410c9442015-02-26 11:45:51 +02001448 wIndex >>= 8;
Magnus Damm33aa8d42014-06-06 19:44:17 +09001449 if (wIndex <= MAX_TEST_MODE_NUM)
1450 result = 0;
1451 break;
1452
1453 default:
1454 break;
1455 }
1456
1457 return result;
1458}
1459
1460/*-------------------------------------------------------------------------*/
1461static int _nbu2ss_get_ep_stall(struct nbu2ss_udc *udc, u8 ep_adrs)
1462{
1463 u8 epnum;
1464 u32 data = 0, bit_data;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +03001465 struct fc_regs *preg = udc->p_regs;
Magnus Damm33aa8d42014-06-06 19:44:17 +09001466
1467 epnum = ep_adrs & ~USB_ENDPOINT_DIR_MASK;
1468 if (epnum == 0) {
1469 data = _nbu2ss_readl(&preg->EP0_CONTROL);
1470 bit_data = EP0_STL;
1471
1472 } else {
1473 data = _nbu2ss_readl(&preg->EP_REGS[epnum-1].EP_CONTROL);
1474 if ((data & EPn_EN) == 0)
1475 return -1;
1476
1477 if (ep_adrs & USB_ENDPOINT_DIR_MASK)
1478 bit_data = EPn_ISTL;
1479 else
1480 bit_data = EPn_OSTL;
1481 }
1482
1483 if ((data & bit_data) == 0)
1484 return 0;
Gulsah Kose924c6ee2014-09-26 00:41:22 +03001485 return 1;
Magnus Damm33aa8d42014-06-06 19:44:17 +09001486}
1487
1488/*-------------------------------------------------------------------------*/
1489static inline int _nbu2ss_req_feature(struct nbu2ss_udc *udc, bool bset)
1490{
1491 u8 recipient = (u8)(udc->ctrl.bRequestType & USB_RECIP_MASK);
1492 u8 direction = (u8)(udc->ctrl.bRequestType & USB_DIR_IN);
1493 u16 selector = udc->ctrl.wValue;
1494 u16 wIndex = udc->ctrl.wIndex;
1495 u8 ep_adrs;
1496 int result = -EOPNOTSUPP;
1497
Cristina Moraru28669142015-09-29 14:47:25 -07001498 if ((udc->ctrl.wLength != 0x0000) ||
1499 (direction != USB_DIR_OUT)) {
Magnus Damm33aa8d42014-06-06 19:44:17 +09001500 return -EINVAL;
1501 }
1502
1503 switch (recipient) {
1504 case USB_RECIP_DEVICE:
1505 if (bset)
1506 result =
1507 _nbu2ss_set_feature_device(udc, selector, wIndex);
1508 break;
1509
1510 case USB_RECIP_ENDPOINT:
1511 if (0x0000 == (wIndex & 0xFF70)) {
Cristina Moraru28669142015-09-29 14:47:25 -07001512 if (selector == USB_ENDPOINT_HALT) {
Magnus Damm33aa8d42014-06-06 19:44:17 +09001513 ep_adrs = wIndex & 0xFF;
1514 if (bset == FALSE) {
1515 _nbu2ss_endpoint_toggle_reset(
1516 udc, ep_adrs);
1517 }
1518
1519 _nbu2ss_set_endpoint_stall(
1520 udc, ep_adrs, bset);
1521
1522 result = 0;
1523 }
1524 }
1525 break;
1526
1527 default:
1528 break;
1529 }
1530
1531 if (result >= 0)
1532 _nbu2ss_create_ep0_packet(udc, udc->ep0_buf, 0);
1533
1534 return result;
1535}
1536
1537/*-------------------------------------------------------------------------*/
1538static inline enum usb_device_speed _nbu2ss_get_speed(struct nbu2ss_udc *udc)
1539{
1540 u32 data;
1541 enum usb_device_speed speed = USB_SPEED_FULL;
1542
1543 data = _nbu2ss_readl(&udc->p_regs->USB_STATUS);
1544 if (data & HIGH_SPEED)
1545 speed = USB_SPEED_HIGH;
1546
1547 return speed;
1548}
1549
1550/*-------------------------------------------------------------------------*/
1551static void _nbu2ss_epn_set_stall(
1552 struct nbu2ss_udc *udc,
1553 struct nbu2ss_ep *ep
1554)
1555{
1556 u8 ep_adrs;
1557 u32 regdata;
1558 int limit_cnt = 0;
1559
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +03001560 struct fc_regs *preg = udc->p_regs;
Magnus Damm33aa8d42014-06-06 19:44:17 +09001561
1562 if (ep->direct == USB_DIR_IN) {
1563 for (limit_cnt = 0
1564 ; limit_cnt < IN_DATA_EMPTY_COUNT
1565 ; limit_cnt++) {
1566
1567 regdata = _nbu2ss_readl(
1568 &preg->EP_REGS[ep->epnum-1].EP_STATUS);
1569
1570 if ((regdata & EPn_IN_DATA) == 0)
1571 break;
1572
1573 mdelay(1);
1574 }
1575 }
1576
1577 ep_adrs = ep->epnum | ep->direct;
1578 _nbu2ss_set_endpoint_stall(udc, ep_adrs, 1);
1579}
1580
1581/*-------------------------------------------------------------------------*/
1582static int std_req_get_status(struct nbu2ss_udc *udc)
1583{
1584 u32 length;
1585 u16 status_data = 0;
1586 u8 recipient = (u8)(udc->ctrl.bRequestType & USB_RECIP_MASK);
1587 u8 direction = (u8)(udc->ctrl.bRequestType & USB_DIR_IN);
1588 u8 ep_adrs;
1589 int result = -EINVAL;
1590
Cristina Moraru28669142015-09-29 14:47:25 -07001591 if ((udc->ctrl.wValue != 0x0000)
1592 || (direction != USB_DIR_IN)) {
Magnus Damm33aa8d42014-06-06 19:44:17 +09001593
1594 return result;
1595 }
1596
Ebru Akagunduz77d966f2014-10-02 23:32:07 +03001597 length = min_t(u16, udc->ctrl.wLength, sizeof(status_data));
Magnus Damm33aa8d42014-06-06 19:44:17 +09001598
1599 switch (recipient) {
1600 case USB_RECIP_DEVICE:
1601 if (udc->ctrl.wIndex == 0x0000) {
Peter Chen9239d882015-01-28 16:32:27 +08001602 if (udc->gadget.is_selfpowered)
Magnus Damm33aa8d42014-06-06 19:44:17 +09001603 status_data |= (1 << USB_DEVICE_SELF_POWERED);
1604
1605 if (udc->remote_wakeup)
1606 status_data |= (1 << USB_DEVICE_REMOTE_WAKEUP);
1607
1608 result = 0;
1609 }
1610 break;
1611
1612 case USB_RECIP_ENDPOINT:
1613 if (0x0000 == (udc->ctrl.wIndex & 0xFF70)) {
1614 ep_adrs = (u8)(udc->ctrl.wIndex & 0xFF);
1615 result = _nbu2ss_get_ep_stall(udc, ep_adrs);
1616
1617 if (result > 0)
1618 status_data |= (1 << USB_ENDPOINT_HALT);
1619 }
1620 break;
1621
1622 default:
1623 break;
1624 }
1625
1626 if (result >= 0) {
1627 memcpy(udc->ep0_buf, &status_data, length);
1628 _nbu2ss_create_ep0_packet(udc, udc->ep0_buf, length);
Ravi Teja Darbhaf2b29162015-09-08 21:18:51 +05301629 _nbu2ss_ep0_in_transfer(udc, &udc->ep0_req);
Magnus Damm33aa8d42014-06-06 19:44:17 +09001630
1631 } else {
Haneen Mohammed88689272015-03-02 21:37:38 +03001632 dev_err(udc->dev, " Error GET_STATUS\n");
Magnus Damm33aa8d42014-06-06 19:44:17 +09001633 }
1634
1635 return result;
1636}
1637
1638/*-------------------------------------------------------------------------*/
1639static int std_req_clear_feature(struct nbu2ss_udc *udc)
1640{
1641 return _nbu2ss_req_feature(udc, FALSE);
1642}
1643
1644/*-------------------------------------------------------------------------*/
1645static int std_req_set_feature(struct nbu2ss_udc *udc)
1646{
1647 return _nbu2ss_req_feature(udc, TRUE);
1648}
1649
1650/*-------------------------------------------------------------------------*/
1651static int std_req_set_address(struct nbu2ss_udc *udc)
1652{
1653 int result = 0;
1654 u32 wValue = udc->ctrl.wValue;
1655
Cristina Moraru28669142015-09-29 14:47:25 -07001656 if ((udc->ctrl.bRequestType != 0x00) ||
1657 (udc->ctrl.wIndex != 0x0000) ||
1658 (udc->ctrl.wLength != 0x0000)) {
Magnus Damm33aa8d42014-06-06 19:44:17 +09001659 return -EINVAL;
1660 }
1661
1662 if (wValue != (wValue & 0x007F))
1663 return -EINVAL;
1664
Aya Mahfouz410c9442015-02-26 11:45:51 +02001665 wValue <<= USB_ADRS_SHIFT;
Magnus Damm33aa8d42014-06-06 19:44:17 +09001666
1667 _nbu2ss_writel(&udc->p_regs->USB_ADDRESS, wValue);
1668 _nbu2ss_create_ep0_packet(udc, udc->ep0_buf, 0);
1669
1670 return result;
1671}
1672
1673/*-------------------------------------------------------------------------*/
1674static int std_req_set_configuration(struct nbu2ss_udc *udc)
1675{
1676 u32 ConfigValue = (u32)(udc->ctrl.wValue & 0x00ff);
1677
Cristina Moraru28669142015-09-29 14:47:25 -07001678 if ((udc->ctrl.wIndex != 0x0000) ||
1679 (udc->ctrl.wLength != 0x0000) ||
1680 (udc->ctrl.bRequestType != 0x00)) {
Magnus Damm33aa8d42014-06-06 19:44:17 +09001681 return -EINVAL;
1682 }
1683
1684 udc->curr_config = ConfigValue;
1685
1686 if (ConfigValue > 0) {
1687 _nbu2ss_bitset(&udc->p_regs->USB_CONTROL, CONF);
1688 udc->devstate = USB_STATE_CONFIGURED;
1689
1690 } else {
1691 _nbu2ss_bitclr(&udc->p_regs->USB_CONTROL, CONF);
1692 udc->devstate = USB_STATE_ADDRESS;
1693 }
1694
1695 return 0;
1696}
1697
1698/*-------------------------------------------------------------------------*/
1699static inline void _nbu2ss_read_request_data(struct nbu2ss_udc *udc, u32 *pdata)
1700{
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05301701 if ((!udc) && (!pdata))
Magnus Damm33aa8d42014-06-06 19:44:17 +09001702 return;
1703
1704 *pdata = _nbu2ss_readl(&udc->p_regs->SETUP_DATA0);
1705 pdata++;
1706 *pdata = _nbu2ss_readl(&udc->p_regs->SETUP_DATA1);
1707}
1708
1709/*-------------------------------------------------------------------------*/
1710static inline int _nbu2ss_decode_request(struct nbu2ss_udc *udc)
1711{
1712 bool bcall_back = TRUE;
1713 int nret = -EINVAL;
1714 struct usb_ctrlrequest *p_ctrl;
1715
1716 p_ctrl = &udc->ctrl;
1717 _nbu2ss_read_request_data(udc, (u32 *)p_ctrl);
1718
1719 /* ep0 state control */
1720 if (p_ctrl->wLength == 0) {
1721 udc->ep0state = EP0_IN_STATUS_PHASE;
1722
1723 } else {
1724 if (p_ctrl->bRequestType & USB_DIR_IN)
1725 udc->ep0state = EP0_IN_DATA_PHASE;
1726 else
1727 udc->ep0state = EP0_OUT_DATA_PHASE;
1728 }
1729
1730 if ((p_ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
1731 switch (p_ctrl->bRequest) {
1732 case USB_REQ_GET_STATUS:
1733 nret = std_req_get_status(udc);
1734 bcall_back = FALSE;
1735 break;
1736
1737 case USB_REQ_CLEAR_FEATURE:
1738 nret = std_req_clear_feature(udc);
1739 bcall_back = FALSE;
1740 break;
1741
1742 case USB_REQ_SET_FEATURE:
1743 nret = std_req_set_feature(udc);
1744 bcall_back = FALSE;
1745 break;
1746
1747 case USB_REQ_SET_ADDRESS:
1748 nret = std_req_set_address(udc);
1749 bcall_back = FALSE;
1750 break;
1751
1752 case USB_REQ_SET_CONFIGURATION:
1753 nret = std_req_set_configuration(udc);
1754 break;
1755
1756 default:
1757 break;
1758 }
1759 }
1760
1761 if (bcall_back == FALSE) {
1762 if (udc->ep0state == EP0_IN_STATUS_PHASE) {
1763 if (nret >= 0) {
1764 /*--------------------------------------*/
1765 /* Status Stage */
1766 nret = EP0_send_NULL(udc, TRUE);
1767 }
1768 }
1769
1770 } else {
1771 spin_unlock(&udc->lock);
1772 nret = udc->driver->setup(&udc->gadget, &udc->ctrl);
1773 spin_lock(&udc->lock);
1774 }
1775
1776 if (nret < 0)
1777 udc->ep0state = EP0_IDLE;
1778
1779 return nret;
1780}
1781
1782/*-------------------------------------------------------------------------*/
1783static inline int _nbu2ss_ep0_in_data_stage(struct nbu2ss_udc *udc)
1784{
1785 int nret;
1786 struct nbu2ss_req *req;
1787 struct nbu2ss_ep *ep = &udc->ep[0];
1788
1789 if (list_empty(&ep->queue))
1790 req = NULL;
1791 else
1792 req = list_entry(ep->queue.next, struct nbu2ss_req, queue);
1793
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05301794 if (!req)
Magnus Damm33aa8d42014-06-06 19:44:17 +09001795 req = &udc->ep0_req;
1796
1797 req->req.actual += req->div_len;
1798 req->div_len = 0;
1799
Ravi Teja Darbhaf2b29162015-09-08 21:18:51 +05301800 nret = _nbu2ss_ep0_in_transfer(udc, req);
Magnus Damm33aa8d42014-06-06 19:44:17 +09001801 if (nret == 0) {
1802 udc->ep0state = EP0_OUT_STATUS_PAHSE;
1803 EP0_receive_NULL(udc, TRUE);
1804 }
1805
1806 return 0;
1807}
1808
1809/*-------------------------------------------------------------------------*/
1810static inline int _nbu2ss_ep0_out_data_stage(struct nbu2ss_udc *udc)
1811{
1812 int nret;
1813 struct nbu2ss_req *req;
1814 struct nbu2ss_ep *ep = &udc->ep[0];
1815
1816 if (list_empty(&ep->queue))
1817 req = NULL;
1818 else
1819 req = list_entry(ep->queue.next, struct nbu2ss_req, queue);
1820
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05301821 if (!req)
Magnus Damm33aa8d42014-06-06 19:44:17 +09001822 req = &udc->ep0_req;
1823
Ravi Teja Darbhaf2b29162015-09-08 21:18:51 +05301824 nret = _nbu2ss_ep0_out_transfer(udc, req);
Magnus Damm33aa8d42014-06-06 19:44:17 +09001825 if (nret == 0) {
1826 udc->ep0state = EP0_IN_STATUS_PHASE;
1827 EP0_send_NULL(udc, TRUE);
1828
1829 } else if (nret < 0) {
1830 _nbu2ss_bitset(&udc->p_regs->EP0_CONTROL, EP0_BCLR);
1831 req->req.status = nret;
1832 }
1833
1834 return 0;
1835}
1836
1837/*-------------------------------------------------------------------------*/
1838static inline int _nbu2ss_ep0_status_stage(struct nbu2ss_udc *udc)
1839{
1840 struct nbu2ss_req *req;
1841 struct nbu2ss_ep *ep = &udc->ep[0];
1842
1843 if (list_empty(&ep->queue))
1844 req = NULL;
1845 else
1846 req = list_entry(ep->queue.next, struct nbu2ss_req, queue);
1847
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05301848 if (!req) {
Magnus Damm33aa8d42014-06-06 19:44:17 +09001849 req = &udc->ep0_req;
1850 if (req->req.complete)
1851 req->req.complete(&ep->ep, &req->req);
1852
1853 } else {
1854 if (req->req.complete)
1855 _nbu2ss_ep_done(ep, req, 0);
1856 }
1857
1858 udc->ep0state = EP0_IDLE;
1859
1860 return 0;
1861}
1862
1863/*-------------------------------------------------------------------------*/
1864static inline void _nbu2ss_ep0_int(struct nbu2ss_udc *udc)
1865{
1866 int i;
1867 u32 status;
1868 u32 intr;
1869 int nret = -1;
1870
1871 status = _nbu2ss_readl(&udc->p_regs->EP0_STATUS);
1872 intr = status & EP0_STATUS_RW_BIT;
1873 _nbu2ss_writel(&udc->p_regs->EP0_STATUS, ~(u32)intr);
1874
1875 status &= (SETUP_INT | EP0_IN_INT | EP0_OUT_INT
1876 | STG_END_INT | EP0_OUT_NULL_INT);
1877
1878 if (status == 0) {
Haneen Mohammed93275c82015-03-16 01:26:37 +03001879 dev_info(udc->dev, "%s Not Decode Interrupt\n", __func__);
1880 dev_info(udc->dev, "EP0_STATUS = 0x%08x\n", intr);
Magnus Damm33aa8d42014-06-06 19:44:17 +09001881 return;
1882 }
1883
1884 if (udc->gadget.speed == USB_SPEED_UNKNOWN)
1885 udc->gadget.speed = _nbu2ss_get_speed(udc);
1886
1887 for (i = 0; i < EP0_END_XFER; i++) {
1888 switch (udc->ep0state) {
1889 case EP0_IDLE:
1890 if (status & SETUP_INT) {
1891 status = 0;
1892 nret = _nbu2ss_decode_request(udc);
1893 }
1894 break;
1895
1896 case EP0_IN_DATA_PHASE:
1897 if (status & EP0_IN_INT) {
1898 status &= ~EP0_IN_INT;
1899 nret = _nbu2ss_ep0_in_data_stage(udc);
1900 }
1901 break;
1902
1903 case EP0_OUT_DATA_PHASE:
1904 if (status & EP0_OUT_INT) {
1905 status &= ~EP0_OUT_INT;
1906 nret = _nbu2ss_ep0_out_data_stage(udc);
1907 }
1908 break;
1909
1910 case EP0_IN_STATUS_PHASE:
1911 if ((status & STG_END_INT) || (status & SETUP_INT)) {
1912 status &= ~(STG_END_INT | EP0_IN_INT);
1913 nret = _nbu2ss_ep0_status_stage(udc);
1914 }
1915 break;
1916
1917 case EP0_OUT_STATUS_PAHSE:
1918 if ((status & STG_END_INT)
1919 || (status & SETUP_INT)
1920 || (status & EP0_OUT_NULL_INT)) {
1921 status &= ~(STG_END_INT
1922 | EP0_OUT_INT
1923 | EP0_OUT_NULL_INT);
1924
1925 nret = _nbu2ss_ep0_status_stage(udc);
1926 }
1927
1928 break;
1929
1930 default:
1931 status = 0;
1932 break;
1933 }
1934
1935 if (status == 0)
1936 break;
1937 }
1938
1939 if (nret < 0) {
1940 /* Send Stall */
1941 _nbu2ss_set_endpoint_stall(udc, 0, TRUE);
1942 }
1943}
1944
1945/*-------------------------------------------------------------------------*/
1946static void _nbu2ss_ep_done(
1947 struct nbu2ss_ep *ep,
1948 struct nbu2ss_req *req,
1949 int status)
1950{
1951 struct nbu2ss_udc *udc = ep->udc;
1952
1953 list_del_init(&req->queue);
1954
1955 if (status == -ECONNRESET)
1956 _nbu2ss_fifo_flush(udc, ep);
1957
1958 if (likely(req->req.status == -EINPROGRESS))
1959 req->req.status = status;
1960
1961 if (ep->stalled)
1962 _nbu2ss_epn_set_stall(udc, ep);
1963 else {
1964 if (!list_empty(&ep->queue))
1965 _nbu2ss_restert_transfer(ep);
1966 }
1967
1968#ifdef USE_DMA
1969 if ((ep->direct == USB_DIR_OUT) && (ep->epnum > 0) &&
1970 (req->req.dma != 0))
1971 _nbu2ss_dma_unmap_single(udc, ep, req, USB_DIR_OUT);
1972#endif
1973
1974 spin_unlock(&udc->lock);
1975 req->req.complete(&ep->ep, &req->req);
1976 spin_lock(&udc->lock);
1977}
1978
1979/*-------------------------------------------------------------------------*/
1980static inline void _nbu2ss_epn_in_int(
1981 struct nbu2ss_udc *udc,
1982 struct nbu2ss_ep *ep,
1983 struct nbu2ss_req *req)
1984{
1985 int result = 0;
1986 u32 status;
1987
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +03001988 struct fc_regs *preg = udc->p_regs;
Magnus Damm33aa8d42014-06-06 19:44:17 +09001989
1990 if (req->dma_flag)
1991 return; /* DMA is forwarded */
1992
1993 req->req.actual += req->div_len;
1994 req->div_len = 0;
1995
1996 if (req->req.actual != req->req.length) {
1997 /*---------------------------------------------------------*/
1998 /* remainder of data */
1999 result = _nbu2ss_epn_in_transfer(udc, ep, req);
2000
2001 } else {
Roberta Dobrescu5cbca952014-09-23 11:36:37 +03002002 if (req->zero && ((req->req.actual % ep->ep.maxpacket) == 0)) {
Magnus Damm33aa8d42014-06-06 19:44:17 +09002003
2004 status =
2005 _nbu2ss_readl(&preg->EP_REGS[ep->epnum-1].EP_STATUS);
2006
2007 if ((status & EPn_IN_FULL) == 0) {
2008 /*-----------------------------------------*/
2009 /* 0 Length Packet */
Roberta Dobrescu666e9082014-09-23 11:37:02 +03002010 req->zero = false;
Magnus Damm33aa8d42014-06-06 19:44:17 +09002011 _nbu2ss_zero_len_pkt(udc, ep->epnum);
2012 }
2013 return;
2014 }
2015 }
2016
2017 if (result <= 0) {
2018 /*---------------------------------------------------------*/
2019 /* Complete */
2020 _nbu2ss_ep_done(ep, req, result);
2021 }
2022}
2023
2024/*-------------------------------------------------------------------------*/
2025static inline void _nbu2ss_epn_out_int(
2026 struct nbu2ss_udc *udc,
2027 struct nbu2ss_ep *ep,
2028 struct nbu2ss_req *req)
2029{
2030 int result;
2031
2032 result = _nbu2ss_epn_out_transfer(udc, ep, req);
2033 if (result <= 0)
2034 _nbu2ss_ep_done(ep, req, result);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002035}
2036
2037/*-------------------------------------------------------------------------*/
2038static inline void _nbu2ss_epn_in_dma_int(
2039 struct nbu2ss_udc *udc,
2040 struct nbu2ss_ep *ep,
2041 struct nbu2ss_req *req)
2042{
2043 u32 mpkt;
2044 u32 size;
2045 struct usb_request *preq;
2046
2047 preq = &req->req;
2048
2049 if (req->dma_flag == FALSE)
2050 return;
2051
2052 preq->actual += req->div_len;
2053 req->div_len = 0;
2054 req->dma_flag = FALSE;
2055
2056#ifdef USE_DMA
2057 _nbu2ss_dma_unmap_single(udc, ep, req, USB_DIR_IN);
2058#endif
2059
2060 if (preq->actual != preq->length) {
2061 _nbu2ss_epn_in_transfer(udc, ep, req);
2062 } else {
2063 mpkt = ep->ep.maxpacket;
2064 size = preq->actual % mpkt;
2065 if (size > 0) {
2066 if (((preq->actual & 0x03) == 0) && (size < mpkt))
2067 _nbu2ss_ep_in_end(udc, ep->epnum, 0, 0);
2068 } else {
2069 _nbu2ss_epn_in_int(udc, ep, req);
2070 }
2071 }
Magnus Damm33aa8d42014-06-06 19:44:17 +09002072}
2073
2074/*-------------------------------------------------------------------------*/
2075static inline void _nbu2ss_epn_out_dma_int(
2076 struct nbu2ss_udc *udc,
2077 struct nbu2ss_ep *ep,
2078 struct nbu2ss_req *req)
2079{
2080 int i;
2081 u32 num;
2082 u32 dmacnt, ep_dmacnt;
2083 u32 mpkt;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +03002084 struct fc_regs *preg = udc->p_regs;
Magnus Damm33aa8d42014-06-06 19:44:17 +09002085
2086 num = ep->epnum - 1;
2087
2088 if (req->req.actual == req->req.length) {
Roberta Dobrescu5cbca952014-09-23 11:36:37 +03002089 if ((req->req.length % ep->ep.maxpacket) && !req->zero) {
Magnus Damm33aa8d42014-06-06 19:44:17 +09002090 req->div_len = 0;
2091 req->dma_flag = FALSE;
2092 _nbu2ss_ep_done(ep, req, 0);
2093 return;
2094 }
2095 }
2096
2097 ep_dmacnt = _nbu2ss_readl(&preg->EP_REGS[num].EP_LEN_DCNT)
2098 & EPn_DMACNT;
2099 ep_dmacnt >>= 16;
2100
2101 for (i = 0; i < EPC_PLL_LOCK_COUNT; i++) {
2102 dmacnt = _nbu2ss_readl(&preg->EP_DCR[num].EP_DCR1)
2103 & DCR1_EPn_DMACNT;
2104 dmacnt >>= 16;
2105 if (ep_dmacnt == dmacnt)
2106 break;
2107 }
2108
2109 _nbu2ss_bitclr(&preg->EP_DCR[num].EP_DCR1, DCR1_EPn_REQEN);
2110
2111 if (dmacnt != 0) {
2112 mpkt = ep->ep.maxpacket;
2113 if ((req->div_len % mpkt) == 0)
2114 req->div_len -= mpkt * dmacnt;
2115 }
2116
2117 if ((req->req.actual % ep->ep.maxpacket) > 0) {
2118 if (req->req.actual == req->div_len) {
2119 req->div_len = 0;
2120 req->dma_flag = FALSE;
2121 _nbu2ss_ep_done(ep, req, 0);
2122 return;
2123 }
2124 }
2125
2126 req->req.actual += req->div_len;
2127 req->div_len = 0;
2128 req->dma_flag = FALSE;
2129
2130 _nbu2ss_epn_out_int(udc, ep, req);
2131}
2132
2133/*-------------------------------------------------------------------------*/
2134static inline void _nbu2ss_epn_int(struct nbu2ss_udc *udc, u32 epnum)
2135{
2136 u32 num;
2137 u32 status;
2138
2139 struct nbu2ss_req *req;
2140 struct nbu2ss_ep *ep = &udc->ep[epnum];
2141
2142 num = epnum - 1;
2143
2144 /* Interrupt Status */
2145 status = _nbu2ss_readl(&udc->p_regs->EP_REGS[num].EP_STATUS);
2146
2147 /* Interrupt Clear */
2148 _nbu2ss_writel(&udc->p_regs->EP_REGS[num].EP_STATUS, ~(u32)status);
2149
2150 if (list_empty(&ep->queue))
2151 req = NULL;
2152 else
2153 req = list_entry(ep->queue.next, struct nbu2ss_req, queue);
2154
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05302155 if (!req) {
Masanari Iidaf02935c2014-09-13 01:14:30 +09002156 /* pr_warn("=== %s(%d) req == NULL\n", __func__, epnum); */
Magnus Damm33aa8d42014-06-06 19:44:17 +09002157 return;
2158 }
2159
2160 if (status & EPn_OUT_END_INT) {
2161 status &= ~EPn_OUT_INT;
2162 _nbu2ss_epn_out_dma_int(udc, ep, req);
2163 }
2164
2165 if (status & EPn_OUT_INT)
2166 _nbu2ss_epn_out_int(udc, ep, req);
2167
2168 if (status & EPn_IN_END_INT) {
2169 status &= ~EPn_IN_INT;
2170 _nbu2ss_epn_in_dma_int(udc, ep, req);
2171 }
2172
2173 if (status & EPn_IN_INT)
2174 _nbu2ss_epn_in_int(udc, ep, req);
2175}
2176
2177/*-------------------------------------------------------------------------*/
2178static inline void _nbu2ss_ep_int(struct nbu2ss_udc *udc, u32 epnum)
2179{
2180 if (epnum == 0)
2181 _nbu2ss_ep0_int(udc);
2182 else
2183 _nbu2ss_epn_int(udc, epnum);
2184}
2185
2186/*-------------------------------------------------------------------------*/
2187static void _nbu2ss_ep0_enable(struct nbu2ss_udc *udc)
2188{
2189 _nbu2ss_bitset(&udc->p_regs->EP0_CONTROL, (EP0_AUTO | EP0_BCLR));
2190 _nbu2ss_writel(&udc->p_regs->EP0_INT_ENA, EP0_INT_EN_BIT);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002191}
2192
Magnus Damm33aa8d42014-06-06 19:44:17 +09002193/*-------------------------------------------------------------------------*/
2194static int _nbu2ss_nuke(struct nbu2ss_udc *udc,
2195 struct nbu2ss_ep *ep,
2196 int status)
2197{
2198 struct nbu2ss_req *req;
2199
2200 /* Endpoint Disable */
2201 _nbu2ss_epn_exit(udc, ep);
2202
2203 /* DMA Disable */
2204 _nbu2ss_ep_dma_exit(udc, ep);
2205
2206 if (list_empty(&ep->queue))
2207 return 0;
2208
2209 /* called with irqs blocked */
Somya Anandca3d2532015-03-14 01:03:08 +05302210 list_for_each_entry(req, &ep->queue, queue) {
Magnus Damm33aa8d42014-06-06 19:44:17 +09002211 _nbu2ss_ep_done(ep, req, status);
2212 }
2213
2214 return 0;
2215}
2216
2217/*-------------------------------------------------------------------------*/
2218static void _nbu2ss_quiesce(struct nbu2ss_udc *udc)
2219{
2220 struct nbu2ss_ep *ep;
2221
2222 udc->gadget.speed = USB_SPEED_UNKNOWN;
2223
2224 _nbu2ss_nuke(udc, &udc->ep[0], -ESHUTDOWN);
2225
2226 /* Endpoint n */
2227 list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
2228 _nbu2ss_nuke(udc, ep, -ESHUTDOWN);
2229 }
2230}
2231
2232/*-------------------------------------------------------------------------*/
2233static int _nbu2ss_pullup(struct nbu2ss_udc *udc, int is_on)
2234{
2235 u32 reg_dt;
2236
Magnus Damm33aa8d42014-06-06 19:44:17 +09002237 if (udc->vbus_active == 0)
2238 return -ESHUTDOWN;
2239
2240 if (is_on) {
2241 /* D+ Pullup */
Magnus Damm33aa8d42014-06-06 19:44:17 +09002242 if (udc->driver) {
2243 reg_dt = (_nbu2ss_readl(&udc->p_regs->USB_CONTROL)
2244 | PUE2) & ~(u32)CONNECTB;
2245
2246 _nbu2ss_writel(&udc->p_regs->USB_CONTROL, reg_dt);
2247 }
2248
2249 } else {
2250 /* D+ Pulldown */
Magnus Damm33aa8d42014-06-06 19:44:17 +09002251 reg_dt = (_nbu2ss_readl(&udc->p_regs->USB_CONTROL) | CONNECTB)
2252 & ~(u32)PUE2;
2253
2254 _nbu2ss_writel(&udc->p_regs->USB_CONTROL, reg_dt);
2255 udc->gadget.speed = USB_SPEED_UNKNOWN;
2256 }
2257
2258 return 0;
2259}
2260
2261/*-------------------------------------------------------------------------*/
2262static void _nbu2ss_fifo_flush(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
2263{
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +03002264 struct fc_regs *p = udc->p_regs;
Magnus Damm33aa8d42014-06-06 19:44:17 +09002265
2266 if (udc->vbus_active == 0)
2267 return;
2268
2269 if (ep->epnum == 0) {
2270 /* EP0 */
2271 _nbu2ss_bitset(&p->EP0_CONTROL, EP0_BCLR);
2272
2273 } else {
2274 /* EPn */
2275 _nbu2ss_ep_dma_abort(udc, ep);
2276 _nbu2ss_bitset(&p->EP_REGS[ep->epnum - 1].EP_CONTROL, EPn_BCLR);
2277 }
2278}
2279
2280/*-------------------------------------------------------------------------*/
2281static int _nbu2ss_enable_controller(struct nbu2ss_udc *udc)
2282{
2283 int waitcnt = 0;
2284
2285 if (udc->udc_enabled)
2286 return 0;
2287
Magnus Damm33aa8d42014-06-06 19:44:17 +09002288 /*
2289 Reset
2290 */
2291 _nbu2ss_bitset(&udc->p_regs->EPCTR, (DIRPD | EPC_RST));
2292 udelay(EPC_RST_DISABLE_TIME); /* 1us wait */
2293
2294 _nbu2ss_bitclr(&udc->p_regs->EPCTR, DIRPD);
2295 mdelay(EPC_DIRPD_DISABLE_TIME); /* 1ms wait */
2296
2297 _nbu2ss_bitclr(&udc->p_regs->EPCTR, EPC_RST);
2298
2299 _nbu2ss_writel(&udc->p_regs->AHBSCTR, WAIT_MODE);
2300
Magnus Damm33aa8d42014-06-06 19:44:17 +09002301 _nbu2ss_writel(&udc->p_regs->AHBMCTR,
2302 HBUSREQ_MODE | HTRANS_MODE | WBURST_TYPE);
2303
2304 while (!(_nbu2ss_readl(&udc->p_regs->EPCTR) & PLL_LOCK)) {
2305 waitcnt++;
2306 udelay(1); /* 1us wait */
2307 if (waitcnt == EPC_PLL_LOCK_COUNT) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002308 dev_err(udc->dev, "*** Reset Cancel failed\n");
Magnus Damm33aa8d42014-06-06 19:44:17 +09002309 return -EINVAL;
2310 }
Gujulan Elango, Hari Prasath (H.)3e2bb642015-04-23 19:29:51 +00002311 }
Magnus Damm33aa8d42014-06-06 19:44:17 +09002312
Magnus Damm33aa8d42014-06-06 19:44:17 +09002313 _nbu2ss_bitset(&udc->p_regs->UTMI_CHARACTER_1, USB_SQUSET);
2314
2315 _nbu2ss_bitset(&udc->p_regs->USB_CONTROL, (INT_SEL | SOF_RCV));
2316
2317 /* EP0 */
2318 _nbu2ss_ep0_enable(udc);
2319
2320 /* USB Interrupt Enable */
2321 _nbu2ss_bitset(&udc->p_regs->USB_INT_ENA, USB_INT_EN_BIT);
2322
2323 udc->udc_enabled = TRUE;
2324
2325 return 0;
2326}
2327
Magnus Damm33aa8d42014-06-06 19:44:17 +09002328/*-------------------------------------------------------------------------*/
2329static void _nbu2ss_reset_controller(struct nbu2ss_udc *udc)
2330{
2331 _nbu2ss_bitset(&udc->p_regs->EPCTR, EPC_RST);
2332 _nbu2ss_bitclr(&udc->p_regs->EPCTR, EPC_RST);
2333}
2334
2335/*-------------------------------------------------------------------------*/
2336static void _nbu2ss_disable_controller(struct nbu2ss_udc *udc)
2337{
2338 if (udc->udc_enabled) {
2339 udc->udc_enabled = FALSE;
2340 _nbu2ss_reset_controller(udc);
2341 _nbu2ss_bitset(&udc->p_regs->EPCTR, (DIRPD | EPC_RST));
2342 }
Magnus Damm33aa8d42014-06-06 19:44:17 +09002343}
2344
2345/*-------------------------------------------------------------------------*/
2346static inline void _nbu2ss_check_vbus(struct nbu2ss_udc *udc)
2347{
2348 int nret;
2349 u32 reg_dt;
2350
2351 /* chattering */
2352 mdelay(VBUS_CHATTERING_MDELAY); /* wait (ms) */
2353
2354 /* VBUS ON Check*/
2355 reg_dt = gpio_get_value(VBUS_VALUE);
2356 if (reg_dt == 0) {
2357
2358 udc->linux_suspended = 0;
2359
2360 _nbu2ss_reset_controller(udc);
Haneen Mohammed93275c82015-03-16 01:26:37 +03002361 dev_info(udc->dev, " ----- VBUS OFF\n");
Magnus Damm33aa8d42014-06-06 19:44:17 +09002362
2363 if (udc->vbus_active == 1) {
2364 /* VBUS OFF */
2365 udc->vbus_active = 0;
2366 if (udc->usb_suspended) {
2367 udc->usb_suspended = 0;
2368 /* _nbu2ss_reset_controller(udc); */
2369 }
2370 udc->devstate = USB_STATE_NOTATTACHED;
2371
2372 _nbu2ss_quiesce(udc);
2373 if (udc->driver) {
2374 spin_unlock(&udc->lock);
2375 udc->driver->disconnect(&udc->gadget);
2376 spin_lock(&udc->lock);
2377 }
2378
2379 _nbu2ss_disable_controller(udc);
2380 }
2381 } else {
2382 mdelay(5); /* wait (5ms) */
2383 reg_dt = gpio_get_value(VBUS_VALUE);
2384 if (reg_dt == 0)
2385 return;
2386
Haneen Mohammed93275c82015-03-16 01:26:37 +03002387 dev_info(udc->dev, " ----- VBUS ON\n");
Magnus Damm33aa8d42014-06-06 19:44:17 +09002388
2389 if (udc->linux_suspended)
2390 return;
2391
2392 if (udc->vbus_active == 0) {
2393 /* VBUS ON */
2394 udc->vbus_active = 1;
2395 udc->devstate = USB_STATE_POWERED;
2396
2397 nret = _nbu2ss_enable_controller(udc);
2398 if (nret < 0) {
2399 _nbu2ss_disable_controller(udc);
2400 udc->vbus_active = 0;
2401 return;
2402 }
2403
2404 _nbu2ss_pullup(udc, 1);
2405
2406#ifdef UDC_DEBUG_DUMP
2407 _nbu2ss_dump_register(udc);
2408#endif /* UDC_DEBUG_DUMP */
2409
2410 } else {
2411 if (udc->devstate == USB_STATE_POWERED)
2412 _nbu2ss_pullup(udc, 1);
2413 }
2414 }
Magnus Damm33aa8d42014-06-06 19:44:17 +09002415}
2416
2417/*-------------------------------------------------------------------------*/
2418static inline void _nbu2ss_int_bus_reset(struct nbu2ss_udc *udc)
2419{
2420 udc->devstate = USB_STATE_DEFAULT;
2421 udc->remote_wakeup = 0;
2422
2423 _nbu2ss_quiesce(udc);
2424
2425 udc->ep0state = EP0_IDLE;
2426}
2427
2428/*-------------------------------------------------------------------------*/
2429static inline void _nbu2ss_int_usb_resume(struct nbu2ss_udc *udc)
2430{
2431 if (udc->usb_suspended == 1) {
2432 udc->usb_suspended = 0;
2433 if (udc->driver && udc->driver->resume) {
2434 spin_unlock(&udc->lock);
2435 udc->driver->resume(&udc->gadget);
2436 spin_lock(&udc->lock);
2437 }
2438 }
2439}
2440
2441/*-------------------------------------------------------------------------*/
2442static inline void _nbu2ss_int_usb_suspend(struct nbu2ss_udc *udc)
2443{
2444 u32 reg_dt;
2445
2446 if (udc->usb_suspended == 0) {
2447 reg_dt = gpio_get_value(VBUS_VALUE);
2448
2449 if (reg_dt == 0)
2450 return;
2451
2452 udc->usb_suspended = 1;
2453 if (udc->driver && udc->driver->suspend) {
2454 spin_unlock(&udc->lock);
2455 udc->driver->suspend(&udc->gadget);
2456 spin_lock(&udc->lock);
2457 }
2458
2459 _nbu2ss_bitset(&udc->p_regs->USB_CONTROL, SUSPEND);
2460 }
2461}
2462
2463/*-------------------------------------------------------------------------*/
2464/* VBUS (GPIO153) Interrupt */
2465static irqreturn_t _nbu2ss_vbus_irq(int irq, void *_udc)
2466{
2467 struct nbu2ss_udc *udc = (struct nbu2ss_udc *)_udc;
2468
2469 spin_lock(&udc->lock);
2470 _nbu2ss_check_vbus(udc);
2471 spin_unlock(&udc->lock);
2472
2473 return IRQ_HANDLED;
2474}
2475
2476/*-------------------------------------------------------------------------*/
2477/* Interrupt (udc) */
2478static irqreturn_t _nbu2ss_udc_irq(int irq, void *_udc)
2479{
2480 u8 suspend_flag = 0;
2481 u32 status;
2482 u32 epnum, int_bit;
2483
2484 struct nbu2ss_udc *udc = (struct nbu2ss_udc *)_udc;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +03002485 struct fc_regs *preg = udc->p_regs;
Magnus Damm33aa8d42014-06-06 19:44:17 +09002486
2487 if (gpio_get_value(VBUS_VALUE) == 0) {
2488 _nbu2ss_writel(&preg->USB_INT_STA, ~USB_INT_STA_RW);
2489 _nbu2ss_writel(&preg->USB_INT_ENA, 0);
2490 return IRQ_HANDLED;
2491 }
2492
2493 spin_lock(&udc->lock);
2494
2495 for (;;) {
2496 if (gpio_get_value(VBUS_VALUE) == 0) {
2497 _nbu2ss_writel(&preg->USB_INT_STA, ~USB_INT_STA_RW);
2498 _nbu2ss_writel(&preg->USB_INT_ENA, 0);
2499 status = 0;
2500 } else
2501 status = _nbu2ss_readl(&preg->USB_INT_STA);
2502
2503 if (status == 0)
2504 break;
2505
2506 _nbu2ss_writel(&preg->USB_INT_STA, ~(status & USB_INT_STA_RW));
2507
2508 if (status & USB_RST_INT) {
2509 /* USB Reset */
2510 _nbu2ss_int_bus_reset(udc);
2511 }
2512
2513 if (status & RSUM_INT) {
2514 /* Resume */
2515 _nbu2ss_int_usb_resume(udc);
2516 }
2517
2518 if (status & SPND_INT) {
2519 /* Suspend */
2520 suspend_flag = 1;
2521 }
2522
2523 if (status & EPn_INT) {
2524 /* EP INT */
2525 int_bit = status >> 8;
2526
2527 for (epnum = 0; epnum < NUM_ENDPOINTS; epnum++) {
2528
2529 if (0x01 & int_bit)
2530 _nbu2ss_ep_int(udc, epnum);
2531
2532 int_bit >>= 1;
2533
2534 if (int_bit == 0)
2535 break;
2536 }
2537 }
2538 }
2539
2540 if (suspend_flag)
2541 _nbu2ss_int_usb_suspend(udc);
2542
2543 spin_unlock(&udc->lock);
2544
2545 return IRQ_HANDLED;
2546}
2547
2548/*-------------------------------------------------------------------------*/
2549/* usb_ep_ops */
2550static int nbu2ss_ep_enable(
2551 struct usb_ep *_ep,
2552 const struct usb_endpoint_descriptor *desc)
2553{
2554 u8 ep_type;
2555 unsigned long flags;
2556
2557 struct nbu2ss_ep *ep;
2558 struct nbu2ss_udc *udc;
2559
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05302560 if ((!_ep) || (!desc)) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002561 pr_err(" *** %s, bad param\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002562 return -EINVAL;
2563 }
2564
2565 ep = container_of(_ep, struct nbu2ss_ep, ep);
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05302566 if ((!ep) || (!ep->udc)) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002567 pr_err(" *** %s, ep == NULL !!\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002568 return -EINVAL;
2569 }
2570
Tapasweni Pathak3f3efca2014-10-30 22:03:36 +05302571 ep_type = usb_endpoint_type(desc);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002572 if ((ep_type == USB_ENDPOINT_XFER_CONTROL)
2573 || (ep_type == USB_ENDPOINT_XFER_ISOC)) {
2574
Haneen Mohammed88689272015-03-02 21:37:38 +03002575 pr_err(" *** %s, bat bmAttributes\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002576 return -EINVAL;
2577 }
2578
2579 udc = ep->udc;
2580 if (udc->vbus_active == 0)
2581 return -ESHUTDOWN;
2582
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05302583 if ((!udc->driver)
Magnus Damm33aa8d42014-06-06 19:44:17 +09002584 || (udc->gadget.speed == USB_SPEED_UNKNOWN)) {
2585
Haneen Mohammed88689272015-03-02 21:37:38 +03002586 dev_err(ep->udc->dev, " *** %s, udc !!\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002587 return -ESHUTDOWN;
2588 }
2589
2590 spin_lock_irqsave(&udc->lock, flags);
2591
2592 ep->desc = desc;
Tapasweni Pathak3f3efca2014-10-30 22:03:36 +05302593 ep->epnum = usb_endpoint_num(desc);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002594 ep->direct = desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK;
2595 ep->ep_type = ep_type;
2596 ep->wedged = 0;
2597 ep->halted = FALSE;
2598 ep->stalled = FALSE;
2599
2600 ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
2601
2602 /* DMA setting */
2603 _nbu2ss_ep_dma_init(udc, ep);
2604
2605 /* Endpoint setting */
2606 _nbu2ss_ep_init(udc, ep);
2607
2608 spin_unlock_irqrestore(&udc->lock, flags);
2609
2610 return 0;
2611}
2612
2613/*-------------------------------------------------------------------------*/
2614static int nbu2ss_ep_disable(struct usb_ep *_ep)
2615{
2616 struct nbu2ss_ep *ep;
2617 struct nbu2ss_udc *udc;
2618 unsigned long flags;
2619
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05302620 if (!_ep) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002621 pr_err(" *** %s, bad param\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002622 return -EINVAL;
2623 }
2624
2625 ep = container_of(_ep, struct nbu2ss_ep, ep);
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05302626 if ((!ep) || (!ep->udc)) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002627 pr_err("udc: *** %s, ep == NULL !!\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002628 return -EINVAL;
2629 }
2630
2631 udc = ep->udc;
2632 if (udc->vbus_active == 0)
2633 return -ESHUTDOWN;
2634
2635 spin_lock_irqsave(&udc->lock, flags);
2636 _nbu2ss_nuke(udc, ep, -EINPROGRESS); /* dequeue request */
2637 spin_unlock_irqrestore(&udc->lock, flags);
2638
2639 return 0;
2640}
2641
2642/*-------------------------------------------------------------------------*/
2643static struct usb_request *nbu2ss_ep_alloc_request(
2644 struct usb_ep *ep,
2645 gfp_t gfp_flags)
2646{
2647 struct nbu2ss_req *req;
2648
2649 req = kzalloc(sizeof(*req), gfp_flags);
2650 if (!req)
2651 return 0;
2652
2653#ifdef USE_DMA
2654 req->req.dma = DMA_ADDR_INVALID;
2655#endif
2656 INIT_LIST_HEAD(&req->queue);
2657
2658 return &req->req;
2659}
2660
2661/*-------------------------------------------------------------------------*/
2662static void nbu2ss_ep_free_request(
2663 struct usb_ep *_ep,
2664 struct usb_request *_req)
2665{
2666 struct nbu2ss_req *req;
2667
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05302668 if (_req) {
Magnus Damm33aa8d42014-06-06 19:44:17 +09002669 req = container_of(_req, struct nbu2ss_req, req);
2670
Tapasweni Pathaka5a89d72014-10-21 09:48:58 +05302671 kfree(req);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002672 }
2673}
2674
2675/*-------------------------------------------------------------------------*/
2676static int nbu2ss_ep_queue(
2677 struct usb_ep *_ep,
2678 struct usb_request *_req,
2679 gfp_t gfp_flags)
2680{
2681 struct nbu2ss_req *req;
2682 struct nbu2ss_ep *ep;
2683 struct nbu2ss_udc *udc;
2684 unsigned long flags;
2685 bool bflag;
2686 int result = -EINVAL;
2687
2688 /* catch various bogus parameters */
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05302689 if ((!_ep) || (!_req)) {
2690 if (!_ep)
Haneen Mohammed88689272015-03-02 21:37:38 +03002691 pr_err("udc: %s --- _ep == NULL\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002692
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05302693 if (!_req)
Haneen Mohammed88689272015-03-02 21:37:38 +03002694 pr_err("udc: %s --- _req == NULL\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002695
2696 return -EINVAL;
2697 }
2698
2699 req = container_of(_req, struct nbu2ss_req, req);
2700 if (unlikely
2701 (!_req->complete || !_req->buf
2702 || !list_empty(&req->queue))) {
2703
2704 if (!_req->complete)
Haneen Mohammed88689272015-03-02 21:37:38 +03002705 pr_err("udc: %s --- !_req->complete\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002706
2707 if (!_req->buf)
Haneen Mohammed88689272015-03-02 21:37:38 +03002708 pr_err("udc:%s --- !_req->buf\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002709
2710 if (!list_empty(&req->queue))
Haneen Mohammed88689272015-03-02 21:37:38 +03002711 pr_err("%s --- !list_empty(&req->queue)\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002712
2713 return -EINVAL;
2714 }
2715
2716 ep = container_of(_ep, struct nbu2ss_ep, ep);
2717 udc = ep->udc;
2718
Magnus Damm33aa8d42014-06-06 19:44:17 +09002719 if (udc->vbus_active == 0) {
Haneen Mohammed93275c82015-03-16 01:26:37 +03002720 dev_info(udc->dev, "Can't ep_queue (VBUS OFF)\n");
Magnus Damm33aa8d42014-06-06 19:44:17 +09002721 return -ESHUTDOWN;
2722 }
2723
2724 if (unlikely(!udc->driver)) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002725 dev_err(udc->dev, "%s, bogus device state %p\n", __func__,
2726 udc->driver);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002727 return -ESHUTDOWN;
2728 }
2729
2730 spin_lock_irqsave(&udc->lock, flags);
2731
2732#ifdef USE_DMA
2733 if ((u32)req->req.buf & 0x3)
2734 req->unaligned = TRUE;
2735 else
2736 req->unaligned = FALSE;
2737
2738 if (req->unaligned) {
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05302739 if (!ep->virt_buf)
Magnus Damm33aa8d42014-06-06 19:44:17 +09002740 ep->virt_buf = (u8 *)dma_alloc_coherent(
2741 NULL, PAGE_SIZE,
Tapasweni Pathak4a0721b2015-02-20 18:43:53 +05302742 &ep->phys_buf, GFP_ATOMIC | GFP_DMA);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002743 if (ep->epnum > 0) {
2744 if (ep->direct == USB_DIR_IN)
2745 memcpy(ep->virt_buf, req->req.buf,
2746 req->req.length);
2747 }
2748 }
2749
2750 if ((ep->epnum > 0) && (ep->direct == USB_DIR_OUT) &&
2751 (req->req.dma != 0))
2752 _nbu2ss_dma_map_single(udc, ep, req, USB_DIR_OUT);
2753#endif
2754
2755 _req->status = -EINPROGRESS;
2756 _req->actual = 0;
2757
2758 bflag = list_empty(&ep->queue);
2759 list_add_tail(&req->queue, &ep->queue);
2760
2761 if ((bflag != FALSE) && (ep->stalled == FALSE)) {
2762
2763 result = _nbu2ss_start_transfer(udc, ep, req, FALSE);
2764 if (result < 0) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002765 dev_err(udc->dev, " *** %s, result = %d\n", __func__,
2766 result);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002767 list_del(&req->queue);
2768 } else if ((ep->epnum > 0) && (ep->direct == USB_DIR_OUT)) {
2769#ifdef USE_DMA
2770 if (req->req.length < 4 &&
2771 req->req.length == req->req.actual)
2772#else
2773 if (req->req.length == req->req.actual)
2774#endif
2775 _nbu2ss_ep_done(ep, req, result);
2776 }
2777 }
2778
2779 spin_unlock_irqrestore(&udc->lock, flags);
2780
2781 return 0;
2782}
2783
2784/*-------------------------------------------------------------------------*/
2785static int nbu2ss_ep_dequeue(
2786 struct usb_ep *_ep,
2787 struct usb_request *_req)
2788{
2789 struct nbu2ss_req *req;
2790 struct nbu2ss_ep *ep;
2791 struct nbu2ss_udc *udc;
2792 unsigned long flags;
2793
Magnus Damm33aa8d42014-06-06 19:44:17 +09002794 /* catch various bogus parameters */
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05302795 if ((!_ep) || (!_req)) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002796 /* pr_err("%s, bad param(1)\n", __func__); */
Magnus Damm33aa8d42014-06-06 19:44:17 +09002797 return -EINVAL;
2798 }
2799
2800 ep = container_of(_ep, struct nbu2ss_ep, ep);
2801 if (!ep) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002802 pr_err("%s, ep == NULL !!\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002803 return -EINVAL;
2804 }
2805
2806 udc = ep->udc;
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05302807 if (!udc)
Magnus Damm33aa8d42014-06-06 19:44:17 +09002808 return -EINVAL;
2809
2810 spin_lock_irqsave(&udc->lock, flags);
2811
2812 /* make sure it's actually queued on this endpoint */
2813 list_for_each_entry(req, &ep->queue, queue) {
2814 if (&req->req == _req)
2815 break;
2816 }
2817 if (&req->req != _req) {
2818 spin_unlock_irqrestore(&udc->lock, flags);
2819 pr_debug("%s no queue(EINVAL)\n", __func__);
2820 return -EINVAL;
2821 }
2822
2823 _nbu2ss_ep_done(ep, req, -ECONNRESET);
2824
2825 spin_unlock_irqrestore(&udc->lock, flags);
2826
2827 return 0;
2828}
2829
2830/*-------------------------------------------------------------------------*/
2831static int nbu2ss_ep_set_halt(struct usb_ep *_ep, int value)
2832{
2833 u8 ep_adrs;
2834 unsigned long flags;
2835
2836 struct nbu2ss_ep *ep;
2837 struct nbu2ss_udc *udc;
2838
Magnus Damm33aa8d42014-06-06 19:44:17 +09002839 if (!_ep) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002840 pr_err("%s, bad param\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002841 return -EINVAL;
2842 }
2843
2844 ep = container_of(_ep, struct nbu2ss_ep, ep);
2845 if (!ep) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002846 pr_err("%s, bad ep\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002847 return -EINVAL;
2848 }
2849
2850 udc = ep->udc;
2851 if (!udc) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002852 dev_err(ep->udc->dev, " *** %s, bad udc\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002853 return -EINVAL;
2854 }
2855
2856 spin_lock_irqsave(&udc->lock, flags);
2857
2858 ep_adrs = ep->epnum | ep->direct;
2859 if (value == 0) {
2860 _nbu2ss_set_endpoint_stall(udc, ep_adrs, value);
2861 ep->stalled = FALSE;
2862 } else {
2863 if (list_empty(&ep->queue))
2864 _nbu2ss_epn_set_stall(udc, ep);
2865 else
2866 ep->stalled = TRUE;
2867 }
2868
2869 if (value == 0)
2870 ep->wedged = 0;
2871
2872 spin_unlock_irqrestore(&udc->lock, flags);
2873
2874 return 0;
2875}
2876
2877static int nbu2ss_ep_set_wedge(struct usb_ep *_ep)
2878{
2879 return nbu2ss_ep_set_halt(_ep, 1);
2880}
2881
2882/*-------------------------------------------------------------------------*/
2883static int nbu2ss_ep_fifo_status(struct usb_ep *_ep)
2884{
2885 u32 data;
2886 struct nbu2ss_ep *ep;
2887 struct nbu2ss_udc *udc;
2888 unsigned long flags;
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +03002889 struct fc_regs *preg;
Magnus Damm33aa8d42014-06-06 19:44:17 +09002890
Magnus Damm33aa8d42014-06-06 19:44:17 +09002891 if (!_ep) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002892 pr_err("%s, bad param\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002893 return -EINVAL;
2894 }
2895
2896 ep = container_of(_ep, struct nbu2ss_ep, ep);
2897 if (!ep) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002898 pr_err("%s, bad ep\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002899 return -EINVAL;
2900 }
2901
2902 udc = ep->udc;
2903 if (!udc) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002904 dev_err(ep->udc->dev, "%s, bad udc\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002905 return -EINVAL;
2906 }
2907
2908 preg = udc->p_regs;
2909
2910 data = gpio_get_value(VBUS_VALUE);
2911 if (data == 0)
2912 return -EINVAL;
2913
2914 spin_lock_irqsave(&udc->lock, flags);
2915
2916 if (ep->epnum == 0) {
2917 data = _nbu2ss_readl(&preg->EP0_LENGTH) & EP0_LDATA;
2918
2919 } else {
2920 data = _nbu2ss_readl(&preg->EP_REGS[ep->epnum-1].EP_LEN_DCNT)
2921 & EPn_LDATA;
2922 }
2923
2924 spin_unlock_irqrestore(&udc->lock, flags);
2925
2926 return 0;
2927}
2928
2929/*-------------------------------------------------------------------------*/
2930static void nbu2ss_ep_fifo_flush(struct usb_ep *_ep)
2931{
2932 u32 data;
2933 struct nbu2ss_ep *ep;
2934 struct nbu2ss_udc *udc;
2935 unsigned long flags;
2936
Magnus Damm33aa8d42014-06-06 19:44:17 +09002937 if (!_ep) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002938 pr_err("udc: %s, bad param\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002939 return;
2940 }
2941
2942 ep = container_of(_ep, struct nbu2ss_ep, ep);
Julia Lawallbd7de5c2015-04-04 16:59:30 +02002943 if (!ep) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002944 pr_err("udc: %s, bad ep\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002945 return;
2946 }
2947
2948 udc = ep->udc;
2949 if (!udc) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002950 dev_err(ep->udc->dev, "%s, bad udc\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002951 return;
2952 }
2953
2954 data = gpio_get_value(VBUS_VALUE);
2955 if (data == 0)
2956 return;
2957
2958 spin_lock_irqsave(&udc->lock, flags);
2959 _nbu2ss_fifo_flush(udc, ep);
2960 spin_unlock_irqrestore(&udc->lock, flags);
2961}
2962
2963/*-------------------------------------------------------------------------*/
2964static struct usb_ep_ops nbu2ss_ep_ops = {
2965 .enable = nbu2ss_ep_enable,
2966 .disable = nbu2ss_ep_disable,
2967
2968 .alloc_request = nbu2ss_ep_alloc_request,
2969 .free_request = nbu2ss_ep_free_request,
2970
2971 .queue = nbu2ss_ep_queue,
2972 .dequeue = nbu2ss_ep_dequeue,
2973
2974 .set_halt = nbu2ss_ep_set_halt,
2975 .set_wedge = nbu2ss_ep_set_wedge,
2976
2977 .fifo_status = nbu2ss_ep_fifo_status,
2978 .fifo_flush = nbu2ss_ep_fifo_flush,
2979};
2980
Magnus Damm33aa8d42014-06-06 19:44:17 +09002981/*-------------------------------------------------------------------------*/
2982/* usb_gadget_ops */
2983
2984/*-------------------------------------------------------------------------*/
2985static int nbu2ss_gad_get_frame(struct usb_gadget *pgadget)
2986{
2987 u32 data;
2988 struct nbu2ss_udc *udc;
2989
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05302990 if (!pgadget) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002991 pr_err("udc: %s, bad param\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002992 return -EINVAL;
2993 }
2994
2995 udc = container_of(pgadget, struct nbu2ss_udc, gadget);
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05302996 if (!udc) {
Haneen Mohammed88689272015-03-02 21:37:38 +03002997 dev_err(&pgadget->dev, "%s, udc == NULL\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09002998 return -EINVAL;
2999 }
3000
3001 data = gpio_get_value(VBUS_VALUE);
3002 if (data == 0)
3003 return -EINVAL;
3004
3005 data = _nbu2ss_readl(&udc->p_regs->USB_ADDRESS) & FRAME;
3006
3007 return data;
3008}
3009
3010/*-------------------------------------------------------------------------*/
3011static int nbu2ss_gad_wakeup(struct usb_gadget *pgadget)
3012{
3013 int i;
3014 u32 data;
3015
3016 struct nbu2ss_udc *udc;
3017
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05303018 if (!pgadget) {
Haneen Mohammed88689272015-03-02 21:37:38 +03003019 pr_err("%s, bad param\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09003020 return -EINVAL;
3021 }
3022
3023 udc = container_of(pgadget, struct nbu2ss_udc, gadget);
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05303024 if (!udc) {
Haneen Mohammed88689272015-03-02 21:37:38 +03003025 dev_err(&pgadget->dev, "%s, udc == NULL\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09003026 return -EINVAL;
3027 }
3028
3029 data = gpio_get_value(VBUS_VALUE);
3030 if (data == 0) {
Haneen Mohammed93275c82015-03-16 01:26:37 +03003031 dev_warn(&pgadget->dev, "VBUS LEVEL = %d\n", data);
Magnus Damm33aa8d42014-06-06 19:44:17 +09003032 return -EINVAL;
3033 }
3034
3035 _nbu2ss_bitset(&udc->p_regs->EPCTR, PLL_RESUME);
3036
3037 for (i = 0; i < EPC_PLL_LOCK_COUNT; i++) {
3038 data = _nbu2ss_readl(&udc->p_regs->EPCTR);
3039
3040 if (data & PLL_LOCK)
3041 break;
3042 }
3043
3044 _nbu2ss_bitclr(&udc->p_regs->EPCTR, PLL_RESUME);
3045
3046 return 0;
3047}
3048
3049/*-------------------------------------------------------------------------*/
3050static int nbu2ss_gad_set_selfpowered(struct usb_gadget *pgadget,
3051 int is_selfpowered)
3052{
Peter Chen1fa2df02015-02-03 10:37:06 +08003053 struct nbu2ss_udc *udc;
Magnus Damm33aa8d42014-06-06 19:44:17 +09003054 unsigned long flags;
3055
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05303056 if (!pgadget) {
Haneen Mohammed88689272015-03-02 21:37:38 +03003057 pr_err("%s, bad param\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09003058 return -EINVAL;
3059 }
3060
Peter Chen1fa2df02015-02-03 10:37:06 +08003061 udc = container_of(pgadget, struct nbu2ss_udc, gadget);
3062
Magnus Damm33aa8d42014-06-06 19:44:17 +09003063 spin_lock_irqsave(&udc->lock, flags);
Peter Chen9239d882015-01-28 16:32:27 +08003064 pgadget->is_selfpowered = (is_selfpowered != 0);
Magnus Damm33aa8d42014-06-06 19:44:17 +09003065 spin_unlock_irqrestore(&udc->lock, flags);
3066
3067 return 0;
3068}
3069
3070/*-------------------------------------------------------------------------*/
3071static int nbu2ss_gad_vbus_session(struct usb_gadget *pgadget, int is_active)
3072{
Magnus Damm33aa8d42014-06-06 19:44:17 +09003073 return 0;
3074}
3075
3076/*-------------------------------------------------------------------------*/
3077static int nbu2ss_gad_vbus_draw(struct usb_gadget *pgadget, unsigned mA)
3078{
3079 struct nbu2ss_udc *udc;
3080 unsigned long flags;
3081
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05303082 if (!pgadget) {
Haneen Mohammed88689272015-03-02 21:37:38 +03003083 pr_err("%s, bad param\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09003084 return -EINVAL;
3085 }
3086
3087 udc = container_of(pgadget, struct nbu2ss_udc, gadget);
3088
3089 spin_lock_irqsave(&udc->lock, flags);
3090 udc->mA = mA;
3091 spin_unlock_irqrestore(&udc->lock, flags);
3092
3093 return 0;
3094}
3095
3096/*-------------------------------------------------------------------------*/
3097static int nbu2ss_gad_pullup(struct usb_gadget *pgadget, int is_on)
3098{
3099 struct nbu2ss_udc *udc;
3100 unsigned long flags;
3101
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05303102 if (!pgadget) {
Haneen Mohammed88689272015-03-02 21:37:38 +03003103 pr_err("%s, bad param\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09003104 return -EINVAL;
3105 }
3106
3107 udc = container_of(pgadget, struct nbu2ss_udc, gadget);
3108
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05303109 if (!udc->driver) {
Masanari Iidaf02935c2014-09-13 01:14:30 +09003110 pr_warn("%s, Not Regist Driver\n", __func__);
Magnus Damm33aa8d42014-06-06 19:44:17 +09003111 return -EINVAL;
3112 }
3113
3114 if (udc->vbus_active == 0)
3115 return -ESHUTDOWN;
3116
3117 spin_lock_irqsave(&udc->lock, flags);
3118 _nbu2ss_pullup(udc, is_on);
3119 spin_unlock_irqrestore(&udc->lock, flags);
3120
3121 return 0;
3122}
3123
3124/*-------------------------------------------------------------------------*/
3125static int nbu2ss_gad_ioctl(
3126 struct usb_gadget *pgadget,
3127 unsigned code,
3128 unsigned long param)
3129{
Magnus Damm33aa8d42014-06-06 19:44:17 +09003130 return 0;
3131}
3132
Magnus Damm33aa8d42014-06-06 19:44:17 +09003133static const struct usb_gadget_ops nbu2ss_gadget_ops = {
3134 .get_frame = nbu2ss_gad_get_frame,
3135 .wakeup = nbu2ss_gad_wakeup,
3136 .set_selfpowered = nbu2ss_gad_set_selfpowered,
3137 .vbus_session = nbu2ss_gad_vbus_session,
3138 .vbus_draw = nbu2ss_gad_vbus_draw,
3139 .pullup = nbu2ss_gad_pullup,
3140 .ioctl = nbu2ss_gad_ioctl,
3141};
3142
Robert Baldyga68b5c942015-07-31 16:00:16 +02003143static const struct {
3144 const char *name;
3145 const struct usb_ep_caps caps;
3146} ep_info[NUM_ENDPOINTS] = {
3147#define EP_INFO(_name, _caps) \
3148 { \
3149 .name = _name, \
3150 .caps = _caps, \
3151 }
Magnus Damm33aa8d42014-06-06 19:44:17 +09003152
Robert Baldyga68b5c942015-07-31 16:00:16 +02003153 EP_INFO("ep0",
3154 USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
3155 EP_INFO("ep1-bulk",
3156 USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)),
3157 EP_INFO("ep2-bulk",
3158 USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)),
3159 EP_INFO("ep3in-int",
3160 USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
3161 EP_INFO("ep4-iso",
3162 USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_ALL)),
3163 EP_INFO("ep5-iso",
3164 USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_ALL)),
3165 EP_INFO("ep6-bulk",
3166 USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)),
3167 EP_INFO("ep7-bulk",
3168 USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)),
3169 EP_INFO("ep8in-int",
3170 USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
3171 EP_INFO("ep9-iso",
3172 USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_ALL)),
3173 EP_INFO("epa-iso",
3174 USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_ALL)),
3175 EP_INFO("epb-bulk",
3176 USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)),
3177 EP_INFO("epc-bulk",
3178 USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)),
3179 EP_INFO("epdin-int",
3180 USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
3181
3182#undef EP_INFO
Magnus Damm33aa8d42014-06-06 19:44:17 +09003183};
3184
3185/*-------------------------------------------------------------------------*/
Magnus Damm33aa8d42014-06-06 19:44:17 +09003186static void __init nbu2ss_drv_ep_init(struct nbu2ss_udc *udc)
3187{
3188 int i;
3189
3190 INIT_LIST_HEAD(&udc->gadget.ep_list);
3191 udc->gadget.ep0 = &udc->ep[0].ep;
3192
Chris Rorvick737fee12015-01-30 17:45:45 -06003193 for (i = 0; i < NUM_ENDPOINTS; i++) {
3194 struct nbu2ss_ep *ep = &udc->ep[i];
Magnus Damm33aa8d42014-06-06 19:44:17 +09003195
Chris Rorvick737fee12015-01-30 17:45:45 -06003196 ep->udc = udc;
3197 ep->desc = NULL;
3198
3199 ep->ep.driver_data = NULL;
Robert Baldyga68b5c942015-07-31 16:00:16 +02003200 ep->ep.name = ep_info[i].name;
3201 ep->ep.caps = ep_info[i].caps;
Chris Rorvick737fee12015-01-30 17:45:45 -06003202 ep->ep.ops = &nbu2ss_ep_ops;
3203
Robert Baldygacb009d62015-07-13 11:03:53 +02003204 usb_ep_set_maxpacket_limit(&ep->ep,
3205 i == 0 ? EP0_PACKETSIZE : EP_PACKETSIZE);
Chris Rorvick737fee12015-01-30 17:45:45 -06003206
3207 list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
3208 INIT_LIST_HEAD(&ep->queue);
3209 }
Magnus Damm33aa8d42014-06-06 19:44:17 +09003210
3211 list_del_init(&udc->ep[0].ep.ep_list);
3212}
3213
3214/*-------------------------------------------------------------------------*/
3215/* platform_driver */
3216static int __init nbu2ss_drv_contest_init(
3217 struct platform_device *pdev,
3218 struct nbu2ss_udc *udc)
3219{
3220 spin_lock_init(&udc->lock);
3221 udc->dev = &pdev->dev;
3222
Peter Chen9239d882015-01-28 16:32:27 +08003223 udc->gadget.is_selfpowered = 1;
Magnus Damm33aa8d42014-06-06 19:44:17 +09003224 udc->devstate = USB_STATE_NOTATTACHED;
3225 udc->pdev = pdev;
3226 udc->mA = 0;
3227
3228 udc->pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
3229
3230 /* init Endpoint */
3231 nbu2ss_drv_ep_init(udc);
3232
3233 /* init Gadget */
3234 udc->gadget.ops = &nbu2ss_gadget_ops;
3235 udc->gadget.ep0 = &udc->ep[0].ep;
3236 udc->gadget.speed = USB_SPEED_UNKNOWN;
3237 udc->gadget.name = driver_name;
KANG Yuxuana2c14e92014-07-16 10:45:01 +08003238 /* udc->gadget.is_dualspeed = 1; */
Magnus Damm33aa8d42014-06-06 19:44:17 +09003239
3240 device_initialize(&udc->gadget.dev);
3241
3242 dev_set_name(&udc->gadget.dev, "gadget");
3243 udc->gadget.dev.parent = &pdev->dev;
3244 udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
3245
3246 return 0;
3247}
3248
3249/*
3250 * probe - binds to the platform device
3251 */
3252static int nbu2ss_drv_probe(struct platform_device *pdev)
3253{
3254 int status = -ENODEV;
3255 struct nbu2ss_udc *udc;
Magnus Damm96b29ca2014-06-06 19:44:26 +09003256 struct resource *r;
3257 int irq;
3258 void __iomem *mmio_base;
Magnus Damm33aa8d42014-06-06 19:44:17 +09003259
3260 udc = &udc_controller;
3261 memset(udc, 0, sizeof(struct nbu2ss_udc));
3262
3263 platform_set_drvdata(pdev, udc);
3264
Magnus Damm96b29ca2014-06-06 19:44:26 +09003265 /* require I/O memory and IRQ to be provided as resources */
3266 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Sachin Kamata790ebc2014-06-23 11:43:08 +05303267 mmio_base = devm_ioremap_resource(&pdev->dev, r);
3268 if (IS_ERR(mmio_base))
Magnus Damm96b29ca2014-06-06 19:44:26 +09003269 return PTR_ERR(mmio_base);
Magnus Damm33aa8d42014-06-06 19:44:17 +09003270
Magnus Damm96b29ca2014-06-06 19:44:26 +09003271 irq = platform_get_irq(pdev, 0);
3272 if (irq < 0) {
3273 dev_err(&pdev->dev, "failed to get IRQ\n");
3274 return irq;
3275 }
3276 status = devm_request_irq(&pdev->dev, irq, _nbu2ss_udc_irq,
3277 0, driver_name, udc);
3278
Magnus Damm33aa8d42014-06-06 19:44:17 +09003279 /* IO Memory */
Haneen Mohammedf6ef6c02015-03-02 20:01:42 +03003280 udc->p_regs = (struct fc_regs *)mmio_base;
Magnus Damm33aa8d42014-06-06 19:44:17 +09003281
3282 /* USB Function Controller Interrupt */
Magnus Damm33aa8d42014-06-06 19:44:17 +09003283 if (status != 0) {
Haneen Mohammed88689272015-03-02 21:37:38 +03003284 dev_err(udc->dev, "request_irq(USB_UDC_IRQ_1) failed\n");
Ravi Teja Darbhac648a572015-09-05 01:08:29 +05303285 return status;
Magnus Damm33aa8d42014-06-06 19:44:17 +09003286 }
3287
3288 /* Driver Initialization */
3289 status = nbu2ss_drv_contest_init(pdev, udc);
3290 if (status < 0) {
3291 /* Error */
Ravi Teja Darbhac648a572015-09-05 01:08:29 +05303292 return status;
Magnus Damm33aa8d42014-06-06 19:44:17 +09003293 }
3294
3295 /* VBUS Interrupt */
3296 irq_set_irq_type(INT_VBUS, IRQ_TYPE_EDGE_BOTH);
3297 status = request_irq(INT_VBUS,
3298 _nbu2ss_vbus_irq,
3299 IRQF_SHARED,
3300 driver_name,
3301 udc);
3302
3303 if (status != 0) {
Haneen Mohammed88689272015-03-02 21:37:38 +03003304 dev_err(udc->dev, "request_irq(INT_VBUS) failed\n");
Ravi Teja Darbhac648a572015-09-05 01:08:29 +05303305 return status;
Magnus Damm33aa8d42014-06-06 19:44:17 +09003306 }
3307
3308 return status;
Magnus Damm33aa8d42014-06-06 19:44:17 +09003309}
3310
3311/*-------------------------------------------------------------------------*/
3312static void nbu2ss_drv_shutdown(struct platform_device *pdev)
3313{
3314 struct nbu2ss_udc *udc;
3315
3316 udc = platform_get_drvdata(pdev);
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05303317 if (!udc)
Magnus Damm33aa8d42014-06-06 19:44:17 +09003318 return;
3319
3320 _nbu2ss_disable_controller(udc);
3321}
3322
3323/*-------------------------------------------------------------------------*/
3324static int __exit nbu2ss_drv_remove(struct platform_device *pdev)
3325{
3326 struct nbu2ss_udc *udc;
3327 struct nbu2ss_ep *ep;
3328 int i;
3329
3330 udc = &udc_controller;
3331
3332 for (i = 0; i < NUM_ENDPOINTS; i++) {
3333 ep = &udc->ep[i];
3334 if (ep->virt_buf)
3335 dma_free_coherent(NULL, PAGE_SIZE,
3336 (void *)ep->virt_buf, ep->phys_buf);
3337 }
3338
3339 /* Interrupt Handler - Release */
Magnus Damm33aa8d42014-06-06 19:44:17 +09003340 free_irq(INT_VBUS, udc);
3341
Magnus Damm33aa8d42014-06-06 19:44:17 +09003342 return 0;
3343}
3344
3345/*-------------------------------------------------------------------------*/
3346static int nbu2ss_drv_suspend(struct platform_device *pdev, pm_message_t state)
3347{
3348 struct nbu2ss_udc *udc;
3349
3350 udc = platform_get_drvdata(pdev);
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05303351 if (!udc)
Magnus Damm33aa8d42014-06-06 19:44:17 +09003352 return 0;
3353
3354 if (udc->vbus_active) {
3355 udc->vbus_active = 0;
3356 udc->devstate = USB_STATE_NOTATTACHED;
3357 udc->linux_suspended = 1;
3358
3359 if (udc->usb_suspended) {
3360 udc->usb_suspended = 0;
3361 _nbu2ss_reset_controller(udc);
3362 }
3363
3364 _nbu2ss_quiesce(udc);
3365 }
3366 _nbu2ss_disable_controller(udc);
3367
3368 return 0;
3369}
3370
3371/*-------------------------------------------------------------------------*/
3372static int nbu2ss_drv_resume(struct platform_device *pdev)
3373{
3374 u32 data;
3375 struct nbu2ss_udc *udc;
3376
3377 udc = platform_get_drvdata(pdev);
Ravi Teja Darbha706eb8c2015-09-04 13:48:22 +05303378 if (!udc)
Magnus Damm33aa8d42014-06-06 19:44:17 +09003379 return 0;
3380
3381 data = gpio_get_value(VBUS_VALUE);
3382 if (data) {
3383 udc->vbus_active = 1;
3384 udc->devstate = USB_STATE_POWERED;
3385 _nbu2ss_enable_controller(udc);
3386 _nbu2ss_pullup(udc, 1);
3387 }
3388
3389 udc->linux_suspended = 0;
3390
3391 return 0;
3392}
3393
Magnus Damm33aa8d42014-06-06 19:44:17 +09003394static struct platform_driver udc_driver = {
3395 .probe = nbu2ss_drv_probe,
3396 .shutdown = nbu2ss_drv_shutdown,
3397 .remove = __exit_p(nbu2ss_drv_remove),
3398 .suspend = nbu2ss_drv_suspend,
3399 .resume = nbu2ss_drv_resume,
3400 .driver = {
Magnus Damm33aa8d42014-06-06 19:44:17 +09003401 .name = driver_name,
3402 },
3403};
3404
Sachin Kamat464cad22014-06-23 11:55:32 +05303405module_platform_driver(udc_driver);
Magnus Damm33aa8d42014-06-06 19:44:17 +09003406
3407MODULE_DESCRIPTION(DRIVER_DESC);
3408MODULE_AUTHOR("Renesas Electronics Corporation");
3409MODULE_LICENSE("GPL");
3410