blob: 6d2d65405ced7ed965427ed23cf9cf07cf2a3e13 [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 *
Alexander Shishkinef15e542012-05-11 17:25:43 +0300725 * This function explicitly sets the address, without the "USBADRA" (advance)
726 * feature, which is not supported by older versions of the controller.
David Lopoaa69a802008-11-17 14:14:51 -0800727 */
Alexander Shishkinef15e542012-05-11 17:25:43 +0300728static void hw_usb_set_address(struct ci13xxx *udc, u8 value)
David Lopoaa69a802008-11-17 14:14:51 -0800729{
Alexander Shishkinef15e542012-05-11 17:25:43 +0300730 hw_write(udc, OP_DEVICEADDR, DEVICEADDR_USBADR,
731 value << ffs_nr(DEVICEADDR_USBADR));
David Lopoaa69a802008-11-17 14:14:51 -0800732}
733
734/**
735 * hw_usb_reset: restart device after a bus reset (execute without
736 * interruption)
737 *
738 * This function returns an error code
739 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300740static int hw_usb_reset(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800741{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300742 hw_usb_set_address(udc, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800743
744 /* ESS flushes only at end?!? */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300745 hw_write(udc, OP_ENDPTFLUSH, ~0, ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800746
747 /* clear setup token semaphores */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300748 hw_write(udc, OP_ENDPTSETUPSTAT, 0, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800749
750 /* clear complete status */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300751 hw_write(udc, OP_ENDPTCOMPLETE, 0, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800752
753 /* wait until all bits cleared */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300754 while (hw_read(udc, OP_ENDPTPRIME, ~0))
David Lopoaa69a802008-11-17 14:14:51 -0800755 udelay(10); /* not RTOS friendly */
756
757 /* reset all endpoints ? */
758
759 /* reset internal status and wait for further instructions
760 no need to verify the port reset status (ESS does it) */
761
762 return 0;
763}
764
765/******************************************************************************
766 * DBG block
767 *****************************************************************************/
768/**
769 * show_device: prints information about device capabilities and status
770 *
771 * Check "device.h" for details
772 */
773static ssize_t show_device(struct device *dev, struct device_attribute *attr,
774 char *buf)
775{
776 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
777 struct usb_gadget *gadget = &udc->gadget;
778 int n = 0;
779
David Lopoaa69a802008-11-17 14:14:51 -0800780 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +0300781 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -0800782 return 0;
783 }
784
785 n += scnprintf(buf + n, PAGE_SIZE - n, "speed = %d\n",
786 gadget->speed);
Michal Nazarewiczd327ab52011-11-19 18:27:37 +0100787 n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed = %d\n",
788 gadget->max_speed);
789 /* TODO: Scheduled for removal in 3.8. */
David Lopoaa69a802008-11-17 14:14:51 -0800790 n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed = %d\n",
Michal Nazarewiczd327ab52011-11-19 18:27:37 +0100791 gadget_is_dualspeed(gadget));
David Lopoaa69a802008-11-17 14:14:51 -0800792 n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg = %d\n",
793 gadget->is_otg);
794 n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral = %d\n",
795 gadget->is_a_peripheral);
796 n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable = %d\n",
797 gadget->b_hnp_enable);
798 n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support = %d\n",
799 gadget->a_hnp_support);
800 n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n",
801 gadget->a_alt_hnp_support);
802 n += scnprintf(buf + n, PAGE_SIZE - n, "name = %s\n",
803 (gadget->name ? gadget->name : ""));
804
805 return n;
806}
807static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
808
809/**
810 * show_driver: prints information about attached gadget (if any)
811 *
812 * Check "device.h" for details
813 */
814static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
815 char *buf)
816{
817 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
818 struct usb_gadget_driver *driver = udc->driver;
819 int n = 0;
820
David Lopoaa69a802008-11-17 14:14:51 -0800821 if (attr == NULL || buf == NULL) {
822 dev_err(dev, "[%s] EINVAL\n", __func__);
823 return 0;
824 }
825
826 if (driver == NULL)
827 return scnprintf(buf, PAGE_SIZE,
828 "There is no gadget attached!\n");
829
830 n += scnprintf(buf + n, PAGE_SIZE - n, "function = %s\n",
831 (driver->function ? driver->function : ""));
832 n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n",
Michal Nazarewicz7177aed2011-11-19 18:27:38 +0100833 driver->max_speed);
David Lopoaa69a802008-11-17 14:14:51 -0800834
835 return n;
836}
837static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL);
838
839/* Maximum event message length */
840#define DBG_DATA_MSG 64UL
841
842/* Maximum event messages */
843#define DBG_DATA_MAX 128UL
844
845/* Event buffer descriptor */
846static struct {
847 char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */
848 unsigned idx; /* index */
849 unsigned tty; /* print to console? */
850 rwlock_t lck; /* lock */
851} dbg_data = {
852 .idx = 0,
853 .tty = 0,
854 .lck = __RW_LOCK_UNLOCKED(lck)
855};
856
857/**
858 * dbg_dec: decrements debug event index
859 * @idx: buffer index
860 */
861static void dbg_dec(unsigned *idx)
862{
863 *idx = (*idx - 1) & (DBG_DATA_MAX-1);
864}
865
866/**
867 * dbg_inc: increments debug event index
868 * @idx: buffer index
869 */
870static void dbg_inc(unsigned *idx)
871{
872 *idx = (*idx + 1) & (DBG_DATA_MAX-1);
873}
874
875/**
876 * dbg_print: prints the common part of the event
877 * @addr: endpoint address
878 * @name: event name
879 * @status: status
880 * @extra: extra information
881 */
882static void dbg_print(u8 addr, const char *name, int status, const char *extra)
883{
884 struct timeval tval;
885 unsigned int stamp;
886 unsigned long flags;
887
888 write_lock_irqsave(&dbg_data.lck, flags);
889
890 do_gettimeofday(&tval);
891 stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s */
892 stamp = stamp * 1000000 + tval.tv_usec;
893
894 scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +0300895 "%04X\t? %02X %-7.7s %4i ?\t%s\n",
David Lopoaa69a802008-11-17 14:14:51 -0800896 stamp, addr, name, status, extra);
897
898 dbg_inc(&dbg_data.idx);
899
900 write_unlock_irqrestore(&dbg_data.lck, flags);
901
902 if (dbg_data.tty != 0)
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +0300903 pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n",
David Lopoaa69a802008-11-17 14:14:51 -0800904 stamp, addr, name, status, extra);
905}
906
907/**
908 * dbg_done: prints a DONE event
909 * @addr: endpoint address
910 * @td: transfer descriptor
911 * @status: status
912 */
913static void dbg_done(u8 addr, const u32 token, int status)
914{
915 char msg[DBG_DATA_MSG];
916
917 scnprintf(msg, sizeof(msg), "%d %02X",
918 (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES),
919 (int)(token & TD_STATUS) >> ffs_nr(TD_STATUS));
920 dbg_print(addr, "DONE", status, msg);
921}
922
923/**
924 * dbg_event: prints a generic event
925 * @addr: endpoint address
926 * @name: event name
927 * @status: status
928 */
929static void dbg_event(u8 addr, const char *name, int status)
930{
931 if (name != NULL)
932 dbg_print(addr, name, status, "");
933}
934
935/*
936 * dbg_queue: prints a QUEUE event
937 * @addr: endpoint address
938 * @req: USB request
939 * @status: status
940 */
941static void dbg_queue(u8 addr, const struct usb_request *req, int status)
942{
943 char msg[DBG_DATA_MSG];
944
945 if (req != NULL) {
946 scnprintf(msg, sizeof(msg),
947 "%d %d", !req->no_interrupt, req->length);
948 dbg_print(addr, "QUEUE", status, msg);
949 }
950}
951
952/**
953 * dbg_setup: prints a SETUP event
954 * @addr: endpoint address
955 * @req: setup request
956 */
957static void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
958{
959 char msg[DBG_DATA_MSG];
960
961 if (req != NULL) {
962 scnprintf(msg, sizeof(msg),
963 "%02X %02X %04X %04X %d", req->bRequestType,
964 req->bRequest, le16_to_cpu(req->wValue),
965 le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
966 dbg_print(addr, "SETUP", 0, msg);
967 }
968}
969
970/**
971 * show_events: displays the event buffer
972 *
973 * Check "device.h" for details
974 */
975static ssize_t show_events(struct device *dev, struct device_attribute *attr,
976 char *buf)
977{
978 unsigned long flags;
979 unsigned i, j, n = 0;
980
David Lopoaa69a802008-11-17 14:14:51 -0800981 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +0300982 dev_err(dev->parent, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -0800983 return 0;
984 }
985
986 read_lock_irqsave(&dbg_data.lck, flags);
987
988 i = dbg_data.idx;
989 for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) {
990 n += strlen(dbg_data.buf[i]);
991 if (n >= PAGE_SIZE) {
992 n -= strlen(dbg_data.buf[i]);
993 break;
994 }
995 }
996 for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i))
997 j += scnprintf(buf + j, PAGE_SIZE - j,
998 "%s", dbg_data.buf[i]);
999
1000 read_unlock_irqrestore(&dbg_data.lck, flags);
1001
1002 return n;
1003}
1004
1005/**
1006 * store_events: configure if events are going to be also printed to console
1007 *
1008 * Check "device.h" for details
1009 */
1010static ssize_t store_events(struct device *dev, struct device_attribute *attr,
1011 const char *buf, size_t count)
1012{
1013 unsigned tty;
1014
David Lopoaa69a802008-11-17 14:14:51 -08001015 if (attr == NULL || buf == NULL) {
1016 dev_err(dev, "[%s] EINVAL\n", __func__);
1017 goto done;
1018 }
1019
1020 if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
1021 dev_err(dev, "<1|0>: enable|disable console log\n");
1022 goto done;
1023 }
1024
1025 dbg_data.tty = tty;
1026 dev_info(dev, "tty = %u", dbg_data.tty);
1027
1028 done:
1029 return count;
1030}
1031static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
1032
1033/**
1034 * show_inters: interrupt status, enable status and historic
1035 *
1036 * Check "device.h" for details
1037 */
1038static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
1039 char *buf)
1040{
1041 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1042 unsigned long flags;
1043 u32 intr;
1044 unsigned i, j, n = 0;
1045
David Lopoaa69a802008-11-17 14:14:51 -08001046 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001047 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -08001048 return 0;
1049 }
1050
Alexander Shishkind3595d12012-05-08 23:28:58 +03001051 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001052
1053 n += scnprintf(buf + n, PAGE_SIZE - n,
Alexander Shishkind3595d12012-05-08 23:28:58 +03001054 "status = %08x\n", hw_read_intr_status(udc));
David Lopoaa69a802008-11-17 14:14:51 -08001055 n += scnprintf(buf + n, PAGE_SIZE - n,
Alexander Shishkind3595d12012-05-08 23:28:58 +03001056 "enable = %08x\n", hw_read_intr_enable(udc));
David Lopoaa69a802008-11-17 14:14:51 -08001057
1058 n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
1059 isr_statistics.test);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001060 n += scnprintf(buf + n, PAGE_SIZE - n, "? ui = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001061 isr_statistics.ui);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001062 n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001063 isr_statistics.uei);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001064 n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001065 isr_statistics.pci);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001066 n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001067 isr_statistics.uri);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001068 n += scnprintf(buf + n, PAGE_SIZE - n, "? sli = %d\n",
David Lopoaa69a802008-11-17 14:14:51 -08001069 isr_statistics.sli);
1070 n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n",
1071 isr_statistics.none);
1072 n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n",
1073 isr_statistics.hndl.cnt);
1074
1075 for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) {
1076 i &= ISR_MASK;
1077 intr = isr_statistics.hndl.buf[i];
1078
1079 if (USBi_UI & intr)
1080 n += scnprintf(buf + n, PAGE_SIZE - n, "ui ");
1081 intr &= ~USBi_UI;
1082 if (USBi_UEI & intr)
1083 n += scnprintf(buf + n, PAGE_SIZE - n, "uei ");
1084 intr &= ~USBi_UEI;
1085 if (USBi_PCI & intr)
1086 n += scnprintf(buf + n, PAGE_SIZE - n, "pci ");
1087 intr &= ~USBi_PCI;
1088 if (USBi_URI & intr)
1089 n += scnprintf(buf + n, PAGE_SIZE - n, "uri ");
1090 intr &= ~USBi_URI;
1091 if (USBi_SLI & intr)
1092 n += scnprintf(buf + n, PAGE_SIZE - n, "sli ");
1093 intr &= ~USBi_SLI;
1094 if (intr)
1095 n += scnprintf(buf + n, PAGE_SIZE - n, "??? ");
1096 if (isr_statistics.hndl.buf[i])
1097 n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
1098 }
1099
Alexander Shishkind3595d12012-05-08 23:28:58 +03001100 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001101
1102 return n;
1103}
1104
1105/**
1106 * store_inters: enable & force or disable an individual interrutps
1107 * (to be used for test purposes only)
1108 *
1109 * Check "device.h" for details
1110 */
1111static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
1112 const char *buf, size_t count)
1113{
1114 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1115 unsigned long flags;
1116 unsigned en, bit;
1117
David Lopoaa69a802008-11-17 14:14:51 -08001118 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001119 dev_err(udc->dev, "EINVAL\n");
David Lopoaa69a802008-11-17 14:14:51 -08001120 goto done;
1121 }
1122
1123 if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001124 dev_err(udc->dev, "<1|0> <bit>: enable|disable interrupt\n");
David Lopoaa69a802008-11-17 14:14:51 -08001125 goto done;
1126 }
1127
Alexander Shishkind3595d12012-05-08 23:28:58 +03001128 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001129 if (en) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001130 if (hw_intr_force(udc, bit))
David Lopoaa69a802008-11-17 14:14:51 -08001131 dev_err(dev, "invalid bit number\n");
1132 else
1133 isr_statistics.test++;
1134 } else {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001135 if (hw_intr_clear(udc, bit))
David Lopoaa69a802008-11-17 14:14:51 -08001136 dev_err(dev, "invalid bit number\n");
1137 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03001138 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001139
1140 done:
1141 return count;
1142}
1143static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
1144
1145/**
1146 * show_port_test: reads port test mode
1147 *
1148 * Check "device.h" for details
1149 */
1150static ssize_t show_port_test(struct device *dev,
1151 struct device_attribute *attr, char *buf)
1152{
1153 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1154 unsigned long flags;
1155 unsigned mode;
1156
David Lopoaa69a802008-11-17 14:14:51 -08001157 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001158 dev_err(udc->dev, "EINVAL\n");
David Lopoaa69a802008-11-17 14:14:51 -08001159 return 0;
1160 }
1161
Alexander Shishkind3595d12012-05-08 23:28:58 +03001162 spin_lock_irqsave(&udc->lock, flags);
1163 mode = hw_port_test_get(udc);
1164 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001165
1166 return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
1167}
1168
1169/**
1170 * store_port_test: writes port test mode
1171 *
1172 * Check "device.h" for details
1173 */
1174static ssize_t store_port_test(struct device *dev,
1175 struct device_attribute *attr,
1176 const char *buf, size_t count)
1177{
1178 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1179 unsigned long flags;
1180 unsigned mode;
1181
David Lopoaa69a802008-11-17 14:14:51 -08001182 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001183 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -08001184 goto done;
1185 }
1186
1187 if (sscanf(buf, "%u", &mode) != 1) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001188 dev_err(udc->dev, "<mode>: set port test mode");
David Lopoaa69a802008-11-17 14:14:51 -08001189 goto done;
1190 }
1191
Alexander Shishkind3595d12012-05-08 23:28:58 +03001192 spin_lock_irqsave(&udc->lock, flags);
1193 if (hw_port_test_set(udc, mode))
Alexander Shishkin0f089092012-05-08 23:29:02 +03001194 dev_err(udc->dev, "invalid mode\n");
Alexander Shishkind3595d12012-05-08 23:28:58 +03001195 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001196
1197 done:
1198 return count;
1199}
1200static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
1201 show_port_test, store_port_test);
1202
1203/**
1204 * show_qheads: DMA contents of all queue heads
1205 *
1206 * Check "device.h" for details
1207 */
1208static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
1209 char *buf)
1210{
1211 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1212 unsigned long flags;
1213 unsigned i, j, n = 0;
1214
David Lopoaa69a802008-11-17 14:14:51 -08001215 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001216 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -08001217 return 0;
1218 }
1219
Alexander Shishkind3595d12012-05-08 23:28:58 +03001220 spin_lock_irqsave(&udc->lock, flags);
1221 for (i = 0; i < udc->hw_ep_max/2; i++) {
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301222 struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i];
Alexander Shishkind3595d12012-05-08 23:28:58 +03001223 struct ci13xxx_ep *mEpTx =
1224 &udc->ci13xxx_ep[i + udc->hw_ep_max/2];
David Lopoaa69a802008-11-17 14:14:51 -08001225 n += scnprintf(buf + n, PAGE_SIZE - n,
1226 "EP=%02i: RX=%08X TX=%08X\n",
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301227 i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
David Lopoaa69a802008-11-17 14:14:51 -08001228 for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) {
1229 n += scnprintf(buf + n, PAGE_SIZE - n,
1230 " %04X: %08X %08X\n", j,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301231 *((u32 *)mEpRx->qh.ptr + j),
1232 *((u32 *)mEpTx->qh.ptr + j));
David Lopoaa69a802008-11-17 14:14:51 -08001233 }
1234 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03001235 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001236
1237 return n;
1238}
1239static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
1240
1241/**
1242 * show_registers: dumps all registers
1243 *
1244 * Check "device.h" for details
1245 */
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001246#define DUMP_ENTRIES 512
David Lopoaa69a802008-11-17 14:14:51 -08001247static ssize_t show_registers(struct device *dev,
1248 struct device_attribute *attr, char *buf)
1249{
1250 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1251 unsigned long flags;
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001252 u32 *dump;
David Lopoaa69a802008-11-17 14:14:51 -08001253 unsigned i, k, n = 0;
1254
David Lopoaa69a802008-11-17 14:14:51 -08001255 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001256 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -08001257 return 0;
1258 }
1259
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001260 dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
1261 if (!dump) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001262 dev_err(udc->dev, "%s: out of memory\n", __func__);
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001263 return 0;
1264 }
1265
Alexander Shishkind3595d12012-05-08 23:28:58 +03001266 spin_lock_irqsave(&udc->lock, flags);
1267 k = hw_register_read(udc, dump, DUMP_ENTRIES);
1268 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001269
1270 for (i = 0; i < k; i++) {
1271 n += scnprintf(buf + n, PAGE_SIZE - n,
1272 "reg[0x%04X] = 0x%08X\n",
1273 i * (unsigned)sizeof(u32), dump[i]);
1274 }
Sebastian Andrzej Siewiorc2b65f82011-07-05 15:57:52 +03001275 kfree(dump);
David Lopoaa69a802008-11-17 14:14:51 -08001276
1277 return n;
1278}
1279
1280/**
1281 * store_registers: writes value to register address
1282 *
1283 * Check "device.h" for details
1284 */
1285static ssize_t store_registers(struct device *dev,
1286 struct device_attribute *attr,
1287 const char *buf, size_t count)
1288{
1289 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1290 unsigned long addr, data, flags;
1291
David Lopoaa69a802008-11-17 14:14:51 -08001292 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001293 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -08001294 goto done;
1295 }
1296
1297 if (sscanf(buf, "%li %li", &addr, &data) != 2) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001298 dev_err(udc->dev,
1299 "<addr> <data>: write data to register address\n");
David Lopoaa69a802008-11-17 14:14:51 -08001300 goto done;
1301 }
1302
Alexander Shishkind3595d12012-05-08 23:28:58 +03001303 spin_lock_irqsave(&udc->lock, flags);
1304 if (hw_register_write(udc, addr, data))
Alexander Shishkin0f089092012-05-08 23:29:02 +03001305 dev_err(udc->dev, "invalid address range\n");
Alexander Shishkind3595d12012-05-08 23:28:58 +03001306 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001307
1308 done:
1309 return count;
1310}
1311static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
1312 show_registers, store_registers);
1313
1314/**
1315 * show_requests: DMA contents of all requests currently queued (all endpts)
1316 *
1317 * Check "device.h" for details
1318 */
1319static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
1320 char *buf)
1321{
1322 struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
1323 unsigned long flags;
1324 struct list_head *ptr = NULL;
1325 struct ci13xxx_req *req = NULL;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301326 unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
David Lopoaa69a802008-11-17 14:14:51 -08001327
David Lopoaa69a802008-11-17 14:14:51 -08001328 if (attr == NULL || buf == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001329 dev_err(udc->dev, "[%s] EINVAL\n", __func__);
David Lopoaa69a802008-11-17 14:14:51 -08001330 return 0;
1331 }
1332
Alexander Shishkind3595d12012-05-08 23:28:58 +03001333 spin_lock_irqsave(&udc->lock, flags);
1334 for (i = 0; i < udc->hw_ep_max; i++)
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301335 list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue)
1336 {
1337 req = list_entry(ptr, struct ci13xxx_req, queue);
David Lopoaa69a802008-11-17 14:14:51 -08001338
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301339 n += scnprintf(buf + n, PAGE_SIZE - n,
1340 "EP=%02i: TD=%08X %s\n",
Alexander Shishkind3595d12012-05-08 23:28:58 +03001341 i % udc->hw_ep_max/2, (u32)req->dma,
1342 ((i < udc->hw_ep_max/2) ? "RX" : "TX"));
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301343
1344 for (j = 0; j < qSize; j++)
David Lopoaa69a802008-11-17 14:14:51 -08001345 n += scnprintf(buf + n, PAGE_SIZE - n,
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301346 " %04X: %08X\n", j,
1347 *((u32 *)req->ptr + j));
1348 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03001349 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001350
1351 return n;
1352}
1353static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL);
1354
1355/**
1356 * dbg_create_files: initializes the attribute interface
1357 * @dev: device
1358 *
1359 * This function returns an error code
1360 */
1361__maybe_unused static int dbg_create_files(struct device *dev)
1362{
1363 int retval = 0;
1364
1365 if (dev == NULL)
1366 return -EINVAL;
1367 retval = device_create_file(dev, &dev_attr_device);
1368 if (retval)
1369 goto done;
1370 retval = device_create_file(dev, &dev_attr_driver);
1371 if (retval)
1372 goto rm_device;
1373 retval = device_create_file(dev, &dev_attr_events);
1374 if (retval)
1375 goto rm_driver;
1376 retval = device_create_file(dev, &dev_attr_inters);
1377 if (retval)
1378 goto rm_events;
1379 retval = device_create_file(dev, &dev_attr_port_test);
1380 if (retval)
1381 goto rm_inters;
1382 retval = device_create_file(dev, &dev_attr_qheads);
1383 if (retval)
1384 goto rm_port_test;
1385 retval = device_create_file(dev, &dev_attr_registers);
1386 if (retval)
1387 goto rm_qheads;
1388 retval = device_create_file(dev, &dev_attr_requests);
1389 if (retval)
1390 goto rm_registers;
1391 return 0;
1392
1393 rm_registers:
1394 device_remove_file(dev, &dev_attr_registers);
1395 rm_qheads:
1396 device_remove_file(dev, &dev_attr_qheads);
1397 rm_port_test:
1398 device_remove_file(dev, &dev_attr_port_test);
1399 rm_inters:
1400 device_remove_file(dev, &dev_attr_inters);
1401 rm_events:
1402 device_remove_file(dev, &dev_attr_events);
1403 rm_driver:
1404 device_remove_file(dev, &dev_attr_driver);
1405 rm_device:
1406 device_remove_file(dev, &dev_attr_device);
1407 done:
1408 return retval;
1409}
1410
1411/**
1412 * dbg_remove_files: destroys the attribute interface
1413 * @dev: device
1414 *
1415 * This function returns an error code
1416 */
1417__maybe_unused static int dbg_remove_files(struct device *dev)
1418{
1419 if (dev == NULL)
1420 return -EINVAL;
1421 device_remove_file(dev, &dev_attr_requests);
1422 device_remove_file(dev, &dev_attr_registers);
1423 device_remove_file(dev, &dev_attr_qheads);
1424 device_remove_file(dev, &dev_attr_port_test);
1425 device_remove_file(dev, &dev_attr_inters);
1426 device_remove_file(dev, &dev_attr_events);
1427 device_remove_file(dev, &dev_attr_driver);
1428 device_remove_file(dev, &dev_attr_device);
1429 return 0;
1430}
1431
1432/******************************************************************************
1433 * UTIL block
1434 *****************************************************************************/
1435/**
1436 * _usb_addr: calculates endpoint address from direction & number
1437 * @ep: endpoint
1438 */
1439static inline u8 _usb_addr(struct ci13xxx_ep *ep)
1440{
1441 return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num;
1442}
1443
1444/**
1445 * _hardware_queue: configures a request at hardware level
1446 * @gadget: gadget
1447 * @mEp: endpoint
1448 *
1449 * This function returns an error code
1450 */
1451static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1452{
Alexander Shishkind3595d12012-05-08 23:28:58 +03001453 struct ci13xxx *udc = mEp->udc;
David Lopoaa69a802008-11-17 14:14:51 -08001454 unsigned i;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301455 int ret = 0;
1456 unsigned length = mReq->req.length;
David Lopoaa69a802008-11-17 14:14:51 -08001457
David Lopoaa69a802008-11-17 14:14:51 -08001458 /* don't queue twice */
1459 if (mReq->req.status == -EALREADY)
1460 return -EALREADY;
1461
David Lopoaa69a802008-11-17 14:14:51 -08001462 mReq->req.status = -EALREADY;
Michael Grzeschik954aad82011-10-10 18:38:06 +02001463 if (length && mReq->req.dma == DMA_ADDR_INVALID) {
David Lopoaa69a802008-11-17 14:14:51 -08001464 mReq->req.dma = \
1465 dma_map_single(mEp->device, mReq->req.buf,
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301466 length, mEp->dir ? DMA_TO_DEVICE :
1467 DMA_FROM_DEVICE);
David Lopoaa69a802008-11-17 14:14:51 -08001468 if (mReq->req.dma == 0)
1469 return -ENOMEM;
1470
1471 mReq->map = 1;
1472 }
1473
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301474 if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) {
1475 mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC,
1476 &mReq->zdma);
1477 if (mReq->zptr == NULL) {
1478 if (mReq->map) {
1479 dma_unmap_single(mEp->device, mReq->req.dma,
1480 length, mEp->dir ? DMA_TO_DEVICE :
1481 DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02001482 mReq->req.dma = DMA_ADDR_INVALID;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301483 mReq->map = 0;
1484 }
1485 return -ENOMEM;
1486 }
1487 memset(mReq->zptr, 0, sizeof(*mReq->zptr));
1488 mReq->zptr->next = TD_TERMINATE;
1489 mReq->zptr->token = TD_STATUS_ACTIVE;
1490 if (!mReq->req.no_interrupt)
1491 mReq->zptr->token |= TD_IOC;
1492 }
David Lopoaa69a802008-11-17 14:14:51 -08001493 /*
1494 * TD configuration
1495 * TODO - handle requests which spawns into several TDs
1496 */
1497 memset(mReq->ptr, 0, sizeof(*mReq->ptr));
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301498 mReq->ptr->token = length << ffs_nr(TD_TOTAL_BYTES);
David Lopoaa69a802008-11-17 14:14:51 -08001499 mReq->ptr->token &= TD_TOTAL_BYTES;
David Lopoaa69a802008-11-17 14:14:51 -08001500 mReq->ptr->token |= TD_STATUS_ACTIVE;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301501 if (mReq->zptr) {
1502 mReq->ptr->next = mReq->zdma;
1503 } else {
1504 mReq->ptr->next = TD_TERMINATE;
1505 if (!mReq->req.no_interrupt)
1506 mReq->ptr->token |= TD_IOC;
1507 }
David Lopoaa69a802008-11-17 14:14:51 -08001508 mReq->ptr->page[0] = mReq->req.dma;
1509 for (i = 1; i < 5; i++)
1510 mReq->ptr->page[i] =
Artem Leonenko0a313c42010-12-14 23:47:06 -08001511 (mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK;
David Lopoaa69a802008-11-17 14:14:51 -08001512
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301513 if (!list_empty(&mEp->qh.queue)) {
1514 struct ci13xxx_req *mReqPrev;
1515 int n = hw_ep_bit(mEp->num, mEp->dir);
1516 int tmp_stat;
1517
1518 mReqPrev = list_entry(mEp->qh.queue.prev,
1519 struct ci13xxx_req, queue);
1520 if (mReqPrev->zptr)
1521 mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
1522 else
1523 mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
1524 wmb();
Alexander Shishkin262c1632012-05-08 23:28:59 +03001525 if (hw_read(udc, OP_ENDPTPRIME, BIT(n)))
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301526 goto done;
1527 do {
Alexander Shishkin262c1632012-05-08 23:28:59 +03001528 hw_write(udc, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
1529 tmp_stat = hw_read(udc, OP_ENDPTSTAT, BIT(n));
1530 } while (!hw_read(udc, OP_USBCMD, USBCMD_ATDTW));
1531 hw_write(udc, OP_USBCMD, USBCMD_ATDTW, 0);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301532 if (tmp_stat)
1533 goto done;
1534 }
1535
1536 /* QH configuration */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301537 mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */
1538 mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301539 mEp->qh.ptr->cap |= QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08001540
1541 wmb(); /* synchronize before ep prime */
1542
Alexander Shishkind3595d12012-05-08 23:28:58 +03001543 ret = hw_ep_prime(udc, mEp->num, mEp->dir,
David Lopoaa69a802008-11-17 14:14:51 -08001544 mEp->type == USB_ENDPOINT_XFER_CONTROL);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301545done:
1546 return ret;
David Lopoaa69a802008-11-17 14:14:51 -08001547}
1548
1549/**
1550 * _hardware_dequeue: handles a request at hardware level
1551 * @gadget: gadget
1552 * @mEp: endpoint
1553 *
1554 * This function returns an error code
1555 */
1556static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
1557{
David Lopoaa69a802008-11-17 14:14:51 -08001558 if (mReq->req.status != -EALREADY)
1559 return -EINVAL;
1560
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301561 if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
1562 return -EBUSY;
1563
1564 if (mReq->zptr) {
1565 if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
1566 return -EBUSY;
1567 dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
1568 mReq->zptr = NULL;
1569 }
David Lopoaa69a802008-11-17 14:14:51 -08001570
1571 mReq->req.status = 0;
1572
1573 if (mReq->map) {
1574 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
1575 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02001576 mReq->req.dma = DMA_ADDR_INVALID;
David Lopoaa69a802008-11-17 14:14:51 -08001577 mReq->map = 0;
1578 }
1579
1580 mReq->req.status = mReq->ptr->token & TD_STATUS;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301581 if ((TD_STATUS_HALTED & mReq->req.status) != 0)
David Lopoaa69a802008-11-17 14:14:51 -08001582 mReq->req.status = -1;
1583 else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0)
1584 mReq->req.status = -1;
1585 else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0)
1586 mReq->req.status = -1;
1587
1588 mReq->req.actual = mReq->ptr->token & TD_TOTAL_BYTES;
1589 mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES);
1590 mReq->req.actual = mReq->req.length - mReq->req.actual;
1591 mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual;
1592
1593 return mReq->req.actual;
1594}
1595
1596/**
1597 * _ep_nuke: dequeues all endpoint requests
1598 * @mEp: endpoint
1599 *
1600 * This function returns an error code
1601 * Caller must hold lock
1602 */
1603static int _ep_nuke(struct ci13xxx_ep *mEp)
1604__releases(mEp->lock)
1605__acquires(mEp->lock)
1606{
David Lopoaa69a802008-11-17 14:14:51 -08001607 if (mEp == NULL)
1608 return -EINVAL;
1609
Alexander Shishkind3595d12012-05-08 23:28:58 +03001610 hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08001611
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301612 while (!list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -08001613
1614 /* pop oldest request */
1615 struct ci13xxx_req *mReq = \
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301616 list_entry(mEp->qh.queue.next,
David Lopoaa69a802008-11-17 14:14:51 -08001617 struct ci13xxx_req, queue);
1618 list_del_init(&mReq->queue);
1619 mReq->req.status = -ESHUTDOWN;
1620
Artem Leonenko7c25a822010-12-14 23:46:55 -08001621 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08001622 spin_unlock(mEp->lock);
1623 mReq->req.complete(&mEp->ep, &mReq->req);
1624 spin_lock(mEp->lock);
1625 }
1626 }
1627 return 0;
1628}
1629
1630/**
1631 * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
1632 * @gadget: gadget
1633 *
1634 * This function returns an error code
David Lopoaa69a802008-11-17 14:14:51 -08001635 */
1636static int _gadget_stop_activity(struct usb_gadget *gadget)
David Lopoaa69a802008-11-17 14:14:51 -08001637{
1638 struct usb_ep *ep;
1639 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301640 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -08001641
David Lopoaa69a802008-11-17 14:14:51 -08001642 if (gadget == NULL)
1643 return -EINVAL;
1644
Alexander Shishkind3595d12012-05-08 23:28:58 +03001645 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301646 udc->gadget.speed = USB_SPEED_UNKNOWN;
1647 udc->remote_wakeup = 0;
1648 udc->suspended = 0;
Alexander Shishkind3595d12012-05-08 23:28:58 +03001649 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301650
David Lopoaa69a802008-11-17 14:14:51 -08001651 /* flush all endpoints */
1652 gadget_for_each_ep(ep, gadget) {
1653 usb_ep_fifo_flush(ep);
1654 }
Alexander Shishkind36ade62012-05-04 16:47:15 +03001655 usb_ep_fifo_flush(&udc->ep0out->ep);
1656 usb_ep_fifo_flush(&udc->ep0in->ep);
David Lopoaa69a802008-11-17 14:14:51 -08001657
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001658 if (udc->driver)
1659 udc->driver->disconnect(gadget);
David Lopoaa69a802008-11-17 14:14:51 -08001660
1661 /* make sure to disable all endpoints */
1662 gadget_for_each_ep(ep, gadget) {
1663 usb_ep_disable(ep);
1664 }
David Lopoaa69a802008-11-17 14:14:51 -08001665
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301666 if (udc->status != NULL) {
Alexander Shishkind36ade62012-05-04 16:47:15 +03001667 usb_ep_free_request(&udc->ep0in->ep, udc->status);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301668 udc->status = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08001669 }
1670
David Lopoaa69a802008-11-17 14:14:51 -08001671 return 0;
1672}
1673
1674/******************************************************************************
1675 * ISR block
1676 *****************************************************************************/
1677/**
1678 * isr_reset_handler: USB reset interrupt handler
1679 * @udc: UDC device
1680 *
1681 * This function resets USB engine after a bus reset occurred
1682 */
1683static void isr_reset_handler(struct ci13xxx *udc)
1684__releases(udc->lock)
1685__acquires(udc->lock)
1686{
David Lopoaa69a802008-11-17 14:14:51 -08001687 int retval;
1688
David Lopoaa69a802008-11-17 14:14:51 -08001689 dbg_event(0xFF, "BUS RST", 0);
1690
Alexander Shishkind3595d12012-05-08 23:28:58 +03001691 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001692 retval = _gadget_stop_activity(&udc->gadget);
1693 if (retval)
1694 goto done;
1695
Alexander Shishkind3595d12012-05-08 23:28:58 +03001696 retval = hw_usb_reset(udc);
David Lopoaa69a802008-11-17 14:14:51 -08001697 if (retval)
1698 goto done;
1699
Alexander Shishkind36ade62012-05-04 16:47:15 +03001700 udc->status = usb_ep_alloc_request(&udc->ep0in->ep, GFP_ATOMIC);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05301701 if (udc->status == NULL)
1702 retval = -ENOMEM;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301703
Alexander Shishkind3595d12012-05-08 23:28:58 +03001704 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001705
1706 done:
1707 if (retval)
Alexander Shishkin0f089092012-05-08 23:29:02 +03001708 dev_err(udc->dev, "error: %i\n", retval);
David Lopoaa69a802008-11-17 14:14:51 -08001709}
1710
1711/**
1712 * isr_get_status_complete: get_status request complete function
1713 * @ep: endpoint
1714 * @req: request handled
1715 *
1716 * Caller must release lock
1717 */
1718static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
1719{
Alexander Shishkin0f089092012-05-08 23:29:02 +03001720 if (ep == NULL || req == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001721 return;
David Lopoaa69a802008-11-17 14:14:51 -08001722
1723 kfree(req->buf);
1724 usb_ep_free_request(ep, req);
1725}
1726
1727/**
1728 * isr_get_status_response: get_status request response
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301729 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08001730 * @setup: setup request packet
1731 *
1732 * This function returns an error code
1733 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301734static int isr_get_status_response(struct ci13xxx *udc,
David Lopoaa69a802008-11-17 14:14:51 -08001735 struct usb_ctrlrequest *setup)
1736__releases(mEp->lock)
1737__acquires(mEp->lock)
1738{
Alexander Shishkind36ade62012-05-04 16:47:15 +03001739 struct ci13xxx_ep *mEp = udc->ep0in;
David Lopoaa69a802008-11-17 14:14:51 -08001740 struct usb_request *req = NULL;
1741 gfp_t gfp_flags = GFP_ATOMIC;
1742 int dir, num, retval;
1743
David Lopoaa69a802008-11-17 14:14:51 -08001744 if (mEp == NULL || setup == NULL)
1745 return -EINVAL;
1746
1747 spin_unlock(mEp->lock);
1748 req = usb_ep_alloc_request(&mEp->ep, gfp_flags);
1749 spin_lock(mEp->lock);
1750 if (req == NULL)
1751 return -ENOMEM;
1752
1753 req->complete = isr_get_status_complete;
1754 req->length = 2;
1755 req->buf = kzalloc(req->length, gfp_flags);
1756 if (req->buf == NULL) {
1757 retval = -ENOMEM;
1758 goto err_free_req;
1759 }
1760
1761 if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301762 /* Assume that device is bus powered for now. */
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001763 *(u16 *)req->buf = udc->remote_wakeup << 1;
David Lopoaa69a802008-11-17 14:14:51 -08001764 retval = 0;
1765 } else if ((setup->bRequestType & USB_RECIP_MASK) \
1766 == USB_RECIP_ENDPOINT) {
1767 dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
1768 TX : RX;
1769 num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK;
Alexander Shishkind3595d12012-05-08 23:28:58 +03001770 *(u16 *)req->buf = hw_ep_get_halt(udc, num, dir);
David Lopoaa69a802008-11-17 14:14:51 -08001771 }
1772 /* else do nothing; reserved for future use */
1773
1774 spin_unlock(mEp->lock);
1775 retval = usb_ep_queue(&mEp->ep, req, gfp_flags);
1776 spin_lock(mEp->lock);
1777 if (retval)
1778 goto err_free_buf;
1779
1780 return 0;
1781
1782 err_free_buf:
1783 kfree(req->buf);
1784 err_free_req:
1785 spin_unlock(mEp->lock);
1786 usb_ep_free_request(&mEp->ep, req);
1787 spin_lock(mEp->lock);
1788 return retval;
1789}
1790
1791/**
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301792 * isr_setup_status_complete: setup_status request complete function
1793 * @ep: endpoint
1794 * @req: request handled
1795 *
1796 * Caller must release lock. Put the port in test mode if test mode
1797 * feature is selected.
1798 */
1799static void
1800isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
1801{
1802 struct ci13xxx *udc = req->context;
1803 unsigned long flags;
1804
Alexander Shishkinef15e542012-05-11 17:25:43 +03001805 if (udc->setaddr) {
1806 hw_usb_set_address(udc, udc->address);
1807 udc->setaddr = false;
1808 }
1809
Alexander Shishkind3595d12012-05-08 23:28:58 +03001810 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301811 if (udc->test_mode)
Alexander Shishkind3595d12012-05-08 23:28:58 +03001812 hw_port_test_set(udc, udc->test_mode);
1813 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301814}
1815
1816/**
David Lopoaa69a802008-11-17 14:14:51 -08001817 * isr_setup_status_phase: queues the status phase of a setup transation
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301818 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -08001819 *
1820 * This function returns an error code
1821 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301822static int isr_setup_status_phase(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -08001823__releases(mEp->lock)
1824__acquires(mEp->lock)
1825{
1826 int retval;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301827 struct ci13xxx_ep *mEp;
David Lopoaa69a802008-11-17 14:14:51 -08001828
Alexander Shishkind36ade62012-05-04 16:47:15 +03001829 mEp = (udc->ep0_dir == TX) ? udc->ep0out : udc->ep0in;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301830 udc->status->context = udc;
1831 udc->status->complete = isr_setup_status_complete;
David Lopoaa69a802008-11-17 14:14:51 -08001832
1833 spin_unlock(mEp->lock);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301834 retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
David Lopoaa69a802008-11-17 14:14:51 -08001835 spin_lock(mEp->lock);
1836
1837 return retval;
1838}
1839
1840/**
1841 * isr_tr_complete_low: transaction complete low level handler
1842 * @mEp: endpoint
1843 *
1844 * This function returns an error code
1845 * Caller must hold lock
1846 */
1847static int isr_tr_complete_low(struct ci13xxx_ep *mEp)
1848__releases(mEp->lock)
1849__acquires(mEp->lock)
1850{
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301851 struct ci13xxx_req *mReq, *mReqTemp;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05301852 struct ci13xxx_ep *mEpTemp = mEp;
Pavankumar Kondeti986b11b2011-05-02 11:56:29 +05301853 int uninitialized_var(retval);
David Lopoaa69a802008-11-17 14:14:51 -08001854
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301855 if (list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08001856 return -EINVAL;
1857
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301858 list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,
1859 queue) {
1860 retval = _hardware_dequeue(mEp, mReq);
1861 if (retval < 0)
1862 break;
1863 list_del_init(&mReq->queue);
1864 dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
1865 if (mReq->req.complete != NULL) {
1866 spin_unlock(mEp->lock);
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05301867 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
1868 mReq->req.length)
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001869 mEpTemp = mEp->udc->ep0in;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05301870 mReq->req.complete(&mEpTemp->ep, &mReq->req);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301871 spin_lock(mEp->lock);
1872 }
1873 }
David Lopoaa69a802008-11-17 14:14:51 -08001874
Pavankumar Kondetief907482011-05-02 11:56:27 +05301875 if (retval == -EBUSY)
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301876 retval = 0;
1877 if (retval < 0)
David Lopoaa69a802008-11-17 14:14:51 -08001878 dbg_event(_usb_addr(mEp), "DONE", retval);
David Lopoaa69a802008-11-17 14:14:51 -08001879
David Lopoaa69a802008-11-17 14:14:51 -08001880 return retval;
1881}
1882
1883/**
1884 * isr_tr_complete_handler: transaction complete interrupt handler
1885 * @udc: UDC descriptor
1886 *
1887 * This function handles traffic events
1888 */
1889static void isr_tr_complete_handler(struct ci13xxx *udc)
1890__releases(udc->lock)
1891__acquires(udc->lock)
1892{
1893 unsigned i;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05301894 u8 tmode = 0;
David Lopoaa69a802008-11-17 14:14:51 -08001895
Alexander Shishkind3595d12012-05-08 23:28:58 +03001896 for (i = 0; i < udc->hw_ep_max; i++) {
David Lopoaa69a802008-11-17 14:14:51 -08001897 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05301898 int type, num, dir, err = -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -08001899 struct usb_ctrlrequest req;
1900
Ido Shayevitz31fb6012012-03-12 20:25:23 +02001901 if (mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001902 continue; /* not configured */
1903
Alexander Shishkind3595d12012-05-08 23:28:58 +03001904 if (hw_test_and_clear_complete(udc, i)) {
David Lopoaa69a802008-11-17 14:14:51 -08001905 err = isr_tr_complete_low(mEp);
1906 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
1907 if (err > 0) /* needs status phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301908 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08001909 if (err < 0) {
1910 dbg_event(_usb_addr(mEp),
1911 "ERROR", err);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001912 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001913 if (usb_ep_set_halt(&mEp->ep))
Alexander Shishkin0f089092012-05-08 23:29:02 +03001914 dev_err(udc->dev,
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07001915 "error: ep_set_halt\n");
Alexander Shishkind3595d12012-05-08 23:28:58 +03001916 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001917 }
1918 }
1919 }
1920
1921 if (mEp->type != USB_ENDPOINT_XFER_CONTROL ||
Alexander Shishkind3595d12012-05-08 23:28:58 +03001922 !hw_test_and_clear_setup_status(udc, i))
David Lopoaa69a802008-11-17 14:14:51 -08001923 continue;
1924
1925 if (i != 0) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001926 dev_warn(udc->dev, "ctrl traffic at endpoint %d\n", i);
David Lopoaa69a802008-11-17 14:14:51 -08001927 continue;
1928 }
1929
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301930 /*
1931 * Flush data and handshake transactions of previous
1932 * setup packet.
1933 */
Alexander Shishkind36ade62012-05-04 16:47:15 +03001934 _ep_nuke(udc->ep0out);
1935 _ep_nuke(udc->ep0in);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301936
David Lopoaa69a802008-11-17 14:14:51 -08001937 /* read_setup_packet */
1938 do {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001939 hw_test_and_set_setup_guard(udc);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301940 memcpy(&req, &mEp->qh.ptr->setup, sizeof(req));
Alexander Shishkind3595d12012-05-08 23:28:58 +03001941 } while (!hw_test_and_clear_setup_guard(udc));
David Lopoaa69a802008-11-17 14:14:51 -08001942
1943 type = req.bRequestType;
1944
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301945 udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
David Lopoaa69a802008-11-17 14:14:51 -08001946
1947 dbg_setup(_usb_addr(mEp), &req);
1948
1949 switch (req.bRequest) {
1950 case USB_REQ_CLEAR_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301951 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
1952 le16_to_cpu(req.wValue) ==
1953 USB_ENDPOINT_HALT) {
1954 if (req.wLength != 0)
David Lopoaa69a802008-11-17 14:14:51 -08001955 break;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301956 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05301957 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301958 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05301959 if (dir) /* TX */
Alexander Shishkind3595d12012-05-08 23:28:58 +03001960 num += udc->hw_ep_max/2;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301961 if (!udc->ci13xxx_ep[num].wedge) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001962 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301963 err = usb_ep_clear_halt(
1964 &udc->ci13xxx_ep[num].ep);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001965 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301966 if (err)
1967 break;
1968 }
1969 err = isr_setup_status_phase(udc);
1970 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
1971 le16_to_cpu(req.wValue) ==
1972 USB_DEVICE_REMOTE_WAKEUP) {
1973 if (req.wLength != 0)
1974 break;
1975 udc->remote_wakeup = 0;
1976 err = isr_setup_status_phase(udc);
1977 } else {
1978 goto delegate;
David Lopoaa69a802008-11-17 14:14:51 -08001979 }
David Lopoaa69a802008-11-17 14:14:51 -08001980 break;
1981 case USB_REQ_GET_STATUS:
1982 if (type != (USB_DIR_IN|USB_RECIP_DEVICE) &&
1983 type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
1984 type != (USB_DIR_IN|USB_RECIP_INTERFACE))
1985 goto delegate;
1986 if (le16_to_cpu(req.wLength) != 2 ||
1987 le16_to_cpu(req.wValue) != 0)
1988 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301989 err = isr_get_status_response(udc, &req);
David Lopoaa69a802008-11-17 14:14:51 -08001990 break;
1991 case USB_REQ_SET_ADDRESS:
1992 if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
1993 goto delegate;
1994 if (le16_to_cpu(req.wLength) != 0 ||
1995 le16_to_cpu(req.wIndex) != 0)
1996 break;
Alexander Shishkinef15e542012-05-11 17:25:43 +03001997 udc->address = (u8)le16_to_cpu(req.wValue);
1998 udc->setaddr = true;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301999 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002000 break;
2001 case USB_REQ_SET_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302002 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
2003 le16_to_cpu(req.wValue) ==
2004 USB_ENDPOINT_HALT) {
2005 if (req.wLength != 0)
2006 break;
2007 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302008 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302009 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +05302010 if (dir) /* TX */
Alexander Shishkind3595d12012-05-08 23:28:58 +03002011 num += udc->hw_ep_max/2;
David Lopoaa69a802008-11-17 14:14:51 -08002012
Alexander Shishkind3595d12012-05-08 23:28:58 +03002013 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302014 err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002015 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302016 if (!err)
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302017 isr_setup_status_phase(udc);
2018 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302019 if (req.wLength != 0)
2020 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +05302021 switch (le16_to_cpu(req.wValue)) {
2022 case USB_DEVICE_REMOTE_WAKEUP:
2023 udc->remote_wakeup = 1;
2024 err = isr_setup_status_phase(udc);
2025 break;
2026 case USB_DEVICE_TEST_MODE:
2027 tmode = le16_to_cpu(req.wIndex) >> 8;
2028 switch (tmode) {
2029 case TEST_J:
2030 case TEST_K:
2031 case TEST_SE0_NAK:
2032 case TEST_PACKET:
2033 case TEST_FORCE_EN:
2034 udc->test_mode = tmode;
2035 err = isr_setup_status_phase(
2036 udc);
2037 break;
2038 default:
2039 break;
2040 }
2041 default:
2042 goto delegate;
2043 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302044 } else {
2045 goto delegate;
2046 }
David Lopoaa69a802008-11-17 14:14:51 -08002047 break;
2048 default:
2049delegate:
2050 if (req.wLength == 0) /* no data phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302051 udc->ep0_dir = TX;
David Lopoaa69a802008-11-17 14:14:51 -08002052
Alexander Shishkind3595d12012-05-08 23:28:58 +03002053 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08002054 err = udc->driver->setup(&udc->gadget, &req);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002055 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08002056 break;
2057 }
2058
2059 if (err < 0) {
2060 dbg_event(_usb_addr(mEp), "ERROR", err);
2061
Alexander Shishkind3595d12012-05-08 23:28:58 +03002062 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08002063 if (usb_ep_set_halt(&mEp->ep))
Alexander Shishkin0f089092012-05-08 23:29:02 +03002064 dev_err(udc->dev, "error: ep_set_halt\n");
Alexander Shishkind3595d12012-05-08 23:28:58 +03002065 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08002066 }
2067 }
2068}
2069
2070/******************************************************************************
2071 * ENDPT block
2072 *****************************************************************************/
2073/**
2074 * ep_enable: configure endpoint, making it usable
2075 *
2076 * Check usb_ep_enable() at "usb_gadget.h" for details
2077 */
2078static int ep_enable(struct usb_ep *ep,
2079 const struct usb_endpoint_descriptor *desc)
2080{
2081 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302082 int retval = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002083 unsigned long flags;
2084
David Lopoaa69a802008-11-17 14:14:51 -08002085 if (ep == NULL || desc == NULL)
2086 return -EINVAL;
2087
2088 spin_lock_irqsave(mEp->lock, flags);
2089
2090 /* only internal SW should enable ctrl endpts */
2091
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002092 mEp->ep.desc = desc;
David Lopoaa69a802008-11-17 14:14:51 -08002093
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302094 if (!list_empty(&mEp->qh.queue))
Alexander Shishkin0f089092012-05-08 23:29:02 +03002095 dev_warn(mEp->udc->dev, "enabling a non-empty endpoint!\n");
David Lopoaa69a802008-11-17 14:14:51 -08002096
Matthias Kaehlcke15739bb2009-04-15 22:28:41 +02002097 mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX;
2098 mEp->num = usb_endpoint_num(desc);
2099 mEp->type = usb_endpoint_type(desc);
David Lopoaa69a802008-11-17 14:14:51 -08002100
Kuninori Morimoto29cc8892011-08-23 03:12:03 -07002101 mEp->ep.maxpacket = usb_endpoint_maxp(desc);
David Lopoaa69a802008-11-17 14:14:51 -08002102
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302103 dbg_event(_usb_addr(mEp), "ENABLE", 0);
David Lopoaa69a802008-11-17 14:14:51 -08002104
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302105 mEp->qh.ptr->cap = 0;
David Lopof23e6492009-04-16 14:35:24 -07002106
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302107 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2108 mEp->qh.ptr->cap |= QH_IOS;
2109 else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
2110 mEp->qh.ptr->cap &= ~QH_MULT;
2111 else
2112 mEp->qh.ptr->cap &= ~QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08002113
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302114 mEp->qh.ptr->cap |=
2115 (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
2116 mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */
David Lopoaa69a802008-11-17 14:14:51 -08002117
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302118 /*
2119 * Enable endpoints in the HW other than ep0 as ep0
2120 * is always enabled
2121 */
2122 if (mEp->num)
Alexander Shishkind3595d12012-05-08 23:28:58 +03002123 retval |= hw_ep_enable(mEp->udc, mEp->num, mEp->dir, mEp->type);
David Lopoaa69a802008-11-17 14:14:51 -08002124
2125 spin_unlock_irqrestore(mEp->lock, flags);
2126 return retval;
2127}
2128
2129/**
2130 * ep_disable: endpoint is no longer usable
2131 *
2132 * Check usb_ep_disable() at "usb_gadget.h" for details
2133 */
2134static int ep_disable(struct usb_ep *ep)
2135{
2136 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2137 int direction, retval = 0;
2138 unsigned long flags;
2139
David Lopoaa69a802008-11-17 14:14:51 -08002140 if (ep == NULL)
2141 return -EINVAL;
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002142 else if (mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002143 return -EBUSY;
2144
2145 spin_lock_irqsave(mEp->lock, flags);
2146
2147 /* only internal SW should disable ctrl endpts */
2148
2149 direction = mEp->dir;
2150 do {
2151 dbg_event(_usb_addr(mEp), "DISABLE", 0);
2152
2153 retval |= _ep_nuke(mEp);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002154 retval |= hw_ep_disable(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08002155
2156 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2157 mEp->dir = (mEp->dir == TX) ? RX : TX;
2158
2159 } while (mEp->dir != direction);
2160
Ido Shayevitzf9c56cd2012-02-08 13:56:48 +02002161 mEp->ep.desc = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002162
2163 spin_unlock_irqrestore(mEp->lock, flags);
2164 return retval;
2165}
2166
2167/**
2168 * ep_alloc_request: allocate a request object to use with this endpoint
2169 *
2170 * Check usb_ep_alloc_request() at "usb_gadget.h" for details
2171 */
2172static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
2173{
2174 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2175 struct ci13xxx_req *mReq = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002176
Alexander Shishkin0f089092012-05-08 23:29:02 +03002177 if (ep == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002178 return NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002179
David Lopoaa69a802008-11-17 14:14:51 -08002180 mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
2181 if (mReq != NULL) {
2182 INIT_LIST_HEAD(&mReq->queue);
Michael Grzeschik954aad82011-10-10 18:38:06 +02002183 mReq->req.dma = DMA_ADDR_INVALID;
David Lopoaa69a802008-11-17 14:14:51 -08002184
2185 mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,
2186 &mReq->dma);
2187 if (mReq->ptr == NULL) {
2188 kfree(mReq);
2189 mReq = NULL;
2190 }
2191 }
2192
2193 dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
2194
David Lopoaa69a802008-11-17 14:14:51 -08002195 return (mReq == NULL) ? NULL : &mReq->req;
2196}
2197
2198/**
2199 * ep_free_request: frees a request object
2200 *
2201 * Check usb_ep_free_request() at "usb_gadget.h" for details
2202 */
2203static void ep_free_request(struct usb_ep *ep, struct usb_request *req)
2204{
2205 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2206 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2207 unsigned long flags;
2208
David Lopoaa69a802008-11-17 14:14:51 -08002209 if (ep == NULL || req == NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08002210 return;
2211 } else if (!list_empty(&mReq->queue)) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03002212 dev_err(mEp->udc->dev, "freeing queued request\n");
David Lopoaa69a802008-11-17 14:14:51 -08002213 return;
2214 }
2215
2216 spin_lock_irqsave(mEp->lock, flags);
2217
2218 if (mReq->ptr)
2219 dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma);
2220 kfree(mReq);
2221
2222 dbg_event(_usb_addr(mEp), "FREE", 0);
2223
2224 spin_unlock_irqrestore(mEp->lock, flags);
2225}
2226
2227/**
2228 * ep_queue: queues (submits) an I/O request to an endpoint
2229 *
2230 * Check usb_ep_queue()* at usb_gadget.h" for details
2231 */
2232static int ep_queue(struct usb_ep *ep, struct usb_request *req,
2233 gfp_t __maybe_unused gfp_flags)
2234{
2235 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2236 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002237 struct ci13xxx *udc = mEp->udc;
David Lopoaa69a802008-11-17 14:14:51 -08002238 int retval = 0;
2239 unsigned long flags;
2240
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002241 if (ep == NULL || req == NULL || mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002242 return -EINVAL;
2243
2244 spin_lock_irqsave(mEp->lock, flags);
2245
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302246 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
2247 if (req->length)
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002248 mEp = (udc->ep0_dir == RX) ?
2249 udc->ep0out : udc->ep0in;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302250 if (!list_empty(&mEp->qh.queue)) {
2251 _ep_nuke(mEp);
2252 retval = -EOVERFLOW;
Alexander Shishkin0f089092012-05-08 23:29:02 +03002253 dev_warn(mEp->udc->dev, "endpoint ctrl %X nuked\n",
2254 _usb_addr(mEp));
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05302255 }
David Lopoaa69a802008-11-17 14:14:51 -08002256 }
2257
2258 /* first nuke then test link, e.g. previous status has not sent */
2259 if (!list_empty(&mReq->queue)) {
2260 retval = -EBUSY;
Alexander Shishkin0f089092012-05-08 23:29:02 +03002261 dev_err(mEp->udc->dev, "request already in queue\n");
David Lopoaa69a802008-11-17 14:14:51 -08002262 goto done;
2263 }
2264
Alexander Shishkin1155a7b2012-05-08 23:28:57 +03002265 if (req->length > 4 * CI13XXX_PAGE_SIZE) {
2266 req->length = 4 * CI13XXX_PAGE_SIZE;
David Lopoaa69a802008-11-17 14:14:51 -08002267 retval = -EMSGSIZE;
Alexander Shishkin0f089092012-05-08 23:29:02 +03002268 dev_warn(mEp->udc->dev, "request length truncated\n");
David Lopoaa69a802008-11-17 14:14:51 -08002269 }
2270
2271 dbg_queue(_usb_addr(mEp), req, retval);
2272
2273 /* push request */
2274 mReq->req.status = -EINPROGRESS;
2275 mReq->req.actual = 0;
David Lopoaa69a802008-11-17 14:14:51 -08002276
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302277 retval = _hardware_enqueue(mEp, mReq);
Artem Leonenkod9bb9c12010-12-14 23:45:50 -08002278
2279 if (retval == -EALREADY) {
David Lopoaa69a802008-11-17 14:14:51 -08002280 dbg_event(_usb_addr(mEp), "QUEUE", retval);
2281 retval = 0;
2282 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302283 if (!retval)
2284 list_add_tail(&mReq->queue, &mEp->qh.queue);
David Lopoaa69a802008-11-17 14:14:51 -08002285
2286 done:
2287 spin_unlock_irqrestore(mEp->lock, flags);
2288 return retval;
2289}
2290
2291/**
2292 * ep_dequeue: dequeues (cancels, unlinks) an I/O request from an endpoint
2293 *
2294 * Check usb_ep_dequeue() at "usb_gadget.h" for details
2295 */
2296static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
2297{
2298 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2299 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
2300 unsigned long flags;
2301
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302302 if (ep == NULL || req == NULL || mReq->req.status != -EALREADY ||
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002303 mEp->ep.desc == NULL || list_empty(&mReq->queue) ||
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302304 list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08002305 return -EINVAL;
2306
2307 spin_lock_irqsave(mEp->lock, flags);
2308
2309 dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
2310
Alexander Shishkind3595d12012-05-08 23:28:58 +03002311 hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08002312
2313 /* pop request */
2314 list_del_init(&mReq->queue);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302315 if (mReq->map) {
2316 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
2317 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02002318 mReq->req.dma = DMA_ADDR_INVALID;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05302319 mReq->map = 0;
2320 }
David Lopoaa69a802008-11-17 14:14:51 -08002321 req->status = -ECONNRESET;
2322
Artem Leonenko7c25a822010-12-14 23:46:55 -08002323 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08002324 spin_unlock(mEp->lock);
2325 mReq->req.complete(&mEp->ep, &mReq->req);
2326 spin_lock(mEp->lock);
2327 }
2328
2329 spin_unlock_irqrestore(mEp->lock, flags);
2330 return 0;
2331}
2332
2333/**
2334 * ep_set_halt: sets the endpoint halt feature
2335 *
2336 * Check usb_ep_set_halt() at "usb_gadget.h" for details
2337 */
2338static int ep_set_halt(struct usb_ep *ep, int value)
2339{
2340 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2341 int direction, retval = 0;
2342 unsigned long flags;
2343
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002344 if (ep == NULL || mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002345 return -EINVAL;
2346
2347 spin_lock_irqsave(mEp->lock, flags);
2348
2349#ifndef STALL_IN
2350 /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
2351 if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX &&
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302352 !list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -08002353 spin_unlock_irqrestore(mEp->lock, flags);
2354 return -EAGAIN;
2355 }
2356#endif
2357
2358 direction = mEp->dir;
2359 do {
2360 dbg_event(_usb_addr(mEp), "HALT", value);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002361 retval |= hw_ep_set_halt(mEp->udc, mEp->num, mEp->dir, value);
David Lopoaa69a802008-11-17 14:14:51 -08002362
2363 if (!value)
2364 mEp->wedge = 0;
2365
2366 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
2367 mEp->dir = (mEp->dir == TX) ? RX : TX;
2368
2369 } while (mEp->dir != direction);
2370
2371 spin_unlock_irqrestore(mEp->lock, flags);
2372 return retval;
2373}
2374
2375/**
2376 * ep_set_wedge: sets the halt feature and ignores clear requests
2377 *
2378 * Check usb_ep_set_wedge() at "usb_gadget.h" for details
2379 */
2380static int ep_set_wedge(struct usb_ep *ep)
2381{
2382 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2383 unsigned long flags;
2384
Ido Shayevitz31fb6012012-03-12 20:25:23 +02002385 if (ep == NULL || mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002386 return -EINVAL;
2387
2388 spin_lock_irqsave(mEp->lock, flags);
2389
2390 dbg_event(_usb_addr(mEp), "WEDGE", 0);
2391 mEp->wedge = 1;
2392
2393 spin_unlock_irqrestore(mEp->lock, flags);
2394
2395 return usb_ep_set_halt(ep);
2396}
2397
2398/**
2399 * ep_fifo_flush: flushes contents of a fifo
2400 *
2401 * Check usb_ep_fifo_flush() at "usb_gadget.h" for details
2402 */
2403static void ep_fifo_flush(struct usb_ep *ep)
2404{
2405 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
2406 unsigned long flags;
2407
David Lopoaa69a802008-11-17 14:14:51 -08002408 if (ep == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03002409 dev_err(mEp->udc->dev, "%02X: -EINVAL\n", _usb_addr(mEp));
David Lopoaa69a802008-11-17 14:14:51 -08002410 return;
2411 }
2412
2413 spin_lock_irqsave(mEp->lock, flags);
2414
2415 dbg_event(_usb_addr(mEp), "FFLUSH", 0);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002416 hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08002417
2418 spin_unlock_irqrestore(mEp->lock, flags);
2419}
2420
2421/**
2422 * Endpoint-specific part of the API to the USB controller hardware
2423 * Check "usb_gadget.h" for details
2424 */
2425static const struct usb_ep_ops usb_ep_ops = {
2426 .enable = ep_enable,
2427 .disable = ep_disable,
2428 .alloc_request = ep_alloc_request,
2429 .free_request = ep_free_request,
2430 .queue = ep_queue,
2431 .dequeue = ep_dequeue,
2432 .set_halt = ep_set_halt,
2433 .set_wedge = ep_set_wedge,
2434 .fifo_flush = ep_fifo_flush,
2435};
2436
2437/******************************************************************************
2438 * GADGET block
2439 *****************************************************************************/
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302440static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
2441{
2442 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2443 unsigned long flags;
2444 int gadget_ready = 0;
2445
2446 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS))
2447 return -EOPNOTSUPP;
2448
Alexander Shishkind3595d12012-05-08 23:28:58 +03002449 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302450 udc->vbus_active = is_active;
2451 if (udc->driver)
2452 gadget_ready = 1;
Alexander Shishkind3595d12012-05-08 23:28:58 +03002453 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302454
2455 if (gadget_ready) {
2456 if (is_active) {
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302457 pm_runtime_get_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302458 hw_device_reset(udc);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002459 hw_device_state(udc, udc->ep0out->qh.dma);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302460 } else {
Alexander Shishkind3595d12012-05-08 23:28:58 +03002461 hw_device_state(udc, 0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302462 if (udc->udc_driver->notify_event)
2463 udc->udc_driver->notify_event(udc,
2464 CI13XXX_CONTROLLER_STOPPED_EVENT);
2465 _gadget_stop_activity(&udc->gadget);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302466 pm_runtime_put_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302467 }
2468 }
2469
2470 return 0;
2471}
2472
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302473static int ci13xxx_wakeup(struct usb_gadget *_gadget)
2474{
2475 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2476 unsigned long flags;
2477 int ret = 0;
2478
Alexander Shishkind3595d12012-05-08 23:28:58 +03002479 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302480 if (!udc->remote_wakeup) {
2481 ret = -EOPNOTSUPP;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302482 goto out;
2483 }
Alexander Shishkin262c1632012-05-08 23:28:59 +03002484 if (!hw_read(udc, OP_PORTSC, PORTSC_SUSP)) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302485 ret = -EINVAL;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302486 goto out;
2487 }
Alexander Shishkin262c1632012-05-08 23:28:59 +03002488 hw_write(udc, OP_PORTSC, PORTSC_FPR, PORTSC_FPR);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302489out:
Alexander Shishkind3595d12012-05-08 23:28:58 +03002490 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302491 return ret;
2492}
2493
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302494static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
2495{
2496 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
2497
2498 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002499 return usb_phy_set_power(udc->transceiver, mA);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302500 return -ENOTSUPP;
2501}
2502
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002503static int ci13xxx_start(struct usb_gadget *gadget,
2504 struct usb_gadget_driver *driver);
2505static int ci13xxx_stop(struct usb_gadget *gadget,
2506 struct usb_gadget_driver *driver);
David Lopoaa69a802008-11-17 14:14:51 -08002507/**
2508 * Device operations part of the API to the USB controller hardware,
2509 * which don't involve endpoints (or i/o)
2510 * Check "usb_gadget.h" for details
2511 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302512static const struct usb_gadget_ops usb_gadget_ops = {
2513 .vbus_session = ci13xxx_vbus_session,
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302514 .wakeup = ci13xxx_wakeup,
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302515 .vbus_draw = ci13xxx_vbus_draw,
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002516 .udc_start = ci13xxx_start,
2517 .udc_stop = ci13xxx_stop,
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302518};
David Lopoaa69a802008-11-17 14:14:51 -08002519
Alexander Shishkin790c2d52012-05-08 23:29:03 +03002520static int init_eps(struct ci13xxx *udc)
2521{
2522 int retval = 0, i, j;
2523
2524 for (i = 0; i < udc->hw_ep_max/2; i++)
2525 for (j = RX; j <= TX; j++) {
2526 int k = i + j * udc->hw_ep_max/2;
2527 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
2528
2529 scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
2530 (j == TX) ? "in" : "out");
2531
2532 mEp->udc = udc;
2533 mEp->lock = &udc->lock;
2534 mEp->device = &udc->gadget.dev;
2535 mEp->td_pool = udc->td_pool;
2536
2537 mEp->ep.name = mEp->name;
2538 mEp->ep.ops = &usb_ep_ops;
2539 mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
2540
2541 INIT_LIST_HEAD(&mEp->qh.queue);
2542 mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
2543 &mEp->qh.dma);
2544 if (mEp->qh.ptr == NULL)
2545 retval = -ENOMEM;
2546 else
2547 memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
2548
2549 /*
2550 * set up shorthands for ep0 out and in endpoints,
2551 * don't add to gadget's ep_list
2552 */
2553 if (i == 0) {
2554 if (j == RX)
2555 udc->ep0out = mEp;
2556 else
2557 udc->ep0in = mEp;
2558
2559 continue;
2560 }
2561
2562 list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
2563 }
2564
2565 return retval;
2566}
2567
David Lopoaa69a802008-11-17 14:14:51 -08002568/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002569 * ci13xxx_start: register a gadget driver
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002570 * @gadget: our gadget
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002571 * @driver: the driver being registered
David Lopoaa69a802008-11-17 14:14:51 -08002572 *
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02002573 * Interrupts are enabled here.
David Lopoaa69a802008-11-17 14:14:51 -08002574 */
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002575static int ci13xxx_start(struct usb_gadget *gadget,
2576 struct usb_gadget_driver *driver)
David Lopoaa69a802008-11-17 14:14:51 -08002577{
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002578 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05302579 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -08002580 int retval = -ENOMEM;
2581
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002582 if (driver->disconnect == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002583 return -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -08002584
David Lopoaa69a802008-11-17 14:14:51 -08002585
Alexander Shishkind36ade62012-05-04 16:47:15 +03002586 udc->ep0out->ep.desc = &ctrl_endpt_out_desc;
2587 retval = usb_ep_enable(&udc->ep0out->ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302588 if (retval)
2589 return retval;
Felipe Balbi877c1f52011-06-29 16:41:57 +03002590
Alexander Shishkind36ade62012-05-04 16:47:15 +03002591 udc->ep0in->ep.desc = &ctrl_endpt_in_desc;
2592 retval = usb_ep_enable(&udc->ep0in->ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05302593 if (retval)
2594 return retval;
Alexander Shishkind3595d12012-05-08 23:28:58 +03002595 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002596
Pavankumar Kondeti49d3df52011-01-11 09:19:21 +05302597 udc->driver = driver;
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302598 pm_runtime_get_sync(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302599 if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
2600 if (udc->vbus_active) {
2601 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
2602 hw_device_reset(udc);
2603 } else {
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302604 pm_runtime_put_sync(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302605 goto done;
2606 }
2607 }
2608
Alexander Shishkind3595d12012-05-08 23:28:58 +03002609 retval = hw_device_state(udc, udc->ep0out->qh.dma);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302610 if (retval)
2611 pm_runtime_put_sync(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08002612
2613 done:
Alexander Shishkind3595d12012-05-08 23:28:58 +03002614 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002615 return retval;
2616}
David Lopoaa69a802008-11-17 14:14:51 -08002617
2618/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002619 * ci13xxx_stop: unregister a gadget driver
David Lopoaa69a802008-11-17 14:14:51 -08002620 */
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002621static int ci13xxx_stop(struct usb_gadget *gadget,
2622 struct usb_gadget_driver *driver)
David Lopoaa69a802008-11-17 14:14:51 -08002623{
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002624 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
2625 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -08002626
Alexander Shishkind3595d12012-05-08 23:28:58 +03002627 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002628
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302629 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) ||
2630 udc->vbus_active) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03002631 hw_device_state(udc, 0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302632 if (udc->udc_driver->notify_event)
2633 udc->udc_driver->notify_event(udc,
2634 CI13XXX_CONTROLLER_STOPPED_EVENT);
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002635 udc->driver = NULL;
Alexander Shishkind3595d12012-05-08 23:28:58 +03002636 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302637 _gadget_stop_activity(&udc->gadget);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002638 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302639 pm_runtime_put(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302640 }
David Lopoaa69a802008-11-17 14:14:51 -08002641
Alexander Shishkind3595d12012-05-08 23:28:58 +03002642 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08002643
David Lopoaa69a802008-11-17 14:14:51 -08002644 return 0;
2645}
David Lopoaa69a802008-11-17 14:14:51 -08002646
2647/******************************************************************************
2648 * BUS block
2649 *****************************************************************************/
2650/**
2651 * udc_irq: global interrupt handler
2652 *
2653 * This function returns IRQ_HANDLED if the IRQ has been handled
2654 * It locks access to registers
2655 */
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03002656static irqreturn_t udc_irq(int irq, void *data)
David Lopoaa69a802008-11-17 14:14:51 -08002657{
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002658 struct ci13xxx *udc = data;
David Lopoaa69a802008-11-17 14:14:51 -08002659 irqreturn_t retval;
2660 u32 intr;
2661
Greg Kroah-Hartmanf6395542012-05-10 11:37:18 -07002662 if (udc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002663 return IRQ_HANDLED;
David Lopoaa69a802008-11-17 14:14:51 -08002664
Alexander Shishkind3595d12012-05-08 23:28:58 +03002665 spin_lock(&udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302666
2667 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) {
Alexander Shishkin262c1632012-05-08 23:28:59 +03002668 if (hw_read(udc, OP_USBMODE, USBMODE_CM) !=
2669 USBMODE_CM_DEVICE) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03002670 spin_unlock(&udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302671 return IRQ_NONE;
2672 }
2673 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03002674 intr = hw_test_and_clear_intr_active(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002675 if (intr) {
2676 isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intr;
2677 isr_statistics.hndl.idx &= ISR_MASK;
2678 isr_statistics.hndl.cnt++;
2679
2680 /* order defines priority - do NOT change it */
2681 if (USBi_URI & intr) {
2682 isr_statistics.uri++;
2683 isr_reset_handler(udc);
2684 }
2685 if (USBi_PCI & intr) {
2686 isr_statistics.pci++;
Alexander Shishkind3595d12012-05-08 23:28:58 +03002687 udc->gadget.speed = hw_port_is_high_speed(udc) ?
David Lopoaa69a802008-11-17 14:14:51 -08002688 USB_SPEED_HIGH : USB_SPEED_FULL;
Marc Kleine-Budde7bb4fdc2011-10-10 18:38:09 +02002689 if (udc->suspended && udc->driver->resume) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03002690 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302691 udc->driver->resume(&udc->gadget);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002692 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302693 udc->suspended = 0;
2694 }
David Lopoaa69a802008-11-17 14:14:51 -08002695 }
2696 if (USBi_UEI & intr)
2697 isr_statistics.uei++;
2698 if (USBi_UI & intr) {
2699 isr_statistics.ui++;
2700 isr_tr_complete_handler(udc);
2701 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302702 if (USBi_SLI & intr) {
Marc Kleine-Budde7bb4fdc2011-10-10 18:38:09 +02002703 if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
2704 udc->driver->suspend) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302705 udc->suspended = 1;
Alexander Shishkind3595d12012-05-08 23:28:58 +03002706 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302707 udc->driver->suspend(&udc->gadget);
Alexander Shishkind3595d12012-05-08 23:28:58 +03002708 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302709 }
David Lopoaa69a802008-11-17 14:14:51 -08002710 isr_statistics.sli++;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05302711 }
David Lopoaa69a802008-11-17 14:14:51 -08002712 retval = IRQ_HANDLED;
2713 } else {
2714 isr_statistics.none++;
2715 retval = IRQ_NONE;
2716 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03002717 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08002718
2719 return retval;
2720}
2721
2722/**
2723 * udc_release: driver release function
2724 * @dev: device
2725 *
2726 * Currently does nothing
2727 */
2728static void udc_release(struct device *dev)
2729{
David Lopoaa69a802008-11-17 14:14:51 -08002730}
2731
2732/**
2733 * udc_probe: parent probe must call this to initialize UDC
2734 * @dev: parent device
2735 * @regs: registers base address
2736 * @name: driver name
2737 *
2738 * This function returns an error code
2739 * No interrupts active, the IRQ has not been requested yet
2740 * Kernel assumes 32-bit DMA operations by default, no need to dma_set_mask
2741 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302742static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002743 void __iomem *regs, struct ci13xxx **_udc)
David Lopoaa69a802008-11-17 14:14:51 -08002744{
2745 struct ci13xxx *udc;
2746 int retval = 0;
2747
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302748 if (dev == NULL || regs == NULL || driver == NULL ||
2749 driver->name == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002750 return -EINVAL;
2751
2752 udc = kzalloc(sizeof(struct ci13xxx), GFP_KERNEL);
2753 if (udc == NULL)
2754 return -ENOMEM;
2755
Alexander Shishkind3595d12012-05-08 23:28:58 +03002756 spin_lock_init(&udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302757 udc->regs = regs;
2758 udc->udc_driver = driver;
David Lopoaa69a802008-11-17 14:14:51 -08002759
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302760 udc->gadget.ops = &usb_gadget_ops;
David Lopoaa69a802008-11-17 14:14:51 -08002761 udc->gadget.speed = USB_SPEED_UNKNOWN;
Michal Nazarewiczd327ab52011-11-19 18:27:37 +01002762 udc->gadget.max_speed = USB_SPEED_HIGH;
David Lopoaa69a802008-11-17 14:14:51 -08002763 udc->gadget.is_otg = 0;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302764 udc->gadget.name = driver->name;
David Lopoaa69a802008-11-17 14:14:51 -08002765
2766 INIT_LIST_HEAD(&udc->gadget.ep_list);
David Lopoaa69a802008-11-17 14:14:51 -08002767
Kay Sievers5df585242009-03-24 16:38:23 -07002768 dev_set_name(&udc->gadget.dev, "gadget");
David Lopoaa69a802008-11-17 14:14:51 -08002769 udc->gadget.dev.dma_mask = dev->dma_mask;
Pavankumar Kondeti61948ee2010-12-07 17:54:01 +05302770 udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
David Lopoaa69a802008-11-17 14:14:51 -08002771 udc->gadget.dev.parent = dev;
2772 udc->gadget.dev.release = udc_release;
2773
Alexander Shishkin0f089092012-05-08 23:29:02 +03002774 udc->dev = dev;
2775
Alexander Shishkin790c2d52012-05-08 23:29:03 +03002776 /* alloc resources */
2777 udc->qh_pool = dma_pool_create("ci13xxx_qh", dev,
2778 sizeof(struct ci13xxx_qh),
2779 64, CI13XXX_PAGE_SIZE);
2780 if (udc->qh_pool == NULL) {
2781 retval = -ENOMEM;
2782 goto free_udc;
2783 }
2784
2785 udc->td_pool = dma_pool_create("ci13xxx_td", dev,
2786 sizeof(struct ci13xxx_td),
2787 64, CI13XXX_PAGE_SIZE);
2788 if (udc->td_pool == NULL) {
2789 retval = -ENOMEM;
2790 goto free_qh_pool;
2791 }
2792
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03002793 retval = hw_device_init(udc, regs, driver->capoffset);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302794 if (retval < 0)
Alexander Shishkin790c2d52012-05-08 23:29:03 +03002795 goto free_pools;
2796
2797 retval = init_eps(udc);
2798 if (retval)
2799 goto free_pools;
2800
2801 udc->gadget.ep0 = &udc->ep0in->ep;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302802
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002803 udc->transceiver = usb_get_transceiver();
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302804
2805 if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
2806 if (udc->transceiver == NULL) {
2807 retval = -ENODEV;
Alexander Shishkin790c2d52012-05-08 23:29:03 +03002808 goto free_pools;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302809 }
2810 }
2811
2812 if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) {
2813 retval = hw_device_reset(udc);
2814 if (retval)
2815 goto put_transceiver;
2816 }
2817
David Lopoaa69a802008-11-17 14:14:51 -08002818 retval = device_register(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302819 if (retval) {
2820 put_device(&udc->gadget.dev);
2821 goto put_transceiver;
2822 }
David Lopoaa69a802008-11-17 14:14:51 -08002823
2824#ifdef CONFIG_USB_GADGET_DEBUG_FILES
2825 retval = dbg_create_files(&udc->gadget.dev);
2826#endif
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302827 if (retval)
2828 goto unreg_device;
2829
2830 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02002831 retval = otg_set_peripheral(udc->transceiver->otg,
2832 &udc->gadget);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302833 if (retval)
2834 goto remove_dbg;
David Lopoaa69a802008-11-17 14:14:51 -08002835 }
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002836
2837 retval = usb_add_gadget_udc(dev, &udc->gadget);
2838 if (retval)
2839 goto remove_trans;
2840
Pavankumar Kondetic0360192010-12-07 17:54:04 +05302841 pm_runtime_no_callbacks(&udc->gadget.dev);
2842 pm_runtime_enable(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08002843
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002844 *_udc = udc;
David Lopoaa69a802008-11-17 14:14:51 -08002845 return retval;
2846
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002847remove_trans:
2848 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02002849 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002850 usb_put_transceiver(udc->transceiver);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002851 }
2852
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07002853 dev_err(dev, "error = %i\n", retval);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302854remove_dbg:
2855#ifdef CONFIG_USB_GADGET_DEBUG_FILES
2856 dbg_remove_files(&udc->gadget.dev);
2857#endif
2858unreg_device:
2859 device_unregister(&udc->gadget.dev);
2860put_transceiver:
2861 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002862 usb_put_transceiver(udc->transceiver);
Alexander Shishkin790c2d52012-05-08 23:29:03 +03002863free_pools:
2864 dma_pool_destroy(udc->td_pool);
2865free_qh_pool:
2866 dma_pool_destroy(udc->qh_pool);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302867free_udc:
David Lopoaa69a802008-11-17 14:14:51 -08002868 kfree(udc);
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002869 *_udc = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08002870 return retval;
2871}
2872
2873/**
2874 * udc_remove: parent remove must call this to remove UDC
2875 *
2876 * No interrupts active, the IRQ has been released
2877 */
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002878static void udc_remove(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -08002879{
Alexander Shishkin790c2d52012-05-08 23:29:03 +03002880 int i;
David Lopoaa69a802008-11-17 14:14:51 -08002881
Alexander Shishkin0f089092012-05-08 23:29:02 +03002882 if (udc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08002883 return;
Alexander Shishkin0f089092012-05-08 23:29:02 +03002884
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03002885 usb_del_gadget_udc(&udc->gadget);
David Lopoaa69a802008-11-17 14:14:51 -08002886
Alexander Shishkin790c2d52012-05-08 23:29:03 +03002887 for (i = 0; i < udc->hw_ep_max; i++) {
2888 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
2889
2890 dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
2891 }
2892
2893 dma_pool_destroy(udc->td_pool);
2894 dma_pool_destroy(udc->qh_pool);
2895
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302896 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02002897 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02002898 usb_put_transceiver(udc->transceiver);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05302899 }
David Lopoaa69a802008-11-17 14:14:51 -08002900#ifdef CONFIG_USB_GADGET_DEBUG_FILES
2901 dbg_remove_files(&udc->gadget.dev);
2902#endif
2903 device_unregister(&udc->gadget.dev);
2904
Alexander Shishkin262c1632012-05-08 23:28:59 +03002905 kfree(udc->hw_bank.regmap);
David Lopoaa69a802008-11-17 14:14:51 -08002906 kfree(udc);
David Lopoaa69a802008-11-17 14:14:51 -08002907}
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03002908
2909static int __devinit ci_udc_probe(struct platform_device *pdev)
2910{
2911 struct device *dev = &pdev->dev;
2912 struct ci13xxx_udc_driver *driver = dev->platform_data;
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002913 struct ci13xxx *udc;
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03002914 struct resource *res;
2915 void __iomem *base;
2916 int ret;
2917
2918 if (!driver) {
2919 dev_err(dev, "platform data missing\n");
2920 return -ENODEV;
2921 }
2922
2923 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2924 if (!res) {
2925 dev_err(dev, "missing resource\n");
2926 return -ENODEV;
2927 }
2928
2929 base = devm_request_and_ioremap(dev, res);
2930 if (!res) {
2931 dev_err(dev, "can't request and ioremap resource\n");
2932 return -ENOMEM;
2933 }
2934
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002935 ret = udc_probe(driver, dev, base, &udc);
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03002936 if (ret)
2937 return ret;
2938
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002939 udc->irq = platform_get_irq(pdev, 0);
2940 if (udc->irq < 0) {
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03002941 dev_err(dev, "missing IRQ\n");
2942 ret = -ENODEV;
2943 goto out;
2944 }
2945
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002946 platform_set_drvdata(pdev, udc);
2947 ret = request_irq(udc->irq, udc_irq, IRQF_SHARED, driver->name, udc);
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03002948
2949out:
2950 if (ret)
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002951 udc_remove(udc);
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03002952
2953 return ret;
2954}
2955
2956static int __devexit ci_udc_remove(struct platform_device *pdev)
2957{
Alexander Shishkin1f339d82012-05-08 23:29:04 +03002958 struct ci13xxx *udc = platform_get_drvdata(pdev);
2959
2960 free_irq(udc->irq, udc);
2961 udc_remove(udc);
Alexander Shishkin62bb84e2012-05-08 23:29:01 +03002962
2963 return 0;
2964}
2965
2966static struct platform_driver ci_udc_driver = {
2967 .probe = ci_udc_probe,
2968 .remove = __devexit_p(ci_udc_remove),
2969 .driver = {
2970 .name = "ci_udc",
2971 },
2972};
2973
2974module_platform_driver(ci_udc_driver);
2975
2976MODULE_ALIAS("platform:ci_udc");
2977MODULE_ALIAS("platform:ci13xxx");
2978MODULE_LICENSE("GPL v2");
2979MODULE_AUTHOR("David Lopo <dlopo@chipidea.mips.com>");
2980MODULE_DESCRIPTION("ChipIdea UDC Driver");