blob: f82c2fee3e3054a33cffc90b4df4a60decaca00b [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>
57#include <linux/interrupt.h>
David Lopoaa69a802008-11-17 14:14:51 -080058#include <linux/io.h>
59#include <linux/irq.h>
60#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090061#include <linux/slab.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070062#include <linux/module.h>
Pavankumar Kondetic0360192010-12-07 17:54:04 +053063#include <linux/pm_runtime.h>
David Lopoaa69a802008-11-17 14:14:51 -080064#include <linux/usb/ch9.h>
65#include <linux/usb/gadget.h>
Pavankumar Kondetif01ef572010-12-07 17:54:02 +053066#include <linux/usb/otg.h>
Ido Shayevitzd1cb16c2012-03-28 18:57:47 +020067#include <linux/usb/msm_hsusb.h>
David Lopoaa69a802008-11-17 14:14:51 -080068
69#include "ci13xxx_udc.h"
70
71
72/******************************************************************************
73 * DEFINE
74 *****************************************************************************/
Michael Grzeschik954aad82011-10-10 18:38:06 +020075
76#define DMA_ADDR_INVALID (~(dma_addr_t)0)
77
David Lopoaa69a802008-11-17 14:14:51 -080078/* ctrl register bank access */
79static DEFINE_SPINLOCK(udc_lock);
80
David Lopoaa69a802008-11-17 14:14:51 -080081/* control endpoint description */
82static const struct usb_endpoint_descriptor
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +053083ctrl_endpt_out_desc = {
David Lopoaa69a802008-11-17 14:14:51 -080084 .bLength = USB_DT_ENDPOINT_SIZE,
85 .bDescriptorType = USB_DT_ENDPOINT,
86
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +053087 .bEndpointAddress = USB_DIR_OUT,
88 .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
89 .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
90};
91
92static const struct usb_endpoint_descriptor
93ctrl_endpt_in_desc = {
94 .bLength = USB_DT_ENDPOINT_SIZE,
95 .bDescriptorType = USB_DT_ENDPOINT,
96
97 .bEndpointAddress = USB_DIR_IN,
David Lopoaa69a802008-11-17 14:14:51 -080098 .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
99 .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
100};
101
102/* UDC descriptor */
103static struct ci13xxx *_udc;
104
105/* Interrupt statistics */
106#define ISR_MASK 0x1F
107static struct {
108 u32 test;
109 u32 ui;
110 u32 uei;
111 u32 pci;
112 u32 uri;
113 u32 sli;
114 u32 none;
115 struct {
116 u32 cnt;
117 u32 buf[ISR_MASK+1];
118 u32 idx;
119 } hndl;
120} isr_statistics;
121
122/**
123 * ffs_nr: find first (least significant) bit set
124 * @x: the word to search
125 *
126 * This function returns bit number (instead of position)
127 */
128static int ffs_nr(u32 x)
129{
130 int n = ffs(x);
131
132 return n ? n-1 : 32;
133}
134
135/******************************************************************************
136 * HW block
137 *****************************************************************************/
138/* register bank descriptor */
139static struct {
140 unsigned lpm; /* is LPM? */
141 void __iomem *abs; /* bus map offset */
142 void __iomem *cap; /* bus map offset + CAP offset + CAP data */
143 size_t size; /* bank size */
144} hw_bank;
145
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530146/* MSM specific */
147#define ABS_AHBBURST (0x0090UL)
148#define ABS_AHBMODE (0x0098UL)
David Lopoaa69a802008-11-17 14:14:51 -0800149/* UDC register map */
150#define ABS_CAPLENGTH (0x100UL)
151#define ABS_HCCPARAMS (0x108UL)
152#define ABS_DCCPARAMS (0x124UL)
153#define ABS_TESTMODE (hw_bank.lpm ? 0x0FCUL : 0x138UL)
154/* offset to CAPLENTGH (addr + data) */
155#define CAP_USBCMD (0x000UL)
156#define CAP_USBSTS (0x004UL)
157#define CAP_USBINTR (0x008UL)
158#define CAP_DEVICEADDR (0x014UL)
159#define CAP_ENDPTLISTADDR (0x018UL)
160#define CAP_PORTSC (0x044UL)
David Lopof23e6492009-04-16 14:35:24 -0700161#define CAP_DEVLC (0x084UL)
Ofir Cohena1c2a872011-12-14 10:26:34 +0200162#define CAP_ENDPTPIPEID (0x0BCUL)
David Lopoaa69a802008-11-17 14:14:51 -0800163#define CAP_USBMODE (hw_bank.lpm ? 0x0C8UL : 0x068UL)
164#define CAP_ENDPTSETUPSTAT (hw_bank.lpm ? 0x0D8UL : 0x06CUL)
165#define CAP_ENDPTPRIME (hw_bank.lpm ? 0x0DCUL : 0x070UL)
166#define CAP_ENDPTFLUSH (hw_bank.lpm ? 0x0E0UL : 0x074UL)
167#define CAP_ENDPTSTAT (hw_bank.lpm ? 0x0E4UL : 0x078UL)
168#define CAP_ENDPTCOMPLETE (hw_bank.lpm ? 0x0E8UL : 0x07CUL)
169#define CAP_ENDPTCTRL (hw_bank.lpm ? 0x0ECUL : 0x080UL)
170#define CAP_LAST (hw_bank.lpm ? 0x12CUL : 0x0C0UL)
171
Amit Blayfd075dd2012-06-26 13:12:50 +0300172#define REMOTE_WAKEUP_DELAY msecs_to_jiffies(200)
173
David Lopoaa69a802008-11-17 14:14:51 -0800174/* maximum number of enpoints: valid only after hw_device_reset() */
175static unsigned hw_ep_max;
176
177/**
178 * hw_ep_bit: calculates the bit number
179 * @num: endpoint number
180 * @dir: endpoint direction
181 *
182 * This function returns bit number
183 */
184static inline int hw_ep_bit(int num, int dir)
185{
186 return num + (dir ? 16 : 0);
187}
188
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200189static int ep_to_bit(int n)
190{
191 int fill = 16 - hw_ep_max / 2;
192
193 if (n >= hw_ep_max / 2)
194 n += fill;
195
196 return n;
197}
198
David Lopoaa69a802008-11-17 14:14:51 -0800199/**
200 * hw_aread: reads from register bitfield
201 * @addr: address relative to bus map
202 * @mask: bitfield mask
203 *
204 * This function returns register bitfield data
205 */
206static u32 hw_aread(u32 addr, u32 mask)
207{
208 return ioread32(addr + hw_bank.abs) & mask;
209}
210
211/**
212 * hw_awrite: writes to register bitfield
213 * @addr: address relative to bus map
214 * @mask: bitfield mask
215 * @data: new data
216 */
217static void hw_awrite(u32 addr, u32 mask, u32 data)
218{
219 iowrite32(hw_aread(addr, ~mask) | (data & mask),
220 addr + hw_bank.abs);
221}
222
223/**
224 * hw_cread: reads from register bitfield
225 * @addr: address relative to CAP offset plus content
226 * @mask: bitfield mask
227 *
228 * This function returns register bitfield data
229 */
230static u32 hw_cread(u32 addr, u32 mask)
231{
232 return ioread32(addr + hw_bank.cap) & mask;
233}
234
235/**
236 * hw_cwrite: writes to register bitfield
237 * @addr: address relative to CAP offset plus content
238 * @mask: bitfield mask
239 * @data: new data
240 */
241static void hw_cwrite(u32 addr, u32 mask, u32 data)
242{
243 iowrite32(hw_cread(addr, ~mask) | (data & mask),
244 addr + hw_bank.cap);
245}
246
247/**
248 * hw_ctest_and_clear: tests & clears 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_ctest_and_clear(u32 addr, u32 mask)
255{
256 u32 reg = hw_cread(addr, mask);
257
258 iowrite32(reg, addr + hw_bank.cap);
259 return reg;
260}
261
262/**
263 * hw_ctest_and_write: tests & writes register bitfield
264 * @addr: address relative to CAP offset plus content
265 * @mask: bitfield mask
266 * @data: new data
267 *
268 * This function returns register bitfield data
269 */
270static u32 hw_ctest_and_write(u32 addr, u32 mask, u32 data)
271{
272 u32 reg = hw_cread(addr, ~0);
273
274 iowrite32((reg & ~mask) | (data & mask), addr + hw_bank.cap);
275 return (reg & mask) >> ffs_nr(mask);
276}
277
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530278static int hw_device_init(void __iomem *base)
David Lopoaa69a802008-11-17 14:14:51 -0800279{
280 u32 reg;
281
282 /* bank is a module variable */
283 hw_bank.abs = base;
284
285 hw_bank.cap = hw_bank.abs;
286 hw_bank.cap += ABS_CAPLENGTH;
287 hw_bank.cap += ioread8(hw_bank.cap);
288
289 reg = hw_aread(ABS_HCCPARAMS, HCCPARAMS_LEN) >> ffs_nr(HCCPARAMS_LEN);
290 hw_bank.lpm = reg;
291 hw_bank.size = hw_bank.cap - hw_bank.abs;
292 hw_bank.size += CAP_LAST;
293 hw_bank.size /= sizeof(u32);
294
David Lopoaa69a802008-11-17 14:14:51 -0800295 reg = hw_aread(ABS_DCCPARAMS, DCCPARAMS_DEN) >> ffs_nr(DCCPARAMS_DEN);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530296 hw_ep_max = reg * 2; /* cache hw ENDPT_MAX */
David Lopoaa69a802008-11-17 14:14:51 -0800297
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530298 if (hw_ep_max == 0 || hw_ep_max > ENDPT_MAX)
299 return -ENODEV;
David Lopoaa69a802008-11-17 14:14:51 -0800300
301 /* setup lock mode ? */
302
303 /* ENDPTSETUPSTAT is '0' by default */
304
305 /* HCSPARAMS.bf.ppc SHOULD BE zero for device */
306
307 return 0;
308}
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530309/**
310 * hw_device_reset: resets chip (execute without interruption)
311 * @base: register base address
312 *
313 * This function returns an error code
314 */
315static int hw_device_reset(struct ci13xxx *udc)
316{
317 /* should flush & stop before reset */
318 hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0);
319 hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
320
321 hw_cwrite(CAP_USBCMD, USBCMD_RST, USBCMD_RST);
322 while (hw_cread(CAP_USBCMD, USBCMD_RST))
323 udelay(10); /* not RTOS friendly */
324
325
326 if (udc->udc_driver->notify_event)
327 udc->udc_driver->notify_event(udc,
328 CI13XXX_CONTROLLER_RESET_EVENT);
329
Pavankumar Kondeti8c2387a2011-05-02 11:56:28 +0530330 if (udc->udc_driver->flags & CI13XXX_DISABLE_STREAMING)
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530331 hw_cwrite(CAP_USBMODE, USBMODE_SDIS, USBMODE_SDIS);
332
333 /* USBMODE should be configured step by step */
334 hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
335 hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE);
336 hw_cwrite(CAP_USBMODE, USBMODE_SLOM, USBMODE_SLOM); /* HW >= 2.3 */
337
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700338 /*
339 * ITC (Interrupt Threshold Control) field is to set the maximum
340 * rate at which the device controller will issue interrupts.
341 * The maximum interrupt interval measured in micro frames.
342 * Valid values are 0, 1, 2, 4, 8, 16, 32, 64. The default value is
343 * 8 micro frames. If CPU can handle interrupts at faster rate, ITC
344 * can be set to lesser value to gain performance.
345 */
346 if (udc->udc_driver->flags & CI13XXX_ZERO_ITC)
347 hw_cwrite(CAP_USBCMD, USBCMD_ITC_MASK, USBCMD_ITC(0));
348
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530349 if (hw_cread(CAP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
350 pr_err("cannot enter in device mode");
351 pr_err("lpm = %i", hw_bank.lpm);
352 return -ENODEV;
353 }
354
355 return 0;
356}
David Lopoaa69a802008-11-17 14:14:51 -0800357
358/**
359 * hw_device_state: enables/disables interrupts & starts/stops device (execute
360 * without interruption)
361 * @dma: 0 => disable, !0 => enable and set dma engine
362 *
363 * This function returns an error code
364 */
365static int hw_device_state(u32 dma)
366{
367 if (dma) {
368 hw_cwrite(CAP_ENDPTLISTADDR, ~0, dma);
369 /* interrupt, error, port change, reset, sleep/suspend */
370 hw_cwrite(CAP_USBINTR, ~0,
371 USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
372 hw_cwrite(CAP_USBCMD, USBCMD_RS, USBCMD_RS);
373 } else {
374 hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
375 hw_cwrite(CAP_USBINTR, ~0, 0);
376 }
377 return 0;
378}
379
380/**
381 * hw_ep_flush: flush endpoint fifo (execute without interruption)
382 * @num: endpoint number
383 * @dir: endpoint direction
384 *
385 * This function returns an error code
386 */
387static int hw_ep_flush(int num, int dir)
388{
389 int n = hw_ep_bit(num, dir);
390
391 do {
392 /* flush any pending transfer */
393 hw_cwrite(CAP_ENDPTFLUSH, BIT(n), BIT(n));
394 while (hw_cread(CAP_ENDPTFLUSH, BIT(n)))
395 cpu_relax();
396 } while (hw_cread(CAP_ENDPTSTAT, BIT(n)));
397
398 return 0;
399}
400
401/**
402 * hw_ep_disable: disables endpoint (execute without interruption)
403 * @num: endpoint number
404 * @dir: endpoint direction
405 *
406 * This function returns an error code
407 */
408static int hw_ep_disable(int num, int dir)
409{
410 hw_ep_flush(num, dir);
411 hw_cwrite(CAP_ENDPTCTRL + num * sizeof(u32),
412 dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0);
413 return 0;
414}
415
416/**
417 * hw_ep_enable: enables endpoint (execute without interruption)
418 * @num: endpoint number
419 * @dir: endpoint direction
420 * @type: endpoint type
421 *
422 * This function returns an error code
423 */
424static int hw_ep_enable(int num, int dir, int type)
425{
426 u32 mask, data;
427
428 if (dir) {
429 mask = ENDPTCTRL_TXT; /* type */
430 data = type << ffs_nr(mask);
431
432 mask |= ENDPTCTRL_TXS; /* unstall */
433 mask |= ENDPTCTRL_TXR; /* reset data toggle */
434 data |= ENDPTCTRL_TXR;
435 mask |= ENDPTCTRL_TXE; /* enable */
436 data |= ENDPTCTRL_TXE;
437 } else {
438 mask = ENDPTCTRL_RXT; /* type */
439 data = type << ffs_nr(mask);
440
441 mask |= ENDPTCTRL_RXS; /* unstall */
442 mask |= ENDPTCTRL_RXR; /* reset data toggle */
443 data |= ENDPTCTRL_RXR;
444 mask |= ENDPTCTRL_RXE; /* enable */
445 data |= ENDPTCTRL_RXE;
446 }
447 hw_cwrite(CAP_ENDPTCTRL + num * sizeof(u32), mask, data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700448
449 /* make sure endpoint is enabled before returning */
450 mb();
451
David Lopoaa69a802008-11-17 14:14:51 -0800452 return 0;
453}
454
455/**
456 * hw_ep_get_halt: return endpoint halt status
457 * @num: endpoint number
458 * @dir: endpoint direction
459 *
460 * This function returns 1 if endpoint halted
461 */
462static int hw_ep_get_halt(int num, int dir)
463{
464 u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
465
466 return hw_cread(CAP_ENDPTCTRL + num * sizeof(u32), mask) ? 1 : 0;
467}
468
469/**
David Lopoaa69a802008-11-17 14:14:51 -0800470 * hw_test_and_clear_setup_status: test & clear setup status (execute without
471 * interruption)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200472 * @n: endpoint number
David Lopoaa69a802008-11-17 14:14:51 -0800473 *
474 * This function returns setup status
475 */
476static int hw_test_and_clear_setup_status(int n)
477{
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200478 n = ep_to_bit(n);
David Lopoaa69a802008-11-17 14:14:51 -0800479 return hw_ctest_and_clear(CAP_ENDPTSETUPSTAT, BIT(n));
480}
481
482/**
483 * hw_ep_prime: primes endpoint (execute without interruption)
484 * @num: endpoint number
485 * @dir: endpoint direction
486 * @is_ctrl: true if control endpoint
487 *
488 * This function returns an error code
489 */
490static int hw_ep_prime(int num, int dir, int is_ctrl)
491{
492 int n = hw_ep_bit(num, dir);
493
David Lopoaa69a802008-11-17 14:14:51 -0800494 if (is_ctrl && dir == RX && hw_cread(CAP_ENDPTSETUPSTAT, BIT(num)))
495 return -EAGAIN;
496
497 hw_cwrite(CAP_ENDPTPRIME, BIT(n), BIT(n));
498
499 while (hw_cread(CAP_ENDPTPRIME, BIT(n)))
500 cpu_relax();
501 if (is_ctrl && dir == RX && hw_cread(CAP_ENDPTSETUPSTAT, BIT(num)))
502 return -EAGAIN;
503
504 /* status shoult be tested according with manual but it doesn't work */
505 return 0;
506}
507
508/**
509 * hw_ep_set_halt: configures ep halt & resets data toggle after clear (execute
510 * without interruption)
511 * @num: endpoint number
512 * @dir: endpoint direction
513 * @value: true => stall, false => unstall
514 *
515 * This function returns an error code
516 */
517static int hw_ep_set_halt(int num, int dir, int value)
518{
Pavankumar Kondeti05598942011-07-06 16:58:44 +0530519 u32 addr, mask_xs, mask_xr;
520
David Lopoaa69a802008-11-17 14:14:51 -0800521 if (value != 0 && value != 1)
522 return -EINVAL;
523
524 do {
Pavankumar Kondeti05598942011-07-06 16:58:44 +0530525 if (hw_cread(CAP_ENDPTSETUPSTAT, BIT(num)))
526 return 0;
527
528 addr = CAP_ENDPTCTRL + num * sizeof(u32);
529 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
530 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR;
David Lopoaa69a802008-11-17 14:14:51 -0800531
532 /* data toggle - reserved for EP0 but it's in ESS */
533 hw_cwrite(addr, mask_xs|mask_xr, value ? mask_xs : mask_xr);
534
535 } while (value != hw_ep_get_halt(num, dir));
536
537 return 0;
538}
539
540/**
541 * hw_intr_clear: disables interrupt & clears interrupt status (execute without
542 * interruption)
543 * @n: interrupt bit
544 *
545 * This function returns an error code
546 */
547static int hw_intr_clear(int n)
548{
549 if (n >= REG_BITS)
550 return -EINVAL;
551
552 hw_cwrite(CAP_USBINTR, BIT(n), 0);
553 hw_cwrite(CAP_USBSTS, BIT(n), BIT(n));
554 return 0;
555}
556
557/**
558 * hw_intr_force: enables interrupt & forces interrupt status (execute without
559 * interruption)
560 * @n: interrupt bit
561 *
562 * This function returns an error code
563 */
564static int hw_intr_force(int n)
565{
566 if (n >= REG_BITS)
567 return -EINVAL;
568
569 hw_awrite(ABS_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
570 hw_cwrite(CAP_USBINTR, BIT(n), BIT(n));
571 hw_cwrite(CAP_USBSTS, BIT(n), BIT(n));
572 hw_awrite(ABS_TESTMODE, TESTMODE_FORCE, 0);
573 return 0;
574}
575
576/**
577 * hw_is_port_high_speed: test if port is high speed
578 *
579 * This function returns true if high speed port
580 */
581static int hw_port_is_high_speed(void)
582{
583 return hw_bank.lpm ? hw_cread(CAP_DEVLC, DEVLC_PSPD) :
584 hw_cread(CAP_PORTSC, PORTSC_HSP);
585}
586
587/**
588 * hw_port_test_get: reads port test mode value
589 *
590 * This function returns port test mode value
591 */
592static u8 hw_port_test_get(void)
593{
594 return hw_cread(CAP_PORTSC, PORTSC_PTC) >> ffs_nr(PORTSC_PTC);
595}
596
597/**
598 * hw_port_test_set: writes port test mode (execute without interruption)
599 * @mode: new value
600 *
601 * This function returns an error code
602 */
603static int hw_port_test_set(u8 mode)
604{
605 const u8 TEST_MODE_MAX = 7;
606
607 if (mode > TEST_MODE_MAX)
608 return -EINVAL;
609
610 hw_cwrite(CAP_PORTSC, PORTSC_PTC, mode << ffs_nr(PORTSC_PTC));
611 return 0;
612}
613
614/**
615 * hw_read_intr_enable: returns interrupt enable register
616 *
617 * This function returns register data
618 */
619static u32 hw_read_intr_enable(void)
620{
621 return hw_cread(CAP_USBINTR, ~0);
622}
623
624/**
625 * hw_read_intr_status: returns interrupt status register
626 *
627 * This function returns register data
628 */
629static u32 hw_read_intr_status(void)
630{
631 return hw_cread(CAP_USBSTS, ~0);
632}
633
634/**
635 * hw_register_read: reads all device registers (execute without interruption)
636 * @buf: destination buffer
637 * @size: buffer size
638 *
639 * This function returns number of registers read
640 */
641static size_t hw_register_read(u32 *buf, size_t size)
642{
643 unsigned i;
644
645 if (size > hw_bank.size)
646 size = hw_bank.size;
647
648 for (i = 0; i < size; i++)
649 buf[i] = hw_aread(i * sizeof(u32), ~0);
650
651 return size;
652}
653
654/**
655 * hw_register_write: writes to register
656 * @addr: register address
657 * @data: register value
658 *
659 * This function returns an error code
660 */
661static int hw_register_write(u16 addr, u32 data)
662{
663 /* align */
664 addr /= sizeof(u32);
665
666 if (addr >= hw_bank.size)
667 return -EINVAL;
668
669 /* align */
670 addr *= sizeof(u32);
671
672 hw_awrite(addr, ~0, data);
673 return 0;
674}
675
676/**
677 * hw_test_and_clear_complete: test & clear complete status (execute without
678 * interruption)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200679 * @n: endpoint number
David Lopoaa69a802008-11-17 14:14:51 -0800680 *
681 * This function returns complete status
682 */
683static int hw_test_and_clear_complete(int n)
684{
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200685 n = ep_to_bit(n);
David Lopoaa69a802008-11-17 14:14:51 -0800686 return hw_ctest_and_clear(CAP_ENDPTCOMPLETE, BIT(n));
687}
688
689/**
690 * hw_test_and_clear_intr_active: test & clear active interrupts (execute
691 * without interruption)
692 *
693 * This function returns active interrutps
694 */
695static u32 hw_test_and_clear_intr_active(void)
696{
697 u32 reg = hw_read_intr_status() & hw_read_intr_enable();
698
699 hw_cwrite(CAP_USBSTS, ~0, reg);
700 return reg;
701}
702
703/**
704 * hw_test_and_clear_setup_guard: test & clear setup guard (execute without
705 * interruption)
706 *
707 * This function returns guard value
708 */
709static int hw_test_and_clear_setup_guard(void)
710{
711 return hw_ctest_and_write(CAP_USBCMD, USBCMD_SUTW, 0);
712}
713
714/**
715 * hw_test_and_set_setup_guard: test & set setup guard (execute without
716 * interruption)
717 *
718 * This function returns guard value
719 */
720static int hw_test_and_set_setup_guard(void)
721{
722 return hw_ctest_and_write(CAP_USBCMD, USBCMD_SUTW, USBCMD_SUTW);
723}
724
725/**
726 * hw_usb_set_address: configures USB address (execute without interruption)
727 * @value: new USB address
728 *
729 * This function returns an error code
730 */
731static int hw_usb_set_address(u8 value)
732{
733 /* advance */
734 hw_cwrite(CAP_DEVICEADDR, DEVICEADDR_USBADR | DEVICEADDR_USBADRA,
735 value << ffs_nr(DEVICEADDR_USBADR) | DEVICEADDR_USBADRA);
736 return 0;
737}
738
739/**
740 * hw_usb_reset: restart device after a bus reset (execute without
741 * interruption)
742 *
743 * This function returns an error code
744 */
745static int hw_usb_reset(void)
746{
747 hw_usb_set_address(0);
748
749 /* ESS flushes only at end?!? */
750 hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0); /* flush all EPs */
751
752 /* clear setup token semaphores */
753 hw_cwrite(CAP_ENDPTSETUPSTAT, 0, 0); /* writes its content */
754
755 /* clear complete status */
756 hw_cwrite(CAP_ENDPTCOMPLETE, 0, 0); /* writes its content */
757
758 /* wait until all bits cleared */
759 while (hw_cread(CAP_ENDPTPRIME, ~0))
760 udelay(10); /* not RTOS friendly */
761
762 /* reset all endpoints ? */
763
764 /* reset internal status and wait for further instructions
765 no need to verify the port reset status (ESS does it) */
766
767 return 0;
768}
769
770/******************************************************************************
771 * DBG block
772 *****************************************************************************/
773/**
774 * show_device: prints information about device capabilities and status
775 *
776 * Check "device.h" for details
777 */
778static ssize_t show_device(struct device *dev, struct device_attribute *attr,
779 char *buf)
780{
781 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
782 struct usb_gadget *gadget = &udc->gadget;
783 int n = 0;
784
785 dbg_trace("[%s] %p\n", __func__, buf);
786 if (attr == NULL || buf == NULL) {
787 dev_err(dev, "[%s] EINVAL\n", __func__);
788 return 0;
789 }
790
791 n += scnprintf(buf + n, PAGE_SIZE - n, "speed = %d\n",
792 gadget->speed);
Michal Nazarewiczd327ab52011-11-19 18:27:37 +0100793 n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed = %d\n",
794 gadget->max_speed);
795 /* TODO: Scheduled for removal in 3.8. */
David Lopoaa69a802008-11-17 14:14:51 -0800796 n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed = %d\n",
Michal Nazarewiczd327ab52011-11-19 18:27:37 +0100797 gadget_is_dualspeed(gadget));
David Lopoaa69a802008-11-17 14:14:51 -0800798 n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg = %d\n",
799 gadget->is_otg);
800 n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral = %d\n",
801 gadget->is_a_peripheral);
802 n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable = %d\n",
803 gadget->b_hnp_enable);
804 n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support = %d\n",
805 gadget->a_hnp_support);
806 n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n",
807 gadget->a_alt_hnp_support);
808 n += scnprintf(buf + n, PAGE_SIZE - n, "name = %s\n",
809 (gadget->name ? gadget->name : ""));
810
811 return n;
812}
813static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
814
815/**
816 * show_driver: prints information about attached gadget (if any)
817 *
818 * Check "device.h" for details
819 */
820static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
821 char *buf)
822{
823 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
824 struct usb_gadget_driver *driver = udc->driver;
825 int n = 0;
826
827 dbg_trace("[%s] %p\n", __func__, buf);
828 if (attr == NULL || buf == NULL) {
829 dev_err(dev, "[%s] EINVAL\n", __func__);
830 return 0;
831 }
832
833 if (driver == NULL)
834 return scnprintf(buf, PAGE_SIZE,
835 "There is no gadget attached!\n");
836
837 n += scnprintf(buf + n, PAGE_SIZE - n, "function = %s\n",
838 (driver->function ? driver->function : ""));
839 n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n",
Michal Nazarewicz7177aed2011-11-19 18:27:38 +0100840 driver->max_speed);
David Lopoaa69a802008-11-17 14:14:51 -0800841
842 return n;
843}
844static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL);
845
846/* Maximum event message length */
847#define DBG_DATA_MSG 64UL
848
849/* Maximum event messages */
850#define DBG_DATA_MAX 128UL
851
852/* Event buffer descriptor */
853static struct {
854 char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */
855 unsigned idx; /* index */
856 unsigned tty; /* print to console? */
857 rwlock_t lck; /* lock */
858} dbg_data = {
859 .idx = 0,
860 .tty = 0,
861 .lck = __RW_LOCK_UNLOCKED(lck)
862};
863
864/**
865 * dbg_dec: decrements debug event index
866 * @idx: buffer index
867 */
868static void dbg_dec(unsigned *idx)
869{
870 *idx = (*idx - 1) & (DBG_DATA_MAX-1);
871}
872
873/**
874 * dbg_inc: increments debug event index
875 * @idx: buffer index
876 */
877static void dbg_inc(unsigned *idx)
878{
879 *idx = (*idx + 1) & (DBG_DATA_MAX-1);
880}
881
Vamsi Krishna8d1bbd52012-02-09 21:13:24 -0800882
883static unsigned int ep_addr_txdbg_mask;
884module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
885static unsigned int ep_addr_rxdbg_mask;
886module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
887
888static int allow_dbg_print(u8 addr)
889{
890 int dir, num;
891
892 /* allow bus wide events */
893 if (addr == 0xff)
894 return 1;
895
896 dir = addr & USB_ENDPOINT_DIR_MASK ? TX : RX;
897 num = addr & ~USB_ENDPOINT_DIR_MASK;
898 num = 1 << num;
899
900 if ((dir == TX) && (num & ep_addr_txdbg_mask))
901 return 1;
902 if ((dir == RX) && (num & ep_addr_rxdbg_mask))
903 return 1;
904
905 return 0;
906}
907
David Lopoaa69a802008-11-17 14:14:51 -0800908/**
909 * dbg_print: prints the common part of the event
910 * @addr: endpoint address
911 * @name: event name
912 * @status: status
913 * @extra: extra information
914 */
915static void dbg_print(u8 addr, const char *name, int status, const char *extra)
916{
917 struct timeval tval;
918 unsigned int stamp;
919 unsigned long flags;
920
Vamsi Krishna8d1bbd52012-02-09 21:13:24 -0800921 if (!allow_dbg_print(addr))
922 return;
923
David Lopoaa69a802008-11-17 14:14:51 -0800924 write_lock_irqsave(&dbg_data.lck, flags);
925
926 do_gettimeofday(&tval);
927 stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s */
928 stamp = stamp * 1000000 + tval.tv_usec;
929
930 scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +0300931 "%04X\t? %02X %-7.7s %4i ?\t%s\n",
David Lopoaa69a802008-11-17 14:14:51 -0800932 stamp, addr, name, status, extra);
933
934 dbg_inc(&dbg_data.idx);
935
936 write_unlock_irqrestore(&dbg_data.lck, flags);
937
938 if (dbg_data.tty != 0)
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +0300939 pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n",
David Lopoaa69a802008-11-17 14:14:51 -0800940 stamp, addr, name, status, extra);
941}
942
943/**
944 * dbg_done: prints a DONE event
945 * @addr: endpoint address
946 * @td: transfer descriptor
947 * @status: status
948 */
949static void dbg_done(u8 addr, const u32 token, int status)
950{
951 char msg[DBG_DATA_MSG];
952
953 scnprintf(msg, sizeof(msg), "%d %02X",
954 (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES),
955 (int)(token & TD_STATUS) >> ffs_nr(TD_STATUS));
956 dbg_print(addr, "DONE", status, msg);
957}
958
959/**
960 * dbg_event: prints a generic event
961 * @addr: endpoint address
962 * @name: event name
963 * @status: status
964 */
965static void dbg_event(u8 addr, const char *name, int status)
966{
967 if (name != NULL)
968 dbg_print(addr, name, status, "");
969}
970
971/*
972 * dbg_queue: prints a QUEUE event
973 * @addr: endpoint address
974 * @req: USB request
975 * @status: status
976 */
977static void dbg_queue(u8 addr, const struct usb_request *req, int status)
978{
979 char msg[DBG_DATA_MSG];
980
981 if (req != NULL) {
982 scnprintf(msg, sizeof(msg),
983 "%d %d", !req->no_interrupt, req->length);
984 dbg_print(addr, "QUEUE", status, msg);
985 }
986}
987
988/**
989 * dbg_setup: prints a SETUP event
990 * @addr: endpoint address
991 * @req: setup request
992 */
993static void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
994{
995 char msg[DBG_DATA_MSG];
996
997 if (req != NULL) {
998 scnprintf(msg, sizeof(msg),
999 "%02X %02X %04X %04X %d", req->bRequestType,
1000 req->bRequest, le16_to_cpu(req->wValue),
1001 le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
1002 dbg_print(addr, "SETUP", 0, msg);
1003 }
1004}
1005
1006/**
1007 * show_events: displays the event buffer
1008 *
1009 * Check "device.h" for details
1010 */
1011static ssize_t show_events(struct device *dev, struct device_attribute *attr,
1012 char *buf)
1013{
1014 unsigned long flags;
1015 unsigned i, j, n = 0;
1016
1017 dbg_trace("[%s] %p\n", __func__, buf);
1018 if (attr == NULL || buf == NULL) {
1019 dev_err(dev, "[%s] EINVAL\n", __func__);
1020 return 0;
1021 }
1022
1023 read_lock_irqsave(&dbg_data.lck, flags);
1024
1025 i = dbg_data.idx;
1026 for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) {
1027 n += strlen(dbg_data.buf[i]);
1028 if (n >= PAGE_SIZE) {
1029 n -= strlen(dbg_data.buf[i]);
1030 break;
1031 }
1032 }
1033 for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i))
1034 j += scnprintf(buf + j, PAGE_SIZE - j,
1035 "%s", dbg_data.buf[i]);
1036
1037 read_unlock_irqrestore(&dbg_data.lck, flags);
1038
1039 return n;
1040}
1041
1042/**
1043 * store_events: configure if events are going to be also printed to console
1044 *
1045 * Check "device.h" for details
1046 */
1047static ssize_t store_events(struct device *dev, struct device_attribute *attr,
1048 const char *buf, size_t count)
1049{
1050 unsigned tty;
1051
1052 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1053 if (attr == NULL || buf == NULL) {
1054 dev_err(dev, "[%s] EINVAL\n", __func__);
1055 goto done;
1056 }
1057
1058 if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
1059 dev_err(dev, "<1|0>: enable|disable console log\n");
1060 goto done;
1061 }
1062
1063 dbg_data.tty = tty;
1064 dev_info(dev, "tty = %u", dbg_data.tty);
1065
1066 done:
1067 return count;
1068}
1069static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
1070
1071/**
1072 * show_inters: interrupt status, enable status and historic
1073 *
1074 * Check "device.h" for details
1075 */
1076static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
1077 char *buf)
1078{
1079 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1080 unsigned long flags;
1081 u32 intr;
1082 unsigned i, j, n = 0;
1083
1084 dbg_trace("[%s] %p\n", __func__, buf);
1085 if (attr == NULL || buf == NULL) {
1086 dev_err(dev, "[%s] EINVAL\n", __func__);
1087 return 0;
1088 }
1089
1090 spin_lock_irqsave(udc->lock, flags);
1091
1092 n += scnprintf(buf + n, PAGE_SIZE - n,
1093 "status = %08x\n", hw_read_intr_status());
1094 n += scnprintf(buf + n, PAGE_SIZE - n,
1095 "enable = %08x\n", hw_read_intr_enable());
1096
1097 n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
1098 isr_statistics.test);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001099 n += scnprintf(buf + n, PAGE_SIZE - n, "? ui = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001100 isr_statistics.ui);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001101 n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001102 isr_statistics.uei);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001103 n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001104 isr_statistics.pci);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001105 n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001106 isr_statistics.uri);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001107 n += scnprintf(buf + n, PAGE_SIZE - n, "? sli = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001108 isr_statistics.sli);
1109 n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n",
1110 isr_statistics.none);
1111 n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n",
1112 isr_statistics.hndl.cnt);
1113
1114 for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) {
1115 i &= ISR_MASK;
1116 intr = isr_statistics.hndl.buf[i];
1117
1118 if (USBi_UI & intr)
1119 n += scnprintf(buf + n, PAGE_SIZE - n, "ui ");
1120 intr &= ~USBi_UI;
1121 if (USBi_UEI & intr)
1122 n += scnprintf(buf + n, PAGE_SIZE - n, "uei ");
1123 intr &= ~USBi_UEI;
1124 if (USBi_PCI & intr)
1125 n += scnprintf(buf + n, PAGE_SIZE - n, "pci ");
1126 intr &= ~USBi_PCI;
1127 if (USBi_URI & intr)
1128 n += scnprintf(buf + n, PAGE_SIZE - n, "uri ");
1129 intr &= ~USBi_URI;
1130 if (USBi_SLI & intr)
1131 n += scnprintf(buf + n, PAGE_SIZE - n, "sli ");
1132 intr &= ~USBi_SLI;
1133 if (intr)
1134 n += scnprintf(buf + n, PAGE_SIZE - n, "??? ");
1135 if (isr_statistics.hndl.buf[i])
1136 n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
1137 }
1138
1139 spin_unlock_irqrestore(udc->lock, flags);
1140
1141 return n;
1142}
1143
1144/**
1145 * store_inters: enable & force or disable an individual interrutps
1146 * (to be used for test purposes only)
1147 *
1148 * Check "device.h" for details
1149 */
1150static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
1151 const char *buf, size_t count)
1152{
1153 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1154 unsigned long flags;
1155 unsigned en, bit;
1156
1157 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1158 if (attr == NULL || buf == NULL) {
1159 dev_err(dev, "[%s] EINVAL\n", __func__);
1160 goto done;
1161 }
1162
1163 if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
1164 dev_err(dev, "<1|0> <bit>: enable|disable interrupt");
1165 goto done;
1166 }
1167
1168 spin_lock_irqsave(udc->lock, flags);
1169 if (en) {
1170 if (hw_intr_force(bit))
1171 dev_err(dev, "invalid bit number\n");
1172 else
1173 isr_statistics.test++;
1174 } else {
1175 if (hw_intr_clear(bit))
1176 dev_err(dev, "invalid bit number\n");
1177 }
1178 spin_unlock_irqrestore(udc->lock, flags);
1179
1180 done:
1181 return count;
1182}
1183static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
1184
1185/**
1186 * show_port_test: reads port test mode
1187 *
1188 * Check "device.h" for details
1189 */
1190static ssize_t show_port_test(struct device *dev,
1191 struct device_attribute *attr, char *buf)
1192{
1193 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1194 unsigned long flags;
1195 unsigned mode;
1196
1197 dbg_trace("[%s] %p\n", __func__, buf);
1198 if (attr == NULL || buf == NULL) {
1199 dev_err(dev, "[%s] EINVAL\n", __func__);
1200 return 0;
1201 }
1202
1203 spin_lock_irqsave(udc->lock, flags);
1204 mode = hw_port_test_get();
1205 spin_unlock_irqrestore(udc->lock, flags);
1206
1207 return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
1208}
1209
1210/**
1211 * store_port_test: writes port test mode
1212 *
1213 * Check "device.h" for details
1214 */
1215static ssize_t store_port_test(struct device *dev,
1216 struct device_attribute *attr,
1217 const char *buf, size_t count)
1218{
1219 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1220 unsigned long flags;
1221 unsigned mode;
1222
1223 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1224 if (attr == NULL || buf == NULL) {
1225 dev_err(dev, "[%s] EINVAL\n", __func__);
1226 goto done;
1227 }
1228
1229 if (sscanf(buf, "%u", &mode) != 1) {
1230 dev_err(dev, "<mode>: set port test mode");
1231 goto done;
1232 }
1233
1234 spin_lock_irqsave(udc->lock, flags);
1235 if (hw_port_test_set(mode))
1236 dev_err(dev, "invalid mode\n");
1237 spin_unlock_irqrestore(udc->lock, flags);
1238
1239 done:
1240 return count;
1241}
1242static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
1243 show_port_test, store_port_test);
1244
1245/**
1246 * show_qheads: DMA contents of all queue heads
1247 *
1248 * Check "device.h" for details
1249 */
1250static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
1251 char *buf)
1252{
1253 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1254 unsigned long flags;
1255 unsigned i, j, n = 0;
1256
1257 dbg_trace("[%s] %p\n", __func__, buf);
1258 if (attr == NULL || buf == NULL) {
1259 dev_err(dev, "[%s] EINVAL\n", __func__);
1260 return 0;
1261 }
1262
1263 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301264 for (i = 0; i < hw_ep_max/2; i++) {
1265 struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i];
1266 struct ci13xxx_ep *mEpTx = &udc->ci13xxx_ep[i + hw_ep_max/2];
David Lopoaa69a802008-11-17 14:14:51 -08001267 n += scnprintf(buf + n, PAGE_SIZE - n,
1268 "EP=%02i: RX=%08X TX=%08X\n",
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301269 i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08001270 for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) {
1271 n += scnprintf(buf + n, PAGE_SIZE - n,
1272 " %04X: %08X %08X\n", j,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301273 *((u32 *)mEpRx->qh.ptr + j),
1274 *((u32 *)mEpTx->qh.ptr + j));
David Lopoaa69a802008-11-17 14:14:51 -08001275 }
1276 }
1277 spin_unlock_irqrestore(udc->lock, flags);
1278
1279 return n;
1280}
1281static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
1282
1283/**
1284 * show_registers: dumps all registers
1285 *
1286 * Check "device.h" for details
1287 */
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001288#define DUMP_ENTRIES 512
David Lopoaa69a802008-11-17 14:14:51 -08001289static ssize_t show_registers(struct device *dev,
1290 struct device_attribute *attr, char *buf)
1291{
1292 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1293 unsigned long flags;
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001294 u32 *dump;
David Lopoaa69a802008-11-17 14:14:51 -08001295 unsigned i, k, n = 0;
1296
1297 dbg_trace("[%s] %p\n", __func__, buf);
1298 if (attr == NULL || buf == NULL) {
1299 dev_err(dev, "[%s] EINVAL\n", __func__);
1300 return 0;
1301 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001302 dump = kmalloc(2048, GFP_KERNEL);
1303 if (dump == NULL)
1304 return -ENOMEM;
David Lopoaa69a802008-11-17 14:14:51 -08001305
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001306 dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
1307 if (!dump) {
1308 dev_err(dev, "%s: out of memory\n", __func__);
1309 return 0;
1310 }
1311
David Lopoaa69a802008-11-17 14:14:51 -08001312 spin_lock_irqsave(udc->lock, flags);
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001313 k = hw_register_read(dump, DUMP_ENTRIES);
David Lopoaa69a802008-11-17 14:14:51 -08001314 spin_unlock_irqrestore(udc->lock, flags);
1315
1316 for (i = 0; i < k; i++) {
1317 n += scnprintf(buf + n, PAGE_SIZE - n,
1318 "reg[0x%04X] = 0x%08X\n",
1319 i * (unsigned)sizeof(u32), dump[i]);
1320 }
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001321 kfree(dump);
David Lopoaa69a802008-11-17 14:14:51 -08001322
1323 return n;
1324}
1325
1326/**
1327 * store_registers: writes value to register address
1328 *
1329 * Check "device.h" for details
1330 */
1331static ssize_t store_registers(struct device *dev,
1332 struct device_attribute *attr,
1333 const char *buf, size_t count)
1334{
1335 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1336 unsigned long addr, data, flags;
1337
1338 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1339 if (attr == NULL || buf == NULL) {
1340 dev_err(dev, "[%s] EINVAL\n", __func__);
1341 goto done;
1342 }
1343
1344 if (sscanf(buf, "%li %li", &addr, &data) != 2) {
1345 dev_err(dev, "<addr> <data>: write data to register address");
1346 goto done;
1347 }
1348
1349 spin_lock_irqsave(udc->lock, flags);
1350 if (hw_register_write(addr, data))
1351 dev_err(dev, "invalid address range\n");
1352 spin_unlock_irqrestore(udc->lock, flags);
1353
1354 done:
1355 return count;
1356}
1357static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
1358 show_registers, store_registers);
1359
1360/**
1361 * show_requests: DMA contents of all requests currently queued (all endpts)
1362 *
1363 * Check "device.h" for details
1364 */
1365static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
1366 char *buf)
1367{
1368 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1369 unsigned long flags;
1370 struct list_head *ptr = NULL;
1371 struct ci13xxx_req *req = NULL;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301372 unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
David Lopoaa69a802008-11-17 14:14:51 -08001373
1374 dbg_trace("[%s] %p\n", __func__, buf);
1375 if (attr == NULL || buf == NULL) {
1376 dev_err(dev, "[%s] EINVAL\n", __func__);
1377 return 0;
1378 }
1379
1380 spin_lock_irqsave(udc->lock, flags);
1381 for (i = 0; i < hw_ep_max; i++)
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301382 list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue)
1383 {
1384 req = list_entry(ptr, struct ci13xxx_req, queue);
David Lopoaa69a802008-11-17 14:14:51 -08001385
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301386 n += scnprintf(buf + n, PAGE_SIZE - n,
1387 "EP=%02i: TD=%08X %s\n",
1388 i % hw_ep_max/2, (u32)req->dma,
1389 ((i < hw_ep_max/2) ? "RX" : "TX"));
1390
1391 for (j = 0; j < qSize; j++)
David Lopoaa69a802008-11-17 14:14:51 -08001392 n += scnprintf(buf + n, PAGE_SIZE - n,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301393 " %04X: %08X\n", j,
1394 *((u32 *)req->ptr + j));
1395 }
David Lopoaa69a802008-11-17 14:14:51 -08001396 spin_unlock_irqrestore(udc->lock, flags);
1397
1398 return n;
1399}
1400static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL);
1401
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001402/* EP# and Direction */
1403static ssize_t prime_ept(struct device *dev,
1404 struct device_attribute *attr,
1405 const char *buf, size_t count)
1406{
1407 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1408 struct ci13xxx_ep *mEp;
1409 unsigned int ep_num, dir;
1410 int n;
1411 struct ci13xxx_req *mReq = NULL;
1412
1413 if (sscanf(buf, "%u %u", &ep_num, &dir) != 2) {
1414 dev_err(dev, "<ep_num> <dir>: prime the ep");
1415 goto done;
1416 }
1417
1418 if (dir)
1419 mEp = &udc->ci13xxx_ep[ep_num + hw_ep_max/2];
1420 else
1421 mEp = &udc->ci13xxx_ep[ep_num];
1422
1423 n = hw_ep_bit(mEp->num, mEp->dir);
1424 mReq = list_entry(mEp->qh.queue.next, struct ci13xxx_req, queue);
1425 mEp->qh.ptr->td.next = mReq->dma;
1426 mEp->qh.ptr->td.token &= ~TD_STATUS;
1427
1428 wmb();
1429
1430 hw_cwrite(CAP_ENDPTPRIME, BIT(n), BIT(n));
1431 while (hw_cread(CAP_ENDPTPRIME, BIT(n)))
1432 cpu_relax();
1433
1434 pr_info("%s: prime:%08x stat:%08x ep#%d dir:%s\n", __func__,
1435 hw_cread(CAP_ENDPTPRIME, ~0),
1436 hw_cread(CAP_ENDPTSTAT, ~0),
1437 mEp->num, mEp->dir ? "IN" : "OUT");
1438done:
1439 return count;
1440
1441}
1442static DEVICE_ATTR(prime, S_IWUSR, NULL, prime_ept);
1443
1444/* EP# and Direction */
1445static ssize_t print_dtds(struct device *dev,
1446 struct device_attribute *attr,
1447 const char *buf, size_t count)
1448{
1449 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1450 struct ci13xxx_ep *mEp;
1451 unsigned int ep_num, dir;
1452 int n;
1453 struct list_head *ptr = NULL;
1454 struct ci13xxx_req *req = NULL;
1455
1456 if (sscanf(buf, "%u %u", &ep_num, &dir) != 2) {
1457 dev_err(dev, "<ep_num> <dir>: to print dtds");
1458 goto done;
1459 }
1460
1461 if (dir)
1462 mEp = &udc->ci13xxx_ep[ep_num + hw_ep_max/2];
1463 else
1464 mEp = &udc->ci13xxx_ep[ep_num];
1465
1466 n = hw_ep_bit(mEp->num, mEp->dir);
Anji jonnala6fb918c2011-10-21 17:54:21 +05301467 pr_info("%s: prime:%08x stat:%08x ep#%d dir:%s"
Vamsi Krishna8d1bbd52012-02-09 21:13:24 -08001468 "dTD_update_fail_count: %lu "
Anji jonnala6fb918c2011-10-21 17:54:21 +05301469 "mEp->dTD_update_fail_count: %lu\n", __func__,
1470 hw_cread(CAP_ENDPTPRIME, ~0),
1471 hw_cread(CAP_ENDPTSTAT, ~0),
1472 mEp->num, mEp->dir ? "IN" : "OUT",
1473 udc->dTD_update_fail_count,
1474 mEp->dTD_update_fail_count);
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001475
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001476 pr_info("QH: cap:%08x cur:%08x next:%08x token:%08x\n",
1477 mEp->qh.ptr->cap, mEp->qh.ptr->curr,
1478 mEp->qh.ptr->td.next, mEp->qh.ptr->td.token);
1479
1480 list_for_each(ptr, &mEp->qh.queue) {
1481 req = list_entry(ptr, struct ci13xxx_req, queue);
1482
1483 pr_info("\treq:%08x next:%08x token:%08x page0:%08x status:%d\n",
1484 req->dma, req->ptr->next, req->ptr->token,
1485 req->ptr->page[0], req->req.status);
1486 }
1487done:
1488 return count;
1489
1490}
1491static DEVICE_ATTR(dtds, S_IWUSR, NULL, print_dtds);
1492
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001493static int ci13xxx_wakeup(struct usb_gadget *_gadget)
1494{
1495 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
1496 unsigned long flags;
1497 int ret = 0;
1498
1499 trace();
1500
1501 spin_lock_irqsave(udc->lock, flags);
1502 if (!udc->remote_wakeup) {
1503 ret = -EOPNOTSUPP;
1504 dbg_trace("remote wakeup feature is not enabled\n");
1505 goto out;
1506 }
Amit Blay725cdeb2012-04-30 14:20:56 +03001507 spin_unlock_irqrestore(udc->lock, flags);
1508
1509 udc->udc_driver->notify_event(udc,
1510 CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT);
1511
1512 if (udc->transceiver)
Steve Mucklef132c6c2012-06-06 18:30:57 -07001513 usb_phy_set_suspend(udc->transceiver, 0);
Amit Blay725cdeb2012-04-30 14:20:56 +03001514
1515 spin_lock_irqsave(udc->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001516 if (!hw_cread(CAP_PORTSC, PORTSC_SUSP)) {
1517 ret = -EINVAL;
1518 dbg_trace("port is not suspended\n");
1519 goto out;
1520 }
1521 hw_cwrite(CAP_PORTSC, PORTSC_FPR, PORTSC_FPR);
1522out:
1523 spin_unlock_irqrestore(udc->lock, flags);
1524 return ret;
1525}
1526
Amit Blayfd075dd2012-06-26 13:12:50 +03001527static void usb_do_remote_wakeup(struct work_struct *w)
1528{
1529 struct ci13xxx *udc = _udc;
Pavankumar Kondeti0679a812012-06-29 10:51:58 +05301530 unsigned long flags;
1531 bool do_wake;
Amit Blayfd075dd2012-06-26 13:12:50 +03001532
Pavankumar Kondeti0679a812012-06-29 10:51:58 +05301533 /*
1534 * This work can not be canceled from interrupt handler. Check
1535 * if wakeup conditions are still met.
1536 */
1537 spin_lock_irqsave(udc->lock, flags);
1538 do_wake = udc->suspended && udc->remote_wakeup;
1539 spin_unlock_irqrestore(udc->lock, flags);
1540
1541 if (do_wake)
1542 ci13xxx_wakeup(&udc->gadget);
Amit Blayfd075dd2012-06-26 13:12:50 +03001543}
1544
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001545static ssize_t usb_remote_wakeup(struct device *dev,
1546 struct device_attribute *attr, const char *buf, size_t count)
1547{
1548 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1549
1550 ci13xxx_wakeup(&udc->gadget);
1551
1552 return count;
1553}
1554static DEVICE_ATTR(wakeup, S_IWUSR, 0, usb_remote_wakeup);
1555
David Lopoaa69a802008-11-17 14:14:51 -08001556/**
1557 * dbg_create_files: initializes the attribute interface
1558 * @dev: device
1559 *
1560 * This function returns an error code
1561 */
1562__maybe_unused static int dbg_create_files(struct device *dev)
1563{
1564 int retval = 0;
1565
1566 if (dev == NULL)
1567 return -EINVAL;
1568 retval = device_create_file(dev, &dev_attr_device);
1569 if (retval)
1570 goto done;
1571 retval = device_create_file(dev, &dev_attr_driver);
1572 if (retval)
1573 goto rm_device;
1574 retval = device_create_file(dev, &dev_attr_events);
1575 if (retval)
1576 goto rm_driver;
1577 retval = device_create_file(dev, &dev_attr_inters);
1578 if (retval)
1579 goto rm_events;
1580 retval = device_create_file(dev, &dev_attr_port_test);
1581 if (retval)
1582 goto rm_inters;
1583 retval = device_create_file(dev, &dev_attr_qheads);
1584 if (retval)
1585 goto rm_port_test;
1586 retval = device_create_file(dev, &dev_attr_registers);
1587 if (retval)
1588 goto rm_qheads;
1589 retval = device_create_file(dev, &dev_attr_requests);
1590 if (retval)
1591 goto rm_registers;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001592 retval = device_create_file(dev, &dev_attr_wakeup);
1593 if (retval)
1594 goto rm_remote_wakeup;
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001595 retval = device_create_file(dev, &dev_attr_prime);
1596 if (retval)
1597 goto rm_prime;
1598 retval = device_create_file(dev, &dev_attr_dtds);
1599 if (retval)
1600 goto rm_dtds;
1601
David Lopoaa69a802008-11-17 14:14:51 -08001602 return 0;
1603
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001604rm_dtds:
1605 device_remove_file(dev, &dev_attr_dtds);
1606rm_prime:
1607 device_remove_file(dev, &dev_attr_prime);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001608rm_remote_wakeup:
1609 device_remove_file(dev, &dev_attr_wakeup);
David Lopoaa69a802008-11-17 14:14:51 -08001610 rm_registers:
1611 device_remove_file(dev, &dev_attr_registers);
1612 rm_qheads:
1613 device_remove_file(dev, &dev_attr_qheads);
1614 rm_port_test:
1615 device_remove_file(dev, &dev_attr_port_test);
1616 rm_inters:
1617 device_remove_file(dev, &dev_attr_inters);
1618 rm_events:
1619 device_remove_file(dev, &dev_attr_events);
1620 rm_driver:
1621 device_remove_file(dev, &dev_attr_driver);
1622 rm_device:
1623 device_remove_file(dev, &dev_attr_device);
1624 done:
1625 return retval;
1626}
1627
1628/**
1629 * dbg_remove_files: destroys the attribute interface
1630 * @dev: device
1631 *
1632 * This function returns an error code
1633 */
1634__maybe_unused static int dbg_remove_files(struct device *dev)
1635{
1636 if (dev == NULL)
1637 return -EINVAL;
1638 device_remove_file(dev, &dev_attr_requests);
1639 device_remove_file(dev, &dev_attr_registers);
1640 device_remove_file(dev, &dev_attr_qheads);
1641 device_remove_file(dev, &dev_attr_port_test);
1642 device_remove_file(dev, &dev_attr_inters);
1643 device_remove_file(dev, &dev_attr_events);
1644 device_remove_file(dev, &dev_attr_driver);
1645 device_remove_file(dev, &dev_attr_device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001646 device_remove_file(dev, &dev_attr_wakeup);
David Lopoaa69a802008-11-17 14:14:51 -08001647 return 0;
1648}
1649
1650/******************************************************************************
1651 * UTIL block
1652 *****************************************************************************/
1653/**
1654 * _usb_addr: calculates endpoint address from direction & number
1655 * @ep: endpoint
1656 */
1657static inline u8 _usb_addr(struct ci13xxx_ep *ep)
1658{
1659 return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num;
1660}
1661
1662/**
1663 * _hardware_queue: configures a request at hardware level
1664 * @gadget: gadget
1665 * @mEp: endpoint
1666 *
1667 * This function returns an error code
1668 */
1669static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1670{
1671 unsigned i;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301672 int ret = 0;
1673 unsigned length = mReq->req.length;
Amit Blayfd075dd2012-06-26 13:12:50 +03001674 struct ci13xxx *udc = _udc;
David Lopoaa69a802008-11-17 14:14:51 -08001675
1676 trace("%p, %p", mEp, mReq);
1677
1678 /* don't queue twice */
1679 if (mReq->req.status == -EALREADY)
1680 return -EALREADY;
1681
David Lopoaa69a802008-11-17 14:14:51 -08001682 mReq->req.status = -EALREADY;
Michael Grzeschik954aad82011-10-10 18:38:06 +02001683 if (length && mReq->req.dma == DMA_ADDR_INVALID) {
David Lopoaa69a802008-11-17 14:14:51 -08001684 mReq->req.dma = \
1685 dma_map_single(mEp->device, mReq->req.buf,
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301686 length, mEp->dir ? DMA_TO_DEVICE :
1687 DMA_FROM_DEVICE);
David Lopoaa69a802008-11-17 14:14:51 -08001688 if (mReq->req.dma == 0)
1689 return -ENOMEM;
1690
1691 mReq->map = 1;
1692 }
1693
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301694 if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) {
1695 mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC,
1696 &mReq->zdma);
1697 if (mReq->zptr == NULL) {
1698 if (mReq->map) {
1699 dma_unmap_single(mEp->device, mReq->req.dma,
1700 length, mEp->dir ? DMA_TO_DEVICE :
1701 DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02001702 mReq->req.dma = DMA_ADDR_INVALID;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301703 mReq->map = 0;
1704 }
1705 return -ENOMEM;
1706 }
1707 memset(mReq->zptr, 0, sizeof(*mReq->zptr));
1708 mReq->zptr->next = TD_TERMINATE;
1709 mReq->zptr->token = TD_STATUS_ACTIVE;
1710 if (!mReq->req.no_interrupt)
1711 mReq->zptr->token |= TD_IOC;
1712 }
David Lopoaa69a802008-11-17 14:14:51 -08001713 /*
1714 * TD configuration
1715 * TODO - handle requests which spawns into several TDs
1716 */
1717 memset(mReq->ptr, 0, sizeof(*mReq->ptr));
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301718 mReq->ptr->token = length << ffs_nr(TD_TOTAL_BYTES);
David Lopoaa69a802008-11-17 14:14:51 -08001719 mReq->ptr->token &= TD_TOTAL_BYTES;
David Lopoaa69a802008-11-17 14:14:51 -08001720 mReq->ptr->token |= TD_STATUS_ACTIVE;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301721 if (mReq->zptr) {
1722 mReq->ptr->next = mReq->zdma;
1723 } else {
1724 mReq->ptr->next = TD_TERMINATE;
1725 if (!mReq->req.no_interrupt)
1726 mReq->ptr->token |= TD_IOC;
1727 }
Ofir Cohena1c2a872011-12-14 10:26:34 +02001728
1729 /* MSM Specific: updating the request as required for
1730 * SPS mode. Enable MSM proprietary DMA engine acording
1731 * to the UDC private data in the request.
1732 */
1733 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
1734 if (mReq->req.udc_priv & MSM_SPS_MODE) {
1735 mReq->ptr->token = TD_STATUS_ACTIVE;
Ido Shayevitzd1cb16c2012-03-28 18:57:47 +02001736 if (mReq->req.udc_priv & MSM_IS_FINITE_TRANSFER)
Ofir Cohena1c2a872011-12-14 10:26:34 +02001737 mReq->ptr->next = TD_TERMINATE;
1738 else
1739 mReq->ptr->next = MSM_ETD_TYPE | mReq->dma;
1740 if (!mReq->req.no_interrupt)
1741 mReq->ptr->token |= MSM_ETD_IOC;
1742 }
Amit Blay522d0362012-06-18 20:56:38 +03001743 mReq->req.dma = 0;
Ofir Cohena1c2a872011-12-14 10:26:34 +02001744 }
1745
David Lopoaa69a802008-11-17 14:14:51 -08001746 mReq->ptr->page[0] = mReq->req.dma;
1747 for (i = 1; i < 5; i++)
1748 mReq->ptr->page[i] =
Artem Leonenko0a313c42010-12-14 23:47:06 -08001749 (mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK;
David Lopoaa69a802008-11-17 14:14:51 -08001750
Amit Blayfd075dd2012-06-26 13:12:50 +03001751 /* Remote Wakeup */
1752 if (udc->suspended) {
1753 if (!udc->remote_wakeup) {
1754 mReq->req.status = -EAGAIN;
1755 dev_dbg(mEp->device, "%s: queue failed (suspend) ept #%d\n",
1756 __func__, mEp->num);
1757 return -EAGAIN;
1758 }
1759 usb_phy_set_suspend(udc->transceiver, 0);
1760 schedule_delayed_work(&udc->rw_work, REMOTE_WAKEUP_DELAY);
1761 }
1762
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301763 if (!list_empty(&mEp->qh.queue)) {
1764 struct ci13xxx_req *mReqPrev;
1765 int n = hw_ep_bit(mEp->num, mEp->dir);
1766 int tmp_stat;
1767
1768 mReqPrev = list_entry(mEp->qh.queue.prev,
1769 struct ci13xxx_req, queue);
1770 if (mReqPrev->zptr)
1771 mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
1772 else
1773 mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
1774 wmb();
1775 if (hw_cread(CAP_ENDPTPRIME, BIT(n)))
1776 goto done;
1777 do {
1778 hw_cwrite(CAP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
1779 tmp_stat = hw_cread(CAP_ENDPTSTAT, BIT(n));
1780 } while (!hw_cread(CAP_USBCMD, USBCMD_ATDTW));
1781 hw_cwrite(CAP_USBCMD, USBCMD_ATDTW, 0);
1782 if (tmp_stat)
1783 goto done;
1784 }
1785
1786 /* QH configuration */
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001787 if (!list_empty(&mEp->qh.queue)) {
1788 struct ci13xxx_req *mReq = \
1789 list_entry(mEp->qh.queue.next,
1790 struct ci13xxx_req, queue);
1791
1792 if (TD_STATUS_ACTIVE & mReq->ptr->token) {
1793 mEp->qh.ptr->td.next = mReq->dma;
1794 mEp->qh.ptr->td.token &= ~TD_STATUS;
1795 goto prime;
1796 }
1797 }
1798
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301799 mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */
Ofir Cohena1c2a872011-12-14 10:26:34 +02001800
1801 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
1802 if (mReq->req.udc_priv & MSM_SPS_MODE) {
1803 mEp->qh.ptr->td.next |= MSM_ETD_TYPE;
1804 i = hw_cread(CAP_ENDPTPIPEID +
1805 mEp->num * sizeof(u32), ~0);
1806 /* Read current value of this EPs pipe id */
1807 i = (mEp->dir == TX) ?
1808 ((i >> MSM_TX_PIPE_ID_OFS) & MSM_PIPE_ID_MASK) :
1809 (i & MSM_PIPE_ID_MASK);
1810 /* If requested pipe id is different from current,
1811 then write it */
1812 if (i != (mReq->req.udc_priv & MSM_PIPE_ID_MASK)) {
1813 if (mEp->dir == TX)
1814 hw_cwrite(
1815 CAP_ENDPTPIPEID +
1816 mEp->num * sizeof(u32),
1817 MSM_PIPE_ID_MASK <<
1818 MSM_TX_PIPE_ID_OFS,
1819 (mReq->req.udc_priv &
1820 MSM_PIPE_ID_MASK)
1821 << MSM_TX_PIPE_ID_OFS);
1822 else
1823 hw_cwrite(
1824 CAP_ENDPTPIPEID +
1825 mEp->num * sizeof(u32),
1826 MSM_PIPE_ID_MASK,
1827 mReq->req.udc_priv &
1828 MSM_PIPE_ID_MASK);
1829 }
1830 }
1831 }
1832
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301833 mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301834 mEp->qh.ptr->cap |= QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08001835
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001836prime:
David Lopoaa69a802008-11-17 14:14:51 -08001837 wmb(); /* synchronize before ep prime */
1838
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301839 ret = hw_ep_prime(mEp->num, mEp->dir,
David Lopoaa69a802008-11-17 14:14:51 -08001840 mEp->type == USB_ENDPOINT_XFER_CONTROL);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301841done:
1842 return ret;
David Lopoaa69a802008-11-17 14:14:51 -08001843}
1844
1845/**
1846 * _hardware_dequeue: handles a request at hardware level
1847 * @gadget: gadget
1848 * @mEp: endpoint
1849 *
1850 * This function returns an error code
1851 */
1852static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1853{
1854 trace("%p, %p", mEp, mReq);
1855
1856 if (mReq->req.status != -EALREADY)
1857 return -EINVAL;
1858
Vijayavardhan Vennapusa590b8ce2011-10-20 02:38:14 +05301859 /* clean speculative fetches on req->ptr->token */
1860 mb();
1861
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301862 if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
1863 return -EBUSY;
1864
Ofir Cohena1c2a872011-12-14 10:26:34 +02001865 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID)
1866 if ((mReq->req.udc_priv & MSM_SPS_MODE) &&
Ido Shayevitzd1cb16c2012-03-28 18:57:47 +02001867 (mReq->req.udc_priv & MSM_IS_FINITE_TRANSFER))
Ofir Cohena1c2a872011-12-14 10:26:34 +02001868 return -EBUSY;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301869 if (mReq->zptr) {
1870 if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
1871 return -EBUSY;
1872 dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
1873 mReq->zptr = NULL;
1874 }
David Lopoaa69a802008-11-17 14:14:51 -08001875
1876 mReq->req.status = 0;
1877
1878 if (mReq->map) {
1879 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
1880 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02001881 mReq->req.dma = DMA_ADDR_INVALID;
David Lopoaa69a802008-11-17 14:14:51 -08001882 mReq->map = 0;
1883 }
1884
1885 mReq->req.status = mReq->ptr->token & TD_STATUS;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301886 if ((TD_STATUS_HALTED & mReq->req.status) != 0)
David Lopoaa69a802008-11-17 14:14:51 -08001887 mReq->req.status = -1;
1888 else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0)
1889 mReq->req.status = -1;
1890 else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0)
1891 mReq->req.status = -1;
1892
1893 mReq->req.actual = mReq->ptr->token & TD_TOTAL_BYTES;
1894 mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES);
1895 mReq->req.actual = mReq->req.length - mReq->req.actual;
1896 mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual;
1897
1898 return mReq->req.actual;
1899}
1900
1901/**
1902 * _ep_nuke: dequeues all endpoint requests
1903 * @mEp: endpoint
1904 *
1905 * This function returns an error code
1906 * Caller must hold lock
1907 */
1908static int _ep_nuke(struct ci13xxx_ep *mEp)
1909__releases(mEp->lock)
1910__acquires(mEp->lock)
1911{
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05301912 struct ci13xxx_ep *mEpTemp = mEp;
Ofir Cohena1c2a872011-12-14 10:26:34 +02001913 unsigned val;
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05301914
David Lopoaa69a802008-11-17 14:14:51 -08001915 trace("%p", mEp);
1916
1917 if (mEp == NULL)
1918 return -EINVAL;
1919
1920 hw_ep_flush(mEp->num, mEp->dir);
1921
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301922 while (!list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -08001923
1924 /* pop oldest request */
1925 struct ci13xxx_req *mReq = \
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301926 list_entry(mEp->qh.queue.next,
David Lopoaa69a802008-11-17 14:14:51 -08001927 struct ci13xxx_req, queue);
1928 list_del_init(&mReq->queue);
Ofir Cohena1c2a872011-12-14 10:26:34 +02001929
1930 /* MSM Specific: Clear end point proprietary register */
1931 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
1932 if (mReq->req.udc_priv & MSM_SPS_MODE) {
1933 val = hw_cread(CAP_ENDPTPIPEID +
1934 mEp->num * sizeof(u32),
1935 ~0);
1936
1937 if (val != MSM_EP_PIPE_ID_RESET_VAL)
1938 hw_cwrite(
1939 CAP_ENDPTPIPEID +
1940 mEp->num * sizeof(u32),
1941 ~0, MSM_EP_PIPE_ID_RESET_VAL);
1942 }
1943 }
David Lopoaa69a802008-11-17 14:14:51 -08001944 mReq->req.status = -ESHUTDOWN;
1945
Anji jonnalaea7bbc32011-12-26 16:39:53 +05301946 if (mReq->map) {
1947 dma_unmap_single(mEp->device, mReq->req.dma,
1948 mReq->req.length,
1949 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Pavankumar Kondeti3c9a1d52012-06-06 09:56:03 +05301950 mReq->req.dma = DMA_ADDR_INVALID;
Anji jonnalaea7bbc32011-12-26 16:39:53 +05301951 mReq->map = 0;
1952 }
1953
Artem Leonenko7c25a822010-12-14 23:46:55 -08001954 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08001955 spin_unlock(mEp->lock);
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05301956 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
1957 mReq->req.length)
1958 mEpTemp = &_udc->ep0in;
1959 mReq->req.complete(&mEpTemp->ep, &mReq->req);
David Lopoaa69a802008-11-17 14:14:51 -08001960 spin_lock(mEp->lock);
1961 }
1962 }
1963 return 0;
1964}
1965
1966/**
1967 * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
1968 * @gadget: gadget
1969 *
1970 * This function returns an error code
David Lopoaa69a802008-11-17 14:14:51 -08001971 */
1972static int _gadget_stop_activity(struct usb_gadget *gadget)
David Lopoaa69a802008-11-17 14:14:51 -08001973{
1974 struct usb_ep *ep;
1975 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301976 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -08001977
1978 trace("%p", gadget);
1979
1980 if (gadget == NULL)
1981 return -EINVAL;
1982
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301983 spin_lock_irqsave(udc->lock, flags);
1984 udc->gadget.speed = USB_SPEED_UNKNOWN;
1985 udc->remote_wakeup = 0;
1986 udc->suspended = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001987 udc->configured = 0;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301988 spin_unlock_irqrestore(udc->lock, flags);
1989
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05301990 gadget->b_hnp_enable = 0;
1991 gadget->a_hnp_support = 0;
1992 gadget->host_request = 0;
1993 gadget->otg_srp_reqd = 0;
1994
David Lopoaa69a802008-11-17 14:14:51 -08001995 /* flush all endpoints */
1996 gadget_for_each_ep(ep, gadget) {
1997 usb_ep_fifo_flush(ep);
1998 }
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301999 usb_ep_fifo_flush(&udc->ep0out.ep);
2000 usb_ep_fifo_flush(&udc->ep0in.ep);
David Lopoaa69a802008-11-17 14:14:51 -08002001
2002 udc->driver->disconnect(gadget);
2003
2004 /* make sure to disable all endpoints */
2005 gadget_for_each_ep(ep, gadget) {
2006 usb_ep_disable(ep);
2007 }
David Lopoaa69a802008-11-17 14:14:51 -08002008
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302009 if (udc->status != NULL) {
2010 usb_ep_free_request(&udc->ep0in.ep, udc->status);
2011 udc->status = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002012 }
2013
David Lopoaa69a802008-11-17 14:14:51 -08002014 return 0;
2015}
2016
2017/******************************************************************************
2018 * ISR block
2019 *****************************************************************************/
2020/**
2021 * isr_reset_handler: USB reset interrupt handler
2022 * @udc: UDC device
2023 *
2024 * This function resets USB engine after a bus reset occurred
2025 */
2026static void isr_reset_handler(struct ci13xxx *udc)
2027__releases(udc->lock)
2028__acquires(udc->lock)
2029{
David Lopoaa69a802008-11-17 14:14:51 -08002030 int retval;
2031
2032 trace("%p", udc);
2033
2034 if (udc == NULL) {
2035 err("EINVAL");
2036 return;
2037 }
2038
2039 dbg_event(0xFF, "BUS RST", 0);
2040
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302041 spin_unlock(udc->lock);
Anji jonnala8bbde012011-10-28 14:17:25 +05302042
2043 /*stop charging upon reset */
2044 if (udc->transceiver)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002045 usb_phy_set_power(udc->transceiver, 0);
Anji jonnala8bbde012011-10-28 14:17:25 +05302046
David Lopoaa69a802008-11-17 14:14:51 -08002047 retval = _gadget_stop_activity(&udc->gadget);
2048 if (retval)
2049 goto done;
2050
2051 retval = hw_usb_reset();
2052 if (retval)
2053 goto done;
2054
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302055 udc->status = usb_ep_alloc_request(&udc->ep0in.ep, GFP_ATOMIC);
2056 if (udc->status == NULL)
2057 retval = -ENOMEM;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302058
David Lopoaa69a802008-11-17 14:14:51 -08002059 spin_lock(udc->lock);
2060
2061 done:
2062 if (retval)
2063 err("error: %i", retval);
2064}
2065
2066/**
Amit Blay6fa647a2012-05-24 14:12:08 +03002067 * isr_resume_handler: USB PCI interrupt handler
2068 * @udc: UDC device
2069 *
2070 */
2071static void isr_resume_handler(struct ci13xxx *udc)
2072{
2073 udc->gadget.speed = hw_port_is_high_speed() ?
2074 USB_SPEED_HIGH : USB_SPEED_FULL;
2075 if (udc->suspended) {
2076 spin_unlock(udc->lock);
Amit Blay9b033682012-05-24 16:59:23 +03002077 if (udc->udc_driver->notify_event)
2078 udc->udc_driver->notify_event(udc,
2079 CI13XXX_CONTROLLER_RESUME_EVENT);
Amit Blay6fa647a2012-05-24 14:12:08 +03002080 if (udc->transceiver)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002081 usb_phy_set_suspend(udc->transceiver, 0);
Amit Blay6fa647a2012-05-24 14:12:08 +03002082 udc->driver->resume(&udc->gadget);
2083 spin_lock(udc->lock);
2084 udc->suspended = 0;
2085 }
2086}
2087
2088/**
2089 * isr_resume_handler: USB SLI interrupt handler
2090 * @udc: UDC device
2091 *
2092 */
2093static void isr_suspend_handler(struct ci13xxx *udc)
2094{
2095 if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
2096 udc->vbus_active) {
2097 if (udc->suspended == 0) {
2098 spin_unlock(udc->lock);
2099 udc->driver->suspend(&udc->gadget);
2100 if (udc->udc_driver->notify_event)
2101 udc->udc_driver->notify_event(udc,
2102 CI13XXX_CONTROLLER_SUSPEND_EVENT);
2103 if (udc->transceiver)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002104 usb_phy_set_suspend(udc->transceiver, 1);
Amit Blay6fa647a2012-05-24 14:12:08 +03002105 spin_lock(udc->lock);
2106 udc->suspended = 1;
2107 }
2108 }
2109}
2110
2111/**
David Lopoaa69a802008-11-17 14:14:51 -08002112 * isr_get_status_complete: get_status request complete function
2113 * @ep: endpoint
2114 * @req: request handled
2115 *
2116 * Caller must release lock
2117 */
2118static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
2119{
2120 trace("%p, %p", ep, req);
2121
2122 if (ep == NULL || req == NULL) {
2123 err("EINVAL");
2124 return;
2125 }
2126
2127 kfree(req->buf);
2128 usb_ep_free_request(ep, req);
2129}
2130
2131/**
2132 * isr_get_status_response: get_status request response
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302133 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08002134 * @setup: setup request packet
2135 *
2136 * This function returns an error code
2137 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302138static int isr_get_status_response(struct ci13xxx *udc,
David Lopoaa69a802008-11-17 14:14:51 -08002139 struct usb_ctrlrequest *setup)
2140__releases(mEp->lock)
2141__acquires(mEp->lock)
2142{
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302143 struct ci13xxx_ep *mEp = &udc->ep0in;
David Lopoaa69a802008-11-17 14:14:51 -08002144 struct usb_request *req = NULL;
2145 gfp_t gfp_flags = GFP_ATOMIC;
2146 int dir, num, retval;
2147
2148 trace("%p, %p", mEp, setup);
2149
2150 if (mEp == NULL || setup == NULL)
2151 return -EINVAL;
2152
2153 spin_unlock(mEp->lock);
2154 req = usb_ep_alloc_request(&mEp->ep, gfp_flags);
2155 spin_lock(mEp->lock);
2156 if (req == NULL)
2157 return -ENOMEM;
2158
2159 req->complete = isr_get_status_complete;
2160 req->length = 2;
2161 req->buf = kzalloc(req->length, gfp_flags);
2162 if (req->buf == NULL) {
2163 retval = -ENOMEM;
2164 goto err_free_req;
2165 }
2166
2167 if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302168 if (setup->wIndex == OTG_STATUS_SELECTOR) {
2169 *((u8 *)req->buf) = _udc->gadget.host_request <<
2170 HOST_REQUEST_FLAG;
2171 req->length = 1;
2172 } else {
2173 /* Assume that device is bus powered for now. */
2174 *((u16 *)req->buf) = _udc->remote_wakeup << 1;
2175 }
2176 /* TODO: D1 - Remote Wakeup; D0 - Self Powered */
David Lopoaa69a802008-11-17 14:14:51 -08002177 retval = 0;
2178 } else if ((setup->bRequestType & USB_RECIP_MASK) \
2179 == USB_RECIP_ENDPOINT) {
2180 dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
2181 TX : RX;
2182 num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK;
2183 *((u16 *)req->buf) = hw_ep_get_halt(num, dir);
2184 }
2185 /* else do nothing; reserved for future use */
2186
2187 spin_unlock(mEp->lock);
2188 retval = usb_ep_queue(&mEp->ep, req, gfp_flags);
2189 spin_lock(mEp->lock);
2190 if (retval)
2191 goto err_free_buf;
2192
2193 return 0;
2194
2195 err_free_buf:
2196 kfree(req->buf);
2197 err_free_req:
2198 spin_unlock(mEp->lock);
2199 usb_ep_free_request(&mEp->ep, req);
2200 spin_lock(mEp->lock);
2201 return retval;
2202}
2203
2204/**
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302205 * isr_setup_status_complete: setup_status request complete function
2206 * @ep: endpoint
2207 * @req: request handled
2208 *
2209 * Caller must release lock. Put the port in test mode if test mode
2210 * feature is selected.
2211 */
2212static void
2213isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
2214{
2215 struct ci13xxx *udc = req->context;
2216 unsigned long flags;
2217
2218 trace("%p, %p", ep, req);
2219
2220 spin_lock_irqsave(udc->lock, flags);
2221 if (udc->test_mode)
2222 hw_port_test_set(udc->test_mode);
2223 spin_unlock_irqrestore(udc->lock, flags);
2224}
2225
2226/**
David Lopoaa69a802008-11-17 14:14:51 -08002227 * isr_setup_status_phase: queues the status phase of a setup transation
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302228 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08002229 *
2230 * This function returns an error code
2231 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302232static int isr_setup_status_phase(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -08002233__releases(mEp->lock)
2234__acquires(mEp->lock)
2235{
2236 int retval;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302237 struct ci13xxx_ep *mEp;
David Lopoaa69a802008-11-17 14:14:51 -08002238
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302239 trace("%p", udc);
David Lopoaa69a802008-11-17 14:14:51 -08002240
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302241 mEp = (udc->ep0_dir == TX) ? &udc->ep0out : &udc->ep0in;
Vijayavardhan Vennapusa28f14ee2012-06-07 16:12:49 +05302242 if (udc->status) {
2243 udc->status->context = udc;
2244 udc->status->complete = isr_setup_status_complete;
2245 } else
2246 return -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -08002247
2248 spin_unlock(mEp->lock);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302249 retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
David Lopoaa69a802008-11-17 14:14:51 -08002250 spin_lock(mEp->lock);
2251
2252 return retval;
2253}
2254
2255/**
2256 * isr_tr_complete_low: transaction complete low level handler
2257 * @mEp: endpoint
2258 *
2259 * This function returns an error code
2260 * Caller must hold lock
2261 */
2262static int isr_tr_complete_low(struct ci13xxx_ep *mEp)
2263__releases(mEp->lock)
2264__acquires(mEp->lock)
2265{
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302266 struct ci13xxx_req *mReq, *mReqTemp;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302267 struct ci13xxx_ep *mEpTemp = mEp;
Pavankumar Kondeti986b11b2011-05-02 11:56:29 +05302268 int uninitialized_var(retval);
Anji jonnala6fb918c2011-10-21 17:54:21 +05302269 int req_dequeue = 1;
2270 struct ci13xxx *udc = _udc;
David Lopoaa69a802008-11-17 14:14:51 -08002271
2272 trace("%p", mEp);
2273
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302274 if (list_empty(&mEp->qh.queue))
Anji jonnala6fb918c2011-10-21 17:54:21 +05302275 return 0;
David Lopoaa69a802008-11-17 14:14:51 -08002276
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302277 list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,
2278 queue) {
Anji jonnala6fb918c2011-10-21 17:54:21 +05302279dequeue:
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302280 retval = _hardware_dequeue(mEp, mReq);
Anji jonnala6fb918c2011-10-21 17:54:21 +05302281 if (retval < 0) {
2282 /*
2283 * FIXME: don't know exact delay
2284 * required for HW to update dTD status
2285 * bits. This is a temporary workaround till
2286 * HW designers come back on this.
2287 */
2288 if (retval == -EBUSY && req_dequeue && mEp->dir == 0) {
2289 req_dequeue = 0;
2290 udc->dTD_update_fail_count++;
2291 mEp->dTD_update_fail_count++;
2292 udelay(10);
2293 goto dequeue;
2294 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302295 break;
Anji jonnala6fb918c2011-10-21 17:54:21 +05302296 }
2297 req_dequeue = 0;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302298 list_del_init(&mReq->queue);
2299 dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
2300 if (mReq->req.complete != NULL) {
2301 spin_unlock(mEp->lock);
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302302 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
2303 mReq->req.length)
2304 mEpTemp = &_udc->ep0in;
2305 mReq->req.complete(&mEpTemp->ep, &mReq->req);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302306 spin_lock(mEp->lock);
2307 }
2308 }
David Lopoaa69a802008-11-17 14:14:51 -08002309
Pavankumar Kondetief907482011-05-02 11:56:27 +05302310 if (retval == -EBUSY)
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302311 retval = 0;
2312 if (retval < 0)
David Lopoaa69a802008-11-17 14:14:51 -08002313 dbg_event(_usb_addr(mEp), "DONE", retval);
David Lopoaa69a802008-11-17 14:14:51 -08002314
David Lopoaa69a802008-11-17 14:14:51 -08002315 return retval;
2316}
2317
2318/**
2319 * isr_tr_complete_handler: transaction complete interrupt handler
2320 * @udc: UDC descriptor
2321 *
2322 * This function handles traffic events
2323 */
2324static void isr_tr_complete_handler(struct ci13xxx *udc)
2325__releases(udc->lock)
2326__acquires(udc->lock)
2327{
2328 unsigned i;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302329 u8 tmode = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002330
2331 trace("%p", udc);
2332
2333 if (udc == NULL) {
2334 err("EINVAL");
2335 return;
2336 }
2337
2338 for (i = 0; i < hw_ep_max; i++) {
2339 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302340 int type, num, dir, err = -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -08002341 struct usb_ctrlrequest req;
2342
David Lopoaa69a802008-11-17 14:14:51 -08002343 if (mEp->desc == NULL)
2344 continue; /* not configured */
2345
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302346 if (hw_test_and_clear_complete(i)) {
David Lopoaa69a802008-11-17 14:14:51 -08002347 err = isr_tr_complete_low(mEp);
2348 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
2349 if (err > 0) /* needs status phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302350 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002351 if (err < 0) {
2352 dbg_event(_usb_addr(mEp),
2353 "ERROR", err);
2354 spin_unlock(udc->lock);
2355 if (usb_ep_set_halt(&mEp->ep))
2356 err("error: ep_set_halt");
2357 spin_lock(udc->lock);
2358 }
2359 }
2360 }
2361
2362 if (mEp->type != USB_ENDPOINT_XFER_CONTROL ||
2363 !hw_test_and_clear_setup_status(i))
2364 continue;
2365
2366 if (i != 0) {
2367 warn("ctrl traffic received at endpoint");
2368 continue;
2369 }
2370
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302371 /*
2372 * Flush data and handshake transactions of previous
2373 * setup packet.
2374 */
2375 _ep_nuke(&udc->ep0out);
2376 _ep_nuke(&udc->ep0in);
2377
David Lopoaa69a802008-11-17 14:14:51 -08002378 /* read_setup_packet */
2379 do {
2380 hw_test_and_set_setup_guard();
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302381 memcpy(&req, &mEp->qh.ptr->setup, sizeof(req));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002382 /* Ensure buffer is read before acknowledging to h/w */
2383 mb();
David Lopoaa69a802008-11-17 14:14:51 -08002384 } while (!hw_test_and_clear_setup_guard());
2385
2386 type = req.bRequestType;
2387
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302388 udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
David Lopoaa69a802008-11-17 14:14:51 -08002389
2390 dbg_setup(_usb_addr(mEp), &req);
2391
2392 switch (req.bRequest) {
2393 case USB_REQ_CLEAR_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302394 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
2395 le16_to_cpu(req.wValue) ==
2396 USB_ENDPOINT_HALT) {
2397 if (req.wLength != 0)
David Lopoaa69a802008-11-17 14:14:51 -08002398 break;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302399 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302400 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302401 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302402 if (dir) /* TX */
2403 num += hw_ep_max/2;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302404 if (!udc->ci13xxx_ep[num].wedge) {
2405 spin_unlock(udc->lock);
2406 err = usb_ep_clear_halt(
2407 &udc->ci13xxx_ep[num].ep);
2408 spin_lock(udc->lock);
2409 if (err)
2410 break;
2411 }
2412 err = isr_setup_status_phase(udc);
2413 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
2414 le16_to_cpu(req.wValue) ==
2415 USB_DEVICE_REMOTE_WAKEUP) {
2416 if (req.wLength != 0)
2417 break;
2418 udc->remote_wakeup = 0;
2419 err = isr_setup_status_phase(udc);
2420 } else {
2421 goto delegate;
David Lopoaa69a802008-11-17 14:14:51 -08002422 }
David Lopoaa69a802008-11-17 14:14:51 -08002423 break;
2424 case USB_REQ_GET_STATUS:
2425 if (type != (USB_DIR_IN|USB_RECIP_DEVICE) &&
2426 type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
2427 type != (USB_DIR_IN|USB_RECIP_INTERFACE))
2428 goto delegate;
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302429 if (le16_to_cpu(req.wValue) != 0)
David Lopoaa69a802008-11-17 14:14:51 -08002430 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302431 err = isr_get_status_response(udc, &req);
David Lopoaa69a802008-11-17 14:14:51 -08002432 break;
2433 case USB_REQ_SET_ADDRESS:
2434 if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
2435 goto delegate;
2436 if (le16_to_cpu(req.wLength) != 0 ||
2437 le16_to_cpu(req.wIndex) != 0)
2438 break;
2439 err = hw_usb_set_address((u8)le16_to_cpu(req.wValue));
2440 if (err)
2441 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302442 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002443 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002444 case USB_REQ_SET_CONFIGURATION:
2445 if (type == (USB_DIR_OUT|USB_TYPE_STANDARD))
2446 udc->configured = !!req.wValue;
2447 goto delegate;
David Lopoaa69a802008-11-17 14:14:51 -08002448 case USB_REQ_SET_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302449 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
2450 le16_to_cpu(req.wValue) ==
2451 USB_ENDPOINT_HALT) {
2452 if (req.wLength != 0)
2453 break;
2454 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302455 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302456 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302457 if (dir) /* TX */
2458 num += hw_ep_max/2;
David Lopoaa69a802008-11-17 14:14:51 -08002459
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302460 spin_unlock(udc->lock);
2461 err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
2462 spin_lock(udc->lock);
2463 if (!err)
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302464 isr_setup_status_phase(udc);
2465 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302466 if (req.wLength != 0)
2467 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302468 switch (le16_to_cpu(req.wValue)) {
2469 case USB_DEVICE_REMOTE_WAKEUP:
2470 udc->remote_wakeup = 1;
2471 err = isr_setup_status_phase(udc);
2472 break;
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302473 case USB_DEVICE_B_HNP_ENABLE:
2474 udc->gadget.b_hnp_enable = 1;
2475 err = isr_setup_status_phase(udc);
2476 break;
2477 case USB_DEVICE_A_HNP_SUPPORT:
2478 udc->gadget.a_hnp_support = 1;
2479 err = isr_setup_status_phase(udc);
2480 break;
2481 case USB_DEVICE_A_ALT_HNP_SUPPORT:
2482 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302483 case USB_DEVICE_TEST_MODE:
2484 tmode = le16_to_cpu(req.wIndex) >> 8;
2485 switch (tmode) {
2486 case TEST_J:
2487 case TEST_K:
2488 case TEST_SE0_NAK:
2489 case TEST_PACKET:
2490 case TEST_FORCE_EN:
2491 udc->test_mode = tmode;
2492 err = isr_setup_status_phase(
2493 udc);
2494 break;
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302495 case TEST_OTG_SRP_REQD:
2496 udc->gadget.otg_srp_reqd = 1;
2497 err = isr_setup_status_phase(
2498 udc);
2499 break;
2500 case TEST_OTG_HNP_REQD:
2501 udc->gadget.host_request = 1;
2502 err = isr_setup_status_phase(
2503 udc);
2504 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302505 default:
2506 break;
2507 }
2508 default:
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302509 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302510 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302511 } else {
2512 goto delegate;
2513 }
David Lopoaa69a802008-11-17 14:14:51 -08002514 break;
2515 default:
2516delegate:
2517 if (req.wLength == 0) /* no data phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302518 udc->ep0_dir = TX;
David Lopoaa69a802008-11-17 14:14:51 -08002519
2520 spin_unlock(udc->lock);
2521 err = udc->driver->setup(&udc->gadget, &req);
2522 spin_lock(udc->lock);
2523 break;
2524 }
2525
2526 if (err < 0) {
2527 dbg_event(_usb_addr(mEp), "ERROR", err);
2528
2529 spin_unlock(udc->lock);
2530 if (usb_ep_set_halt(&mEp->ep))
2531 err("error: ep_set_halt");
2532 spin_lock(udc->lock);
2533 }
2534 }
2535}
2536
2537/******************************************************************************
2538 * ENDPT block
2539 *****************************************************************************/
2540/**
2541 * ep_enable: configure endpoint, making it usable
2542 *
2543 * Check usb_ep_enable() at "usb_gadget.h" for details
2544 */
2545static int ep_enable(struct usb_ep *ep,
2546 const struct usb_endpoint_descriptor *desc)
2547{
2548 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302549 int retval = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002550 unsigned long flags;
2551
2552 trace("%p, %p", ep, desc);
2553
2554 if (ep == NULL || desc == NULL)
2555 return -EINVAL;
2556
2557 spin_lock_irqsave(mEp->lock, flags);
2558
2559 /* only internal SW should enable ctrl endpts */
2560
2561 mEp->desc = desc;
2562
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302563 if (!list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08002564 warn("enabling a non-empty endpoint!");
2565
Matthias Kaehlcke15739bb2009-04-15 22:28:41 +02002566 mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX;
2567 mEp->num = usb_endpoint_num(desc);
2568 mEp->type = usb_endpoint_type(desc);
David Lopoaa69a802008-11-17 14:14:51 -08002569
Kuninori Morimoto29cc8892011-08-23 03:12:03 -07002570 mEp->ep.maxpacket = usb_endpoint_maxp(desc);
David Lopoaa69a802008-11-17 14:14:51 -08002571
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302572 dbg_event(_usb_addr(mEp), "ENABLE", 0);
David Lopoaa69a802008-11-17 14:14:51 -08002573
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302574 mEp->qh.ptr->cap = 0;
David Lopof23e6492009-04-16 14:35:24 -07002575
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302576 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2577 mEp->qh.ptr->cap |= QH_IOS;
2578 else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
2579 mEp->qh.ptr->cap &= ~QH_MULT;
2580 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002581 mEp->qh.ptr->cap |= QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08002582
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302583 mEp->qh.ptr->cap |=
2584 (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
2585 mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */
David Lopoaa69a802008-11-17 14:14:51 -08002586
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002587 /* complete all the updates to ept->head before enabling endpoint*/
2588 mb();
2589
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302590 /*
2591 * Enable endpoints in the HW other than ep0 as ep0
2592 * is always enabled
2593 */
2594 if (mEp->num)
2595 retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type);
David Lopoaa69a802008-11-17 14:14:51 -08002596
2597 spin_unlock_irqrestore(mEp->lock, flags);
2598 return retval;
2599}
2600
2601/**
2602 * ep_disable: endpoint is no longer usable
2603 *
2604 * Check usb_ep_disable() at "usb_gadget.h" for details
2605 */
2606static int ep_disable(struct usb_ep *ep)
2607{
2608 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2609 int direction, retval = 0;
2610 unsigned long flags;
2611
2612 trace("%p", ep);
2613
2614 if (ep == NULL)
2615 return -EINVAL;
2616 else if (mEp->desc == NULL)
2617 return -EBUSY;
2618
2619 spin_lock_irqsave(mEp->lock, flags);
2620
2621 /* only internal SW should disable ctrl endpts */
2622
2623 direction = mEp->dir;
2624 do {
2625 dbg_event(_usb_addr(mEp), "DISABLE", 0);
2626
2627 retval |= _ep_nuke(mEp);
2628 retval |= hw_ep_disable(mEp->num, mEp->dir);
2629
2630 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2631 mEp->dir = (mEp->dir == TX) ? RX : TX;
2632
2633 } while (mEp->dir != direction);
2634
2635 mEp->desc = NULL;
Ido Shayevitzf9c56cd2012-02-08 13:56:48 +02002636 mEp->ep.desc = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002637
2638 spin_unlock_irqrestore(mEp->lock, flags);
2639 return retval;
2640}
2641
2642/**
2643 * ep_alloc_request: allocate a request object to use with this endpoint
2644 *
2645 * Check usb_ep_alloc_request() at "usb_gadget.h" for details
2646 */
2647static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
2648{
2649 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2650 struct ci13xxx_req *mReq = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002651
2652 trace("%p, %i", ep, gfp_flags);
2653
2654 if (ep == NULL) {
2655 err("EINVAL");
2656 return NULL;
2657 }
2658
David Lopoaa69a802008-11-17 14:14:51 -08002659 mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
2660 if (mReq != NULL) {
2661 INIT_LIST_HEAD(&mReq->queue);
Michael Grzeschik954aad82011-10-10 18:38:06 +02002662 mReq->req.dma = DMA_ADDR_INVALID;
David Lopoaa69a802008-11-17 14:14:51 -08002663
2664 mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,
2665 &mReq->dma);
2666 if (mReq->ptr == NULL) {
2667 kfree(mReq);
2668 mReq = NULL;
2669 }
2670 }
2671
2672 dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
2673
David Lopoaa69a802008-11-17 14:14:51 -08002674 return (mReq == NULL) ? NULL : &mReq->req;
2675}
2676
2677/**
2678 * ep_free_request: frees a request object
2679 *
2680 * Check usb_ep_free_request() at "usb_gadget.h" for details
2681 */
2682static void ep_free_request(struct usb_ep *ep, struct usb_request *req)
2683{
2684 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2685 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2686 unsigned long flags;
2687
2688 trace("%p, %p", ep, req);
2689
2690 if (ep == NULL || req == NULL) {
2691 err("EINVAL");
2692 return;
2693 } else if (!list_empty(&mReq->queue)) {
2694 err("EBUSY");
2695 return;
2696 }
2697
2698 spin_lock_irqsave(mEp->lock, flags);
2699
2700 if (mReq->ptr)
2701 dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma);
2702 kfree(mReq);
2703
2704 dbg_event(_usb_addr(mEp), "FREE", 0);
2705
2706 spin_unlock_irqrestore(mEp->lock, flags);
2707}
2708
2709/**
2710 * ep_queue: queues (submits) an I/O request to an endpoint
2711 *
2712 * Check usb_ep_queue()* at usb_gadget.h" for details
2713 */
2714static int ep_queue(struct usb_ep *ep, struct usb_request *req,
2715 gfp_t __maybe_unused gfp_flags)
2716{
2717 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2718 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2719 int retval = 0;
2720 unsigned long flags;
Anji jonnala6c174d42011-07-13 13:01:47 +05302721 struct ci13xxx *udc = _udc;
David Lopoaa69a802008-11-17 14:14:51 -08002722
2723 trace("%p, %p, %X", ep, req, gfp_flags);
2724
2725 if (ep == NULL || req == NULL || mEp->desc == NULL)
2726 return -EINVAL;
2727
2728 spin_lock_irqsave(mEp->lock, flags);
2729
Anji jonnala6c174d42011-07-13 13:01:47 +05302730 if (!udc->configured && mEp->type !=
2731 USB_ENDPOINT_XFER_CONTROL) {
2732 spin_unlock_irqrestore(mEp->lock, flags);
2733 trace("usb is not configured"
2734 "ept #%d, ept name#%s\n",
2735 mEp->num, mEp->ep.name);
2736 return -ESHUTDOWN;
2737 }
2738
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302739 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
2740 if (req->length)
2741 mEp = (_udc->ep0_dir == RX) ?
2742 &_udc->ep0out : &_udc->ep0in;
2743 if (!list_empty(&mEp->qh.queue)) {
2744 _ep_nuke(mEp);
2745 retval = -EOVERFLOW;
2746 warn("endpoint ctrl %X nuked", _usb_addr(mEp));
2747 }
David Lopoaa69a802008-11-17 14:14:51 -08002748 }
2749
2750 /* first nuke then test link, e.g. previous status has not sent */
2751 if (!list_empty(&mReq->queue)) {
2752 retval = -EBUSY;
2753 err("request already in queue");
2754 goto done;
2755 }
2756
Artem Leonenko0a313c42010-12-14 23:47:06 -08002757 if (req->length > (4 * CI13XXX_PAGE_SIZE)) {
2758 req->length = (4 * CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08002759 retval = -EMSGSIZE;
2760 warn("request length truncated");
2761 }
2762
2763 dbg_queue(_usb_addr(mEp), req, retval);
2764
2765 /* push request */
2766 mReq->req.status = -EINPROGRESS;
2767 mReq->req.actual = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002768
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302769 retval = _hardware_enqueue(mEp, mReq);
Artem Leonenkod9bb9c12010-12-14 23:45:50 -08002770
2771 if (retval == -EALREADY) {
David Lopoaa69a802008-11-17 14:14:51 -08002772 dbg_event(_usb_addr(mEp), "QUEUE", retval);
2773 retval = 0;
2774 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302775 if (!retval)
2776 list_add_tail(&mReq->queue, &mEp->qh.queue);
David Lopoaa69a802008-11-17 14:14:51 -08002777
2778 done:
2779 spin_unlock_irqrestore(mEp->lock, flags);
2780 return retval;
2781}
2782
2783/**
2784 * ep_dequeue: dequeues (cancels, unlinks) an I/O request from an endpoint
2785 *
2786 * Check usb_ep_dequeue() at "usb_gadget.h" for details
2787 */
2788static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
2789{
2790 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05302791 struct ci13xxx_ep *mEpTemp = mEp;
David Lopoaa69a802008-11-17 14:14:51 -08002792 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2793 unsigned long flags;
2794
2795 trace("%p, %p", ep, req);
2796
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302797 if (ep == NULL || req == NULL || mReq->req.status != -EALREADY ||
2798 mEp->desc == NULL || list_empty(&mReq->queue) ||
2799 list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08002800 return -EINVAL;
2801
2802 spin_lock_irqsave(mEp->lock, flags);
2803
2804 dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
2805
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302806 hw_ep_flush(mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08002807
2808 /* pop request */
2809 list_del_init(&mReq->queue);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302810 if (mReq->map) {
2811 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
2812 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02002813 mReq->req.dma = DMA_ADDR_INVALID;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302814 mReq->map = 0;
2815 }
David Lopoaa69a802008-11-17 14:14:51 -08002816 req->status = -ECONNRESET;
2817
Artem Leonenko7c25a822010-12-14 23:46:55 -08002818 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08002819 spin_unlock(mEp->lock);
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05302820 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
2821 mReq->req.length)
2822 mEpTemp = &_udc->ep0in;
2823 mReq->req.complete(&mEpTemp->ep, &mReq->req);
David Lopoaa69a802008-11-17 14:14:51 -08002824 spin_lock(mEp->lock);
2825 }
2826
2827 spin_unlock_irqrestore(mEp->lock, flags);
2828 return 0;
2829}
2830
Bar Weiner0fc137a2012-03-28 16:58:09 +02002831static int is_sps_req(struct ci13xxx_req *mReq)
2832{
2833 return (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID &&
2834 mReq->req.udc_priv & MSM_SPS_MODE);
2835}
2836
David Lopoaa69a802008-11-17 14:14:51 -08002837/**
2838 * ep_set_halt: sets the endpoint halt feature
2839 *
2840 * Check usb_ep_set_halt() at "usb_gadget.h" for details
2841 */
2842static int ep_set_halt(struct usb_ep *ep, int value)
2843{
2844 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2845 int direction, retval = 0;
2846 unsigned long flags;
2847
2848 trace("%p, %i", ep, value);
2849
2850 if (ep == NULL || mEp->desc == NULL)
2851 return -EINVAL;
2852
2853 spin_lock_irqsave(mEp->lock, flags);
2854
2855#ifndef STALL_IN
2856 /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
2857 if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX &&
Bar Weiner0fc137a2012-03-28 16:58:09 +02002858 !list_empty(&mEp->qh.queue) &&
2859 !is_sps_req(list_entry(mEp->qh.queue.next, struct ci13xxx_req,
2860 queue))){
David Lopoaa69a802008-11-17 14:14:51 -08002861 spin_unlock_irqrestore(mEp->lock, flags);
2862 return -EAGAIN;
2863 }
2864#endif
2865
2866 direction = mEp->dir;
2867 do {
2868 dbg_event(_usb_addr(mEp), "HALT", value);
2869 retval |= hw_ep_set_halt(mEp->num, mEp->dir, value);
2870
2871 if (!value)
2872 mEp->wedge = 0;
2873
2874 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2875 mEp->dir = (mEp->dir == TX) ? RX : TX;
2876
2877 } while (mEp->dir != direction);
2878
2879 spin_unlock_irqrestore(mEp->lock, flags);
2880 return retval;
2881}
2882
2883/**
2884 * ep_set_wedge: sets the halt feature and ignores clear requests
2885 *
2886 * Check usb_ep_set_wedge() at "usb_gadget.h" for details
2887 */
2888static int ep_set_wedge(struct usb_ep *ep)
2889{
2890 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2891 unsigned long flags;
2892
2893 trace("%p", ep);
2894
2895 if (ep == NULL || mEp->desc == NULL)
2896 return -EINVAL;
2897
2898 spin_lock_irqsave(mEp->lock, flags);
2899
2900 dbg_event(_usb_addr(mEp), "WEDGE", 0);
2901 mEp->wedge = 1;
2902
2903 spin_unlock_irqrestore(mEp->lock, flags);
2904
2905 return usb_ep_set_halt(ep);
2906}
2907
2908/**
2909 * ep_fifo_flush: flushes contents of a fifo
2910 *
2911 * Check usb_ep_fifo_flush() at "usb_gadget.h" for details
2912 */
2913static void ep_fifo_flush(struct usb_ep *ep)
2914{
2915 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2916 unsigned long flags;
2917
2918 trace("%p", ep);
2919
2920 if (ep == NULL) {
2921 err("%02X: -EINVAL", _usb_addr(mEp));
2922 return;
2923 }
2924
2925 spin_lock_irqsave(mEp->lock, flags);
2926
2927 dbg_event(_usb_addr(mEp), "FFLUSH", 0);
2928 hw_ep_flush(mEp->num, mEp->dir);
2929
2930 spin_unlock_irqrestore(mEp->lock, flags);
2931}
2932
2933/**
2934 * Endpoint-specific part of the API to the USB controller hardware
2935 * Check "usb_gadget.h" for details
2936 */
2937static const struct usb_ep_ops usb_ep_ops = {
2938 .enable = ep_enable,
2939 .disable = ep_disable,
2940 .alloc_request = ep_alloc_request,
2941 .free_request = ep_free_request,
2942 .queue = ep_queue,
2943 .dequeue = ep_dequeue,
2944 .set_halt = ep_set_halt,
2945 .set_wedge = ep_set_wedge,
2946 .fifo_flush = ep_fifo_flush,
2947};
2948
2949/******************************************************************************
2950 * GADGET block
2951 *****************************************************************************/
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302952static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
2953{
2954 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2955 unsigned long flags;
2956 int gadget_ready = 0;
2957
2958 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS))
2959 return -EOPNOTSUPP;
2960
2961 spin_lock_irqsave(udc->lock, flags);
2962 udc->vbus_active = is_active;
2963 if (udc->driver)
2964 gadget_ready = 1;
2965 spin_unlock_irqrestore(udc->lock, flags);
2966
2967 if (gadget_ready) {
2968 if (is_active) {
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302969 pm_runtime_get_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302970 hw_device_reset(udc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002971 if (udc->softconnect)
2972 hw_device_state(udc->ep0out.qh.dma);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302973 } else {
2974 hw_device_state(0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302975 _gadget_stop_activity(&udc->gadget);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302976 if (udc->udc_driver->notify_event)
2977 udc->udc_driver->notify_event(udc,
Amit Blay9b033682012-05-24 16:59:23 +03002978 CI13XXX_CONTROLLER_DISCONNECT_EVENT);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302979 pm_runtime_put_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302980 }
2981 }
2982
2983 return 0;
2984}
2985
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302986static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
2987{
2988 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2989
2990 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002991 return usb_phy_set_power(udc->transceiver, mA);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302992 return -ENOTSUPP;
2993}
2994
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002995static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_active)
2996{
2997 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2998 unsigned long flags;
2999
3000 spin_lock_irqsave(udc->lock, flags);
3001 udc->softconnect = is_active;
3002 if (((udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) &&
3003 !udc->vbus_active) || !udc->driver) {
3004 spin_unlock_irqrestore(udc->lock, flags);
3005 return 0;
3006 }
3007 spin_unlock_irqrestore(udc->lock, flags);
3008
Ofir Cohen06789f12012-01-16 09:43:13 +02003009 if (is_active) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003010 hw_device_state(udc->ep0out.qh.dma);
Ofir Cohen06789f12012-01-16 09:43:13 +02003011 if (udc->udc_driver->notify_event)
3012 udc->udc_driver->notify_event(udc,
3013 CI13XXX_CONTROLLER_CONNECT_EVENT);
3014 }
Pavankumar Kondetib7f53dc2011-08-23 12:40:33 +05303015 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003016 hw_device_state(0);
Pavankumar Kondetib7f53dc2011-08-23 12:40:33 +05303017
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003018 return 0;
3019}
3020
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003021static int ci13xxx_start(struct usb_gadget_driver *driver,
3022 int (*bind)(struct usb_gadget *));
3023static int ci13xxx_stop(struct usb_gadget_driver *driver);
David Lopoaa69a802008-11-17 14:14:51 -08003024/**
3025 * Device operations part of the API to the USB controller hardware,
3026 * which don't involve endpoints (or i/o)
3027 * Check "usb_gadget.h" for details
3028 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303029static const struct usb_gadget_ops usb_gadget_ops = {
3030 .vbus_session = ci13xxx_vbus_session,
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05303031 .wakeup = ci13xxx_wakeup,
Pavankumar Kondetid8608522011-05-04 10:19:47 +05303032 .vbus_draw = ci13xxx_vbus_draw,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003033 .pullup = ci13xxx_pullup,
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003034 .start = ci13xxx_start,
3035 .stop = ci13xxx_stop,
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303036};
David Lopoaa69a802008-11-17 14:14:51 -08003037
3038/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003039 * ci13xxx_start: register a gadget driver
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003040 * @driver: the driver being registered
3041 * @bind: the driver's bind callback
David Lopoaa69a802008-11-17 14:14:51 -08003042 *
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003043 * Check ci13xxx_start() at <linux/usb/gadget.h> for details.
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003044 * Interrupts are enabled here.
David Lopoaa69a802008-11-17 14:14:51 -08003045 */
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003046static int ci13xxx_start(struct usb_gadget_driver *driver,
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003047 int (*bind)(struct usb_gadget *))
David Lopoaa69a802008-11-17 14:14:51 -08003048{
3049 struct ci13xxx *udc = _udc;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303050 unsigned long flags;
3051 int i, j;
David Lopoaa69a802008-11-17 14:14:51 -08003052 int retval = -ENOMEM;
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303053 bool put = false;
David Lopoaa69a802008-11-17 14:14:51 -08003054
3055 trace("%p", driver);
3056
3057 if (driver == NULL ||
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003058 bind == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08003059 driver->setup == NULL ||
Marc Kleine-Budde7bb4fdc2011-10-10 18:38:09 +02003060 driver->disconnect == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08003061 return -EINVAL;
3062 else if (udc == NULL)
3063 return -ENODEV;
3064 else if (udc->driver != NULL)
3065 return -EBUSY;
3066
3067 /* alloc resources */
3068 udc->qh_pool = dma_pool_create("ci13xxx_qh", &udc->gadget.dev,
3069 sizeof(struct ci13xxx_qh),
Artem Leonenko0a313c42010-12-14 23:47:06 -08003070 64, CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08003071 if (udc->qh_pool == NULL)
3072 return -ENOMEM;
3073
3074 udc->td_pool = dma_pool_create("ci13xxx_td", &udc->gadget.dev,
3075 sizeof(struct ci13xxx_td),
Artem Leonenko0a313c42010-12-14 23:47:06 -08003076 64, CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08003077 if (udc->td_pool == NULL) {
3078 dma_pool_destroy(udc->qh_pool);
3079 udc->qh_pool = NULL;
3080 return -ENOMEM;
3081 }
3082
3083 spin_lock_irqsave(udc->lock, flags);
3084
3085 info("hw_ep_max = %d", hw_ep_max);
3086
David Lopoaa69a802008-11-17 14:14:51 -08003087 udc->gadget.dev.driver = NULL;
3088
3089 retval = 0;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303090 for (i = 0; i < hw_ep_max/2; i++) {
3091 for (j = RX; j <= TX; j++) {
3092 int k = i + j * hw_ep_max/2;
3093 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
David Lopoaa69a802008-11-17 14:14:51 -08003094
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303095 scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
3096 (j == TX) ? "in" : "out");
David Lopoaa69a802008-11-17 14:14:51 -08003097
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303098 mEp->lock = udc->lock;
3099 mEp->device = &udc->gadget.dev;
3100 mEp->td_pool = udc->td_pool;
David Lopoaa69a802008-11-17 14:14:51 -08003101
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303102 mEp->ep.name = mEp->name;
3103 mEp->ep.ops = &usb_ep_ops;
3104 mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
David Lopoaa69a802008-11-17 14:14:51 -08003105
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303106 INIT_LIST_HEAD(&mEp->qh.queue);
Pavankumar Kondeti0a91efa2010-12-07 17:54:00 +05303107 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303108 mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
3109 &mEp->qh.dma);
Pavankumar Kondeti0a91efa2010-12-07 17:54:00 +05303110 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303111 if (mEp->qh.ptr == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08003112 retval = -ENOMEM;
3113 else
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303114 memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
3115
3116 /* skip ep0 out and in endpoints */
3117 if (i == 0)
3118 continue;
3119
David Lopoaa69a802008-11-17 14:14:51 -08003120 list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303121 }
David Lopoaa69a802008-11-17 14:14:51 -08003122 }
3123 if (retval)
3124 goto done;
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05303125 spin_unlock_irqrestore(udc->lock, flags);
Felipe Balbi877c1f52011-06-29 16:41:57 +03003126 udc->ep0out.ep.desc = &ctrl_endpt_out_desc;
3127 retval = usb_ep_enable(&udc->ep0out.ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05303128 if (retval)
3129 return retval;
Felipe Balbi877c1f52011-06-29 16:41:57 +03003130
3131 udc->ep0in.ep.desc = &ctrl_endpt_in_desc;
3132 retval = usb_ep_enable(&udc->ep0in.ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05303133 if (retval)
3134 return retval;
3135 spin_lock_irqsave(udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08003136
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303137 udc->gadget.ep0 = &udc->ep0in.ep;
David Lopoaa69a802008-11-17 14:14:51 -08003138 /* bind gadget */
3139 driver->driver.bus = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08003140 udc->gadget.dev.driver = &driver->driver;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003141 udc->softconnect = 1;
David Lopoaa69a802008-11-17 14:14:51 -08003142
3143 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondeti98853282011-11-24 09:01:54 +05303144 pm_runtime_get_sync(&udc->gadget.dev);
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003145 retval = bind(&udc->gadget); /* MAY SLEEP */
David Lopoaa69a802008-11-17 14:14:51 -08003146 spin_lock_irqsave(udc->lock, flags);
3147
3148 if (retval) {
David Lopoaa69a802008-11-17 14:14:51 -08003149 udc->gadget.dev.driver = NULL;
3150 goto done;
3151 }
3152
Pavankumar Kondeti49d3df52011-01-11 09:19:21 +05303153 udc->driver = driver;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303154 if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
3155 if (udc->vbus_active) {
3156 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
3157 hw_device_reset(udc);
3158 } else {
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303159 put = true;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303160 goto done;
3161 }
3162 }
3163
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303164 if (!udc->softconnect) {
3165 put = true;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003166 goto done;
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303167 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003168
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303169 retval = hw_device_state(udc->ep0out.qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08003170
3171 done:
3172 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303173 if (retval || put)
Pavankumar Kondeti98853282011-11-24 09:01:54 +05303174 pm_runtime_put_sync(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08003175 return retval;
3176}
David Lopoaa69a802008-11-17 14:14:51 -08003177
3178/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003179 * ci13xxx_stop: unregister a gadget driver
David Lopoaa69a802008-11-17 14:14:51 -08003180 *
3181 * Check usb_gadget_unregister_driver() at "usb_gadget.h" for details
3182 */
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003183static int ci13xxx_stop(struct usb_gadget_driver *driver)
David Lopoaa69a802008-11-17 14:14:51 -08003184{
3185 struct ci13xxx *udc = _udc;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303186 unsigned long i, flags;
David Lopoaa69a802008-11-17 14:14:51 -08003187
3188 trace("%p", driver);
3189
3190 if (driver == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08003191 driver->unbind == NULL ||
3192 driver->setup == NULL ||
3193 driver->disconnect == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08003194 driver != udc->driver)
3195 return -EINVAL;
3196
3197 spin_lock_irqsave(udc->lock, flags);
3198
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303199 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) ||
3200 udc->vbus_active) {
3201 hw_device_state(0);
Marc Kleine-Buddefd537c02011-10-10 18:38:07 +02003202 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303203 _gadget_stop_activity(&udc->gadget);
Marc Kleine-Buddefd537c02011-10-10 18:38:07 +02003204 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05303205 pm_runtime_put(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303206 }
David Lopoaa69a802008-11-17 14:14:51 -08003207
3208 /* unbind gadget */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303209 spin_unlock_irqrestore(udc->lock, flags);
3210 driver->unbind(&udc->gadget); /* MAY SLEEP */
3211 spin_lock_irqsave(udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08003212
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303213 udc->gadget.dev.driver = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08003214
3215 /* free resources */
3216 for (i = 0; i < hw_ep_max; i++) {
3217 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
3218
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303219 if (!list_empty(&mEp->ep.ep_list))
David Lopoaa69a802008-11-17 14:14:51 -08003220 list_del_init(&mEp->ep.ep_list);
3221
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303222 if (mEp->qh.ptr != NULL)
3223 dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08003224 }
3225
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303226 udc->gadget.ep0 = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08003227 udc->driver = NULL;
3228
3229 spin_unlock_irqrestore(udc->lock, flags);
3230
3231 if (udc->td_pool != NULL) {
3232 dma_pool_destroy(udc->td_pool);
3233 udc->td_pool = NULL;
3234 }
3235 if (udc->qh_pool != NULL) {
3236 dma_pool_destroy(udc->qh_pool);
3237 udc->qh_pool = NULL;
3238 }
3239
3240 return 0;
3241}
David Lopoaa69a802008-11-17 14:14:51 -08003242
3243/******************************************************************************
3244 * BUS block
3245 *****************************************************************************/
3246/**
3247 * udc_irq: global interrupt handler
3248 *
3249 * This function returns IRQ_HANDLED if the IRQ has been handled
3250 * It locks access to registers
3251 */
3252static irqreturn_t udc_irq(void)
3253{
3254 struct ci13xxx *udc = _udc;
3255 irqreturn_t retval;
3256 u32 intr;
3257
3258 trace();
3259
3260 if (udc == NULL) {
3261 err("ENODEV");
3262 return IRQ_HANDLED;
3263 }
3264
3265 spin_lock(udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303266
3267 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) {
3268 if (hw_cread(CAP_USBMODE, USBMODE_CM) !=
3269 USBMODE_CM_DEVICE) {
3270 spin_unlock(udc->lock);
3271 return IRQ_NONE;
3272 }
3273 }
David Lopoaa69a802008-11-17 14:14:51 -08003274 intr = hw_test_and_clear_intr_active();
3275 if (intr) {
3276 isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intr;
3277 isr_statistics.hndl.idx &= ISR_MASK;
3278 isr_statistics.hndl.cnt++;
3279
3280 /* order defines priority - do NOT change it */
3281 if (USBi_URI & intr) {
3282 isr_statistics.uri++;
3283 isr_reset_handler(udc);
3284 }
3285 if (USBi_PCI & intr) {
3286 isr_statistics.pci++;
Amit Blay6fa647a2012-05-24 14:12:08 +03003287 isr_resume_handler(udc);
David Lopoaa69a802008-11-17 14:14:51 -08003288 }
3289 if (USBi_UEI & intr)
3290 isr_statistics.uei++;
3291 if (USBi_UI & intr) {
3292 isr_statistics.ui++;
3293 isr_tr_complete_handler(udc);
3294 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05303295 if (USBi_SLI & intr) {
Amit Blay6fa647a2012-05-24 14:12:08 +03003296 isr_suspend_handler(udc);
David Lopoaa69a802008-11-17 14:14:51 -08003297 isr_statistics.sli++;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05303298 }
David Lopoaa69a802008-11-17 14:14:51 -08003299 retval = IRQ_HANDLED;
3300 } else {
3301 isr_statistics.none++;
3302 retval = IRQ_NONE;
3303 }
3304 spin_unlock(udc->lock);
3305
3306 return retval;
3307}
3308
3309/**
3310 * udc_release: driver release function
3311 * @dev: device
3312 *
3313 * Currently does nothing
3314 */
3315static void udc_release(struct device *dev)
3316{
3317 trace("%p", dev);
3318
3319 if (dev == NULL)
3320 err("EINVAL");
3321}
3322
3323/**
3324 * udc_probe: parent probe must call this to initialize UDC
3325 * @dev: parent device
3326 * @regs: registers base address
3327 * @name: driver name
3328 *
3329 * This function returns an error code
3330 * No interrupts active, the IRQ has not been requested yet
3331 * Kernel assumes 32-bit DMA operations by default, no need to dma_set_mask
3332 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303333static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
3334 void __iomem *regs)
David Lopoaa69a802008-11-17 14:14:51 -08003335{
3336 struct ci13xxx *udc;
Lena Salmana7a05202012-03-19 10:39:44 +02003337 int retval = 0, i;
David Lopoaa69a802008-11-17 14:14:51 -08003338
Marc Kleine-Budde194fa472011-10-10 18:38:08 +02003339 trace("%p, %p, %p", dev, regs, driver->name);
David Lopoaa69a802008-11-17 14:14:51 -08003340
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303341 if (dev == NULL || regs == NULL || driver == NULL ||
3342 driver->name == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08003343 return -EINVAL;
3344
3345 udc = kzalloc(sizeof(struct ci13xxx), GFP_KERNEL);
3346 if (udc == NULL)
3347 return -ENOMEM;
3348
3349 udc->lock = &udc_lock;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303350 udc->regs = regs;
3351 udc->udc_driver = driver;
David Lopoaa69a802008-11-17 14:14:51 -08003352
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303353 udc->gadget.ops = &usb_gadget_ops;
David Lopoaa69a802008-11-17 14:14:51 -08003354 udc->gadget.speed = USB_SPEED_UNKNOWN;
Michal Nazarewiczd327ab52011-11-19 18:27:37 +01003355 udc->gadget.max_speed = USB_SPEED_HIGH;
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05303356 if (udc->udc_driver->flags & CI13XXX_IS_OTG)
3357 udc->gadget.is_otg = 1;
3358 else
3359 udc->gadget.is_otg = 0;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303360 udc->gadget.name = driver->name;
David Lopoaa69a802008-11-17 14:14:51 -08003361
3362 INIT_LIST_HEAD(&udc->gadget.ep_list);
3363 udc->gadget.ep0 = NULL;
3364
Kay Sievers5df58522009-03-24 16:38:23 -07003365 dev_set_name(&udc->gadget.dev, "gadget");
David Lopoaa69a802008-11-17 14:14:51 -08003366 udc->gadget.dev.dma_mask = dev->dma_mask;
Pavankumar Kondeti61948ee2010-12-07 17:54:01 +05303367 udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
David Lopoaa69a802008-11-17 14:14:51 -08003368 udc->gadget.dev.parent = dev;
3369 udc->gadget.dev.release = udc_release;
3370
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303371 if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
Steve Mucklef132c6c2012-06-06 18:30:57 -07003372 udc->transceiver = usb_get_transceiver();
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303373 if (udc->transceiver == NULL) {
3374 retval = -ENODEV;
3375 goto free_udc;
3376 }
3377 }
3378
Amit Blayfd075dd2012-06-26 13:12:50 +03003379 INIT_DELAYED_WORK(&udc->rw_work, usb_do_remote_wakeup);
3380
Pavankumar Kondetic898b7d2012-05-16 11:54:35 +05303381 retval = hw_device_init(regs);
3382 if (retval < 0)
3383 goto put_transceiver;
3384
3385 for (i = 0; i < hw_ep_max; i++) {
3386 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
3387 INIT_LIST_HEAD(&mEp->ep.ep_list);
3388 }
3389
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303390 if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) {
3391 retval = hw_device_reset(udc);
3392 if (retval)
3393 goto put_transceiver;
3394 }
3395
David Lopoaa69a802008-11-17 14:14:51 -08003396 retval = device_register(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303397 if (retval) {
3398 put_device(&udc->gadget.dev);
3399 goto put_transceiver;
3400 }
David Lopoaa69a802008-11-17 14:14:51 -08003401
3402#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3403 retval = dbg_create_files(&udc->gadget.dev);
3404#endif
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303405 if (retval)
3406 goto unreg_device;
3407
3408 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02003409 retval = otg_set_peripheral(udc->transceiver->otg,
3410 &udc->gadget);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303411 if (retval)
3412 goto remove_dbg;
David Lopoaa69a802008-11-17 14:14:51 -08003413 }
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003414
3415 retval = usb_add_gadget_udc(dev, &udc->gadget);
3416 if (retval)
3417 goto remove_trans;
3418
Pavankumar Kondetic0360192010-12-07 17:54:04 +05303419 pm_runtime_no_callbacks(&udc->gadget.dev);
3420 pm_runtime_enable(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08003421
3422 _udc = udc;
3423 return retval;
3424
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003425remove_trans:
3426 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02003427 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02003428 usb_put_transceiver(udc->transceiver);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003429 }
3430
David Lopoaa69a802008-11-17 14:14:51 -08003431 err("error = %i", retval);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303432remove_dbg:
3433#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3434 dbg_remove_files(&udc->gadget.dev);
3435#endif
3436unreg_device:
3437 device_unregister(&udc->gadget.dev);
3438put_transceiver:
3439 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02003440 usb_put_transceiver(udc->transceiver);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303441free_udc:
David Lopoaa69a802008-11-17 14:14:51 -08003442 kfree(udc);
3443 _udc = NULL;
3444 return retval;
3445}
3446
3447/**
3448 * udc_remove: parent remove must call this to remove UDC
3449 *
3450 * No interrupts active, the IRQ has been released
3451 */
3452static void udc_remove(void)
3453{
3454 struct ci13xxx *udc = _udc;
3455
3456 if (udc == NULL) {
3457 err("EINVAL");
3458 return;
3459 }
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003460 usb_del_gadget_udc(&udc->gadget);
David Lopoaa69a802008-11-17 14:14:51 -08003461
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303462 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02003463 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02003464 usb_put_transceiver(udc->transceiver);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303465 }
David Lopoaa69a802008-11-17 14:14:51 -08003466#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3467 dbg_remove_files(&udc->gadget.dev);
3468#endif
3469 device_unregister(&udc->gadget.dev);
3470
3471 kfree(udc);
3472 _udc = NULL;
3473}