blob: 992ce1145d262eb5d08052600f3fd52729f6eca2 [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 *****************************************************************************/
Michael Grzeschik954aad82011-10-10 18:38:06 +020074
75#define DMA_ADDR_INVALID (~(dma_addr_t)0)
76
David Lopoaa69a802008-11-17 14:14:51 -080077/* ctrl register bank access */
78static DEFINE_SPINLOCK(udc_lock);
79
David Lopoaa69a802008-11-17 14:14:51 -080080/* control endpoint description */
81static const struct usb_endpoint_descriptor
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +053082ctrl_endpt_out_desc = {
David Lopoaa69a802008-11-17 14:14:51 -080083 .bLength = USB_DT_ENDPOINT_SIZE,
84 .bDescriptorType = USB_DT_ENDPOINT,
85
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +053086 .bEndpointAddress = USB_DIR_OUT,
87 .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
88 .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
89};
90
91static const struct usb_endpoint_descriptor
92ctrl_endpt_in_desc = {
93 .bLength = USB_DT_ENDPOINT_SIZE,
94 .bDescriptorType = USB_DT_ENDPOINT,
95
96 .bEndpointAddress = USB_DIR_IN,
David Lopoaa69a802008-11-17 14:14:51 -080097 .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
98 .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
99};
100
101/* UDC descriptor */
102static struct ci13xxx *_udc;
103
104/* Interrupt statistics */
105#define ISR_MASK 0x1F
106static struct {
107 u32 test;
108 u32 ui;
109 u32 uei;
110 u32 pci;
111 u32 uri;
112 u32 sli;
113 u32 none;
114 struct {
115 u32 cnt;
116 u32 buf[ISR_MASK+1];
117 u32 idx;
118 } hndl;
119} isr_statistics;
120
121/**
122 * ffs_nr: find first (least significant) bit set
123 * @x: the word to search
124 *
125 * This function returns bit number (instead of position)
126 */
127static int ffs_nr(u32 x)
128{
129 int n = ffs(x);
130
131 return n ? n-1 : 32;
132}
133
134/******************************************************************************
135 * HW block
136 *****************************************************************************/
137/* register bank descriptor */
138static struct {
139 unsigned lpm; /* is LPM? */
140 void __iomem *abs; /* bus map offset */
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300141 void __iomem *cap; /* bus map offset + CAP offset */
142 void __iomem *op; /* bus map offset + OP offset */
David Lopoaa69a802008-11-17 14:14:51 -0800143 size_t size; /* bank size */
144} hw_bank;
145
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530146/* MSM specific */
147#define ABS_AHBBURST (0x0090UL)
148#define ABS_AHBMODE (0x0098UL)
David Lopoaa69a802008-11-17 14:14:51 -0800149/* UDC register map */
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300150#define CAP_CAPLENGTH (0x000UL)
151#define CAP_HCCPARAMS (0x008UL)
152#define CAP_DCCPARAMS (0x024UL)
David Lopoaa69a802008-11-17 14:14:51 -0800153#define ABS_TESTMODE (hw_bank.lpm ? 0x0FCUL : 0x138UL)
154/* offset to CAPLENTGH (addr + data) */
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300155#define OP_USBCMD (0x000UL)
156#define OP_USBSTS (0x004UL)
157#define OP_USBINTR (0x008UL)
158#define OP_DEVICEADDR (0x014UL)
159#define OP_ENDPTLISTADDR (0x018UL)
160#define OP_PORTSC (0x044UL)
161#define OP_DEVLC (0x084UL)
162#define OP_USBMODE (hw_bank.lpm ? 0x0C8UL : 0x068UL)
163#define OP_ENDPTSETUPSTAT (hw_bank.lpm ? 0x0D8UL : 0x06CUL)
164#define OP_ENDPTPRIME (hw_bank.lpm ? 0x0DCUL : 0x070UL)
165#define OP_ENDPTFLUSH (hw_bank.lpm ? 0x0E0UL : 0x074UL)
166#define OP_ENDPTSTAT (hw_bank.lpm ? 0x0E4UL : 0x078UL)
167#define OP_ENDPTCOMPLETE (hw_bank.lpm ? 0x0E8UL : 0x07CUL)
168#define OP_ENDPTCTRL (hw_bank.lpm ? 0x0ECUL : 0x080UL)
169#define OP_LAST (hw_bank.lpm ? 0x12CUL : 0x0C0UL)
David Lopoaa69a802008-11-17 14:14:51 -0800170
171/* maximum number of enpoints: valid only after hw_device_reset() */
172static unsigned hw_ep_max;
173
174/**
175 * hw_ep_bit: calculates the bit number
176 * @num: endpoint number
177 * @dir: endpoint direction
178 *
179 * This function returns bit number
180 */
181static inline int hw_ep_bit(int num, int dir)
182{
183 return num + (dir ? 16 : 0);
184}
185
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200186static int ep_to_bit(int n)
187{
188 int fill = 16 - hw_ep_max / 2;
189
190 if (n >= hw_ep_max / 2)
191 n += fill;
192
193 return n;
194}
195
David Lopoaa69a802008-11-17 14:14:51 -0800196/**
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300197 * hw_read: reads from a register bitfield
198 * @base: register block address
199 * @addr: address relative to operational register base
David Lopoaa69a802008-11-17 14:14:51 -0800200 * @mask: bitfield mask
201 *
202 * This function returns register bitfield data
203 */
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300204static u32 hw_read(void __iomem *base, u32 addr, u32 mask)
David Lopoaa69a802008-11-17 14:14:51 -0800205{
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300206 return ioread32(addr + base) & mask;
David Lopoaa69a802008-11-17 14:14:51 -0800207}
208
209/**
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300210 * hw_write: writes to a register bitfield
211 * @base: register block address
212 * @addr: address relative to operational register base
David Lopoaa69a802008-11-17 14:14:51 -0800213 * @mask: bitfield mask
214 * @data: new data
215 */
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300216static void hw_write(void __iomem *base, u32 addr, u32 mask, u32 data)
David Lopoaa69a802008-11-17 14:14:51 -0800217{
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300218 iowrite32(hw_read(base, addr, ~mask) | (data & mask),
219 addr + base);
David Lopoaa69a802008-11-17 14:14:51 -0800220}
221
222/**
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300223 * hw_test_and_clear: tests & clears operational register bitfield
224 * @base: register block address
225 * @addr: address relative to operational register base
David Lopoaa69a802008-11-17 14:14:51 -0800226 * @mask: bitfield mask
227 *
228 * This function returns register bitfield data
229 */
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300230static u32 hw_test_and_clear(void __iomem *base, u32 addr, u32 mask)
David Lopoaa69a802008-11-17 14:14:51 -0800231{
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300232 u32 reg = hw_read(base, addr, mask);
David Lopoaa69a802008-11-17 14:14:51 -0800233
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300234 iowrite32(reg, addr + base);
David Lopoaa69a802008-11-17 14:14:51 -0800235 return reg;
236}
237
238/**
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300239 * hw_test_and_write: tests & writes operational register bitfield
240 * @base: register block address
241 * @addr: address relative to operational register base
David Lopoaa69a802008-11-17 14:14:51 -0800242 * @mask: bitfield mask
243 * @data: new data
244 *
245 * This function returns register bitfield data
246 */
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300247static u32 hw_test_and_write(void __iomem *base, u32 addr, u32 mask, u32 data)
David Lopoaa69a802008-11-17 14:14:51 -0800248{
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300249 u32 reg = hw_read(base, addr, ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800250
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300251 iowrite32((reg & ~mask) | (data & mask), addr + base);
David Lopoaa69a802008-11-17 14:14:51 -0800252 return (reg & mask) >> ffs_nr(mask);
253}
254
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300255static int hw_device_init(void __iomem *base, uintptr_t cap_offset)
David Lopoaa69a802008-11-17 14:14:51 -0800256{
257 u32 reg;
258
259 /* bank is a module variable */
260 hw_bank.abs = base;
261
262 hw_bank.cap = hw_bank.abs;
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300263 hw_bank.cap += cap_offset;
264 hw_bank.op = hw_bank.cap + ioread8(hw_bank.cap);
David Lopoaa69a802008-11-17 14:14:51 -0800265
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300266 reg = hw_read(hw_bank.cap, CAP_HCCPARAMS, HCCPARAMS_LEN) >>
267 ffs_nr(HCCPARAMS_LEN);
David Lopoaa69a802008-11-17 14:14:51 -0800268 hw_bank.lpm = reg;
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300269 hw_bank.size = hw_bank.op - hw_bank.abs;
270 hw_bank.size += OP_LAST;
David Lopoaa69a802008-11-17 14:14:51 -0800271 hw_bank.size /= sizeof(u32);
272
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300273 reg = hw_read(hw_bank.cap, CAP_DCCPARAMS, DCCPARAMS_DEN) >>
274 ffs_nr(DCCPARAMS_DEN);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530275 hw_ep_max = reg * 2; /* cache hw ENDPT_MAX */
David Lopoaa69a802008-11-17 14:14:51 -0800276
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530277 if (hw_ep_max == 0 || hw_ep_max > ENDPT_MAX)
278 return -ENODEV;
David Lopoaa69a802008-11-17 14:14:51 -0800279
280 /* setup lock mode ? */
281
282 /* ENDPTSETUPSTAT is '0' by default */
283
284 /* HCSPARAMS.bf.ppc SHOULD BE zero for device */
285
286 return 0;
287}
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530288/**
289 * hw_device_reset: resets chip (execute without interruption)
290 * @base: register base address
291 *
292 * This function returns an error code
293 */
294static int hw_device_reset(struct ci13xxx *udc)
295{
296 /* should flush & stop before reset */
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300297 hw_write(hw_bank.op, OP_ENDPTFLUSH, ~0, ~0);
298 hw_write(hw_bank.op, OP_USBCMD, USBCMD_RS, 0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530299
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300300 hw_write(hw_bank.op, OP_USBCMD, USBCMD_RST, USBCMD_RST);
301 while (hw_read(hw_bank.op, OP_USBCMD, USBCMD_RST))
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530302 udelay(10); /* not RTOS friendly */
303
304
305 if (udc->udc_driver->notify_event)
306 udc->udc_driver->notify_event(udc,
307 CI13XXX_CONTROLLER_RESET_EVENT);
308
Pavankumar Kondeti8c2387a2011-05-02 11:56:28 +0530309 if (udc->udc_driver->flags & CI13XXX_DISABLE_STREAMING)
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300310 hw_write(hw_bank.op, OP_USBMODE, USBMODE_SDIS, USBMODE_SDIS);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530311
312 /* USBMODE should be configured step by step */
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300313 hw_write(hw_bank.op, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
314 hw_write(hw_bank.op, OP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE);
315 /* HW >= 2.3 */
316 hw_write(hw_bank.op, OP_USBMODE, USBMODE_SLOM, USBMODE_SLOM);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530317
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300318 if (hw_read(hw_bank.op, OP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530319 pr_err("cannot enter in device mode");
320 pr_err("lpm = %i", hw_bank.lpm);
321 return -ENODEV;
322 }
323
324 return 0;
325}
David Lopoaa69a802008-11-17 14:14:51 -0800326
327/**
328 * hw_device_state: enables/disables interrupts & starts/stops device (execute
329 * without interruption)
330 * @dma: 0 => disable, !0 => enable and set dma engine
331 *
332 * This function returns an error code
333 */
334static int hw_device_state(u32 dma)
335{
336 if (dma) {
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300337 hw_write(hw_bank.op, OP_ENDPTLISTADDR, ~0, dma);
David Lopoaa69a802008-11-17 14:14:51 -0800338 /* interrupt, error, port change, reset, sleep/suspend */
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300339 hw_write(hw_bank.op, OP_USBINTR, ~0,
David Lopoaa69a802008-11-17 14:14:51 -0800340 USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300341 hw_write(hw_bank.op, OP_USBCMD, USBCMD_RS, USBCMD_RS);
David Lopoaa69a802008-11-17 14:14:51 -0800342 } else {
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300343 hw_write(hw_bank.op, OP_USBCMD, USBCMD_RS, 0);
344 hw_write(hw_bank.op, OP_USBINTR, ~0, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800345 }
346 return 0;
347}
348
349/**
350 * hw_ep_flush: flush endpoint fifo (execute without interruption)
351 * @num: endpoint number
352 * @dir: endpoint direction
353 *
354 * This function returns an error code
355 */
356static int hw_ep_flush(int num, int dir)
357{
358 int n = hw_ep_bit(num, dir);
359
360 do {
361 /* flush any pending transfer */
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300362 hw_write(hw_bank.op, OP_ENDPTFLUSH, BIT(n), BIT(n));
363 while (hw_read(hw_bank.op, OP_ENDPTFLUSH, BIT(n)))
David Lopoaa69a802008-11-17 14:14:51 -0800364 cpu_relax();
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300365 } while (hw_read(hw_bank.op, OP_ENDPTSTAT, BIT(n)));
David Lopoaa69a802008-11-17 14:14:51 -0800366
367 return 0;
368}
369
370/**
371 * hw_ep_disable: disables endpoint (execute without interruption)
372 * @num: endpoint number
373 * @dir: endpoint direction
374 *
375 * This function returns an error code
376 */
377static int hw_ep_disable(int num, int dir)
378{
379 hw_ep_flush(num, dir);
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300380 hw_write(hw_bank.op, OP_ENDPTCTRL + num * sizeof(u32),
David Lopoaa69a802008-11-17 14:14:51 -0800381 dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0);
382 return 0;
383}
384
385/**
386 * hw_ep_enable: enables endpoint (execute without interruption)
387 * @num: endpoint number
388 * @dir: endpoint direction
389 * @type: endpoint type
390 *
391 * This function returns an error code
392 */
393static int hw_ep_enable(int num, int dir, int type)
394{
395 u32 mask, data;
396
397 if (dir) {
398 mask = ENDPTCTRL_TXT; /* type */
399 data = type << ffs_nr(mask);
400
401 mask |= ENDPTCTRL_TXS; /* unstall */
402 mask |= ENDPTCTRL_TXR; /* reset data toggle */
403 data |= ENDPTCTRL_TXR;
404 mask |= ENDPTCTRL_TXE; /* enable */
405 data |= ENDPTCTRL_TXE;
406 } else {
407 mask = ENDPTCTRL_RXT; /* type */
408 data = type << ffs_nr(mask);
409
410 mask |= ENDPTCTRL_RXS; /* unstall */
411 mask |= ENDPTCTRL_RXR; /* reset data toggle */
412 data |= ENDPTCTRL_RXR;
413 mask |= ENDPTCTRL_RXE; /* enable */
414 data |= ENDPTCTRL_RXE;
415 }
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300416 hw_write(hw_bank.op, OP_ENDPTCTRL + num * sizeof(u32), mask, data);
David Lopoaa69a802008-11-17 14:14:51 -0800417 return 0;
418}
419
420/**
421 * hw_ep_get_halt: return endpoint halt status
422 * @num: endpoint number
423 * @dir: endpoint direction
424 *
425 * This function returns 1 if endpoint halted
426 */
427static int hw_ep_get_halt(int num, int dir)
428{
429 u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
430
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300431 return !!hw_read(hw_bank.op, OP_ENDPTCTRL + num * sizeof(u32), mask);
David Lopoaa69a802008-11-17 14:14:51 -0800432}
433
434/**
David Lopoaa69a802008-11-17 14:14:51 -0800435 * hw_test_and_clear_setup_status: test & clear setup status (execute without
436 * interruption)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200437 * @n: endpoint number
David Lopoaa69a802008-11-17 14:14:51 -0800438 *
439 * This function returns setup status
440 */
441static int hw_test_and_clear_setup_status(int n)
442{
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200443 n = ep_to_bit(n);
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300444 return hw_test_and_clear(hw_bank.op, OP_ENDPTSETUPSTAT, BIT(n));
David Lopoaa69a802008-11-17 14:14:51 -0800445}
446
447/**
448 * hw_ep_prime: primes endpoint (execute without interruption)
449 * @num: endpoint number
450 * @dir: endpoint direction
451 * @is_ctrl: true if control endpoint
452 *
453 * This function returns an error code
454 */
455static int hw_ep_prime(int num, int dir, int is_ctrl)
456{
457 int n = hw_ep_bit(num, dir);
458
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300459 if (is_ctrl && dir == RX &&
460 hw_read(hw_bank.op, OP_ENDPTSETUPSTAT, BIT(num)))
David Lopoaa69a802008-11-17 14:14:51 -0800461 return -EAGAIN;
462
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300463 hw_write(hw_bank.op, OP_ENDPTPRIME, BIT(n), BIT(n));
David Lopoaa69a802008-11-17 14:14:51 -0800464
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300465 while (hw_read(hw_bank.op, OP_ENDPTPRIME, BIT(n)))
David Lopoaa69a802008-11-17 14:14:51 -0800466 cpu_relax();
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300467 if (is_ctrl && dir == RX &&
468 hw_read(hw_bank.op, OP_ENDPTSETUPSTAT, BIT(num)))
David Lopoaa69a802008-11-17 14:14:51 -0800469 return -EAGAIN;
470
471 /* status shoult be tested according with manual but it doesn't work */
472 return 0;
473}
474
475/**
476 * hw_ep_set_halt: configures ep halt & resets data toggle after clear (execute
477 * without interruption)
478 * @num: endpoint number
479 * @dir: endpoint direction
480 * @value: true => stall, false => unstall
481 *
482 * This function returns an error code
483 */
484static int hw_ep_set_halt(int num, int dir, int value)
485{
486 if (value != 0 && value != 1)
487 return -EINVAL;
488
489 do {
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300490 u32 addr = OP_ENDPTCTRL + num * sizeof(u32);
David Lopoaa69a802008-11-17 14:14:51 -0800491 u32 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
492 u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR;
493
494 /* data toggle - reserved for EP0 but it's in ESS */
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300495 hw_write(hw_bank.op, addr, mask_xs|mask_xr,
496 value ? mask_xs : mask_xr);
David Lopoaa69a802008-11-17 14:14:51 -0800497
498 } while (value != hw_ep_get_halt(num, dir));
499
500 return 0;
501}
502
503/**
504 * hw_intr_clear: disables interrupt & clears interrupt status (execute without
505 * interruption)
506 * @n: interrupt bit
507 *
508 * This function returns an error code
509 */
510static int hw_intr_clear(int n)
511{
512 if (n >= REG_BITS)
513 return -EINVAL;
514
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300515 hw_write(hw_bank.op, OP_USBINTR, BIT(n), 0);
516 hw_write(hw_bank.op, OP_USBSTS, BIT(n), BIT(n));
David Lopoaa69a802008-11-17 14:14:51 -0800517 return 0;
518}
519
520/**
521 * hw_intr_force: enables interrupt & forces interrupt status (execute without
522 * interruption)
523 * @n: interrupt bit
524 *
525 * This function returns an error code
526 */
527static int hw_intr_force(int n)
528{
529 if (n >= REG_BITS)
530 return -EINVAL;
531
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300532 hw_write(hw_bank.cap, ABS_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
533 hw_write(hw_bank.op, OP_USBINTR, BIT(n), BIT(n));
534 hw_write(hw_bank.op, OP_USBSTS, BIT(n), BIT(n));
535 hw_write(hw_bank.cap, ABS_TESTMODE, TESTMODE_FORCE, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800536 return 0;
537}
538
539/**
540 * hw_is_port_high_speed: test if port is high speed
541 *
542 * This function returns true if high speed port
543 */
544static int hw_port_is_high_speed(void)
545{
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300546 return hw_bank.lpm ? hw_read(hw_bank.op, OP_DEVLC, DEVLC_PSPD) :
547 hw_read(hw_bank.op, OP_PORTSC, PORTSC_HSP);
David Lopoaa69a802008-11-17 14:14:51 -0800548}
549
550/**
551 * hw_port_test_get: reads port test mode value
552 *
553 * This function returns port test mode value
554 */
555static u8 hw_port_test_get(void)
556{
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300557 return hw_read(hw_bank.op, OP_PORTSC, PORTSC_PTC) >> ffs_nr(PORTSC_PTC);
David Lopoaa69a802008-11-17 14:14:51 -0800558}
559
560/**
561 * hw_port_test_set: writes port test mode (execute without interruption)
562 * @mode: new value
563 *
564 * This function returns an error code
565 */
566static int hw_port_test_set(u8 mode)
567{
568 const u8 TEST_MODE_MAX = 7;
569
570 if (mode > TEST_MODE_MAX)
571 return -EINVAL;
572
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300573 hw_write(hw_bank.op, OP_PORTSC, PORTSC_PTC, mode << ffs_nr(PORTSC_PTC));
David Lopoaa69a802008-11-17 14:14:51 -0800574 return 0;
575}
576
577/**
578 * hw_read_intr_enable: returns interrupt enable register
579 *
580 * This function returns register data
581 */
582static u32 hw_read_intr_enable(void)
583{
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300584 return hw_read(hw_bank.op, OP_USBINTR, ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800585}
586
587/**
588 * hw_read_intr_status: returns interrupt status register
589 *
590 * This function returns register data
591 */
592static u32 hw_read_intr_status(void)
593{
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300594 return hw_read(hw_bank.op, OP_USBSTS, ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800595}
596
597/**
598 * hw_register_read: reads all device registers (execute without interruption)
599 * @buf: destination buffer
600 * @size: buffer size
601 *
602 * This function returns number of registers read
603 */
604static size_t hw_register_read(u32 *buf, size_t size)
605{
606 unsigned i;
607
608 if (size > hw_bank.size)
609 size = hw_bank.size;
610
611 for (i = 0; i < size; i++)
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300612 buf[i] = hw_read(hw_bank.cap, i * sizeof(u32), ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800613
614 return size;
615}
616
617/**
618 * hw_register_write: writes to register
619 * @addr: register address
620 * @data: register value
621 *
622 * This function returns an error code
623 */
624static int hw_register_write(u16 addr, u32 data)
625{
626 /* align */
627 addr /= sizeof(u32);
628
629 if (addr >= hw_bank.size)
630 return -EINVAL;
631
632 /* align */
633 addr *= sizeof(u32);
634
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300635 hw_write(hw_bank.cap, addr, ~0, data);
David Lopoaa69a802008-11-17 14:14:51 -0800636 return 0;
637}
638
639/**
640 * hw_test_and_clear_complete: test & clear complete status (execute without
641 * interruption)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200642 * @n: endpoint number
David Lopoaa69a802008-11-17 14:14:51 -0800643 *
644 * This function returns complete status
645 */
646static int hw_test_and_clear_complete(int n)
647{
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200648 n = ep_to_bit(n);
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300649 return hw_test_and_clear(hw_bank.op, OP_ENDPTCOMPLETE, BIT(n));
David Lopoaa69a802008-11-17 14:14:51 -0800650}
651
652/**
653 * hw_test_and_clear_intr_active: test & clear active interrupts (execute
654 * without interruption)
655 *
656 * This function returns active interrutps
657 */
658static u32 hw_test_and_clear_intr_active(void)
659{
660 u32 reg = hw_read_intr_status() & hw_read_intr_enable();
661
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300662 hw_write(hw_bank.op, OP_USBSTS, ~0, reg);
David Lopoaa69a802008-11-17 14:14:51 -0800663 return reg;
664}
665
666/**
667 * hw_test_and_clear_setup_guard: test & clear setup guard (execute without
668 * interruption)
669 *
670 * This function returns guard value
671 */
672static int hw_test_and_clear_setup_guard(void)
673{
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300674 return hw_test_and_write(hw_bank.op, OP_USBCMD, USBCMD_SUTW, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800675}
676
677/**
678 * hw_test_and_set_setup_guard: test & set setup guard (execute without
679 * interruption)
680 *
681 * This function returns guard value
682 */
683static int hw_test_and_set_setup_guard(void)
684{
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300685 return hw_test_and_write(hw_bank.op, OP_USBCMD, USBCMD_SUTW,
686 USBCMD_SUTW);
David Lopoaa69a802008-11-17 14:14:51 -0800687}
688
689/**
690 * hw_usb_set_address: configures USB address (execute without interruption)
691 * @value: new USB address
692 *
693 * This function returns an error code
694 */
695static int hw_usb_set_address(u8 value)
696{
697 /* advance */
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300698 hw_write(hw_bank.op, OP_DEVICEADDR,
699 DEVICEADDR_USBADR | DEVICEADDR_USBADRA,
700 value << ffs_nr(DEVICEADDR_USBADR) | DEVICEADDR_USBADRA);
David Lopoaa69a802008-11-17 14:14:51 -0800701 return 0;
702}
703
704/**
705 * hw_usb_reset: restart device after a bus reset (execute without
706 * interruption)
707 *
708 * This function returns an error code
709 */
710static int hw_usb_reset(void)
711{
712 hw_usb_set_address(0);
713
714 /* ESS flushes only at end?!? */
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300715 hw_write(hw_bank.op, OP_ENDPTFLUSH, ~0, ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800716
717 /* clear setup token semaphores */
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300718 hw_write(hw_bank.op, OP_ENDPTSETUPSTAT, 0, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800719
720 /* clear complete status */
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300721 hw_write(hw_bank.op, OP_ENDPTCOMPLETE, 0, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800722
723 /* wait until all bits cleared */
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300724 while (hw_read(hw_bank.op, OP_ENDPTPRIME, ~0))
David Lopoaa69a802008-11-17 14:14:51 -0800725 udelay(10); /* not RTOS friendly */
726
727 /* reset all endpoints ? */
728
729 /* reset internal status and wait for further instructions
730 no need to verify the port reset status (ESS does it) */
731
732 return 0;
733}
734
735/******************************************************************************
736 * DBG block
737 *****************************************************************************/
738/**
739 * show_device: prints information about device capabilities and status
740 *
741 * Check "device.h" for details
742 */
743static ssize_t show_device(struct device *dev, struct device_attribute *attr,
744 char *buf)
745{
746 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
747 struct usb_gadget *gadget = &udc->gadget;
748 int n = 0;
749
750 dbg_trace("[%s] %p\n", __func__, buf);
751 if (attr == NULL || buf == NULL) {
752 dev_err(dev, "[%s] EINVAL\n", __func__);
753 return 0;
754 }
755
756 n += scnprintf(buf + n, PAGE_SIZE - n, "speed = %d\n",
757 gadget->speed);
Michal Nazarewiczd327ab52011-11-19 18:27:37 +0100758 n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed = %d\n",
759 gadget->max_speed);
760 /* TODO: Scheduled for removal in 3.8. */
David Lopoaa69a802008-11-17 14:14:51 -0800761 n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed = %d\n",
Michal Nazarewiczd327ab52011-11-19 18:27:37 +0100762 gadget_is_dualspeed(gadget));
David Lopoaa69a802008-11-17 14:14:51 -0800763 n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg = %d\n",
764 gadget->is_otg);
765 n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral = %d\n",
766 gadget->is_a_peripheral);
767 n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable = %d\n",
768 gadget->b_hnp_enable);
769 n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support = %d\n",
770 gadget->a_hnp_support);
771 n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n",
772 gadget->a_alt_hnp_support);
773 n += scnprintf(buf + n, PAGE_SIZE - n, "name = %s\n",
774 (gadget->name ? gadget->name : ""));
775
776 return n;
777}
778static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
779
780/**
781 * show_driver: prints information about attached gadget (if any)
782 *
783 * Check "device.h" for details
784 */
785static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
786 char *buf)
787{
788 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
789 struct usb_gadget_driver *driver = udc->driver;
790 int n = 0;
791
792 dbg_trace("[%s] %p\n", __func__, buf);
793 if (attr == NULL || buf == NULL) {
794 dev_err(dev, "[%s] EINVAL\n", __func__);
795 return 0;
796 }
797
798 if (driver == NULL)
799 return scnprintf(buf, PAGE_SIZE,
800 "There is no gadget attached!\n");
801
802 n += scnprintf(buf + n, PAGE_SIZE - n, "function = %s\n",
803 (driver->function ? driver->function : ""));
804 n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n",
Michal Nazarewicz7177aed2011-11-19 18:27:38 +0100805 driver->max_speed);
David Lopoaa69a802008-11-17 14:14:51 -0800806
807 return n;
808}
809static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL);
810
811/* Maximum event message length */
812#define DBG_DATA_MSG 64UL
813
814/* Maximum event messages */
815#define DBG_DATA_MAX 128UL
816
817/* Event buffer descriptor */
818static struct {
819 char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */
820 unsigned idx; /* index */
821 unsigned tty; /* print to console? */
822 rwlock_t lck; /* lock */
823} dbg_data = {
824 .idx = 0,
825 .tty = 0,
826 .lck = __RW_LOCK_UNLOCKED(lck)
827};
828
829/**
830 * dbg_dec: decrements debug event index
831 * @idx: buffer index
832 */
833static void dbg_dec(unsigned *idx)
834{
835 *idx = (*idx - 1) & (DBG_DATA_MAX-1);
836}
837
838/**
839 * dbg_inc: increments debug event index
840 * @idx: buffer index
841 */
842static void dbg_inc(unsigned *idx)
843{
844 *idx = (*idx + 1) & (DBG_DATA_MAX-1);
845}
846
847/**
848 * dbg_print: prints the common part of the event
849 * @addr: endpoint address
850 * @name: event name
851 * @status: status
852 * @extra: extra information
853 */
854static void dbg_print(u8 addr, const char *name, int status, const char *extra)
855{
856 struct timeval tval;
857 unsigned int stamp;
858 unsigned long flags;
859
860 write_lock_irqsave(&dbg_data.lck, flags);
861
862 do_gettimeofday(&tval);
863 stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s */
864 stamp = stamp * 1000000 + tval.tv_usec;
865
866 scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +0300867 "%04X\t? %02X %-7.7s %4i ?\t%s\n",
David Lopoaa69a802008-11-17 14:14:51 -0800868 stamp, addr, name, status, extra);
869
870 dbg_inc(&dbg_data.idx);
871
872 write_unlock_irqrestore(&dbg_data.lck, flags);
873
874 if (dbg_data.tty != 0)
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +0300875 pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n",
David Lopoaa69a802008-11-17 14:14:51 -0800876 stamp, addr, name, status, extra);
877}
878
879/**
880 * dbg_done: prints a DONE event
881 * @addr: endpoint address
882 * @td: transfer descriptor
883 * @status: status
884 */
885static void dbg_done(u8 addr, const u32 token, int status)
886{
887 char msg[DBG_DATA_MSG];
888
889 scnprintf(msg, sizeof(msg), "%d %02X",
890 (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES),
891 (int)(token & TD_STATUS) >> ffs_nr(TD_STATUS));
892 dbg_print(addr, "DONE", status, msg);
893}
894
895/**
896 * dbg_event: prints a generic event
897 * @addr: endpoint address
898 * @name: event name
899 * @status: status
900 */
901static void dbg_event(u8 addr, const char *name, int status)
902{
903 if (name != NULL)
904 dbg_print(addr, name, status, "");
905}
906
907/*
908 * dbg_queue: prints a QUEUE event
909 * @addr: endpoint address
910 * @req: USB request
911 * @status: status
912 */
913static void dbg_queue(u8 addr, const struct usb_request *req, int status)
914{
915 char msg[DBG_DATA_MSG];
916
917 if (req != NULL) {
918 scnprintf(msg, sizeof(msg),
919 "%d %d", !req->no_interrupt, req->length);
920 dbg_print(addr, "QUEUE", status, msg);
921 }
922}
923
924/**
925 * dbg_setup: prints a SETUP event
926 * @addr: endpoint address
927 * @req: setup request
928 */
929static void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
930{
931 char msg[DBG_DATA_MSG];
932
933 if (req != NULL) {
934 scnprintf(msg, sizeof(msg),
935 "%02X %02X %04X %04X %d", req->bRequestType,
936 req->bRequest, le16_to_cpu(req->wValue),
937 le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
938 dbg_print(addr, "SETUP", 0, msg);
939 }
940}
941
942/**
943 * show_events: displays the event buffer
944 *
945 * Check "device.h" for details
946 */
947static ssize_t show_events(struct device *dev, struct device_attribute *attr,
948 char *buf)
949{
950 unsigned long flags;
951 unsigned i, j, n = 0;
952
953 dbg_trace("[%s] %p\n", __func__, buf);
954 if (attr == NULL || buf == NULL) {
955 dev_err(dev, "[%s] EINVAL\n", __func__);
956 return 0;
957 }
958
959 read_lock_irqsave(&dbg_data.lck, flags);
960
961 i = dbg_data.idx;
962 for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) {
963 n += strlen(dbg_data.buf[i]);
964 if (n >= PAGE_SIZE) {
965 n -= strlen(dbg_data.buf[i]);
966 break;
967 }
968 }
969 for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i))
970 j += scnprintf(buf + j, PAGE_SIZE - j,
971 "%s", dbg_data.buf[i]);
972
973 read_unlock_irqrestore(&dbg_data.lck, flags);
974
975 return n;
976}
977
978/**
979 * store_events: configure if events are going to be also printed to console
980 *
981 * Check "device.h" for details
982 */
983static ssize_t store_events(struct device *dev, struct device_attribute *attr,
984 const char *buf, size_t count)
985{
986 unsigned tty;
987
988 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
989 if (attr == NULL || buf == NULL) {
990 dev_err(dev, "[%s] EINVAL\n", __func__);
991 goto done;
992 }
993
994 if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
995 dev_err(dev, "<1|0>: enable|disable console log\n");
996 goto done;
997 }
998
999 dbg_data.tty = tty;
1000 dev_info(dev, "tty = %u", dbg_data.tty);
1001
1002 done:
1003 return count;
1004}
1005static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
1006
1007/**
1008 * show_inters: interrupt status, enable status and historic
1009 *
1010 * Check "device.h" for details
1011 */
1012static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
1013 char *buf)
1014{
1015 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1016 unsigned long flags;
1017 u32 intr;
1018 unsigned i, j, n = 0;
1019
1020 dbg_trace("[%s] %p\n", __func__, buf);
1021 if (attr == NULL || buf == NULL) {
1022 dev_err(dev, "[%s] EINVAL\n", __func__);
1023 return 0;
1024 }
1025
1026 spin_lock_irqsave(udc->lock, flags);
1027
1028 n += scnprintf(buf + n, PAGE_SIZE - n,
1029 "status = %08x\n", hw_read_intr_status());
1030 n += scnprintf(buf + n, PAGE_SIZE - n,
1031 "enable = %08x\n", hw_read_intr_enable());
1032
1033 n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
1034 isr_statistics.test);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001035 n += scnprintf(buf + n, PAGE_SIZE - n, "? ui = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001036 isr_statistics.ui);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001037 n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001038 isr_statistics.uei);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001039 n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001040 isr_statistics.pci);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001041 n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001042 isr_statistics.uri);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001043 n += scnprintf(buf + n, PAGE_SIZE - n, "? sli = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001044 isr_statistics.sli);
1045 n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n",
1046 isr_statistics.none);
1047 n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n",
1048 isr_statistics.hndl.cnt);
1049
1050 for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) {
1051 i &= ISR_MASK;
1052 intr = isr_statistics.hndl.buf[i];
1053
1054 if (USBi_UI & intr)
1055 n += scnprintf(buf + n, PAGE_SIZE - n, "ui ");
1056 intr &= ~USBi_UI;
1057 if (USBi_UEI & intr)
1058 n += scnprintf(buf + n, PAGE_SIZE - n, "uei ");
1059 intr &= ~USBi_UEI;
1060 if (USBi_PCI & intr)
1061 n += scnprintf(buf + n, PAGE_SIZE - n, "pci ");
1062 intr &= ~USBi_PCI;
1063 if (USBi_URI & intr)
1064 n += scnprintf(buf + n, PAGE_SIZE - n, "uri ");
1065 intr &= ~USBi_URI;
1066 if (USBi_SLI & intr)
1067 n += scnprintf(buf + n, PAGE_SIZE - n, "sli ");
1068 intr &= ~USBi_SLI;
1069 if (intr)
1070 n += scnprintf(buf + n, PAGE_SIZE - n, "??? ");
1071 if (isr_statistics.hndl.buf[i])
1072 n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
1073 }
1074
1075 spin_unlock_irqrestore(udc->lock, flags);
1076
1077 return n;
1078}
1079
1080/**
1081 * store_inters: enable & force or disable an individual interrutps
1082 * (to be used for test purposes only)
1083 *
1084 * Check "device.h" for details
1085 */
1086static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
1087 const char *buf, size_t count)
1088{
1089 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1090 unsigned long flags;
1091 unsigned en, bit;
1092
1093 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1094 if (attr == NULL || buf == NULL) {
1095 dev_err(dev, "[%s] EINVAL\n", __func__);
1096 goto done;
1097 }
1098
1099 if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
1100 dev_err(dev, "<1|0> <bit>: enable|disable interrupt");
1101 goto done;
1102 }
1103
1104 spin_lock_irqsave(udc->lock, flags);
1105 if (en) {
1106 if (hw_intr_force(bit))
1107 dev_err(dev, "invalid bit number\n");
1108 else
1109 isr_statistics.test++;
1110 } else {
1111 if (hw_intr_clear(bit))
1112 dev_err(dev, "invalid bit number\n");
1113 }
1114 spin_unlock_irqrestore(udc->lock, flags);
1115
1116 done:
1117 return count;
1118}
1119static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
1120
1121/**
1122 * show_port_test: reads port test mode
1123 *
1124 * Check "device.h" for details
1125 */
1126static ssize_t show_port_test(struct device *dev,
1127 struct device_attribute *attr, char *buf)
1128{
1129 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1130 unsigned long flags;
1131 unsigned mode;
1132
1133 dbg_trace("[%s] %p\n", __func__, buf);
1134 if (attr == NULL || buf == NULL) {
1135 dev_err(dev, "[%s] EINVAL\n", __func__);
1136 return 0;
1137 }
1138
1139 spin_lock_irqsave(udc->lock, flags);
1140 mode = hw_port_test_get();
1141 spin_unlock_irqrestore(udc->lock, flags);
1142
1143 return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
1144}
1145
1146/**
1147 * store_port_test: writes port test mode
1148 *
1149 * Check "device.h" for details
1150 */
1151static ssize_t store_port_test(struct device *dev,
1152 struct device_attribute *attr,
1153 const char *buf, size_t count)
1154{
1155 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1156 unsigned long flags;
1157 unsigned mode;
1158
1159 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1160 if (attr == NULL || buf == NULL) {
1161 dev_err(dev, "[%s] EINVAL\n", __func__);
1162 goto done;
1163 }
1164
1165 if (sscanf(buf, "%u", &mode) != 1) {
1166 dev_err(dev, "<mode>: set port test mode");
1167 goto done;
1168 }
1169
1170 spin_lock_irqsave(udc->lock, flags);
1171 if (hw_port_test_set(mode))
1172 dev_err(dev, "invalid mode\n");
1173 spin_unlock_irqrestore(udc->lock, flags);
1174
1175 done:
1176 return count;
1177}
1178static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
1179 show_port_test, store_port_test);
1180
1181/**
1182 * show_qheads: DMA contents of all queue heads
1183 *
1184 * Check "device.h" for details
1185 */
1186static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
1187 char *buf)
1188{
1189 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1190 unsigned long flags;
1191 unsigned i, j, n = 0;
1192
1193 dbg_trace("[%s] %p\n", __func__, buf);
1194 if (attr == NULL || buf == NULL) {
1195 dev_err(dev, "[%s] EINVAL\n", __func__);
1196 return 0;
1197 }
1198
1199 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301200 for (i = 0; i < hw_ep_max/2; i++) {
1201 struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i];
1202 struct ci13xxx_ep *mEpTx = &udc->ci13xxx_ep[i + hw_ep_max/2];
David Lopoaa69a802008-11-17 14:14:51 -08001203 n += scnprintf(buf + n, PAGE_SIZE - n,
1204 "EP=%02i: RX=%08X TX=%08X\n",
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301205 i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08001206 for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) {
1207 n += scnprintf(buf + n, PAGE_SIZE - n,
1208 " %04X: %08X %08X\n", j,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301209 *((u32 *)mEpRx->qh.ptr + j),
1210 *((u32 *)mEpTx->qh.ptr + j));
David Lopoaa69a802008-11-17 14:14:51 -08001211 }
1212 }
1213 spin_unlock_irqrestore(udc->lock, flags);
1214
1215 return n;
1216}
1217static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
1218
1219/**
1220 * show_registers: dumps all registers
1221 *
1222 * Check "device.h" for details
1223 */
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001224#define DUMP_ENTRIES 512
David Lopoaa69a802008-11-17 14:14:51 -08001225static ssize_t show_registers(struct device *dev,
1226 struct device_attribute *attr, char *buf)
1227{
1228 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1229 unsigned long flags;
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001230 u32 *dump;
David Lopoaa69a802008-11-17 14:14:51 -08001231 unsigned i, k, n = 0;
1232
1233 dbg_trace("[%s] %p\n", __func__, buf);
1234 if (attr == NULL || buf == NULL) {
1235 dev_err(dev, "[%s] EINVAL\n", __func__);
1236 return 0;
1237 }
1238
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001239 dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
1240 if (!dump) {
1241 dev_err(dev, "%s: out of memory\n", __func__);
1242 return 0;
1243 }
1244
David Lopoaa69a802008-11-17 14:14:51 -08001245 spin_lock_irqsave(udc->lock, flags);
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001246 k = hw_register_read(dump, DUMP_ENTRIES);
David Lopoaa69a802008-11-17 14:14:51 -08001247 spin_unlock_irqrestore(udc->lock, flags);
1248
1249 for (i = 0; i < k; i++) {
1250 n += scnprintf(buf + n, PAGE_SIZE - n,
1251 "reg[0x%04X] = 0x%08X\n",
1252 i * (unsigned)sizeof(u32), dump[i]);
1253 }
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001254 kfree(dump);
David Lopoaa69a802008-11-17 14:14:51 -08001255
1256 return n;
1257}
1258
1259/**
1260 * store_registers: writes value to register address
1261 *
1262 * Check "device.h" for details
1263 */
1264static ssize_t store_registers(struct device *dev,
1265 struct device_attribute *attr,
1266 const char *buf, size_t count)
1267{
1268 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1269 unsigned long addr, data, flags;
1270
1271 dbg_trace("[%s] %p, %d\n", __func__, buf, count);
1272 if (attr == NULL || buf == NULL) {
1273 dev_err(dev, "[%s] EINVAL\n", __func__);
1274 goto done;
1275 }
1276
1277 if (sscanf(buf, "%li %li", &addr, &data) != 2) {
1278 dev_err(dev, "<addr> <data>: write data to register address");
1279 goto done;
1280 }
1281
1282 spin_lock_irqsave(udc->lock, flags);
1283 if (hw_register_write(addr, data))
1284 dev_err(dev, "invalid address range\n");
1285 spin_unlock_irqrestore(udc->lock, flags);
1286
1287 done:
1288 return count;
1289}
1290static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
1291 show_registers, store_registers);
1292
1293/**
1294 * show_requests: DMA contents of all requests currently queued (all endpts)
1295 *
1296 * Check "device.h" for details
1297 */
1298static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
1299 char *buf)
1300{
1301 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1302 unsigned long flags;
1303 struct list_head *ptr = NULL;
1304 struct ci13xxx_req *req = NULL;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301305 unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
David Lopoaa69a802008-11-17 14:14:51 -08001306
1307 dbg_trace("[%s] %p\n", __func__, buf);
1308 if (attr == NULL || buf == NULL) {
1309 dev_err(dev, "[%s] EINVAL\n", __func__);
1310 return 0;
1311 }
1312
1313 spin_lock_irqsave(udc->lock, flags);
1314 for (i = 0; i < hw_ep_max; i++)
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301315 list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue)
1316 {
1317 req = list_entry(ptr, struct ci13xxx_req, queue);
David Lopoaa69a802008-11-17 14:14:51 -08001318
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301319 n += scnprintf(buf + n, PAGE_SIZE - n,
1320 "EP=%02i: TD=%08X %s\n",
1321 i % hw_ep_max/2, (u32)req->dma,
1322 ((i < hw_ep_max/2) ? "RX" : "TX"));
1323
1324 for (j = 0; j < qSize; j++)
David Lopoaa69a802008-11-17 14:14:51 -08001325 n += scnprintf(buf + n, PAGE_SIZE - n,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301326 " %04X: %08X\n", j,
1327 *((u32 *)req->ptr + j));
1328 }
David Lopoaa69a802008-11-17 14:14:51 -08001329 spin_unlock_irqrestore(udc->lock, flags);
1330
1331 return n;
1332}
1333static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL);
1334
1335/**
1336 * dbg_create_files: initializes the attribute interface
1337 * @dev: device
1338 *
1339 * This function returns an error code
1340 */
1341__maybe_unused static int dbg_create_files(struct device *dev)
1342{
1343 int retval = 0;
1344
1345 if (dev == NULL)
1346 return -EINVAL;
1347 retval = device_create_file(dev, &dev_attr_device);
1348 if (retval)
1349 goto done;
1350 retval = device_create_file(dev, &dev_attr_driver);
1351 if (retval)
1352 goto rm_device;
1353 retval = device_create_file(dev, &dev_attr_events);
1354 if (retval)
1355 goto rm_driver;
1356 retval = device_create_file(dev, &dev_attr_inters);
1357 if (retval)
1358 goto rm_events;
1359 retval = device_create_file(dev, &dev_attr_port_test);
1360 if (retval)
1361 goto rm_inters;
1362 retval = device_create_file(dev, &dev_attr_qheads);
1363 if (retval)
1364 goto rm_port_test;
1365 retval = device_create_file(dev, &dev_attr_registers);
1366 if (retval)
1367 goto rm_qheads;
1368 retval = device_create_file(dev, &dev_attr_requests);
1369 if (retval)
1370 goto rm_registers;
1371 return 0;
1372
1373 rm_registers:
1374 device_remove_file(dev, &dev_attr_registers);
1375 rm_qheads:
1376 device_remove_file(dev, &dev_attr_qheads);
1377 rm_port_test:
1378 device_remove_file(dev, &dev_attr_port_test);
1379 rm_inters:
1380 device_remove_file(dev, &dev_attr_inters);
1381 rm_events:
1382 device_remove_file(dev, &dev_attr_events);
1383 rm_driver:
1384 device_remove_file(dev, &dev_attr_driver);
1385 rm_device:
1386 device_remove_file(dev, &dev_attr_device);
1387 done:
1388 return retval;
1389}
1390
1391/**
1392 * dbg_remove_files: destroys the attribute interface
1393 * @dev: device
1394 *
1395 * This function returns an error code
1396 */
1397__maybe_unused static int dbg_remove_files(struct device *dev)
1398{
1399 if (dev == NULL)
1400 return -EINVAL;
1401 device_remove_file(dev, &dev_attr_requests);
1402 device_remove_file(dev, &dev_attr_registers);
1403 device_remove_file(dev, &dev_attr_qheads);
1404 device_remove_file(dev, &dev_attr_port_test);
1405 device_remove_file(dev, &dev_attr_inters);
1406 device_remove_file(dev, &dev_attr_events);
1407 device_remove_file(dev, &dev_attr_driver);
1408 device_remove_file(dev, &dev_attr_device);
1409 return 0;
1410}
1411
1412/******************************************************************************
1413 * UTIL block
1414 *****************************************************************************/
1415/**
1416 * _usb_addr: calculates endpoint address from direction & number
1417 * @ep: endpoint
1418 */
1419static inline u8 _usb_addr(struct ci13xxx_ep *ep)
1420{
1421 return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num;
1422}
1423
1424/**
1425 * _hardware_queue: configures a request at hardware level
1426 * @gadget: gadget
1427 * @mEp: endpoint
1428 *
1429 * This function returns an error code
1430 */
1431static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1432{
1433 unsigned i;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301434 int ret = 0;
1435 unsigned length = mReq->req.length;
David Lopoaa69a802008-11-17 14:14:51 -08001436
1437 trace("%p, %p", mEp, mReq);
1438
1439 /* don't queue twice */
1440 if (mReq->req.status == -EALREADY)
1441 return -EALREADY;
1442
David Lopoaa69a802008-11-17 14:14:51 -08001443 mReq->req.status = -EALREADY;
Michael Grzeschik954aad82011-10-10 18:38:06 +02001444 if (length && mReq->req.dma == DMA_ADDR_INVALID) {
David Lopoaa69a802008-11-17 14:14:51 -08001445 mReq->req.dma = \
1446 dma_map_single(mEp->device, mReq->req.buf,
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301447 length, mEp->dir ? DMA_TO_DEVICE :
1448 DMA_FROM_DEVICE);
David Lopoaa69a802008-11-17 14:14:51 -08001449 if (mReq->req.dma == 0)
1450 return -ENOMEM;
1451
1452 mReq->map = 1;
1453 }
1454
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301455 if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) {
1456 mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC,
1457 &mReq->zdma);
1458 if (mReq->zptr == NULL) {
1459 if (mReq->map) {
1460 dma_unmap_single(mEp->device, mReq->req.dma,
1461 length, mEp->dir ? DMA_TO_DEVICE :
1462 DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02001463 mReq->req.dma = DMA_ADDR_INVALID;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301464 mReq->map = 0;
1465 }
1466 return -ENOMEM;
1467 }
1468 memset(mReq->zptr, 0, sizeof(*mReq->zptr));
1469 mReq->zptr->next = TD_TERMINATE;
1470 mReq->zptr->token = TD_STATUS_ACTIVE;
1471 if (!mReq->req.no_interrupt)
1472 mReq->zptr->token |= TD_IOC;
1473 }
David Lopoaa69a802008-11-17 14:14:51 -08001474 /*
1475 * TD configuration
1476 * TODO - handle requests which spawns into several TDs
1477 */
1478 memset(mReq->ptr, 0, sizeof(*mReq->ptr));
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301479 mReq->ptr->token = length << ffs_nr(TD_TOTAL_BYTES);
David Lopoaa69a802008-11-17 14:14:51 -08001480 mReq->ptr->token &= TD_TOTAL_BYTES;
David Lopoaa69a802008-11-17 14:14:51 -08001481 mReq->ptr->token |= TD_STATUS_ACTIVE;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301482 if (mReq->zptr) {
1483 mReq->ptr->next = mReq->zdma;
1484 } else {
1485 mReq->ptr->next = TD_TERMINATE;
1486 if (!mReq->req.no_interrupt)
1487 mReq->ptr->token |= TD_IOC;
1488 }
David Lopoaa69a802008-11-17 14:14:51 -08001489 mReq->ptr->page[0] = mReq->req.dma;
1490 for (i = 1; i < 5; i++)
1491 mReq->ptr->page[i] =
Artem Leonenko0a313c42010-12-14 23:47:06 -08001492 (mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK;
David Lopoaa69a802008-11-17 14:14:51 -08001493
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301494 if (!list_empty(&mEp->qh.queue)) {
1495 struct ci13xxx_req *mReqPrev;
1496 int n = hw_ep_bit(mEp->num, mEp->dir);
1497 int tmp_stat;
1498
1499 mReqPrev = list_entry(mEp->qh.queue.prev,
1500 struct ci13xxx_req, queue);
1501 if (mReqPrev->zptr)
1502 mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
1503 else
1504 mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
1505 wmb();
Alexander Shishkinf9df8392012-05-04 16:47:16 +03001506 if (hw_read(hw_bank.op, OP_ENDPTPRIME, BIT(n)))
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301507 goto done;
1508 do {
Alexander Shishkinf9df8392012-05-04 16:47:16 +03001509 hw_write(hw_bank.op, OP_USBCMD, USBCMD_ATDTW,
1510 USBCMD_ATDTW);
1511 tmp_stat = hw_read(hw_bank.op, OP_ENDPTSTAT, BIT(n));
1512 } while (!hw_read(hw_bank.op, OP_USBCMD, USBCMD_ATDTW));
1513 hw_write(hw_bank.op, OP_USBCMD, USBCMD_ATDTW, 0);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301514 if (tmp_stat)
1515 goto done;
1516 }
1517
1518 /* QH configuration */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301519 mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */
1520 mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301521 mEp->qh.ptr->cap |= QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08001522
1523 wmb(); /* synchronize before ep prime */
1524
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301525 ret = hw_ep_prime(mEp->num, mEp->dir,
David Lopoaa69a802008-11-17 14:14:51 -08001526 mEp->type == USB_ENDPOINT_XFER_CONTROL);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301527done:
1528 return ret;
David Lopoaa69a802008-11-17 14:14:51 -08001529}
1530
1531/**
1532 * _hardware_dequeue: handles a request at hardware level
1533 * @gadget: gadget
1534 * @mEp: endpoint
1535 *
1536 * This function returns an error code
1537 */
1538static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1539{
1540 trace("%p, %p", mEp, mReq);
1541
1542 if (mReq->req.status != -EALREADY)
1543 return -EINVAL;
1544
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301545 if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
1546 return -EBUSY;
1547
1548 if (mReq->zptr) {
1549 if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
1550 return -EBUSY;
1551 dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
1552 mReq->zptr = NULL;
1553 }
David Lopoaa69a802008-11-17 14:14:51 -08001554
1555 mReq->req.status = 0;
1556
1557 if (mReq->map) {
1558 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
1559 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02001560 mReq->req.dma = DMA_ADDR_INVALID;
David Lopoaa69a802008-11-17 14:14:51 -08001561 mReq->map = 0;
1562 }
1563
1564 mReq->req.status = mReq->ptr->token & TD_STATUS;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301565 if ((TD_STATUS_HALTED & mReq->req.status) != 0)
David Lopoaa69a802008-11-17 14:14:51 -08001566 mReq->req.status = -1;
1567 else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0)
1568 mReq->req.status = -1;
1569 else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0)
1570 mReq->req.status = -1;
1571
1572 mReq->req.actual = mReq->ptr->token & TD_TOTAL_BYTES;
1573 mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES);
1574 mReq->req.actual = mReq->req.length - mReq->req.actual;
1575 mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual;
1576
1577 return mReq->req.actual;
1578}
1579
1580/**
1581 * _ep_nuke: dequeues all endpoint requests
1582 * @mEp: endpoint
1583 *
1584 * This function returns an error code
1585 * Caller must hold lock
1586 */
1587static int _ep_nuke(struct ci13xxx_ep *mEp)
1588__releases(mEp->lock)
1589__acquires(mEp->lock)
1590{
1591 trace("%p", mEp);
1592
1593 if (mEp == NULL)
1594 return -EINVAL;
1595
1596 hw_ep_flush(mEp->num, mEp->dir);
1597
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301598 while (!list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -08001599
1600 /* pop oldest request */
1601 struct ci13xxx_req *mReq = \
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301602 list_entry(mEp->qh.queue.next,
David Lopoaa69a802008-11-17 14:14:51 -08001603 struct ci13xxx_req, queue);
1604 list_del_init(&mReq->queue);
1605 mReq->req.status = -ESHUTDOWN;
1606
Artem Leonenko7c25a822010-12-14 23:46:55 -08001607 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08001608 spin_unlock(mEp->lock);
1609 mReq->req.complete(&mEp->ep, &mReq->req);
1610 spin_lock(mEp->lock);
1611 }
1612 }
1613 return 0;
1614}
1615
1616/**
1617 * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
1618 * @gadget: gadget
1619 *
1620 * This function returns an error code
David Lopoaa69a802008-11-17 14:14:51 -08001621 */
1622static int _gadget_stop_activity(struct usb_gadget *gadget)
David Lopoaa69a802008-11-17 14:14:51 -08001623{
1624 struct usb_ep *ep;
1625 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301626 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -08001627
1628 trace("%p", gadget);
1629
1630 if (gadget == NULL)
1631 return -EINVAL;
1632
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301633 spin_lock_irqsave(udc->lock, flags);
1634 udc->gadget.speed = USB_SPEED_UNKNOWN;
1635 udc->remote_wakeup = 0;
1636 udc->suspended = 0;
1637 spin_unlock_irqrestore(udc->lock, flags);
1638
David Lopoaa69a802008-11-17 14:14:51 -08001639 /* flush all endpoints */
1640 gadget_for_each_ep(ep, gadget) {
1641 usb_ep_fifo_flush(ep);
1642 }
Alexander Shishkind36ade62012-05-04 16:47:15 +03001643 usb_ep_fifo_flush(&udc->ep0out->ep);
1644 usb_ep_fifo_flush(&udc->ep0in->ep);
David Lopoaa69a802008-11-17 14:14:51 -08001645
1646 udc->driver->disconnect(gadget);
1647
1648 /* make sure to disable all endpoints */
1649 gadget_for_each_ep(ep, gadget) {
1650 usb_ep_disable(ep);
1651 }
David Lopoaa69a802008-11-17 14:14:51 -08001652
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301653 if (udc->status != NULL) {
Alexander Shishkind36ade62012-05-04 16:47:15 +03001654 usb_ep_free_request(&udc->ep0in->ep, udc->status);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301655 udc->status = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08001656 }
1657
David Lopoaa69a802008-11-17 14:14:51 -08001658 return 0;
1659}
1660
1661/******************************************************************************
1662 * ISR block
1663 *****************************************************************************/
1664/**
1665 * isr_reset_handler: USB reset interrupt handler
1666 * @udc: UDC device
1667 *
1668 * This function resets USB engine after a bus reset occurred
1669 */
1670static void isr_reset_handler(struct ci13xxx *udc)
1671__releases(udc->lock)
1672__acquires(udc->lock)
1673{
David Lopoaa69a802008-11-17 14:14:51 -08001674 int retval;
1675
1676 trace("%p", udc);
1677
1678 if (udc == NULL) {
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07001679 pr_err("EINVAL\n");
David Lopoaa69a802008-11-17 14:14:51 -08001680 return;
1681 }
1682
1683 dbg_event(0xFF, "BUS RST", 0);
1684
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301685 spin_unlock(udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001686 retval = _gadget_stop_activity(&udc->gadget);
1687 if (retval)
1688 goto done;
1689
1690 retval = hw_usb_reset();
1691 if (retval)
1692 goto done;
1693
Alexander Shishkind36ade62012-05-04 16:47:15 +03001694 udc->status = usb_ep_alloc_request(&udc->ep0in->ep, GFP_ATOMIC);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05301695 if (udc->status == NULL)
1696 retval = -ENOMEM;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301697
David Lopoaa69a802008-11-17 14:14:51 -08001698 spin_lock(udc->lock);
1699
1700 done:
1701 if (retval)
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07001702 pr_err("error: %i\n", retval);
David Lopoaa69a802008-11-17 14:14:51 -08001703}
1704
1705/**
1706 * isr_get_status_complete: get_status request complete function
1707 * @ep: endpoint
1708 * @req: request handled
1709 *
1710 * Caller must release lock
1711 */
1712static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
1713{
1714 trace("%p, %p", ep, req);
1715
1716 if (ep == NULL || req == NULL) {
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07001717 pr_err("EINVAL\n");
David Lopoaa69a802008-11-17 14:14:51 -08001718 return;
1719 }
1720
1721 kfree(req->buf);
1722 usb_ep_free_request(ep, req);
1723}
1724
1725/**
1726 * isr_get_status_response: get_status request response
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301727 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08001728 * @setup: setup request packet
1729 *
1730 * This function returns an error code
1731 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301732static int isr_get_status_response(struct ci13xxx *udc,
David Lopoaa69a802008-11-17 14:14:51 -08001733 struct usb_ctrlrequest *setup)
1734__releases(mEp->lock)
1735__acquires(mEp->lock)
1736{
Alexander Shishkind36ade62012-05-04 16:47:15 +03001737 struct ci13xxx_ep *mEp = udc->ep0in;
David Lopoaa69a802008-11-17 14:14:51 -08001738 struct usb_request *req = NULL;
1739 gfp_t gfp_flags = GFP_ATOMIC;
1740 int dir, num, retval;
1741
1742 trace("%p, %p", mEp, setup);
1743
1744 if (mEp == NULL || setup == NULL)
1745 return -EINVAL;
1746
1747 spin_unlock(mEp->lock);
1748 req = usb_ep_alloc_request(&mEp->ep, gfp_flags);
1749 spin_lock(mEp->lock);
1750 if (req == NULL)
1751 return -ENOMEM;
1752
1753 req->complete = isr_get_status_complete;
1754 req->length = 2;
1755 req->buf = kzalloc(req->length, gfp_flags);
1756 if (req->buf == NULL) {
1757 retval = -ENOMEM;
1758 goto err_free_req;
1759 }
1760
1761 if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301762 /* Assume that device is bus powered for now. */
Alexander Shishkin1155a7b2012-05-08 23:28:57 +03001763 *(u16 *)req->buf = _udc->remote_wakeup << 1;
David Lopoaa69a802008-11-17 14:14:51 -08001764 retval = 0;
1765 } else if ((setup->bRequestType & USB_RECIP_MASK) \
1766 == USB_RECIP_ENDPOINT) {
1767 dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
1768 TX : RX;
1769 num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK;
Alexander Shishkin1155a7b2012-05-08 23:28:57 +03001770 *(u16 *)req->buf = hw_ep_get_halt(num, dir);
David Lopoaa69a802008-11-17 14:14:51 -08001771 }
1772 /* else do nothing; reserved for future use */
1773
1774 spin_unlock(mEp->lock);
1775 retval = usb_ep_queue(&mEp->ep, req, gfp_flags);
1776 spin_lock(mEp->lock);
1777 if (retval)
1778 goto err_free_buf;
1779
1780 return 0;
1781
1782 err_free_buf:
1783 kfree(req->buf);
1784 err_free_req:
1785 spin_unlock(mEp->lock);
1786 usb_ep_free_request(&mEp->ep, req);
1787 spin_lock(mEp->lock);
1788 return retval;
1789}
1790
1791/**
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301792 * isr_setup_status_complete: setup_status request complete function
1793 * @ep: endpoint
1794 * @req: request handled
1795 *
1796 * Caller must release lock. Put the port in test mode if test mode
1797 * feature is selected.
1798 */
1799static void
1800isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
1801{
1802 struct ci13xxx *udc = req->context;
1803 unsigned long flags;
1804
1805 trace("%p, %p", ep, req);
1806
1807 spin_lock_irqsave(udc->lock, flags);
1808 if (udc->test_mode)
1809 hw_port_test_set(udc->test_mode);
1810 spin_unlock_irqrestore(udc->lock, flags);
1811}
1812
1813/**
David Lopoaa69a802008-11-17 14:14:51 -08001814 * isr_setup_status_phase: queues the status phase of a setup transation
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301815 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08001816 *
1817 * This function returns an error code
1818 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301819static int isr_setup_status_phase(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -08001820__releases(mEp->lock)
1821__acquires(mEp->lock)
1822{
1823 int retval;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301824 struct ci13xxx_ep *mEp;
David Lopoaa69a802008-11-17 14:14:51 -08001825
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301826 trace("%p", udc);
David Lopoaa69a802008-11-17 14:14:51 -08001827
Alexander Shishkind36ade62012-05-04 16:47:15 +03001828 mEp = (udc->ep0_dir == TX) ? udc->ep0out : udc->ep0in;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301829 udc->status->context = udc;
1830 udc->status->complete = isr_setup_status_complete;
David Lopoaa69a802008-11-17 14:14:51 -08001831
1832 spin_unlock(mEp->lock);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301833 retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
David Lopoaa69a802008-11-17 14:14:51 -08001834 spin_lock(mEp->lock);
1835
1836 return retval;
1837}
1838
1839/**
1840 * isr_tr_complete_low: transaction complete low level handler
1841 * @mEp: endpoint
1842 *
1843 * This function returns an error code
1844 * Caller must hold lock
1845 */
1846static int isr_tr_complete_low(struct ci13xxx_ep *mEp)
1847__releases(mEp->lock)
1848__acquires(mEp->lock)
1849{
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301850 struct ci13xxx_req *mReq, *mReqTemp;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05301851 struct ci13xxx_ep *mEpTemp = mEp;
Pavankumar Kondeti986b11b2011-05-02 11:56:29 +05301852 int uninitialized_var(retval);
David Lopoaa69a802008-11-17 14:14:51 -08001853
1854 trace("%p", mEp);
1855
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301856 if (list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08001857 return -EINVAL;
1858
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301859 list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,
1860 queue) {
1861 retval = _hardware_dequeue(mEp, mReq);
1862 if (retval < 0)
1863 break;
1864 list_del_init(&mReq->queue);
1865 dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
1866 if (mReq->req.complete != NULL) {
1867 spin_unlock(mEp->lock);
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05301868 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
1869 mReq->req.length)
Alexander Shishkind36ade62012-05-04 16:47:15 +03001870 mEpTemp = _udc->ep0in;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05301871 mReq->req.complete(&mEpTemp->ep, &mReq->req);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301872 spin_lock(mEp->lock);
1873 }
1874 }
David Lopoaa69a802008-11-17 14:14:51 -08001875
Pavankumar Kondetief907482011-05-02 11:56:27 +05301876 if (retval == -EBUSY)
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301877 retval = 0;
1878 if (retval < 0)
David Lopoaa69a802008-11-17 14:14:51 -08001879 dbg_event(_usb_addr(mEp), "DONE", retval);
David Lopoaa69a802008-11-17 14:14:51 -08001880
David Lopoaa69a802008-11-17 14:14:51 -08001881 return retval;
1882}
1883
1884/**
1885 * isr_tr_complete_handler: transaction complete interrupt handler
1886 * @udc: UDC descriptor
1887 *
1888 * This function handles traffic events
1889 */
1890static void isr_tr_complete_handler(struct ci13xxx *udc)
1891__releases(udc->lock)
1892__acquires(udc->lock)
1893{
1894 unsigned i;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301895 u8 tmode = 0;
David Lopoaa69a802008-11-17 14:14:51 -08001896
1897 trace("%p", udc);
1898
1899 if (udc == NULL) {
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07001900 pr_err("EINVAL\n");
David Lopoaa69a802008-11-17 14:14:51 -08001901 return;
1902 }
1903
1904 for (i = 0; i < hw_ep_max; i++) {
1905 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05301906 int type, num, dir, err = -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -08001907 struct usb_ctrlrequest req;
1908
Ido Shayevitz31fb6012012-03-12 20:25:23 +02001909 if (mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001910 continue; /* not configured */
1911
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301912 if (hw_test_and_clear_complete(i)) {
David Lopoaa69a802008-11-17 14:14:51 -08001913 err = isr_tr_complete_low(mEp);
1914 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
1915 if (err > 0) /* needs status phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301916 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08001917 if (err < 0) {
1918 dbg_event(_usb_addr(mEp),
1919 "ERROR", err);
1920 spin_unlock(udc->lock);
1921 if (usb_ep_set_halt(&mEp->ep))
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07001922 dev_err(&udc->gadget.dev,
1923 "error: ep_set_halt\n");
David Lopoaa69a802008-11-17 14:14:51 -08001924 spin_lock(udc->lock);
1925 }
1926 }
1927 }
1928
1929 if (mEp->type != USB_ENDPOINT_XFER_CONTROL ||
1930 !hw_test_and_clear_setup_status(i))
1931 continue;
1932
1933 if (i != 0) {
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07001934 dev_warn(&udc->gadget.dev,
1935 "ctrl traffic received at endpoint\n");
David Lopoaa69a802008-11-17 14:14:51 -08001936 continue;
1937 }
1938
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301939 /*
1940 * Flush data and handshake transactions of previous
1941 * setup packet.
1942 */
Alexander Shishkind36ade62012-05-04 16:47:15 +03001943 _ep_nuke(udc->ep0out);
1944 _ep_nuke(udc->ep0in);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301945
David Lopoaa69a802008-11-17 14:14:51 -08001946 /* read_setup_packet */
1947 do {
1948 hw_test_and_set_setup_guard();
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301949 memcpy(&req, &mEp->qh.ptr->setup, sizeof(req));
David Lopoaa69a802008-11-17 14:14:51 -08001950 } while (!hw_test_and_clear_setup_guard());
1951
1952 type = req.bRequestType;
1953
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301954 udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
David Lopoaa69a802008-11-17 14:14:51 -08001955
1956 dbg_setup(_usb_addr(mEp), &req);
1957
1958 switch (req.bRequest) {
1959 case USB_REQ_CLEAR_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301960 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
1961 le16_to_cpu(req.wValue) ==
1962 USB_ENDPOINT_HALT) {
1963 if (req.wLength != 0)
David Lopoaa69a802008-11-17 14:14:51 -08001964 break;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301965 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05301966 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301967 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05301968 if (dir) /* TX */
1969 num += hw_ep_max/2;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301970 if (!udc->ci13xxx_ep[num].wedge) {
1971 spin_unlock(udc->lock);
1972 err = usb_ep_clear_halt(
1973 &udc->ci13xxx_ep[num].ep);
1974 spin_lock(udc->lock);
1975 if (err)
1976 break;
1977 }
1978 err = isr_setup_status_phase(udc);
1979 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
1980 le16_to_cpu(req.wValue) ==
1981 USB_DEVICE_REMOTE_WAKEUP) {
1982 if (req.wLength != 0)
1983 break;
1984 udc->remote_wakeup = 0;
1985 err = isr_setup_status_phase(udc);
1986 } else {
1987 goto delegate;
David Lopoaa69a802008-11-17 14:14:51 -08001988 }
David Lopoaa69a802008-11-17 14:14:51 -08001989 break;
1990 case USB_REQ_GET_STATUS:
1991 if (type != (USB_DIR_IN|USB_RECIP_DEVICE) &&
1992 type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
1993 type != (USB_DIR_IN|USB_RECIP_INTERFACE))
1994 goto delegate;
1995 if (le16_to_cpu(req.wLength) != 2 ||
1996 le16_to_cpu(req.wValue) != 0)
1997 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301998 err = isr_get_status_response(udc, &req);
David Lopoaa69a802008-11-17 14:14:51 -08001999 break;
2000 case USB_REQ_SET_ADDRESS:
2001 if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
2002 goto delegate;
2003 if (le16_to_cpu(req.wLength) != 0 ||
2004 le16_to_cpu(req.wIndex) != 0)
2005 break;
2006 err = hw_usb_set_address((u8)le16_to_cpu(req.wValue));
2007 if (err)
2008 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302009 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002010 break;
2011 case USB_REQ_SET_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302012 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
2013 le16_to_cpu(req.wValue) ==
2014 USB_ENDPOINT_HALT) {
2015 if (req.wLength != 0)
2016 break;
2017 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302018 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302019 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302020 if (dir) /* TX */
2021 num += hw_ep_max/2;
David Lopoaa69a802008-11-17 14:14:51 -08002022
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302023 spin_unlock(udc->lock);
2024 err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
2025 spin_lock(udc->lock);
2026 if (!err)
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302027 isr_setup_status_phase(udc);
2028 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302029 if (req.wLength != 0)
2030 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302031 switch (le16_to_cpu(req.wValue)) {
2032 case USB_DEVICE_REMOTE_WAKEUP:
2033 udc->remote_wakeup = 1;
2034 err = isr_setup_status_phase(udc);
2035 break;
2036 case USB_DEVICE_TEST_MODE:
2037 tmode = le16_to_cpu(req.wIndex) >> 8;
2038 switch (tmode) {
2039 case TEST_J:
2040 case TEST_K:
2041 case TEST_SE0_NAK:
2042 case TEST_PACKET:
2043 case TEST_FORCE_EN:
2044 udc->test_mode = tmode;
2045 err = isr_setup_status_phase(
2046 udc);
2047 break;
2048 default:
2049 break;
2050 }
2051 default:
2052 goto delegate;
2053 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302054 } else {
2055 goto delegate;
2056 }
David Lopoaa69a802008-11-17 14:14:51 -08002057 break;
2058 default:
2059delegate:
2060 if (req.wLength == 0) /* no data phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302061 udc->ep0_dir = TX;
David Lopoaa69a802008-11-17 14:14:51 -08002062
2063 spin_unlock(udc->lock);
2064 err = udc->driver->setup(&udc->gadget, &req);
2065 spin_lock(udc->lock);
2066 break;
2067 }
2068
2069 if (err < 0) {
2070 dbg_event(_usb_addr(mEp), "ERROR", err);
2071
2072 spin_unlock(udc->lock);
2073 if (usb_ep_set_halt(&mEp->ep))
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07002074 dev_err(&udc->gadget.dev,
2075 "error: ep_set_halt\n");
David Lopoaa69a802008-11-17 14:14:51 -08002076 spin_lock(udc->lock);
2077 }
2078 }
2079}
2080
2081/******************************************************************************
2082 * ENDPT block
2083 *****************************************************************************/
2084/**
2085 * ep_enable: configure endpoint, making it usable
2086 *
2087 * Check usb_ep_enable() at "usb_gadget.h" for details
2088 */
2089static int ep_enable(struct usb_ep *ep,
2090 const struct usb_endpoint_descriptor *desc)
2091{
2092 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302093 int retval = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002094 unsigned long flags;
2095
2096 trace("%p, %p", ep, desc);
2097
2098 if (ep == NULL || desc == NULL)
2099 return -EINVAL;
2100
2101 spin_lock_irqsave(mEp->lock, flags);
2102
2103 /* only internal SW should enable ctrl endpts */
2104
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002105 mEp->ep.desc = desc;
David Lopoaa69a802008-11-17 14:14:51 -08002106
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302107 if (!list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08002108 warn("enabling a non-empty endpoint!");
2109
Matthias Kaehlcke15739bb2009-04-15 22:28:41 +02002110 mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX;
2111 mEp->num = usb_endpoint_num(desc);
2112 mEp->type = usb_endpoint_type(desc);
David Lopoaa69a802008-11-17 14:14:51 -08002113
Kuninori Morimoto29cc8892011-08-23 03:12:03 -07002114 mEp->ep.maxpacket = usb_endpoint_maxp(desc);
David Lopoaa69a802008-11-17 14:14:51 -08002115
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302116 dbg_event(_usb_addr(mEp), "ENABLE", 0);
David Lopoaa69a802008-11-17 14:14:51 -08002117
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302118 mEp->qh.ptr->cap = 0;
David Lopof23e6492009-04-16 14:35:24 -07002119
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302120 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2121 mEp->qh.ptr->cap |= QH_IOS;
2122 else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
2123 mEp->qh.ptr->cap &= ~QH_MULT;
2124 else
2125 mEp->qh.ptr->cap &= ~QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08002126
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302127 mEp->qh.ptr->cap |=
2128 (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
2129 mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */
David Lopoaa69a802008-11-17 14:14:51 -08002130
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302131 /*
2132 * Enable endpoints in the HW other than ep0 as ep0
2133 * is always enabled
2134 */
2135 if (mEp->num)
2136 retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type);
David Lopoaa69a802008-11-17 14:14:51 -08002137
2138 spin_unlock_irqrestore(mEp->lock, flags);
2139 return retval;
2140}
2141
2142/**
2143 * ep_disable: endpoint is no longer usable
2144 *
2145 * Check usb_ep_disable() at "usb_gadget.h" for details
2146 */
2147static int ep_disable(struct usb_ep *ep)
2148{
2149 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2150 int direction, retval = 0;
2151 unsigned long flags;
2152
2153 trace("%p", ep);
2154
2155 if (ep == NULL)
2156 return -EINVAL;
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002157 else if (mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002158 return -EBUSY;
2159
2160 spin_lock_irqsave(mEp->lock, flags);
2161
2162 /* only internal SW should disable ctrl endpts */
2163
2164 direction = mEp->dir;
2165 do {
2166 dbg_event(_usb_addr(mEp), "DISABLE", 0);
2167
2168 retval |= _ep_nuke(mEp);
2169 retval |= hw_ep_disable(mEp->num, mEp->dir);
2170
2171 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2172 mEp->dir = (mEp->dir == TX) ? RX : TX;
2173
2174 } while (mEp->dir != direction);
2175
Ido Shayevitzf9c56cd2012-02-08 13:56:48 +02002176 mEp->ep.desc = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002177
2178 spin_unlock_irqrestore(mEp->lock, flags);
2179 return retval;
2180}
2181
2182/**
2183 * ep_alloc_request: allocate a request object to use with this endpoint
2184 *
2185 * Check usb_ep_alloc_request() at "usb_gadget.h" for details
2186 */
2187static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
2188{
2189 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2190 struct ci13xxx_req *mReq = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002191
2192 trace("%p, %i", ep, gfp_flags);
2193
2194 if (ep == NULL) {
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07002195 pr_err("EINVAL\n");
David Lopoaa69a802008-11-17 14:14:51 -08002196 return NULL;
2197 }
2198
David Lopoaa69a802008-11-17 14:14:51 -08002199 mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
2200 if (mReq != NULL) {
2201 INIT_LIST_HEAD(&mReq->queue);
Michael Grzeschik954aad82011-10-10 18:38:06 +02002202 mReq->req.dma = DMA_ADDR_INVALID;
David Lopoaa69a802008-11-17 14:14:51 -08002203
2204 mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,
2205 &mReq->dma);
2206 if (mReq->ptr == NULL) {
2207 kfree(mReq);
2208 mReq = NULL;
2209 }
2210 }
2211
2212 dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
2213
David Lopoaa69a802008-11-17 14:14:51 -08002214 return (mReq == NULL) ? NULL : &mReq->req;
2215}
2216
2217/**
2218 * ep_free_request: frees a request object
2219 *
2220 * Check usb_ep_free_request() at "usb_gadget.h" for details
2221 */
2222static void ep_free_request(struct usb_ep *ep, struct usb_request *req)
2223{
2224 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2225 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2226 unsigned long flags;
2227
2228 trace("%p, %p", ep, req);
2229
2230 if (ep == NULL || req == NULL) {
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07002231 pr_err("EINVAL\n");
David Lopoaa69a802008-11-17 14:14:51 -08002232 return;
2233 } else if (!list_empty(&mReq->queue)) {
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07002234 pr_err("EBUSY\n");
David Lopoaa69a802008-11-17 14:14:51 -08002235 return;
2236 }
2237
2238 spin_lock_irqsave(mEp->lock, flags);
2239
2240 if (mReq->ptr)
2241 dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma);
2242 kfree(mReq);
2243
2244 dbg_event(_usb_addr(mEp), "FREE", 0);
2245
2246 spin_unlock_irqrestore(mEp->lock, flags);
2247}
2248
2249/**
2250 * ep_queue: queues (submits) an I/O request to an endpoint
2251 *
2252 * Check usb_ep_queue()* at usb_gadget.h" for details
2253 */
2254static int ep_queue(struct usb_ep *ep, struct usb_request *req,
2255 gfp_t __maybe_unused gfp_flags)
2256{
2257 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2258 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2259 int retval = 0;
2260 unsigned long flags;
2261
2262 trace("%p, %p, %X", ep, req, gfp_flags);
2263
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002264 if (ep == NULL || req == NULL || mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002265 return -EINVAL;
2266
2267 spin_lock_irqsave(mEp->lock, flags);
2268
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302269 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
2270 if (req->length)
2271 mEp = (_udc->ep0_dir == RX) ?
Alexander Shishkind36ade62012-05-04 16:47:15 +03002272 _udc->ep0out : _udc->ep0in;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302273 if (!list_empty(&mEp->qh.queue)) {
2274 _ep_nuke(mEp);
2275 retval = -EOVERFLOW;
2276 warn("endpoint ctrl %X nuked", _usb_addr(mEp));
2277 }
David Lopoaa69a802008-11-17 14:14:51 -08002278 }
2279
2280 /* first nuke then test link, e.g. previous status has not sent */
2281 if (!list_empty(&mReq->queue)) {
2282 retval = -EBUSY;
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07002283 pr_err("request already in queue\n");
David Lopoaa69a802008-11-17 14:14:51 -08002284 goto done;
2285 }
2286
Alexander Shishkin1155a7b2012-05-08 23:28:57 +03002287 if (req->length > 4 * CI13XXX_PAGE_SIZE) {
2288 req->length = 4 * CI13XXX_PAGE_SIZE;
David Lopoaa69a802008-11-17 14:14:51 -08002289 retval = -EMSGSIZE;
2290 warn("request length truncated");
2291 }
2292
2293 dbg_queue(_usb_addr(mEp), req, retval);
2294
2295 /* push request */
2296 mReq->req.status = -EINPROGRESS;
2297 mReq->req.actual = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002298
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302299 retval = _hardware_enqueue(mEp, mReq);
Artem Leonenkod9bb9c12010-12-14 23:45:50 -08002300
2301 if (retval == -EALREADY) {
David Lopoaa69a802008-11-17 14:14:51 -08002302 dbg_event(_usb_addr(mEp), "QUEUE", retval);
2303 retval = 0;
2304 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302305 if (!retval)
2306 list_add_tail(&mReq->queue, &mEp->qh.queue);
David Lopoaa69a802008-11-17 14:14:51 -08002307
2308 done:
2309 spin_unlock_irqrestore(mEp->lock, flags);
2310 return retval;
2311}
2312
2313/**
2314 * ep_dequeue: dequeues (cancels, unlinks) an I/O request from an endpoint
2315 *
2316 * Check usb_ep_dequeue() at "usb_gadget.h" for details
2317 */
2318static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
2319{
2320 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2321 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2322 unsigned long flags;
2323
2324 trace("%p, %p", ep, req);
2325
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302326 if (ep == NULL || req == NULL || mReq->req.status != -EALREADY ||
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002327 mEp->ep.desc == NULL || list_empty(&mReq->queue) ||
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302328 list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08002329 return -EINVAL;
2330
2331 spin_lock_irqsave(mEp->lock, flags);
2332
2333 dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
2334
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302335 hw_ep_flush(mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08002336
2337 /* pop request */
2338 list_del_init(&mReq->queue);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302339 if (mReq->map) {
2340 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
2341 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02002342 mReq->req.dma = DMA_ADDR_INVALID;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302343 mReq->map = 0;
2344 }
David Lopoaa69a802008-11-17 14:14:51 -08002345 req->status = -ECONNRESET;
2346
Artem Leonenko7c25a822010-12-14 23:46:55 -08002347 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08002348 spin_unlock(mEp->lock);
2349 mReq->req.complete(&mEp->ep, &mReq->req);
2350 spin_lock(mEp->lock);
2351 }
2352
2353 spin_unlock_irqrestore(mEp->lock, flags);
2354 return 0;
2355}
2356
2357/**
2358 * ep_set_halt: sets the endpoint halt feature
2359 *
2360 * Check usb_ep_set_halt() at "usb_gadget.h" for details
2361 */
2362static int ep_set_halt(struct usb_ep *ep, int value)
2363{
2364 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2365 int direction, retval = 0;
2366 unsigned long flags;
2367
2368 trace("%p, %i", ep, value);
2369
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002370 if (ep == NULL || mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002371 return -EINVAL;
2372
2373 spin_lock_irqsave(mEp->lock, flags);
2374
2375#ifndef STALL_IN
2376 /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
2377 if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX &&
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302378 !list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -08002379 spin_unlock_irqrestore(mEp->lock, flags);
2380 return -EAGAIN;
2381 }
2382#endif
2383
2384 direction = mEp->dir;
2385 do {
2386 dbg_event(_usb_addr(mEp), "HALT", value);
2387 retval |= hw_ep_set_halt(mEp->num, mEp->dir, value);
2388
2389 if (!value)
2390 mEp->wedge = 0;
2391
2392 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2393 mEp->dir = (mEp->dir == TX) ? RX : TX;
2394
2395 } while (mEp->dir != direction);
2396
2397 spin_unlock_irqrestore(mEp->lock, flags);
2398 return retval;
2399}
2400
2401/**
2402 * ep_set_wedge: sets the halt feature and ignores clear requests
2403 *
2404 * Check usb_ep_set_wedge() at "usb_gadget.h" for details
2405 */
2406static int ep_set_wedge(struct usb_ep *ep)
2407{
2408 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2409 unsigned long flags;
2410
2411 trace("%p", ep);
2412
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002413 if (ep == NULL || mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002414 return -EINVAL;
2415
2416 spin_lock_irqsave(mEp->lock, flags);
2417
2418 dbg_event(_usb_addr(mEp), "WEDGE", 0);
2419 mEp->wedge = 1;
2420
2421 spin_unlock_irqrestore(mEp->lock, flags);
2422
2423 return usb_ep_set_halt(ep);
2424}
2425
2426/**
2427 * ep_fifo_flush: flushes contents of a fifo
2428 *
2429 * Check usb_ep_fifo_flush() at "usb_gadget.h" for details
2430 */
2431static void ep_fifo_flush(struct usb_ep *ep)
2432{
2433 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2434 unsigned long flags;
2435
2436 trace("%p", ep);
2437
2438 if (ep == NULL) {
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07002439 pr_err("%02X: -EINVAL\n", _usb_addr(mEp));
David Lopoaa69a802008-11-17 14:14:51 -08002440 return;
2441 }
2442
2443 spin_lock_irqsave(mEp->lock, flags);
2444
2445 dbg_event(_usb_addr(mEp), "FFLUSH", 0);
2446 hw_ep_flush(mEp->num, mEp->dir);
2447
2448 spin_unlock_irqrestore(mEp->lock, flags);
2449}
2450
2451/**
2452 * Endpoint-specific part of the API to the USB controller hardware
2453 * Check "usb_gadget.h" for details
2454 */
2455static const struct usb_ep_ops usb_ep_ops = {
2456 .enable = ep_enable,
2457 .disable = ep_disable,
2458 .alloc_request = ep_alloc_request,
2459 .free_request = ep_free_request,
2460 .queue = ep_queue,
2461 .dequeue = ep_dequeue,
2462 .set_halt = ep_set_halt,
2463 .set_wedge = ep_set_wedge,
2464 .fifo_flush = ep_fifo_flush,
2465};
2466
2467/******************************************************************************
2468 * GADGET block
2469 *****************************************************************************/
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302470static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
2471{
2472 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2473 unsigned long flags;
2474 int gadget_ready = 0;
2475
2476 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS))
2477 return -EOPNOTSUPP;
2478
2479 spin_lock_irqsave(udc->lock, flags);
2480 udc->vbus_active = is_active;
2481 if (udc->driver)
2482 gadget_ready = 1;
2483 spin_unlock_irqrestore(udc->lock, flags);
2484
2485 if (gadget_ready) {
2486 if (is_active) {
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302487 pm_runtime_get_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302488 hw_device_reset(udc);
Alexander Shishkind36ade62012-05-04 16:47:15 +03002489 hw_device_state(udc->ep0out->qh.dma);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302490 } else {
2491 hw_device_state(0);
2492 if (udc->udc_driver->notify_event)
2493 udc->udc_driver->notify_event(udc,
2494 CI13XXX_CONTROLLER_STOPPED_EVENT);
2495 _gadget_stop_activity(&udc->gadget);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302496 pm_runtime_put_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302497 }
2498 }
2499
2500 return 0;
2501}
2502
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302503static int ci13xxx_wakeup(struct usb_gadget *_gadget)
2504{
2505 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2506 unsigned long flags;
2507 int ret = 0;
2508
2509 trace();
2510
2511 spin_lock_irqsave(udc->lock, flags);
2512 if (!udc->remote_wakeup) {
2513 ret = -EOPNOTSUPP;
Marc Kleine-Budde194fa472011-10-10 18:38:08 +02002514 trace("remote wakeup feature is not enabled\n");
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302515 goto out;
2516 }
Alexander Shishkinf9df8392012-05-04 16:47:16 +03002517 if (!hw_read(hw_bank.op, OP_PORTSC, PORTSC_SUSP)) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302518 ret = -EINVAL;
Marc Kleine-Budde194fa472011-10-10 18:38:08 +02002519 trace("port is not suspended\n");
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302520 goto out;
2521 }
Alexander Shishkinf9df8392012-05-04 16:47:16 +03002522 hw_write(hw_bank.op, OP_PORTSC, PORTSC_FPR, PORTSC_FPR);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302523out:
2524 spin_unlock_irqrestore(udc->lock, flags);
2525 return ret;
2526}
2527
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302528static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
2529{
2530 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2531
2532 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002533 return usb_phy_set_power(udc->transceiver, mA);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302534 return -ENOTSUPP;
2535}
2536
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002537static int ci13xxx_start(struct usb_gadget_driver *driver,
2538 int (*bind)(struct usb_gadget *));
2539static int ci13xxx_stop(struct usb_gadget_driver *driver);
David Lopoaa69a802008-11-17 14:14:51 -08002540/**
2541 * Device operations part of the API to the USB controller hardware,
2542 * which don't involve endpoints (or i/o)
2543 * Check "usb_gadget.h" for details
2544 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302545static const struct usb_gadget_ops usb_gadget_ops = {
2546 .vbus_session = ci13xxx_vbus_session,
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302547 .wakeup = ci13xxx_wakeup,
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302548 .vbus_draw = ci13xxx_vbus_draw,
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002549 .start = ci13xxx_start,
2550 .stop = ci13xxx_stop,
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302551};
David Lopoaa69a802008-11-17 14:14:51 -08002552
2553/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002554 * ci13xxx_start: register a gadget driver
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002555 * @driver: the driver being registered
2556 * @bind: the driver's bind callback
David Lopoaa69a802008-11-17 14:14:51 -08002557 *
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002558 * Check ci13xxx_start() at <linux/usb/gadget.h> for details.
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002559 * Interrupts are enabled here.
David Lopoaa69a802008-11-17 14:14:51 -08002560 */
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002561static int ci13xxx_start(struct usb_gadget_driver *driver,
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002562 int (*bind)(struct usb_gadget *))
David Lopoaa69a802008-11-17 14:14:51 -08002563{
2564 struct ci13xxx *udc = _udc;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302565 unsigned long flags;
2566 int i, j;
David Lopoaa69a802008-11-17 14:14:51 -08002567 int retval = -ENOMEM;
2568
2569 trace("%p", driver);
2570
2571 if (driver == NULL ||
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002572 bind == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08002573 driver->setup == NULL ||
Marc Kleine-Budde7bb4fdc2011-10-10 18:38:09 +02002574 driver->disconnect == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002575 return -EINVAL;
2576 else if (udc == NULL)
2577 return -ENODEV;
2578 else if (udc->driver != NULL)
2579 return -EBUSY;
2580
2581 /* alloc resources */
2582 udc->qh_pool = dma_pool_create("ci13xxx_qh", &udc->gadget.dev,
2583 sizeof(struct ci13xxx_qh),
Artem Leonenko0a313c42010-12-14 23:47:06 -08002584 64, CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08002585 if (udc->qh_pool == NULL)
2586 return -ENOMEM;
2587
2588 udc->td_pool = dma_pool_create("ci13xxx_td", &udc->gadget.dev,
2589 sizeof(struct ci13xxx_td),
Artem Leonenko0a313c42010-12-14 23:47:06 -08002590 64, CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08002591 if (udc->td_pool == NULL) {
2592 dma_pool_destroy(udc->qh_pool);
2593 udc->qh_pool = NULL;
2594 return -ENOMEM;
2595 }
2596
2597 spin_lock_irqsave(udc->lock, flags);
2598
2599 info("hw_ep_max = %d", hw_ep_max);
2600
David Lopoaa69a802008-11-17 14:14:51 -08002601 udc->gadget.dev.driver = NULL;
2602
2603 retval = 0;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302604 for (i = 0; i < hw_ep_max/2; i++) {
2605 for (j = RX; j <= TX; j++) {
2606 int k = i + j * hw_ep_max/2;
2607 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
David Lopoaa69a802008-11-17 14:14:51 -08002608
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302609 scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
2610 (j == TX) ? "in" : "out");
David Lopoaa69a802008-11-17 14:14:51 -08002611
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302612 mEp->lock = udc->lock;
2613 mEp->device = &udc->gadget.dev;
2614 mEp->td_pool = udc->td_pool;
David Lopoaa69a802008-11-17 14:14:51 -08002615
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302616 mEp->ep.name = mEp->name;
2617 mEp->ep.ops = &usb_ep_ops;
2618 mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
David Lopoaa69a802008-11-17 14:14:51 -08002619
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302620 INIT_LIST_HEAD(&mEp->qh.queue);
Pavankumar Kondeti0a91efa2010-12-07 17:54:00 +05302621 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302622 mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
2623 &mEp->qh.dma);
Pavankumar Kondeti0a91efa2010-12-07 17:54:00 +05302624 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302625 if (mEp->qh.ptr == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002626 retval = -ENOMEM;
2627 else
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302628 memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
2629
Alexander Shishkind36ade62012-05-04 16:47:15 +03002630 /*
2631 * set up shorthands for ep0 out and in endpoints,
2632 * don't add to gadget's ep_list
2633 */
2634 if (i == 0) {
2635 if (j == RX)
2636 udc->ep0out = mEp;
2637 else
2638 udc->ep0in = mEp;
2639
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302640 continue;
Alexander Shishkind36ade62012-05-04 16:47:15 +03002641 }
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302642
David Lopoaa69a802008-11-17 14:14:51 -08002643 list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302644 }
David Lopoaa69a802008-11-17 14:14:51 -08002645 }
2646 if (retval)
2647 goto done;
Alexander Shishkind36ade62012-05-04 16:47:15 +03002648
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302649 spin_unlock_irqrestore(udc->lock, flags);
Alexander Shishkind36ade62012-05-04 16:47:15 +03002650 udc->ep0out->ep.desc = &ctrl_endpt_out_desc;
2651 retval = usb_ep_enable(&udc->ep0out->ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302652 if (retval)
2653 return retval;
Felipe Balbi877c1f52011-06-29 16:41:57 +03002654
Alexander Shishkind36ade62012-05-04 16:47:15 +03002655 udc->ep0in->ep.desc = &ctrl_endpt_in_desc;
2656 retval = usb_ep_enable(&udc->ep0in->ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302657 if (retval)
2658 return retval;
2659 spin_lock_irqsave(udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002660
Alexander Shishkind36ade62012-05-04 16:47:15 +03002661 udc->gadget.ep0 = &udc->ep0in->ep;
David Lopoaa69a802008-11-17 14:14:51 -08002662 /* bind gadget */
2663 driver->driver.bus = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002664 udc->gadget.dev.driver = &driver->driver;
2665
2666 spin_unlock_irqrestore(udc->lock, flags);
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002667 retval = bind(&udc->gadget); /* MAY SLEEP */
David Lopoaa69a802008-11-17 14:14:51 -08002668 spin_lock_irqsave(udc->lock, flags);
2669
2670 if (retval) {
David Lopoaa69a802008-11-17 14:14:51 -08002671 udc->gadget.dev.driver = NULL;
2672 goto done;
2673 }
2674
Pavankumar Kondeti49d3df52011-01-11 09:19:21 +05302675 udc->driver = driver;
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302676 pm_runtime_get_sync(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302677 if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
2678 if (udc->vbus_active) {
2679 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
2680 hw_device_reset(udc);
2681 } else {
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302682 pm_runtime_put_sync(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302683 goto done;
2684 }
2685 }
2686
Alexander Shishkind36ade62012-05-04 16:47:15 +03002687 retval = hw_device_state(udc->ep0out->qh.dma);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302688 if (retval)
2689 pm_runtime_put_sync(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08002690
2691 done:
2692 spin_unlock_irqrestore(udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002693 return retval;
2694}
David Lopoaa69a802008-11-17 14:14:51 -08002695
2696/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002697 * ci13xxx_stop: unregister a gadget driver
David Lopoaa69a802008-11-17 14:14:51 -08002698 *
2699 * Check usb_gadget_unregister_driver() at "usb_gadget.h" for details
2700 */
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002701static int ci13xxx_stop(struct usb_gadget_driver *driver)
David Lopoaa69a802008-11-17 14:14:51 -08002702{
2703 struct ci13xxx *udc = _udc;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302704 unsigned long i, flags;
David Lopoaa69a802008-11-17 14:14:51 -08002705
2706 trace("%p", driver);
2707
2708 if (driver == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08002709 driver->unbind == NULL ||
2710 driver->setup == NULL ||
2711 driver->disconnect == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08002712 driver != udc->driver)
2713 return -EINVAL;
2714
2715 spin_lock_irqsave(udc->lock, flags);
2716
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302717 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) ||
2718 udc->vbus_active) {
2719 hw_device_state(0);
2720 if (udc->udc_driver->notify_event)
2721 udc->udc_driver->notify_event(udc,
2722 CI13XXX_CONTROLLER_STOPPED_EVENT);
Marc Kleine-Buddefd537c02011-10-10 18:38:07 +02002723 spin_unlock_irqrestore(udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302724 _gadget_stop_activity(&udc->gadget);
Marc Kleine-Buddefd537c02011-10-10 18:38:07 +02002725 spin_lock_irqsave(udc->lock, flags);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302726 pm_runtime_put(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302727 }
David Lopoaa69a802008-11-17 14:14:51 -08002728
2729 /* unbind gadget */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302730 spin_unlock_irqrestore(udc->lock, flags);
2731 driver->unbind(&udc->gadget); /* MAY SLEEP */
2732 spin_lock_irqsave(udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002733
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302734 udc->gadget.dev.driver = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002735
2736 /* free resources */
2737 for (i = 0; i < hw_ep_max; i++) {
2738 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
2739
Alexander Shishkinefa015b2012-05-04 16:47:14 +03002740 if (mEp->num)
David Lopoaa69a802008-11-17 14:14:51 -08002741 list_del_init(&mEp->ep.ep_list);
2742
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302743 if (mEp->qh.ptr != NULL)
2744 dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08002745 }
2746
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302747 udc->gadget.ep0 = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002748 udc->driver = NULL;
2749
2750 spin_unlock_irqrestore(udc->lock, flags);
2751
2752 if (udc->td_pool != NULL) {
2753 dma_pool_destroy(udc->td_pool);
2754 udc->td_pool = NULL;
2755 }
2756 if (udc->qh_pool != NULL) {
2757 dma_pool_destroy(udc->qh_pool);
2758 udc->qh_pool = NULL;
2759 }
2760
2761 return 0;
2762}
David Lopoaa69a802008-11-17 14:14:51 -08002763
2764/******************************************************************************
2765 * BUS block
2766 *****************************************************************************/
2767/**
2768 * udc_irq: global interrupt handler
2769 *
2770 * This function returns IRQ_HANDLED if the IRQ has been handled
2771 * It locks access to registers
2772 */
2773static irqreturn_t udc_irq(void)
2774{
2775 struct ci13xxx *udc = _udc;
2776 irqreturn_t retval;
2777 u32 intr;
2778
2779 trace();
2780
2781 if (udc == NULL) {
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07002782 pr_err("ENODEV\n");
David Lopoaa69a802008-11-17 14:14:51 -08002783 return IRQ_HANDLED;
2784 }
2785
2786 spin_lock(udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302787
2788 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) {
Alexander Shishkinf9df8392012-05-04 16:47:16 +03002789 if (hw_read(hw_bank.op, OP_USBMODE, USBMODE_CM) !=
2790 USBMODE_CM_DEVICE) {
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302791 spin_unlock(udc->lock);
2792 return IRQ_NONE;
2793 }
2794 }
David Lopoaa69a802008-11-17 14:14:51 -08002795 intr = hw_test_and_clear_intr_active();
2796 if (intr) {
2797 isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intr;
2798 isr_statistics.hndl.idx &= ISR_MASK;
2799 isr_statistics.hndl.cnt++;
2800
2801 /* order defines priority - do NOT change it */
2802 if (USBi_URI & intr) {
2803 isr_statistics.uri++;
2804 isr_reset_handler(udc);
2805 }
2806 if (USBi_PCI & intr) {
2807 isr_statistics.pci++;
2808 udc->gadget.speed = hw_port_is_high_speed() ?
2809 USB_SPEED_HIGH : USB_SPEED_FULL;
Marc Kleine-Budde7bb4fdc2011-10-10 18:38:09 +02002810 if (udc->suspended && udc->driver->resume) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302811 spin_unlock(udc->lock);
2812 udc->driver->resume(&udc->gadget);
2813 spin_lock(udc->lock);
2814 udc->suspended = 0;
2815 }
David Lopoaa69a802008-11-17 14:14:51 -08002816 }
2817 if (USBi_UEI & intr)
2818 isr_statistics.uei++;
2819 if (USBi_UI & intr) {
2820 isr_statistics.ui++;
2821 isr_tr_complete_handler(udc);
2822 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302823 if (USBi_SLI & intr) {
Marc Kleine-Budde7bb4fdc2011-10-10 18:38:09 +02002824 if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
2825 udc->driver->suspend) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302826 udc->suspended = 1;
2827 spin_unlock(udc->lock);
2828 udc->driver->suspend(&udc->gadget);
2829 spin_lock(udc->lock);
2830 }
David Lopoaa69a802008-11-17 14:14:51 -08002831 isr_statistics.sli++;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302832 }
David Lopoaa69a802008-11-17 14:14:51 -08002833 retval = IRQ_HANDLED;
2834 } else {
2835 isr_statistics.none++;
2836 retval = IRQ_NONE;
2837 }
2838 spin_unlock(udc->lock);
2839
2840 return retval;
2841}
2842
2843/**
2844 * udc_release: driver release function
2845 * @dev: device
2846 *
2847 * Currently does nothing
2848 */
2849static void udc_release(struct device *dev)
2850{
2851 trace("%p", dev);
2852
2853 if (dev == NULL)
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07002854 pr_err("EINVAL\n");
David Lopoaa69a802008-11-17 14:14:51 -08002855}
2856
2857/**
2858 * udc_probe: parent probe must call this to initialize UDC
2859 * @dev: parent device
2860 * @regs: registers base address
2861 * @name: driver name
2862 *
2863 * This function returns an error code
2864 * No interrupts active, the IRQ has not been requested yet
2865 * Kernel assumes 32-bit DMA operations by default, no need to dma_set_mask
2866 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302867static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
Alexander Shishkinf9df8392012-05-04 16:47:16 +03002868 void __iomem *regs, uintptr_t capoffset)
David Lopoaa69a802008-11-17 14:14:51 -08002869{
2870 struct ci13xxx *udc;
2871 int retval = 0;
2872
Marc Kleine-Budde194fa472011-10-10 18:38:08 +02002873 trace("%p, %p, %p", dev, regs, driver->name);
David Lopoaa69a802008-11-17 14:14:51 -08002874
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302875 if (dev == NULL || regs == NULL || driver == NULL ||
2876 driver->name == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002877 return -EINVAL;
2878
2879 udc = kzalloc(sizeof(struct ci13xxx), GFP_KERNEL);
2880 if (udc == NULL)
2881 return -ENOMEM;
2882
2883 udc->lock = &udc_lock;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302884 udc->regs = regs;
2885 udc->udc_driver = driver;
David Lopoaa69a802008-11-17 14:14:51 -08002886
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302887 udc->gadget.ops = &usb_gadget_ops;
David Lopoaa69a802008-11-17 14:14:51 -08002888 udc->gadget.speed = USB_SPEED_UNKNOWN;
Michal Nazarewiczd327ab52011-11-19 18:27:37 +01002889 udc->gadget.max_speed = USB_SPEED_HIGH;
David Lopoaa69a802008-11-17 14:14:51 -08002890 udc->gadget.is_otg = 0;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302891 udc->gadget.name = driver->name;
David Lopoaa69a802008-11-17 14:14:51 -08002892
2893 INIT_LIST_HEAD(&udc->gadget.ep_list);
2894 udc->gadget.ep0 = NULL;
2895
Kay Sievers5df585242009-03-24 16:38:23 -07002896 dev_set_name(&udc->gadget.dev, "gadget");
David Lopoaa69a802008-11-17 14:14:51 -08002897 udc->gadget.dev.dma_mask = dev->dma_mask;
Pavankumar Kondeti61948ee2010-12-07 17:54:01 +05302898 udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
David Lopoaa69a802008-11-17 14:14:51 -08002899 udc->gadget.dev.parent = dev;
2900 udc->gadget.dev.release = udc_release;
2901
Alexander Shishkinf9df8392012-05-04 16:47:16 +03002902 retval = hw_device_init(regs, capoffset);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302903 if (retval < 0)
2904 goto free_udc;
2905
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002906 udc->transceiver = usb_get_transceiver();
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302907
2908 if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
2909 if (udc->transceiver == NULL) {
2910 retval = -ENODEV;
2911 goto free_udc;
2912 }
2913 }
2914
2915 if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) {
2916 retval = hw_device_reset(udc);
2917 if (retval)
2918 goto put_transceiver;
2919 }
2920
David Lopoaa69a802008-11-17 14:14:51 -08002921 retval = device_register(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302922 if (retval) {
2923 put_device(&udc->gadget.dev);
2924 goto put_transceiver;
2925 }
David Lopoaa69a802008-11-17 14:14:51 -08002926
2927#ifdef CONFIG_USB_GADGET_DEBUG_FILES
2928 retval = dbg_create_files(&udc->gadget.dev);
2929#endif
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302930 if (retval)
2931 goto unreg_device;
2932
2933 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02002934 retval = otg_set_peripheral(udc->transceiver->otg,
2935 &udc->gadget);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302936 if (retval)
2937 goto remove_dbg;
David Lopoaa69a802008-11-17 14:14:51 -08002938 }
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002939
2940 retval = usb_add_gadget_udc(dev, &udc->gadget);
2941 if (retval)
2942 goto remove_trans;
2943
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302944 pm_runtime_no_callbacks(&udc->gadget.dev);
2945 pm_runtime_enable(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08002946
2947 _udc = udc;
2948 return retval;
2949
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002950remove_trans:
2951 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02002952 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002953 usb_put_transceiver(udc->transceiver);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002954 }
2955
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07002956 dev_err(dev, "error = %i\n", retval);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302957remove_dbg:
2958#ifdef CONFIG_USB_GADGET_DEBUG_FILES
2959 dbg_remove_files(&udc->gadget.dev);
2960#endif
2961unreg_device:
2962 device_unregister(&udc->gadget.dev);
2963put_transceiver:
2964 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002965 usb_put_transceiver(udc->transceiver);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302966free_udc:
David Lopoaa69a802008-11-17 14:14:51 -08002967 kfree(udc);
2968 _udc = NULL;
2969 return retval;
2970}
2971
2972/**
2973 * udc_remove: parent remove must call this to remove UDC
2974 *
2975 * No interrupts active, the IRQ has been released
2976 */
2977static void udc_remove(void)
2978{
2979 struct ci13xxx *udc = _udc;
2980
2981 if (udc == NULL) {
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07002982 pr_err("EINVAL\n");
David Lopoaa69a802008-11-17 14:14:51 -08002983 return;
2984 }
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002985 usb_del_gadget_udc(&udc->gadget);
David Lopoaa69a802008-11-17 14:14:51 -08002986
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302987 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02002988 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002989 usb_put_transceiver(udc->transceiver);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302990 }
David Lopoaa69a802008-11-17 14:14:51 -08002991#ifdef CONFIG_USB_GADGET_DEBUG_FILES
2992 dbg_remove_files(&udc->gadget.dev);
2993#endif
2994 device_unregister(&udc->gadget.dev);
2995
2996 kfree(udc);
2997 _udc = NULL;
2998}