blob: fb86874801ddf9b0797211910f0fed9a8462cda9 [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)
51 * - Suspend & Remote Wakeup
52 */
Matthias Kaehlcke36825a22009-04-15 22:28:36 +020053#include <linux/delay.h>
David Lopoaa69a802008-11-17 14:14:51 -080054#include <linux/device.h>
55#include <linux/dmapool.h>
56#include <linux/dma-mapping.h>
57#include <linux/init.h>
58#include <linux/interrupt.h>
David Lopoaa69a802008-11-17 14:14:51 -080059#include <linux/io.h>
60#include <linux/irq.h>
61#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090062#include <linux/slab.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070063#include <linux/module.h>
Pavankumar Kondetic0360192010-12-07 17:54:04 +053064#include <linux/pm_runtime.h>
David Lopoaa69a802008-11-17 14:14:51 -080065#include <linux/usb/ch9.h>
66#include <linux/usb/gadget.h>
Pavankumar Kondetif01ef572010-12-07 17:54:02 +053067#include <linux/usb/otg.h>
Ido Shayevitzd1cb16c2012-03-28 18:57:47 +020068#include <linux/usb/msm_hsusb.h>
David Lopoaa69a802008-11-17 14:14:51 -080069
70#include "ci13xxx_udc.h"
71
72
73/******************************************************************************
74 * DEFINE
75 *****************************************************************************/
Michael Grzeschik954aad82011-10-10 18:38:06 +020076
77#define DMA_ADDR_INVALID (~(dma_addr_t)0)
78
David Lopoaa69a802008-11-17 14:14:51 -080079/* ctrl register bank access */
80static DEFINE_SPINLOCK(udc_lock);
81
David Lopoaa69a802008-11-17 14:14:51 -080082/* control endpoint description */
83static const struct usb_endpoint_descriptor
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +053084ctrl_endpt_out_desc = {
David Lopoaa69a802008-11-17 14:14:51 -080085 .bLength = USB_DT_ENDPOINT_SIZE,
86 .bDescriptorType = USB_DT_ENDPOINT,
87
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +053088 .bEndpointAddress = USB_DIR_OUT,
89 .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
90 .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
91};
92
93static const struct usb_endpoint_descriptor
94ctrl_endpt_in_desc = {
95 .bLength = USB_DT_ENDPOINT_SIZE,
96 .bDescriptorType = USB_DT_ENDPOINT,
97
98 .bEndpointAddress = USB_DIR_IN,
David Lopoaa69a802008-11-17 14:14:51 -080099 .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
100 .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
101};
102
103/* UDC descriptor */
104static struct ci13xxx *_udc;
105
106/* Interrupt statistics */
107#define ISR_MASK 0x1F
108static struct {
109 u32 test;
110 u32 ui;
111 u32 uei;
112 u32 pci;
113 u32 uri;
114 u32 sli;
115 u32 none;
116 struct {
117 u32 cnt;
118 u32 buf[ISR_MASK+1];
119 u32 idx;
120 } hndl;
121} isr_statistics;
122
123/**
124 * ffs_nr: find first (least significant) bit set
125 * @x: the word to search
126 *
127 * This function returns bit number (instead of position)
128 */
129static int ffs_nr(u32 x)
130{
131 int n = ffs(x);
132
133 return n ? n-1 : 32;
134}
135
136/******************************************************************************
137 * HW block
138 *****************************************************************************/
139/* register bank descriptor */
140static struct {
141 unsigned lpm; /* is LPM? */
142 void __iomem *abs; /* bus map offset */
143 void __iomem *cap; /* bus map offset + CAP offset + CAP data */
144 size_t size; /* bank size */
145} hw_bank;
146
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530147/* MSM specific */
148#define ABS_AHBBURST (0x0090UL)
149#define ABS_AHBMODE (0x0098UL)
David Lopoaa69a802008-11-17 14:14:51 -0800150/* UDC register map */
151#define ABS_CAPLENGTH (0x100UL)
152#define ABS_HCCPARAMS (0x108UL)
153#define ABS_DCCPARAMS (0x124UL)
154#define ABS_TESTMODE (hw_bank.lpm ? 0x0FCUL : 0x138UL)
155/* offset to CAPLENTGH (addr + data) */
156#define CAP_USBCMD (0x000UL)
157#define CAP_USBSTS (0x004UL)
158#define CAP_USBINTR (0x008UL)
159#define CAP_DEVICEADDR (0x014UL)
160#define CAP_ENDPTLISTADDR (0x018UL)
161#define CAP_PORTSC (0x044UL)
David Lopof23e6492009-04-16 14:35:24 -0700162#define CAP_DEVLC (0x084UL)
Ofir Cohena1c2a872011-12-14 10:26:34 +0200163#define CAP_ENDPTPIPEID (0x0BCUL)
David Lopoaa69a802008-11-17 14:14:51 -0800164#define CAP_USBMODE (hw_bank.lpm ? 0x0C8UL : 0x068UL)
165#define CAP_ENDPTSETUPSTAT (hw_bank.lpm ? 0x0D8UL : 0x06CUL)
166#define CAP_ENDPTPRIME (hw_bank.lpm ? 0x0DCUL : 0x070UL)
167#define CAP_ENDPTFLUSH (hw_bank.lpm ? 0x0E0UL : 0x074UL)
168#define CAP_ENDPTSTAT (hw_bank.lpm ? 0x0E4UL : 0x078UL)
169#define CAP_ENDPTCOMPLETE (hw_bank.lpm ? 0x0E8UL : 0x07CUL)
170#define CAP_ENDPTCTRL (hw_bank.lpm ? 0x0ECUL : 0x080UL)
171#define CAP_LAST (hw_bank.lpm ? 0x12CUL : 0x0C0UL)
172
173/* maximum number of enpoints: valid only after hw_device_reset() */
174static unsigned hw_ep_max;
175
176/**
177 * hw_ep_bit: calculates the bit number
178 * @num: endpoint number
179 * @dir: endpoint direction
180 *
181 * This function returns bit number
182 */
183static inline int hw_ep_bit(int num, int dir)
184{
185 return num + (dir ? 16 : 0);
186}
187
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200188static int ep_to_bit(int n)
189{
190 int fill = 16 - hw_ep_max / 2;
191
192 if (n >= hw_ep_max / 2)
193 n += fill;
194
195 return n;
196}
197
David Lopoaa69a802008-11-17 14:14:51 -0800198/**
199 * hw_aread: reads from register bitfield
200 * @addr: address relative to bus map
201 * @mask: bitfield mask
202 *
203 * This function returns register bitfield data
204 */
205static u32 hw_aread(u32 addr, u32 mask)
206{
207 return ioread32(addr + hw_bank.abs) & mask;
208}
209
210/**
211 * hw_awrite: writes to register bitfield
212 * @addr: address relative to bus map
213 * @mask: bitfield mask
214 * @data: new data
215 */
216static void hw_awrite(u32 addr, u32 mask, u32 data)
217{
218 iowrite32(hw_aread(addr, ~mask) | (data & mask),
219 addr + hw_bank.abs);
220}
221
222/**
223 * hw_cread: reads from register bitfield
224 * @addr: address relative to CAP offset plus content
225 * @mask: bitfield mask
226 *
227 * This function returns register bitfield data
228 */
229static u32 hw_cread(u32 addr, u32 mask)
230{
231 return ioread32(addr + hw_bank.cap) & mask;
232}
233
234/**
235 * hw_cwrite: writes to register bitfield
236 * @addr: address relative to CAP offset plus content
237 * @mask: bitfield mask
238 * @data: new data
239 */
240static void hw_cwrite(u32 addr, u32 mask, u32 data)
241{
242 iowrite32(hw_cread(addr, ~mask) | (data & mask),
243 addr + hw_bank.cap);
244}
245
246/**
247 * hw_ctest_and_clear: tests & clears register bitfield
248 * @addr: address relative to CAP offset plus content
249 * @mask: bitfield mask
250 *
251 * This function returns register bitfield data
252 */
253static u32 hw_ctest_and_clear(u32 addr, u32 mask)
254{
255 u32 reg = hw_cread(addr, mask);
256
257 iowrite32(reg, addr + hw_bank.cap);
258 return reg;
259}
260
261/**
262 * hw_ctest_and_write: tests & writes register bitfield
263 * @addr: address relative to CAP offset plus content
264 * @mask: bitfield mask
265 * @data: new data
266 *
267 * This function returns register bitfield data
268 */
269static u32 hw_ctest_and_write(u32 addr, u32 mask, u32 data)
270{
271 u32 reg = hw_cread(addr, ~0);
272
273 iowrite32((reg & ~mask) | (data & mask), addr + hw_bank.cap);
274 return (reg & mask) >> ffs_nr(mask);
275}
276
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530277static int hw_device_init(void __iomem *base)
David Lopoaa69a802008-11-17 14:14:51 -0800278{
279 u32 reg;
280
281 /* bank is a module variable */
282 hw_bank.abs = base;
283
284 hw_bank.cap = hw_bank.abs;
285 hw_bank.cap += ABS_CAPLENGTH;
286 hw_bank.cap += ioread8(hw_bank.cap);
287
288 reg = hw_aread(ABS_HCCPARAMS, HCCPARAMS_LEN) >> ffs_nr(HCCPARAMS_LEN);
289 hw_bank.lpm = reg;
290 hw_bank.size = hw_bank.cap - hw_bank.abs;
291 hw_bank.size += CAP_LAST;
292 hw_bank.size /= sizeof(u32);
293
David Lopoaa69a802008-11-17 14:14:51 -0800294 reg = hw_aread(ABS_DCCPARAMS, DCCPARAMS_DEN) >> ffs_nr(DCCPARAMS_DEN);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530295 hw_ep_max = reg * 2; /* cache hw ENDPT_MAX */
David Lopoaa69a802008-11-17 14:14:51 -0800296
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530297 if (hw_ep_max == 0 || hw_ep_max > ENDPT_MAX)
298 return -ENODEV;
David Lopoaa69a802008-11-17 14:14:51 -0800299
300 /* setup lock mode ? */
301
302 /* ENDPTSETUPSTAT is '0' by default */
303
304 /* HCSPARAMS.bf.ppc SHOULD BE zero for device */
305
306 return 0;
307}
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530308/**
309 * hw_device_reset: resets chip (execute without interruption)
310 * @base: register base address
311 *
312 * This function returns an error code
313 */
314static int hw_device_reset(struct ci13xxx *udc)
315{
316 /* should flush & stop before reset */
317 hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0);
318 hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
319
320 hw_cwrite(CAP_USBCMD, USBCMD_RST, USBCMD_RST);
321 while (hw_cread(CAP_USBCMD, USBCMD_RST))
322 udelay(10); /* not RTOS friendly */
323
324
325 if (udc->udc_driver->notify_event)
326 udc->udc_driver->notify_event(udc,
327 CI13XXX_CONTROLLER_RESET_EVENT);
328
Pavankumar Kondeti8c2387a2011-05-02 11:56:28 +0530329 if (udc->udc_driver->flags & CI13XXX_DISABLE_STREAMING)
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530330 hw_cwrite(CAP_USBMODE, USBMODE_SDIS, USBMODE_SDIS);
331
332 /* USBMODE should be configured step by step */
333 hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
334 hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE);
335 hw_cwrite(CAP_USBMODE, USBMODE_SLOM, USBMODE_SLOM); /* HW >= 2.3 */
336
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700337 /*
338 * ITC (Interrupt Threshold Control) field is to set the maximum
339 * rate at which the device controller will issue interrupts.
340 * The maximum interrupt interval measured in micro frames.
341 * Valid values are 0, 1, 2, 4, 8, 16, 32, 64. The default value is
342 * 8 micro frames. If CPU can handle interrupts at faster rate, ITC
343 * can be set to lesser value to gain performance.
344 */
345 if (udc->udc_driver->flags & CI13XXX_ZERO_ITC)
346 hw_cwrite(CAP_USBCMD, USBCMD_ITC_MASK, USBCMD_ITC(0));
347
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530348 if (hw_cread(CAP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
349 pr_err("cannot enter in device mode");
350 pr_err("lpm = %i", hw_bank.lpm);
351 return -ENODEV;
352 }
353
354 return 0;
355}
David Lopoaa69a802008-11-17 14:14:51 -0800356
357/**
358 * hw_device_state: enables/disables interrupts & starts/stops device (execute
359 * without interruption)
360 * @dma: 0 => disable, !0 => enable and set dma engine
361 *
362 * This function returns an error code
363 */
364static int hw_device_state(u32 dma)
365{
366 if (dma) {
367 hw_cwrite(CAP_ENDPTLISTADDR, ~0, dma);
368 /* interrupt, error, port change, reset, sleep/suspend */
369 hw_cwrite(CAP_USBINTR, ~0,
370 USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
371 hw_cwrite(CAP_USBCMD, USBCMD_RS, USBCMD_RS);
372 } else {
373 hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
374 hw_cwrite(CAP_USBINTR, ~0, 0);
375 }
376 return 0;
377}
378
379/**
380 * hw_ep_flush: flush endpoint fifo (execute without interruption)
381 * @num: endpoint number
382 * @dir: endpoint direction
383 *
384 * This function returns an error code
385 */
386static int hw_ep_flush(int num, int dir)
387{
388 int n = hw_ep_bit(num, dir);
389
390 do {
391 /* flush any pending transfer */
392 hw_cwrite(CAP_ENDPTFLUSH, BIT(n), BIT(n));
393 while (hw_cread(CAP_ENDPTFLUSH, BIT(n)))
394 cpu_relax();
395 } while (hw_cread(CAP_ENDPTSTAT, BIT(n)));
396
397 return 0;
398}
399
400/**
401 * hw_ep_disable: disables endpoint (execute without interruption)
402 * @num: endpoint number
403 * @dir: endpoint direction
404 *
405 * This function returns an error code
406 */
407static int hw_ep_disable(int num, int dir)
408{
409 hw_ep_flush(num, dir);
410 hw_cwrite(CAP_ENDPTCTRL + num * sizeof(u32),
411 dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0);
412 return 0;
413}
414
415/**
416 * hw_ep_enable: enables endpoint (execute without interruption)
417 * @num: endpoint number
418 * @dir: endpoint direction
419 * @type: endpoint type
420 *
421 * This function returns an error code
422 */
423static int hw_ep_enable(int num, int dir, int type)
424{
425 u32 mask, data;
426
427 if (dir) {
428 mask = ENDPTCTRL_TXT; /* type */
429 data = type << ffs_nr(mask);
430
431 mask |= ENDPTCTRL_TXS; /* unstall */
432 mask |= ENDPTCTRL_TXR; /* reset data toggle */
433 data |= ENDPTCTRL_TXR;
434 mask |= ENDPTCTRL_TXE; /* enable */
435 data |= ENDPTCTRL_TXE;
436 } else {
437 mask = ENDPTCTRL_RXT; /* type */
438 data = type << ffs_nr(mask);
439
440 mask |= ENDPTCTRL_RXS; /* unstall */
441 mask |= ENDPTCTRL_RXR; /* reset data toggle */
442 data |= ENDPTCTRL_RXR;
443 mask |= ENDPTCTRL_RXE; /* enable */
444 data |= ENDPTCTRL_RXE;
445 }
446 hw_cwrite(CAP_ENDPTCTRL + num * sizeof(u32), mask, data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700447
448 /* make sure endpoint is enabled before returning */
449 mb();
450
David Lopoaa69a802008-11-17 14:14:51 -0800451 return 0;
452}
453
454/**
455 * hw_ep_get_halt: return endpoint halt status
456 * @num: endpoint number
457 * @dir: endpoint direction
458 *
459 * This function returns 1 if endpoint halted
460 */
461static int hw_ep_get_halt(int num, int dir)
462{
463 u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
464
465 return hw_cread(CAP_ENDPTCTRL + num * sizeof(u32), mask) ? 1 : 0;
466}
467
468/**
David Lopoaa69a802008-11-17 14:14:51 -0800469 * hw_test_and_clear_setup_status: test & clear setup status (execute without
470 * interruption)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200471 * @n: endpoint number
David Lopoaa69a802008-11-17 14:14:51 -0800472 *
473 * This function returns setup status
474 */
475static int hw_test_and_clear_setup_status(int n)
476{
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200477 n = ep_to_bit(n);
David Lopoaa69a802008-11-17 14:14:51 -0800478 return hw_ctest_and_clear(CAP_ENDPTSETUPSTAT, BIT(n));
479}
480
481/**
482 * hw_ep_prime: primes endpoint (execute without interruption)
483 * @num: endpoint number
484 * @dir: endpoint direction
485 * @is_ctrl: true if control endpoint
486 *
487 * This function returns an error code
488 */
489static int hw_ep_prime(int num, int dir, int is_ctrl)
490{
491 int n = hw_ep_bit(num, dir);
492
David Lopoaa69a802008-11-17 14:14:51 -0800493 if (is_ctrl && dir == RX && hw_cread(CAP_ENDPTSETUPSTAT, BIT(num)))
494 return -EAGAIN;
495
496 hw_cwrite(CAP_ENDPTPRIME, BIT(n), BIT(n));
497
498 while (hw_cread(CAP_ENDPTPRIME, BIT(n)))
499 cpu_relax();
500 if (is_ctrl && dir == RX && hw_cread(CAP_ENDPTSETUPSTAT, BIT(num)))
501 return -EAGAIN;
502
503 /* status shoult be tested according with manual but it doesn't work */
504 return 0;
505}
506
507/**
508 * hw_ep_set_halt: configures ep halt & resets data toggle after clear (execute
509 * without interruption)
510 * @num: endpoint number
511 * @dir: endpoint direction
512 * @value: true => stall, false => unstall
513 *
514 * This function returns an error code
515 */
516static int hw_ep_set_halt(int num, int dir, int value)
517{
Pavankumar Kondeti05598942011-07-06 16:58:44 +0530518 u32 addr, mask_xs, mask_xr;
519
David Lopoaa69a802008-11-17 14:14:51 -0800520 if (value != 0 && value != 1)
521 return -EINVAL;
522
523 do {
Pavankumar Kondeti05598942011-07-06 16:58:44 +0530524 if (hw_cread(CAP_ENDPTSETUPSTAT, BIT(num)))
525 return 0;
526
527 addr = CAP_ENDPTCTRL + num * sizeof(u32);
528 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
529 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR;
David Lopoaa69a802008-11-17 14:14:51 -0800530
531 /* data toggle - reserved for EP0 but it's in ESS */
532 hw_cwrite(addr, mask_xs|mask_xr, value ? mask_xs : mask_xr);
533
534 } while (value != hw_ep_get_halt(num, dir));
535
536 return 0;
537}
538
539/**
540 * hw_intr_clear: disables interrupt & clears interrupt status (execute without
541 * interruption)
542 * @n: interrupt bit
543 *
544 * This function returns an error code
545 */
546static int hw_intr_clear(int n)
547{
548 if (n >= REG_BITS)
549 return -EINVAL;
550
551 hw_cwrite(CAP_USBINTR, BIT(n), 0);
552 hw_cwrite(CAP_USBSTS, BIT(n), BIT(n));
553 return 0;
554}
555
556/**
557 * hw_intr_force: enables interrupt & forces interrupt status (execute without
558 * interruption)
559 * @n: interrupt bit
560 *
561 * This function returns an error code
562 */
563static int hw_intr_force(int n)
564{
565 if (n >= REG_BITS)
566 return -EINVAL;
567
568 hw_awrite(ABS_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
569 hw_cwrite(CAP_USBINTR, BIT(n), BIT(n));
570 hw_cwrite(CAP_USBSTS, BIT(n), BIT(n));
571 hw_awrite(ABS_TESTMODE, TESTMODE_FORCE, 0);
572 return 0;
573}
574
575/**
576 * hw_is_port_high_speed: test if port is high speed
577 *
578 * This function returns true if high speed port
579 */
580static int hw_port_is_high_speed(void)
581{
582 return hw_bank.lpm ? hw_cread(CAP_DEVLC, DEVLC_PSPD) :
583 hw_cread(CAP_PORTSC, PORTSC_HSP);
584}
585
586/**
587 * hw_port_test_get: reads port test mode value
588 *
589 * This function returns port test mode value
590 */
591static u8 hw_port_test_get(void)
592{
593 return hw_cread(CAP_PORTSC, PORTSC_PTC) >> ffs_nr(PORTSC_PTC);
594}
595
596/**
597 * hw_port_test_set: writes port test mode (execute without interruption)
598 * @mode: new value
599 *
600 * This function returns an error code
601 */
602static int hw_port_test_set(u8 mode)
603{
604 const u8 TEST_MODE_MAX = 7;
605
606 if (mode > TEST_MODE_MAX)
607 return -EINVAL;
608
609 hw_cwrite(CAP_PORTSC, PORTSC_PTC, mode << ffs_nr(PORTSC_PTC));
610 return 0;
611}
612
613/**
614 * hw_read_intr_enable: returns interrupt enable register
615 *
616 * This function returns register data
617 */
618static u32 hw_read_intr_enable(void)
619{
620 return hw_cread(CAP_USBINTR, ~0);
621}
622
623/**
624 * hw_read_intr_status: returns interrupt status register
625 *
626 * This function returns register data
627 */
628static u32 hw_read_intr_status(void)
629{
630 return hw_cread(CAP_USBSTS, ~0);
631}
632
633/**
634 * hw_register_read: reads all device registers (execute without interruption)
635 * @buf: destination buffer
636 * @size: buffer size
637 *
638 * This function returns number of registers read
639 */
640static size_t hw_register_read(u32 *buf, size_t size)
641{
642 unsigned i;
643
644 if (size > hw_bank.size)
645 size = hw_bank.size;
646
647 for (i = 0; i < size; i++)
648 buf[i] = hw_aread(i * sizeof(u32), ~0);
649
650 return size;
651}
652
653/**
654 * hw_register_write: writes to register
655 * @addr: register address
656 * @data: register value
657 *
658 * This function returns an error code
659 */
660static int hw_register_write(u16 addr, u32 data)
661{
662 /* align */
663 addr /= sizeof(u32);
664
665 if (addr >= hw_bank.size)
666 return -EINVAL;
667
668 /* align */
669 addr *= sizeof(u32);
670
671 hw_awrite(addr, ~0, data);
672 return 0;
673}
674
675/**
676 * hw_test_and_clear_complete: test & clear complete status (execute without
677 * interruption)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200678 * @n: endpoint number
David Lopoaa69a802008-11-17 14:14:51 -0800679 *
680 * This function returns complete status
681 */
682static int hw_test_and_clear_complete(int n)
683{
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200684 n = ep_to_bit(n);
David Lopoaa69a802008-11-17 14:14:51 -0800685 return hw_ctest_and_clear(CAP_ENDPTCOMPLETE, BIT(n));
686}
687
688/**
689 * hw_test_and_clear_intr_active: test & clear active interrupts (execute
690 * without interruption)
691 *
692 * This function returns active interrutps
693 */
694static u32 hw_test_and_clear_intr_active(void)
695{
696 u32 reg = hw_read_intr_status() & hw_read_intr_enable();
697
698 hw_cwrite(CAP_USBSTS, ~0, reg);
699 return reg;
700}
701
702/**
703 * hw_test_and_clear_setup_guard: test & clear setup guard (execute without
704 * interruption)
705 *
706 * This function returns guard value
707 */
708static int hw_test_and_clear_setup_guard(void)
709{
710 return hw_ctest_and_write(CAP_USBCMD, USBCMD_SUTW, 0);
711}
712
713/**
714 * hw_test_and_set_setup_guard: test & set setup guard (execute without
715 * interruption)
716 *
717 * This function returns guard value
718 */
719static int hw_test_and_set_setup_guard(void)
720{
721 return hw_ctest_and_write(CAP_USBCMD, USBCMD_SUTW, USBCMD_SUTW);
722}
723
724/**
725 * hw_usb_set_address: configures USB address (execute without interruption)
726 * @value: new USB address
727 *
728 * This function returns an error code
729 */
730static int hw_usb_set_address(u8 value)
731{
732 /* advance */
733 hw_cwrite(CAP_DEVICEADDR, DEVICEADDR_USBADR | DEVICEADDR_USBADRA,
734 value << ffs_nr(DEVICEADDR_USBADR) | DEVICEADDR_USBADRA);
735 return 0;
736}
737
738/**
739 * hw_usb_reset: restart device after a bus reset (execute without
740 * interruption)
741 *
742 * This function returns an error code
743 */
744static int hw_usb_reset(void)
745{
746 hw_usb_set_address(0);
747
748 /* ESS flushes only at end?!? */
749 hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0); /* flush all EPs */
750
751 /* clear setup token semaphores */
752 hw_cwrite(CAP_ENDPTSETUPSTAT, 0, 0); /* writes its content */
753
754 /* clear complete status */
755 hw_cwrite(CAP_ENDPTCOMPLETE, 0, 0); /* writes its content */
756
757 /* wait until all bits cleared */
758 while (hw_cread(CAP_ENDPTPRIME, ~0))
759 udelay(10); /* not RTOS friendly */
760
761 /* reset all endpoints ? */
762
763 /* reset internal status and wait for further instructions
764 no need to verify the port reset status (ESS does it) */
765
766 return 0;
767}
768
769/******************************************************************************
770 * DBG block
771 *****************************************************************************/
772/**
773 * show_device: prints information about device capabilities and status
774 *
775 * Check "device.h" for details
776 */
777static ssize_t show_device(struct device *dev, struct device_attribute *attr,
778 char *buf)
779{
780 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
781 struct usb_gadget *gadget = &udc->gadget;
782 int n = 0;
783
784 dbg_trace("[%s] %p\n", __func__, buf);
785 if (attr == NULL || buf == NULL) {
786 dev_err(dev, "[%s] EINVAL\n", __func__);
787 return 0;
788 }
789
790 n += scnprintf(buf + n, PAGE_SIZE - n, "speed = %d\n",
791 gadget->speed);
Michal Nazarewiczd327ab52011-11-19 18:27:37 +0100792 n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed = %d\n",
793 gadget->max_speed);
794 /* TODO: Scheduled for removal in 3.8. */
David Lopoaa69a802008-11-17 14:14:51 -0800795 n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed = %d\n",
Michal Nazarewiczd327ab52011-11-19 18:27:37 +0100796 gadget_is_dualspeed(gadget));
David Lopoaa69a802008-11-17 14:14:51 -0800797 n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg = %d\n",
798 gadget->is_otg);
799 n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral = %d\n",
800 gadget->is_a_peripheral);
801 n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable = %d\n",
802 gadget->b_hnp_enable);
803 n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support = %d\n",
804 gadget->a_hnp_support);
805 n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n",
806 gadget->a_alt_hnp_support);
807 n += scnprintf(buf + n, PAGE_SIZE - n, "name = %s\n",
808 (gadget->name ? gadget->name : ""));
809
810 return n;
811}
812static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
813
814/**
815 * show_driver: prints information about attached gadget (if any)
816 *
817 * Check "device.h" for details
818 */
819static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
820 char *buf)
821{
822 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
823 struct usb_gadget_driver *driver = udc->driver;
824 int n = 0;
825
826 dbg_trace("[%s] %p\n", __func__, buf);
827 if (attr == NULL || buf == NULL) {
828 dev_err(dev, "[%s] EINVAL\n", __func__);
829 return 0;
830 }
831
832 if (driver == NULL)
833 return scnprintf(buf, PAGE_SIZE,
834 "There is no gadget attached!\n");
835
836 n += scnprintf(buf + n, PAGE_SIZE - n, "function = %s\n",
837 (driver->function ? driver->function : ""));
838 n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n",
Michal Nazarewicz7177aed2011-11-19 18:27:38 +0100839 driver->max_speed);
David Lopoaa69a802008-11-17 14:14:51 -0800840
841 return n;
842}
843static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL);
844
845/* Maximum event message length */
846#define DBG_DATA_MSG 64UL
847
848/* Maximum event messages */
849#define DBG_DATA_MAX 128UL
850
851/* Event buffer descriptor */
852static struct {
853 char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */
854 unsigned idx; /* index */
855 unsigned tty; /* print to console? */
856 rwlock_t lck; /* lock */
857} dbg_data = {
858 .idx = 0,
859 .tty = 0,
860 .lck = __RW_LOCK_UNLOCKED(lck)
861};
862
863/**
864 * dbg_dec: decrements debug event index
865 * @idx: buffer index
866 */
867static void dbg_dec(unsigned *idx)
868{
869 *idx = (*idx - 1) & (DBG_DATA_MAX-1);
870}
871
872/**
873 * dbg_inc: increments debug event index
874 * @idx: buffer index
875 */
876static void dbg_inc(unsigned *idx)
877{
878 *idx = (*idx + 1) & (DBG_DATA_MAX-1);
879}
880
Vamsi Krishna8d1bbd52012-02-09 21:13:24 -0800881
882static unsigned int ep_addr_txdbg_mask;
883module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
884static unsigned int ep_addr_rxdbg_mask;
885module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
886
887static int allow_dbg_print(u8 addr)
888{
889 int dir, num;
890
891 /* allow bus wide events */
892 if (addr == 0xff)
893 return 1;
894
895 dir = addr & USB_ENDPOINT_DIR_MASK ? TX : RX;
896 num = addr & ~USB_ENDPOINT_DIR_MASK;
897 num = 1 << num;
898
899 if ((dir == TX) && (num & ep_addr_txdbg_mask))
900 return 1;
901 if ((dir == RX) && (num & ep_addr_rxdbg_mask))
902 return 1;
903
904 return 0;
905}
906
David Lopoaa69a802008-11-17 14:14:51 -0800907/**
908 * dbg_print: prints the common part of the event
909 * @addr: endpoint address
910 * @name: event name
911 * @status: status
912 * @extra: extra information
913 */
914static void dbg_print(u8 addr, const char *name, int status, const char *extra)
915{
916 struct timeval tval;
917 unsigned int stamp;
918 unsigned long flags;
919
Vamsi Krishna8d1bbd52012-02-09 21:13:24 -0800920 if (!allow_dbg_print(addr))
921 return;
922
David Lopoaa69a802008-11-17 14:14:51 -0800923 write_lock_irqsave(&dbg_data.lck, flags);
924
925 do_gettimeofday(&tval);
926 stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s */
927 stamp = stamp * 1000000 + tval.tv_usec;
928
929 scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +0300930 "%04X\t? %02X %-7.7s %4i ?\t%s\n",
David Lopoaa69a802008-11-17 14:14:51 -0800931 stamp, addr, name, status, extra);
932
933 dbg_inc(&dbg_data.idx);
934
935 write_unlock_irqrestore(&dbg_data.lck, flags);
936
937 if (dbg_data.tty != 0)
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +0300938 pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n",
David Lopoaa69a802008-11-17 14:14:51 -0800939 stamp, addr, name, status, extra);
940}
941
942/**
943 * dbg_done: prints a DONE event
944 * @addr: endpoint address
945 * @td: transfer descriptor
946 * @status: status
947 */
948static void dbg_done(u8 addr, const u32 token, int status)
949{
950 char msg[DBG_DATA_MSG];
951
952 scnprintf(msg, sizeof(msg), "%d %02X",
953 (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES),
954 (int)(token & TD_STATUS) >> ffs_nr(TD_STATUS));
955 dbg_print(addr, "DONE", status, msg);
956}
957
958/**
959 * dbg_event: prints a generic event
960 * @addr: endpoint address
961 * @name: event name
962 * @status: status
963 */
964static void dbg_event(u8 addr, const char *name, int status)
965{
966 if (name != NULL)
967 dbg_print(addr, name, status, "");
968}
969
970/*
971 * dbg_queue: prints a QUEUE event
972 * @addr: endpoint address
973 * @req: USB request
974 * @status: status
975 */
976static void dbg_queue(u8 addr, const struct usb_request *req, int status)
977{
978 char msg[DBG_DATA_MSG];
979
980 if (req != NULL) {
981 scnprintf(msg, sizeof(msg),
982 "%d %d", !req->no_interrupt, req->length);
983 dbg_print(addr, "QUEUE", status, msg);
984 }
985}
986
987/**
988 * dbg_setup: prints a SETUP event
989 * @addr: endpoint address
990 * @req: setup request
991 */
992static void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
993{
994 char msg[DBG_DATA_MSG];
995
996 if (req != NULL) {
997 scnprintf(msg, sizeof(msg),
998 "%02X %02X %04X %04X %d", req->bRequestType,
999 req->bRequest, le16_to_cpu(req->wValue),
1000 le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
1001 dbg_print(addr, "SETUP", 0, msg);
1002 }
1003}
1004
1005/**
1006 * show_events: displays the event buffer
1007 *
1008 * Check "device.h" for details
1009 */
1010static ssize_t show_events(struct device *dev, struct device_attribute *attr,
1011 char *buf)
1012{
1013 unsigned long flags;
1014 unsigned i, j, n = 0;
1015
1016 dbg_trace("[%s] %p\n", __func__, buf);
1017 if (attr == NULL || buf == NULL) {
1018 dev_err(dev, "[%s] EINVAL\n", __func__);
1019 return 0;
1020 }
1021
1022 read_lock_irqsave(&dbg_data.lck, flags);
1023
1024 i = dbg_data.idx;
1025 for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) {
1026 n += strlen(dbg_data.buf[i]);
1027 if (n >= PAGE_SIZE) {
1028 n -= strlen(dbg_data.buf[i]);
1029 break;
1030 }
1031 }
1032 for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i))
1033 j += scnprintf(buf + j, PAGE_SIZE - j,
1034 "%s", dbg_data.buf[i]);
1035
1036 read_unlock_irqrestore(&dbg_data.lck, flags);
1037
1038 return n;
1039}
1040
1041/**
1042 * store_events: configure if events are going to be also printed to console
1043 *
1044 * Check "device.h" for details
1045 */
1046static ssize_t store_events(struct device *dev, struct device_attribute *attr,
1047 const char *buf, size_t count)
1048{
1049 unsigned tty;
1050
1051 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1052 if (attr == NULL || buf == NULL) {
1053 dev_err(dev, "[%s] EINVAL\n", __func__);
1054 goto done;
1055 }
1056
1057 if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
1058 dev_err(dev, "<1|0>: enable|disable console log\n");
1059 goto done;
1060 }
1061
1062 dbg_data.tty = tty;
1063 dev_info(dev, "tty = %u", dbg_data.tty);
1064
1065 done:
1066 return count;
1067}
1068static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
1069
1070/**
1071 * show_inters: interrupt status, enable status and historic
1072 *
1073 * Check "device.h" for details
1074 */
1075static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
1076 char *buf)
1077{
1078 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1079 unsigned long flags;
1080 u32 intr;
1081 unsigned i, j, n = 0;
1082
1083 dbg_trace("[%s] %p\n", __func__, buf);
1084 if (attr == NULL || buf == NULL) {
1085 dev_err(dev, "[%s] EINVAL\n", __func__);
1086 return 0;
1087 }
1088
1089 spin_lock_irqsave(udc->lock, flags);
1090
1091 n += scnprintf(buf + n, PAGE_SIZE - n,
1092 "status = %08x\n", hw_read_intr_status());
1093 n += scnprintf(buf + n, PAGE_SIZE - n,
1094 "enable = %08x\n", hw_read_intr_enable());
1095
1096 n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
1097 isr_statistics.test);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001098 n += scnprintf(buf + n, PAGE_SIZE - n, "? ui = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001099 isr_statistics.ui);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001100 n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001101 isr_statistics.uei);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001102 n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001103 isr_statistics.pci);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001104 n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001105 isr_statistics.uri);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001106 n += scnprintf(buf + n, PAGE_SIZE - n, "? sli = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001107 isr_statistics.sli);
1108 n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n",
1109 isr_statistics.none);
1110 n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n",
1111 isr_statistics.hndl.cnt);
1112
1113 for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) {
1114 i &= ISR_MASK;
1115 intr = isr_statistics.hndl.buf[i];
1116
1117 if (USBi_UI & intr)
1118 n += scnprintf(buf + n, PAGE_SIZE - n, "ui ");
1119 intr &= ~USBi_UI;
1120 if (USBi_UEI & intr)
1121 n += scnprintf(buf + n, PAGE_SIZE - n, "uei ");
1122 intr &= ~USBi_UEI;
1123 if (USBi_PCI & intr)
1124 n += scnprintf(buf + n, PAGE_SIZE - n, "pci ");
1125 intr &= ~USBi_PCI;
1126 if (USBi_URI & intr)
1127 n += scnprintf(buf + n, PAGE_SIZE - n, "uri ");
1128 intr &= ~USBi_URI;
1129 if (USBi_SLI & intr)
1130 n += scnprintf(buf + n, PAGE_SIZE - n, "sli ");
1131 intr &= ~USBi_SLI;
1132 if (intr)
1133 n += scnprintf(buf + n, PAGE_SIZE - n, "??? ");
1134 if (isr_statistics.hndl.buf[i])
1135 n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
1136 }
1137
1138 spin_unlock_irqrestore(udc->lock, flags);
1139
1140 return n;
1141}
1142
1143/**
1144 * store_inters: enable & force or disable an individual interrutps
1145 * (to be used for test purposes only)
1146 *
1147 * Check "device.h" for details
1148 */
1149static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
1150 const char *buf, size_t count)
1151{
1152 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1153 unsigned long flags;
1154 unsigned en, bit;
1155
1156 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1157 if (attr == NULL || buf == NULL) {
1158 dev_err(dev, "[%s] EINVAL\n", __func__);
1159 goto done;
1160 }
1161
1162 if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
1163 dev_err(dev, "<1|0> <bit>: enable|disable interrupt");
1164 goto done;
1165 }
1166
1167 spin_lock_irqsave(udc->lock, flags);
1168 if (en) {
1169 if (hw_intr_force(bit))
1170 dev_err(dev, "invalid bit number\n");
1171 else
1172 isr_statistics.test++;
1173 } else {
1174 if (hw_intr_clear(bit))
1175 dev_err(dev, "invalid bit number\n");
1176 }
1177 spin_unlock_irqrestore(udc->lock, flags);
1178
1179 done:
1180 return count;
1181}
1182static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
1183
1184/**
1185 * show_port_test: reads port test mode
1186 *
1187 * Check "device.h" for details
1188 */
1189static ssize_t show_port_test(struct device *dev,
1190 struct device_attribute *attr, char *buf)
1191{
1192 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1193 unsigned long flags;
1194 unsigned mode;
1195
1196 dbg_trace("[%s] %p\n", __func__, buf);
1197 if (attr == NULL || buf == NULL) {
1198 dev_err(dev, "[%s] EINVAL\n", __func__);
1199 return 0;
1200 }
1201
1202 spin_lock_irqsave(udc->lock, flags);
1203 mode = hw_port_test_get();
1204 spin_unlock_irqrestore(udc->lock, flags);
1205
1206 return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
1207}
1208
1209/**
1210 * store_port_test: writes port test mode
1211 *
1212 * Check "device.h" for details
1213 */
1214static ssize_t store_port_test(struct device *dev,
1215 struct device_attribute *attr,
1216 const char *buf, size_t count)
1217{
1218 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1219 unsigned long flags;
1220 unsigned mode;
1221
1222 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1223 if (attr == NULL || buf == NULL) {
1224 dev_err(dev, "[%s] EINVAL\n", __func__);
1225 goto done;
1226 }
1227
1228 if (sscanf(buf, "%u", &mode) != 1) {
1229 dev_err(dev, "<mode>: set port test mode");
1230 goto done;
1231 }
1232
1233 spin_lock_irqsave(udc->lock, flags);
1234 if (hw_port_test_set(mode))
1235 dev_err(dev, "invalid mode\n");
1236 spin_unlock_irqrestore(udc->lock, flags);
1237
1238 done:
1239 return count;
1240}
1241static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
1242 show_port_test, store_port_test);
1243
1244/**
1245 * show_qheads: DMA contents of all queue heads
1246 *
1247 * Check "device.h" for details
1248 */
1249static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
1250 char *buf)
1251{
1252 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1253 unsigned long flags;
1254 unsigned i, j, n = 0;
1255
1256 dbg_trace("[%s] %p\n", __func__, buf);
1257 if (attr == NULL || buf == NULL) {
1258 dev_err(dev, "[%s] EINVAL\n", __func__);
1259 return 0;
1260 }
1261
1262 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301263 for (i = 0; i < hw_ep_max/2; i++) {
1264 struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i];
1265 struct ci13xxx_ep *mEpTx = &udc->ci13xxx_ep[i + hw_ep_max/2];
David Lopoaa69a802008-11-17 14:14:51 -08001266 n += scnprintf(buf + n, PAGE_SIZE - n,
1267 "EP=%02i: RX=%08X TX=%08X\n",
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301268 i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08001269 for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) {
1270 n += scnprintf(buf + n, PAGE_SIZE - n,
1271 " %04X: %08X %08X\n", j,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301272 *((u32 *)mEpRx->qh.ptr + j),
1273 *((u32 *)mEpTx->qh.ptr + j));
David Lopoaa69a802008-11-17 14:14:51 -08001274 }
1275 }
1276 spin_unlock_irqrestore(udc->lock, flags);
1277
1278 return n;
1279}
1280static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
1281
1282/**
1283 * show_registers: dumps all registers
1284 *
1285 * Check "device.h" for details
1286 */
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001287#define DUMP_ENTRIES 512
David Lopoaa69a802008-11-17 14:14:51 -08001288static ssize_t show_registers(struct device *dev,
1289 struct device_attribute *attr, char *buf)
1290{
1291 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1292 unsigned long flags;
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001293 u32 *dump;
David Lopoaa69a802008-11-17 14:14:51 -08001294 unsigned i, k, n = 0;
1295
1296 dbg_trace("[%s] %p\n", __func__, buf);
1297 if (attr == NULL || buf == NULL) {
1298 dev_err(dev, "[%s] EINVAL\n", __func__);
1299 return 0;
1300 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001301 dump = kmalloc(2048, GFP_KERNEL);
1302 if (dump == NULL)
1303 return -ENOMEM;
David Lopoaa69a802008-11-17 14:14:51 -08001304
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001305 dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
1306 if (!dump) {
1307 dev_err(dev, "%s: out of memory\n", __func__);
1308 return 0;
1309 }
1310
David Lopoaa69a802008-11-17 14:14:51 -08001311 spin_lock_irqsave(udc->lock, flags);
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001312 k = hw_register_read(dump, DUMP_ENTRIES);
David Lopoaa69a802008-11-17 14:14:51 -08001313 spin_unlock_irqrestore(udc->lock, flags);
1314
1315 for (i = 0; i < k; i++) {
1316 n += scnprintf(buf + n, PAGE_SIZE - n,
1317 "reg[0x%04X] = 0x%08X\n",
1318 i * (unsigned)sizeof(u32), dump[i]);
1319 }
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001320 kfree(dump);
David Lopoaa69a802008-11-17 14:14:51 -08001321
1322 return n;
1323}
1324
1325/**
1326 * store_registers: writes value to register address
1327 *
1328 * Check "device.h" for details
1329 */
1330static ssize_t store_registers(struct device *dev,
1331 struct device_attribute *attr,
1332 const char *buf, size_t count)
1333{
1334 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1335 unsigned long addr, data, flags;
1336
1337 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1338 if (attr == NULL || buf == NULL) {
1339 dev_err(dev, "[%s] EINVAL\n", __func__);
1340 goto done;
1341 }
1342
1343 if (sscanf(buf, "%li %li", &addr, &data) != 2) {
1344 dev_err(dev, "<addr> <data>: write data to register address");
1345 goto done;
1346 }
1347
1348 spin_lock_irqsave(udc->lock, flags);
1349 if (hw_register_write(addr, data))
1350 dev_err(dev, "invalid address range\n");
1351 spin_unlock_irqrestore(udc->lock, flags);
1352
1353 done:
1354 return count;
1355}
1356static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
1357 show_registers, store_registers);
1358
1359/**
1360 * show_requests: DMA contents of all requests currently queued (all endpts)
1361 *
1362 * Check "device.h" for details
1363 */
1364static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
1365 char *buf)
1366{
1367 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1368 unsigned long flags;
1369 struct list_head *ptr = NULL;
1370 struct ci13xxx_req *req = NULL;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301371 unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
David Lopoaa69a802008-11-17 14:14:51 -08001372
1373 dbg_trace("[%s] %p\n", __func__, buf);
1374 if (attr == NULL || buf == NULL) {
1375 dev_err(dev, "[%s] EINVAL\n", __func__);
1376 return 0;
1377 }
1378
1379 spin_lock_irqsave(udc->lock, flags);
1380 for (i = 0; i < hw_ep_max; i++)
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301381 list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue)
1382 {
1383 req = list_entry(ptr, struct ci13xxx_req, queue);
David Lopoaa69a802008-11-17 14:14:51 -08001384
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301385 n += scnprintf(buf + n, PAGE_SIZE - n,
1386 "EP=%02i: TD=%08X %s\n",
1387 i % hw_ep_max/2, (u32)req->dma,
1388 ((i < hw_ep_max/2) ? "RX" : "TX"));
1389
1390 for (j = 0; j < qSize; j++)
David Lopoaa69a802008-11-17 14:14:51 -08001391 n += scnprintf(buf + n, PAGE_SIZE - n,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301392 " %04X: %08X\n", j,
1393 *((u32 *)req->ptr + j));
1394 }
David Lopoaa69a802008-11-17 14:14:51 -08001395 spin_unlock_irqrestore(udc->lock, flags);
1396
1397 return n;
1398}
1399static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL);
1400
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001401/* EP# and Direction */
1402static ssize_t prime_ept(struct device *dev,
1403 struct device_attribute *attr,
1404 const char *buf, size_t count)
1405{
1406 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1407 struct ci13xxx_ep *mEp;
1408 unsigned int ep_num, dir;
1409 int n;
1410 struct ci13xxx_req *mReq = NULL;
1411
1412 if (sscanf(buf, "%u %u", &ep_num, &dir) != 2) {
1413 dev_err(dev, "<ep_num> <dir>: prime the ep");
1414 goto done;
1415 }
1416
1417 if (dir)
1418 mEp = &udc->ci13xxx_ep[ep_num + hw_ep_max/2];
1419 else
1420 mEp = &udc->ci13xxx_ep[ep_num];
1421
1422 n = hw_ep_bit(mEp->num, mEp->dir);
1423 mReq = list_entry(mEp->qh.queue.next, struct ci13xxx_req, queue);
1424 mEp->qh.ptr->td.next = mReq->dma;
1425 mEp->qh.ptr->td.token &= ~TD_STATUS;
1426
1427 wmb();
1428
1429 hw_cwrite(CAP_ENDPTPRIME, BIT(n), BIT(n));
1430 while (hw_cread(CAP_ENDPTPRIME, BIT(n)))
1431 cpu_relax();
1432
1433 pr_info("%s: prime:%08x stat:%08x ep#%d dir:%s\n", __func__,
1434 hw_cread(CAP_ENDPTPRIME, ~0),
1435 hw_cread(CAP_ENDPTSTAT, ~0),
1436 mEp->num, mEp->dir ? "IN" : "OUT");
1437done:
1438 return count;
1439
1440}
1441static DEVICE_ATTR(prime, S_IWUSR, NULL, prime_ept);
1442
1443/* EP# and Direction */
1444static ssize_t print_dtds(struct device *dev,
1445 struct device_attribute *attr,
1446 const char *buf, size_t count)
1447{
1448 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1449 struct ci13xxx_ep *mEp;
1450 unsigned int ep_num, dir;
1451 int n;
1452 struct list_head *ptr = NULL;
1453 struct ci13xxx_req *req = NULL;
1454
1455 if (sscanf(buf, "%u %u", &ep_num, &dir) != 2) {
1456 dev_err(dev, "<ep_num> <dir>: to print dtds");
1457 goto done;
1458 }
1459
1460 if (dir)
1461 mEp = &udc->ci13xxx_ep[ep_num + hw_ep_max/2];
1462 else
1463 mEp = &udc->ci13xxx_ep[ep_num];
1464
1465 n = hw_ep_bit(mEp->num, mEp->dir);
Anji jonnala6fb918c2011-10-21 17:54:21 +05301466 pr_info("%s: prime:%08x stat:%08x ep#%d dir:%s"
Vamsi Krishna8d1bbd52012-02-09 21:13:24 -08001467 "dTD_update_fail_count: %lu "
Anji jonnala6fb918c2011-10-21 17:54:21 +05301468 "mEp->dTD_update_fail_count: %lu\n", __func__,
1469 hw_cread(CAP_ENDPTPRIME, ~0),
1470 hw_cread(CAP_ENDPTSTAT, ~0),
1471 mEp->num, mEp->dir ? "IN" : "OUT",
1472 udc->dTD_update_fail_count,
1473 mEp->dTD_update_fail_count);
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001474
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001475 pr_info("QH: cap:%08x cur:%08x next:%08x token:%08x\n",
1476 mEp->qh.ptr->cap, mEp->qh.ptr->curr,
1477 mEp->qh.ptr->td.next, mEp->qh.ptr->td.token);
1478
1479 list_for_each(ptr, &mEp->qh.queue) {
1480 req = list_entry(ptr, struct ci13xxx_req, queue);
1481
1482 pr_info("\treq:%08x next:%08x token:%08x page0:%08x status:%d\n",
1483 req->dma, req->ptr->next, req->ptr->token,
1484 req->ptr->page[0], req->req.status);
1485 }
1486done:
1487 return count;
1488
1489}
1490static DEVICE_ATTR(dtds, S_IWUSR, NULL, print_dtds);
1491
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001492static int ci13xxx_wakeup(struct usb_gadget *_gadget)
1493{
1494 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
1495 unsigned long flags;
1496 int ret = 0;
1497
1498 trace();
1499
1500 spin_lock_irqsave(udc->lock, flags);
1501 if (!udc->remote_wakeup) {
1502 ret = -EOPNOTSUPP;
1503 dbg_trace("remote wakeup feature is not enabled\n");
1504 goto out;
1505 }
Amit Blay725cdeb2012-04-30 14:20:56 +03001506 spin_unlock_irqrestore(udc->lock, flags);
1507
1508 udc->udc_driver->notify_event(udc,
1509 CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT);
1510
1511 if (udc->transceiver)
Steve Mucklef132c6c2012-06-06 18:30:57 -07001512 usb_phy_set_suspend(udc->transceiver, 0);
Amit Blay725cdeb2012-04-30 14:20:56 +03001513
1514 spin_lock_irqsave(udc->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001515 if (!hw_cread(CAP_PORTSC, PORTSC_SUSP)) {
1516 ret = -EINVAL;
1517 dbg_trace("port is not suspended\n");
1518 goto out;
1519 }
1520 hw_cwrite(CAP_PORTSC, PORTSC_FPR, PORTSC_FPR);
1521out:
1522 spin_unlock_irqrestore(udc->lock, flags);
1523 return ret;
1524}
1525
1526static ssize_t usb_remote_wakeup(struct device *dev,
1527 struct device_attribute *attr, const char *buf, size_t count)
1528{
1529 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1530
1531 ci13xxx_wakeup(&udc->gadget);
1532
1533 return count;
1534}
1535static DEVICE_ATTR(wakeup, S_IWUSR, 0, usb_remote_wakeup);
1536
David Lopoaa69a802008-11-17 14:14:51 -08001537/**
1538 * dbg_create_files: initializes the attribute interface
1539 * @dev: device
1540 *
1541 * This function returns an error code
1542 */
1543__maybe_unused static int dbg_create_files(struct device *dev)
1544{
1545 int retval = 0;
1546
1547 if (dev == NULL)
1548 return -EINVAL;
1549 retval = device_create_file(dev, &dev_attr_device);
1550 if (retval)
1551 goto done;
1552 retval = device_create_file(dev, &dev_attr_driver);
1553 if (retval)
1554 goto rm_device;
1555 retval = device_create_file(dev, &dev_attr_events);
1556 if (retval)
1557 goto rm_driver;
1558 retval = device_create_file(dev, &dev_attr_inters);
1559 if (retval)
1560 goto rm_events;
1561 retval = device_create_file(dev, &dev_attr_port_test);
1562 if (retval)
1563 goto rm_inters;
1564 retval = device_create_file(dev, &dev_attr_qheads);
1565 if (retval)
1566 goto rm_port_test;
1567 retval = device_create_file(dev, &dev_attr_registers);
1568 if (retval)
1569 goto rm_qheads;
1570 retval = device_create_file(dev, &dev_attr_requests);
1571 if (retval)
1572 goto rm_registers;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001573 retval = device_create_file(dev, &dev_attr_wakeup);
1574 if (retval)
1575 goto rm_remote_wakeup;
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001576 retval = device_create_file(dev, &dev_attr_prime);
1577 if (retval)
1578 goto rm_prime;
1579 retval = device_create_file(dev, &dev_attr_dtds);
1580 if (retval)
1581 goto rm_dtds;
1582
David Lopoaa69a802008-11-17 14:14:51 -08001583 return 0;
1584
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001585rm_dtds:
1586 device_remove_file(dev, &dev_attr_dtds);
1587rm_prime:
1588 device_remove_file(dev, &dev_attr_prime);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001589rm_remote_wakeup:
1590 device_remove_file(dev, &dev_attr_wakeup);
David Lopoaa69a802008-11-17 14:14:51 -08001591 rm_registers:
1592 device_remove_file(dev, &dev_attr_registers);
1593 rm_qheads:
1594 device_remove_file(dev, &dev_attr_qheads);
1595 rm_port_test:
1596 device_remove_file(dev, &dev_attr_port_test);
1597 rm_inters:
1598 device_remove_file(dev, &dev_attr_inters);
1599 rm_events:
1600 device_remove_file(dev, &dev_attr_events);
1601 rm_driver:
1602 device_remove_file(dev, &dev_attr_driver);
1603 rm_device:
1604 device_remove_file(dev, &dev_attr_device);
1605 done:
1606 return retval;
1607}
1608
1609/**
1610 * dbg_remove_files: destroys the attribute interface
1611 * @dev: device
1612 *
1613 * This function returns an error code
1614 */
1615__maybe_unused static int dbg_remove_files(struct device *dev)
1616{
1617 if (dev == NULL)
1618 return -EINVAL;
1619 device_remove_file(dev, &dev_attr_requests);
1620 device_remove_file(dev, &dev_attr_registers);
1621 device_remove_file(dev, &dev_attr_qheads);
1622 device_remove_file(dev, &dev_attr_port_test);
1623 device_remove_file(dev, &dev_attr_inters);
1624 device_remove_file(dev, &dev_attr_events);
1625 device_remove_file(dev, &dev_attr_driver);
1626 device_remove_file(dev, &dev_attr_device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001627 device_remove_file(dev, &dev_attr_wakeup);
David Lopoaa69a802008-11-17 14:14:51 -08001628 return 0;
1629}
1630
1631/******************************************************************************
1632 * UTIL block
1633 *****************************************************************************/
1634/**
1635 * _usb_addr: calculates endpoint address from direction & number
1636 * @ep: endpoint
1637 */
1638static inline u8 _usb_addr(struct ci13xxx_ep *ep)
1639{
1640 return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num;
1641}
1642
1643/**
1644 * _hardware_queue: configures a request at hardware level
1645 * @gadget: gadget
1646 * @mEp: endpoint
1647 *
1648 * This function returns an error code
1649 */
1650static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1651{
1652 unsigned i;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301653 int ret = 0;
1654 unsigned length = mReq->req.length;
David Lopoaa69a802008-11-17 14:14:51 -08001655
1656 trace("%p, %p", mEp, mReq);
1657
1658 /* don't queue twice */
1659 if (mReq->req.status == -EALREADY)
1660 return -EALREADY;
1661
David Lopoaa69a802008-11-17 14:14:51 -08001662 mReq->req.status = -EALREADY;
Michael Grzeschik954aad82011-10-10 18:38:06 +02001663 if (length && mReq->req.dma == DMA_ADDR_INVALID) {
David Lopoaa69a802008-11-17 14:14:51 -08001664 mReq->req.dma = \
1665 dma_map_single(mEp->device, mReq->req.buf,
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301666 length, mEp->dir ? DMA_TO_DEVICE :
1667 DMA_FROM_DEVICE);
David Lopoaa69a802008-11-17 14:14:51 -08001668 if (mReq->req.dma == 0)
1669 return -ENOMEM;
1670
1671 mReq->map = 1;
1672 }
1673
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301674 if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) {
1675 mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC,
1676 &mReq->zdma);
1677 if (mReq->zptr == NULL) {
1678 if (mReq->map) {
1679 dma_unmap_single(mEp->device, mReq->req.dma,
1680 length, mEp->dir ? DMA_TO_DEVICE :
1681 DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02001682 mReq->req.dma = DMA_ADDR_INVALID;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301683 mReq->map = 0;
1684 }
1685 return -ENOMEM;
1686 }
1687 memset(mReq->zptr, 0, sizeof(*mReq->zptr));
1688 mReq->zptr->next = TD_TERMINATE;
1689 mReq->zptr->token = TD_STATUS_ACTIVE;
1690 if (!mReq->req.no_interrupt)
1691 mReq->zptr->token |= TD_IOC;
1692 }
David Lopoaa69a802008-11-17 14:14:51 -08001693 /*
1694 * TD configuration
1695 * TODO - handle requests which spawns into several TDs
1696 */
1697 memset(mReq->ptr, 0, sizeof(*mReq->ptr));
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301698 mReq->ptr->token = length << ffs_nr(TD_TOTAL_BYTES);
David Lopoaa69a802008-11-17 14:14:51 -08001699 mReq->ptr->token &= TD_TOTAL_BYTES;
David Lopoaa69a802008-11-17 14:14:51 -08001700 mReq->ptr->token |= TD_STATUS_ACTIVE;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301701 if (mReq->zptr) {
1702 mReq->ptr->next = mReq->zdma;
1703 } else {
1704 mReq->ptr->next = TD_TERMINATE;
1705 if (!mReq->req.no_interrupt)
1706 mReq->ptr->token |= TD_IOC;
1707 }
Ofir Cohena1c2a872011-12-14 10:26:34 +02001708
1709 /* MSM Specific: updating the request as required for
1710 * SPS mode. Enable MSM proprietary DMA engine acording
1711 * to the UDC private data in the request.
1712 */
1713 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
1714 if (mReq->req.udc_priv & MSM_SPS_MODE) {
1715 mReq->ptr->token = TD_STATUS_ACTIVE;
Ido Shayevitzd1cb16c2012-03-28 18:57:47 +02001716 if (mReq->req.udc_priv & MSM_IS_FINITE_TRANSFER)
Ofir Cohena1c2a872011-12-14 10:26:34 +02001717 mReq->ptr->next = TD_TERMINATE;
1718 else
1719 mReq->ptr->next = MSM_ETD_TYPE | mReq->dma;
1720 if (!mReq->req.no_interrupt)
1721 mReq->ptr->token |= MSM_ETD_IOC;
1722 }
1723 }
1724
David Lopoaa69a802008-11-17 14:14:51 -08001725 mReq->ptr->page[0] = mReq->req.dma;
1726 for (i = 1; i < 5; i++)
1727 mReq->ptr->page[i] =
Artem Leonenko0a313c42010-12-14 23:47:06 -08001728 (mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK;
David Lopoaa69a802008-11-17 14:14:51 -08001729
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301730 if (!list_empty(&mEp->qh.queue)) {
1731 struct ci13xxx_req *mReqPrev;
1732 int n = hw_ep_bit(mEp->num, mEp->dir);
1733 int tmp_stat;
1734
1735 mReqPrev = list_entry(mEp->qh.queue.prev,
1736 struct ci13xxx_req, queue);
1737 if (mReqPrev->zptr)
1738 mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
1739 else
1740 mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
1741 wmb();
1742 if (hw_cread(CAP_ENDPTPRIME, BIT(n)))
1743 goto done;
1744 do {
1745 hw_cwrite(CAP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
1746 tmp_stat = hw_cread(CAP_ENDPTSTAT, BIT(n));
1747 } while (!hw_cread(CAP_USBCMD, USBCMD_ATDTW));
1748 hw_cwrite(CAP_USBCMD, USBCMD_ATDTW, 0);
1749 if (tmp_stat)
1750 goto done;
1751 }
1752
1753 /* QH configuration */
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001754 if (!list_empty(&mEp->qh.queue)) {
1755 struct ci13xxx_req *mReq = \
1756 list_entry(mEp->qh.queue.next,
1757 struct ci13xxx_req, queue);
1758
1759 if (TD_STATUS_ACTIVE & mReq->ptr->token) {
1760 mEp->qh.ptr->td.next = mReq->dma;
1761 mEp->qh.ptr->td.token &= ~TD_STATUS;
1762 goto prime;
1763 }
1764 }
1765
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301766 mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */
Ofir Cohena1c2a872011-12-14 10:26:34 +02001767
1768 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
1769 if (mReq->req.udc_priv & MSM_SPS_MODE) {
1770 mEp->qh.ptr->td.next |= MSM_ETD_TYPE;
1771 i = hw_cread(CAP_ENDPTPIPEID +
1772 mEp->num * sizeof(u32), ~0);
1773 /* Read current value of this EPs pipe id */
1774 i = (mEp->dir == TX) ?
1775 ((i >> MSM_TX_PIPE_ID_OFS) & MSM_PIPE_ID_MASK) :
1776 (i & MSM_PIPE_ID_MASK);
1777 /* If requested pipe id is different from current,
1778 then write it */
1779 if (i != (mReq->req.udc_priv & MSM_PIPE_ID_MASK)) {
1780 if (mEp->dir == TX)
1781 hw_cwrite(
1782 CAP_ENDPTPIPEID +
1783 mEp->num * sizeof(u32),
1784 MSM_PIPE_ID_MASK <<
1785 MSM_TX_PIPE_ID_OFS,
1786 (mReq->req.udc_priv &
1787 MSM_PIPE_ID_MASK)
1788 << MSM_TX_PIPE_ID_OFS);
1789 else
1790 hw_cwrite(
1791 CAP_ENDPTPIPEID +
1792 mEp->num * sizeof(u32),
1793 MSM_PIPE_ID_MASK,
1794 mReq->req.udc_priv &
1795 MSM_PIPE_ID_MASK);
1796 }
1797 }
1798 }
1799
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301800 mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301801 mEp->qh.ptr->cap |= QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08001802
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001803prime:
David Lopoaa69a802008-11-17 14:14:51 -08001804 wmb(); /* synchronize before ep prime */
1805
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301806 ret = hw_ep_prime(mEp->num, mEp->dir,
David Lopoaa69a802008-11-17 14:14:51 -08001807 mEp->type == USB_ENDPOINT_XFER_CONTROL);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301808done:
1809 return ret;
David Lopoaa69a802008-11-17 14:14:51 -08001810}
1811
1812/**
1813 * _hardware_dequeue: handles a request at hardware level
1814 * @gadget: gadget
1815 * @mEp: endpoint
1816 *
1817 * This function returns an error code
1818 */
1819static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1820{
1821 trace("%p, %p", mEp, mReq);
1822
1823 if (mReq->req.status != -EALREADY)
1824 return -EINVAL;
1825
Vijayavardhan Vennapusa590b8ce2011-10-20 02:38:14 +05301826 /* clean speculative fetches on req->ptr->token */
1827 mb();
1828
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301829 if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
1830 return -EBUSY;
1831
Ofir Cohena1c2a872011-12-14 10:26:34 +02001832 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID)
1833 if ((mReq->req.udc_priv & MSM_SPS_MODE) &&
Ido Shayevitzd1cb16c2012-03-28 18:57:47 +02001834 (mReq->req.udc_priv & MSM_IS_FINITE_TRANSFER))
Ofir Cohena1c2a872011-12-14 10:26:34 +02001835 return -EBUSY;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301836 if (mReq->zptr) {
1837 if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
1838 return -EBUSY;
1839 dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
1840 mReq->zptr = NULL;
1841 }
David Lopoaa69a802008-11-17 14:14:51 -08001842
1843 mReq->req.status = 0;
1844
1845 if (mReq->map) {
1846 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
1847 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02001848 mReq->req.dma = DMA_ADDR_INVALID;
David Lopoaa69a802008-11-17 14:14:51 -08001849 mReq->map = 0;
1850 }
1851
1852 mReq->req.status = mReq->ptr->token & TD_STATUS;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301853 if ((TD_STATUS_HALTED & mReq->req.status) != 0)
David Lopoaa69a802008-11-17 14:14:51 -08001854 mReq->req.status = -1;
1855 else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0)
1856 mReq->req.status = -1;
1857 else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0)
1858 mReq->req.status = -1;
1859
1860 mReq->req.actual = mReq->ptr->token & TD_TOTAL_BYTES;
1861 mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES);
1862 mReq->req.actual = mReq->req.length - mReq->req.actual;
1863 mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual;
1864
1865 return mReq->req.actual;
1866}
1867
1868/**
1869 * _ep_nuke: dequeues all endpoint requests
1870 * @mEp: endpoint
1871 *
1872 * This function returns an error code
1873 * Caller must hold lock
1874 */
1875static int _ep_nuke(struct ci13xxx_ep *mEp)
1876__releases(mEp->lock)
1877__acquires(mEp->lock)
1878{
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05301879 struct ci13xxx_ep *mEpTemp = mEp;
Ofir Cohena1c2a872011-12-14 10:26:34 +02001880 unsigned val;
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05301881
David Lopoaa69a802008-11-17 14:14:51 -08001882 trace("%p", mEp);
1883
1884 if (mEp == NULL)
1885 return -EINVAL;
1886
1887 hw_ep_flush(mEp->num, mEp->dir);
1888
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301889 while (!list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -08001890
1891 /* pop oldest request */
1892 struct ci13xxx_req *mReq = \
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301893 list_entry(mEp->qh.queue.next,
David Lopoaa69a802008-11-17 14:14:51 -08001894 struct ci13xxx_req, queue);
1895 list_del_init(&mReq->queue);
Ofir Cohena1c2a872011-12-14 10:26:34 +02001896
1897 /* MSM Specific: Clear end point proprietary register */
1898 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
1899 if (mReq->req.udc_priv & MSM_SPS_MODE) {
1900 val = hw_cread(CAP_ENDPTPIPEID +
1901 mEp->num * sizeof(u32),
1902 ~0);
1903
1904 if (val != MSM_EP_PIPE_ID_RESET_VAL)
1905 hw_cwrite(
1906 CAP_ENDPTPIPEID +
1907 mEp->num * sizeof(u32),
1908 ~0, MSM_EP_PIPE_ID_RESET_VAL);
1909 }
1910 }
David Lopoaa69a802008-11-17 14:14:51 -08001911 mReq->req.status = -ESHUTDOWN;
1912
Anji jonnalaea7bbc32011-12-26 16:39:53 +05301913 if (mReq->map) {
1914 dma_unmap_single(mEp->device, mReq->req.dma,
1915 mReq->req.length,
1916 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Pavankumar Kondeti3c9a1d52012-06-06 09:56:03 +05301917 mReq->req.dma = DMA_ADDR_INVALID;
Anji jonnalaea7bbc32011-12-26 16:39:53 +05301918 mReq->map = 0;
1919 }
1920
Artem Leonenko7c25a822010-12-14 23:46:55 -08001921 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08001922 spin_unlock(mEp->lock);
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05301923 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
1924 mReq->req.length)
1925 mEpTemp = &_udc->ep0in;
1926 mReq->req.complete(&mEpTemp->ep, &mReq->req);
David Lopoaa69a802008-11-17 14:14:51 -08001927 spin_lock(mEp->lock);
1928 }
1929 }
1930 return 0;
1931}
1932
1933/**
1934 * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
1935 * @gadget: gadget
1936 *
1937 * This function returns an error code
David Lopoaa69a802008-11-17 14:14:51 -08001938 */
1939static int _gadget_stop_activity(struct usb_gadget *gadget)
David Lopoaa69a802008-11-17 14:14:51 -08001940{
1941 struct usb_ep *ep;
1942 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301943 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -08001944
1945 trace("%p", gadget);
1946
1947 if (gadget == NULL)
1948 return -EINVAL;
1949
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301950 spin_lock_irqsave(udc->lock, flags);
1951 udc->gadget.speed = USB_SPEED_UNKNOWN;
1952 udc->remote_wakeup = 0;
1953 udc->suspended = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001954 udc->configured = 0;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301955 spin_unlock_irqrestore(udc->lock, flags);
1956
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05301957 gadget->b_hnp_enable = 0;
1958 gadget->a_hnp_support = 0;
1959 gadget->host_request = 0;
1960 gadget->otg_srp_reqd = 0;
1961
David Lopoaa69a802008-11-17 14:14:51 -08001962 /* flush all endpoints */
1963 gadget_for_each_ep(ep, gadget) {
1964 usb_ep_fifo_flush(ep);
1965 }
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301966 usb_ep_fifo_flush(&udc->ep0out.ep);
1967 usb_ep_fifo_flush(&udc->ep0in.ep);
David Lopoaa69a802008-11-17 14:14:51 -08001968
1969 udc->driver->disconnect(gadget);
1970
1971 /* make sure to disable all endpoints */
1972 gadget_for_each_ep(ep, gadget) {
1973 usb_ep_disable(ep);
1974 }
David Lopoaa69a802008-11-17 14:14:51 -08001975
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301976 if (udc->status != NULL) {
1977 usb_ep_free_request(&udc->ep0in.ep, udc->status);
1978 udc->status = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08001979 }
1980
David Lopoaa69a802008-11-17 14:14:51 -08001981 return 0;
1982}
1983
1984/******************************************************************************
1985 * ISR block
1986 *****************************************************************************/
1987/**
1988 * isr_reset_handler: USB reset interrupt handler
1989 * @udc: UDC device
1990 *
1991 * This function resets USB engine after a bus reset occurred
1992 */
1993static void isr_reset_handler(struct ci13xxx *udc)
1994__releases(udc->lock)
1995__acquires(udc->lock)
1996{
David Lopoaa69a802008-11-17 14:14:51 -08001997 int retval;
1998
1999 trace("%p", udc);
2000
2001 if (udc == NULL) {
2002 err("EINVAL");
2003 return;
2004 }
2005
2006 dbg_event(0xFF, "BUS RST", 0);
2007
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302008 spin_unlock(udc->lock);
Anji jonnala8bbde012011-10-28 14:17:25 +05302009
2010 /*stop charging upon reset */
2011 if (udc->transceiver)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002012 usb_phy_set_power(udc->transceiver, 0);
Anji jonnala8bbde012011-10-28 14:17:25 +05302013
David Lopoaa69a802008-11-17 14:14:51 -08002014 retval = _gadget_stop_activity(&udc->gadget);
2015 if (retval)
2016 goto done;
2017
2018 retval = hw_usb_reset();
2019 if (retval)
2020 goto done;
2021
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302022 udc->status = usb_ep_alloc_request(&udc->ep0in.ep, GFP_ATOMIC);
2023 if (udc->status == NULL)
2024 retval = -ENOMEM;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302025
David Lopoaa69a802008-11-17 14:14:51 -08002026 spin_lock(udc->lock);
2027
2028 done:
2029 if (retval)
2030 err("error: %i", retval);
2031}
2032
2033/**
Amit Blay6fa647a2012-05-24 14:12:08 +03002034 * isr_resume_handler: USB PCI interrupt handler
2035 * @udc: UDC device
2036 *
2037 */
2038static void isr_resume_handler(struct ci13xxx *udc)
2039{
2040 udc->gadget.speed = hw_port_is_high_speed() ?
2041 USB_SPEED_HIGH : USB_SPEED_FULL;
2042 if (udc->suspended) {
2043 spin_unlock(udc->lock);
Amit Blay9b033682012-05-24 16:59:23 +03002044 if (udc->udc_driver->notify_event)
2045 udc->udc_driver->notify_event(udc,
2046 CI13XXX_CONTROLLER_RESUME_EVENT);
Amit Blay6fa647a2012-05-24 14:12:08 +03002047 if (udc->transceiver)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002048 usb_phy_set_suspend(udc->transceiver, 0);
Amit Blay6fa647a2012-05-24 14:12:08 +03002049 udc->driver->resume(&udc->gadget);
2050 spin_lock(udc->lock);
2051 udc->suspended = 0;
2052 }
2053}
2054
2055/**
2056 * isr_resume_handler: USB SLI interrupt handler
2057 * @udc: UDC device
2058 *
2059 */
2060static void isr_suspend_handler(struct ci13xxx *udc)
2061{
2062 if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
2063 udc->vbus_active) {
2064 if (udc->suspended == 0) {
2065 spin_unlock(udc->lock);
2066 udc->driver->suspend(&udc->gadget);
2067 if (udc->udc_driver->notify_event)
2068 udc->udc_driver->notify_event(udc,
2069 CI13XXX_CONTROLLER_SUSPEND_EVENT);
2070 if (udc->transceiver)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002071 usb_phy_set_suspend(udc->transceiver, 1);
Amit Blay6fa647a2012-05-24 14:12:08 +03002072 spin_lock(udc->lock);
2073 udc->suspended = 1;
2074 }
2075 }
2076}
2077
2078/**
David Lopoaa69a802008-11-17 14:14:51 -08002079 * isr_get_status_complete: get_status request complete function
2080 * @ep: endpoint
2081 * @req: request handled
2082 *
2083 * Caller must release lock
2084 */
2085static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
2086{
2087 trace("%p, %p", ep, req);
2088
2089 if (ep == NULL || req == NULL) {
2090 err("EINVAL");
2091 return;
2092 }
2093
2094 kfree(req->buf);
2095 usb_ep_free_request(ep, req);
2096}
2097
2098/**
2099 * isr_get_status_response: get_status request response
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302100 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08002101 * @setup: setup request packet
2102 *
2103 * This function returns an error code
2104 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302105static int isr_get_status_response(struct ci13xxx *udc,
David Lopoaa69a802008-11-17 14:14:51 -08002106 struct usb_ctrlrequest *setup)
2107__releases(mEp->lock)
2108__acquires(mEp->lock)
2109{
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302110 struct ci13xxx_ep *mEp = &udc->ep0in;
David Lopoaa69a802008-11-17 14:14:51 -08002111 struct usb_request *req = NULL;
2112 gfp_t gfp_flags = GFP_ATOMIC;
2113 int dir, num, retval;
2114
2115 trace("%p, %p", mEp, setup);
2116
2117 if (mEp == NULL || setup == NULL)
2118 return -EINVAL;
2119
2120 spin_unlock(mEp->lock);
2121 req = usb_ep_alloc_request(&mEp->ep, gfp_flags);
2122 spin_lock(mEp->lock);
2123 if (req == NULL)
2124 return -ENOMEM;
2125
2126 req->complete = isr_get_status_complete;
2127 req->length = 2;
2128 req->buf = kzalloc(req->length, gfp_flags);
2129 if (req->buf == NULL) {
2130 retval = -ENOMEM;
2131 goto err_free_req;
2132 }
2133
2134 if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302135 if (setup->wIndex == OTG_STATUS_SELECTOR) {
2136 *((u8 *)req->buf) = _udc->gadget.host_request <<
2137 HOST_REQUEST_FLAG;
2138 req->length = 1;
2139 } else {
2140 /* Assume that device is bus powered for now. */
2141 *((u16 *)req->buf) = _udc->remote_wakeup << 1;
2142 }
2143 /* TODO: D1 - Remote Wakeup; D0 - Self Powered */
David Lopoaa69a802008-11-17 14:14:51 -08002144 retval = 0;
2145 } else if ((setup->bRequestType & USB_RECIP_MASK) \
2146 == USB_RECIP_ENDPOINT) {
2147 dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
2148 TX : RX;
2149 num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK;
2150 *((u16 *)req->buf) = hw_ep_get_halt(num, dir);
2151 }
2152 /* else do nothing; reserved for future use */
2153
2154 spin_unlock(mEp->lock);
2155 retval = usb_ep_queue(&mEp->ep, req, gfp_flags);
2156 spin_lock(mEp->lock);
2157 if (retval)
2158 goto err_free_buf;
2159
2160 return 0;
2161
2162 err_free_buf:
2163 kfree(req->buf);
2164 err_free_req:
2165 spin_unlock(mEp->lock);
2166 usb_ep_free_request(&mEp->ep, req);
2167 spin_lock(mEp->lock);
2168 return retval;
2169}
2170
2171/**
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302172 * isr_setup_status_complete: setup_status request complete function
2173 * @ep: endpoint
2174 * @req: request handled
2175 *
2176 * Caller must release lock. Put the port in test mode if test mode
2177 * feature is selected.
2178 */
2179static void
2180isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
2181{
2182 struct ci13xxx *udc = req->context;
2183 unsigned long flags;
2184
2185 trace("%p, %p", ep, req);
2186
2187 spin_lock_irqsave(udc->lock, flags);
2188 if (udc->test_mode)
2189 hw_port_test_set(udc->test_mode);
2190 spin_unlock_irqrestore(udc->lock, flags);
2191}
2192
2193/**
David Lopoaa69a802008-11-17 14:14:51 -08002194 * isr_setup_status_phase: queues the status phase of a setup transation
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302195 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08002196 *
2197 * This function returns an error code
2198 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302199static int isr_setup_status_phase(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -08002200__releases(mEp->lock)
2201__acquires(mEp->lock)
2202{
2203 int retval;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302204 struct ci13xxx_ep *mEp;
David Lopoaa69a802008-11-17 14:14:51 -08002205
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302206 trace("%p", udc);
David Lopoaa69a802008-11-17 14:14:51 -08002207
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302208 mEp = (udc->ep0_dir == TX) ? &udc->ep0out : &udc->ep0in;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302209 udc->status->context = udc;
2210 udc->status->complete = isr_setup_status_complete;
David Lopoaa69a802008-11-17 14:14:51 -08002211
2212 spin_unlock(mEp->lock);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302213 retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
David Lopoaa69a802008-11-17 14:14:51 -08002214 spin_lock(mEp->lock);
2215
2216 return retval;
2217}
2218
2219/**
2220 * isr_tr_complete_low: transaction complete low level handler
2221 * @mEp: endpoint
2222 *
2223 * This function returns an error code
2224 * Caller must hold lock
2225 */
2226static int isr_tr_complete_low(struct ci13xxx_ep *mEp)
2227__releases(mEp->lock)
2228__acquires(mEp->lock)
2229{
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302230 struct ci13xxx_req *mReq, *mReqTemp;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302231 struct ci13xxx_ep *mEpTemp = mEp;
Pavankumar Kondeti986b11b2011-05-02 11:56:29 +05302232 int uninitialized_var(retval);
Anji jonnala6fb918c2011-10-21 17:54:21 +05302233 int req_dequeue = 1;
2234 struct ci13xxx *udc = _udc;
David Lopoaa69a802008-11-17 14:14:51 -08002235
2236 trace("%p", mEp);
2237
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302238 if (list_empty(&mEp->qh.queue))
Anji jonnala6fb918c2011-10-21 17:54:21 +05302239 return 0;
David Lopoaa69a802008-11-17 14:14:51 -08002240
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302241 list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,
2242 queue) {
Anji jonnala6fb918c2011-10-21 17:54:21 +05302243dequeue:
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302244 retval = _hardware_dequeue(mEp, mReq);
Anji jonnala6fb918c2011-10-21 17:54:21 +05302245 if (retval < 0) {
2246 /*
2247 * FIXME: don't know exact delay
2248 * required for HW to update dTD status
2249 * bits. This is a temporary workaround till
2250 * HW designers come back on this.
2251 */
2252 if (retval == -EBUSY && req_dequeue && mEp->dir == 0) {
2253 req_dequeue = 0;
2254 udc->dTD_update_fail_count++;
2255 mEp->dTD_update_fail_count++;
2256 udelay(10);
2257 goto dequeue;
2258 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302259 break;
Anji jonnala6fb918c2011-10-21 17:54:21 +05302260 }
2261 req_dequeue = 0;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302262 list_del_init(&mReq->queue);
2263 dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
2264 if (mReq->req.complete != NULL) {
2265 spin_unlock(mEp->lock);
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302266 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
2267 mReq->req.length)
2268 mEpTemp = &_udc->ep0in;
2269 mReq->req.complete(&mEpTemp->ep, &mReq->req);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302270 spin_lock(mEp->lock);
2271 }
2272 }
David Lopoaa69a802008-11-17 14:14:51 -08002273
Pavankumar Kondetief907482011-05-02 11:56:27 +05302274 if (retval == -EBUSY)
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302275 retval = 0;
2276 if (retval < 0)
David Lopoaa69a802008-11-17 14:14:51 -08002277 dbg_event(_usb_addr(mEp), "DONE", retval);
David Lopoaa69a802008-11-17 14:14:51 -08002278
David Lopoaa69a802008-11-17 14:14:51 -08002279 return retval;
2280}
2281
2282/**
2283 * isr_tr_complete_handler: transaction complete interrupt handler
2284 * @udc: UDC descriptor
2285 *
2286 * This function handles traffic events
2287 */
2288static void isr_tr_complete_handler(struct ci13xxx *udc)
2289__releases(udc->lock)
2290__acquires(udc->lock)
2291{
2292 unsigned i;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302293 u8 tmode = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002294
2295 trace("%p", udc);
2296
2297 if (udc == NULL) {
2298 err("EINVAL");
2299 return;
2300 }
2301
2302 for (i = 0; i < hw_ep_max; i++) {
2303 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302304 int type, num, dir, err = -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -08002305 struct usb_ctrlrequest req;
2306
David Lopoaa69a802008-11-17 14:14:51 -08002307 if (mEp->desc == NULL)
2308 continue; /* not configured */
2309
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302310 if (hw_test_and_clear_complete(i)) {
David Lopoaa69a802008-11-17 14:14:51 -08002311 err = isr_tr_complete_low(mEp);
2312 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
2313 if (err > 0) /* needs status phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302314 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002315 if (err < 0) {
2316 dbg_event(_usb_addr(mEp),
2317 "ERROR", err);
2318 spin_unlock(udc->lock);
2319 if (usb_ep_set_halt(&mEp->ep))
2320 err("error: ep_set_halt");
2321 spin_lock(udc->lock);
2322 }
2323 }
2324 }
2325
2326 if (mEp->type != USB_ENDPOINT_XFER_CONTROL ||
2327 !hw_test_and_clear_setup_status(i))
2328 continue;
2329
2330 if (i != 0) {
2331 warn("ctrl traffic received at endpoint");
2332 continue;
2333 }
2334
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302335 /*
2336 * Flush data and handshake transactions of previous
2337 * setup packet.
2338 */
2339 _ep_nuke(&udc->ep0out);
2340 _ep_nuke(&udc->ep0in);
2341
David Lopoaa69a802008-11-17 14:14:51 -08002342 /* read_setup_packet */
2343 do {
2344 hw_test_and_set_setup_guard();
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302345 memcpy(&req, &mEp->qh.ptr->setup, sizeof(req));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002346 /* Ensure buffer is read before acknowledging to h/w */
2347 mb();
David Lopoaa69a802008-11-17 14:14:51 -08002348 } while (!hw_test_and_clear_setup_guard());
2349
2350 type = req.bRequestType;
2351
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302352 udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
David Lopoaa69a802008-11-17 14:14:51 -08002353
2354 dbg_setup(_usb_addr(mEp), &req);
2355
2356 switch (req.bRequest) {
2357 case USB_REQ_CLEAR_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302358 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
2359 le16_to_cpu(req.wValue) ==
2360 USB_ENDPOINT_HALT) {
2361 if (req.wLength != 0)
David Lopoaa69a802008-11-17 14:14:51 -08002362 break;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302363 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302364 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302365 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302366 if (dir) /* TX */
2367 num += hw_ep_max/2;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302368 if (!udc->ci13xxx_ep[num].wedge) {
2369 spin_unlock(udc->lock);
2370 err = usb_ep_clear_halt(
2371 &udc->ci13xxx_ep[num].ep);
2372 spin_lock(udc->lock);
2373 if (err)
2374 break;
2375 }
2376 err = isr_setup_status_phase(udc);
2377 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
2378 le16_to_cpu(req.wValue) ==
2379 USB_DEVICE_REMOTE_WAKEUP) {
2380 if (req.wLength != 0)
2381 break;
2382 udc->remote_wakeup = 0;
2383 err = isr_setup_status_phase(udc);
2384 } else {
2385 goto delegate;
David Lopoaa69a802008-11-17 14:14:51 -08002386 }
David Lopoaa69a802008-11-17 14:14:51 -08002387 break;
2388 case USB_REQ_GET_STATUS:
2389 if (type != (USB_DIR_IN|USB_RECIP_DEVICE) &&
2390 type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
2391 type != (USB_DIR_IN|USB_RECIP_INTERFACE))
2392 goto delegate;
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302393 if (le16_to_cpu(req.wValue) != 0)
David Lopoaa69a802008-11-17 14:14:51 -08002394 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302395 err = isr_get_status_response(udc, &req);
David Lopoaa69a802008-11-17 14:14:51 -08002396 break;
2397 case USB_REQ_SET_ADDRESS:
2398 if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
2399 goto delegate;
2400 if (le16_to_cpu(req.wLength) != 0 ||
2401 le16_to_cpu(req.wIndex) != 0)
2402 break;
2403 err = hw_usb_set_address((u8)le16_to_cpu(req.wValue));
2404 if (err)
2405 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302406 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002407 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002408 case USB_REQ_SET_CONFIGURATION:
2409 if (type == (USB_DIR_OUT|USB_TYPE_STANDARD))
2410 udc->configured = !!req.wValue;
2411 goto delegate;
David Lopoaa69a802008-11-17 14:14:51 -08002412 case USB_REQ_SET_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302413 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
2414 le16_to_cpu(req.wValue) ==
2415 USB_ENDPOINT_HALT) {
2416 if (req.wLength != 0)
2417 break;
2418 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302419 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302420 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302421 if (dir) /* TX */
2422 num += hw_ep_max/2;
David Lopoaa69a802008-11-17 14:14:51 -08002423
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302424 spin_unlock(udc->lock);
2425 err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
2426 spin_lock(udc->lock);
2427 if (!err)
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302428 isr_setup_status_phase(udc);
2429 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302430 if (req.wLength != 0)
2431 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302432 switch (le16_to_cpu(req.wValue)) {
2433 case USB_DEVICE_REMOTE_WAKEUP:
2434 udc->remote_wakeup = 1;
2435 err = isr_setup_status_phase(udc);
2436 break;
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302437 case USB_DEVICE_B_HNP_ENABLE:
2438 udc->gadget.b_hnp_enable = 1;
2439 err = isr_setup_status_phase(udc);
2440 break;
2441 case USB_DEVICE_A_HNP_SUPPORT:
2442 udc->gadget.a_hnp_support = 1;
2443 err = isr_setup_status_phase(udc);
2444 break;
2445 case USB_DEVICE_A_ALT_HNP_SUPPORT:
2446 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302447 case USB_DEVICE_TEST_MODE:
2448 tmode = le16_to_cpu(req.wIndex) >> 8;
2449 switch (tmode) {
2450 case TEST_J:
2451 case TEST_K:
2452 case TEST_SE0_NAK:
2453 case TEST_PACKET:
2454 case TEST_FORCE_EN:
2455 udc->test_mode = tmode;
2456 err = isr_setup_status_phase(
2457 udc);
2458 break;
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302459 case TEST_OTG_SRP_REQD:
2460 udc->gadget.otg_srp_reqd = 1;
2461 err = isr_setup_status_phase(
2462 udc);
2463 break;
2464 case TEST_OTG_HNP_REQD:
2465 udc->gadget.host_request = 1;
2466 err = isr_setup_status_phase(
2467 udc);
2468 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302469 default:
2470 break;
2471 }
2472 default:
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302473 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302474 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302475 } else {
2476 goto delegate;
2477 }
David Lopoaa69a802008-11-17 14:14:51 -08002478 break;
2479 default:
2480delegate:
2481 if (req.wLength == 0) /* no data phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302482 udc->ep0_dir = TX;
David Lopoaa69a802008-11-17 14:14:51 -08002483
2484 spin_unlock(udc->lock);
2485 err = udc->driver->setup(&udc->gadget, &req);
2486 spin_lock(udc->lock);
2487 break;
2488 }
2489
2490 if (err < 0) {
2491 dbg_event(_usb_addr(mEp), "ERROR", err);
2492
2493 spin_unlock(udc->lock);
2494 if (usb_ep_set_halt(&mEp->ep))
2495 err("error: ep_set_halt");
2496 spin_lock(udc->lock);
2497 }
2498 }
2499}
2500
2501/******************************************************************************
2502 * ENDPT block
2503 *****************************************************************************/
2504/**
2505 * ep_enable: configure endpoint, making it usable
2506 *
2507 * Check usb_ep_enable() at "usb_gadget.h" for details
2508 */
2509static int ep_enable(struct usb_ep *ep,
2510 const struct usb_endpoint_descriptor *desc)
2511{
2512 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302513 int retval = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002514 unsigned long flags;
2515
2516 trace("%p, %p", ep, desc);
2517
2518 if (ep == NULL || desc == NULL)
2519 return -EINVAL;
2520
2521 spin_lock_irqsave(mEp->lock, flags);
2522
2523 /* only internal SW should enable ctrl endpts */
2524
2525 mEp->desc = desc;
2526
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302527 if (!list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08002528 warn("enabling a non-empty endpoint!");
2529
Matthias Kaehlcke15739bb2009-04-15 22:28:41 +02002530 mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX;
2531 mEp->num = usb_endpoint_num(desc);
2532 mEp->type = usb_endpoint_type(desc);
David Lopoaa69a802008-11-17 14:14:51 -08002533
Kuninori Morimoto29cc8892011-08-23 03:12:03 -07002534 mEp->ep.maxpacket = usb_endpoint_maxp(desc);
David Lopoaa69a802008-11-17 14:14:51 -08002535
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302536 dbg_event(_usb_addr(mEp), "ENABLE", 0);
David Lopoaa69a802008-11-17 14:14:51 -08002537
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302538 mEp->qh.ptr->cap = 0;
David Lopof23e6492009-04-16 14:35:24 -07002539
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302540 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2541 mEp->qh.ptr->cap |= QH_IOS;
2542 else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
2543 mEp->qh.ptr->cap &= ~QH_MULT;
2544 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002545 mEp->qh.ptr->cap |= QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08002546
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302547 mEp->qh.ptr->cap |=
2548 (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
2549 mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */
David Lopoaa69a802008-11-17 14:14:51 -08002550
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002551 /* complete all the updates to ept->head before enabling endpoint*/
2552 mb();
2553
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302554 /*
2555 * Enable endpoints in the HW other than ep0 as ep0
2556 * is always enabled
2557 */
2558 if (mEp->num)
2559 retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type);
David Lopoaa69a802008-11-17 14:14:51 -08002560
2561 spin_unlock_irqrestore(mEp->lock, flags);
2562 return retval;
2563}
2564
2565/**
2566 * ep_disable: endpoint is no longer usable
2567 *
2568 * Check usb_ep_disable() at "usb_gadget.h" for details
2569 */
2570static int ep_disable(struct usb_ep *ep)
2571{
2572 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2573 int direction, retval = 0;
2574 unsigned long flags;
2575
2576 trace("%p", ep);
2577
2578 if (ep == NULL)
2579 return -EINVAL;
2580 else if (mEp->desc == NULL)
2581 return -EBUSY;
2582
2583 spin_lock_irqsave(mEp->lock, flags);
2584
2585 /* only internal SW should disable ctrl endpts */
2586
2587 direction = mEp->dir;
2588 do {
2589 dbg_event(_usb_addr(mEp), "DISABLE", 0);
2590
2591 retval |= _ep_nuke(mEp);
2592 retval |= hw_ep_disable(mEp->num, mEp->dir);
2593
2594 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2595 mEp->dir = (mEp->dir == TX) ? RX : TX;
2596
2597 } while (mEp->dir != direction);
2598
2599 mEp->desc = NULL;
Ido Shayevitzf9c56cd2012-02-08 13:56:48 +02002600 mEp->ep.desc = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002601
2602 spin_unlock_irqrestore(mEp->lock, flags);
2603 return retval;
2604}
2605
2606/**
2607 * ep_alloc_request: allocate a request object to use with this endpoint
2608 *
2609 * Check usb_ep_alloc_request() at "usb_gadget.h" for details
2610 */
2611static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
2612{
2613 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2614 struct ci13xxx_req *mReq = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002615
2616 trace("%p, %i", ep, gfp_flags);
2617
2618 if (ep == NULL) {
2619 err("EINVAL");
2620 return NULL;
2621 }
2622
David Lopoaa69a802008-11-17 14:14:51 -08002623 mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
2624 if (mReq != NULL) {
2625 INIT_LIST_HEAD(&mReq->queue);
Michael Grzeschik954aad82011-10-10 18:38:06 +02002626 mReq->req.dma = DMA_ADDR_INVALID;
David Lopoaa69a802008-11-17 14:14:51 -08002627
2628 mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,
2629 &mReq->dma);
2630 if (mReq->ptr == NULL) {
2631 kfree(mReq);
2632 mReq = NULL;
2633 }
2634 }
2635
2636 dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
2637
David Lopoaa69a802008-11-17 14:14:51 -08002638 return (mReq == NULL) ? NULL : &mReq->req;
2639}
2640
2641/**
2642 * ep_free_request: frees a request object
2643 *
2644 * Check usb_ep_free_request() at "usb_gadget.h" for details
2645 */
2646static void ep_free_request(struct usb_ep *ep, struct usb_request *req)
2647{
2648 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2649 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2650 unsigned long flags;
2651
2652 trace("%p, %p", ep, req);
2653
2654 if (ep == NULL || req == NULL) {
2655 err("EINVAL");
2656 return;
2657 } else if (!list_empty(&mReq->queue)) {
2658 err("EBUSY");
2659 return;
2660 }
2661
2662 spin_lock_irqsave(mEp->lock, flags);
2663
2664 if (mReq->ptr)
2665 dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma);
2666 kfree(mReq);
2667
2668 dbg_event(_usb_addr(mEp), "FREE", 0);
2669
2670 spin_unlock_irqrestore(mEp->lock, flags);
2671}
2672
2673/**
2674 * ep_queue: queues (submits) an I/O request to an endpoint
2675 *
2676 * Check usb_ep_queue()* at usb_gadget.h" for details
2677 */
2678static int ep_queue(struct usb_ep *ep, struct usb_request *req,
2679 gfp_t __maybe_unused gfp_flags)
2680{
2681 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2682 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2683 int retval = 0;
2684 unsigned long flags;
Anji jonnala6c174d42011-07-13 13:01:47 +05302685 struct ci13xxx *udc = _udc;
David Lopoaa69a802008-11-17 14:14:51 -08002686
2687 trace("%p, %p, %X", ep, req, gfp_flags);
2688
2689 if (ep == NULL || req == NULL || mEp->desc == NULL)
2690 return -EINVAL;
2691
2692 spin_lock_irqsave(mEp->lock, flags);
2693
Anji jonnala6c174d42011-07-13 13:01:47 +05302694 if (!udc->configured && mEp->type !=
2695 USB_ENDPOINT_XFER_CONTROL) {
2696 spin_unlock_irqrestore(mEp->lock, flags);
2697 trace("usb is not configured"
2698 "ept #%d, ept name#%s\n",
2699 mEp->num, mEp->ep.name);
2700 return -ESHUTDOWN;
2701 }
2702
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302703 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
2704 if (req->length)
2705 mEp = (_udc->ep0_dir == RX) ?
2706 &_udc->ep0out : &_udc->ep0in;
2707 if (!list_empty(&mEp->qh.queue)) {
2708 _ep_nuke(mEp);
2709 retval = -EOVERFLOW;
2710 warn("endpoint ctrl %X nuked", _usb_addr(mEp));
2711 }
David Lopoaa69a802008-11-17 14:14:51 -08002712 }
2713
2714 /* first nuke then test link, e.g. previous status has not sent */
2715 if (!list_empty(&mReq->queue)) {
2716 retval = -EBUSY;
2717 err("request already in queue");
2718 goto done;
2719 }
2720
Artem Leonenko0a313c42010-12-14 23:47:06 -08002721 if (req->length > (4 * CI13XXX_PAGE_SIZE)) {
2722 req->length = (4 * CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08002723 retval = -EMSGSIZE;
2724 warn("request length truncated");
2725 }
2726
2727 dbg_queue(_usb_addr(mEp), req, retval);
2728
2729 /* push request */
2730 mReq->req.status = -EINPROGRESS;
2731 mReq->req.actual = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002732
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302733 retval = _hardware_enqueue(mEp, mReq);
Artem Leonenkod9bb9c12010-12-14 23:45:50 -08002734
2735 if (retval == -EALREADY) {
David Lopoaa69a802008-11-17 14:14:51 -08002736 dbg_event(_usb_addr(mEp), "QUEUE", retval);
2737 retval = 0;
2738 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302739 if (!retval)
2740 list_add_tail(&mReq->queue, &mEp->qh.queue);
David Lopoaa69a802008-11-17 14:14:51 -08002741
2742 done:
2743 spin_unlock_irqrestore(mEp->lock, flags);
2744 return retval;
2745}
2746
2747/**
2748 * ep_dequeue: dequeues (cancels, unlinks) an I/O request from an endpoint
2749 *
2750 * Check usb_ep_dequeue() at "usb_gadget.h" for details
2751 */
2752static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
2753{
2754 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05302755 struct ci13xxx_ep *mEpTemp = mEp;
David Lopoaa69a802008-11-17 14:14:51 -08002756 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2757 unsigned long flags;
2758
2759 trace("%p, %p", ep, req);
2760
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302761 if (ep == NULL || req == NULL || mReq->req.status != -EALREADY ||
2762 mEp->desc == NULL || list_empty(&mReq->queue) ||
2763 list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08002764 return -EINVAL;
2765
2766 spin_lock_irqsave(mEp->lock, flags);
2767
2768 dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
2769
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302770 hw_ep_flush(mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08002771
2772 /* pop request */
2773 list_del_init(&mReq->queue);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302774 if (mReq->map) {
2775 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
2776 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02002777 mReq->req.dma = DMA_ADDR_INVALID;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302778 mReq->map = 0;
2779 }
David Lopoaa69a802008-11-17 14:14:51 -08002780 req->status = -ECONNRESET;
2781
Artem Leonenko7c25a822010-12-14 23:46:55 -08002782 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08002783 spin_unlock(mEp->lock);
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05302784 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
2785 mReq->req.length)
2786 mEpTemp = &_udc->ep0in;
2787 mReq->req.complete(&mEpTemp->ep, &mReq->req);
David Lopoaa69a802008-11-17 14:14:51 -08002788 spin_lock(mEp->lock);
2789 }
2790
2791 spin_unlock_irqrestore(mEp->lock, flags);
2792 return 0;
2793}
2794
Bar Weiner0fc137a2012-03-28 16:58:09 +02002795static int is_sps_req(struct ci13xxx_req *mReq)
2796{
2797 return (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID &&
2798 mReq->req.udc_priv & MSM_SPS_MODE);
2799}
2800
David Lopoaa69a802008-11-17 14:14:51 -08002801/**
2802 * ep_set_halt: sets the endpoint halt feature
2803 *
2804 * Check usb_ep_set_halt() at "usb_gadget.h" for details
2805 */
2806static int ep_set_halt(struct usb_ep *ep, int value)
2807{
2808 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2809 int direction, retval = 0;
2810 unsigned long flags;
2811
2812 trace("%p, %i", ep, value);
2813
2814 if (ep == NULL || mEp->desc == NULL)
2815 return -EINVAL;
2816
2817 spin_lock_irqsave(mEp->lock, flags);
2818
2819#ifndef STALL_IN
2820 /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
2821 if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX &&
Bar Weiner0fc137a2012-03-28 16:58:09 +02002822 !list_empty(&mEp->qh.queue) &&
2823 !is_sps_req(list_entry(mEp->qh.queue.next, struct ci13xxx_req,
2824 queue))){
David Lopoaa69a802008-11-17 14:14:51 -08002825 spin_unlock_irqrestore(mEp->lock, flags);
2826 return -EAGAIN;
2827 }
2828#endif
2829
2830 direction = mEp->dir;
2831 do {
2832 dbg_event(_usb_addr(mEp), "HALT", value);
2833 retval |= hw_ep_set_halt(mEp->num, mEp->dir, value);
2834
2835 if (!value)
2836 mEp->wedge = 0;
2837
2838 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2839 mEp->dir = (mEp->dir == TX) ? RX : TX;
2840
2841 } while (mEp->dir != direction);
2842
2843 spin_unlock_irqrestore(mEp->lock, flags);
2844 return retval;
2845}
2846
2847/**
2848 * ep_set_wedge: sets the halt feature and ignores clear requests
2849 *
2850 * Check usb_ep_set_wedge() at "usb_gadget.h" for details
2851 */
2852static int ep_set_wedge(struct usb_ep *ep)
2853{
2854 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2855 unsigned long flags;
2856
2857 trace("%p", ep);
2858
2859 if (ep == NULL || mEp->desc == NULL)
2860 return -EINVAL;
2861
2862 spin_lock_irqsave(mEp->lock, flags);
2863
2864 dbg_event(_usb_addr(mEp), "WEDGE", 0);
2865 mEp->wedge = 1;
2866
2867 spin_unlock_irqrestore(mEp->lock, flags);
2868
2869 return usb_ep_set_halt(ep);
2870}
2871
2872/**
2873 * ep_fifo_flush: flushes contents of a fifo
2874 *
2875 * Check usb_ep_fifo_flush() at "usb_gadget.h" for details
2876 */
2877static void ep_fifo_flush(struct usb_ep *ep)
2878{
2879 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2880 unsigned long flags;
2881
2882 trace("%p", ep);
2883
2884 if (ep == NULL) {
2885 err("%02X: -EINVAL", _usb_addr(mEp));
2886 return;
2887 }
2888
2889 spin_lock_irqsave(mEp->lock, flags);
2890
2891 dbg_event(_usb_addr(mEp), "FFLUSH", 0);
2892 hw_ep_flush(mEp->num, mEp->dir);
2893
2894 spin_unlock_irqrestore(mEp->lock, flags);
2895}
2896
2897/**
2898 * Endpoint-specific part of the API to the USB controller hardware
2899 * Check "usb_gadget.h" for details
2900 */
2901static const struct usb_ep_ops usb_ep_ops = {
2902 .enable = ep_enable,
2903 .disable = ep_disable,
2904 .alloc_request = ep_alloc_request,
2905 .free_request = ep_free_request,
2906 .queue = ep_queue,
2907 .dequeue = ep_dequeue,
2908 .set_halt = ep_set_halt,
2909 .set_wedge = ep_set_wedge,
2910 .fifo_flush = ep_fifo_flush,
2911};
2912
2913/******************************************************************************
2914 * GADGET block
2915 *****************************************************************************/
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302916static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
2917{
2918 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2919 unsigned long flags;
2920 int gadget_ready = 0;
2921
2922 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS))
2923 return -EOPNOTSUPP;
2924
2925 spin_lock_irqsave(udc->lock, flags);
2926 udc->vbus_active = is_active;
2927 if (udc->driver)
2928 gadget_ready = 1;
2929 spin_unlock_irqrestore(udc->lock, flags);
2930
2931 if (gadget_ready) {
2932 if (is_active) {
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302933 pm_runtime_get_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302934 hw_device_reset(udc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002935 if (udc->softconnect)
2936 hw_device_state(udc->ep0out.qh.dma);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302937 } else {
2938 hw_device_state(0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302939 _gadget_stop_activity(&udc->gadget);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302940 if (udc->udc_driver->notify_event)
2941 udc->udc_driver->notify_event(udc,
Amit Blay9b033682012-05-24 16:59:23 +03002942 CI13XXX_CONTROLLER_DISCONNECT_EVENT);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302943 pm_runtime_put_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302944 }
2945 }
2946
2947 return 0;
2948}
2949
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302950static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
2951{
2952 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2953
2954 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002955 return usb_phy_set_power(udc->transceiver, mA);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302956 return -ENOTSUPP;
2957}
2958
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002959static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_active)
2960{
2961 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2962 unsigned long flags;
2963
2964 spin_lock_irqsave(udc->lock, flags);
2965 udc->softconnect = is_active;
2966 if (((udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) &&
2967 !udc->vbus_active) || !udc->driver) {
2968 spin_unlock_irqrestore(udc->lock, flags);
2969 return 0;
2970 }
2971 spin_unlock_irqrestore(udc->lock, flags);
2972
Ofir Cohen06789f12012-01-16 09:43:13 +02002973 if (is_active) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002974 hw_device_state(udc->ep0out.qh.dma);
Ofir Cohen06789f12012-01-16 09:43:13 +02002975 if (udc->udc_driver->notify_event)
2976 udc->udc_driver->notify_event(udc,
2977 CI13XXX_CONTROLLER_CONNECT_EVENT);
2978 }
Pavankumar Kondetib7f53dc2011-08-23 12:40:33 +05302979 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002980 hw_device_state(0);
Pavankumar Kondetib7f53dc2011-08-23 12:40:33 +05302981
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002982 return 0;
2983}
2984
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002985static int ci13xxx_start(struct usb_gadget_driver *driver,
2986 int (*bind)(struct usb_gadget *));
2987static int ci13xxx_stop(struct usb_gadget_driver *driver);
David Lopoaa69a802008-11-17 14:14:51 -08002988/**
2989 * Device operations part of the API to the USB controller hardware,
2990 * which don't involve endpoints (or i/o)
2991 * Check "usb_gadget.h" for details
2992 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302993static const struct usb_gadget_ops usb_gadget_ops = {
2994 .vbus_session = ci13xxx_vbus_session,
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302995 .wakeup = ci13xxx_wakeup,
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302996 .vbus_draw = ci13xxx_vbus_draw,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002997 .pullup = ci13xxx_pullup,
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002998 .start = ci13xxx_start,
2999 .stop = ci13xxx_stop,
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303000};
David Lopoaa69a802008-11-17 14:14:51 -08003001
3002/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003003 * ci13xxx_start: register a gadget driver
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003004 * @driver: the driver being registered
3005 * @bind: the driver's bind callback
David Lopoaa69a802008-11-17 14:14:51 -08003006 *
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003007 * Check ci13xxx_start() at <linux/usb/gadget.h> for details.
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003008 * Interrupts are enabled here.
David Lopoaa69a802008-11-17 14:14:51 -08003009 */
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003010static int ci13xxx_start(struct usb_gadget_driver *driver,
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003011 int (*bind)(struct usb_gadget *))
David Lopoaa69a802008-11-17 14:14:51 -08003012{
3013 struct ci13xxx *udc = _udc;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303014 unsigned long flags;
3015 int i, j;
David Lopoaa69a802008-11-17 14:14:51 -08003016 int retval = -ENOMEM;
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303017 bool put = false;
David Lopoaa69a802008-11-17 14:14:51 -08003018
3019 trace("%p", driver);
3020
3021 if (driver == NULL ||
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003022 bind == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08003023 driver->setup == NULL ||
Marc Kleine-Budde7bb4fdc2011-10-10 18:38:09 +02003024 driver->disconnect == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08003025 return -EINVAL;
3026 else if (udc == NULL)
3027 return -ENODEV;
3028 else if (udc->driver != NULL)
3029 return -EBUSY;
3030
3031 /* alloc resources */
3032 udc->qh_pool = dma_pool_create("ci13xxx_qh", &udc->gadget.dev,
3033 sizeof(struct ci13xxx_qh),
Artem Leonenko0a313c42010-12-14 23:47:06 -08003034 64, CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08003035 if (udc->qh_pool == NULL)
3036 return -ENOMEM;
3037
3038 udc->td_pool = dma_pool_create("ci13xxx_td", &udc->gadget.dev,
3039 sizeof(struct ci13xxx_td),
Artem Leonenko0a313c42010-12-14 23:47:06 -08003040 64, CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08003041 if (udc->td_pool == NULL) {
3042 dma_pool_destroy(udc->qh_pool);
3043 udc->qh_pool = NULL;
3044 return -ENOMEM;
3045 }
3046
3047 spin_lock_irqsave(udc->lock, flags);
3048
3049 info("hw_ep_max = %d", hw_ep_max);
3050
David Lopoaa69a802008-11-17 14:14:51 -08003051 udc->gadget.dev.driver = NULL;
3052
3053 retval = 0;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303054 for (i = 0; i < hw_ep_max/2; i++) {
3055 for (j = RX; j <= TX; j++) {
3056 int k = i + j * hw_ep_max/2;
3057 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
David Lopoaa69a802008-11-17 14:14:51 -08003058
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303059 scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
3060 (j == TX) ? "in" : "out");
David Lopoaa69a802008-11-17 14:14:51 -08003061
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303062 mEp->lock = udc->lock;
3063 mEp->device = &udc->gadget.dev;
3064 mEp->td_pool = udc->td_pool;
David Lopoaa69a802008-11-17 14:14:51 -08003065
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303066 mEp->ep.name = mEp->name;
3067 mEp->ep.ops = &usb_ep_ops;
3068 mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
David Lopoaa69a802008-11-17 14:14:51 -08003069
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303070 INIT_LIST_HEAD(&mEp->qh.queue);
Pavankumar Kondeti0a91efa2010-12-07 17:54:00 +05303071 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303072 mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
3073 &mEp->qh.dma);
Pavankumar Kondeti0a91efa2010-12-07 17:54:00 +05303074 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303075 if (mEp->qh.ptr == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08003076 retval = -ENOMEM;
3077 else
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303078 memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
3079
3080 /* skip ep0 out and in endpoints */
3081 if (i == 0)
3082 continue;
3083
David Lopoaa69a802008-11-17 14:14:51 -08003084 list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303085 }
David Lopoaa69a802008-11-17 14:14:51 -08003086 }
3087 if (retval)
3088 goto done;
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05303089 spin_unlock_irqrestore(udc->lock, flags);
Felipe Balbi877c1f52011-06-29 16:41:57 +03003090 udc->ep0out.ep.desc = &ctrl_endpt_out_desc;
3091 retval = usb_ep_enable(&udc->ep0out.ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05303092 if (retval)
3093 return retval;
Felipe Balbi877c1f52011-06-29 16:41:57 +03003094
3095 udc->ep0in.ep.desc = &ctrl_endpt_in_desc;
3096 retval = usb_ep_enable(&udc->ep0in.ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05303097 if (retval)
3098 return retval;
3099 spin_lock_irqsave(udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08003100
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303101 udc->gadget.ep0 = &udc->ep0in.ep;
David Lopoaa69a802008-11-17 14:14:51 -08003102 /* bind gadget */
3103 driver->driver.bus = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08003104 udc->gadget.dev.driver = &driver->driver;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003105 udc->softconnect = 1;
David Lopoaa69a802008-11-17 14:14:51 -08003106
3107 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondeti98853282011-11-24 09:01:54 +05303108 pm_runtime_get_sync(&udc->gadget.dev);
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003109 retval = bind(&udc->gadget); /* MAY SLEEP */
David Lopoaa69a802008-11-17 14:14:51 -08003110 spin_lock_irqsave(udc->lock, flags);
3111
3112 if (retval) {
David Lopoaa69a802008-11-17 14:14:51 -08003113 udc->gadget.dev.driver = NULL;
3114 goto done;
3115 }
3116
Pavankumar Kondeti49d3df52011-01-11 09:19:21 +05303117 udc->driver = driver;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303118 if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
3119 if (udc->vbus_active) {
3120 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
3121 hw_device_reset(udc);
3122 } else {
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303123 put = true;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303124 goto done;
3125 }
3126 }
3127
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303128 if (!udc->softconnect) {
3129 put = true;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003130 goto done;
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303131 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003132
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303133 retval = hw_device_state(udc->ep0out.qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08003134
3135 done:
3136 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303137 if (retval || put)
Pavankumar Kondeti98853282011-11-24 09:01:54 +05303138 pm_runtime_put_sync(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08003139 return retval;
3140}
David Lopoaa69a802008-11-17 14:14:51 -08003141
3142/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003143 * ci13xxx_stop: unregister a gadget driver
David Lopoaa69a802008-11-17 14:14:51 -08003144 *
3145 * Check usb_gadget_unregister_driver() at "usb_gadget.h" for details
3146 */
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003147static int ci13xxx_stop(struct usb_gadget_driver *driver)
David Lopoaa69a802008-11-17 14:14:51 -08003148{
3149 struct ci13xxx *udc = _udc;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303150 unsigned long i, flags;
David Lopoaa69a802008-11-17 14:14:51 -08003151
3152 trace("%p", driver);
3153
3154 if (driver == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08003155 driver->unbind == NULL ||
3156 driver->setup == NULL ||
3157 driver->disconnect == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08003158 driver != udc->driver)
3159 return -EINVAL;
3160
3161 spin_lock_irqsave(udc->lock, flags);
3162
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303163 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) ||
3164 udc->vbus_active) {
3165 hw_device_state(0);
Marc Kleine-Buddefd537c02011-10-10 18:38:07 +02003166 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303167 _gadget_stop_activity(&udc->gadget);
Marc Kleine-Buddefd537c02011-10-10 18:38:07 +02003168 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05303169 pm_runtime_put(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303170 }
David Lopoaa69a802008-11-17 14:14:51 -08003171
3172 /* unbind gadget */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303173 spin_unlock_irqrestore(udc->lock, flags);
3174 driver->unbind(&udc->gadget); /* MAY SLEEP */
3175 spin_lock_irqsave(udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08003176
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303177 udc->gadget.dev.driver = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08003178
3179 /* free resources */
3180 for (i = 0; i < hw_ep_max; i++) {
3181 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
3182
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303183 if (!list_empty(&mEp->ep.ep_list))
David Lopoaa69a802008-11-17 14:14:51 -08003184 list_del_init(&mEp->ep.ep_list);
3185
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303186 if (mEp->qh.ptr != NULL)
3187 dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08003188 }
3189
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303190 udc->gadget.ep0 = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08003191 udc->driver = NULL;
3192
3193 spin_unlock_irqrestore(udc->lock, flags);
3194
3195 if (udc->td_pool != NULL) {
3196 dma_pool_destroy(udc->td_pool);
3197 udc->td_pool = NULL;
3198 }
3199 if (udc->qh_pool != NULL) {
3200 dma_pool_destroy(udc->qh_pool);
3201 udc->qh_pool = NULL;
3202 }
3203
3204 return 0;
3205}
David Lopoaa69a802008-11-17 14:14:51 -08003206
3207/******************************************************************************
3208 * BUS block
3209 *****************************************************************************/
3210/**
3211 * udc_irq: global interrupt handler
3212 *
3213 * This function returns IRQ_HANDLED if the IRQ has been handled
3214 * It locks access to registers
3215 */
3216static irqreturn_t udc_irq(void)
3217{
3218 struct ci13xxx *udc = _udc;
3219 irqreturn_t retval;
3220 u32 intr;
3221
3222 trace();
3223
3224 if (udc == NULL) {
3225 err("ENODEV");
3226 return IRQ_HANDLED;
3227 }
3228
3229 spin_lock(udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303230
3231 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) {
3232 if (hw_cread(CAP_USBMODE, USBMODE_CM) !=
3233 USBMODE_CM_DEVICE) {
3234 spin_unlock(udc->lock);
3235 return IRQ_NONE;
3236 }
3237 }
David Lopoaa69a802008-11-17 14:14:51 -08003238 intr = hw_test_and_clear_intr_active();
3239 if (intr) {
3240 isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intr;
3241 isr_statistics.hndl.idx &= ISR_MASK;
3242 isr_statistics.hndl.cnt++;
3243
3244 /* order defines priority - do NOT change it */
3245 if (USBi_URI & intr) {
3246 isr_statistics.uri++;
3247 isr_reset_handler(udc);
3248 }
3249 if (USBi_PCI & intr) {
3250 isr_statistics.pci++;
Amit Blay6fa647a2012-05-24 14:12:08 +03003251 isr_resume_handler(udc);
David Lopoaa69a802008-11-17 14:14:51 -08003252 }
3253 if (USBi_UEI & intr)
3254 isr_statistics.uei++;
3255 if (USBi_UI & intr) {
3256 isr_statistics.ui++;
3257 isr_tr_complete_handler(udc);
3258 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05303259 if (USBi_SLI & intr) {
Amit Blay6fa647a2012-05-24 14:12:08 +03003260 isr_suspend_handler(udc);
David Lopoaa69a802008-11-17 14:14:51 -08003261 isr_statistics.sli++;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05303262 }
David Lopoaa69a802008-11-17 14:14:51 -08003263 retval = IRQ_HANDLED;
3264 } else {
3265 isr_statistics.none++;
3266 retval = IRQ_NONE;
3267 }
3268 spin_unlock(udc->lock);
3269
3270 return retval;
3271}
3272
3273/**
3274 * udc_release: driver release function
3275 * @dev: device
3276 *
3277 * Currently does nothing
3278 */
3279static void udc_release(struct device *dev)
3280{
3281 trace("%p", dev);
3282
3283 if (dev == NULL)
3284 err("EINVAL");
3285}
3286
3287/**
3288 * udc_probe: parent probe must call this to initialize UDC
3289 * @dev: parent device
3290 * @regs: registers base address
3291 * @name: driver name
3292 *
3293 * This function returns an error code
3294 * No interrupts active, the IRQ has not been requested yet
3295 * Kernel assumes 32-bit DMA operations by default, no need to dma_set_mask
3296 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303297static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
3298 void __iomem *regs)
David Lopoaa69a802008-11-17 14:14:51 -08003299{
3300 struct ci13xxx *udc;
Lena Salmana7a05202012-03-19 10:39:44 +02003301 int retval = 0, i;
David Lopoaa69a802008-11-17 14:14:51 -08003302
Marc Kleine-Budde194fa472011-10-10 18:38:08 +02003303 trace("%p, %p, %p", dev, regs, driver->name);
David Lopoaa69a802008-11-17 14:14:51 -08003304
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303305 if (dev == NULL || regs == NULL || driver == NULL ||
3306 driver->name == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08003307 return -EINVAL;
3308
3309 udc = kzalloc(sizeof(struct ci13xxx), GFP_KERNEL);
3310 if (udc == NULL)
3311 return -ENOMEM;
3312
3313 udc->lock = &udc_lock;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303314 udc->regs = regs;
3315 udc->udc_driver = driver;
David Lopoaa69a802008-11-17 14:14:51 -08003316
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303317 udc->gadget.ops = &usb_gadget_ops;
David Lopoaa69a802008-11-17 14:14:51 -08003318 udc->gadget.speed = USB_SPEED_UNKNOWN;
Michal Nazarewiczd327ab52011-11-19 18:27:37 +01003319 udc->gadget.max_speed = USB_SPEED_HIGH;
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05303320 if (udc->udc_driver->flags & CI13XXX_IS_OTG)
3321 udc->gadget.is_otg = 1;
3322 else
3323 udc->gadget.is_otg = 0;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303324 udc->gadget.name = driver->name;
David Lopoaa69a802008-11-17 14:14:51 -08003325
3326 INIT_LIST_HEAD(&udc->gadget.ep_list);
3327 udc->gadget.ep0 = NULL;
3328
Kay Sievers5df58522009-03-24 16:38:23 -07003329 dev_set_name(&udc->gadget.dev, "gadget");
David Lopoaa69a802008-11-17 14:14:51 -08003330 udc->gadget.dev.dma_mask = dev->dma_mask;
Pavankumar Kondeti61948ee2010-12-07 17:54:01 +05303331 udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
David Lopoaa69a802008-11-17 14:14:51 -08003332 udc->gadget.dev.parent = dev;
3333 udc->gadget.dev.release = udc_release;
3334
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303335 if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
Steve Mucklef132c6c2012-06-06 18:30:57 -07003336 udc->transceiver = usb_get_transceiver();
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303337 if (udc->transceiver == NULL) {
3338 retval = -ENODEV;
3339 goto free_udc;
3340 }
3341 }
3342
Pavankumar Kondetic898b7d2012-05-16 11:54:35 +05303343 retval = hw_device_init(regs);
3344 if (retval < 0)
3345 goto put_transceiver;
3346
3347 for (i = 0; i < hw_ep_max; i++) {
3348 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
3349 INIT_LIST_HEAD(&mEp->ep.ep_list);
3350 }
3351
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303352 if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) {
3353 retval = hw_device_reset(udc);
3354 if (retval)
3355 goto put_transceiver;
3356 }
3357
David Lopoaa69a802008-11-17 14:14:51 -08003358 retval = device_register(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303359 if (retval) {
3360 put_device(&udc->gadget.dev);
3361 goto put_transceiver;
3362 }
David Lopoaa69a802008-11-17 14:14:51 -08003363
3364#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3365 retval = dbg_create_files(&udc->gadget.dev);
3366#endif
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303367 if (retval)
3368 goto unreg_device;
3369
3370 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02003371 retval = otg_set_peripheral(udc->transceiver->otg,
3372 &udc->gadget);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303373 if (retval)
3374 goto remove_dbg;
David Lopoaa69a802008-11-17 14:14:51 -08003375 }
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003376
3377 retval = usb_add_gadget_udc(dev, &udc->gadget);
3378 if (retval)
3379 goto remove_trans;
3380
Pavankumar Kondetic0360192010-12-07 17:54:04 +05303381 pm_runtime_no_callbacks(&udc->gadget.dev);
3382 pm_runtime_enable(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08003383
3384 _udc = udc;
3385 return retval;
3386
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003387remove_trans:
3388 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02003389 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02003390 usb_put_transceiver(udc->transceiver);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003391 }
3392
David Lopoaa69a802008-11-17 14:14:51 -08003393 err("error = %i", retval);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303394remove_dbg:
3395#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3396 dbg_remove_files(&udc->gadget.dev);
3397#endif
3398unreg_device:
3399 device_unregister(&udc->gadget.dev);
3400put_transceiver:
3401 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02003402 usb_put_transceiver(udc->transceiver);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303403free_udc:
David Lopoaa69a802008-11-17 14:14:51 -08003404 kfree(udc);
3405 _udc = NULL;
3406 return retval;
3407}
3408
3409/**
3410 * udc_remove: parent remove must call this to remove UDC
3411 *
3412 * No interrupts active, the IRQ has been released
3413 */
3414static void udc_remove(void)
3415{
3416 struct ci13xxx *udc = _udc;
3417
3418 if (udc == NULL) {
3419 err("EINVAL");
3420 return;
3421 }
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003422 usb_del_gadget_udc(&udc->gadget);
David Lopoaa69a802008-11-17 14:14:51 -08003423
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303424 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02003425 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02003426 usb_put_transceiver(udc->transceiver);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303427 }
David Lopoaa69a802008-11-17 14:14:51 -08003428#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3429 dbg_remove_files(&udc->gadget.dev);
3430#endif
3431 device_unregister(&udc->gadget.dev);
3432
3433 kfree(udc);
3434 _udc = NULL;
3435}