blob: 51f96942dc5ef109319429464d267acc43d09600 [file] [log] [blame]
David Lopoaa69a802008-11-17 14:14:51 -08001/*
Alexander Shishkineb70e5a2012-05-11 17:25:54 +03002 * udc.c - ChipIdea UDC driver
David Lopoaa69a802008-11-17 14:14:51 -08003 *
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
Matthias Kaehlcke36825a22009-04-15 22:28:36 +020013#include <linux/delay.h>
David Lopoaa69a802008-11-17 14:14:51 -080014#include <linux/device.h>
15#include <linux/dmapool.h>
16#include <linux/dma-mapping.h>
17#include <linux/init.h>
Alexander Shishkin62bb84e2012-05-08 23:29:01 +030018#include <linux/platform_device.h>
19#include <linux/module.h>
David Lopoaa69a802008-11-17 14:14:51 -080020#include <linux/interrupt.h>
David Lopoaa69a802008-11-17 14:14:51 -080021#include <linux/io.h>
22#include <linux/irq.h>
23#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090024#include <linux/slab.h>
Pavankumar Kondetic0360192010-12-07 17:54:04 +053025#include <linux/pm_runtime.h>
David Lopoaa69a802008-11-17 14:14:51 -080026#include <linux/usb/ch9.h>
27#include <linux/usb/gadget.h>
Pavankumar Kondetif01ef572010-12-07 17:54:02 +053028#include <linux/usb/otg.h>
Alexander Shishkine443b332012-05-11 17:25:46 +030029#include <linux/usb/chipidea.h>
David Lopoaa69a802008-11-17 14:14:51 -080030
Alexander Shishkine443b332012-05-11 17:25:46 +030031#include "ci.h"
32#include "udc.h"
33#include "bits.h"
34#include "debug.h"
Michael Grzeschik954aad82011-10-10 18:38:06 +020035
David Lopoaa69a802008-11-17 14:14:51 -080036/* control endpoint description */
37static const struct usb_endpoint_descriptor
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +053038ctrl_endpt_out_desc = {
David Lopoaa69a802008-11-17 14:14:51 -080039 .bLength = USB_DT_ENDPOINT_SIZE,
40 .bDescriptorType = USB_DT_ENDPOINT,
41
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +053042 .bEndpointAddress = USB_DIR_OUT,
43 .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
44 .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
45};
46
47static const struct usb_endpoint_descriptor
48ctrl_endpt_in_desc = {
49 .bLength = USB_DT_ENDPOINT_SIZE,
50 .bDescriptorType = USB_DT_ENDPOINT,
51
52 .bEndpointAddress = USB_DIR_IN,
David Lopoaa69a802008-11-17 14:14:51 -080053 .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
54 .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
55};
56
David Lopoaa69a802008-11-17 14:14:51 -080057/**
58 * hw_ep_bit: calculates the bit number
59 * @num: endpoint number
60 * @dir: endpoint direction
61 *
62 * This function returns bit number
63 */
64static inline int hw_ep_bit(int num, int dir)
65{
66 return num + (dir ? 16 : 0);
67}
68
Alexander Shishkine443b332012-05-11 17:25:46 +030069static inline int ep_to_bit(struct ci13xxx *udc, int n)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +020070{
Alexander Shishkind3595d12012-05-08 23:28:58 +030071 int fill = 16 - udc->hw_ep_max / 2;
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +020072
Alexander Shishkind3595d12012-05-08 23:28:58 +030073 if (n >= udc->hw_ep_max / 2)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +020074 n += fill;
75
76 return n;
77}
78
David Lopoaa69a802008-11-17 14:14:51 -080079/**
David Lopoaa69a802008-11-17 14:14:51 -080080 * hw_device_state: enables/disables interrupts & starts/stops device (execute
81 * without interruption)
82 * @dma: 0 => disable, !0 => enable and set dma engine
83 *
84 * This function returns an error code
85 */
Alexander Shishkind3595d12012-05-08 23:28:58 +030086static int hw_device_state(struct ci13xxx *udc, u32 dma)
David Lopoaa69a802008-11-17 14:14:51 -080087{
88 if (dma) {
Alexander Shishkin262c1632012-05-08 23:28:59 +030089 hw_write(udc, OP_ENDPTLISTADDR, ~0, dma);
David Lopoaa69a802008-11-17 14:14:51 -080090 /* interrupt, error, port change, reset, sleep/suspend */
Alexander Shishkin262c1632012-05-08 23:28:59 +030091 hw_write(udc, OP_USBINTR, ~0,
David Lopoaa69a802008-11-17 14:14:51 -080092 USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
Alexander Shishkin262c1632012-05-08 23:28:59 +030093 hw_write(udc, OP_USBCMD, USBCMD_RS, USBCMD_RS);
David Lopoaa69a802008-11-17 14:14:51 -080094 } else {
Alexander Shishkin262c1632012-05-08 23:28:59 +030095 hw_write(udc, OP_USBCMD, USBCMD_RS, 0);
96 hw_write(udc, OP_USBINTR, ~0, 0);
David Lopoaa69a802008-11-17 14:14:51 -080097 }
98 return 0;
99}
100
101/**
102 * hw_ep_flush: flush endpoint fifo (execute without interruption)
103 * @num: endpoint number
104 * @dir: endpoint direction
105 *
106 * This function returns an error code
107 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300108static int hw_ep_flush(struct ci13xxx *udc, int num, int dir)
David Lopoaa69a802008-11-17 14:14:51 -0800109{
110 int n = hw_ep_bit(num, dir);
111
112 do {
113 /* flush any pending transfer */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300114 hw_write(udc, OP_ENDPTFLUSH, BIT(n), BIT(n));
115 while (hw_read(udc, OP_ENDPTFLUSH, BIT(n)))
David Lopoaa69a802008-11-17 14:14:51 -0800116 cpu_relax();
Alexander Shishkin262c1632012-05-08 23:28:59 +0300117 } while (hw_read(udc, OP_ENDPTSTAT, BIT(n)));
David Lopoaa69a802008-11-17 14:14:51 -0800118
119 return 0;
120}
121
122/**
123 * hw_ep_disable: disables endpoint (execute without interruption)
124 * @num: endpoint number
125 * @dir: endpoint direction
126 *
127 * This function returns an error code
128 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300129static int hw_ep_disable(struct ci13xxx *udc, int num, int dir)
David Lopoaa69a802008-11-17 14:14:51 -0800130{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300131 hw_ep_flush(udc, num, dir);
Alexander Shishkin262c1632012-05-08 23:28:59 +0300132 hw_write(udc, OP_ENDPTCTRL + num,
Alexander Shishkind3595d12012-05-08 23:28:58 +0300133 dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800134 return 0;
135}
136
137/**
138 * hw_ep_enable: enables endpoint (execute without interruption)
139 * @num: endpoint number
140 * @dir: endpoint direction
141 * @type: endpoint type
142 *
143 * This function returns an error code
144 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300145static int hw_ep_enable(struct ci13xxx *udc, int num, int dir, int type)
David Lopoaa69a802008-11-17 14:14:51 -0800146{
147 u32 mask, data;
148
149 if (dir) {
150 mask = ENDPTCTRL_TXT; /* type */
151 data = type << ffs_nr(mask);
152
153 mask |= ENDPTCTRL_TXS; /* unstall */
154 mask |= ENDPTCTRL_TXR; /* reset data toggle */
155 data |= ENDPTCTRL_TXR;
156 mask |= ENDPTCTRL_TXE; /* enable */
157 data |= ENDPTCTRL_TXE;
158 } else {
159 mask = ENDPTCTRL_RXT; /* type */
160 data = type << ffs_nr(mask);
161
162 mask |= ENDPTCTRL_RXS; /* unstall */
163 mask |= ENDPTCTRL_RXR; /* reset data toggle */
164 data |= ENDPTCTRL_RXR;
165 mask |= ENDPTCTRL_RXE; /* enable */
166 data |= ENDPTCTRL_RXE;
167 }
Alexander Shishkin262c1632012-05-08 23:28:59 +0300168 hw_write(udc, OP_ENDPTCTRL + num, mask, data);
David Lopoaa69a802008-11-17 14:14:51 -0800169 return 0;
170}
171
172/**
173 * hw_ep_get_halt: return endpoint halt status
174 * @num: endpoint number
175 * @dir: endpoint direction
176 *
177 * This function returns 1 if endpoint halted
178 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300179static int hw_ep_get_halt(struct ci13xxx *udc, int num, int dir)
David Lopoaa69a802008-11-17 14:14:51 -0800180{
181 u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
182
Alexander Shishkin262c1632012-05-08 23:28:59 +0300183 return hw_read(udc, OP_ENDPTCTRL + num, mask) ? 1 : 0;
David Lopoaa69a802008-11-17 14:14:51 -0800184}
185
186/**
David Lopoaa69a802008-11-17 14:14:51 -0800187 * hw_test_and_clear_setup_status: test & clear setup status (execute without
188 * interruption)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200189 * @n: endpoint number
David Lopoaa69a802008-11-17 14:14:51 -0800190 *
191 * This function returns setup status
192 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300193static int hw_test_and_clear_setup_status(struct ci13xxx *udc, int n)
David Lopoaa69a802008-11-17 14:14:51 -0800194{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300195 n = ep_to_bit(udc, n);
Alexander Shishkin262c1632012-05-08 23:28:59 +0300196 return hw_test_and_clear(udc, OP_ENDPTSETUPSTAT, BIT(n));
David Lopoaa69a802008-11-17 14:14:51 -0800197}
198
199/**
200 * hw_ep_prime: primes endpoint (execute without interruption)
201 * @num: endpoint number
202 * @dir: endpoint direction
203 * @is_ctrl: true if control endpoint
204 *
205 * This function returns an error code
206 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300207static int hw_ep_prime(struct ci13xxx *udc, int num, int dir, int is_ctrl)
David Lopoaa69a802008-11-17 14:14:51 -0800208{
209 int n = hw_ep_bit(num, dir);
210
Alexander Shishkin262c1632012-05-08 23:28:59 +0300211 if (is_ctrl && dir == RX && hw_read(udc, OP_ENDPTSETUPSTAT, BIT(num)))
David Lopoaa69a802008-11-17 14:14:51 -0800212 return -EAGAIN;
213
Alexander Shishkin262c1632012-05-08 23:28:59 +0300214 hw_write(udc, OP_ENDPTPRIME, BIT(n), BIT(n));
David Lopoaa69a802008-11-17 14:14:51 -0800215
Alexander Shishkin262c1632012-05-08 23:28:59 +0300216 while (hw_read(udc, OP_ENDPTPRIME, BIT(n)))
David Lopoaa69a802008-11-17 14:14:51 -0800217 cpu_relax();
Alexander Shishkin262c1632012-05-08 23:28:59 +0300218 if (is_ctrl && dir == RX && hw_read(udc, OP_ENDPTSETUPSTAT, BIT(num)))
David Lopoaa69a802008-11-17 14:14:51 -0800219 return -EAGAIN;
220
221 /* status shoult be tested according with manual but it doesn't work */
222 return 0;
223}
224
225/**
226 * hw_ep_set_halt: configures ep halt & resets data toggle after clear (execute
227 * without interruption)
228 * @num: endpoint number
229 * @dir: endpoint direction
230 * @value: true => stall, false => unstall
231 *
232 * This function returns an error code
233 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300234static int hw_ep_set_halt(struct ci13xxx *udc, int num, int dir, int value)
David Lopoaa69a802008-11-17 14:14:51 -0800235{
236 if (value != 0 && value != 1)
237 return -EINVAL;
238
239 do {
Alexander Shishkin262c1632012-05-08 23:28:59 +0300240 enum ci13xxx_regs reg = OP_ENDPTCTRL + num;
David Lopoaa69a802008-11-17 14:14:51 -0800241 u32 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS;
242 u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR;
243
244 /* data toggle - reserved for EP0 but it's in ESS */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300245 hw_write(udc, reg, mask_xs|mask_xr,
246 value ? mask_xs : mask_xr);
Alexander Shishkind3595d12012-05-08 23:28:58 +0300247 } while (value != hw_ep_get_halt(udc, num, dir));
David Lopoaa69a802008-11-17 14:14:51 -0800248
249 return 0;
250}
251
252/**
David Lopoaa69a802008-11-17 14:14:51 -0800253 * hw_is_port_high_speed: test if port is high speed
254 *
255 * This function returns true if high speed port
256 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300257static int hw_port_is_high_speed(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800258{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300259 return udc->hw_bank.lpm ? hw_read(udc, OP_DEVLC, DEVLC_PSPD) :
260 hw_read(udc, OP_PORTSC, PORTSC_HSP);
David Lopoaa69a802008-11-17 14:14:51 -0800261}
262
263/**
David Lopoaa69a802008-11-17 14:14:51 -0800264 * hw_read_intr_enable: returns interrupt enable register
265 *
266 * This function returns register data
267 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300268static u32 hw_read_intr_enable(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800269{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300270 return hw_read(udc, OP_USBINTR, ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800271}
272
273/**
274 * hw_read_intr_status: returns interrupt status register
275 *
276 * This function returns register data
277 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300278static u32 hw_read_intr_status(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800279{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300280 return hw_read(udc, OP_USBSTS, ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800281}
282
283/**
David Lopoaa69a802008-11-17 14:14:51 -0800284 * hw_test_and_clear_complete: test & clear complete status (execute without
285 * interruption)
Marc Kleine-Buddedd39c352011-10-10 18:38:10 +0200286 * @n: endpoint number
David Lopoaa69a802008-11-17 14:14:51 -0800287 *
288 * This function returns complete status
289 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300290static int hw_test_and_clear_complete(struct ci13xxx *udc, int n)
David Lopoaa69a802008-11-17 14:14:51 -0800291{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300292 n = ep_to_bit(udc, n);
Alexander Shishkin262c1632012-05-08 23:28:59 +0300293 return hw_test_and_clear(udc, OP_ENDPTCOMPLETE, BIT(n));
David Lopoaa69a802008-11-17 14:14:51 -0800294}
295
296/**
297 * hw_test_and_clear_intr_active: test & clear active interrupts (execute
298 * without interruption)
299 *
300 * This function returns active interrutps
301 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300302static u32 hw_test_and_clear_intr_active(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800303{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300304 u32 reg = hw_read_intr_status(udc) & hw_read_intr_enable(udc);
David Lopoaa69a802008-11-17 14:14:51 -0800305
Alexander Shishkin262c1632012-05-08 23:28:59 +0300306 hw_write(udc, OP_USBSTS, ~0, reg);
David Lopoaa69a802008-11-17 14:14:51 -0800307 return reg;
308}
309
310/**
311 * hw_test_and_clear_setup_guard: test & clear setup guard (execute without
312 * interruption)
313 *
314 * This function returns guard value
315 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300316static int hw_test_and_clear_setup_guard(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800317{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300318 return hw_test_and_write(udc, OP_USBCMD, USBCMD_SUTW, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800319}
320
321/**
322 * hw_test_and_set_setup_guard: test & set setup guard (execute without
323 * interruption)
324 *
325 * This function returns guard value
326 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300327static int hw_test_and_set_setup_guard(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800328{
Alexander Shishkin262c1632012-05-08 23:28:59 +0300329 return hw_test_and_write(udc, OP_USBCMD, USBCMD_SUTW, USBCMD_SUTW);
David Lopoaa69a802008-11-17 14:14:51 -0800330}
331
332/**
333 * hw_usb_set_address: configures USB address (execute without interruption)
334 * @value: new USB address
335 *
Alexander Shishkinef15e542012-05-11 17:25:43 +0300336 * This function explicitly sets the address, without the "USBADRA" (advance)
337 * feature, which is not supported by older versions of the controller.
David Lopoaa69a802008-11-17 14:14:51 -0800338 */
Alexander Shishkinef15e542012-05-11 17:25:43 +0300339static void hw_usb_set_address(struct ci13xxx *udc, u8 value)
David Lopoaa69a802008-11-17 14:14:51 -0800340{
Alexander Shishkinef15e542012-05-11 17:25:43 +0300341 hw_write(udc, OP_DEVICEADDR, DEVICEADDR_USBADR,
342 value << ffs_nr(DEVICEADDR_USBADR));
David Lopoaa69a802008-11-17 14:14:51 -0800343}
344
345/**
346 * hw_usb_reset: restart device after a bus reset (execute without
347 * interruption)
348 *
349 * This function returns an error code
350 */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300351static int hw_usb_reset(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800352{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300353 hw_usb_set_address(udc, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800354
355 /* ESS flushes only at end?!? */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300356 hw_write(udc, OP_ENDPTFLUSH, ~0, ~0);
David Lopoaa69a802008-11-17 14:14:51 -0800357
358 /* clear setup token semaphores */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300359 hw_write(udc, OP_ENDPTSETUPSTAT, 0, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800360
361 /* clear complete status */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300362 hw_write(udc, OP_ENDPTCOMPLETE, 0, 0);
David Lopoaa69a802008-11-17 14:14:51 -0800363
364 /* wait until all bits cleared */
Alexander Shishkin262c1632012-05-08 23:28:59 +0300365 while (hw_read(udc, OP_ENDPTPRIME, ~0))
David Lopoaa69a802008-11-17 14:14:51 -0800366 udelay(10); /* not RTOS friendly */
367
368 /* reset all endpoints ? */
369
370 /* reset internal status and wait for further instructions
371 no need to verify the port reset status (ESS does it) */
372
373 return 0;
374}
375
376/******************************************************************************
David Lopoaa69a802008-11-17 14:14:51 -0800377 * UTIL block
378 *****************************************************************************/
379/**
380 * _usb_addr: calculates endpoint address from direction & number
381 * @ep: endpoint
382 */
383static inline u8 _usb_addr(struct ci13xxx_ep *ep)
384{
385 return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num;
386}
387
388/**
389 * _hardware_queue: configures a request at hardware level
390 * @gadget: gadget
391 * @mEp: endpoint
392 *
393 * This function returns an error code
394 */
395static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
396{
Alexander Shishkind3595d12012-05-08 23:28:58 +0300397 struct ci13xxx *udc = mEp->udc;
David Lopoaa69a802008-11-17 14:14:51 -0800398 unsigned i;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530399 int ret = 0;
400 unsigned length = mReq->req.length;
David Lopoaa69a802008-11-17 14:14:51 -0800401
David Lopoaa69a802008-11-17 14:14:51 -0800402 /* don't queue twice */
403 if (mReq->req.status == -EALREADY)
404 return -EALREADY;
405
David Lopoaa69a802008-11-17 14:14:51 -0800406 mReq->req.status = -EALREADY;
David Lopoaa69a802008-11-17 14:14:51 -0800407
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530408 if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) {
409 mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC,
410 &mReq->zdma);
Alexander Shishkin5e0aa492012-05-11 17:25:56 +0300411 if (mReq->zptr == NULL)
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530412 return -ENOMEM;
Alexander Shishkin5e0aa492012-05-11 17:25:56 +0300413
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530414 memset(mReq->zptr, 0, sizeof(*mReq->zptr));
415 mReq->zptr->next = TD_TERMINATE;
416 mReq->zptr->token = TD_STATUS_ACTIVE;
417 if (!mReq->req.no_interrupt)
418 mReq->zptr->token |= TD_IOC;
419 }
Alexander Shishkin5e0aa492012-05-11 17:25:56 +0300420 ret = usb_gadget_map_request(&udc->gadget, &mReq->req, mEp->dir);
421 if (ret)
422 return ret;
423
David Lopoaa69a802008-11-17 14:14:51 -0800424 /*
425 * TD configuration
426 * TODO - handle requests which spawns into several TDs
427 */
428 memset(mReq->ptr, 0, sizeof(*mReq->ptr));
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530429 mReq->ptr->token = length << ffs_nr(TD_TOTAL_BYTES);
David Lopoaa69a802008-11-17 14:14:51 -0800430 mReq->ptr->token &= TD_TOTAL_BYTES;
David Lopoaa69a802008-11-17 14:14:51 -0800431 mReq->ptr->token |= TD_STATUS_ACTIVE;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530432 if (mReq->zptr) {
433 mReq->ptr->next = mReq->zdma;
434 } else {
435 mReq->ptr->next = TD_TERMINATE;
436 if (!mReq->req.no_interrupt)
437 mReq->ptr->token |= TD_IOC;
438 }
David Lopoaa69a802008-11-17 14:14:51 -0800439 mReq->ptr->page[0] = mReq->req.dma;
440 for (i = 1; i < 5; i++)
441 mReq->ptr->page[i] =
Artem Leonenko0a313c42010-12-14 23:47:06 -0800442 (mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK;
David Lopoaa69a802008-11-17 14:14:51 -0800443
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530444 if (!list_empty(&mEp->qh.queue)) {
445 struct ci13xxx_req *mReqPrev;
446 int n = hw_ep_bit(mEp->num, mEp->dir);
447 int tmp_stat;
448
449 mReqPrev = list_entry(mEp->qh.queue.prev,
450 struct ci13xxx_req, queue);
451 if (mReqPrev->zptr)
452 mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
453 else
454 mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
455 wmb();
Alexander Shishkin262c1632012-05-08 23:28:59 +0300456 if (hw_read(udc, OP_ENDPTPRIME, BIT(n)))
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530457 goto done;
458 do {
Alexander Shishkin262c1632012-05-08 23:28:59 +0300459 hw_write(udc, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
460 tmp_stat = hw_read(udc, OP_ENDPTSTAT, BIT(n));
461 } while (!hw_read(udc, OP_USBCMD, USBCMD_ATDTW));
462 hw_write(udc, OP_USBCMD, USBCMD_ATDTW, 0);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530463 if (tmp_stat)
464 goto done;
465 }
466
467 /* QH configuration */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530468 mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */
469 mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530470 mEp->qh.ptr->cap |= QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -0800471
472 wmb(); /* synchronize before ep prime */
473
Alexander Shishkind3595d12012-05-08 23:28:58 +0300474 ret = hw_ep_prime(udc, mEp->num, mEp->dir,
David Lopoaa69a802008-11-17 14:14:51 -0800475 mEp->type == USB_ENDPOINT_XFER_CONTROL);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530476done:
477 return ret;
David Lopoaa69a802008-11-17 14:14:51 -0800478}
479
480/**
481 * _hardware_dequeue: handles a request at hardware level
482 * @gadget: gadget
483 * @mEp: endpoint
484 *
485 * This function returns an error code
486 */
487static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
488{
David Lopoaa69a802008-11-17 14:14:51 -0800489 if (mReq->req.status != -EALREADY)
490 return -EINVAL;
491
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530492 if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
493 return -EBUSY;
494
495 if (mReq->zptr) {
496 if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
497 return -EBUSY;
498 dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
499 mReq->zptr = NULL;
500 }
David Lopoaa69a802008-11-17 14:14:51 -0800501
502 mReq->req.status = 0;
503
Alexander Shishkin5e0aa492012-05-11 17:25:56 +0300504 usb_gadget_unmap_request(&mEp->udc->gadget, &mReq->req, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -0800505
506 mReq->req.status = mReq->ptr->token & TD_STATUS;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530507 if ((TD_STATUS_HALTED & mReq->req.status) != 0)
David Lopoaa69a802008-11-17 14:14:51 -0800508 mReq->req.status = -1;
509 else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0)
510 mReq->req.status = -1;
511 else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0)
512 mReq->req.status = -1;
513
514 mReq->req.actual = mReq->ptr->token & TD_TOTAL_BYTES;
515 mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES);
516 mReq->req.actual = mReq->req.length - mReq->req.actual;
517 mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual;
518
519 return mReq->req.actual;
520}
521
522/**
523 * _ep_nuke: dequeues all endpoint requests
524 * @mEp: endpoint
525 *
526 * This function returns an error code
527 * Caller must hold lock
528 */
529static int _ep_nuke(struct ci13xxx_ep *mEp)
530__releases(mEp->lock)
531__acquires(mEp->lock)
532{
David Lopoaa69a802008-11-17 14:14:51 -0800533 if (mEp == NULL)
534 return -EINVAL;
535
Alexander Shishkind3595d12012-05-08 23:28:58 +0300536 hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -0800537
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530538 while (!list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -0800539
540 /* pop oldest request */
541 struct ci13xxx_req *mReq = \
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530542 list_entry(mEp->qh.queue.next,
David Lopoaa69a802008-11-17 14:14:51 -0800543 struct ci13xxx_req, queue);
544 list_del_init(&mReq->queue);
545 mReq->req.status = -ESHUTDOWN;
546
Artem Leonenko7c25a822010-12-14 23:46:55 -0800547 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -0800548 spin_unlock(mEp->lock);
549 mReq->req.complete(&mEp->ep, &mReq->req);
550 spin_lock(mEp->lock);
551 }
552 }
553 return 0;
554}
555
556/**
557 * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
558 * @gadget: gadget
559 *
560 * This function returns an error code
David Lopoaa69a802008-11-17 14:14:51 -0800561 */
562static int _gadget_stop_activity(struct usb_gadget *gadget)
David Lopoaa69a802008-11-17 14:14:51 -0800563{
564 struct usb_ep *ep;
565 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530566 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -0800567
Alexander Shishkind3595d12012-05-08 23:28:58 +0300568 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530569 udc->gadget.speed = USB_SPEED_UNKNOWN;
570 udc->remote_wakeup = 0;
571 udc->suspended = 0;
Alexander Shishkind3595d12012-05-08 23:28:58 +0300572 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530573
David Lopoaa69a802008-11-17 14:14:51 -0800574 /* flush all endpoints */
575 gadget_for_each_ep(ep, gadget) {
576 usb_ep_fifo_flush(ep);
577 }
Alexander Shishkind36ade62012-05-04 16:47:15 +0300578 usb_ep_fifo_flush(&udc->ep0out->ep);
579 usb_ep_fifo_flush(&udc->ep0in->ep);
David Lopoaa69a802008-11-17 14:14:51 -0800580
Alexander Shishkin1f339d82012-05-08 23:29:04 +0300581 if (udc->driver)
582 udc->driver->disconnect(gadget);
David Lopoaa69a802008-11-17 14:14:51 -0800583
584 /* make sure to disable all endpoints */
585 gadget_for_each_ep(ep, gadget) {
586 usb_ep_disable(ep);
587 }
David Lopoaa69a802008-11-17 14:14:51 -0800588
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530589 if (udc->status != NULL) {
Alexander Shishkind36ade62012-05-04 16:47:15 +0300590 usb_ep_free_request(&udc->ep0in->ep, udc->status);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530591 udc->status = NULL;
David Lopoaa69a802008-11-17 14:14:51 -0800592 }
593
David Lopoaa69a802008-11-17 14:14:51 -0800594 return 0;
595}
596
597/******************************************************************************
598 * ISR block
599 *****************************************************************************/
600/**
601 * isr_reset_handler: USB reset interrupt handler
602 * @udc: UDC device
603 *
604 * This function resets USB engine after a bus reset occurred
605 */
606static void isr_reset_handler(struct ci13xxx *udc)
607__releases(udc->lock)
608__acquires(udc->lock)
609{
David Lopoaa69a802008-11-17 14:14:51 -0800610 int retval;
611
David Lopoaa69a802008-11-17 14:14:51 -0800612 dbg_event(0xFF, "BUS RST", 0);
613
Alexander Shishkind3595d12012-05-08 23:28:58 +0300614 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -0800615 retval = _gadget_stop_activity(&udc->gadget);
616 if (retval)
617 goto done;
618
Alexander Shishkind3595d12012-05-08 23:28:58 +0300619 retval = hw_usb_reset(udc);
David Lopoaa69a802008-11-17 14:14:51 -0800620 if (retval)
621 goto done;
622
Alexander Shishkind36ade62012-05-04 16:47:15 +0300623 udc->status = usb_ep_alloc_request(&udc->ep0in->ep, GFP_ATOMIC);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +0530624 if (udc->status == NULL)
625 retval = -ENOMEM;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530626
Michael Grzeschikb9322252012-05-11 17:25:50 +0300627done:
Alexander Shishkind3595d12012-05-08 23:28:58 +0300628 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -0800629
David Lopoaa69a802008-11-17 14:14:51 -0800630 if (retval)
Alexander Shishkin0f089092012-05-08 23:29:02 +0300631 dev_err(udc->dev, "error: %i\n", retval);
David Lopoaa69a802008-11-17 14:14:51 -0800632}
633
634/**
635 * isr_get_status_complete: get_status request complete function
636 * @ep: endpoint
637 * @req: request handled
638 *
639 * Caller must release lock
640 */
641static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
642{
Alexander Shishkin0f089092012-05-08 23:29:02 +0300643 if (ep == NULL || req == NULL)
David Lopoaa69a802008-11-17 14:14:51 -0800644 return;
David Lopoaa69a802008-11-17 14:14:51 -0800645
646 kfree(req->buf);
647 usb_ep_free_request(ep, req);
648}
649
650/**
651 * isr_get_status_response: get_status request response
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530652 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -0800653 * @setup: setup request packet
654 *
655 * This function returns an error code
656 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530657static int isr_get_status_response(struct ci13xxx *udc,
David Lopoaa69a802008-11-17 14:14:51 -0800658 struct usb_ctrlrequest *setup)
659__releases(mEp->lock)
660__acquires(mEp->lock)
661{
Alexander Shishkind36ade62012-05-04 16:47:15 +0300662 struct ci13xxx_ep *mEp = udc->ep0in;
David Lopoaa69a802008-11-17 14:14:51 -0800663 struct usb_request *req = NULL;
664 gfp_t gfp_flags = GFP_ATOMIC;
665 int dir, num, retval;
666
David Lopoaa69a802008-11-17 14:14:51 -0800667 if (mEp == NULL || setup == NULL)
668 return -EINVAL;
669
670 spin_unlock(mEp->lock);
671 req = usb_ep_alloc_request(&mEp->ep, gfp_flags);
672 spin_lock(mEp->lock);
673 if (req == NULL)
674 return -ENOMEM;
675
676 req->complete = isr_get_status_complete;
677 req->length = 2;
678 req->buf = kzalloc(req->length, gfp_flags);
679 if (req->buf == NULL) {
680 retval = -ENOMEM;
681 goto err_free_req;
682 }
683
684 if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530685 /* Assume that device is bus powered for now. */
Alexander Shishkin1f339d82012-05-08 23:29:04 +0300686 *(u16 *)req->buf = udc->remote_wakeup << 1;
David Lopoaa69a802008-11-17 14:14:51 -0800687 retval = 0;
688 } else if ((setup->bRequestType & USB_RECIP_MASK) \
689 == USB_RECIP_ENDPOINT) {
690 dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
691 TX : RX;
692 num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK;
Alexander Shishkind3595d12012-05-08 23:28:58 +0300693 *(u16 *)req->buf = hw_ep_get_halt(udc, num, dir);
David Lopoaa69a802008-11-17 14:14:51 -0800694 }
695 /* else do nothing; reserved for future use */
696
697 spin_unlock(mEp->lock);
698 retval = usb_ep_queue(&mEp->ep, req, gfp_flags);
699 spin_lock(mEp->lock);
700 if (retval)
701 goto err_free_buf;
702
703 return 0;
704
705 err_free_buf:
706 kfree(req->buf);
707 err_free_req:
708 spin_unlock(mEp->lock);
709 usb_ep_free_request(&mEp->ep, req);
710 spin_lock(mEp->lock);
711 return retval;
712}
713
714/**
Pavankumar Kondeti541cace2011-02-18 17:43:18 +0530715 * isr_setup_status_complete: setup_status request complete function
716 * @ep: endpoint
717 * @req: request handled
718 *
719 * Caller must release lock. Put the port in test mode if test mode
720 * feature is selected.
721 */
722static void
723isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
724{
725 struct ci13xxx *udc = req->context;
726 unsigned long flags;
727
Alexander Shishkinef15e542012-05-11 17:25:43 +0300728 if (udc->setaddr) {
729 hw_usb_set_address(udc, udc->address);
730 udc->setaddr = false;
731 }
732
Alexander Shishkind3595d12012-05-08 23:28:58 +0300733 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondeti541cace2011-02-18 17:43:18 +0530734 if (udc->test_mode)
Alexander Shishkind3595d12012-05-08 23:28:58 +0300735 hw_port_test_set(udc, udc->test_mode);
736 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondeti541cace2011-02-18 17:43:18 +0530737}
738
739/**
David Lopoaa69a802008-11-17 14:14:51 -0800740 * isr_setup_status_phase: queues the status phase of a setup transation
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530741 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -0800742 *
743 * This function returns an error code
744 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530745static int isr_setup_status_phase(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800746__releases(mEp->lock)
747__acquires(mEp->lock)
748{
749 int retval;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530750 struct ci13xxx_ep *mEp;
David Lopoaa69a802008-11-17 14:14:51 -0800751
Alexander Shishkind36ade62012-05-04 16:47:15 +0300752 mEp = (udc->ep0_dir == TX) ? udc->ep0out : udc->ep0in;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +0530753 udc->status->context = udc;
754 udc->status->complete = isr_setup_status_complete;
David Lopoaa69a802008-11-17 14:14:51 -0800755
756 spin_unlock(mEp->lock);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530757 retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
David Lopoaa69a802008-11-17 14:14:51 -0800758 spin_lock(mEp->lock);
759
760 return retval;
761}
762
763/**
764 * isr_tr_complete_low: transaction complete low level handler
765 * @mEp: endpoint
766 *
767 * This function returns an error code
768 * Caller must hold lock
769 */
770static int isr_tr_complete_low(struct ci13xxx_ep *mEp)
771__releases(mEp->lock)
772__acquires(mEp->lock)
773{
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530774 struct ci13xxx_req *mReq, *mReqTemp;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +0530775 struct ci13xxx_ep *mEpTemp = mEp;
Pavankumar Kondeti986b11b2011-05-02 11:56:29 +0530776 int uninitialized_var(retval);
David Lopoaa69a802008-11-17 14:14:51 -0800777
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530778 if (list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -0800779 return -EINVAL;
780
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530781 list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,
782 queue) {
783 retval = _hardware_dequeue(mEp, mReq);
784 if (retval < 0)
785 break;
786 list_del_init(&mReq->queue);
787 dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
788 if (mReq->req.complete != NULL) {
789 spin_unlock(mEp->lock);
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +0530790 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
791 mReq->req.length)
Alexander Shishkin1f339d82012-05-08 23:29:04 +0300792 mEpTemp = mEp->udc->ep0in;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +0530793 mReq->req.complete(&mEpTemp->ep, &mReq->req);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530794 spin_lock(mEp->lock);
795 }
796 }
David Lopoaa69a802008-11-17 14:14:51 -0800797
Pavankumar Kondetief907482011-05-02 11:56:27 +0530798 if (retval == -EBUSY)
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530799 retval = 0;
800 if (retval < 0)
David Lopoaa69a802008-11-17 14:14:51 -0800801 dbg_event(_usb_addr(mEp), "DONE", retval);
David Lopoaa69a802008-11-17 14:14:51 -0800802
David Lopoaa69a802008-11-17 14:14:51 -0800803 return retval;
804}
805
806/**
807 * isr_tr_complete_handler: transaction complete interrupt handler
808 * @udc: UDC descriptor
809 *
810 * This function handles traffic events
811 */
812static void isr_tr_complete_handler(struct ci13xxx *udc)
813__releases(udc->lock)
814__acquires(udc->lock)
815{
816 unsigned i;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +0530817 u8 tmode = 0;
David Lopoaa69a802008-11-17 14:14:51 -0800818
Alexander Shishkind3595d12012-05-08 23:28:58 +0300819 for (i = 0; i < udc->hw_ep_max; i++) {
David Lopoaa69a802008-11-17 14:14:51 -0800820 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +0530821 int type, num, dir, err = -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -0800822 struct usb_ctrlrequest req;
823
Ido Shayevitz31fb6012012-03-12 20:25:23 +0200824 if (mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -0800825 continue; /* not configured */
826
Alexander Shishkind3595d12012-05-08 23:28:58 +0300827 if (hw_test_and_clear_complete(udc, i)) {
David Lopoaa69a802008-11-17 14:14:51 -0800828 err = isr_tr_complete_low(mEp);
829 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
830 if (err > 0) /* needs status phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530831 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -0800832 if (err < 0) {
833 dbg_event(_usb_addr(mEp),
834 "ERROR", err);
Alexander Shishkind3595d12012-05-08 23:28:58 +0300835 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -0800836 if (usb_ep_set_halt(&mEp->ep))
Alexander Shishkin0f089092012-05-08 23:29:02 +0300837 dev_err(udc->dev,
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -0700838 "error: ep_set_halt\n");
Alexander Shishkind3595d12012-05-08 23:28:58 +0300839 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -0800840 }
841 }
842 }
843
844 if (mEp->type != USB_ENDPOINT_XFER_CONTROL ||
Alexander Shishkind3595d12012-05-08 23:28:58 +0300845 !hw_test_and_clear_setup_status(udc, i))
David Lopoaa69a802008-11-17 14:14:51 -0800846 continue;
847
848 if (i != 0) {
Alexander Shishkin0f089092012-05-08 23:29:02 +0300849 dev_warn(udc->dev, "ctrl traffic at endpoint %d\n", i);
David Lopoaa69a802008-11-17 14:14:51 -0800850 continue;
851 }
852
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530853 /*
854 * Flush data and handshake transactions of previous
855 * setup packet.
856 */
Alexander Shishkind36ade62012-05-04 16:47:15 +0300857 _ep_nuke(udc->ep0out);
858 _ep_nuke(udc->ep0in);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530859
David Lopoaa69a802008-11-17 14:14:51 -0800860 /* read_setup_packet */
861 do {
Alexander Shishkind3595d12012-05-08 23:28:58 +0300862 hw_test_and_set_setup_guard(udc);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530863 memcpy(&req, &mEp->qh.ptr->setup, sizeof(req));
Alexander Shishkind3595d12012-05-08 23:28:58 +0300864 } while (!hw_test_and_clear_setup_guard(udc));
David Lopoaa69a802008-11-17 14:14:51 -0800865
866 type = req.bRequestType;
867
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530868 udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
David Lopoaa69a802008-11-17 14:14:51 -0800869
870 dbg_setup(_usb_addr(mEp), &req);
871
872 switch (req.bRequest) {
873 case USB_REQ_CLEAR_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530874 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
875 le16_to_cpu(req.wValue) ==
876 USB_ENDPOINT_HALT) {
877 if (req.wLength != 0)
David Lopoaa69a802008-11-17 14:14:51 -0800878 break;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530879 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +0530880 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530881 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +0530882 if (dir) /* TX */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300883 num += udc->hw_ep_max/2;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530884 if (!udc->ci13xxx_ep[num].wedge) {
Alexander Shishkind3595d12012-05-08 23:28:58 +0300885 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530886 err = usb_ep_clear_halt(
887 &udc->ci13xxx_ep[num].ep);
Alexander Shishkind3595d12012-05-08 23:28:58 +0300888 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530889 if (err)
890 break;
891 }
892 err = isr_setup_status_phase(udc);
893 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
894 le16_to_cpu(req.wValue) ==
895 USB_DEVICE_REMOTE_WAKEUP) {
896 if (req.wLength != 0)
897 break;
898 udc->remote_wakeup = 0;
899 err = isr_setup_status_phase(udc);
900 } else {
901 goto delegate;
David Lopoaa69a802008-11-17 14:14:51 -0800902 }
David Lopoaa69a802008-11-17 14:14:51 -0800903 break;
904 case USB_REQ_GET_STATUS:
905 if (type != (USB_DIR_IN|USB_RECIP_DEVICE) &&
906 type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
907 type != (USB_DIR_IN|USB_RECIP_INTERFACE))
908 goto delegate;
909 if (le16_to_cpu(req.wLength) != 2 ||
910 le16_to_cpu(req.wValue) != 0)
911 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530912 err = isr_get_status_response(udc, &req);
David Lopoaa69a802008-11-17 14:14:51 -0800913 break;
914 case USB_REQ_SET_ADDRESS:
915 if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
916 goto delegate;
917 if (le16_to_cpu(req.wLength) != 0 ||
918 le16_to_cpu(req.wIndex) != 0)
919 break;
Alexander Shishkinef15e542012-05-11 17:25:43 +0300920 udc->address = (u8)le16_to_cpu(req.wValue);
921 udc->setaddr = true;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530922 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -0800923 break;
924 case USB_REQ_SET_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530925 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
926 le16_to_cpu(req.wValue) ==
927 USB_ENDPOINT_HALT) {
928 if (req.wLength != 0)
929 break;
930 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +0530931 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530932 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +0530933 if (dir) /* TX */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300934 num += udc->hw_ep_max/2;
David Lopoaa69a802008-11-17 14:14:51 -0800935
Alexander Shishkind3595d12012-05-08 23:28:58 +0300936 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530937 err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
Alexander Shishkind3595d12012-05-08 23:28:58 +0300938 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530939 if (!err)
Pavankumar Kondeti541cace2011-02-18 17:43:18 +0530940 isr_setup_status_phase(udc);
941 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530942 if (req.wLength != 0)
943 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +0530944 switch (le16_to_cpu(req.wValue)) {
945 case USB_DEVICE_REMOTE_WAKEUP:
946 udc->remote_wakeup = 1;
947 err = isr_setup_status_phase(udc);
948 break;
949 case USB_DEVICE_TEST_MODE:
950 tmode = le16_to_cpu(req.wIndex) >> 8;
951 switch (tmode) {
952 case TEST_J:
953 case TEST_K:
954 case TEST_SE0_NAK:
955 case TEST_PACKET:
956 case TEST_FORCE_EN:
957 udc->test_mode = tmode;
958 err = isr_setup_status_phase(
959 udc);
960 break;
961 default:
962 break;
963 }
964 default:
965 goto delegate;
966 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530967 } else {
968 goto delegate;
969 }
David Lopoaa69a802008-11-17 14:14:51 -0800970 break;
971 default:
972delegate:
973 if (req.wLength == 0) /* no data phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530974 udc->ep0_dir = TX;
David Lopoaa69a802008-11-17 14:14:51 -0800975
Alexander Shishkind3595d12012-05-08 23:28:58 +0300976 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -0800977 err = udc->driver->setup(&udc->gadget, &req);
Alexander Shishkind3595d12012-05-08 23:28:58 +0300978 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -0800979 break;
980 }
981
982 if (err < 0) {
983 dbg_event(_usb_addr(mEp), "ERROR", err);
984
Alexander Shishkind3595d12012-05-08 23:28:58 +0300985 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -0800986 if (usb_ep_set_halt(&mEp->ep))
Alexander Shishkin0f089092012-05-08 23:29:02 +0300987 dev_err(udc->dev, "error: ep_set_halt\n");
Alexander Shishkind3595d12012-05-08 23:28:58 +0300988 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -0800989 }
990 }
991}
992
993/******************************************************************************
994 * ENDPT block
995 *****************************************************************************/
996/**
997 * ep_enable: configure endpoint, making it usable
998 *
999 * Check usb_ep_enable() at "usb_gadget.h" for details
1000 */
1001static int ep_enable(struct usb_ep *ep,
1002 const struct usb_endpoint_descriptor *desc)
1003{
1004 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301005 int retval = 0;
David Lopoaa69a802008-11-17 14:14:51 -08001006 unsigned long flags;
1007
David Lopoaa69a802008-11-17 14:14:51 -08001008 if (ep == NULL || desc == NULL)
1009 return -EINVAL;
1010
1011 spin_lock_irqsave(mEp->lock, flags);
1012
1013 /* only internal SW should enable ctrl endpts */
1014
Ido Shayevitz31fb6012012-03-12 20:25:23 +02001015 mEp->ep.desc = desc;
David Lopoaa69a802008-11-17 14:14:51 -08001016
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301017 if (!list_empty(&mEp->qh.queue))
Alexander Shishkin0f089092012-05-08 23:29:02 +03001018 dev_warn(mEp->udc->dev, "enabling a non-empty endpoint!\n");
David Lopoaa69a802008-11-17 14:14:51 -08001019
Matthias Kaehlcke15739bb2009-04-15 22:28:41 +02001020 mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX;
1021 mEp->num = usb_endpoint_num(desc);
1022 mEp->type = usb_endpoint_type(desc);
David Lopoaa69a802008-11-17 14:14:51 -08001023
Kuninori Morimoto29cc8892011-08-23 03:12:03 -07001024 mEp->ep.maxpacket = usb_endpoint_maxp(desc);
David Lopoaa69a802008-11-17 14:14:51 -08001025
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301026 dbg_event(_usb_addr(mEp), "ENABLE", 0);
David Lopoaa69a802008-11-17 14:14:51 -08001027
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301028 mEp->qh.ptr->cap = 0;
David Lopof23e6492009-04-16 14:35:24 -07001029
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301030 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
1031 mEp->qh.ptr->cap |= QH_IOS;
1032 else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
1033 mEp->qh.ptr->cap &= ~QH_MULT;
1034 else
1035 mEp->qh.ptr->cap &= ~QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08001036
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301037 mEp->qh.ptr->cap |=
1038 (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
1039 mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */
David Lopoaa69a802008-11-17 14:14:51 -08001040
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05301041 /*
1042 * Enable endpoints in the HW other than ep0 as ep0
1043 * is always enabled
1044 */
1045 if (mEp->num)
Alexander Shishkind3595d12012-05-08 23:28:58 +03001046 retval |= hw_ep_enable(mEp->udc, mEp->num, mEp->dir, mEp->type);
David Lopoaa69a802008-11-17 14:14:51 -08001047
1048 spin_unlock_irqrestore(mEp->lock, flags);
1049 return retval;
1050}
1051
1052/**
1053 * ep_disable: endpoint is no longer usable
1054 *
1055 * Check usb_ep_disable() at "usb_gadget.h" for details
1056 */
1057static int ep_disable(struct usb_ep *ep)
1058{
1059 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
1060 int direction, retval = 0;
1061 unsigned long flags;
1062
David Lopoaa69a802008-11-17 14:14:51 -08001063 if (ep == NULL)
1064 return -EINVAL;
Ido Shayevitz31fb6012012-03-12 20:25:23 +02001065 else if (mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001066 return -EBUSY;
1067
1068 spin_lock_irqsave(mEp->lock, flags);
1069
1070 /* only internal SW should disable ctrl endpts */
1071
1072 direction = mEp->dir;
1073 do {
1074 dbg_event(_usb_addr(mEp), "DISABLE", 0);
1075
1076 retval |= _ep_nuke(mEp);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001077 retval |= hw_ep_disable(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08001078
1079 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
1080 mEp->dir = (mEp->dir == TX) ? RX : TX;
1081
1082 } while (mEp->dir != direction);
1083
Ido Shayevitzf9c56cd2012-02-08 13:56:48 +02001084 mEp->ep.desc = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08001085
1086 spin_unlock_irqrestore(mEp->lock, flags);
1087 return retval;
1088}
1089
1090/**
1091 * ep_alloc_request: allocate a request object to use with this endpoint
1092 *
1093 * Check usb_ep_alloc_request() at "usb_gadget.h" for details
1094 */
1095static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
1096{
1097 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
1098 struct ci13xxx_req *mReq = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08001099
Alexander Shishkin0f089092012-05-08 23:29:02 +03001100 if (ep == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001101 return NULL;
David Lopoaa69a802008-11-17 14:14:51 -08001102
David Lopoaa69a802008-11-17 14:14:51 -08001103 mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
1104 if (mReq != NULL) {
1105 INIT_LIST_HEAD(&mReq->queue);
1106
1107 mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,
1108 &mReq->dma);
1109 if (mReq->ptr == NULL) {
1110 kfree(mReq);
1111 mReq = NULL;
1112 }
1113 }
1114
1115 dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
1116
David Lopoaa69a802008-11-17 14:14:51 -08001117 return (mReq == NULL) ? NULL : &mReq->req;
1118}
1119
1120/**
1121 * ep_free_request: frees a request object
1122 *
1123 * Check usb_ep_free_request() at "usb_gadget.h" for details
1124 */
1125static void ep_free_request(struct usb_ep *ep, struct usb_request *req)
1126{
1127 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
1128 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
1129 unsigned long flags;
1130
David Lopoaa69a802008-11-17 14:14:51 -08001131 if (ep == NULL || req == NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08001132 return;
1133 } else if (!list_empty(&mReq->queue)) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001134 dev_err(mEp->udc->dev, "freeing queued request\n");
David Lopoaa69a802008-11-17 14:14:51 -08001135 return;
1136 }
1137
1138 spin_lock_irqsave(mEp->lock, flags);
1139
1140 if (mReq->ptr)
1141 dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma);
1142 kfree(mReq);
1143
1144 dbg_event(_usb_addr(mEp), "FREE", 0);
1145
1146 spin_unlock_irqrestore(mEp->lock, flags);
1147}
1148
1149/**
1150 * ep_queue: queues (submits) an I/O request to an endpoint
1151 *
1152 * Check usb_ep_queue()* at usb_gadget.h" for details
1153 */
1154static int ep_queue(struct usb_ep *ep, struct usb_request *req,
1155 gfp_t __maybe_unused gfp_flags)
1156{
1157 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
1158 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001159 struct ci13xxx *udc = mEp->udc;
David Lopoaa69a802008-11-17 14:14:51 -08001160 int retval = 0;
1161 unsigned long flags;
1162
Ido Shayevitz31fb6012012-03-12 20:25:23 +02001163 if (ep == NULL || req == NULL || mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001164 return -EINVAL;
1165
1166 spin_lock_irqsave(mEp->lock, flags);
1167
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05301168 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
1169 if (req->length)
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001170 mEp = (udc->ep0_dir == RX) ?
1171 udc->ep0out : udc->ep0in;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05301172 if (!list_empty(&mEp->qh.queue)) {
1173 _ep_nuke(mEp);
1174 retval = -EOVERFLOW;
Alexander Shishkin0f089092012-05-08 23:29:02 +03001175 dev_warn(mEp->udc->dev, "endpoint ctrl %X nuked\n",
1176 _usb_addr(mEp));
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05301177 }
David Lopoaa69a802008-11-17 14:14:51 -08001178 }
1179
1180 /* first nuke then test link, e.g. previous status has not sent */
1181 if (!list_empty(&mReq->queue)) {
1182 retval = -EBUSY;
Alexander Shishkin0f089092012-05-08 23:29:02 +03001183 dev_err(mEp->udc->dev, "request already in queue\n");
David Lopoaa69a802008-11-17 14:14:51 -08001184 goto done;
1185 }
1186
Alexander Shishkin1155a7b2012-05-08 23:28:57 +03001187 if (req->length > 4 * CI13XXX_PAGE_SIZE) {
1188 req->length = 4 * CI13XXX_PAGE_SIZE;
David Lopoaa69a802008-11-17 14:14:51 -08001189 retval = -EMSGSIZE;
Alexander Shishkin0f089092012-05-08 23:29:02 +03001190 dev_warn(mEp->udc->dev, "request length truncated\n");
David Lopoaa69a802008-11-17 14:14:51 -08001191 }
1192
1193 dbg_queue(_usb_addr(mEp), req, retval);
1194
1195 /* push request */
1196 mReq->req.status = -EINPROGRESS;
1197 mReq->req.actual = 0;
David Lopoaa69a802008-11-17 14:14:51 -08001198
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301199 retval = _hardware_enqueue(mEp, mReq);
Artem Leonenkod9bb9c12010-12-14 23:45:50 -08001200
1201 if (retval == -EALREADY) {
David Lopoaa69a802008-11-17 14:14:51 -08001202 dbg_event(_usb_addr(mEp), "QUEUE", retval);
1203 retval = 0;
1204 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301205 if (!retval)
1206 list_add_tail(&mReq->queue, &mEp->qh.queue);
David Lopoaa69a802008-11-17 14:14:51 -08001207
1208 done:
1209 spin_unlock_irqrestore(mEp->lock, flags);
1210 return retval;
1211}
1212
1213/**
1214 * ep_dequeue: dequeues (cancels, unlinks) an I/O request from an endpoint
1215 *
1216 * Check usb_ep_dequeue() at "usb_gadget.h" for details
1217 */
1218static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
1219{
1220 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
1221 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
1222 unsigned long flags;
1223
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301224 if (ep == NULL || req == NULL || mReq->req.status != -EALREADY ||
Ido Shayevitz31fb6012012-03-12 20:25:23 +02001225 mEp->ep.desc == NULL || list_empty(&mReq->queue) ||
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301226 list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08001227 return -EINVAL;
1228
1229 spin_lock_irqsave(mEp->lock, flags);
1230
1231 dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
1232
Alexander Shishkind3595d12012-05-08 23:28:58 +03001233 hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08001234
1235 /* pop request */
1236 list_del_init(&mReq->queue);
Alexander Shishkin5e0aa492012-05-11 17:25:56 +03001237
1238 usb_gadget_unmap_request(&mEp->udc->gadget, req, mEp->dir);
1239
David Lopoaa69a802008-11-17 14:14:51 -08001240 req->status = -ECONNRESET;
1241
Artem Leonenko7c25a822010-12-14 23:46:55 -08001242 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08001243 spin_unlock(mEp->lock);
1244 mReq->req.complete(&mEp->ep, &mReq->req);
1245 spin_lock(mEp->lock);
1246 }
1247
1248 spin_unlock_irqrestore(mEp->lock, flags);
1249 return 0;
1250}
1251
1252/**
1253 * ep_set_halt: sets the endpoint halt feature
1254 *
1255 * Check usb_ep_set_halt() at "usb_gadget.h" for details
1256 */
1257static int ep_set_halt(struct usb_ep *ep, int value)
1258{
1259 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
1260 int direction, retval = 0;
1261 unsigned long flags;
1262
Ido Shayevitz31fb6012012-03-12 20:25:23 +02001263 if (ep == NULL || mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001264 return -EINVAL;
1265
1266 spin_lock_irqsave(mEp->lock, flags);
1267
1268#ifndef STALL_IN
1269 /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
1270 if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX &&
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301271 !list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -08001272 spin_unlock_irqrestore(mEp->lock, flags);
1273 return -EAGAIN;
1274 }
1275#endif
1276
1277 direction = mEp->dir;
1278 do {
1279 dbg_event(_usb_addr(mEp), "HALT", value);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001280 retval |= hw_ep_set_halt(mEp->udc, mEp->num, mEp->dir, value);
David Lopoaa69a802008-11-17 14:14:51 -08001281
1282 if (!value)
1283 mEp->wedge = 0;
1284
1285 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
1286 mEp->dir = (mEp->dir == TX) ? RX : TX;
1287
1288 } while (mEp->dir != direction);
1289
1290 spin_unlock_irqrestore(mEp->lock, flags);
1291 return retval;
1292}
1293
1294/**
1295 * ep_set_wedge: sets the halt feature and ignores clear requests
1296 *
1297 * Check usb_ep_set_wedge() at "usb_gadget.h" for details
1298 */
1299static int ep_set_wedge(struct usb_ep *ep)
1300{
1301 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
1302 unsigned long flags;
1303
Ido Shayevitz31fb6012012-03-12 20:25:23 +02001304 if (ep == NULL || mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001305 return -EINVAL;
1306
1307 spin_lock_irqsave(mEp->lock, flags);
1308
1309 dbg_event(_usb_addr(mEp), "WEDGE", 0);
1310 mEp->wedge = 1;
1311
1312 spin_unlock_irqrestore(mEp->lock, flags);
1313
1314 return usb_ep_set_halt(ep);
1315}
1316
1317/**
1318 * ep_fifo_flush: flushes contents of a fifo
1319 *
1320 * Check usb_ep_fifo_flush() at "usb_gadget.h" for details
1321 */
1322static void ep_fifo_flush(struct usb_ep *ep)
1323{
1324 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
1325 unsigned long flags;
1326
David Lopoaa69a802008-11-17 14:14:51 -08001327 if (ep == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001328 dev_err(mEp->udc->dev, "%02X: -EINVAL\n", _usb_addr(mEp));
David Lopoaa69a802008-11-17 14:14:51 -08001329 return;
1330 }
1331
1332 spin_lock_irqsave(mEp->lock, flags);
1333
1334 dbg_event(_usb_addr(mEp), "FFLUSH", 0);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001335 hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08001336
1337 spin_unlock_irqrestore(mEp->lock, flags);
1338}
1339
1340/**
1341 * Endpoint-specific part of the API to the USB controller hardware
1342 * Check "usb_gadget.h" for details
1343 */
1344static const struct usb_ep_ops usb_ep_ops = {
1345 .enable = ep_enable,
1346 .disable = ep_disable,
1347 .alloc_request = ep_alloc_request,
1348 .free_request = ep_free_request,
1349 .queue = ep_queue,
1350 .dequeue = ep_dequeue,
1351 .set_halt = ep_set_halt,
1352 .set_wedge = ep_set_wedge,
1353 .fifo_flush = ep_fifo_flush,
1354};
1355
1356/******************************************************************************
1357 * GADGET block
1358 *****************************************************************************/
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301359static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
1360{
1361 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
1362 unsigned long flags;
1363 int gadget_ready = 0;
1364
1365 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS))
1366 return -EOPNOTSUPP;
1367
Alexander Shishkind3595d12012-05-08 23:28:58 +03001368 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301369 udc->vbus_active = is_active;
1370 if (udc->driver)
1371 gadget_ready = 1;
Alexander Shishkind3595d12012-05-08 23:28:58 +03001372 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301373
1374 if (gadget_ready) {
1375 if (is_active) {
Pavankumar Kondetic0360192010-12-07 17:54:04 +05301376 pm_runtime_get_sync(&_gadget->dev);
Alexander Shishkineb70e5a2012-05-11 17:25:54 +03001377 hw_device_reset(udc, USBMODE_CM_DC);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001378 hw_device_state(udc, udc->ep0out->qh.dma);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301379 } else {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001380 hw_device_state(udc, 0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301381 if (udc->udc_driver->notify_event)
1382 udc->udc_driver->notify_event(udc,
1383 CI13XXX_CONTROLLER_STOPPED_EVENT);
1384 _gadget_stop_activity(&udc->gadget);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05301385 pm_runtime_put_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301386 }
1387 }
1388
1389 return 0;
1390}
1391
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301392static int ci13xxx_wakeup(struct usb_gadget *_gadget)
1393{
1394 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
1395 unsigned long flags;
1396 int ret = 0;
1397
Alexander Shishkind3595d12012-05-08 23:28:58 +03001398 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301399 if (!udc->remote_wakeup) {
1400 ret = -EOPNOTSUPP;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301401 goto out;
1402 }
Alexander Shishkin262c1632012-05-08 23:28:59 +03001403 if (!hw_read(udc, OP_PORTSC, PORTSC_SUSP)) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301404 ret = -EINVAL;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301405 goto out;
1406 }
Alexander Shishkin262c1632012-05-08 23:28:59 +03001407 hw_write(udc, OP_PORTSC, PORTSC_FPR, PORTSC_FPR);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301408out:
Alexander Shishkind3595d12012-05-08 23:28:58 +03001409 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301410 return ret;
1411}
1412
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301413static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
1414{
1415 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
1416
1417 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02001418 return usb_phy_set_power(udc->transceiver, mA);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301419 return -ENOTSUPP;
1420}
1421
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001422static int ci13xxx_start(struct usb_gadget *gadget,
1423 struct usb_gadget_driver *driver);
1424static int ci13xxx_stop(struct usb_gadget *gadget,
1425 struct usb_gadget_driver *driver);
David Lopoaa69a802008-11-17 14:14:51 -08001426/**
1427 * Device operations part of the API to the USB controller hardware,
1428 * which don't involve endpoints (or i/o)
1429 * Check "usb_gadget.h" for details
1430 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301431static const struct usb_gadget_ops usb_gadget_ops = {
1432 .vbus_session = ci13xxx_vbus_session,
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301433 .wakeup = ci13xxx_wakeup,
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301434 .vbus_draw = ci13xxx_vbus_draw,
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001435 .udc_start = ci13xxx_start,
1436 .udc_stop = ci13xxx_stop,
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301437};
David Lopoaa69a802008-11-17 14:14:51 -08001438
Alexander Shishkin790c2d52012-05-08 23:29:03 +03001439static int init_eps(struct ci13xxx *udc)
1440{
1441 int retval = 0, i, j;
1442
1443 for (i = 0; i < udc->hw_ep_max/2; i++)
1444 for (j = RX; j <= TX; j++) {
1445 int k = i + j * udc->hw_ep_max/2;
1446 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
1447
1448 scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
1449 (j == TX) ? "in" : "out");
1450
1451 mEp->udc = udc;
1452 mEp->lock = &udc->lock;
Alexander Shishkin790c2d52012-05-08 23:29:03 +03001453 mEp->td_pool = udc->td_pool;
1454
1455 mEp->ep.name = mEp->name;
1456 mEp->ep.ops = &usb_ep_ops;
1457 mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
1458
1459 INIT_LIST_HEAD(&mEp->qh.queue);
1460 mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
1461 &mEp->qh.dma);
1462 if (mEp->qh.ptr == NULL)
1463 retval = -ENOMEM;
1464 else
1465 memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
1466
1467 /*
1468 * set up shorthands for ep0 out and in endpoints,
1469 * don't add to gadget's ep_list
1470 */
1471 if (i == 0) {
1472 if (j == RX)
1473 udc->ep0out = mEp;
1474 else
1475 udc->ep0in = mEp;
1476
1477 continue;
1478 }
1479
1480 list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
1481 }
1482
1483 return retval;
1484}
1485
David Lopoaa69a802008-11-17 14:14:51 -08001486/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001487 * ci13xxx_start: register a gadget driver
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001488 * @gadget: our gadget
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02001489 * @driver: the driver being registered
David Lopoaa69a802008-11-17 14:14:51 -08001490 *
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02001491 * Interrupts are enabled here.
David Lopoaa69a802008-11-17 14:14:51 -08001492 */
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001493static int ci13xxx_start(struct usb_gadget *gadget,
1494 struct usb_gadget_driver *driver)
David Lopoaa69a802008-11-17 14:14:51 -08001495{
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001496 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301497 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -08001498 int retval = -ENOMEM;
1499
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001500 if (driver->disconnect == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001501 return -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -08001502
David Lopoaa69a802008-11-17 14:14:51 -08001503
Alexander Shishkind36ade62012-05-04 16:47:15 +03001504 udc->ep0out->ep.desc = &ctrl_endpt_out_desc;
1505 retval = usb_ep_enable(&udc->ep0out->ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05301506 if (retval)
1507 return retval;
Felipe Balbi877c1f52011-06-29 16:41:57 +03001508
Alexander Shishkind36ade62012-05-04 16:47:15 +03001509 udc->ep0in->ep.desc = &ctrl_endpt_in_desc;
1510 retval = usb_ep_enable(&udc->ep0in->ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05301511 if (retval)
1512 return retval;
Alexander Shishkind3595d12012-05-08 23:28:58 +03001513 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001514
Pavankumar Kondeti49d3df52011-01-11 09:19:21 +05301515 udc->driver = driver;
Pavankumar Kondetic0360192010-12-07 17:54:04 +05301516 pm_runtime_get_sync(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301517 if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
1518 if (udc->vbus_active) {
1519 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
Alexander Shishkineb70e5a2012-05-11 17:25:54 +03001520 hw_device_reset(udc, USBMODE_CM_DC);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301521 } else {
Pavankumar Kondetic0360192010-12-07 17:54:04 +05301522 pm_runtime_put_sync(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301523 goto done;
1524 }
1525 }
1526
Alexander Shishkind3595d12012-05-08 23:28:58 +03001527 retval = hw_device_state(udc, udc->ep0out->qh.dma);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05301528 if (retval)
1529 pm_runtime_put_sync(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08001530
1531 done:
Alexander Shishkind3595d12012-05-08 23:28:58 +03001532 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001533 return retval;
1534}
David Lopoaa69a802008-11-17 14:14:51 -08001535
1536/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001537 * ci13xxx_stop: unregister a gadget driver
David Lopoaa69a802008-11-17 14:14:51 -08001538 */
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001539static int ci13xxx_stop(struct usb_gadget *gadget,
1540 struct usb_gadget_driver *driver)
David Lopoaa69a802008-11-17 14:14:51 -08001541{
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001542 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
1543 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -08001544
Alexander Shishkind3595d12012-05-08 23:28:58 +03001545 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001546
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301547 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) ||
1548 udc->vbus_active) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001549 hw_device_state(udc, 0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301550 if (udc->udc_driver->notify_event)
1551 udc->udc_driver->notify_event(udc,
1552 CI13XXX_CONTROLLER_STOPPED_EVENT);
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001553 udc->driver = NULL;
Alexander Shishkind3595d12012-05-08 23:28:58 +03001554 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301555 _gadget_stop_activity(&udc->gadget);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001556 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05301557 pm_runtime_put(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301558 }
David Lopoaa69a802008-11-17 14:14:51 -08001559
Alexander Shishkind3595d12012-05-08 23:28:58 +03001560 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001561
David Lopoaa69a802008-11-17 14:14:51 -08001562 return 0;
1563}
David Lopoaa69a802008-11-17 14:14:51 -08001564
1565/******************************************************************************
1566 * BUS block
1567 *****************************************************************************/
1568/**
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001569 * udc_irq: udc interrupt handler
David Lopoaa69a802008-11-17 14:14:51 -08001570 *
1571 * This function returns IRQ_HANDLED if the IRQ has been handled
1572 * It locks access to registers
1573 */
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001574static irqreturn_t udc_irq(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -08001575{
David Lopoaa69a802008-11-17 14:14:51 -08001576 irqreturn_t retval;
1577 u32 intr;
1578
Greg Kroah-Hartmanf6395542012-05-10 11:37:18 -07001579 if (udc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001580 return IRQ_HANDLED;
David Lopoaa69a802008-11-17 14:14:51 -08001581
Alexander Shishkind3595d12012-05-08 23:28:58 +03001582 spin_lock(&udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301583
1584 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) {
Alexander Shishkin262c1632012-05-08 23:28:59 +03001585 if (hw_read(udc, OP_USBMODE, USBMODE_CM) !=
Alexander Shishkin758fc982012-05-11 17:25:53 +03001586 USBMODE_CM_DC) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001587 spin_unlock(&udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301588 return IRQ_NONE;
1589 }
1590 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03001591 intr = hw_test_and_clear_intr_active(udc);
Alexander Shishkine443b332012-05-11 17:25:46 +03001592 dbg_interrupt(intr);
David Lopoaa69a802008-11-17 14:14:51 -08001593
Alexander Shishkine443b332012-05-11 17:25:46 +03001594 if (intr) {
David Lopoaa69a802008-11-17 14:14:51 -08001595 /* order defines priority - do NOT change it */
Alexander Shishkine443b332012-05-11 17:25:46 +03001596 if (USBi_URI & intr)
David Lopoaa69a802008-11-17 14:14:51 -08001597 isr_reset_handler(udc);
Alexander Shishkine443b332012-05-11 17:25:46 +03001598
David Lopoaa69a802008-11-17 14:14:51 -08001599 if (USBi_PCI & intr) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001600 udc->gadget.speed = hw_port_is_high_speed(udc) ?
David Lopoaa69a802008-11-17 14:14:51 -08001601 USB_SPEED_HIGH : USB_SPEED_FULL;
Marc Kleine-Budde7bb4fdc2011-10-10 18:38:09 +02001602 if (udc->suspended && udc->driver->resume) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001603 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301604 udc->driver->resume(&udc->gadget);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001605 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301606 udc->suspended = 0;
1607 }
David Lopoaa69a802008-11-17 14:14:51 -08001608 }
Alexander Shishkine443b332012-05-11 17:25:46 +03001609
1610 if (USBi_UI & intr)
David Lopoaa69a802008-11-17 14:14:51 -08001611 isr_tr_complete_handler(udc);
Alexander Shishkine443b332012-05-11 17:25:46 +03001612
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301613 if (USBi_SLI & intr) {
Marc Kleine-Budde7bb4fdc2011-10-10 18:38:09 +02001614 if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
1615 udc->driver->suspend) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301616 udc->suspended = 1;
Alexander Shishkind3595d12012-05-08 23:28:58 +03001617 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301618 udc->driver->suspend(&udc->gadget);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001619 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301620 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301621 }
David Lopoaa69a802008-11-17 14:14:51 -08001622 retval = IRQ_HANDLED;
1623 } else {
David Lopoaa69a802008-11-17 14:14:51 -08001624 retval = IRQ_NONE;
1625 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03001626 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001627
1628 return retval;
1629}
1630
1631/**
1632 * udc_release: driver release function
1633 * @dev: device
1634 *
1635 * Currently does nothing
1636 */
1637static void udc_release(struct device *dev)
1638{
David Lopoaa69a802008-11-17 14:14:51 -08001639}
1640
1641/**
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001642 * udc_start: initialize gadget role
1643 * @udc: chipidea controller
David Lopoaa69a802008-11-17 14:14:51 -08001644 */
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001645static int udc_start(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -08001646{
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001647 struct device *dev = udc->dev;
David Lopoaa69a802008-11-17 14:14:51 -08001648 int retval = 0;
1649
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001650 if (!udc)
David Lopoaa69a802008-11-17 14:14:51 -08001651 return -EINVAL;
1652
Alexander Shishkind3595d12012-05-08 23:28:58 +03001653 spin_lock_init(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001654
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301655 udc->gadget.ops = &usb_gadget_ops;
David Lopoaa69a802008-11-17 14:14:51 -08001656 udc->gadget.speed = USB_SPEED_UNKNOWN;
Michal Nazarewiczd327ab52011-11-19 18:27:37 +01001657 udc->gadget.max_speed = USB_SPEED_HIGH;
David Lopoaa69a802008-11-17 14:14:51 -08001658 udc->gadget.is_otg = 0;
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001659 udc->gadget.name = udc->udc_driver->name;
David Lopoaa69a802008-11-17 14:14:51 -08001660
1661 INIT_LIST_HEAD(&udc->gadget.ep_list);
David Lopoaa69a802008-11-17 14:14:51 -08001662
Kay Sievers5df58522009-03-24 16:38:23 -07001663 dev_set_name(&udc->gadget.dev, "gadget");
David Lopoaa69a802008-11-17 14:14:51 -08001664 udc->gadget.dev.dma_mask = dev->dma_mask;
Pavankumar Kondeti61948ee2010-12-07 17:54:01 +05301665 udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
David Lopoaa69a802008-11-17 14:14:51 -08001666 udc->gadget.dev.parent = dev;
1667 udc->gadget.dev.release = udc_release;
1668
Alexander Shishkin790c2d52012-05-08 23:29:03 +03001669 /* alloc resources */
1670 udc->qh_pool = dma_pool_create("ci13xxx_qh", dev,
1671 sizeof(struct ci13xxx_qh),
1672 64, CI13XXX_PAGE_SIZE);
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001673 if (udc->qh_pool == NULL)
1674 return -ENOMEM;
Alexander Shishkin790c2d52012-05-08 23:29:03 +03001675
1676 udc->td_pool = dma_pool_create("ci13xxx_td", dev,
1677 sizeof(struct ci13xxx_td),
1678 64, CI13XXX_PAGE_SIZE);
1679 if (udc->td_pool == NULL) {
1680 retval = -ENOMEM;
1681 goto free_qh_pool;
1682 }
1683
Alexander Shishkin790c2d52012-05-08 23:29:03 +03001684 retval = init_eps(udc);
1685 if (retval)
1686 goto free_pools;
1687
1688 udc->gadget.ep0 = &udc->ep0in->ep;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301689
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02001690 udc->transceiver = usb_get_transceiver();
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301691
1692 if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
1693 if (udc->transceiver == NULL) {
1694 retval = -ENODEV;
Alexander Shishkin790c2d52012-05-08 23:29:03 +03001695 goto free_pools;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301696 }
1697 }
1698
1699 if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) {
Alexander Shishkineb70e5a2012-05-11 17:25:54 +03001700 retval = hw_device_reset(udc, USBMODE_CM_DC);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301701 if (retval)
1702 goto put_transceiver;
1703 }
1704
David Lopoaa69a802008-11-17 14:14:51 -08001705 retval = device_register(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301706 if (retval) {
1707 put_device(&udc->gadget.dev);
1708 goto put_transceiver;
1709 }
David Lopoaa69a802008-11-17 14:14:51 -08001710
David Lopoaa69a802008-11-17 14:14:51 -08001711 retval = dbg_create_files(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301712 if (retval)
1713 goto unreg_device;
1714
1715 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02001716 retval = otg_set_peripheral(udc->transceiver->otg,
1717 &udc->gadget);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301718 if (retval)
1719 goto remove_dbg;
David Lopoaa69a802008-11-17 14:14:51 -08001720 }
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001721
1722 retval = usb_add_gadget_udc(dev, &udc->gadget);
1723 if (retval)
1724 goto remove_trans;
1725
Pavankumar Kondetic0360192010-12-07 17:54:04 +05301726 pm_runtime_no_callbacks(&udc->gadget.dev);
1727 pm_runtime_enable(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08001728
David Lopoaa69a802008-11-17 14:14:51 -08001729 return retval;
1730
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001731remove_trans:
1732 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02001733 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02001734 usb_put_transceiver(udc->transceiver);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001735 }
1736
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07001737 dev_err(dev, "error = %i\n", retval);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301738remove_dbg:
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301739 dbg_remove_files(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301740unreg_device:
1741 device_unregister(&udc->gadget.dev);
1742put_transceiver:
1743 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02001744 usb_put_transceiver(udc->transceiver);
Alexander Shishkin790c2d52012-05-08 23:29:03 +03001745free_pools:
1746 dma_pool_destroy(udc->td_pool);
1747free_qh_pool:
1748 dma_pool_destroy(udc->qh_pool);
David Lopoaa69a802008-11-17 14:14:51 -08001749 return retval;
1750}
1751
1752/**
1753 * udc_remove: parent remove must call this to remove UDC
1754 *
1755 * No interrupts active, the IRQ has been released
1756 */
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001757static void udc_stop(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -08001758{
Alexander Shishkin790c2d52012-05-08 23:29:03 +03001759 int i;
David Lopoaa69a802008-11-17 14:14:51 -08001760
Alexander Shishkin0f089092012-05-08 23:29:02 +03001761 if (udc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001762 return;
Alexander Shishkin0f089092012-05-08 23:29:02 +03001763
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001764 usb_del_gadget_udc(&udc->gadget);
David Lopoaa69a802008-11-17 14:14:51 -08001765
Alexander Shishkin790c2d52012-05-08 23:29:03 +03001766 for (i = 0; i < udc->hw_ep_max; i++) {
1767 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
1768
1769 dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
1770 }
1771
1772 dma_pool_destroy(udc->td_pool);
1773 dma_pool_destroy(udc->qh_pool);
1774
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301775 if (udc->transceiver) {
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001776 otg_set_peripheral(udc->transceiver->otg, NULL);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02001777 usb_put_transceiver(udc->transceiver);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301778 }
David Lopoaa69a802008-11-17 14:14:51 -08001779 dbg_remove_files(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08001780 device_unregister(&udc->gadget.dev);
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001781 /* my kobject is dynamic, I swear! */
1782 memset(&udc->gadget, 0, sizeof(udc->gadget));
1783}
David Lopoaa69a802008-11-17 14:14:51 -08001784
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001785/**
1786 * ci_hdrc_gadget_init - initialize device related bits
1787 * ci: the controller
1788 *
1789 * This function enables the gadget role, if the device is "device capable".
1790 */
1791int ci_hdrc_gadget_init(struct ci13xxx *ci)
1792{
1793 struct ci_role_driver *rdrv;
1794
1795 if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_DC))
1796 return -ENXIO;
1797
1798 rdrv = devm_kzalloc(ci->dev, sizeof(struct ci_role_driver), GFP_KERNEL);
1799 if (!rdrv)
1800 return -ENOMEM;
1801
1802 rdrv->start = udc_start;
1803 rdrv->stop = udc_stop;
1804 rdrv->irq = udc_irq;
1805 rdrv->name = "gadget";
1806 ci->roles[CI_ROLE_GADGET] = rdrv;
1807
1808 return 0;
David Lopoaa69a802008-11-17 14:14:51 -08001809}