blob: ce50af97ab3fefaae342578d74a79bdab8f78c73 [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>
Alexander Shishkin62bb84e2012-05-08 23:29:01 +030058#include <linux/platform_device.h>
59#include <linux/module.h>
David Lopoaa69a802008-11-17 14:14:51 -080060#include <linux/interrupt.h>
David Lopoaa69a802008-11-17 14:14:51 -080061#include <linux/io.h>
62#include <linux/irq.h>
63#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090064#include <linux/slab.h>
Pavankumar Kondetic0360192010-12-07 17:54:04 +053065#include <linux/pm_runtime.h>
David Lopoaa69a802008-11-17 14:14:51 -080066#include <linux/usb/ch9.h>
67#include <linux/usb/gadget.h>
Pavankumar Kondetif01ef572010-12-07 17:54:02 +053068#include <linux/usb/otg.h>
David Lopoaa69a802008-11-17 14:14:51 -080069
70#include "ci13xxx_udc.h"
71
David Lopoaa69a802008-11-17 14:14:51 -080072/******************************************************************************
73 * DEFINE
74 *****************************************************************************/
Michael Grzeschik954aad82011-10-10 18:38:06 +020075
76#define DMA_ADDR_INVALID (~(dma_addr_t)0)
77
David Lopoaa69a802008-11-17 14:14:51 -080078/* control endpoint description */
79static const struct usb_endpoint_descriptor
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +053080ctrl_endpt_out_desc = {
David Lopoaa69a802008-11-17 14:14:51 -080081 .bLength = USB_DT_ENDPOINT_SIZE,
82 .bDescriptorType = USB_DT_ENDPOINT,
83
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +053084 .bEndpointAddress = USB_DIR_OUT,
85 .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
86 .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
87};
88
89static const struct usb_endpoint_descriptor
90ctrl_endpt_in_desc = {
91 .bLength = USB_DT_ENDPOINT_SIZE,
92 .bDescriptorType = USB_DT_ENDPOINT,
93
94 .bEndpointAddress = USB_DIR_IN,
David Lopoaa69a802008-11-17 14:14:51 -080095 .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
96 .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
97};
98
99/* UDC descriptor */
100static struct ci13xxx *_udc;
101
102/* Interrupt statistics */
103#define ISR_MASK 0x1F
104static struct {
105 u32 test;
106 u32 ui;
107 u32 uei;
108 u32 pci;
109 u32 uri;
110 u32 sli;
111 u32 none;
112 struct {
113 u32 cnt;
114 u32 buf[ISR_MASK+1];
115 u32 idx;
116 } hndl;
117} isr_statistics;
118
119/**
120 * ffs_nr: find first (least significant) bit set
121 * @x: the word to search
122 *
123 * This function returns bit number (instead of position)
124 */
125static int ffs_nr(u32 x)
126{
127 int n = ffs(x);
128
129 return n ? n-1 : 32;
130}
131
132/******************************************************************************
133 * HW block
134 *****************************************************************************/
David Lopoaa69a802008-11-17 14:14:51 -0800135
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530136/* MSM specific */
137#define ABS_AHBBURST (0x0090UL)
138#define ABS_AHBMODE (0x0098UL)
David Lopoaa69a802008-11-17 14:14:51 -0800139/* UDC register map */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300140static uintptr_t ci_regs_nolpm[] = {
141 [CAP_CAPLENGTH] = 0x000UL,
142 [CAP_HCCPARAMS] = 0x008UL,
143 [CAP_DCCPARAMS] = 0x024UL,
144 [CAP_TESTMODE] = 0x038UL,
145 [OP_USBCMD] = 0x000UL,
146 [OP_USBSTS] = 0x004UL,
147 [OP_USBINTR] = 0x008UL,
148 [OP_DEVICEADDR] = 0x014UL,
149 [OP_ENDPTLISTADDR] = 0x018UL,
150 [OP_PORTSC] = 0x044UL,
151 [OP_DEVLC] = 0x084UL,
152 [OP_USBMODE] = 0x068UL,
153 [OP_ENDPTSETUPSTAT] = 0x06CUL,
154 [OP_ENDPTPRIME] = 0x070UL,
155 [OP_ENDPTFLUSH] = 0x074UL,
156 [OP_ENDPTSTAT] = 0x078UL,
157 [OP_ENDPTCOMPLETE] = 0x07CUL,
158 [OP_ENDPTCTRL] = 0x080UL,
159};
160
161static uintptr_t ci_regs_lpm[] = {
162 [CAP_CAPLENGTH] = 0x000UL,
163 [CAP_HCCPARAMS] = 0x008UL,
164 [CAP_DCCPARAMS] = 0x024UL,
165 [CAP_TESTMODE] = 0x0FCUL,
166 [OP_USBCMD] = 0x000UL,
167 [OP_USBSTS] = 0x004UL,
168 [OP_USBINTR] = 0x008UL,
169 [OP_DEVICEADDR] = 0x014UL,
170 [OP_ENDPTLISTADDR] = 0x018UL,
171 [OP_PORTSC] = 0x044UL,
172 [OP_DEVLC] = 0x084UL,
173 [OP_USBMODE] = 0x0C8UL,
174 [OP_ENDPTSETUPSTAT] = 0x0D8UL,
175 [OP_ENDPTPRIME] = 0x0DCUL,
176 [OP_ENDPTFLUSH] = 0x0E0UL,
177 [OP_ENDPTSTAT] = 0x0E4UL,
178 [OP_ENDPTCOMPLETE] = 0x0E8UL,
179 [OP_ENDPTCTRL] = 0x0ECUL,
180};
181
182static int hw_alloc_regmap(struct ci13xxx *udc, bool is_lpm)
183{
184 int i;
185
186 kfree(udc->hw_bank.regmap);
187
188 udc->hw_bank.regmap = kzalloc((OP_LAST + 1) * sizeof(void *),
189 GFP_KERNEL);
190 if (!udc->hw_bank.regmap)
191 return -ENOMEM;
192
193 for (i = 0; i < OP_ENDPTCTRL; i++)
194 udc->hw_bank.regmap[i] =
195 (i <= CAP_LAST ? udc->hw_bank.cap : udc->hw_bank.op) +
196 (is_lpm ? ci_regs_lpm[i] : ci_regs_nolpm[i]);
197
198 for (; i <= OP_LAST; i++)
199 udc->hw_bank.regmap[i] = udc->hw_bank.op +
200 4 * (i - OP_ENDPTCTRL) +
201 (is_lpm
202 ? ci_regs_lpm[OP_ENDPTCTRL]
203 : ci_regs_nolpm[OP_ENDPTCTRL]);
204
205 return 0;
206}
David Lopoaa69a802008-11-17 14:14:51 -0800207
208/**
209 * hw_ep_bit: calculates the bit number
210 * @num: endpoint number
211 * @dir: endpoint direction
212 *
213 * This function returns bit number
214 */
215static inline int hw_ep_bit(int num, int dir)
216{
217 return num + (dir ? 16 : 0);
218}
219
Alexander Shishkind3595d12012-05-08 23:28:58 +0300220static int ep_to_bit(struct ci13xxx *udc, int n)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200221{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300222 int fill = 16 - udc->hw_ep_max / 2;
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200223
Alexander Shishkind3595d12012-05-08 23:28:58 +0300224 if (n >= udc->hw_ep_max / 2)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200225 n += fill;
226
227 return n;
228}
229
David Lopoaa69a802008-11-17 14:14:51 -0800230/**
Alexander Shishkin262c1632012-05-08 23:28:59 +0300231 * hw_read: reads from a hw register
232 * @reg: register index
David Lopoaa69a802008-11-17 14:14:51 -0800233 * @mask: bitfield mask
234 *
Alexander Shishkin262c1632012-05-08 23:28:59 +0300235 * This function returns register contents
David Lopoaa69a802008-11-17 14:14:51 -0800236 */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300237static u32 hw_read(struct ci13xxx *udc, enum ci13xxx_regs reg, u32 mask)
David Lopoaa69a802008-11-17 14:14:51 -0800238{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300239 return ioread32(udc->hw_bank.regmap[reg]) & mask;
David Lopoaa69a802008-11-17 14:14:51 -0800240}
241
242/**
Alexander Shishkin262c1632012-05-08 23:28:59 +0300243 * hw_write: writes to a hw register
244 * @reg: register index
David Lopoaa69a802008-11-17 14:14:51 -0800245 * @mask: bitfield mask
Alexander Shishkin262c1632012-05-08 23:28:59 +0300246 * @data: new value
David Lopoaa69a802008-11-17 14:14:51 -0800247 */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300248static void hw_write(struct ci13xxx *udc, enum ci13xxx_regs reg, u32 mask,
249 u32 data)
David Lopoaa69a802008-11-17 14:14:51 -0800250{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300251 if (~mask)
252 data = (ioread32(udc->hw_bank.regmap[reg]) & ~mask)
253 | (data & mask);
254
255 iowrite32(data, udc->hw_bank.regmap[reg]);
David Lopoaa69a802008-11-17 14:14:51 -0800256}
257
258/**
Alexander Shishkin262c1632012-05-08 23:28:59 +0300259 * hw_test_and_clear: tests & clears a hw register
260 * @reg: register index
David Lopoaa69a802008-11-17 14:14:51 -0800261 * @mask: bitfield mask
262 *
Alexander Shishkin262c1632012-05-08 23:28:59 +0300263 * This function returns register contents
David Lopoaa69a802008-11-17 14:14:51 -0800264 */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300265static u32 hw_test_and_clear(struct ci13xxx *udc, enum ci13xxx_regs reg,
266 u32 mask)
David Lopoaa69a802008-11-17 14:14:51 -0800267{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300268 u32 val = ioread32(udc->hw_bank.regmap[reg]) & mask;
David Lopoaa69a802008-11-17 14:14:51 -0800269
Alexander Shishkin262c1632012-05-08 23:28:59 +0300270 iowrite32(val, udc->hw_bank.regmap[reg]);
271 return val;
David Lopoaa69a802008-11-17 14:14:51 -0800272}
273
274/**
Alexander Shishkin262c1632012-05-08 23:28:59 +0300275 * hw_test_and_write: tests & writes a hw register
276 * @reg: register index
David Lopoaa69a802008-11-17 14:14:51 -0800277 * @mask: bitfield mask
Alexander Shishkin262c1632012-05-08 23:28:59 +0300278 * @data: new value
David Lopoaa69a802008-11-17 14:14:51 -0800279 *
Alexander Shishkin262c1632012-05-08 23:28:59 +0300280 * This function returns register contents
David Lopoaa69a802008-11-17 14:14:51 -0800281 */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300282static u32 hw_test_and_write(struct ci13xxx *udc, enum ci13xxx_regs reg,
283 u32 mask, u32 data)
David Lopoaa69a802008-11-17 14:14:51 -0800284{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300285 u32 val = hw_read(udc, reg, ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800286
Alexander Shishkin262c1632012-05-08 23:28:59 +0300287 hw_write(udc, reg, mask, data);
288 return (val & mask) >> ffs_nr(mask);
David Lopoaa69a802008-11-17 14:14:51 -0800289}
290
Alexander Shishkind3595d12012-05-08 23:28:58 +0300291static int hw_device_init(struct ci13xxx *udc, void __iomem *base,
292 uintptr_t cap_offset)
David Lopoaa69a802008-11-17 14:14:51 -0800293{
294 u32 reg;
295
296 /* bank is a module variable */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300297 udc->hw_bank.abs = base;
David Lopoaa69a802008-11-17 14:14:51 -0800298
Alexander Shishkind3595d12012-05-08 23:28:58 +0300299 udc->hw_bank.cap = udc->hw_bank.abs;
300 udc->hw_bank.cap += cap_offset;
301 udc->hw_bank.op = udc->hw_bank.cap + ioread8(udc->hw_bank.cap);
David Lopoaa69a802008-11-17 14:14:51 -0800302
Alexander Shishkin262c1632012-05-08 23:28:59 +0300303 hw_alloc_regmap(udc, false);
304 reg = hw_read(udc, CAP_HCCPARAMS, HCCPARAMS_LEN) >>
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300305 ffs_nr(HCCPARAMS_LEN);
Alexander Shishkind3595d12012-05-08 23:28:58 +0300306 udc->hw_bank.lpm = reg;
Alexander Shishkin262c1632012-05-08 23:28:59 +0300307 hw_alloc_regmap(udc, !!reg);
Alexander Shishkind3595d12012-05-08 23:28:58 +0300308 udc->hw_bank.size = udc->hw_bank.op - udc->hw_bank.abs;
309 udc->hw_bank.size += OP_LAST;
310 udc->hw_bank.size /= sizeof(u32);
David Lopoaa69a802008-11-17 14:14:51 -0800311
Alexander Shishkin262c1632012-05-08 23:28:59 +0300312 reg = hw_read(udc, CAP_DCCPARAMS, DCCPARAMS_DEN) >>
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300313 ffs_nr(DCCPARAMS_DEN);
Alexander Shishkind3595d12012-05-08 23:28:58 +0300314 udc->hw_ep_max = reg * 2; /* cache hw ENDPT_MAX */
David Lopoaa69a802008-11-17 14:14:51 -0800315
Alexander Shishkind3595d12012-05-08 23:28:58 +0300316 if (udc->hw_ep_max == 0 || udc->hw_ep_max > ENDPT_MAX)
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530317 return -ENODEV;
David Lopoaa69a802008-11-17 14:14:51 -0800318
319 /* setup lock mode ? */
320
321 /* ENDPTSETUPSTAT is '0' by default */
322
323 /* HCSPARAMS.bf.ppc SHOULD BE zero for device */
324
325 return 0;
326}
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530327/**
328 * hw_device_reset: resets chip (execute without interruption)
329 * @base: register base address
330 *
331 * This function returns an error code
332 */
333static int hw_device_reset(struct ci13xxx *udc)
334{
335 /* should flush & stop before reset */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300336 hw_write(udc, OP_ENDPTFLUSH, ~0, ~0);
337 hw_write(udc, OP_USBCMD, USBCMD_RS, 0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530338
Alexander Shishkin262c1632012-05-08 23:28:59 +0300339 hw_write(udc, OP_USBCMD, USBCMD_RST, USBCMD_RST);
340 while (hw_read(udc, OP_USBCMD, USBCMD_RST))
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530341 udelay(10); /* not RTOS friendly */
342
343
344 if (udc->udc_driver->notify_event)
345 udc->udc_driver->notify_event(udc,
346 CI13XXX_CONTROLLER_RESET_EVENT);
347
Pavankumar Kondeti8c2387a2011-05-02 11:56:28 +0530348 if (udc->udc_driver->flags & CI13XXX_DISABLE_STREAMING)
Alexander Shishkin262c1632012-05-08 23:28:59 +0300349 hw_write(udc, OP_USBMODE, USBMODE_SDIS, USBMODE_SDIS);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530350
351 /* USBMODE should be configured step by step */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300352 hw_write(udc, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
353 hw_write(udc, OP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE);
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300354 /* HW >= 2.3 */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300355 hw_write(udc, OP_USBMODE, USBMODE_SLOM, USBMODE_SLOM);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530356
Alexander Shishkin262c1632012-05-08 23:28:59 +0300357 if (hw_read(udc, OP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530358 pr_err("cannot enter in device mode");
Alexander Shishkind3595d12012-05-08 23:28:58 +0300359 pr_err("lpm = %i", udc->hw_bank.lpm);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530360 return -ENODEV;
361 }
362
363 return 0;
364}
David Lopoaa69a802008-11-17 14:14:51 -0800365
366/**
367 * hw_device_state: enables/disables interrupts & starts/stops device (execute
368 * without interruption)
369 * @dma: 0 => disable, !0 => enable and set dma engine
370 *
371 * This function returns an error code
372 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300373static int hw_device_state(struct ci13xxx *udc, u32 dma)
David Lopoaa69a802008-11-17 14:14:51 -0800374{
375 if (dma) {
Alexander Shishkin262c1632012-05-08 23:28:59 +0300376 hw_write(udc, OP_ENDPTLISTADDR, ~0, dma);
David Lopoaa69a802008-11-17 14:14:51 -0800377 /* interrupt, error, port change, reset, sleep/suspend */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300378 hw_write(udc, OP_USBINTR, ~0,
David Lopoaa69a802008-11-17 14:14:51 -0800379 USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
Alexander Shishkin262c1632012-05-08 23:28:59 +0300380 hw_write(udc, OP_USBCMD, USBCMD_RS, USBCMD_RS);
David Lopoaa69a802008-11-17 14:14:51 -0800381 } else {
Alexander Shishkin262c1632012-05-08 23:28:59 +0300382 hw_write(udc, OP_USBCMD, USBCMD_RS, 0);
383 hw_write(udc, OP_USBINTR, ~0, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800384 }
385 return 0;
386}
387
388/**
389 * hw_ep_flush: flush endpoint fifo (execute without interruption)
390 * @num: endpoint number
391 * @dir: endpoint direction
392 *
393 * This function returns an error code
394 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300395static int hw_ep_flush(struct ci13xxx *udc, int num, int dir)
David Lopoaa69a802008-11-17 14:14:51 -0800396{
397 int n = hw_ep_bit(num, dir);
398
399 do {
400 /* flush any pending transfer */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300401 hw_write(udc, OP_ENDPTFLUSH, BIT(n), BIT(n));
402 while (hw_read(udc, OP_ENDPTFLUSH, BIT(n)))
David Lopoaa69a802008-11-17 14:14:51 -0800403 cpu_relax();
Alexander Shishkin262c1632012-05-08 23:28:59 +0300404 } while (hw_read(udc, OP_ENDPTSTAT, BIT(n)));
David Lopoaa69a802008-11-17 14:14:51 -0800405
406 return 0;
407}
408
409/**
410 * hw_ep_disable: disables endpoint (execute without interruption)
411 * @num: endpoint number
412 * @dir: endpoint direction
413 *
414 * This function returns an error code
415 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300416static int hw_ep_disable(struct ci13xxx *udc, int num, int dir)
David Lopoaa69a802008-11-17 14:14:51 -0800417{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300418 hw_ep_flush(udc, num, dir);
Alexander Shishkin262c1632012-05-08 23:28:59 +0300419 hw_write(udc, OP_ENDPTCTRL + num,
Alexander Shishkind3595d12012-05-08 23:28:58 +0300420 dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800421 return 0;
422}
423
424/**
425 * hw_ep_enable: enables endpoint (execute without interruption)
426 * @num: endpoint number
427 * @dir: endpoint direction
428 * @type: endpoint type
429 *
430 * This function returns an error code
431 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300432static int hw_ep_enable(struct ci13xxx *udc, int num, int dir, int type)
David Lopoaa69a802008-11-17 14:14:51 -0800433{
434 u32 mask, data;
435
436 if (dir) {
437 mask = ENDPTCTRL_TXT; /* type */
438 data = type << ffs_nr(mask);
439
440 mask |= ENDPTCTRL_TXS; /* unstall */
441 mask |= ENDPTCTRL_TXR; /* reset data toggle */
442 data |= ENDPTCTRL_TXR;
443 mask |= ENDPTCTRL_TXE; /* enable */
444 data |= ENDPTCTRL_TXE;
445 } else {
446 mask = ENDPTCTRL_RXT; /* type */
447 data = type << ffs_nr(mask);
448
449 mask |= ENDPTCTRL_RXS; /* unstall */
450 mask |= ENDPTCTRL_RXR; /* reset data toggle */
451 data |= ENDPTCTRL_RXR;
452 mask |= ENDPTCTRL_RXE; /* enable */
453 data |= ENDPTCTRL_RXE;
454 }
Alexander Shishkin262c1632012-05-08 23:28:59 +0300455 hw_write(udc, OP_ENDPTCTRL + num, mask, data);
David Lopoaa69a802008-11-17 14:14:51 -0800456 return 0;
457}
458
459/**
460 * hw_ep_get_halt: return endpoint halt status
461 * @num: endpoint number
462 * @dir: endpoint direction
463 *
464 * This function returns 1 if endpoint halted
465 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300466static int hw_ep_get_halt(struct ci13xxx *udc, int num, int dir)
David Lopoaa69a802008-11-17 14:14:51 -0800467{
468 u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
469
Alexander Shishkin262c1632012-05-08 23:28:59 +0300470 return hw_read(udc, OP_ENDPTCTRL + num, mask) ? 1 : 0;
David Lopoaa69a802008-11-17 14:14:51 -0800471}
472
473/**
David Lopoaa69a802008-11-17 14:14:51 -0800474 * hw_test_and_clear_setup_status: test & clear setup status (execute without
475 * interruption)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200476 * @n: endpoint number
David Lopoaa69a802008-11-17 14:14:51 -0800477 *
478 * This function returns setup status
479 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300480static int hw_test_and_clear_setup_status(struct ci13xxx *udc, int n)
David Lopoaa69a802008-11-17 14:14:51 -0800481{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300482 n = ep_to_bit(udc, n);
Alexander Shishkin262c1632012-05-08 23:28:59 +0300483 return hw_test_and_clear(udc, OP_ENDPTSETUPSTAT, BIT(n));
David Lopoaa69a802008-11-17 14:14:51 -0800484}
485
486/**
487 * hw_ep_prime: primes endpoint (execute without interruption)
488 * @num: endpoint number
489 * @dir: endpoint direction
490 * @is_ctrl: true if control endpoint
491 *
492 * This function returns an error code
493 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300494static int hw_ep_prime(struct ci13xxx *udc, int num, int dir, int is_ctrl)
David Lopoaa69a802008-11-17 14:14:51 -0800495{
496 int n = hw_ep_bit(num, dir);
497
Alexander Shishkin262c1632012-05-08 23:28:59 +0300498 if (is_ctrl && dir == RX && hw_read(udc, OP_ENDPTSETUPSTAT, BIT(num)))
David Lopoaa69a802008-11-17 14:14:51 -0800499 return -EAGAIN;
500
Alexander Shishkin262c1632012-05-08 23:28:59 +0300501 hw_write(udc, OP_ENDPTPRIME, BIT(n), BIT(n));
David Lopoaa69a802008-11-17 14:14:51 -0800502
Alexander Shishkin262c1632012-05-08 23:28:59 +0300503 while (hw_read(udc, OP_ENDPTPRIME, BIT(n)))
David Lopoaa69a802008-11-17 14:14:51 -0800504 cpu_relax();
Alexander Shishkin262c1632012-05-08 23:28:59 +0300505 if (is_ctrl && dir == RX && hw_read(udc, OP_ENDPTSETUPSTAT, BIT(num)))
David Lopoaa69a802008-11-17 14:14:51 -0800506 return -EAGAIN;
507
508 /* status shoult be tested according with manual but it doesn't work */
509 return 0;
510}
511
512/**
513 * hw_ep_set_halt: configures ep halt & resets data toggle after clear (execute
514 * without interruption)
515 * @num: endpoint number
516 * @dir: endpoint direction
517 * @value: true => stall, false => unstall
518 *
519 * This function returns an error code
520 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300521static int hw_ep_set_halt(struct ci13xxx *udc, int num, int dir, int value)
David Lopoaa69a802008-11-17 14:14:51 -0800522{
523 if (value != 0 && value != 1)
524 return -EINVAL;
525
526 do {
Alexander Shishkin262c1632012-05-08 23:28:59 +0300527 enum ci13xxx_regs reg = OP_ENDPTCTRL + num;
David Lopoaa69a802008-11-17 14:14:51 -0800528 u32 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
529 u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR;
530
531 /* data toggle - reserved for EP0 but it's in ESS */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300532 hw_write(udc, reg, mask_xs|mask_xr,
533 value ? mask_xs : mask_xr);
Alexander Shishkind3595d12012-05-08 23:28:58 +0300534 } while (value != hw_ep_get_halt(udc, num, dir));
David Lopoaa69a802008-11-17 14:14:51 -0800535
536 return 0;
537}
538
539/**
540 * hw_intr_clear: disables interrupt & clears interrupt status (execute without
541 * interruption)
542 * @n: interrupt bit
543 *
544 * This function returns an error code
545 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300546static int hw_intr_clear(struct ci13xxx *udc, int n)
David Lopoaa69a802008-11-17 14:14:51 -0800547{
548 if (n >= REG_BITS)
549 return -EINVAL;
550
Alexander Shishkin262c1632012-05-08 23:28:59 +0300551 hw_write(udc, OP_USBINTR, BIT(n), 0);
552 hw_write(udc, OP_USBSTS, BIT(n), BIT(n));
David Lopoaa69a802008-11-17 14:14:51 -0800553 return 0;
554}
555
556/**
557 * hw_intr_force: enables interrupt & forces interrupt status (execute without
558 * interruption)
559 * @n: interrupt bit
560 *
561 * This function returns an error code
562 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300563static int hw_intr_force(struct ci13xxx *udc, int n)
David Lopoaa69a802008-11-17 14:14:51 -0800564{
565 if (n >= REG_BITS)
566 return -EINVAL;
567
Alexander Shishkin262c1632012-05-08 23:28:59 +0300568 hw_write(udc, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
569 hw_write(udc, OP_USBINTR, BIT(n), BIT(n));
570 hw_write(udc, OP_USBSTS, BIT(n), BIT(n));
571 hw_write(udc, CAP_TESTMODE, TESTMODE_FORCE, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800572 return 0;
573}
574
575/**
576 * hw_is_port_high_speed: test if port is high speed
577 *
578 * This function returns true if high speed port
579 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300580static int hw_port_is_high_speed(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800581{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300582 return udc->hw_bank.lpm ? hw_read(udc, OP_DEVLC, DEVLC_PSPD) :
583 hw_read(udc, OP_PORTSC, PORTSC_HSP);
David Lopoaa69a802008-11-17 14:14:51 -0800584}
585
586/**
587 * hw_port_test_get: reads port test mode value
588 *
589 * This function returns port test mode value
590 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300591static u8 hw_port_test_get(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800592{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300593 return hw_read(udc, OP_PORTSC, PORTSC_PTC) >> ffs_nr(PORTSC_PTC);
David Lopoaa69a802008-11-17 14:14:51 -0800594}
595
596/**
597 * hw_port_test_set: writes port test mode (execute without interruption)
598 * @mode: new value
599 *
600 * This function returns an error code
601 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300602static int hw_port_test_set(struct ci13xxx *udc, u8 mode)
David Lopoaa69a802008-11-17 14:14:51 -0800603{
604 const u8 TEST_MODE_MAX = 7;
605
606 if (mode > TEST_MODE_MAX)
607 return -EINVAL;
608
Alexander Shishkin262c1632012-05-08 23:28:59 +0300609 hw_write(udc, OP_PORTSC, PORTSC_PTC, mode << ffs_nr(PORTSC_PTC));
David Lopoaa69a802008-11-17 14:14:51 -0800610 return 0;
611}
612
613/**
614 * hw_read_intr_enable: returns interrupt enable register
615 *
616 * This function returns register data
617 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300618static u32 hw_read_intr_enable(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800619{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300620 return hw_read(udc, OP_USBINTR, ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800621}
622
623/**
624 * hw_read_intr_status: returns interrupt status register
625 *
626 * This function returns register data
627 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300628static u32 hw_read_intr_status(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800629{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300630 return hw_read(udc, OP_USBSTS, ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800631}
632
633/**
634 * hw_register_read: reads all device registers (execute without interruption)
635 * @buf: destination buffer
636 * @size: buffer size
637 *
638 * This function returns number of registers read
639 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300640static size_t hw_register_read(struct ci13xxx *udc, u32 *buf, size_t size)
David Lopoaa69a802008-11-17 14:14:51 -0800641{
642 unsigned i;
643
Alexander Shishkind3595d12012-05-08 23:28:58 +0300644 if (size > udc->hw_bank.size)
645 size = udc->hw_bank.size;
David Lopoaa69a802008-11-17 14:14:51 -0800646
647 for (i = 0; i < size; i++)
Alexander Shishkin262c1632012-05-08 23:28:59 +0300648 buf[i] = hw_read(udc, i * sizeof(u32), ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800649
650 return size;
651}
652
653/**
654 * hw_register_write: writes to register
655 * @addr: register address
656 * @data: register value
657 *
658 * This function returns an error code
659 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300660static int hw_register_write(struct ci13xxx *udc, u16 addr, u32 data)
David Lopoaa69a802008-11-17 14:14:51 -0800661{
662 /* align */
663 addr /= sizeof(u32);
664
Alexander Shishkind3595d12012-05-08 23:28:58 +0300665 if (addr >= udc->hw_bank.size)
David Lopoaa69a802008-11-17 14:14:51 -0800666 return -EINVAL;
667
668 /* align */
669 addr *= sizeof(u32);
670
Alexander Shishkin262c1632012-05-08 23:28:59 +0300671 hw_write(udc, addr, ~0, data);
David Lopoaa69a802008-11-17 14:14:51 -0800672 return 0;
673}
674
675/**
676 * hw_test_and_clear_complete: test & clear complete status (execute without
677 * interruption)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200678 * @n: endpoint number
David Lopoaa69a802008-11-17 14:14:51 -0800679 *
680 * This function returns complete status
681 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300682static int hw_test_and_clear_complete(struct ci13xxx *udc, int n)
David Lopoaa69a802008-11-17 14:14:51 -0800683{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300684 n = ep_to_bit(udc, n);
Alexander Shishkin262c1632012-05-08 23:28:59 +0300685 return hw_test_and_clear(udc, OP_ENDPTCOMPLETE, BIT(n));
David Lopoaa69a802008-11-17 14:14:51 -0800686}
687
688/**
689 * hw_test_and_clear_intr_active: test & clear active interrupts (execute
690 * without interruption)
691 *
692 * This function returns active interrutps
693 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300694static u32 hw_test_and_clear_intr_active(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800695{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300696 u32 reg = hw_read_intr_status(udc) & hw_read_intr_enable(udc);
David Lopoaa69a802008-11-17 14:14:51 -0800697
Alexander Shishkin262c1632012-05-08 23:28:59 +0300698 hw_write(udc, OP_USBSTS, ~0, reg);
David Lopoaa69a802008-11-17 14:14:51 -0800699 return reg;
700}
701
702/**
703 * hw_test_and_clear_setup_guard: test & clear setup guard (execute without
704 * interruption)
705 *
706 * This function returns guard value
707 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300708static int hw_test_and_clear_setup_guard(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800709{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300710 return hw_test_and_write(udc, OP_USBCMD, USBCMD_SUTW, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800711}
712
713/**
714 * hw_test_and_set_setup_guard: test & set setup guard (execute without
715 * interruption)
716 *
717 * This function returns guard value
718 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300719static int hw_test_and_set_setup_guard(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800720{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300721 return hw_test_and_write(udc, OP_USBCMD, USBCMD_SUTW, USBCMD_SUTW);
David Lopoaa69a802008-11-17 14:14:51 -0800722}
723
724/**
725 * hw_usb_set_address: configures USB address (execute without interruption)
726 * @value: new USB address
727 *
728 * This function returns an error code
729 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300730static int hw_usb_set_address(struct ci13xxx *udc, u8 value)
David Lopoaa69a802008-11-17 14:14:51 -0800731{
732 /* advance */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300733 hw_write(udc, OP_DEVICEADDR, DEVICEADDR_USBADR | DEVICEADDR_USBADRA,
734 value << ffs_nr(DEVICEADDR_USBADR) | DEVICEADDR_USBADRA);
David Lopoaa69a802008-11-17 14:14:51 -0800735 return 0;
736}
737
738/**
739 * hw_usb_reset: restart device after a bus reset (execute without
740 * interruption)
741 *
742 * This function returns an error code
743 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300744static int hw_usb_reset(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800745{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300746 hw_usb_set_address(udc, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800747
748 /* ESS flushes only at end?!? */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300749 hw_write(udc, OP_ENDPTFLUSH, ~0, ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800750
751 /* clear setup token semaphores */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300752 hw_write(udc, OP_ENDPTSETUPSTAT, 0, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800753
754 /* clear complete status */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300755 hw_write(udc, OP_ENDPTCOMPLETE, 0, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800756
757 /* wait until all bits cleared */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300758 while (hw_read(udc, OP_ENDPTPRIME, ~0))
David Lopoaa69a802008-11-17 14:14:51 -0800759 udelay(10); /* not RTOS friendly */
760
761 /* reset all endpoints ? */
762
763 /* reset internal status and wait for further instructions
764 no need to verify the port reset status (ESS does it) */
765
766 return 0;
767}
768
769/******************************************************************************
770 * DBG block
771 *****************************************************************************/
772/**
773 * show_device: prints information about device capabilities and status
774 *
775 * Check "device.h" for details
776 */
777static ssize_t show_device(struct device *dev, struct device_attribute *attr,
778 char *buf)
779{
780 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
781 struct usb_gadget *gadget = &udc->gadget;
782 int n = 0;
783
Alexander Shishkin0f089092012-05-08 23:29:02 +0300784 trace(udc->dev, "%p\n", buf);
David Lopoaa69a802008-11-17 14:14:51 -0800785 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +0300786 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -0800787 return 0;
788 }
789
790 n += scnprintf(buf + n, PAGE_SIZE - n, "speed = %d\n",
791 gadget->speed);
Michal Nazarewiczd327ab52011-11-19 18:27:37 +0100792 n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed = %d\n",
793 gadget->max_speed);
794 /* TODO: Scheduled for removal in 3.8. */
David Lopoaa69a802008-11-17 14:14:51 -0800795 n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed = %d\n",
Michal Nazarewiczd327ab52011-11-19 18:27:37 +0100796 gadget_is_dualspeed(gadget));
David Lopoaa69a802008-11-17 14:14:51 -0800797 n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg = %d\n",
798 gadget->is_otg);
799 n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral = %d\n",
800 gadget->is_a_peripheral);
801 n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable = %d\n",
802 gadget->b_hnp_enable);
803 n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support = %d\n",
804 gadget->a_hnp_support);
805 n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n",
806 gadget->a_alt_hnp_support);
807 n += scnprintf(buf + n, PAGE_SIZE - n, "name = %s\n",
808 (gadget->name ? gadget->name : ""));
809
810 return n;
811}
812static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
813
814/**
815 * show_driver: prints information about attached gadget (if any)
816 *
817 * Check "device.h" for details
818 */
819static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
820 char *buf)
821{
822 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
823 struct usb_gadget_driver *driver = udc->driver;
824 int n = 0;
825
Alexander Shishkin0f089092012-05-08 23:29:02 +0300826 trace(udc->dev, "%p\n", buf);
David Lopoaa69a802008-11-17 14:14:51 -0800827 if (attr == NULL || buf == NULL) {
828 dev_err(dev, "[%s] EINVAL\n", __func__);
829 return 0;
830 }
831
832 if (driver == NULL)
833 return scnprintf(buf, PAGE_SIZE,
834 "There is no gadget attached!\n");
835
836 n += scnprintf(buf + n, PAGE_SIZE - n, "function = %s\n",
837 (driver->function ? driver->function : ""));
838 n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n",
Michal Nazarewicz7177aed2011-11-19 18:27:38 +0100839 driver->max_speed);
David Lopoaa69a802008-11-17 14:14:51 -0800840
841 return n;
842}
843static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL);
844
845/* Maximum event message length */
846#define DBG_DATA_MSG 64UL
847
848/* Maximum event messages */
849#define DBG_DATA_MAX 128UL
850
851/* Event buffer descriptor */
852static struct {
853 char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */
854 unsigned idx; /* index */
855 unsigned tty; /* print to console? */
856 rwlock_t lck; /* lock */
857} dbg_data = {
858 .idx = 0,
859 .tty = 0,
860 .lck = __RW_LOCK_UNLOCKED(lck)
861};
862
863/**
864 * dbg_dec: decrements debug event index
865 * @idx: buffer index
866 */
867static void dbg_dec(unsigned *idx)
868{
869 *idx = (*idx - 1) & (DBG_DATA_MAX-1);
870}
871
872/**
873 * dbg_inc: increments debug event index
874 * @idx: buffer index
875 */
876static void dbg_inc(unsigned *idx)
877{
878 *idx = (*idx + 1) & (DBG_DATA_MAX-1);
879}
880
881/**
882 * dbg_print: prints the common part of the event
883 * @addr: endpoint address
884 * @name: event name
885 * @status: status
886 * @extra: extra information
887 */
888static void dbg_print(u8 addr, const char *name, int status, const char *extra)
889{
890 struct timeval tval;
891 unsigned int stamp;
892 unsigned long flags;
893
894 write_lock_irqsave(&dbg_data.lck, flags);
895
896 do_gettimeofday(&tval);
897 stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s */
898 stamp = stamp * 1000000 + tval.tv_usec;
899
900 scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +0300901 "%04X\t? %02X %-7.7s %4i ?\t%s\n",
David Lopoaa69a802008-11-17 14:14:51 -0800902 stamp, addr, name, status, extra);
903
904 dbg_inc(&dbg_data.idx);
905
906 write_unlock_irqrestore(&dbg_data.lck, flags);
907
908 if (dbg_data.tty != 0)
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +0300909 pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n",
David Lopoaa69a802008-11-17 14:14:51 -0800910 stamp, addr, name, status, extra);
911}
912
913/**
914 * dbg_done: prints a DONE event
915 * @addr: endpoint address
916 * @td: transfer descriptor
917 * @status: status
918 */
919static void dbg_done(u8 addr, const u32 token, int status)
920{
921 char msg[DBG_DATA_MSG];
922
923 scnprintf(msg, sizeof(msg), "%d %02X",
924 (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES),
925 (int)(token & TD_STATUS) >> ffs_nr(TD_STATUS));
926 dbg_print(addr, "DONE", status, msg);
927}
928
929/**
930 * dbg_event: prints a generic event
931 * @addr: endpoint address
932 * @name: event name
933 * @status: status
934 */
935static void dbg_event(u8 addr, const char *name, int status)
936{
937 if (name != NULL)
938 dbg_print(addr, name, status, "");
939}
940
941/*
942 * dbg_queue: prints a QUEUE event
943 * @addr: endpoint address
944 * @req: USB request
945 * @status: status
946 */
947static void dbg_queue(u8 addr, const struct usb_request *req, int status)
948{
949 char msg[DBG_DATA_MSG];
950
951 if (req != NULL) {
952 scnprintf(msg, sizeof(msg),
953 "%d %d", !req->no_interrupt, req->length);
954 dbg_print(addr, "QUEUE", status, msg);
955 }
956}
957
958/**
959 * dbg_setup: prints a SETUP event
960 * @addr: endpoint address
961 * @req: setup request
962 */
963static void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
964{
965 char msg[DBG_DATA_MSG];
966
967 if (req != NULL) {
968 scnprintf(msg, sizeof(msg),
969 "%02X %02X %04X %04X %d", req->bRequestType,
970 req->bRequest, le16_to_cpu(req->wValue),
971 le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
972 dbg_print(addr, "SETUP", 0, msg);
973 }
974}
975
976/**
977 * show_events: displays the event buffer
978 *
979 * Check "device.h" for details
980 */
981static ssize_t show_events(struct device *dev, struct device_attribute *attr,
982 char *buf)
983{
984 unsigned long flags;
985 unsigned i, j, n = 0;
986
Alexander Shishkin0f089092012-05-08 23:29:02 +0300987 trace(dev->parent, "%p\n", buf);
David Lopoaa69a802008-11-17 14:14:51 -0800988 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +0300989 dev_err(dev->parent, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -0800990 return 0;
991 }
992
993 read_lock_irqsave(&dbg_data.lck, flags);
994
995 i = dbg_data.idx;
996 for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) {
997 n += strlen(dbg_data.buf[i]);
998 if (n >= PAGE_SIZE) {
999 n -= strlen(dbg_data.buf[i]);
1000 break;
1001 }
1002 }
1003 for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i))
1004 j += scnprintf(buf + j, PAGE_SIZE - j,
1005 "%s", dbg_data.buf[i]);
1006
1007 read_unlock_irqrestore(&dbg_data.lck, flags);
1008
1009 return n;
1010}
1011
1012/**
1013 * store_events: configure if events are going to be also printed to console
1014 *
1015 * Check "device.h" for details
1016 */
1017static ssize_t store_events(struct device *dev, struct device_attribute *attr,
1018 const char *buf, size_t count)
1019{
1020 unsigned tty;
1021
Alexander Shishkin0f089092012-05-08 23:29:02 +03001022 trace(dev->parent, "[%s] %p, %d\n", __func__, buf, count);
David Lopoaa69a802008-11-17 14:14:51 -08001023 if (attr == NULL || buf == NULL) {
1024 dev_err(dev, "[%s] EINVAL\n", __func__);
1025 goto done;
1026 }
1027
1028 if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
1029 dev_err(dev, "<1|0>: enable|disable console log\n");
1030 goto done;
1031 }
1032
1033 dbg_data.tty = tty;
1034 dev_info(dev, "tty = %u", dbg_data.tty);
1035
1036 done:
1037 return count;
1038}
1039static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
1040
1041/**
1042 * show_inters: interrupt status, enable status and historic
1043 *
1044 * Check "device.h" for details
1045 */
1046static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
1047 char *buf)
1048{
1049 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1050 unsigned long flags;
1051 u32 intr;
1052 unsigned i, j, n = 0;
1053
Alexander Shishkin0f089092012-05-08 23:29:02 +03001054 trace(udc->dev, "%p\n", buf);
David Lopoaa69a802008-11-17 14:14:51 -08001055 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001056 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -08001057 return 0;
1058 }
1059
Alexander Shishkind3595d12012-05-08 23:28:58 +03001060 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001061
1062 n += scnprintf(buf + n, PAGE_SIZE - n,
Alexander Shishkind3595d12012-05-08 23:28:58 +03001063 "status = %08x\n", hw_read_intr_status(udc));
David Lopoaa69a802008-11-17 14:14:51 -08001064 n += scnprintf(buf + n, PAGE_SIZE - n,
Alexander Shishkind3595d12012-05-08 23:28:58 +03001065 "enable = %08x\n", hw_read_intr_enable(udc));
David Lopoaa69a802008-11-17 14:14:51 -08001066
1067 n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
1068 isr_statistics.test);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001069 n += scnprintf(buf + n, PAGE_SIZE - n, "? ui = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001070 isr_statistics.ui);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001071 n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001072 isr_statistics.uei);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001073 n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001074 isr_statistics.pci);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001075 n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001076 isr_statistics.uri);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001077 n += scnprintf(buf + n, PAGE_SIZE - n, "? sli = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001078 isr_statistics.sli);
1079 n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n",
1080 isr_statistics.none);
1081 n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n",
1082 isr_statistics.hndl.cnt);
1083
1084 for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) {
1085 i &= ISR_MASK;
1086 intr = isr_statistics.hndl.buf[i];
1087
1088 if (USBi_UI & intr)
1089 n += scnprintf(buf + n, PAGE_SIZE - n, "ui ");
1090 intr &= ~USBi_UI;
1091 if (USBi_UEI & intr)
1092 n += scnprintf(buf + n, PAGE_SIZE - n, "uei ");
1093 intr &= ~USBi_UEI;
1094 if (USBi_PCI & intr)
1095 n += scnprintf(buf + n, PAGE_SIZE - n, "pci ");
1096 intr &= ~USBi_PCI;
1097 if (USBi_URI & intr)
1098 n += scnprintf(buf + n, PAGE_SIZE - n, "uri ");
1099 intr &= ~USBi_URI;
1100 if (USBi_SLI & intr)
1101 n += scnprintf(buf + n, PAGE_SIZE - n, "sli ");
1102 intr &= ~USBi_SLI;
1103 if (intr)
1104 n += scnprintf(buf + n, PAGE_SIZE - n, "??? ");
1105 if (isr_statistics.hndl.buf[i])
1106 n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
1107 }
1108
Alexander Shishkind3595d12012-05-08 23:28:58 +03001109 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001110
1111 return n;
1112}
1113
1114/**
1115 * store_inters: enable & force or disable an individual interrutps
1116 * (to be used for test purposes only)
1117 *
1118 * Check "device.h" for details
1119 */
1120static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
1121 const char *buf, size_t count)
1122{
1123 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1124 unsigned long flags;
1125 unsigned en, bit;
1126
Alexander Shishkin0f089092012-05-08 23:29:02 +03001127 trace(udc->dev, "%p, %d\n", buf, count);
David Lopoaa69a802008-11-17 14:14:51 -08001128 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001129 dev_err(udc->dev, "EINVAL\n");
David Lopoaa69a802008-11-17 14:14:51 -08001130 goto done;
1131 }
1132
1133 if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001134 dev_err(udc->dev, "<1|0> <bit>: enable|disable interrupt\n");
David Lopoaa69a802008-11-17 14:14:51 -08001135 goto done;
1136 }
1137
Alexander Shishkind3595d12012-05-08 23:28:58 +03001138 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001139 if (en) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001140 if (hw_intr_force(udc, bit))
David Lopoaa69a802008-11-17 14:14:51 -08001141 dev_err(dev, "invalid bit number\n");
1142 else
1143 isr_statistics.test++;
1144 } else {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001145 if (hw_intr_clear(udc, bit))
David Lopoaa69a802008-11-17 14:14:51 -08001146 dev_err(dev, "invalid bit number\n");
1147 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03001148 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001149
1150 done:
1151 return count;
1152}
1153static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
1154
1155/**
1156 * show_port_test: reads port test mode
1157 *
1158 * Check "device.h" for details
1159 */
1160static ssize_t show_port_test(struct device *dev,
1161 struct device_attribute *attr, char *buf)
1162{
1163 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1164 unsigned long flags;
1165 unsigned mode;
1166
Alexander Shishkin0f089092012-05-08 23:29:02 +03001167 trace(udc->dev, "%p\n", buf);
David Lopoaa69a802008-11-17 14:14:51 -08001168 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001169 dev_err(udc->dev, "EINVAL\n");
David Lopoaa69a802008-11-17 14:14:51 -08001170 return 0;
1171 }
1172
Alexander Shishkind3595d12012-05-08 23:28:58 +03001173 spin_lock_irqsave(&udc->lock, flags);
1174 mode = hw_port_test_get(udc);
1175 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001176
1177 return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
1178}
1179
1180/**
1181 * store_port_test: writes port test mode
1182 *
1183 * Check "device.h" for details
1184 */
1185static ssize_t store_port_test(struct device *dev,
1186 struct device_attribute *attr,
1187 const char *buf, size_t count)
1188{
1189 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1190 unsigned long flags;
1191 unsigned mode;
1192
Alexander Shishkin0f089092012-05-08 23:29:02 +03001193 trace(udc->dev, "%p, %d\n", buf, count);
David Lopoaa69a802008-11-17 14:14:51 -08001194 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001195 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -08001196 goto done;
1197 }
1198
1199 if (sscanf(buf, "%u", &mode) != 1) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001200 dev_err(udc->dev, "<mode>: set port test mode");
David Lopoaa69a802008-11-17 14:14:51 -08001201 goto done;
1202 }
1203
Alexander Shishkind3595d12012-05-08 23:28:58 +03001204 spin_lock_irqsave(&udc->lock, flags);
1205 if (hw_port_test_set(udc, mode))
Alexander Shishkin0f089092012-05-08 23:29:02 +03001206 dev_err(udc->dev, "invalid mode\n");
Alexander Shishkind3595d12012-05-08 23:28:58 +03001207 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001208
1209 done:
1210 return count;
1211}
1212static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
1213 show_port_test, store_port_test);
1214
1215/**
1216 * show_qheads: DMA contents of all queue heads
1217 *
1218 * Check "device.h" for details
1219 */
1220static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
1221 char *buf)
1222{
1223 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1224 unsigned long flags;
1225 unsigned i, j, n = 0;
1226
Alexander Shishkin0f089092012-05-08 23:29:02 +03001227 trace(udc->dev, "%p\n", buf);
David Lopoaa69a802008-11-17 14:14:51 -08001228 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001229 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -08001230 return 0;
1231 }
1232
Alexander Shishkind3595d12012-05-08 23:28:58 +03001233 spin_lock_irqsave(&udc->lock, flags);
1234 for (i = 0; i < udc->hw_ep_max/2; i++) {
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301235 struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i];
Alexander Shishkind3595d12012-05-08 23:28:58 +03001236 struct ci13xxx_ep *mEpTx =
1237 &udc->ci13xxx_ep[i + udc->hw_ep_max/2];
David Lopoaa69a802008-11-17 14:14:51 -08001238 n += scnprintf(buf + n, PAGE_SIZE - n,
1239 "EP=%02i: RX=%08X TX=%08X\n",
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301240 i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08001241 for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) {
1242 n += scnprintf(buf + n, PAGE_SIZE - n,
1243 " %04X: %08X %08X\n", j,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301244 *((u32 *)mEpRx->qh.ptr + j),
1245 *((u32 *)mEpTx->qh.ptr + j));
David Lopoaa69a802008-11-17 14:14:51 -08001246 }
1247 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03001248 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001249
1250 return n;
1251}
1252static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
1253
1254/**
1255 * show_registers: dumps all registers
1256 *
1257 * Check "device.h" for details
1258 */
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001259#define DUMP_ENTRIES 512
David Lopoaa69a802008-11-17 14:14:51 -08001260static ssize_t show_registers(struct device *dev,
1261 struct device_attribute *attr, char *buf)
1262{
1263 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1264 unsigned long flags;
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001265 u32 *dump;
David Lopoaa69a802008-11-17 14:14:51 -08001266 unsigned i, k, n = 0;
1267
Alexander Shishkin0f089092012-05-08 23:29:02 +03001268 trace(udc->dev, "%p\n", buf);
David Lopoaa69a802008-11-17 14:14:51 -08001269 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001270 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -08001271 return 0;
1272 }
1273
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001274 dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
1275 if (!dump) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001276 dev_err(udc->dev, "%s: out of memory\n", __func__);
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001277 return 0;
1278 }
1279
Alexander Shishkind3595d12012-05-08 23:28:58 +03001280 spin_lock_irqsave(&udc->lock, flags);
1281 k = hw_register_read(udc, dump, DUMP_ENTRIES);
1282 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001283
1284 for (i = 0; i < k; i++) {
1285 n += scnprintf(buf + n, PAGE_SIZE - n,
1286 "reg[0x%04X] = 0x%08X\n",
1287 i * (unsigned)sizeof(u32), dump[i]);
1288 }
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001289 kfree(dump);
David Lopoaa69a802008-11-17 14:14:51 -08001290
1291 return n;
1292}
1293
1294/**
1295 * store_registers: writes value to register address
1296 *
1297 * Check "device.h" for details
1298 */
1299static ssize_t store_registers(struct device *dev,
1300 struct device_attribute *attr,
1301 const char *buf, size_t count)
1302{
1303 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1304 unsigned long addr, data, flags;
1305
Alexander Shishkin0f089092012-05-08 23:29:02 +03001306 trace(udc->dev, "%p, %d\n", buf, count);
David Lopoaa69a802008-11-17 14:14:51 -08001307 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001308 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -08001309 goto done;
1310 }
1311
1312 if (sscanf(buf, "%li %li", &addr, &data) != 2) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001313 dev_err(udc->dev,
1314 "<addr> <data>: write data to register address\n");
David Lopoaa69a802008-11-17 14:14:51 -08001315 goto done;
1316 }
1317
Alexander Shishkind3595d12012-05-08 23:28:58 +03001318 spin_lock_irqsave(&udc->lock, flags);
1319 if (hw_register_write(udc, addr, data))
Alexander Shishkin0f089092012-05-08 23:29:02 +03001320 dev_err(udc->dev, "invalid address range\n");
Alexander Shishkind3595d12012-05-08 23:28:58 +03001321 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001322
1323 done:
1324 return count;
1325}
1326static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
1327 show_registers, store_registers);
1328
1329/**
1330 * show_requests: DMA contents of all requests currently queued (all endpts)
1331 *
1332 * Check "device.h" for details
1333 */
1334static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
1335 char *buf)
1336{
1337 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1338 unsigned long flags;
1339 struct list_head *ptr = NULL;
1340 struct ci13xxx_req *req = NULL;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301341 unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
David Lopoaa69a802008-11-17 14:14:51 -08001342
Alexander Shishkin0f089092012-05-08 23:29:02 +03001343 trace(udc->dev, "%p\n", buf);
David Lopoaa69a802008-11-17 14:14:51 -08001344 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001345 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -08001346 return 0;
1347 }
1348
Alexander Shishkind3595d12012-05-08 23:28:58 +03001349 spin_lock_irqsave(&udc->lock, flags);
1350 for (i = 0; i < udc->hw_ep_max; i++)
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301351 list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue)
1352 {
1353 req = list_entry(ptr, struct ci13xxx_req, queue);
David Lopoaa69a802008-11-17 14:14:51 -08001354
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301355 n += scnprintf(buf + n, PAGE_SIZE - n,
1356 "EP=%02i: TD=%08X %s\n",
Alexander Shishkind3595d12012-05-08 23:28:58 +03001357 i % udc->hw_ep_max/2, (u32)req->dma,
1358 ((i < udc->hw_ep_max/2) ? "RX" : "TX"));
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301359
1360 for (j = 0; j < qSize; j++)
David Lopoaa69a802008-11-17 14:14:51 -08001361 n += scnprintf(buf + n, PAGE_SIZE - n,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301362 " %04X: %08X\n", j,
1363 *((u32 *)req->ptr + j));
1364 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03001365 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001366
1367 return n;
1368}
1369static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL);
1370
1371/**
1372 * dbg_create_files: initializes the attribute interface
1373 * @dev: device
1374 *
1375 * This function returns an error code
1376 */
1377__maybe_unused static int dbg_create_files(struct device *dev)
1378{
1379 int retval = 0;
1380
1381 if (dev == NULL)
1382 return -EINVAL;
1383 retval = device_create_file(dev, &dev_attr_device);
1384 if (retval)
1385 goto done;
1386 retval = device_create_file(dev, &dev_attr_driver);
1387 if (retval)
1388 goto rm_device;
1389 retval = device_create_file(dev, &dev_attr_events);
1390 if (retval)
1391 goto rm_driver;
1392 retval = device_create_file(dev, &dev_attr_inters);
1393 if (retval)
1394 goto rm_events;
1395 retval = device_create_file(dev, &dev_attr_port_test);
1396 if (retval)
1397 goto rm_inters;
1398 retval = device_create_file(dev, &dev_attr_qheads);
1399 if (retval)
1400 goto rm_port_test;
1401 retval = device_create_file(dev, &dev_attr_registers);
1402 if (retval)
1403 goto rm_qheads;
1404 retval = device_create_file(dev, &dev_attr_requests);
1405 if (retval)
1406 goto rm_registers;
1407 return 0;
1408
1409 rm_registers:
1410 device_remove_file(dev, &dev_attr_registers);
1411 rm_qheads:
1412 device_remove_file(dev, &dev_attr_qheads);
1413 rm_port_test:
1414 device_remove_file(dev, &dev_attr_port_test);
1415 rm_inters:
1416 device_remove_file(dev, &dev_attr_inters);
1417 rm_events:
1418 device_remove_file(dev, &dev_attr_events);
1419 rm_driver:
1420 device_remove_file(dev, &dev_attr_driver);
1421 rm_device:
1422 device_remove_file(dev, &dev_attr_device);
1423 done:
1424 return retval;
1425}
1426
1427/**
1428 * dbg_remove_files: destroys the attribute interface
1429 * @dev: device
1430 *
1431 * This function returns an error code
1432 */
1433__maybe_unused static int dbg_remove_files(struct device *dev)
1434{
1435 if (dev == NULL)
1436 return -EINVAL;
1437 device_remove_file(dev, &dev_attr_requests);
1438 device_remove_file(dev, &dev_attr_registers);
1439 device_remove_file(dev, &dev_attr_qheads);
1440 device_remove_file(dev, &dev_attr_port_test);
1441 device_remove_file(dev, &dev_attr_inters);
1442 device_remove_file(dev, &dev_attr_events);
1443 device_remove_file(dev, &dev_attr_driver);
1444 device_remove_file(dev, &dev_attr_device);
1445 return 0;
1446}
1447
1448/******************************************************************************
1449 * UTIL block
1450 *****************************************************************************/
1451/**
1452 * _usb_addr: calculates endpoint address from direction & number
1453 * @ep: endpoint
1454 */
1455static inline u8 _usb_addr(struct ci13xxx_ep *ep)
1456{
1457 return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num;
1458}
1459
1460/**
1461 * _hardware_queue: configures a request at hardware level
1462 * @gadget: gadget
1463 * @mEp: endpoint
1464 *
1465 * This function returns an error code
1466 */
1467static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1468{
Alexander Shishkind3595d12012-05-08 23:28:58 +03001469 struct ci13xxx *udc = mEp->udc;
David Lopoaa69a802008-11-17 14:14:51 -08001470 unsigned i;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301471 int ret = 0;
1472 unsigned length = mReq->req.length;
David Lopoaa69a802008-11-17 14:14:51 -08001473
Alexander Shishkin0f089092012-05-08 23:29:02 +03001474 trace(udc->dev, "%p, %p", mEp, mReq);
David Lopoaa69a802008-11-17 14:14:51 -08001475
1476 /* don't queue twice */
1477 if (mReq->req.status == -EALREADY)
1478 return -EALREADY;
1479
David Lopoaa69a802008-11-17 14:14:51 -08001480 mReq->req.status = -EALREADY;
Michael Grzeschik954aad82011-10-10 18:38:06 +02001481 if (length && mReq->req.dma == DMA_ADDR_INVALID) {
David Lopoaa69a802008-11-17 14:14:51 -08001482 mReq->req.dma = \
1483 dma_map_single(mEp->device, mReq->req.buf,
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301484 length, mEp->dir ? DMA_TO_DEVICE :
1485 DMA_FROM_DEVICE);
David Lopoaa69a802008-11-17 14:14:51 -08001486 if (mReq->req.dma == 0)
1487 return -ENOMEM;
1488
1489 mReq->map = 1;
1490 }
1491
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301492 if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) {
1493 mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC,
1494 &mReq->zdma);
1495 if (mReq->zptr == NULL) {
1496 if (mReq->map) {
1497 dma_unmap_single(mEp->device, mReq->req.dma,
1498 length, mEp->dir ? DMA_TO_DEVICE :
1499 DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02001500 mReq->req.dma = DMA_ADDR_INVALID;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301501 mReq->map = 0;
1502 }
1503 return -ENOMEM;
1504 }
1505 memset(mReq->zptr, 0, sizeof(*mReq->zptr));
1506 mReq->zptr->next = TD_TERMINATE;
1507 mReq->zptr->token = TD_STATUS_ACTIVE;
1508 if (!mReq->req.no_interrupt)
1509 mReq->zptr->token |= TD_IOC;
1510 }
David Lopoaa69a802008-11-17 14:14:51 -08001511 /*
1512 * TD configuration
1513 * TODO - handle requests which spawns into several TDs
1514 */
1515 memset(mReq->ptr, 0, sizeof(*mReq->ptr));
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301516 mReq->ptr->token = length << ffs_nr(TD_TOTAL_BYTES);
David Lopoaa69a802008-11-17 14:14:51 -08001517 mReq->ptr->token &= TD_TOTAL_BYTES;
David Lopoaa69a802008-11-17 14:14:51 -08001518 mReq->ptr->token |= TD_STATUS_ACTIVE;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301519 if (mReq->zptr) {
1520 mReq->ptr->next = mReq->zdma;
1521 } else {
1522 mReq->ptr->next = TD_TERMINATE;
1523 if (!mReq->req.no_interrupt)
1524 mReq->ptr->token |= TD_IOC;
1525 }
David Lopoaa69a802008-11-17 14:14:51 -08001526 mReq->ptr->page[0] = mReq->req.dma;
1527 for (i = 1; i < 5; i++)
1528 mReq->ptr->page[i] =
Artem Leonenko0a313c42010-12-14 23:47:06 -08001529 (mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK;
David Lopoaa69a802008-11-17 14:14:51 -08001530
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301531 if (!list_empty(&mEp->qh.queue)) {
1532 struct ci13xxx_req *mReqPrev;
1533 int n = hw_ep_bit(mEp->num, mEp->dir);
1534 int tmp_stat;
1535
1536 mReqPrev = list_entry(mEp->qh.queue.prev,
1537 struct ci13xxx_req, queue);
1538 if (mReqPrev->zptr)
1539 mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
1540 else
1541 mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
1542 wmb();
Alexander Shishkin262c1632012-05-08 23:28:59 +03001543 if (hw_read(udc, OP_ENDPTPRIME, BIT(n)))
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301544 goto done;
1545 do {
Alexander Shishkin262c1632012-05-08 23:28:59 +03001546 hw_write(udc, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
1547 tmp_stat = hw_read(udc, OP_ENDPTSTAT, BIT(n));
1548 } while (!hw_read(udc, OP_USBCMD, USBCMD_ATDTW));
1549 hw_write(udc, OP_USBCMD, USBCMD_ATDTW, 0);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301550 if (tmp_stat)
1551 goto done;
1552 }
1553
1554 /* QH configuration */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301555 mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */
1556 mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301557 mEp->qh.ptr->cap |= QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08001558
1559 wmb(); /* synchronize before ep prime */
1560
Alexander Shishkind3595d12012-05-08 23:28:58 +03001561 ret = hw_ep_prime(udc, mEp->num, mEp->dir,
David Lopoaa69a802008-11-17 14:14:51 -08001562 mEp->type == USB_ENDPOINT_XFER_CONTROL);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301563done:
1564 return ret;
David Lopoaa69a802008-11-17 14:14:51 -08001565}
1566
1567/**
1568 * _hardware_dequeue: handles a request at hardware level
1569 * @gadget: gadget
1570 * @mEp: endpoint
1571 *
1572 * This function returns an error code
1573 */
1574static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1575{
Alexander Shishkin0f089092012-05-08 23:29:02 +03001576 trace(mEp->udc->dev, "%p, %p", mEp, mReq);
David Lopoaa69a802008-11-17 14:14:51 -08001577
1578 if (mReq->req.status != -EALREADY)
1579 return -EINVAL;
1580
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301581 if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
1582 return -EBUSY;
1583
1584 if (mReq->zptr) {
1585 if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
1586 return -EBUSY;
1587 dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
1588 mReq->zptr = NULL;
1589 }
David Lopoaa69a802008-11-17 14:14:51 -08001590
1591 mReq->req.status = 0;
1592
1593 if (mReq->map) {
1594 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
1595 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02001596 mReq->req.dma = DMA_ADDR_INVALID;
David Lopoaa69a802008-11-17 14:14:51 -08001597 mReq->map = 0;
1598 }
1599
1600 mReq->req.status = mReq->ptr->token & TD_STATUS;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301601 if ((TD_STATUS_HALTED & mReq->req.status) != 0)
David Lopoaa69a802008-11-17 14:14:51 -08001602 mReq->req.status = -1;
1603 else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0)
1604 mReq->req.status = -1;
1605 else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0)
1606 mReq->req.status = -1;
1607
1608 mReq->req.actual = mReq->ptr->token & TD_TOTAL_BYTES;
1609 mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES);
1610 mReq->req.actual = mReq->req.length - mReq->req.actual;
1611 mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual;
1612
1613 return mReq->req.actual;
1614}
1615
1616/**
1617 * _ep_nuke: dequeues all endpoint requests
1618 * @mEp: endpoint
1619 *
1620 * This function returns an error code
1621 * Caller must hold lock
1622 */
1623static int _ep_nuke(struct ci13xxx_ep *mEp)
1624__releases(mEp->lock)
1625__acquires(mEp->lock)
1626{
Alexander Shishkin0f089092012-05-08 23:29:02 +03001627 trace(mEp->udc->dev, "%p", mEp);
David Lopoaa69a802008-11-17 14:14:51 -08001628
1629 if (mEp == NULL)
1630 return -EINVAL;
1631
Alexander Shishkind3595d12012-05-08 23:28:58 +03001632 hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08001633
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301634 while (!list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -08001635
1636 /* pop oldest request */
1637 struct ci13xxx_req *mReq = \
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301638 list_entry(mEp->qh.queue.next,
David Lopoaa69a802008-11-17 14:14:51 -08001639 struct ci13xxx_req, queue);
1640 list_del_init(&mReq->queue);
1641 mReq->req.status = -ESHUTDOWN;
1642
Artem Leonenko7c25a822010-12-14 23:46:55 -08001643 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08001644 spin_unlock(mEp->lock);
1645 mReq->req.complete(&mEp->ep, &mReq->req);
1646 spin_lock(mEp->lock);
1647 }
1648 }
1649 return 0;
1650}
1651
1652/**
1653 * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
1654 * @gadget: gadget
1655 *
1656 * This function returns an error code
David Lopoaa69a802008-11-17 14:14:51 -08001657 */
1658static int _gadget_stop_activity(struct usb_gadget *gadget)
David Lopoaa69a802008-11-17 14:14:51 -08001659{
1660 struct usb_ep *ep;
1661 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301662 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -08001663
Alexander Shishkin0f089092012-05-08 23:29:02 +03001664 trace(udc->dev, "%p", gadget);
David Lopoaa69a802008-11-17 14:14:51 -08001665
1666 if (gadget == NULL)
1667 return -EINVAL;
1668
Alexander Shishkind3595d12012-05-08 23:28:58 +03001669 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301670 udc->gadget.speed = USB_SPEED_UNKNOWN;
1671 udc->remote_wakeup = 0;
1672 udc->suspended = 0;
Alexander Shishkind3595d12012-05-08 23:28:58 +03001673 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301674
David Lopoaa69a802008-11-17 14:14:51 -08001675 /* flush all endpoints */
1676 gadget_for_each_ep(ep, gadget) {
1677 usb_ep_fifo_flush(ep);
1678 }
Alexander Shishkind36ade62012-05-04 16:47:15 +03001679 usb_ep_fifo_flush(&udc->ep0out->ep);
1680 usb_ep_fifo_flush(&udc->ep0in->ep);
David Lopoaa69a802008-11-17 14:14:51 -08001681
1682 udc->driver->disconnect(gadget);
1683
1684 /* make sure to disable all endpoints */
1685 gadget_for_each_ep(ep, gadget) {
1686 usb_ep_disable(ep);
1687 }
David Lopoaa69a802008-11-17 14:14:51 -08001688
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301689 if (udc->status != NULL) {
Alexander Shishkind36ade62012-05-04 16:47:15 +03001690 usb_ep_free_request(&udc->ep0in->ep, udc->status);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301691 udc->status = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08001692 }
1693
David Lopoaa69a802008-11-17 14:14:51 -08001694 return 0;
1695}
1696
1697/******************************************************************************
1698 * ISR block
1699 *****************************************************************************/
1700/**
1701 * isr_reset_handler: USB reset interrupt handler
1702 * @udc: UDC device
1703 *
1704 * This function resets USB engine after a bus reset occurred
1705 */
1706static void isr_reset_handler(struct ci13xxx *udc)
1707__releases(udc->lock)
1708__acquires(udc->lock)
1709{
David Lopoaa69a802008-11-17 14:14:51 -08001710 int retval;
1711
Alexander Shishkin0f089092012-05-08 23:29:02 +03001712 trace(udc->dev, "%p", udc);
David Lopoaa69a802008-11-17 14:14:51 -08001713
1714 dbg_event(0xFF, "BUS RST", 0);
1715
Alexander Shishkind3595d12012-05-08 23:28:58 +03001716 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001717 retval = _gadget_stop_activity(&udc->gadget);
1718 if (retval)
1719 goto done;
1720
Alexander Shishkind3595d12012-05-08 23:28:58 +03001721 retval = hw_usb_reset(udc);
David Lopoaa69a802008-11-17 14:14:51 -08001722 if (retval)
1723 goto done;
1724
Alexander Shishkind36ade62012-05-04 16:47:15 +03001725 udc->status = usb_ep_alloc_request(&udc->ep0in->ep, GFP_ATOMIC);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05301726 if (udc->status == NULL)
1727 retval = -ENOMEM;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301728
Alexander Shishkind3595d12012-05-08 23:28:58 +03001729 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001730
1731 done:
1732 if (retval)
Alexander Shishkin0f089092012-05-08 23:29:02 +03001733 dev_err(udc->dev, "error: %i\n", retval);
David Lopoaa69a802008-11-17 14:14:51 -08001734}
1735
1736/**
1737 * isr_get_status_complete: get_status request complete function
1738 * @ep: endpoint
1739 * @req: request handled
1740 *
1741 * Caller must release lock
1742 */
1743static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
1744{
Alexander Shishkin0f089092012-05-08 23:29:02 +03001745 trace(NULL, "%p, %p", ep, req);
David Lopoaa69a802008-11-17 14:14:51 -08001746
Alexander Shishkin0f089092012-05-08 23:29:02 +03001747 if (ep == NULL || req == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001748 return;
David Lopoaa69a802008-11-17 14:14:51 -08001749
1750 kfree(req->buf);
1751 usb_ep_free_request(ep, req);
1752}
1753
1754/**
1755 * isr_get_status_response: get_status request response
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301756 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08001757 * @setup: setup request packet
1758 *
1759 * This function returns an error code
1760 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301761static int isr_get_status_response(struct ci13xxx *udc,
David Lopoaa69a802008-11-17 14:14:51 -08001762 struct usb_ctrlrequest *setup)
1763__releases(mEp->lock)
1764__acquires(mEp->lock)
1765{
Alexander Shishkind36ade62012-05-04 16:47:15 +03001766 struct ci13xxx_ep *mEp = udc->ep0in;
David Lopoaa69a802008-11-17 14:14:51 -08001767 struct usb_request *req = NULL;
1768 gfp_t gfp_flags = GFP_ATOMIC;
1769 int dir, num, retval;
1770
Alexander Shishkin0f089092012-05-08 23:29:02 +03001771 trace(udc->dev, "%p, %p", mEp, setup);
David Lopoaa69a802008-11-17 14:14:51 -08001772
1773 if (mEp == NULL || setup == NULL)
1774 return -EINVAL;
1775
1776 spin_unlock(mEp->lock);
1777 req = usb_ep_alloc_request(&mEp->ep, gfp_flags);
1778 spin_lock(mEp->lock);
1779 if (req == NULL)
1780 return -ENOMEM;
1781
1782 req->complete = isr_get_status_complete;
1783 req->length = 2;
1784 req->buf = kzalloc(req->length, gfp_flags);
1785 if (req->buf == NULL) {
1786 retval = -ENOMEM;
1787 goto err_free_req;
1788 }
1789
1790 if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301791 /* Assume that device is bus powered for now. */
Alexander Shishkin1155a7b2012-05-08 23:28:57 +03001792 *(u16 *)req->buf = _udc->remote_wakeup << 1;
David Lopoaa69a802008-11-17 14:14:51 -08001793 retval = 0;
1794 } else if ((setup->bRequestType & USB_RECIP_MASK) \
1795 == USB_RECIP_ENDPOINT) {
1796 dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
1797 TX : RX;
1798 num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK;
Alexander Shishkind3595d12012-05-08 23:28:58 +03001799 *(u16 *)req->buf = hw_ep_get_halt(udc, num, dir);
David Lopoaa69a802008-11-17 14:14:51 -08001800 }
1801 /* else do nothing; reserved for future use */
1802
1803 spin_unlock(mEp->lock);
1804 retval = usb_ep_queue(&mEp->ep, req, gfp_flags);
1805 spin_lock(mEp->lock);
1806 if (retval)
1807 goto err_free_buf;
1808
1809 return 0;
1810
1811 err_free_buf:
1812 kfree(req->buf);
1813 err_free_req:
1814 spin_unlock(mEp->lock);
1815 usb_ep_free_request(&mEp->ep, req);
1816 spin_lock(mEp->lock);
1817 return retval;
1818}
1819
1820/**
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301821 * isr_setup_status_complete: setup_status request complete function
1822 * @ep: endpoint
1823 * @req: request handled
1824 *
1825 * Caller must release lock. Put the port in test mode if test mode
1826 * feature is selected.
1827 */
1828static void
1829isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
1830{
1831 struct ci13xxx *udc = req->context;
1832 unsigned long flags;
1833
Alexander Shishkin0f089092012-05-08 23:29:02 +03001834 trace(udc->dev, "%p, %p", ep, req);
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301835
Alexander Shishkind3595d12012-05-08 23:28:58 +03001836 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301837 if (udc->test_mode)
Alexander Shishkind3595d12012-05-08 23:28:58 +03001838 hw_port_test_set(udc, udc->test_mode);
1839 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301840}
1841
1842/**
David Lopoaa69a802008-11-17 14:14:51 -08001843 * isr_setup_status_phase: queues the status phase of a setup transation
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301844 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08001845 *
1846 * This function returns an error code
1847 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301848static int isr_setup_status_phase(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -08001849__releases(mEp->lock)
1850__acquires(mEp->lock)
1851{
1852 int retval;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301853 struct ci13xxx_ep *mEp;
David Lopoaa69a802008-11-17 14:14:51 -08001854
Alexander Shishkin0f089092012-05-08 23:29:02 +03001855 trace(udc->dev, "%p", udc);
David Lopoaa69a802008-11-17 14:14:51 -08001856
Alexander Shishkind36ade62012-05-04 16:47:15 +03001857 mEp = (udc->ep0_dir == TX) ? udc->ep0out : udc->ep0in;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301858 udc->status->context = udc;
1859 udc->status->complete = isr_setup_status_complete;
David Lopoaa69a802008-11-17 14:14:51 -08001860
1861 spin_unlock(mEp->lock);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301862 retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
David Lopoaa69a802008-11-17 14:14:51 -08001863 spin_lock(mEp->lock);
1864
1865 return retval;
1866}
1867
1868/**
1869 * isr_tr_complete_low: transaction complete low level handler
1870 * @mEp: endpoint
1871 *
1872 * This function returns an error code
1873 * Caller must hold lock
1874 */
1875static int isr_tr_complete_low(struct ci13xxx_ep *mEp)
1876__releases(mEp->lock)
1877__acquires(mEp->lock)
1878{
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301879 struct ci13xxx_req *mReq, *mReqTemp;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05301880 struct ci13xxx_ep *mEpTemp = mEp;
Pavankumar Kondeti986b11b2011-05-02 11:56:29 +05301881 int uninitialized_var(retval);
David Lopoaa69a802008-11-17 14:14:51 -08001882
Alexander Shishkin0f089092012-05-08 23:29:02 +03001883 trace(mEp->udc->dev, "%p", mEp);
David Lopoaa69a802008-11-17 14:14:51 -08001884
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301885 if (list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08001886 return -EINVAL;
1887
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301888 list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,
1889 queue) {
1890 retval = _hardware_dequeue(mEp, mReq);
1891 if (retval < 0)
1892 break;
1893 list_del_init(&mReq->queue);
1894 dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
1895 if (mReq->req.complete != NULL) {
1896 spin_unlock(mEp->lock);
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05301897 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
1898 mReq->req.length)
Alexander Shishkind36ade62012-05-04 16:47:15 +03001899 mEpTemp = _udc->ep0in;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05301900 mReq->req.complete(&mEpTemp->ep, &mReq->req);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301901 spin_lock(mEp->lock);
1902 }
1903 }
David Lopoaa69a802008-11-17 14:14:51 -08001904
Pavankumar Kondetief907482011-05-02 11:56:27 +05301905 if (retval == -EBUSY)
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301906 retval = 0;
1907 if (retval < 0)
David Lopoaa69a802008-11-17 14:14:51 -08001908 dbg_event(_usb_addr(mEp), "DONE", retval);
David Lopoaa69a802008-11-17 14:14:51 -08001909
David Lopoaa69a802008-11-17 14:14:51 -08001910 return retval;
1911}
1912
1913/**
1914 * isr_tr_complete_handler: transaction complete interrupt handler
1915 * @udc: UDC descriptor
1916 *
1917 * This function handles traffic events
1918 */
1919static void isr_tr_complete_handler(struct ci13xxx *udc)
1920__releases(udc->lock)
1921__acquires(udc->lock)
1922{
1923 unsigned i;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301924 u8 tmode = 0;
David Lopoaa69a802008-11-17 14:14:51 -08001925
Alexander Shishkin0f089092012-05-08 23:29:02 +03001926 trace(udc->dev, "%p", udc);
David Lopoaa69a802008-11-17 14:14:51 -08001927
Alexander Shishkind3595d12012-05-08 23:28:58 +03001928 for (i = 0; i < udc->hw_ep_max; i++) {
David Lopoaa69a802008-11-17 14:14:51 -08001929 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05301930 int type, num, dir, err = -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -08001931 struct usb_ctrlrequest req;
1932
Ido Shayevitz31fb6012012-03-12 20:25:23 +02001933 if (mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001934 continue; /* not configured */
1935
Alexander Shishkind3595d12012-05-08 23:28:58 +03001936 if (hw_test_and_clear_complete(udc, i)) {
David Lopoaa69a802008-11-17 14:14:51 -08001937 err = isr_tr_complete_low(mEp);
1938 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
1939 if (err > 0) /* needs status phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301940 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08001941 if (err < 0) {
1942 dbg_event(_usb_addr(mEp),
1943 "ERROR", err);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001944 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001945 if (usb_ep_set_halt(&mEp->ep))
Alexander Shishkin0f089092012-05-08 23:29:02 +03001946 dev_err(udc->dev,
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07001947 "error: ep_set_halt\n");
Alexander Shishkind3595d12012-05-08 23:28:58 +03001948 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001949 }
1950 }
1951 }
1952
1953 if (mEp->type != USB_ENDPOINT_XFER_CONTROL ||
Alexander Shishkind3595d12012-05-08 23:28:58 +03001954 !hw_test_and_clear_setup_status(udc, i))
David Lopoaa69a802008-11-17 14:14:51 -08001955 continue;
1956
1957 if (i != 0) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001958 dev_warn(udc->dev, "ctrl traffic at endpoint %d\n", i);
David Lopoaa69a802008-11-17 14:14:51 -08001959 continue;
1960 }
1961
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301962 /*
1963 * Flush data and handshake transactions of previous
1964 * setup packet.
1965 */
Alexander Shishkind36ade62012-05-04 16:47:15 +03001966 _ep_nuke(udc->ep0out);
1967 _ep_nuke(udc->ep0in);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301968
David Lopoaa69a802008-11-17 14:14:51 -08001969 /* read_setup_packet */
1970 do {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001971 hw_test_and_set_setup_guard(udc);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301972 memcpy(&req, &mEp->qh.ptr->setup, sizeof(req));
Alexander Shishkind3595d12012-05-08 23:28:58 +03001973 } while (!hw_test_and_clear_setup_guard(udc));
David Lopoaa69a802008-11-17 14:14:51 -08001974
1975 type = req.bRequestType;
1976
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301977 udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
David Lopoaa69a802008-11-17 14:14:51 -08001978
1979 dbg_setup(_usb_addr(mEp), &req);
1980
1981 switch (req.bRequest) {
1982 case USB_REQ_CLEAR_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301983 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
1984 le16_to_cpu(req.wValue) ==
1985 USB_ENDPOINT_HALT) {
1986 if (req.wLength != 0)
David Lopoaa69a802008-11-17 14:14:51 -08001987 break;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301988 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05301989 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301990 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05301991 if (dir) /* TX */
Alexander Shishkind3595d12012-05-08 23:28:58 +03001992 num += udc->hw_ep_max/2;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301993 if (!udc->ci13xxx_ep[num].wedge) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001994 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301995 err = usb_ep_clear_halt(
1996 &udc->ci13xxx_ep[num].ep);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001997 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301998 if (err)
1999 break;
2000 }
2001 err = isr_setup_status_phase(udc);
2002 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
2003 le16_to_cpu(req.wValue) ==
2004 USB_DEVICE_REMOTE_WAKEUP) {
2005 if (req.wLength != 0)
2006 break;
2007 udc->remote_wakeup = 0;
2008 err = isr_setup_status_phase(udc);
2009 } else {
2010 goto delegate;
David Lopoaa69a802008-11-17 14:14:51 -08002011 }
David Lopoaa69a802008-11-17 14:14:51 -08002012 break;
2013 case USB_REQ_GET_STATUS:
2014 if (type != (USB_DIR_IN|USB_RECIP_DEVICE) &&
2015 type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
2016 type != (USB_DIR_IN|USB_RECIP_INTERFACE))
2017 goto delegate;
2018 if (le16_to_cpu(req.wLength) != 2 ||
2019 le16_to_cpu(req.wValue) != 0)
2020 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302021 err = isr_get_status_response(udc, &req);
David Lopoaa69a802008-11-17 14:14:51 -08002022 break;
2023 case USB_REQ_SET_ADDRESS:
2024 if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
2025 goto delegate;
2026 if (le16_to_cpu(req.wLength) != 0 ||
2027 le16_to_cpu(req.wIndex) != 0)
2028 break;
Alexander Shishkind3595d12012-05-08 23:28:58 +03002029 err = hw_usb_set_address(udc,
2030 (u8)le16_to_cpu(req.wValue));
David Lopoaa69a802008-11-17 14:14:51 -08002031 if (err)
2032 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302033 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002034 break;
2035 case USB_REQ_SET_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302036 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
2037 le16_to_cpu(req.wValue) ==
2038 USB_ENDPOINT_HALT) {
2039 if (req.wLength != 0)
2040 break;
2041 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302042 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302043 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302044 if (dir) /* TX */
Alexander Shishkind3595d12012-05-08 23:28:58 +03002045 num += udc->hw_ep_max/2;
David Lopoaa69a802008-11-17 14:14:51 -08002046
Alexander Shishkind3595d12012-05-08 23:28:58 +03002047 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302048 err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002049 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302050 if (!err)
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302051 isr_setup_status_phase(udc);
2052 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302053 if (req.wLength != 0)
2054 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302055 switch (le16_to_cpu(req.wValue)) {
2056 case USB_DEVICE_REMOTE_WAKEUP:
2057 udc->remote_wakeup = 1;
2058 err = isr_setup_status_phase(udc);
2059 break;
2060 case USB_DEVICE_TEST_MODE:
2061 tmode = le16_to_cpu(req.wIndex) >> 8;
2062 switch (tmode) {
2063 case TEST_J:
2064 case TEST_K:
2065 case TEST_SE0_NAK:
2066 case TEST_PACKET:
2067 case TEST_FORCE_EN:
2068 udc->test_mode = tmode;
2069 err = isr_setup_status_phase(
2070 udc);
2071 break;
2072 default:
2073 break;
2074 }
2075 default:
2076 goto delegate;
2077 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302078 } else {
2079 goto delegate;
2080 }
David Lopoaa69a802008-11-17 14:14:51 -08002081 break;
2082 default:
2083delegate:
2084 if (req.wLength == 0) /* no data phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302085 udc->ep0_dir = TX;
David Lopoaa69a802008-11-17 14:14:51 -08002086
Alexander Shishkind3595d12012-05-08 23:28:58 +03002087 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08002088 err = udc->driver->setup(&udc->gadget, &req);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002089 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08002090 break;
2091 }
2092
2093 if (err < 0) {
2094 dbg_event(_usb_addr(mEp), "ERROR", err);
2095
Alexander Shishkind3595d12012-05-08 23:28:58 +03002096 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08002097 if (usb_ep_set_halt(&mEp->ep))
Alexander Shishkin0f089092012-05-08 23:29:02 +03002098 dev_err(udc->dev, "error: ep_set_halt\n");
Alexander Shishkind3595d12012-05-08 23:28:58 +03002099 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08002100 }
2101 }
2102}
2103
2104/******************************************************************************
2105 * ENDPT block
2106 *****************************************************************************/
2107/**
2108 * ep_enable: configure endpoint, making it usable
2109 *
2110 * Check usb_ep_enable() at "usb_gadget.h" for details
2111 */
2112static int ep_enable(struct usb_ep *ep,
2113 const struct usb_endpoint_descriptor *desc)
2114{
2115 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302116 int retval = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002117 unsigned long flags;
2118
Alexander Shishkin0f089092012-05-08 23:29:02 +03002119 trace(mEp->udc->dev, "%p, %p", ep, desc);
David Lopoaa69a802008-11-17 14:14:51 -08002120
2121 if (ep == NULL || desc == NULL)
2122 return -EINVAL;
2123
2124 spin_lock_irqsave(mEp->lock, flags);
2125
2126 /* only internal SW should enable ctrl endpts */
2127
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002128 mEp->ep.desc = desc;
David Lopoaa69a802008-11-17 14:14:51 -08002129
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302130 if (!list_empty(&mEp->qh.queue))
Alexander Shishkin0f089092012-05-08 23:29:02 +03002131 dev_warn(mEp->udc->dev, "enabling a non-empty endpoint!\n");
David Lopoaa69a802008-11-17 14:14:51 -08002132
Matthias Kaehlcke15739bb2009-04-15 22:28:41 +02002133 mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX;
2134 mEp->num = usb_endpoint_num(desc);
2135 mEp->type = usb_endpoint_type(desc);
David Lopoaa69a802008-11-17 14:14:51 -08002136
Kuninori Morimoto29cc8892011-08-23 03:12:03 -07002137 mEp->ep.maxpacket = usb_endpoint_maxp(desc);
David Lopoaa69a802008-11-17 14:14:51 -08002138
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302139 dbg_event(_usb_addr(mEp), "ENABLE", 0);
David Lopoaa69a802008-11-17 14:14:51 -08002140
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302141 mEp->qh.ptr->cap = 0;
David Lopof23e6492009-04-16 14:35:24 -07002142
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302143 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2144 mEp->qh.ptr->cap |= QH_IOS;
2145 else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
2146 mEp->qh.ptr->cap &= ~QH_MULT;
2147 else
2148 mEp->qh.ptr->cap &= ~QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08002149
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302150 mEp->qh.ptr->cap |=
2151 (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
2152 mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */
David Lopoaa69a802008-11-17 14:14:51 -08002153
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302154 /*
2155 * Enable endpoints in the HW other than ep0 as ep0
2156 * is always enabled
2157 */
2158 if (mEp->num)
Alexander Shishkind3595d12012-05-08 23:28:58 +03002159 retval |= hw_ep_enable(mEp->udc, mEp->num, mEp->dir, mEp->type);
David Lopoaa69a802008-11-17 14:14:51 -08002160
2161 spin_unlock_irqrestore(mEp->lock, flags);
2162 return retval;
2163}
2164
2165/**
2166 * ep_disable: endpoint is no longer usable
2167 *
2168 * Check usb_ep_disable() at "usb_gadget.h" for details
2169 */
2170static int ep_disable(struct usb_ep *ep)
2171{
2172 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2173 int direction, retval = 0;
2174 unsigned long flags;
2175
Alexander Shishkin0f089092012-05-08 23:29:02 +03002176 trace(mEp->udc->dev, "%p", ep);
David Lopoaa69a802008-11-17 14:14:51 -08002177
2178 if (ep == NULL)
2179 return -EINVAL;
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002180 else if (mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002181 return -EBUSY;
2182
2183 spin_lock_irqsave(mEp->lock, flags);
2184
2185 /* only internal SW should disable ctrl endpts */
2186
2187 direction = mEp->dir;
2188 do {
2189 dbg_event(_usb_addr(mEp), "DISABLE", 0);
2190
2191 retval |= _ep_nuke(mEp);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002192 retval |= hw_ep_disable(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08002193
2194 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2195 mEp->dir = (mEp->dir == TX) ? RX : TX;
2196
2197 } while (mEp->dir != direction);
2198
Ido Shayevitzf9c56cd2012-02-08 13:56:48 +02002199 mEp->ep.desc = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002200
2201 spin_unlock_irqrestore(mEp->lock, flags);
2202 return retval;
2203}
2204
2205/**
2206 * ep_alloc_request: allocate a request object to use with this endpoint
2207 *
2208 * Check usb_ep_alloc_request() at "usb_gadget.h" for details
2209 */
2210static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
2211{
2212 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2213 struct ci13xxx_req *mReq = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002214
Alexander Shishkin0f089092012-05-08 23:29:02 +03002215 trace(mEp->udc->dev, "%p, %i", ep, gfp_flags);
David Lopoaa69a802008-11-17 14:14:51 -08002216
Alexander Shishkin0f089092012-05-08 23:29:02 +03002217 if (ep == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002218 return NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002219
David Lopoaa69a802008-11-17 14:14:51 -08002220 mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
2221 if (mReq != NULL) {
2222 INIT_LIST_HEAD(&mReq->queue);
Michael Grzeschik954aad82011-10-10 18:38:06 +02002223 mReq->req.dma = DMA_ADDR_INVALID;
David Lopoaa69a802008-11-17 14:14:51 -08002224
2225 mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,
2226 &mReq->dma);
2227 if (mReq->ptr == NULL) {
2228 kfree(mReq);
2229 mReq = NULL;
2230 }
2231 }
2232
2233 dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
2234
David Lopoaa69a802008-11-17 14:14:51 -08002235 return (mReq == NULL) ? NULL : &mReq->req;
2236}
2237
2238/**
2239 * ep_free_request: frees a request object
2240 *
2241 * Check usb_ep_free_request() at "usb_gadget.h" for details
2242 */
2243static void ep_free_request(struct usb_ep *ep, struct usb_request *req)
2244{
2245 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2246 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2247 unsigned long flags;
2248
Alexander Shishkin0f089092012-05-08 23:29:02 +03002249 trace(mEp->udc->dev, "%p, %p", ep, req);
David Lopoaa69a802008-11-17 14:14:51 -08002250
2251 if (ep == NULL || req == NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08002252 return;
2253 } else if (!list_empty(&mReq->queue)) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03002254 dev_err(mEp->udc->dev, "freeing queued request\n");
David Lopoaa69a802008-11-17 14:14:51 -08002255 return;
2256 }
2257
2258 spin_lock_irqsave(mEp->lock, flags);
2259
2260 if (mReq->ptr)
2261 dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma);
2262 kfree(mReq);
2263
2264 dbg_event(_usb_addr(mEp), "FREE", 0);
2265
2266 spin_unlock_irqrestore(mEp->lock, flags);
2267}
2268
2269/**
2270 * ep_queue: queues (submits) an I/O request to an endpoint
2271 *
2272 * Check usb_ep_queue()* at usb_gadget.h" for details
2273 */
2274static int ep_queue(struct usb_ep *ep, struct usb_request *req,
2275 gfp_t __maybe_unused gfp_flags)
2276{
2277 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2278 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2279 int retval = 0;
2280 unsigned long flags;
2281
Alexander Shishkin0f089092012-05-08 23:29:02 +03002282 trace(mEp->udc->dev, "%p, %p, %X", ep, req, gfp_flags);
David Lopoaa69a802008-11-17 14:14:51 -08002283
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002284 if (ep == NULL || req == NULL || mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002285 return -EINVAL;
2286
2287 spin_lock_irqsave(mEp->lock, flags);
2288
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302289 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
2290 if (req->length)
2291 mEp = (_udc->ep0_dir == RX) ?
Alexander Shishkind36ade62012-05-04 16:47:15 +03002292 _udc->ep0out : _udc->ep0in;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302293 if (!list_empty(&mEp->qh.queue)) {
2294 _ep_nuke(mEp);
2295 retval = -EOVERFLOW;
Alexander Shishkin0f089092012-05-08 23:29:02 +03002296 dev_warn(mEp->udc->dev, "endpoint ctrl %X nuked\n",
2297 _usb_addr(mEp));
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302298 }
David Lopoaa69a802008-11-17 14:14:51 -08002299 }
2300
2301 /* first nuke then test link, e.g. previous status has not sent */
2302 if (!list_empty(&mReq->queue)) {
2303 retval = -EBUSY;
Alexander Shishkin0f089092012-05-08 23:29:02 +03002304 dev_err(mEp->udc->dev, "request already in queue\n");
David Lopoaa69a802008-11-17 14:14:51 -08002305 goto done;
2306 }
2307
Alexander Shishkin1155a7b2012-05-08 23:28:57 +03002308 if (req->length > 4 * CI13XXX_PAGE_SIZE) {
2309 req->length = 4 * CI13XXX_PAGE_SIZE;
David Lopoaa69a802008-11-17 14:14:51 -08002310 retval = -EMSGSIZE;
Alexander Shishkin0f089092012-05-08 23:29:02 +03002311 dev_warn(mEp->udc->dev, "request length truncated\n");
David Lopoaa69a802008-11-17 14:14:51 -08002312 }
2313
2314 dbg_queue(_usb_addr(mEp), req, retval);
2315
2316 /* push request */
2317 mReq->req.status = -EINPROGRESS;
2318 mReq->req.actual = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002319
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302320 retval = _hardware_enqueue(mEp, mReq);
Artem Leonenkod9bb9c12010-12-14 23:45:50 -08002321
2322 if (retval == -EALREADY) {
David Lopoaa69a802008-11-17 14:14:51 -08002323 dbg_event(_usb_addr(mEp), "QUEUE", retval);
2324 retval = 0;
2325 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302326 if (!retval)
2327 list_add_tail(&mReq->queue, &mEp->qh.queue);
David Lopoaa69a802008-11-17 14:14:51 -08002328
2329 done:
2330 spin_unlock_irqrestore(mEp->lock, flags);
2331 return retval;
2332}
2333
2334/**
2335 * ep_dequeue: dequeues (cancels, unlinks) an I/O request from an endpoint
2336 *
2337 * Check usb_ep_dequeue() at "usb_gadget.h" for details
2338 */
2339static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
2340{
2341 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2342 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2343 unsigned long flags;
2344
Alexander Shishkin0f089092012-05-08 23:29:02 +03002345 trace(mEp->udc->dev, "%p, %p", ep, req);
David Lopoaa69a802008-11-17 14:14:51 -08002346
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302347 if (ep == NULL || req == NULL || mReq->req.status != -EALREADY ||
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002348 mEp->ep.desc == NULL || list_empty(&mReq->queue) ||
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302349 list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08002350 return -EINVAL;
2351
2352 spin_lock_irqsave(mEp->lock, flags);
2353
2354 dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
2355
Alexander Shishkind3595d12012-05-08 23:28:58 +03002356 hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08002357
2358 /* pop request */
2359 list_del_init(&mReq->queue);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302360 if (mReq->map) {
2361 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
2362 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02002363 mReq->req.dma = DMA_ADDR_INVALID;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302364 mReq->map = 0;
2365 }
David Lopoaa69a802008-11-17 14:14:51 -08002366 req->status = -ECONNRESET;
2367
Artem Leonenko7c25a822010-12-14 23:46:55 -08002368 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08002369 spin_unlock(mEp->lock);
2370 mReq->req.complete(&mEp->ep, &mReq->req);
2371 spin_lock(mEp->lock);
2372 }
2373
2374 spin_unlock_irqrestore(mEp->lock, flags);
2375 return 0;
2376}
2377
2378/**
2379 * ep_set_halt: sets the endpoint halt feature
2380 *
2381 * Check usb_ep_set_halt() at "usb_gadget.h" for details
2382 */
2383static int ep_set_halt(struct usb_ep *ep, int value)
2384{
2385 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2386 int direction, retval = 0;
2387 unsigned long flags;
2388
Alexander Shishkin0f089092012-05-08 23:29:02 +03002389 trace(mEp->udc->dev, "%p, %i", ep, value);
David Lopoaa69a802008-11-17 14:14:51 -08002390
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002391 if (ep == NULL || mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002392 return -EINVAL;
2393
2394 spin_lock_irqsave(mEp->lock, flags);
2395
2396#ifndef STALL_IN
2397 /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
2398 if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX &&
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302399 !list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -08002400 spin_unlock_irqrestore(mEp->lock, flags);
2401 return -EAGAIN;
2402 }
2403#endif
2404
2405 direction = mEp->dir;
2406 do {
2407 dbg_event(_usb_addr(mEp), "HALT", value);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002408 retval |= hw_ep_set_halt(mEp->udc, mEp->num, mEp->dir, value);
David Lopoaa69a802008-11-17 14:14:51 -08002409
2410 if (!value)
2411 mEp->wedge = 0;
2412
2413 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2414 mEp->dir = (mEp->dir == TX) ? RX : TX;
2415
2416 } while (mEp->dir != direction);
2417
2418 spin_unlock_irqrestore(mEp->lock, flags);
2419 return retval;
2420}
2421
2422/**
2423 * ep_set_wedge: sets the halt feature and ignores clear requests
2424 *
2425 * Check usb_ep_set_wedge() at "usb_gadget.h" for details
2426 */
2427static int ep_set_wedge(struct usb_ep *ep)
2428{
2429 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2430 unsigned long flags;
2431
Alexander Shishkin0f089092012-05-08 23:29:02 +03002432 trace(mEp->udc->dev, "%p", ep);
David Lopoaa69a802008-11-17 14:14:51 -08002433
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002434 if (ep == NULL || mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002435 return -EINVAL;
2436
2437 spin_lock_irqsave(mEp->lock, flags);
2438
2439 dbg_event(_usb_addr(mEp), "WEDGE", 0);
2440 mEp->wedge = 1;
2441
2442 spin_unlock_irqrestore(mEp->lock, flags);
2443
2444 return usb_ep_set_halt(ep);
2445}
2446
2447/**
2448 * ep_fifo_flush: flushes contents of a fifo
2449 *
2450 * Check usb_ep_fifo_flush() at "usb_gadget.h" for details
2451 */
2452static void ep_fifo_flush(struct usb_ep *ep)
2453{
2454 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2455 unsigned long flags;
2456
Alexander Shishkin0f089092012-05-08 23:29:02 +03002457 trace(mEp->udc->dev, "%p", ep);
David Lopoaa69a802008-11-17 14:14:51 -08002458
2459 if (ep == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03002460 dev_err(mEp->udc->dev, "%02X: -EINVAL\n", _usb_addr(mEp));
David Lopoaa69a802008-11-17 14:14:51 -08002461 return;
2462 }
2463
2464 spin_lock_irqsave(mEp->lock, flags);
2465
2466 dbg_event(_usb_addr(mEp), "FFLUSH", 0);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002467 hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08002468
2469 spin_unlock_irqrestore(mEp->lock, flags);
2470}
2471
2472/**
2473 * Endpoint-specific part of the API to the USB controller hardware
2474 * Check "usb_gadget.h" for details
2475 */
2476static const struct usb_ep_ops usb_ep_ops = {
2477 .enable = ep_enable,
2478 .disable = ep_disable,
2479 .alloc_request = ep_alloc_request,
2480 .free_request = ep_free_request,
2481 .queue = ep_queue,
2482 .dequeue = ep_dequeue,
2483 .set_halt = ep_set_halt,
2484 .set_wedge = ep_set_wedge,
2485 .fifo_flush = ep_fifo_flush,
2486};
2487
2488/******************************************************************************
2489 * GADGET block
2490 *****************************************************************************/
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302491static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
2492{
2493 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2494 unsigned long flags;
2495 int gadget_ready = 0;
2496
2497 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS))
2498 return -EOPNOTSUPP;
2499
Alexander Shishkind3595d12012-05-08 23:28:58 +03002500 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302501 udc->vbus_active = is_active;
2502 if (udc->driver)
2503 gadget_ready = 1;
Alexander Shishkind3595d12012-05-08 23:28:58 +03002504 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302505
2506 if (gadget_ready) {
2507 if (is_active) {
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302508 pm_runtime_get_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302509 hw_device_reset(udc);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002510 hw_device_state(udc, udc->ep0out->qh.dma);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302511 } else {
Alexander Shishkind3595d12012-05-08 23:28:58 +03002512 hw_device_state(udc, 0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302513 if (udc->udc_driver->notify_event)
2514 udc->udc_driver->notify_event(udc,
2515 CI13XXX_CONTROLLER_STOPPED_EVENT);
2516 _gadget_stop_activity(&udc->gadget);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302517 pm_runtime_put_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302518 }
2519 }
2520
2521 return 0;
2522}
2523
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302524static int ci13xxx_wakeup(struct usb_gadget *_gadget)
2525{
2526 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2527 unsigned long flags;
2528 int ret = 0;
2529
Alexander Shishkin0f089092012-05-08 23:29:02 +03002530 trace(udc->dev, "");
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302531
Alexander Shishkind3595d12012-05-08 23:28:58 +03002532 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302533 if (!udc->remote_wakeup) {
2534 ret = -EOPNOTSUPP;
Alexander Shishkin0f089092012-05-08 23:29:02 +03002535 trace(udc->dev, "remote wakeup feature is not enabled\n");
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302536 goto out;
2537 }
Alexander Shishkin262c1632012-05-08 23:28:59 +03002538 if (!hw_read(udc, OP_PORTSC, PORTSC_SUSP)) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302539 ret = -EINVAL;
Alexander Shishkin0f089092012-05-08 23:29:02 +03002540 trace(udc->dev, "port is not suspended\n");
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302541 goto out;
2542 }
Alexander Shishkin262c1632012-05-08 23:28:59 +03002543 hw_write(udc, OP_PORTSC, PORTSC_FPR, PORTSC_FPR);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302544out:
Alexander Shishkind3595d12012-05-08 23:28:58 +03002545 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302546 return ret;
2547}
2548
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302549static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
2550{
2551 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2552
2553 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002554 return usb_phy_set_power(udc->transceiver, mA);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302555 return -ENOTSUPP;
2556}
2557
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002558static int ci13xxx_start(struct usb_gadget_driver *driver,
2559 int (*bind)(struct usb_gadget *));
2560static int ci13xxx_stop(struct usb_gadget_driver *driver);
David Lopoaa69a802008-11-17 14:14:51 -08002561/**
2562 * Device operations part of the API to the USB controller hardware,
2563 * which don't involve endpoints (or i/o)
2564 * Check "usb_gadget.h" for details
2565 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302566static const struct usb_gadget_ops usb_gadget_ops = {
2567 .vbus_session = ci13xxx_vbus_session,
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302568 .wakeup = ci13xxx_wakeup,
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302569 .vbus_draw = ci13xxx_vbus_draw,
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002570 .start = ci13xxx_start,
2571 .stop = ci13xxx_stop,
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302572};
David Lopoaa69a802008-11-17 14:14:51 -08002573
2574/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002575 * ci13xxx_start: register a gadget driver
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002576 * @driver: the driver being registered
2577 * @bind: the driver's bind callback
David Lopoaa69a802008-11-17 14:14:51 -08002578 *
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002579 * Check ci13xxx_start() at <linux/usb/gadget.h> for details.
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002580 * Interrupts are enabled here.
David Lopoaa69a802008-11-17 14:14:51 -08002581 */
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002582static int ci13xxx_start(struct usb_gadget_driver *driver,
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002583 int (*bind)(struct usb_gadget *))
David Lopoaa69a802008-11-17 14:14:51 -08002584{
2585 struct ci13xxx *udc = _udc;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302586 unsigned long flags;
2587 int i, j;
David Lopoaa69a802008-11-17 14:14:51 -08002588 int retval = -ENOMEM;
2589
Alexander Shishkin0f089092012-05-08 23:29:02 +03002590 trace(udc->dev, "%p", driver);
David Lopoaa69a802008-11-17 14:14:51 -08002591
2592 if (driver == NULL ||
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002593 bind == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08002594 driver->setup == NULL ||
Marc Kleine-Budde7bb4fdc2011-10-10 18:38:09 +02002595 driver->disconnect == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002596 return -EINVAL;
2597 else if (udc == NULL)
2598 return -ENODEV;
2599 else if (udc->driver != NULL)
2600 return -EBUSY;
2601
2602 /* alloc resources */
2603 udc->qh_pool = dma_pool_create("ci13xxx_qh", &udc->gadget.dev,
2604 sizeof(struct ci13xxx_qh),
Artem Leonenko0a313c42010-12-14 23:47:06 -08002605 64, CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08002606 if (udc->qh_pool == NULL)
2607 return -ENOMEM;
2608
2609 udc->td_pool = dma_pool_create("ci13xxx_td", &udc->gadget.dev,
2610 sizeof(struct ci13xxx_td),
Artem Leonenko0a313c42010-12-14 23:47:06 -08002611 64, CI13XXX_PAGE_SIZE);
David Lopoaa69a802008-11-17 14:14:51 -08002612 if (udc->td_pool == NULL) {
2613 dma_pool_destroy(udc->qh_pool);
2614 udc->qh_pool = NULL;
2615 return -ENOMEM;
2616 }
2617
Alexander Shishkind3595d12012-05-08 23:28:58 +03002618 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002619
Alexander Shishkin0f089092012-05-08 23:29:02 +03002620 dev_info(udc->dev, "hw_ep_max = %d\n", udc->hw_ep_max);
David Lopoaa69a802008-11-17 14:14:51 -08002621
David Lopoaa69a802008-11-17 14:14:51 -08002622 udc->gadget.dev.driver = NULL;
2623
2624 retval = 0;
Alexander Shishkind3595d12012-05-08 23:28:58 +03002625 for (i = 0; i < udc->hw_ep_max/2; i++) {
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302626 for (j = RX; j <= TX; j++) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03002627 int k = i + j * udc->hw_ep_max/2;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302628 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
David Lopoaa69a802008-11-17 14:14:51 -08002629
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302630 scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
2631 (j == TX) ? "in" : "out");
David Lopoaa69a802008-11-17 14:14:51 -08002632
Alexander Shishkind3595d12012-05-08 23:28:58 +03002633 mEp->udc = udc;
2634 mEp->lock = &udc->lock;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302635 mEp->device = &udc->gadget.dev;
2636 mEp->td_pool = udc->td_pool;
David Lopoaa69a802008-11-17 14:14:51 -08002637
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302638 mEp->ep.name = mEp->name;
2639 mEp->ep.ops = &usb_ep_ops;
2640 mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
David Lopoaa69a802008-11-17 14:14:51 -08002641
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302642 INIT_LIST_HEAD(&mEp->qh.queue);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002643 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302644 mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
2645 &mEp->qh.dma);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002646 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302647 if (mEp->qh.ptr == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002648 retval = -ENOMEM;
2649 else
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302650 memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
2651
Alexander Shishkind36ade62012-05-04 16:47:15 +03002652 /*
2653 * set up shorthands for ep0 out and in endpoints,
2654 * don't add to gadget's ep_list
2655 */
2656 if (i == 0) {
2657 if (j == RX)
2658 udc->ep0out = mEp;
2659 else
2660 udc->ep0in = mEp;
2661
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302662 continue;
Alexander Shishkind36ade62012-05-04 16:47:15 +03002663 }
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302664
David Lopoaa69a802008-11-17 14:14:51 -08002665 list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302666 }
David Lopoaa69a802008-11-17 14:14:51 -08002667 }
2668 if (retval)
2669 goto done;
Alexander Shishkind36ade62012-05-04 16:47:15 +03002670
Alexander Shishkind3595d12012-05-08 23:28:58 +03002671 spin_unlock_irqrestore(&udc->lock, flags);
Alexander Shishkind36ade62012-05-04 16:47:15 +03002672 udc->ep0out->ep.desc = &ctrl_endpt_out_desc;
2673 retval = usb_ep_enable(&udc->ep0out->ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302674 if (retval)
2675 return retval;
Felipe Balbi877c1f52011-06-29 16:41:57 +03002676
Alexander Shishkind36ade62012-05-04 16:47:15 +03002677 udc->ep0in->ep.desc = &ctrl_endpt_in_desc;
2678 retval = usb_ep_enable(&udc->ep0in->ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302679 if (retval)
2680 return retval;
Alexander Shishkind3595d12012-05-08 23:28:58 +03002681 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002682
Alexander Shishkind36ade62012-05-04 16:47:15 +03002683 udc->gadget.ep0 = &udc->ep0in->ep;
David Lopoaa69a802008-11-17 14:14:51 -08002684 /* bind gadget */
2685 driver->driver.bus = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002686 udc->gadget.dev.driver = &driver->driver;
2687
Alexander Shishkind3595d12012-05-08 23:28:58 +03002688 spin_unlock_irqrestore(&udc->lock, flags);
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002689 retval = bind(&udc->gadget); /* MAY SLEEP */
Alexander Shishkind3595d12012-05-08 23:28:58 +03002690 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002691
2692 if (retval) {
David Lopoaa69a802008-11-17 14:14:51 -08002693 udc->gadget.dev.driver = NULL;
2694 goto done;
2695 }
2696
Pavankumar Kondeti49d3df52011-01-11 09:19:21 +05302697 udc->driver = driver;
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302698 pm_runtime_get_sync(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302699 if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
2700 if (udc->vbus_active) {
2701 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
2702 hw_device_reset(udc);
2703 } else {
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302704 pm_runtime_put_sync(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302705 goto done;
2706 }
2707 }
2708
Alexander Shishkind3595d12012-05-08 23:28:58 +03002709 retval = hw_device_state(udc, udc->ep0out->qh.dma);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302710 if (retval)
2711 pm_runtime_put_sync(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08002712
2713 done:
Alexander Shishkind3595d12012-05-08 23:28:58 +03002714 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002715 return retval;
2716}
David Lopoaa69a802008-11-17 14:14:51 -08002717
2718/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002719 * ci13xxx_stop: unregister a gadget driver
David Lopoaa69a802008-11-17 14:14:51 -08002720 *
2721 * Check usb_gadget_unregister_driver() at "usb_gadget.h" for details
2722 */
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002723static int ci13xxx_stop(struct usb_gadget_driver *driver)
David Lopoaa69a802008-11-17 14:14:51 -08002724{
2725 struct ci13xxx *udc = _udc;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302726 unsigned long i, flags;
David Lopoaa69a802008-11-17 14:14:51 -08002727
Alexander Shishkin0f089092012-05-08 23:29:02 +03002728 trace(udc->dev, "%p", driver);
David Lopoaa69a802008-11-17 14:14:51 -08002729
2730 if (driver == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08002731 driver->unbind == NULL ||
2732 driver->setup == NULL ||
2733 driver->disconnect == NULL ||
David Lopoaa69a802008-11-17 14:14:51 -08002734 driver != udc->driver)
2735 return -EINVAL;
2736
Alexander Shishkind3595d12012-05-08 23:28:58 +03002737 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002738
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302739 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) ||
2740 udc->vbus_active) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03002741 hw_device_state(udc, 0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302742 if (udc->udc_driver->notify_event)
2743 udc->udc_driver->notify_event(udc,
2744 CI13XXX_CONTROLLER_STOPPED_EVENT);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002745 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302746 _gadget_stop_activity(&udc->gadget);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002747 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302748 pm_runtime_put(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302749 }
David Lopoaa69a802008-11-17 14:14:51 -08002750
2751 /* unbind gadget */
Alexander Shishkind3595d12012-05-08 23:28:58 +03002752 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302753 driver->unbind(&udc->gadget); /* MAY SLEEP */
Alexander Shishkind3595d12012-05-08 23:28:58 +03002754 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002755
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302756 udc->gadget.dev.driver = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002757
2758 /* free resources */
Alexander Shishkind3595d12012-05-08 23:28:58 +03002759 for (i = 0; i < udc->hw_ep_max; i++) {
David Lopoaa69a802008-11-17 14:14:51 -08002760 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
2761
Alexander Shishkinefa015b2012-05-04 16:47:14 +03002762 if (mEp->num)
David Lopoaa69a802008-11-17 14:14:51 -08002763 list_del_init(&mEp->ep.ep_list);
2764
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302765 if (mEp->qh.ptr != NULL)
2766 dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08002767 }
2768
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302769 udc->gadget.ep0 = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002770 udc->driver = NULL;
2771
Alexander Shishkind3595d12012-05-08 23:28:58 +03002772 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002773
2774 if (udc->td_pool != NULL) {
2775 dma_pool_destroy(udc->td_pool);
2776 udc->td_pool = NULL;
2777 }
2778 if (udc->qh_pool != NULL) {
2779 dma_pool_destroy(udc->qh_pool);
2780 udc->qh_pool = NULL;
2781 }
2782
2783 return 0;
2784}
David Lopoaa69a802008-11-17 14:14:51 -08002785
2786/******************************************************************************
2787 * BUS block
2788 *****************************************************************************/
2789/**
2790 * udc_irq: global interrupt handler
2791 *
2792 * This function returns IRQ_HANDLED if the IRQ has been handled
2793 * It locks access to registers
2794 */
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03002795static irqreturn_t udc_irq(int irq, void *data)
David Lopoaa69a802008-11-17 14:14:51 -08002796{
2797 struct ci13xxx *udc = _udc;
2798 irqreturn_t retval;
2799 u32 intr;
2800
Alexander Shishkin0f089092012-05-08 23:29:02 +03002801 trace(udc ? udc->dev : NULL, "");
David Lopoaa69a802008-11-17 14:14:51 -08002802
2803 if (udc == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03002804 dev_err(udc->dev, "ENODEV");
David Lopoaa69a802008-11-17 14:14:51 -08002805 return IRQ_HANDLED;
2806 }
2807
Alexander Shishkind3595d12012-05-08 23:28:58 +03002808 spin_lock(&udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302809
2810 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) {
Alexander Shishkin262c1632012-05-08 23:28:59 +03002811 if (hw_read(udc, OP_USBMODE, USBMODE_CM) !=
2812 USBMODE_CM_DEVICE) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03002813 spin_unlock(&udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302814 return IRQ_NONE;
2815 }
2816 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03002817 intr = hw_test_and_clear_intr_active(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002818 if (intr) {
2819 isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intr;
2820 isr_statistics.hndl.idx &= ISR_MASK;
2821 isr_statistics.hndl.cnt++;
2822
2823 /* order defines priority - do NOT change it */
2824 if (USBi_URI & intr) {
2825 isr_statistics.uri++;
2826 isr_reset_handler(udc);
2827 }
2828 if (USBi_PCI & intr) {
2829 isr_statistics.pci++;
Alexander Shishkind3595d12012-05-08 23:28:58 +03002830 udc->gadget.speed = hw_port_is_high_speed(udc) ?
David Lopoaa69a802008-11-17 14:14:51 -08002831 USB_SPEED_HIGH : USB_SPEED_FULL;
Marc Kleine-Budde7bb4fdc2011-10-10 18:38:09 +02002832 if (udc->suspended && udc->driver->resume) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03002833 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302834 udc->driver->resume(&udc->gadget);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002835 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302836 udc->suspended = 0;
2837 }
David Lopoaa69a802008-11-17 14:14:51 -08002838 }
2839 if (USBi_UEI & intr)
2840 isr_statistics.uei++;
2841 if (USBi_UI & intr) {
2842 isr_statistics.ui++;
2843 isr_tr_complete_handler(udc);
2844 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302845 if (USBi_SLI & intr) {
Marc Kleine-Budde7bb4fdc2011-10-10 18:38:09 +02002846 if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
2847 udc->driver->suspend) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302848 udc->suspended = 1;
Alexander Shishkind3595d12012-05-08 23:28:58 +03002849 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302850 udc->driver->suspend(&udc->gadget);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002851 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302852 }
David Lopoaa69a802008-11-17 14:14:51 -08002853 isr_statistics.sli++;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302854 }
David Lopoaa69a802008-11-17 14:14:51 -08002855 retval = IRQ_HANDLED;
2856 } else {
2857 isr_statistics.none++;
2858 retval = IRQ_NONE;
2859 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03002860 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08002861
2862 return retval;
2863}
2864
2865/**
2866 * udc_release: driver release function
2867 * @dev: device
2868 *
2869 * Currently does nothing
2870 */
2871static void udc_release(struct device *dev)
2872{
Alexander Shishkin0f089092012-05-08 23:29:02 +03002873 trace(dev->parent, "%p", dev);
David Lopoaa69a802008-11-17 14:14:51 -08002874}
2875
2876/**
2877 * udc_probe: parent probe must call this to initialize UDC
2878 * @dev: parent device
2879 * @regs: registers base address
2880 * @name: driver name
2881 *
2882 * This function returns an error code
2883 * No interrupts active, the IRQ has not been requested yet
2884 * Kernel assumes 32-bit DMA operations by default, no need to dma_set_mask
2885 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302886static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03002887 void __iomem *regs)
David Lopoaa69a802008-11-17 14:14:51 -08002888{
2889 struct ci13xxx *udc;
2890 int retval = 0;
2891
Alexander Shishkin0f089092012-05-08 23:29:02 +03002892 trace(dev, "%p, %p, %p", dev, regs, driver->name);
David Lopoaa69a802008-11-17 14:14:51 -08002893
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302894 if (dev == NULL || regs == NULL || driver == NULL ||
2895 driver->name == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002896 return -EINVAL;
2897
2898 udc = kzalloc(sizeof(struct ci13xxx), GFP_KERNEL);
2899 if (udc == NULL)
2900 return -ENOMEM;
2901
Alexander Shishkind3595d12012-05-08 23:28:58 +03002902 spin_lock_init(&udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302903 udc->regs = regs;
2904 udc->udc_driver = driver;
David Lopoaa69a802008-11-17 14:14:51 -08002905
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302906 udc->gadget.ops = &usb_gadget_ops;
David Lopoaa69a802008-11-17 14:14:51 -08002907 udc->gadget.speed = USB_SPEED_UNKNOWN;
Michal Nazarewiczd327ab52011-11-19 18:27:37 +01002908 udc->gadget.max_speed = USB_SPEED_HIGH;
David Lopoaa69a802008-11-17 14:14:51 -08002909 udc->gadget.is_otg = 0;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302910 udc->gadget.name = driver->name;
David Lopoaa69a802008-11-17 14:14:51 -08002911
2912 INIT_LIST_HEAD(&udc->gadget.ep_list);
2913 udc->gadget.ep0 = NULL;
2914
Kay Sievers5df585242009-03-24 16:38:23 -07002915 dev_set_name(&udc->gadget.dev, "gadget");
David Lopoaa69a802008-11-17 14:14:51 -08002916 udc->gadget.dev.dma_mask = dev->dma_mask;
Pavankumar Kondeti61948ee2010-12-07 17:54:01 +05302917 udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
David Lopoaa69a802008-11-17 14:14:51 -08002918 udc->gadget.dev.parent = dev;
2919 udc->gadget.dev.release = udc_release;
2920
Alexander Shishkin0f089092012-05-08 23:29:02 +03002921 udc->dev = dev;
2922
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03002923 retval = hw_device_init(udc, regs, driver->capoffset);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302924 if (retval < 0)
2925 goto free_udc;
2926
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002927 udc->transceiver = usb_get_transceiver();
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302928
2929 if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
2930 if (udc->transceiver == NULL) {
2931 retval = -ENODEV;
2932 goto free_udc;
2933 }
2934 }
2935
2936 if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) {
2937 retval = hw_device_reset(udc);
2938 if (retval)
2939 goto put_transceiver;
2940 }
2941
David Lopoaa69a802008-11-17 14:14:51 -08002942 retval = device_register(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302943 if (retval) {
2944 put_device(&udc->gadget.dev);
2945 goto put_transceiver;
2946 }
David Lopoaa69a802008-11-17 14:14:51 -08002947
2948#ifdef CONFIG_USB_GADGET_DEBUG_FILES
2949 retval = dbg_create_files(&udc->gadget.dev);
2950#endif
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302951 if (retval)
2952 goto unreg_device;
2953
2954 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02002955 retval = otg_set_peripheral(udc->transceiver->otg,
2956 &udc->gadget);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302957 if (retval)
2958 goto remove_dbg;
David Lopoaa69a802008-11-17 14:14:51 -08002959 }
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002960
2961 retval = usb_add_gadget_udc(dev, &udc->gadget);
2962 if (retval)
2963 goto remove_trans;
2964
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302965 pm_runtime_no_callbacks(&udc->gadget.dev);
2966 pm_runtime_enable(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08002967
2968 _udc = udc;
2969 return retval;
2970
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002971remove_trans:
2972 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02002973 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002974 usb_put_transceiver(udc->transceiver);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002975 }
2976
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07002977 dev_err(dev, "error = %i\n", retval);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302978remove_dbg:
2979#ifdef CONFIG_USB_GADGET_DEBUG_FILES
2980 dbg_remove_files(&udc->gadget.dev);
2981#endif
2982unreg_device:
2983 device_unregister(&udc->gadget.dev);
2984put_transceiver:
2985 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002986 usb_put_transceiver(udc->transceiver);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302987free_udc:
David Lopoaa69a802008-11-17 14:14:51 -08002988 kfree(udc);
2989 _udc = NULL;
2990 return retval;
2991}
2992
2993/**
2994 * udc_remove: parent remove must call this to remove UDC
2995 *
2996 * No interrupts active, the IRQ has been released
2997 */
2998static void udc_remove(void)
2999{
3000 struct ci13xxx *udc = _udc;
3001
Alexander Shishkin0f089092012-05-08 23:29:02 +03003002 if (udc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08003003 return;
Alexander Shishkin0f089092012-05-08 23:29:02 +03003004
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03003005 usb_del_gadget_udc(&udc->gadget);
David Lopoaa69a802008-11-17 14:14:51 -08003006
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303007 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02003008 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02003009 usb_put_transceiver(udc->transceiver);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05303010 }
David Lopoaa69a802008-11-17 14:14:51 -08003011#ifdef CONFIG_USB_GADGET_DEBUG_FILES
3012 dbg_remove_files(&udc->gadget.dev);
3013#endif
3014 device_unregister(&udc->gadget.dev);
3015
Alexander Shishkin262c1632012-05-08 23:28:59 +03003016 kfree(udc->hw_bank.regmap);
David Lopoaa69a802008-11-17 14:14:51 -08003017 kfree(udc);
3018 _udc = NULL;
3019}
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03003020
3021static int __devinit ci_udc_probe(struct platform_device *pdev)
3022{
3023 struct device *dev = &pdev->dev;
3024 struct ci13xxx_udc_driver *driver = dev->platform_data;
3025 struct resource *res;
3026 void __iomem *base;
3027 int ret;
3028
3029 if (!driver) {
3030 dev_err(dev, "platform data missing\n");
3031 return -ENODEV;
3032 }
3033
3034 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3035 if (!res) {
3036 dev_err(dev, "missing resource\n");
3037 return -ENODEV;
3038 }
3039
3040 base = devm_request_and_ioremap(dev, res);
3041 if (!res) {
3042 dev_err(dev, "can't request and ioremap resource\n");
3043 return -ENOMEM;
3044 }
3045
3046 ret = udc_probe(driver, dev, base);
3047 if (ret)
3048 return ret;
3049
3050 _udc->irq = platform_get_irq(pdev, 0);
3051 if (_udc->irq < 0) {
3052 dev_err(dev, "missing IRQ\n");
3053 ret = -ENODEV;
3054 goto out;
3055 }
3056
3057 ret = request_irq(_udc->irq, udc_irq, IRQF_SHARED, driver->name, _udc);
3058
3059out:
3060 if (ret)
3061 udc_remove();
3062
3063 return ret;
3064}
3065
3066static int __devexit ci_udc_remove(struct platform_device *pdev)
3067{
3068 free_irq(_udc->irq, _udc);
3069 udc_remove();
3070
3071 return 0;
3072}
3073
3074static struct platform_driver ci_udc_driver = {
3075 .probe = ci_udc_probe,
3076 .remove = __devexit_p(ci_udc_remove),
3077 .driver = {
3078 .name = "ci_udc",
3079 },
3080};
3081
3082module_platform_driver(ci_udc_driver);
3083
3084MODULE_ALIAS("platform:ci_udc");
3085MODULE_ALIAS("platform:ci13xxx");
3086MODULE_LICENSE("GPL v2");
3087MODULE_AUTHOR("David Lopo <dlopo@chipidea.mips.com>");
3088MODULE_DESCRIPTION("ChipIdea UDC Driver");