blob: 560b539b9def037378c0405442a1fc69b21e0d76 [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
David Lopoaa69a802008-11-17 14:14:51 -080099/* Interrupt statistics */
100#define ISR_MASK 0x1F
101static struct {
102 u32 test;
103 u32 ui;
104 u32 uei;
105 u32 pci;
106 u32 uri;
107 u32 sli;
108 u32 none;
109 struct {
110 u32 cnt;
111 u32 buf[ISR_MASK+1];
112 u32 idx;
113 } hndl;
114} isr_statistics;
115
116/**
117 * ffs_nr: find first (least significant) bit set
118 * @x: the word to search
119 *
120 * This function returns bit number (instead of position)
121 */
122static int ffs_nr(u32 x)
123{
124 int n = ffs(x);
125
126 return n ? n-1 : 32;
127}
128
129/******************************************************************************
130 * HW block
131 *****************************************************************************/
David Lopoaa69a802008-11-17 14:14:51 -0800132
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530133/* MSM specific */
134#define ABS_AHBBURST (0x0090UL)
135#define ABS_AHBMODE (0x0098UL)
David Lopoaa69a802008-11-17 14:14:51 -0800136/* UDC register map */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300137static uintptr_t ci_regs_nolpm[] = {
138 [CAP_CAPLENGTH] = 0x000UL,
139 [CAP_HCCPARAMS] = 0x008UL,
140 [CAP_DCCPARAMS] = 0x024UL,
141 [CAP_TESTMODE] = 0x038UL,
142 [OP_USBCMD] = 0x000UL,
143 [OP_USBSTS] = 0x004UL,
144 [OP_USBINTR] = 0x008UL,
145 [OP_DEVICEADDR] = 0x014UL,
146 [OP_ENDPTLISTADDR] = 0x018UL,
147 [OP_PORTSC] = 0x044UL,
148 [OP_DEVLC] = 0x084UL,
149 [OP_USBMODE] = 0x068UL,
150 [OP_ENDPTSETUPSTAT] = 0x06CUL,
151 [OP_ENDPTPRIME] = 0x070UL,
152 [OP_ENDPTFLUSH] = 0x074UL,
153 [OP_ENDPTSTAT] = 0x078UL,
154 [OP_ENDPTCOMPLETE] = 0x07CUL,
155 [OP_ENDPTCTRL] = 0x080UL,
156};
157
158static uintptr_t ci_regs_lpm[] = {
159 [CAP_CAPLENGTH] = 0x000UL,
160 [CAP_HCCPARAMS] = 0x008UL,
161 [CAP_DCCPARAMS] = 0x024UL,
162 [CAP_TESTMODE] = 0x0FCUL,
163 [OP_USBCMD] = 0x000UL,
164 [OP_USBSTS] = 0x004UL,
165 [OP_USBINTR] = 0x008UL,
166 [OP_DEVICEADDR] = 0x014UL,
167 [OP_ENDPTLISTADDR] = 0x018UL,
168 [OP_PORTSC] = 0x044UL,
169 [OP_DEVLC] = 0x084UL,
170 [OP_USBMODE] = 0x0C8UL,
171 [OP_ENDPTSETUPSTAT] = 0x0D8UL,
172 [OP_ENDPTPRIME] = 0x0DCUL,
173 [OP_ENDPTFLUSH] = 0x0E0UL,
174 [OP_ENDPTSTAT] = 0x0E4UL,
175 [OP_ENDPTCOMPLETE] = 0x0E8UL,
176 [OP_ENDPTCTRL] = 0x0ECUL,
177};
178
179static int hw_alloc_regmap(struct ci13xxx *udc, bool is_lpm)
180{
181 int i;
182
183 kfree(udc->hw_bank.regmap);
184
185 udc->hw_bank.regmap = kzalloc((OP_LAST + 1) * sizeof(void *),
186 GFP_KERNEL);
187 if (!udc->hw_bank.regmap)
188 return -ENOMEM;
189
190 for (i = 0; i < OP_ENDPTCTRL; i++)
191 udc->hw_bank.regmap[i] =
192 (i <= CAP_LAST ? udc->hw_bank.cap : udc->hw_bank.op) +
193 (is_lpm ? ci_regs_lpm[i] : ci_regs_nolpm[i]);
194
195 for (; i <= OP_LAST; i++)
196 udc->hw_bank.regmap[i] = udc->hw_bank.op +
197 4 * (i - OP_ENDPTCTRL) +
198 (is_lpm
199 ? ci_regs_lpm[OP_ENDPTCTRL]
200 : ci_regs_nolpm[OP_ENDPTCTRL]);
201
202 return 0;
203}
David Lopoaa69a802008-11-17 14:14:51 -0800204
205/**
206 * hw_ep_bit: calculates the bit number
207 * @num: endpoint number
208 * @dir: endpoint direction
209 *
210 * This function returns bit number
211 */
212static inline int hw_ep_bit(int num, int dir)
213{
214 return num + (dir ? 16 : 0);
215}
216
Alexander Shishkind3595d12012-05-08 23:28:58 +0300217static int ep_to_bit(struct ci13xxx *udc, int n)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200218{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300219 int fill = 16 - udc->hw_ep_max / 2;
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200220
Alexander Shishkind3595d12012-05-08 23:28:58 +0300221 if (n >= udc->hw_ep_max / 2)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200222 n += fill;
223
224 return n;
225}
226
David Lopoaa69a802008-11-17 14:14:51 -0800227/**
Alexander Shishkin262c1632012-05-08 23:28:59 +0300228 * hw_read: reads from a hw register
229 * @reg: register index
David Lopoaa69a802008-11-17 14:14:51 -0800230 * @mask: bitfield mask
231 *
Alexander Shishkin262c1632012-05-08 23:28:59 +0300232 * This function returns register contents
David Lopoaa69a802008-11-17 14:14:51 -0800233 */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300234static u32 hw_read(struct ci13xxx *udc, enum ci13xxx_regs reg, u32 mask)
David Lopoaa69a802008-11-17 14:14:51 -0800235{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300236 return ioread32(udc->hw_bank.regmap[reg]) & mask;
David Lopoaa69a802008-11-17 14:14:51 -0800237}
238
239/**
Alexander Shishkin262c1632012-05-08 23:28:59 +0300240 * hw_write: writes to a hw register
241 * @reg: register index
David Lopoaa69a802008-11-17 14:14:51 -0800242 * @mask: bitfield mask
Alexander Shishkin262c1632012-05-08 23:28:59 +0300243 * @data: new value
David Lopoaa69a802008-11-17 14:14:51 -0800244 */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300245static void hw_write(struct ci13xxx *udc, enum ci13xxx_regs reg, u32 mask,
246 u32 data)
David Lopoaa69a802008-11-17 14:14:51 -0800247{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300248 if (~mask)
249 data = (ioread32(udc->hw_bank.regmap[reg]) & ~mask)
250 | (data & mask);
251
252 iowrite32(data, udc->hw_bank.regmap[reg]);
David Lopoaa69a802008-11-17 14:14:51 -0800253}
254
255/**
Alexander Shishkin262c1632012-05-08 23:28:59 +0300256 * hw_test_and_clear: tests & clears a hw register
257 * @reg: register index
David Lopoaa69a802008-11-17 14:14:51 -0800258 * @mask: bitfield mask
259 *
Alexander Shishkin262c1632012-05-08 23:28:59 +0300260 * This function returns register contents
David Lopoaa69a802008-11-17 14:14:51 -0800261 */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300262static u32 hw_test_and_clear(struct ci13xxx *udc, enum ci13xxx_regs reg,
263 u32 mask)
David Lopoaa69a802008-11-17 14:14:51 -0800264{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300265 u32 val = ioread32(udc->hw_bank.regmap[reg]) & mask;
David Lopoaa69a802008-11-17 14:14:51 -0800266
Alexander Shishkin262c1632012-05-08 23:28:59 +0300267 iowrite32(val, udc->hw_bank.regmap[reg]);
268 return val;
David Lopoaa69a802008-11-17 14:14:51 -0800269}
270
271/**
Alexander Shishkin262c1632012-05-08 23:28:59 +0300272 * hw_test_and_write: tests & writes a hw register
273 * @reg: register index
David Lopoaa69a802008-11-17 14:14:51 -0800274 * @mask: bitfield mask
Alexander Shishkin262c1632012-05-08 23:28:59 +0300275 * @data: new value
David Lopoaa69a802008-11-17 14:14:51 -0800276 *
Alexander Shishkin262c1632012-05-08 23:28:59 +0300277 * This function returns register contents
David Lopoaa69a802008-11-17 14:14:51 -0800278 */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300279static u32 hw_test_and_write(struct ci13xxx *udc, enum ci13xxx_regs reg,
280 u32 mask, u32 data)
David Lopoaa69a802008-11-17 14:14:51 -0800281{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300282 u32 val = hw_read(udc, reg, ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800283
Alexander Shishkin262c1632012-05-08 23:28:59 +0300284 hw_write(udc, reg, mask, data);
285 return (val & mask) >> ffs_nr(mask);
David Lopoaa69a802008-11-17 14:14:51 -0800286}
287
Alexander Shishkind3595d12012-05-08 23:28:58 +0300288static int hw_device_init(struct ci13xxx *udc, void __iomem *base,
289 uintptr_t cap_offset)
David Lopoaa69a802008-11-17 14:14:51 -0800290{
291 u32 reg;
292
293 /* bank is a module variable */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300294 udc->hw_bank.abs = base;
David Lopoaa69a802008-11-17 14:14:51 -0800295
Alexander Shishkind3595d12012-05-08 23:28:58 +0300296 udc->hw_bank.cap = udc->hw_bank.abs;
297 udc->hw_bank.cap += cap_offset;
298 udc->hw_bank.op = udc->hw_bank.cap + ioread8(udc->hw_bank.cap);
David Lopoaa69a802008-11-17 14:14:51 -0800299
Alexander Shishkin262c1632012-05-08 23:28:59 +0300300 hw_alloc_regmap(udc, false);
301 reg = hw_read(udc, CAP_HCCPARAMS, HCCPARAMS_LEN) >>
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300302 ffs_nr(HCCPARAMS_LEN);
Alexander Shishkind3595d12012-05-08 23:28:58 +0300303 udc->hw_bank.lpm = reg;
Alexander Shishkin262c1632012-05-08 23:28:59 +0300304 hw_alloc_regmap(udc, !!reg);
Alexander Shishkind3595d12012-05-08 23:28:58 +0300305 udc->hw_bank.size = udc->hw_bank.op - udc->hw_bank.abs;
306 udc->hw_bank.size += OP_LAST;
307 udc->hw_bank.size /= sizeof(u32);
David Lopoaa69a802008-11-17 14:14:51 -0800308
Alexander Shishkin262c1632012-05-08 23:28:59 +0300309 reg = hw_read(udc, CAP_DCCPARAMS, DCCPARAMS_DEN) >>
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300310 ffs_nr(DCCPARAMS_DEN);
Alexander Shishkind3595d12012-05-08 23:28:58 +0300311 udc->hw_ep_max = reg * 2; /* cache hw ENDPT_MAX */
David Lopoaa69a802008-11-17 14:14:51 -0800312
Alexander Shishkind3595d12012-05-08 23:28:58 +0300313 if (udc->hw_ep_max == 0 || udc->hw_ep_max > ENDPT_MAX)
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530314 return -ENODEV;
David Lopoaa69a802008-11-17 14:14:51 -0800315
316 /* setup lock mode ? */
317
318 /* ENDPTSETUPSTAT is '0' by default */
319
320 /* HCSPARAMS.bf.ppc SHOULD BE zero for device */
321
322 return 0;
323}
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530324/**
325 * hw_device_reset: resets chip (execute without interruption)
326 * @base: register base address
327 *
328 * This function returns an error code
329 */
330static int hw_device_reset(struct ci13xxx *udc)
331{
332 /* should flush & stop before reset */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300333 hw_write(udc, OP_ENDPTFLUSH, ~0, ~0);
334 hw_write(udc, OP_USBCMD, USBCMD_RS, 0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530335
Alexander Shishkin262c1632012-05-08 23:28:59 +0300336 hw_write(udc, OP_USBCMD, USBCMD_RST, USBCMD_RST);
337 while (hw_read(udc, OP_USBCMD, USBCMD_RST))
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530338 udelay(10); /* not RTOS friendly */
339
340
341 if (udc->udc_driver->notify_event)
342 udc->udc_driver->notify_event(udc,
343 CI13XXX_CONTROLLER_RESET_EVENT);
344
Pavankumar Kondeti8c2387a2011-05-02 11:56:28 +0530345 if (udc->udc_driver->flags & CI13XXX_DISABLE_STREAMING)
Alexander Shishkin262c1632012-05-08 23:28:59 +0300346 hw_write(udc, OP_USBMODE, USBMODE_SDIS, USBMODE_SDIS);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530347
348 /* USBMODE should be configured step by step */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300349 hw_write(udc, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
350 hw_write(udc, OP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE);
Alexander Shishkinf9df8392012-05-04 16:47:16 +0300351 /* HW >= 2.3 */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300352 hw_write(udc, OP_USBMODE, USBMODE_SLOM, USBMODE_SLOM);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530353
Alexander Shishkin262c1632012-05-08 23:28:59 +0300354 if (hw_read(udc, OP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530355 pr_err("cannot enter in device mode");
Alexander Shishkind3595d12012-05-08 23:28:58 +0300356 pr_err("lpm = %i", udc->hw_bank.lpm);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +0530357 return -ENODEV;
358 }
359
360 return 0;
361}
David Lopoaa69a802008-11-17 14:14:51 -0800362
363/**
364 * hw_device_state: enables/disables interrupts & starts/stops device (execute
365 * without interruption)
366 * @dma: 0 => disable, !0 => enable and set dma engine
367 *
368 * This function returns an error code
369 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300370static int hw_device_state(struct ci13xxx *udc, u32 dma)
David Lopoaa69a802008-11-17 14:14:51 -0800371{
372 if (dma) {
Alexander Shishkin262c1632012-05-08 23:28:59 +0300373 hw_write(udc, OP_ENDPTLISTADDR, ~0, dma);
David Lopoaa69a802008-11-17 14:14:51 -0800374 /* interrupt, error, port change, reset, sleep/suspend */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300375 hw_write(udc, OP_USBINTR, ~0,
David Lopoaa69a802008-11-17 14:14:51 -0800376 USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
Alexander Shishkin262c1632012-05-08 23:28:59 +0300377 hw_write(udc, OP_USBCMD, USBCMD_RS, USBCMD_RS);
David Lopoaa69a802008-11-17 14:14:51 -0800378 } else {
Alexander Shishkin262c1632012-05-08 23:28:59 +0300379 hw_write(udc, OP_USBCMD, USBCMD_RS, 0);
380 hw_write(udc, OP_USBINTR, ~0, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800381 }
382 return 0;
383}
384
385/**
386 * hw_ep_flush: flush endpoint fifo (execute without interruption)
387 * @num: endpoint number
388 * @dir: endpoint direction
389 *
390 * This function returns an error code
391 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300392static int hw_ep_flush(struct ci13xxx *udc, int num, int dir)
David Lopoaa69a802008-11-17 14:14:51 -0800393{
394 int n = hw_ep_bit(num, dir);
395
396 do {
397 /* flush any pending transfer */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300398 hw_write(udc, OP_ENDPTFLUSH, BIT(n), BIT(n));
399 while (hw_read(udc, OP_ENDPTFLUSH, BIT(n)))
David Lopoaa69a802008-11-17 14:14:51 -0800400 cpu_relax();
Alexander Shishkin262c1632012-05-08 23:28:59 +0300401 } while (hw_read(udc, OP_ENDPTSTAT, BIT(n)));
David Lopoaa69a802008-11-17 14:14:51 -0800402
403 return 0;
404}
405
406/**
407 * hw_ep_disable: disables endpoint (execute without interruption)
408 * @num: endpoint number
409 * @dir: endpoint direction
410 *
411 * This function returns an error code
412 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300413static int hw_ep_disable(struct ci13xxx *udc, int num, int dir)
David Lopoaa69a802008-11-17 14:14:51 -0800414{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300415 hw_ep_flush(udc, num, dir);
Alexander Shishkin262c1632012-05-08 23:28:59 +0300416 hw_write(udc, OP_ENDPTCTRL + num,
Alexander Shishkind3595d12012-05-08 23:28:58 +0300417 dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800418 return 0;
419}
420
421/**
422 * hw_ep_enable: enables endpoint (execute without interruption)
423 * @num: endpoint number
424 * @dir: endpoint direction
425 * @type: endpoint type
426 *
427 * This function returns an error code
428 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300429static int hw_ep_enable(struct ci13xxx *udc, int num, int dir, int type)
David Lopoaa69a802008-11-17 14:14:51 -0800430{
431 u32 mask, data;
432
433 if (dir) {
434 mask = ENDPTCTRL_TXT; /* type */
435 data = type << ffs_nr(mask);
436
437 mask |= ENDPTCTRL_TXS; /* unstall */
438 mask |= ENDPTCTRL_TXR; /* reset data toggle */
439 data |= ENDPTCTRL_TXR;
440 mask |= ENDPTCTRL_TXE; /* enable */
441 data |= ENDPTCTRL_TXE;
442 } else {
443 mask = ENDPTCTRL_RXT; /* type */
444 data = type << ffs_nr(mask);
445
446 mask |= ENDPTCTRL_RXS; /* unstall */
447 mask |= ENDPTCTRL_RXR; /* reset data toggle */
448 data |= ENDPTCTRL_RXR;
449 mask |= ENDPTCTRL_RXE; /* enable */
450 data |= ENDPTCTRL_RXE;
451 }
Alexander Shishkin262c1632012-05-08 23:28:59 +0300452 hw_write(udc, OP_ENDPTCTRL + num, mask, data);
David Lopoaa69a802008-11-17 14:14:51 -0800453 return 0;
454}
455
456/**
457 * hw_ep_get_halt: return endpoint halt status
458 * @num: endpoint number
459 * @dir: endpoint direction
460 *
461 * This function returns 1 if endpoint halted
462 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300463static int hw_ep_get_halt(struct ci13xxx *udc, int num, int dir)
David Lopoaa69a802008-11-17 14:14:51 -0800464{
465 u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
466
Alexander Shishkin262c1632012-05-08 23:28:59 +0300467 return hw_read(udc, OP_ENDPTCTRL + num, mask) ? 1 : 0;
David Lopoaa69a802008-11-17 14:14:51 -0800468}
469
470/**
David Lopoaa69a802008-11-17 14:14:51 -0800471 * hw_test_and_clear_setup_status: test & clear setup status (execute without
472 * interruption)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200473 * @n: endpoint number
David Lopoaa69a802008-11-17 14:14:51 -0800474 *
475 * This function returns setup status
476 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300477static int hw_test_and_clear_setup_status(struct ci13xxx *udc, int n)
David Lopoaa69a802008-11-17 14:14:51 -0800478{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300479 n = ep_to_bit(udc, n);
Alexander Shishkin262c1632012-05-08 23:28:59 +0300480 return hw_test_and_clear(udc, OP_ENDPTSETUPSTAT, BIT(n));
David Lopoaa69a802008-11-17 14:14:51 -0800481}
482
483/**
484 * hw_ep_prime: primes endpoint (execute without interruption)
485 * @num: endpoint number
486 * @dir: endpoint direction
487 * @is_ctrl: true if control endpoint
488 *
489 * This function returns an error code
490 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300491static int hw_ep_prime(struct ci13xxx *udc, int num, int dir, int is_ctrl)
David Lopoaa69a802008-11-17 14:14:51 -0800492{
493 int n = hw_ep_bit(num, dir);
494
Alexander Shishkin262c1632012-05-08 23:28:59 +0300495 if (is_ctrl && dir == RX && hw_read(udc, OP_ENDPTSETUPSTAT, BIT(num)))
David Lopoaa69a802008-11-17 14:14:51 -0800496 return -EAGAIN;
497
Alexander Shishkin262c1632012-05-08 23:28:59 +0300498 hw_write(udc, OP_ENDPTPRIME, BIT(n), BIT(n));
David Lopoaa69a802008-11-17 14:14:51 -0800499
Alexander Shishkin262c1632012-05-08 23:28:59 +0300500 while (hw_read(udc, OP_ENDPTPRIME, BIT(n)))
David Lopoaa69a802008-11-17 14:14:51 -0800501 cpu_relax();
Alexander Shishkin262c1632012-05-08 23:28:59 +0300502 if (is_ctrl && dir == RX && hw_read(udc, OP_ENDPTSETUPSTAT, BIT(num)))
David Lopoaa69a802008-11-17 14:14:51 -0800503 return -EAGAIN;
504
505 /* status shoult be tested according with manual but it doesn't work */
506 return 0;
507}
508
509/**
510 * hw_ep_set_halt: configures ep halt & resets data toggle after clear (execute
511 * without interruption)
512 * @num: endpoint number
513 * @dir: endpoint direction
514 * @value: true => stall, false => unstall
515 *
516 * This function returns an error code
517 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300518static int hw_ep_set_halt(struct ci13xxx *udc, int num, int dir, int value)
David Lopoaa69a802008-11-17 14:14:51 -0800519{
520 if (value != 0 && value != 1)
521 return -EINVAL;
522
523 do {
Alexander Shishkin262c1632012-05-08 23:28:59 +0300524 enum ci13xxx_regs reg = OP_ENDPTCTRL + num;
David Lopoaa69a802008-11-17 14:14:51 -0800525 u32 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
526 u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR;
527
528 /* data toggle - reserved for EP0 but it's in ESS */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300529 hw_write(udc, reg, mask_xs|mask_xr,
530 value ? mask_xs : mask_xr);
Alexander Shishkind3595d12012-05-08 23:28:58 +0300531 } while (value != hw_ep_get_halt(udc, num, dir));
David Lopoaa69a802008-11-17 14:14:51 -0800532
533 return 0;
534}
535
536/**
537 * hw_intr_clear: disables interrupt & clears interrupt status (execute without
538 * interruption)
539 * @n: interrupt bit
540 *
541 * This function returns an error code
542 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300543static int hw_intr_clear(struct ci13xxx *udc, int n)
David Lopoaa69a802008-11-17 14:14:51 -0800544{
545 if (n >= REG_BITS)
546 return -EINVAL;
547
Alexander Shishkin262c1632012-05-08 23:28:59 +0300548 hw_write(udc, OP_USBINTR, BIT(n), 0);
549 hw_write(udc, OP_USBSTS, BIT(n), BIT(n));
David Lopoaa69a802008-11-17 14:14:51 -0800550 return 0;
551}
552
553/**
554 * hw_intr_force: enables interrupt & forces interrupt status (execute without
555 * interruption)
556 * @n: interrupt bit
557 *
558 * This function returns an error code
559 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300560static int hw_intr_force(struct ci13xxx *udc, int n)
David Lopoaa69a802008-11-17 14:14:51 -0800561{
562 if (n >= REG_BITS)
563 return -EINVAL;
564
Alexander Shishkin262c1632012-05-08 23:28:59 +0300565 hw_write(udc, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
566 hw_write(udc, OP_USBINTR, BIT(n), BIT(n));
567 hw_write(udc, OP_USBSTS, BIT(n), BIT(n));
568 hw_write(udc, CAP_TESTMODE, TESTMODE_FORCE, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800569 return 0;
570}
571
572/**
573 * hw_is_port_high_speed: test if port is high speed
574 *
575 * This function returns true if high speed port
576 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300577static int hw_port_is_high_speed(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800578{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300579 return udc->hw_bank.lpm ? hw_read(udc, OP_DEVLC, DEVLC_PSPD) :
580 hw_read(udc, OP_PORTSC, PORTSC_HSP);
David Lopoaa69a802008-11-17 14:14:51 -0800581}
582
583/**
584 * hw_port_test_get: reads port test mode value
585 *
586 * This function returns port test mode value
587 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300588static u8 hw_port_test_get(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800589{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300590 return hw_read(udc, OP_PORTSC, PORTSC_PTC) >> ffs_nr(PORTSC_PTC);
David Lopoaa69a802008-11-17 14:14:51 -0800591}
592
593/**
594 * hw_port_test_set: writes port test mode (execute without interruption)
595 * @mode: new value
596 *
597 * This function returns an error code
598 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300599static int hw_port_test_set(struct ci13xxx *udc, u8 mode)
David Lopoaa69a802008-11-17 14:14:51 -0800600{
601 const u8 TEST_MODE_MAX = 7;
602
603 if (mode > TEST_MODE_MAX)
604 return -EINVAL;
605
Alexander Shishkin262c1632012-05-08 23:28:59 +0300606 hw_write(udc, OP_PORTSC, PORTSC_PTC, mode << ffs_nr(PORTSC_PTC));
David Lopoaa69a802008-11-17 14:14:51 -0800607 return 0;
608}
609
610/**
611 * hw_read_intr_enable: returns interrupt enable register
612 *
613 * This function returns register data
614 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300615static u32 hw_read_intr_enable(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800616{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300617 return hw_read(udc, OP_USBINTR, ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800618}
619
620/**
621 * hw_read_intr_status: returns interrupt status register
622 *
623 * This function returns register data
624 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300625static u32 hw_read_intr_status(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800626{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300627 return hw_read(udc, OP_USBSTS, ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800628}
629
630/**
631 * hw_register_read: reads all device registers (execute without interruption)
632 * @buf: destination buffer
633 * @size: buffer size
634 *
635 * This function returns number of registers read
636 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300637static size_t hw_register_read(struct ci13xxx *udc, u32 *buf, size_t size)
David Lopoaa69a802008-11-17 14:14:51 -0800638{
639 unsigned i;
640
Alexander Shishkind3595d12012-05-08 23:28:58 +0300641 if (size > udc->hw_bank.size)
642 size = udc->hw_bank.size;
David Lopoaa69a802008-11-17 14:14:51 -0800643
644 for (i = 0; i < size; i++)
Alexander Shishkin262c1632012-05-08 23:28:59 +0300645 buf[i] = hw_read(udc, i * sizeof(u32), ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800646
647 return size;
648}
649
650/**
651 * hw_register_write: writes to register
652 * @addr: register address
653 * @data: register value
654 *
655 * This function returns an error code
656 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300657static int hw_register_write(struct ci13xxx *udc, u16 addr, u32 data)
David Lopoaa69a802008-11-17 14:14:51 -0800658{
659 /* align */
660 addr /= sizeof(u32);
661
Alexander Shishkind3595d12012-05-08 23:28:58 +0300662 if (addr >= udc->hw_bank.size)
David Lopoaa69a802008-11-17 14:14:51 -0800663 return -EINVAL;
664
665 /* align */
666 addr *= sizeof(u32);
667
Alexander Shishkin262c1632012-05-08 23:28:59 +0300668 hw_write(udc, addr, ~0, data);
David Lopoaa69a802008-11-17 14:14:51 -0800669 return 0;
670}
671
672/**
673 * hw_test_and_clear_complete: test & clear complete status (execute without
674 * interruption)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200675 * @n: endpoint number
David Lopoaa69a802008-11-17 14:14:51 -0800676 *
677 * This function returns complete status
678 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300679static int hw_test_and_clear_complete(struct ci13xxx *udc, int n)
David Lopoaa69a802008-11-17 14:14:51 -0800680{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300681 n = ep_to_bit(udc, n);
Alexander Shishkin262c1632012-05-08 23:28:59 +0300682 return hw_test_and_clear(udc, OP_ENDPTCOMPLETE, BIT(n));
David Lopoaa69a802008-11-17 14:14:51 -0800683}
684
685/**
686 * hw_test_and_clear_intr_active: test & clear active interrupts (execute
687 * without interruption)
688 *
689 * This function returns active interrutps
690 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300691static u32 hw_test_and_clear_intr_active(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800692{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300693 u32 reg = hw_read_intr_status(udc) & hw_read_intr_enable(udc);
David Lopoaa69a802008-11-17 14:14:51 -0800694
Alexander Shishkin262c1632012-05-08 23:28:59 +0300695 hw_write(udc, OP_USBSTS, ~0, reg);
David Lopoaa69a802008-11-17 14:14:51 -0800696 return reg;
697}
698
699/**
700 * hw_test_and_clear_setup_guard: test & clear setup guard (execute without
701 * interruption)
702 *
703 * This function returns guard value
704 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300705static int hw_test_and_clear_setup_guard(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800706{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300707 return hw_test_and_write(udc, OP_USBCMD, USBCMD_SUTW, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800708}
709
710/**
711 * hw_test_and_set_setup_guard: test & set setup guard (execute without
712 * interruption)
713 *
714 * This function returns guard value
715 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300716static int hw_test_and_set_setup_guard(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800717{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300718 return hw_test_and_write(udc, OP_USBCMD, USBCMD_SUTW, USBCMD_SUTW);
David Lopoaa69a802008-11-17 14:14:51 -0800719}
720
721/**
722 * hw_usb_set_address: configures USB address (execute without interruption)
723 * @value: new USB address
724 *
725 * This function returns an error code
726 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300727static int hw_usb_set_address(struct ci13xxx *udc, u8 value)
David Lopoaa69a802008-11-17 14:14:51 -0800728{
729 /* advance */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300730 hw_write(udc, OP_DEVICEADDR, DEVICEADDR_USBADR | DEVICEADDR_USBADRA,
731 value << ffs_nr(DEVICEADDR_USBADR) | DEVICEADDR_USBADRA);
David Lopoaa69a802008-11-17 14:14:51 -0800732 return 0;
733}
734
735/**
736 * hw_usb_reset: restart device after a bus reset (execute without
737 * interruption)
738 *
739 * This function returns an error code
740 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300741static int hw_usb_reset(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800742{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300743 hw_usb_set_address(udc, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800744
745 /* ESS flushes only at end?!? */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300746 hw_write(udc, OP_ENDPTFLUSH, ~0, ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800747
748 /* clear setup token semaphores */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300749 hw_write(udc, OP_ENDPTSETUPSTAT, 0, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800750
751 /* clear complete status */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300752 hw_write(udc, OP_ENDPTCOMPLETE, 0, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800753
754 /* wait until all bits cleared */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300755 while (hw_read(udc, OP_ENDPTPRIME, ~0))
David Lopoaa69a802008-11-17 14:14:51 -0800756 udelay(10); /* not RTOS friendly */
757
758 /* reset all endpoints ? */
759
760 /* reset internal status and wait for further instructions
761 no need to verify the port reset status (ESS does it) */
762
763 return 0;
764}
765
766/******************************************************************************
767 * DBG block
768 *****************************************************************************/
769/**
770 * show_device: prints information about device capabilities and status
771 *
772 * Check "device.h" for details
773 */
774static ssize_t show_device(struct device *dev, struct device_attribute *attr,
775 char *buf)
776{
777 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
778 struct usb_gadget *gadget = &udc->gadget;
779 int n = 0;
780
Alexander Shishkin0f089092012-05-08 23:29:02 +0300781 trace(udc->dev, "%p\n", buf);
David Lopoaa69a802008-11-17 14:14:51 -0800782 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +0300783 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -0800784 return 0;
785 }
786
787 n += scnprintf(buf + n, PAGE_SIZE - n, "speed = %d\n",
788 gadget->speed);
Michal Nazarewiczd327ab52011-11-19 18:27:37 +0100789 n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed = %d\n",
790 gadget->max_speed);
791 /* TODO: Scheduled for removal in 3.8. */
David Lopoaa69a802008-11-17 14:14:51 -0800792 n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed = %d\n",
Michal Nazarewiczd327ab52011-11-19 18:27:37 +0100793 gadget_is_dualspeed(gadget));
David Lopoaa69a802008-11-17 14:14:51 -0800794 n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg = %d\n",
795 gadget->is_otg);
796 n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral = %d\n",
797 gadget->is_a_peripheral);
798 n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable = %d\n",
799 gadget->b_hnp_enable);
800 n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support = %d\n",
801 gadget->a_hnp_support);
802 n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n",
803 gadget->a_alt_hnp_support);
804 n += scnprintf(buf + n, PAGE_SIZE - n, "name = %s\n",
805 (gadget->name ? gadget->name : ""));
806
807 return n;
808}
809static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
810
811/**
812 * show_driver: prints information about attached gadget (if any)
813 *
814 * Check "device.h" for details
815 */
816static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
817 char *buf)
818{
819 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
820 struct usb_gadget_driver *driver = udc->driver;
821 int n = 0;
822
Alexander Shishkin0f089092012-05-08 23:29:02 +0300823 trace(udc->dev, "%p\n", buf);
David Lopoaa69a802008-11-17 14:14:51 -0800824 if (attr == NULL || buf == NULL) {
825 dev_err(dev, "[%s] EINVAL\n", __func__);
826 return 0;
827 }
828
829 if (driver == NULL)
830 return scnprintf(buf, PAGE_SIZE,
831 "There is no gadget attached!\n");
832
833 n += scnprintf(buf + n, PAGE_SIZE - n, "function = %s\n",
834 (driver->function ? driver->function : ""));
835 n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n",
Michal Nazarewicz7177aed2011-11-19 18:27:38 +0100836 driver->max_speed);
David Lopoaa69a802008-11-17 14:14:51 -0800837
838 return n;
839}
840static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL);
841
842/* Maximum event message length */
843#define DBG_DATA_MSG 64UL
844
845/* Maximum event messages */
846#define DBG_DATA_MAX 128UL
847
848/* Event buffer descriptor */
849static struct {
850 char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */
851 unsigned idx; /* index */
852 unsigned tty; /* print to console? */
853 rwlock_t lck; /* lock */
854} dbg_data = {
855 .idx = 0,
856 .tty = 0,
857 .lck = __RW_LOCK_UNLOCKED(lck)
858};
859
860/**
861 * dbg_dec: decrements debug event index
862 * @idx: buffer index
863 */
864static void dbg_dec(unsigned *idx)
865{
866 *idx = (*idx - 1) & (DBG_DATA_MAX-1);
867}
868
869/**
870 * dbg_inc: increments debug event index
871 * @idx: buffer index
872 */
873static void dbg_inc(unsigned *idx)
874{
875 *idx = (*idx + 1) & (DBG_DATA_MAX-1);
876}
877
878/**
879 * dbg_print: prints the common part of the event
880 * @addr: endpoint address
881 * @name: event name
882 * @status: status
883 * @extra: extra information
884 */
885static void dbg_print(u8 addr, const char *name, int status, const char *extra)
886{
887 struct timeval tval;
888 unsigned int stamp;
889 unsigned long flags;
890
891 write_lock_irqsave(&dbg_data.lck, flags);
892
893 do_gettimeofday(&tval);
894 stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s */
895 stamp = stamp * 1000000 + tval.tv_usec;
896
897 scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +0300898 "%04X\t? %02X %-7.7s %4i ?\t%s\n",
David Lopoaa69a802008-11-17 14:14:51 -0800899 stamp, addr, name, status, extra);
900
901 dbg_inc(&dbg_data.idx);
902
903 write_unlock_irqrestore(&dbg_data.lck, flags);
904
905 if (dbg_data.tty != 0)
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +0300906 pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n",
David Lopoaa69a802008-11-17 14:14:51 -0800907 stamp, addr, name, status, extra);
908}
909
910/**
911 * dbg_done: prints a DONE event
912 * @addr: endpoint address
913 * @td: transfer descriptor
914 * @status: status
915 */
916static void dbg_done(u8 addr, const u32 token, int status)
917{
918 char msg[DBG_DATA_MSG];
919
920 scnprintf(msg, sizeof(msg), "%d %02X",
921 (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES),
922 (int)(token & TD_STATUS) >> ffs_nr(TD_STATUS));
923 dbg_print(addr, "DONE", status, msg);
924}
925
926/**
927 * dbg_event: prints a generic event
928 * @addr: endpoint address
929 * @name: event name
930 * @status: status
931 */
932static void dbg_event(u8 addr, const char *name, int status)
933{
934 if (name != NULL)
935 dbg_print(addr, name, status, "");
936}
937
938/*
939 * dbg_queue: prints a QUEUE event
940 * @addr: endpoint address
941 * @req: USB request
942 * @status: status
943 */
944static void dbg_queue(u8 addr, const struct usb_request *req, int status)
945{
946 char msg[DBG_DATA_MSG];
947
948 if (req != NULL) {
949 scnprintf(msg, sizeof(msg),
950 "%d %d", !req->no_interrupt, req->length);
951 dbg_print(addr, "QUEUE", status, msg);
952 }
953}
954
955/**
956 * dbg_setup: prints a SETUP event
957 * @addr: endpoint address
958 * @req: setup request
959 */
960static void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
961{
962 char msg[DBG_DATA_MSG];
963
964 if (req != NULL) {
965 scnprintf(msg, sizeof(msg),
966 "%02X %02X %04X %04X %d", req->bRequestType,
967 req->bRequest, le16_to_cpu(req->wValue),
968 le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
969 dbg_print(addr, "SETUP", 0, msg);
970 }
971}
972
973/**
974 * show_events: displays the event buffer
975 *
976 * Check "device.h" for details
977 */
978static ssize_t show_events(struct device *dev, struct device_attribute *attr,
979 char *buf)
980{
981 unsigned long flags;
982 unsigned i, j, n = 0;
983
Alexander Shishkin0f089092012-05-08 23:29:02 +0300984 trace(dev->parent, "%p\n", buf);
David Lopoaa69a802008-11-17 14:14:51 -0800985 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +0300986 dev_err(dev->parent, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -0800987 return 0;
988 }
989
990 read_lock_irqsave(&dbg_data.lck, flags);
991
992 i = dbg_data.idx;
993 for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) {
994 n += strlen(dbg_data.buf[i]);
995 if (n >= PAGE_SIZE) {
996 n -= strlen(dbg_data.buf[i]);
997 break;
998 }
999 }
1000 for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i))
1001 j += scnprintf(buf + j, PAGE_SIZE - j,
1002 "%s", dbg_data.buf[i]);
1003
1004 read_unlock_irqrestore(&dbg_data.lck, flags);
1005
1006 return n;
1007}
1008
1009/**
1010 * store_events: configure if events are going to be also printed to console
1011 *
1012 * Check "device.h" for details
1013 */
1014static ssize_t store_events(struct device *dev, struct device_attribute *attr,
1015 const char *buf, size_t count)
1016{
1017 unsigned tty;
1018
Alexander Shishkin0f089092012-05-08 23:29:02 +03001019 trace(dev->parent, "[%s] %p, %d\n", __func__, buf, count);
David Lopoaa69a802008-11-17 14:14:51 -08001020 if (attr == NULL || buf == NULL) {
1021 dev_err(dev, "[%s] EINVAL\n", __func__);
1022 goto done;
1023 }
1024
1025 if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
1026 dev_err(dev, "<1|0>: enable|disable console log\n");
1027 goto done;
1028 }
1029
1030 dbg_data.tty = tty;
1031 dev_info(dev, "tty = %u", dbg_data.tty);
1032
1033 done:
1034 return count;
1035}
1036static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
1037
1038/**
1039 * show_inters: interrupt status, enable status and historic
1040 *
1041 * Check "device.h" for details
1042 */
1043static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
1044 char *buf)
1045{
1046 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1047 unsigned long flags;
1048 u32 intr;
1049 unsigned i, j, n = 0;
1050
Alexander Shishkin0f089092012-05-08 23:29:02 +03001051 trace(udc->dev, "%p\n", buf);
David Lopoaa69a802008-11-17 14:14:51 -08001052 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001053 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -08001054 return 0;
1055 }
1056
Alexander Shishkind3595d12012-05-08 23:28:58 +03001057 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001058
1059 n += scnprintf(buf + n, PAGE_SIZE - n,
Alexander Shishkind3595d12012-05-08 23:28:58 +03001060 "status = %08x\n", hw_read_intr_status(udc));
David Lopoaa69a802008-11-17 14:14:51 -08001061 n += scnprintf(buf + n, PAGE_SIZE - n,
Alexander Shishkind3595d12012-05-08 23:28:58 +03001062 "enable = %08x\n", hw_read_intr_enable(udc));
David Lopoaa69a802008-11-17 14:14:51 -08001063
1064 n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
1065 isr_statistics.test);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001066 n += scnprintf(buf + n, PAGE_SIZE - n, "? ui = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001067 isr_statistics.ui);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001068 n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001069 isr_statistics.uei);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001070 n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001071 isr_statistics.pci);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001072 n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001073 isr_statistics.uri);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001074 n += scnprintf(buf + n, PAGE_SIZE - n, "? sli = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001075 isr_statistics.sli);
1076 n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n",
1077 isr_statistics.none);
1078 n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n",
1079 isr_statistics.hndl.cnt);
1080
1081 for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) {
1082 i &= ISR_MASK;
1083 intr = isr_statistics.hndl.buf[i];
1084
1085 if (USBi_UI & intr)
1086 n += scnprintf(buf + n, PAGE_SIZE - n, "ui ");
1087 intr &= ~USBi_UI;
1088 if (USBi_UEI & intr)
1089 n += scnprintf(buf + n, PAGE_SIZE - n, "uei ");
1090 intr &= ~USBi_UEI;
1091 if (USBi_PCI & intr)
1092 n += scnprintf(buf + n, PAGE_SIZE - n, "pci ");
1093 intr &= ~USBi_PCI;
1094 if (USBi_URI & intr)
1095 n += scnprintf(buf + n, PAGE_SIZE - n, "uri ");
1096 intr &= ~USBi_URI;
1097 if (USBi_SLI & intr)
1098 n += scnprintf(buf + n, PAGE_SIZE - n, "sli ");
1099 intr &= ~USBi_SLI;
1100 if (intr)
1101 n += scnprintf(buf + n, PAGE_SIZE - n, "??? ");
1102 if (isr_statistics.hndl.buf[i])
1103 n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
1104 }
1105
Alexander Shishkind3595d12012-05-08 23:28:58 +03001106 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001107
1108 return n;
1109}
1110
1111/**
1112 * store_inters: enable & force or disable an individual interrutps
1113 * (to be used for test purposes only)
1114 *
1115 * Check "device.h" for details
1116 */
1117static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
1118 const char *buf, size_t count)
1119{
1120 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1121 unsigned long flags;
1122 unsigned en, bit;
1123
Alexander Shishkin0f089092012-05-08 23:29:02 +03001124 trace(udc->dev, "%p, %d\n", buf, count);
David Lopoaa69a802008-11-17 14:14:51 -08001125 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001126 dev_err(udc->dev, "EINVAL\n");
David Lopoaa69a802008-11-17 14:14:51 -08001127 goto done;
1128 }
1129
1130 if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001131 dev_err(udc->dev, "<1|0> <bit>: enable|disable interrupt\n");
David Lopoaa69a802008-11-17 14:14:51 -08001132 goto done;
1133 }
1134
Alexander Shishkind3595d12012-05-08 23:28:58 +03001135 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001136 if (en) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001137 if (hw_intr_force(udc, bit))
David Lopoaa69a802008-11-17 14:14:51 -08001138 dev_err(dev, "invalid bit number\n");
1139 else
1140 isr_statistics.test++;
1141 } else {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001142 if (hw_intr_clear(udc, bit))
David Lopoaa69a802008-11-17 14:14:51 -08001143 dev_err(dev, "invalid bit number\n");
1144 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03001145 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001146
1147 done:
1148 return count;
1149}
1150static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
1151
1152/**
1153 * show_port_test: reads port test mode
1154 *
1155 * Check "device.h" for details
1156 */
1157static ssize_t show_port_test(struct device *dev,
1158 struct device_attribute *attr, char *buf)
1159{
1160 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1161 unsigned long flags;
1162 unsigned mode;
1163
Alexander Shishkin0f089092012-05-08 23:29:02 +03001164 trace(udc->dev, "%p\n", buf);
David Lopoaa69a802008-11-17 14:14:51 -08001165 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001166 dev_err(udc->dev, "EINVAL\n");
David Lopoaa69a802008-11-17 14:14:51 -08001167 return 0;
1168 }
1169
Alexander Shishkind3595d12012-05-08 23:28:58 +03001170 spin_lock_irqsave(&udc->lock, flags);
1171 mode = hw_port_test_get(udc);
1172 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001173
1174 return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
1175}
1176
1177/**
1178 * store_port_test: writes port test mode
1179 *
1180 * Check "device.h" for details
1181 */
1182static ssize_t store_port_test(struct device *dev,
1183 struct device_attribute *attr,
1184 const char *buf, size_t count)
1185{
1186 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1187 unsigned long flags;
1188 unsigned mode;
1189
Alexander Shishkin0f089092012-05-08 23:29:02 +03001190 trace(udc->dev, "%p, %d\n", buf, count);
David Lopoaa69a802008-11-17 14:14:51 -08001191 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001192 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -08001193 goto done;
1194 }
1195
1196 if (sscanf(buf, "%u", &mode) != 1) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001197 dev_err(udc->dev, "<mode>: set port test mode");
David Lopoaa69a802008-11-17 14:14:51 -08001198 goto done;
1199 }
1200
Alexander Shishkind3595d12012-05-08 23:28:58 +03001201 spin_lock_irqsave(&udc->lock, flags);
1202 if (hw_port_test_set(udc, mode))
Alexander Shishkin0f089092012-05-08 23:29:02 +03001203 dev_err(udc->dev, "invalid mode\n");
Alexander Shishkind3595d12012-05-08 23:28:58 +03001204 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001205
1206 done:
1207 return count;
1208}
1209static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
1210 show_port_test, store_port_test);
1211
1212/**
1213 * show_qheads: DMA contents of all queue heads
1214 *
1215 * Check "device.h" for details
1216 */
1217static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
1218 char *buf)
1219{
1220 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1221 unsigned long flags;
1222 unsigned i, j, n = 0;
1223
Alexander Shishkin0f089092012-05-08 23:29:02 +03001224 trace(udc->dev, "%p\n", buf);
David Lopoaa69a802008-11-17 14:14:51 -08001225 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001226 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -08001227 return 0;
1228 }
1229
Alexander Shishkind3595d12012-05-08 23:28:58 +03001230 spin_lock_irqsave(&udc->lock, flags);
1231 for (i = 0; i < udc->hw_ep_max/2; i++) {
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301232 struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i];
Alexander Shishkind3595d12012-05-08 23:28:58 +03001233 struct ci13xxx_ep *mEpTx =
1234 &udc->ci13xxx_ep[i + udc->hw_ep_max/2];
David Lopoaa69a802008-11-17 14:14:51 -08001235 n += scnprintf(buf + n, PAGE_SIZE - n,
1236 "EP=%02i: RX=%08X TX=%08X\n",
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301237 i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08001238 for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) {
1239 n += scnprintf(buf + n, PAGE_SIZE - n,
1240 " %04X: %08X %08X\n", j,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301241 *((u32 *)mEpRx->qh.ptr + j),
1242 *((u32 *)mEpTx->qh.ptr + j));
David Lopoaa69a802008-11-17 14:14:51 -08001243 }
1244 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03001245 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001246
1247 return n;
1248}
1249static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
1250
1251/**
1252 * show_registers: dumps all registers
1253 *
1254 * Check "device.h" for details
1255 */
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001256#define DUMP_ENTRIES 512
David Lopoaa69a802008-11-17 14:14:51 -08001257static ssize_t show_registers(struct device *dev,
1258 struct device_attribute *attr, char *buf)
1259{
1260 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1261 unsigned long flags;
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001262 u32 *dump;
David Lopoaa69a802008-11-17 14:14:51 -08001263 unsigned i, k, n = 0;
1264
Alexander Shishkin0f089092012-05-08 23:29:02 +03001265 trace(udc->dev, "%p\n", buf);
David Lopoaa69a802008-11-17 14:14:51 -08001266 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001267 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -08001268 return 0;
1269 }
1270
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001271 dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
1272 if (!dump) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001273 dev_err(udc->dev, "%s: out of memory\n", __func__);
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001274 return 0;
1275 }
1276
Alexander Shishkind3595d12012-05-08 23:28:58 +03001277 spin_lock_irqsave(&udc->lock, flags);
1278 k = hw_register_read(udc, dump, DUMP_ENTRIES);
1279 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001280
1281 for (i = 0; i < k; i++) {
1282 n += scnprintf(buf + n, PAGE_SIZE - n,
1283 "reg[0x%04X] = 0x%08X\n",
1284 i * (unsigned)sizeof(u32), dump[i]);
1285 }
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001286 kfree(dump);
David Lopoaa69a802008-11-17 14:14:51 -08001287
1288 return n;
1289}
1290
1291/**
1292 * store_registers: writes value to register address
1293 *
1294 * Check "device.h" for details
1295 */
1296static ssize_t store_registers(struct device *dev,
1297 struct device_attribute *attr,
1298 const char *buf, size_t count)
1299{
1300 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1301 unsigned long addr, data, flags;
1302
Alexander Shishkin0f089092012-05-08 23:29:02 +03001303 trace(udc->dev, "%p, %d\n", buf, count);
David Lopoaa69a802008-11-17 14:14:51 -08001304 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001305 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -08001306 goto done;
1307 }
1308
1309 if (sscanf(buf, "%li %li", &addr, &data) != 2) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001310 dev_err(udc->dev,
1311 "<addr> <data>: write data to register address\n");
David Lopoaa69a802008-11-17 14:14:51 -08001312 goto done;
1313 }
1314
Alexander Shishkind3595d12012-05-08 23:28:58 +03001315 spin_lock_irqsave(&udc->lock, flags);
1316 if (hw_register_write(udc, addr, data))
Alexander Shishkin0f089092012-05-08 23:29:02 +03001317 dev_err(udc->dev, "invalid address range\n");
Alexander Shishkind3595d12012-05-08 23:28:58 +03001318 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001319
1320 done:
1321 return count;
1322}
1323static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
1324 show_registers, store_registers);
1325
1326/**
1327 * show_requests: DMA contents of all requests currently queued (all endpts)
1328 *
1329 * Check "device.h" for details
1330 */
1331static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
1332 char *buf)
1333{
1334 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1335 unsigned long flags;
1336 struct list_head *ptr = NULL;
1337 struct ci13xxx_req *req = NULL;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301338 unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
David Lopoaa69a802008-11-17 14:14:51 -08001339
Alexander Shishkin0f089092012-05-08 23:29:02 +03001340 trace(udc->dev, "%p\n", buf);
David Lopoaa69a802008-11-17 14:14:51 -08001341 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001342 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -08001343 return 0;
1344 }
1345
Alexander Shishkind3595d12012-05-08 23:28:58 +03001346 spin_lock_irqsave(&udc->lock, flags);
1347 for (i = 0; i < udc->hw_ep_max; i++)
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301348 list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue)
1349 {
1350 req = list_entry(ptr, struct ci13xxx_req, queue);
David Lopoaa69a802008-11-17 14:14:51 -08001351
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301352 n += scnprintf(buf + n, PAGE_SIZE - n,
1353 "EP=%02i: TD=%08X %s\n",
Alexander Shishkind3595d12012-05-08 23:28:58 +03001354 i % udc->hw_ep_max/2, (u32)req->dma,
1355 ((i < udc->hw_ep_max/2) ? "RX" : "TX"));
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301356
1357 for (j = 0; j < qSize; j++)
David Lopoaa69a802008-11-17 14:14:51 -08001358 n += scnprintf(buf + n, PAGE_SIZE - n,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301359 " %04X: %08X\n", j,
1360 *((u32 *)req->ptr + j));
1361 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03001362 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001363
1364 return n;
1365}
1366static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL);
1367
1368/**
1369 * dbg_create_files: initializes the attribute interface
1370 * @dev: device
1371 *
1372 * This function returns an error code
1373 */
1374__maybe_unused static int dbg_create_files(struct device *dev)
1375{
1376 int retval = 0;
1377
1378 if (dev == NULL)
1379 return -EINVAL;
1380 retval = device_create_file(dev, &dev_attr_device);
1381 if (retval)
1382 goto done;
1383 retval = device_create_file(dev, &dev_attr_driver);
1384 if (retval)
1385 goto rm_device;
1386 retval = device_create_file(dev, &dev_attr_events);
1387 if (retval)
1388 goto rm_driver;
1389 retval = device_create_file(dev, &dev_attr_inters);
1390 if (retval)
1391 goto rm_events;
1392 retval = device_create_file(dev, &dev_attr_port_test);
1393 if (retval)
1394 goto rm_inters;
1395 retval = device_create_file(dev, &dev_attr_qheads);
1396 if (retval)
1397 goto rm_port_test;
1398 retval = device_create_file(dev, &dev_attr_registers);
1399 if (retval)
1400 goto rm_qheads;
1401 retval = device_create_file(dev, &dev_attr_requests);
1402 if (retval)
1403 goto rm_registers;
1404 return 0;
1405
1406 rm_registers:
1407 device_remove_file(dev, &dev_attr_registers);
1408 rm_qheads:
1409 device_remove_file(dev, &dev_attr_qheads);
1410 rm_port_test:
1411 device_remove_file(dev, &dev_attr_port_test);
1412 rm_inters:
1413 device_remove_file(dev, &dev_attr_inters);
1414 rm_events:
1415 device_remove_file(dev, &dev_attr_events);
1416 rm_driver:
1417 device_remove_file(dev, &dev_attr_driver);
1418 rm_device:
1419 device_remove_file(dev, &dev_attr_device);
1420 done:
1421 return retval;
1422}
1423
1424/**
1425 * dbg_remove_files: destroys the attribute interface
1426 * @dev: device
1427 *
1428 * This function returns an error code
1429 */
1430__maybe_unused static int dbg_remove_files(struct device *dev)
1431{
1432 if (dev == NULL)
1433 return -EINVAL;
1434 device_remove_file(dev, &dev_attr_requests);
1435 device_remove_file(dev, &dev_attr_registers);
1436 device_remove_file(dev, &dev_attr_qheads);
1437 device_remove_file(dev, &dev_attr_port_test);
1438 device_remove_file(dev, &dev_attr_inters);
1439 device_remove_file(dev, &dev_attr_events);
1440 device_remove_file(dev, &dev_attr_driver);
1441 device_remove_file(dev, &dev_attr_device);
1442 return 0;
1443}
1444
1445/******************************************************************************
1446 * UTIL block
1447 *****************************************************************************/
1448/**
1449 * _usb_addr: calculates endpoint address from direction & number
1450 * @ep: endpoint
1451 */
1452static inline u8 _usb_addr(struct ci13xxx_ep *ep)
1453{
1454 return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num;
1455}
1456
1457/**
1458 * _hardware_queue: configures a request at hardware level
1459 * @gadget: gadget
1460 * @mEp: endpoint
1461 *
1462 * This function returns an error code
1463 */
1464static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1465{
Alexander Shishkind3595d12012-05-08 23:28:58 +03001466 struct ci13xxx *udc = mEp->udc;
David Lopoaa69a802008-11-17 14:14:51 -08001467 unsigned i;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301468 int ret = 0;
1469 unsigned length = mReq->req.length;
David Lopoaa69a802008-11-17 14:14:51 -08001470
Alexander Shishkin0f089092012-05-08 23:29:02 +03001471 trace(udc->dev, "%p, %p", mEp, mReq);
David Lopoaa69a802008-11-17 14:14:51 -08001472
1473 /* don't queue twice */
1474 if (mReq->req.status == -EALREADY)
1475 return -EALREADY;
1476
David Lopoaa69a802008-11-17 14:14:51 -08001477 mReq->req.status = -EALREADY;
Michael Grzeschik954aad82011-10-10 18:38:06 +02001478 if (length && mReq->req.dma == DMA_ADDR_INVALID) {
David Lopoaa69a802008-11-17 14:14:51 -08001479 mReq->req.dma = \
1480 dma_map_single(mEp->device, mReq->req.buf,
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301481 length, mEp->dir ? DMA_TO_DEVICE :
1482 DMA_FROM_DEVICE);
David Lopoaa69a802008-11-17 14:14:51 -08001483 if (mReq->req.dma == 0)
1484 return -ENOMEM;
1485
1486 mReq->map = 1;
1487 }
1488
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301489 if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) {
1490 mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC,
1491 &mReq->zdma);
1492 if (mReq->zptr == NULL) {
1493 if (mReq->map) {
1494 dma_unmap_single(mEp->device, mReq->req.dma,
1495 length, mEp->dir ? DMA_TO_DEVICE :
1496 DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02001497 mReq->req.dma = DMA_ADDR_INVALID;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301498 mReq->map = 0;
1499 }
1500 return -ENOMEM;
1501 }
1502 memset(mReq->zptr, 0, sizeof(*mReq->zptr));
1503 mReq->zptr->next = TD_TERMINATE;
1504 mReq->zptr->token = TD_STATUS_ACTIVE;
1505 if (!mReq->req.no_interrupt)
1506 mReq->zptr->token |= TD_IOC;
1507 }
David Lopoaa69a802008-11-17 14:14:51 -08001508 /*
1509 * TD configuration
1510 * TODO - handle requests which spawns into several TDs
1511 */
1512 memset(mReq->ptr, 0, sizeof(*mReq->ptr));
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301513 mReq->ptr->token = length << ffs_nr(TD_TOTAL_BYTES);
David Lopoaa69a802008-11-17 14:14:51 -08001514 mReq->ptr->token &= TD_TOTAL_BYTES;
David Lopoaa69a802008-11-17 14:14:51 -08001515 mReq->ptr->token |= TD_STATUS_ACTIVE;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301516 if (mReq->zptr) {
1517 mReq->ptr->next = mReq->zdma;
1518 } else {
1519 mReq->ptr->next = TD_TERMINATE;
1520 if (!mReq->req.no_interrupt)
1521 mReq->ptr->token |= TD_IOC;
1522 }
David Lopoaa69a802008-11-17 14:14:51 -08001523 mReq->ptr->page[0] = mReq->req.dma;
1524 for (i = 1; i < 5; i++)
1525 mReq->ptr->page[i] =
Artem Leonenko0a313c42010-12-14 23:47:06 -08001526 (mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK;
David Lopoaa69a802008-11-17 14:14:51 -08001527
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301528 if (!list_empty(&mEp->qh.queue)) {
1529 struct ci13xxx_req *mReqPrev;
1530 int n = hw_ep_bit(mEp->num, mEp->dir);
1531 int tmp_stat;
1532
1533 mReqPrev = list_entry(mEp->qh.queue.prev,
1534 struct ci13xxx_req, queue);
1535 if (mReqPrev->zptr)
1536 mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
1537 else
1538 mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
1539 wmb();
Alexander Shishkin262c1632012-05-08 23:28:59 +03001540 if (hw_read(udc, OP_ENDPTPRIME, BIT(n)))
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301541 goto done;
1542 do {
Alexander Shishkin262c1632012-05-08 23:28:59 +03001543 hw_write(udc, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
1544 tmp_stat = hw_read(udc, OP_ENDPTSTAT, BIT(n));
1545 } while (!hw_read(udc, OP_USBCMD, USBCMD_ATDTW));
1546 hw_write(udc, OP_USBCMD, USBCMD_ATDTW, 0);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301547 if (tmp_stat)
1548 goto done;
1549 }
1550
1551 /* QH configuration */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301552 mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */
1553 mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301554 mEp->qh.ptr->cap |= QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08001555
1556 wmb(); /* synchronize before ep prime */
1557
Alexander Shishkind3595d12012-05-08 23:28:58 +03001558 ret = hw_ep_prime(udc, mEp->num, mEp->dir,
David Lopoaa69a802008-11-17 14:14:51 -08001559 mEp->type == USB_ENDPOINT_XFER_CONTROL);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301560done:
1561 return ret;
David Lopoaa69a802008-11-17 14:14:51 -08001562}
1563
1564/**
1565 * _hardware_dequeue: handles a request at hardware level
1566 * @gadget: gadget
1567 * @mEp: endpoint
1568 *
1569 * This function returns an error code
1570 */
1571static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1572{
Alexander Shishkin0f089092012-05-08 23:29:02 +03001573 trace(mEp->udc->dev, "%p, %p", mEp, mReq);
David Lopoaa69a802008-11-17 14:14:51 -08001574
1575 if (mReq->req.status != -EALREADY)
1576 return -EINVAL;
1577
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301578 if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
1579 return -EBUSY;
1580
1581 if (mReq->zptr) {
1582 if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
1583 return -EBUSY;
1584 dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
1585 mReq->zptr = NULL;
1586 }
David Lopoaa69a802008-11-17 14:14:51 -08001587
1588 mReq->req.status = 0;
1589
1590 if (mReq->map) {
1591 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
1592 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02001593 mReq->req.dma = DMA_ADDR_INVALID;
David Lopoaa69a802008-11-17 14:14:51 -08001594 mReq->map = 0;
1595 }
1596
1597 mReq->req.status = mReq->ptr->token & TD_STATUS;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301598 if ((TD_STATUS_HALTED & mReq->req.status) != 0)
David Lopoaa69a802008-11-17 14:14:51 -08001599 mReq->req.status = -1;
1600 else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0)
1601 mReq->req.status = -1;
1602 else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0)
1603 mReq->req.status = -1;
1604
1605 mReq->req.actual = mReq->ptr->token & TD_TOTAL_BYTES;
1606 mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES);
1607 mReq->req.actual = mReq->req.length - mReq->req.actual;
1608 mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual;
1609
1610 return mReq->req.actual;
1611}
1612
1613/**
1614 * _ep_nuke: dequeues all endpoint requests
1615 * @mEp: endpoint
1616 *
1617 * This function returns an error code
1618 * Caller must hold lock
1619 */
1620static int _ep_nuke(struct ci13xxx_ep *mEp)
1621__releases(mEp->lock)
1622__acquires(mEp->lock)
1623{
Alexander Shishkin0f089092012-05-08 23:29:02 +03001624 trace(mEp->udc->dev, "%p", mEp);
David Lopoaa69a802008-11-17 14:14:51 -08001625
1626 if (mEp == NULL)
1627 return -EINVAL;
1628
Alexander Shishkind3595d12012-05-08 23:28:58 +03001629 hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08001630
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301631 while (!list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -08001632
1633 /* pop oldest request */
1634 struct ci13xxx_req *mReq = \
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301635 list_entry(mEp->qh.queue.next,
David Lopoaa69a802008-11-17 14:14:51 -08001636 struct ci13xxx_req, queue);
1637 list_del_init(&mReq->queue);
1638 mReq->req.status = -ESHUTDOWN;
1639
Artem Leonenko7c25a822010-12-14 23:46:55 -08001640 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08001641 spin_unlock(mEp->lock);
1642 mReq->req.complete(&mEp->ep, &mReq->req);
1643 spin_lock(mEp->lock);
1644 }
1645 }
1646 return 0;
1647}
1648
1649/**
1650 * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
1651 * @gadget: gadget
1652 *
1653 * This function returns an error code
David Lopoaa69a802008-11-17 14:14:51 -08001654 */
1655static int _gadget_stop_activity(struct usb_gadget *gadget)
David Lopoaa69a802008-11-17 14:14:51 -08001656{
1657 struct usb_ep *ep;
1658 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301659 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -08001660
Alexander Shishkin0f089092012-05-08 23:29:02 +03001661 trace(udc->dev, "%p", gadget);
David Lopoaa69a802008-11-17 14:14:51 -08001662
1663 if (gadget == NULL)
1664 return -EINVAL;
1665
Alexander Shishkind3595d12012-05-08 23:28:58 +03001666 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301667 udc->gadget.speed = USB_SPEED_UNKNOWN;
1668 udc->remote_wakeup = 0;
1669 udc->suspended = 0;
Alexander Shishkind3595d12012-05-08 23:28:58 +03001670 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301671
David Lopoaa69a802008-11-17 14:14:51 -08001672 /* flush all endpoints */
1673 gadget_for_each_ep(ep, gadget) {
1674 usb_ep_fifo_flush(ep);
1675 }
Alexander Shishkind36ade62012-05-04 16:47:15 +03001676 usb_ep_fifo_flush(&udc->ep0out->ep);
1677 usb_ep_fifo_flush(&udc->ep0in->ep);
David Lopoaa69a802008-11-17 14:14:51 -08001678
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001679 if (udc->driver)
1680 udc->driver->disconnect(gadget);
David Lopoaa69a802008-11-17 14:14:51 -08001681
1682 /* make sure to disable all endpoints */
1683 gadget_for_each_ep(ep, gadget) {
1684 usb_ep_disable(ep);
1685 }
David Lopoaa69a802008-11-17 14:14:51 -08001686
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301687 if (udc->status != NULL) {
Alexander Shishkind36ade62012-05-04 16:47:15 +03001688 usb_ep_free_request(&udc->ep0in->ep, udc->status);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301689 udc->status = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08001690 }
1691
David Lopoaa69a802008-11-17 14:14:51 -08001692 return 0;
1693}
1694
1695/******************************************************************************
1696 * ISR block
1697 *****************************************************************************/
1698/**
1699 * isr_reset_handler: USB reset interrupt handler
1700 * @udc: UDC device
1701 *
1702 * This function resets USB engine after a bus reset occurred
1703 */
1704static void isr_reset_handler(struct ci13xxx *udc)
1705__releases(udc->lock)
1706__acquires(udc->lock)
1707{
David Lopoaa69a802008-11-17 14:14:51 -08001708 int retval;
1709
Alexander Shishkin0f089092012-05-08 23:29:02 +03001710 trace(udc->dev, "%p", udc);
David Lopoaa69a802008-11-17 14:14:51 -08001711
1712 dbg_event(0xFF, "BUS RST", 0);
1713
Alexander Shishkind3595d12012-05-08 23:28:58 +03001714 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001715 retval = _gadget_stop_activity(&udc->gadget);
1716 if (retval)
1717 goto done;
1718
Alexander Shishkind3595d12012-05-08 23:28:58 +03001719 retval = hw_usb_reset(udc);
David Lopoaa69a802008-11-17 14:14:51 -08001720 if (retval)
1721 goto done;
1722
Alexander Shishkind36ade62012-05-04 16:47:15 +03001723 udc->status = usb_ep_alloc_request(&udc->ep0in->ep, GFP_ATOMIC);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05301724 if (udc->status == NULL)
1725 retval = -ENOMEM;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301726
Alexander Shishkind3595d12012-05-08 23:28:58 +03001727 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001728
1729 done:
1730 if (retval)
Alexander Shishkin0f089092012-05-08 23:29:02 +03001731 dev_err(udc->dev, "error: %i\n", retval);
David Lopoaa69a802008-11-17 14:14:51 -08001732}
1733
1734/**
1735 * isr_get_status_complete: get_status request complete function
1736 * @ep: endpoint
1737 * @req: request handled
1738 *
1739 * Caller must release lock
1740 */
1741static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
1742{
Alexander Shishkin0f089092012-05-08 23:29:02 +03001743 trace(NULL, "%p, %p", ep, req);
David Lopoaa69a802008-11-17 14:14:51 -08001744
Alexander Shishkin0f089092012-05-08 23:29:02 +03001745 if (ep == NULL || req == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001746 return;
David Lopoaa69a802008-11-17 14:14:51 -08001747
1748 kfree(req->buf);
1749 usb_ep_free_request(ep, req);
1750}
1751
1752/**
1753 * isr_get_status_response: get_status request response
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301754 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08001755 * @setup: setup request packet
1756 *
1757 * This function returns an error code
1758 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301759static int isr_get_status_response(struct ci13xxx *udc,
David Lopoaa69a802008-11-17 14:14:51 -08001760 struct usb_ctrlrequest *setup)
1761__releases(mEp->lock)
1762__acquires(mEp->lock)
1763{
Alexander Shishkind36ade62012-05-04 16:47:15 +03001764 struct ci13xxx_ep *mEp = udc->ep0in;
David Lopoaa69a802008-11-17 14:14:51 -08001765 struct usb_request *req = NULL;
1766 gfp_t gfp_flags = GFP_ATOMIC;
1767 int dir, num, retval;
1768
Alexander Shishkin0f089092012-05-08 23:29:02 +03001769 trace(udc->dev, "%p, %p", mEp, setup);
David Lopoaa69a802008-11-17 14:14:51 -08001770
1771 if (mEp == NULL || setup == NULL)
1772 return -EINVAL;
1773
1774 spin_unlock(mEp->lock);
1775 req = usb_ep_alloc_request(&mEp->ep, gfp_flags);
1776 spin_lock(mEp->lock);
1777 if (req == NULL)
1778 return -ENOMEM;
1779
1780 req->complete = isr_get_status_complete;
1781 req->length = 2;
1782 req->buf = kzalloc(req->length, gfp_flags);
1783 if (req->buf == NULL) {
1784 retval = -ENOMEM;
1785 goto err_free_req;
1786 }
1787
1788 if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301789 /* Assume that device is bus powered for now. */
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001790 *(u16 *)req->buf = udc->remote_wakeup << 1;
David Lopoaa69a802008-11-17 14:14:51 -08001791 retval = 0;
1792 } else if ((setup->bRequestType & USB_RECIP_MASK) \
1793 == USB_RECIP_ENDPOINT) {
1794 dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
1795 TX : RX;
1796 num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK;
Alexander Shishkind3595d12012-05-08 23:28:58 +03001797 *(u16 *)req->buf = hw_ep_get_halt(udc, num, dir);
David Lopoaa69a802008-11-17 14:14:51 -08001798 }
1799 /* else do nothing; reserved for future use */
1800
1801 spin_unlock(mEp->lock);
1802 retval = usb_ep_queue(&mEp->ep, req, gfp_flags);
1803 spin_lock(mEp->lock);
1804 if (retval)
1805 goto err_free_buf;
1806
1807 return 0;
1808
1809 err_free_buf:
1810 kfree(req->buf);
1811 err_free_req:
1812 spin_unlock(mEp->lock);
1813 usb_ep_free_request(&mEp->ep, req);
1814 spin_lock(mEp->lock);
1815 return retval;
1816}
1817
1818/**
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301819 * isr_setup_status_complete: setup_status request complete function
1820 * @ep: endpoint
1821 * @req: request handled
1822 *
1823 * Caller must release lock. Put the port in test mode if test mode
1824 * feature is selected.
1825 */
1826static void
1827isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
1828{
1829 struct ci13xxx *udc = req->context;
1830 unsigned long flags;
1831
Alexander Shishkin0f089092012-05-08 23:29:02 +03001832 trace(udc->dev, "%p, %p", ep, req);
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301833
Alexander Shishkind3595d12012-05-08 23:28:58 +03001834 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301835 if (udc->test_mode)
Alexander Shishkind3595d12012-05-08 23:28:58 +03001836 hw_port_test_set(udc, udc->test_mode);
1837 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301838}
1839
1840/**
David Lopoaa69a802008-11-17 14:14:51 -08001841 * isr_setup_status_phase: queues the status phase of a setup transation
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301842 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08001843 *
1844 * This function returns an error code
1845 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301846static int isr_setup_status_phase(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -08001847__releases(mEp->lock)
1848__acquires(mEp->lock)
1849{
1850 int retval;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301851 struct ci13xxx_ep *mEp;
David Lopoaa69a802008-11-17 14:14:51 -08001852
Alexander Shishkin0f089092012-05-08 23:29:02 +03001853 trace(udc->dev, "%p", udc);
David Lopoaa69a802008-11-17 14:14:51 -08001854
Alexander Shishkind36ade62012-05-04 16:47:15 +03001855 mEp = (udc->ep0_dir == TX) ? udc->ep0out : udc->ep0in;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301856 udc->status->context = udc;
1857 udc->status->complete = isr_setup_status_complete;
David Lopoaa69a802008-11-17 14:14:51 -08001858
1859 spin_unlock(mEp->lock);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301860 retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
David Lopoaa69a802008-11-17 14:14:51 -08001861 spin_lock(mEp->lock);
1862
1863 return retval;
1864}
1865
1866/**
1867 * isr_tr_complete_low: transaction complete low level handler
1868 * @mEp: endpoint
1869 *
1870 * This function returns an error code
1871 * Caller must hold lock
1872 */
1873static int isr_tr_complete_low(struct ci13xxx_ep *mEp)
1874__releases(mEp->lock)
1875__acquires(mEp->lock)
1876{
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301877 struct ci13xxx_req *mReq, *mReqTemp;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05301878 struct ci13xxx_ep *mEpTemp = mEp;
Pavankumar Kondeti986b11b2011-05-02 11:56:29 +05301879 int uninitialized_var(retval);
David Lopoaa69a802008-11-17 14:14:51 -08001880
Alexander Shishkin0f089092012-05-08 23:29:02 +03001881 trace(mEp->udc->dev, "%p", mEp);
David Lopoaa69a802008-11-17 14:14:51 -08001882
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301883 if (list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08001884 return -EINVAL;
1885
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301886 list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,
1887 queue) {
1888 retval = _hardware_dequeue(mEp, mReq);
1889 if (retval < 0)
1890 break;
1891 list_del_init(&mReq->queue);
1892 dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
1893 if (mReq->req.complete != NULL) {
1894 spin_unlock(mEp->lock);
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05301895 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
1896 mReq->req.length)
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001897 mEpTemp = mEp->udc->ep0in;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05301898 mReq->req.complete(&mEpTemp->ep, &mReq->req);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301899 spin_lock(mEp->lock);
1900 }
1901 }
David Lopoaa69a802008-11-17 14:14:51 -08001902
Pavankumar Kondetief907482011-05-02 11:56:27 +05301903 if (retval == -EBUSY)
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301904 retval = 0;
1905 if (retval < 0)
David Lopoaa69a802008-11-17 14:14:51 -08001906 dbg_event(_usb_addr(mEp), "DONE", retval);
David Lopoaa69a802008-11-17 14:14:51 -08001907
David Lopoaa69a802008-11-17 14:14:51 -08001908 return retval;
1909}
1910
1911/**
1912 * isr_tr_complete_handler: transaction complete interrupt handler
1913 * @udc: UDC descriptor
1914 *
1915 * This function handles traffic events
1916 */
1917static void isr_tr_complete_handler(struct ci13xxx *udc)
1918__releases(udc->lock)
1919__acquires(udc->lock)
1920{
1921 unsigned i;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301922 u8 tmode = 0;
David Lopoaa69a802008-11-17 14:14:51 -08001923
Alexander Shishkin0f089092012-05-08 23:29:02 +03001924 trace(udc->dev, "%p", udc);
David Lopoaa69a802008-11-17 14:14:51 -08001925
Alexander Shishkind3595d12012-05-08 23:28:58 +03001926 for (i = 0; i < udc->hw_ep_max; i++) {
David Lopoaa69a802008-11-17 14:14:51 -08001927 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05301928 int type, num, dir, err = -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -08001929 struct usb_ctrlrequest req;
1930
Ido Shayevitz31fb6012012-03-12 20:25:23 +02001931 if (mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001932 continue; /* not configured */
1933
Alexander Shishkind3595d12012-05-08 23:28:58 +03001934 if (hw_test_and_clear_complete(udc, i)) {
David Lopoaa69a802008-11-17 14:14:51 -08001935 err = isr_tr_complete_low(mEp);
1936 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
1937 if (err > 0) /* needs status phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301938 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08001939 if (err < 0) {
1940 dbg_event(_usb_addr(mEp),
1941 "ERROR", err);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001942 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001943 if (usb_ep_set_halt(&mEp->ep))
Alexander Shishkin0f089092012-05-08 23:29:02 +03001944 dev_err(udc->dev,
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07001945 "error: ep_set_halt\n");
Alexander Shishkind3595d12012-05-08 23:28:58 +03001946 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001947 }
1948 }
1949 }
1950
1951 if (mEp->type != USB_ENDPOINT_XFER_CONTROL ||
Alexander Shishkind3595d12012-05-08 23:28:58 +03001952 !hw_test_and_clear_setup_status(udc, i))
David Lopoaa69a802008-11-17 14:14:51 -08001953 continue;
1954
1955 if (i != 0) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001956 dev_warn(udc->dev, "ctrl traffic at endpoint %d\n", i);
David Lopoaa69a802008-11-17 14:14:51 -08001957 continue;
1958 }
1959
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301960 /*
1961 * Flush data and handshake transactions of previous
1962 * setup packet.
1963 */
Alexander Shishkind36ade62012-05-04 16:47:15 +03001964 _ep_nuke(udc->ep0out);
1965 _ep_nuke(udc->ep0in);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301966
David Lopoaa69a802008-11-17 14:14:51 -08001967 /* read_setup_packet */
1968 do {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001969 hw_test_and_set_setup_guard(udc);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301970 memcpy(&req, &mEp->qh.ptr->setup, sizeof(req));
Alexander Shishkind3595d12012-05-08 23:28:58 +03001971 } while (!hw_test_and_clear_setup_guard(udc));
David Lopoaa69a802008-11-17 14:14:51 -08001972
1973 type = req.bRequestType;
1974
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301975 udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
David Lopoaa69a802008-11-17 14:14:51 -08001976
1977 dbg_setup(_usb_addr(mEp), &req);
1978
1979 switch (req.bRequest) {
1980 case USB_REQ_CLEAR_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301981 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
1982 le16_to_cpu(req.wValue) ==
1983 USB_ENDPOINT_HALT) {
1984 if (req.wLength != 0)
David Lopoaa69a802008-11-17 14:14:51 -08001985 break;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301986 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05301987 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301988 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05301989 if (dir) /* TX */
Alexander Shishkind3595d12012-05-08 23:28:58 +03001990 num += udc->hw_ep_max/2;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301991 if (!udc->ci13xxx_ep[num].wedge) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001992 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301993 err = usb_ep_clear_halt(
1994 &udc->ci13xxx_ep[num].ep);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001995 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301996 if (err)
1997 break;
1998 }
1999 err = isr_setup_status_phase(udc);
2000 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
2001 le16_to_cpu(req.wValue) ==
2002 USB_DEVICE_REMOTE_WAKEUP) {
2003 if (req.wLength != 0)
2004 break;
2005 udc->remote_wakeup = 0;
2006 err = isr_setup_status_phase(udc);
2007 } else {
2008 goto delegate;
David Lopoaa69a802008-11-17 14:14:51 -08002009 }
David Lopoaa69a802008-11-17 14:14:51 -08002010 break;
2011 case USB_REQ_GET_STATUS:
2012 if (type != (USB_DIR_IN|USB_RECIP_DEVICE) &&
2013 type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
2014 type != (USB_DIR_IN|USB_RECIP_INTERFACE))
2015 goto delegate;
2016 if (le16_to_cpu(req.wLength) != 2 ||
2017 le16_to_cpu(req.wValue) != 0)
2018 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302019 err = isr_get_status_response(udc, &req);
David Lopoaa69a802008-11-17 14:14:51 -08002020 break;
2021 case USB_REQ_SET_ADDRESS:
2022 if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
2023 goto delegate;
2024 if (le16_to_cpu(req.wLength) != 0 ||
2025 le16_to_cpu(req.wIndex) != 0)
2026 break;
Alexander Shishkind3595d12012-05-08 23:28:58 +03002027 err = hw_usb_set_address(udc,
2028 (u8)le16_to_cpu(req.wValue));
David Lopoaa69a802008-11-17 14:14:51 -08002029 if (err)
2030 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302031 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002032 break;
2033 case USB_REQ_SET_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302034 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
2035 le16_to_cpu(req.wValue) ==
2036 USB_ENDPOINT_HALT) {
2037 if (req.wLength != 0)
2038 break;
2039 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302040 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302041 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302042 if (dir) /* TX */
Alexander Shishkind3595d12012-05-08 23:28:58 +03002043 num += udc->hw_ep_max/2;
David Lopoaa69a802008-11-17 14:14:51 -08002044
Alexander Shishkind3595d12012-05-08 23:28:58 +03002045 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302046 err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002047 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302048 if (!err)
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302049 isr_setup_status_phase(udc);
2050 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302051 if (req.wLength != 0)
2052 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302053 switch (le16_to_cpu(req.wValue)) {
2054 case USB_DEVICE_REMOTE_WAKEUP:
2055 udc->remote_wakeup = 1;
2056 err = isr_setup_status_phase(udc);
2057 break;
2058 case USB_DEVICE_TEST_MODE:
2059 tmode = le16_to_cpu(req.wIndex) >> 8;
2060 switch (tmode) {
2061 case TEST_J:
2062 case TEST_K:
2063 case TEST_SE0_NAK:
2064 case TEST_PACKET:
2065 case TEST_FORCE_EN:
2066 udc->test_mode = tmode;
2067 err = isr_setup_status_phase(
2068 udc);
2069 break;
2070 default:
2071 break;
2072 }
2073 default:
2074 goto delegate;
2075 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302076 } else {
2077 goto delegate;
2078 }
David Lopoaa69a802008-11-17 14:14:51 -08002079 break;
2080 default:
2081delegate:
2082 if (req.wLength == 0) /* no data phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302083 udc->ep0_dir = TX;
David Lopoaa69a802008-11-17 14:14:51 -08002084
Alexander Shishkind3595d12012-05-08 23:28:58 +03002085 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08002086 err = udc->driver->setup(&udc->gadget, &req);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002087 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08002088 break;
2089 }
2090
2091 if (err < 0) {
2092 dbg_event(_usb_addr(mEp), "ERROR", err);
2093
Alexander Shishkind3595d12012-05-08 23:28:58 +03002094 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08002095 if (usb_ep_set_halt(&mEp->ep))
Alexander Shishkin0f089092012-05-08 23:29:02 +03002096 dev_err(udc->dev, "error: ep_set_halt\n");
Alexander Shishkind3595d12012-05-08 23:28:58 +03002097 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08002098 }
2099 }
2100}
2101
2102/******************************************************************************
2103 * ENDPT block
2104 *****************************************************************************/
2105/**
2106 * ep_enable: configure endpoint, making it usable
2107 *
2108 * Check usb_ep_enable() at "usb_gadget.h" for details
2109 */
2110static int ep_enable(struct usb_ep *ep,
2111 const struct usb_endpoint_descriptor *desc)
2112{
2113 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302114 int retval = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002115 unsigned long flags;
2116
Alexander Shishkin0f089092012-05-08 23:29:02 +03002117 trace(mEp->udc->dev, "%p, %p", ep, desc);
David Lopoaa69a802008-11-17 14:14:51 -08002118
2119 if (ep == NULL || desc == NULL)
2120 return -EINVAL;
2121
2122 spin_lock_irqsave(mEp->lock, flags);
2123
2124 /* only internal SW should enable ctrl endpts */
2125
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002126 mEp->ep.desc = desc;
David Lopoaa69a802008-11-17 14:14:51 -08002127
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302128 if (!list_empty(&mEp->qh.queue))
Alexander Shishkin0f089092012-05-08 23:29:02 +03002129 dev_warn(mEp->udc->dev, "enabling a non-empty endpoint!\n");
David Lopoaa69a802008-11-17 14:14:51 -08002130
Matthias Kaehlcke15739bb2009-04-15 22:28:41 +02002131 mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX;
2132 mEp->num = usb_endpoint_num(desc);
2133 mEp->type = usb_endpoint_type(desc);
David Lopoaa69a802008-11-17 14:14:51 -08002134
Kuninori Morimoto29cc8892011-08-23 03:12:03 -07002135 mEp->ep.maxpacket = usb_endpoint_maxp(desc);
David Lopoaa69a802008-11-17 14:14:51 -08002136
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302137 dbg_event(_usb_addr(mEp), "ENABLE", 0);
David Lopoaa69a802008-11-17 14:14:51 -08002138
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302139 mEp->qh.ptr->cap = 0;
David Lopof23e6492009-04-16 14:35:24 -07002140
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302141 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2142 mEp->qh.ptr->cap |= QH_IOS;
2143 else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
2144 mEp->qh.ptr->cap &= ~QH_MULT;
2145 else
2146 mEp->qh.ptr->cap &= ~QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08002147
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302148 mEp->qh.ptr->cap |=
2149 (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
2150 mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */
David Lopoaa69a802008-11-17 14:14:51 -08002151
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302152 /*
2153 * Enable endpoints in the HW other than ep0 as ep0
2154 * is always enabled
2155 */
2156 if (mEp->num)
Alexander Shishkind3595d12012-05-08 23:28:58 +03002157 retval |= hw_ep_enable(mEp->udc, mEp->num, mEp->dir, mEp->type);
David Lopoaa69a802008-11-17 14:14:51 -08002158
2159 spin_unlock_irqrestore(mEp->lock, flags);
2160 return retval;
2161}
2162
2163/**
2164 * ep_disable: endpoint is no longer usable
2165 *
2166 * Check usb_ep_disable() at "usb_gadget.h" for details
2167 */
2168static int ep_disable(struct usb_ep *ep)
2169{
2170 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2171 int direction, retval = 0;
2172 unsigned long flags;
2173
Alexander Shishkin0f089092012-05-08 23:29:02 +03002174 trace(mEp->udc->dev, "%p", ep);
David Lopoaa69a802008-11-17 14:14:51 -08002175
2176 if (ep == NULL)
2177 return -EINVAL;
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002178 else if (mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002179 return -EBUSY;
2180
2181 spin_lock_irqsave(mEp->lock, flags);
2182
2183 /* only internal SW should disable ctrl endpts */
2184
2185 direction = mEp->dir;
2186 do {
2187 dbg_event(_usb_addr(mEp), "DISABLE", 0);
2188
2189 retval |= _ep_nuke(mEp);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002190 retval |= hw_ep_disable(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08002191
2192 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2193 mEp->dir = (mEp->dir == TX) ? RX : TX;
2194
2195 } while (mEp->dir != direction);
2196
Ido Shayevitzf9c56cd2012-02-08 13:56:48 +02002197 mEp->ep.desc = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002198
2199 spin_unlock_irqrestore(mEp->lock, flags);
2200 return retval;
2201}
2202
2203/**
2204 * ep_alloc_request: allocate a request object to use with this endpoint
2205 *
2206 * Check usb_ep_alloc_request() at "usb_gadget.h" for details
2207 */
2208static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
2209{
2210 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2211 struct ci13xxx_req *mReq = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002212
Alexander Shishkin0f089092012-05-08 23:29:02 +03002213 trace(mEp->udc->dev, "%p, %i", ep, gfp_flags);
David Lopoaa69a802008-11-17 14:14:51 -08002214
Alexander Shishkin0f089092012-05-08 23:29:02 +03002215 if (ep == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002216 return NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002217
David Lopoaa69a802008-11-17 14:14:51 -08002218 mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
2219 if (mReq != NULL) {
2220 INIT_LIST_HEAD(&mReq->queue);
Michael Grzeschik954aad82011-10-10 18:38:06 +02002221 mReq->req.dma = DMA_ADDR_INVALID;
David Lopoaa69a802008-11-17 14:14:51 -08002222
2223 mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,
2224 &mReq->dma);
2225 if (mReq->ptr == NULL) {
2226 kfree(mReq);
2227 mReq = NULL;
2228 }
2229 }
2230
2231 dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
2232
David Lopoaa69a802008-11-17 14:14:51 -08002233 return (mReq == NULL) ? NULL : &mReq->req;
2234}
2235
2236/**
2237 * ep_free_request: frees a request object
2238 *
2239 * Check usb_ep_free_request() at "usb_gadget.h" for details
2240 */
2241static void ep_free_request(struct usb_ep *ep, struct usb_request *req)
2242{
2243 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2244 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2245 unsigned long flags;
2246
Alexander Shishkin0f089092012-05-08 23:29:02 +03002247 trace(mEp->udc->dev, "%p, %p", ep, req);
David Lopoaa69a802008-11-17 14:14:51 -08002248
2249 if (ep == NULL || req == NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08002250 return;
2251 } else if (!list_empty(&mReq->queue)) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03002252 dev_err(mEp->udc->dev, "freeing queued request\n");
David Lopoaa69a802008-11-17 14:14:51 -08002253 return;
2254 }
2255
2256 spin_lock_irqsave(mEp->lock, flags);
2257
2258 if (mReq->ptr)
2259 dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma);
2260 kfree(mReq);
2261
2262 dbg_event(_usb_addr(mEp), "FREE", 0);
2263
2264 spin_unlock_irqrestore(mEp->lock, flags);
2265}
2266
2267/**
2268 * ep_queue: queues (submits) an I/O request to an endpoint
2269 *
2270 * Check usb_ep_queue()* at usb_gadget.h" for details
2271 */
2272static int ep_queue(struct usb_ep *ep, struct usb_request *req,
2273 gfp_t __maybe_unused gfp_flags)
2274{
2275 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2276 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002277 struct ci13xxx *udc = mEp->udc;
David Lopoaa69a802008-11-17 14:14:51 -08002278 int retval = 0;
2279 unsigned long flags;
2280
Alexander Shishkin0f089092012-05-08 23:29:02 +03002281 trace(mEp->udc->dev, "%p, %p, %X", ep, req, gfp_flags);
David Lopoaa69a802008-11-17 14:14:51 -08002282
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002283 if (ep == NULL || req == NULL || mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002284 return -EINVAL;
2285
2286 spin_lock_irqsave(mEp->lock, flags);
2287
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302288 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
2289 if (req->length)
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002290 mEp = (udc->ep0_dir == RX) ?
2291 udc->ep0out : udc->ep0in;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302292 if (!list_empty(&mEp->qh.queue)) {
2293 _ep_nuke(mEp);
2294 retval = -EOVERFLOW;
Alexander Shishkin0f089092012-05-08 23:29:02 +03002295 dev_warn(mEp->udc->dev, "endpoint ctrl %X nuked\n",
2296 _usb_addr(mEp));
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302297 }
David Lopoaa69a802008-11-17 14:14:51 -08002298 }
2299
2300 /* first nuke then test link, e.g. previous status has not sent */
2301 if (!list_empty(&mReq->queue)) {
2302 retval = -EBUSY;
Alexander Shishkin0f089092012-05-08 23:29:02 +03002303 dev_err(mEp->udc->dev, "request already in queue\n");
David Lopoaa69a802008-11-17 14:14:51 -08002304 goto done;
2305 }
2306
Alexander Shishkin1155a7b2012-05-08 23:28:57 +03002307 if (req->length > 4 * CI13XXX_PAGE_SIZE) {
2308 req->length = 4 * CI13XXX_PAGE_SIZE;
David Lopoaa69a802008-11-17 14:14:51 -08002309 retval = -EMSGSIZE;
Alexander Shishkin0f089092012-05-08 23:29:02 +03002310 dev_warn(mEp->udc->dev, "request length truncated\n");
David Lopoaa69a802008-11-17 14:14:51 -08002311 }
2312
2313 dbg_queue(_usb_addr(mEp), req, retval);
2314
2315 /* push request */
2316 mReq->req.status = -EINPROGRESS;
2317 mReq->req.actual = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002318
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302319 retval = _hardware_enqueue(mEp, mReq);
Artem Leonenkod9bb9c12010-12-14 23:45:50 -08002320
2321 if (retval == -EALREADY) {
David Lopoaa69a802008-11-17 14:14:51 -08002322 dbg_event(_usb_addr(mEp), "QUEUE", retval);
2323 retval = 0;
2324 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302325 if (!retval)
2326 list_add_tail(&mReq->queue, &mEp->qh.queue);
David Lopoaa69a802008-11-17 14:14:51 -08002327
2328 done:
2329 spin_unlock_irqrestore(mEp->lock, flags);
2330 return retval;
2331}
2332
2333/**
2334 * ep_dequeue: dequeues (cancels, unlinks) an I/O request from an endpoint
2335 *
2336 * Check usb_ep_dequeue() at "usb_gadget.h" for details
2337 */
2338static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
2339{
2340 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2341 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2342 unsigned long flags;
2343
Alexander Shishkin0f089092012-05-08 23:29:02 +03002344 trace(mEp->udc->dev, "%p, %p", ep, req);
David Lopoaa69a802008-11-17 14:14:51 -08002345
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302346 if (ep == NULL || req == NULL || mReq->req.status != -EALREADY ||
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002347 mEp->ep.desc == NULL || list_empty(&mReq->queue) ||
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302348 list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08002349 return -EINVAL;
2350
2351 spin_lock_irqsave(mEp->lock, flags);
2352
2353 dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
2354
Alexander Shishkind3595d12012-05-08 23:28:58 +03002355 hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08002356
2357 /* pop request */
2358 list_del_init(&mReq->queue);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302359 if (mReq->map) {
2360 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
2361 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02002362 mReq->req.dma = DMA_ADDR_INVALID;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302363 mReq->map = 0;
2364 }
David Lopoaa69a802008-11-17 14:14:51 -08002365 req->status = -ECONNRESET;
2366
Artem Leonenko7c25a822010-12-14 23:46:55 -08002367 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08002368 spin_unlock(mEp->lock);
2369 mReq->req.complete(&mEp->ep, &mReq->req);
2370 spin_lock(mEp->lock);
2371 }
2372
2373 spin_unlock_irqrestore(mEp->lock, flags);
2374 return 0;
2375}
2376
2377/**
2378 * ep_set_halt: sets the endpoint halt feature
2379 *
2380 * Check usb_ep_set_halt() at "usb_gadget.h" for details
2381 */
2382static int ep_set_halt(struct usb_ep *ep, int value)
2383{
2384 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2385 int direction, retval = 0;
2386 unsigned long flags;
2387
Alexander Shishkin0f089092012-05-08 23:29:02 +03002388 trace(mEp->udc->dev, "%p, %i", ep, value);
David Lopoaa69a802008-11-17 14:14:51 -08002389
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002390 if (ep == NULL || mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002391 return -EINVAL;
2392
2393 spin_lock_irqsave(mEp->lock, flags);
2394
2395#ifndef STALL_IN
2396 /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
2397 if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX &&
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302398 !list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -08002399 spin_unlock_irqrestore(mEp->lock, flags);
2400 return -EAGAIN;
2401 }
2402#endif
2403
2404 direction = mEp->dir;
2405 do {
2406 dbg_event(_usb_addr(mEp), "HALT", value);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002407 retval |= hw_ep_set_halt(mEp->udc, mEp->num, mEp->dir, value);
David Lopoaa69a802008-11-17 14:14:51 -08002408
2409 if (!value)
2410 mEp->wedge = 0;
2411
2412 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2413 mEp->dir = (mEp->dir == TX) ? RX : TX;
2414
2415 } while (mEp->dir != direction);
2416
2417 spin_unlock_irqrestore(mEp->lock, flags);
2418 return retval;
2419}
2420
2421/**
2422 * ep_set_wedge: sets the halt feature and ignores clear requests
2423 *
2424 * Check usb_ep_set_wedge() at "usb_gadget.h" for details
2425 */
2426static int ep_set_wedge(struct usb_ep *ep)
2427{
2428 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2429 unsigned long flags;
2430
Alexander Shishkin0f089092012-05-08 23:29:02 +03002431 trace(mEp->udc->dev, "%p", ep);
David Lopoaa69a802008-11-17 14:14:51 -08002432
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002433 if (ep == NULL || mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002434 return -EINVAL;
2435
2436 spin_lock_irqsave(mEp->lock, flags);
2437
2438 dbg_event(_usb_addr(mEp), "WEDGE", 0);
2439 mEp->wedge = 1;
2440
2441 spin_unlock_irqrestore(mEp->lock, flags);
2442
2443 return usb_ep_set_halt(ep);
2444}
2445
2446/**
2447 * ep_fifo_flush: flushes contents of a fifo
2448 *
2449 * Check usb_ep_fifo_flush() at "usb_gadget.h" for details
2450 */
2451static void ep_fifo_flush(struct usb_ep *ep)
2452{
2453 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2454 unsigned long flags;
2455
Alexander Shishkin0f089092012-05-08 23:29:02 +03002456 trace(mEp->udc->dev, "%p", ep);
David Lopoaa69a802008-11-17 14:14:51 -08002457
2458 if (ep == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03002459 dev_err(mEp->udc->dev, "%02X: -EINVAL\n", _usb_addr(mEp));
David Lopoaa69a802008-11-17 14:14:51 -08002460 return;
2461 }
2462
2463 spin_lock_irqsave(mEp->lock, flags);
2464
2465 dbg_event(_usb_addr(mEp), "FFLUSH", 0);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002466 hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08002467
2468 spin_unlock_irqrestore(mEp->lock, flags);
2469}
2470
2471/**
2472 * Endpoint-specific part of the API to the USB controller hardware
2473 * Check "usb_gadget.h" for details
2474 */
2475static const struct usb_ep_ops usb_ep_ops = {
2476 .enable = ep_enable,
2477 .disable = ep_disable,
2478 .alloc_request = ep_alloc_request,
2479 .free_request = ep_free_request,
2480 .queue = ep_queue,
2481 .dequeue = ep_dequeue,
2482 .set_halt = ep_set_halt,
2483 .set_wedge = ep_set_wedge,
2484 .fifo_flush = ep_fifo_flush,
2485};
2486
2487/******************************************************************************
2488 * GADGET block
2489 *****************************************************************************/
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302490static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
2491{
2492 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2493 unsigned long flags;
2494 int gadget_ready = 0;
2495
2496 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS))
2497 return -EOPNOTSUPP;
2498
Alexander Shishkind3595d12012-05-08 23:28:58 +03002499 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302500 udc->vbus_active = is_active;
2501 if (udc->driver)
2502 gadget_ready = 1;
Alexander Shishkind3595d12012-05-08 23:28:58 +03002503 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302504
2505 if (gadget_ready) {
2506 if (is_active) {
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302507 pm_runtime_get_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302508 hw_device_reset(udc);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002509 hw_device_state(udc, udc->ep0out->qh.dma);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302510 } else {
Alexander Shishkind3595d12012-05-08 23:28:58 +03002511 hw_device_state(udc, 0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302512 if (udc->udc_driver->notify_event)
2513 udc->udc_driver->notify_event(udc,
2514 CI13XXX_CONTROLLER_STOPPED_EVENT);
2515 _gadget_stop_activity(&udc->gadget);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302516 pm_runtime_put_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302517 }
2518 }
2519
2520 return 0;
2521}
2522
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302523static int ci13xxx_wakeup(struct usb_gadget *_gadget)
2524{
2525 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2526 unsigned long flags;
2527 int ret = 0;
2528
Alexander Shishkin0f089092012-05-08 23:29:02 +03002529 trace(udc->dev, "");
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302530
Alexander Shishkind3595d12012-05-08 23:28:58 +03002531 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302532 if (!udc->remote_wakeup) {
2533 ret = -EOPNOTSUPP;
Alexander Shishkin0f089092012-05-08 23:29:02 +03002534 trace(udc->dev, "remote wakeup feature is not enabled\n");
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302535 goto out;
2536 }
Alexander Shishkin262c1632012-05-08 23:28:59 +03002537 if (!hw_read(udc, OP_PORTSC, PORTSC_SUSP)) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302538 ret = -EINVAL;
Alexander Shishkin0f089092012-05-08 23:29:02 +03002539 trace(udc->dev, "port is not suspended\n");
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302540 goto out;
2541 }
Alexander Shishkin262c1632012-05-08 23:28:59 +03002542 hw_write(udc, OP_PORTSC, PORTSC_FPR, PORTSC_FPR);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302543out:
Alexander Shishkind3595d12012-05-08 23:28:58 +03002544 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302545 return ret;
2546}
2547
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302548static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
2549{
2550 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2551
2552 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002553 return usb_phy_set_power(udc->transceiver, mA);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302554 return -ENOTSUPP;
2555}
2556
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002557static int ci13xxx_start(struct usb_gadget *gadget,
2558 struct usb_gadget_driver *driver);
2559static int ci13xxx_stop(struct usb_gadget *gadget,
2560 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,
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002570 .udc_start = ci13xxx_start,
2571 .udc_stop = ci13xxx_stop,
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302572};
David Lopoaa69a802008-11-17 14:14:51 -08002573
Alexander Shishkin790c2d52012-05-08 23:29:03 +03002574static int init_eps(struct ci13xxx *udc)
2575{
2576 int retval = 0, i, j;
2577
2578 for (i = 0; i < udc->hw_ep_max/2; i++)
2579 for (j = RX; j <= TX; j++) {
2580 int k = i + j * udc->hw_ep_max/2;
2581 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
2582
2583 scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
2584 (j == TX) ? "in" : "out");
2585
2586 mEp->udc = udc;
2587 mEp->lock = &udc->lock;
2588 mEp->device = &udc->gadget.dev;
2589 mEp->td_pool = udc->td_pool;
2590
2591 mEp->ep.name = mEp->name;
2592 mEp->ep.ops = &usb_ep_ops;
2593 mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
2594
2595 INIT_LIST_HEAD(&mEp->qh.queue);
2596 mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
2597 &mEp->qh.dma);
2598 if (mEp->qh.ptr == NULL)
2599 retval = -ENOMEM;
2600 else
2601 memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
2602
2603 /*
2604 * set up shorthands for ep0 out and in endpoints,
2605 * don't add to gadget's ep_list
2606 */
2607 if (i == 0) {
2608 if (j == RX)
2609 udc->ep0out = mEp;
2610 else
2611 udc->ep0in = mEp;
2612
2613 continue;
2614 }
2615
2616 list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
2617 }
2618
2619 return retval;
2620}
2621
David Lopoaa69a802008-11-17 14:14:51 -08002622/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002623 * ci13xxx_start: register a gadget driver
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002624 * @gadget: our gadget
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002625 * @driver: the driver being registered
David Lopoaa69a802008-11-17 14:14:51 -08002626 *
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002627 * Interrupts are enabled here.
David Lopoaa69a802008-11-17 14:14:51 -08002628 */
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002629static int ci13xxx_start(struct usb_gadget *gadget,
2630 struct usb_gadget_driver *driver)
David Lopoaa69a802008-11-17 14:14:51 -08002631{
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002632 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302633 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -08002634 int retval = -ENOMEM;
2635
Alexander Shishkin0f089092012-05-08 23:29:02 +03002636 trace(udc->dev, "%p", driver);
David Lopoaa69a802008-11-17 14:14:51 -08002637
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002638 if (driver->disconnect == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002639 return -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -08002640
David Lopoaa69a802008-11-17 14:14:51 -08002641
Alexander Shishkind36ade62012-05-04 16:47:15 +03002642 udc->ep0out->ep.desc = &ctrl_endpt_out_desc;
2643 retval = usb_ep_enable(&udc->ep0out->ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302644 if (retval)
2645 return retval;
Felipe Balbi877c1f52011-06-29 16:41:57 +03002646
Alexander Shishkind36ade62012-05-04 16:47:15 +03002647 udc->ep0in->ep.desc = &ctrl_endpt_in_desc;
2648 retval = usb_ep_enable(&udc->ep0in->ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302649 if (retval)
2650 return retval;
Alexander Shishkind3595d12012-05-08 23:28:58 +03002651 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002652
Pavankumar Kondeti49d3df52011-01-11 09:19:21 +05302653 udc->driver = driver;
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302654 pm_runtime_get_sync(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302655 if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
2656 if (udc->vbus_active) {
2657 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
2658 hw_device_reset(udc);
2659 } else {
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302660 pm_runtime_put_sync(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302661 goto done;
2662 }
2663 }
2664
Alexander Shishkind3595d12012-05-08 23:28:58 +03002665 retval = hw_device_state(udc, udc->ep0out->qh.dma);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302666 if (retval)
2667 pm_runtime_put_sync(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08002668
2669 done:
Alexander Shishkind3595d12012-05-08 23:28:58 +03002670 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002671 return retval;
2672}
David Lopoaa69a802008-11-17 14:14:51 -08002673
2674/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002675 * ci13xxx_stop: unregister a gadget driver
David Lopoaa69a802008-11-17 14:14:51 -08002676 */
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002677static int ci13xxx_stop(struct usb_gadget *gadget,
2678 struct usb_gadget_driver *driver)
David Lopoaa69a802008-11-17 14:14:51 -08002679{
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002680 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
2681 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -08002682
Alexander Shishkin0f089092012-05-08 23:29:02 +03002683 trace(udc->dev, "%p", driver);
David Lopoaa69a802008-11-17 14:14:51 -08002684
Alexander Shishkind3595d12012-05-08 23:28:58 +03002685 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002686
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302687 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) ||
2688 udc->vbus_active) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03002689 hw_device_state(udc, 0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302690 if (udc->udc_driver->notify_event)
2691 udc->udc_driver->notify_event(udc,
2692 CI13XXX_CONTROLLER_STOPPED_EVENT);
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002693 udc->driver = NULL;
Alexander Shishkind3595d12012-05-08 23:28:58 +03002694 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302695 _gadget_stop_activity(&udc->gadget);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002696 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302697 pm_runtime_put(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302698 }
David Lopoaa69a802008-11-17 14:14:51 -08002699
Alexander Shishkind3595d12012-05-08 23:28:58 +03002700 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002701
David Lopoaa69a802008-11-17 14:14:51 -08002702 return 0;
2703}
David Lopoaa69a802008-11-17 14:14:51 -08002704
2705/******************************************************************************
2706 * BUS block
2707 *****************************************************************************/
2708/**
2709 * udc_irq: global interrupt handler
2710 *
2711 * This function returns IRQ_HANDLED if the IRQ has been handled
2712 * It locks access to registers
2713 */
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03002714static irqreturn_t udc_irq(int irq, void *data)
David Lopoaa69a802008-11-17 14:14:51 -08002715{
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002716 struct ci13xxx *udc = data;
David Lopoaa69a802008-11-17 14:14:51 -08002717 irqreturn_t retval;
2718 u32 intr;
2719
Alexander Shishkin0f089092012-05-08 23:29:02 +03002720 trace(udc ? udc->dev : NULL, "");
David Lopoaa69a802008-11-17 14:14:51 -08002721
2722 if (udc == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03002723 dev_err(udc->dev, "ENODEV");
David Lopoaa69a802008-11-17 14:14:51 -08002724 return IRQ_HANDLED;
2725 }
2726
Alexander Shishkind3595d12012-05-08 23:28:58 +03002727 spin_lock(&udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302728
2729 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) {
Alexander Shishkin262c1632012-05-08 23:28:59 +03002730 if (hw_read(udc, OP_USBMODE, USBMODE_CM) !=
2731 USBMODE_CM_DEVICE) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03002732 spin_unlock(&udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302733 return IRQ_NONE;
2734 }
2735 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03002736 intr = hw_test_and_clear_intr_active(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002737 if (intr) {
2738 isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intr;
2739 isr_statistics.hndl.idx &= ISR_MASK;
2740 isr_statistics.hndl.cnt++;
2741
2742 /* order defines priority - do NOT change it */
2743 if (USBi_URI & intr) {
2744 isr_statistics.uri++;
2745 isr_reset_handler(udc);
2746 }
2747 if (USBi_PCI & intr) {
2748 isr_statistics.pci++;
Alexander Shishkind3595d12012-05-08 23:28:58 +03002749 udc->gadget.speed = hw_port_is_high_speed(udc) ?
David Lopoaa69a802008-11-17 14:14:51 -08002750 USB_SPEED_HIGH : USB_SPEED_FULL;
Marc Kleine-Budde7bb4fdc2011-10-10 18:38:09 +02002751 if (udc->suspended && udc->driver->resume) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03002752 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302753 udc->driver->resume(&udc->gadget);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002754 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302755 udc->suspended = 0;
2756 }
David Lopoaa69a802008-11-17 14:14:51 -08002757 }
2758 if (USBi_UEI & intr)
2759 isr_statistics.uei++;
2760 if (USBi_UI & intr) {
2761 isr_statistics.ui++;
2762 isr_tr_complete_handler(udc);
2763 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302764 if (USBi_SLI & intr) {
Marc Kleine-Budde7bb4fdc2011-10-10 18:38:09 +02002765 if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
2766 udc->driver->suspend) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302767 udc->suspended = 1;
Alexander Shishkind3595d12012-05-08 23:28:58 +03002768 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302769 udc->driver->suspend(&udc->gadget);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002770 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302771 }
David Lopoaa69a802008-11-17 14:14:51 -08002772 isr_statistics.sli++;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302773 }
David Lopoaa69a802008-11-17 14:14:51 -08002774 retval = IRQ_HANDLED;
2775 } else {
2776 isr_statistics.none++;
2777 retval = IRQ_NONE;
2778 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03002779 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08002780
2781 return retval;
2782}
2783
2784/**
2785 * udc_release: driver release function
2786 * @dev: device
2787 *
2788 * Currently does nothing
2789 */
2790static void udc_release(struct device *dev)
2791{
Alexander Shishkin0f089092012-05-08 23:29:02 +03002792 trace(dev->parent, "%p", dev);
David Lopoaa69a802008-11-17 14:14:51 -08002793}
2794
2795/**
2796 * udc_probe: parent probe must call this to initialize UDC
2797 * @dev: parent device
2798 * @regs: registers base address
2799 * @name: driver name
2800 *
2801 * This function returns an error code
2802 * No interrupts active, the IRQ has not been requested yet
2803 * Kernel assumes 32-bit DMA operations by default, no need to dma_set_mask
2804 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302805static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002806 void __iomem *regs, struct ci13xxx **_udc)
David Lopoaa69a802008-11-17 14:14:51 -08002807{
2808 struct ci13xxx *udc;
2809 int retval = 0;
2810
Alexander Shishkin0f089092012-05-08 23:29:02 +03002811 trace(dev, "%p, %p, %p", dev, regs, driver->name);
David Lopoaa69a802008-11-17 14:14:51 -08002812
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302813 if (dev == NULL || regs == NULL || driver == NULL ||
2814 driver->name == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002815 return -EINVAL;
2816
2817 udc = kzalloc(sizeof(struct ci13xxx), GFP_KERNEL);
2818 if (udc == NULL)
2819 return -ENOMEM;
2820
Alexander Shishkind3595d12012-05-08 23:28:58 +03002821 spin_lock_init(&udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302822 udc->regs = regs;
2823 udc->udc_driver = driver;
David Lopoaa69a802008-11-17 14:14:51 -08002824
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302825 udc->gadget.ops = &usb_gadget_ops;
David Lopoaa69a802008-11-17 14:14:51 -08002826 udc->gadget.speed = USB_SPEED_UNKNOWN;
Michal Nazarewiczd327ab52011-11-19 18:27:37 +01002827 udc->gadget.max_speed = USB_SPEED_HIGH;
David Lopoaa69a802008-11-17 14:14:51 -08002828 udc->gadget.is_otg = 0;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302829 udc->gadget.name = driver->name;
David Lopoaa69a802008-11-17 14:14:51 -08002830
2831 INIT_LIST_HEAD(&udc->gadget.ep_list);
David Lopoaa69a802008-11-17 14:14:51 -08002832
Kay Sievers5df585242009-03-24 16:38:23 -07002833 dev_set_name(&udc->gadget.dev, "gadget");
David Lopoaa69a802008-11-17 14:14:51 -08002834 udc->gadget.dev.dma_mask = dev->dma_mask;
Pavankumar Kondeti61948ee2010-12-07 17:54:01 +05302835 udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
David Lopoaa69a802008-11-17 14:14:51 -08002836 udc->gadget.dev.parent = dev;
2837 udc->gadget.dev.release = udc_release;
2838
Alexander Shishkin0f089092012-05-08 23:29:02 +03002839 udc->dev = dev;
2840
Alexander Shishkin790c2d52012-05-08 23:29:03 +03002841 /* alloc resources */
2842 udc->qh_pool = dma_pool_create("ci13xxx_qh", dev,
2843 sizeof(struct ci13xxx_qh),
2844 64, CI13XXX_PAGE_SIZE);
2845 if (udc->qh_pool == NULL) {
2846 retval = -ENOMEM;
2847 goto free_udc;
2848 }
2849
2850 udc->td_pool = dma_pool_create("ci13xxx_td", dev,
2851 sizeof(struct ci13xxx_td),
2852 64, CI13XXX_PAGE_SIZE);
2853 if (udc->td_pool == NULL) {
2854 retval = -ENOMEM;
2855 goto free_qh_pool;
2856 }
2857
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03002858 retval = hw_device_init(udc, regs, driver->capoffset);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302859 if (retval < 0)
Alexander Shishkin790c2d52012-05-08 23:29:03 +03002860 goto free_pools;
2861
2862 retval = init_eps(udc);
2863 if (retval)
2864 goto free_pools;
2865
2866 udc->gadget.ep0 = &udc->ep0in->ep;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302867
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002868 udc->transceiver = usb_get_transceiver();
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302869
2870 if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
2871 if (udc->transceiver == NULL) {
2872 retval = -ENODEV;
Alexander Shishkin790c2d52012-05-08 23:29:03 +03002873 goto free_pools;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302874 }
2875 }
2876
2877 if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) {
2878 retval = hw_device_reset(udc);
2879 if (retval)
2880 goto put_transceiver;
2881 }
2882
David Lopoaa69a802008-11-17 14:14:51 -08002883 retval = device_register(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302884 if (retval) {
2885 put_device(&udc->gadget.dev);
2886 goto put_transceiver;
2887 }
David Lopoaa69a802008-11-17 14:14:51 -08002888
2889#ifdef CONFIG_USB_GADGET_DEBUG_FILES
2890 retval = dbg_create_files(&udc->gadget.dev);
2891#endif
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302892 if (retval)
2893 goto unreg_device;
2894
2895 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02002896 retval = otg_set_peripheral(udc->transceiver->otg,
2897 &udc->gadget);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302898 if (retval)
2899 goto remove_dbg;
David Lopoaa69a802008-11-17 14:14:51 -08002900 }
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002901
2902 retval = usb_add_gadget_udc(dev, &udc->gadget);
2903 if (retval)
2904 goto remove_trans;
2905
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302906 pm_runtime_no_callbacks(&udc->gadget.dev);
2907 pm_runtime_enable(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08002908
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002909 *_udc = udc;
David Lopoaa69a802008-11-17 14:14:51 -08002910 return retval;
2911
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002912remove_trans:
2913 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02002914 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002915 usb_put_transceiver(udc->transceiver);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002916 }
2917
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07002918 dev_err(dev, "error = %i\n", retval);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302919remove_dbg:
2920#ifdef CONFIG_USB_GADGET_DEBUG_FILES
2921 dbg_remove_files(&udc->gadget.dev);
2922#endif
2923unreg_device:
2924 device_unregister(&udc->gadget.dev);
2925put_transceiver:
2926 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002927 usb_put_transceiver(udc->transceiver);
Alexander Shishkin790c2d52012-05-08 23:29:03 +03002928free_pools:
2929 dma_pool_destroy(udc->td_pool);
2930free_qh_pool:
2931 dma_pool_destroy(udc->qh_pool);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302932free_udc:
David Lopoaa69a802008-11-17 14:14:51 -08002933 kfree(udc);
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002934 *_udc = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002935 return retval;
2936}
2937
2938/**
2939 * udc_remove: parent remove must call this to remove UDC
2940 *
2941 * No interrupts active, the IRQ has been released
2942 */
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002943static void udc_remove(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -08002944{
Alexander Shishkin790c2d52012-05-08 23:29:03 +03002945 int i;
David Lopoaa69a802008-11-17 14:14:51 -08002946
Alexander Shishkin0f089092012-05-08 23:29:02 +03002947 if (udc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002948 return;
Alexander Shishkin0f089092012-05-08 23:29:02 +03002949
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002950 usb_del_gadget_udc(&udc->gadget);
David Lopoaa69a802008-11-17 14:14:51 -08002951
Alexander Shishkin790c2d52012-05-08 23:29:03 +03002952 for (i = 0; i < udc->hw_ep_max; i++) {
2953 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
2954
2955 dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
2956 }
2957
2958 dma_pool_destroy(udc->td_pool);
2959 dma_pool_destroy(udc->qh_pool);
2960
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302961 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02002962 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002963 usb_put_transceiver(udc->transceiver);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302964 }
David Lopoaa69a802008-11-17 14:14:51 -08002965#ifdef CONFIG_USB_GADGET_DEBUG_FILES
2966 dbg_remove_files(&udc->gadget.dev);
2967#endif
2968 device_unregister(&udc->gadget.dev);
2969
Alexander Shishkin262c1632012-05-08 23:28:59 +03002970 kfree(udc->hw_bank.regmap);
David Lopoaa69a802008-11-17 14:14:51 -08002971 kfree(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002972}
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03002973
2974static int __devinit ci_udc_probe(struct platform_device *pdev)
2975{
2976 struct device *dev = &pdev->dev;
2977 struct ci13xxx_udc_driver *driver = dev->platform_data;
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002978 struct ci13xxx *udc;
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03002979 struct resource *res;
2980 void __iomem *base;
2981 int ret;
2982
2983 if (!driver) {
2984 dev_err(dev, "platform data missing\n");
2985 return -ENODEV;
2986 }
2987
2988 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2989 if (!res) {
2990 dev_err(dev, "missing resource\n");
2991 return -ENODEV;
2992 }
2993
2994 base = devm_request_and_ioremap(dev, res);
2995 if (!res) {
2996 dev_err(dev, "can't request and ioremap resource\n");
2997 return -ENOMEM;
2998 }
2999
Alexander Shishkin1f339d82012-05-08 23:29:04 +03003000 ret = udc_probe(driver, dev, base, &udc);
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03003001 if (ret)
3002 return ret;
3003
Alexander Shishkin1f339d82012-05-08 23:29:04 +03003004 udc->irq = platform_get_irq(pdev, 0);
3005 if (udc->irq < 0) {
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03003006 dev_err(dev, "missing IRQ\n");
3007 ret = -ENODEV;
3008 goto out;
3009 }
3010
Alexander Shishkin1f339d82012-05-08 23:29:04 +03003011 platform_set_drvdata(pdev, udc);
3012 ret = request_irq(udc->irq, udc_irq, IRQF_SHARED, driver->name, udc);
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03003013
3014out:
3015 if (ret)
Alexander Shishkin1f339d82012-05-08 23:29:04 +03003016 udc_remove(udc);
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03003017
3018 return ret;
3019}
3020
3021static int __devexit ci_udc_remove(struct platform_device *pdev)
3022{
Alexander Shishkin1f339d82012-05-08 23:29:04 +03003023 struct ci13xxx *udc = platform_get_drvdata(pdev);
3024
3025 free_irq(udc->irq, udc);
3026 udc_remove(udc);
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03003027
3028 return 0;
3029}
3030
3031static struct platform_driver ci_udc_driver = {
3032 .probe = ci_udc_probe,
3033 .remove = __devexit_p(ci_udc_remove),
3034 .driver = {
3035 .name = "ci_udc",
3036 },
3037};
3038
3039module_platform_driver(ci_udc_driver);
3040
3041MODULE_ALIAS("platform:ci_udc");
3042MODULE_ALIAS("platform:ci13xxx");
3043MODULE_LICENSE("GPL v2");
3044MODULE_AUTHOR("David Lopo <dlopo@chipidea.mips.com>");
3045MODULE_DESCRIPTION("ChipIdea UDC Driver");