blob: ff4bbadd752d949d11df39091bd2fe57d437935d [file] [log] [blame]
David Lopoaa69a802008-11-17 14:14:51 -08001/*
2 * ci13xxx_udc.c - MIPS USB IP core family device controller
3 *
4 * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
5 *
6 * Author: David Lopo
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13/*
14 * Description: MIPS USB IP core family device controller
15 * Currently it only supports IP part number CI13412
16 *
17 * This driver is composed of several blocks:
18 * - HW: hardware interface
19 * - DBG: debug facilities (optional)
20 * - UTIL: utilities
21 * - ISR: interrupts handling
22 * - ENDPT: endpoint operations (Gadget API)
23 * - GADGET: gadget operations (Gadget API)
24 * - BUS: bus glue code, bus abstraction layer
David Lopoaa69a802008-11-17 14:14:51 -080025 *
26 * Compile Options
27 * - CONFIG_USB_GADGET_DEBUG_FILES: enable debug facilities
28 * - STALL_IN: non-empty bulk-in pipes cannot be halted
29 * if defined mass storage compliance succeeds but with warnings
30 * => case 4: Hi > Dn
31 * => case 5: Hi > Di
32 * => case 8: Hi <> Do
33 * if undefined usbtest 13 fails
34 * - TRACE: enable function tracing (depends on DEBUG)
35 *
36 * Main Features
37 * - Chapter 9 & Mass Storage Compliance with Gadget File Storage
38 * - Chapter 9 Compliance with Gadget Zero (STALL_IN undefined)
39 * - Normal & LPM support
40 *
41 * USBTEST Report
42 * - OK: 0-12, 13 (STALL_IN defined) & 14
43 * - Not Supported: 15 & 16 (ISO)
44 *
45 * TODO List
46 * - OTG
47 * - Isochronous & Interrupt Traffic
48 * - Handle requests which spawns into several TDs
49 * - GET_STATUS(device) - always reports 0
50 * - Gadget API (majority of optional features)
51 * - Suspend & Remote Wakeup
52 */
Matthias Kaehlcke36825a22009-04-15 22:28:36 +020053#include <linux/delay.h>
David Lopoaa69a802008-11-17 14:14:51 -080054#include <linux/device.h>
55#include <linux/dmapool.h>
56#include <linux/dma-mapping.h>
57#include <linux/init.h>
58#include <linux/interrupt.h>
David Lopoaa69a802008-11-17 14:14:51 -080059#include <linux/io.h>
60#include <linux/irq.h>
61#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090062#include <linux/slab.h>
Pavankumar Kondetic0360192010-12-07 17:54:04 +053063#include <linux/pm_runtime.h>
David Lopoaa69a802008-11-17 14:14:51 -080064#include <linux/usb/ch9.h>
65#include <linux/usb/gadget.h>
Pavankumar Kondetif01ef572010-12-07 17:54:02 +053066#include <linux/usb/otg.h>
David Lopoaa69a802008-11-17 14:14:51 -080067
68#include "ci13xxx_udc.h"
69
70
71/******************************************************************************
72 * DEFINE
73 *****************************************************************************/
74/* ctrl register bank access */
75static DEFINE_SPINLOCK(udc_lock);
76
David Lopoaa69a802008-11-17 14:14:51 -080077/* control endpoint description */
78static const struct usb_endpoint_descriptor
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +053079ctrl_endpt_out_desc = {
David Lopoaa69a802008-11-17 14:14:51 -080080 .bLength = USB_DT_ENDPOINT_SIZE,
81 .bDescriptorType = USB_DT_ENDPOINT,
82
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +053083 .bEndpointAddress = USB_DIR_OUT,
84 .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
85 .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
86};
87
88static const struct usb_endpoint_descriptor
89ctrl_endpt_in_desc = {
90 .bLength = USB_DT_ENDPOINT_SIZE,
91 .bDescriptorType = USB_DT_ENDPOINT,
92
93 .bEndpointAddress = USB_DIR_IN,
David Lopoaa69a802008-11-17 14:14:51 -080094 .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
95 .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
96};
97
98/* UDC descriptor */
99static struct ci13xxx *_udc;
100
101/* Interrupt statistics */
102#define ISR_MASK 0x1F
103static struct {
104 u32 test;
105 u32 ui;
106 u32 uei;
107 u32 pci;
108 u32 uri;
109 u32 sli;
110 u32 none;
111 struct {
112 u32 cnt;
113 u32 buf[ISR_MASK+1];
114 u32 idx;
115 } hndl;
116} isr_statistics;
117
118/**
119 * ffs_nr: find first (least significant) bit set
120 * @x: the word to search
121 *
122 * This function returns bit number (instead of position)
123 */
124static int ffs_nr(u32 x)
125{
126 int n = ffs(x);
127
128 return n ? n-1 : 32;
129}
130
131/******************************************************************************
132 * HW block
133 *****************************************************************************/
134/* register bank descriptor */
135static struct {
136 unsigned lpm; /* is LPM? */
137 void __iomem *abs; /* bus map offset */
138 void __iomem *cap; /* bus map offset + CAP offset + CAP data */
139 size_t size; /* bank size */
140} hw_bank;
141
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530142/* MSM specific */
143#define ABS_AHBBURST (0x0090UL)
144#define ABS_AHBMODE (0x0098UL)
David Lopoaa69a802008-11-17 14:14:51 -0800145/* UDC register map */
146#define ABS_CAPLENGTH (0x100UL)
147#define ABS_HCCPARAMS (0x108UL)
148#define ABS_DCCPARAMS (0x124UL)
149#define ABS_TESTMODE (hw_bank.lpm ? 0x0FCUL : 0x138UL)
150/* offset to CAPLENTGH (addr + data) */
151#define CAP_USBCMD (0x000UL)
152#define CAP_USBSTS (0x004UL)
153#define CAP_USBINTR (0x008UL)
154#define CAP_DEVICEADDR (0x014UL)
155#define CAP_ENDPTLISTADDR (0x018UL)
156#define CAP_PORTSC (0x044UL)
David Lopof23e6492009-04-16 14:35:24 -0700157#define CAP_DEVLC (0x084UL)
Ofir Cohena1c2a872011-12-14 10:26:34 +0200158#define CAP_ENDPTPIPEID (0x0BCUL)
David Lopoaa69a802008-11-17 14:14:51 -0800159#define CAP_USBMODE (hw_bank.lpm ? 0x0C8UL : 0x068UL)
160#define CAP_ENDPTSETUPSTAT (hw_bank.lpm ? 0x0D8UL : 0x06CUL)
161#define CAP_ENDPTPRIME (hw_bank.lpm ? 0x0DCUL : 0x070UL)
162#define CAP_ENDPTFLUSH (hw_bank.lpm ? 0x0E0UL : 0x074UL)
163#define CAP_ENDPTSTAT (hw_bank.lpm ? 0x0E4UL : 0x078UL)
164#define CAP_ENDPTCOMPLETE (hw_bank.lpm ? 0x0E8UL : 0x07CUL)
165#define CAP_ENDPTCTRL (hw_bank.lpm ? 0x0ECUL : 0x080UL)
166#define CAP_LAST (hw_bank.lpm ? 0x12CUL : 0x0C0UL)
167
168/* maximum number of enpoints: valid only after hw_device_reset() */
169static unsigned hw_ep_max;
170
171/**
172 * hw_ep_bit: calculates the bit number
173 * @num: endpoint number
174 * @dir: endpoint direction
175 *
176 * This function returns bit number
177 */
178static inline int hw_ep_bit(int num, int dir)
179{
180 return num + (dir ? 16 : 0);
181}
182
183/**
184 * hw_aread: reads from register bitfield
185 * @addr: address relative to bus map
186 * @mask: bitfield mask
187 *
188 * This function returns register bitfield data
189 */
190static u32 hw_aread(u32 addr, u32 mask)
191{
192 return ioread32(addr + hw_bank.abs) & mask;
193}
194
195/**
196 * hw_awrite: writes to register bitfield
197 * @addr: address relative to bus map
198 * @mask: bitfield mask
199 * @data: new data
200 */
201static void hw_awrite(u32 addr, u32 mask, u32 data)
202{
203 iowrite32(hw_aread(addr, ~mask) | (data & mask),
204 addr + hw_bank.abs);
205}
206
207/**
208 * hw_cread: reads from register bitfield
209 * @addr: address relative to CAP offset plus content
210 * @mask: bitfield mask
211 *
212 * This function returns register bitfield data
213 */
214static u32 hw_cread(u32 addr, u32 mask)
215{
216 return ioread32(addr + hw_bank.cap) & mask;
217}
218
219/**
220 * hw_cwrite: writes to register bitfield
221 * @addr: address relative to CAP offset plus content
222 * @mask: bitfield mask
223 * @data: new data
224 */
225static void hw_cwrite(u32 addr, u32 mask, u32 data)
226{
227 iowrite32(hw_cread(addr, ~mask) | (data & mask),
228 addr + hw_bank.cap);
229}
230
231/**
232 * hw_ctest_and_clear: tests & clears register bitfield
233 * @addr: address relative to CAP offset plus content
234 * @mask: bitfield mask
235 *
236 * This function returns register bitfield data
237 */
238static u32 hw_ctest_and_clear(u32 addr, u32 mask)
239{
240 u32 reg = hw_cread(addr, mask);
241
242 iowrite32(reg, addr + hw_bank.cap);
243 return reg;
244}
245
246/**
247 * hw_ctest_and_write: tests & writes register bitfield
248 * @addr: address relative to CAP offset plus content
249 * @mask: bitfield mask
250 * @data: new data
251 *
252 * This function returns register bitfield data
253 */
254static u32 hw_ctest_and_write(u32 addr, u32 mask, u32 data)
255{
256 u32 reg = hw_cread(addr, ~0);
257
258 iowrite32((reg & ~mask) | (data & mask), addr + hw_bank.cap);
259 return (reg & mask) >> ffs_nr(mask);
260}
261
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530262static int hw_device_init(void __iomem *base)
David Lopoaa69a802008-11-17 14:14:51 -0800263{
264 u32 reg;
265
266 /* bank is a module variable */
267 hw_bank.abs = base;
268
269 hw_bank.cap = hw_bank.abs;
270 hw_bank.cap += ABS_CAPLENGTH;
271 hw_bank.cap += ioread8(hw_bank.cap);
272
273 reg = hw_aread(ABS_HCCPARAMS, HCCPARAMS_LEN) >> ffs_nr(HCCPARAMS_LEN);
274 hw_bank.lpm = reg;
275 hw_bank.size = hw_bank.cap - hw_bank.abs;
276 hw_bank.size += CAP_LAST;
277 hw_bank.size /= sizeof(u32);
278
David Lopoaa69a802008-11-17 14:14:51 -0800279 reg = hw_aread(ABS_DCCPARAMS, DCCPARAMS_DEN) >> ffs_nr(DCCPARAMS_DEN);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530280 hw_ep_max = reg * 2; /* cache hw ENDPT_MAX */
David Lopoaa69a802008-11-17 14:14:51 -0800281
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530282 if (hw_ep_max == 0 || hw_ep_max > ENDPT_MAX)
283 return -ENODEV;
David Lopoaa69a802008-11-17 14:14:51 -0800284
285 /* setup lock mode ? */
286
287 /* ENDPTSETUPSTAT is '0' by default */
288
289 /* HCSPARAMS.bf.ppc SHOULD BE zero for device */
290
291 return 0;
292}
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530293/**
294 * hw_device_reset: resets chip (execute without interruption)
295 * @base: register base address
296 *
297 * This function returns an error code
298 */
299static int hw_device_reset(struct ci13xxx *udc)
300{
301 /* should flush & stop before reset */
302 hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0);
303 hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
304
305 hw_cwrite(CAP_USBCMD, USBCMD_RST, USBCMD_RST);
306 while (hw_cread(CAP_USBCMD, USBCMD_RST))
307 udelay(10); /* not RTOS friendly */
308
309
310 if (udc->udc_driver->notify_event)
311 udc->udc_driver->notify_event(udc,
312 CI13XXX_CONTROLLER_RESET_EVENT);
313
Pavankumar Kondeti8c2387a2011-05-02 11:56:28 +0530314 if (udc->udc_driver->flags & CI13XXX_DISABLE_STREAMING)
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530315 hw_cwrite(CAP_USBMODE, USBMODE_SDIS, USBMODE_SDIS);
316
317 /* USBMODE should be configured step by step */
318 hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
319 hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE);
320 hw_cwrite(CAP_USBMODE, USBMODE_SLOM, USBMODE_SLOM); /* HW >= 2.3 */
321
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700322 /*
323 * ITC (Interrupt Threshold Control) field is to set the maximum
324 * rate at which the device controller will issue interrupts.
325 * The maximum interrupt interval measured in micro frames.
326 * Valid values are 0, 1, 2, 4, 8, 16, 32, 64. The default value is
327 * 8 micro frames. If CPU can handle interrupts at faster rate, ITC
328 * can be set to lesser value to gain performance.
329 */
330 if (udc->udc_driver->flags & CI13XXX_ZERO_ITC)
331 hw_cwrite(CAP_USBCMD, USBCMD_ITC_MASK, USBCMD_ITC(0));
332
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530333 if (hw_cread(CAP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
334 pr_err("cannot enter in device mode");
335 pr_err("lpm = %i", hw_bank.lpm);
336 return -ENODEV;
337 }
338
339 return 0;
340}
David Lopoaa69a802008-11-17 14:14:51 -0800341
342/**
343 * hw_device_state: enables/disables interrupts & starts/stops device (execute
344 * without interruption)
345 * @dma: 0 => disable, !0 => enable and set dma engine
346 *
347 * This function returns an error code
348 */
349static int hw_device_state(u32 dma)
350{
351 if (dma) {
352 hw_cwrite(CAP_ENDPTLISTADDR, ~0, dma);
353 /* interrupt, error, port change, reset, sleep/suspend */
354 hw_cwrite(CAP_USBINTR, ~0,
355 USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
356 hw_cwrite(CAP_USBCMD, USBCMD_RS, USBCMD_RS);
357 } else {
358 hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
359 hw_cwrite(CAP_USBINTR, ~0, 0);
360 }
361 return 0;
362}
363
364/**
365 * hw_ep_flush: flush endpoint fifo (execute without interruption)
366 * @num: endpoint number
367 * @dir: endpoint direction
368 *
369 * This function returns an error code
370 */
371static int hw_ep_flush(int num, int dir)
372{
373 int n = hw_ep_bit(num, dir);
374
375 do {
376 /* flush any pending transfer */
377 hw_cwrite(CAP_ENDPTFLUSH, BIT(n), BIT(n));
378 while (hw_cread(CAP_ENDPTFLUSH, BIT(n)))
379 cpu_relax();
380 } while (hw_cread(CAP_ENDPTSTAT, BIT(n)));
381
382 return 0;
383}
384
385/**
386 * hw_ep_disable: disables endpoint (execute without interruption)
387 * @num: endpoint number
388 * @dir: endpoint direction
389 *
390 * This function returns an error code
391 */
392static int hw_ep_disable(int num, int dir)
393{
394 hw_ep_flush(num, dir);
395 hw_cwrite(CAP_ENDPTCTRL + num * sizeof(u32),
396 dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0);
397 return 0;
398}
399
400/**
401 * hw_ep_enable: enables endpoint (execute without interruption)
402 * @num: endpoint number
403 * @dir: endpoint direction
404 * @type: endpoint type
405 *
406 * This function returns an error code
407 */
408static int hw_ep_enable(int num, int dir, int type)
409{
410 u32 mask, data;
411
412 if (dir) {
413 mask = ENDPTCTRL_TXT; /* type */
414 data = type << ffs_nr(mask);
415
416 mask |= ENDPTCTRL_TXS; /* unstall */
417 mask |= ENDPTCTRL_TXR; /* reset data toggle */
418 data |= ENDPTCTRL_TXR;
419 mask |= ENDPTCTRL_TXE; /* enable */
420 data |= ENDPTCTRL_TXE;
421 } else {
422 mask = ENDPTCTRL_RXT; /* type */
423 data = type << ffs_nr(mask);
424
425 mask |= ENDPTCTRL_RXS; /* unstall */
426 mask |= ENDPTCTRL_RXR; /* reset data toggle */
427 data |= ENDPTCTRL_RXR;
428 mask |= ENDPTCTRL_RXE; /* enable */
429 data |= ENDPTCTRL_RXE;
430 }
431 hw_cwrite(CAP_ENDPTCTRL + num * sizeof(u32), mask, data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700432
433 /* make sure endpoint is enabled before returning */
434 mb();
435
David Lopoaa69a802008-11-17 14:14:51 -0800436 return 0;
437}
438
439/**
440 * hw_ep_get_halt: return endpoint halt status
441 * @num: endpoint number
442 * @dir: endpoint direction
443 *
444 * This function returns 1 if endpoint halted
445 */
446static int hw_ep_get_halt(int num, int dir)
447{
448 u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
449
450 return hw_cread(CAP_ENDPTCTRL + num * sizeof(u32), mask) ? 1 : 0;
451}
452
453/**
David Lopoaa69a802008-11-17 14:14:51 -0800454 * hw_test_and_clear_setup_status: test & clear setup status (execute without
455 * interruption)
456 * @n: bit number (endpoint)
457 *
458 * This function returns setup status
459 */
460static int hw_test_and_clear_setup_status(int n)
461{
462 return hw_ctest_and_clear(CAP_ENDPTSETUPSTAT, BIT(n));
463}
464
465/**
466 * hw_ep_prime: primes endpoint (execute without interruption)
467 * @num: endpoint number
468 * @dir: endpoint direction
469 * @is_ctrl: true if control endpoint
470 *
471 * This function returns an error code
472 */
473static int hw_ep_prime(int num, int dir, int is_ctrl)
474{
475 int n = hw_ep_bit(num, dir);
476
David Lopoaa69a802008-11-17 14:14:51 -0800477 if (is_ctrl && dir == RX && hw_cread(CAP_ENDPTSETUPSTAT, BIT(num)))
478 return -EAGAIN;
479
480 hw_cwrite(CAP_ENDPTPRIME, BIT(n), BIT(n));
481
482 while (hw_cread(CAP_ENDPTPRIME, BIT(n)))
483 cpu_relax();
484 if (is_ctrl && dir == RX && hw_cread(CAP_ENDPTSETUPSTAT, BIT(num)))
485 return -EAGAIN;
486
487 /* status shoult be tested according with manual but it doesn't work */
488 return 0;
489}
490
491/**
492 * hw_ep_set_halt: configures ep halt & resets data toggle after clear (execute
493 * without interruption)
494 * @num: endpoint number
495 * @dir: endpoint direction
496 * @value: true => stall, false => unstall
497 *
498 * This function returns an error code
499 */
500static int hw_ep_set_halt(int num, int dir, int value)
501{
Pavankumar Kondeti05598942011-07-06 16:58:44 +0530502 u32 addr, mask_xs, mask_xr;
503
David Lopoaa69a802008-11-17 14:14:51 -0800504 if (value != 0 && value != 1)
505 return -EINVAL;
506
507 do {
Pavankumar Kondeti05598942011-07-06 16:58:44 +0530508 if (hw_cread(CAP_ENDPTSETUPSTAT, BIT(num)))
509 return 0;
510
511 addr = CAP_ENDPTCTRL + num * sizeof(u32);
512 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
513 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR;
David Lopoaa69a802008-11-17 14:14:51 -0800514
515 /* data toggle - reserved for EP0 but it's in ESS */
516 hw_cwrite(addr, mask_xs|mask_xr, value ? mask_xs : mask_xr);
517
518 } while (value != hw_ep_get_halt(num, dir));
519
520 return 0;
521}
522
523/**
524 * hw_intr_clear: disables interrupt & clears interrupt status (execute without
525 * interruption)
526 * @n: interrupt bit
527 *
528 * This function returns an error code
529 */
530static int hw_intr_clear(int n)
531{
532 if (n >= REG_BITS)
533 return -EINVAL;
534
535 hw_cwrite(CAP_USBINTR, BIT(n), 0);
536 hw_cwrite(CAP_USBSTS, BIT(n), BIT(n));
537 return 0;
538}
539
540/**
541 * hw_intr_force: enables interrupt & forces interrupt status (execute without
542 * interruption)
543 * @n: interrupt bit
544 *
545 * This function returns an error code
546 */
547static int hw_intr_force(int n)
548{
549 if (n >= REG_BITS)
550 return -EINVAL;
551
552 hw_awrite(ABS_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
553 hw_cwrite(CAP_USBINTR, BIT(n), BIT(n));
554 hw_cwrite(CAP_USBSTS, BIT(n), BIT(n));
555 hw_awrite(ABS_TESTMODE, TESTMODE_FORCE, 0);
556 return 0;
557}
558
559/**
560 * hw_is_port_high_speed: test if port is high speed
561 *
562 * This function returns true if high speed port
563 */
564static int hw_port_is_high_speed(void)
565{
566 return hw_bank.lpm ? hw_cread(CAP_DEVLC, DEVLC_PSPD) :
567 hw_cread(CAP_PORTSC, PORTSC_HSP);
568}
569
570/**
571 * hw_port_test_get: reads port test mode value
572 *
573 * This function returns port test mode value
574 */
575static u8 hw_port_test_get(void)
576{
577 return hw_cread(CAP_PORTSC, PORTSC_PTC) >> ffs_nr(PORTSC_PTC);
578}
579
580/**
581 * hw_port_test_set: writes port test mode (execute without interruption)
582 * @mode: new value
583 *
584 * This function returns an error code
585 */
586static int hw_port_test_set(u8 mode)
587{
588 const u8 TEST_MODE_MAX = 7;
589
590 if (mode > TEST_MODE_MAX)
591 return -EINVAL;
592
593 hw_cwrite(CAP_PORTSC, PORTSC_PTC, mode << ffs_nr(PORTSC_PTC));
594 return 0;
595}
596
597/**
598 * hw_read_intr_enable: returns interrupt enable register
599 *
600 * This function returns register data
601 */
602static u32 hw_read_intr_enable(void)
603{
604 return hw_cread(CAP_USBINTR, ~0);
605}
606
607/**
608 * hw_read_intr_status: returns interrupt status register
609 *
610 * This function returns register data
611 */
612static u32 hw_read_intr_status(void)
613{
614 return hw_cread(CAP_USBSTS, ~0);
615}
616
617/**
618 * hw_register_read: reads all device registers (execute without interruption)
619 * @buf: destination buffer
620 * @size: buffer size
621 *
622 * This function returns number of registers read
623 */
624static size_t hw_register_read(u32 *buf, size_t size)
625{
626 unsigned i;
627
628 if (size > hw_bank.size)
629 size = hw_bank.size;
630
631 for (i = 0; i < size; i++)
632 buf[i] = hw_aread(i * sizeof(u32), ~0);
633
634 return size;
635}
636
637/**
638 * hw_register_write: writes to register
639 * @addr: register address
640 * @data: register value
641 *
642 * This function returns an error code
643 */
644static int hw_register_write(u16 addr, u32 data)
645{
646 /* align */
647 addr /= sizeof(u32);
648
649 if (addr >= hw_bank.size)
650 return -EINVAL;
651
652 /* align */
653 addr *= sizeof(u32);
654
655 hw_awrite(addr, ~0, data);
656 return 0;
657}
658
659/**
660 * hw_test_and_clear_complete: test & clear complete status (execute without
661 * interruption)
662 * @n: bit number (endpoint)
663 *
664 * This function returns complete status
665 */
666static int hw_test_and_clear_complete(int n)
667{
668 return hw_ctest_and_clear(CAP_ENDPTCOMPLETE, BIT(n));
669}
670
671/**
672 * hw_test_and_clear_intr_active: test & clear active interrupts (execute
673 * without interruption)
674 *
675 * This function returns active interrutps
676 */
677static u32 hw_test_and_clear_intr_active(void)
678{
679 u32 reg = hw_read_intr_status() & hw_read_intr_enable();
680
681 hw_cwrite(CAP_USBSTS, ~0, reg);
682 return reg;
683}
684
685/**
686 * hw_test_and_clear_setup_guard: test & clear setup guard (execute without
687 * interruption)
688 *
689 * This function returns guard value
690 */
691static int hw_test_and_clear_setup_guard(void)
692{
693 return hw_ctest_and_write(CAP_USBCMD, USBCMD_SUTW, 0);
694}
695
696/**
697 * hw_test_and_set_setup_guard: test & set setup guard (execute without
698 * interruption)
699 *
700 * This function returns guard value
701 */
702static int hw_test_and_set_setup_guard(void)
703{
704 return hw_ctest_and_write(CAP_USBCMD, USBCMD_SUTW, USBCMD_SUTW);
705}
706
707/**
708 * hw_usb_set_address: configures USB address (execute without interruption)
709 * @value: new USB address
710 *
711 * This function returns an error code
712 */
713static int hw_usb_set_address(u8 value)
714{
715 /* advance */
716 hw_cwrite(CAP_DEVICEADDR, DEVICEADDR_USBADR | DEVICEADDR_USBADRA,
717 value << ffs_nr(DEVICEADDR_USBADR) | DEVICEADDR_USBADRA);
718 return 0;
719}
720
721/**
722 * hw_usb_reset: restart device after a bus reset (execute without
723 * interruption)
724 *
725 * This function returns an error code
726 */
727static int hw_usb_reset(void)
728{
729 hw_usb_set_address(0);
730
731 /* ESS flushes only at end?!? */
732 hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0); /* flush all EPs */
733
734 /* clear setup token semaphores */
735 hw_cwrite(CAP_ENDPTSETUPSTAT, 0, 0); /* writes its content */
736
737 /* clear complete status */
738 hw_cwrite(CAP_ENDPTCOMPLETE, 0, 0); /* writes its content */
739
740 /* wait until all bits cleared */
741 while (hw_cread(CAP_ENDPTPRIME, ~0))
742 udelay(10); /* not RTOS friendly */
743
744 /* reset all endpoints ? */
745
746 /* reset internal status and wait for further instructions
747 no need to verify the port reset status (ESS does it) */
748
749 return 0;
750}
751
752/******************************************************************************
753 * DBG block
754 *****************************************************************************/
755/**
756 * show_device: prints information about device capabilities and status
757 *
758 * Check "device.h" for details
759 */
760static ssize_t show_device(struct device *dev, struct device_attribute *attr,
761 char *buf)
762{
763 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
764 struct usb_gadget *gadget = &udc->gadget;
765 int n = 0;
766
767 dbg_trace("[%s] %p\n", __func__, buf);
768 if (attr == NULL || buf == NULL) {
769 dev_err(dev, "[%s] EINVAL\n", __func__);
770 return 0;
771 }
772
773 n += scnprintf(buf + n, PAGE_SIZE - n, "speed = %d\n",
774 gadget->speed);
775 n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed = %d\n",
776 gadget->is_dualspeed);
777 n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg = %d\n",
778 gadget->is_otg);
779 n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral = %d\n",
780 gadget->is_a_peripheral);
781 n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable = %d\n",
782 gadget->b_hnp_enable);
783 n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support = %d\n",
784 gadget->a_hnp_support);
785 n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n",
786 gadget->a_alt_hnp_support);
787 n += scnprintf(buf + n, PAGE_SIZE - n, "name = %s\n",
788 (gadget->name ? gadget->name : ""));
789
790 return n;
791}
792static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
793
794/**
795 * show_driver: prints information about attached gadget (if any)
796 *
797 * Check "device.h" for details
798 */
799static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
800 char *buf)
801{
802 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
803 struct usb_gadget_driver *driver = udc->driver;
804 int n = 0;
805
806 dbg_trace("[%s] %p\n", __func__, buf);
807 if (attr == NULL || buf == NULL) {
808 dev_err(dev, "[%s] EINVAL\n", __func__);
809 return 0;
810 }
811
812 if (driver == NULL)
813 return scnprintf(buf, PAGE_SIZE,
814 "There is no gadget attached!\n");
815
816 n += scnprintf(buf + n, PAGE_SIZE - n, "function = %s\n",
817 (driver->function ? driver->function : ""));
818 n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n",
819 driver->speed);
820
821 return n;
822}
823static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL);
824
825/* Maximum event message length */
826#define DBG_DATA_MSG 64UL
827
828/* Maximum event messages */
829#define DBG_DATA_MAX 128UL
830
831/* Event buffer descriptor */
832static struct {
833 char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */
834 unsigned idx; /* index */
835 unsigned tty; /* print to console? */
836 rwlock_t lck; /* lock */
837} dbg_data = {
838 .idx = 0,
839 .tty = 0,
840 .lck = __RW_LOCK_UNLOCKED(lck)
841};
842
843/**
844 * dbg_dec: decrements debug event index
845 * @idx: buffer index
846 */
847static void dbg_dec(unsigned *idx)
848{
849 *idx = (*idx - 1) & (DBG_DATA_MAX-1);
850}
851
852/**
853 * dbg_inc: increments debug event index
854 * @idx: buffer index
855 */
856static void dbg_inc(unsigned *idx)
857{
858 *idx = (*idx + 1) & (DBG_DATA_MAX-1);
859}
860
Vamsi Krishna8d1bbd52012-02-09 21:13:24 -0800861
862static unsigned int ep_addr_txdbg_mask;
863module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
864static unsigned int ep_addr_rxdbg_mask;
865module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
866
867static int allow_dbg_print(u8 addr)
868{
869 int dir, num;
870
871 /* allow bus wide events */
872 if (addr == 0xff)
873 return 1;
874
875 dir = addr & USB_ENDPOINT_DIR_MASK ? TX : RX;
876 num = addr & ~USB_ENDPOINT_DIR_MASK;
877 num = 1 << num;
878
879 if ((dir == TX) && (num & ep_addr_txdbg_mask))
880 return 1;
881 if ((dir == RX) && (num & ep_addr_rxdbg_mask))
882 return 1;
883
884 return 0;
885}
886
David Lopoaa69a802008-11-17 14:14:51 -0800887/**
888 * dbg_print: prints the common part of the event
889 * @addr: endpoint address
890 * @name: event name
891 * @status: status
892 * @extra: extra information
893 */
894static void dbg_print(u8 addr, const char *name, int status, const char *extra)
895{
896 struct timeval tval;
897 unsigned int stamp;
898 unsigned long flags;
899
Vamsi Krishna8d1bbd52012-02-09 21:13:24 -0800900 if (!allow_dbg_print(addr))
901 return;
902
David Lopoaa69a802008-11-17 14:14:51 -0800903 write_lock_irqsave(&dbg_data.lck, flags);
904
905 do_gettimeofday(&tval);
906 stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s */
907 stamp = stamp * 1000000 + tval.tv_usec;
908
909 scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
910 "%04X\t» %02X %-7.7s %4i «\t%s\n",
911 stamp, addr, name, status, extra);
912
913 dbg_inc(&dbg_data.idx);
914
915 write_unlock_irqrestore(&dbg_data.lck, flags);
916
917 if (dbg_data.tty != 0)
918 pr_notice("%04X\t» %02X %-7.7s %4i «\t%s\n",
919 stamp, addr, name, status, extra);
920}
921
922/**
923 * dbg_done: prints a DONE event
924 * @addr: endpoint address
925 * @td: transfer descriptor
926 * @status: status
927 */
928static void dbg_done(u8 addr, const u32 token, int status)
929{
930 char msg[DBG_DATA_MSG];
931
932 scnprintf(msg, sizeof(msg), "%d %02X",
933 (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES),
934 (int)(token & TD_STATUS) >> ffs_nr(TD_STATUS));
935 dbg_print(addr, "DONE", status, msg);
936}
937
938/**
939 * dbg_event: prints a generic event
940 * @addr: endpoint address
941 * @name: event name
942 * @status: status
943 */
944static void dbg_event(u8 addr, const char *name, int status)
945{
946 if (name != NULL)
947 dbg_print(addr, name, status, "");
948}
949
950/*
951 * dbg_queue: prints a QUEUE event
952 * @addr: endpoint address
953 * @req: USB request
954 * @status: status
955 */
956static void dbg_queue(u8 addr, const struct usb_request *req, int status)
957{
958 char msg[DBG_DATA_MSG];
959
960 if (req != NULL) {
961 scnprintf(msg, sizeof(msg),
962 "%d %d", !req->no_interrupt, req->length);
963 dbg_print(addr, "QUEUE", status, msg);
964 }
965}
966
967/**
968 * dbg_setup: prints a SETUP event
969 * @addr: endpoint address
970 * @req: setup request
971 */
972static void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
973{
974 char msg[DBG_DATA_MSG];
975
976 if (req != NULL) {
977 scnprintf(msg, sizeof(msg),
978 "%02X %02X %04X %04X %d", req->bRequestType,
979 req->bRequest, le16_to_cpu(req->wValue),
980 le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
981 dbg_print(addr, "SETUP", 0, msg);
982 }
983}
984
985/**
986 * show_events: displays the event buffer
987 *
988 * Check "device.h" for details
989 */
990static ssize_t show_events(struct device *dev, struct device_attribute *attr,
991 char *buf)
992{
993 unsigned long flags;
994 unsigned i, j, n = 0;
995
996 dbg_trace("[%s] %p\n", __func__, buf);
997 if (attr == NULL || buf == NULL) {
998 dev_err(dev, "[%s] EINVAL\n", __func__);
999 return 0;
1000 }
1001
1002 read_lock_irqsave(&dbg_data.lck, flags);
1003
1004 i = dbg_data.idx;
1005 for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) {
1006 n += strlen(dbg_data.buf[i]);
1007 if (n >= PAGE_SIZE) {
1008 n -= strlen(dbg_data.buf[i]);
1009 break;
1010 }
1011 }
1012 for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i))
1013 j += scnprintf(buf + j, PAGE_SIZE - j,
1014 "%s", dbg_data.buf[i]);
1015
1016 read_unlock_irqrestore(&dbg_data.lck, flags);
1017
1018 return n;
1019}
1020
1021/**
1022 * store_events: configure if events are going to be also printed to console
1023 *
1024 * Check "device.h" for details
1025 */
1026static ssize_t store_events(struct device *dev, struct device_attribute *attr,
1027 const char *buf, size_t count)
1028{
1029 unsigned tty;
1030
1031 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1032 if (attr == NULL || buf == NULL) {
1033 dev_err(dev, "[%s] EINVAL\n", __func__);
1034 goto done;
1035 }
1036
1037 if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
1038 dev_err(dev, "<1|0>: enable|disable console log\n");
1039 goto done;
1040 }
1041
1042 dbg_data.tty = tty;
1043 dev_info(dev, "tty = %u", dbg_data.tty);
1044
1045 done:
1046 return count;
1047}
1048static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
1049
1050/**
1051 * show_inters: interrupt status, enable status and historic
1052 *
1053 * Check "device.h" for details
1054 */
1055static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
1056 char *buf)
1057{
1058 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1059 unsigned long flags;
1060 u32 intr;
1061 unsigned i, j, n = 0;
1062
1063 dbg_trace("[%s] %p\n", __func__, buf);
1064 if (attr == NULL || buf == NULL) {
1065 dev_err(dev, "[%s] EINVAL\n", __func__);
1066 return 0;
1067 }
1068
1069 spin_lock_irqsave(udc->lock, flags);
1070
1071 n += scnprintf(buf + n, PAGE_SIZE - n,
1072 "status = %08x\n", hw_read_intr_status());
1073 n += scnprintf(buf + n, PAGE_SIZE - n,
1074 "enable = %08x\n", hw_read_intr_enable());
1075
1076 n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
1077 isr_statistics.test);
1078 n += scnprintf(buf + n, PAGE_SIZE - n, "» ui = %d\n",
1079 isr_statistics.ui);
1080 n += scnprintf(buf + n, PAGE_SIZE - n, "» uei = %d\n",
1081 isr_statistics.uei);
1082 n += scnprintf(buf + n, PAGE_SIZE - n, "» pci = %d\n",
1083 isr_statistics.pci);
1084 n += scnprintf(buf + n, PAGE_SIZE - n, "» uri = %d\n",
1085 isr_statistics.uri);
1086 n += scnprintf(buf + n, PAGE_SIZE - n, "» sli = %d\n",
1087 isr_statistics.sli);
1088 n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n",
1089 isr_statistics.none);
1090 n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n",
1091 isr_statistics.hndl.cnt);
1092
1093 for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) {
1094 i &= ISR_MASK;
1095 intr = isr_statistics.hndl.buf[i];
1096
1097 if (USBi_UI & intr)
1098 n += scnprintf(buf + n, PAGE_SIZE - n, "ui ");
1099 intr &= ~USBi_UI;
1100 if (USBi_UEI & intr)
1101 n += scnprintf(buf + n, PAGE_SIZE - n, "uei ");
1102 intr &= ~USBi_UEI;
1103 if (USBi_PCI & intr)
1104 n += scnprintf(buf + n, PAGE_SIZE - n, "pci ");
1105 intr &= ~USBi_PCI;
1106 if (USBi_URI & intr)
1107 n += scnprintf(buf + n, PAGE_SIZE - n, "uri ");
1108 intr &= ~USBi_URI;
1109 if (USBi_SLI & intr)
1110 n += scnprintf(buf + n, PAGE_SIZE - n, "sli ");
1111 intr &= ~USBi_SLI;
1112 if (intr)
1113 n += scnprintf(buf + n, PAGE_SIZE - n, "??? ");
1114 if (isr_statistics.hndl.buf[i])
1115 n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
1116 }
1117
1118 spin_unlock_irqrestore(udc->lock, flags);
1119
1120 return n;
1121}
1122
1123/**
1124 * store_inters: enable & force or disable an individual interrutps
1125 * (to be used for test purposes only)
1126 *
1127 * Check "device.h" for details
1128 */
1129static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
1130 const char *buf, size_t count)
1131{
1132 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1133 unsigned long flags;
1134 unsigned en, bit;
1135
1136 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1137 if (attr == NULL || buf == NULL) {
1138 dev_err(dev, "[%s] EINVAL\n", __func__);
1139 goto done;
1140 }
1141
1142 if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
1143 dev_err(dev, "<1|0> <bit>: enable|disable interrupt");
1144 goto done;
1145 }
1146
1147 spin_lock_irqsave(udc->lock, flags);
1148 if (en) {
1149 if (hw_intr_force(bit))
1150 dev_err(dev, "invalid bit number\n");
1151 else
1152 isr_statistics.test++;
1153 } else {
1154 if (hw_intr_clear(bit))
1155 dev_err(dev, "invalid bit number\n");
1156 }
1157 spin_unlock_irqrestore(udc->lock, flags);
1158
1159 done:
1160 return count;
1161}
1162static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
1163
1164/**
1165 * show_port_test: reads port test mode
1166 *
1167 * Check "device.h" for details
1168 */
1169static ssize_t show_port_test(struct device *dev,
1170 struct device_attribute *attr, char *buf)
1171{
1172 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1173 unsigned long flags;
1174 unsigned mode;
1175
1176 dbg_trace("[%s] %p\n", __func__, buf);
1177 if (attr == NULL || buf == NULL) {
1178 dev_err(dev, "[%s] EINVAL\n", __func__);
1179 return 0;
1180 }
1181
1182 spin_lock_irqsave(udc->lock, flags);
1183 mode = hw_port_test_get();
1184 spin_unlock_irqrestore(udc->lock, flags);
1185
1186 return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
1187}
1188
1189/**
1190 * store_port_test: writes port test mode
1191 *
1192 * Check "device.h" for details
1193 */
1194static ssize_t store_port_test(struct device *dev,
1195 struct device_attribute *attr,
1196 const char *buf, size_t count)
1197{
1198 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1199 unsigned long flags;
1200 unsigned mode;
1201
1202 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1203 if (attr == NULL || buf == NULL) {
1204 dev_err(dev, "[%s] EINVAL\n", __func__);
1205 goto done;
1206 }
1207
1208 if (sscanf(buf, "%u", &mode) != 1) {
1209 dev_err(dev, "<mode>: set port test mode");
1210 goto done;
1211 }
1212
1213 spin_lock_irqsave(udc->lock, flags);
1214 if (hw_port_test_set(mode))
1215 dev_err(dev, "invalid mode\n");
1216 spin_unlock_irqrestore(udc->lock, flags);
1217
1218 done:
1219 return count;
1220}
1221static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
1222 show_port_test, store_port_test);
1223
1224/**
1225 * show_qheads: DMA contents of all queue heads
1226 *
1227 * Check "device.h" for details
1228 */
1229static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
1230 char *buf)
1231{
1232 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1233 unsigned long flags;
1234 unsigned i, j, n = 0;
1235
1236 dbg_trace("[%s] %p\n", __func__, buf);
1237 if (attr == NULL || buf == NULL) {
1238 dev_err(dev, "[%s] EINVAL\n", __func__);
1239 return 0;
1240 }
1241
1242 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301243 for (i = 0; i < hw_ep_max/2; i++) {
1244 struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i];
1245 struct ci13xxx_ep *mEpTx = &udc->ci13xxx_ep[i + hw_ep_max/2];
David Lopoaa69a802008-11-17 14:14:51 -08001246 n += scnprintf(buf + n, PAGE_SIZE - n,
1247 "EP=%02i: RX=%08X TX=%08X\n",
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301248 i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08001249 for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) {
1250 n += scnprintf(buf + n, PAGE_SIZE - n,
1251 " %04X: %08X %08X\n", j,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301252 *((u32 *)mEpRx->qh.ptr + j),
1253 *((u32 *)mEpTx->qh.ptr + j));
David Lopoaa69a802008-11-17 14:14:51 -08001254 }
1255 }
1256 spin_unlock_irqrestore(udc->lock, flags);
1257
1258 return n;
1259}
1260static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
1261
1262/**
1263 * show_registers: dumps all registers
1264 *
1265 * Check "device.h" for details
1266 */
1267static ssize_t show_registers(struct device *dev,
1268 struct device_attribute *attr, char *buf)
1269{
1270 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1271 unsigned long flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001272 u32 *dump;
David Lopoaa69a802008-11-17 14:14:51 -08001273 unsigned i, k, n = 0;
1274
1275 dbg_trace("[%s] %p\n", __func__, buf);
1276 if (attr == NULL || buf == NULL) {
1277 dev_err(dev, "[%s] EINVAL\n", __func__);
1278 return 0;
1279 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001280 dump = kmalloc(2048, GFP_KERNEL);
1281 if (dump == NULL)
1282 return -ENOMEM;
David Lopoaa69a802008-11-17 14:14:51 -08001283
1284 spin_lock_irqsave(udc->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001285 k = hw_register_read(dump, 512);
David Lopoaa69a802008-11-17 14:14:51 -08001286 spin_unlock_irqrestore(udc->lock, flags);
1287
1288 for (i = 0; i < k; i++) {
1289 n += scnprintf(buf + n, PAGE_SIZE - n,
1290 "reg[0x%04X] = 0x%08X\n",
1291 i * (unsigned)sizeof(u32), dump[i]);
1292 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001293 kfree(dump);
David Lopoaa69a802008-11-17 14:14:51 -08001294 return n;
1295}
1296
1297/**
1298 * store_registers: writes value to register address
1299 *
1300 * Check "device.h" for details
1301 */
1302static ssize_t store_registers(struct device *dev,
1303 struct device_attribute *attr,
1304 const char *buf, size_t count)
1305{
1306 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1307 unsigned long addr, data, flags;
1308
1309 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1310 if (attr == NULL || buf == NULL) {
1311 dev_err(dev, "[%s] EINVAL\n", __func__);
1312 goto done;
1313 }
1314
1315 if (sscanf(buf, "%li %li", &addr, &data) != 2) {
1316 dev_err(dev, "<addr> <data>: write data to register address");
1317 goto done;
1318 }
1319
1320 spin_lock_irqsave(udc->lock, flags);
1321 if (hw_register_write(addr, data))
1322 dev_err(dev, "invalid address range\n");
1323 spin_unlock_irqrestore(udc->lock, flags);
1324
1325 done:
1326 return count;
1327}
1328static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
1329 show_registers, store_registers);
1330
1331/**
1332 * show_requests: DMA contents of all requests currently queued (all endpts)
1333 *
1334 * Check "device.h" for details
1335 */
1336static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
1337 char *buf)
1338{
1339 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1340 unsigned long flags;
1341 struct list_head *ptr = NULL;
1342 struct ci13xxx_req *req = NULL;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301343 unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
David Lopoaa69a802008-11-17 14:14:51 -08001344
1345 dbg_trace("[%s] %p\n", __func__, buf);
1346 if (attr == NULL || buf == NULL) {
1347 dev_err(dev, "[%s] EINVAL\n", __func__);
1348 return 0;
1349 }
1350
1351 spin_lock_irqsave(udc->lock, flags);
1352 for (i = 0; i < hw_ep_max; i++)
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301353 list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue)
1354 {
1355 req = list_entry(ptr, struct ci13xxx_req, queue);
David Lopoaa69a802008-11-17 14:14:51 -08001356
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301357 n += scnprintf(buf + n, PAGE_SIZE - n,
1358 "EP=%02i: TD=%08X %s\n",
1359 i % hw_ep_max/2, (u32)req->dma,
1360 ((i < hw_ep_max/2) ? "RX" : "TX"));
1361
1362 for (j = 0; j < qSize; j++)
David Lopoaa69a802008-11-17 14:14:51 -08001363 n += scnprintf(buf + n, PAGE_SIZE - n,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301364 " %04X: %08X\n", j,
1365 *((u32 *)req->ptr + j));
1366 }
David Lopoaa69a802008-11-17 14:14:51 -08001367 spin_unlock_irqrestore(udc->lock, flags);
1368
1369 return n;
1370}
1371static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL);
1372
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001373/* EP# and Direction */
1374static ssize_t prime_ept(struct device *dev,
1375 struct device_attribute *attr,
1376 const char *buf, size_t count)
1377{
1378 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1379 struct ci13xxx_ep *mEp;
1380 unsigned int ep_num, dir;
1381 int n;
1382 struct ci13xxx_req *mReq = NULL;
1383
1384 if (sscanf(buf, "%u %u", &ep_num, &dir) != 2) {
1385 dev_err(dev, "<ep_num> <dir>: prime the ep");
1386 goto done;
1387 }
1388
1389 if (dir)
1390 mEp = &udc->ci13xxx_ep[ep_num + hw_ep_max/2];
1391 else
1392 mEp = &udc->ci13xxx_ep[ep_num];
1393
1394 n = hw_ep_bit(mEp->num, mEp->dir);
1395 mReq = list_entry(mEp->qh.queue.next, struct ci13xxx_req, queue);
1396 mEp->qh.ptr->td.next = mReq->dma;
1397 mEp->qh.ptr->td.token &= ~TD_STATUS;
1398
1399 wmb();
1400
1401 hw_cwrite(CAP_ENDPTPRIME, BIT(n), BIT(n));
1402 while (hw_cread(CAP_ENDPTPRIME, BIT(n)))
1403 cpu_relax();
1404
1405 pr_info("%s: prime:%08x stat:%08x ep#%d dir:%s\n", __func__,
1406 hw_cread(CAP_ENDPTPRIME, ~0),
1407 hw_cread(CAP_ENDPTSTAT, ~0),
1408 mEp->num, mEp->dir ? "IN" : "OUT");
1409done:
1410 return count;
1411
1412}
1413static DEVICE_ATTR(prime, S_IWUSR, NULL, prime_ept);
1414
1415/* EP# and Direction */
1416static ssize_t print_dtds(struct device *dev,
1417 struct device_attribute *attr,
1418 const char *buf, size_t count)
1419{
1420 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1421 struct ci13xxx_ep *mEp;
1422 unsigned int ep_num, dir;
1423 int n;
1424 struct list_head *ptr = NULL;
1425 struct ci13xxx_req *req = NULL;
1426
1427 if (sscanf(buf, "%u %u", &ep_num, &dir) != 2) {
1428 dev_err(dev, "<ep_num> <dir>: to print dtds");
1429 goto done;
1430 }
1431
1432 if (dir)
1433 mEp = &udc->ci13xxx_ep[ep_num + hw_ep_max/2];
1434 else
1435 mEp = &udc->ci13xxx_ep[ep_num];
1436
1437 n = hw_ep_bit(mEp->num, mEp->dir);
Anji jonnala6fb918c2011-10-21 17:54:21 +05301438 pr_info("%s: prime:%08x stat:%08x ep#%d dir:%s"
Vamsi Krishna8d1bbd52012-02-09 21:13:24 -08001439 "dTD_update_fail_count: %lu "
Anji jonnala6fb918c2011-10-21 17:54:21 +05301440 "mEp->dTD_update_fail_count: %lu\n", __func__,
1441 hw_cread(CAP_ENDPTPRIME, ~0),
1442 hw_cread(CAP_ENDPTSTAT, ~0),
1443 mEp->num, mEp->dir ? "IN" : "OUT",
1444 udc->dTD_update_fail_count,
1445 mEp->dTD_update_fail_count);
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001446
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001447 pr_info("QH: cap:%08x cur:%08x next:%08x token:%08x\n",
1448 mEp->qh.ptr->cap, mEp->qh.ptr->curr,
1449 mEp->qh.ptr->td.next, mEp->qh.ptr->td.token);
1450
1451 list_for_each(ptr, &mEp->qh.queue) {
1452 req = list_entry(ptr, struct ci13xxx_req, queue);
1453
1454 pr_info("\treq:%08x next:%08x token:%08x page0:%08x status:%d\n",
1455 req->dma, req->ptr->next, req->ptr->token,
1456 req->ptr->page[0], req->req.status);
1457 }
1458done:
1459 return count;
1460
1461}
1462static DEVICE_ATTR(dtds, S_IWUSR, NULL, print_dtds);
1463
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001464static int ci13xxx_wakeup(struct usb_gadget *_gadget)
1465{
1466 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
1467 unsigned long flags;
1468 int ret = 0;
1469
1470 trace();
1471
1472 spin_lock_irqsave(udc->lock, flags);
1473 if (!udc->remote_wakeup) {
1474 ret = -EOPNOTSUPP;
1475 dbg_trace("remote wakeup feature is not enabled\n");
1476 goto out;
1477 }
1478 if (!hw_cread(CAP_PORTSC, PORTSC_SUSP)) {
1479 ret = -EINVAL;
1480 dbg_trace("port is not suspended\n");
1481 goto out;
1482 }
1483 hw_cwrite(CAP_PORTSC, PORTSC_FPR, PORTSC_FPR);
1484out:
1485 spin_unlock_irqrestore(udc->lock, flags);
1486 return ret;
1487}
1488
1489static ssize_t usb_remote_wakeup(struct device *dev,
1490 struct device_attribute *attr, const char *buf, size_t count)
1491{
1492 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1493
1494 ci13xxx_wakeup(&udc->gadget);
1495
1496 return count;
1497}
1498static DEVICE_ATTR(wakeup, S_IWUSR, 0, usb_remote_wakeup);
1499
David Lopoaa69a802008-11-17 14:14:51 -08001500/**
1501 * dbg_create_files: initializes the attribute interface
1502 * @dev: device
1503 *
1504 * This function returns an error code
1505 */
1506__maybe_unused static int dbg_create_files(struct device *dev)
1507{
1508 int retval = 0;
1509
1510 if (dev == NULL)
1511 return -EINVAL;
1512 retval = device_create_file(dev, &dev_attr_device);
1513 if (retval)
1514 goto done;
1515 retval = device_create_file(dev, &dev_attr_driver);
1516 if (retval)
1517 goto rm_device;
1518 retval = device_create_file(dev, &dev_attr_events);
1519 if (retval)
1520 goto rm_driver;
1521 retval = device_create_file(dev, &dev_attr_inters);
1522 if (retval)
1523 goto rm_events;
1524 retval = device_create_file(dev, &dev_attr_port_test);
1525 if (retval)
1526 goto rm_inters;
1527 retval = device_create_file(dev, &dev_attr_qheads);
1528 if (retval)
1529 goto rm_port_test;
1530 retval = device_create_file(dev, &dev_attr_registers);
1531 if (retval)
1532 goto rm_qheads;
1533 retval = device_create_file(dev, &dev_attr_requests);
1534 if (retval)
1535 goto rm_registers;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001536 retval = device_create_file(dev, &dev_attr_wakeup);
1537 if (retval)
1538 goto rm_remote_wakeup;
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001539 retval = device_create_file(dev, &dev_attr_prime);
1540 if (retval)
1541 goto rm_prime;
1542 retval = device_create_file(dev, &dev_attr_dtds);
1543 if (retval)
1544 goto rm_dtds;
1545
David Lopoaa69a802008-11-17 14:14:51 -08001546 return 0;
1547
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001548rm_dtds:
1549 device_remove_file(dev, &dev_attr_dtds);
1550rm_prime:
1551 device_remove_file(dev, &dev_attr_prime);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001552rm_remote_wakeup:
1553 device_remove_file(dev, &dev_attr_wakeup);
David Lopoaa69a802008-11-17 14:14:51 -08001554 rm_registers:
1555 device_remove_file(dev, &dev_attr_registers);
1556 rm_qheads:
1557 device_remove_file(dev, &dev_attr_qheads);
1558 rm_port_test:
1559 device_remove_file(dev, &dev_attr_port_test);
1560 rm_inters:
1561 device_remove_file(dev, &dev_attr_inters);
1562 rm_events:
1563 device_remove_file(dev, &dev_attr_events);
1564 rm_driver:
1565 device_remove_file(dev, &dev_attr_driver);
1566 rm_device:
1567 device_remove_file(dev, &dev_attr_device);
1568 done:
1569 return retval;
1570}
1571
1572/**
1573 * dbg_remove_files: destroys the attribute interface
1574 * @dev: device
1575 *
1576 * This function returns an error code
1577 */
1578__maybe_unused static int dbg_remove_files(struct device *dev)
1579{
1580 if (dev == NULL)
1581 return -EINVAL;
1582 device_remove_file(dev, &dev_attr_requests);
1583 device_remove_file(dev, &dev_attr_registers);
1584 device_remove_file(dev, &dev_attr_qheads);
1585 device_remove_file(dev, &dev_attr_port_test);
1586 device_remove_file(dev, &dev_attr_inters);
1587 device_remove_file(dev, &dev_attr_events);
1588 device_remove_file(dev, &dev_attr_driver);
1589 device_remove_file(dev, &dev_attr_device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001590 device_remove_file(dev, &dev_attr_wakeup);
David Lopoaa69a802008-11-17 14:14:51 -08001591 return 0;
1592}
1593
1594/******************************************************************************
1595 * UTIL block
1596 *****************************************************************************/
1597/**
1598 * _usb_addr: calculates endpoint address from direction & number
1599 * @ep: endpoint
1600 */
1601static inline u8 _usb_addr(struct ci13xxx_ep *ep)
1602{
1603 return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num;
1604}
1605
1606/**
1607 * _hardware_queue: configures a request at hardware level
1608 * @gadget: gadget
1609 * @mEp: endpoint
1610 *
1611 * This function returns an error code
1612 */
1613static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1614{
1615 unsigned i;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301616 int ret = 0;
1617 unsigned length = mReq->req.length;
David Lopoaa69a802008-11-17 14:14:51 -08001618
1619 trace("%p, %p", mEp, mReq);
1620
1621 /* don't queue twice */
1622 if (mReq->req.status == -EALREADY)
1623 return -EALREADY;
1624
David Lopoaa69a802008-11-17 14:14:51 -08001625 mReq->req.status = -EALREADY;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301626 if (length && !mReq->req.dma) {
David Lopoaa69a802008-11-17 14:14:51 -08001627 mReq->req.dma = \
1628 dma_map_single(mEp->device, mReq->req.buf,
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301629 length, mEp->dir ? DMA_TO_DEVICE :
1630 DMA_FROM_DEVICE);
David Lopoaa69a802008-11-17 14:14:51 -08001631 if (mReq->req.dma == 0)
1632 return -ENOMEM;
1633
1634 mReq->map = 1;
1635 }
1636
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301637 if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) {
1638 mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC,
1639 &mReq->zdma);
1640 if (mReq->zptr == NULL) {
1641 if (mReq->map) {
1642 dma_unmap_single(mEp->device, mReq->req.dma,
1643 length, mEp->dir ? DMA_TO_DEVICE :
1644 DMA_FROM_DEVICE);
1645 mReq->req.dma = 0;
1646 mReq->map = 0;
1647 }
1648 return -ENOMEM;
1649 }
1650 memset(mReq->zptr, 0, sizeof(*mReq->zptr));
1651 mReq->zptr->next = TD_TERMINATE;
1652 mReq->zptr->token = TD_STATUS_ACTIVE;
1653 if (!mReq->req.no_interrupt)
1654 mReq->zptr->token |= TD_IOC;
1655 }
David Lopoaa69a802008-11-17 14:14:51 -08001656 /*
1657 * TD configuration
1658 * TODO - handle requests which spawns into several TDs
1659 */
1660 memset(mReq->ptr, 0, sizeof(*mReq->ptr));
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301661 mReq->ptr->token = length << ffs_nr(TD_TOTAL_BYTES);
David Lopoaa69a802008-11-17 14:14:51 -08001662 mReq->ptr->token &= TD_TOTAL_BYTES;
David Lopoaa69a802008-11-17 14:14:51 -08001663 mReq->ptr->token |= TD_STATUS_ACTIVE;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301664 if (mReq->zptr) {
1665 mReq->ptr->next = mReq->zdma;
1666 } else {
1667 mReq->ptr->next = TD_TERMINATE;
1668 if (!mReq->req.no_interrupt)
1669 mReq->ptr->token |= TD_IOC;
1670 }
Ofir Cohena1c2a872011-12-14 10:26:34 +02001671
1672 /* MSM Specific: updating the request as required for
1673 * SPS mode. Enable MSM proprietary DMA engine acording
1674 * to the UDC private data in the request.
1675 */
1676 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
1677 if (mReq->req.udc_priv & MSM_SPS_MODE) {
1678 mReq->ptr->token = TD_STATUS_ACTIVE;
1679 if (mReq->req.udc_priv & MSM_TBE)
1680 mReq->ptr->next = TD_TERMINATE;
1681 else
1682 mReq->ptr->next = MSM_ETD_TYPE | mReq->dma;
1683 if (!mReq->req.no_interrupt)
1684 mReq->ptr->token |= MSM_ETD_IOC;
1685 }
1686 }
1687
David Lopoaa69a802008-11-17 14:14:51 -08001688 mReq->ptr->page[0] = mReq->req.dma;
1689 for (i = 1; i < 5; i++)
1690 mReq->ptr->page[i] =
Artem Leonenko0a313c42010-12-14 23:47:06 -08001691 (mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK;
David Lopoaa69a802008-11-17 14:14:51 -08001692
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301693 if (!list_empty(&mEp->qh.queue)) {
1694 struct ci13xxx_req *mReqPrev;
1695 int n = hw_ep_bit(mEp->num, mEp->dir);
1696 int tmp_stat;
1697
1698 mReqPrev = list_entry(mEp->qh.queue.prev,
1699 struct ci13xxx_req, queue);
1700 if (mReqPrev->zptr)
1701 mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
1702 else
1703 mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
1704 wmb();
1705 if (hw_cread(CAP_ENDPTPRIME, BIT(n)))
1706 goto done;
1707 do {
1708 hw_cwrite(CAP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
1709 tmp_stat = hw_cread(CAP_ENDPTSTAT, BIT(n));
1710 } while (!hw_cread(CAP_USBCMD, USBCMD_ATDTW));
1711 hw_cwrite(CAP_USBCMD, USBCMD_ATDTW, 0);
1712 if (tmp_stat)
1713 goto done;
1714 }
1715
1716 /* QH configuration */
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001717 if (!list_empty(&mEp->qh.queue)) {
1718 struct ci13xxx_req *mReq = \
1719 list_entry(mEp->qh.queue.next,
1720 struct ci13xxx_req, queue);
1721
1722 if (TD_STATUS_ACTIVE & mReq->ptr->token) {
1723 mEp->qh.ptr->td.next = mReq->dma;
1724 mEp->qh.ptr->td.token &= ~TD_STATUS;
1725 goto prime;
1726 }
1727 }
1728
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301729 mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */
Ofir Cohena1c2a872011-12-14 10:26:34 +02001730
1731 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
1732 if (mReq->req.udc_priv & MSM_SPS_MODE) {
1733 mEp->qh.ptr->td.next |= MSM_ETD_TYPE;
1734 i = hw_cread(CAP_ENDPTPIPEID +
1735 mEp->num * sizeof(u32), ~0);
1736 /* Read current value of this EPs pipe id */
1737 i = (mEp->dir == TX) ?
1738 ((i >> MSM_TX_PIPE_ID_OFS) & MSM_PIPE_ID_MASK) :
1739 (i & MSM_PIPE_ID_MASK);
1740 /* If requested pipe id is different from current,
1741 then write it */
1742 if (i != (mReq->req.udc_priv & MSM_PIPE_ID_MASK)) {
1743 if (mEp->dir == TX)
1744 hw_cwrite(
1745 CAP_ENDPTPIPEID +
1746 mEp->num * sizeof(u32),
1747 MSM_PIPE_ID_MASK <<
1748 MSM_TX_PIPE_ID_OFS,
1749 (mReq->req.udc_priv &
1750 MSM_PIPE_ID_MASK)
1751 << MSM_TX_PIPE_ID_OFS);
1752 else
1753 hw_cwrite(
1754 CAP_ENDPTPIPEID +
1755 mEp->num * sizeof(u32),
1756 MSM_PIPE_ID_MASK,
1757 mReq->req.udc_priv &
1758 MSM_PIPE_ID_MASK);
1759 }
1760 }
1761 }
1762
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301763 mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301764 mEp->qh.ptr->cap |= QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08001765
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001766prime:
David Lopoaa69a802008-11-17 14:14:51 -08001767 wmb(); /* synchronize before ep prime */
1768
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301769 ret = hw_ep_prime(mEp->num, mEp->dir,
David Lopoaa69a802008-11-17 14:14:51 -08001770 mEp->type == USB_ENDPOINT_XFER_CONTROL);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301771done:
1772 return ret;
David Lopoaa69a802008-11-17 14:14:51 -08001773}
1774
1775/**
1776 * _hardware_dequeue: handles a request at hardware level
1777 * @gadget: gadget
1778 * @mEp: endpoint
1779 *
1780 * This function returns an error code
1781 */
1782static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1783{
1784 trace("%p, %p", mEp, mReq);
1785
1786 if (mReq->req.status != -EALREADY)
1787 return -EINVAL;
1788
Vijayavardhan Vennapusa590b8ce2011-10-20 02:38:14 +05301789 /* clean speculative fetches on req->ptr->token */
1790 mb();
1791
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301792 if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
1793 return -EBUSY;
1794
Ofir Cohena1c2a872011-12-14 10:26:34 +02001795 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID)
1796 if ((mReq->req.udc_priv & MSM_SPS_MODE) &&
1797 (mReq->req.udc_priv & MSM_TBE))
1798 return -EBUSY;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301799 if (mReq->zptr) {
1800 if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
1801 return -EBUSY;
1802 dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
1803 mReq->zptr = NULL;
1804 }
David Lopoaa69a802008-11-17 14:14:51 -08001805
1806 mReq->req.status = 0;
1807
1808 if (mReq->map) {
1809 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
1810 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
1811 mReq->req.dma = 0;
1812 mReq->map = 0;
1813 }
1814
1815 mReq->req.status = mReq->ptr->token & TD_STATUS;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301816 if ((TD_STATUS_HALTED & mReq->req.status) != 0)
David Lopoaa69a802008-11-17 14:14:51 -08001817 mReq->req.status = -1;
1818 else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0)
1819 mReq->req.status = -1;
1820 else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0)
1821 mReq->req.status = -1;
1822
1823 mReq->req.actual = mReq->ptr->token & TD_TOTAL_BYTES;
1824 mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES);
1825 mReq->req.actual = mReq->req.length - mReq->req.actual;
1826 mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual;
1827
1828 return mReq->req.actual;
1829}
1830
1831/**
1832 * _ep_nuke: dequeues all endpoint requests
1833 * @mEp: endpoint
1834 *
1835 * This function returns an error code
1836 * Caller must hold lock
1837 */
1838static int _ep_nuke(struct ci13xxx_ep *mEp)
1839__releases(mEp->lock)
1840__acquires(mEp->lock)
1841{
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05301842 struct ci13xxx_ep *mEpTemp = mEp;
Ofir Cohena1c2a872011-12-14 10:26:34 +02001843 unsigned val;
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05301844
David Lopoaa69a802008-11-17 14:14:51 -08001845 trace("%p", mEp);
1846
1847 if (mEp == NULL)
1848 return -EINVAL;
1849
1850 hw_ep_flush(mEp->num, mEp->dir);
1851
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301852 while (!list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -08001853
1854 /* pop oldest request */
1855 struct ci13xxx_req *mReq = \
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301856 list_entry(mEp->qh.queue.next,
David Lopoaa69a802008-11-17 14:14:51 -08001857 struct ci13xxx_req, queue);
1858 list_del_init(&mReq->queue);
Ofir Cohena1c2a872011-12-14 10:26:34 +02001859
1860 /* MSM Specific: Clear end point proprietary register */
1861 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
1862 if (mReq->req.udc_priv & MSM_SPS_MODE) {
1863 val = hw_cread(CAP_ENDPTPIPEID +
1864 mEp->num * sizeof(u32),
1865 ~0);
1866
1867 if (val != MSM_EP_PIPE_ID_RESET_VAL)
1868 hw_cwrite(
1869 CAP_ENDPTPIPEID +
1870 mEp->num * sizeof(u32),
1871 ~0, MSM_EP_PIPE_ID_RESET_VAL);
1872 }
1873 }
David Lopoaa69a802008-11-17 14:14:51 -08001874 mReq->req.status = -ESHUTDOWN;
1875
Anji jonnalaea7bbc32011-12-26 16:39:53 +05301876 if (mReq->map) {
1877 dma_unmap_single(mEp->device, mReq->req.dma,
1878 mReq->req.length,
1879 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
1880 mReq->req.dma = 0;
1881 mReq->map = 0;
1882 }
1883
Artem Leonenko7c25a822010-12-14 23:46:55 -08001884 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08001885 spin_unlock(mEp->lock);
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05301886 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
1887 mReq->req.length)
1888 mEpTemp = &_udc->ep0in;
1889 mReq->req.complete(&mEpTemp->ep, &mReq->req);
David Lopoaa69a802008-11-17 14:14:51 -08001890 spin_lock(mEp->lock);
1891 }
1892 }
1893 return 0;
1894}
1895
1896/**
1897 * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
1898 * @gadget: gadget
1899 *
1900 * This function returns an error code
1901 * Caller must hold lock
1902 */
1903static int _gadget_stop_activity(struct usb_gadget *gadget)
David Lopoaa69a802008-11-17 14:14:51 -08001904{
1905 struct usb_ep *ep;
1906 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301907 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -08001908
1909 trace("%p", gadget);
1910
1911 if (gadget == NULL)
1912 return -EINVAL;
1913
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301914 spin_lock_irqsave(udc->lock, flags);
1915 udc->gadget.speed = USB_SPEED_UNKNOWN;
1916 udc->remote_wakeup = 0;
1917 udc->suspended = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001918 udc->configured = 0;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301919 spin_unlock_irqrestore(udc->lock, flags);
1920
David Lopoaa69a802008-11-17 14:14:51 -08001921 /* flush all endpoints */
1922 gadget_for_each_ep(ep, gadget) {
1923 usb_ep_fifo_flush(ep);
1924 }
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301925 usb_ep_fifo_flush(&udc->ep0out.ep);
1926 usb_ep_fifo_flush(&udc->ep0in.ep);
David Lopoaa69a802008-11-17 14:14:51 -08001927
1928 udc->driver->disconnect(gadget);
1929
1930 /* make sure to disable all endpoints */
1931 gadget_for_each_ep(ep, gadget) {
1932 usb_ep_disable(ep);
1933 }
David Lopoaa69a802008-11-17 14:14:51 -08001934
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301935 if (udc->status != NULL) {
1936 usb_ep_free_request(&udc->ep0in.ep, udc->status);
1937 udc->status = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08001938 }
1939
David Lopoaa69a802008-11-17 14:14:51 -08001940 return 0;
1941}
1942
1943/******************************************************************************
1944 * ISR block
1945 *****************************************************************************/
1946/**
1947 * isr_reset_handler: USB reset interrupt handler
1948 * @udc: UDC device
1949 *
1950 * This function resets USB engine after a bus reset occurred
1951 */
1952static void isr_reset_handler(struct ci13xxx *udc)
1953__releases(udc->lock)
1954__acquires(udc->lock)
1955{
David Lopoaa69a802008-11-17 14:14:51 -08001956 int retval;
1957
1958 trace("%p", udc);
1959
1960 if (udc == NULL) {
1961 err("EINVAL");
1962 return;
1963 }
1964
1965 dbg_event(0xFF, "BUS RST", 0);
1966
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301967 spin_unlock(udc->lock);
Anji jonnala8bbde012011-10-28 14:17:25 +05301968
1969 /*stop charging upon reset */
1970 if (udc->transceiver)
1971 otg_set_power(udc->transceiver, 0);
1972
David Lopoaa69a802008-11-17 14:14:51 -08001973 retval = _gadget_stop_activity(&udc->gadget);
1974 if (retval)
1975 goto done;
1976
1977 retval = hw_usb_reset();
1978 if (retval)
1979 goto done;
1980
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05301981 udc->status = usb_ep_alloc_request(&udc->ep0in.ep, GFP_ATOMIC);
1982 if (udc->status == NULL)
1983 retval = -ENOMEM;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301984
David Lopoaa69a802008-11-17 14:14:51 -08001985 spin_lock(udc->lock);
1986
1987 done:
1988 if (retval)
1989 err("error: %i", retval);
1990}
1991
1992/**
1993 * isr_get_status_complete: get_status request complete function
1994 * @ep: endpoint
1995 * @req: request handled
1996 *
1997 * Caller must release lock
1998 */
1999static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
2000{
2001 trace("%p, %p", ep, req);
2002
2003 if (ep == NULL || req == NULL) {
2004 err("EINVAL");
2005 return;
2006 }
2007
2008 kfree(req->buf);
2009 usb_ep_free_request(ep, req);
2010}
2011
2012/**
2013 * isr_get_status_response: get_status request response
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302014 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08002015 * @setup: setup request packet
2016 *
2017 * This function returns an error code
2018 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302019static int isr_get_status_response(struct ci13xxx *udc,
David Lopoaa69a802008-11-17 14:14:51 -08002020 struct usb_ctrlrequest *setup)
2021__releases(mEp->lock)
2022__acquires(mEp->lock)
2023{
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302024 struct ci13xxx_ep *mEp = &udc->ep0in;
David Lopoaa69a802008-11-17 14:14:51 -08002025 struct usb_request *req = NULL;
2026 gfp_t gfp_flags = GFP_ATOMIC;
2027 int dir, num, retval;
2028
2029 trace("%p, %p", mEp, setup);
2030
2031 if (mEp == NULL || setup == NULL)
2032 return -EINVAL;
2033
2034 spin_unlock(mEp->lock);
2035 req = usb_ep_alloc_request(&mEp->ep, gfp_flags);
2036 spin_lock(mEp->lock);
2037 if (req == NULL)
2038 return -ENOMEM;
2039
2040 req->complete = isr_get_status_complete;
2041 req->length = 2;
2042 req->buf = kzalloc(req->length, gfp_flags);
2043 if (req->buf == NULL) {
2044 retval = -ENOMEM;
2045 goto err_free_req;
2046 }
2047
2048 if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302049 /* Assume that device is bus powered for now. */
2050 *((u16 *)req->buf) = _udc->remote_wakeup << 1;
David Lopoaa69a802008-11-17 14:14:51 -08002051 retval = 0;
2052 } else if ((setup->bRequestType & USB_RECIP_MASK) \
2053 == USB_RECIP_ENDPOINT) {
2054 dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
2055 TX : RX;
2056 num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK;
2057 *((u16 *)req->buf) = hw_ep_get_halt(num, dir);
2058 }
2059 /* else do nothing; reserved for future use */
2060
2061 spin_unlock(mEp->lock);
2062 retval = usb_ep_queue(&mEp->ep, req, gfp_flags);
2063 spin_lock(mEp->lock);
2064 if (retval)
2065 goto err_free_buf;
2066
2067 return 0;
2068
2069 err_free_buf:
2070 kfree(req->buf);
2071 err_free_req:
2072 spin_unlock(mEp->lock);
2073 usb_ep_free_request(&mEp->ep, req);
2074 spin_lock(mEp->lock);
2075 return retval;
2076}
2077
2078/**
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302079 * isr_setup_status_complete: setup_status request complete function
2080 * @ep: endpoint
2081 * @req: request handled
2082 *
2083 * Caller must release lock. Put the port in test mode if test mode
2084 * feature is selected.
2085 */
2086static void
2087isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
2088{
2089 struct ci13xxx *udc = req->context;
2090 unsigned long flags;
2091
2092 trace("%p, %p", ep, req);
2093
2094 spin_lock_irqsave(udc->lock, flags);
2095 if (udc->test_mode)
2096 hw_port_test_set(udc->test_mode);
2097 spin_unlock_irqrestore(udc->lock, flags);
2098}
2099
2100/**
David Lopoaa69a802008-11-17 14:14:51 -08002101 * isr_setup_status_phase: queues the status phase of a setup transation
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302102 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08002103 *
2104 * This function returns an error code
2105 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302106static int isr_setup_status_phase(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -08002107__releases(mEp->lock)
2108__acquires(mEp->lock)
2109{
2110 int retval;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302111 struct ci13xxx_ep *mEp;
David Lopoaa69a802008-11-17 14:14:51 -08002112
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302113 trace("%p", udc);
David Lopoaa69a802008-11-17 14:14:51 -08002114
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302115 mEp = (udc->ep0_dir == TX) ? &udc->ep0out : &udc->ep0in;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302116 udc->status->context = udc;
2117 udc->status->complete = isr_setup_status_complete;
David Lopoaa69a802008-11-17 14:14:51 -08002118
2119 spin_unlock(mEp->lock);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302120 retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
David Lopoaa69a802008-11-17 14:14:51 -08002121 spin_lock(mEp->lock);
2122
2123 return retval;
2124}
2125
2126/**
2127 * isr_tr_complete_low: transaction complete low level handler
2128 * @mEp: endpoint
2129 *
2130 * This function returns an error code
2131 * Caller must hold lock
2132 */
2133static int isr_tr_complete_low(struct ci13xxx_ep *mEp)
2134__releases(mEp->lock)
2135__acquires(mEp->lock)
2136{
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302137 struct ci13xxx_req *mReq, *mReqTemp;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302138 struct ci13xxx_ep *mEpTemp = mEp;
Pavankumar Kondeti986b11b2011-05-02 11:56:29 +05302139 int uninitialized_var(retval);
Anji jonnala6fb918c2011-10-21 17:54:21 +05302140 int req_dequeue = 1;
2141 struct ci13xxx *udc = _udc;
David Lopoaa69a802008-11-17 14:14:51 -08002142
2143 trace("%p", mEp);
2144
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302145 if (list_empty(&mEp->qh.queue))
Anji jonnala6fb918c2011-10-21 17:54:21 +05302146 return 0;
David Lopoaa69a802008-11-17 14:14:51 -08002147
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302148 list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,
2149 queue) {
Anji jonnala6fb918c2011-10-21 17:54:21 +05302150dequeue:
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302151 retval = _hardware_dequeue(mEp, mReq);
Anji jonnala6fb918c2011-10-21 17:54:21 +05302152 if (retval < 0) {
2153 /*
2154 * FIXME: don't know exact delay
2155 * required for HW to update dTD status
2156 * bits. This is a temporary workaround till
2157 * HW designers come back on this.
2158 */
2159 if (retval == -EBUSY && req_dequeue && mEp->dir == 0) {
2160 req_dequeue = 0;
2161 udc->dTD_update_fail_count++;
2162 mEp->dTD_update_fail_count++;
2163 udelay(10);
2164 goto dequeue;
2165 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302166 break;
Anji jonnala6fb918c2011-10-21 17:54:21 +05302167 }
2168 req_dequeue = 0;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302169 list_del_init(&mReq->queue);
2170 dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
2171 if (mReq->req.complete != NULL) {
2172 spin_unlock(mEp->lock);
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302173 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
2174 mReq->req.length)
2175 mEpTemp = &_udc->ep0in;
2176 mReq->req.complete(&mEpTemp->ep, &mReq->req);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302177 spin_lock(mEp->lock);
2178 }
2179 }
David Lopoaa69a802008-11-17 14:14:51 -08002180
Pavankumar Kondetief907482011-05-02 11:56:27 +05302181 if (retval == -EBUSY)
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302182 retval = 0;
2183 if (retval < 0)
David Lopoaa69a802008-11-17 14:14:51 -08002184 dbg_event(_usb_addr(mEp), "DONE", retval);
David Lopoaa69a802008-11-17 14:14:51 -08002185
David Lopoaa69a802008-11-17 14:14:51 -08002186 return retval;
2187}
2188
2189/**
2190 * isr_tr_complete_handler: transaction complete interrupt handler
2191 * @udc: UDC descriptor
2192 *
2193 * This function handles traffic events
2194 */
2195static void isr_tr_complete_handler(struct ci13xxx *udc)
2196__releases(udc->lock)
2197__acquires(udc->lock)
2198{
2199 unsigned i;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302200 u8 tmode = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002201
2202 trace("%p", udc);
2203
2204 if (udc == NULL) {
2205 err("EINVAL");
2206 return;
2207 }
2208
2209 for (i = 0; i < hw_ep_max; i++) {
2210 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302211 int type, num, dir, err = -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -08002212 struct usb_ctrlrequest req;
2213
David Brownac5d1542012-02-06 10:37:22 -08002214 if (mEp->desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002215 continue; /* not configured */
2216
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302217 if (hw_test_and_clear_complete(i)) {
David Lopoaa69a802008-11-17 14:14:51 -08002218 err = isr_tr_complete_low(mEp);
2219 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
2220 if (err > 0) /* needs status phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302221 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002222 if (err < 0) {
2223 dbg_event(_usb_addr(mEp),
2224 "ERROR", err);
2225 spin_unlock(udc->lock);
2226 if (usb_ep_set_halt(&mEp->ep))
2227 err("error: ep_set_halt");
2228 spin_lock(udc->lock);
2229 }
2230 }
2231 }
2232
2233 if (mEp->type != USB_ENDPOINT_XFER_CONTROL ||
2234 !hw_test_and_clear_setup_status(i))
2235 continue;
2236
2237 if (i != 0) {
2238 warn("ctrl traffic received at endpoint");
2239 continue;
2240 }
2241
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302242 /*
2243 * Flush data and handshake transactions of previous
2244 * setup packet.
2245 */
2246 _ep_nuke(&udc->ep0out);
2247 _ep_nuke(&udc->ep0in);
2248
David Lopoaa69a802008-11-17 14:14:51 -08002249 /* read_setup_packet */
2250 do {
2251 hw_test_and_set_setup_guard();
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302252 memcpy(&req, &mEp->qh.ptr->setup, sizeof(req));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002253 /* Ensure buffer is read before acknowledging to h/w */
2254 mb();
David Lopoaa69a802008-11-17 14:14:51 -08002255 } while (!hw_test_and_clear_setup_guard());
2256
2257 type = req.bRequestType;
2258
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302259 udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
David Lopoaa69a802008-11-17 14:14:51 -08002260
2261 dbg_setup(_usb_addr(mEp), &req);
2262
2263 switch (req.bRequest) {
2264 case USB_REQ_CLEAR_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302265 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
2266 le16_to_cpu(req.wValue) ==
2267 USB_ENDPOINT_HALT) {
2268 if (req.wLength != 0)
David Lopoaa69a802008-11-17 14:14:51 -08002269 break;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302270 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302271 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302272 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302273 if (dir) /* TX */
2274 num += hw_ep_max/2;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302275 if (!udc->ci13xxx_ep[num].wedge) {
2276 spin_unlock(udc->lock);
2277 err = usb_ep_clear_halt(
2278 &udc->ci13xxx_ep[num].ep);
2279 spin_lock(udc->lock);
2280 if (err)
2281 break;
2282 }
2283 err = isr_setup_status_phase(udc);
2284 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
2285 le16_to_cpu(req.wValue) ==
2286 USB_DEVICE_REMOTE_WAKEUP) {
2287 if (req.wLength != 0)
2288 break;
2289 udc->remote_wakeup = 0;
2290 err = isr_setup_status_phase(udc);
2291 } else {
2292 goto delegate;
David Lopoaa69a802008-11-17 14:14:51 -08002293 }
David Lopoaa69a802008-11-17 14:14:51 -08002294 break;
2295 case USB_REQ_GET_STATUS:
2296 if (type != (USB_DIR_IN|USB_RECIP_DEVICE) &&
2297 type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
2298 type != (USB_DIR_IN|USB_RECIP_INTERFACE))
2299 goto delegate;
2300 if (le16_to_cpu(req.wLength) != 2 ||
2301 le16_to_cpu(req.wValue) != 0)
2302 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302303 err = isr_get_status_response(udc, &req);
David Lopoaa69a802008-11-17 14:14:51 -08002304 break;
2305 case USB_REQ_SET_ADDRESS:
2306 if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
2307 goto delegate;
2308 if (le16_to_cpu(req.wLength) != 0 ||
2309 le16_to_cpu(req.wIndex) != 0)
2310 break;
2311 err = hw_usb_set_address((u8)le16_to_cpu(req.wValue));
2312 if (err)
2313 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302314 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002315 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002316 case USB_REQ_SET_CONFIGURATION:
2317 if (type == (USB_DIR_OUT|USB_TYPE_STANDARD))
2318 udc->configured = !!req.wValue;
2319 goto delegate;
David Lopoaa69a802008-11-17 14:14:51 -08002320 case USB_REQ_SET_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302321 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
2322 le16_to_cpu(req.wValue) ==
2323 USB_ENDPOINT_HALT) {
2324 if (req.wLength != 0)
2325 break;
2326 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302327 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302328 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302329 if (dir) /* TX */
2330 num += hw_ep_max/2;
David Lopoaa69a802008-11-17 14:14:51 -08002331
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302332 spin_unlock(udc->lock);
2333 err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
2334 spin_lock(udc->lock);
2335 if (!err)
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302336 isr_setup_status_phase(udc);
2337 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302338 if (req.wLength != 0)
2339 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302340 switch (le16_to_cpu(req.wValue)) {
2341 case USB_DEVICE_REMOTE_WAKEUP:
2342 udc->remote_wakeup = 1;
2343 err = isr_setup_status_phase(udc);
2344 break;
2345 case USB_DEVICE_TEST_MODE:
2346 tmode = le16_to_cpu(req.wIndex) >> 8;
2347 switch (tmode) {
2348 case TEST_J:
2349 case TEST_K:
2350 case TEST_SE0_NAK:
2351 case TEST_PACKET:
2352 case TEST_FORCE_EN:
2353 udc->test_mode = tmode;
2354 err = isr_setup_status_phase(
2355 udc);
2356 break;
2357 default:
2358 break;
2359 }
2360 default:
2361 goto delegate;
2362 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302363 } else {
2364 goto delegate;
2365 }
David Lopoaa69a802008-11-17 14:14:51 -08002366 break;
2367 default:
2368delegate:
2369 if (req.wLength == 0) /* no data phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302370 udc->ep0_dir = TX;
David Lopoaa69a802008-11-17 14:14:51 -08002371
2372 spin_unlock(udc->lock);
2373 err = udc->driver->setup(&udc->gadget, &req);
2374 spin_lock(udc->lock);
2375 break;
2376 }
2377
2378 if (err < 0) {
2379 dbg_event(_usb_addr(mEp), "ERROR", err);
2380
2381 spin_unlock(udc->lock);
2382 if (usb_ep_set_halt(&mEp->ep))
2383 err("error: ep_set_halt");
2384 spin_lock(udc->lock);
2385 }
2386 }
2387}
2388
2389/******************************************************************************
2390 * ENDPT block
2391 *****************************************************************************/
2392/**
2393 * ep_enable: configure endpoint, making it usable
2394 *
2395 * Check usb_ep_enable() at "usb_gadget.h" for details
2396 */
2397static int ep_enable(struct usb_ep *ep,
2398 const struct usb_endpoint_descriptor *desc)
2399{
2400 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302401 int retval = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002402 unsigned long flags;
2403
2404 trace("%p, %p", ep, desc);
2405
2406 if (ep == NULL || desc == NULL)
2407 return -EINVAL;
2408
2409 spin_lock_irqsave(mEp->lock, flags);
2410
2411 /* only internal SW should enable ctrl endpts */
2412
David Brownac5d1542012-02-06 10:37:22 -08002413 mEp->desc = desc;
David Lopoaa69a802008-11-17 14:14:51 -08002414
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302415 if (!list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08002416 warn("enabling a non-empty endpoint!");
2417
Matthias Kaehlcke15739bb2009-04-15 22:28:41 +02002418 mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX;
2419 mEp->num = usb_endpoint_num(desc);
2420 mEp->type = usb_endpoint_type(desc);
David Lopoaa69a802008-11-17 14:14:51 -08002421
2422 mEp->ep.maxpacket = __constant_le16_to_cpu(desc->wMaxPacketSize);
2423
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302424 dbg_event(_usb_addr(mEp), "ENABLE", 0);
David Lopoaa69a802008-11-17 14:14:51 -08002425
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302426 mEp->qh.ptr->cap = 0;
David Lopof23e6492009-04-16 14:35:24 -07002427
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302428 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2429 mEp->qh.ptr->cap |= QH_IOS;
2430 else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
2431 mEp->qh.ptr->cap &= ~QH_MULT;
2432 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002433 mEp->qh.ptr->cap |= QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08002434
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302435 mEp->qh.ptr->cap |=
2436 (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
2437 mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */
David Lopoaa69a802008-11-17 14:14:51 -08002438
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002439 /* complete all the updates to ept->head before enabling endpoint*/
2440 mb();
2441
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302442 /*
2443 * Enable endpoints in the HW other than ep0 as ep0
2444 * is always enabled
2445 */
2446 if (mEp->num)
2447 retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type);
David Lopoaa69a802008-11-17 14:14:51 -08002448
2449 spin_unlock_irqrestore(mEp->lock, flags);
2450 return retval;
2451}
2452
2453/**
2454 * ep_disable: endpoint is no longer usable
2455 *
2456 * Check usb_ep_disable() at "usb_gadget.h" for details
2457 */
2458static int ep_disable(struct usb_ep *ep)
2459{
2460 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2461 int direction, retval = 0;
2462 unsigned long flags;
2463
2464 trace("%p", ep);
2465
2466 if (ep == NULL)
2467 return -EINVAL;
David Brownac5d1542012-02-06 10:37:22 -08002468 else if (mEp->desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002469 return -EBUSY;
2470
2471 spin_lock_irqsave(mEp->lock, flags);
2472
2473 /* only internal SW should disable ctrl endpts */
2474
2475 direction = mEp->dir;
2476 do {
2477 dbg_event(_usb_addr(mEp), "DISABLE", 0);
2478
2479 retval |= _ep_nuke(mEp);
2480 retval |= hw_ep_disable(mEp->num, mEp->dir);
2481
2482 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2483 mEp->dir = (mEp->dir == TX) ? RX : TX;
2484
2485 } while (mEp->dir != direction);
2486
David Brownac5d1542012-02-06 10:37:22 -08002487 mEp->desc = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002488
2489 spin_unlock_irqrestore(mEp->lock, flags);
2490 return retval;
2491}
2492
2493/**
2494 * ep_alloc_request: allocate a request object to use with this endpoint
2495 *
2496 * Check usb_ep_alloc_request() at "usb_gadget.h" for details
2497 */
2498static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
2499{
2500 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2501 struct ci13xxx_req *mReq = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002502
2503 trace("%p, %i", ep, gfp_flags);
2504
2505 if (ep == NULL) {
2506 err("EINVAL");
2507 return NULL;
2508 }
2509
David Lopoaa69a802008-11-17 14:14:51 -08002510 mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
2511 if (mReq != NULL) {
2512 INIT_LIST_HEAD(&mReq->queue);
2513
2514 mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,
2515 &mReq->dma);
2516 if (mReq->ptr == NULL) {
2517 kfree(mReq);
2518 mReq = NULL;
2519 }
2520 }
2521
2522 dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
2523
David Lopoaa69a802008-11-17 14:14:51 -08002524 return (mReq == NULL) ? NULL : &mReq->req;
2525}
2526
2527/**
2528 * ep_free_request: frees a request object
2529 *
2530 * Check usb_ep_free_request() at "usb_gadget.h" for details
2531 */
2532static void ep_free_request(struct usb_ep *ep, struct usb_request *req)
2533{
2534 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2535 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2536 unsigned long flags;
2537
2538 trace("%p, %p", ep, req);
2539
2540 if (ep == NULL || req == NULL) {
2541 err("EINVAL");
2542 return;
2543 } else if (!list_empty(&mReq->queue)) {
2544 err("EBUSY");
2545 return;
2546 }
2547
2548 spin_lock_irqsave(mEp->lock, flags);
2549
2550 if (mReq->ptr)
2551 dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma);
2552 kfree(mReq);
2553
2554 dbg_event(_usb_addr(mEp), "FREE", 0);
2555
2556 spin_unlock_irqrestore(mEp->lock, flags);
2557}
2558
2559/**
2560 * ep_queue: queues (submits) an I/O request to an endpoint
2561 *
2562 * Check usb_ep_queue()* at usb_gadget.h" for details
2563 */
2564static int ep_queue(struct usb_ep *ep, struct usb_request *req,
2565 gfp_t __maybe_unused gfp_flags)
2566{
2567 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2568 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2569 int retval = 0;
2570 unsigned long flags;
Anji jonnala6c174d42011-07-13 13:01:47 +05302571 struct ci13xxx *udc = _udc;
David Lopoaa69a802008-11-17 14:14:51 -08002572
2573 trace("%p, %p, %X", ep, req, gfp_flags);
2574
David Brownac5d1542012-02-06 10:37:22 -08002575 if (ep == NULL || req == NULL || mEp->desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002576 return -EINVAL;
2577
2578 spin_lock_irqsave(mEp->lock, flags);
2579
Anji jonnala6c174d42011-07-13 13:01:47 +05302580 if (!udc->configured && mEp->type !=
2581 USB_ENDPOINT_XFER_CONTROL) {
2582 spin_unlock_irqrestore(mEp->lock, flags);
2583 trace("usb is not configured"
2584 "ept #%d, ept name#%s\n",
2585 mEp->num, mEp->ep.name);
2586 return -ESHUTDOWN;
2587 }
2588
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302589 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
2590 if (req->length)
2591 mEp = (_udc->ep0_dir == RX) ?
2592 &_udc->ep0out : &_udc->ep0in;
2593 if (!list_empty(&mEp->qh.queue)) {
2594 _ep_nuke(mEp);
2595 retval = -EOVERFLOW;
2596 warn("endpoint ctrl %X nuked", _usb_addr(mEp));
2597 }
David Lopoaa69a802008-11-17 14:14:51 -08002598 }
2599
2600 /* first nuke then test link, e.g. previous status has not sent */
2601 if (!list_empty(&mReq->queue)) {
2602 retval = -EBUSY;
2603 err("request already in queue");
2604 goto done;
2605 }
2606
Artem Leonenko0a313c42010-12-14 23:47:06 -08002607 if (req->length > (4 * CI13XXX_PAGE_SIZE)) {
2608 req->length = (4 * CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08002609 retval = -EMSGSIZE;
2610 warn("request length truncated");
2611 }
2612
2613 dbg_queue(_usb_addr(mEp), req, retval);
2614
2615 /* push request */
2616 mReq->req.status = -EINPROGRESS;
2617 mReq->req.actual = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002618
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302619 retval = _hardware_enqueue(mEp, mReq);
Artem Leonenkod9bb9c12010-12-14 23:45:50 -08002620
2621 if (retval == -EALREADY) {
David Lopoaa69a802008-11-17 14:14:51 -08002622 dbg_event(_usb_addr(mEp), "QUEUE", retval);
2623 retval = 0;
2624 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302625 if (!retval)
2626 list_add_tail(&mReq->queue, &mEp->qh.queue);
David Lopoaa69a802008-11-17 14:14:51 -08002627
2628 done:
2629 spin_unlock_irqrestore(mEp->lock, flags);
2630 return retval;
2631}
2632
2633/**
2634 * ep_dequeue: dequeues (cancels, unlinks) an I/O request from an endpoint
2635 *
2636 * Check usb_ep_dequeue() at "usb_gadget.h" for details
2637 */
2638static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
2639{
2640 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05302641 struct ci13xxx_ep *mEpTemp = mEp;
David Lopoaa69a802008-11-17 14:14:51 -08002642 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2643 unsigned long flags;
2644
2645 trace("%p, %p", ep, req);
2646
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302647 if (ep == NULL || req == NULL || mReq->req.status != -EALREADY ||
David Brownac5d1542012-02-06 10:37:22 -08002648 mEp->desc == NULL || list_empty(&mReq->queue) ||
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302649 list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08002650 return -EINVAL;
2651
2652 spin_lock_irqsave(mEp->lock, flags);
2653
2654 dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
2655
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302656 hw_ep_flush(mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08002657
2658 /* pop request */
2659 list_del_init(&mReq->queue);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302660 if (mReq->map) {
2661 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
2662 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
2663 mReq->req.dma = 0;
2664 mReq->map = 0;
2665 }
David Lopoaa69a802008-11-17 14:14:51 -08002666 req->status = -ECONNRESET;
2667
Artem Leonenko7c25a822010-12-14 23:46:55 -08002668 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08002669 spin_unlock(mEp->lock);
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05302670 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
2671 mReq->req.length)
2672 mEpTemp = &_udc->ep0in;
2673 mReq->req.complete(&mEpTemp->ep, &mReq->req);
David Lopoaa69a802008-11-17 14:14:51 -08002674 spin_lock(mEp->lock);
2675 }
2676
2677 spin_unlock_irqrestore(mEp->lock, flags);
2678 return 0;
2679}
2680
2681/**
2682 * ep_set_halt: sets the endpoint halt feature
2683 *
2684 * Check usb_ep_set_halt() at "usb_gadget.h" for details
2685 */
2686static int ep_set_halt(struct usb_ep *ep, int value)
2687{
2688 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2689 int direction, retval = 0;
2690 unsigned long flags;
2691
2692 trace("%p, %i", ep, value);
2693
David Brownac5d1542012-02-06 10:37:22 -08002694 if (ep == NULL || mEp->desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002695 return -EINVAL;
2696
2697 spin_lock_irqsave(mEp->lock, flags);
2698
2699#ifndef STALL_IN
2700 /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
2701 if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX &&
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302702 !list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -08002703 spin_unlock_irqrestore(mEp->lock, flags);
2704 return -EAGAIN;
2705 }
2706#endif
2707
2708 direction = mEp->dir;
2709 do {
2710 dbg_event(_usb_addr(mEp), "HALT", value);
2711 retval |= hw_ep_set_halt(mEp->num, mEp->dir, value);
2712
2713 if (!value)
2714 mEp->wedge = 0;
2715
2716 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2717 mEp->dir = (mEp->dir == TX) ? RX : TX;
2718
2719 } while (mEp->dir != direction);
2720
2721 spin_unlock_irqrestore(mEp->lock, flags);
2722 return retval;
2723}
2724
2725/**
2726 * ep_set_wedge: sets the halt feature and ignores clear requests
2727 *
2728 * Check usb_ep_set_wedge() at "usb_gadget.h" for details
2729 */
2730static int ep_set_wedge(struct usb_ep *ep)
2731{
2732 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2733 unsigned long flags;
2734
2735 trace("%p", ep);
2736
David Brownac5d1542012-02-06 10:37:22 -08002737 if (ep == NULL || mEp->desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002738 return -EINVAL;
2739
2740 spin_lock_irqsave(mEp->lock, flags);
2741
2742 dbg_event(_usb_addr(mEp), "WEDGE", 0);
2743 mEp->wedge = 1;
2744
2745 spin_unlock_irqrestore(mEp->lock, flags);
2746
2747 return usb_ep_set_halt(ep);
2748}
2749
2750/**
2751 * ep_fifo_flush: flushes contents of a fifo
2752 *
2753 * Check usb_ep_fifo_flush() at "usb_gadget.h" for details
2754 */
2755static void ep_fifo_flush(struct usb_ep *ep)
2756{
2757 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2758 unsigned long flags;
2759
2760 trace("%p", ep);
2761
2762 if (ep == NULL) {
2763 err("%02X: -EINVAL", _usb_addr(mEp));
2764 return;
2765 }
2766
2767 spin_lock_irqsave(mEp->lock, flags);
2768
2769 dbg_event(_usb_addr(mEp), "FFLUSH", 0);
2770 hw_ep_flush(mEp->num, mEp->dir);
2771
2772 spin_unlock_irqrestore(mEp->lock, flags);
2773}
2774
2775/**
2776 * Endpoint-specific part of the API to the USB controller hardware
2777 * Check "usb_gadget.h" for details
2778 */
2779static const struct usb_ep_ops usb_ep_ops = {
2780 .enable = ep_enable,
2781 .disable = ep_disable,
2782 .alloc_request = ep_alloc_request,
2783 .free_request = ep_free_request,
2784 .queue = ep_queue,
2785 .dequeue = ep_dequeue,
2786 .set_halt = ep_set_halt,
2787 .set_wedge = ep_set_wedge,
2788 .fifo_flush = ep_fifo_flush,
2789};
2790
2791/******************************************************************************
2792 * GADGET block
2793 *****************************************************************************/
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302794static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
2795{
2796 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2797 unsigned long flags;
2798 int gadget_ready = 0;
2799
2800 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS))
2801 return -EOPNOTSUPP;
2802
2803 spin_lock_irqsave(udc->lock, flags);
2804 udc->vbus_active = is_active;
2805 if (udc->driver)
2806 gadget_ready = 1;
2807 spin_unlock_irqrestore(udc->lock, flags);
2808
2809 if (gadget_ready) {
2810 if (is_active) {
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302811 pm_runtime_get_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302812 hw_device_reset(udc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002813 if (udc->softconnect)
2814 hw_device_state(udc->ep0out.qh.dma);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302815 } else {
2816 hw_device_state(0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302817 _gadget_stop_activity(&udc->gadget);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302818 pm_runtime_put_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302819 }
2820 }
2821
2822 return 0;
2823}
2824
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302825static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
2826{
2827 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2828
2829 if (udc->transceiver)
2830 return otg_set_power(udc->transceiver, mA);
2831 return -ENOTSUPP;
2832}
2833
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002834static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_active)
2835{
2836 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2837 unsigned long flags;
2838
2839 spin_lock_irqsave(udc->lock, flags);
2840 udc->softconnect = is_active;
2841 if (((udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) &&
2842 !udc->vbus_active) || !udc->driver) {
2843 spin_unlock_irqrestore(udc->lock, flags);
2844 return 0;
2845 }
2846 spin_unlock_irqrestore(udc->lock, flags);
2847
Ofir Cohen06789f12012-01-16 09:43:13 +02002848 if (is_active) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002849 hw_device_state(udc->ep0out.qh.dma);
Ofir Cohen06789f12012-01-16 09:43:13 +02002850 if (udc->udc_driver->notify_event)
2851 udc->udc_driver->notify_event(udc,
2852 CI13XXX_CONTROLLER_CONNECT_EVENT);
2853 }
Pavankumar Kondetib7f53dc2011-08-23 12:40:33 +05302854 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002855 hw_device_state(0);
Pavankumar Kondetib7f53dc2011-08-23 12:40:33 +05302856
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002857 return 0;
2858}
2859
David Brownac5d1542012-02-06 10:37:22 -08002860
David Lopoaa69a802008-11-17 14:14:51 -08002861/**
2862 * Device operations part of the API to the USB controller hardware,
2863 * which don't involve endpoints (or i/o)
2864 * Check "usb_gadget.h" for details
2865 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302866static const struct usb_gadget_ops usb_gadget_ops = {
2867 .vbus_session = ci13xxx_vbus_session,
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302868 .wakeup = ci13xxx_wakeup,
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302869 .vbus_draw = ci13xxx_vbus_draw,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002870 .pullup = ci13xxx_pullup,
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302871};
David Lopoaa69a802008-11-17 14:14:51 -08002872
2873/**
David Brownac5d1542012-02-06 10:37:22 -08002874 * usb_gadget_probe_driver: register a gadget driver
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002875 * @driver: the driver being registered
2876 * @bind: the driver's bind callback
David Lopoaa69a802008-11-17 14:14:51 -08002877 *
David Brownac5d1542012-02-06 10:37:22 -08002878 * Check usb_gadget_probe_driver() at <linux/usb/gadget.h> for details.
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002879 * Interrupts are enabled here.
David Lopoaa69a802008-11-17 14:14:51 -08002880 */
David Brownac5d1542012-02-06 10:37:22 -08002881int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002882 int (*bind)(struct usb_gadget *))
David Lopoaa69a802008-11-17 14:14:51 -08002883{
2884 struct ci13xxx *udc = _udc;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302885 unsigned long flags;
2886 int i, j;
David Lopoaa69a802008-11-17 14:14:51 -08002887 int retval = -ENOMEM;
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05302888 bool put = false;
David Lopoaa69a802008-11-17 14:14:51 -08002889
2890 trace("%p", driver);
2891
2892 if (driver == NULL ||
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002893 bind == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08002894 driver->setup == NULL ||
2895 driver->disconnect == NULL ||
2896 driver->suspend == NULL ||
2897 driver->resume == NULL)
2898 return -EINVAL;
2899 else if (udc == NULL)
2900 return -ENODEV;
2901 else if (udc->driver != NULL)
2902 return -EBUSY;
2903
2904 /* alloc resources */
2905 udc->qh_pool = dma_pool_create("ci13xxx_qh", &udc->gadget.dev,
2906 sizeof(struct ci13xxx_qh),
Artem Leonenko0a313c42010-12-14 23:47:06 -08002907 64, CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08002908 if (udc->qh_pool == NULL)
2909 return -ENOMEM;
2910
2911 udc->td_pool = dma_pool_create("ci13xxx_td", &udc->gadget.dev,
2912 sizeof(struct ci13xxx_td),
Artem Leonenko0a313c42010-12-14 23:47:06 -08002913 64, CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08002914 if (udc->td_pool == NULL) {
2915 dma_pool_destroy(udc->qh_pool);
2916 udc->qh_pool = NULL;
2917 return -ENOMEM;
2918 }
2919
2920 spin_lock_irqsave(udc->lock, flags);
2921
2922 info("hw_ep_max = %d", hw_ep_max);
2923
David Lopoaa69a802008-11-17 14:14:51 -08002924 udc->gadget.dev.driver = NULL;
2925
2926 retval = 0;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302927 for (i = 0; i < hw_ep_max/2; i++) {
2928 for (j = RX; j <= TX; j++) {
2929 int k = i + j * hw_ep_max/2;
2930 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
David Lopoaa69a802008-11-17 14:14:51 -08002931
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302932 scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
2933 (j == TX) ? "in" : "out");
David Lopoaa69a802008-11-17 14:14:51 -08002934
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302935 mEp->lock = udc->lock;
2936 mEp->device = &udc->gadget.dev;
2937 mEp->td_pool = udc->td_pool;
David Lopoaa69a802008-11-17 14:14:51 -08002938
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302939 mEp->ep.name = mEp->name;
2940 mEp->ep.ops = &usb_ep_ops;
2941 mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
David Lopoaa69a802008-11-17 14:14:51 -08002942
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302943 INIT_LIST_HEAD(&mEp->qh.queue);
Pavankumar Kondeti0a91efa2010-12-07 17:54:00 +05302944 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302945 mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
2946 &mEp->qh.dma);
Pavankumar Kondeti0a91efa2010-12-07 17:54:00 +05302947 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302948 if (mEp->qh.ptr == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002949 retval = -ENOMEM;
2950 else
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302951 memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
2952
2953 /* skip ep0 out and in endpoints */
2954 if (i == 0)
2955 continue;
2956
David Lopoaa69a802008-11-17 14:14:51 -08002957 list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302958 }
David Lopoaa69a802008-11-17 14:14:51 -08002959 }
2960 if (retval)
2961 goto done;
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302962 spin_unlock_irqrestore(udc->lock, flags);
David Brownac5d1542012-02-06 10:37:22 -08002963 retval = usb_ep_enable(&udc->ep0out.ep, &ctrl_endpt_out_desc);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302964 if (retval)
2965 return retval;
David Brownac5d1542012-02-06 10:37:22 -08002966 retval = usb_ep_enable(&udc->ep0in.ep, &ctrl_endpt_in_desc);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302967 if (retval)
2968 return retval;
2969 spin_lock_irqsave(udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002970
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302971 udc->gadget.ep0 = &udc->ep0in.ep;
David Lopoaa69a802008-11-17 14:14:51 -08002972 /* bind gadget */
2973 driver->driver.bus = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002974 udc->gadget.dev.driver = &driver->driver;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002975 udc->softconnect = 1;
David Lopoaa69a802008-11-17 14:14:51 -08002976
2977 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondeti98853282011-11-24 09:01:54 +05302978 pm_runtime_get_sync(&udc->gadget.dev);
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002979 retval = bind(&udc->gadget); /* MAY SLEEP */
David Lopoaa69a802008-11-17 14:14:51 -08002980 spin_lock_irqsave(udc->lock, flags);
2981
2982 if (retval) {
David Lopoaa69a802008-11-17 14:14:51 -08002983 udc->gadget.dev.driver = NULL;
2984 goto done;
2985 }
2986
Pavankumar Kondeti49d3df52011-01-11 09:19:21 +05302987 udc->driver = driver;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302988 if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
2989 if (udc->vbus_active) {
2990 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
2991 hw_device_reset(udc);
2992 } else {
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05302993 put = true;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302994 goto done;
2995 }
2996 }
2997
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05302998 if (!udc->softconnect) {
2999 put = true;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003000 goto done;
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303001 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003002
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303003 retval = hw_device_state(udc->ep0out.qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08003004
3005 done:
3006 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05303007 if (retval || put)
Pavankumar Kondeti98853282011-11-24 09:01:54 +05303008 pm_runtime_put_sync(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08003009 return retval;
3010}
David Brownac5d1542012-02-06 10:37:22 -08003011EXPORT_SYMBOL(usb_gadget_probe_driver);
David Lopoaa69a802008-11-17 14:14:51 -08003012
3013/**
David Brownac5d1542012-02-06 10:37:22 -08003014 * usb_gadget_unregister_driver: unregister a gadget driver
David Lopoaa69a802008-11-17 14:14:51 -08003015 *
3016 * Check usb_gadget_unregister_driver() at "usb_gadget.h" for details
3017 */
David Brownac5d1542012-02-06 10:37:22 -08003018int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
David Lopoaa69a802008-11-17 14:14:51 -08003019{
3020 struct ci13xxx *udc = _udc;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303021 unsigned long i, flags;
David Lopoaa69a802008-11-17 14:14:51 -08003022
3023 trace("%p", driver);
3024
3025 if (driver == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08003026 driver->unbind == NULL ||
3027 driver->setup == NULL ||
3028 driver->disconnect == NULL ||
3029 driver->suspend == NULL ||
3030 driver->resume == NULL ||
3031 driver != udc->driver)
3032 return -EINVAL;
3033
3034 spin_lock_irqsave(udc->lock, flags);
3035
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303036 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) ||
3037 udc->vbus_active) {
3038 hw_device_state(0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303039 _gadget_stop_activity(&udc->gadget);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05303040 pm_runtime_put(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303041 }
David Lopoaa69a802008-11-17 14:14:51 -08003042
3043 /* unbind gadget */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303044 spin_unlock_irqrestore(udc->lock, flags);
3045 driver->unbind(&udc->gadget); /* MAY SLEEP */
3046 spin_lock_irqsave(udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08003047
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303048 udc->gadget.dev.driver = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08003049
3050 /* free resources */
3051 for (i = 0; i < hw_ep_max; i++) {
3052 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
3053
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303054 if (!list_empty(&mEp->ep.ep_list))
David Lopoaa69a802008-11-17 14:14:51 -08003055 list_del_init(&mEp->ep.ep_list);
3056
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303057 if (mEp->qh.ptr != NULL)
3058 dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08003059 }
3060
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303061 udc->gadget.ep0 = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08003062 udc->driver = NULL;
3063
3064 spin_unlock_irqrestore(udc->lock, flags);
3065
3066 if (udc->td_pool != NULL) {
3067 dma_pool_destroy(udc->td_pool);
3068 udc->td_pool = NULL;
3069 }
3070 if (udc->qh_pool != NULL) {
3071 dma_pool_destroy(udc->qh_pool);
3072 udc->qh_pool = NULL;
3073 }
3074
3075 return 0;
3076}
David Brownac5d1542012-02-06 10:37:22 -08003077EXPORT_SYMBOL(usb_gadget_unregister_driver);
David Lopoaa69a802008-11-17 14:14:51 -08003078
3079/******************************************************************************
3080 * BUS block
3081 *****************************************************************************/
3082/**
3083 * udc_irq: global interrupt handler
3084 *
3085 * This function returns IRQ_HANDLED if the IRQ has been handled
3086 * It locks access to registers
3087 */
3088static irqreturn_t udc_irq(void)
3089{
3090 struct ci13xxx *udc = _udc;
3091 irqreturn_t retval;
3092 u32 intr;
3093
3094 trace();
3095
3096 if (udc == NULL) {
3097 err("ENODEV");
3098 return IRQ_HANDLED;
3099 }
3100
3101 spin_lock(udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303102
3103 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) {
3104 if (hw_cread(CAP_USBMODE, USBMODE_CM) !=
3105 USBMODE_CM_DEVICE) {
3106 spin_unlock(udc->lock);
3107 return IRQ_NONE;
3108 }
3109 }
David Lopoaa69a802008-11-17 14:14:51 -08003110 intr = hw_test_and_clear_intr_active();
3111 if (intr) {
3112 isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intr;
3113 isr_statistics.hndl.idx &= ISR_MASK;
3114 isr_statistics.hndl.cnt++;
3115
3116 /* order defines priority - do NOT change it */
3117 if (USBi_URI & intr) {
3118 isr_statistics.uri++;
3119 isr_reset_handler(udc);
3120 }
3121 if (USBi_PCI & intr) {
3122 isr_statistics.pci++;
3123 udc->gadget.speed = hw_port_is_high_speed() ?
3124 USB_SPEED_HIGH : USB_SPEED_FULL;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05303125 if (udc->suspended) {
3126 spin_unlock(udc->lock);
3127 udc->driver->resume(&udc->gadget);
3128 spin_lock(udc->lock);
3129 udc->suspended = 0;
3130 }
David Lopoaa69a802008-11-17 14:14:51 -08003131 }
3132 if (USBi_UEI & intr)
3133 isr_statistics.uei++;
3134 if (USBi_UI & intr) {
3135 isr_statistics.ui++;
3136 isr_tr_complete_handler(udc);
3137 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05303138 if (USBi_SLI & intr) {
3139 if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
3140 udc->suspended = 1;
3141 spin_unlock(udc->lock);
3142 udc->driver->suspend(&udc->gadget);
3143 spin_lock(udc->lock);
3144 }
David Lopoaa69a802008-11-17 14:14:51 -08003145 isr_statistics.sli++;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05303146 }
David Lopoaa69a802008-11-17 14:14:51 -08003147 retval = IRQ_HANDLED;
3148 } else {
3149 isr_statistics.none++;
3150 retval = IRQ_NONE;
3151 }
3152 spin_unlock(udc->lock);
3153
3154 return retval;
3155}
3156
3157/**
3158 * udc_release: driver release function
3159 * @dev: device
3160 *
3161 * Currently does nothing
3162 */
3163static void udc_release(struct device *dev)
3164{
3165 trace("%p", dev);
3166
3167 if (dev == NULL)
3168 err("EINVAL");
3169}
3170
3171/**
3172 * udc_probe: parent probe must call this to initialize UDC
3173 * @dev: parent device
3174 * @regs: registers base address
3175 * @name: driver name
3176 *
3177 * This function returns an error code
3178 * No interrupts active, the IRQ has not been requested yet
3179 * Kernel assumes 32-bit DMA operations by default, no need to dma_set_mask
3180 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303181static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
3182 void __iomem *regs)
David Lopoaa69a802008-11-17 14:14:51 -08003183{
3184 struct ci13xxx *udc;
3185 int retval = 0;
3186
3187 trace("%p, %p, %p", dev, regs, name);
3188
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303189 if (dev == NULL || regs == NULL || driver == NULL ||
3190 driver->name == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08003191 return -EINVAL;
3192
3193 udc = kzalloc(sizeof(struct ci13xxx), GFP_KERNEL);
3194 if (udc == NULL)
3195 return -ENOMEM;
3196
3197 udc->lock = &udc_lock;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303198 udc->regs = regs;
3199 udc->udc_driver = driver;
David Lopoaa69a802008-11-17 14:14:51 -08003200
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303201 udc->gadget.ops = &usb_gadget_ops;
David Lopoaa69a802008-11-17 14:14:51 -08003202 udc->gadget.speed = USB_SPEED_UNKNOWN;
3203 udc->gadget.is_dualspeed = 1;
3204 udc->gadget.is_otg = 0;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303205 udc->gadget.name = driver->name;
David Lopoaa69a802008-11-17 14:14:51 -08003206
3207 INIT_LIST_HEAD(&udc->gadget.ep_list);
3208 udc->gadget.ep0 = NULL;
3209
Kay Sievers5df58522009-03-24 16:38:23 -07003210 dev_set_name(&udc->gadget.dev, "gadget");
David Lopoaa69a802008-11-17 14:14:51 -08003211 udc->gadget.dev.dma_mask = dev->dma_mask;
Pavankumar Kondeti61948ee2010-12-07 17:54:01 +05303212 udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
David Lopoaa69a802008-11-17 14:14:51 -08003213 udc->gadget.dev.parent = dev;
3214 udc->gadget.dev.release = udc_release;
3215
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303216 retval = hw_device_init(regs);
3217 if (retval < 0)
3218 goto free_udc;
3219
3220 udc->transceiver = otg_get_transceiver();
3221
3222 if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
3223 if (udc->transceiver == NULL) {
3224 retval = -ENODEV;
3225 goto free_udc;
3226 }
3227 }
3228
3229 if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) {
3230 retval = hw_device_reset(udc);
3231 if (retval)
3232 goto put_transceiver;
3233 }
3234
David Lopoaa69a802008-11-17 14:14:51 -08003235 retval = device_register(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303236 if (retval) {
3237 put_device(&udc->gadget.dev);
3238 goto put_transceiver;
3239 }
David Lopoaa69a802008-11-17 14:14:51 -08003240
3241#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3242 retval = dbg_create_files(&udc->gadget.dev);
3243#endif
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303244 if (retval)
3245 goto unreg_device;
3246
3247 if (udc->transceiver) {
3248 retval = otg_set_peripheral(udc->transceiver, &udc->gadget);
3249 if (retval)
3250 goto remove_dbg;
David Lopoaa69a802008-11-17 14:14:51 -08003251 }
Pavankumar Kondetic0360192010-12-07 17:54:04 +05303252 pm_runtime_no_callbacks(&udc->gadget.dev);
3253 pm_runtime_enable(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08003254
3255 _udc = udc;
3256 return retval;
3257
David Lopoaa69a802008-11-17 14:14:51 -08003258 err("error = %i", retval);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303259remove_dbg:
3260#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3261 dbg_remove_files(&udc->gadget.dev);
3262#endif
3263unreg_device:
3264 device_unregister(&udc->gadget.dev);
3265put_transceiver:
3266 if (udc->transceiver)
3267 otg_put_transceiver(udc->transceiver);
3268free_udc:
David Lopoaa69a802008-11-17 14:14:51 -08003269 kfree(udc);
3270 _udc = NULL;
3271 return retval;
3272}
3273
3274/**
3275 * udc_remove: parent remove must call this to remove UDC
3276 *
3277 * No interrupts active, the IRQ has been released
3278 */
3279static void udc_remove(void)
3280{
3281 struct ci13xxx *udc = _udc;
3282
3283 if (udc == NULL) {
3284 err("EINVAL");
3285 return;
3286 }
3287
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303288 if (udc->transceiver) {
3289 otg_set_peripheral(udc->transceiver, &udc->gadget);
3290 otg_put_transceiver(udc->transceiver);
3291 }
David Lopoaa69a802008-11-17 14:14:51 -08003292#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3293 dbg_remove_files(&udc->gadget.dev);
3294#endif
3295 device_unregister(&udc->gadget.dev);
3296
3297 kfree(udc);
3298 _udc = NULL;
3299}