blob: 6282389a214a0454881c9afb1837106acdd2a1c1 [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
861/**
862 * dbg_print: prints the common part of the event
863 * @addr: endpoint address
864 * @name: event name
865 * @status: status
866 * @extra: extra information
867 */
868static void dbg_print(u8 addr, const char *name, int status, const char *extra)
869{
870 struct timeval tval;
871 unsigned int stamp;
872 unsigned long flags;
873
874 write_lock_irqsave(&dbg_data.lck, flags);
875
876 do_gettimeofday(&tval);
877 stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s */
878 stamp = stamp * 1000000 + tval.tv_usec;
879
880 scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
881 "%04X\t» %02X %-7.7s %4i «\t%s\n",
882 stamp, addr, name, status, extra);
883
884 dbg_inc(&dbg_data.idx);
885
886 write_unlock_irqrestore(&dbg_data.lck, flags);
887
888 if (dbg_data.tty != 0)
889 pr_notice("%04X\t» %02X %-7.7s %4i «\t%s\n",
890 stamp, addr, name, status, extra);
891}
892
893/**
894 * dbg_done: prints a DONE event
895 * @addr: endpoint address
896 * @td: transfer descriptor
897 * @status: status
898 */
899static void dbg_done(u8 addr, const u32 token, int status)
900{
901 char msg[DBG_DATA_MSG];
902
903 scnprintf(msg, sizeof(msg), "%d %02X",
904 (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES),
905 (int)(token & TD_STATUS) >> ffs_nr(TD_STATUS));
906 dbg_print(addr, "DONE", status, msg);
907}
908
909/**
910 * dbg_event: prints a generic event
911 * @addr: endpoint address
912 * @name: event name
913 * @status: status
914 */
915static void dbg_event(u8 addr, const char *name, int status)
916{
917 if (name != NULL)
918 dbg_print(addr, name, status, "");
919}
920
921/*
922 * dbg_queue: prints a QUEUE event
923 * @addr: endpoint address
924 * @req: USB request
925 * @status: status
926 */
927static void dbg_queue(u8 addr, const struct usb_request *req, int status)
928{
929 char msg[DBG_DATA_MSG];
930
931 if (req != NULL) {
932 scnprintf(msg, sizeof(msg),
933 "%d %d", !req->no_interrupt, req->length);
934 dbg_print(addr, "QUEUE", status, msg);
935 }
936}
937
938/**
939 * dbg_setup: prints a SETUP event
940 * @addr: endpoint address
941 * @req: setup request
942 */
943static void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
944{
945 char msg[DBG_DATA_MSG];
946
947 if (req != NULL) {
948 scnprintf(msg, sizeof(msg),
949 "%02X %02X %04X %04X %d", req->bRequestType,
950 req->bRequest, le16_to_cpu(req->wValue),
951 le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
952 dbg_print(addr, "SETUP", 0, msg);
953 }
954}
955
956/**
957 * show_events: displays the event buffer
958 *
959 * Check "device.h" for details
960 */
961static ssize_t show_events(struct device *dev, struct device_attribute *attr,
962 char *buf)
963{
964 unsigned long flags;
965 unsigned i, j, n = 0;
966
967 dbg_trace("[%s] %p\n", __func__, buf);
968 if (attr == NULL || buf == NULL) {
969 dev_err(dev, "[%s] EINVAL\n", __func__);
970 return 0;
971 }
972
973 read_lock_irqsave(&dbg_data.lck, flags);
974
975 i = dbg_data.idx;
976 for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) {
977 n += strlen(dbg_data.buf[i]);
978 if (n >= PAGE_SIZE) {
979 n -= strlen(dbg_data.buf[i]);
980 break;
981 }
982 }
983 for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i))
984 j += scnprintf(buf + j, PAGE_SIZE - j,
985 "%s", dbg_data.buf[i]);
986
987 read_unlock_irqrestore(&dbg_data.lck, flags);
988
989 return n;
990}
991
992/**
993 * store_events: configure if events are going to be also printed to console
994 *
995 * Check "device.h" for details
996 */
997static ssize_t store_events(struct device *dev, struct device_attribute *attr,
998 const char *buf, size_t count)
999{
1000 unsigned tty;
1001
1002 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1003 if (attr == NULL || buf == NULL) {
1004 dev_err(dev, "[%s] EINVAL\n", __func__);
1005 goto done;
1006 }
1007
1008 if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
1009 dev_err(dev, "<1|0>: enable|disable console log\n");
1010 goto done;
1011 }
1012
1013 dbg_data.tty = tty;
1014 dev_info(dev, "tty = %u", dbg_data.tty);
1015
1016 done:
1017 return count;
1018}
1019static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
1020
1021/**
1022 * show_inters: interrupt status, enable status and historic
1023 *
1024 * Check "device.h" for details
1025 */
1026static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
1027 char *buf)
1028{
1029 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1030 unsigned long flags;
1031 u32 intr;
1032 unsigned i, j, n = 0;
1033
1034 dbg_trace("[%s] %p\n", __func__, buf);
1035 if (attr == NULL || buf == NULL) {
1036 dev_err(dev, "[%s] EINVAL\n", __func__);
1037 return 0;
1038 }
1039
1040 spin_lock_irqsave(udc->lock, flags);
1041
1042 n += scnprintf(buf + n, PAGE_SIZE - n,
1043 "status = %08x\n", hw_read_intr_status());
1044 n += scnprintf(buf + n, PAGE_SIZE - n,
1045 "enable = %08x\n", hw_read_intr_enable());
1046
1047 n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
1048 isr_statistics.test);
1049 n += scnprintf(buf + n, PAGE_SIZE - n, "» ui = %d\n",
1050 isr_statistics.ui);
1051 n += scnprintf(buf + n, PAGE_SIZE - n, "» uei = %d\n",
1052 isr_statistics.uei);
1053 n += scnprintf(buf + n, PAGE_SIZE - n, "» pci = %d\n",
1054 isr_statistics.pci);
1055 n += scnprintf(buf + n, PAGE_SIZE - n, "» uri = %d\n",
1056 isr_statistics.uri);
1057 n += scnprintf(buf + n, PAGE_SIZE - n, "» sli = %d\n",
1058 isr_statistics.sli);
1059 n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n",
1060 isr_statistics.none);
1061 n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n",
1062 isr_statistics.hndl.cnt);
1063
1064 for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) {
1065 i &= ISR_MASK;
1066 intr = isr_statistics.hndl.buf[i];
1067
1068 if (USBi_UI & intr)
1069 n += scnprintf(buf + n, PAGE_SIZE - n, "ui ");
1070 intr &= ~USBi_UI;
1071 if (USBi_UEI & intr)
1072 n += scnprintf(buf + n, PAGE_SIZE - n, "uei ");
1073 intr &= ~USBi_UEI;
1074 if (USBi_PCI & intr)
1075 n += scnprintf(buf + n, PAGE_SIZE - n, "pci ");
1076 intr &= ~USBi_PCI;
1077 if (USBi_URI & intr)
1078 n += scnprintf(buf + n, PAGE_SIZE - n, "uri ");
1079 intr &= ~USBi_URI;
1080 if (USBi_SLI & intr)
1081 n += scnprintf(buf + n, PAGE_SIZE - n, "sli ");
1082 intr &= ~USBi_SLI;
1083 if (intr)
1084 n += scnprintf(buf + n, PAGE_SIZE - n, "??? ");
1085 if (isr_statistics.hndl.buf[i])
1086 n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
1087 }
1088
1089 spin_unlock_irqrestore(udc->lock, flags);
1090
1091 return n;
1092}
1093
1094/**
1095 * store_inters: enable & force or disable an individual interrutps
1096 * (to be used for test purposes only)
1097 *
1098 * Check "device.h" for details
1099 */
1100static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
1101 const char *buf, size_t count)
1102{
1103 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1104 unsigned long flags;
1105 unsigned en, bit;
1106
1107 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1108 if (attr == NULL || buf == NULL) {
1109 dev_err(dev, "[%s] EINVAL\n", __func__);
1110 goto done;
1111 }
1112
1113 if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
1114 dev_err(dev, "<1|0> <bit>: enable|disable interrupt");
1115 goto done;
1116 }
1117
1118 spin_lock_irqsave(udc->lock, flags);
1119 if (en) {
1120 if (hw_intr_force(bit))
1121 dev_err(dev, "invalid bit number\n");
1122 else
1123 isr_statistics.test++;
1124 } else {
1125 if (hw_intr_clear(bit))
1126 dev_err(dev, "invalid bit number\n");
1127 }
1128 spin_unlock_irqrestore(udc->lock, flags);
1129
1130 done:
1131 return count;
1132}
1133static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
1134
1135/**
1136 * show_port_test: reads port test mode
1137 *
1138 * Check "device.h" for details
1139 */
1140static ssize_t show_port_test(struct device *dev,
1141 struct device_attribute *attr, char *buf)
1142{
1143 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1144 unsigned long flags;
1145 unsigned mode;
1146
1147 dbg_trace("[%s] %p\n", __func__, buf);
1148 if (attr == NULL || buf == NULL) {
1149 dev_err(dev, "[%s] EINVAL\n", __func__);
1150 return 0;
1151 }
1152
1153 spin_lock_irqsave(udc->lock, flags);
1154 mode = hw_port_test_get();
1155 spin_unlock_irqrestore(udc->lock, flags);
1156
1157 return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
1158}
1159
1160/**
1161 * store_port_test: writes port test mode
1162 *
1163 * Check "device.h" for details
1164 */
1165static ssize_t store_port_test(struct device *dev,
1166 struct device_attribute *attr,
1167 const char *buf, size_t count)
1168{
1169 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1170 unsigned long flags;
1171 unsigned mode;
1172
1173 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1174 if (attr == NULL || buf == NULL) {
1175 dev_err(dev, "[%s] EINVAL\n", __func__);
1176 goto done;
1177 }
1178
1179 if (sscanf(buf, "%u", &mode) != 1) {
1180 dev_err(dev, "<mode>: set port test mode");
1181 goto done;
1182 }
1183
1184 spin_lock_irqsave(udc->lock, flags);
1185 if (hw_port_test_set(mode))
1186 dev_err(dev, "invalid mode\n");
1187 spin_unlock_irqrestore(udc->lock, flags);
1188
1189 done:
1190 return count;
1191}
1192static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
1193 show_port_test, store_port_test);
1194
1195/**
1196 * show_qheads: DMA contents of all queue heads
1197 *
1198 * Check "device.h" for details
1199 */
1200static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
1201 char *buf)
1202{
1203 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1204 unsigned long flags;
1205 unsigned i, j, n = 0;
1206
1207 dbg_trace("[%s] %p\n", __func__, buf);
1208 if (attr == NULL || buf == NULL) {
1209 dev_err(dev, "[%s] EINVAL\n", __func__);
1210 return 0;
1211 }
1212
1213 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301214 for (i = 0; i < hw_ep_max/2; i++) {
1215 struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i];
1216 struct ci13xxx_ep *mEpTx = &udc->ci13xxx_ep[i + hw_ep_max/2];
David Lopoaa69a802008-11-17 14:14:51 -08001217 n += scnprintf(buf + n, PAGE_SIZE - n,
1218 "EP=%02i: RX=%08X TX=%08X\n",
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301219 i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08001220 for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) {
1221 n += scnprintf(buf + n, PAGE_SIZE - n,
1222 " %04X: %08X %08X\n", j,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301223 *((u32 *)mEpRx->qh.ptr + j),
1224 *((u32 *)mEpTx->qh.ptr + j));
David Lopoaa69a802008-11-17 14:14:51 -08001225 }
1226 }
1227 spin_unlock_irqrestore(udc->lock, flags);
1228
1229 return n;
1230}
1231static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
1232
1233/**
1234 * show_registers: dumps all registers
1235 *
1236 * Check "device.h" for details
1237 */
1238static ssize_t show_registers(struct device *dev,
1239 struct device_attribute *attr, char *buf)
1240{
1241 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1242 unsigned long flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001243 u32 *dump;
David Lopoaa69a802008-11-17 14:14:51 -08001244 unsigned i, k, n = 0;
1245
1246 dbg_trace("[%s] %p\n", __func__, buf);
1247 if (attr == NULL || buf == NULL) {
1248 dev_err(dev, "[%s] EINVAL\n", __func__);
1249 return 0;
1250 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001251 dump = kmalloc(2048, GFP_KERNEL);
1252 if (dump == NULL)
1253 return -ENOMEM;
David Lopoaa69a802008-11-17 14:14:51 -08001254
1255 spin_lock_irqsave(udc->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001256 k = hw_register_read(dump, 512);
David Lopoaa69a802008-11-17 14:14:51 -08001257 spin_unlock_irqrestore(udc->lock, flags);
1258
1259 for (i = 0; i < k; i++) {
1260 n += scnprintf(buf + n, PAGE_SIZE - n,
1261 "reg[0x%04X] = 0x%08X\n",
1262 i * (unsigned)sizeof(u32), dump[i]);
1263 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001264 kfree(dump);
David Lopoaa69a802008-11-17 14:14:51 -08001265 return n;
1266}
1267
1268/**
1269 * store_registers: writes value to register address
1270 *
1271 * Check "device.h" for details
1272 */
1273static ssize_t store_registers(struct device *dev,
1274 struct device_attribute *attr,
1275 const char *buf, size_t count)
1276{
1277 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1278 unsigned long addr, data, flags;
1279
1280 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1281 if (attr == NULL || buf == NULL) {
1282 dev_err(dev, "[%s] EINVAL\n", __func__);
1283 goto done;
1284 }
1285
1286 if (sscanf(buf, "%li %li", &addr, &data) != 2) {
1287 dev_err(dev, "<addr> <data>: write data to register address");
1288 goto done;
1289 }
1290
1291 spin_lock_irqsave(udc->lock, flags);
1292 if (hw_register_write(addr, data))
1293 dev_err(dev, "invalid address range\n");
1294 spin_unlock_irqrestore(udc->lock, flags);
1295
1296 done:
1297 return count;
1298}
1299static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
1300 show_registers, store_registers);
1301
1302/**
1303 * show_requests: DMA contents of all requests currently queued (all endpts)
1304 *
1305 * Check "device.h" for details
1306 */
1307static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
1308 char *buf)
1309{
1310 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1311 unsigned long flags;
1312 struct list_head *ptr = NULL;
1313 struct ci13xxx_req *req = NULL;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301314 unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
David Lopoaa69a802008-11-17 14:14:51 -08001315
1316 dbg_trace("[%s] %p\n", __func__, buf);
1317 if (attr == NULL || buf == NULL) {
1318 dev_err(dev, "[%s] EINVAL\n", __func__);
1319 return 0;
1320 }
1321
1322 spin_lock_irqsave(udc->lock, flags);
1323 for (i = 0; i < hw_ep_max; i++)
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301324 list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue)
1325 {
1326 req = list_entry(ptr, struct ci13xxx_req, queue);
David Lopoaa69a802008-11-17 14:14:51 -08001327
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301328 n += scnprintf(buf + n, PAGE_SIZE - n,
1329 "EP=%02i: TD=%08X %s\n",
1330 i % hw_ep_max/2, (u32)req->dma,
1331 ((i < hw_ep_max/2) ? "RX" : "TX"));
1332
1333 for (j = 0; j < qSize; j++)
David Lopoaa69a802008-11-17 14:14:51 -08001334 n += scnprintf(buf + n, PAGE_SIZE - n,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301335 " %04X: %08X\n", j,
1336 *((u32 *)req->ptr + j));
1337 }
David Lopoaa69a802008-11-17 14:14:51 -08001338 spin_unlock_irqrestore(udc->lock, flags);
1339
1340 return n;
1341}
1342static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL);
1343
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001344/* EP# and Direction */
1345static ssize_t prime_ept(struct device *dev,
1346 struct device_attribute *attr,
1347 const char *buf, size_t count)
1348{
1349 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1350 struct ci13xxx_ep *mEp;
1351 unsigned int ep_num, dir;
1352 int n;
1353 struct ci13xxx_req *mReq = NULL;
1354
1355 if (sscanf(buf, "%u %u", &ep_num, &dir) != 2) {
1356 dev_err(dev, "<ep_num> <dir>: prime the ep");
1357 goto done;
1358 }
1359
1360 if (dir)
1361 mEp = &udc->ci13xxx_ep[ep_num + hw_ep_max/2];
1362 else
1363 mEp = &udc->ci13xxx_ep[ep_num];
1364
1365 n = hw_ep_bit(mEp->num, mEp->dir);
1366 mReq = list_entry(mEp->qh.queue.next, struct ci13xxx_req, queue);
1367 mEp->qh.ptr->td.next = mReq->dma;
1368 mEp->qh.ptr->td.token &= ~TD_STATUS;
1369
1370 wmb();
1371
1372 hw_cwrite(CAP_ENDPTPRIME, BIT(n), BIT(n));
1373 while (hw_cread(CAP_ENDPTPRIME, BIT(n)))
1374 cpu_relax();
1375
1376 pr_info("%s: prime:%08x stat:%08x ep#%d dir:%s\n", __func__,
1377 hw_cread(CAP_ENDPTPRIME, ~0),
1378 hw_cread(CAP_ENDPTSTAT, ~0),
1379 mEp->num, mEp->dir ? "IN" : "OUT");
1380done:
1381 return count;
1382
1383}
1384static DEVICE_ATTR(prime, S_IWUSR, NULL, prime_ept);
1385
1386/* EP# and Direction */
1387static ssize_t print_dtds(struct device *dev,
1388 struct device_attribute *attr,
1389 const char *buf, size_t count)
1390{
1391 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1392 struct ci13xxx_ep *mEp;
1393 unsigned int ep_num, dir;
1394 int n;
1395 struct list_head *ptr = NULL;
1396 struct ci13xxx_req *req = NULL;
1397
1398 if (sscanf(buf, "%u %u", &ep_num, &dir) != 2) {
1399 dev_err(dev, "<ep_num> <dir>: to print dtds");
1400 goto done;
1401 }
1402
1403 if (dir)
1404 mEp = &udc->ci13xxx_ep[ep_num + hw_ep_max/2];
1405 else
1406 mEp = &udc->ci13xxx_ep[ep_num];
1407
1408 n = hw_ep_bit(mEp->num, mEp->dir);
Anji jonnala6fb918c2011-10-21 17:54:21 +05301409 pr_info("%s: prime:%08x stat:%08x ep#%d dir:%s"
1410 "dTD_update_fail_count: %lu"
1411 "mEp->dTD_update_fail_count: %lu\n", __func__,
1412 hw_cread(CAP_ENDPTPRIME, ~0),
1413 hw_cread(CAP_ENDPTSTAT, ~0),
1414 mEp->num, mEp->dir ? "IN" : "OUT",
1415 udc->dTD_update_fail_count,
1416 mEp->dTD_update_fail_count);
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001417
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001418 pr_info("QH: cap:%08x cur:%08x next:%08x token:%08x\n",
1419 mEp->qh.ptr->cap, mEp->qh.ptr->curr,
1420 mEp->qh.ptr->td.next, mEp->qh.ptr->td.token);
1421
1422 list_for_each(ptr, &mEp->qh.queue) {
1423 req = list_entry(ptr, struct ci13xxx_req, queue);
1424
1425 pr_info("\treq:%08x next:%08x token:%08x page0:%08x status:%d\n",
1426 req->dma, req->ptr->next, req->ptr->token,
1427 req->ptr->page[0], req->req.status);
1428 }
1429done:
1430 return count;
1431
1432}
1433static DEVICE_ATTR(dtds, S_IWUSR, NULL, print_dtds);
1434
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001435static int ci13xxx_wakeup(struct usb_gadget *_gadget)
1436{
1437 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
1438 unsigned long flags;
1439 int ret = 0;
1440
1441 trace();
1442
1443 spin_lock_irqsave(udc->lock, flags);
1444 if (!udc->remote_wakeup) {
1445 ret = -EOPNOTSUPP;
1446 dbg_trace("remote wakeup feature is not enabled\n");
1447 goto out;
1448 }
1449 if (!hw_cread(CAP_PORTSC, PORTSC_SUSP)) {
1450 ret = -EINVAL;
1451 dbg_trace("port is not suspended\n");
1452 goto out;
1453 }
1454 hw_cwrite(CAP_PORTSC, PORTSC_FPR, PORTSC_FPR);
1455out:
1456 spin_unlock_irqrestore(udc->lock, flags);
1457 return ret;
1458}
1459
1460static ssize_t usb_remote_wakeup(struct device *dev,
1461 struct device_attribute *attr, const char *buf, size_t count)
1462{
1463 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1464
1465 ci13xxx_wakeup(&udc->gadget);
1466
1467 return count;
1468}
1469static DEVICE_ATTR(wakeup, S_IWUSR, 0, usb_remote_wakeup);
1470
David Lopoaa69a802008-11-17 14:14:51 -08001471/**
1472 * dbg_create_files: initializes the attribute interface
1473 * @dev: device
1474 *
1475 * This function returns an error code
1476 */
1477__maybe_unused static int dbg_create_files(struct device *dev)
1478{
1479 int retval = 0;
1480
1481 if (dev == NULL)
1482 return -EINVAL;
1483 retval = device_create_file(dev, &dev_attr_device);
1484 if (retval)
1485 goto done;
1486 retval = device_create_file(dev, &dev_attr_driver);
1487 if (retval)
1488 goto rm_device;
1489 retval = device_create_file(dev, &dev_attr_events);
1490 if (retval)
1491 goto rm_driver;
1492 retval = device_create_file(dev, &dev_attr_inters);
1493 if (retval)
1494 goto rm_events;
1495 retval = device_create_file(dev, &dev_attr_port_test);
1496 if (retval)
1497 goto rm_inters;
1498 retval = device_create_file(dev, &dev_attr_qheads);
1499 if (retval)
1500 goto rm_port_test;
1501 retval = device_create_file(dev, &dev_attr_registers);
1502 if (retval)
1503 goto rm_qheads;
1504 retval = device_create_file(dev, &dev_attr_requests);
1505 if (retval)
1506 goto rm_registers;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001507 retval = device_create_file(dev, &dev_attr_wakeup);
1508 if (retval)
1509 goto rm_remote_wakeup;
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001510 retval = device_create_file(dev, &dev_attr_prime);
1511 if (retval)
1512 goto rm_prime;
1513 retval = device_create_file(dev, &dev_attr_dtds);
1514 if (retval)
1515 goto rm_dtds;
1516
David Lopoaa69a802008-11-17 14:14:51 -08001517 return 0;
1518
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001519rm_dtds:
1520 device_remove_file(dev, &dev_attr_dtds);
1521rm_prime:
1522 device_remove_file(dev, &dev_attr_prime);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001523rm_remote_wakeup:
1524 device_remove_file(dev, &dev_attr_wakeup);
David Lopoaa69a802008-11-17 14:14:51 -08001525 rm_registers:
1526 device_remove_file(dev, &dev_attr_registers);
1527 rm_qheads:
1528 device_remove_file(dev, &dev_attr_qheads);
1529 rm_port_test:
1530 device_remove_file(dev, &dev_attr_port_test);
1531 rm_inters:
1532 device_remove_file(dev, &dev_attr_inters);
1533 rm_events:
1534 device_remove_file(dev, &dev_attr_events);
1535 rm_driver:
1536 device_remove_file(dev, &dev_attr_driver);
1537 rm_device:
1538 device_remove_file(dev, &dev_attr_device);
1539 done:
1540 return retval;
1541}
1542
1543/**
1544 * dbg_remove_files: destroys the attribute interface
1545 * @dev: device
1546 *
1547 * This function returns an error code
1548 */
1549__maybe_unused static int dbg_remove_files(struct device *dev)
1550{
1551 if (dev == NULL)
1552 return -EINVAL;
1553 device_remove_file(dev, &dev_attr_requests);
1554 device_remove_file(dev, &dev_attr_registers);
1555 device_remove_file(dev, &dev_attr_qheads);
1556 device_remove_file(dev, &dev_attr_port_test);
1557 device_remove_file(dev, &dev_attr_inters);
1558 device_remove_file(dev, &dev_attr_events);
1559 device_remove_file(dev, &dev_attr_driver);
1560 device_remove_file(dev, &dev_attr_device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001561 device_remove_file(dev, &dev_attr_wakeup);
David Lopoaa69a802008-11-17 14:14:51 -08001562 return 0;
1563}
1564
1565/******************************************************************************
1566 * UTIL block
1567 *****************************************************************************/
1568/**
1569 * _usb_addr: calculates endpoint address from direction & number
1570 * @ep: endpoint
1571 */
1572static inline u8 _usb_addr(struct ci13xxx_ep *ep)
1573{
1574 return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num;
1575}
1576
1577/**
1578 * _hardware_queue: configures a request at hardware level
1579 * @gadget: gadget
1580 * @mEp: endpoint
1581 *
1582 * This function returns an error code
1583 */
1584static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1585{
1586 unsigned i;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301587 int ret = 0;
1588 unsigned length = mReq->req.length;
David Lopoaa69a802008-11-17 14:14:51 -08001589
1590 trace("%p, %p", mEp, mReq);
1591
1592 /* don't queue twice */
1593 if (mReq->req.status == -EALREADY)
1594 return -EALREADY;
1595
David Lopoaa69a802008-11-17 14:14:51 -08001596 mReq->req.status = -EALREADY;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301597 if (length && !mReq->req.dma) {
David Lopoaa69a802008-11-17 14:14:51 -08001598 mReq->req.dma = \
1599 dma_map_single(mEp->device, mReq->req.buf,
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301600 length, mEp->dir ? DMA_TO_DEVICE :
1601 DMA_FROM_DEVICE);
David Lopoaa69a802008-11-17 14:14:51 -08001602 if (mReq->req.dma == 0)
1603 return -ENOMEM;
1604
1605 mReq->map = 1;
1606 }
1607
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301608 if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) {
1609 mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC,
1610 &mReq->zdma);
1611 if (mReq->zptr == NULL) {
1612 if (mReq->map) {
1613 dma_unmap_single(mEp->device, mReq->req.dma,
1614 length, mEp->dir ? DMA_TO_DEVICE :
1615 DMA_FROM_DEVICE);
1616 mReq->req.dma = 0;
1617 mReq->map = 0;
1618 }
1619 return -ENOMEM;
1620 }
1621 memset(mReq->zptr, 0, sizeof(*mReq->zptr));
1622 mReq->zptr->next = TD_TERMINATE;
1623 mReq->zptr->token = TD_STATUS_ACTIVE;
1624 if (!mReq->req.no_interrupt)
1625 mReq->zptr->token |= TD_IOC;
1626 }
David Lopoaa69a802008-11-17 14:14:51 -08001627 /*
1628 * TD configuration
1629 * TODO - handle requests which spawns into several TDs
1630 */
1631 memset(mReq->ptr, 0, sizeof(*mReq->ptr));
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301632 mReq->ptr->token = length << ffs_nr(TD_TOTAL_BYTES);
David Lopoaa69a802008-11-17 14:14:51 -08001633 mReq->ptr->token &= TD_TOTAL_BYTES;
David Lopoaa69a802008-11-17 14:14:51 -08001634 mReq->ptr->token |= TD_STATUS_ACTIVE;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301635 if (mReq->zptr) {
1636 mReq->ptr->next = mReq->zdma;
1637 } else {
1638 mReq->ptr->next = TD_TERMINATE;
1639 if (!mReq->req.no_interrupt)
1640 mReq->ptr->token |= TD_IOC;
1641 }
Ofir Cohena1c2a872011-12-14 10:26:34 +02001642
1643 /* MSM Specific: updating the request as required for
1644 * SPS mode. Enable MSM proprietary DMA engine acording
1645 * to the UDC private data in the request.
1646 */
1647 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
1648 if (mReq->req.udc_priv & MSM_SPS_MODE) {
1649 mReq->ptr->token = TD_STATUS_ACTIVE;
1650 if (mReq->req.udc_priv & MSM_TBE)
1651 mReq->ptr->next = TD_TERMINATE;
1652 else
1653 mReq->ptr->next = MSM_ETD_TYPE | mReq->dma;
1654 if (!mReq->req.no_interrupt)
1655 mReq->ptr->token |= MSM_ETD_IOC;
1656 }
1657 }
1658
David Lopoaa69a802008-11-17 14:14:51 -08001659 mReq->ptr->page[0] = mReq->req.dma;
1660 for (i = 1; i < 5; i++)
1661 mReq->ptr->page[i] =
Artem Leonenko0a313c42010-12-14 23:47:06 -08001662 (mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK;
David Lopoaa69a802008-11-17 14:14:51 -08001663
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301664 if (!list_empty(&mEp->qh.queue)) {
1665 struct ci13xxx_req *mReqPrev;
1666 int n = hw_ep_bit(mEp->num, mEp->dir);
1667 int tmp_stat;
1668
1669 mReqPrev = list_entry(mEp->qh.queue.prev,
1670 struct ci13xxx_req, queue);
1671 if (mReqPrev->zptr)
1672 mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
1673 else
1674 mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
1675 wmb();
1676 if (hw_cread(CAP_ENDPTPRIME, BIT(n)))
1677 goto done;
1678 do {
1679 hw_cwrite(CAP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
1680 tmp_stat = hw_cread(CAP_ENDPTSTAT, BIT(n));
1681 } while (!hw_cread(CAP_USBCMD, USBCMD_ATDTW));
1682 hw_cwrite(CAP_USBCMD, USBCMD_ATDTW, 0);
1683 if (tmp_stat)
1684 goto done;
1685 }
1686
1687 /* QH configuration */
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001688 if (!list_empty(&mEp->qh.queue)) {
1689 struct ci13xxx_req *mReq = \
1690 list_entry(mEp->qh.queue.next,
1691 struct ci13xxx_req, queue);
1692
1693 if (TD_STATUS_ACTIVE & mReq->ptr->token) {
1694 mEp->qh.ptr->td.next = mReq->dma;
1695 mEp->qh.ptr->td.token &= ~TD_STATUS;
1696 goto prime;
1697 }
1698 }
1699
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301700 mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */
Ofir Cohena1c2a872011-12-14 10:26:34 +02001701
1702 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
1703 if (mReq->req.udc_priv & MSM_SPS_MODE) {
1704 mEp->qh.ptr->td.next |= MSM_ETD_TYPE;
1705 i = hw_cread(CAP_ENDPTPIPEID +
1706 mEp->num * sizeof(u32), ~0);
1707 /* Read current value of this EPs pipe id */
1708 i = (mEp->dir == TX) ?
1709 ((i >> MSM_TX_PIPE_ID_OFS) & MSM_PIPE_ID_MASK) :
1710 (i & MSM_PIPE_ID_MASK);
1711 /* If requested pipe id is different from current,
1712 then write it */
1713 if (i != (mReq->req.udc_priv & MSM_PIPE_ID_MASK)) {
1714 if (mEp->dir == TX)
1715 hw_cwrite(
1716 CAP_ENDPTPIPEID +
1717 mEp->num * sizeof(u32),
1718 MSM_PIPE_ID_MASK <<
1719 MSM_TX_PIPE_ID_OFS,
1720 (mReq->req.udc_priv &
1721 MSM_PIPE_ID_MASK)
1722 << MSM_TX_PIPE_ID_OFS);
1723 else
1724 hw_cwrite(
1725 CAP_ENDPTPIPEID +
1726 mEp->num * sizeof(u32),
1727 MSM_PIPE_ID_MASK,
1728 mReq->req.udc_priv &
1729 MSM_PIPE_ID_MASK);
1730 }
1731 }
1732 }
1733
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301734 mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301735 mEp->qh.ptr->cap |= QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08001736
Vamsi Krishna603d1cb2011-07-24 17:17:04 -07001737prime:
David Lopoaa69a802008-11-17 14:14:51 -08001738 wmb(); /* synchronize before ep prime */
1739
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301740 ret = hw_ep_prime(mEp->num, mEp->dir,
David Lopoaa69a802008-11-17 14:14:51 -08001741 mEp->type == USB_ENDPOINT_XFER_CONTROL);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301742done:
1743 return ret;
David Lopoaa69a802008-11-17 14:14:51 -08001744}
1745
1746/**
1747 * _hardware_dequeue: handles a request at hardware level
1748 * @gadget: gadget
1749 * @mEp: endpoint
1750 *
1751 * This function returns an error code
1752 */
1753static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1754{
1755 trace("%p, %p", mEp, mReq);
1756
1757 if (mReq->req.status != -EALREADY)
1758 return -EINVAL;
1759
Vijayavardhan Vennapusa590b8ce2011-10-20 02:38:14 +05301760 /* clean speculative fetches on req->ptr->token */
1761 mb();
1762
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301763 if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
1764 return -EBUSY;
1765
Ofir Cohena1c2a872011-12-14 10:26:34 +02001766 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID)
1767 if ((mReq->req.udc_priv & MSM_SPS_MODE) &&
1768 (mReq->req.udc_priv & MSM_TBE))
1769 return -EBUSY;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301770 if (mReq->zptr) {
1771 if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
1772 return -EBUSY;
1773 dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
1774 mReq->zptr = NULL;
1775 }
David Lopoaa69a802008-11-17 14:14:51 -08001776
1777 mReq->req.status = 0;
1778
1779 if (mReq->map) {
1780 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
1781 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
1782 mReq->req.dma = 0;
1783 mReq->map = 0;
1784 }
1785
1786 mReq->req.status = mReq->ptr->token & TD_STATUS;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301787 if ((TD_STATUS_HALTED & mReq->req.status) != 0)
David Lopoaa69a802008-11-17 14:14:51 -08001788 mReq->req.status = -1;
1789 else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0)
1790 mReq->req.status = -1;
1791 else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0)
1792 mReq->req.status = -1;
1793
1794 mReq->req.actual = mReq->ptr->token & TD_TOTAL_BYTES;
1795 mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES);
1796 mReq->req.actual = mReq->req.length - mReq->req.actual;
1797 mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual;
1798
1799 return mReq->req.actual;
1800}
1801
1802/**
1803 * _ep_nuke: dequeues all endpoint requests
1804 * @mEp: endpoint
1805 *
1806 * This function returns an error code
1807 * Caller must hold lock
1808 */
1809static int _ep_nuke(struct ci13xxx_ep *mEp)
1810__releases(mEp->lock)
1811__acquires(mEp->lock)
1812{
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05301813 struct ci13xxx_ep *mEpTemp = mEp;
Ofir Cohena1c2a872011-12-14 10:26:34 +02001814 unsigned val;
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05301815
David Lopoaa69a802008-11-17 14:14:51 -08001816 trace("%p", mEp);
1817
1818 if (mEp == NULL)
1819 return -EINVAL;
1820
1821 hw_ep_flush(mEp->num, mEp->dir);
1822
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301823 while (!list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -08001824
1825 /* pop oldest request */
1826 struct ci13xxx_req *mReq = \
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301827 list_entry(mEp->qh.queue.next,
David Lopoaa69a802008-11-17 14:14:51 -08001828 struct ci13xxx_req, queue);
1829 list_del_init(&mReq->queue);
Ofir Cohena1c2a872011-12-14 10:26:34 +02001830
1831 /* MSM Specific: Clear end point proprietary register */
1832 if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
1833 if (mReq->req.udc_priv & MSM_SPS_MODE) {
1834 val = hw_cread(CAP_ENDPTPIPEID +
1835 mEp->num * sizeof(u32),
1836 ~0);
1837
1838 if (val != MSM_EP_PIPE_ID_RESET_VAL)
1839 hw_cwrite(
1840 CAP_ENDPTPIPEID +
1841 mEp->num * sizeof(u32),
1842 ~0, MSM_EP_PIPE_ID_RESET_VAL);
1843 }
1844 }
David Lopoaa69a802008-11-17 14:14:51 -08001845 mReq->req.status = -ESHUTDOWN;
1846
Artem Leonenko7c25a822010-12-14 23:46:55 -08001847 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08001848 spin_unlock(mEp->lock);
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05301849 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
1850 mReq->req.length)
1851 mEpTemp = &_udc->ep0in;
1852 mReq->req.complete(&mEpTemp->ep, &mReq->req);
David Lopoaa69a802008-11-17 14:14:51 -08001853 spin_lock(mEp->lock);
1854 }
1855 }
1856 return 0;
1857}
1858
1859/**
1860 * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
1861 * @gadget: gadget
1862 *
1863 * This function returns an error code
1864 * Caller must hold lock
1865 */
1866static int _gadget_stop_activity(struct usb_gadget *gadget)
David Lopoaa69a802008-11-17 14:14:51 -08001867{
1868 struct usb_ep *ep;
1869 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301870 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -08001871
1872 trace("%p", gadget);
1873
1874 if (gadget == NULL)
1875 return -EINVAL;
1876
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301877 spin_lock_irqsave(udc->lock, flags);
1878 udc->gadget.speed = USB_SPEED_UNKNOWN;
1879 udc->remote_wakeup = 0;
1880 udc->suspended = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001881 udc->configured = 0;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301882 spin_unlock_irqrestore(udc->lock, flags);
1883
David Lopoaa69a802008-11-17 14:14:51 -08001884 /* flush all endpoints */
1885 gadget_for_each_ep(ep, gadget) {
1886 usb_ep_fifo_flush(ep);
1887 }
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301888 usb_ep_fifo_flush(&udc->ep0out.ep);
1889 usb_ep_fifo_flush(&udc->ep0in.ep);
David Lopoaa69a802008-11-17 14:14:51 -08001890
1891 udc->driver->disconnect(gadget);
1892
1893 /* make sure to disable all endpoints */
1894 gadget_for_each_ep(ep, gadget) {
1895 usb_ep_disable(ep);
1896 }
David Lopoaa69a802008-11-17 14:14:51 -08001897
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301898 if (udc->status != NULL) {
1899 usb_ep_free_request(&udc->ep0in.ep, udc->status);
1900 udc->status = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08001901 }
1902
David Lopoaa69a802008-11-17 14:14:51 -08001903 return 0;
1904}
1905
1906/******************************************************************************
1907 * ISR block
1908 *****************************************************************************/
1909/**
1910 * isr_reset_handler: USB reset interrupt handler
1911 * @udc: UDC device
1912 *
1913 * This function resets USB engine after a bus reset occurred
1914 */
1915static void isr_reset_handler(struct ci13xxx *udc)
1916__releases(udc->lock)
1917__acquires(udc->lock)
1918{
David Lopoaa69a802008-11-17 14:14:51 -08001919 int retval;
1920
1921 trace("%p", udc);
1922
1923 if (udc == NULL) {
1924 err("EINVAL");
1925 return;
1926 }
1927
1928 dbg_event(0xFF, "BUS RST", 0);
1929
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301930 spin_unlock(udc->lock);
Anji jonnala8bbde012011-10-28 14:17:25 +05301931
1932 /*stop charging upon reset */
1933 if (udc->transceiver)
1934 otg_set_power(udc->transceiver, 0);
1935
David Lopoaa69a802008-11-17 14:14:51 -08001936 retval = _gadget_stop_activity(&udc->gadget);
1937 if (retval)
1938 goto done;
1939
1940 retval = hw_usb_reset();
1941 if (retval)
1942 goto done;
1943
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05301944 udc->status = usb_ep_alloc_request(&udc->ep0in.ep, GFP_ATOMIC);
1945 if (udc->status == NULL)
1946 retval = -ENOMEM;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301947
David Lopoaa69a802008-11-17 14:14:51 -08001948 spin_lock(udc->lock);
1949
1950 done:
1951 if (retval)
1952 err("error: %i", retval);
1953}
1954
1955/**
1956 * isr_get_status_complete: get_status request complete function
1957 * @ep: endpoint
1958 * @req: request handled
1959 *
1960 * Caller must release lock
1961 */
1962static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
1963{
1964 trace("%p, %p", ep, req);
1965
1966 if (ep == NULL || req == NULL) {
1967 err("EINVAL");
1968 return;
1969 }
1970
1971 kfree(req->buf);
1972 usb_ep_free_request(ep, req);
1973}
1974
1975/**
1976 * isr_get_status_response: get_status request response
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301977 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08001978 * @setup: setup request packet
1979 *
1980 * This function returns an error code
1981 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301982static int isr_get_status_response(struct ci13xxx *udc,
David Lopoaa69a802008-11-17 14:14:51 -08001983 struct usb_ctrlrequest *setup)
1984__releases(mEp->lock)
1985__acquires(mEp->lock)
1986{
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301987 struct ci13xxx_ep *mEp = &udc->ep0in;
David Lopoaa69a802008-11-17 14:14:51 -08001988 struct usb_request *req = NULL;
1989 gfp_t gfp_flags = GFP_ATOMIC;
1990 int dir, num, retval;
1991
1992 trace("%p, %p", mEp, setup);
1993
1994 if (mEp == NULL || setup == NULL)
1995 return -EINVAL;
1996
1997 spin_unlock(mEp->lock);
1998 req = usb_ep_alloc_request(&mEp->ep, gfp_flags);
1999 spin_lock(mEp->lock);
2000 if (req == NULL)
2001 return -ENOMEM;
2002
2003 req->complete = isr_get_status_complete;
2004 req->length = 2;
2005 req->buf = kzalloc(req->length, gfp_flags);
2006 if (req->buf == NULL) {
2007 retval = -ENOMEM;
2008 goto err_free_req;
2009 }
2010
2011 if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302012 /* Assume that device is bus powered for now. */
2013 *((u16 *)req->buf) = _udc->remote_wakeup << 1;
David Lopoaa69a802008-11-17 14:14:51 -08002014 retval = 0;
2015 } else if ((setup->bRequestType & USB_RECIP_MASK) \
2016 == USB_RECIP_ENDPOINT) {
2017 dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
2018 TX : RX;
2019 num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK;
2020 *((u16 *)req->buf) = hw_ep_get_halt(num, dir);
2021 }
2022 /* else do nothing; reserved for future use */
2023
2024 spin_unlock(mEp->lock);
2025 retval = usb_ep_queue(&mEp->ep, req, gfp_flags);
2026 spin_lock(mEp->lock);
2027 if (retval)
2028 goto err_free_buf;
2029
2030 return 0;
2031
2032 err_free_buf:
2033 kfree(req->buf);
2034 err_free_req:
2035 spin_unlock(mEp->lock);
2036 usb_ep_free_request(&mEp->ep, req);
2037 spin_lock(mEp->lock);
2038 return retval;
2039}
2040
2041/**
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302042 * isr_setup_status_complete: setup_status request complete function
2043 * @ep: endpoint
2044 * @req: request handled
2045 *
2046 * Caller must release lock. Put the port in test mode if test mode
2047 * feature is selected.
2048 */
2049static void
2050isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
2051{
2052 struct ci13xxx *udc = req->context;
2053 unsigned long flags;
2054
2055 trace("%p, %p", ep, req);
2056
2057 spin_lock_irqsave(udc->lock, flags);
2058 if (udc->test_mode)
2059 hw_port_test_set(udc->test_mode);
2060 spin_unlock_irqrestore(udc->lock, flags);
2061}
2062
2063/**
David Lopoaa69a802008-11-17 14:14:51 -08002064 * isr_setup_status_phase: queues the status phase of a setup transation
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302065 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08002066 *
2067 * This function returns an error code
2068 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302069static int isr_setup_status_phase(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -08002070__releases(mEp->lock)
2071__acquires(mEp->lock)
2072{
2073 int retval;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302074 struct ci13xxx_ep *mEp;
David Lopoaa69a802008-11-17 14:14:51 -08002075
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302076 trace("%p", udc);
David Lopoaa69a802008-11-17 14:14:51 -08002077
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302078 mEp = (udc->ep0_dir == TX) ? &udc->ep0out : &udc->ep0in;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302079 udc->status->context = udc;
2080 udc->status->complete = isr_setup_status_complete;
David Lopoaa69a802008-11-17 14:14:51 -08002081
2082 spin_unlock(mEp->lock);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302083 retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
David Lopoaa69a802008-11-17 14:14:51 -08002084 spin_lock(mEp->lock);
2085
2086 return retval;
2087}
2088
2089/**
2090 * isr_tr_complete_low: transaction complete low level handler
2091 * @mEp: endpoint
2092 *
2093 * This function returns an error code
2094 * Caller must hold lock
2095 */
2096static int isr_tr_complete_low(struct ci13xxx_ep *mEp)
2097__releases(mEp->lock)
2098__acquires(mEp->lock)
2099{
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302100 struct ci13xxx_req *mReq, *mReqTemp;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302101 struct ci13xxx_ep *mEpTemp = mEp;
Pavankumar Kondeti986b11b2011-05-02 11:56:29 +05302102 int uninitialized_var(retval);
Anji jonnala6fb918c2011-10-21 17:54:21 +05302103 int req_dequeue = 1;
2104 struct ci13xxx *udc = _udc;
David Lopoaa69a802008-11-17 14:14:51 -08002105
2106 trace("%p", mEp);
2107
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302108 if (list_empty(&mEp->qh.queue))
Anji jonnala6fb918c2011-10-21 17:54:21 +05302109 return 0;
David Lopoaa69a802008-11-17 14:14:51 -08002110
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302111 list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,
2112 queue) {
Anji jonnala6fb918c2011-10-21 17:54:21 +05302113dequeue:
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302114 retval = _hardware_dequeue(mEp, mReq);
Anji jonnala6fb918c2011-10-21 17:54:21 +05302115 if (retval < 0) {
2116 /*
2117 * FIXME: don't know exact delay
2118 * required for HW to update dTD status
2119 * bits. This is a temporary workaround till
2120 * HW designers come back on this.
2121 */
2122 if (retval == -EBUSY && req_dequeue && mEp->dir == 0) {
2123 req_dequeue = 0;
2124 udc->dTD_update_fail_count++;
2125 mEp->dTD_update_fail_count++;
2126 udelay(10);
2127 goto dequeue;
2128 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302129 break;
Anji jonnala6fb918c2011-10-21 17:54:21 +05302130 }
2131 req_dequeue = 0;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302132 list_del_init(&mReq->queue);
2133 dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
2134 if (mReq->req.complete != NULL) {
2135 spin_unlock(mEp->lock);
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302136 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
2137 mReq->req.length)
2138 mEpTemp = &_udc->ep0in;
2139 mReq->req.complete(&mEpTemp->ep, &mReq->req);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302140 spin_lock(mEp->lock);
2141 }
2142 }
David Lopoaa69a802008-11-17 14:14:51 -08002143
Pavankumar Kondetief907482011-05-02 11:56:27 +05302144 if (retval == -EBUSY)
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302145 retval = 0;
2146 if (retval < 0)
David Lopoaa69a802008-11-17 14:14:51 -08002147 dbg_event(_usb_addr(mEp), "DONE", retval);
David Lopoaa69a802008-11-17 14:14:51 -08002148
David Lopoaa69a802008-11-17 14:14:51 -08002149 return retval;
2150}
2151
2152/**
2153 * isr_tr_complete_handler: transaction complete interrupt handler
2154 * @udc: UDC descriptor
2155 *
2156 * This function handles traffic events
2157 */
2158static void isr_tr_complete_handler(struct ci13xxx *udc)
2159__releases(udc->lock)
2160__acquires(udc->lock)
2161{
2162 unsigned i;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302163 u8 tmode = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002164
2165 trace("%p", udc);
2166
2167 if (udc == NULL) {
2168 err("EINVAL");
2169 return;
2170 }
2171
2172 for (i = 0; i < hw_ep_max; i++) {
2173 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302174 int type, num, dir, err = -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -08002175 struct usb_ctrlrequest req;
2176
David Lopoaa69a802008-11-17 14:14:51 -08002177 if (mEp->desc == NULL)
2178 continue; /* not configured */
2179
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302180 if (hw_test_and_clear_complete(i)) {
David Lopoaa69a802008-11-17 14:14:51 -08002181 err = isr_tr_complete_low(mEp);
2182 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
2183 if (err > 0) /* needs status phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302184 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002185 if (err < 0) {
2186 dbg_event(_usb_addr(mEp),
2187 "ERROR", err);
2188 spin_unlock(udc->lock);
2189 if (usb_ep_set_halt(&mEp->ep))
2190 err("error: ep_set_halt");
2191 spin_lock(udc->lock);
2192 }
2193 }
2194 }
2195
2196 if (mEp->type != USB_ENDPOINT_XFER_CONTROL ||
2197 !hw_test_and_clear_setup_status(i))
2198 continue;
2199
2200 if (i != 0) {
2201 warn("ctrl traffic received at endpoint");
2202 continue;
2203 }
2204
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302205 /*
2206 * Flush data and handshake transactions of previous
2207 * setup packet.
2208 */
2209 _ep_nuke(&udc->ep0out);
2210 _ep_nuke(&udc->ep0in);
2211
David Lopoaa69a802008-11-17 14:14:51 -08002212 /* read_setup_packet */
2213 do {
2214 hw_test_and_set_setup_guard();
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302215 memcpy(&req, &mEp->qh.ptr->setup, sizeof(req));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002216 /* Ensure buffer is read before acknowledging to h/w */
2217 mb();
David Lopoaa69a802008-11-17 14:14:51 -08002218 } while (!hw_test_and_clear_setup_guard());
2219
2220 type = req.bRequestType;
2221
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302222 udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
David Lopoaa69a802008-11-17 14:14:51 -08002223
2224 dbg_setup(_usb_addr(mEp), &req);
2225
2226 switch (req.bRequest) {
2227 case USB_REQ_CLEAR_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302228 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
2229 le16_to_cpu(req.wValue) ==
2230 USB_ENDPOINT_HALT) {
2231 if (req.wLength != 0)
David Lopoaa69a802008-11-17 14:14:51 -08002232 break;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302233 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302234 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302235 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302236 if (dir) /* TX */
2237 num += hw_ep_max/2;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302238 if (!udc->ci13xxx_ep[num].wedge) {
2239 spin_unlock(udc->lock);
2240 err = usb_ep_clear_halt(
2241 &udc->ci13xxx_ep[num].ep);
2242 spin_lock(udc->lock);
2243 if (err)
2244 break;
2245 }
2246 err = isr_setup_status_phase(udc);
2247 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
2248 le16_to_cpu(req.wValue) ==
2249 USB_DEVICE_REMOTE_WAKEUP) {
2250 if (req.wLength != 0)
2251 break;
2252 udc->remote_wakeup = 0;
2253 err = isr_setup_status_phase(udc);
2254 } else {
2255 goto delegate;
David Lopoaa69a802008-11-17 14:14:51 -08002256 }
David Lopoaa69a802008-11-17 14:14:51 -08002257 break;
2258 case USB_REQ_GET_STATUS:
2259 if (type != (USB_DIR_IN|USB_RECIP_DEVICE) &&
2260 type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
2261 type != (USB_DIR_IN|USB_RECIP_INTERFACE))
2262 goto delegate;
2263 if (le16_to_cpu(req.wLength) != 2 ||
2264 le16_to_cpu(req.wValue) != 0)
2265 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302266 err = isr_get_status_response(udc, &req);
David Lopoaa69a802008-11-17 14:14:51 -08002267 break;
2268 case USB_REQ_SET_ADDRESS:
2269 if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
2270 goto delegate;
2271 if (le16_to_cpu(req.wLength) != 0 ||
2272 le16_to_cpu(req.wIndex) != 0)
2273 break;
2274 err = hw_usb_set_address((u8)le16_to_cpu(req.wValue));
2275 if (err)
2276 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302277 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002278 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002279 case USB_REQ_SET_CONFIGURATION:
2280 if (type == (USB_DIR_OUT|USB_TYPE_STANDARD))
2281 udc->configured = !!req.wValue;
2282 goto delegate;
David Lopoaa69a802008-11-17 14:14:51 -08002283 case USB_REQ_SET_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302284 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
2285 le16_to_cpu(req.wValue) ==
2286 USB_ENDPOINT_HALT) {
2287 if (req.wLength != 0)
2288 break;
2289 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302290 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302291 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302292 if (dir) /* TX */
2293 num += hw_ep_max/2;
David Lopoaa69a802008-11-17 14:14:51 -08002294
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302295 spin_unlock(udc->lock);
2296 err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
2297 spin_lock(udc->lock);
2298 if (!err)
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302299 isr_setup_status_phase(udc);
2300 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302301 if (req.wLength != 0)
2302 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302303 switch (le16_to_cpu(req.wValue)) {
2304 case USB_DEVICE_REMOTE_WAKEUP:
2305 udc->remote_wakeup = 1;
2306 err = isr_setup_status_phase(udc);
2307 break;
2308 case USB_DEVICE_TEST_MODE:
2309 tmode = le16_to_cpu(req.wIndex) >> 8;
2310 switch (tmode) {
2311 case TEST_J:
2312 case TEST_K:
2313 case TEST_SE0_NAK:
2314 case TEST_PACKET:
2315 case TEST_FORCE_EN:
2316 udc->test_mode = tmode;
2317 err = isr_setup_status_phase(
2318 udc);
2319 break;
2320 default:
2321 break;
2322 }
2323 default:
2324 goto delegate;
2325 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302326 } else {
2327 goto delegate;
2328 }
David Lopoaa69a802008-11-17 14:14:51 -08002329 break;
2330 default:
2331delegate:
2332 if (req.wLength == 0) /* no data phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302333 udc->ep0_dir = TX;
David Lopoaa69a802008-11-17 14:14:51 -08002334
2335 spin_unlock(udc->lock);
2336 err = udc->driver->setup(&udc->gadget, &req);
2337 spin_lock(udc->lock);
2338 break;
2339 }
2340
2341 if (err < 0) {
2342 dbg_event(_usb_addr(mEp), "ERROR", err);
2343
2344 spin_unlock(udc->lock);
2345 if (usb_ep_set_halt(&mEp->ep))
2346 err("error: ep_set_halt");
2347 spin_lock(udc->lock);
2348 }
2349 }
2350}
2351
2352/******************************************************************************
2353 * ENDPT block
2354 *****************************************************************************/
2355/**
2356 * ep_enable: configure endpoint, making it usable
2357 *
2358 * Check usb_ep_enable() at "usb_gadget.h" for details
2359 */
2360static int ep_enable(struct usb_ep *ep,
2361 const struct usb_endpoint_descriptor *desc)
2362{
2363 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302364 int retval = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002365 unsigned long flags;
2366
2367 trace("%p, %p", ep, desc);
2368
2369 if (ep == NULL || desc == NULL)
2370 return -EINVAL;
2371
2372 spin_lock_irqsave(mEp->lock, flags);
2373
2374 /* only internal SW should enable ctrl endpts */
2375
2376 mEp->desc = desc;
2377
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302378 if (!list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08002379 warn("enabling a non-empty endpoint!");
2380
Matthias Kaehlcke15739bb2009-04-15 22:28:41 +02002381 mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX;
2382 mEp->num = usb_endpoint_num(desc);
2383 mEp->type = usb_endpoint_type(desc);
David Lopoaa69a802008-11-17 14:14:51 -08002384
2385 mEp->ep.maxpacket = __constant_le16_to_cpu(desc->wMaxPacketSize);
2386
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302387 dbg_event(_usb_addr(mEp), "ENABLE", 0);
David Lopoaa69a802008-11-17 14:14:51 -08002388
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302389 mEp->qh.ptr->cap = 0;
David Lopof23e6492009-04-16 14:35:24 -07002390
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302391 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2392 mEp->qh.ptr->cap |= QH_IOS;
2393 else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
2394 mEp->qh.ptr->cap &= ~QH_MULT;
2395 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002396 mEp->qh.ptr->cap |= QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08002397
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302398 mEp->qh.ptr->cap |=
2399 (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
2400 mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */
David Lopoaa69a802008-11-17 14:14:51 -08002401
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002402 /* complete all the updates to ept->head before enabling endpoint*/
2403 mb();
2404
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302405 /*
2406 * Enable endpoints in the HW other than ep0 as ep0
2407 * is always enabled
2408 */
2409 if (mEp->num)
2410 retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type);
David Lopoaa69a802008-11-17 14:14:51 -08002411
2412 spin_unlock_irqrestore(mEp->lock, flags);
2413 return retval;
2414}
2415
2416/**
2417 * ep_disable: endpoint is no longer usable
2418 *
2419 * Check usb_ep_disable() at "usb_gadget.h" for details
2420 */
2421static int ep_disable(struct usb_ep *ep)
2422{
2423 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2424 int direction, retval = 0;
2425 unsigned long flags;
2426
2427 trace("%p", ep);
2428
2429 if (ep == NULL)
2430 return -EINVAL;
2431 else if (mEp->desc == NULL)
2432 return -EBUSY;
2433
2434 spin_lock_irqsave(mEp->lock, flags);
2435
2436 /* only internal SW should disable ctrl endpts */
2437
2438 direction = mEp->dir;
2439 do {
2440 dbg_event(_usb_addr(mEp), "DISABLE", 0);
2441
2442 retval |= _ep_nuke(mEp);
2443 retval |= hw_ep_disable(mEp->num, mEp->dir);
2444
2445 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2446 mEp->dir = (mEp->dir == TX) ? RX : TX;
2447
2448 } while (mEp->dir != direction);
2449
2450 mEp->desc = NULL;
2451
2452 spin_unlock_irqrestore(mEp->lock, flags);
2453 return retval;
2454}
2455
2456/**
2457 * ep_alloc_request: allocate a request object to use with this endpoint
2458 *
2459 * Check usb_ep_alloc_request() at "usb_gadget.h" for details
2460 */
2461static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
2462{
2463 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2464 struct ci13xxx_req *mReq = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002465
2466 trace("%p, %i", ep, gfp_flags);
2467
2468 if (ep == NULL) {
2469 err("EINVAL");
2470 return NULL;
2471 }
2472
David Lopoaa69a802008-11-17 14:14:51 -08002473 mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
2474 if (mReq != NULL) {
2475 INIT_LIST_HEAD(&mReq->queue);
2476
2477 mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,
2478 &mReq->dma);
2479 if (mReq->ptr == NULL) {
2480 kfree(mReq);
2481 mReq = NULL;
2482 }
2483 }
2484
2485 dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
2486
David Lopoaa69a802008-11-17 14:14:51 -08002487 return (mReq == NULL) ? NULL : &mReq->req;
2488}
2489
2490/**
2491 * ep_free_request: frees a request object
2492 *
2493 * Check usb_ep_free_request() at "usb_gadget.h" for details
2494 */
2495static void ep_free_request(struct usb_ep *ep, struct usb_request *req)
2496{
2497 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2498 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2499 unsigned long flags;
2500
2501 trace("%p, %p", ep, req);
2502
2503 if (ep == NULL || req == NULL) {
2504 err("EINVAL");
2505 return;
2506 } else if (!list_empty(&mReq->queue)) {
2507 err("EBUSY");
2508 return;
2509 }
2510
2511 spin_lock_irqsave(mEp->lock, flags);
2512
2513 if (mReq->ptr)
2514 dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma);
2515 kfree(mReq);
2516
2517 dbg_event(_usb_addr(mEp), "FREE", 0);
2518
2519 spin_unlock_irqrestore(mEp->lock, flags);
2520}
2521
2522/**
2523 * ep_queue: queues (submits) an I/O request to an endpoint
2524 *
2525 * Check usb_ep_queue()* at usb_gadget.h" for details
2526 */
2527static int ep_queue(struct usb_ep *ep, struct usb_request *req,
2528 gfp_t __maybe_unused gfp_flags)
2529{
2530 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2531 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2532 int retval = 0;
2533 unsigned long flags;
Anji jonnala6c174d42011-07-13 13:01:47 +05302534 struct ci13xxx *udc = _udc;
David Lopoaa69a802008-11-17 14:14:51 -08002535
2536 trace("%p, %p, %X", ep, req, gfp_flags);
2537
2538 if (ep == NULL || req == NULL || mEp->desc == NULL)
2539 return -EINVAL;
2540
2541 spin_lock_irqsave(mEp->lock, flags);
2542
Anji jonnala6c174d42011-07-13 13:01:47 +05302543 if (!udc->configured && mEp->type !=
2544 USB_ENDPOINT_XFER_CONTROL) {
2545 spin_unlock_irqrestore(mEp->lock, flags);
2546 trace("usb is not configured"
2547 "ept #%d, ept name#%s\n",
2548 mEp->num, mEp->ep.name);
2549 return -ESHUTDOWN;
2550 }
2551
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302552 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
2553 if (req->length)
2554 mEp = (_udc->ep0_dir == RX) ?
2555 &_udc->ep0out : &_udc->ep0in;
2556 if (!list_empty(&mEp->qh.queue)) {
2557 _ep_nuke(mEp);
2558 retval = -EOVERFLOW;
2559 warn("endpoint ctrl %X nuked", _usb_addr(mEp));
2560 }
David Lopoaa69a802008-11-17 14:14:51 -08002561 }
2562
2563 /* first nuke then test link, e.g. previous status has not sent */
2564 if (!list_empty(&mReq->queue)) {
2565 retval = -EBUSY;
2566 err("request already in queue");
2567 goto done;
2568 }
2569
Artem Leonenko0a313c42010-12-14 23:47:06 -08002570 if (req->length > (4 * CI13XXX_PAGE_SIZE)) {
2571 req->length = (4 * CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08002572 retval = -EMSGSIZE;
2573 warn("request length truncated");
2574 }
2575
2576 dbg_queue(_usb_addr(mEp), req, retval);
2577
2578 /* push request */
2579 mReq->req.status = -EINPROGRESS;
2580 mReq->req.actual = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002581
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302582 retval = _hardware_enqueue(mEp, mReq);
Artem Leonenkod9bb9c12010-12-14 23:45:50 -08002583
2584 if (retval == -EALREADY) {
David Lopoaa69a802008-11-17 14:14:51 -08002585 dbg_event(_usb_addr(mEp), "QUEUE", retval);
2586 retval = 0;
2587 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302588 if (!retval)
2589 list_add_tail(&mReq->queue, &mEp->qh.queue);
David Lopoaa69a802008-11-17 14:14:51 -08002590
2591 done:
2592 spin_unlock_irqrestore(mEp->lock, flags);
2593 return retval;
2594}
2595
2596/**
2597 * ep_dequeue: dequeues (cancels, unlinks) an I/O request from an endpoint
2598 *
2599 * Check usb_ep_dequeue() at "usb_gadget.h" for details
2600 */
2601static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
2602{
2603 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05302604 struct ci13xxx_ep *mEpTemp = mEp;
David Lopoaa69a802008-11-17 14:14:51 -08002605 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2606 unsigned long flags;
2607
2608 trace("%p, %p", ep, req);
2609
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302610 if (ep == NULL || req == NULL || mReq->req.status != -EALREADY ||
2611 mEp->desc == NULL || list_empty(&mReq->queue) ||
2612 list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08002613 return -EINVAL;
2614
2615 spin_lock_irqsave(mEp->lock, flags);
2616
2617 dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
2618
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302619 hw_ep_flush(mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08002620
2621 /* pop request */
2622 list_del_init(&mReq->queue);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302623 if (mReq->map) {
2624 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
2625 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
2626 mReq->req.dma = 0;
2627 mReq->map = 0;
2628 }
David Lopoaa69a802008-11-17 14:14:51 -08002629 req->status = -ECONNRESET;
2630
Artem Leonenko7c25a822010-12-14 23:46:55 -08002631 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08002632 spin_unlock(mEp->lock);
Pavankumar Kondeti05cdbdb2011-09-12 09:13:12 +05302633 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
2634 mReq->req.length)
2635 mEpTemp = &_udc->ep0in;
2636 mReq->req.complete(&mEpTemp->ep, &mReq->req);
David Lopoaa69a802008-11-17 14:14:51 -08002637 spin_lock(mEp->lock);
2638 }
2639
2640 spin_unlock_irqrestore(mEp->lock, flags);
2641 return 0;
2642}
2643
2644/**
2645 * ep_set_halt: sets the endpoint halt feature
2646 *
2647 * Check usb_ep_set_halt() at "usb_gadget.h" for details
2648 */
2649static int ep_set_halt(struct usb_ep *ep, int value)
2650{
2651 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2652 int direction, retval = 0;
2653 unsigned long flags;
2654
2655 trace("%p, %i", ep, value);
2656
2657 if (ep == NULL || mEp->desc == NULL)
2658 return -EINVAL;
2659
2660 spin_lock_irqsave(mEp->lock, flags);
2661
2662#ifndef STALL_IN
2663 /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
2664 if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX &&
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302665 !list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -08002666 spin_unlock_irqrestore(mEp->lock, flags);
2667 return -EAGAIN;
2668 }
2669#endif
2670
2671 direction = mEp->dir;
2672 do {
2673 dbg_event(_usb_addr(mEp), "HALT", value);
2674 retval |= hw_ep_set_halt(mEp->num, mEp->dir, value);
2675
2676 if (!value)
2677 mEp->wedge = 0;
2678
2679 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2680 mEp->dir = (mEp->dir == TX) ? RX : TX;
2681
2682 } while (mEp->dir != direction);
2683
2684 spin_unlock_irqrestore(mEp->lock, flags);
2685 return retval;
2686}
2687
2688/**
2689 * ep_set_wedge: sets the halt feature and ignores clear requests
2690 *
2691 * Check usb_ep_set_wedge() at "usb_gadget.h" for details
2692 */
2693static int ep_set_wedge(struct usb_ep *ep)
2694{
2695 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2696 unsigned long flags;
2697
2698 trace("%p", ep);
2699
2700 if (ep == NULL || mEp->desc == NULL)
2701 return -EINVAL;
2702
2703 spin_lock_irqsave(mEp->lock, flags);
2704
2705 dbg_event(_usb_addr(mEp), "WEDGE", 0);
2706 mEp->wedge = 1;
2707
2708 spin_unlock_irqrestore(mEp->lock, flags);
2709
2710 return usb_ep_set_halt(ep);
2711}
2712
2713/**
2714 * ep_fifo_flush: flushes contents of a fifo
2715 *
2716 * Check usb_ep_fifo_flush() at "usb_gadget.h" for details
2717 */
2718static void ep_fifo_flush(struct usb_ep *ep)
2719{
2720 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2721 unsigned long flags;
2722
2723 trace("%p", ep);
2724
2725 if (ep == NULL) {
2726 err("%02X: -EINVAL", _usb_addr(mEp));
2727 return;
2728 }
2729
2730 spin_lock_irqsave(mEp->lock, flags);
2731
2732 dbg_event(_usb_addr(mEp), "FFLUSH", 0);
2733 hw_ep_flush(mEp->num, mEp->dir);
2734
2735 spin_unlock_irqrestore(mEp->lock, flags);
2736}
2737
2738/**
2739 * Endpoint-specific part of the API to the USB controller hardware
2740 * Check "usb_gadget.h" for details
2741 */
2742static const struct usb_ep_ops usb_ep_ops = {
2743 .enable = ep_enable,
2744 .disable = ep_disable,
2745 .alloc_request = ep_alloc_request,
2746 .free_request = ep_free_request,
2747 .queue = ep_queue,
2748 .dequeue = ep_dequeue,
2749 .set_halt = ep_set_halt,
2750 .set_wedge = ep_set_wedge,
2751 .fifo_flush = ep_fifo_flush,
2752};
2753
2754/******************************************************************************
2755 * GADGET block
2756 *****************************************************************************/
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302757static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
2758{
2759 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2760 unsigned long flags;
2761 int gadget_ready = 0;
2762
2763 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS))
2764 return -EOPNOTSUPP;
2765
2766 spin_lock_irqsave(udc->lock, flags);
2767 udc->vbus_active = is_active;
2768 if (udc->driver)
2769 gadget_ready = 1;
2770 spin_unlock_irqrestore(udc->lock, flags);
2771
2772 if (gadget_ready) {
2773 if (is_active) {
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302774 pm_runtime_get_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302775 hw_device_reset(udc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002776 if (udc->softconnect)
2777 hw_device_state(udc->ep0out.qh.dma);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302778 } else {
2779 hw_device_state(0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302780 _gadget_stop_activity(&udc->gadget);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302781 pm_runtime_put_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302782 }
2783 }
2784
2785 return 0;
2786}
2787
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302788static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
2789{
2790 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2791
2792 if (udc->transceiver)
2793 return otg_set_power(udc->transceiver, mA);
2794 return -ENOTSUPP;
2795}
2796
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002797static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_active)
2798{
2799 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2800 unsigned long flags;
2801
2802 spin_lock_irqsave(udc->lock, flags);
2803 udc->softconnect = is_active;
2804 if (((udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) &&
2805 !udc->vbus_active) || !udc->driver) {
2806 spin_unlock_irqrestore(udc->lock, flags);
2807 return 0;
2808 }
2809 spin_unlock_irqrestore(udc->lock, flags);
2810
Pavankumar Kondetib7f53dc2011-08-23 12:40:33 +05302811 if (is_active)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002812 hw_device_state(udc->ep0out.qh.dma);
Pavankumar Kondetib7f53dc2011-08-23 12:40:33 +05302813 else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002814 hw_device_state(0);
Pavankumar Kondetib7f53dc2011-08-23 12:40:33 +05302815
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002816 return 0;
2817}
2818
2819
David Lopoaa69a802008-11-17 14:14:51 -08002820/**
2821 * Device operations part of the API to the USB controller hardware,
2822 * which don't involve endpoints (or i/o)
2823 * Check "usb_gadget.h" for details
2824 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302825static const struct usb_gadget_ops usb_gadget_ops = {
2826 .vbus_session = ci13xxx_vbus_session,
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302827 .wakeup = ci13xxx_wakeup,
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302828 .vbus_draw = ci13xxx_vbus_draw,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002829 .pullup = ci13xxx_pullup,
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302830};
David Lopoaa69a802008-11-17 14:14:51 -08002831
2832/**
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002833 * usb_gadget_probe_driver: register a gadget driver
2834 * @driver: the driver being registered
2835 * @bind: the driver's bind callback
David Lopoaa69a802008-11-17 14:14:51 -08002836 *
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002837 * Check usb_gadget_probe_driver() at <linux/usb/gadget.h> for details.
2838 * Interrupts are enabled here.
David Lopoaa69a802008-11-17 14:14:51 -08002839 */
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002840int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
2841 int (*bind)(struct usb_gadget *))
David Lopoaa69a802008-11-17 14:14:51 -08002842{
2843 struct ci13xxx *udc = _udc;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302844 unsigned long flags;
2845 int i, j;
David Lopoaa69a802008-11-17 14:14:51 -08002846 int retval = -ENOMEM;
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05302847 bool put = false;
David Lopoaa69a802008-11-17 14:14:51 -08002848
2849 trace("%p", driver);
2850
2851 if (driver == NULL ||
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002852 bind == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08002853 driver->setup == NULL ||
2854 driver->disconnect == NULL ||
2855 driver->suspend == NULL ||
2856 driver->resume == NULL)
2857 return -EINVAL;
2858 else if (udc == NULL)
2859 return -ENODEV;
2860 else if (udc->driver != NULL)
2861 return -EBUSY;
2862
2863 /* alloc resources */
2864 udc->qh_pool = dma_pool_create("ci13xxx_qh", &udc->gadget.dev,
2865 sizeof(struct ci13xxx_qh),
Artem Leonenko0a313c42010-12-14 23:47:06 -08002866 64, CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08002867 if (udc->qh_pool == NULL)
2868 return -ENOMEM;
2869
2870 udc->td_pool = dma_pool_create("ci13xxx_td", &udc->gadget.dev,
2871 sizeof(struct ci13xxx_td),
Artem Leonenko0a313c42010-12-14 23:47:06 -08002872 64, CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08002873 if (udc->td_pool == NULL) {
2874 dma_pool_destroy(udc->qh_pool);
2875 udc->qh_pool = NULL;
2876 return -ENOMEM;
2877 }
2878
2879 spin_lock_irqsave(udc->lock, flags);
2880
2881 info("hw_ep_max = %d", hw_ep_max);
2882
David Lopoaa69a802008-11-17 14:14:51 -08002883 udc->gadget.dev.driver = NULL;
2884
2885 retval = 0;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302886 for (i = 0; i < hw_ep_max/2; i++) {
2887 for (j = RX; j <= TX; j++) {
2888 int k = i + j * hw_ep_max/2;
2889 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
David Lopoaa69a802008-11-17 14:14:51 -08002890
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302891 scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
2892 (j == TX) ? "in" : "out");
David Lopoaa69a802008-11-17 14:14:51 -08002893
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302894 mEp->lock = udc->lock;
2895 mEp->device = &udc->gadget.dev;
2896 mEp->td_pool = udc->td_pool;
David Lopoaa69a802008-11-17 14:14:51 -08002897
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302898 mEp->ep.name = mEp->name;
2899 mEp->ep.ops = &usb_ep_ops;
2900 mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
David Lopoaa69a802008-11-17 14:14:51 -08002901
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302902 INIT_LIST_HEAD(&mEp->qh.queue);
Pavankumar Kondeti0a91efa2010-12-07 17:54:00 +05302903 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302904 mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
2905 &mEp->qh.dma);
Pavankumar Kondeti0a91efa2010-12-07 17:54:00 +05302906 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302907 if (mEp->qh.ptr == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002908 retval = -ENOMEM;
2909 else
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302910 memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
2911
2912 /* skip ep0 out and in endpoints */
2913 if (i == 0)
2914 continue;
2915
David Lopoaa69a802008-11-17 14:14:51 -08002916 list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302917 }
David Lopoaa69a802008-11-17 14:14:51 -08002918 }
2919 if (retval)
2920 goto done;
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302921 spin_unlock_irqrestore(udc->lock, flags);
2922 retval = usb_ep_enable(&udc->ep0out.ep, &ctrl_endpt_out_desc);
2923 if (retval)
2924 return retval;
2925 retval = usb_ep_enable(&udc->ep0in.ep, &ctrl_endpt_in_desc);
2926 if (retval)
2927 return retval;
2928 spin_lock_irqsave(udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002929
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302930 udc->gadget.ep0 = &udc->ep0in.ep;
David Lopoaa69a802008-11-17 14:14:51 -08002931 /* bind gadget */
2932 driver->driver.bus = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002933 udc->gadget.dev.driver = &driver->driver;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002934 udc->softconnect = 1;
David Lopoaa69a802008-11-17 14:14:51 -08002935
2936 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondeti98853282011-11-24 09:01:54 +05302937 pm_runtime_get_sync(&udc->gadget.dev);
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002938 retval = bind(&udc->gadget); /* MAY SLEEP */
David Lopoaa69a802008-11-17 14:14:51 -08002939 spin_lock_irqsave(udc->lock, flags);
2940
2941 if (retval) {
David Lopoaa69a802008-11-17 14:14:51 -08002942 udc->gadget.dev.driver = NULL;
2943 goto done;
2944 }
2945
Pavankumar Kondeti49d3df52011-01-11 09:19:21 +05302946 udc->driver = driver;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302947 if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
2948 if (udc->vbus_active) {
2949 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
2950 hw_device_reset(udc);
2951 } else {
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05302952 put = true;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302953 goto done;
2954 }
2955 }
2956
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05302957 if (!udc->softconnect) {
2958 put = true;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002959 goto done;
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05302960 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002961
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302962 retval = hw_device_state(udc->ep0out.qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08002963
2964 done:
2965 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondetid519cf42011-12-05 08:30:21 +05302966 if (retval || put)
Pavankumar Kondeti98853282011-11-24 09:01:54 +05302967 pm_runtime_put_sync(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08002968 return retval;
2969}
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002970EXPORT_SYMBOL(usb_gadget_probe_driver);
David Lopoaa69a802008-11-17 14:14:51 -08002971
2972/**
2973 * usb_gadget_unregister_driver: unregister a gadget driver
2974 *
2975 * Check usb_gadget_unregister_driver() at "usb_gadget.h" for details
2976 */
2977int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
2978{
2979 struct ci13xxx *udc = _udc;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302980 unsigned long i, flags;
David Lopoaa69a802008-11-17 14:14:51 -08002981
2982 trace("%p", driver);
2983
2984 if (driver == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08002985 driver->unbind == NULL ||
2986 driver->setup == NULL ||
2987 driver->disconnect == NULL ||
2988 driver->suspend == NULL ||
2989 driver->resume == NULL ||
2990 driver != udc->driver)
2991 return -EINVAL;
2992
2993 spin_lock_irqsave(udc->lock, flags);
2994
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302995 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) ||
2996 udc->vbus_active) {
2997 hw_device_state(0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302998 _gadget_stop_activity(&udc->gadget);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302999 pm_runtime_put(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303000 }
David Lopoaa69a802008-11-17 14:14:51 -08003001
3002 /* unbind gadget */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303003 spin_unlock_irqrestore(udc->lock, flags);
3004 driver->unbind(&udc->gadget); /* MAY SLEEP */
3005 spin_lock_irqsave(udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08003006
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303007 udc->gadget.dev.driver = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08003008
3009 /* free resources */
3010 for (i = 0; i < hw_ep_max; i++) {
3011 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
3012
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303013 if (!list_empty(&mEp->ep.ep_list))
David Lopoaa69a802008-11-17 14:14:51 -08003014 list_del_init(&mEp->ep.ep_list);
3015
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303016 if (mEp->qh.ptr != NULL)
3017 dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08003018 }
3019
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05303020 udc->gadget.ep0 = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08003021 udc->driver = NULL;
3022
3023 spin_unlock_irqrestore(udc->lock, flags);
3024
3025 if (udc->td_pool != NULL) {
3026 dma_pool_destroy(udc->td_pool);
3027 udc->td_pool = NULL;
3028 }
3029 if (udc->qh_pool != NULL) {
3030 dma_pool_destroy(udc->qh_pool);
3031 udc->qh_pool = NULL;
3032 }
3033
3034 return 0;
3035}
3036EXPORT_SYMBOL(usb_gadget_unregister_driver);
3037
3038/******************************************************************************
3039 * BUS block
3040 *****************************************************************************/
3041/**
3042 * udc_irq: global interrupt handler
3043 *
3044 * This function returns IRQ_HANDLED if the IRQ has been handled
3045 * It locks access to registers
3046 */
3047static irqreturn_t udc_irq(void)
3048{
3049 struct ci13xxx *udc = _udc;
3050 irqreturn_t retval;
3051 u32 intr;
3052
3053 trace();
3054
3055 if (udc == NULL) {
3056 err("ENODEV");
3057 return IRQ_HANDLED;
3058 }
3059
3060 spin_lock(udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303061
3062 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) {
3063 if (hw_cread(CAP_USBMODE, USBMODE_CM) !=
3064 USBMODE_CM_DEVICE) {
3065 spin_unlock(udc->lock);
3066 return IRQ_NONE;
3067 }
3068 }
David Lopoaa69a802008-11-17 14:14:51 -08003069 intr = hw_test_and_clear_intr_active();
3070 if (intr) {
3071 isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intr;
3072 isr_statistics.hndl.idx &= ISR_MASK;
3073 isr_statistics.hndl.cnt++;
3074
3075 /* order defines priority - do NOT change it */
3076 if (USBi_URI & intr) {
3077 isr_statistics.uri++;
3078 isr_reset_handler(udc);
3079 }
3080 if (USBi_PCI & intr) {
3081 isr_statistics.pci++;
3082 udc->gadget.speed = hw_port_is_high_speed() ?
3083 USB_SPEED_HIGH : USB_SPEED_FULL;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05303084 if (udc->suspended) {
3085 spin_unlock(udc->lock);
3086 udc->driver->resume(&udc->gadget);
3087 spin_lock(udc->lock);
3088 udc->suspended = 0;
3089 }
David Lopoaa69a802008-11-17 14:14:51 -08003090 }
3091 if (USBi_UEI & intr)
3092 isr_statistics.uei++;
3093 if (USBi_UI & intr) {
3094 isr_statistics.ui++;
3095 isr_tr_complete_handler(udc);
3096 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05303097 if (USBi_SLI & intr) {
3098 if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
3099 udc->suspended = 1;
3100 spin_unlock(udc->lock);
3101 udc->driver->suspend(&udc->gadget);
3102 spin_lock(udc->lock);
3103 }
David Lopoaa69a802008-11-17 14:14:51 -08003104 isr_statistics.sli++;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05303105 }
David Lopoaa69a802008-11-17 14:14:51 -08003106 retval = IRQ_HANDLED;
3107 } else {
3108 isr_statistics.none++;
3109 retval = IRQ_NONE;
3110 }
3111 spin_unlock(udc->lock);
3112
3113 return retval;
3114}
3115
3116/**
3117 * udc_release: driver release function
3118 * @dev: device
3119 *
3120 * Currently does nothing
3121 */
3122static void udc_release(struct device *dev)
3123{
3124 trace("%p", dev);
3125
3126 if (dev == NULL)
3127 err("EINVAL");
3128}
3129
3130/**
3131 * udc_probe: parent probe must call this to initialize UDC
3132 * @dev: parent device
3133 * @regs: registers base address
3134 * @name: driver name
3135 *
3136 * This function returns an error code
3137 * No interrupts active, the IRQ has not been requested yet
3138 * Kernel assumes 32-bit DMA operations by default, no need to dma_set_mask
3139 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303140static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
3141 void __iomem *regs)
David Lopoaa69a802008-11-17 14:14:51 -08003142{
3143 struct ci13xxx *udc;
3144 int retval = 0;
3145
3146 trace("%p, %p, %p", dev, regs, name);
3147
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303148 if (dev == NULL || regs == NULL || driver == NULL ||
3149 driver->name == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08003150 return -EINVAL;
3151
3152 udc = kzalloc(sizeof(struct ci13xxx), GFP_KERNEL);
3153 if (udc == NULL)
3154 return -ENOMEM;
3155
3156 udc->lock = &udc_lock;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303157 udc->regs = regs;
3158 udc->udc_driver = driver;
David Lopoaa69a802008-11-17 14:14:51 -08003159
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303160 udc->gadget.ops = &usb_gadget_ops;
David Lopoaa69a802008-11-17 14:14:51 -08003161 udc->gadget.speed = USB_SPEED_UNKNOWN;
3162 udc->gadget.is_dualspeed = 1;
3163 udc->gadget.is_otg = 0;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303164 udc->gadget.name = driver->name;
David Lopoaa69a802008-11-17 14:14:51 -08003165
3166 INIT_LIST_HEAD(&udc->gadget.ep_list);
3167 udc->gadget.ep0 = NULL;
3168
Kay Sievers5df58522009-03-24 16:38:23 -07003169 dev_set_name(&udc->gadget.dev, "gadget");
David Lopoaa69a802008-11-17 14:14:51 -08003170 udc->gadget.dev.dma_mask = dev->dma_mask;
Pavankumar Kondeti61948ee2010-12-07 17:54:01 +05303171 udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
David Lopoaa69a802008-11-17 14:14:51 -08003172 udc->gadget.dev.parent = dev;
3173 udc->gadget.dev.release = udc_release;
3174
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303175 retval = hw_device_init(regs);
3176 if (retval < 0)
3177 goto free_udc;
3178
3179 udc->transceiver = otg_get_transceiver();
3180
3181 if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
3182 if (udc->transceiver == NULL) {
3183 retval = -ENODEV;
3184 goto free_udc;
3185 }
3186 }
3187
3188 if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) {
3189 retval = hw_device_reset(udc);
3190 if (retval)
3191 goto put_transceiver;
3192 }
3193
David Lopoaa69a802008-11-17 14:14:51 -08003194 retval = device_register(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303195 if (retval) {
3196 put_device(&udc->gadget.dev);
3197 goto put_transceiver;
3198 }
David Lopoaa69a802008-11-17 14:14:51 -08003199
3200#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3201 retval = dbg_create_files(&udc->gadget.dev);
3202#endif
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303203 if (retval)
3204 goto unreg_device;
3205
3206 if (udc->transceiver) {
3207 retval = otg_set_peripheral(udc->transceiver, &udc->gadget);
3208 if (retval)
3209 goto remove_dbg;
David Lopoaa69a802008-11-17 14:14:51 -08003210 }
Pavankumar Kondetic0360192010-12-07 17:54:04 +05303211 pm_runtime_no_callbacks(&udc->gadget.dev);
3212 pm_runtime_enable(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08003213
3214 _udc = udc;
3215 return retval;
3216
David Lopoaa69a802008-11-17 14:14:51 -08003217 err("error = %i", retval);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303218remove_dbg:
3219#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3220 dbg_remove_files(&udc->gadget.dev);
3221#endif
3222unreg_device:
3223 device_unregister(&udc->gadget.dev);
3224put_transceiver:
3225 if (udc->transceiver)
3226 otg_put_transceiver(udc->transceiver);
3227free_udc:
David Lopoaa69a802008-11-17 14:14:51 -08003228 kfree(udc);
3229 _udc = NULL;
3230 return retval;
3231}
3232
3233/**
3234 * udc_remove: parent remove must call this to remove UDC
3235 *
3236 * No interrupts active, the IRQ has been released
3237 */
3238static void udc_remove(void)
3239{
3240 struct ci13xxx *udc = _udc;
3241
3242 if (udc == NULL) {
3243 err("EINVAL");
3244 return;
3245 }
3246
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303247 if (udc->transceiver) {
3248 otg_set_peripheral(udc->transceiver, &udc->gadget);
3249 otg_put_transceiver(udc->transceiver);
3250 }
David Lopoaa69a802008-11-17 14:14:51 -08003251#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3252 dbg_remove_files(&udc->gadget.dev);
3253#endif
3254 device_unregister(&udc->gadget.dev);
3255
3256 kfree(udc);
3257 _udc = NULL;
3258}