blob: 01d41300e5cea03d395addb8628b7ebc69308dde [file] [log] [blame]
David Lopoaa69a802008-11-17 14:14:51 -08001/*
2 * ci13xxx_udc.c - MIPS USB IP core family device controller
3 *
4 * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
5 *
6 * Author: David Lopo
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13/*
14 * Description: MIPS USB IP core family device controller
15 * Currently it only supports IP part number CI13412
16 *
17 * This driver is composed of several blocks:
18 * - HW: hardware interface
19 * - DBG: debug facilities (optional)
20 * - UTIL: utilities
21 * - ISR: interrupts handling
22 * - ENDPT: endpoint operations (Gadget API)
23 * - GADGET: gadget operations (Gadget API)
24 * - BUS: bus glue code, bus abstraction layer
David Lopoaa69a802008-11-17 14:14:51 -080025 *
26 * Compile Options
27 * - CONFIG_USB_GADGET_DEBUG_FILES: enable debug facilities
28 * - STALL_IN: non-empty bulk-in pipes cannot be halted
29 * if defined mass storage compliance succeeds but with warnings
30 * => case 4: Hi > Dn
31 * => case 5: Hi > Di
32 * => case 8: Hi <> Do
33 * if undefined usbtest 13 fails
34 * - TRACE: enable function tracing (depends on DEBUG)
35 *
36 * Main Features
37 * - Chapter 9 & Mass Storage Compliance with Gadget File Storage
38 * - Chapter 9 Compliance with Gadget Zero (STALL_IN undefined)
39 * - Normal & LPM support
40 *
41 * USBTEST Report
42 * - OK: 0-12, 13 (STALL_IN defined) & 14
43 * - Not Supported: 15 & 16 (ISO)
44 *
45 * TODO List
46 * - OTG
47 * - Isochronous & Interrupt Traffic
48 * - Handle requests which spawns into several TDs
49 * - GET_STATUS(device) - always reports 0
50 * - Gadget API (majority of optional features)
David Lopoaa69a802008-11-17 14:14:51 -080051 */
Matthias Kaehlcke36825a22009-04-15 22:28:36 +020052#include <linux/delay.h>
David Lopoaa69a802008-11-17 14:14:51 -080053#include <linux/device.h>
54#include <linux/dmapool.h>
55#include <linux/dma-mapping.h>
56#include <linux/init.h>
Vijayavardhan Vennapusa397a4532012-07-20 13:18:32 +053057#include <linux/ratelimit.h>
David Lopoaa69a802008-11-17 14:14:51 -080058#include <linux/interrupt.h>
David Lopoaa69a802008-11-17 14:14:51 -080059#include <linux/io.h>
60#include <linux/irq.h>
61#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090062#include <linux/slab.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070063#include <linux/module.h>
Pavankumar Kondetic0360192010-12-07 17:54:04 +053064#include <linux/pm_runtime.h>
David Lopoaa69a802008-11-17 14:14:51 -080065#include <linux/usb/ch9.h>
66#include <linux/usb/gadget.h>
Pavankumar Kondetif01ef572010-12-07 17:54:02 +053067#include <linux/usb/otg.h>
Ido Shayevitzd1cb16c2012-03-28 18:57:47 +020068#include <linux/usb/msm_hsusb.h>
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)
Vijayavardhan Vennapusa397a4532012-07-20 13:18:32 +053078#define ATDTW_SET_DELAY 100 /* 100msec delay */
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +053079#define EP_PRIME_CHECK_DELAY (jiffies + msecs_to_jiffies(1000))
80#define MAX_PRIME_CHECK_RETRY 3 /*Wait for 3sec for EP prime failure */
Michael Grzeschik954aad82011-10-10 18:38:06 +020081
David Lopoaa69a802008-11-17 14:14:51 -080082/* ctrl register bank access */
83static DEFINE_SPINLOCK(udc_lock);
84
David Lopoaa69a802008-11-17 14:14:51 -080085/* control endpoint description */
86static const struct usb_endpoint_descriptor
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +053087ctrl_endpt_out_desc = {
David Lopoaa69a802008-11-17 14:14:51 -080088 .bLength = USB_DT_ENDPOINT_SIZE,
89 .bDescriptorType = USB_DT_ENDPOINT,
90
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +053091 .bEndpointAddress = USB_DIR_OUT,
92 .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
93 .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
94};
95
96static const struct usb_endpoint_descriptor
97ctrl_endpt_in_desc = {
98 .bLength = USB_DT_ENDPOINT_SIZE,
99 .bDescriptorType = USB_DT_ENDPOINT,
100
101 .bEndpointAddress = USB_DIR_IN,
David Lopoaa69a802008-11-17 14:14:51 -0800102 .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
103 .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
104};
105
106/* UDC descriptor */
107static struct ci13xxx *_udc;
108
109/* Interrupt statistics */
110#define ISR_MASK 0x1F
111static struct {
112 u32 test;
113 u32 ui;
114 u32 uei;
115 u32 pci;
116 u32 uri;
117 u32 sli;
118 u32 none;
119 struct {
120 u32 cnt;
121 u32 buf[ISR_MASK+1];
122 u32 idx;
123 } hndl;
124} isr_statistics;
125
126/**
127 * ffs_nr: find first (least significant) bit set
128 * @x: the word to search
129 *
130 * This function returns bit number (instead of position)
131 */
132static int ffs_nr(u32 x)
133{
134 int n = ffs(x);
135
136 return n ? n-1 : 32;
137}
138
139/******************************************************************************
140 * HW block
141 *****************************************************************************/
142/* register bank descriptor */
143static struct {
144 unsigned lpm; /* is LPM? */
145 void __iomem *abs; /* bus map offset */
146 void __iomem *cap; /* bus map offset + CAP offset + CAP data */
147 size_t size; /* bank size */
148} hw_bank;
149
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530150/* MSM specific */
151#define ABS_AHBBURST (0x0090UL)
152#define ABS_AHBMODE (0x0098UL)
David Lopoaa69a802008-11-17 14:14:51 -0800153/* UDC register map */
154#define ABS_CAPLENGTH (0x100UL)
155#define ABS_HCCPARAMS (0x108UL)
156#define ABS_DCCPARAMS (0x124UL)
157#define ABS_TESTMODE (hw_bank.lpm ? 0x0FCUL : 0x138UL)
158/* offset to CAPLENTGH (addr + data) */
159#define CAP_USBCMD (0x000UL)
160#define CAP_USBSTS (0x004UL)
161#define CAP_USBINTR (0x008UL)
162#define CAP_DEVICEADDR (0x014UL)
163#define CAP_ENDPTLISTADDR (0x018UL)
164#define CAP_PORTSC (0x044UL)
David Lopof23e6492009-04-16 14:35:24 -0700165#define CAP_DEVLC (0x084UL)
Ofir Cohena1c2a872011-12-14 10:26:34 +0200166#define CAP_ENDPTPIPEID (0x0BCUL)
David Lopoaa69a802008-11-17 14:14:51 -0800167#define CAP_USBMODE (hw_bank.lpm ? 0x0C8UL : 0x068UL)
168#define CAP_ENDPTSETUPSTAT (hw_bank.lpm ? 0x0D8UL : 0x06CUL)
169#define CAP_ENDPTPRIME (hw_bank.lpm ? 0x0DCUL : 0x070UL)
170#define CAP_ENDPTFLUSH (hw_bank.lpm ? 0x0E0UL : 0x074UL)
171#define CAP_ENDPTSTAT (hw_bank.lpm ? 0x0E4UL : 0x078UL)
172#define CAP_ENDPTCOMPLETE (hw_bank.lpm ? 0x0E8UL : 0x07CUL)
173#define CAP_ENDPTCTRL (hw_bank.lpm ? 0x0ECUL : 0x080UL)
174#define CAP_LAST (hw_bank.lpm ? 0x12CUL : 0x0C0UL)
175
Amit Blayfd075dd2012-06-26 13:12:50 +0300176#define REMOTE_WAKEUP_DELAY msecs_to_jiffies(200)
177
David Lopoaa69a802008-11-17 14:14:51 -0800178/* maximum number of enpoints: valid only after hw_device_reset() */
179static unsigned hw_ep_max;
180
181/**
182 * hw_ep_bit: calculates the bit number
183 * @num: endpoint number
184 * @dir: endpoint direction
185 *
186 * This function returns bit number
187 */
188static inline int hw_ep_bit(int num, int dir)
189{
190 return num + (dir ? 16 : 0);
191}
192
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200193static int ep_to_bit(int n)
194{
195 int fill = 16 - hw_ep_max / 2;
196
197 if (n >= hw_ep_max / 2)
198 n += fill;
199
200 return n;
201}
202
David Lopoaa69a802008-11-17 14:14:51 -0800203/**
204 * hw_aread: reads from register bitfield
205 * @addr: address relative to bus map
206 * @mask: bitfield mask
207 *
208 * This function returns register bitfield data
209 */
210static u32 hw_aread(u32 addr, u32 mask)
211{
212 return ioread32(addr + hw_bank.abs) & mask;
213}
214
215/**
216 * hw_awrite: writes to register bitfield
217 * @addr: address relative to bus map
218 * @mask: bitfield mask
219 * @data: new data
220 */
221static void hw_awrite(u32 addr, u32 mask, u32 data)
222{
223 iowrite32(hw_aread(addr, ~mask) | (data & mask),
224 addr + hw_bank.abs);
225}
226
227/**
228 * hw_cread: reads from register bitfield
229 * @addr: address relative to CAP offset plus content
230 * @mask: bitfield mask
231 *
232 * This function returns register bitfield data
233 */
234static u32 hw_cread(u32 addr, u32 mask)
235{
236 return ioread32(addr + hw_bank.cap) & mask;
237}
238
239/**
240 * hw_cwrite: writes to register bitfield
241 * @addr: address relative to CAP offset plus content
242 * @mask: bitfield mask
243 * @data: new data
244 */
245static void hw_cwrite(u32 addr, u32 mask, u32 data)
246{
247 iowrite32(hw_cread(addr, ~mask) | (data & mask),
248 addr + hw_bank.cap);
249}
250
251/**
252 * hw_ctest_and_clear: tests & clears register bitfield
253 * @addr: address relative to CAP offset plus content
254 * @mask: bitfield mask
255 *
256 * This function returns register bitfield data
257 */
258static u32 hw_ctest_and_clear(u32 addr, u32 mask)
259{
260 u32 reg = hw_cread(addr, mask);
261
262 iowrite32(reg, addr + hw_bank.cap);
263 return reg;
264}
265
266/**
267 * hw_ctest_and_write: tests & writes register bitfield
268 * @addr: address relative to CAP offset plus content
269 * @mask: bitfield mask
270 * @data: new data
271 *
272 * This function returns register bitfield data
273 */
274static u32 hw_ctest_and_write(u32 addr, u32 mask, u32 data)
275{
276 u32 reg = hw_cread(addr, ~0);
277
278 iowrite32((reg & ~mask) | (data & mask), addr + hw_bank.cap);
279 return (reg & mask) >> ffs_nr(mask);
280}
281
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530282static int hw_device_init(void __iomem *base)
David Lopoaa69a802008-11-17 14:14:51 -0800283{
284 u32 reg;
285
286 /* bank is a module variable */
287 hw_bank.abs = base;
288
289 hw_bank.cap = hw_bank.abs;
290 hw_bank.cap += ABS_CAPLENGTH;
291 hw_bank.cap += ioread8(hw_bank.cap);
292
293 reg = hw_aread(ABS_HCCPARAMS, HCCPARAMS_LEN) >> ffs_nr(HCCPARAMS_LEN);
294 hw_bank.lpm = reg;
295 hw_bank.size = hw_bank.cap - hw_bank.abs;
296 hw_bank.size += CAP_LAST;
297 hw_bank.size /= sizeof(u32);
298
David Lopoaa69a802008-11-17 14:14:51 -0800299 reg = hw_aread(ABS_DCCPARAMS, DCCPARAMS_DEN) >> ffs_nr(DCCPARAMS_DEN);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530300 hw_ep_max = reg * 2; /* cache hw ENDPT_MAX */
David Lopoaa69a802008-11-17 14:14:51 -0800301
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530302 if (hw_ep_max == 0 || hw_ep_max > ENDPT_MAX)
303 return -ENODEV;
David Lopoaa69a802008-11-17 14:14:51 -0800304
305 /* setup lock mode ? */
306
307 /* ENDPTSETUPSTAT is '0' by default */
308
309 /* HCSPARAMS.bf.ppc SHOULD BE zero for device */
310
311 return 0;
312}
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530313/**
314 * hw_device_reset: resets chip (execute without interruption)
315 * @base: register base address
316 *
317 * This function returns an error code
318 */
319static int hw_device_reset(struct ci13xxx *udc)
320{
321 /* should flush & stop before reset */
322 hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0);
323 hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
324
325 hw_cwrite(CAP_USBCMD, USBCMD_RST, USBCMD_RST);
326 while (hw_cread(CAP_USBCMD, USBCMD_RST))
327 udelay(10); /* not RTOS friendly */
328
329
330 if (udc->udc_driver->notify_event)
331 udc->udc_driver->notify_event(udc,
332 CI13XXX_CONTROLLER_RESET_EVENT);
333
Pavankumar Kondeti8c2387a2011-05-02 11:56:28 +0530334 if (udc->udc_driver->flags & CI13XXX_DISABLE_STREAMING)
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530335 hw_cwrite(CAP_USBMODE, USBMODE_SDIS, USBMODE_SDIS);
336
337 /* USBMODE should be configured step by step */
338 hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
339 hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE);
340 hw_cwrite(CAP_USBMODE, USBMODE_SLOM, USBMODE_SLOM); /* HW >= 2.3 */
341
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700342 /*
343 * ITC (Interrupt Threshold Control) field is to set the maximum
344 * rate at which the device controller will issue interrupts.
345 * The maximum interrupt interval measured in micro frames.
346 * Valid values are 0, 1, 2, 4, 8, 16, 32, 64. The default value is
347 * 8 micro frames. If CPU can handle interrupts at faster rate, ITC
348 * can be set to lesser value to gain performance.
349 */
350 if (udc->udc_driver->flags & CI13XXX_ZERO_ITC)
351 hw_cwrite(CAP_USBCMD, USBCMD_ITC_MASK, USBCMD_ITC(0));
352
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530353 if (hw_cread(CAP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
354 pr_err("cannot enter in device mode");
355 pr_err("lpm = %i", hw_bank.lpm);
356 return -ENODEV;
357 }
358
359 return 0;
360}
David Lopoaa69a802008-11-17 14:14:51 -0800361
362/**
363 * hw_device_state: enables/disables interrupts & starts/stops device (execute
364 * without interruption)
365 * @dma: 0 => disable, !0 => enable and set dma engine
366 *
367 * This function returns an error code
368 */
369static int hw_device_state(u32 dma)
370{
371 if (dma) {
372 hw_cwrite(CAP_ENDPTLISTADDR, ~0, dma);
373 /* interrupt, error, port change, reset, sleep/suspend */
374 hw_cwrite(CAP_USBINTR, ~0,
375 USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
376 hw_cwrite(CAP_USBCMD, USBCMD_RS, USBCMD_RS);
377 } else {
378 hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
379 hw_cwrite(CAP_USBINTR, ~0, 0);
380 }
381 return 0;
382}
383
384/**
385 * hw_ep_flush: flush endpoint fifo (execute without interruption)
386 * @num: endpoint number
387 * @dir: endpoint direction
388 *
389 * This function returns an error code
390 */
391static int hw_ep_flush(int num, int dir)
392{
393 int n = hw_ep_bit(num, dir);
394
395 do {
396 /* flush any pending transfer */
397 hw_cwrite(CAP_ENDPTFLUSH, BIT(n), BIT(n));
398 while (hw_cread(CAP_ENDPTFLUSH, BIT(n)))
399 cpu_relax();
400 } while (hw_cread(CAP_ENDPTSTAT, BIT(n)));
401
402 return 0;
403}
404
405/**
406 * hw_ep_disable: disables endpoint (execute without interruption)
407 * @num: endpoint number
408 * @dir: endpoint direction
409 *
410 * This function returns an error code
411 */
412static int hw_ep_disable(int num, int dir)
413{
414 hw_ep_flush(num, dir);
415 hw_cwrite(CAP_ENDPTCTRL + num * sizeof(u32),
416 dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0);
417 return 0;
418}
419
420/**
421 * hw_ep_enable: enables endpoint (execute without interruption)
422 * @num: endpoint number
423 * @dir: endpoint direction
424 * @type: endpoint type
425 *
426 * This function returns an error code
427 */
428static int hw_ep_enable(int num, int dir, int type)
429{
430 u32 mask, data;
431
432 if (dir) {
433 mask = ENDPTCTRL_TXT; /* type */
434 data = type << ffs_nr(mask);
435
436 mask |= ENDPTCTRL_TXS; /* unstall */
437 mask |= ENDPTCTRL_TXR; /* reset data toggle */
438 data |= ENDPTCTRL_TXR;
439 mask |= ENDPTCTRL_TXE; /* enable */
440 data |= ENDPTCTRL_TXE;
441 } else {
442 mask = ENDPTCTRL_RXT; /* type */
443 data = type << ffs_nr(mask);
444
445 mask |= ENDPTCTRL_RXS; /* unstall */
446 mask |= ENDPTCTRL_RXR; /* reset data toggle */
447 data |= ENDPTCTRL_RXR;
448 mask |= ENDPTCTRL_RXE; /* enable */
449 data |= ENDPTCTRL_RXE;
450 }
451 hw_cwrite(CAP_ENDPTCTRL + num * sizeof(u32), mask, data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700452
453 /* make sure endpoint is enabled before returning */
454 mb();
455
David Lopoaa69a802008-11-17 14:14:51 -0800456 return 0;
457}
458
459/**
460 * hw_ep_get_halt: return endpoint halt status
461 * @num: endpoint number
462 * @dir: endpoint direction
463 *
464 * This function returns 1 if endpoint halted
465 */
466static int hw_ep_get_halt(int num, int dir)
467{
468 u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
469
470 return hw_cread(CAP_ENDPTCTRL + num * sizeof(u32), mask) ? 1 : 0;
471}
472
473/**
David Lopoaa69a802008-11-17 14:14:51 -0800474 * hw_test_and_clear_setup_status: test & clear setup status (execute without
475 * interruption)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200476 * @n: endpoint number
David Lopoaa69a802008-11-17 14:14:51 -0800477 *
478 * This function returns setup status
479 */
480static int hw_test_and_clear_setup_status(int n)
481{
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200482 n = ep_to_bit(n);
David Lopoaa69a802008-11-17 14:14:51 -0800483 return hw_ctest_and_clear(CAP_ENDPTSETUPSTAT, BIT(n));
484}
485
486/**
487 * hw_ep_prime: primes endpoint (execute without interruption)
488 * @num: endpoint number
489 * @dir: endpoint direction
490 * @is_ctrl: true if control endpoint
491 *
492 * This function returns an error code
493 */
494static int hw_ep_prime(int num, int dir, int is_ctrl)
495{
496 int n = hw_ep_bit(num, dir);
497
David Lopoaa69a802008-11-17 14:14:51 -0800498 if (is_ctrl && dir == RX && hw_cread(CAP_ENDPTSETUPSTAT, BIT(num)))
499 return -EAGAIN;
500
501 hw_cwrite(CAP_ENDPTPRIME, BIT(n), BIT(n));
502
David Lopoaa69a802008-11-17 14:14:51 -0800503 if (is_ctrl && dir == RX && hw_cread(CAP_ENDPTSETUPSTAT, BIT(num)))
504 return -EAGAIN;
505
506 /* status shoult be tested according with manual but it doesn't work */
507 return 0;
508}
509
510/**
511 * hw_ep_set_halt: configures ep halt & resets data toggle after clear (execute
512 * without interruption)
513 * @num: endpoint number
514 * @dir: endpoint direction
515 * @value: true => stall, false => unstall
516 *
517 * This function returns an error code
518 */
519static int hw_ep_set_halt(int num, int dir, int value)
520{
Pavankumar Kondeti05598942011-07-06 16:58:44 +0530521 u32 addr, mask_xs, mask_xr;
522
David Lopoaa69a802008-11-17 14:14:51 -0800523 if (value != 0 && value != 1)
524 return -EINVAL;
525
526 do {
Pavankumar Kondeti05598942011-07-06 16:58:44 +0530527 if (hw_cread(CAP_ENDPTSETUPSTAT, BIT(num)))
528 return 0;
529
530 addr = CAP_ENDPTCTRL + num * sizeof(u32);
531 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
532 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR;
David Lopoaa69a802008-11-17 14:14:51 -0800533
534 /* data toggle - reserved for EP0 but it's in ESS */
535 hw_cwrite(addr, mask_xs|mask_xr, value ? mask_xs : mask_xr);
536
537 } while (value != hw_ep_get_halt(num, dir));
538
539 return 0;
540}
541
542/**
543 * hw_intr_clear: disables interrupt & clears interrupt status (execute without
544 * interruption)
545 * @n: interrupt bit
546 *
547 * This function returns an error code
548 */
549static int hw_intr_clear(int n)
550{
551 if (n >= REG_BITS)
552 return -EINVAL;
553
554 hw_cwrite(CAP_USBINTR, BIT(n), 0);
555 hw_cwrite(CAP_USBSTS, BIT(n), BIT(n));
556 return 0;
557}
558
559/**
560 * hw_intr_force: enables interrupt & forces interrupt status (execute without
561 * interruption)
562 * @n: interrupt bit
563 *
564 * This function returns an error code
565 */
566static int hw_intr_force(int n)
567{
568 if (n >= REG_BITS)
569 return -EINVAL;
570
571 hw_awrite(ABS_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
572 hw_cwrite(CAP_USBINTR, BIT(n), BIT(n));
573 hw_cwrite(CAP_USBSTS, BIT(n), BIT(n));
574 hw_awrite(ABS_TESTMODE, TESTMODE_FORCE, 0);
575 return 0;
576}
577
578/**
579 * hw_is_port_high_speed: test if port is high speed
580 *
581 * This function returns true if high speed port
582 */
583static int hw_port_is_high_speed(void)
584{
585 return hw_bank.lpm ? hw_cread(CAP_DEVLC, DEVLC_PSPD) :
586 hw_cread(CAP_PORTSC, PORTSC_HSP);
587}
588
589/**
590 * hw_port_test_get: reads port test mode value
591 *
592 * This function returns port test mode value
593 */
594static u8 hw_port_test_get(void)
595{
596 return hw_cread(CAP_PORTSC, PORTSC_PTC) >> ffs_nr(PORTSC_PTC);
597}
598
599/**
600 * hw_port_test_set: writes port test mode (execute without interruption)
601 * @mode: new value
602 *
603 * This function returns an error code
604 */
605static int hw_port_test_set(u8 mode)
606{
607 const u8 TEST_MODE_MAX = 7;
608
609 if (mode > TEST_MODE_MAX)
610 return -EINVAL;
611
612 hw_cwrite(CAP_PORTSC, PORTSC_PTC, mode << ffs_nr(PORTSC_PTC));
613 return 0;
614}
615
616/**
617 * hw_read_intr_enable: returns interrupt enable register
618 *
619 * This function returns register data
620 */
621static u32 hw_read_intr_enable(void)
622{
623 return hw_cread(CAP_USBINTR, ~0);
624}
625
626/**
627 * hw_read_intr_status: returns interrupt status register
628 *
629 * This function returns register data
630 */
631static u32 hw_read_intr_status(void)
632{
633 return hw_cread(CAP_USBSTS, ~0);
634}
635
636/**
637 * hw_register_read: reads all device registers (execute without interruption)
638 * @buf: destination buffer
639 * @size: buffer size
640 *
641 * This function returns number of registers read
642 */
643static size_t hw_register_read(u32 *buf, size_t size)
644{
645 unsigned i;
646
647 if (size > hw_bank.size)
648 size = hw_bank.size;
649
650 for (i = 0; i < size; i++)
651 buf[i] = hw_aread(i * sizeof(u32), ~0);
652
653 return size;
654}
655
656/**
657 * hw_register_write: writes to register
658 * @addr: register address
659 * @data: register value
660 *
661 * This function returns an error code
662 */
663static int hw_register_write(u16 addr, u32 data)
664{
665 /* align */
666 addr /= sizeof(u32);
667
668 if (addr >= hw_bank.size)
669 return -EINVAL;
670
671 /* align */
672 addr *= sizeof(u32);
673
674 hw_awrite(addr, ~0, data);
675 return 0;
676}
677
678/**
679 * hw_test_and_clear_complete: test & clear complete status (execute without
680 * interruption)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200681 * @n: endpoint number
David Lopoaa69a802008-11-17 14:14:51 -0800682 *
683 * This function returns complete status
684 */
685static int hw_test_and_clear_complete(int n)
686{
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200687 n = ep_to_bit(n);
David Lopoaa69a802008-11-17 14:14:51 -0800688 return hw_ctest_and_clear(CAP_ENDPTCOMPLETE, BIT(n));
689}
690
691/**
692 * hw_test_and_clear_intr_active: test & clear active interrupts (execute
693 * without interruption)
694 *
695 * This function returns active interrutps
696 */
697static u32 hw_test_and_clear_intr_active(void)
698{
699 u32 reg = hw_read_intr_status() & hw_read_intr_enable();
700
701 hw_cwrite(CAP_USBSTS, ~0, reg);
702 return reg;
703}
704
705/**
706 * hw_test_and_clear_setup_guard: test & clear setup guard (execute without
707 * interruption)
708 *
709 * This function returns guard value
710 */
711static int hw_test_and_clear_setup_guard(void)
712{
713 return hw_ctest_and_write(CAP_USBCMD, USBCMD_SUTW, 0);
714}
715
716/**
717 * hw_test_and_set_setup_guard: test & set setup guard (execute without
718 * interruption)
719 *
720 * This function returns guard value
721 */
722static int hw_test_and_set_setup_guard(void)
723{
724 return hw_ctest_and_write(CAP_USBCMD, USBCMD_SUTW, USBCMD_SUTW);
725}
726
727/**
728 * hw_usb_set_address: configures USB address (execute without interruption)
729 * @value: new USB address
730 *
731 * This function returns an error code
732 */
733static int hw_usb_set_address(u8 value)
734{
735 /* advance */
736 hw_cwrite(CAP_DEVICEADDR, DEVICEADDR_USBADR | DEVICEADDR_USBADRA,
737 value << ffs_nr(DEVICEADDR_USBADR) | DEVICEADDR_USBADRA);
738 return 0;
739}
740
741/**
742 * hw_usb_reset: restart device after a bus reset (execute without
743 * interruption)
744 *
745 * This function returns an error code
746 */
747static int hw_usb_reset(void)
748{
749 hw_usb_set_address(0);
750
751 /* ESS flushes only at end?!? */
752 hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0); /* flush all EPs */
753
754 /* clear setup token semaphores */
755 hw_cwrite(CAP_ENDPTSETUPSTAT, 0, 0); /* writes its content */
756
757 /* clear complete status */
758 hw_cwrite(CAP_ENDPTCOMPLETE, 0, 0); /* writes its content */
759
760 /* wait until all bits cleared */
761 while (hw_cread(CAP_ENDPTPRIME, ~0))
762 udelay(10); /* not RTOS friendly */
763
764 /* reset all endpoints ? */
765
766 /* reset internal status and wait for further instructions
767 no need to verify the port reset status (ESS does it) */
768
769 return 0;
770}
771
772/******************************************************************************
773 * DBG block
774 *****************************************************************************/
775/**
776 * show_device: prints information about device capabilities and status
777 *
778 * Check "device.h" for details
779 */
780static ssize_t show_device(struct device *dev, struct device_attribute *attr,
781 char *buf)
782{
783 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
784 struct usb_gadget *gadget = &udc->gadget;
785 int n = 0;
786
787 dbg_trace("[%s] %p\n", __func__, buf);
788 if (attr == NULL || buf == NULL) {
789 dev_err(dev, "[%s] EINVAL\n", __func__);
790 return 0;
791 }
792
793 n += scnprintf(buf + n, PAGE_SIZE - n, "speed = %d\n",
794 gadget->speed);
Michal Nazarewiczd327ab52011-11-19 18:27:37 +0100795 n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed = %d\n",
796 gadget->max_speed);
797 /* TODO: Scheduled for removal in 3.8. */
David Lopoaa69a802008-11-17 14:14:51 -0800798 n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed = %d\n",
Michal Nazarewiczd327ab52011-11-19 18:27:37 +0100799 gadget_is_dualspeed(gadget));
David Lopoaa69a802008-11-17 14:14:51 -0800800 n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg = %d\n",
801 gadget->is_otg);
802 n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral = %d\n",
803 gadget->is_a_peripheral);
804 n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable = %d\n",
805 gadget->b_hnp_enable);
806 n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support = %d\n",
807 gadget->a_hnp_support);
808 n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n",
809 gadget->a_alt_hnp_support);
810 n += scnprintf(buf + n, PAGE_SIZE - n, "name = %s\n",
811 (gadget->name ? gadget->name : ""));
812
813 return n;
814}
815static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
816
817/**
818 * show_driver: prints information about attached gadget (if any)
819 *
820 * Check "device.h" for details
821 */
822static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
823 char *buf)
824{
825 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
826 struct usb_gadget_driver *driver = udc->driver;
827 int n = 0;
828
829 dbg_trace("[%s] %p\n", __func__, buf);
830 if (attr == NULL || buf == NULL) {
831 dev_err(dev, "[%s] EINVAL\n", __func__);
832 return 0;
833 }
834
835 if (driver == NULL)
836 return scnprintf(buf, PAGE_SIZE,
837 "There is no gadget attached!\n");
838
839 n += scnprintf(buf + n, PAGE_SIZE - n, "function = %s\n",
840 (driver->function ? driver->function : ""));
841 n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n",
Michal Nazarewicz7177aed2011-11-19 18:27:38 +0100842 driver->max_speed);
David Lopoaa69a802008-11-17 14:14:51 -0800843
844 return n;
845}
846static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL);
847
848/* Maximum event message length */
849#define DBG_DATA_MSG 64UL
850
851/* Maximum event messages */
852#define DBG_DATA_MAX 128UL
853
854/* Event buffer descriptor */
855static struct {
856 char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */
857 unsigned idx; /* index */
858 unsigned tty; /* print to console? */
859 rwlock_t lck; /* lock */
860} dbg_data = {
861 .idx = 0,
862 .tty = 0,
863 .lck = __RW_LOCK_UNLOCKED(lck)
864};
865
866/**
867 * dbg_dec: decrements debug event index
868 * @idx: buffer index
869 */
870static void dbg_dec(unsigned *idx)
871{
872 *idx = (*idx - 1) & (DBG_DATA_MAX-1);
873}
874
875/**
876 * dbg_inc: increments debug event index
877 * @idx: buffer index
878 */
879static void dbg_inc(unsigned *idx)
880{
881 *idx = (*idx + 1) & (DBG_DATA_MAX-1);
882}
883
Vamsi Krishna8d1bbd52012-02-09 21:13:24 -0800884
885static unsigned int ep_addr_txdbg_mask;
886module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
887static unsigned int ep_addr_rxdbg_mask;
888module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
889
890static int allow_dbg_print(u8 addr)
891{
892 int dir, num;
893
894 /* allow bus wide events */
895 if (addr == 0xff)
896 return 1;
897
898 dir = addr & USB_ENDPOINT_DIR_MASK ? TX : RX;
899 num = addr & ~USB_ENDPOINT_DIR_MASK;
900 num = 1 << num;
901
902 if ((dir == TX) && (num & ep_addr_txdbg_mask))
903 return 1;
904 if ((dir == RX) && (num & ep_addr_rxdbg_mask))
905 return 1;
906
907 return 0;
908}
909
David Lopoaa69a802008-11-17 14:14:51 -0800910/**
911 * dbg_print: prints the common part of the event
912 * @addr: endpoint address
913 * @name: event name
914 * @status: status
915 * @extra: extra information
916 */
917static void dbg_print(u8 addr, const char *name, int status, const char *extra)
918{
919 struct timeval tval;
920 unsigned int stamp;
921 unsigned long flags;
922
Vamsi Krishna8d1bbd52012-02-09 21:13:24 -0800923 if (!allow_dbg_print(addr))
924 return;
925
David Lopoaa69a802008-11-17 14:14:51 -0800926 write_lock_irqsave(&dbg_data.lck, flags);
927
928 do_gettimeofday(&tval);
929 stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s */
930 stamp = stamp * 1000000 + tval.tv_usec;
931
932 scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +0300933 "%04X\t? %02X %-7.7s %4i ?\t%s\n",
David Lopoaa69a802008-11-17 14:14:51 -0800934 stamp, addr, name, status, extra);
935
936 dbg_inc(&dbg_data.idx);
937
938 write_unlock_irqrestore(&dbg_data.lck, flags);
939
940 if (dbg_data.tty != 0)
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +0300941 pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n",
David Lopoaa69a802008-11-17 14:14:51 -0800942 stamp, addr, name, status, extra);
943}
944
945/**
946 * dbg_done: prints a DONE event
947 * @addr: endpoint address
948 * @td: transfer descriptor
949 * @status: status
950 */
951static void dbg_done(u8 addr, const u32 token, int status)
952{
953 char msg[DBG_DATA_MSG];
954
955 scnprintf(msg, sizeof(msg), "%d %02X",
956 (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES),
957 (int)(token & TD_STATUS) >> ffs_nr(TD_STATUS));
958 dbg_print(addr, "DONE", status, msg);
959}
960
961/**
962 * dbg_event: prints a generic event
963 * @addr: endpoint address
964 * @name: event name
965 * @status: status
966 */
967static void dbg_event(u8 addr, const char *name, int status)
968{
969 if (name != NULL)
970 dbg_print(addr, name, status, "");
971}
972
973/*
974 * dbg_queue: prints a QUEUE event
975 * @addr: endpoint address
976 * @req: USB request
977 * @status: status
978 */
979static void dbg_queue(u8 addr, const struct usb_request *req, int status)
980{
981 char msg[DBG_DATA_MSG];
982
983 if (req != NULL) {
984 scnprintf(msg, sizeof(msg),
985 "%d %d", !req->no_interrupt, req->length);
986 dbg_print(addr, "QUEUE", status, msg);
987 }
988}
989
990/**
991 * dbg_setup: prints a SETUP event
992 * @addr: endpoint address
993 * @req: setup request
994 */
995static void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
996{
997 char msg[DBG_DATA_MSG];
998
999 if (req != NULL) {
1000 scnprintf(msg, sizeof(msg),
1001 "%02X %02X %04X %04X %d", req->bRequestType,
1002 req->bRequest, le16_to_cpu(req->wValue),
1003 le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
1004 dbg_print(addr, "SETUP", 0, msg);
1005 }
1006}
1007
1008/**
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301009 * dbg_prime_fail: prints a PRIME FAIL event
1010 * @addr: endpoint address
1011 * @mEp: endpoint structure
1012 */
1013static void dbg_prime_fail(u8 addr, const char *name,
1014 const struct ci13xxx_ep *mEp)
1015{
1016 char msg[DBG_DATA_MSG];
1017 struct ci13xxx_req *req;
1018 struct list_head *ptr = NULL;
1019
1020 if (mEp != NULL) {
1021 scnprintf(msg, sizeof(msg),
1022 "PRIME fail EP%d%s QH:%08X",
1023 mEp->num, mEp->dir ? "IN" : "OUT", mEp->qh.ptr->cap);
1024 dbg_print(addr, name, 0, msg);
1025 scnprintf(msg, sizeof(msg),
1026 "cap:%08X %08X %08X\n",
1027 mEp->qh.ptr->curr, mEp->qh.ptr->td.next,
1028 mEp->qh.ptr->td.token);
1029 dbg_print(addr, "QHEAD", 0, msg);
1030
1031 list_for_each(ptr, &mEp->qh.queue) {
1032 req = list_entry(ptr, struct ci13xxx_req, queue);
1033 scnprintf(msg, sizeof(msg),
1034 "%08X:%08X:%08X\n",
1035 req->dma, req->ptr->next,
1036 req->ptr->token);
1037 dbg_print(addr, "REQ", 0, msg);
1038 scnprintf(msg, sizeof(msg), "%08X:%d\n",
1039 req->ptr->page[0],
1040 req->req.status);
1041 dbg_print(addr, "REQPAGE", 0, msg);
1042 }
1043 }
1044}
1045
1046/**
David Lopoaa69a802008-11-17 14:14:51 -08001047 * show_events: displays the event buffer
1048 *
1049 * Check "device.h" for details
1050 */
1051static ssize_t show_events(struct device *dev, struct device_attribute *attr,
1052 char *buf)
1053{
1054 unsigned long flags;
1055 unsigned i, j, n = 0;
1056
1057 dbg_trace("[%s] %p\n", __func__, buf);
1058 if (attr == NULL || buf == NULL) {
1059 dev_err(dev, "[%s] EINVAL\n", __func__);
1060 return 0;
1061 }
1062
1063 read_lock_irqsave(&dbg_data.lck, flags);
1064
1065 i = dbg_data.idx;
1066 for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) {
1067 n += strlen(dbg_data.buf[i]);
1068 if (n >= PAGE_SIZE) {
1069 n -= strlen(dbg_data.buf[i]);
1070 break;
1071 }
1072 }
1073 for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i))
1074 j += scnprintf(buf + j, PAGE_SIZE - j,
1075 "%s", dbg_data.buf[i]);
1076
1077 read_unlock_irqrestore(&dbg_data.lck, flags);
1078
1079 return n;
1080}
1081
1082/**
1083 * store_events: configure if events are going to be also printed to console
1084 *
1085 * Check "device.h" for details
1086 */
1087static ssize_t store_events(struct device *dev, struct device_attribute *attr,
1088 const char *buf, size_t count)
1089{
1090 unsigned tty;
1091
1092 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1093 if (attr == NULL || buf == NULL) {
1094 dev_err(dev, "[%s] EINVAL\n", __func__);
1095 goto done;
1096 }
1097
1098 if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
1099 dev_err(dev, "<1|0>: enable|disable console log\n");
1100 goto done;
1101 }
1102
1103 dbg_data.tty = tty;
1104 dev_info(dev, "tty = %u", dbg_data.tty);
1105
1106 done:
1107 return count;
1108}
1109static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
1110
1111/**
1112 * show_inters: interrupt status, enable status and historic
1113 *
1114 * Check "device.h" for details
1115 */
1116static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
1117 char *buf)
1118{
1119 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1120 unsigned long flags;
1121 u32 intr;
1122 unsigned i, j, n = 0;
1123
1124 dbg_trace("[%s] %p\n", __func__, buf);
1125 if (attr == NULL || buf == NULL) {
1126 dev_err(dev, "[%s] EINVAL\n", __func__);
1127 return 0;
1128 }
1129
1130 spin_lock_irqsave(udc->lock, flags);
1131
1132 n += scnprintf(buf + n, PAGE_SIZE - n,
1133 "status = %08x\n", hw_read_intr_status());
1134 n += scnprintf(buf + n, PAGE_SIZE - n,
1135 "enable = %08x\n", hw_read_intr_enable());
1136
1137 n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
1138 isr_statistics.test);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001139 n += scnprintf(buf + n, PAGE_SIZE - n, "? ui = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001140 isr_statistics.ui);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001141 n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001142 isr_statistics.uei);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001143 n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001144 isr_statistics.pci);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001145 n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001146 isr_statistics.uri);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001147 n += scnprintf(buf + n, PAGE_SIZE - n, "? sli = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001148 isr_statistics.sli);
1149 n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n",
1150 isr_statistics.none);
1151 n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n",
1152 isr_statistics.hndl.cnt);
1153
1154 for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) {
1155 i &= ISR_MASK;
1156 intr = isr_statistics.hndl.buf[i];
1157
1158 if (USBi_UI & intr)
1159 n += scnprintf(buf + n, PAGE_SIZE - n, "ui ");
1160 intr &= ~USBi_UI;
1161 if (USBi_UEI & intr)
1162 n += scnprintf(buf + n, PAGE_SIZE - n, "uei ");
1163 intr &= ~USBi_UEI;
1164 if (USBi_PCI & intr)
1165 n += scnprintf(buf + n, PAGE_SIZE - n, "pci ");
1166 intr &= ~USBi_PCI;
1167 if (USBi_URI & intr)
1168 n += scnprintf(buf + n, PAGE_SIZE - n, "uri ");
1169 intr &= ~USBi_URI;
1170 if (USBi_SLI & intr)
1171 n += scnprintf(buf + n, PAGE_SIZE - n, "sli ");
1172 intr &= ~USBi_SLI;
1173 if (intr)
1174 n += scnprintf(buf + n, PAGE_SIZE - n, "??? ");
1175 if (isr_statistics.hndl.buf[i])
1176 n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
1177 }
1178
1179 spin_unlock_irqrestore(udc->lock, flags);
1180
1181 return n;
1182}
1183
1184/**
1185 * store_inters: enable & force or disable an individual interrutps
1186 * (to be used for test purposes only)
1187 *
1188 * Check "device.h" for details
1189 */
1190static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
1191 const char *buf, size_t count)
1192{
1193 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1194 unsigned long flags;
1195 unsigned en, bit;
1196
1197 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1198 if (attr == NULL || buf == NULL) {
1199 dev_err(dev, "[%s] EINVAL\n", __func__);
1200 goto done;
1201 }
1202
1203 if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
1204 dev_err(dev, "<1|0> <bit>: enable|disable interrupt");
1205 goto done;
1206 }
1207
1208 spin_lock_irqsave(udc->lock, flags);
1209 if (en) {
1210 if (hw_intr_force(bit))
1211 dev_err(dev, "invalid bit number\n");
1212 else
1213 isr_statistics.test++;
1214 } else {
1215 if (hw_intr_clear(bit))
1216 dev_err(dev, "invalid bit number\n");
1217 }
1218 spin_unlock_irqrestore(udc->lock, flags);
1219
1220 done:
1221 return count;
1222}
1223static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
1224
1225/**
1226 * show_port_test: reads port test mode
1227 *
1228 * Check "device.h" for details
1229 */
1230static ssize_t show_port_test(struct device *dev,
1231 struct device_attribute *attr, char *buf)
1232{
1233 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1234 unsigned long flags;
1235 unsigned mode;
1236
1237 dbg_trace("[%s] %p\n", __func__, buf);
1238 if (attr == NULL || buf == NULL) {
1239 dev_err(dev, "[%s] EINVAL\n", __func__);
1240 return 0;
1241 }
1242
1243 spin_lock_irqsave(udc->lock, flags);
1244 mode = hw_port_test_get();
1245 spin_unlock_irqrestore(udc->lock, flags);
1246
1247 return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
1248}
1249
1250/**
1251 * store_port_test: writes port test mode
1252 *
1253 * Check "device.h" for details
1254 */
1255static ssize_t store_port_test(struct device *dev,
1256 struct device_attribute *attr,
1257 const char *buf, size_t count)
1258{
1259 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1260 unsigned long flags;
1261 unsigned mode;
1262
1263 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1264 if (attr == NULL || buf == NULL) {
1265 dev_err(dev, "[%s] EINVAL\n", __func__);
1266 goto done;
1267 }
1268
1269 if (sscanf(buf, "%u", &mode) != 1) {
1270 dev_err(dev, "<mode>: set port test mode");
1271 goto done;
1272 }
1273
1274 spin_lock_irqsave(udc->lock, flags);
1275 if (hw_port_test_set(mode))
1276 dev_err(dev, "invalid mode\n");
1277 spin_unlock_irqrestore(udc->lock, flags);
1278
1279 done:
1280 return count;
1281}
1282static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
1283 show_port_test, store_port_test);
1284
1285/**
1286 * show_qheads: DMA contents of all queue heads
1287 *
1288 * Check "device.h" for details
1289 */
1290static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
1291 char *buf)
1292{
1293 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1294 unsigned long flags;
1295 unsigned i, j, n = 0;
1296
1297 dbg_trace("[%s] %p\n", __func__, buf);
1298 if (attr == NULL || buf == NULL) {
1299 dev_err(dev, "[%s] EINVAL\n", __func__);
1300 return 0;
1301 }
1302
1303 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301304 for (i = 0; i < hw_ep_max/2; i++) {
1305 struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i];
1306 struct ci13xxx_ep *mEpTx = &udc->ci13xxx_ep[i + hw_ep_max/2];
David Lopoaa69a802008-11-17 14:14:51 -08001307 n += scnprintf(buf + n, PAGE_SIZE - n,
1308 "EP=%02i: RX=%08X TX=%08X\n",
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301309 i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08001310 for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) {
1311 n += scnprintf(buf + n, PAGE_SIZE - n,
1312 " %04X: %08X %08X\n", j,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301313 *((u32 *)mEpRx->qh.ptr + j),
1314 *((u32 *)mEpTx->qh.ptr + j));
David Lopoaa69a802008-11-17 14:14:51 -08001315 }
1316 }
1317 spin_unlock_irqrestore(udc->lock, flags);
1318
1319 return n;
1320}
1321static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
1322
1323/**
1324 * show_registers: dumps all registers
1325 *
1326 * Check "device.h" for details
1327 */
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001328#define DUMP_ENTRIES 512
David Lopoaa69a802008-11-17 14:14:51 -08001329static ssize_t show_registers(struct device *dev,
1330 struct device_attribute *attr, char *buf)
1331{
1332 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1333 unsigned long flags;
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001334 u32 *dump;
David Lopoaa69a802008-11-17 14:14:51 -08001335 unsigned i, k, n = 0;
1336
1337 dbg_trace("[%s] %p\n", __func__, buf);
1338 if (attr == NULL || buf == NULL) {
1339 dev_err(dev, "[%s] EINVAL\n", __func__);
1340 return 0;
1341 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001342 dump = kmalloc(2048, GFP_KERNEL);
1343 if (dump == NULL)
1344 return -ENOMEM;
David Lopoaa69a802008-11-17 14:14:51 -08001345
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001346 dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
1347 if (!dump) {
1348 dev_err(dev, "%s: out of memory\n", __func__);
1349 return 0;
1350 }
1351
David Lopoaa69a802008-11-17 14:14:51 -08001352 spin_lock_irqsave(udc->lock, flags);
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001353 k = hw_register_read(dump, DUMP_ENTRIES);
David Lopoaa69a802008-11-17 14:14:51 -08001354 spin_unlock_irqrestore(udc->lock, flags);
1355
1356 for (i = 0; i < k; i++) {
1357 n += scnprintf(buf + n, PAGE_SIZE - n,
1358 "reg[0x%04X] = 0x%08X\n",
1359 i * (unsigned)sizeof(u32), dump[i]);
1360 }
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001361 kfree(dump);
David Lopoaa69a802008-11-17 14:14:51 -08001362
1363 return n;
1364}
1365
1366/**
1367 * store_registers: writes value to register address
1368 *
1369 * Check "device.h" for details
1370 */
1371static ssize_t store_registers(struct device *dev,
1372 struct device_attribute *attr,
1373 const char *buf, size_t count)
1374{
1375 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1376 unsigned long addr, data, flags;
1377
1378 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1379 if (attr == NULL || buf == NULL) {
1380 dev_err(dev, "[%s] EINVAL\n", __func__);
1381 goto done;
1382 }
1383
1384 if (sscanf(buf, "%li %li", &addr, &data) != 2) {
1385 dev_err(dev, "<addr> <data>: write data to register address");
1386 goto done;
1387 }
1388
1389 spin_lock_irqsave(udc->lock, flags);
1390 if (hw_register_write(addr, data))
1391 dev_err(dev, "invalid address range\n");
1392 spin_unlock_irqrestore(udc->lock, flags);
1393
1394 done:
1395 return count;
1396}
1397static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
1398 show_registers, store_registers);
1399
1400/**
1401 * show_requests: DMA contents of all requests currently queued (all endpts)
1402 *
1403 * Check "device.h" for details
1404 */
1405static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
1406 char *buf)
1407{
1408 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1409 unsigned long flags;
1410 struct list_head *ptr = NULL;
1411 struct ci13xxx_req *req = NULL;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301412 unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
David Lopoaa69a802008-11-17 14:14:51 -08001413
1414 dbg_trace("[%s] %p\n", __func__, buf);
1415 if (attr == NULL || buf == NULL) {
1416 dev_err(dev, "[%s] EINVAL\n", __func__);
1417 return 0;
1418 }
1419
1420 spin_lock_irqsave(udc->lock, flags);
1421 for (i = 0; i < hw_ep_max; i++)
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301422 list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue)
1423 {
1424 req = list_entry(ptr, struct ci13xxx_req, queue);
David Lopoaa69a802008-11-17 14:14:51 -08001425
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301426 n += scnprintf(buf + n, PAGE_SIZE - n,
1427 "EP=%02i: TD=%08X %s\n",
1428 i % hw_ep_max/2, (u32)req->dma,
1429 ((i < hw_ep_max/2) ? "RX" : "TX"));
1430
1431 for (j = 0; j < qSize; j++)
David Lopoaa69a802008-11-17 14:14:51 -08001432 n += scnprintf(buf + n, PAGE_SIZE - n,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301433 " %04X: %08X\n", j,
1434 *((u32 *)req->ptr + j));
1435 }
David Lopoaa69a802008-11-17 14:14:51 -08001436 spin_unlock_irqrestore(udc->lock, flags);
1437
1438 return n;
1439}
1440static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL);
1441
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001442/* EP# and Direction */
1443static ssize_t prime_ept(struct device *dev,
1444 struct device_attribute *attr,
1445 const char *buf, size_t count)
1446{
1447 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1448 struct ci13xxx_ep *mEp;
1449 unsigned int ep_num, dir;
1450 int n;
1451 struct ci13xxx_req *mReq = NULL;
1452
1453 if (sscanf(buf, "%u %u", &ep_num, &dir) != 2) {
1454 dev_err(dev, "<ep_num> <dir>: prime the ep");
1455 goto done;
1456 }
1457
1458 if (dir)
1459 mEp = &udc->ci13xxx_ep[ep_num + hw_ep_max/2];
1460 else
1461 mEp = &udc->ci13xxx_ep[ep_num];
1462
1463 n = hw_ep_bit(mEp->num, mEp->dir);
1464 mReq = list_entry(mEp->qh.queue.next, struct ci13xxx_req, queue);
1465 mEp->qh.ptr->td.next = mReq->dma;
1466 mEp->qh.ptr->td.token &= ~TD_STATUS;
1467
1468 wmb();
1469
1470 hw_cwrite(CAP_ENDPTPRIME, BIT(n), BIT(n));
1471 while (hw_cread(CAP_ENDPTPRIME, BIT(n)))
1472 cpu_relax();
1473
1474 pr_info("%s: prime:%08x stat:%08x ep#%d dir:%s\n", __func__,
1475 hw_cread(CAP_ENDPTPRIME, ~0),
1476 hw_cread(CAP_ENDPTSTAT, ~0),
1477 mEp->num, mEp->dir ? "IN" : "OUT");
1478done:
1479 return count;
1480
1481}
1482static DEVICE_ATTR(prime, S_IWUSR, NULL, prime_ept);
1483
1484/* EP# and Direction */
1485static ssize_t print_dtds(struct device *dev,
1486 struct device_attribute *attr,
1487 const char *buf, size_t count)
1488{
1489 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1490 struct ci13xxx_ep *mEp;
1491 unsigned int ep_num, dir;
1492 int n;
1493 struct list_head *ptr = NULL;
1494 struct ci13xxx_req *req = NULL;
1495
1496 if (sscanf(buf, "%u %u", &ep_num, &dir) != 2) {
1497 dev_err(dev, "<ep_num> <dir>: to print dtds");
1498 goto done;
1499 }
1500
1501 if (dir)
1502 mEp = &udc->ci13xxx_ep[ep_num + hw_ep_max/2];
1503 else
1504 mEp = &udc->ci13xxx_ep[ep_num];
1505
1506 n = hw_ep_bit(mEp->num, mEp->dir);
Anji jonnala6fb918c2011-10-21 17:54:21 +05301507 pr_info("%s: prime:%08x stat:%08x ep#%d dir:%s"
Vamsi Krishna8d1bbd52012-02-09 21:13:24 -08001508 "dTD_update_fail_count: %lu "
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301509 "mEp->dTD_update_fail_count: %lu"
1510 "mEp->prime_fail_count: %lu\n", __func__,
Anji jonnala6fb918c2011-10-21 17:54:21 +05301511 hw_cread(CAP_ENDPTPRIME, ~0),
1512 hw_cread(CAP_ENDPTSTAT, ~0),
1513 mEp->num, mEp->dir ? "IN" : "OUT",
1514 udc->dTD_update_fail_count,
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301515 mEp->dTD_update_fail_count,
1516 mEp->prime_fail_count);
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001517
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001518 pr_info("QH: cap:%08x cur:%08x next:%08x token:%08x\n",
1519 mEp->qh.ptr->cap, mEp->qh.ptr->curr,
1520 mEp->qh.ptr->td.next, mEp->qh.ptr->td.token);
1521
1522 list_for_each(ptr, &mEp->qh.queue) {
1523 req = list_entry(ptr, struct ci13xxx_req, queue);
1524
1525 pr_info("\treq:%08x next:%08x token:%08x page0:%08x status:%d\n",
1526 req->dma, req->ptr->next, req->ptr->token,
1527 req->ptr->page[0], req->req.status);
1528 }
1529done:
1530 return count;
1531
1532}
1533static DEVICE_ATTR(dtds, S_IWUSR, NULL, print_dtds);
1534
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001535static int ci13xxx_wakeup(struct usb_gadget *_gadget)
1536{
1537 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
1538 unsigned long flags;
1539 int ret = 0;
1540
1541 trace();
1542
1543 spin_lock_irqsave(udc->lock, flags);
1544 if (!udc->remote_wakeup) {
1545 ret = -EOPNOTSUPP;
1546 dbg_trace("remote wakeup feature is not enabled\n");
1547 goto out;
1548 }
Amit Blay725cdeb2012-04-30 14:20:56 +03001549 spin_unlock_irqrestore(udc->lock, flags);
1550
1551 udc->udc_driver->notify_event(udc,
1552 CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT);
1553
1554 if (udc->transceiver)
Steve Mucklef132c6c2012-06-06 18:30:57 -07001555 usb_phy_set_suspend(udc->transceiver, 0);
Amit Blay725cdeb2012-04-30 14:20:56 +03001556
1557 spin_lock_irqsave(udc->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001558 if (!hw_cread(CAP_PORTSC, PORTSC_SUSP)) {
1559 ret = -EINVAL;
1560 dbg_trace("port is not suspended\n");
1561 goto out;
1562 }
1563 hw_cwrite(CAP_PORTSC, PORTSC_FPR, PORTSC_FPR);
1564out:
1565 spin_unlock_irqrestore(udc->lock, flags);
1566 return ret;
1567}
1568
Amit Blayfd075dd2012-06-26 13:12:50 +03001569static void usb_do_remote_wakeup(struct work_struct *w)
1570{
1571 struct ci13xxx *udc = _udc;
Pavankumar Kondeti0679a812012-06-29 10:51:58 +05301572 unsigned long flags;
1573 bool do_wake;
Amit Blayfd075dd2012-06-26 13:12:50 +03001574
Pavankumar Kondeti0679a812012-06-29 10:51:58 +05301575 /*
1576 * This work can not be canceled from interrupt handler. Check
1577 * if wakeup conditions are still met.
1578 */
1579 spin_lock_irqsave(udc->lock, flags);
1580 do_wake = udc->suspended && udc->remote_wakeup;
1581 spin_unlock_irqrestore(udc->lock, flags);
1582
1583 if (do_wake)
1584 ci13xxx_wakeup(&udc->gadget);
Amit Blayfd075dd2012-06-26 13:12:50 +03001585}
1586
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001587static ssize_t usb_remote_wakeup(struct device *dev,
1588 struct device_attribute *attr, const char *buf, size_t count)
1589{
1590 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1591
1592 ci13xxx_wakeup(&udc->gadget);
1593
1594 return count;
1595}
1596static DEVICE_ATTR(wakeup, S_IWUSR, 0, usb_remote_wakeup);
1597
David Lopoaa69a802008-11-17 14:14:51 -08001598/**
1599 * dbg_create_files: initializes the attribute interface
1600 * @dev: device
1601 *
1602 * This function returns an error code
1603 */
1604__maybe_unused static int dbg_create_files(struct device *dev)
1605{
1606 int retval = 0;
1607
1608 if (dev == NULL)
1609 return -EINVAL;
1610 retval = device_create_file(dev, &dev_attr_device);
1611 if (retval)
1612 goto done;
1613 retval = device_create_file(dev, &dev_attr_driver);
1614 if (retval)
1615 goto rm_device;
1616 retval = device_create_file(dev, &dev_attr_events);
1617 if (retval)
1618 goto rm_driver;
1619 retval = device_create_file(dev, &dev_attr_inters);
1620 if (retval)
1621 goto rm_events;
1622 retval = device_create_file(dev, &dev_attr_port_test);
1623 if (retval)
1624 goto rm_inters;
1625 retval = device_create_file(dev, &dev_attr_qheads);
1626 if (retval)
1627 goto rm_port_test;
1628 retval = device_create_file(dev, &dev_attr_registers);
1629 if (retval)
1630 goto rm_qheads;
1631 retval = device_create_file(dev, &dev_attr_requests);
1632 if (retval)
1633 goto rm_registers;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001634 retval = device_create_file(dev, &dev_attr_wakeup);
1635 if (retval)
1636 goto rm_remote_wakeup;
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001637 retval = device_create_file(dev, &dev_attr_prime);
1638 if (retval)
1639 goto rm_prime;
1640 retval = device_create_file(dev, &dev_attr_dtds);
1641 if (retval)
1642 goto rm_dtds;
1643
David Lopoaa69a802008-11-17 14:14:51 -08001644 return 0;
1645
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001646rm_dtds:
1647 device_remove_file(dev, &dev_attr_dtds);
1648rm_prime:
1649 device_remove_file(dev, &dev_attr_prime);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001650rm_remote_wakeup:
1651 device_remove_file(dev, &dev_attr_wakeup);
David Lopoaa69a802008-11-17 14:14:51 -08001652 rm_registers:
1653 device_remove_file(dev, &dev_attr_registers);
1654 rm_qheads:
1655 device_remove_file(dev, &dev_attr_qheads);
1656 rm_port_test:
1657 device_remove_file(dev, &dev_attr_port_test);
1658 rm_inters:
1659 device_remove_file(dev, &dev_attr_inters);
1660 rm_events:
1661 device_remove_file(dev, &dev_attr_events);
1662 rm_driver:
1663 device_remove_file(dev, &dev_attr_driver);
1664 rm_device:
1665 device_remove_file(dev, &dev_attr_device);
1666 done:
1667 return retval;
1668}
1669
1670/**
1671 * dbg_remove_files: destroys the attribute interface
1672 * @dev: device
1673 *
1674 * This function returns an error code
1675 */
1676__maybe_unused static int dbg_remove_files(struct device *dev)
1677{
1678 if (dev == NULL)
1679 return -EINVAL;
1680 device_remove_file(dev, &dev_attr_requests);
1681 device_remove_file(dev, &dev_attr_registers);
1682 device_remove_file(dev, &dev_attr_qheads);
1683 device_remove_file(dev, &dev_attr_port_test);
1684 device_remove_file(dev, &dev_attr_inters);
1685 device_remove_file(dev, &dev_attr_events);
1686 device_remove_file(dev, &dev_attr_driver);
1687 device_remove_file(dev, &dev_attr_device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001688 device_remove_file(dev, &dev_attr_wakeup);
David Lopoaa69a802008-11-17 14:14:51 -08001689 return 0;
1690}
1691
1692/******************************************************************************
1693 * UTIL block
1694 *****************************************************************************/
1695/**
1696 * _usb_addr: calculates endpoint address from direction & number
1697 * @ep: endpoint
1698 */
1699static inline u8 _usb_addr(struct ci13xxx_ep *ep)
1700{
1701 return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num;
1702}
1703
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301704static void ep_prime_timer_func(unsigned long data)
1705{
1706 struct ci13xxx_ep *mEp = (struct ci13xxx_ep *)data;
1707 struct ci13xxx_req *req;
1708 struct list_head *ptr = NULL;
1709 int n = hw_ep_bit(mEp->num, mEp->dir);
1710 unsigned long flags;
1711
1712
1713 spin_lock_irqsave(mEp->lock, flags);
1714 if (!hw_cread(CAP_ENDPTPRIME, BIT(n)))
1715 goto out;
1716
1717 if (list_empty(&mEp->qh.queue))
1718 goto out;
1719
1720 req = list_entry(mEp->qh.queue.next, struct ci13xxx_req, queue);
1721
1722 mb();
1723 if (!(TD_STATUS_ACTIVE & req->ptr->token))
1724 goto out;
1725
1726 mEp->prime_timer_count++;
1727 if (mEp->prime_timer_count == MAX_PRIME_CHECK_RETRY) {
1728 mEp->prime_timer_count = 0;
1729 pr_info("ep%d dir:%s QH:cap:%08x cur:%08x next:%08x tkn:%08x\n",
1730 mEp->num, mEp->dir ? "IN" : "OUT",
1731 mEp->qh.ptr->cap, mEp->qh.ptr->curr,
1732 mEp->qh.ptr->td.next, mEp->qh.ptr->td.token);
1733 list_for_each(ptr, &mEp->qh.queue) {
1734 req = list_entry(ptr, struct ci13xxx_req, queue);
1735 pr_info("\treq:%08xnext:%08xtkn:%08xpage0:%08xsts:%d\n",
1736 req->dma, req->ptr->next,
1737 req->ptr->token, req->ptr->page[0],
1738 req->req.status);
1739 }
1740 dbg_prime_fail(0xFF, "PRIMEF", mEp);
1741 mEp->prime_fail_count++;
1742 } else {
1743 mod_timer(&mEp->prime_timer, EP_PRIME_CHECK_DELAY);
1744 }
1745
1746 spin_unlock_irqrestore(mEp->lock, flags);
1747 return;
1748
1749out:
1750 mEp->prime_timer_count = 0;
1751 spin_unlock_irqrestore(mEp->lock, flags);
1752
1753}
1754
David Lopoaa69a802008-11-17 14:14:51 -08001755/**
1756 * _hardware_queue: configures a request at hardware level
1757 * @gadget: gadget
1758 * @mEp: endpoint
1759 *
1760 * This function returns an error code
1761 */
1762static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1763{
1764 unsigned i;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301765 int ret = 0;
1766 unsigned length = mReq->req.length;
Amit Blayfd075dd2012-06-26 13:12:50 +03001767 struct ci13xxx *udc = _udc;
David Lopoaa69a802008-11-17 14:14:51 -08001768
1769 trace("%p, %p", mEp, mReq);
1770
1771 /* don't queue twice */
1772 if (mReq->req.status == -EALREADY)
1773 return -EALREADY;
1774
David Lopoaa69a802008-11-17 14:14:51 -08001775 mReq->req.status = -EALREADY;
Michael Grzeschik954aad82011-10-10 18:38:06 +02001776 if (length && mReq->req.dma == DMA_ADDR_INVALID) {
David Lopoaa69a802008-11-17 14:14:51 -08001777 mReq->req.dma = \
1778 dma_map_single(mEp->device, mReq->req.buf,
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301779 length, mEp->dir ? DMA_TO_DEVICE :
1780 DMA_FROM_DEVICE);
David Lopoaa69a802008-11-17 14:14:51 -08001781 if (mReq->req.dma == 0)
1782 return -ENOMEM;
1783
1784 mReq->map = 1;
1785 }
1786
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301787 if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) {
1788 mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC,
1789 &mReq->zdma);
1790 if (mReq->zptr == NULL) {
1791 if (mReq->map) {
1792 dma_unmap_single(mEp->device, mReq->req.dma,
1793 length, mEp->dir ? DMA_TO_DEVICE :
1794 DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02001795 mReq->req.dma = DMA_ADDR_INVALID;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301796 mReq->map = 0;
1797 }
1798 return -ENOMEM;
1799 }
1800 memset(mReq->zptr, 0, sizeof(*mReq->zptr));
1801 mReq->zptr->next = TD_TERMINATE;
1802 mReq->zptr->token = TD_STATUS_ACTIVE;
1803 if (!mReq->req.no_interrupt)
1804 mReq->zptr->token |= TD_IOC;
1805 }
David Lopoaa69a802008-11-17 14:14:51 -08001806 /*
1807 * TD configuration
1808 * TODO - handle requests which spawns into several TDs
1809 */
1810 memset(mReq->ptr, 0, sizeof(*mReq->ptr));
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301811 mReq->ptr->token = length << ffs_nr(TD_TOTAL_BYTES);
David Lopoaa69a802008-11-17 14:14:51 -08001812 mReq->ptr->token &= TD_TOTAL_BYTES;
David Lopoaa69a802008-11-17 14:14:51 -08001813 mReq->ptr->token |= TD_STATUS_ACTIVE;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301814 if (mReq->zptr) {
1815 mReq->ptr->next = mReq->zdma;
1816 } else {
1817 mReq->ptr->next = TD_TERMINATE;
1818 if (!mReq->req.no_interrupt)
1819 mReq->ptr->token |= TD_IOC;
1820 }
Ofir Cohena1c2a872011-12-14 10:26:34 +02001821
1822 /* MSM Specific: updating the request as required for
1823 * SPS mode. Enable MSM proprietary DMA engine acording
1824 * to the UDC private data in the request.
1825 */
1826 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
1827 if (mReq->req.udc_priv & MSM_SPS_MODE) {
1828 mReq->ptr->token = TD_STATUS_ACTIVE;
Ido Shayevitzd1cb16c2012-03-28 18:57:47 +02001829 if (mReq->req.udc_priv & MSM_IS_FINITE_TRANSFER)
Ofir Cohena1c2a872011-12-14 10:26:34 +02001830 mReq->ptr->next = TD_TERMINATE;
1831 else
1832 mReq->ptr->next = MSM_ETD_TYPE | mReq->dma;
1833 if (!mReq->req.no_interrupt)
1834 mReq->ptr->token |= MSM_ETD_IOC;
1835 }
Amit Blay522d0362012-06-18 20:56:38 +03001836 mReq->req.dma = 0;
Ofir Cohena1c2a872011-12-14 10:26:34 +02001837 }
1838
David Lopoaa69a802008-11-17 14:14:51 -08001839 mReq->ptr->page[0] = mReq->req.dma;
1840 for (i = 1; i < 5; i++)
1841 mReq->ptr->page[i] =
Artem Leonenko0a313c42010-12-14 23:47:06 -08001842 (mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK;
David Lopoaa69a802008-11-17 14:14:51 -08001843
Amit Blayfd075dd2012-06-26 13:12:50 +03001844 /* Remote Wakeup */
1845 if (udc->suspended) {
1846 if (!udc->remote_wakeup) {
1847 mReq->req.status = -EAGAIN;
1848 dev_dbg(mEp->device, "%s: queue failed (suspend) ept #%d\n",
1849 __func__, mEp->num);
1850 return -EAGAIN;
1851 }
1852 usb_phy_set_suspend(udc->transceiver, 0);
1853 schedule_delayed_work(&udc->rw_work, REMOTE_WAKEUP_DELAY);
1854 }
1855
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301856 if (!list_empty(&mEp->qh.queue)) {
1857 struct ci13xxx_req *mReqPrev;
1858 int n = hw_ep_bit(mEp->num, mEp->dir);
1859 int tmp_stat;
Vijayavardhan Vennapusa397a4532012-07-20 13:18:32 +05301860 ktime_t start, diff;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301861
1862 mReqPrev = list_entry(mEp->qh.queue.prev,
1863 struct ci13xxx_req, queue);
1864 if (mReqPrev->zptr)
1865 mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
1866 else
1867 mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
1868 wmb();
1869 if (hw_cread(CAP_ENDPTPRIME, BIT(n)))
1870 goto done;
Vijayavardhan Vennapusa397a4532012-07-20 13:18:32 +05301871 start = ktime_get();
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301872 do {
1873 hw_cwrite(CAP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
1874 tmp_stat = hw_cread(CAP_ENDPTSTAT, BIT(n));
Vijayavardhan Vennapusa397a4532012-07-20 13:18:32 +05301875 diff = ktime_sub(ktime_get(), start);
1876 /* poll for max. 100ms */
1877 if (ktime_to_ms(diff) > ATDTW_SET_DELAY) {
1878 if (hw_cread(CAP_USBCMD, USBCMD_ATDTW))
1879 break;
1880 printk_ratelimited(KERN_ERR
1881 "%s:queue failed ep#%d %s\n",
1882 __func__, mEp->num, mEp->dir ? "IN" : "OUT");
1883 return -EAGAIN;
1884 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301885 } while (!hw_cread(CAP_USBCMD, USBCMD_ATDTW));
1886 hw_cwrite(CAP_USBCMD, USBCMD_ATDTW, 0);
1887 if (tmp_stat)
1888 goto done;
1889 }
1890
1891 /* QH configuration */
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001892 if (!list_empty(&mEp->qh.queue)) {
1893 struct ci13xxx_req *mReq = \
1894 list_entry(mEp->qh.queue.next,
1895 struct ci13xxx_req, queue);
1896
1897 if (TD_STATUS_ACTIVE & mReq->ptr->token) {
1898 mEp->qh.ptr->td.next = mReq->dma;
1899 mEp->qh.ptr->td.token &= ~TD_STATUS;
1900 goto prime;
1901 }
1902 }
1903
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301904 mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */
Ofir Cohena1c2a872011-12-14 10:26:34 +02001905
1906 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
1907 if (mReq->req.udc_priv & MSM_SPS_MODE) {
1908 mEp->qh.ptr->td.next |= MSM_ETD_TYPE;
1909 i = hw_cread(CAP_ENDPTPIPEID +
1910 mEp->num * sizeof(u32), ~0);
1911 /* Read current value of this EPs pipe id */
1912 i = (mEp->dir == TX) ?
1913 ((i >> MSM_TX_PIPE_ID_OFS) & MSM_PIPE_ID_MASK) :
1914 (i & MSM_PIPE_ID_MASK);
1915 /* If requested pipe id is different from current,
1916 then write it */
1917 if (i != (mReq->req.udc_priv & MSM_PIPE_ID_MASK)) {
1918 if (mEp->dir == TX)
1919 hw_cwrite(
1920 CAP_ENDPTPIPEID +
1921 mEp->num * sizeof(u32),
1922 MSM_PIPE_ID_MASK <<
1923 MSM_TX_PIPE_ID_OFS,
1924 (mReq->req.udc_priv &
1925 MSM_PIPE_ID_MASK)
1926 << MSM_TX_PIPE_ID_OFS);
1927 else
1928 hw_cwrite(
1929 CAP_ENDPTPIPEID +
1930 mEp->num * sizeof(u32),
1931 MSM_PIPE_ID_MASK,
1932 mReq->req.udc_priv &
1933 MSM_PIPE_ID_MASK);
1934 }
1935 }
1936 }
1937
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301938 mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301939 mEp->qh.ptr->cap |= QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08001940
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001941prime:
David Lopoaa69a802008-11-17 14:14:51 -08001942 wmb(); /* synchronize before ep prime */
1943
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301944 ret = hw_ep_prime(mEp->num, mEp->dir,
David Lopoaa69a802008-11-17 14:14:51 -08001945 mEp->type == USB_ENDPOINT_XFER_CONTROL);
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05301946 if (!ret)
1947 mod_timer(&mEp->prime_timer, EP_PRIME_CHECK_DELAY);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301948done:
1949 return ret;
David Lopoaa69a802008-11-17 14:14:51 -08001950}
1951
1952/**
1953 * _hardware_dequeue: handles a request at hardware level
1954 * @gadget: gadget
1955 * @mEp: endpoint
1956 *
1957 * This function returns an error code
1958 */
1959static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1960{
1961 trace("%p, %p", mEp, mReq);
1962
1963 if (mReq->req.status != -EALREADY)
1964 return -EINVAL;
1965
Vijayavardhan Vennapusa590b8ce2011-10-20 02:38:14 +05301966 /* clean speculative fetches on req->ptr->token */
1967 mb();
1968
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301969 if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
1970 return -EBUSY;
1971
Ofir Cohena1c2a872011-12-14 10:26:34 +02001972 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID)
1973 if ((mReq->req.udc_priv & MSM_SPS_MODE) &&
Ido Shayevitzd1cb16c2012-03-28 18:57:47 +02001974 (mReq->req.udc_priv & MSM_IS_FINITE_TRANSFER))
Ofir Cohena1c2a872011-12-14 10:26:34 +02001975 return -EBUSY;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301976 if (mReq->zptr) {
1977 if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
1978 return -EBUSY;
1979 dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
1980 mReq->zptr = NULL;
1981 }
David Lopoaa69a802008-11-17 14:14:51 -08001982
1983 mReq->req.status = 0;
1984
1985 if (mReq->map) {
1986 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
1987 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02001988 mReq->req.dma = DMA_ADDR_INVALID;
David Lopoaa69a802008-11-17 14:14:51 -08001989 mReq->map = 0;
1990 }
1991
1992 mReq->req.status = mReq->ptr->token & TD_STATUS;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301993 if ((TD_STATUS_HALTED & mReq->req.status) != 0)
David Lopoaa69a802008-11-17 14:14:51 -08001994 mReq->req.status = -1;
1995 else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0)
1996 mReq->req.status = -1;
1997 else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0)
1998 mReq->req.status = -1;
1999
2000 mReq->req.actual = mReq->ptr->token & TD_TOTAL_BYTES;
2001 mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES);
2002 mReq->req.actual = mReq->req.length - mReq->req.actual;
2003 mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual;
2004
2005 return mReq->req.actual;
2006}
2007
2008/**
2009 * _ep_nuke: dequeues all endpoint requests
2010 * @mEp: endpoint
2011 *
2012 * This function returns an error code
2013 * Caller must hold lock
2014 */
2015static int _ep_nuke(struct ci13xxx_ep *mEp)
2016__releases(mEp->lock)
2017__acquires(mEp->lock)
2018{
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05302019 struct ci13xxx_ep *mEpTemp = mEp;
Ofir Cohena1c2a872011-12-14 10:26:34 +02002020 unsigned val;
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05302021
David Lopoaa69a802008-11-17 14:14:51 -08002022 trace("%p", mEp);
2023
2024 if (mEp == NULL)
2025 return -EINVAL;
2026
2027 hw_ep_flush(mEp->num, mEp->dir);
2028
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302029 while (!list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -08002030
2031 /* pop oldest request */
2032 struct ci13xxx_req *mReq = \
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302033 list_entry(mEp->qh.queue.next,
David Lopoaa69a802008-11-17 14:14:51 -08002034 struct ci13xxx_req, queue);
2035 list_del_init(&mReq->queue);
Ofir Cohena1c2a872011-12-14 10:26:34 +02002036
2037 /* MSM Specific: Clear end point proprietary register */
2038 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
2039 if (mReq->req.udc_priv & MSM_SPS_MODE) {
2040 val = hw_cread(CAP_ENDPTPIPEID +
2041 mEp->num * sizeof(u32),
2042 ~0);
2043
2044 if (val != MSM_EP_PIPE_ID_RESET_VAL)
2045 hw_cwrite(
2046 CAP_ENDPTPIPEID +
2047 mEp->num * sizeof(u32),
2048 ~0, MSM_EP_PIPE_ID_RESET_VAL);
2049 }
2050 }
David Lopoaa69a802008-11-17 14:14:51 -08002051 mReq->req.status = -ESHUTDOWN;
2052
Anji jonnalaea7bbc32011-12-26 16:39:53 +05302053 if (mReq->map) {
2054 dma_unmap_single(mEp->device, mReq->req.dma,
2055 mReq->req.length,
2056 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Pavankumar Kondeti3c9a1d52012-06-06 09:56:03 +05302057 mReq->req.dma = DMA_ADDR_INVALID;
Anji jonnalaea7bbc32011-12-26 16:39:53 +05302058 mReq->map = 0;
2059 }
2060
Artem Leonenko7c25a822010-12-14 23:46:55 -08002061 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08002062 spin_unlock(mEp->lock);
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05302063 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
2064 mReq->req.length)
2065 mEpTemp = &_udc->ep0in;
2066 mReq->req.complete(&mEpTemp->ep, &mReq->req);
Mayank Rana0c1b8b22012-07-04 16:17:38 +05302067 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2068 mReq->req.complete = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002069 spin_lock(mEp->lock);
2070 }
2071 }
2072 return 0;
2073}
2074
2075/**
2076 * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
2077 * @gadget: gadget
2078 *
2079 * This function returns an error code
David Lopoaa69a802008-11-17 14:14:51 -08002080 */
2081static int _gadget_stop_activity(struct usb_gadget *gadget)
David Lopoaa69a802008-11-17 14:14:51 -08002082{
2083 struct usb_ep *ep;
2084 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302085 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -08002086
2087 trace("%p", gadget);
2088
2089 if (gadget == NULL)
2090 return -EINVAL;
2091
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302092 spin_lock_irqsave(udc->lock, flags);
2093 udc->gadget.speed = USB_SPEED_UNKNOWN;
2094 udc->remote_wakeup = 0;
2095 udc->suspended = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002096 udc->configured = 0;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302097 spin_unlock_irqrestore(udc->lock, flags);
2098
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302099 gadget->b_hnp_enable = 0;
2100 gadget->a_hnp_support = 0;
2101 gadget->host_request = 0;
2102 gadget->otg_srp_reqd = 0;
2103
David Lopoaa69a802008-11-17 14:14:51 -08002104 /* flush all endpoints */
2105 gadget_for_each_ep(ep, gadget) {
2106 usb_ep_fifo_flush(ep);
2107 }
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302108 usb_ep_fifo_flush(&udc->ep0out.ep);
2109 usb_ep_fifo_flush(&udc->ep0in.ep);
David Lopoaa69a802008-11-17 14:14:51 -08002110
2111 udc->driver->disconnect(gadget);
2112
2113 /* make sure to disable all endpoints */
2114 gadget_for_each_ep(ep, gadget) {
2115 usb_ep_disable(ep);
2116 }
David Lopoaa69a802008-11-17 14:14:51 -08002117
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302118 if (udc->status != NULL) {
2119 usb_ep_free_request(&udc->ep0in.ep, udc->status);
2120 udc->status = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002121 }
2122
David Lopoaa69a802008-11-17 14:14:51 -08002123 return 0;
2124}
2125
2126/******************************************************************************
2127 * ISR block
2128 *****************************************************************************/
2129/**
2130 * isr_reset_handler: USB reset interrupt handler
2131 * @udc: UDC device
2132 *
2133 * This function resets USB engine after a bus reset occurred
2134 */
2135static void isr_reset_handler(struct ci13xxx *udc)
2136__releases(udc->lock)
2137__acquires(udc->lock)
2138{
David Lopoaa69a802008-11-17 14:14:51 -08002139 int retval;
2140
2141 trace("%p", udc);
2142
2143 if (udc == NULL) {
2144 err("EINVAL");
2145 return;
2146 }
2147
2148 dbg_event(0xFF, "BUS RST", 0);
2149
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302150 spin_unlock(udc->lock);
Anji jonnala8bbde012011-10-28 14:17:25 +05302151
Ido Shayevitz16cd0982012-08-27 20:36:43 +03002152 if (udc->suspended) {
2153 if (udc->udc_driver->notify_event)
2154 udc->udc_driver->notify_event(udc,
2155 CI13XXX_CONTROLLER_RESUME_EVENT);
2156 if (udc->transceiver)
2157 usb_phy_set_suspend(udc->transceiver, 0);
2158 udc->driver->resume(&udc->gadget);
2159 udc->suspended = 0;
2160 }
2161
Anji jonnala8bbde012011-10-28 14:17:25 +05302162 /*stop charging upon reset */
2163 if (udc->transceiver)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002164 usb_phy_set_power(udc->transceiver, 0);
Anji jonnala8bbde012011-10-28 14:17:25 +05302165
David Lopoaa69a802008-11-17 14:14:51 -08002166 retval = _gadget_stop_activity(&udc->gadget);
2167 if (retval)
2168 goto done;
2169
2170 retval = hw_usb_reset();
2171 if (retval)
2172 goto done;
2173
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302174 udc->status = usb_ep_alloc_request(&udc->ep0in.ep, GFP_ATOMIC);
2175 if (udc->status == NULL)
2176 retval = -ENOMEM;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302177
David Lopoaa69a802008-11-17 14:14:51 -08002178 spin_lock(udc->lock);
2179
2180 done:
2181 if (retval)
2182 err("error: %i", retval);
2183}
2184
2185/**
Amit Blay6fa647a2012-05-24 14:12:08 +03002186 * isr_resume_handler: USB PCI interrupt handler
2187 * @udc: UDC device
2188 *
2189 */
2190static void isr_resume_handler(struct ci13xxx *udc)
2191{
2192 udc->gadget.speed = hw_port_is_high_speed() ?
2193 USB_SPEED_HIGH : USB_SPEED_FULL;
2194 if (udc->suspended) {
2195 spin_unlock(udc->lock);
Amit Blay9b033682012-05-24 16:59:23 +03002196 if (udc->udc_driver->notify_event)
2197 udc->udc_driver->notify_event(udc,
2198 CI13XXX_CONTROLLER_RESUME_EVENT);
Amit Blay6fa647a2012-05-24 14:12:08 +03002199 if (udc->transceiver)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002200 usb_phy_set_suspend(udc->transceiver, 0);
Amit Blay6fa647a2012-05-24 14:12:08 +03002201 udc->driver->resume(&udc->gadget);
2202 spin_lock(udc->lock);
2203 udc->suspended = 0;
2204 }
2205}
2206
2207/**
2208 * isr_resume_handler: USB SLI interrupt handler
2209 * @udc: UDC device
2210 *
2211 */
2212static void isr_suspend_handler(struct ci13xxx *udc)
2213{
2214 if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
2215 udc->vbus_active) {
2216 if (udc->suspended == 0) {
2217 spin_unlock(udc->lock);
2218 udc->driver->suspend(&udc->gadget);
2219 if (udc->udc_driver->notify_event)
2220 udc->udc_driver->notify_event(udc,
2221 CI13XXX_CONTROLLER_SUSPEND_EVENT);
2222 if (udc->transceiver)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002223 usb_phy_set_suspend(udc->transceiver, 1);
Amit Blay6fa647a2012-05-24 14:12:08 +03002224 spin_lock(udc->lock);
2225 udc->suspended = 1;
2226 }
2227 }
2228}
2229
2230/**
David Lopoaa69a802008-11-17 14:14:51 -08002231 * isr_get_status_complete: get_status request complete function
2232 * @ep: endpoint
2233 * @req: request handled
2234 *
2235 * Caller must release lock
2236 */
2237static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
2238{
2239 trace("%p, %p", ep, req);
2240
2241 if (ep == NULL || req == NULL) {
2242 err("EINVAL");
2243 return;
2244 }
2245
2246 kfree(req->buf);
2247 usb_ep_free_request(ep, req);
2248}
2249
2250/**
2251 * isr_get_status_response: get_status request response
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302252 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08002253 * @setup: setup request packet
2254 *
2255 * This function returns an error code
2256 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302257static int isr_get_status_response(struct ci13xxx *udc,
David Lopoaa69a802008-11-17 14:14:51 -08002258 struct usb_ctrlrequest *setup)
2259__releases(mEp->lock)
2260__acquires(mEp->lock)
2261{
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302262 struct ci13xxx_ep *mEp = &udc->ep0in;
David Lopoaa69a802008-11-17 14:14:51 -08002263 struct usb_request *req = NULL;
2264 gfp_t gfp_flags = GFP_ATOMIC;
2265 int dir, num, retval;
2266
2267 trace("%p, %p", mEp, setup);
2268
2269 if (mEp == NULL || setup == NULL)
2270 return -EINVAL;
2271
2272 spin_unlock(mEp->lock);
2273 req = usb_ep_alloc_request(&mEp->ep, gfp_flags);
2274 spin_lock(mEp->lock);
2275 if (req == NULL)
2276 return -ENOMEM;
2277
2278 req->complete = isr_get_status_complete;
2279 req->length = 2;
2280 req->buf = kzalloc(req->length, gfp_flags);
2281 if (req->buf == NULL) {
2282 retval = -ENOMEM;
2283 goto err_free_req;
2284 }
2285
2286 if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302287 if (setup->wIndex == OTG_STATUS_SELECTOR) {
2288 *((u8 *)req->buf) = _udc->gadget.host_request <<
2289 HOST_REQUEST_FLAG;
2290 req->length = 1;
2291 } else {
2292 /* Assume that device is bus powered for now. */
2293 *((u16 *)req->buf) = _udc->remote_wakeup << 1;
2294 }
2295 /* TODO: D1 - Remote Wakeup; D0 - Self Powered */
David Lopoaa69a802008-11-17 14:14:51 -08002296 retval = 0;
2297 } else if ((setup->bRequestType & USB_RECIP_MASK) \
2298 == USB_RECIP_ENDPOINT) {
2299 dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
2300 TX : RX;
2301 num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK;
2302 *((u16 *)req->buf) = hw_ep_get_halt(num, dir);
2303 }
2304 /* else do nothing; reserved for future use */
2305
2306 spin_unlock(mEp->lock);
2307 retval = usb_ep_queue(&mEp->ep, req, gfp_flags);
2308 spin_lock(mEp->lock);
2309 if (retval)
2310 goto err_free_buf;
2311
2312 return 0;
2313
2314 err_free_buf:
2315 kfree(req->buf);
2316 err_free_req:
2317 spin_unlock(mEp->lock);
2318 usb_ep_free_request(&mEp->ep, req);
2319 spin_lock(mEp->lock);
2320 return retval;
2321}
2322
2323/**
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302324 * isr_setup_status_complete: setup_status request complete function
2325 * @ep: endpoint
2326 * @req: request handled
2327 *
2328 * Caller must release lock. Put the port in test mode if test mode
2329 * feature is selected.
2330 */
2331static void
2332isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
2333{
2334 struct ci13xxx *udc = req->context;
2335 unsigned long flags;
2336
2337 trace("%p, %p", ep, req);
2338
2339 spin_lock_irqsave(udc->lock, flags);
2340 if (udc->test_mode)
2341 hw_port_test_set(udc->test_mode);
2342 spin_unlock_irqrestore(udc->lock, flags);
2343}
2344
2345/**
David Lopoaa69a802008-11-17 14:14:51 -08002346 * isr_setup_status_phase: queues the status phase of a setup transation
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302347 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08002348 *
2349 * This function returns an error code
2350 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302351static int isr_setup_status_phase(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -08002352__releases(mEp->lock)
2353__acquires(mEp->lock)
2354{
2355 int retval;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302356 struct ci13xxx_ep *mEp;
David Lopoaa69a802008-11-17 14:14:51 -08002357
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302358 trace("%p", udc);
David Lopoaa69a802008-11-17 14:14:51 -08002359
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302360 mEp = (udc->ep0_dir == TX) ? &udc->ep0out : &udc->ep0in;
Vijayavardhan Vennapusa28f14ee2012-06-07 16:12:49 +05302361 if (udc->status) {
2362 udc->status->context = udc;
2363 udc->status->complete = isr_setup_status_complete;
2364 } else
2365 return -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -08002366
2367 spin_unlock(mEp->lock);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302368 retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
David Lopoaa69a802008-11-17 14:14:51 -08002369 spin_lock(mEp->lock);
2370
2371 return retval;
2372}
2373
2374/**
2375 * isr_tr_complete_low: transaction complete low level handler
2376 * @mEp: endpoint
2377 *
2378 * This function returns an error code
2379 * Caller must hold lock
2380 */
2381static int isr_tr_complete_low(struct ci13xxx_ep *mEp)
2382__releases(mEp->lock)
2383__acquires(mEp->lock)
2384{
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302385 struct ci13xxx_req *mReq, *mReqTemp;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302386 struct ci13xxx_ep *mEpTemp = mEp;
Pavankumar Kondeti986b11b2011-05-02 11:56:29 +05302387 int uninitialized_var(retval);
Anji jonnala6fb918c2011-10-21 17:54:21 +05302388 int req_dequeue = 1;
2389 struct ci13xxx *udc = _udc;
David Lopoaa69a802008-11-17 14:14:51 -08002390
2391 trace("%p", mEp);
2392
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302393 if (list_empty(&mEp->qh.queue))
Anji jonnala6fb918c2011-10-21 17:54:21 +05302394 return 0;
David Lopoaa69a802008-11-17 14:14:51 -08002395
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05302396 del_timer(&mEp->prime_timer);
2397 mEp->prime_timer_count = 0;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302398 list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,
2399 queue) {
Anji jonnala6fb918c2011-10-21 17:54:21 +05302400dequeue:
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302401 retval = _hardware_dequeue(mEp, mReq);
Anji jonnala6fb918c2011-10-21 17:54:21 +05302402 if (retval < 0) {
2403 /*
2404 * FIXME: don't know exact delay
2405 * required for HW to update dTD status
2406 * bits. This is a temporary workaround till
2407 * HW designers come back on this.
2408 */
2409 if (retval == -EBUSY && req_dequeue && mEp->dir == 0) {
2410 req_dequeue = 0;
2411 udc->dTD_update_fail_count++;
2412 mEp->dTD_update_fail_count++;
2413 udelay(10);
2414 goto dequeue;
2415 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302416 break;
Anji jonnala6fb918c2011-10-21 17:54:21 +05302417 }
2418 req_dequeue = 0;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302419 list_del_init(&mReq->queue);
2420 dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
2421 if (mReq->req.complete != NULL) {
2422 spin_unlock(mEp->lock);
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302423 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
2424 mReq->req.length)
2425 mEpTemp = &_udc->ep0in;
2426 mReq->req.complete(&mEpTemp->ep, &mReq->req);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302427 spin_lock(mEp->lock);
2428 }
2429 }
David Lopoaa69a802008-11-17 14:14:51 -08002430
Pavankumar Kondetief907482011-05-02 11:56:27 +05302431 if (retval == -EBUSY)
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302432 retval = 0;
2433 if (retval < 0)
David Lopoaa69a802008-11-17 14:14:51 -08002434 dbg_event(_usb_addr(mEp), "DONE", retval);
David Lopoaa69a802008-11-17 14:14:51 -08002435
David Lopoaa69a802008-11-17 14:14:51 -08002436 return retval;
2437}
2438
2439/**
2440 * isr_tr_complete_handler: transaction complete interrupt handler
2441 * @udc: UDC descriptor
2442 *
2443 * This function handles traffic events
2444 */
2445static void isr_tr_complete_handler(struct ci13xxx *udc)
2446__releases(udc->lock)
2447__acquires(udc->lock)
2448{
2449 unsigned i;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302450 u8 tmode = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002451
2452 trace("%p", udc);
2453
2454 if (udc == NULL) {
2455 err("EINVAL");
2456 return;
2457 }
2458
2459 for (i = 0; i < hw_ep_max; i++) {
2460 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302461 int type, num, dir, err = -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -08002462 struct usb_ctrlrequest req;
2463
David Lopoaa69a802008-11-17 14:14:51 -08002464 if (mEp->desc == NULL)
2465 continue; /* not configured */
2466
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302467 if (hw_test_and_clear_complete(i)) {
David Lopoaa69a802008-11-17 14:14:51 -08002468 err = isr_tr_complete_low(mEp);
2469 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
2470 if (err > 0) /* needs status phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302471 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002472 if (err < 0) {
2473 dbg_event(_usb_addr(mEp),
2474 "ERROR", err);
2475 spin_unlock(udc->lock);
2476 if (usb_ep_set_halt(&mEp->ep))
2477 err("error: ep_set_halt");
2478 spin_lock(udc->lock);
2479 }
2480 }
2481 }
2482
2483 if (mEp->type != USB_ENDPOINT_XFER_CONTROL ||
2484 !hw_test_and_clear_setup_status(i))
2485 continue;
2486
2487 if (i != 0) {
2488 warn("ctrl traffic received at endpoint");
2489 continue;
2490 }
2491
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302492 /*
2493 * Flush data and handshake transactions of previous
2494 * setup packet.
2495 */
2496 _ep_nuke(&udc->ep0out);
2497 _ep_nuke(&udc->ep0in);
2498
David Lopoaa69a802008-11-17 14:14:51 -08002499 /* read_setup_packet */
2500 do {
2501 hw_test_and_set_setup_guard();
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302502 memcpy(&req, &mEp->qh.ptr->setup, sizeof(req));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002503 /* Ensure buffer is read before acknowledging to h/w */
2504 mb();
David Lopoaa69a802008-11-17 14:14:51 -08002505 } while (!hw_test_and_clear_setup_guard());
2506
2507 type = req.bRequestType;
2508
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302509 udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
David Lopoaa69a802008-11-17 14:14:51 -08002510
2511 dbg_setup(_usb_addr(mEp), &req);
2512
2513 switch (req.bRequest) {
2514 case USB_REQ_CLEAR_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302515 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
2516 le16_to_cpu(req.wValue) ==
2517 USB_ENDPOINT_HALT) {
2518 if (req.wLength != 0)
David Lopoaa69a802008-11-17 14:14:51 -08002519 break;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302520 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302521 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302522 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302523 if (dir) /* TX */
2524 num += hw_ep_max/2;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302525 if (!udc->ci13xxx_ep[num].wedge) {
2526 spin_unlock(udc->lock);
2527 err = usb_ep_clear_halt(
2528 &udc->ci13xxx_ep[num].ep);
2529 spin_lock(udc->lock);
2530 if (err)
2531 break;
2532 }
2533 err = isr_setup_status_phase(udc);
2534 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
2535 le16_to_cpu(req.wValue) ==
2536 USB_DEVICE_REMOTE_WAKEUP) {
2537 if (req.wLength != 0)
2538 break;
2539 udc->remote_wakeup = 0;
2540 err = isr_setup_status_phase(udc);
2541 } else {
2542 goto delegate;
David Lopoaa69a802008-11-17 14:14:51 -08002543 }
David Lopoaa69a802008-11-17 14:14:51 -08002544 break;
2545 case USB_REQ_GET_STATUS:
2546 if (type != (USB_DIR_IN|USB_RECIP_DEVICE) &&
2547 type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
2548 type != (USB_DIR_IN|USB_RECIP_INTERFACE))
2549 goto delegate;
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302550 if (le16_to_cpu(req.wValue) != 0)
David Lopoaa69a802008-11-17 14:14:51 -08002551 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302552 err = isr_get_status_response(udc, &req);
David Lopoaa69a802008-11-17 14:14:51 -08002553 break;
2554 case USB_REQ_SET_ADDRESS:
2555 if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
2556 goto delegate;
2557 if (le16_to_cpu(req.wLength) != 0 ||
2558 le16_to_cpu(req.wIndex) != 0)
2559 break;
2560 err = hw_usb_set_address((u8)le16_to_cpu(req.wValue));
2561 if (err)
2562 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302563 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002564 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002565 case USB_REQ_SET_CONFIGURATION:
2566 if (type == (USB_DIR_OUT|USB_TYPE_STANDARD))
2567 udc->configured = !!req.wValue;
2568 goto delegate;
David Lopoaa69a802008-11-17 14:14:51 -08002569 case USB_REQ_SET_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302570 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
2571 le16_to_cpu(req.wValue) ==
2572 USB_ENDPOINT_HALT) {
2573 if (req.wLength != 0)
2574 break;
2575 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302576 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302577 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302578 if (dir) /* TX */
2579 num += hw_ep_max/2;
David Lopoaa69a802008-11-17 14:14:51 -08002580
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302581 spin_unlock(udc->lock);
2582 err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
2583 spin_lock(udc->lock);
2584 if (!err)
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302585 isr_setup_status_phase(udc);
2586 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302587 if (req.wLength != 0)
2588 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302589 switch (le16_to_cpu(req.wValue)) {
2590 case USB_DEVICE_REMOTE_WAKEUP:
2591 udc->remote_wakeup = 1;
2592 err = isr_setup_status_phase(udc);
2593 break;
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302594 case USB_DEVICE_B_HNP_ENABLE:
2595 udc->gadget.b_hnp_enable = 1;
2596 err = isr_setup_status_phase(udc);
2597 break;
2598 case USB_DEVICE_A_HNP_SUPPORT:
2599 udc->gadget.a_hnp_support = 1;
2600 err = isr_setup_status_phase(udc);
2601 break;
2602 case USB_DEVICE_A_ALT_HNP_SUPPORT:
2603 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302604 case USB_DEVICE_TEST_MODE:
2605 tmode = le16_to_cpu(req.wIndex) >> 8;
2606 switch (tmode) {
2607 case TEST_J:
2608 case TEST_K:
2609 case TEST_SE0_NAK:
2610 case TEST_PACKET:
2611 case TEST_FORCE_EN:
2612 udc->test_mode = tmode;
2613 err = isr_setup_status_phase(
2614 udc);
2615 break;
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302616 case TEST_OTG_SRP_REQD:
2617 udc->gadget.otg_srp_reqd = 1;
2618 err = isr_setup_status_phase(
2619 udc);
2620 break;
2621 case TEST_OTG_HNP_REQD:
2622 udc->gadget.host_request = 1;
2623 err = isr_setup_status_phase(
2624 udc);
2625 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302626 default:
2627 break;
2628 }
2629 default:
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05302630 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302631 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302632 } else {
2633 goto delegate;
2634 }
David Lopoaa69a802008-11-17 14:14:51 -08002635 break;
2636 default:
2637delegate:
2638 if (req.wLength == 0) /* no data phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302639 udc->ep0_dir = TX;
David Lopoaa69a802008-11-17 14:14:51 -08002640
2641 spin_unlock(udc->lock);
2642 err = udc->driver->setup(&udc->gadget, &req);
2643 spin_lock(udc->lock);
2644 break;
2645 }
2646
2647 if (err < 0) {
2648 dbg_event(_usb_addr(mEp), "ERROR", err);
2649
2650 spin_unlock(udc->lock);
2651 if (usb_ep_set_halt(&mEp->ep))
2652 err("error: ep_set_halt");
2653 spin_lock(udc->lock);
2654 }
2655 }
2656}
2657
2658/******************************************************************************
2659 * ENDPT block
2660 *****************************************************************************/
2661/**
2662 * ep_enable: configure endpoint, making it usable
2663 *
2664 * Check usb_ep_enable() at "usb_gadget.h" for details
2665 */
2666static int ep_enable(struct usb_ep *ep,
2667 const struct usb_endpoint_descriptor *desc)
2668{
2669 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302670 int retval = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002671 unsigned long flags;
2672
Anna Perel432367a2012-09-20 10:55:32 +03002673 trace("ep = %p, desc = %p", ep, desc);
David Lopoaa69a802008-11-17 14:14:51 -08002674
2675 if (ep == NULL || desc == NULL)
2676 return -EINVAL;
2677
2678 spin_lock_irqsave(mEp->lock, flags);
2679
2680 /* only internal SW should enable ctrl endpts */
2681
2682 mEp->desc = desc;
2683
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302684 if (!list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08002685 warn("enabling a non-empty endpoint!");
2686
Matthias Kaehlcke15739bb2009-04-15 22:28:41 +02002687 mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX;
2688 mEp->num = usb_endpoint_num(desc);
2689 mEp->type = usb_endpoint_type(desc);
David Lopoaa69a802008-11-17 14:14:51 -08002690
Kuninori Morimoto29cc8892011-08-23 03:12:03 -07002691 mEp->ep.maxpacket = usb_endpoint_maxp(desc);
David Lopoaa69a802008-11-17 14:14:51 -08002692
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302693 dbg_event(_usb_addr(mEp), "ENABLE", 0);
David Lopoaa69a802008-11-17 14:14:51 -08002694
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302695 mEp->qh.ptr->cap = 0;
David Lopof23e6492009-04-16 14:35:24 -07002696
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302697 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2698 mEp->qh.ptr->cap |= QH_IOS;
Anna Perel432367a2012-09-20 10:55:32 +03002699 else if (mEp->type == USB_ENDPOINT_XFER_ISOC) {
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302700 mEp->qh.ptr->cap &= ~QH_MULT;
Anna Perel432367a2012-09-20 10:55:32 +03002701 mEp->qh.ptr->cap |= BIT(30);
2702 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002703 mEp->qh.ptr->cap |= QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08002704
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302705 mEp->qh.ptr->cap |=
2706 (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
2707 mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */
David Lopoaa69a802008-11-17 14:14:51 -08002708
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002709 /* complete all the updates to ept->head before enabling endpoint*/
2710 mb();
2711
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302712 /*
2713 * Enable endpoints in the HW other than ep0 as ep0
2714 * is always enabled
2715 */
2716 if (mEp->num)
2717 retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type);
David Lopoaa69a802008-11-17 14:14:51 -08002718
2719 spin_unlock_irqrestore(mEp->lock, flags);
2720 return retval;
2721}
2722
2723/**
2724 * ep_disable: endpoint is no longer usable
2725 *
2726 * Check usb_ep_disable() at "usb_gadget.h" for details
2727 */
2728static int ep_disable(struct usb_ep *ep)
2729{
2730 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2731 int direction, retval = 0;
2732 unsigned long flags;
2733
2734 trace("%p", ep);
2735
2736 if (ep == NULL)
2737 return -EINVAL;
2738 else if (mEp->desc == NULL)
2739 return -EBUSY;
2740
2741 spin_lock_irqsave(mEp->lock, flags);
2742
2743 /* only internal SW should disable ctrl endpts */
2744
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05302745 del_timer(&mEp->prime_timer);
2746 mEp->prime_timer_count = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002747 direction = mEp->dir;
2748 do {
2749 dbg_event(_usb_addr(mEp), "DISABLE", 0);
2750
2751 retval |= _ep_nuke(mEp);
2752 retval |= hw_ep_disable(mEp->num, mEp->dir);
2753
2754 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2755 mEp->dir = (mEp->dir == TX) ? RX : TX;
2756
2757 } while (mEp->dir != direction);
2758
2759 mEp->desc = NULL;
Ido Shayevitzf9c56cd2012-02-08 13:56:48 +02002760 mEp->ep.desc = NULL;
Hemant Kumarca8fa3f2012-09-27 16:42:36 -07002761 mEp->ep.maxpacket = USHRT_MAX;
David Lopoaa69a802008-11-17 14:14:51 -08002762
2763 spin_unlock_irqrestore(mEp->lock, flags);
2764 return retval;
2765}
2766
2767/**
2768 * ep_alloc_request: allocate a request object to use with this endpoint
2769 *
2770 * Check usb_ep_alloc_request() at "usb_gadget.h" for details
2771 */
2772static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
2773{
2774 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2775 struct ci13xxx_req *mReq = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002776
2777 trace("%p, %i", ep, gfp_flags);
2778
2779 if (ep == NULL) {
2780 err("EINVAL");
2781 return NULL;
2782 }
2783
David Lopoaa69a802008-11-17 14:14:51 -08002784 mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
2785 if (mReq != NULL) {
2786 INIT_LIST_HEAD(&mReq->queue);
Michael Grzeschik954aad82011-10-10 18:38:06 +02002787 mReq->req.dma = DMA_ADDR_INVALID;
David Lopoaa69a802008-11-17 14:14:51 -08002788
2789 mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,
2790 &mReq->dma);
2791 if (mReq->ptr == NULL) {
2792 kfree(mReq);
2793 mReq = NULL;
2794 }
2795 }
2796
2797 dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
2798
David Lopoaa69a802008-11-17 14:14:51 -08002799 return (mReq == NULL) ? NULL : &mReq->req;
2800}
2801
2802/**
2803 * ep_free_request: frees a request object
2804 *
2805 * Check usb_ep_free_request() at "usb_gadget.h" for details
2806 */
2807static void ep_free_request(struct usb_ep *ep, struct usb_request *req)
2808{
2809 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2810 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2811 unsigned long flags;
2812
2813 trace("%p, %p", ep, req);
2814
2815 if (ep == NULL || req == NULL) {
2816 err("EINVAL");
2817 return;
2818 } else if (!list_empty(&mReq->queue)) {
2819 err("EBUSY");
2820 return;
2821 }
2822
2823 spin_lock_irqsave(mEp->lock, flags);
2824
2825 if (mReq->ptr)
2826 dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma);
2827 kfree(mReq);
2828
2829 dbg_event(_usb_addr(mEp), "FREE", 0);
2830
2831 spin_unlock_irqrestore(mEp->lock, flags);
2832}
2833
2834/**
2835 * ep_queue: queues (submits) an I/O request to an endpoint
2836 *
2837 * Check usb_ep_queue()* at usb_gadget.h" for details
2838 */
2839static int ep_queue(struct usb_ep *ep, struct usb_request *req,
2840 gfp_t __maybe_unused gfp_flags)
2841{
2842 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2843 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2844 int retval = 0;
2845 unsigned long flags;
Anji jonnala6c174d42011-07-13 13:01:47 +05302846 struct ci13xxx *udc = _udc;
David Lopoaa69a802008-11-17 14:14:51 -08002847
2848 trace("%p, %p, %X", ep, req, gfp_flags);
2849
2850 if (ep == NULL || req == NULL || mEp->desc == NULL)
2851 return -EINVAL;
2852
2853 spin_lock_irqsave(mEp->lock, flags);
2854
Anji jonnala6c174d42011-07-13 13:01:47 +05302855 if (!udc->configured && mEp->type !=
2856 USB_ENDPOINT_XFER_CONTROL) {
2857 spin_unlock_irqrestore(mEp->lock, flags);
2858 trace("usb is not configured"
2859 "ept #%d, ept name#%s\n",
2860 mEp->num, mEp->ep.name);
2861 return -ESHUTDOWN;
2862 }
2863
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302864 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
2865 if (req->length)
2866 mEp = (_udc->ep0_dir == RX) ?
2867 &_udc->ep0out : &_udc->ep0in;
2868 if (!list_empty(&mEp->qh.queue)) {
2869 _ep_nuke(mEp);
2870 retval = -EOVERFLOW;
2871 warn("endpoint ctrl %X nuked", _usb_addr(mEp));
2872 }
David Lopoaa69a802008-11-17 14:14:51 -08002873 }
2874
2875 /* first nuke then test link, e.g. previous status has not sent */
2876 if (!list_empty(&mReq->queue)) {
2877 retval = -EBUSY;
2878 err("request already in queue");
2879 goto done;
2880 }
2881
Artem Leonenko0a313c42010-12-14 23:47:06 -08002882 if (req->length > (4 * CI13XXX_PAGE_SIZE)) {
2883 req->length = (4 * CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08002884 retval = -EMSGSIZE;
2885 warn("request length truncated");
2886 }
2887
2888 dbg_queue(_usb_addr(mEp), req, retval);
2889
2890 /* push request */
2891 mReq->req.status = -EINPROGRESS;
2892 mReq->req.actual = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002893
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302894 retval = _hardware_enqueue(mEp, mReq);
Artem Leonenkod9bb9c12010-12-14 23:45:50 -08002895
2896 if (retval == -EALREADY) {
David Lopoaa69a802008-11-17 14:14:51 -08002897 dbg_event(_usb_addr(mEp), "QUEUE", retval);
2898 retval = 0;
2899 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302900 if (!retval)
2901 list_add_tail(&mReq->queue, &mEp->qh.queue);
David Lopoaa69a802008-11-17 14:14:51 -08002902
2903 done:
2904 spin_unlock_irqrestore(mEp->lock, flags);
2905 return retval;
2906}
2907
2908/**
2909 * ep_dequeue: dequeues (cancels, unlinks) an I/O request from an endpoint
2910 *
2911 * Check usb_ep_dequeue() at "usb_gadget.h" for details
2912 */
2913static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
2914{
2915 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05302916 struct ci13xxx_ep *mEpTemp = mEp;
David Lopoaa69a802008-11-17 14:14:51 -08002917 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2918 unsigned long flags;
2919
2920 trace("%p, %p", ep, req);
2921
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302922 if (ep == NULL || req == NULL || mReq->req.status != -EALREADY ||
2923 mEp->desc == NULL || list_empty(&mReq->queue) ||
2924 list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08002925 return -EINVAL;
2926
2927 spin_lock_irqsave(mEp->lock, flags);
2928
2929 dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
2930
Mayank Rana0c1b8b22012-07-04 16:17:38 +05302931 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL)) {
2932 hw_ep_flush(_udc->ep0out.num, RX);
2933 hw_ep_flush(_udc->ep0in.num, TX);
2934 } else {
2935 hw_ep_flush(mEp->num, mEp->dir);
2936 }
David Lopoaa69a802008-11-17 14:14:51 -08002937
2938 /* pop request */
2939 list_del_init(&mReq->queue);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302940 if (mReq->map) {
2941 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
2942 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02002943 mReq->req.dma = DMA_ADDR_INVALID;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302944 mReq->map = 0;
2945 }
David Lopoaa69a802008-11-17 14:14:51 -08002946 req->status = -ECONNRESET;
2947
Artem Leonenko7c25a822010-12-14 23:46:55 -08002948 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08002949 spin_unlock(mEp->lock);
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05302950 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
2951 mReq->req.length)
2952 mEpTemp = &_udc->ep0in;
2953 mReq->req.complete(&mEpTemp->ep, &mReq->req);
Mayank Rana0c1b8b22012-07-04 16:17:38 +05302954 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2955 mReq->req.complete = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002956 spin_lock(mEp->lock);
2957 }
2958
2959 spin_unlock_irqrestore(mEp->lock, flags);
2960 return 0;
2961}
2962
Bar Weiner0fc137a2012-03-28 16:58:09 +02002963static int is_sps_req(struct ci13xxx_req *mReq)
2964{
2965 return (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID &&
2966 mReq->req.udc_priv & MSM_SPS_MODE);
2967}
2968
David Lopoaa69a802008-11-17 14:14:51 -08002969/**
2970 * ep_set_halt: sets the endpoint halt feature
2971 *
2972 * Check usb_ep_set_halt() at "usb_gadget.h" for details
2973 */
2974static int ep_set_halt(struct usb_ep *ep, int value)
2975{
2976 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2977 int direction, retval = 0;
2978 unsigned long flags;
2979
2980 trace("%p, %i", ep, value);
2981
2982 if (ep == NULL || mEp->desc == NULL)
2983 return -EINVAL;
2984
2985 spin_lock_irqsave(mEp->lock, flags);
2986
2987#ifndef STALL_IN
2988 /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
2989 if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX &&
Bar Weiner0fc137a2012-03-28 16:58:09 +02002990 !list_empty(&mEp->qh.queue) &&
2991 !is_sps_req(list_entry(mEp->qh.queue.next, struct ci13xxx_req,
2992 queue))){
David Lopoaa69a802008-11-17 14:14:51 -08002993 spin_unlock_irqrestore(mEp->lock, flags);
2994 return -EAGAIN;
2995 }
2996#endif
2997
2998 direction = mEp->dir;
2999 do {
3000 dbg_event(_usb_addr(mEp), "HALT", value);
3001 retval |= hw_ep_set_halt(mEp->num, mEp->dir, value);
3002
3003 if (!value)
3004 mEp->wedge = 0;
3005
3006 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
3007 mEp->dir = (mEp->dir == TX) ? RX : TX;
3008
3009 } while (mEp->dir != direction);
3010
3011 spin_unlock_irqrestore(mEp->lock, flags);
3012 return retval;
3013}
3014
3015/**
3016 * ep_set_wedge: sets the halt feature and ignores clear requests
3017 *
3018 * Check usb_ep_set_wedge() at "usb_gadget.h" for details
3019 */
3020static int ep_set_wedge(struct usb_ep *ep)
3021{
3022 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
3023 unsigned long flags;
3024
3025 trace("%p", ep);
3026
3027 if (ep == NULL || mEp->desc == NULL)
3028 return -EINVAL;
3029
3030 spin_lock_irqsave(mEp->lock, flags);
3031
3032 dbg_event(_usb_addr(mEp), "WEDGE", 0);
3033 mEp->wedge = 1;
3034
3035 spin_unlock_irqrestore(mEp->lock, flags);
3036
3037 return usb_ep_set_halt(ep);
3038}
3039
3040/**
3041 * ep_fifo_flush: flushes contents of a fifo
3042 *
3043 * Check usb_ep_fifo_flush() at "usb_gadget.h" for details
3044 */
3045static void ep_fifo_flush(struct usb_ep *ep)
3046{
3047 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
3048 unsigned long flags;
3049
3050 trace("%p", ep);
3051
3052 if (ep == NULL) {
3053 err("%02X: -EINVAL", _usb_addr(mEp));
3054 return;
3055 }
3056
3057 spin_lock_irqsave(mEp->lock, flags);
3058
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05303059 del_timer(&mEp->prime_timer);
3060 mEp->prime_timer_count = 0;
David Lopoaa69a802008-11-17 14:14:51 -08003061 dbg_event(_usb_addr(mEp), "FFLUSH", 0);
3062 hw_ep_flush(mEp->num, mEp->dir);
3063
3064 spin_unlock_irqrestore(mEp->lock, flags);
3065}
3066
3067/**
3068 * Endpoint-specific part of the API to the USB controller hardware
3069 * Check "usb_gadget.h" for details
3070 */
3071static const struct usb_ep_ops usb_ep_ops = {
3072 .enable = ep_enable,
3073 .disable = ep_disable,
3074 .alloc_request = ep_alloc_request,
3075 .free_request = ep_free_request,
3076 .queue = ep_queue,
3077 .dequeue = ep_dequeue,
3078 .set_halt = ep_set_halt,
3079 .set_wedge = ep_set_wedge,
3080 .fifo_flush = ep_fifo_flush,
3081};
3082
3083/******************************************************************************
3084 * GADGET block
3085 *****************************************************************************/
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303086static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
3087{
3088 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
3089 unsigned long flags;
3090 int gadget_ready = 0;
3091
3092 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS))
3093 return -EOPNOTSUPP;
3094
3095 spin_lock_irqsave(udc->lock, flags);
3096 udc->vbus_active = is_active;
3097 if (udc->driver)
3098 gadget_ready = 1;
3099 spin_unlock_irqrestore(udc->lock, flags);
3100
3101 if (gadget_ready) {
3102 if (is_active) {
Pavankumar Kondetic0360192010-12-07 17:54:04 +05303103 pm_runtime_get_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303104 hw_device_reset(udc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003105 if (udc->softconnect)
3106 hw_device_state(udc->ep0out.qh.dma);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303107 } else {
3108 hw_device_state(0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303109 _gadget_stop_activity(&udc->gadget);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303110 if (udc->udc_driver->notify_event)
3111 udc->udc_driver->notify_event(udc,
Amit Blay9b033682012-05-24 16:59:23 +03003112 CI13XXX_CONTROLLER_DISCONNECT_EVENT);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05303113 pm_runtime_put_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303114 }
3115 }
3116
3117 return 0;
3118}
3119
Pavankumar Kondetid8608522011-05-04 10:19:47 +05303120static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
3121{
3122 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
3123
3124 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02003125 return usb_phy_set_power(udc->transceiver, mA);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05303126 return -ENOTSUPP;
3127}
3128
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003129static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_active)
3130{
3131 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
3132 unsigned long flags;
3133
3134 spin_lock_irqsave(udc->lock, flags);
3135 udc->softconnect = is_active;
3136 if (((udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) &&
3137 !udc->vbus_active) || !udc->driver) {
3138 spin_unlock_irqrestore(udc->lock, flags);
3139 return 0;
3140 }
3141 spin_unlock_irqrestore(udc->lock, flags);
3142
Ofir Cohen06789f12012-01-16 09:43:13 +02003143 if (is_active) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003144 hw_device_state(udc->ep0out.qh.dma);
Ofir Cohen06789f12012-01-16 09:43:13 +02003145 if (udc->udc_driver->notify_event)
3146 udc->udc_driver->notify_event(udc,
3147 CI13XXX_CONTROLLER_CONNECT_EVENT);
3148 }
Pavankumar Kondetib7f53dc2011-08-23 12:40:33 +05303149 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003150 hw_device_state(0);
Pavankumar Kondetib7f53dc2011-08-23 12:40:33 +05303151
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003152 return 0;
3153}
3154
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003155static int ci13xxx_start(struct usb_gadget_driver *driver,
3156 int (*bind)(struct usb_gadget *));
3157static int ci13xxx_stop(struct usb_gadget_driver *driver);
David Lopoaa69a802008-11-17 14:14:51 -08003158/**
3159 * Device operations part of the API to the USB controller hardware,
3160 * which don't involve endpoints (or i/o)
3161 * Check "usb_gadget.h" for details
3162 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303163static const struct usb_gadget_ops usb_gadget_ops = {
3164 .vbus_session = ci13xxx_vbus_session,
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05303165 .wakeup = ci13xxx_wakeup,
Pavankumar Kondetid8608522011-05-04 10:19:47 +05303166 .vbus_draw = ci13xxx_vbus_draw,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003167 .pullup = ci13xxx_pullup,
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003168 .start = ci13xxx_start,
3169 .stop = ci13xxx_stop,
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303170};
David Lopoaa69a802008-11-17 14:14:51 -08003171
3172/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003173 * ci13xxx_start: register a gadget driver
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003174 * @driver: the driver being registered
3175 * @bind: the driver's bind callback
David Lopoaa69a802008-11-17 14:14:51 -08003176 *
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003177 * Check ci13xxx_start() at <linux/usb/gadget.h> for details.
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003178 * Interrupts are enabled here.
David Lopoaa69a802008-11-17 14:14:51 -08003179 */
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003180static int ci13xxx_start(struct usb_gadget_driver *driver,
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003181 int (*bind)(struct usb_gadget *))
David Lopoaa69a802008-11-17 14:14:51 -08003182{
3183 struct ci13xxx *udc = _udc;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303184 unsigned long flags;
3185 int i, j;
David Lopoaa69a802008-11-17 14:14:51 -08003186 int retval = -ENOMEM;
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303187 bool put = false;
David Lopoaa69a802008-11-17 14:14:51 -08003188
3189 trace("%p", driver);
3190
3191 if (driver == NULL ||
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003192 bind == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08003193 driver->setup == NULL ||
Marc Kleine-Budde7bb4fdc2011-10-10 18:38:09 +02003194 driver->disconnect == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08003195 return -EINVAL;
3196 else if (udc == NULL)
3197 return -ENODEV;
3198 else if (udc->driver != NULL)
3199 return -EBUSY;
3200
3201 /* alloc resources */
3202 udc->qh_pool = dma_pool_create("ci13xxx_qh", &udc->gadget.dev,
3203 sizeof(struct ci13xxx_qh),
Artem Leonenko0a313c42010-12-14 23:47:06 -08003204 64, CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08003205 if (udc->qh_pool == NULL)
3206 return -ENOMEM;
3207
3208 udc->td_pool = dma_pool_create("ci13xxx_td", &udc->gadget.dev,
3209 sizeof(struct ci13xxx_td),
Artem Leonenko0a313c42010-12-14 23:47:06 -08003210 64, CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08003211 if (udc->td_pool == NULL) {
3212 dma_pool_destroy(udc->qh_pool);
3213 udc->qh_pool = NULL;
3214 return -ENOMEM;
3215 }
3216
3217 spin_lock_irqsave(udc->lock, flags);
3218
3219 info("hw_ep_max = %d", hw_ep_max);
3220
David Lopoaa69a802008-11-17 14:14:51 -08003221 udc->gadget.dev.driver = NULL;
3222
3223 retval = 0;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303224 for (i = 0; i < hw_ep_max/2; i++) {
3225 for (j = RX; j <= TX; j++) {
3226 int k = i + j * hw_ep_max/2;
3227 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
David Lopoaa69a802008-11-17 14:14:51 -08003228
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303229 scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
3230 (j == TX) ? "in" : "out");
David Lopoaa69a802008-11-17 14:14:51 -08003231
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303232 mEp->lock = udc->lock;
3233 mEp->device = &udc->gadget.dev;
3234 mEp->td_pool = udc->td_pool;
David Lopoaa69a802008-11-17 14:14:51 -08003235
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303236 mEp->ep.name = mEp->name;
3237 mEp->ep.ops = &usb_ep_ops;
Hemant Kumarca8fa3f2012-09-27 16:42:36 -07003238 mEp->ep.maxpacket =
3239 k ? USHRT_MAX : CTRL_PAYLOAD_MAX;
David Lopoaa69a802008-11-17 14:14:51 -08003240
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303241 INIT_LIST_HEAD(&mEp->qh.queue);
Pavankumar Kondeti0a91efa2010-12-07 17:54:00 +05303242 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303243 mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
3244 &mEp->qh.dma);
Pavankumar Kondeti0a91efa2010-12-07 17:54:00 +05303245 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303246 if (mEp->qh.ptr == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08003247 retval = -ENOMEM;
3248 else
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303249 memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
3250
3251 /* skip ep0 out and in endpoints */
3252 if (i == 0)
3253 continue;
3254
David Lopoaa69a802008-11-17 14:14:51 -08003255 list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303256 }
David Lopoaa69a802008-11-17 14:14:51 -08003257 }
3258 if (retval)
3259 goto done;
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05303260 spin_unlock_irqrestore(udc->lock, flags);
Felipe Balbi877c1f52011-06-29 16:41:57 +03003261 udc->ep0out.ep.desc = &ctrl_endpt_out_desc;
3262 retval = usb_ep_enable(&udc->ep0out.ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05303263 if (retval)
3264 return retval;
Felipe Balbi877c1f52011-06-29 16:41:57 +03003265
3266 udc->ep0in.ep.desc = &ctrl_endpt_in_desc;
3267 retval = usb_ep_enable(&udc->ep0in.ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05303268 if (retval)
3269 return retval;
3270 spin_lock_irqsave(udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08003271
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303272 udc->gadget.ep0 = &udc->ep0in.ep;
David Lopoaa69a802008-11-17 14:14:51 -08003273 /* bind gadget */
3274 driver->driver.bus = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08003275 udc->gadget.dev.driver = &driver->driver;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003276 udc->softconnect = 1;
David Lopoaa69a802008-11-17 14:14:51 -08003277
3278 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondeti98853282011-11-24 09:01:54 +05303279 pm_runtime_get_sync(&udc->gadget.dev);
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02003280 retval = bind(&udc->gadget); /* MAY SLEEP */
David Lopoaa69a802008-11-17 14:14:51 -08003281 spin_lock_irqsave(udc->lock, flags);
3282
3283 if (retval) {
David Lopoaa69a802008-11-17 14:14:51 -08003284 udc->gadget.dev.driver = NULL;
3285 goto done;
3286 }
3287
Pavankumar Kondeti49d3df52011-01-11 09:19:21 +05303288 udc->driver = driver;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303289 if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
3290 if (udc->vbus_active) {
3291 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
3292 hw_device_reset(udc);
3293 } else {
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303294 put = true;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303295 goto done;
3296 }
3297 }
3298
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303299 if (!udc->softconnect) {
3300 put = true;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003301 goto done;
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303302 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003303
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303304 retval = hw_device_state(udc->ep0out.qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08003305
3306 done:
3307 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303308 if (retval || put)
Pavankumar Kondeti98853282011-11-24 09:01:54 +05303309 pm_runtime_put_sync(&udc->gadget.dev);
Ido Shayevitzab601632012-09-16 15:11:26 +03003310
3311 if (udc->udc_driver->notify_event)
3312 udc->udc_driver->notify_event(udc,
3313 CI13XXX_CONTROLLER_UDC_STARTED_EVENT);
3314
David Lopoaa69a802008-11-17 14:14:51 -08003315 return retval;
3316}
David Lopoaa69a802008-11-17 14:14:51 -08003317
3318/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003319 * ci13xxx_stop: unregister a gadget driver
David Lopoaa69a802008-11-17 14:14:51 -08003320 *
3321 * Check usb_gadget_unregister_driver() at "usb_gadget.h" for details
3322 */
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003323static int ci13xxx_stop(struct usb_gadget_driver *driver)
David Lopoaa69a802008-11-17 14:14:51 -08003324{
3325 struct ci13xxx *udc = _udc;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303326 unsigned long i, flags;
David Lopoaa69a802008-11-17 14:14:51 -08003327
3328 trace("%p", driver);
3329
3330 if (driver == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08003331 driver->unbind == NULL ||
3332 driver->setup == NULL ||
3333 driver->disconnect == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08003334 driver != udc->driver)
3335 return -EINVAL;
3336
3337 spin_lock_irqsave(udc->lock, flags);
3338
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303339 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) ||
3340 udc->vbus_active) {
3341 hw_device_state(0);
Marc Kleine-Buddefd537c02011-10-10 18:38:07 +02003342 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303343 _gadget_stop_activity(&udc->gadget);
Marc Kleine-Buddefd537c02011-10-10 18:38:07 +02003344 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05303345 pm_runtime_put(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303346 }
David Lopoaa69a802008-11-17 14:14:51 -08003347
3348 /* unbind gadget */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303349 spin_unlock_irqrestore(udc->lock, flags);
3350 driver->unbind(&udc->gadget); /* MAY SLEEP */
3351 spin_lock_irqsave(udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08003352
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303353 udc->gadget.dev.driver = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08003354
3355 /* free resources */
3356 for (i = 0; i < hw_ep_max; i++) {
3357 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
3358
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303359 if (!list_empty(&mEp->ep.ep_list))
David Lopoaa69a802008-11-17 14:14:51 -08003360 list_del_init(&mEp->ep.ep_list);
3361
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303362 if (mEp->qh.ptr != NULL)
3363 dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08003364 }
3365
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303366 udc->gadget.ep0 = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08003367 udc->driver = NULL;
3368
3369 spin_unlock_irqrestore(udc->lock, flags);
3370
3371 if (udc->td_pool != NULL) {
3372 dma_pool_destroy(udc->td_pool);
3373 udc->td_pool = NULL;
3374 }
3375 if (udc->qh_pool != NULL) {
3376 dma_pool_destroy(udc->qh_pool);
3377 udc->qh_pool = NULL;
3378 }
3379
3380 return 0;
3381}
David Lopoaa69a802008-11-17 14:14:51 -08003382
3383/******************************************************************************
3384 * BUS block
3385 *****************************************************************************/
3386/**
3387 * udc_irq: global interrupt handler
3388 *
3389 * This function returns IRQ_HANDLED if the IRQ has been handled
3390 * It locks access to registers
3391 */
3392static irqreturn_t udc_irq(void)
3393{
3394 struct ci13xxx *udc = _udc;
3395 irqreturn_t retval;
3396 u32 intr;
3397
3398 trace();
3399
3400 if (udc == NULL) {
3401 err("ENODEV");
3402 return IRQ_HANDLED;
3403 }
3404
3405 spin_lock(udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303406
3407 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) {
3408 if (hw_cread(CAP_USBMODE, USBMODE_CM) !=
3409 USBMODE_CM_DEVICE) {
3410 spin_unlock(udc->lock);
3411 return IRQ_NONE;
3412 }
3413 }
David Lopoaa69a802008-11-17 14:14:51 -08003414 intr = hw_test_and_clear_intr_active();
3415 if (intr) {
3416 isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intr;
3417 isr_statistics.hndl.idx &= ISR_MASK;
3418 isr_statistics.hndl.cnt++;
3419
3420 /* order defines priority - do NOT change it */
3421 if (USBi_URI & intr) {
3422 isr_statistics.uri++;
3423 isr_reset_handler(udc);
3424 }
3425 if (USBi_PCI & intr) {
3426 isr_statistics.pci++;
Amit Blay6fa647a2012-05-24 14:12:08 +03003427 isr_resume_handler(udc);
David Lopoaa69a802008-11-17 14:14:51 -08003428 }
3429 if (USBi_UEI & intr)
3430 isr_statistics.uei++;
3431 if (USBi_UI & intr) {
3432 isr_statistics.ui++;
3433 isr_tr_complete_handler(udc);
3434 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05303435 if (USBi_SLI & intr) {
Amit Blay6fa647a2012-05-24 14:12:08 +03003436 isr_suspend_handler(udc);
David Lopoaa69a802008-11-17 14:14:51 -08003437 isr_statistics.sli++;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05303438 }
David Lopoaa69a802008-11-17 14:14:51 -08003439 retval = IRQ_HANDLED;
3440 } else {
3441 isr_statistics.none++;
3442 retval = IRQ_NONE;
3443 }
3444 spin_unlock(udc->lock);
3445
3446 return retval;
3447}
3448
3449/**
3450 * udc_release: driver release function
3451 * @dev: device
3452 *
3453 * Currently does nothing
3454 */
3455static void udc_release(struct device *dev)
3456{
3457 trace("%p", dev);
3458
3459 if (dev == NULL)
3460 err("EINVAL");
3461}
3462
3463/**
3464 * udc_probe: parent probe must call this to initialize UDC
3465 * @dev: parent device
3466 * @regs: registers base address
3467 * @name: driver name
3468 *
3469 * This function returns an error code
3470 * No interrupts active, the IRQ has not been requested yet
3471 * Kernel assumes 32-bit DMA operations by default, no need to dma_set_mask
3472 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303473static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
3474 void __iomem *regs)
David Lopoaa69a802008-11-17 14:14:51 -08003475{
3476 struct ci13xxx *udc;
Ido Shayevitz4314d1e2012-06-26 15:21:09 +03003477 struct ci13xxx_platform_data *pdata =
3478 (struct ci13xxx_platform_data *)(dev->platform_data);
Lena Salmana7a05202012-03-19 10:39:44 +02003479 int retval = 0, i;
David Lopoaa69a802008-11-17 14:14:51 -08003480
Marc Kleine-Budde194fa472011-10-10 18:38:08 +02003481 trace("%p, %p, %p", dev, regs, driver->name);
David Lopoaa69a802008-11-17 14:14:51 -08003482
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303483 if (dev == NULL || regs == NULL || driver == NULL ||
3484 driver->name == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08003485 return -EINVAL;
3486
3487 udc = kzalloc(sizeof(struct ci13xxx), GFP_KERNEL);
3488 if (udc == NULL)
3489 return -ENOMEM;
3490
3491 udc->lock = &udc_lock;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303492 udc->regs = regs;
3493 udc->udc_driver = driver;
David Lopoaa69a802008-11-17 14:14:51 -08003494
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303495 udc->gadget.ops = &usb_gadget_ops;
David Lopoaa69a802008-11-17 14:14:51 -08003496 udc->gadget.speed = USB_SPEED_UNKNOWN;
Michal Nazarewiczd327ab52011-11-19 18:27:37 +01003497 udc->gadget.max_speed = USB_SPEED_HIGH;
Vijayavardhan Vennapusad450cb02012-02-25 14:35:26 +05303498 if (udc->udc_driver->flags & CI13XXX_IS_OTG)
3499 udc->gadget.is_otg = 1;
3500 else
3501 udc->gadget.is_otg = 0;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303502 udc->gadget.name = driver->name;
David Lopoaa69a802008-11-17 14:14:51 -08003503
3504 INIT_LIST_HEAD(&udc->gadget.ep_list);
3505 udc->gadget.ep0 = NULL;
3506
Ido Shayevitz4314d1e2012-06-26 15:21:09 +03003507 if (pdata)
3508 udc->gadget.usb_core_id = pdata->usb_core_id;
3509
Kay Sievers5df58522009-03-24 16:38:23 -07003510 dev_set_name(&udc->gadget.dev, "gadget");
David Lopoaa69a802008-11-17 14:14:51 -08003511 udc->gadget.dev.dma_mask = dev->dma_mask;
Pavankumar Kondeti61948ee2010-12-07 17:54:01 +05303512 udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
David Lopoaa69a802008-11-17 14:14:51 -08003513 udc->gadget.dev.parent = dev;
3514 udc->gadget.dev.release = udc_release;
3515
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303516 if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
Steve Mucklef132c6c2012-06-06 18:30:57 -07003517 udc->transceiver = usb_get_transceiver();
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303518 if (udc->transceiver == NULL) {
3519 retval = -ENODEV;
3520 goto free_udc;
3521 }
3522 }
3523
Amit Blayfd075dd2012-06-26 13:12:50 +03003524 INIT_DELAYED_WORK(&udc->rw_work, usb_do_remote_wakeup);
3525
Pavankumar Kondetic898b7d2012-05-16 11:54:35 +05303526 retval = hw_device_init(regs);
3527 if (retval < 0)
3528 goto put_transceiver;
3529
3530 for (i = 0; i < hw_ep_max; i++) {
3531 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
3532 INIT_LIST_HEAD(&mEp->ep.ep_list);
Vijayavardhan Vennapusa9e4a5052012-10-03 13:14:06 +05303533 setup_timer(&mEp->prime_timer, ep_prime_timer_func,
3534 (unsigned long) mEp);
Pavankumar Kondetic898b7d2012-05-16 11:54:35 +05303535 }
3536
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303537 if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) {
3538 retval = hw_device_reset(udc);
3539 if (retval)
3540 goto put_transceiver;
3541 }
3542
David Lopoaa69a802008-11-17 14:14:51 -08003543 retval = device_register(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303544 if (retval) {
3545 put_device(&udc->gadget.dev);
3546 goto put_transceiver;
3547 }
David Lopoaa69a802008-11-17 14:14:51 -08003548
3549#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3550 retval = dbg_create_files(&udc->gadget.dev);
3551#endif
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303552 if (retval)
3553 goto unreg_device;
3554
3555 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02003556 retval = otg_set_peripheral(udc->transceiver->otg,
3557 &udc->gadget);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303558 if (retval)
3559 goto remove_dbg;
David Lopoaa69a802008-11-17 14:14:51 -08003560 }
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003561
3562 retval = usb_add_gadget_udc(dev, &udc->gadget);
3563 if (retval)
3564 goto remove_trans;
3565
Pavankumar Kondetic0360192010-12-07 17:54:04 +05303566 pm_runtime_no_callbacks(&udc->gadget.dev);
3567 pm_runtime_enable(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08003568
3569 _udc = udc;
3570 return retval;
3571
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003572remove_trans:
3573 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02003574 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02003575 usb_put_transceiver(udc->transceiver);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003576 }
3577
David Lopoaa69a802008-11-17 14:14:51 -08003578 err("error = %i", retval);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303579remove_dbg:
3580#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3581 dbg_remove_files(&udc->gadget.dev);
3582#endif
3583unreg_device:
3584 device_unregister(&udc->gadget.dev);
3585put_transceiver:
3586 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02003587 usb_put_transceiver(udc->transceiver);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303588free_udc:
David Lopoaa69a802008-11-17 14:14:51 -08003589 kfree(udc);
3590 _udc = NULL;
3591 return retval;
3592}
3593
3594/**
3595 * udc_remove: parent remove must call this to remove UDC
3596 *
3597 * No interrupts active, the IRQ has been released
3598 */
3599static void udc_remove(void)
3600{
3601 struct ci13xxx *udc = _udc;
3602
3603 if (udc == NULL) {
3604 err("EINVAL");
3605 return;
3606 }
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003607 usb_del_gadget_udc(&udc->gadget);
David Lopoaa69a802008-11-17 14:14:51 -08003608
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303609 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02003610 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02003611 usb_put_transceiver(udc->transceiver);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303612 }
David Lopoaa69a802008-11-17 14:14:51 -08003613#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3614 dbg_remove_files(&udc->gadget.dev);
3615#endif
3616 device_unregister(&udc->gadget.dev);
3617
3618 kfree(udc);
3619 _udc = NULL;
3620}