staging: csr: Fix obvious logic error in staging/csr
[deliverable/linux.git] / drivers / staging / octeon-usb / octeon-hcd.c
CommitLineData
b164935b
AK
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2008 Cavium Networks
7 */
8#include <linux/kernel.h>
9#include <linux/module.h>
10#include <linux/init.h>
11#include <linux/pci.h>
12#include <linux/interrupt.h>
13#include <linux/platform_device.h>
b164935b
AK
14#include <linux/usb.h>
15
16#include <asm/time.h>
17#include <asm/delay.h>
18
19#include <asm/octeon/cvmx.h>
20#include "cvmx-usb.h"
21#include <asm/octeon/cvmx-iob-defs.h>
22
23#include <linux/usb/hcd.h>
24
55fa328a
DN
25#include <linux/err.h>
26
b164935b
AK
27//#define DEBUG_CALL(format, ...) printk(format, ##__VA_ARGS__)
28#define DEBUG_CALL(format, ...) do {} while (0)
29//#define DEBUG_SUBMIT(format, ...) printk(format, ##__VA_ARGS__)
30#define DEBUG_SUBMIT(format, ...) do {} while (0)
31//#define DEBUG_ROOT_HUB(format, ...) printk(format, ##__VA_ARGS__)
32#define DEBUG_ROOT_HUB(format, ...) do {} while (0)
33//#define DEBUG_ERROR(format, ...) printk(format, ##__VA_ARGS__)
34#define DEBUG_ERROR(format, ...) do {} while (0)
35#define DEBUG_FATAL(format, ...) printk(format, ##__VA_ARGS__)
36
37struct octeon_hcd {
38 spinlock_t lock;
39 cvmx_usb_state_t usb;
40 struct tasklet_struct dequeue_tasklet;
41 struct list_head dequeue_list;
42};
43
44/* convert between an HCD pointer and the corresponding struct octeon_hcd */
45static inline struct octeon_hcd *hcd_to_octeon(struct usb_hcd *hcd)
46{
47 return (struct octeon_hcd *)(hcd->hcd_priv);
48}
49
50static inline struct usb_hcd *octeon_to_hcd(struct octeon_hcd *p)
51{
52 return container_of((void *)p, struct usb_hcd, hcd_priv);
53}
54
55static inline struct octeon_hcd *cvmx_usb_to_octeon(cvmx_usb_state_t *p)
56{
57 return container_of(p, struct octeon_hcd, usb);
58}
59
60static irqreturn_t octeon_usb_irq(struct usb_hcd *hcd)
61{
62 struct octeon_hcd *priv = hcd_to_octeon(hcd);
63 unsigned long flags;
64 DEBUG_CALL("OcteonUSB: %s called\n", __FUNCTION__);
65 spin_lock_irqsave(&priv->lock, flags);
66 cvmx_usb_poll(&priv->usb);
67 spin_unlock_irqrestore(&priv->lock, flags);
68 return IRQ_HANDLED;
69}
70
71static void octeon_usb_port_callback(cvmx_usb_state_t *usb,
72 cvmx_usb_callback_t reason,
73 cvmx_usb_complete_t status,
74 int pipe_handle,
75 int submit_handle,
76 int bytes_transferred,
77 void *user_data)
78{
79 struct octeon_hcd *priv = cvmx_usb_to_octeon(usb);
80 DEBUG_CALL("OcteonUSB: %s called\n", __FUNCTION__);
81 spin_unlock(&priv->lock);
82 usb_hcd_poll_rh_status(octeon_to_hcd(priv));
83 spin_lock(&priv->lock);
84}
85
86static int octeon_usb_start(struct usb_hcd *hcd)
87{
88 struct octeon_hcd *priv = hcd_to_octeon(hcd);
89 unsigned long flags;
90 DEBUG_CALL("OcteonUSB: %s called\n", __FUNCTION__);
91 hcd->state = HC_STATE_RUNNING;
92 spin_lock_irqsave(&priv->lock, flags);
93 cvmx_usb_register_callback(&priv->usb, CVMX_USB_CALLBACK_PORT_CHANGED,
94 octeon_usb_port_callback, NULL);
95 spin_unlock_irqrestore(&priv->lock, flags);
96 return 0;
97}
98
99static void octeon_usb_stop(struct usb_hcd *hcd)
100{
101 struct octeon_hcd *priv = hcd_to_octeon(hcd);
102 unsigned long flags;
103 DEBUG_CALL("OcteonUSB: %s called\n", __FUNCTION__);
104 spin_lock_irqsave(&priv->lock, flags);
105 cvmx_usb_register_callback(&priv->usb, CVMX_USB_CALLBACK_PORT_CHANGED,
106 NULL, NULL);
107 spin_unlock_irqrestore(&priv->lock, flags);
108 hcd->state = HC_STATE_HALT;
109}
110
111static int octeon_usb_get_frame_number(struct usb_hcd *hcd)
112{
113 struct octeon_hcd *priv = hcd_to_octeon(hcd);
114 DEBUG_CALL("OcteonUSB: %s called\n", __FUNCTION__);
115 return cvmx_usb_get_frame_number(&priv->usb);
116}
117
118static void octeon_usb_urb_complete_callback(cvmx_usb_state_t *usb,
119 cvmx_usb_callback_t reason,
120 cvmx_usb_complete_t status,
121 int pipe_handle,
122 int submit_handle,
123 int bytes_transferred,
124 void *user_data)
125{
126 struct octeon_hcd *priv = cvmx_usb_to_octeon(usb);
127 struct urb *urb = user_data;
128 DEBUG_CALL("OcteonUSB: %s called\n", __FUNCTION__);
129 urb->actual_length = bytes_transferred;
130 urb->hcpriv = NULL;
131
132 if (!list_empty(&urb->urb_list)) {
133 /*
134 * It is on the dequeue_list, but we are going to call
135 * usb_hcd_giveback_urb(), so we must clear it from
136 * the list. We got to it before the
137 * octeon_usb_urb_dequeue_work() tasklet did.
138 */
139 list_del(&urb->urb_list);
140 /* No longer on the dequeue_list. */
141 INIT_LIST_HEAD(&urb->urb_list);
142 }
143
144 /* For Isochronous transactions we need to update the URB packet status
145 list from data in our private copy */
3fa98f34 146 if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
b164935b
AK
147 int i;
148 /* The pointer to the private list is stored in the setup_packet field */
149 cvmx_usb_iso_packet_t *iso_packet = (cvmx_usb_iso_packet_t *)urb->setup_packet;
150 /* Recalculate the transfer size by adding up each packet */
151 urb->actual_length = 0;
3fa98f34
DN
152 for (i=0; i<urb->number_of_packets; i++) {
153 if (iso_packet[i].status == CVMX_USB_COMPLETE_SUCCESS) {
b164935b
AK
154 urb->iso_frame_desc[i].status = 0;
155 urb->iso_frame_desc[i].actual_length = iso_packet[i].length;
156 urb->actual_length += urb->iso_frame_desc[i].actual_length;
3fa98f34 157 } else {
b164935b
AK
158 DEBUG_ERROR("%s: ISOCHRONOUS packet=%d of %d status=%d pipe=%d submit=%d size=%d\n",
159 __FUNCTION__, i, urb->number_of_packets,
160 iso_packet[i].status, pipe_handle,
161 submit_handle, iso_packet[i].length);
162 urb->iso_frame_desc[i].status = -EREMOTEIO;
163 }
164 }
165 /* Free the private list now that we don't need it anymore */
166 kfree(iso_packet);
167 urb->setup_packet = NULL;
168 }
169
3fa98f34 170 switch (status) {
b164935b
AK
171 case CVMX_USB_COMPLETE_SUCCESS:
172 urb->status = 0;
173 break;
174 case CVMX_USB_COMPLETE_CANCEL:
175 if (urb->status == 0)
176 urb->status = -ENOENT;
177 break;
178 case CVMX_USB_COMPLETE_STALL:
179 DEBUG_ERROR("%s: status=stall pipe=%d submit=%d size=%d\n", __FUNCTION__, pipe_handle, submit_handle, bytes_transferred);
180 urb->status = -EPIPE;
181 break;
182 case CVMX_USB_COMPLETE_BABBLEERR:
183 DEBUG_ERROR("%s: status=babble pipe=%d submit=%d size=%d\n", __FUNCTION__, pipe_handle, submit_handle, bytes_transferred);
184 urb->status = -EPIPE;
185 break;
186 case CVMX_USB_COMPLETE_SHORT:
187 DEBUG_ERROR("%s: status=short pipe=%d submit=%d size=%d\n", __FUNCTION__, pipe_handle, submit_handle, bytes_transferred);
188 urb->status = -EREMOTEIO;
189 break;
190 case CVMX_USB_COMPLETE_ERROR:
191 case CVMX_USB_COMPLETE_XACTERR:
192 case CVMX_USB_COMPLETE_DATATGLERR:
193 case CVMX_USB_COMPLETE_FRAMEERR:
194 DEBUG_ERROR("%s: status=%d pipe=%d submit=%d size=%d\n", __FUNCTION__, status, pipe_handle, submit_handle, bytes_transferred);
195 urb->status = -EPROTO;
196 break;
197 }
198 spin_unlock(&priv->lock);
199 usb_hcd_giveback_urb(octeon_to_hcd(priv), urb, urb->status);
200 spin_lock(&priv->lock);
201}
202
203static int octeon_usb_urb_enqueue(struct usb_hcd *hcd,
204 struct urb *urb,
205 gfp_t mem_flags)
206{
207 struct octeon_hcd *priv = hcd_to_octeon(hcd);
208 int submit_handle = -1;
209 int pipe_handle;
210 unsigned long flags;
211 cvmx_usb_iso_packet_t *iso_packet;
212 struct usb_host_endpoint *ep = urb->ep;
213
214 DEBUG_CALL("OcteonUSB: %s called\n", __FUNCTION__);
215
216 urb->status = 0;
217 INIT_LIST_HEAD(&urb->urb_list); /* not enqueued on dequeue_list */
218 spin_lock_irqsave(&priv->lock, flags);
219
3fa98f34 220 if (!ep->hcpriv) {
b164935b
AK
221 cvmx_usb_transfer_t transfer_type;
222 cvmx_usb_speed_t speed;
223 int split_device = 0;
224 int split_port = 0;
3fa98f34 225 switch (usb_pipetype(urb->pipe)) {
b164935b
AK
226 case PIPE_ISOCHRONOUS:
227 transfer_type = CVMX_USB_TRANSFER_ISOCHRONOUS;
228 break;
229 case PIPE_INTERRUPT:
230 transfer_type = CVMX_USB_TRANSFER_INTERRUPT;
231 break;
232 case PIPE_CONTROL:
233 transfer_type = CVMX_USB_TRANSFER_CONTROL;
234 break;
235 default:
236 transfer_type = CVMX_USB_TRANSFER_BULK;
237 break;
238 }
3fa98f34 239 switch (urb->dev->speed) {
b164935b
AK
240 case USB_SPEED_LOW:
241 speed = CVMX_USB_SPEED_LOW;
242 break;
243 case USB_SPEED_FULL:
244 speed = CVMX_USB_SPEED_FULL;
245 break;
246 default:
247 speed = CVMX_USB_SPEED_HIGH;
248 break;
249 }
250 /* For slow devices on high speed ports we need to find the hub that
251 does the speed translation so we know where to send the split
252 transactions */
3fa98f34 253 if (speed != CVMX_USB_SPEED_HIGH) {
b164935b
AK
254 /* Start at this device and work our way up the usb tree */
255 struct usb_device *dev = urb->dev;
3fa98f34 256 while (dev->parent) {
b164935b 257 /* If our parent is high speed then he'll receive the splits */
3fa98f34 258 if (dev->parent->speed == USB_SPEED_HIGH) {
b164935b
AK
259 split_device = dev->parent->devnum;
260 split_port = dev->portnum;
261 break;
262 }
263 /* Move up the tree one level. If we make it all the way up the
264 tree, then the port must not be in high speed mode and we
265 don't need a split */
266 dev = dev->parent;
267 }
268 }
269 pipe_handle = cvmx_usb_open_pipe(&priv->usb,
270 0,
271 usb_pipedevice(urb->pipe),
272 usb_pipeendpoint(urb->pipe),
273 speed,
274 le16_to_cpu(ep->desc.wMaxPacketSize) & 0x7ff,
275 transfer_type,
276 usb_pipein(urb->pipe) ? CVMX_USB_DIRECTION_IN : CVMX_USB_DIRECTION_OUT,
277 urb->interval,
278 (le16_to_cpu(ep->desc.wMaxPacketSize)>>11) & 0x3,
279 split_device,
280 split_port);
3fa98f34 281 if (pipe_handle < 0) {
b164935b
AK
282 spin_unlock_irqrestore(&priv->lock, flags);
283 DEBUG_ERROR("OcteonUSB: %s failed to create pipe\n", __FUNCTION__);
284 return -ENOMEM;
285 }
286 ep->hcpriv = (void*)(0x10000L + pipe_handle);
287 }
288 else
289 pipe_handle = 0xffff & (long)ep->hcpriv;
290
3fa98f34 291 switch (usb_pipetype(urb->pipe)) {
b164935b
AK
292 case PIPE_ISOCHRONOUS:
293 DEBUG_SUBMIT("OcteonUSB: %s submit isochronous to %d.%d\n", __FUNCTION__, usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe));
294 /* Allocate a structure to use for our private list of isochronous
295 packets */
296 iso_packet = kmalloc(urb->number_of_packets * sizeof(cvmx_usb_iso_packet_t), GFP_ATOMIC);
3fa98f34 297 if (iso_packet) {
b164935b
AK
298 int i;
299 /* Fill the list with the data from the URB */
3fa98f34 300 for (i=0; i<urb->number_of_packets; i++) {
b164935b
AK
301 iso_packet[i].offset = urb->iso_frame_desc[i].offset;
302 iso_packet[i].length = urb->iso_frame_desc[i].length;
303 iso_packet[i].status = CVMX_USB_COMPLETE_ERROR;
304 }
305 /* Store a pointer to the list in uthe URB setup_pakcet field.
306 We know this currently isn't being used and this saves us
307 a bunch of logic */
308 urb->setup_packet = (char*)iso_packet;
309 submit_handle = cvmx_usb_submit_isochronous(&priv->usb, pipe_handle,
310 urb->start_frame,
311 0 /* flags */,
312 urb->number_of_packets,
313 iso_packet,
314 urb->transfer_dma,
315 urb->transfer_buffer_length,
316 octeon_usb_urb_complete_callback,
317 urb);
318 /* If submit failed we need to free our private packet list */
3fa98f34 319 if (submit_handle < 0) {
b164935b
AK
320 urb->setup_packet = NULL;
321 kfree(iso_packet);
322 }
323 }
324 break;
325 case PIPE_INTERRUPT:
326 DEBUG_SUBMIT("OcteonUSB: %s submit interrupt to %d.%d\n", __FUNCTION__, usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe));
327 submit_handle = cvmx_usb_submit_interrupt(&priv->usb, pipe_handle,
328 urb->transfer_dma,
329 urb->transfer_buffer_length,
330 octeon_usb_urb_complete_callback,
331 urb);
332 break;
333 case PIPE_CONTROL:
334 DEBUG_SUBMIT("OcteonUSB: %s submit control to %d.%d\n", __FUNCTION__, usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe));
335 submit_handle = cvmx_usb_submit_control(&priv->usb, pipe_handle,
336 urb->setup_dma,
337 urb->transfer_dma,
338 urb->transfer_buffer_length,
339 octeon_usb_urb_complete_callback,
340 urb);
341 break;
342 case PIPE_BULK:
343 DEBUG_SUBMIT("OcteonUSB: %s submit bulk to %d.%d\n", __FUNCTION__, usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe));
344 submit_handle = cvmx_usb_submit_bulk(&priv->usb, pipe_handle,
345 urb->transfer_dma,
346 urb->transfer_buffer_length,
347 octeon_usb_urb_complete_callback,
348 urb);
349 break;
350 }
3fa98f34 351 if (submit_handle < 0) {
b164935b
AK
352 spin_unlock_irqrestore(&priv->lock, flags);
353 DEBUG_ERROR("OcteonUSB: %s failed to submit\n", __FUNCTION__);
354 return -ENOMEM;
355 }
356 urb->hcpriv = (void*)(long)(((submit_handle & 0xffff) << 16) | pipe_handle);
357 spin_unlock_irqrestore(&priv->lock, flags);
358 return 0;
359}
360
361static void octeon_usb_urb_dequeue_work(unsigned long arg)
362{
363 unsigned long flags;
364 struct octeon_hcd *priv = (struct octeon_hcd *)arg;
365
366 spin_lock_irqsave(&priv->lock, flags);
367
368 while (!list_empty(&priv->dequeue_list)) {
369 int pipe_handle;
370 int submit_handle;
371 struct urb *urb = container_of(priv->dequeue_list.next, struct urb, urb_list);
372 list_del(&urb->urb_list);
373 /* not enqueued on dequeue_list */
374 INIT_LIST_HEAD(&urb->urb_list);
375 pipe_handle = 0xffff & (long)urb->hcpriv;
376 submit_handle = ((long)urb->hcpriv) >> 16;
377 cvmx_usb_cancel(&priv->usb, pipe_handle, submit_handle);
378 }
379
380 spin_unlock_irqrestore(&priv->lock, flags);
381}
382
383static int octeon_usb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
384{
385 struct octeon_hcd *priv = hcd_to_octeon(hcd);
386 unsigned long flags;
387
388 DEBUG_CALL("OcteonUSB: %s called\n", __FUNCTION__);
389
390 if (!urb->dev)
391 return -EINVAL;
392
393 spin_lock_irqsave(&priv->lock, flags);
394
395 urb->status = status;
396 list_add_tail(&urb->urb_list, &priv->dequeue_list);
397
398 spin_unlock_irqrestore(&priv->lock, flags);
399
400 tasklet_schedule(&priv->dequeue_tasklet);
401
402 return 0;
403}
404
405static void octeon_usb_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
406{
407 DEBUG_CALL("OcteonUSB: %s called\n", __FUNCTION__);
3fa98f34 408 if (ep->hcpriv) {
b164935b
AK
409 struct octeon_hcd *priv = hcd_to_octeon(hcd);
410 int pipe_handle = 0xffff & (long)ep->hcpriv;
411 unsigned long flags;
412 spin_lock_irqsave(&priv->lock, flags);
413 cvmx_usb_cancel_all(&priv->usb, pipe_handle);
414 if (cvmx_usb_close_pipe(&priv->usb, pipe_handle))
415 DEBUG_ERROR("OcteonUSB: Closing pipe %d failed\n", pipe_handle);
416 spin_unlock_irqrestore(&priv->lock, flags);
417 ep->hcpriv = NULL;
418 }
419}
420
421static int octeon_usb_hub_status_data(struct usb_hcd *hcd, char *buf)
422{
423 struct octeon_hcd *priv = hcd_to_octeon(hcd);
424 cvmx_usb_port_status_t port_status;
425 unsigned long flags;
426
427 DEBUG_CALL("OcteonUSB: %s called\n", __FUNCTION__);
428
429 spin_lock_irqsave(&priv->lock, flags);
430 port_status = cvmx_usb_get_status(&priv->usb);
431 spin_unlock_irqrestore(&priv->lock, flags);
432 buf[0] = 0;
433 buf[0] = port_status.connect_change << 1;
434
435 return(buf[0] != 0);
436}
437
438static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength)
439{
440 struct octeon_hcd *priv = hcd_to_octeon(hcd);
441 cvmx_usb_port_status_t usb_port_status;
442 int port_status;
443 struct usb_hub_descriptor *desc;
444 unsigned long flags;
445
3fa98f34 446 switch (typeReq) {
b164935b
AK
447 case ClearHubFeature:
448 DEBUG_ROOT_HUB("OcteonUSB: ClearHubFeature\n");
3fa98f34 449 switch (wValue) {
b164935b
AK
450 case C_HUB_LOCAL_POWER:
451 case C_HUB_OVER_CURRENT:
452 /* Nothing required here */
453 break;
454 default:
455 return -EINVAL;
456 }
457 break;
458 case ClearPortFeature:
459 DEBUG_ROOT_HUB("OcteonUSB: ClearPortFeature");
3fa98f34 460 if (wIndex != 1) {
b164935b
AK
461 DEBUG_ROOT_HUB(" INVALID\n");
462 return -EINVAL;
463 }
464
3fa98f34 465 switch (wValue) {
b164935b
AK
466 case USB_PORT_FEAT_ENABLE:
467 DEBUG_ROOT_HUB(" ENABLE");
468 spin_lock_irqsave(&priv->lock, flags);
469 cvmx_usb_disable(&priv->usb);
470 spin_unlock_irqrestore(&priv->lock, flags);
471 break;
472 case USB_PORT_FEAT_SUSPEND:
473 DEBUG_ROOT_HUB(" SUSPEND");
474 /* Not supported on Octeon */
475 break;
476 case USB_PORT_FEAT_POWER:
477 DEBUG_ROOT_HUB(" POWER");
478 /* Not supported on Octeon */
479 break;
480 case USB_PORT_FEAT_INDICATOR:
481 DEBUG_ROOT_HUB(" INDICATOR");
482 /* Port inidicator not supported */
483 break;
484 case USB_PORT_FEAT_C_CONNECTION:
485 DEBUG_ROOT_HUB(" C_CONNECTION");
486 /* Clears drivers internal connect status change flag */
487 spin_lock_irqsave(&priv->lock, flags);
488 cvmx_usb_set_status(&priv->usb, cvmx_usb_get_status(&priv->usb));
489 spin_unlock_irqrestore(&priv->lock, flags);
490 break;
491 case USB_PORT_FEAT_C_RESET:
492 DEBUG_ROOT_HUB(" C_RESET");
493 /* Clears the driver's internal Port Reset Change flag */
494 spin_lock_irqsave(&priv->lock, flags);
495 cvmx_usb_set_status(&priv->usb, cvmx_usb_get_status(&priv->usb));
496 spin_unlock_irqrestore(&priv->lock, flags);
497 break;
498 case USB_PORT_FEAT_C_ENABLE:
499 DEBUG_ROOT_HUB(" C_ENABLE");
500 /* Clears the driver's internal Port Enable/Disable Change flag */
501 spin_lock_irqsave(&priv->lock, flags);
502 cvmx_usb_set_status(&priv->usb, cvmx_usb_get_status(&priv->usb));
503 spin_unlock_irqrestore(&priv->lock, flags);
504 break;
505 case USB_PORT_FEAT_C_SUSPEND:
506 DEBUG_ROOT_HUB(" C_SUSPEND");
507 /* Clears the driver's internal Port Suspend Change flag,
508 which is set when resume signaling on the host port is
509 complete */
510 break;
511 case USB_PORT_FEAT_C_OVER_CURRENT:
512 DEBUG_ROOT_HUB(" C_OVER_CURRENT");
513 /* Clears the driver's overcurrent Change flag */
514 spin_lock_irqsave(&priv->lock, flags);
515 cvmx_usb_set_status(&priv->usb, cvmx_usb_get_status(&priv->usb));
516 spin_unlock_irqrestore(&priv->lock, flags);
517 break;
518 default:
519 DEBUG_ROOT_HUB(" UNKNOWN\n");
520 return -EINVAL;
521 }
522 DEBUG_ROOT_HUB("\n");
523 break;
524 case GetHubDescriptor:
525 DEBUG_ROOT_HUB("OcteonUSB: GetHubDescriptor\n");
526 desc = (struct usb_hub_descriptor *)buf;
527 desc->bDescLength = 9;
528 desc->bDescriptorType = 0x29;
529 desc->bNbrPorts = 1;
530 desc->wHubCharacteristics = 0x08;
531 desc->bPwrOn2PwrGood = 1;
532 desc->bHubContrCurrent = 0;
533 desc->u.hs.DeviceRemovable[0] = 0;
534 desc->u.hs.DeviceRemovable[1] = 0xff;
535 break;
536 case GetHubStatus:
537 DEBUG_ROOT_HUB("OcteonUSB: GetHubStatus\n");
538 *(__le32 *)buf = 0;
539 break;
540 case GetPortStatus:
541 DEBUG_ROOT_HUB("OcteonUSB: GetPortStatus");
3fa98f34 542 if (wIndex != 1) {
b164935b
AK
543 DEBUG_ROOT_HUB(" INVALID\n");
544 return -EINVAL;
545 }
546
547 spin_lock_irqsave(&priv->lock, flags);
548 usb_port_status = cvmx_usb_get_status(&priv->usb);
549 spin_unlock_irqrestore(&priv->lock, flags);
550 port_status = 0;
551
3fa98f34 552 if (usb_port_status.connect_change) {
b164935b
AK
553 port_status |= (1 << USB_PORT_FEAT_C_CONNECTION);
554 DEBUG_ROOT_HUB(" C_CONNECTION");
555 }
556
3fa98f34 557 if (usb_port_status.port_enabled) {
b164935b
AK
558 port_status |= (1 << USB_PORT_FEAT_C_ENABLE);
559 DEBUG_ROOT_HUB(" C_ENABLE");
560 }
561
3fa98f34 562 if (usb_port_status.connected) {
b164935b
AK
563 port_status |= (1 << USB_PORT_FEAT_CONNECTION);
564 DEBUG_ROOT_HUB(" CONNECTION");
565 }
566
3fa98f34 567 if (usb_port_status.port_enabled) {
b164935b
AK
568 port_status |= (1 << USB_PORT_FEAT_ENABLE);
569 DEBUG_ROOT_HUB(" ENABLE");
570 }
571
3fa98f34 572 if (usb_port_status.port_over_current) {
b164935b
AK
573 port_status |= (1 << USB_PORT_FEAT_OVER_CURRENT);
574 DEBUG_ROOT_HUB(" OVER_CURRENT");
575 }
576
3fa98f34 577 if (usb_port_status.port_powered) {
b164935b
AK
578 port_status |= (1 << USB_PORT_FEAT_POWER);
579 DEBUG_ROOT_HUB(" POWER");
580 }
581
3fa98f34 582 if (usb_port_status.port_speed == CVMX_USB_SPEED_HIGH) {
b164935b
AK
583 port_status |= USB_PORT_STAT_HIGH_SPEED;
584 DEBUG_ROOT_HUB(" HIGHSPEED");
3fa98f34 585 } else if (usb_port_status.port_speed == CVMX_USB_SPEED_LOW) {
b164935b
AK
586 port_status |= (1 << USB_PORT_FEAT_LOWSPEED);
587 DEBUG_ROOT_HUB(" LOWSPEED");
588 }
589
590 *((__le32 *)buf) = cpu_to_le32(port_status);
591 DEBUG_ROOT_HUB("\n");
592 break;
593 case SetHubFeature:
594 DEBUG_ROOT_HUB("OcteonUSB: SetHubFeature\n");
595 /* No HUB features supported */
596 break;
597 case SetPortFeature:
598 DEBUG_ROOT_HUB("OcteonUSB: SetPortFeature");
3fa98f34 599 if (wIndex != 1) {
b164935b
AK
600 DEBUG_ROOT_HUB(" INVALID\n");
601 return -EINVAL;
602 }
603
3fa98f34 604 switch (wValue) {
b164935b
AK
605 case USB_PORT_FEAT_SUSPEND:
606 DEBUG_ROOT_HUB(" SUSPEND\n");
607 return -EINVAL;
608 case USB_PORT_FEAT_POWER:
609 DEBUG_ROOT_HUB(" POWER\n");
610 return -EINVAL;
611 case USB_PORT_FEAT_RESET:
612 DEBUG_ROOT_HUB(" RESET\n");
613 spin_lock_irqsave(&priv->lock, flags);
614 cvmx_usb_disable(&priv->usb);
615 if (cvmx_usb_enable(&priv->usb))
616 DEBUG_ERROR("Failed to enable the port\n");
617 spin_unlock_irqrestore(&priv->lock, flags);
618 return 0;
619 case USB_PORT_FEAT_INDICATOR:
620 DEBUG_ROOT_HUB(" INDICATOR\n");
621 /* Not supported */
622 break;
623 default:
624 DEBUG_ROOT_HUB(" UNKNOWN\n");
625 return -EINVAL;
626 }
627 break;
628 default:
629 DEBUG_ROOT_HUB("OcteonUSB: Unknown root hub request\n");
630 return -EINVAL;
631 }
632 return 0;
633}
634
635
636static const struct hc_driver octeon_hc_driver = {
637 .description = "Octeon USB",
638 .product_desc = "Octeon Host Controller",
639 .hcd_priv_size = sizeof(struct octeon_hcd),
640 .irq = octeon_usb_irq,
641 .flags = HCD_MEMORY | HCD_USB2,
642 .start = octeon_usb_start,
643 .stop = octeon_usb_stop,
644 .urb_enqueue = octeon_usb_urb_enqueue,
645 .urb_dequeue = octeon_usb_urb_dequeue,
646 .endpoint_disable = octeon_usb_endpoint_disable,
647 .get_frame_number = octeon_usb_get_frame_number,
648 .hub_status_data = octeon_usb_hub_status_data,
649 .hub_control = octeon_usb_hub_control,
650};
651
652
653static int octeon_usb_driver_probe(struct device *dev)
654{
655 int status;
656 int usb_num = to_platform_device(dev)->id;
657 int irq = platform_get_irq(to_platform_device(dev), 0);
658 struct octeon_hcd *priv;
659 struct usb_hcd *hcd;
660 unsigned long flags;
661
662 DEBUG_CALL("OcteonUSB: %s called\n", __FUNCTION__);
663
664 /* Set the DMA mask to 64bits so we get buffers already translated for
665 DMA */
666 dev->coherent_dma_mask = ~0;
667 dev->dma_mask = &dev->coherent_dma_mask;
668
669 hcd = usb_create_hcd(&octeon_hc_driver, dev, dev_name(dev));
3fa98f34 670 if (!hcd) {
b164935b
AK
671 DEBUG_FATAL("OcteonUSB: Failed to allocate memory for HCD\n");
672 return -1;
673 }
674 hcd->uses_new_polling = 1;
675 priv = (struct octeon_hcd *)hcd->hcd_priv;
676
677 spin_lock_init(&priv->lock);
678
679 tasklet_init(&priv->dequeue_tasklet, octeon_usb_urb_dequeue_work, (unsigned long)priv);
680 INIT_LIST_HEAD(&priv->dequeue_list);
681
682 //status = cvmx_usb_initialize(&priv->usb, usb_num, CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO | CVMX_USB_INITIALIZE_FLAGS_DEBUG_INFO | CVMX_USB_INITIALIZE_FLAGS_DEBUG_TRANSFERS | CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLBACKS);
683 status = cvmx_usb_initialize(&priv->usb, usb_num, CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO);
3fa98f34 684 if (status) {
b164935b
AK
685 DEBUG_FATAL("OcteonUSB: USB initialization failed with %d\n", status);
686 kfree(hcd);
687 return -1;
688 }
689
690 /* This delay is needed for CN3010, but I don't know why... */
691 mdelay(10);
692
693 spin_lock_irqsave(&priv->lock, flags);
694 cvmx_usb_poll(&priv->usb);
695 spin_unlock_irqrestore(&priv->lock, flags);
696
697 status = usb_add_hcd(hcd, irq, IRQF_SHARED);
3fa98f34 698 if (status) {
b164935b
AK
699 DEBUG_FATAL("OcteonUSB: USB add HCD failed with %d\n", status);
700 kfree(hcd);
701 return -1;
702 }
703
704 printk("OcteonUSB: Registered HCD for port %d on irq %d\n", usb_num, irq);
705
706 return 0;
707}
708
709static int octeon_usb_driver_remove(struct device *dev)
710{
711 int status;
712 struct usb_hcd *hcd = dev_get_drvdata(dev);
713 struct octeon_hcd *priv = hcd_to_octeon(hcd);
714 unsigned long flags;
715
716 DEBUG_CALL("OcteonUSB: %s called\n", __FUNCTION__);
717
718 usb_remove_hcd(hcd);
719 tasklet_kill(&priv->dequeue_tasklet);
720 spin_lock_irqsave(&priv->lock, flags);
721 status = cvmx_usb_shutdown(&priv->usb);
722 spin_unlock_irqrestore(&priv->lock, flags);
723 if (status)
724 DEBUG_FATAL("OcteonUSB: USB shutdown failed with %d\n", status);
725
726 kfree(hcd);
727
728 return 0;
729}
730
731static struct device_driver octeon_usb_driver = {
732 .name = "OcteonUSB",
733 .bus = &platform_bus_type,
734 .probe = octeon_usb_driver_probe,
735 .remove = octeon_usb_driver_remove,
736};
737
738
739#define MAX_USB_PORTS 10
740struct platform_device *pdev_glob[MAX_USB_PORTS];
741static int octeon_usb_registered;
742static int __init octeon_usb_module_init(void)
743{
744 int num_devices = cvmx_usb_get_num_ports();
745 int device;
746
747 if (usb_disabled() || num_devices == 0)
748 return -ENODEV;
749
3fa98f34 750 if (driver_register(&octeon_usb_driver)) {
b164935b
AK
751 DEBUG_FATAL("OcteonUSB: Failed to register driver\n");
752 return -ENOMEM;
753 }
754 octeon_usb_registered = 1;
755 printk("OcteonUSB: Detected %d ports\n", num_devices);
756
757 /*
758 * Only cn52XX and cn56XX have DWC_OTG USB hardware and the
759 * IOB priority registers. Under heavy network load USB
760 * hardware can be starved by the IOB causing a crash. Give
761 * it a priority boost if it has been waiting more than 400
762 * cycles to avoid this situation.
763 *
764 * Testing indicates that a cnt_val of 8192 is not sufficient,
765 * but no failures are seen with 4096. We choose a value of
766 * 400 to give a safety factor of 10.
767 */
768 if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN56XX)) {
769 union cvmx_iob_n2c_l2c_pri_cnt pri_cnt;
770
771 pri_cnt.u64 = 0;
772 pri_cnt.s.cnt_enb = 1;
773 pri_cnt.s.cnt_val = 400;
774 cvmx_write_csr(CVMX_IOB_N2C_L2C_PRI_CNT, pri_cnt.u64);
775 }
776
3fa98f34 777 for (device = 0; device < num_devices; device++) {
b164935b
AK
778 struct resource irq_resource;
779 struct platform_device *pdev;
780 memset(&irq_resource, 0, sizeof(irq_resource));
781 irq_resource.start = (device==0) ? OCTEON_IRQ_USB0 : OCTEON_IRQ_USB1;
782 irq_resource.end = irq_resource.start;
783 irq_resource.flags = IORESOURCE_IRQ;
784 pdev = platform_device_register_simple((char*)octeon_usb_driver.name, device, &irq_resource, 1);
55fa328a 785 if (IS_ERR(pdev)) {
b164935b 786 DEBUG_FATAL("OcteonUSB: Failed to allocate platform device for USB%d\n", device);
5e15430e
DN
787 driver_unregister(&octeon_usb_driver);
788 octeon_usb_registered = 0;
55fa328a 789 return PTR_ERR(pdev);
b164935b
AK
790 }
791 if (device < MAX_USB_PORTS)
792 pdev_glob[device] = pdev;
793
794 }
795 return 0;
796}
797
798static void __exit octeon_usb_module_cleanup(void)
799{
800 int i;
801 DEBUG_CALL("OcteonUSB: %s called\n", __FUNCTION__);
802 for (i = 0; i <MAX_USB_PORTS; i++)
3fa98f34 803 if (pdev_glob[i]) {
b164935b
AK
804 platform_device_unregister(pdev_glob[i]);
805 pdev_glob[i] = NULL;
806 }
807 if (octeon_usb_registered)
808 driver_unregister(&octeon_usb_driver);
809}
810
811MODULE_LICENSE("GPL");
812MODULE_AUTHOR("Cavium Networks <support@caviumnetworks.com>");
813MODULE_DESCRIPTION("Cavium Networks Octeon USB Host driver.");
814module_init(octeon_usb_module_init);
815module_exit(octeon_usb_module_cleanup);
This page took 0.063076 seconds and 5 git commands to generate.