blob: 290946d618d834c5fdc4314af16a6a7c21efbf2c [file] [log] [blame]
David Lopoaa69a802008-11-17 14:14:51 -08001/*
Alexander Shishkine443b332012-05-11 17:25:46 +03002 * udc.h - 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;
Michael Grzeschik954aad82011-10-10 18:38:06 +0200407 if (length && mReq->req.dma == DMA_ADDR_INVALID) {
David Lopoaa69a802008-11-17 14:14:51 -0800408 mReq->req.dma = \
409 dma_map_single(mEp->device, mReq->req.buf,
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530410 length, mEp->dir ? DMA_TO_DEVICE :
411 DMA_FROM_DEVICE);
David Lopoaa69a802008-11-17 14:14:51 -0800412 if (mReq->req.dma == 0)
413 return -ENOMEM;
414
415 mReq->map = 1;
416 }
417
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530418 if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) {
419 mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC,
420 &mReq->zdma);
421 if (mReq->zptr == NULL) {
422 if (mReq->map) {
423 dma_unmap_single(mEp->device, mReq->req.dma,
424 length, mEp->dir ? DMA_TO_DEVICE :
425 DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +0200426 mReq->req.dma = DMA_ADDR_INVALID;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530427 mReq->map = 0;
428 }
429 return -ENOMEM;
430 }
431 memset(mReq->zptr, 0, sizeof(*mReq->zptr));
432 mReq->zptr->next = TD_TERMINATE;
433 mReq->zptr->token = TD_STATUS_ACTIVE;
434 if (!mReq->req.no_interrupt)
435 mReq->zptr->token |= TD_IOC;
436 }
David Lopoaa69a802008-11-17 14:14:51 -0800437 /*
438 * TD configuration
439 * TODO - handle requests which spawns into several TDs
440 */
441 memset(mReq->ptr, 0, sizeof(*mReq->ptr));
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530442 mReq->ptr->token = length << ffs_nr(TD_TOTAL_BYTES);
David Lopoaa69a802008-11-17 14:14:51 -0800443 mReq->ptr->token &= TD_TOTAL_BYTES;
David Lopoaa69a802008-11-17 14:14:51 -0800444 mReq->ptr->token |= TD_STATUS_ACTIVE;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530445 if (mReq->zptr) {
446 mReq->ptr->next = mReq->zdma;
447 } else {
448 mReq->ptr->next = TD_TERMINATE;
449 if (!mReq->req.no_interrupt)
450 mReq->ptr->token |= TD_IOC;
451 }
David Lopoaa69a802008-11-17 14:14:51 -0800452 mReq->ptr->page[0] = mReq->req.dma;
453 for (i = 1; i < 5; i++)
454 mReq->ptr->page[i] =
Artem Leonenko0a313c42010-12-14 23:47:06 -0800455 (mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK;
David Lopoaa69a802008-11-17 14:14:51 -0800456
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530457 if (!list_empty(&mEp->qh.queue)) {
458 struct ci13xxx_req *mReqPrev;
459 int n = hw_ep_bit(mEp->num, mEp->dir);
460 int tmp_stat;
461
462 mReqPrev = list_entry(mEp->qh.queue.prev,
463 struct ci13xxx_req, queue);
464 if (mReqPrev->zptr)
465 mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
466 else
467 mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
468 wmb();
Alexander Shishkin262c1632012-05-08 23:28:59 +0300469 if (hw_read(udc, OP_ENDPTPRIME, BIT(n)))
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530470 goto done;
471 do {
Alexander Shishkin262c1632012-05-08 23:28:59 +0300472 hw_write(udc, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
473 tmp_stat = hw_read(udc, OP_ENDPTSTAT, BIT(n));
474 } while (!hw_read(udc, OP_USBCMD, USBCMD_ATDTW));
475 hw_write(udc, OP_USBCMD, USBCMD_ATDTW, 0);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530476 if (tmp_stat)
477 goto done;
478 }
479
480 /* QH configuration */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530481 mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */
482 mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530483 mEp->qh.ptr->cap |= QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -0800484
485 wmb(); /* synchronize before ep prime */
486
Alexander Shishkind3595d12012-05-08 23:28:58 +0300487 ret = hw_ep_prime(udc, mEp->num, mEp->dir,
David Lopoaa69a802008-11-17 14:14:51 -0800488 mEp->type == USB_ENDPOINT_XFER_CONTROL);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530489done:
490 return ret;
David Lopoaa69a802008-11-17 14:14:51 -0800491}
492
493/**
494 * _hardware_dequeue: handles a request at hardware level
495 * @gadget: gadget
496 * @mEp: endpoint
497 *
498 * This function returns an error code
499 */
500static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
501{
David Lopoaa69a802008-11-17 14:14:51 -0800502 if (mReq->req.status != -EALREADY)
503 return -EINVAL;
504
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530505 if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
506 return -EBUSY;
507
508 if (mReq->zptr) {
509 if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
510 return -EBUSY;
511 dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
512 mReq->zptr = NULL;
513 }
David Lopoaa69a802008-11-17 14:14:51 -0800514
515 mReq->req.status = 0;
516
517 if (mReq->map) {
518 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
519 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +0200520 mReq->req.dma = DMA_ADDR_INVALID;
David Lopoaa69a802008-11-17 14:14:51 -0800521 mReq->map = 0;
522 }
523
524 mReq->req.status = mReq->ptr->token & TD_STATUS;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530525 if ((TD_STATUS_HALTED & mReq->req.status) != 0)
David Lopoaa69a802008-11-17 14:14:51 -0800526 mReq->req.status = -1;
527 else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0)
528 mReq->req.status = -1;
529 else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0)
530 mReq->req.status = -1;
531
532 mReq->req.actual = mReq->ptr->token & TD_TOTAL_BYTES;
533 mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES);
534 mReq->req.actual = mReq->req.length - mReq->req.actual;
535 mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual;
536
537 return mReq->req.actual;
538}
539
540/**
541 * _ep_nuke: dequeues all endpoint requests
542 * @mEp: endpoint
543 *
544 * This function returns an error code
545 * Caller must hold lock
546 */
547static int _ep_nuke(struct ci13xxx_ep *mEp)
548__releases(mEp->lock)
549__acquires(mEp->lock)
550{
David Lopoaa69a802008-11-17 14:14:51 -0800551 if (mEp == NULL)
552 return -EINVAL;
553
Alexander Shishkind3595d12012-05-08 23:28:58 +0300554 hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -0800555
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530556 while (!list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -0800557
558 /* pop oldest request */
559 struct ci13xxx_req *mReq = \
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530560 list_entry(mEp->qh.queue.next,
David Lopoaa69a802008-11-17 14:14:51 -0800561 struct ci13xxx_req, queue);
562 list_del_init(&mReq->queue);
563 mReq->req.status = -ESHUTDOWN;
564
Artem Leonenko7c25a822010-12-14 23:46:55 -0800565 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -0800566 spin_unlock(mEp->lock);
567 mReq->req.complete(&mEp->ep, &mReq->req);
568 spin_lock(mEp->lock);
569 }
570 }
571 return 0;
572}
573
574/**
575 * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
576 * @gadget: gadget
577 *
578 * This function returns an error code
David Lopoaa69a802008-11-17 14:14:51 -0800579 */
580static int _gadget_stop_activity(struct usb_gadget *gadget)
David Lopoaa69a802008-11-17 14:14:51 -0800581{
582 struct usb_ep *ep;
583 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530584 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -0800585
Alexander Shishkind3595d12012-05-08 23:28:58 +0300586 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530587 udc->gadget.speed = USB_SPEED_UNKNOWN;
588 udc->remote_wakeup = 0;
589 udc->suspended = 0;
Alexander Shishkind3595d12012-05-08 23:28:58 +0300590 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530591
David Lopoaa69a802008-11-17 14:14:51 -0800592 /* flush all endpoints */
593 gadget_for_each_ep(ep, gadget) {
594 usb_ep_fifo_flush(ep);
595 }
Alexander Shishkind36ade62012-05-04 16:47:15 +0300596 usb_ep_fifo_flush(&udc->ep0out->ep);
597 usb_ep_fifo_flush(&udc->ep0in->ep);
David Lopoaa69a802008-11-17 14:14:51 -0800598
Alexander Shishkin1f339d82012-05-08 23:29:04 +0300599 if (udc->driver)
600 udc->driver->disconnect(gadget);
David Lopoaa69a802008-11-17 14:14:51 -0800601
602 /* make sure to disable all endpoints */
603 gadget_for_each_ep(ep, gadget) {
604 usb_ep_disable(ep);
605 }
David Lopoaa69a802008-11-17 14:14:51 -0800606
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530607 if (udc->status != NULL) {
Alexander Shishkind36ade62012-05-04 16:47:15 +0300608 usb_ep_free_request(&udc->ep0in->ep, udc->status);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530609 udc->status = NULL;
David Lopoaa69a802008-11-17 14:14:51 -0800610 }
611
David Lopoaa69a802008-11-17 14:14:51 -0800612 return 0;
613}
614
615/******************************************************************************
616 * ISR block
617 *****************************************************************************/
618/**
619 * isr_reset_handler: USB reset interrupt handler
620 * @udc: UDC device
621 *
622 * This function resets USB engine after a bus reset occurred
623 */
624static void isr_reset_handler(struct ci13xxx *udc)
625__releases(udc->lock)
626__acquires(udc->lock)
627{
David Lopoaa69a802008-11-17 14:14:51 -0800628 int retval;
629
David Lopoaa69a802008-11-17 14:14:51 -0800630 dbg_event(0xFF, "BUS RST", 0);
631
Alexander Shishkind3595d12012-05-08 23:28:58 +0300632 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -0800633 retval = _gadget_stop_activity(&udc->gadget);
634 if (retval)
635 goto done;
636
Alexander Shishkind3595d12012-05-08 23:28:58 +0300637 retval = hw_usb_reset(udc);
David Lopoaa69a802008-11-17 14:14:51 -0800638 if (retval)
639 goto done;
640
Alexander Shishkind36ade62012-05-04 16:47:15 +0300641 udc->status = usb_ep_alloc_request(&udc->ep0in->ep, GFP_ATOMIC);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +0530642 if (udc->status == NULL)
643 retval = -ENOMEM;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530644
Michael Grzeschikb9322252012-05-11 17:25:50 +0300645done:
Alexander Shishkind3595d12012-05-08 23:28:58 +0300646 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -0800647
David Lopoaa69a802008-11-17 14:14:51 -0800648 if (retval)
Alexander Shishkin0f089092012-05-08 23:29:02 +0300649 dev_err(udc->dev, "error: %i\n", retval);
David Lopoaa69a802008-11-17 14:14:51 -0800650}
651
652/**
653 * isr_get_status_complete: get_status request complete function
654 * @ep: endpoint
655 * @req: request handled
656 *
657 * Caller must release lock
658 */
659static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
660{
Alexander Shishkin0f089092012-05-08 23:29:02 +0300661 if (ep == NULL || req == NULL)
David Lopoaa69a802008-11-17 14:14:51 -0800662 return;
David Lopoaa69a802008-11-17 14:14:51 -0800663
664 kfree(req->buf);
665 usb_ep_free_request(ep, req);
666}
667
668/**
669 * isr_get_status_response: get_status request response
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530670 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -0800671 * @setup: setup request packet
672 *
673 * This function returns an error code
674 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530675static int isr_get_status_response(struct ci13xxx *udc,
David Lopoaa69a802008-11-17 14:14:51 -0800676 struct usb_ctrlrequest *setup)
677__releases(mEp->lock)
678__acquires(mEp->lock)
679{
Alexander Shishkind36ade62012-05-04 16:47:15 +0300680 struct ci13xxx_ep *mEp = udc->ep0in;
David Lopoaa69a802008-11-17 14:14:51 -0800681 struct usb_request *req = NULL;
682 gfp_t gfp_flags = GFP_ATOMIC;
683 int dir, num, retval;
684
David Lopoaa69a802008-11-17 14:14:51 -0800685 if (mEp == NULL || setup == NULL)
686 return -EINVAL;
687
688 spin_unlock(mEp->lock);
689 req = usb_ep_alloc_request(&mEp->ep, gfp_flags);
690 spin_lock(mEp->lock);
691 if (req == NULL)
692 return -ENOMEM;
693
694 req->complete = isr_get_status_complete;
695 req->length = 2;
696 req->buf = kzalloc(req->length, gfp_flags);
697 if (req->buf == NULL) {
698 retval = -ENOMEM;
699 goto err_free_req;
700 }
701
702 if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530703 /* Assume that device is bus powered for now. */
Alexander Shishkin1f339d82012-05-08 23:29:04 +0300704 *(u16 *)req->buf = udc->remote_wakeup << 1;
David Lopoaa69a802008-11-17 14:14:51 -0800705 retval = 0;
706 } else if ((setup->bRequestType & USB_RECIP_MASK) \
707 == USB_RECIP_ENDPOINT) {
708 dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
709 TX : RX;
710 num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK;
Alexander Shishkind3595d12012-05-08 23:28:58 +0300711 *(u16 *)req->buf = hw_ep_get_halt(udc, num, dir);
David Lopoaa69a802008-11-17 14:14:51 -0800712 }
713 /* else do nothing; reserved for future use */
714
715 spin_unlock(mEp->lock);
716 retval = usb_ep_queue(&mEp->ep, req, gfp_flags);
717 spin_lock(mEp->lock);
718 if (retval)
719 goto err_free_buf;
720
721 return 0;
722
723 err_free_buf:
724 kfree(req->buf);
725 err_free_req:
726 spin_unlock(mEp->lock);
727 usb_ep_free_request(&mEp->ep, req);
728 spin_lock(mEp->lock);
729 return retval;
730}
731
732/**
Pavankumar Kondeti541cace2011-02-18 17:43:18 +0530733 * isr_setup_status_complete: setup_status request complete function
734 * @ep: endpoint
735 * @req: request handled
736 *
737 * Caller must release lock. Put the port in test mode if test mode
738 * feature is selected.
739 */
740static void
741isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
742{
743 struct ci13xxx *udc = req->context;
744 unsigned long flags;
745
Alexander Shishkinef15e542012-05-11 17:25:43 +0300746 if (udc->setaddr) {
747 hw_usb_set_address(udc, udc->address);
748 udc->setaddr = false;
749 }
750
Alexander Shishkind3595d12012-05-08 23:28:58 +0300751 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondeti541cace2011-02-18 17:43:18 +0530752 if (udc->test_mode)
Alexander Shishkind3595d12012-05-08 23:28:58 +0300753 hw_port_test_set(udc, udc->test_mode);
754 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondeti541cace2011-02-18 17:43:18 +0530755}
756
757/**
David Lopoaa69a802008-11-17 14:14:51 -0800758 * isr_setup_status_phase: queues the status phase of a setup transation
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530759 * @udc: udc struct
David Lopoaa69a802008-11-17 14:14:51 -0800760 *
761 * This function returns an error code
762 */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530763static int isr_setup_status_phase(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -0800764__releases(mEp->lock)
765__acquires(mEp->lock)
766{
767 int retval;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530768 struct ci13xxx_ep *mEp;
David Lopoaa69a802008-11-17 14:14:51 -0800769
Alexander Shishkind36ade62012-05-04 16:47:15 +0300770 mEp = (udc->ep0_dir == TX) ? udc->ep0out : udc->ep0in;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +0530771 udc->status->context = udc;
772 udc->status->complete = isr_setup_status_complete;
David Lopoaa69a802008-11-17 14:14:51 -0800773
774 spin_unlock(mEp->lock);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530775 retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
David Lopoaa69a802008-11-17 14:14:51 -0800776 spin_lock(mEp->lock);
777
778 return retval;
779}
780
781/**
782 * isr_tr_complete_low: transaction complete low level handler
783 * @mEp: endpoint
784 *
785 * This function returns an error code
786 * Caller must hold lock
787 */
788static int isr_tr_complete_low(struct ci13xxx_ep *mEp)
789__releases(mEp->lock)
790__acquires(mEp->lock)
791{
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530792 struct ci13xxx_req *mReq, *mReqTemp;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +0530793 struct ci13xxx_ep *mEpTemp = mEp;
Pavankumar Kondeti986b11b2011-05-02 11:56:29 +0530794 int uninitialized_var(retval);
David Lopoaa69a802008-11-17 14:14:51 -0800795
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530796 if (list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -0800797 return -EINVAL;
798
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530799 list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,
800 queue) {
801 retval = _hardware_dequeue(mEp, mReq);
802 if (retval < 0)
803 break;
804 list_del_init(&mReq->queue);
805 dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
806 if (mReq->req.complete != NULL) {
807 spin_unlock(mEp->lock);
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +0530808 if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
809 mReq->req.length)
Alexander Shishkin1f339d82012-05-08 23:29:04 +0300810 mEpTemp = mEp->udc->ep0in;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +0530811 mReq->req.complete(&mEpTemp->ep, &mReq->req);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530812 spin_lock(mEp->lock);
813 }
814 }
David Lopoaa69a802008-11-17 14:14:51 -0800815
Pavankumar Kondetief907482011-05-02 11:56:27 +0530816 if (retval == -EBUSY)
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +0530817 retval = 0;
818 if (retval < 0)
David Lopoaa69a802008-11-17 14:14:51 -0800819 dbg_event(_usb_addr(mEp), "DONE", retval);
David Lopoaa69a802008-11-17 14:14:51 -0800820
David Lopoaa69a802008-11-17 14:14:51 -0800821 return retval;
822}
823
824/**
825 * isr_tr_complete_handler: transaction complete interrupt handler
826 * @udc: UDC descriptor
827 *
828 * This function handles traffic events
829 */
830static void isr_tr_complete_handler(struct ci13xxx *udc)
831__releases(udc->lock)
832__acquires(udc->lock)
833{
834 unsigned i;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +0530835 u8 tmode = 0;
David Lopoaa69a802008-11-17 14:14:51 -0800836
Alexander Shishkind3595d12012-05-08 23:28:58 +0300837 for (i = 0; i < udc->hw_ep_max; i++) {
David Lopoaa69a802008-11-17 14:14:51 -0800838 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +0530839 int type, num, dir, err = -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -0800840 struct usb_ctrlrequest req;
841
Ido Shayevitz31fb6012012-03-12 20:25:23 +0200842 if (mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -0800843 continue; /* not configured */
844
Alexander Shishkind3595d12012-05-08 23:28:58 +0300845 if (hw_test_and_clear_complete(udc, i)) {
David Lopoaa69a802008-11-17 14:14:51 -0800846 err = isr_tr_complete_low(mEp);
847 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
848 if (err > 0) /* needs status phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530849 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -0800850 if (err < 0) {
851 dbg_event(_usb_addr(mEp),
852 "ERROR", err);
Alexander Shishkind3595d12012-05-08 23:28:58 +0300853 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -0800854 if (usb_ep_set_halt(&mEp->ep))
Alexander Shishkin0f089092012-05-08 23:29:02 +0300855 dev_err(udc->dev,
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -0700856 "error: ep_set_halt\n");
Alexander Shishkind3595d12012-05-08 23:28:58 +0300857 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -0800858 }
859 }
860 }
861
862 if (mEp->type != USB_ENDPOINT_XFER_CONTROL ||
Alexander Shishkind3595d12012-05-08 23:28:58 +0300863 !hw_test_and_clear_setup_status(udc, i))
David Lopoaa69a802008-11-17 14:14:51 -0800864 continue;
865
866 if (i != 0) {
Alexander Shishkin0f089092012-05-08 23:29:02 +0300867 dev_warn(udc->dev, "ctrl traffic at endpoint %d\n", i);
David Lopoaa69a802008-11-17 14:14:51 -0800868 continue;
869 }
870
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530871 /*
872 * Flush data and handshake transactions of previous
873 * setup packet.
874 */
Alexander Shishkind36ade62012-05-04 16:47:15 +0300875 _ep_nuke(udc->ep0out);
876 _ep_nuke(udc->ep0in);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530877
David Lopoaa69a802008-11-17 14:14:51 -0800878 /* read_setup_packet */
879 do {
Alexander Shishkind3595d12012-05-08 23:28:58 +0300880 hw_test_and_set_setup_guard(udc);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530881 memcpy(&req, &mEp->qh.ptr->setup, sizeof(req));
Alexander Shishkind3595d12012-05-08 23:28:58 +0300882 } while (!hw_test_and_clear_setup_guard(udc));
David Lopoaa69a802008-11-17 14:14:51 -0800883
884 type = req.bRequestType;
885
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530886 udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
David Lopoaa69a802008-11-17 14:14:51 -0800887
888 dbg_setup(_usb_addr(mEp), &req);
889
890 switch (req.bRequest) {
891 case USB_REQ_CLEAR_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530892 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
893 le16_to_cpu(req.wValue) ==
894 USB_ENDPOINT_HALT) {
895 if (req.wLength != 0)
David Lopoaa69a802008-11-17 14:14:51 -0800896 break;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530897 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +0530898 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530899 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +0530900 if (dir) /* TX */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300901 num += udc->hw_ep_max/2;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530902 if (!udc->ci13xxx_ep[num].wedge) {
Alexander Shishkind3595d12012-05-08 23:28:58 +0300903 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530904 err = usb_ep_clear_halt(
905 &udc->ci13xxx_ep[num].ep);
Alexander Shishkind3595d12012-05-08 23:28:58 +0300906 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530907 if (err)
908 break;
909 }
910 err = isr_setup_status_phase(udc);
911 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
912 le16_to_cpu(req.wValue) ==
913 USB_DEVICE_REMOTE_WAKEUP) {
914 if (req.wLength != 0)
915 break;
916 udc->remote_wakeup = 0;
917 err = isr_setup_status_phase(udc);
918 } else {
919 goto delegate;
David Lopoaa69a802008-11-17 14:14:51 -0800920 }
David Lopoaa69a802008-11-17 14:14:51 -0800921 break;
922 case USB_REQ_GET_STATUS:
923 if (type != (USB_DIR_IN|USB_RECIP_DEVICE) &&
924 type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
925 type != (USB_DIR_IN|USB_RECIP_INTERFACE))
926 goto delegate;
927 if (le16_to_cpu(req.wLength) != 2 ||
928 le16_to_cpu(req.wValue) != 0)
929 break;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530930 err = isr_get_status_response(udc, &req);
David Lopoaa69a802008-11-17 14:14:51 -0800931 break;
932 case USB_REQ_SET_ADDRESS:
933 if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
934 goto delegate;
935 if (le16_to_cpu(req.wLength) != 0 ||
936 le16_to_cpu(req.wIndex) != 0)
937 break;
Alexander Shishkinef15e542012-05-11 17:25:43 +0300938 udc->address = (u8)le16_to_cpu(req.wValue);
939 udc->setaddr = true;
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530940 err = isr_setup_status_phase(udc);
David Lopoaa69a802008-11-17 14:14:51 -0800941 break;
942 case USB_REQ_SET_FEATURE:
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530943 if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
944 le16_to_cpu(req.wValue) ==
945 USB_ENDPOINT_HALT) {
946 if (req.wLength != 0)
947 break;
948 num = le16_to_cpu(req.wIndex);
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +0530949 dir = num & USB_ENDPOINT_DIR_MASK;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530950 num &= USB_ENDPOINT_NUMBER_MASK;
Pavankumar Kondeti4c5212b2011-05-02 11:56:30 +0530951 if (dir) /* TX */
Alexander Shishkind3595d12012-05-08 23:28:58 +0300952 num += udc->hw_ep_max/2;
David Lopoaa69a802008-11-17 14:14:51 -0800953
Alexander Shishkind3595d12012-05-08 23:28:58 +0300954 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530955 err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
Alexander Shishkind3595d12012-05-08 23:28:58 +0300956 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530957 if (!err)
Pavankumar Kondeti541cace2011-02-18 17:43:18 +0530958 isr_setup_status_phase(udc);
959 } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530960 if (req.wLength != 0)
961 break;
Pavankumar Kondeti541cace2011-02-18 17:43:18 +0530962 switch (le16_to_cpu(req.wValue)) {
963 case USB_DEVICE_REMOTE_WAKEUP:
964 udc->remote_wakeup = 1;
965 err = isr_setup_status_phase(udc);
966 break;
967 case USB_DEVICE_TEST_MODE:
968 tmode = le16_to_cpu(req.wIndex) >> 8;
969 switch (tmode) {
970 case TEST_J:
971 case TEST_K:
972 case TEST_SE0_NAK:
973 case TEST_PACKET:
974 case TEST_FORCE_EN:
975 udc->test_mode = tmode;
976 err = isr_setup_status_phase(
977 udc);
978 break;
979 default:
980 break;
981 }
982 default:
983 goto delegate;
984 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +0530985 } else {
986 goto delegate;
987 }
David Lopoaa69a802008-11-17 14:14:51 -0800988 break;
989 default:
990delegate:
991 if (req.wLength == 0) /* no data phase */
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +0530992 udc->ep0_dir = TX;
David Lopoaa69a802008-11-17 14:14:51 -0800993
Alexander Shishkind3595d12012-05-08 23:28:58 +0300994 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -0800995 err = udc->driver->setup(&udc->gadget, &req);
Alexander Shishkind3595d12012-05-08 23:28:58 +0300996 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -0800997 break;
998 }
999
1000 if (err < 0) {
1001 dbg_event(_usb_addr(mEp), "ERROR", err);
1002
Alexander Shishkind3595d12012-05-08 23:28:58 +03001003 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001004 if (usb_ep_set_halt(&mEp->ep))
Alexander Shishkin0f089092012-05-08 23:29:02 +03001005 dev_err(udc->dev, "error: ep_set_halt\n");
Alexander Shishkind3595d12012-05-08 23:28:58 +03001006 spin_lock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001007 }
1008 }
1009}
1010
1011/******************************************************************************
1012 * ENDPT block
1013 *****************************************************************************/
1014/**
1015 * ep_enable: configure endpoint, making it usable
1016 *
1017 * Check usb_ep_enable() at "usb_gadget.h" for details
1018 */
1019static int ep_enable(struct usb_ep *ep,
1020 const struct usb_endpoint_descriptor *desc)
1021{
1022 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301023 int retval = 0;
David Lopoaa69a802008-11-17 14:14:51 -08001024 unsigned long flags;
1025
David Lopoaa69a802008-11-17 14:14:51 -08001026 if (ep == NULL || desc == NULL)
1027 return -EINVAL;
1028
1029 spin_lock_irqsave(mEp->lock, flags);
1030
1031 /* only internal SW should enable ctrl endpts */
1032
Ido Shayevitz31fb6012012-03-12 20:25:23 +02001033 mEp->ep.desc = desc;
David Lopoaa69a802008-11-17 14:14:51 -08001034
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301035 if (!list_empty(&mEp->qh.queue))
Alexander Shishkin0f089092012-05-08 23:29:02 +03001036 dev_warn(mEp->udc->dev, "enabling a non-empty endpoint!\n");
David Lopoaa69a802008-11-17 14:14:51 -08001037
Matthias Kaehlcke15739bb2009-04-15 22:28:41 +02001038 mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX;
1039 mEp->num = usb_endpoint_num(desc);
1040 mEp->type = usb_endpoint_type(desc);
David Lopoaa69a802008-11-17 14:14:51 -08001041
Kuninori Morimoto29cc8892011-08-23 03:12:03 -07001042 mEp->ep.maxpacket = usb_endpoint_maxp(desc);
David Lopoaa69a802008-11-17 14:14:51 -08001043
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301044 dbg_event(_usb_addr(mEp), "ENABLE", 0);
David Lopoaa69a802008-11-17 14:14:51 -08001045
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301046 mEp->qh.ptr->cap = 0;
David Lopof23e6492009-04-16 14:35:24 -07001047
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301048 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
1049 mEp->qh.ptr->cap |= QH_IOS;
1050 else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
1051 mEp->qh.ptr->cap &= ~QH_MULT;
1052 else
1053 mEp->qh.ptr->cap &= ~QH_ZLT;
David Lopoaa69a802008-11-17 14:14:51 -08001054
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301055 mEp->qh.ptr->cap |=
1056 (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
1057 mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */
David Lopoaa69a802008-11-17 14:14:51 -08001058
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05301059 /*
1060 * Enable endpoints in the HW other than ep0 as ep0
1061 * is always enabled
1062 */
1063 if (mEp->num)
Alexander Shishkind3595d12012-05-08 23:28:58 +03001064 retval |= hw_ep_enable(mEp->udc, mEp->num, mEp->dir, mEp->type);
David Lopoaa69a802008-11-17 14:14:51 -08001065
1066 spin_unlock_irqrestore(mEp->lock, flags);
1067 return retval;
1068}
1069
1070/**
1071 * ep_disable: endpoint is no longer usable
1072 *
1073 * Check usb_ep_disable() at "usb_gadget.h" for details
1074 */
1075static int ep_disable(struct usb_ep *ep)
1076{
1077 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
1078 int direction, retval = 0;
1079 unsigned long flags;
1080
David Lopoaa69a802008-11-17 14:14:51 -08001081 if (ep == NULL)
1082 return -EINVAL;
Ido Shayevitz31fb6012012-03-12 20:25:23 +02001083 else if (mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001084 return -EBUSY;
1085
1086 spin_lock_irqsave(mEp->lock, flags);
1087
1088 /* only internal SW should disable ctrl endpts */
1089
1090 direction = mEp->dir;
1091 do {
1092 dbg_event(_usb_addr(mEp), "DISABLE", 0);
1093
1094 retval |= _ep_nuke(mEp);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001095 retval |= hw_ep_disable(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08001096
1097 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
1098 mEp->dir = (mEp->dir == TX) ? RX : TX;
1099
1100 } while (mEp->dir != direction);
1101
Ido Shayevitzf9c56cd2012-02-08 13:56:48 +02001102 mEp->ep.desc = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08001103
1104 spin_unlock_irqrestore(mEp->lock, flags);
1105 return retval;
1106}
1107
1108/**
1109 * ep_alloc_request: allocate a request object to use with this endpoint
1110 *
1111 * Check usb_ep_alloc_request() at "usb_gadget.h" for details
1112 */
1113static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
1114{
1115 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
1116 struct ci13xxx_req *mReq = NULL;
David Lopoaa69a802008-11-17 14:14:51 -08001117
Alexander Shishkin0f089092012-05-08 23:29:02 +03001118 if (ep == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001119 return NULL;
David Lopoaa69a802008-11-17 14:14:51 -08001120
David Lopoaa69a802008-11-17 14:14:51 -08001121 mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
1122 if (mReq != NULL) {
1123 INIT_LIST_HEAD(&mReq->queue);
Michael Grzeschik954aad82011-10-10 18:38:06 +02001124 mReq->req.dma = DMA_ADDR_INVALID;
David Lopoaa69a802008-11-17 14:14:51 -08001125
1126 mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,
1127 &mReq->dma);
1128 if (mReq->ptr == NULL) {
1129 kfree(mReq);
1130 mReq = NULL;
1131 }
1132 }
1133
1134 dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
1135
David Lopoaa69a802008-11-17 14:14:51 -08001136 return (mReq == NULL) ? NULL : &mReq->req;
1137}
1138
1139/**
1140 * ep_free_request: frees a request object
1141 *
1142 * Check usb_ep_free_request() at "usb_gadget.h" for details
1143 */
1144static void ep_free_request(struct usb_ep *ep, struct usb_request *req)
1145{
1146 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
1147 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
1148 unsigned long flags;
1149
David Lopoaa69a802008-11-17 14:14:51 -08001150 if (ep == NULL || req == NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08001151 return;
1152 } else if (!list_empty(&mReq->queue)) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001153 dev_err(mEp->udc->dev, "freeing queued request\n");
David Lopoaa69a802008-11-17 14:14:51 -08001154 return;
1155 }
1156
1157 spin_lock_irqsave(mEp->lock, flags);
1158
1159 if (mReq->ptr)
1160 dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma);
1161 kfree(mReq);
1162
1163 dbg_event(_usb_addr(mEp), "FREE", 0);
1164
1165 spin_unlock_irqrestore(mEp->lock, flags);
1166}
1167
1168/**
1169 * ep_queue: queues (submits) an I/O request to an endpoint
1170 *
1171 * Check usb_ep_queue()* at usb_gadget.h" for details
1172 */
1173static int ep_queue(struct usb_ep *ep, struct usb_request *req,
1174 gfp_t __maybe_unused gfp_flags)
1175{
1176 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
1177 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001178 struct ci13xxx *udc = mEp->udc;
David Lopoaa69a802008-11-17 14:14:51 -08001179 int retval = 0;
1180 unsigned long flags;
1181
Ido Shayevitz31fb6012012-03-12 20:25:23 +02001182 if (ep == NULL || req == NULL || mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001183 return -EINVAL;
1184
1185 spin_lock_irqsave(mEp->lock, flags);
1186
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05301187 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
1188 if (req->length)
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001189 mEp = (udc->ep0_dir == RX) ?
1190 udc->ep0out : udc->ep0in;
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05301191 if (!list_empty(&mEp->qh.queue)) {
1192 _ep_nuke(mEp);
1193 retval = -EOVERFLOW;
Alexander Shishkin0f089092012-05-08 23:29:02 +03001194 dev_warn(mEp->udc->dev, "endpoint ctrl %X nuked\n",
1195 _usb_addr(mEp));
Pavankumar Kondeti76cd9cf2011-05-02 11:56:31 +05301196 }
David Lopoaa69a802008-11-17 14:14:51 -08001197 }
1198
1199 /* first nuke then test link, e.g. previous status has not sent */
1200 if (!list_empty(&mReq->queue)) {
1201 retval = -EBUSY;
Alexander Shishkin0f089092012-05-08 23:29:02 +03001202 dev_err(mEp->udc->dev, "request already in queue\n");
David Lopoaa69a802008-11-17 14:14:51 -08001203 goto done;
1204 }
1205
Alexander Shishkin1155a7b2012-05-08 23:28:57 +03001206 if (req->length > 4 * CI13XXX_PAGE_SIZE) {
1207 req->length = 4 * CI13XXX_PAGE_SIZE;
David Lopoaa69a802008-11-17 14:14:51 -08001208 retval = -EMSGSIZE;
Alexander Shishkin0f089092012-05-08 23:29:02 +03001209 dev_warn(mEp->udc->dev, "request length truncated\n");
David Lopoaa69a802008-11-17 14:14:51 -08001210 }
1211
1212 dbg_queue(_usb_addr(mEp), req, retval);
1213
1214 /* push request */
1215 mReq->req.status = -EINPROGRESS;
1216 mReq->req.actual = 0;
David Lopoaa69a802008-11-17 14:14:51 -08001217
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301218 retval = _hardware_enqueue(mEp, mReq);
Artem Leonenkod9bb9c12010-12-14 23:45:50 -08001219
1220 if (retval == -EALREADY) {
David Lopoaa69a802008-11-17 14:14:51 -08001221 dbg_event(_usb_addr(mEp), "QUEUE", retval);
1222 retval = 0;
1223 }
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301224 if (!retval)
1225 list_add_tail(&mReq->queue, &mEp->qh.queue);
David Lopoaa69a802008-11-17 14:14:51 -08001226
1227 done:
1228 spin_unlock_irqrestore(mEp->lock, flags);
1229 return retval;
1230}
1231
1232/**
1233 * ep_dequeue: dequeues (cancels, unlinks) an I/O request from an endpoint
1234 *
1235 * Check usb_ep_dequeue() at "usb_gadget.h" for details
1236 */
1237static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
1238{
1239 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
1240 struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
1241 unsigned long flags;
1242
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301243 if (ep == NULL || req == NULL || mReq->req.status != -EALREADY ||
Ido Shayevitz31fb6012012-03-12 20:25:23 +02001244 mEp->ep.desc == NULL || list_empty(&mReq->queue) ||
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301245 list_empty(&mEp->qh.queue))
David Lopoaa69a802008-11-17 14:14:51 -08001246 return -EINVAL;
1247
1248 spin_lock_irqsave(mEp->lock, flags);
1249
1250 dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
1251
Alexander Shishkind3595d12012-05-08 23:28:58 +03001252 hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08001253
1254 /* pop request */
1255 list_del_init(&mReq->queue);
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301256 if (mReq->map) {
1257 dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
1258 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
Michael Grzeschik954aad82011-10-10 18:38:06 +02001259 mReq->req.dma = DMA_ADDR_INVALID;
Pavankumar Kondeti0e6ca192011-02-18 17:43:16 +05301260 mReq->map = 0;
1261 }
David Lopoaa69a802008-11-17 14:14:51 -08001262 req->status = -ECONNRESET;
1263
Artem Leonenko7c25a822010-12-14 23:46:55 -08001264 if (mReq->req.complete != NULL) {
David Lopoaa69a802008-11-17 14:14:51 -08001265 spin_unlock(mEp->lock);
1266 mReq->req.complete(&mEp->ep, &mReq->req);
1267 spin_lock(mEp->lock);
1268 }
1269
1270 spin_unlock_irqrestore(mEp->lock, flags);
1271 return 0;
1272}
1273
1274/**
1275 * ep_set_halt: sets the endpoint halt feature
1276 *
1277 * Check usb_ep_set_halt() at "usb_gadget.h" for details
1278 */
1279static int ep_set_halt(struct usb_ep *ep, int value)
1280{
1281 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
1282 int direction, retval = 0;
1283 unsigned long flags;
1284
Ido Shayevitz31fb6012012-03-12 20:25:23 +02001285 if (ep == NULL || mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001286 return -EINVAL;
1287
1288 spin_lock_irqsave(mEp->lock, flags);
1289
1290#ifndef STALL_IN
1291 /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
1292 if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX &&
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301293 !list_empty(&mEp->qh.queue)) {
David Lopoaa69a802008-11-17 14:14:51 -08001294 spin_unlock_irqrestore(mEp->lock, flags);
1295 return -EAGAIN;
1296 }
1297#endif
1298
1299 direction = mEp->dir;
1300 do {
1301 dbg_event(_usb_addr(mEp), "HALT", value);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001302 retval |= hw_ep_set_halt(mEp->udc, mEp->num, mEp->dir, value);
David Lopoaa69a802008-11-17 14:14:51 -08001303
1304 if (!value)
1305 mEp->wedge = 0;
1306
1307 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
1308 mEp->dir = (mEp->dir == TX) ? RX : TX;
1309
1310 } while (mEp->dir != direction);
1311
1312 spin_unlock_irqrestore(mEp->lock, flags);
1313 return retval;
1314}
1315
1316/**
1317 * ep_set_wedge: sets the halt feature and ignores clear requests
1318 *
1319 * Check usb_ep_set_wedge() at "usb_gadget.h" for details
1320 */
1321static int ep_set_wedge(struct usb_ep *ep)
1322{
1323 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
1324 unsigned long flags;
1325
Ido Shayevitz31fb6012012-03-12 20:25:23 +02001326 if (ep == NULL || mEp->ep.desc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001327 return -EINVAL;
1328
1329 spin_lock_irqsave(mEp->lock, flags);
1330
1331 dbg_event(_usb_addr(mEp), "WEDGE", 0);
1332 mEp->wedge = 1;
1333
1334 spin_unlock_irqrestore(mEp->lock, flags);
1335
1336 return usb_ep_set_halt(ep);
1337}
1338
1339/**
1340 * ep_fifo_flush: flushes contents of a fifo
1341 *
1342 * Check usb_ep_fifo_flush() at "usb_gadget.h" for details
1343 */
1344static void ep_fifo_flush(struct usb_ep *ep)
1345{
1346 struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
1347 unsigned long flags;
1348
David Lopoaa69a802008-11-17 14:14:51 -08001349 if (ep == NULL) {
Alexander Shishkin0f089092012-05-08 23:29:02 +03001350 dev_err(mEp->udc->dev, "%02X: -EINVAL\n", _usb_addr(mEp));
David Lopoaa69a802008-11-17 14:14:51 -08001351 return;
1352 }
1353
1354 spin_lock_irqsave(mEp->lock, flags);
1355
1356 dbg_event(_usb_addr(mEp), "FFLUSH", 0);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001357 hw_ep_flush(mEp->udc, mEp->num, mEp->dir);
David Lopoaa69a802008-11-17 14:14:51 -08001358
1359 spin_unlock_irqrestore(mEp->lock, flags);
1360}
1361
1362/**
1363 * Endpoint-specific part of the API to the USB controller hardware
1364 * Check "usb_gadget.h" for details
1365 */
1366static const struct usb_ep_ops usb_ep_ops = {
1367 .enable = ep_enable,
1368 .disable = ep_disable,
1369 .alloc_request = ep_alloc_request,
1370 .free_request = ep_free_request,
1371 .queue = ep_queue,
1372 .dequeue = ep_dequeue,
1373 .set_halt = ep_set_halt,
1374 .set_wedge = ep_set_wedge,
1375 .fifo_flush = ep_fifo_flush,
1376};
1377
1378/******************************************************************************
1379 * GADGET block
1380 *****************************************************************************/
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301381static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
1382{
1383 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
1384 unsigned long flags;
1385 int gadget_ready = 0;
1386
1387 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS))
1388 return -EOPNOTSUPP;
1389
Alexander Shishkind3595d12012-05-08 23:28:58 +03001390 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301391 udc->vbus_active = is_active;
1392 if (udc->driver)
1393 gadget_ready = 1;
Alexander Shishkind3595d12012-05-08 23:28:58 +03001394 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301395
1396 if (gadget_ready) {
1397 if (is_active) {
Pavankumar Kondetic0360192010-12-07 17:54:04 +05301398 pm_runtime_get_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301399 hw_device_reset(udc);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001400 hw_device_state(udc, udc->ep0out->qh.dma);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301401 } else {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001402 hw_device_state(udc, 0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301403 if (udc->udc_driver->notify_event)
1404 udc->udc_driver->notify_event(udc,
1405 CI13XXX_CONTROLLER_STOPPED_EVENT);
1406 _gadget_stop_activity(&udc->gadget);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05301407 pm_runtime_put_sync(&_gadget->dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301408 }
1409 }
1410
1411 return 0;
1412}
1413
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301414static int ci13xxx_wakeup(struct usb_gadget *_gadget)
1415{
1416 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
1417 unsigned long flags;
1418 int ret = 0;
1419
Alexander Shishkind3595d12012-05-08 23:28:58 +03001420 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301421 if (!udc->remote_wakeup) {
1422 ret = -EOPNOTSUPP;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301423 goto out;
1424 }
Alexander Shishkin262c1632012-05-08 23:28:59 +03001425 if (!hw_read(udc, OP_PORTSC, PORTSC_SUSP)) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301426 ret = -EINVAL;
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301427 goto out;
1428 }
Alexander Shishkin262c1632012-05-08 23:28:59 +03001429 hw_write(udc, OP_PORTSC, PORTSC_FPR, PORTSC_FPR);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301430out:
Alexander Shishkind3595d12012-05-08 23:28:58 +03001431 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301432 return ret;
1433}
1434
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301435static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
1436{
1437 struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
1438
1439 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02001440 return usb_phy_set_power(udc->transceiver, mA);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301441 return -ENOTSUPP;
1442}
1443
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001444static int ci13xxx_start(struct usb_gadget *gadget,
1445 struct usb_gadget_driver *driver);
1446static int ci13xxx_stop(struct usb_gadget *gadget,
1447 struct usb_gadget_driver *driver);
David Lopoaa69a802008-11-17 14:14:51 -08001448/**
1449 * Device operations part of the API to the USB controller hardware,
1450 * which don't involve endpoints (or i/o)
1451 * Check "usb_gadget.h" for details
1452 */
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301453static const struct usb_gadget_ops usb_gadget_ops = {
1454 .vbus_session = ci13xxx_vbus_session,
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301455 .wakeup = ci13xxx_wakeup,
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301456 .vbus_draw = ci13xxx_vbus_draw,
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001457 .udc_start = ci13xxx_start,
1458 .udc_stop = ci13xxx_stop,
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301459};
David Lopoaa69a802008-11-17 14:14:51 -08001460
Alexander Shishkin790c2d52012-05-08 23:29:03 +03001461static int init_eps(struct ci13xxx *udc)
1462{
1463 int retval = 0, i, j;
1464
1465 for (i = 0; i < udc->hw_ep_max/2; i++)
1466 for (j = RX; j <= TX; j++) {
1467 int k = i + j * udc->hw_ep_max/2;
1468 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
1469
1470 scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
1471 (j == TX) ? "in" : "out");
1472
1473 mEp->udc = udc;
1474 mEp->lock = &udc->lock;
1475 mEp->device = &udc->gadget.dev;
1476 mEp->td_pool = udc->td_pool;
1477
1478 mEp->ep.name = mEp->name;
1479 mEp->ep.ops = &usb_ep_ops;
1480 mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
1481
1482 INIT_LIST_HEAD(&mEp->qh.queue);
1483 mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
1484 &mEp->qh.dma);
1485 if (mEp->qh.ptr == NULL)
1486 retval = -ENOMEM;
1487 else
1488 memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
1489
1490 /*
1491 * set up shorthands for ep0 out and in endpoints,
1492 * don't add to gadget's ep_list
1493 */
1494 if (i == 0) {
1495 if (j == RX)
1496 udc->ep0out = mEp;
1497 else
1498 udc->ep0in = mEp;
1499
1500 continue;
1501 }
1502
1503 list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
1504 }
1505
1506 return retval;
1507}
1508
David Lopoaa69a802008-11-17 14:14:51 -08001509/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001510 * ci13xxx_start: register a gadget driver
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001511 * @gadget: our gadget
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02001512 * @driver: the driver being registered
David Lopoaa69a802008-11-17 14:14:51 -08001513 *
Uwe Kleine-Königb0fca502010-08-12 17:43:53 +02001514 * Interrupts are enabled here.
David Lopoaa69a802008-11-17 14:14:51 -08001515 */
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001516static int ci13xxx_start(struct usb_gadget *gadget,
1517 struct usb_gadget_driver *driver)
David Lopoaa69a802008-11-17 14:14:51 -08001518{
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001519 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
Pavankumar Kondetica9cfea2011-01-11 09:19:22 +05301520 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -08001521 int retval = -ENOMEM;
1522
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001523 if (driver->disconnect == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001524 return -EINVAL;
David Lopoaa69a802008-11-17 14:14:51 -08001525
David Lopoaa69a802008-11-17 14:14:51 -08001526
Alexander Shishkind36ade62012-05-04 16:47:15 +03001527 udc->ep0out->ep.desc = &ctrl_endpt_out_desc;
1528 retval = usb_ep_enable(&udc->ep0out->ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05301529 if (retval)
1530 return retval;
Felipe Balbi877c1f52011-06-29 16:41:57 +03001531
Alexander Shishkind36ade62012-05-04 16:47:15 +03001532 udc->ep0in->ep.desc = &ctrl_endpt_in_desc;
1533 retval = usb_ep_enable(&udc->ep0in->ep);
Anji jonnalaac1aa6a2011-05-02 11:56:32 +05301534 if (retval)
1535 return retval;
Alexander Shishkind3595d12012-05-08 23:28:58 +03001536 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001537
Pavankumar Kondeti49d3df52011-01-11 09:19:21 +05301538 udc->driver = driver;
Pavankumar Kondetic0360192010-12-07 17:54:04 +05301539 pm_runtime_get_sync(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301540 if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
1541 if (udc->vbus_active) {
1542 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
1543 hw_device_reset(udc);
1544 } else {
Pavankumar Kondetic0360192010-12-07 17:54:04 +05301545 pm_runtime_put_sync(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301546 goto done;
1547 }
1548 }
1549
Alexander Shishkind3595d12012-05-08 23:28:58 +03001550 retval = hw_device_state(udc, udc->ep0out->qh.dma);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05301551 if (retval)
1552 pm_runtime_put_sync(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08001553
1554 done:
Alexander Shishkind3595d12012-05-08 23:28:58 +03001555 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001556 return retval;
1557}
David Lopoaa69a802008-11-17 14:14:51 -08001558
1559/**
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001560 * ci13xxx_stop: unregister a gadget driver
David Lopoaa69a802008-11-17 14:14:51 -08001561 */
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001562static int ci13xxx_stop(struct usb_gadget *gadget,
1563 struct usb_gadget_driver *driver)
David Lopoaa69a802008-11-17 14:14:51 -08001564{
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001565 struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
1566 unsigned long flags;
David Lopoaa69a802008-11-17 14:14:51 -08001567
Alexander Shishkind3595d12012-05-08 23:28:58 +03001568 spin_lock_irqsave(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001569
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301570 if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) ||
1571 udc->vbus_active) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001572 hw_device_state(udc, 0);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301573 if (udc->udc_driver->notify_event)
1574 udc->udc_driver->notify_event(udc,
1575 CI13XXX_CONTROLLER_STOPPED_EVENT);
Alexander Shishkin1f339d82012-05-08 23:29:04 +03001576 udc->driver = NULL;
Alexander Shishkind3595d12012-05-08 23:28:58 +03001577 spin_unlock_irqrestore(&udc->lock, flags);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301578 _gadget_stop_activity(&udc->gadget);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001579 spin_lock_irqsave(&udc->lock, flags);
Pavankumar Kondetic0360192010-12-07 17:54:04 +05301580 pm_runtime_put(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301581 }
David Lopoaa69a802008-11-17 14:14:51 -08001582
Alexander Shishkind3595d12012-05-08 23:28:58 +03001583 spin_unlock_irqrestore(&udc->lock, flags);
David Lopoaa69a802008-11-17 14:14:51 -08001584
David Lopoaa69a802008-11-17 14:14:51 -08001585 return 0;
1586}
David Lopoaa69a802008-11-17 14:14:51 -08001587
1588/******************************************************************************
1589 * BUS block
1590 *****************************************************************************/
1591/**
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001592 * udc_irq: udc interrupt handler
David Lopoaa69a802008-11-17 14:14:51 -08001593 *
1594 * This function returns IRQ_HANDLED if the IRQ has been handled
1595 * It locks access to registers
1596 */
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001597static irqreturn_t udc_irq(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -08001598{
David Lopoaa69a802008-11-17 14:14:51 -08001599 irqreturn_t retval;
1600 u32 intr;
1601
Greg Kroah-Hartmanf6395542012-05-10 11:37:18 -07001602 if (udc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001603 return IRQ_HANDLED;
David Lopoaa69a802008-11-17 14:14:51 -08001604
Alexander Shishkind3595d12012-05-08 23:28:58 +03001605 spin_lock(&udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301606
1607 if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) {
Alexander Shishkin262c1632012-05-08 23:28:59 +03001608 if (hw_read(udc, OP_USBMODE, USBMODE_CM) !=
Alexander Shishkin758fc982012-05-11 17:25:53 +03001609 USBMODE_CM_DC) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001610 spin_unlock(&udc->lock);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301611 return IRQ_NONE;
1612 }
1613 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03001614 intr = hw_test_and_clear_intr_active(udc);
Alexander Shishkine443b332012-05-11 17:25:46 +03001615 dbg_interrupt(intr);
David Lopoaa69a802008-11-17 14:14:51 -08001616
Alexander Shishkine443b332012-05-11 17:25:46 +03001617 if (intr) {
David Lopoaa69a802008-11-17 14:14:51 -08001618 /* order defines priority - do NOT change it */
Alexander Shishkine443b332012-05-11 17:25:46 +03001619 if (USBi_URI & intr)
David Lopoaa69a802008-11-17 14:14:51 -08001620 isr_reset_handler(udc);
Alexander Shishkine443b332012-05-11 17:25:46 +03001621
David Lopoaa69a802008-11-17 14:14:51 -08001622 if (USBi_PCI & intr) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001623 udc->gadget.speed = hw_port_is_high_speed(udc) ?
David Lopoaa69a802008-11-17 14:14:51 -08001624 USB_SPEED_HIGH : USB_SPEED_FULL;
Marc Kleine-Budde7bb4fdc2011-10-10 18:38:09 +02001625 if (udc->suspended && udc->driver->resume) {
Alexander Shishkind3595d12012-05-08 23:28:58 +03001626 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301627 udc->driver->resume(&udc->gadget);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001628 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301629 udc->suspended = 0;
1630 }
David Lopoaa69a802008-11-17 14:14:51 -08001631 }
Alexander Shishkine443b332012-05-11 17:25:46 +03001632
1633 if (USBi_UI & intr)
David Lopoaa69a802008-11-17 14:14:51 -08001634 isr_tr_complete_handler(udc);
Alexander Shishkine443b332012-05-11 17:25:46 +03001635
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301636 if (USBi_SLI & intr) {
Marc Kleine-Budde7bb4fdc2011-10-10 18:38:09 +02001637 if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
1638 udc->driver->suspend) {
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301639 udc->suspended = 1;
Alexander Shishkind3595d12012-05-08 23:28:58 +03001640 spin_unlock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301641 udc->driver->suspend(&udc->gadget);
Alexander Shishkind3595d12012-05-08 23:28:58 +03001642 spin_lock(&udc->lock);
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301643 }
Pavankumar Kondetie2b61c12011-02-18 17:43:17 +05301644 }
David Lopoaa69a802008-11-17 14:14:51 -08001645 retval = IRQ_HANDLED;
1646 } else {
David Lopoaa69a802008-11-17 14:14:51 -08001647 retval = IRQ_NONE;
1648 }
Alexander Shishkind3595d12012-05-08 23:28:58 +03001649 spin_unlock(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001650
1651 return retval;
1652}
1653
1654/**
1655 * udc_release: driver release function
1656 * @dev: device
1657 *
1658 * Currently does nothing
1659 */
1660static void udc_release(struct device *dev)
1661{
David Lopoaa69a802008-11-17 14:14:51 -08001662}
1663
1664/**
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001665 * udc_start: initialize gadget role
1666 * @udc: chipidea controller
David Lopoaa69a802008-11-17 14:14:51 -08001667 */
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001668static int udc_start(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -08001669{
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001670 struct device *dev = udc->dev;
David Lopoaa69a802008-11-17 14:14:51 -08001671 int retval = 0;
1672
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001673 if (!udc)
David Lopoaa69a802008-11-17 14:14:51 -08001674 return -EINVAL;
1675
Alexander Shishkind3595d12012-05-08 23:28:58 +03001676 spin_lock_init(&udc->lock);
David Lopoaa69a802008-11-17 14:14:51 -08001677
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301678 udc->gadget.ops = &usb_gadget_ops;
David Lopoaa69a802008-11-17 14:14:51 -08001679 udc->gadget.speed = USB_SPEED_UNKNOWN;
Michal Nazarewiczd327ab52011-11-19 18:27:37 +01001680 udc->gadget.max_speed = USB_SPEED_HIGH;
David Lopoaa69a802008-11-17 14:14:51 -08001681 udc->gadget.is_otg = 0;
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001682 udc->gadget.name = udc->udc_driver->name;
David Lopoaa69a802008-11-17 14:14:51 -08001683
1684 INIT_LIST_HEAD(&udc->gadget.ep_list);
David Lopoaa69a802008-11-17 14:14:51 -08001685
Kay Sievers5df58522009-03-24 16:38:23 -07001686 dev_set_name(&udc->gadget.dev, "gadget");
David Lopoaa69a802008-11-17 14:14:51 -08001687 udc->gadget.dev.dma_mask = dev->dma_mask;
Pavankumar Kondeti61948ee2010-12-07 17:54:01 +05301688 udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
David Lopoaa69a802008-11-17 14:14:51 -08001689 udc->gadget.dev.parent = dev;
1690 udc->gadget.dev.release = udc_release;
1691
Alexander Shishkin790c2d52012-05-08 23:29:03 +03001692 /* alloc resources */
1693 udc->qh_pool = dma_pool_create("ci13xxx_qh", dev,
1694 sizeof(struct ci13xxx_qh),
1695 64, CI13XXX_PAGE_SIZE);
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001696 if (udc->qh_pool == NULL)
1697 return -ENOMEM;
Alexander Shishkin790c2d52012-05-08 23:29:03 +03001698
1699 udc->td_pool = dma_pool_create("ci13xxx_td", dev,
1700 sizeof(struct ci13xxx_td),
1701 64, CI13XXX_PAGE_SIZE);
1702 if (udc->td_pool == NULL) {
1703 retval = -ENOMEM;
1704 goto free_qh_pool;
1705 }
1706
Alexander Shishkin790c2d52012-05-08 23:29:03 +03001707 retval = init_eps(udc);
1708 if (retval)
1709 goto free_pools;
1710
1711 udc->gadget.ep0 = &udc->ep0in->ep;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301712
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02001713 udc->transceiver = usb_get_transceiver();
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301714
1715 if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
1716 if (udc->transceiver == NULL) {
1717 retval = -ENODEV;
Alexander Shishkin790c2d52012-05-08 23:29:03 +03001718 goto free_pools;
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301719 }
1720 }
1721
1722 if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) {
1723 retval = hw_device_reset(udc);
1724 if (retval)
1725 goto put_transceiver;
1726 }
1727
David Lopoaa69a802008-11-17 14:14:51 -08001728 retval = device_register(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301729 if (retval) {
1730 put_device(&udc->gadget.dev);
1731 goto put_transceiver;
1732 }
David Lopoaa69a802008-11-17 14:14:51 -08001733
David Lopoaa69a802008-11-17 14:14:51 -08001734 retval = dbg_create_files(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301735 if (retval)
1736 goto unreg_device;
1737
1738 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02001739 retval = otg_set_peripheral(udc->transceiver->otg,
1740 &udc->gadget);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301741 if (retval)
1742 goto remove_dbg;
David Lopoaa69a802008-11-17 14:14:51 -08001743 }
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001744
1745 retval = usb_add_gadget_udc(dev, &udc->gadget);
1746 if (retval)
1747 goto remove_trans;
1748
Pavankumar Kondetic0360192010-12-07 17:54:04 +05301749 pm_runtime_no_callbacks(&udc->gadget.dev);
1750 pm_runtime_enable(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08001751
David Lopoaa69a802008-11-17 14:14:51 -08001752 return retval;
1753
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001754remove_trans:
1755 if (udc->transceiver) {
Heikki Krogerus6e13c652012-02-13 13:24:20 +02001756 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02001757 usb_put_transceiver(udc->transceiver);
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001758 }
1759
Greg Kroah-Hartman0917ba82012-04-27 11:24:39 -07001760 dev_err(dev, "error = %i\n", retval);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301761remove_dbg:
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301762 dbg_remove_files(&udc->gadget.dev);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301763unreg_device:
1764 device_unregister(&udc->gadget.dev);
1765put_transceiver:
1766 if (udc->transceiver)
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02001767 usb_put_transceiver(udc->transceiver);
Alexander Shishkin790c2d52012-05-08 23:29:03 +03001768free_pools:
1769 dma_pool_destroy(udc->td_pool);
1770free_qh_pool:
1771 dma_pool_destroy(udc->qh_pool);
David Lopoaa69a802008-11-17 14:14:51 -08001772 return retval;
1773}
1774
1775/**
1776 * udc_remove: parent remove must call this to remove UDC
1777 *
1778 * No interrupts active, the IRQ has been released
1779 */
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001780static void udc_stop(struct ci13xxx *udc)
David Lopoaa69a802008-11-17 14:14:51 -08001781{
Alexander Shishkin790c2d52012-05-08 23:29:03 +03001782 int i;
David Lopoaa69a802008-11-17 14:14:51 -08001783
Alexander Shishkin0f089092012-05-08 23:29:02 +03001784 if (udc == NULL)
David Lopoaa69a802008-11-17 14:14:51 -08001785 return;
Alexander Shishkin0f089092012-05-08 23:29:02 +03001786
Sebastian Andrzej Siewior0f913492011-06-28 16:33:47 +03001787 usb_del_gadget_udc(&udc->gadget);
David Lopoaa69a802008-11-17 14:14:51 -08001788
Alexander Shishkin790c2d52012-05-08 23:29:03 +03001789 for (i = 0; i < udc->hw_ep_max; i++) {
1790 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
1791
1792 dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
1793 }
1794
1795 dma_pool_destroy(udc->td_pool);
1796 dma_pool_destroy(udc->qh_pool);
1797
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301798 if (udc->transceiver) {
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001799 otg_set_peripheral(udc->transceiver->otg, NULL);
Heikki Krogerusb96d3b02012-02-13 13:24:18 +02001800 usb_put_transceiver(udc->transceiver);
Pavankumar Kondetif01ef572010-12-07 17:54:02 +05301801 }
David Lopoaa69a802008-11-17 14:14:51 -08001802 dbg_remove_files(&udc->gadget.dev);
David Lopoaa69a802008-11-17 14:14:51 -08001803 device_unregister(&udc->gadget.dev);
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001804 /* my kobject is dynamic, I swear! */
1805 memset(&udc->gadget, 0, sizeof(udc->gadget));
1806}
David Lopoaa69a802008-11-17 14:14:51 -08001807
Alexander Shishkin5f36e232012-05-11 17:25:47 +03001808/**
1809 * ci_hdrc_gadget_init - initialize device related bits
1810 * ci: the controller
1811 *
1812 * This function enables the gadget role, if the device is "device capable".
1813 */
1814int ci_hdrc_gadget_init(struct ci13xxx *ci)
1815{
1816 struct ci_role_driver *rdrv;
1817
1818 if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_DC))
1819 return -ENXIO;
1820
1821 rdrv = devm_kzalloc(ci->dev, sizeof(struct ci_role_driver), GFP_KERNEL);
1822 if (!rdrv)
1823 return -ENOMEM;
1824
1825 rdrv->start = udc_start;
1826 rdrv->stop = udc_stop;
1827 rdrv->irq = udc_irq;
1828 rdrv->name = "gadget";
1829 ci->roles[CI_ROLE_GADGET] = rdrv;
1830
1831 return 0;
David Lopoaa69a802008-11-17 14:14:51 -08001832}