blob: 6fca9104baf4952b8a4ac6969a1531c47b4e0941 [file] [log] [blame]
David Lopoaa69a802008-11-17 14:14:51 -08001/*
2 * ci13xxx_udc.c - MIPS USB IP core family device controller
3 *
4 * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
5 *
6 * Author: David Lopo
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13/*
14 * Description: MIPS USB IP core family device controller
15 * Currently it only supports IP part number CI13412
16 *
17 * This driver is composed of several blocks:
18 * - HW: hardware interface
19 * - DBG: debug facilities (optional)
20 * - UTIL: utilities
21 * - ISR: interrupts handling
22 * - ENDPT: endpoint operations (Gadget API)
23 * - GADGET: gadget operations (Gadget API)
24 * - BUS: bus glue code, bus abstraction layer
David Lopoaa69a802008-11-17 14:14:51 -080025 *
26 * Compile Options
27 * - CONFIG_USB_GADGET_DEBUG_FILES: enable debug facilities
28 * - STALL_IN: non-empty bulk-in pipes cannot be halted
29 * if defined mass storage compliance succeeds but with warnings
30 * => case 4: Hi > Dn
31 * => case 5: Hi > Di
32 * => case 8: Hi <> Do
33 * if undefined usbtest 13 fails
34 * - TRACE: enable function tracing (depends on DEBUG)
35 *
36 * Main Features
37 * - Chapter 9 & Mass Storage Compliance with Gadget File Storage
38 * - Chapter 9 Compliance with Gadget Zero (STALL_IN undefined)
39 * - Normal & LPM support
40 *
41 * USBTEST Report
42 * - OK: 0-12, 13 (STALL_IN defined) & 14
43 * - Not Supported: 15 & 16 (ISO)
44 *
45 * TODO List
46 * - OTG
47 * - Isochronous & Interrupt Traffic
48 * - Handle requests which spawns into several TDs
49 * - GET_STATUS(device) - always reports 0
50 * - Gadget API (majority of optional features)
David Lopoaa69a802008-11-17 14:14:51 -080051 */
Matthias Kaehlcke36825a22009-04-15 22:28:36 +020052#include <linux/delay.h>
David Lopoaa69a802008-11-17 14:14:51 -080053#include <linux/device.h>
54#include <linux/dmapool.h>
55#include <linux/dma-mapping.h>
56#include <linux/init.h>
Vijayavardhan Vennapusa397a4532012-07-20 13:18:32 +053057#include <linux/ratelimit.h>
David Lopoaa69a802008-11-17 14:14:51 -080058#include <linux/interrupt.h>
David Lopoaa69a802008-11-17 14:14:51 -080059#include <linux/io.h>
60#include <linux/irq.h>
61#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090062#include <linux/slab.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070063#include <linux/module.h>
Pavankumar Kondetic0360192010-12-07 17:54:04 +053064#include <linux/pm_runtime.h>
David Lopoaa69a802008-11-17 14:14:51 -080065#include <linux/usb/ch9.h>
66#include <linux/usb/gadget.h>
Pavankumar Kondetif01ef572010-12-07 17:54:02 +053067#include <linux/usb/otg.h>
Ido Shayevitzd1cb16c2012-03-28 18:57:47 +020068#include <linux/usb/msm_hsusb.h>
Rajkumar Raghupathyc01decf2013-03-29 17:39:58 +053069#include <linux/tracepoint.h>
70#include <mach/usb_trace.h>
David Lopoaa69a802008-11-17 14:14:51 -080071#include "ci13xxx_udc.h"
72
Pavankumar Kondetic46fdc32012-12-21 18:07:40 +053073/* Turns on streaming. overrides CI13XXX_DISABLE_STREAMING */
74static unsigned int streaming;
75module_param(streaming, uint, S_IRUGO | S_IWUSR);
David Lopoaa69a802008-11-17 14:14:51 -080076
77/******************************************************************************
78 * DEFINE
79 *****************************************************************************/
Michael Grzeschik954aad82011-10-10 18:38:06 +020080
81#define DMA_ADDR_INVALID (~(dma_addr_t)0)
Mayank Ranabdcbfe52012-08-16 14:00:40 +053082#define USB_MAX_TIMEOUT 100 /* 100msec timeout */
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +053083#define EP_PRIME_CHECK_DELAY (jiffies + msecs_to_jiffies(1000))
84#define MAX_PRIME_CHECK_RETRY 3 /*Wait for 3sec for EP prime failure */
Michael Grzeschik954aad82011-10-10 18:38:06 +020085
David Lopoaa69a802008-11-17 14:14:51 -080086/* ctrl register bank access */
87static DEFINE_SPINLOCK(udc_lock);
88
David Lopoaa69a802008-11-17 14:14:51 -080089/* control endpoint description */
90static const struct usb_endpoint_descriptor
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +053091ctrl_endpt_out_desc = {
David Lopoaa69a802008-11-17 14:14:51 -080092 .bLength = USB_DT_ENDPOINT_SIZE,
93 .bDescriptorType = USB_DT_ENDPOINT,
94
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +053095 .bEndpointAddress = USB_DIR_OUT,
96 .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
97 .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
98};
99
100static const struct usb_endpoint_descriptor
101ctrl_endpt_in_desc = {
102 .bLength = USB_DT_ENDPOINT_SIZE,
103 .bDescriptorType = USB_DT_ENDPOINT,
104
105 .bEndpointAddress = USB_DIR_IN,
David Lopoaa69a802008-11-17 14:14:51 -0800106 .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
107 .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
108};
109
110/* UDC descriptor */
111static struct ci13xxx *_udc;
112
113/* Interrupt statistics */
114#define ISR_MASK 0x1F
115static struct {
116 u32 test;
117 u32 ui;
118 u32 uei;
119 u32 pci;
120 u32 uri;
121 u32 sli;
122 u32 none;
123 struct {
124 u32 cnt;
125 u32 buf[ISR_MASK+1];
126 u32 idx;
127 } hndl;
128} isr_statistics;
129
130/**
131 * ffs_nr: find first (least significant) bit set
132 * @x: the word to search
133 *
134 * This function returns bit number (instead of position)
135 */
136static int ffs_nr(u32 x)
137{
138 int n = ffs(x);
139
140 return n ? n-1 : 32;
141}
142
Rajkumar Raghupathyc01decf2013-03-29 17:39:58 +0530143struct ci13xxx_ebi_err_entry {
144 u32 *usb_req_buf;
145 u32 usb_req_length;
146 u32 ep_info;
147 struct ci13xxx_ebi_err_entry *next;
148};
149
150struct ci13xxx_ebi_err_data {
151 u32 ebi_err_addr;
152 u32 apkt0;
153 u32 apkt1;
154 struct ci13xxx_ebi_err_entry *ebi_err_entry;
155};
156static struct ci13xxx_ebi_err_data *ebi_err_data;
157
David Lopoaa69a802008-11-17 14:14:51 -0800158/******************************************************************************
159 * HW block
160 *****************************************************************************/
161/* register bank descriptor */
162static struct {
163 unsigned lpm; /* is LPM? */
164 void __iomem *abs; /* bus map offset */
165 void __iomem *cap; /* bus map offset + CAP offset + CAP data */
166 size_t size; /* bank size */
167} hw_bank;
168
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530169/* MSM specific */
170#define ABS_AHBBURST (0x0090UL)
171#define ABS_AHBMODE (0x0098UL)
David Lopoaa69a802008-11-17 14:14:51 -0800172/* UDC register map */
173#define ABS_CAPLENGTH (0x100UL)
174#define ABS_HCCPARAMS (0x108UL)
175#define ABS_DCCPARAMS (0x124UL)
176#define ABS_TESTMODE (hw_bank.lpm ? 0x0FCUL : 0x138UL)
177/* offset to CAPLENTGH (addr + data) */
178#define CAP_USBCMD (0x000UL)
179#define CAP_USBSTS (0x004UL)
180#define CAP_USBINTR (0x008UL)
181#define CAP_DEVICEADDR (0x014UL)
182#define CAP_ENDPTLISTADDR (0x018UL)
183#define CAP_PORTSC (0x044UL)
David Lopof23e6492009-04-16 14:35:24 -0700184#define CAP_DEVLC (0x084UL)
Ofir Cohena1c2a872011-12-14 10:26:34 +0200185#define CAP_ENDPTPIPEID (0x0BCUL)
David Lopoaa69a802008-11-17 14:14:51 -0800186#define CAP_USBMODE (hw_bank.lpm ? 0x0C8UL : 0x068UL)
187#define CAP_ENDPTSETUPSTAT (hw_bank.lpm ? 0x0D8UL : 0x06CUL)
188#define CAP_ENDPTPRIME (hw_bank.lpm ? 0x0DCUL : 0x070UL)
189#define CAP_ENDPTFLUSH (hw_bank.lpm ? 0x0E0UL : 0x074UL)
190#define CAP_ENDPTSTAT (hw_bank.lpm ? 0x0E4UL : 0x078UL)
191#define CAP_ENDPTCOMPLETE (hw_bank.lpm ? 0x0E8UL : 0x07CUL)
192#define CAP_ENDPTCTRL (hw_bank.lpm ? 0x0ECUL : 0x080UL)
193#define CAP_LAST (hw_bank.lpm ? 0x12CUL : 0x0C0UL)
194
Amit Blayfd075dd2012-06-26 13:12:50 +0300195#define REMOTE_WAKEUP_DELAY msecs_to_jiffies(200)
196
David Lopoaa69a802008-11-17 14:14:51 -0800197/* maximum number of enpoints: valid only after hw_device_reset() */
198static unsigned hw_ep_max;
Mayank Ranabdcbfe52012-08-16 14:00:40 +0530199static void dbg_usb_op_fail(u8 addr, const char *name,
200 const struct ci13xxx_ep *mep);
David Lopoaa69a802008-11-17 14:14:51 -0800201/**
202 * hw_ep_bit: calculates the bit number
203 * @num: endpoint number
204 * @dir: endpoint direction
205 *
206 * This function returns bit number
207 */
208static inline int hw_ep_bit(int num, int dir)
209{
210 return num + (dir ? 16 : 0);
211}
212
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200213static int ep_to_bit(int n)
214{
215 int fill = 16 - hw_ep_max / 2;
216
217 if (n >= hw_ep_max / 2)
218 n += fill;
219
220 return n;
221}
222
David Lopoaa69a802008-11-17 14:14:51 -0800223/**
224 * hw_aread: reads from register bitfield
225 * @addr: address relative to bus map
226 * @mask: bitfield mask
227 *
228 * This function returns register bitfield data
229 */
230static u32 hw_aread(u32 addr, u32 mask)
231{
232 return ioread32(addr + hw_bank.abs) & mask;
233}
234
235/**
236 * hw_awrite: writes to register bitfield
237 * @addr: address relative to bus map
238 * @mask: bitfield mask
239 * @data: new data
240 */
241static void hw_awrite(u32 addr, u32 mask, u32 data)
242{
243 iowrite32(hw_aread(addr, ~mask) | (data & mask),
244 addr + hw_bank.abs);
245}
246
247/**
248 * hw_cread: reads from register bitfield
249 * @addr: address relative to CAP offset plus content
250 * @mask: bitfield mask
251 *
252 * This function returns register bitfield data
253 */
254static u32 hw_cread(u32 addr, u32 mask)
255{
256 return ioread32(addr + hw_bank.cap) & mask;
257}
258
259/**
260 * hw_cwrite: writes to register bitfield
261 * @addr: address relative to CAP offset plus content
262 * @mask: bitfield mask
263 * @data: new data
264 */
265static void hw_cwrite(u32 addr, u32 mask, u32 data)
266{
267 iowrite32(hw_cread(addr, ~mask) | (data & mask),
268 addr + hw_bank.cap);
269}
270
271/**
272 * hw_ctest_and_clear: tests & clears register bitfield
273 * @addr: address relative to CAP offset plus content
274 * @mask: bitfield mask
275 *
276 * This function returns register bitfield data
277 */
278static u32 hw_ctest_and_clear(u32 addr, u32 mask)
279{
280 u32 reg = hw_cread(addr, mask);
281
282 iowrite32(reg, addr + hw_bank.cap);
283 return reg;
284}
285
286/**
287 * hw_ctest_and_write: tests & writes register bitfield
288 * @addr: address relative to CAP offset plus content
289 * @mask: bitfield mask
290 * @data: new data
291 *
292 * This function returns register bitfield data
293 */
294static u32 hw_ctest_and_write(u32 addr, u32 mask, u32 data)
295{
296 u32 reg = hw_cread(addr, ~0);
297
298 iowrite32((reg & ~mask) | (data & mask), addr + hw_bank.cap);
299 return (reg & mask) >> ffs_nr(mask);
300}
301
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530302static int hw_device_init(void __iomem *base)
David Lopoaa69a802008-11-17 14:14:51 -0800303{
304 u32 reg;
305
306 /* bank is a module variable */
307 hw_bank.abs = base;
308
309 hw_bank.cap = hw_bank.abs;
310 hw_bank.cap += ABS_CAPLENGTH;
311 hw_bank.cap += ioread8(hw_bank.cap);
312
313 reg = hw_aread(ABS_HCCPARAMS, HCCPARAMS_LEN) >> ffs_nr(HCCPARAMS_LEN);
314 hw_bank.lpm = reg;
315 hw_bank.size = hw_bank.cap - hw_bank.abs;
316 hw_bank.size += CAP_LAST;
317 hw_bank.size /= sizeof(u32);
318
David Lopoaa69a802008-11-17 14:14:51 -0800319 reg = hw_aread(ABS_DCCPARAMS, DCCPARAMS_DEN) >> ffs_nr(DCCPARAMS_DEN);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530320 hw_ep_max = reg * 2; /* cache hw ENDPT_MAX */
David Lopoaa69a802008-11-17 14:14:51 -0800321
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530322 if (hw_ep_max == 0 || hw_ep_max > ENDPT_MAX)
323 return -ENODEV;
David Lopoaa69a802008-11-17 14:14:51 -0800324
325 /* setup lock mode ? */
326
327 /* ENDPTSETUPSTAT is '0' by default */
328
329 /* HCSPARAMS.bf.ppc SHOULD BE zero for device */
330
331 return 0;
332}
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530333/**
334 * hw_device_reset: resets chip (execute without interruption)
335 * @base: register base address
336 *
337 * This function returns an error code
338 */
339static int hw_device_reset(struct ci13xxx *udc)
340{
341 /* should flush & stop before reset */
342 hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0);
343 hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
344
345 hw_cwrite(CAP_USBCMD, USBCMD_RST, USBCMD_RST);
346 while (hw_cread(CAP_USBCMD, USBCMD_RST))
347 udelay(10); /* not RTOS friendly */
348
349
350 if (udc->udc_driver->notify_event)
351 udc->udc_driver->notify_event(udc,
352 CI13XXX_CONTROLLER_RESET_EVENT);
353
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530354 /* USBMODE should be configured step by step */
355 hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
356 hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE);
357 hw_cwrite(CAP_USBMODE, USBMODE_SLOM, USBMODE_SLOM); /* HW >= 2.3 */
358
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700359 /*
360 * ITC (Interrupt Threshold Control) field is to set the maximum
361 * rate at which the device controller will issue interrupts.
362 * The maximum interrupt interval measured in micro frames.
363 * Valid values are 0, 1, 2, 4, 8, 16, 32, 64. The default value is
364 * 8 micro frames. If CPU can handle interrupts at faster rate, ITC
365 * can be set to lesser value to gain performance.
366 */
367 if (udc->udc_driver->flags & CI13XXX_ZERO_ITC)
368 hw_cwrite(CAP_USBCMD, USBCMD_ITC_MASK, USBCMD_ITC(0));
369
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530370 if (hw_cread(CAP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
371 pr_err("cannot enter in device mode");
372 pr_err("lpm = %i", hw_bank.lpm);
373 return -ENODEV;
374 }
375
376 return 0;
377}
David Lopoaa69a802008-11-17 14:14:51 -0800378
379/**
380 * hw_device_state: enables/disables interrupts & starts/stops device (execute
381 * without interruption)
382 * @dma: 0 => disable, !0 => enable and set dma engine
383 *
384 * This function returns an error code
385 */
386static int hw_device_state(u32 dma)
387{
Pavankumar Kondetic46fdc32012-12-21 18:07:40 +0530388 struct ci13xxx *udc = _udc;
389
David Lopoaa69a802008-11-17 14:14:51 -0800390 if (dma) {
Pavankumar Kondetic46fdc32012-12-21 18:07:40 +0530391 if (streaming || !(udc->udc_driver->flags &
392 CI13XXX_DISABLE_STREAMING))
393 hw_cwrite(CAP_USBMODE, USBMODE_SDIS, 0);
394 else
395 hw_cwrite(CAP_USBMODE, USBMODE_SDIS, USBMODE_SDIS);
396
David Lopoaa69a802008-11-17 14:14:51 -0800397 hw_cwrite(CAP_ENDPTLISTADDR, ~0, dma);
Vamsi Krishna1a1684b2013-03-02 16:14:52 -0800398
399 if (udc->udc_driver->notify_event)
400 udc->udc_driver->notify_event(udc,
401 CI13XXX_CONTROLLER_CONNECT_EVENT);
402
David Lopoaa69a802008-11-17 14:14:51 -0800403 /* interrupt, error, port change, reset, sleep/suspend */
404 hw_cwrite(CAP_USBINTR, ~0,
405 USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
406 hw_cwrite(CAP_USBCMD, USBCMD_RS, USBCMD_RS);
407 } else {
408 hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
409 hw_cwrite(CAP_USBINTR, ~0, 0);
410 }
411 return 0;
412}
413
Mayank Ranabdcbfe52012-08-16 14:00:40 +0530414static void debug_ept_flush_info(int ep_num, int dir)
415{
416 struct ci13xxx *udc = _udc;
417 struct ci13xxx_ep *mep;
418
419 if (dir)
420 mep = &udc->ci13xxx_ep[ep_num + hw_ep_max/2];
421 else
422 mep = &udc->ci13xxx_ep[ep_num];
423
424 pr_err_ratelimited("USB Registers\n");
425 pr_err_ratelimited("USBCMD:%x\n", hw_cread(CAP_USBCMD, ~0));
426 pr_err_ratelimited("USBSTS:%x\n", hw_cread(CAP_USBSTS, ~0));
427 pr_err_ratelimited("ENDPTLISTADDR:%x\n",
428 hw_cread(CAP_ENDPTLISTADDR, ~0));
429 pr_err_ratelimited("PORTSC:%x\n", hw_cread(CAP_PORTSC, ~0));
430 pr_err_ratelimited("USBMODE:%x\n", hw_cread(CAP_USBMODE, ~0));
431 pr_err_ratelimited("ENDPTSTAT:%x\n", hw_cread(CAP_ENDPTSTAT, ~0));
432
433 dbg_usb_op_fail(0xFF, "FLUSHF", mep);
434}
David Lopoaa69a802008-11-17 14:14:51 -0800435/**
436 * hw_ep_flush: flush endpoint fifo (execute without interruption)
437 * @num: endpoint number
438 * @dir: endpoint direction
439 *
440 * This function returns an error code
441 */
442static int hw_ep_flush(int num, int dir)
443{
Mayank Ranabdcbfe52012-08-16 14:00:40 +0530444 ktime_t start, diff;
David Lopoaa69a802008-11-17 14:14:51 -0800445 int n = hw_ep_bit(num, dir);
Pavankumar Kondeti58db2c12013-01-28 11:15:18 +0530446 struct ci13xxx_ep *mEp = &_udc->ci13xxx_ep[n];
447
Pavankumar Kondeti2a630fb2013-01-28 12:31:15 +0530448 if (_udc->skip_flush || list_empty(&mEp->qh.queue))
Pavankumar Kondeti58db2c12013-01-28 11:15:18 +0530449 return 0;
David Lopoaa69a802008-11-17 14:14:51 -0800450
Mayank Ranabdcbfe52012-08-16 14:00:40 +0530451 start = ktime_get();
David Lopoaa69a802008-11-17 14:14:51 -0800452 do {
453 /* flush any pending transfer */
454 hw_cwrite(CAP_ENDPTFLUSH, BIT(n), BIT(n));
Mayank Ranabdcbfe52012-08-16 14:00:40 +0530455 while (hw_cread(CAP_ENDPTFLUSH, BIT(n))) {
David Lopoaa69a802008-11-17 14:14:51 -0800456 cpu_relax();
Mayank Ranabdcbfe52012-08-16 14:00:40 +0530457 diff = ktime_sub(ktime_get(), start);
458 if (ktime_to_ms(diff) > USB_MAX_TIMEOUT) {
459 printk_ratelimited(KERN_ERR
460 "%s: Failed to flush ep#%d %s\n",
461 __func__, num,
462 dir ? "IN" : "OUT");
463 debug_ept_flush_info(num, dir);
Pavankumar Kondeti2a630fb2013-01-28 12:31:15 +0530464 _udc->skip_flush = true;
Mayank Ranabdcbfe52012-08-16 14:00:40 +0530465 return 0;
466 }
467 }
David Lopoaa69a802008-11-17 14:14:51 -0800468 } while (hw_cread(CAP_ENDPTSTAT, BIT(n)));
469
470 return 0;
471}
472
473/**
474 * hw_ep_disable: disables endpoint (execute without interruption)
475 * @num: endpoint number
476 * @dir: endpoint direction
477 *
478 * This function returns an error code
479 */
480static int hw_ep_disable(int num, int dir)
481{
David Lopoaa69a802008-11-17 14:14:51 -0800482 hw_cwrite(CAP_ENDPTCTRL + num * sizeof(u32),
483 dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0);
484 return 0;
485}
486
487/**
488 * hw_ep_enable: enables endpoint (execute without interruption)
489 * @num: endpoint number
490 * @dir: endpoint direction
491 * @type: endpoint type
492 *
493 * This function returns an error code
494 */
495static int hw_ep_enable(int num, int dir, int type)
496{
497 u32 mask, data;
498
499 if (dir) {
500 mask = ENDPTCTRL_TXT; /* type */
501 data = type << ffs_nr(mask);
502
503 mask |= ENDPTCTRL_TXS; /* unstall */
504 mask |= ENDPTCTRL_TXR; /* reset data toggle */
505 data |= ENDPTCTRL_TXR;
506 mask |= ENDPTCTRL_TXE; /* enable */
507 data |= ENDPTCTRL_TXE;
508 } else {
509 mask = ENDPTCTRL_RXT; /* type */
510 data = type << ffs_nr(mask);
511
512 mask |= ENDPTCTRL_RXS; /* unstall */
513 mask |= ENDPTCTRL_RXR; /* reset data toggle */
514 data |= ENDPTCTRL_RXR;
515 mask |= ENDPTCTRL_RXE; /* enable */
516 data |= ENDPTCTRL_RXE;
517 }
518 hw_cwrite(CAP_ENDPTCTRL + num * sizeof(u32), mask, data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700519
520 /* make sure endpoint is enabled before returning */
521 mb();
522
David Lopoaa69a802008-11-17 14:14:51 -0800523 return 0;
524}
525
526/**
527 * hw_ep_get_halt: return endpoint halt status
528 * @num: endpoint number
529 * @dir: endpoint direction
530 *
531 * This function returns 1 if endpoint halted
532 */
533static int hw_ep_get_halt(int num, int dir)
534{
535 u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
536
537 return hw_cread(CAP_ENDPTCTRL + num * sizeof(u32), mask) ? 1 : 0;
538}
539
540/**
David Lopoaa69a802008-11-17 14:14:51 -0800541 * hw_test_and_clear_setup_status: test & clear setup status (execute without
542 * interruption)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200543 * @n: endpoint number
David Lopoaa69a802008-11-17 14:14:51 -0800544 *
545 * This function returns setup status
546 */
547static int hw_test_and_clear_setup_status(int n)
548{
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200549 n = ep_to_bit(n);
David Lopoaa69a802008-11-17 14:14:51 -0800550 return hw_ctest_and_clear(CAP_ENDPTSETUPSTAT, BIT(n));
551}
552
553/**
554 * hw_ep_prime: primes endpoint (execute without interruption)
555 * @num: endpoint number
556 * @dir: endpoint direction
557 * @is_ctrl: true if control endpoint
558 *
559 * This function returns an error code
560 */
561static int hw_ep_prime(int num, int dir, int is_ctrl)
562{
563 int n = hw_ep_bit(num, dir);
564
David Lopoaa69a802008-11-17 14:14:51 -0800565 if (is_ctrl && dir == RX && hw_cread(CAP_ENDPTSETUPSTAT, BIT(num)))
566 return -EAGAIN;
567
568 hw_cwrite(CAP_ENDPTPRIME, BIT(n), BIT(n));
569
David Lopoaa69a802008-11-17 14:14:51 -0800570 if (is_ctrl && dir == RX && hw_cread(CAP_ENDPTSETUPSTAT, BIT(num)))
571 return -EAGAIN;
572
573 /* status shoult be tested according with manual but it doesn't work */
574 return 0;
575}
576
577/**
578 * hw_ep_set_halt: configures ep halt & resets data toggle after clear (execute
579 * without interruption)
580 * @num: endpoint number
581 * @dir: endpoint direction
582 * @value: true => stall, false => unstall
583 *
584 * This function returns an error code
585 */
586static int hw_ep_set_halt(int num, int dir, int value)
587{
Pavankumar Kondeti05598942011-07-06 16:58:44 +0530588 u32 addr, mask_xs, mask_xr;
589
David Lopoaa69a802008-11-17 14:14:51 -0800590 if (value != 0 && value != 1)
591 return -EINVAL;
592
593 do {
Pavankumar Kondeti05598942011-07-06 16:58:44 +0530594 if (hw_cread(CAP_ENDPTSETUPSTAT, BIT(num)))
595 return 0;
596
597 addr = CAP_ENDPTCTRL + num * sizeof(u32);
598 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
599 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR;
David Lopoaa69a802008-11-17 14:14:51 -0800600
601 /* data toggle - reserved for EP0 but it's in ESS */
602 hw_cwrite(addr, mask_xs|mask_xr, value ? mask_xs : mask_xr);
603
604 } while (value != hw_ep_get_halt(num, dir));
605
606 return 0;
607}
608
609/**
610 * hw_intr_clear: disables interrupt & clears interrupt status (execute without
611 * interruption)
612 * @n: interrupt bit
613 *
614 * This function returns an error code
615 */
616static int hw_intr_clear(int n)
617{
618 if (n >= REG_BITS)
619 return -EINVAL;
620
621 hw_cwrite(CAP_USBINTR, BIT(n), 0);
622 hw_cwrite(CAP_USBSTS, BIT(n), BIT(n));
623 return 0;
624}
625
626/**
627 * hw_intr_force: enables interrupt & forces interrupt status (execute without
628 * interruption)
629 * @n: interrupt bit
630 *
631 * This function returns an error code
632 */
633static int hw_intr_force(int n)
634{
635 if (n >= REG_BITS)
636 return -EINVAL;
637
638 hw_awrite(ABS_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
639 hw_cwrite(CAP_USBINTR, BIT(n), BIT(n));
640 hw_cwrite(CAP_USBSTS, BIT(n), BIT(n));
641 hw_awrite(ABS_TESTMODE, TESTMODE_FORCE, 0);
642 return 0;
643}
644
645/**
646 * hw_is_port_high_speed: test if port is high speed
647 *
648 * This function returns true if high speed port
649 */
650static int hw_port_is_high_speed(void)
651{
652 return hw_bank.lpm ? hw_cread(CAP_DEVLC, DEVLC_PSPD) :
653 hw_cread(CAP_PORTSC, PORTSC_HSP);
654}
655
656/**
657 * hw_port_test_get: reads port test mode value
658 *
659 * This function returns port test mode value
660 */
661static u8 hw_port_test_get(void)
662{
663 return hw_cread(CAP_PORTSC, PORTSC_PTC) >> ffs_nr(PORTSC_PTC);
664}
665
666/**
667 * hw_port_test_set: writes port test mode (execute without interruption)
668 * @mode: new value
669 *
670 * This function returns an error code
671 */
672static int hw_port_test_set(u8 mode)
673{
674 const u8 TEST_MODE_MAX = 7;
675
676 if (mode > TEST_MODE_MAX)
677 return -EINVAL;
678
679 hw_cwrite(CAP_PORTSC, PORTSC_PTC, mode << ffs_nr(PORTSC_PTC));
680 return 0;
681}
682
683/**
684 * hw_read_intr_enable: returns interrupt enable register
685 *
686 * This function returns register data
687 */
688static u32 hw_read_intr_enable(void)
689{
690 return hw_cread(CAP_USBINTR, ~0);
691}
692
693/**
694 * hw_read_intr_status: returns interrupt status register
695 *
696 * This function returns register data
697 */
698static u32 hw_read_intr_status(void)
699{
700 return hw_cread(CAP_USBSTS, ~0);
701}
702
703/**
704 * hw_register_read: reads all device registers (execute without interruption)
705 * @buf: destination buffer
706 * @size: buffer size
707 *
708 * This function returns number of registers read
709 */
710static size_t hw_register_read(u32 *buf, size_t size)
711{
712 unsigned i;
713
714 if (size > hw_bank.size)
715 size = hw_bank.size;
716
717 for (i = 0; i < size; i++)
718 buf[i] = hw_aread(i * sizeof(u32), ~0);
719
720 return size;
721}
722
723/**
724 * hw_register_write: writes to register
725 * @addr: register address
726 * @data: register value
727 *
728 * This function returns an error code
729 */
730static int hw_register_write(u16 addr, u32 data)
731{
732 /* align */
733 addr /= sizeof(u32);
734
735 if (addr >= hw_bank.size)
736 return -EINVAL;
737
738 /* align */
739 addr *= sizeof(u32);
740
741 hw_awrite(addr, ~0, data);
742 return 0;
743}
744
745/**
746 * hw_test_and_clear_complete: test & clear complete status (execute without
747 * interruption)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200748 * @n: endpoint number
David Lopoaa69a802008-11-17 14:14:51 -0800749 *
750 * This function returns complete status
751 */
752static int hw_test_and_clear_complete(int n)
753{
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200754 n = ep_to_bit(n);
David Lopoaa69a802008-11-17 14:14:51 -0800755 return hw_ctest_and_clear(CAP_ENDPTCOMPLETE, BIT(n));
756}
757
758/**
759 * hw_test_and_clear_intr_active: test & clear active interrupts (execute
760 * without interruption)
761 *
762 * This function returns active interrutps
763 */
764static u32 hw_test_and_clear_intr_active(void)
765{
766 u32 reg = hw_read_intr_status() & hw_read_intr_enable();
767
768 hw_cwrite(CAP_USBSTS, ~0, reg);
769 return reg;
770}
771
772/**
773 * hw_test_and_clear_setup_guard: test & clear setup guard (execute without
774 * interruption)
775 *
776 * This function returns guard value
777 */
778static int hw_test_and_clear_setup_guard(void)
779{
780 return hw_ctest_and_write(CAP_USBCMD, USBCMD_SUTW, 0);
781}
782
783/**
784 * hw_test_and_set_setup_guard: test & set setup guard (execute without
785 * interruption)
786 *
787 * This function returns guard value
788 */
789static int hw_test_and_set_setup_guard(void)
790{
791 return hw_ctest_and_write(CAP_USBCMD, USBCMD_SUTW, USBCMD_SUTW);
792}
793
794/**
795 * hw_usb_set_address: configures USB address (execute without interruption)
796 * @value: new USB address
797 *
798 * This function returns an error code
799 */
800static int hw_usb_set_address(u8 value)
801{
802 /* advance */
803 hw_cwrite(CAP_DEVICEADDR, DEVICEADDR_USBADR | DEVICEADDR_USBADRA,
804 value << ffs_nr(DEVICEADDR_USBADR) | DEVICEADDR_USBADRA);
805 return 0;
806}
807
808/**
809 * hw_usb_reset: restart device after a bus reset (execute without
810 * interruption)
811 *
812 * This function returns an error code
813 */
814static int hw_usb_reset(void)
815{
816 hw_usb_set_address(0);
817
818 /* ESS flushes only at end?!? */
819 hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0); /* flush all EPs */
820
821 /* clear setup token semaphores */
822 hw_cwrite(CAP_ENDPTSETUPSTAT, 0, 0); /* writes its content */
823
824 /* clear complete status */
825 hw_cwrite(CAP_ENDPTCOMPLETE, 0, 0); /* writes its content */
826
827 /* wait until all bits cleared */
828 while (hw_cread(CAP_ENDPTPRIME, ~0))
829 udelay(10); /* not RTOS friendly */
830
831 /* reset all endpoints ? */
832
833 /* reset internal status and wait for further instructions
834 no need to verify the port reset status (ESS does it) */
835
836 return 0;
837}
838
839/******************************************************************************
840 * DBG block
841 *****************************************************************************/
842/**
843 * show_device: prints information about device capabilities and status
844 *
845 * Check "device.h" for details
846 */
847static ssize_t show_device(struct device *dev, struct device_attribute *attr,
848 char *buf)
849{
850 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
851 struct usb_gadget *gadget = &udc->gadget;
852 int n = 0;
853
854 dbg_trace("[%s] %p\n", __func__, buf);
855 if (attr == NULL || buf == NULL) {
856 dev_err(dev, "[%s] EINVAL\n", __func__);
857 return 0;
858 }
859
860 n += scnprintf(buf + n, PAGE_SIZE - n, "speed = %d\n",
861 gadget->speed);
Michal Nazarewiczd327ab52011-11-19 18:27:37 +0100862 n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed = %d\n",
863 gadget->max_speed);
864 /* TODO: Scheduled for removal in 3.8. */
David Lopoaa69a802008-11-17 14:14:51 -0800865 n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed = %d\n",
Michal Nazarewiczd327ab52011-11-19 18:27:37 +0100866 gadget_is_dualspeed(gadget));
David Lopoaa69a802008-11-17 14:14:51 -0800867 n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg = %d\n",
868 gadget->is_otg);
869 n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral = %d\n",
870 gadget->is_a_peripheral);
871 n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable = %d\n",
872 gadget->b_hnp_enable);
873 n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support = %d\n",
874 gadget->a_hnp_support);
875 n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n",
876 gadget->a_alt_hnp_support);
877 n += scnprintf(buf + n, PAGE_SIZE - n, "name = %s\n",
878 (gadget->name ? gadget->name : ""));
879
880 return n;
881}
882static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
883
884/**
885 * show_driver: prints information about attached gadget (if any)
886 *
887 * Check "device.h" for details
888 */
889static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
890 char *buf)
891{
892 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
893 struct usb_gadget_driver *driver = udc->driver;
894 int n = 0;
895
896 dbg_trace("[%s] %p\n", __func__, buf);
897 if (attr == NULL || buf == NULL) {
898 dev_err(dev, "[%s] EINVAL\n", __func__);
899 return 0;
900 }
901
902 if (driver == NULL)
903 return scnprintf(buf, PAGE_SIZE,
904 "There is no gadget attached!\n");
905
906 n += scnprintf(buf + n, PAGE_SIZE - n, "function = %s\n",
907 (driver->function ? driver->function : ""));
908 n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n",
Michal Nazarewicz7177aed2011-11-19 18:27:38 +0100909 driver->max_speed);
David Lopoaa69a802008-11-17 14:14:51 -0800910
911 return n;
912}
913static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL);
914
915/* Maximum event message length */
916#define DBG_DATA_MSG 64UL
917
918/* Maximum event messages */
919#define DBG_DATA_MAX 128UL
920
921/* Event buffer descriptor */
922static struct {
923 char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */
924 unsigned idx; /* index */
925 unsigned tty; /* print to console? */
926 rwlock_t lck; /* lock */
927} dbg_data = {
928 .idx = 0,
929 .tty = 0,
930 .lck = __RW_LOCK_UNLOCKED(lck)
931};
932
933/**
934 * dbg_dec: decrements debug event index
935 * @idx: buffer index
936 */
937static void dbg_dec(unsigned *idx)
938{
939 *idx = (*idx - 1) & (DBG_DATA_MAX-1);
940}
941
942/**
943 * dbg_inc: increments debug event index
944 * @idx: buffer index
945 */
946static void dbg_inc(unsigned *idx)
947{
948 *idx = (*idx + 1) & (DBG_DATA_MAX-1);
949}
950
Vamsi Krishna8d1bbd52012-02-09 21:13:24 -0800951
952static unsigned int ep_addr_txdbg_mask;
953module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
954static unsigned int ep_addr_rxdbg_mask;
955module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
956
957static int allow_dbg_print(u8 addr)
958{
959 int dir, num;
960
961 /* allow bus wide events */
962 if (addr == 0xff)
963 return 1;
964
965 dir = addr & USB_ENDPOINT_DIR_MASK ? TX : RX;
966 num = addr & ~USB_ENDPOINT_DIR_MASK;
967 num = 1 << num;
968
969 if ((dir == TX) && (num & ep_addr_txdbg_mask))
970 return 1;
971 if ((dir == RX) && (num & ep_addr_rxdbg_mask))
972 return 1;
973
974 return 0;
975}
976
David Lopoaa69a802008-11-17 14:14:51 -0800977/**
978 * dbg_print: prints the common part of the event
979 * @addr: endpoint address
980 * @name: event name
981 * @status: status
982 * @extra: extra information
983 */
984static void dbg_print(u8 addr, const char *name, int status, const char *extra)
985{
986 struct timeval tval;
987 unsigned int stamp;
988 unsigned long flags;
989
Vamsi Krishna8d1bbd52012-02-09 21:13:24 -0800990 if (!allow_dbg_print(addr))
991 return;
992
David Lopoaa69a802008-11-17 14:14:51 -0800993 write_lock_irqsave(&dbg_data.lck, flags);
994
995 do_gettimeofday(&tval);
996 stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s */
997 stamp = stamp * 1000000 + tval.tv_usec;
998
999 scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001000 "%04X\t? %02X %-7.7s %4i ?\t%s\n",
David Lopoaa69a802008-11-17 14:14:51 -08001001 stamp, addr, name, status, extra);
1002
1003 dbg_inc(&dbg_data.idx);
1004
1005 write_unlock_irqrestore(&dbg_data.lck, flags);
1006
1007 if (dbg_data.tty != 0)
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001008 pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n",
David Lopoaa69a802008-11-17 14:14:51 -08001009 stamp, addr, name, status, extra);
1010}
1011
1012/**
1013 * dbg_done: prints a DONE event
1014 * @addr: endpoint address
1015 * @td: transfer descriptor
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301016 * @status: status
David Lopoaa69a802008-11-17 14:14:51 -08001017 */
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301018static void dbg_done(u8 addr, const u32 token, int status)
David Lopoaa69a802008-11-17 14:14:51 -08001019{
1020 char msg[DBG_DATA_MSG];
1021
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301022 scnprintf(msg, sizeof(msg), "%d %02X",
1023 (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES),
1024 (int)(token & TD_STATUS) >> ffs_nr(TD_STATUS));
1025 dbg_print(addr, "DONE", status, msg);
David Lopoaa69a802008-11-17 14:14:51 -08001026}
1027
1028/**
1029 * dbg_event: prints a generic event
1030 * @addr: endpoint address
1031 * @name: event name
1032 * @status: status
1033 */
1034static void dbg_event(u8 addr, const char *name, int status)
1035{
1036 if (name != NULL)
1037 dbg_print(addr, name, status, "");
1038}
1039
1040/*
1041 * dbg_queue: prints a QUEUE event
1042 * @addr: endpoint address
1043 * @req: USB request
1044 * @status: status
1045 */
1046static void dbg_queue(u8 addr, const struct usb_request *req, int status)
1047{
1048 char msg[DBG_DATA_MSG];
1049
1050 if (req != NULL) {
1051 scnprintf(msg, sizeof(msg),
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301052 "%d %d", !req->no_interrupt, req->length);
David Lopoaa69a802008-11-17 14:14:51 -08001053 dbg_print(addr, "QUEUE", status, msg);
1054 }
1055}
1056
1057/**
1058 * dbg_setup: prints a SETUP event
1059 * @addr: endpoint address
1060 * @req: setup request
1061 */
1062static void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
1063{
1064 char msg[DBG_DATA_MSG];
1065
1066 if (req != NULL) {
1067 scnprintf(msg, sizeof(msg),
1068 "%02X %02X %04X %04X %d", req->bRequestType,
1069 req->bRequest, le16_to_cpu(req->wValue),
1070 le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
1071 dbg_print(addr, "SETUP", 0, msg);
1072 }
1073}
1074
1075/**
Mayank Ranabdcbfe52012-08-16 14:00:40 +05301076 * dbg_usb_op_fail: prints USB Operation FAIL event
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301077 * @addr: endpoint address
1078 * @mEp: endpoint structure
1079 */
Mayank Ranabdcbfe52012-08-16 14:00:40 +05301080static void dbg_usb_op_fail(u8 addr, const char *name,
1081 const struct ci13xxx_ep *mep)
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301082{
1083 char msg[DBG_DATA_MSG];
1084 struct ci13xxx_req *req;
1085 struct list_head *ptr = NULL;
1086
Mayank Ranabdcbfe52012-08-16 14:00:40 +05301087 if (mep != NULL) {
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301088 scnprintf(msg, sizeof(msg),
Mayank Ranabdcbfe52012-08-16 14:00:40 +05301089 "%s Fail EP%d%s QH:%08X",
1090 name, mep->num,
1091 mep->dir ? "IN" : "OUT", mep->qh.ptr->cap);
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301092 dbg_print(addr, name, 0, msg);
1093 scnprintf(msg, sizeof(msg),
1094 "cap:%08X %08X %08X\n",
Mayank Ranabdcbfe52012-08-16 14:00:40 +05301095 mep->qh.ptr->curr, mep->qh.ptr->td.next,
1096 mep->qh.ptr->td.token);
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301097 dbg_print(addr, "QHEAD", 0, msg);
1098
Mayank Ranabdcbfe52012-08-16 14:00:40 +05301099 list_for_each(ptr, &mep->qh.queue) {
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301100 req = list_entry(ptr, struct ci13xxx_req, queue);
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301101 scnprintf(msg, sizeof(msg),
1102 "%08X:%08X:%08X\n",
1103 req->dma, req->ptr->next,
1104 req->ptr->token);
1105 dbg_print(addr, "REQ", 0, msg);
1106 scnprintf(msg, sizeof(msg), "%08X:%d\n",
1107 req->ptr->page[0],
1108 req->req.status);
1109 dbg_print(addr, "REQPAGE", 0, msg);
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301110 }
1111 }
1112}
1113
1114/**
David Lopoaa69a802008-11-17 14:14:51 -08001115 * show_events: displays the event buffer
1116 *
1117 * Check "device.h" for details
1118 */
1119static ssize_t show_events(struct device *dev, struct device_attribute *attr,
1120 char *buf)
1121{
1122 unsigned long flags;
1123 unsigned i, j, n = 0;
1124
1125 dbg_trace("[%s] %p\n", __func__, buf);
1126 if (attr == NULL || buf == NULL) {
1127 dev_err(dev, "[%s] EINVAL\n", __func__);
1128 return 0;
1129 }
1130
1131 read_lock_irqsave(&dbg_data.lck, flags);
1132
1133 i = dbg_data.idx;
1134 for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) {
1135 n += strlen(dbg_data.buf[i]);
1136 if (n >= PAGE_SIZE) {
1137 n -= strlen(dbg_data.buf[i]);
1138 break;
1139 }
1140 }
1141 for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i))
1142 j += scnprintf(buf + j, PAGE_SIZE - j,
1143 "%s", dbg_data.buf[i]);
1144
1145 read_unlock_irqrestore(&dbg_data.lck, flags);
1146
1147 return n;
1148}
1149
1150/**
1151 * store_events: configure if events are going to be also printed to console
1152 *
1153 * Check "device.h" for details
1154 */
1155static ssize_t store_events(struct device *dev, struct device_attribute *attr,
1156 const char *buf, size_t count)
1157{
1158 unsigned tty;
1159
1160 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1161 if (attr == NULL || buf == NULL) {
1162 dev_err(dev, "[%s] EINVAL\n", __func__);
1163 goto done;
1164 }
1165
1166 if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
1167 dev_err(dev, "<1|0>: enable|disable console log\n");
1168 goto done;
1169 }
1170
1171 dbg_data.tty = tty;
1172 dev_info(dev, "tty = %u", dbg_data.tty);
1173
1174 done:
1175 return count;
1176}
1177static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
1178
1179/**
1180 * show_inters: interrupt status, enable status and historic
1181 *
1182 * Check "device.h" for details
1183 */
1184static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
1185 char *buf)
1186{
1187 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1188 unsigned long flags;
1189 u32 intr;
1190 unsigned i, j, n = 0;
1191
1192 dbg_trace("[%s] %p\n", __func__, buf);
1193 if (attr == NULL || buf == NULL) {
1194 dev_err(dev, "[%s] EINVAL\n", __func__);
1195 return 0;
1196 }
1197
1198 spin_lock_irqsave(udc->lock, flags);
1199
1200 n += scnprintf(buf + n, PAGE_SIZE - n,
1201 "status = %08x\n", hw_read_intr_status());
1202 n += scnprintf(buf + n, PAGE_SIZE - n,
1203 "enable = %08x\n", hw_read_intr_enable());
1204
1205 n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
1206 isr_statistics.test);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001207 n += scnprintf(buf + n, PAGE_SIZE - n, "? ui = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001208 isr_statistics.ui);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001209 n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001210 isr_statistics.uei);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001211 n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001212 isr_statistics.pci);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001213 n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001214 isr_statistics.uri);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001215 n += scnprintf(buf + n, PAGE_SIZE - n, "? sli = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001216 isr_statistics.sli);
1217 n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n",
1218 isr_statistics.none);
1219 n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n",
1220 isr_statistics.hndl.cnt);
1221
1222 for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) {
1223 i &= ISR_MASK;
1224 intr = isr_statistics.hndl.buf[i];
1225
1226 if (USBi_UI & intr)
1227 n += scnprintf(buf + n, PAGE_SIZE - n, "ui ");
1228 intr &= ~USBi_UI;
1229 if (USBi_UEI & intr)
1230 n += scnprintf(buf + n, PAGE_SIZE - n, "uei ");
1231 intr &= ~USBi_UEI;
1232 if (USBi_PCI & intr)
1233 n += scnprintf(buf + n, PAGE_SIZE - n, "pci ");
1234 intr &= ~USBi_PCI;
1235 if (USBi_URI & intr)
1236 n += scnprintf(buf + n, PAGE_SIZE - n, "uri ");
1237 intr &= ~USBi_URI;
1238 if (USBi_SLI & intr)
1239 n += scnprintf(buf + n, PAGE_SIZE - n, "sli ");
1240 intr &= ~USBi_SLI;
1241 if (intr)
1242 n += scnprintf(buf + n, PAGE_SIZE - n, "??? ");
1243 if (isr_statistics.hndl.buf[i])
1244 n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
1245 }
1246
1247 spin_unlock_irqrestore(udc->lock, flags);
1248
1249 return n;
1250}
1251
1252/**
1253 * store_inters: enable & force or disable an individual interrutps
1254 * (to be used for test purposes only)
1255 *
1256 * Check "device.h" for details
1257 */
1258static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
1259 const char *buf, size_t count)
1260{
1261 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1262 unsigned long flags;
1263 unsigned en, bit;
1264
1265 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1266 if (attr == NULL || buf == NULL) {
1267 dev_err(dev, "[%s] EINVAL\n", __func__);
1268 goto done;
1269 }
1270
1271 if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
1272 dev_err(dev, "<1|0> <bit>: enable|disable interrupt");
1273 goto done;
1274 }
1275
1276 spin_lock_irqsave(udc->lock, flags);
1277 if (en) {
1278 if (hw_intr_force(bit))
1279 dev_err(dev, "invalid bit number\n");
1280 else
1281 isr_statistics.test++;
1282 } else {
1283 if (hw_intr_clear(bit))
1284 dev_err(dev, "invalid bit number\n");
1285 }
1286 spin_unlock_irqrestore(udc->lock, flags);
1287
1288 done:
1289 return count;
1290}
1291static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
1292
1293/**
1294 * show_port_test: reads port test mode
1295 *
1296 * Check "device.h" for details
1297 */
1298static ssize_t show_port_test(struct device *dev,
1299 struct device_attribute *attr, char *buf)
1300{
1301 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1302 unsigned long flags;
1303 unsigned mode;
1304
1305 dbg_trace("[%s] %p\n", __func__, buf);
1306 if (attr == NULL || buf == NULL) {
1307 dev_err(dev, "[%s] EINVAL\n", __func__);
1308 return 0;
1309 }
1310
1311 spin_lock_irqsave(udc->lock, flags);
1312 mode = hw_port_test_get();
1313 spin_unlock_irqrestore(udc->lock, flags);
1314
1315 return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
1316}
1317
1318/**
1319 * store_port_test: writes port test mode
1320 *
1321 * Check "device.h" for details
1322 */
1323static ssize_t store_port_test(struct device *dev,
1324 struct device_attribute *attr,
1325 const char *buf, size_t count)
1326{
1327 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1328 unsigned long flags;
1329 unsigned mode;
1330
1331 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1332 if (attr == NULL || buf == NULL) {
1333 dev_err(dev, "[%s] EINVAL\n", __func__);
1334 goto done;
1335 }
1336
1337 if (sscanf(buf, "%u", &mode) != 1) {
1338 dev_err(dev, "<mode>: set port test mode");
1339 goto done;
1340 }
1341
1342 spin_lock_irqsave(udc->lock, flags);
1343 if (hw_port_test_set(mode))
1344 dev_err(dev, "invalid mode\n");
1345 spin_unlock_irqrestore(udc->lock, flags);
1346
1347 done:
1348 return count;
1349}
1350static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
1351 show_port_test, store_port_test);
1352
1353/**
1354 * show_qheads: DMA contents of all queue heads
1355 *
1356 * Check "device.h" for details
1357 */
1358static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
1359 char *buf)
1360{
1361 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1362 unsigned long flags;
1363 unsigned i, j, n = 0;
1364
1365 dbg_trace("[%s] %p\n", __func__, buf);
1366 if (attr == NULL || buf == NULL) {
1367 dev_err(dev, "[%s] EINVAL\n", __func__);
1368 return 0;
1369 }
1370
1371 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301372 for (i = 0; i < hw_ep_max/2; i++) {
1373 struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i];
1374 struct ci13xxx_ep *mEpTx = &udc->ci13xxx_ep[i + hw_ep_max/2];
David Lopoaa69a802008-11-17 14:14:51 -08001375 n += scnprintf(buf + n, PAGE_SIZE - n,
1376 "EP=%02i: RX=%08X TX=%08X\n",
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301377 i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08001378 for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) {
1379 n += scnprintf(buf + n, PAGE_SIZE - n,
1380 " %04X: %08X %08X\n", j,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301381 *((u32 *)mEpRx->qh.ptr + j),
1382 *((u32 *)mEpTx->qh.ptr + j));
David Lopoaa69a802008-11-17 14:14:51 -08001383 }
1384 }
1385 spin_unlock_irqrestore(udc->lock, flags);
1386
1387 return n;
1388}
1389static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
1390
1391/**
1392 * show_registers: dumps all registers
1393 *
1394 * Check "device.h" for details
1395 */
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001396#define DUMP_ENTRIES 512
David Lopoaa69a802008-11-17 14:14:51 -08001397static ssize_t show_registers(struct device *dev,
1398 struct device_attribute *attr, char *buf)
1399{
1400 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1401 unsigned long flags;
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001402 u32 *dump;
David Lopoaa69a802008-11-17 14:14:51 -08001403 unsigned i, k, n = 0;
1404
1405 dbg_trace("[%s] %p\n", __func__, buf);
1406 if (attr == NULL || buf == NULL) {
1407 dev_err(dev, "[%s] EINVAL\n", __func__);
1408 return 0;
1409 }
1410
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001411 dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
1412 if (!dump) {
1413 dev_err(dev, "%s: out of memory\n", __func__);
1414 return 0;
1415 }
1416
David Lopoaa69a802008-11-17 14:14:51 -08001417 spin_lock_irqsave(udc->lock, flags);
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001418 k = hw_register_read(dump, DUMP_ENTRIES);
David Lopoaa69a802008-11-17 14:14:51 -08001419 spin_unlock_irqrestore(udc->lock, flags);
1420
1421 for (i = 0; i < k; i++) {
1422 n += scnprintf(buf + n, PAGE_SIZE - n,
1423 "reg[0x%04X] = 0x%08X\n",
1424 i * (unsigned)sizeof(u32), dump[i]);
1425 }
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001426 kfree(dump);
David Lopoaa69a802008-11-17 14:14:51 -08001427
1428 return n;
1429}
1430
1431/**
1432 * store_registers: writes value to register address
1433 *
1434 * Check "device.h" for details
1435 */
1436static ssize_t store_registers(struct device *dev,
1437 struct device_attribute *attr,
1438 const char *buf, size_t count)
1439{
1440 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1441 unsigned long addr, data, flags;
1442
1443 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1444 if (attr == NULL || buf == NULL) {
1445 dev_err(dev, "[%s] EINVAL\n", __func__);
1446 goto done;
1447 }
1448
1449 if (sscanf(buf, "%li %li", &addr, &data) != 2) {
1450 dev_err(dev, "<addr> <data>: write data to register address");
1451 goto done;
1452 }
1453
1454 spin_lock_irqsave(udc->lock, flags);
1455 if (hw_register_write(addr, data))
1456 dev_err(dev, "invalid address range\n");
1457 spin_unlock_irqrestore(udc->lock, flags);
1458
1459 done:
1460 return count;
1461}
1462static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
1463 show_registers, store_registers);
1464
1465/**
1466 * show_requests: DMA contents of all requests currently queued (all endpts)
1467 *
1468 * Check "device.h" for details
1469 */
1470static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
1471 char *buf)
1472{
1473 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1474 unsigned long flags;
1475 struct list_head *ptr = NULL;
1476 struct ci13xxx_req *req = NULL;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301477 unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
David Lopoaa69a802008-11-17 14:14:51 -08001478
1479 dbg_trace("[%s] %p\n", __func__, buf);
1480 if (attr == NULL || buf == NULL) {
1481 dev_err(dev, "[%s] EINVAL\n", __func__);
1482 return 0;
1483 }
1484
1485 spin_lock_irqsave(udc->lock, flags);
1486 for (i = 0; i < hw_ep_max; i++)
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301487 list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue)
1488 {
1489 req = list_entry(ptr, struct ci13xxx_req, queue);
David Lopoaa69a802008-11-17 14:14:51 -08001490
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301491 n += scnprintf(buf + n, PAGE_SIZE - n,
1492 "EP=%02i: TD=%08X %s\n",
1493 i % hw_ep_max/2, (u32)req->dma,
1494 ((i < hw_ep_max/2) ? "RX" : "TX"));
Pavankumar Kondetid2a03612012-12-19 20:00:26 +05301495
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301496 for (j = 0; j < qSize; j++)
1497 n += scnprintf(buf + n, PAGE_SIZE - n,
1498 " %04X: %08X\n", j,
1499 *((u32 *)req->ptr + j));
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301500 }
David Lopoaa69a802008-11-17 14:14:51 -08001501 spin_unlock_irqrestore(udc->lock, flags);
1502
1503 return n;
1504}
1505static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL);
1506
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001507/* EP# and Direction */
1508static ssize_t prime_ept(struct device *dev,
1509 struct device_attribute *attr,
1510 const char *buf, size_t count)
1511{
1512 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1513 struct ci13xxx_ep *mEp;
1514 unsigned int ep_num, dir;
1515 int n;
1516 struct ci13xxx_req *mReq = NULL;
1517
1518 if (sscanf(buf, "%u %u", &ep_num, &dir) != 2) {
1519 dev_err(dev, "<ep_num> <dir>: prime the ep");
1520 goto done;
1521 }
1522
1523 if (dir)
1524 mEp = &udc->ci13xxx_ep[ep_num + hw_ep_max/2];
1525 else
1526 mEp = &udc->ci13xxx_ep[ep_num];
1527
1528 n = hw_ep_bit(mEp->num, mEp->dir);
1529 mReq = list_entry(mEp->qh.queue.next, struct ci13xxx_req, queue);
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301530 mEp->qh.ptr->td.next = mReq->dma;
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001531 mEp->qh.ptr->td.token &= ~TD_STATUS;
1532
1533 wmb();
1534
1535 hw_cwrite(CAP_ENDPTPRIME, BIT(n), BIT(n));
1536 while (hw_cread(CAP_ENDPTPRIME, BIT(n)))
1537 cpu_relax();
1538
1539 pr_info("%s: prime:%08x stat:%08x ep#%d dir:%s\n", __func__,
1540 hw_cread(CAP_ENDPTPRIME, ~0),
1541 hw_cread(CAP_ENDPTSTAT, ~0),
1542 mEp->num, mEp->dir ? "IN" : "OUT");
1543done:
1544 return count;
1545
1546}
1547static DEVICE_ATTR(prime, S_IWUSR, NULL, prime_ept);
1548
1549/* EP# and Direction */
1550static ssize_t print_dtds(struct device *dev,
1551 struct device_attribute *attr,
1552 const char *buf, size_t count)
1553{
1554 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1555 struct ci13xxx_ep *mEp;
1556 unsigned int ep_num, dir;
1557 int n;
1558 struct list_head *ptr = NULL;
1559 struct ci13xxx_req *req = NULL;
1560
1561 if (sscanf(buf, "%u %u", &ep_num, &dir) != 2) {
1562 dev_err(dev, "<ep_num> <dir>: to print dtds");
1563 goto done;
1564 }
1565
1566 if (dir)
1567 mEp = &udc->ci13xxx_ep[ep_num + hw_ep_max/2];
1568 else
1569 mEp = &udc->ci13xxx_ep[ep_num];
1570
1571 n = hw_ep_bit(mEp->num, mEp->dir);
Anji jonnala6fb918c2011-10-21 17:54:21 +05301572 pr_info("%s: prime:%08x stat:%08x ep#%d dir:%s"
Vamsi Krishna8d1bbd52012-02-09 21:13:24 -08001573 "dTD_update_fail_count: %lu "
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301574 "mEp->dTD_update_fail_count: %lu"
1575 "mEp->prime_fail_count: %lu\n", __func__,
Anji jonnala6fb918c2011-10-21 17:54:21 +05301576 hw_cread(CAP_ENDPTPRIME, ~0),
1577 hw_cread(CAP_ENDPTSTAT, ~0),
1578 mEp->num, mEp->dir ? "IN" : "OUT",
1579 udc->dTD_update_fail_count,
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301580 mEp->dTD_update_fail_count,
1581 mEp->prime_fail_count);
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001582
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001583 pr_info("QH: cap:%08x cur:%08x next:%08x token:%08x\n",
1584 mEp->qh.ptr->cap, mEp->qh.ptr->curr,
1585 mEp->qh.ptr->td.next, mEp->qh.ptr->td.token);
1586
1587 list_for_each(ptr, &mEp->qh.queue) {
1588 req = list_entry(ptr, struct ci13xxx_req, queue);
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301589
1590 pr_info("\treq:%08x next:%08x token:%08x page0:%08x status:%d\n",
1591 req->dma, req->ptr->next, req->ptr->token,
1592 req->ptr->page[0], req->req.status);
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001593 }
1594done:
1595 return count;
1596
1597}
1598static DEVICE_ATTR(dtds, S_IWUSR, NULL, print_dtds);
1599
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001600static int ci13xxx_wakeup(struct usb_gadget *_gadget)
1601{
1602 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
1603 unsigned long flags;
1604 int ret = 0;
1605
1606 trace();
1607
1608 spin_lock_irqsave(udc->lock, flags);
1609 if (!udc->remote_wakeup) {
1610 ret = -EOPNOTSUPP;
1611 dbg_trace("remote wakeup feature is not enabled\n");
1612 goto out;
1613 }
Amit Blay725cdeb2012-04-30 14:20:56 +03001614 spin_unlock_irqrestore(udc->lock, flags);
1615
1616 udc->udc_driver->notify_event(udc,
1617 CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT);
1618
1619 if (udc->transceiver)
Steve Mucklef132c6c2012-06-06 18:30:57 -07001620 usb_phy_set_suspend(udc->transceiver, 0);
Amit Blay725cdeb2012-04-30 14:20:56 +03001621
1622 spin_lock_irqsave(udc->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001623 if (!hw_cread(CAP_PORTSC, PORTSC_SUSP)) {
1624 ret = -EINVAL;
1625 dbg_trace("port is not suspended\n");
1626 goto out;
1627 }
1628 hw_cwrite(CAP_PORTSC, PORTSC_FPR, PORTSC_FPR);
1629out:
1630 spin_unlock_irqrestore(udc->lock, flags);
1631 return ret;
1632}
1633
Amit Blayfd075dd2012-06-26 13:12:50 +03001634static void usb_do_remote_wakeup(struct work_struct *w)
1635{
1636 struct ci13xxx *udc = _udc;
Pavankumar Kondeti0679a812012-06-29 10:51:58 +05301637 unsigned long flags;
1638 bool do_wake;
Amit Blayfd075dd2012-06-26 13:12:50 +03001639
Pavankumar Kondeti0679a812012-06-29 10:51:58 +05301640 /*
1641 * This work can not be canceled from interrupt handler. Check
1642 * if wakeup conditions are still met.
1643 */
1644 spin_lock_irqsave(udc->lock, flags);
1645 do_wake = udc->suspended && udc->remote_wakeup;
1646 spin_unlock_irqrestore(udc->lock, flags);
1647
1648 if (do_wake)
1649 ci13xxx_wakeup(&udc->gadget);
Amit Blayfd075dd2012-06-26 13:12:50 +03001650}
1651
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001652static ssize_t usb_remote_wakeup(struct device *dev,
1653 struct device_attribute *attr, const char *buf, size_t count)
1654{
1655 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1656
1657 ci13xxx_wakeup(&udc->gadget);
1658
1659 return count;
1660}
1661static DEVICE_ATTR(wakeup, S_IWUSR, 0, usb_remote_wakeup);
1662
David Lopoaa69a802008-11-17 14:14:51 -08001663/**
1664 * dbg_create_files: initializes the attribute interface
1665 * @dev: device
1666 *
1667 * This function returns an error code
1668 */
1669__maybe_unused static int dbg_create_files(struct device *dev)
1670{
1671 int retval = 0;
1672
1673 if (dev == NULL)
1674 return -EINVAL;
1675 retval = device_create_file(dev, &dev_attr_device);
1676 if (retval)
1677 goto done;
1678 retval = device_create_file(dev, &dev_attr_driver);
1679 if (retval)
1680 goto rm_device;
1681 retval = device_create_file(dev, &dev_attr_events);
1682 if (retval)
1683 goto rm_driver;
1684 retval = device_create_file(dev, &dev_attr_inters);
1685 if (retval)
1686 goto rm_events;
1687 retval = device_create_file(dev, &dev_attr_port_test);
1688 if (retval)
1689 goto rm_inters;
1690 retval = device_create_file(dev, &dev_attr_qheads);
1691 if (retval)
1692 goto rm_port_test;
1693 retval = device_create_file(dev, &dev_attr_registers);
1694 if (retval)
1695 goto rm_qheads;
1696 retval = device_create_file(dev, &dev_attr_requests);
1697 if (retval)
1698 goto rm_registers;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001699 retval = device_create_file(dev, &dev_attr_wakeup);
1700 if (retval)
1701 goto rm_remote_wakeup;
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001702 retval = device_create_file(dev, &dev_attr_prime);
1703 if (retval)
1704 goto rm_prime;
1705 retval = device_create_file(dev, &dev_attr_dtds);
1706 if (retval)
1707 goto rm_dtds;
1708
David Lopoaa69a802008-11-17 14:14:51 -08001709 return 0;
1710
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001711rm_dtds:
1712 device_remove_file(dev, &dev_attr_dtds);
1713rm_prime:
1714 device_remove_file(dev, &dev_attr_prime);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001715rm_remote_wakeup:
1716 device_remove_file(dev, &dev_attr_wakeup);
David Lopoaa69a802008-11-17 14:14:51 -08001717 rm_registers:
1718 device_remove_file(dev, &dev_attr_registers);
1719 rm_qheads:
1720 device_remove_file(dev, &dev_attr_qheads);
1721 rm_port_test:
1722 device_remove_file(dev, &dev_attr_port_test);
1723 rm_inters:
1724 device_remove_file(dev, &dev_attr_inters);
1725 rm_events:
1726 device_remove_file(dev, &dev_attr_events);
1727 rm_driver:
1728 device_remove_file(dev, &dev_attr_driver);
1729 rm_device:
1730 device_remove_file(dev, &dev_attr_device);
1731 done:
1732 return retval;
1733}
1734
1735/**
1736 * dbg_remove_files: destroys the attribute interface
1737 * @dev: device
1738 *
1739 * This function returns an error code
1740 */
1741__maybe_unused static int dbg_remove_files(struct device *dev)
1742{
1743 if (dev == NULL)
1744 return -EINVAL;
1745 device_remove_file(dev, &dev_attr_requests);
1746 device_remove_file(dev, &dev_attr_registers);
1747 device_remove_file(dev, &dev_attr_qheads);
1748 device_remove_file(dev, &dev_attr_port_test);
1749 device_remove_file(dev, &dev_attr_inters);
1750 device_remove_file(dev, &dev_attr_events);
1751 device_remove_file(dev, &dev_attr_driver);
1752 device_remove_file(dev, &dev_attr_device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001753 device_remove_file(dev, &dev_attr_wakeup);
David Lopoaa69a802008-11-17 14:14:51 -08001754 return 0;
1755}
1756
Rajkumar Raghupathyc01decf2013-03-29 17:39:58 +05301757static void dump_usb_info(void *ignore, unsigned int ebi_addr,
1758 unsigned int ebi_apacket0, unsigned int ebi_apacket1)
1759{
1760 struct ci13xxx *udc = _udc;
1761 unsigned long flags;
1762 struct list_head *ptr = NULL;
1763 struct ci13xxx_req *req = NULL;
1764 struct ci13xxx_ep *mEp;
1765 unsigned i;
1766 struct ci13xxx_ebi_err_entry *temp_dump;
1767 static int count;
1768 u32 epdir = 0;
1769
1770 if (count)
1771 return;
1772 count++;
1773
1774 pr_info("%s: USB EBI error detected\n", __func__);
1775
1776 ebi_err_data = kmalloc(sizeof(struct ci13xxx_ebi_err_data),
1777 GFP_ATOMIC);
1778 if (!ebi_err_data) {
1779 pr_err("%s: memory alloc failed for ebi_err_data\n", __func__);
1780 return;
1781 }
1782
1783 ebi_err_data->ebi_err_entry = kmalloc(
1784 sizeof(struct ci13xxx_ebi_err_entry),
1785 GFP_ATOMIC);
1786 if (!ebi_err_data->ebi_err_entry) {
1787 kfree(ebi_err_data);
1788 pr_err("%s: memory alloc failed for ebi_err_entry\n", __func__);
1789 return;
1790 }
1791
1792 ebi_err_data->ebi_err_addr = ebi_addr;
1793 ebi_err_data->apkt0 = ebi_apacket0;
1794 ebi_err_data->apkt1 = ebi_apacket1;
1795
1796 temp_dump = ebi_err_data->ebi_err_entry;
1797 pr_info("\n DUMPING USB Requests Information\n");
1798 spin_lock_irqsave(udc->lock, flags);
1799 for (i = 0; i < hw_ep_max; i++) {
1800 list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue) {
1801 mEp = &udc->ci13xxx_ep[i];
1802 req = list_entry(ptr, struct ci13xxx_req, queue);
1803
1804 temp_dump->usb_req_buf = req->req.buf;
1805 temp_dump->usb_req_length = req->req.length;
1806 epdir = mEp->dir;
1807 temp_dump->ep_info = mEp->num | (epdir << 15);
1808
1809 temp_dump->next = kmalloc(
1810 sizeof(struct ci13xxx_ebi_err_entry),
1811 GFP_ATOMIC);
1812 if (!temp_dump->next) {
1813 pr_err("%s: memory alloc failed\n", __func__);
1814 spin_unlock_irqrestore(udc->lock, flags);
1815 return;
1816 }
1817 temp_dump = temp_dump->next;
1818 }
1819 }
1820 spin_unlock_irqrestore(udc->lock, flags);
1821}
1822
David Lopoaa69a802008-11-17 14:14:51 -08001823/******************************************************************************
1824 * UTIL block
1825 *****************************************************************************/
1826/**
1827 * _usb_addr: calculates endpoint address from direction & number
1828 * @ep: endpoint
1829 */
1830static inline u8 _usb_addr(struct ci13xxx_ep *ep)
1831{
1832 return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num;
1833}
1834
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301835static void ep_prime_timer_func(unsigned long data)
1836{
Mayank Ranabdcbfe52012-08-16 14:00:40 +05301837 struct ci13xxx_ep *mep = (struct ci13xxx_ep *)data;
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301838 struct ci13xxx_req *req;
1839 struct list_head *ptr = NULL;
Mayank Ranabdcbfe52012-08-16 14:00:40 +05301840 int n = hw_ep_bit(mep->num, mep->dir);
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301841 unsigned long flags;
1842
1843
Mayank Ranabdcbfe52012-08-16 14:00:40 +05301844 spin_lock_irqsave(mep->lock, flags);
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301845 if (!hw_cread(CAP_ENDPTPRIME, BIT(n)))
1846 goto out;
1847
Mayank Ranabdcbfe52012-08-16 14:00:40 +05301848 if (list_empty(&mep->qh.queue))
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301849 goto out;
1850
Mayank Ranabdcbfe52012-08-16 14:00:40 +05301851 req = list_entry(mep->qh.queue.next, struct ci13xxx_req, queue);
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301852
1853 mb();
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301854 if (!(TD_STATUS_ACTIVE & req->ptr->token))
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301855 goto out;
1856
Mayank Ranabdcbfe52012-08-16 14:00:40 +05301857 mep->prime_timer_count++;
1858 if (mep->prime_timer_count == MAX_PRIME_CHECK_RETRY) {
1859 mep->prime_timer_count = 0;
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301860 pr_info("ep%d dir:%s QH:cap:%08x cur:%08x next:%08x tkn:%08x\n",
Mayank Ranabdcbfe52012-08-16 14:00:40 +05301861 mep->num, mep->dir ? "IN" : "OUT",
1862 mep->qh.ptr->cap, mep->qh.ptr->curr,
1863 mep->qh.ptr->td.next, mep->qh.ptr->td.token);
1864 list_for_each(ptr, &mep->qh.queue) {
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301865 req = list_entry(ptr, struct ci13xxx_req, queue);
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301866 pr_info("\treq:%08xnext:%08xtkn:%08xpage0:%08xsts:%d\n",
1867 req->dma, req->ptr->next,
1868 req->ptr->token, req->ptr->page[0],
1869 req->req.status);
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301870 }
Mayank Ranabdcbfe52012-08-16 14:00:40 +05301871 dbg_usb_op_fail(0xFF, "PRIMEF", mep);
1872 mep->prime_fail_count++;
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301873 } else {
Mayank Ranabdcbfe52012-08-16 14:00:40 +05301874 mod_timer(&mep->prime_timer, EP_PRIME_CHECK_DELAY);
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301875 }
1876
Mayank Ranabdcbfe52012-08-16 14:00:40 +05301877 spin_unlock_irqrestore(mep->lock, flags);
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301878 return;
1879
1880out:
Mayank Ranabdcbfe52012-08-16 14:00:40 +05301881 mep->prime_timer_count = 0;
1882 spin_unlock_irqrestore(mep->lock, flags);
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301883
1884}
1885
David Lopoaa69a802008-11-17 14:14:51 -08001886/**
1887 * _hardware_queue: configures a request at hardware level
1888 * @gadget: gadget
1889 * @mEp: endpoint
1890 *
1891 * This function returns an error code
1892 */
1893static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1894{
1895 unsigned i;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301896 int ret = 0;
1897 unsigned length = mReq->req.length;
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301898 struct ci13xxx *udc = _udc;
David Lopoaa69a802008-11-17 14:14:51 -08001899
1900 trace("%p, %p", mEp, mReq);
1901
1902 /* don't queue twice */
1903 if (mReq->req.status == -EALREADY)
1904 return -EALREADY;
1905
David Lopoaa69a802008-11-17 14:14:51 -08001906 mReq->req.status = -EALREADY;
Michael Grzeschik954aad82011-10-10 18:38:06 +02001907 if (length && mReq->req.dma == DMA_ADDR_INVALID) {
David Lopoaa69a802008-11-17 14:14:51 -08001908 mReq->req.dma = \
1909 dma_map_single(mEp->device, mReq->req.buf,
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301910 length, mEp->dir ? DMA_TO_DEVICE :
1911 DMA_FROM_DEVICE);
David Lopoaa69a802008-11-17 14:14:51 -08001912 if (mReq->req.dma == 0)
1913 return -ENOMEM;
1914
1915 mReq->map = 1;
1916 }
1917
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301918 if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) {
1919 mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC,
1920 &mReq->zdma);
1921 if (mReq->zptr == NULL) {
1922 if (mReq->map) {
1923 dma_unmap_single(mEp->device, mReq->req.dma,
1924 length, mEp->dir ? DMA_TO_DEVICE :
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301925 DMA_FROM_DEVICE);
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301926 mReq->req.dma = DMA_ADDR_INVALID;
1927 mReq->map = 0;
1928 }
1929 return -ENOMEM;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301930 }
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301931 memset(mReq->zptr, 0, sizeof(*mReq->zptr));
1932 mReq->zptr->next = TD_TERMINATE;
1933 mReq->zptr->token = TD_STATUS_ACTIVE;
1934 if (!mReq->req.no_interrupt)
1935 mReq->zptr->token |= TD_IOC;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301936 }
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301937 /*
1938 * TD configuration
1939 * TODO - handle requests which spawns into several TDs
1940 */
1941 memset(mReq->ptr, 0, sizeof(*mReq->ptr));
1942 mReq->ptr->token = length << ffs_nr(TD_TOTAL_BYTES);
1943 mReq->ptr->token &= TD_TOTAL_BYTES;
1944 mReq->ptr->token |= TD_STATUS_ACTIVE;
1945 if (mReq->zptr) {
1946 mReq->ptr->next = mReq->zdma;
1947 } else {
1948 mReq->ptr->next = TD_TERMINATE;
1949 if (!mReq->req.no_interrupt)
1950 mReq->ptr->token |= TD_IOC;
1951 }
Ofir Cohena1c2a872011-12-14 10:26:34 +02001952
1953 /* MSM Specific: updating the request as required for
1954 * SPS mode. Enable MSM proprietary DMA engine acording
1955 * to the UDC private data in the request.
1956 */
1957 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
1958 if (mReq->req.udc_priv & MSM_SPS_MODE) {
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301959 mReq->ptr->token = TD_STATUS_ACTIVE;
Ido Shayevitzd1cb16c2012-03-28 18:57:47 +02001960 if (mReq->req.udc_priv & MSM_IS_FINITE_TRANSFER)
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301961 mReq->ptr->next = TD_TERMINATE;
Ofir Cohena1c2a872011-12-14 10:26:34 +02001962 else
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301963 mReq->ptr->next = MSM_ETD_TYPE | mReq->dma;
Ofir Cohena1c2a872011-12-14 10:26:34 +02001964 if (!mReq->req.no_interrupt)
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301965 mReq->ptr->token |= MSM_ETD_IOC;
Ofir Cohena1c2a872011-12-14 10:26:34 +02001966 }
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301967 mReq->req.dma = 0;
1968 }
1969
1970 mReq->ptr->page[0] = mReq->req.dma;
1971 for (i = 1; i < 5; i++)
1972 mReq->ptr->page[i] = (mReq->req.dma + i * CI13XXX_PAGE_SIZE) &
1973 ~TD_RESERVED_MASK;
1974
1975 /* Remote Wakeup */
1976 if (udc->suspended) {
1977 if (!udc->remote_wakeup) {
1978 mReq->req.status = -EAGAIN;
1979 dev_dbg(mEp->device, "%s: queue failed (suspend) ept #%d\n",
1980 __func__, mEp->num);
1981 return -EAGAIN;
1982 }
1983 usb_phy_set_suspend(udc->transceiver, 0);
1984 schedule_delayed_work(&udc->rw_work, REMOTE_WAKEUP_DELAY);
Amit Blayfd075dd2012-06-26 13:12:50 +03001985 }
1986
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301987 if (!list_empty(&mEp->qh.queue)) {
1988 struct ci13xxx_req *mReqPrev;
1989 int n = hw_ep_bit(mEp->num, mEp->dir);
1990 int tmp_stat;
Vijayavardhan Vennapusa397a4532012-07-20 13:18:32 +05301991 ktime_t start, diff;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301992
1993 mReqPrev = list_entry(mEp->qh.queue.prev,
1994 struct ci13xxx_req, queue);
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05301995 if (mReqPrev->zptr)
1996 mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
1997 else
1998 mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301999 wmb();
2000 if (hw_cread(CAP_ENDPTPRIME, BIT(n)))
2001 goto done;
Vijayavardhan Vennapusa397a4532012-07-20 13:18:32 +05302002 start = ktime_get();
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302003 do {
2004 hw_cwrite(CAP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
2005 tmp_stat = hw_cread(CAP_ENDPTSTAT, BIT(n));
Vijayavardhan Vennapusa397a4532012-07-20 13:18:32 +05302006 diff = ktime_sub(ktime_get(), start);
2007 /* poll for max. 100ms */
Mayank Ranabdcbfe52012-08-16 14:00:40 +05302008 if (ktime_to_ms(diff) > USB_MAX_TIMEOUT) {
Vijayavardhan Vennapusa397a4532012-07-20 13:18:32 +05302009 if (hw_cread(CAP_USBCMD, USBCMD_ATDTW))
2010 break;
2011 printk_ratelimited(KERN_ERR
2012 "%s:queue failed ep#%d %s\n",
2013 __func__, mEp->num, mEp->dir ? "IN" : "OUT");
2014 return -EAGAIN;
2015 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302016 } while (!hw_cread(CAP_USBCMD, USBCMD_ATDTW));
2017 hw_cwrite(CAP_USBCMD, USBCMD_ATDTW, 0);
2018 if (tmp_stat)
2019 goto done;
2020 }
2021
2022 /* QH configuration */
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07002023 if (!list_empty(&mEp->qh.queue)) {
2024 struct ci13xxx_req *mReq = \
2025 list_entry(mEp->qh.queue.next,
2026 struct ci13xxx_req, queue);
2027
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05302028 if (TD_STATUS_ACTIVE & mReq->ptr->token) {
2029 mEp->qh.ptr->td.next = mReq->dma;
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07002030 mEp->qh.ptr->td.token &= ~TD_STATUS;
2031 goto prime;
2032 }
2033 }
2034
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05302035 mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */
Ofir Cohena1c2a872011-12-14 10:26:34 +02002036
2037 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
2038 if (mReq->req.udc_priv & MSM_SPS_MODE) {
2039 mEp->qh.ptr->td.next |= MSM_ETD_TYPE;
2040 i = hw_cread(CAP_ENDPTPIPEID +
2041 mEp->num * sizeof(u32), ~0);
2042 /* Read current value of this EPs pipe id */
2043 i = (mEp->dir == TX) ?
2044 ((i >> MSM_TX_PIPE_ID_OFS) & MSM_PIPE_ID_MASK) :
2045 (i & MSM_PIPE_ID_MASK);
2046 /* If requested pipe id is different from current,
2047 then write it */
2048 if (i != (mReq->req.udc_priv & MSM_PIPE_ID_MASK)) {
2049 if (mEp->dir == TX)
2050 hw_cwrite(
2051 CAP_ENDPTPIPEID +
2052 mEp->num * sizeof(u32),
2053 MSM_PIPE_ID_MASK <<
2054 MSM_TX_PIPE_ID_OFS,
2055 (mReq->req.udc_priv &
2056 MSM_PIPE_ID_MASK)
2057 << MSM_TX_PIPE_ID_OFS);
2058 else
2059 hw_cwrite(
2060 CAP_ENDPTPIPEID +
2061 mEp->num * sizeof(u32),
2062 MSM_PIPE_ID_MASK,
2063 mReq->req.udc_priv &
2064 MSM_PIPE_ID_MASK);
2065 }
2066 }
2067 }
2068
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302069 mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302070 mEp->qh.ptr->cap |= QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08002071
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07002072prime:
David Lopoaa69a802008-11-17 14:14:51 -08002073 wmb(); /* synchronize before ep prime */
2074
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302075 ret = hw_ep_prime(mEp->num, mEp->dir,
David Lopoaa69a802008-11-17 14:14:51 -08002076 mEp->type == USB_ENDPOINT_XFER_CONTROL);
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05302077 if (!ret)
2078 mod_timer(&mEp->prime_timer, EP_PRIME_CHECK_DELAY);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302079done:
2080 return ret;
David Lopoaa69a802008-11-17 14:14:51 -08002081}
2082
2083/**
2084 * _hardware_dequeue: handles a request at hardware level
2085 * @gadget: gadget
2086 * @mEp: endpoint
2087 *
2088 * This function returns an error code
2089 */
2090static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
2091{
2092 trace("%p, %p", mEp, mReq);
2093
2094 if (mReq->req.status != -EALREADY)
2095 return -EINVAL;
2096
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05302097 /* clean speculative fetches on req->ptr->token */
Vijayavardhan Vennapusa590b8ce2011-10-20 02:38:14 +05302098 mb();
2099
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05302100 if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302101 return -EBUSY;
2102
Ofir Cohena1c2a872011-12-14 10:26:34 +02002103 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID)
2104 if ((mReq->req.udc_priv & MSM_SPS_MODE) &&
Ido Shayevitzd1cb16c2012-03-28 18:57:47 +02002105 (mReq->req.udc_priv & MSM_IS_FINITE_TRANSFER))
Ofir Cohena1c2a872011-12-14 10:26:34 +02002106 return -EBUSY;
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05302107 if (mReq->zptr) {
2108 if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
2109 return -EBUSY;
2110 dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
2111 mReq->zptr = NULL;
2112 }
David Lopoaa69a802008-11-17 14:14:51 -08002113
2114 mReq->req.status = 0;
2115
2116 if (mReq->map) {
2117 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
2118 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02002119 mReq->req.dma = DMA_ADDR_INVALID;
David Lopoaa69a802008-11-17 14:14:51 -08002120 mReq->map = 0;
2121 }
2122
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05302123 mReq->req.status = mReq->ptr->token & TD_STATUS;
2124 if ((TD_STATUS_HALTED & mReq->req.status) != 0)
2125 mReq->req.status = -1;
2126 else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0)
2127 mReq->req.status = -1;
2128 else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0)
2129 mReq->req.status = -1;
David Lopoaa69a802008-11-17 14:14:51 -08002130
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05302131 mReq->req.actual = mReq->ptr->token & TD_TOTAL_BYTES;
2132 mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES);
2133 mReq->req.actual = mReq->req.length - mReq->req.actual;
2134 mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual;
David Lopoaa69a802008-11-17 14:14:51 -08002135
2136 return mReq->req.actual;
2137}
2138
2139/**
Pavankumar Kondeticbd44db2013-02-06 20:52:46 +05302140 * restore_original_req: Restore original req's attributes
2141 * @mReq: Request
2142 *
2143 * This function restores original req's attributes. Call
2144 * this function before completing the large req (>16K).
2145 */
2146static void restore_original_req(struct ci13xxx_req *mReq)
2147{
2148 mReq->req.buf = mReq->multi.buf;
2149 mReq->req.length = mReq->multi.len;
2150 if (!mReq->req.status)
2151 mReq->req.actual = mReq->multi.actual;
2152
2153 mReq->multi.len = 0;
2154 mReq->multi.actual = 0;
2155 mReq->multi.buf = NULL;
2156}
2157
2158/**
David Lopoaa69a802008-11-17 14:14:51 -08002159 * _ep_nuke: dequeues all endpoint requests
2160 * @mEp: endpoint
2161 *
2162 * This function returns an error code
2163 * Caller must hold lock
2164 */
2165static int _ep_nuke(struct ci13xxx_ep *mEp)
2166__releases(mEp->lock)
2167__acquires(mEp->lock)
2168{
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05302169 struct ci13xxx_ep *mEpTemp = mEp;
Ofir Cohena1c2a872011-12-14 10:26:34 +02002170 unsigned val;
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05302171
David Lopoaa69a802008-11-17 14:14:51 -08002172 trace("%p", mEp);
2173
2174 if (mEp == NULL)
2175 return -EINVAL;
2176
2177 hw_ep_flush(mEp->num, mEp->dir);
2178
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302179 while (!list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -08002180
2181 /* pop oldest request */
2182 struct ci13xxx_req *mReq = \
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302183 list_entry(mEp->qh.queue.next,
David Lopoaa69a802008-11-17 14:14:51 -08002184 struct ci13xxx_req, queue);
2185 list_del_init(&mReq->queue);
Ofir Cohena1c2a872011-12-14 10:26:34 +02002186
2187 /* MSM Specific: Clear end point proprietary register */
2188 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
2189 if (mReq->req.udc_priv & MSM_SPS_MODE) {
2190 val = hw_cread(CAP_ENDPTPIPEID +
2191 mEp->num * sizeof(u32),
2192 ~0);
2193
2194 if (val != MSM_EP_PIPE_ID_RESET_VAL)
2195 hw_cwrite(
2196 CAP_ENDPTPIPEID +
2197 mEp->num * sizeof(u32),
2198 ~0, MSM_EP_PIPE_ID_RESET_VAL);
2199 }
2200 }
David Lopoaa69a802008-11-17 14:14:51 -08002201 mReq->req.status = -ESHUTDOWN;
2202
Anji jonnalaea7bbc32011-12-26 16:39:53 +05302203 if (mReq->map) {
2204 dma_unmap_single(mEp->device, mReq->req.dma,
2205 mReq->req.length,
2206 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Pavankumar Kondeti3c9a1d52012-06-06 09:56:03 +05302207 mReq->req.dma = DMA_ADDR_INVALID;
Anji jonnalaea7bbc32011-12-26 16:39:53 +05302208 mReq->map = 0;
2209 }
2210
Pavankumar Kondeticbd44db2013-02-06 20:52:46 +05302211 if (mEp->multi_req) {
2212 restore_original_req(mReq);
2213 mEp->multi_req = false;
2214 }
2215
Artem Leonenko7c25a822010-12-14 23:46:55 -08002216 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08002217 spin_unlock(mEp->lock);
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05302218 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05302219 mReq->req.length)
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05302220 mEpTemp = &_udc->ep0in;
2221 mReq->req.complete(&mEpTemp->ep, &mReq->req);
Mayank Rana0c1b8b22012-07-04 16:17:38 +05302222 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2223 mReq->req.complete = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002224 spin_lock(mEp->lock);
2225 }
2226 }
2227 return 0;
2228}
2229
2230/**
2231 * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
2232 * @gadget: gadget
2233 *
2234 * This function returns an error code
David Lopoaa69a802008-11-17 14:14:51 -08002235 */
2236static int _gadget_stop_activity(struct usb_gadget *gadget)
David Lopoaa69a802008-11-17 14:14:51 -08002237{
David Lopoaa69a802008-11-17 14:14:51 -08002238 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302239 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -08002240
2241 trace("%p", gadget);
2242
2243 if (gadget == NULL)
2244 return -EINVAL;
2245
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302246 spin_lock_irqsave(udc->lock, flags);
2247 udc->gadget.speed = USB_SPEED_UNKNOWN;
2248 udc->remote_wakeup = 0;
2249 udc->suspended = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002250 udc->configured = 0;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302251 spin_unlock_irqrestore(udc->lock, flags);
2252
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302253 gadget->b_hnp_enable = 0;
2254 gadget->a_hnp_support = 0;
2255 gadget->host_request = 0;
2256 gadget->otg_srp_reqd = 0;
2257
Pavankumar Kondetid658d932012-12-28 17:54:57 +05302258 udc->driver->disconnect(gadget);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302259 usb_ep_fifo_flush(&udc->ep0out.ep);
2260 usb_ep_fifo_flush(&udc->ep0in.ep);
David Lopoaa69a802008-11-17 14:14:51 -08002261
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302262 if (udc->status != NULL) {
2263 usb_ep_free_request(&udc->ep0in.ep, udc->status);
2264 udc->status = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002265 }
2266
David Lopoaa69a802008-11-17 14:14:51 -08002267 return 0;
2268}
2269
2270/******************************************************************************
2271 * ISR block
2272 *****************************************************************************/
2273/**
2274 * isr_reset_handler: USB reset interrupt handler
2275 * @udc: UDC device
2276 *
2277 * This function resets USB engine after a bus reset occurred
2278 */
2279static void isr_reset_handler(struct ci13xxx *udc)
2280__releases(udc->lock)
2281__acquires(udc->lock)
2282{
David Lopoaa69a802008-11-17 14:14:51 -08002283 int retval;
2284
2285 trace("%p", udc);
2286
2287 if (udc == NULL) {
2288 err("EINVAL");
2289 return;
2290 }
2291
2292 dbg_event(0xFF, "BUS RST", 0);
2293
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302294 spin_unlock(udc->lock);
Anji jonnala8bbde012011-10-28 14:17:25 +05302295
Ido Shayevitz16cd0982012-08-27 20:36:43 +03002296 if (udc->suspended) {
2297 if (udc->udc_driver->notify_event)
2298 udc->udc_driver->notify_event(udc,
2299 CI13XXX_CONTROLLER_RESUME_EVENT);
2300 if (udc->transceiver)
2301 usb_phy_set_suspend(udc->transceiver, 0);
2302 udc->driver->resume(&udc->gadget);
2303 udc->suspended = 0;
2304 }
2305
Anji jonnala8bbde012011-10-28 14:17:25 +05302306 /*stop charging upon reset */
2307 if (udc->transceiver)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002308 usb_phy_set_power(udc->transceiver, 0);
Anji jonnala8bbde012011-10-28 14:17:25 +05302309
David Lopoaa69a802008-11-17 14:14:51 -08002310 retval = _gadget_stop_activity(&udc->gadget);
2311 if (retval)
2312 goto done;
2313
Pavankumar Kondeti2a630fb2013-01-28 12:31:15 +05302314 _udc->skip_flush = false;
David Lopoaa69a802008-11-17 14:14:51 -08002315 retval = hw_usb_reset();
2316 if (retval)
2317 goto done;
2318
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302319 udc->status = usb_ep_alloc_request(&udc->ep0in.ep, GFP_ATOMIC);
2320 if (udc->status == NULL)
2321 retval = -ENOMEM;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302322
David Lopoaa69a802008-11-17 14:14:51 -08002323 spin_lock(udc->lock);
2324
2325 done:
2326 if (retval)
2327 err("error: %i", retval);
2328}
2329
2330/**
Amit Blay6fa647a2012-05-24 14:12:08 +03002331 * isr_resume_handler: USB PCI interrupt handler
2332 * @udc: UDC device
2333 *
2334 */
2335static void isr_resume_handler(struct ci13xxx *udc)
2336{
2337 udc->gadget.speed = hw_port_is_high_speed() ?
2338 USB_SPEED_HIGH : USB_SPEED_FULL;
2339 if (udc->suspended) {
2340 spin_unlock(udc->lock);
Amit Blay9b033682012-05-24 16:59:23 +03002341 if (udc->udc_driver->notify_event)
2342 udc->udc_driver->notify_event(udc,
2343 CI13XXX_CONTROLLER_RESUME_EVENT);
Amit Blay6fa647a2012-05-24 14:12:08 +03002344 if (udc->transceiver)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002345 usb_phy_set_suspend(udc->transceiver, 0);
Amit Blay6fa647a2012-05-24 14:12:08 +03002346 udc->driver->resume(&udc->gadget);
2347 spin_lock(udc->lock);
2348 udc->suspended = 0;
2349 }
2350}
2351
2352/**
2353 * isr_resume_handler: USB SLI interrupt handler
2354 * @udc: UDC device
2355 *
2356 */
2357static void isr_suspend_handler(struct ci13xxx *udc)
2358{
2359 if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
2360 udc->vbus_active) {
2361 if (udc->suspended == 0) {
2362 spin_unlock(udc->lock);
2363 udc->driver->suspend(&udc->gadget);
2364 if (udc->udc_driver->notify_event)
2365 udc->udc_driver->notify_event(udc,
2366 CI13XXX_CONTROLLER_SUSPEND_EVENT);
2367 if (udc->transceiver)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002368 usb_phy_set_suspend(udc->transceiver, 1);
Amit Blay6fa647a2012-05-24 14:12:08 +03002369 spin_lock(udc->lock);
2370 udc->suspended = 1;
2371 }
2372 }
2373}
2374
2375/**
David Lopoaa69a802008-11-17 14:14:51 -08002376 * isr_get_status_complete: get_status request complete function
2377 * @ep: endpoint
2378 * @req: request handled
2379 *
2380 * Caller must release lock
2381 */
2382static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
2383{
2384 trace("%p, %p", ep, req);
2385
2386 if (ep == NULL || req == NULL) {
2387 err("EINVAL");
2388 return;
2389 }
2390
2391 kfree(req->buf);
2392 usb_ep_free_request(ep, req);
2393}
2394
2395/**
2396 * isr_get_status_response: get_status request response
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302397 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08002398 * @setup: setup request packet
2399 *
2400 * This function returns an error code
2401 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302402static int isr_get_status_response(struct ci13xxx *udc,
David Lopoaa69a802008-11-17 14:14:51 -08002403 struct usb_ctrlrequest *setup)
2404__releases(mEp->lock)
2405__acquires(mEp->lock)
2406{
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302407 struct ci13xxx_ep *mEp = &udc->ep0in;
David Lopoaa69a802008-11-17 14:14:51 -08002408 struct usb_request *req = NULL;
2409 gfp_t gfp_flags = GFP_ATOMIC;
2410 int dir, num, retval;
2411
2412 trace("%p, %p", mEp, setup);
2413
2414 if (mEp == NULL || setup == NULL)
2415 return -EINVAL;
2416
2417 spin_unlock(mEp->lock);
2418 req = usb_ep_alloc_request(&mEp->ep, gfp_flags);
2419 spin_lock(mEp->lock);
2420 if (req == NULL)
2421 return -ENOMEM;
2422
2423 req->complete = isr_get_status_complete;
2424 req->length = 2;
2425 req->buf = kzalloc(req->length, gfp_flags);
2426 if (req->buf == NULL) {
2427 retval = -ENOMEM;
2428 goto err_free_req;
2429 }
2430
2431 if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302432 if (setup->wIndex == OTG_STATUS_SELECTOR) {
2433 *((u8 *)req->buf) = _udc->gadget.host_request <<
2434 HOST_REQUEST_FLAG;
2435 req->length = 1;
2436 } else {
2437 /* Assume that device is bus powered for now. */
2438 *((u16 *)req->buf) = _udc->remote_wakeup << 1;
2439 }
2440 /* TODO: D1 - Remote Wakeup; D0 - Self Powered */
David Lopoaa69a802008-11-17 14:14:51 -08002441 retval = 0;
2442 } else if ((setup->bRequestType & USB_RECIP_MASK) \
2443 == USB_RECIP_ENDPOINT) {
2444 dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
2445 TX : RX;
2446 num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK;
2447 *((u16 *)req->buf) = hw_ep_get_halt(num, dir);
2448 }
2449 /* else do nothing; reserved for future use */
2450
2451 spin_unlock(mEp->lock);
2452 retval = usb_ep_queue(&mEp->ep, req, gfp_flags);
2453 spin_lock(mEp->lock);
2454 if (retval)
2455 goto err_free_buf;
2456
2457 return 0;
2458
2459 err_free_buf:
2460 kfree(req->buf);
2461 err_free_req:
2462 spin_unlock(mEp->lock);
2463 usb_ep_free_request(&mEp->ep, req);
2464 spin_lock(mEp->lock);
2465 return retval;
2466}
2467
2468/**
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302469 * isr_setup_status_complete: setup_status request complete function
2470 * @ep: endpoint
2471 * @req: request handled
2472 *
2473 * Caller must release lock. Put the port in test mode if test mode
2474 * feature is selected.
2475 */
2476static void
2477isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
2478{
2479 struct ci13xxx *udc = req->context;
2480 unsigned long flags;
2481
2482 trace("%p, %p", ep, req);
2483
2484 spin_lock_irqsave(udc->lock, flags);
2485 if (udc->test_mode)
2486 hw_port_test_set(udc->test_mode);
2487 spin_unlock_irqrestore(udc->lock, flags);
2488}
2489
2490/**
David Lopoaa69a802008-11-17 14:14:51 -08002491 * isr_setup_status_phase: queues the status phase of a setup transation
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302492 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08002493 *
2494 * This function returns an error code
2495 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302496static int isr_setup_status_phase(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -08002497__releases(mEp->lock)
2498__acquires(mEp->lock)
2499{
2500 int retval;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302501 struct ci13xxx_ep *mEp;
David Lopoaa69a802008-11-17 14:14:51 -08002502
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302503 trace("%p", udc);
David Lopoaa69a802008-11-17 14:14:51 -08002504
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302505 mEp = (udc->ep0_dir == TX) ? &udc->ep0out : &udc->ep0in;
Vijayavardhan Vennapusa28f14ee2012-06-07 16:12:49 +05302506 if (udc->status) {
2507 udc->status->context = udc;
2508 udc->status->complete = isr_setup_status_complete;
2509 } else
2510 return -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -08002511
2512 spin_unlock(mEp->lock);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302513 retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
David Lopoaa69a802008-11-17 14:14:51 -08002514 spin_lock(mEp->lock);
2515
2516 return retval;
2517}
2518
2519/**
2520 * isr_tr_complete_low: transaction complete low level handler
2521 * @mEp: endpoint
2522 *
2523 * This function returns an error code
2524 * Caller must hold lock
2525 */
2526static int isr_tr_complete_low(struct ci13xxx_ep *mEp)
2527__releases(mEp->lock)
2528__acquires(mEp->lock)
2529{
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302530 struct ci13xxx_req *mReq, *mReqTemp;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302531 struct ci13xxx_ep *mEpTemp = mEp;
Pavankumar Kondeti986b11b2011-05-02 11:56:29 +05302532 int uninitialized_var(retval);
Anji jonnala6fb918c2011-10-21 17:54:21 +05302533 int req_dequeue = 1;
2534 struct ci13xxx *udc = _udc;
David Lopoaa69a802008-11-17 14:14:51 -08002535
2536 trace("%p", mEp);
2537
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302538 if (list_empty(&mEp->qh.queue))
Anji jonnala6fb918c2011-10-21 17:54:21 +05302539 return 0;
David Lopoaa69a802008-11-17 14:14:51 -08002540
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05302541 del_timer(&mEp->prime_timer);
2542 mEp->prime_timer_count = 0;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302543 list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,
2544 queue) {
Anji jonnala6fb918c2011-10-21 17:54:21 +05302545dequeue:
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302546 retval = _hardware_dequeue(mEp, mReq);
Anji jonnala6fb918c2011-10-21 17:54:21 +05302547 if (retval < 0) {
2548 /*
2549 * FIXME: don't know exact delay
2550 * required for HW to update dTD status
2551 * bits. This is a temporary workaround till
2552 * HW designers come back on this.
2553 */
Pavankumar Kondeti012800e2012-10-12 14:06:36 +05302554 if (retval == -EBUSY && req_dequeue &&
2555 (mEp->dir == 0 || mEp->num == 0)) {
Anji jonnala6fb918c2011-10-21 17:54:21 +05302556 req_dequeue = 0;
2557 udc->dTD_update_fail_count++;
2558 mEp->dTD_update_fail_count++;
2559 udelay(10);
2560 goto dequeue;
2561 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302562 break;
Anji jonnala6fb918c2011-10-21 17:54:21 +05302563 }
2564 req_dequeue = 0;
Pavankumar Kondeticbd44db2013-02-06 20:52:46 +05302565
2566 if (mEp->multi_req) { /* Large request in progress */
2567 unsigned remain_len;
2568
2569 mReq->multi.actual += mReq->req.actual;
2570 remain_len = mReq->multi.len - mReq->multi.actual;
2571 if (mReq->req.status || !remain_len ||
2572 (mReq->req.actual != mReq->req.length)) {
2573 restore_original_req(mReq);
2574 mEp->multi_req = false;
2575 } else {
2576 mReq->req.buf = mReq->multi.buf +
2577 mReq->multi.actual;
2578 mReq->req.length = min_t(unsigned, remain_len,
2579 (4 * CI13XXX_PAGE_SIZE));
2580
2581 mReq->req.status = -EINPROGRESS;
2582 mReq->req.actual = 0;
2583 list_del_init(&mReq->queue);
2584 retval = _hardware_enqueue(mEp, mReq);
2585 if (retval) {
2586 err("Large req failed in middle");
2587 mReq->req.status = retval;
2588 restore_original_req(mReq);
2589 mEp->multi_req = false;
2590 goto done;
2591 } else {
2592 list_add_tail(&mReq->queue,
2593 &mEp->qh.queue);
2594 return 0;
2595 }
2596 }
2597 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302598 list_del_init(&mReq->queue);
Pavankumar Kondeticbd44db2013-02-06 20:52:46 +05302599done:
2600
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05302601 dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
Pavankumar Kondeticbd44db2013-02-06 20:52:46 +05302602
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302603 if (mReq->req.complete != NULL) {
2604 spin_unlock(mEp->lock);
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302605 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
2606 mReq->req.length)
2607 mEpTemp = &_udc->ep0in;
2608 mReq->req.complete(&mEpTemp->ep, &mReq->req);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302609 spin_lock(mEp->lock);
2610 }
2611 }
David Lopoaa69a802008-11-17 14:14:51 -08002612
Pavankumar Kondetief907482011-05-02 11:56:27 +05302613 if (retval == -EBUSY)
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302614 retval = 0;
2615 if (retval < 0)
David Lopoaa69a802008-11-17 14:14:51 -08002616 dbg_event(_usb_addr(mEp), "DONE", retval);
David Lopoaa69a802008-11-17 14:14:51 -08002617
David Lopoaa69a802008-11-17 14:14:51 -08002618 return retval;
2619}
2620
2621/**
2622 * isr_tr_complete_handler: transaction complete interrupt handler
2623 * @udc: UDC descriptor
2624 *
2625 * This function handles traffic events
2626 */
2627static void isr_tr_complete_handler(struct ci13xxx *udc)
2628__releases(udc->lock)
2629__acquires(udc->lock)
2630{
2631 unsigned i;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302632 u8 tmode = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002633
2634 trace("%p", udc);
2635
2636 if (udc == NULL) {
2637 err("EINVAL");
2638 return;
2639 }
2640
2641 for (i = 0; i < hw_ep_max; i++) {
2642 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302643 int type, num, dir, err = -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -08002644 struct usb_ctrlrequest req;
2645
David Lopoaa69a802008-11-17 14:14:51 -08002646 if (mEp->desc == NULL)
2647 continue; /* not configured */
2648
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302649 if (hw_test_and_clear_complete(i)) {
David Lopoaa69a802008-11-17 14:14:51 -08002650 err = isr_tr_complete_low(mEp);
2651 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
2652 if (err > 0) /* needs status phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302653 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002654 if (err < 0) {
2655 dbg_event(_usb_addr(mEp),
2656 "ERROR", err);
2657 spin_unlock(udc->lock);
2658 if (usb_ep_set_halt(&mEp->ep))
2659 err("error: ep_set_halt");
2660 spin_lock(udc->lock);
2661 }
2662 }
2663 }
2664
2665 if (mEp->type != USB_ENDPOINT_XFER_CONTROL ||
2666 !hw_test_and_clear_setup_status(i))
2667 continue;
2668
2669 if (i != 0) {
2670 warn("ctrl traffic received at endpoint");
2671 continue;
2672 }
2673
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302674 /*
2675 * Flush data and handshake transactions of previous
2676 * setup packet.
2677 */
2678 _ep_nuke(&udc->ep0out);
2679 _ep_nuke(&udc->ep0in);
2680
David Lopoaa69a802008-11-17 14:14:51 -08002681 /* read_setup_packet */
2682 do {
2683 hw_test_and_set_setup_guard();
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302684 memcpy(&req, &mEp->qh.ptr->setup, sizeof(req));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002685 /* Ensure buffer is read before acknowledging to h/w */
2686 mb();
David Lopoaa69a802008-11-17 14:14:51 -08002687 } while (!hw_test_and_clear_setup_guard());
2688
2689 type = req.bRequestType;
2690
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302691 udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
David Lopoaa69a802008-11-17 14:14:51 -08002692
2693 dbg_setup(_usb_addr(mEp), &req);
2694
2695 switch (req.bRequest) {
2696 case USB_REQ_CLEAR_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302697 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
2698 le16_to_cpu(req.wValue) ==
2699 USB_ENDPOINT_HALT) {
2700 if (req.wLength != 0)
David Lopoaa69a802008-11-17 14:14:51 -08002701 break;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302702 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302703 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302704 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302705 if (dir) /* TX */
2706 num += hw_ep_max/2;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302707 if (!udc->ci13xxx_ep[num].wedge) {
2708 spin_unlock(udc->lock);
2709 err = usb_ep_clear_halt(
2710 &udc->ci13xxx_ep[num].ep);
2711 spin_lock(udc->lock);
2712 if (err)
2713 break;
2714 }
2715 err = isr_setup_status_phase(udc);
2716 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
2717 le16_to_cpu(req.wValue) ==
2718 USB_DEVICE_REMOTE_WAKEUP) {
2719 if (req.wLength != 0)
2720 break;
2721 udc->remote_wakeup = 0;
2722 err = isr_setup_status_phase(udc);
2723 } else {
2724 goto delegate;
David Lopoaa69a802008-11-17 14:14:51 -08002725 }
David Lopoaa69a802008-11-17 14:14:51 -08002726 break;
2727 case USB_REQ_GET_STATUS:
2728 if (type != (USB_DIR_IN|USB_RECIP_DEVICE) &&
2729 type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
2730 type != (USB_DIR_IN|USB_RECIP_INTERFACE))
2731 goto delegate;
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302732 if (le16_to_cpu(req.wValue) != 0)
David Lopoaa69a802008-11-17 14:14:51 -08002733 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302734 err = isr_get_status_response(udc, &req);
David Lopoaa69a802008-11-17 14:14:51 -08002735 break;
2736 case USB_REQ_SET_ADDRESS:
2737 if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
2738 goto delegate;
2739 if (le16_to_cpu(req.wLength) != 0 ||
2740 le16_to_cpu(req.wIndex) != 0)
2741 break;
2742 err = hw_usb_set_address((u8)le16_to_cpu(req.wValue));
2743 if (err)
2744 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302745 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002746 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002747 case USB_REQ_SET_CONFIGURATION:
2748 if (type == (USB_DIR_OUT|USB_TYPE_STANDARD))
2749 udc->configured = !!req.wValue;
2750 goto delegate;
David Lopoaa69a802008-11-17 14:14:51 -08002751 case USB_REQ_SET_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302752 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
2753 le16_to_cpu(req.wValue) ==
2754 USB_ENDPOINT_HALT) {
2755 if (req.wLength != 0)
2756 break;
2757 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302758 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302759 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302760 if (dir) /* TX */
2761 num += hw_ep_max/2;
David Lopoaa69a802008-11-17 14:14:51 -08002762
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302763 spin_unlock(udc->lock);
2764 err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
2765 spin_lock(udc->lock);
2766 if (!err)
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302767 isr_setup_status_phase(udc);
2768 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302769 if (req.wLength != 0)
2770 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302771 switch (le16_to_cpu(req.wValue)) {
2772 case USB_DEVICE_REMOTE_WAKEUP:
2773 udc->remote_wakeup = 1;
2774 err = isr_setup_status_phase(udc);
2775 break;
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302776 case USB_DEVICE_B_HNP_ENABLE:
2777 udc->gadget.b_hnp_enable = 1;
2778 err = isr_setup_status_phase(udc);
2779 break;
2780 case USB_DEVICE_A_HNP_SUPPORT:
2781 udc->gadget.a_hnp_support = 1;
2782 err = isr_setup_status_phase(udc);
2783 break;
2784 case USB_DEVICE_A_ALT_HNP_SUPPORT:
2785 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302786 case USB_DEVICE_TEST_MODE:
2787 tmode = le16_to_cpu(req.wIndex) >> 8;
2788 switch (tmode) {
2789 case TEST_J:
2790 case TEST_K:
2791 case TEST_SE0_NAK:
2792 case TEST_PACKET:
2793 case TEST_FORCE_EN:
2794 udc->test_mode = tmode;
2795 err = isr_setup_status_phase(
2796 udc);
2797 break;
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302798 case TEST_OTG_SRP_REQD:
2799 udc->gadget.otg_srp_reqd = 1;
2800 err = isr_setup_status_phase(
2801 udc);
2802 break;
2803 case TEST_OTG_HNP_REQD:
2804 udc->gadget.host_request = 1;
2805 err = isr_setup_status_phase(
2806 udc);
2807 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302808 default:
2809 break;
2810 }
2811 default:
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302812 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302813 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302814 } else {
2815 goto delegate;
2816 }
David Lopoaa69a802008-11-17 14:14:51 -08002817 break;
2818 default:
2819delegate:
2820 if (req.wLength == 0) /* no data phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302821 udc->ep0_dir = TX;
David Lopoaa69a802008-11-17 14:14:51 -08002822
2823 spin_unlock(udc->lock);
2824 err = udc->driver->setup(&udc->gadget, &req);
2825 spin_lock(udc->lock);
2826 break;
2827 }
2828
2829 if (err < 0) {
2830 dbg_event(_usb_addr(mEp), "ERROR", err);
2831
2832 spin_unlock(udc->lock);
2833 if (usb_ep_set_halt(&mEp->ep))
2834 err("error: ep_set_halt");
2835 spin_lock(udc->lock);
2836 }
2837 }
2838}
2839
2840/******************************************************************************
2841 * ENDPT block
2842 *****************************************************************************/
2843/**
2844 * ep_enable: configure endpoint, making it usable
2845 *
2846 * Check usb_ep_enable() at "usb_gadget.h" for details
2847 */
2848static int ep_enable(struct usb_ep *ep,
2849 const struct usb_endpoint_descriptor *desc)
2850{
2851 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302852 int retval = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002853 unsigned long flags;
Vijayavardhan Vennapusa153be582012-10-05 15:36:59 +05302854 unsigned mult = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002855
Anna Perel432367a2012-09-20 10:55:32 +03002856 trace("ep = %p, desc = %p", ep, desc);
David Lopoaa69a802008-11-17 14:14:51 -08002857
2858 if (ep == NULL || desc == NULL)
2859 return -EINVAL;
2860
2861 spin_lock_irqsave(mEp->lock, flags);
2862
2863 /* only internal SW should enable ctrl endpts */
2864
2865 mEp->desc = desc;
2866
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302867 if (!list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08002868 warn("enabling a non-empty endpoint!");
2869
Matthias Kaehlcke15739bb2009-04-15 22:28:41 +02002870 mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX;
2871 mEp->num = usb_endpoint_num(desc);
2872 mEp->type = usb_endpoint_type(desc);
David Lopoaa69a802008-11-17 14:14:51 -08002873
Kuninori Morimoto29cc8892011-08-23 03:12:03 -07002874 mEp->ep.maxpacket = usb_endpoint_maxp(desc);
David Lopoaa69a802008-11-17 14:14:51 -08002875
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302876 dbg_event(_usb_addr(mEp), "ENABLE", 0);
David Lopoaa69a802008-11-17 14:14:51 -08002877
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302878 mEp->qh.ptr->cap = 0;
David Lopof23e6492009-04-16 14:35:24 -07002879
Vijayavardhan Vennapusa153be582012-10-05 15:36:59 +05302880 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302881 mEp->qh.ptr->cap |= QH_IOS;
Vijayavardhan Vennapusa153be582012-10-05 15:36:59 +05302882 } else if (mEp->type == USB_ENDPOINT_XFER_ISOC) {
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302883 mEp->qh.ptr->cap &= ~QH_MULT;
Vijayavardhan Vennapusa153be582012-10-05 15:36:59 +05302884 mult = ((mEp->ep.maxpacket >> QH_MULT_SHIFT) + 1) & 0x03;
2885 mEp->qh.ptr->cap |= (mult << ffs_nr(QH_MULT));
2886 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002887 mEp->qh.ptr->cap |= QH_ZLT;
Vijayavardhan Vennapusa153be582012-10-05 15:36:59 +05302888 }
David Lopoaa69a802008-11-17 14:14:51 -08002889
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302890 mEp->qh.ptr->cap |=
2891 (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
2892 mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */
David Lopoaa69a802008-11-17 14:14:51 -08002893
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002894 /* complete all the updates to ept->head before enabling endpoint*/
2895 mb();
2896
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302897 /*
2898 * Enable endpoints in the HW other than ep0 as ep0
2899 * is always enabled
2900 */
2901 if (mEp->num)
2902 retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type);
David Lopoaa69a802008-11-17 14:14:51 -08002903
2904 spin_unlock_irqrestore(mEp->lock, flags);
2905 return retval;
2906}
2907
2908/**
2909 * ep_disable: endpoint is no longer usable
2910 *
2911 * Check usb_ep_disable() at "usb_gadget.h" for details
2912 */
2913static int ep_disable(struct usb_ep *ep)
2914{
2915 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2916 int direction, retval = 0;
2917 unsigned long flags;
2918
2919 trace("%p", ep);
2920
2921 if (ep == NULL)
2922 return -EINVAL;
2923 else if (mEp->desc == NULL)
2924 return -EBUSY;
2925
2926 spin_lock_irqsave(mEp->lock, flags);
2927
2928 /* only internal SW should disable ctrl endpts */
2929
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05302930 del_timer(&mEp->prime_timer);
2931 mEp->prime_timer_count = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002932 direction = mEp->dir;
2933 do {
2934 dbg_event(_usb_addr(mEp), "DISABLE", 0);
2935
2936 retval |= _ep_nuke(mEp);
2937 retval |= hw_ep_disable(mEp->num, mEp->dir);
2938
2939 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2940 mEp->dir = (mEp->dir == TX) ? RX : TX;
2941
2942 } while (mEp->dir != direction);
2943
2944 mEp->desc = NULL;
Ido Shayevitzf9c56cd2012-02-08 13:56:48 +02002945 mEp->ep.desc = NULL;
Hemant Kumarca8fa3f2012-09-27 16:42:36 -07002946 mEp->ep.maxpacket = USHRT_MAX;
David Lopoaa69a802008-11-17 14:14:51 -08002947
2948 spin_unlock_irqrestore(mEp->lock, flags);
2949 return retval;
2950}
2951
2952/**
2953 * ep_alloc_request: allocate a request object to use with this endpoint
2954 *
2955 * Check usb_ep_alloc_request() at "usb_gadget.h" for details
2956 */
2957static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
2958{
2959 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2960 struct ci13xxx_req *mReq = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002961
2962 trace("%p, %i", ep, gfp_flags);
2963
2964 if (ep == NULL) {
2965 err("EINVAL");
2966 return NULL;
2967 }
2968
David Lopoaa69a802008-11-17 14:14:51 -08002969 mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05302970 if (mReq != NULL) {
2971 INIT_LIST_HEAD(&mReq->queue);
2972 mReq->req.dma = DMA_ADDR_INVALID;
David Lopoaa69a802008-11-17 14:14:51 -08002973
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05302974 mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,
2975 &mReq->dma);
2976 if (mReq->ptr == NULL) {
2977 kfree(mReq);
2978 mReq = NULL;
2979 }
2980 }
David Lopoaa69a802008-11-17 14:14:51 -08002981
2982 dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
2983
David Lopoaa69a802008-11-17 14:14:51 -08002984 return (mReq == NULL) ? NULL : &mReq->req;
2985}
2986
2987/**
2988 * ep_free_request: frees a request object
2989 *
2990 * Check usb_ep_free_request() at "usb_gadget.h" for details
2991 */
2992static void ep_free_request(struct usb_ep *ep, struct usb_request *req)
2993{
2994 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2995 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2996 unsigned long flags;
2997
2998 trace("%p, %p", ep, req);
2999
3000 if (ep == NULL || req == NULL) {
3001 err("EINVAL");
3002 return;
3003 } else if (!list_empty(&mReq->queue)) {
3004 err("EBUSY");
3005 return;
3006 }
3007
3008 spin_lock_irqsave(mEp->lock, flags);
3009
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05303010 if (mReq->ptr)
3011 dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma);
David Lopoaa69a802008-11-17 14:14:51 -08003012 kfree(mReq);
3013
3014 dbg_event(_usb_addr(mEp), "FREE", 0);
3015
3016 spin_unlock_irqrestore(mEp->lock, flags);
3017}
3018
3019/**
3020 * ep_queue: queues (submits) an I/O request to an endpoint
3021 *
3022 * Check usb_ep_queue()* at usb_gadget.h" for details
3023 */
3024static int ep_queue(struct usb_ep *ep, struct usb_request *req,
3025 gfp_t __maybe_unused gfp_flags)
3026{
3027 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
3028 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
3029 int retval = 0;
3030 unsigned long flags;
Anji jonnala6c174d42011-07-13 13:01:47 +05303031 struct ci13xxx *udc = _udc;
David Lopoaa69a802008-11-17 14:14:51 -08003032
3033 trace("%p, %p, %X", ep, req, gfp_flags);
3034
3035 if (ep == NULL || req == NULL || mEp->desc == NULL)
3036 return -EINVAL;
3037
Chiranjeevi Velempati46874732013-01-31 14:35:46 +05303038 if (!udc->softconnect)
3039 return -ENODEV;
3040
David Lopoaa69a802008-11-17 14:14:51 -08003041 spin_lock_irqsave(mEp->lock, flags);
3042
Anji jonnala6c174d42011-07-13 13:01:47 +05303043 if (!udc->configured && mEp->type !=
3044 USB_ENDPOINT_XFER_CONTROL) {
3045 spin_unlock_irqrestore(mEp->lock, flags);
3046 trace("usb is not configured"
3047 "ept #%d, ept name#%s\n",
3048 mEp->num, mEp->ep.name);
3049 return -ESHUTDOWN;
3050 }
3051
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05303052 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
3053 if (req->length)
3054 mEp = (_udc->ep0_dir == RX) ?
3055 &_udc->ep0out : &_udc->ep0in;
3056 if (!list_empty(&mEp->qh.queue)) {
3057 _ep_nuke(mEp);
3058 retval = -EOVERFLOW;
3059 warn("endpoint ctrl %X nuked", _usb_addr(mEp));
3060 }
David Lopoaa69a802008-11-17 14:14:51 -08003061 }
3062
3063 /* first nuke then test link, e.g. previous status has not sent */
3064 if (!list_empty(&mReq->queue)) {
3065 retval = -EBUSY;
3066 err("request already in queue");
3067 goto done;
3068 }
Pavankumar Kondeticbd44db2013-02-06 20:52:46 +05303069 if (mEp->multi_req) {
3070 retval = -EAGAIN;
3071 err("Large request is in progress. come again");
3072 goto done;
3073 }
David Lopoaa69a802008-11-17 14:14:51 -08003074
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05303075 if (req->length > (4 * CI13XXX_PAGE_SIZE)) {
Pavankumar Kondeticbd44db2013-02-06 20:52:46 +05303076 if (!list_empty(&mEp->qh.queue)) {
3077 retval = -EAGAIN;
3078 err("Queue is busy. Large req is not allowed");
3079 goto done;
3080 }
3081 if ((mEp->type != USB_ENDPOINT_XFER_BULK) ||
3082 (mEp->dir != RX)) {
3083 retval = -EINVAL;
3084 err("Larger req is supported only for Bulk OUT");
3085 goto done;
3086 }
3087 mEp->multi_req = true;
3088 mReq->multi.len = req->length;
3089 mReq->multi.buf = req->buf;
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05303090 req->length = (4 * CI13XXX_PAGE_SIZE);
Pavankumar Kondetie0bf8262013-02-07 20:48:34 +05303091 }
David Lopoaa69a802008-11-17 14:14:51 -08003092
3093 dbg_queue(_usb_addr(mEp), req, retval);
3094
3095 /* push request */
3096 mReq->req.status = -EINPROGRESS;
3097 mReq->req.actual = 0;
David Lopoaa69a802008-11-17 14:14:51 -08003098
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05303099 retval = _hardware_enqueue(mEp, mReq);
Artem Leonenkod9bb9c12010-12-14 23:45:50 -08003100
3101 if (retval == -EALREADY) {
David Lopoaa69a802008-11-17 14:14:51 -08003102 dbg_event(_usb_addr(mEp), "QUEUE", retval);
3103 retval = 0;
3104 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05303105 if (!retval)
3106 list_add_tail(&mReq->queue, &mEp->qh.queue);
Pavankumar Kondeticbd44db2013-02-06 20:52:46 +05303107 else if (mEp->multi_req)
3108 mEp->multi_req = false;
David Lopoaa69a802008-11-17 14:14:51 -08003109
3110 done:
3111 spin_unlock_irqrestore(mEp->lock, flags);
3112 return retval;
3113}
3114
3115/**
3116 * ep_dequeue: dequeues (cancels, unlinks) an I/O request from an endpoint
3117 *
3118 * Check usb_ep_dequeue() at "usb_gadget.h" for details
3119 */
3120static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
3121{
3122 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05303123 struct ci13xxx_ep *mEpTemp = mEp;
David Lopoaa69a802008-11-17 14:14:51 -08003124 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
3125 unsigned long flags;
3126
3127 trace("%p, %p", ep, req);
3128
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05303129 if (ep == NULL || req == NULL || mReq->req.status != -EALREADY ||
3130 mEp->desc == NULL || list_empty(&mReq->queue) ||
3131 list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08003132 return -EINVAL;
3133
3134 spin_lock_irqsave(mEp->lock, flags);
3135
3136 dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
3137
Mayank Rana0c1b8b22012-07-04 16:17:38 +05303138 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL)) {
3139 hw_ep_flush(_udc->ep0out.num, RX);
3140 hw_ep_flush(_udc->ep0in.num, TX);
3141 } else {
3142 hw_ep_flush(mEp->num, mEp->dir);
3143 }
David Lopoaa69a802008-11-17 14:14:51 -08003144
3145 /* pop request */
3146 list_del_init(&mReq->queue);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05303147 if (mReq->map) {
3148 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
3149 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02003150 mReq->req.dma = DMA_ADDR_INVALID;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05303151 mReq->map = 0;
3152 }
David Lopoaa69a802008-11-17 14:14:51 -08003153 req->status = -ECONNRESET;
Pavankumar Kondeticbd44db2013-02-06 20:52:46 +05303154 if (mEp->multi_req) {
3155 restore_original_req(mReq);
3156 mEp->multi_req = false;
3157 }
David Lopoaa69a802008-11-17 14:14:51 -08003158
Artem Leonenko7c25a822010-12-14 23:46:55 -08003159 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08003160 spin_unlock(mEp->lock);
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05303161 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
3162 mReq->req.length)
3163 mEpTemp = &_udc->ep0in;
3164 mReq->req.complete(&mEpTemp->ep, &mReq->req);
Mayank Rana0c1b8b22012-07-04 16:17:38 +05303165 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
3166 mReq->req.complete = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08003167 spin_lock(mEp->lock);
3168 }
3169
3170 spin_unlock_irqrestore(mEp->lock, flags);
3171 return 0;
3172}
3173
Bar Weiner0fc137a2012-03-28 16:58:09 +02003174static int is_sps_req(struct ci13xxx_req *mReq)
3175{
3176 return (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID &&
3177 mReq->req.udc_priv & MSM_SPS_MODE);
3178}
3179
David Lopoaa69a802008-11-17 14:14:51 -08003180/**
3181 * ep_set_halt: sets the endpoint halt feature
3182 *
3183 * Check usb_ep_set_halt() at "usb_gadget.h" for details
3184 */
3185static int ep_set_halt(struct usb_ep *ep, int value)
3186{
3187 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
3188 int direction, retval = 0;
3189 unsigned long flags;
3190
3191 trace("%p, %i", ep, value);
3192
3193 if (ep == NULL || mEp->desc == NULL)
3194 return -EINVAL;
3195
3196 spin_lock_irqsave(mEp->lock, flags);
3197
3198#ifndef STALL_IN
3199 /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
3200 if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX &&
Bar Weiner0fc137a2012-03-28 16:58:09 +02003201 !list_empty(&mEp->qh.queue) &&
3202 !is_sps_req(list_entry(mEp->qh.queue.next, struct ci13xxx_req,
3203 queue))){
David Lopoaa69a802008-11-17 14:14:51 -08003204 spin_unlock_irqrestore(mEp->lock, flags);
3205 return -EAGAIN;
3206 }
3207#endif
3208
3209 direction = mEp->dir;
3210 do {
3211 dbg_event(_usb_addr(mEp), "HALT", value);
3212 retval |= hw_ep_set_halt(mEp->num, mEp->dir, value);
3213
3214 if (!value)
3215 mEp->wedge = 0;
3216
3217 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
3218 mEp->dir = (mEp->dir == TX) ? RX : TX;
3219
3220 } while (mEp->dir != direction);
3221
3222 spin_unlock_irqrestore(mEp->lock, flags);
3223 return retval;
3224}
3225
3226/**
3227 * ep_set_wedge: sets the halt feature and ignores clear requests
3228 *
3229 * Check usb_ep_set_wedge() at "usb_gadget.h" for details
3230 */
3231static int ep_set_wedge(struct usb_ep *ep)
3232{
3233 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
3234 unsigned long flags;
3235
3236 trace("%p", ep);
3237
3238 if (ep == NULL || mEp->desc == NULL)
3239 return -EINVAL;
3240
3241 spin_lock_irqsave(mEp->lock, flags);
3242
3243 dbg_event(_usb_addr(mEp), "WEDGE", 0);
3244 mEp->wedge = 1;
3245
3246 spin_unlock_irqrestore(mEp->lock, flags);
3247
3248 return usb_ep_set_halt(ep);
3249}
3250
3251/**
3252 * ep_fifo_flush: flushes contents of a fifo
3253 *
3254 * Check usb_ep_fifo_flush() at "usb_gadget.h" for details
3255 */
3256static void ep_fifo_flush(struct usb_ep *ep)
3257{
3258 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
3259 unsigned long flags;
3260
3261 trace("%p", ep);
3262
3263 if (ep == NULL) {
3264 err("%02X: -EINVAL", _usb_addr(mEp));
3265 return;
3266 }
3267
3268 spin_lock_irqsave(mEp->lock, flags);
3269
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05303270 del_timer(&mEp->prime_timer);
3271 mEp->prime_timer_count = 0;
David Lopoaa69a802008-11-17 14:14:51 -08003272 dbg_event(_usb_addr(mEp), "FFLUSH", 0);
3273 hw_ep_flush(mEp->num, mEp->dir);
3274
3275 spin_unlock_irqrestore(mEp->lock, flags);
3276}
3277
3278/**
3279 * Endpoint-specific part of the API to the USB controller hardware
3280 * Check "usb_gadget.h" for details
3281 */
3282static const struct usb_ep_ops usb_ep_ops = {
3283 .enable = ep_enable,
3284 .disable = ep_disable,
3285 .alloc_request = ep_alloc_request,
3286 .free_request = ep_free_request,
3287 .queue = ep_queue,
3288 .dequeue = ep_dequeue,
3289 .set_halt = ep_set_halt,
3290 .set_wedge = ep_set_wedge,
3291 .fifo_flush = ep_fifo_flush,
3292};
3293
3294/******************************************************************************
3295 * GADGET block
3296 *****************************************************************************/
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303297static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
3298{
3299 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
3300 unsigned long flags;
3301 int gadget_ready = 0;
3302
3303 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS))
3304 return -EOPNOTSUPP;
3305
3306 spin_lock_irqsave(udc->lock, flags);
3307 udc->vbus_active = is_active;
3308 if (udc->driver)
3309 gadget_ready = 1;
3310 spin_unlock_irqrestore(udc->lock, flags);
3311
3312 if (gadget_ready) {
3313 if (is_active) {
Pavankumar Kondetic0360192010-12-07 17:54:04 +05303314 pm_runtime_get_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303315 hw_device_reset(udc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003316 if (udc->softconnect)
3317 hw_device_state(udc->ep0out.qh.dma);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303318 } else {
3319 hw_device_state(0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303320 _gadget_stop_activity(&udc->gadget);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303321 if (udc->udc_driver->notify_event)
3322 udc->udc_driver->notify_event(udc,
Amit Blay9b033682012-05-24 16:59:23 +03003323 CI13XXX_CONTROLLER_DISCONNECT_EVENT);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05303324 pm_runtime_put_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303325 }
3326 }
3327
3328 return 0;
3329}
3330
Pavankumar Kondetid8608522011-05-04 10:19:47 +05303331static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
3332{
3333 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
3334
3335 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02003336 return usb_phy_set_power(udc->transceiver, mA);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05303337 return -ENOTSUPP;
3338}
3339
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003340static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_active)
3341{
3342 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
3343 unsigned long flags;
3344
3345 spin_lock_irqsave(udc->lock, flags);
3346 udc->softconnect = is_active;
3347 if (((udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) &&
3348 !udc->vbus_active) || !udc->driver) {
3349 spin_unlock_irqrestore(udc->lock, flags);
3350 return 0;
3351 }
3352 spin_unlock_irqrestore(udc->lock, flags);
3353
Vamsi Krishna1a1684b2013-03-02 16:14:52 -08003354 if (is_active)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003355 hw_device_state(udc->ep0out.qh.dma);
Pavankumar Kondetib7f53dc2011-08-23 12:40:33 +05303356 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003357 hw_device_state(0);
Pavankumar Kondetib7f53dc2011-08-23 12:40:33 +05303358
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003359 return 0;
3360}
3361
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003362static int ci13xxx_start(struct usb_gadget_driver *driver,
3363 int (*bind)(struct usb_gadget *));
3364static int ci13xxx_stop(struct usb_gadget_driver *driver);
Stephen Boyd42517402013-01-14 16:41:42 -08003365
David Lopoaa69a802008-11-17 14:14:51 -08003366/**
3367 * Device operations part of the API to the USB controller hardware,
3368 * which don't involve endpoints (or i/o)
3369 * Check "usb_gadget.h" for details
3370 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303371static const struct usb_gadget_ops usb_gadget_ops = {
3372 .vbus_session = ci13xxx_vbus_session,
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05303373 .wakeup = ci13xxx_wakeup,
Pavankumar Kondetid8608522011-05-04 10:19:47 +05303374 .vbus_draw = ci13xxx_vbus_draw,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003375 .pullup = ci13xxx_pullup,
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003376 .start = ci13xxx_start,
3377 .stop = ci13xxx_stop,
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303378};
David Lopoaa69a802008-11-17 14:14:51 -08003379
3380/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003381 * ci13xxx_start: register a gadget driver
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003382 * @driver: the driver being registered
3383 * @bind: the driver's bind callback
David Lopoaa69a802008-11-17 14:14:51 -08003384 *
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003385 * Check ci13xxx_start() at <linux/usb/gadget.h> for details.
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003386 * Interrupts are enabled here.
David Lopoaa69a802008-11-17 14:14:51 -08003387 */
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003388static int ci13xxx_start(struct usb_gadget_driver *driver,
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003389 int (*bind)(struct usb_gadget *))
David Lopoaa69a802008-11-17 14:14:51 -08003390{
3391 struct ci13xxx *udc = _udc;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303392 unsigned long flags;
3393 int i, j;
David Lopoaa69a802008-11-17 14:14:51 -08003394 int retval = -ENOMEM;
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303395 bool put = false;
David Lopoaa69a802008-11-17 14:14:51 -08003396
3397 trace("%p", driver);
3398
3399 if (driver == NULL ||
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003400 bind == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08003401 driver->setup == NULL ||
Marc Kleine-Budde7bb4fdc2011-10-10 18:38:09 +02003402 driver->disconnect == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08003403 return -EINVAL;
3404 else if (udc == NULL)
3405 return -ENODEV;
3406 else if (udc->driver != NULL)
3407 return -EBUSY;
3408
3409 /* alloc resources */
3410 udc->qh_pool = dma_pool_create("ci13xxx_qh", &udc->gadget.dev,
3411 sizeof(struct ci13xxx_qh),
Artem Leonenko0a313c42010-12-14 23:47:06 -08003412 64, CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08003413 if (udc->qh_pool == NULL)
3414 return -ENOMEM;
3415
3416 udc->td_pool = dma_pool_create("ci13xxx_td", &udc->gadget.dev,
3417 sizeof(struct ci13xxx_td),
Artem Leonenko0a313c42010-12-14 23:47:06 -08003418 64, CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08003419 if (udc->td_pool == NULL) {
3420 dma_pool_destroy(udc->qh_pool);
3421 udc->qh_pool = NULL;
3422 return -ENOMEM;
3423 }
3424
3425 spin_lock_irqsave(udc->lock, flags);
3426
3427 info("hw_ep_max = %d", hw_ep_max);
3428
David Lopoaa69a802008-11-17 14:14:51 -08003429 udc->gadget.dev.driver = NULL;
3430
3431 retval = 0;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303432 for (i = 0; i < hw_ep_max/2; i++) {
3433 for (j = RX; j <= TX; j++) {
3434 int k = i + j * hw_ep_max/2;
3435 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
David Lopoaa69a802008-11-17 14:14:51 -08003436
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303437 scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
3438 (j == TX) ? "in" : "out");
David Lopoaa69a802008-11-17 14:14:51 -08003439
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303440 mEp->lock = udc->lock;
3441 mEp->device = &udc->gadget.dev;
3442 mEp->td_pool = udc->td_pool;
David Lopoaa69a802008-11-17 14:14:51 -08003443
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303444 mEp->ep.name = mEp->name;
3445 mEp->ep.ops = &usb_ep_ops;
Hemant Kumarca8fa3f2012-09-27 16:42:36 -07003446 mEp->ep.maxpacket =
3447 k ? USHRT_MAX : CTRL_PAYLOAD_MAX;
David Lopoaa69a802008-11-17 14:14:51 -08003448
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303449 INIT_LIST_HEAD(&mEp->qh.queue);
Pavankumar Kondeti0a91efa2010-12-07 17:54:00 +05303450 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303451 mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
3452 &mEp->qh.dma);
Pavankumar Kondeti0a91efa2010-12-07 17:54:00 +05303453 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303454 if (mEp->qh.ptr == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08003455 retval = -ENOMEM;
3456 else
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303457 memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
3458
3459 /* skip ep0 out and in endpoints */
3460 if (i == 0)
3461 continue;
3462
David Lopoaa69a802008-11-17 14:14:51 -08003463 list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303464 }
David Lopoaa69a802008-11-17 14:14:51 -08003465 }
3466 if (retval)
3467 goto done;
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05303468 spin_unlock_irqrestore(udc->lock, flags);
Felipe Balbi877c1f52011-06-29 16:41:57 +03003469 udc->ep0out.ep.desc = &ctrl_endpt_out_desc;
3470 retval = usb_ep_enable(&udc->ep0out.ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05303471 if (retval)
3472 return retval;
Felipe Balbi877c1f52011-06-29 16:41:57 +03003473
3474 udc->ep0in.ep.desc = &ctrl_endpt_in_desc;
3475 retval = usb_ep_enable(&udc->ep0in.ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05303476 if (retval)
3477 return retval;
3478 spin_lock_irqsave(udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08003479
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303480 udc->gadget.ep0 = &udc->ep0in.ep;
David Lopoaa69a802008-11-17 14:14:51 -08003481 /* bind gadget */
3482 driver->driver.bus = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08003483 udc->gadget.dev.driver = &driver->driver;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003484 udc->softconnect = 1;
David Lopoaa69a802008-11-17 14:14:51 -08003485
3486 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondeti98853282011-11-24 09:01:54 +05303487 pm_runtime_get_sync(&udc->gadget.dev);
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003488 retval = bind(&udc->gadget); /* MAY SLEEP */
David Lopoaa69a802008-11-17 14:14:51 -08003489 spin_lock_irqsave(udc->lock, flags);
3490
3491 if (retval) {
David Lopoaa69a802008-11-17 14:14:51 -08003492 udc->gadget.dev.driver = NULL;
3493 goto done;
3494 }
3495
Pavankumar Kondeti49d3df52011-01-11 09:19:21 +05303496 udc->driver = driver;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303497 if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
3498 if (udc->vbus_active) {
3499 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
3500 hw_device_reset(udc);
3501 } else {
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303502 put = true;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303503 goto done;
3504 }
3505 }
3506
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303507 if (!udc->softconnect) {
3508 put = true;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003509 goto done;
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303510 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003511
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303512 retval = hw_device_state(udc->ep0out.qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08003513
3514 done:
3515 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303516 if (retval || put)
Pavankumar Kondeti98853282011-11-24 09:01:54 +05303517 pm_runtime_put_sync(&udc->gadget.dev);
Ido Shayevitzab601632012-09-16 15:11:26 +03003518
3519 if (udc->udc_driver->notify_event)
3520 udc->udc_driver->notify_event(udc,
3521 CI13XXX_CONTROLLER_UDC_STARTED_EVENT);
3522
David Lopoaa69a802008-11-17 14:14:51 -08003523 return retval;
3524}
David Lopoaa69a802008-11-17 14:14:51 -08003525
3526/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003527 * ci13xxx_stop: unregister a gadget driver
David Lopoaa69a802008-11-17 14:14:51 -08003528 *
3529 * Check usb_gadget_unregister_driver() at "usb_gadget.h" for details
3530 */
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003531static int ci13xxx_stop(struct usb_gadget_driver *driver)
David Lopoaa69a802008-11-17 14:14:51 -08003532{
3533 struct ci13xxx *udc = _udc;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303534 unsigned long i, flags;
David Lopoaa69a802008-11-17 14:14:51 -08003535
3536 trace("%p", driver);
3537
3538 if (driver == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08003539 driver->unbind == NULL ||
3540 driver->setup == NULL ||
3541 driver->disconnect == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08003542 driver != udc->driver)
3543 return -EINVAL;
3544
3545 spin_lock_irqsave(udc->lock, flags);
3546
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303547 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) ||
3548 udc->vbus_active) {
3549 hw_device_state(0);
Marc Kleine-Buddefd537c02011-10-10 18:38:07 +02003550 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303551 _gadget_stop_activity(&udc->gadget);
Marc Kleine-Buddefd537c02011-10-10 18:38:07 +02003552 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05303553 pm_runtime_put(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303554 }
David Lopoaa69a802008-11-17 14:14:51 -08003555
3556 /* unbind gadget */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303557 spin_unlock_irqrestore(udc->lock, flags);
3558 driver->unbind(&udc->gadget); /* MAY SLEEP */
3559 spin_lock_irqsave(udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08003560
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303561 udc->gadget.dev.driver = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08003562
3563 /* free resources */
3564 for (i = 0; i < hw_ep_max; i++) {
3565 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
3566
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303567 if (!list_empty(&mEp->ep.ep_list))
David Lopoaa69a802008-11-17 14:14:51 -08003568 list_del_init(&mEp->ep.ep_list);
3569
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303570 if (mEp->qh.ptr != NULL)
3571 dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08003572 }
3573
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303574 udc->gadget.ep0 = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08003575 udc->driver = NULL;
3576
3577 spin_unlock_irqrestore(udc->lock, flags);
3578
3579 if (udc->td_pool != NULL) {
3580 dma_pool_destroy(udc->td_pool);
3581 udc->td_pool = NULL;
3582 }
3583 if (udc->qh_pool != NULL) {
3584 dma_pool_destroy(udc->qh_pool);
3585 udc->qh_pool = NULL;
3586 }
3587
3588 return 0;
3589}
David Lopoaa69a802008-11-17 14:14:51 -08003590
3591/******************************************************************************
3592 * BUS block
3593 *****************************************************************************/
3594/**
3595 * udc_irq: global interrupt handler
3596 *
3597 * This function returns IRQ_HANDLED if the IRQ has been handled
3598 * It locks access to registers
3599 */
3600static irqreturn_t udc_irq(void)
3601{
3602 struct ci13xxx *udc = _udc;
3603 irqreturn_t retval;
3604 u32 intr;
3605
3606 trace();
3607
3608 if (udc == NULL) {
3609 err("ENODEV");
3610 return IRQ_HANDLED;
3611 }
3612
3613 spin_lock(udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303614
3615 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) {
3616 if (hw_cread(CAP_USBMODE, USBMODE_CM) !=
3617 USBMODE_CM_DEVICE) {
3618 spin_unlock(udc->lock);
3619 return IRQ_NONE;
3620 }
3621 }
David Lopoaa69a802008-11-17 14:14:51 -08003622 intr = hw_test_and_clear_intr_active();
3623 if (intr) {
3624 isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intr;
3625 isr_statistics.hndl.idx &= ISR_MASK;
3626 isr_statistics.hndl.cnt++;
3627
3628 /* order defines priority - do NOT change it */
3629 if (USBi_URI & intr) {
3630 isr_statistics.uri++;
3631 isr_reset_handler(udc);
3632 }
3633 if (USBi_PCI & intr) {
3634 isr_statistics.pci++;
Amit Blay6fa647a2012-05-24 14:12:08 +03003635 isr_resume_handler(udc);
David Lopoaa69a802008-11-17 14:14:51 -08003636 }
3637 if (USBi_UEI & intr)
3638 isr_statistics.uei++;
3639 if (USBi_UI & intr) {
3640 isr_statistics.ui++;
3641 isr_tr_complete_handler(udc);
3642 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05303643 if (USBi_SLI & intr) {
Amit Blay6fa647a2012-05-24 14:12:08 +03003644 isr_suspend_handler(udc);
David Lopoaa69a802008-11-17 14:14:51 -08003645 isr_statistics.sli++;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05303646 }
David Lopoaa69a802008-11-17 14:14:51 -08003647 retval = IRQ_HANDLED;
3648 } else {
3649 isr_statistics.none++;
3650 retval = IRQ_NONE;
3651 }
3652 spin_unlock(udc->lock);
3653
3654 return retval;
3655}
3656
3657/**
3658 * udc_release: driver release function
3659 * @dev: device
3660 *
3661 * Currently does nothing
3662 */
3663static void udc_release(struct device *dev)
3664{
3665 trace("%p", dev);
3666
3667 if (dev == NULL)
3668 err("EINVAL");
3669}
3670
3671/**
3672 * udc_probe: parent probe must call this to initialize UDC
3673 * @dev: parent device
3674 * @regs: registers base address
3675 * @name: driver name
3676 *
3677 * This function returns an error code
3678 * No interrupts active, the IRQ has not been requested yet
3679 * Kernel assumes 32-bit DMA operations by default, no need to dma_set_mask
3680 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303681static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
3682 void __iomem *regs)
David Lopoaa69a802008-11-17 14:14:51 -08003683{
3684 struct ci13xxx *udc;
Pavankumar Kondetibb4cd9e2013-01-11 11:34:16 +05303685 struct ci13xxx_platform_data *pdata;
Lena Salmana7a05202012-03-19 10:39:44 +02003686 int retval = 0, i;
David Lopoaa69a802008-11-17 14:14:51 -08003687
Marc Kleine-Budde194fa472011-10-10 18:38:08 +02003688 trace("%p, %p, %p", dev, regs, driver->name);
David Lopoaa69a802008-11-17 14:14:51 -08003689
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303690 if (dev == NULL || regs == NULL || driver == NULL ||
3691 driver->name == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08003692 return -EINVAL;
3693
3694 udc = kzalloc(sizeof(struct ci13xxx), GFP_KERNEL);
3695 if (udc == NULL)
3696 return -ENOMEM;
3697
3698 udc->lock = &udc_lock;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303699 udc->regs = regs;
3700 udc->udc_driver = driver;
David Lopoaa69a802008-11-17 14:14:51 -08003701
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303702 udc->gadget.ops = &usb_gadget_ops;
David Lopoaa69a802008-11-17 14:14:51 -08003703 udc->gadget.speed = USB_SPEED_UNKNOWN;
Michal Nazarewiczd327ab52011-11-19 18:27:37 +01003704 udc->gadget.max_speed = USB_SPEED_HIGH;
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05303705 if (udc->udc_driver->flags & CI13XXX_IS_OTG)
3706 udc->gadget.is_otg = 1;
3707 else
3708 udc->gadget.is_otg = 0;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303709 udc->gadget.name = driver->name;
David Lopoaa69a802008-11-17 14:14:51 -08003710
3711 INIT_LIST_HEAD(&udc->gadget.ep_list);
3712 udc->gadget.ep0 = NULL;
3713
Pavankumar Kondetibb4cd9e2013-01-11 11:34:16 +05303714 pdata = dev->platform_data;
Ido Shayevitz4314d1e2012-06-26 15:21:09 +03003715 if (pdata)
3716 udc->gadget.usb_core_id = pdata->usb_core_id;
3717
Kay Sievers5df58522009-03-24 16:38:23 -07003718 dev_set_name(&udc->gadget.dev, "gadget");
David Lopoaa69a802008-11-17 14:14:51 -08003719 udc->gadget.dev.dma_mask = dev->dma_mask;
Pavankumar Kondeti61948ee2010-12-07 17:54:01 +05303720 udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
David Lopoaa69a802008-11-17 14:14:51 -08003721 udc->gadget.dev.parent = dev;
3722 udc->gadget.dev.release = udc_release;
3723
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303724 if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
Steve Mucklef132c6c2012-06-06 18:30:57 -07003725 udc->transceiver = usb_get_transceiver();
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303726 if (udc->transceiver == NULL) {
3727 retval = -ENODEV;
3728 goto free_udc;
3729 }
3730 }
3731
Amit Blayfd075dd2012-06-26 13:12:50 +03003732 INIT_DELAYED_WORK(&udc->rw_work, usb_do_remote_wakeup);
3733
Pavankumar Kondetic898b7d2012-05-16 11:54:35 +05303734 retval = hw_device_init(regs);
3735 if (retval < 0)
3736 goto put_transceiver;
3737
3738 for (i = 0; i < hw_ep_max; i++) {
3739 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
3740 INIT_LIST_HEAD(&mEp->ep.ep_list);
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05303741 setup_timer(&mEp->prime_timer, ep_prime_timer_func,
3742 (unsigned long) mEp);
Pavankumar Kondetic898b7d2012-05-16 11:54:35 +05303743 }
3744
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303745 if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) {
3746 retval = hw_device_reset(udc);
3747 if (retval)
3748 goto put_transceiver;
3749 }
3750
David Lopoaa69a802008-11-17 14:14:51 -08003751 retval = device_register(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303752 if (retval) {
3753 put_device(&udc->gadget.dev);
3754 goto put_transceiver;
3755 }
David Lopoaa69a802008-11-17 14:14:51 -08003756
3757#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3758 retval = dbg_create_files(&udc->gadget.dev);
3759#endif
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303760 if (retval)
3761 goto unreg_device;
3762
3763 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02003764 retval = otg_set_peripheral(udc->transceiver->otg,
3765 &udc->gadget);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303766 if (retval)
3767 goto remove_dbg;
David Lopoaa69a802008-11-17 14:14:51 -08003768 }
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003769
3770 retval = usb_add_gadget_udc(dev, &udc->gadget);
3771 if (retval)
3772 goto remove_trans;
3773
Pavankumar Kondetic0360192010-12-07 17:54:04 +05303774 pm_runtime_no_callbacks(&udc->gadget.dev);
3775 pm_runtime_enable(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08003776
Rajkumar Raghupathyc01decf2013-03-29 17:39:58 +05303777 retval = register_trace_usb_daytona_invalid_access(dump_usb_info,
3778 NULL);
3779 if (retval)
3780 pr_err("Registering trace failed\n");
3781
David Lopoaa69a802008-11-17 14:14:51 -08003782 _udc = udc;
3783 return retval;
3784
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003785remove_trans:
3786 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02003787 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02003788 usb_put_transceiver(udc->transceiver);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003789 }
3790
David Lopoaa69a802008-11-17 14:14:51 -08003791 err("error = %i", retval);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303792remove_dbg:
3793#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3794 dbg_remove_files(&udc->gadget.dev);
3795#endif
3796unreg_device:
3797 device_unregister(&udc->gadget.dev);
3798put_transceiver:
3799 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02003800 usb_put_transceiver(udc->transceiver);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303801free_udc:
David Lopoaa69a802008-11-17 14:14:51 -08003802 kfree(udc);
3803 _udc = NULL;
3804 return retval;
3805}
3806
3807/**
3808 * udc_remove: parent remove must call this to remove UDC
3809 *
3810 * No interrupts active, the IRQ has been released
3811 */
3812static void udc_remove(void)
3813{
3814 struct ci13xxx *udc = _udc;
Rajkumar Raghupathyc01decf2013-03-29 17:39:58 +05303815 int retval;
David Lopoaa69a802008-11-17 14:14:51 -08003816
3817 if (udc == NULL) {
3818 err("EINVAL");
3819 return;
3820 }
Rajkumar Raghupathyc01decf2013-03-29 17:39:58 +05303821 retval = unregister_trace_usb_daytona_invalid_access(dump_usb_info,
3822 NULL);
3823 if (retval)
3824 pr_err("Unregistering trace failed\n");
3825
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003826 usb_del_gadget_udc(&udc->gadget);
David Lopoaa69a802008-11-17 14:14:51 -08003827
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303828 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02003829 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02003830 usb_put_transceiver(udc->transceiver);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303831 }
David Lopoaa69a802008-11-17 14:14:51 -08003832#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3833 dbg_remove_files(&udc->gadget.dev);
3834#endif
3835 device_unregister(&udc->gadget.dev);
3836
3837 kfree(udc);
3838 _udc = NULL;
3839}