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