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
6 * Copyright (C) 2008 Cavium Networks
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/usb.h>
16 #include <linux/time.h>
17 #include <linux/delay.h>
19 #include <asm/octeon/cvmx.h>
21 #include <asm/octeon/cvmx-iob-defs.h>
23 #include <linux/usb/hcd.h>
25 #include <linux/err.h>
30 struct tasklet_struct dequeue_tasklet;
31 struct list_head dequeue_list;
34 /* convert between an HCD pointer and the corresponding struct octeon_hcd */
35 static inline struct octeon_hcd *hcd_to_octeon(struct usb_hcd *hcd)
37 return (struct octeon_hcd *)(hcd->hcd_priv);
40 static inline struct usb_hcd *octeon_to_hcd(struct octeon_hcd *p)
42 return container_of((void *)p, struct usb_hcd, hcd_priv);
45 static inline struct octeon_hcd *cvmx_usb_to_octeon(cvmx_usb_state_t *p)
47 return container_of(p, struct octeon_hcd, usb);
50 static irqreturn_t octeon_usb_irq(struct usb_hcd *hcd)
52 struct octeon_hcd *priv = hcd_to_octeon(hcd);
55 spin_lock_irqsave(&priv->lock, flags);
56 cvmx_usb_poll(&priv->usb);
57 spin_unlock_irqrestore(&priv->lock, flags);
61 static void octeon_usb_port_callback(cvmx_usb_state_t *usb,
62 cvmx_usb_callback_t reason,
63 cvmx_usb_complete_t status,
66 int bytes_transferred,
69 struct octeon_hcd *priv = cvmx_usb_to_octeon(usb);
71 spin_unlock(&priv->lock);
72 usb_hcd_poll_rh_status(octeon_to_hcd(priv));
73 spin_lock(&priv->lock);
76 static int octeon_usb_start(struct usb_hcd *hcd)
78 struct octeon_hcd *priv = hcd_to_octeon(hcd);
81 hcd->state = HC_STATE_RUNNING;
82 spin_lock_irqsave(&priv->lock, flags);
83 cvmx_usb_register_callback(&priv->usb, CVMX_USB_CALLBACK_PORT_CHANGED,
84 octeon_usb_port_callback, NULL);
85 spin_unlock_irqrestore(&priv->lock, flags);
89 static void octeon_usb_stop(struct usb_hcd *hcd)
91 struct octeon_hcd *priv = hcd_to_octeon(hcd);
94 spin_lock_irqsave(&priv->lock, flags);
95 cvmx_usb_register_callback(&priv->usb, CVMX_USB_CALLBACK_PORT_CHANGED,
97 spin_unlock_irqrestore(&priv->lock, flags);
98 hcd->state = HC_STATE_HALT;
101 static int octeon_usb_get_frame_number(struct usb_hcd *hcd)
103 struct octeon_hcd *priv = hcd_to_octeon(hcd);
105 return cvmx_usb_get_frame_number(&priv->usb);
108 static void octeon_usb_urb_complete_callback(cvmx_usb_state_t *usb,
109 cvmx_usb_callback_t reason,
110 cvmx_usb_complete_t status,
113 int bytes_transferred,
116 struct octeon_hcd *priv = cvmx_usb_to_octeon(usb);
117 struct usb_hcd *hcd = octeon_to_hcd(priv);
118 struct device *dev = hcd->self.controller;
119 struct urb *urb = user_data;
121 urb->actual_length = bytes_transferred;
124 if (!list_empty(&urb->urb_list)) {
126 * It is on the dequeue_list, but we are going to call
127 * usb_hcd_giveback_urb(), so we must clear it from
128 * the list. We got to it before the
129 * octeon_usb_urb_dequeue_work() tasklet did.
131 list_del(&urb->urb_list);
132 /* No longer on the dequeue_list. */
133 INIT_LIST_HEAD(&urb->urb_list);
136 /* For Isochronous transactions we need to update the URB packet status
137 list from data in our private copy */
138 if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
141 * The pointer to the private list is stored in the setup_packet
144 cvmx_usb_iso_packet_t *iso_packet = (cvmx_usb_iso_packet_t *) urb->setup_packet;
145 /* Recalculate the transfer size by adding up each packet */
146 urb->actual_length = 0;
147 for (i = 0; i < urb->number_of_packets; i++) {
148 if (iso_packet[i].status == CVMX_USB_COMPLETE_SUCCESS) {
149 urb->iso_frame_desc[i].status = 0;
150 urb->iso_frame_desc[i].actual_length = iso_packet[i].length;
151 urb->actual_length += urb->iso_frame_desc[i].actual_length;
153 dev_dbg(dev, "ISOCHRONOUS packet=%d of %d status=%d pipe=%d submit=%d size=%d\n",
154 i, urb->number_of_packets,
155 iso_packet[i].status, pipe_handle,
156 submit_handle, iso_packet[i].length);
157 urb->iso_frame_desc[i].status = -EREMOTEIO;
160 /* Free the private list now that we don't need it anymore */
162 urb->setup_packet = NULL;
166 case CVMX_USB_COMPLETE_SUCCESS:
169 case CVMX_USB_COMPLETE_CANCEL:
170 if (urb->status == 0)
171 urb->status = -ENOENT;
173 case CVMX_USB_COMPLETE_STALL:
174 dev_dbg(dev, "status=stall pipe=%d submit=%d size=%d\n",
175 pipe_handle, submit_handle, bytes_transferred);
176 urb->status = -EPIPE;
178 case CVMX_USB_COMPLETE_BABBLEERR:
179 dev_dbg(dev, "status=babble pipe=%d submit=%d size=%d\n",
180 pipe_handle, submit_handle, bytes_transferred);
181 urb->status = -EPIPE;
183 case CVMX_USB_COMPLETE_SHORT:
184 dev_dbg(dev, "status=short pipe=%d submit=%d size=%d\n",
185 pipe_handle, submit_handle, bytes_transferred);
186 urb->status = -EREMOTEIO;
188 case CVMX_USB_COMPLETE_ERROR:
189 case CVMX_USB_COMPLETE_XACTERR:
190 case CVMX_USB_COMPLETE_DATATGLERR:
191 case CVMX_USB_COMPLETE_FRAMEERR:
192 dev_dbg(dev, "status=%d pipe=%d submit=%d size=%d\n",
193 status, pipe_handle, submit_handle, bytes_transferred);
194 urb->status = -EPROTO;
197 spin_unlock(&priv->lock);
198 usb_hcd_giveback_urb(octeon_to_hcd(priv), urb, urb->status);
199 spin_lock(&priv->lock);
202 static int octeon_usb_urb_enqueue(struct usb_hcd *hcd,
206 struct octeon_hcd *priv = hcd_to_octeon(hcd);
207 struct device *dev = hcd->self.controller;
208 int submit_handle = -1;
211 cvmx_usb_iso_packet_t *iso_packet;
212 struct usb_host_endpoint *ep = urb->ep;
215 INIT_LIST_HEAD(&urb->urb_list); /* not enqueued on dequeue_list */
216 spin_lock_irqsave(&priv->lock, flags);
219 cvmx_usb_transfer_t transfer_type;
220 cvmx_usb_speed_t speed;
221 int split_device = 0;
223 switch (usb_pipetype(urb->pipe)) {
224 case PIPE_ISOCHRONOUS:
225 transfer_type = CVMX_USB_TRANSFER_ISOCHRONOUS;
228 transfer_type = CVMX_USB_TRANSFER_INTERRUPT;
231 transfer_type = CVMX_USB_TRANSFER_CONTROL;
234 transfer_type = CVMX_USB_TRANSFER_BULK;
237 switch (urb->dev->speed) {
239 speed = CVMX_USB_SPEED_LOW;
242 speed = CVMX_USB_SPEED_FULL;
245 speed = CVMX_USB_SPEED_HIGH;
249 * For slow devices on high speed ports we need to find the hub
250 * that does the speed translation so we know where to send the
251 * split transactions.
253 if (speed != CVMX_USB_SPEED_HIGH) {
255 * Start at this device and work our way up the usb
258 struct usb_device *dev = urb->dev;
259 while (dev->parent) {
261 * If our parent is high speed then he'll
262 * receive the splits.
264 if (dev->parent->speed == USB_SPEED_HIGH) {
265 split_device = dev->parent->devnum;
266 split_port = dev->portnum;
270 * Move up the tree one level. If we make it all
271 * the way up the tree, then the port must not
272 * be in high speed mode and we don't need a
278 pipe_handle = cvmx_usb_open_pipe(&priv->usb,
280 usb_pipedevice(urb->pipe),
281 usb_pipeendpoint(urb->pipe),
283 le16_to_cpu(ep->desc.wMaxPacketSize) & 0x7ff,
285 usb_pipein(urb->pipe) ? CVMX_USB_DIRECTION_IN : CVMX_USB_DIRECTION_OUT,
287 (le16_to_cpu(ep->desc.wMaxPacketSize) >> 11) & 0x3,
290 if (pipe_handle < 0) {
291 spin_unlock_irqrestore(&priv->lock, flags);
292 dev_dbg(dev, "Failed to create pipe\n");
295 ep->hcpriv = (void *)(0x10000L + pipe_handle);
297 pipe_handle = 0xffff & (long)ep->hcpriv;
300 switch (usb_pipetype(urb->pipe)) {
301 case PIPE_ISOCHRONOUS:
302 dev_dbg(dev, "Submit isochronous to %d.%d\n",
303 usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe));
305 * Allocate a structure to use for our private list of
306 * isochronous packets.
308 iso_packet = kmalloc(urb->number_of_packets * sizeof(cvmx_usb_iso_packet_t), GFP_ATOMIC);
311 /* Fill the list with the data from the URB */
312 for (i = 0; i < urb->number_of_packets; i++) {
313 iso_packet[i].offset = urb->iso_frame_desc[i].offset;
314 iso_packet[i].length = urb->iso_frame_desc[i].length;
315 iso_packet[i].status = CVMX_USB_COMPLETE_ERROR;
318 * Store a pointer to the list in the URB setup_packet
319 * field. We know this currently isn't being used and
320 * this saves us a bunch of logic.
322 urb->setup_packet = (char *)iso_packet;
323 submit_handle = cvmx_usb_submit_isochronous(&priv->usb, pipe_handle,
326 urb->number_of_packets,
329 urb->transfer_buffer_length,
330 octeon_usb_urb_complete_callback,
333 * If submit failed we need to free our private packet
336 if (submit_handle < 0) {
337 urb->setup_packet = NULL;
343 dev_dbg(dev, "Submit interrupt to %d.%d\n",
344 usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe));
345 submit_handle = cvmx_usb_submit_interrupt(&priv->usb, pipe_handle,
347 urb->transfer_buffer_length,
348 octeon_usb_urb_complete_callback,
352 dev_dbg(dev, "Submit control to %d.%d\n",
353 usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe));
354 submit_handle = cvmx_usb_submit_control(&priv->usb, pipe_handle,
357 urb->transfer_buffer_length,
358 octeon_usb_urb_complete_callback,
362 dev_dbg(dev, "Submit bulk to %d.%d\n",
363 usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe));
364 submit_handle = cvmx_usb_submit_bulk(&priv->usb, pipe_handle,
366 urb->transfer_buffer_length,
367 octeon_usb_urb_complete_callback,
371 if (submit_handle < 0) {
372 spin_unlock_irqrestore(&priv->lock, flags);
373 dev_dbg(dev, "Failed to submit\n");
376 urb->hcpriv = (void *)(long)(((submit_handle & 0xffff) << 16) | pipe_handle);
377 spin_unlock_irqrestore(&priv->lock, flags);
381 static void octeon_usb_urb_dequeue_work(unsigned long arg)
384 struct octeon_hcd *priv = (struct octeon_hcd *)arg;
386 spin_lock_irqsave(&priv->lock, flags);
388 while (!list_empty(&priv->dequeue_list)) {
391 struct urb *urb = container_of(priv->dequeue_list.next, struct urb, urb_list);
392 list_del(&urb->urb_list);
393 /* not enqueued on dequeue_list */
394 INIT_LIST_HEAD(&urb->urb_list);
395 pipe_handle = 0xffff & (long)urb->hcpriv;
396 submit_handle = ((long)urb->hcpriv) >> 16;
397 cvmx_usb_cancel(&priv->usb, pipe_handle, submit_handle);
400 spin_unlock_irqrestore(&priv->lock, flags);
403 static int octeon_usb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
405 struct octeon_hcd *priv = hcd_to_octeon(hcd);
411 spin_lock_irqsave(&priv->lock, flags);
413 urb->status = status;
414 list_add_tail(&urb->urb_list, &priv->dequeue_list);
416 spin_unlock_irqrestore(&priv->lock, flags);
418 tasklet_schedule(&priv->dequeue_tasklet);
423 static void octeon_usb_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
425 struct device *dev = hcd->self.controller;
428 struct octeon_hcd *priv = hcd_to_octeon(hcd);
429 int pipe_handle = 0xffff & (long)ep->hcpriv;
431 spin_lock_irqsave(&priv->lock, flags);
432 cvmx_usb_cancel_all(&priv->usb, pipe_handle);
433 if (cvmx_usb_close_pipe(&priv->usb, pipe_handle))
434 dev_dbg(dev, "Closing pipe %d failed\n", pipe_handle);
435 spin_unlock_irqrestore(&priv->lock, flags);
440 static int octeon_usb_hub_status_data(struct usb_hcd *hcd, char *buf)
442 struct octeon_hcd *priv = hcd_to_octeon(hcd);
443 cvmx_usb_port_status_t port_status;
446 spin_lock_irqsave(&priv->lock, flags);
447 port_status = cvmx_usb_get_status(&priv->usb);
448 spin_unlock_irqrestore(&priv->lock, flags);
450 buf[0] = port_status.connect_change << 1;
452 return (buf[0] != 0);
455 static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength)
457 struct octeon_hcd *priv = hcd_to_octeon(hcd);
458 struct device *dev = hcd->self.controller;
459 cvmx_usb_port_status_t usb_port_status;
461 struct usb_hub_descriptor *desc;
465 case ClearHubFeature:
466 dev_dbg(dev, "ClearHubFeature\n");
468 case C_HUB_LOCAL_POWER:
469 case C_HUB_OVER_CURRENT:
470 /* Nothing required here */
476 case ClearPortFeature:
477 dev_dbg(dev, "ClearPortFeature\n");
479 dev_dbg(dev, " INVALID\n");
484 case USB_PORT_FEAT_ENABLE:
485 dev_dbg(dev, " ENABLE\n");
486 spin_lock_irqsave(&priv->lock, flags);
487 cvmx_usb_disable(&priv->usb);
488 spin_unlock_irqrestore(&priv->lock, flags);
490 case USB_PORT_FEAT_SUSPEND:
491 dev_dbg(dev, " SUSPEND\n");
492 /* Not supported on Octeon */
494 case USB_PORT_FEAT_POWER:
495 dev_dbg(dev, " POWER\n");
496 /* Not supported on Octeon */
498 case USB_PORT_FEAT_INDICATOR:
499 dev_dbg(dev, " INDICATOR\n");
500 /* Port inidicator not supported */
502 case USB_PORT_FEAT_C_CONNECTION:
503 dev_dbg(dev, " C_CONNECTION\n");
504 /* Clears drivers internal connect status change flag */
505 spin_lock_irqsave(&priv->lock, flags);
506 cvmx_usb_set_status(&priv->usb, cvmx_usb_get_status(&priv->usb));
507 spin_unlock_irqrestore(&priv->lock, flags);
509 case USB_PORT_FEAT_C_RESET:
510 dev_dbg(dev, " C_RESET\n");
512 * Clears the driver's internal Port Reset 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);
518 case USB_PORT_FEAT_C_ENABLE:
519 dev_dbg(dev, " C_ENABLE\n");
521 * Clears the driver's internal Port Enable/Disable
524 spin_lock_irqsave(&priv->lock, flags);
525 cvmx_usb_set_status(&priv->usb, cvmx_usb_get_status(&priv->usb));
526 spin_unlock_irqrestore(&priv->lock, flags);
528 case USB_PORT_FEAT_C_SUSPEND:
529 dev_dbg(dev, " C_SUSPEND\n");
531 * Clears the driver's internal Port Suspend Change
532 * flag, which is set when resume signaling on the host
536 case USB_PORT_FEAT_C_OVER_CURRENT:
537 dev_dbg(dev, " C_OVER_CURRENT\n");
538 /* Clears the driver's overcurrent Change flag */
539 spin_lock_irqsave(&priv->lock, flags);
540 cvmx_usb_set_status(&priv->usb, cvmx_usb_get_status(&priv->usb));
541 spin_unlock_irqrestore(&priv->lock, flags);
544 dev_dbg(dev, " UNKNOWN\n");
548 case GetHubDescriptor:
549 dev_dbg(dev, "GetHubDescriptor\n");
550 desc = (struct usb_hub_descriptor *)buf;
551 desc->bDescLength = 9;
552 desc->bDescriptorType = 0x29;
554 desc->wHubCharacteristics = 0x08;
555 desc->bPwrOn2PwrGood = 1;
556 desc->bHubContrCurrent = 0;
557 desc->u.hs.DeviceRemovable[0] = 0;
558 desc->u.hs.DeviceRemovable[1] = 0xff;
561 dev_dbg(dev, "GetHubStatus\n");
565 dev_dbg(dev, "GetPortStatus\n");
567 dev_dbg(dev, " INVALID\n");
571 spin_lock_irqsave(&priv->lock, flags);
572 usb_port_status = cvmx_usb_get_status(&priv->usb);
573 spin_unlock_irqrestore(&priv->lock, flags);
576 if (usb_port_status.connect_change) {
577 port_status |= (1 << USB_PORT_FEAT_C_CONNECTION);
578 dev_dbg(dev, " C_CONNECTION\n");
581 if (usb_port_status.port_enabled) {
582 port_status |= (1 << USB_PORT_FEAT_C_ENABLE);
583 dev_dbg(dev, " C_ENABLE\n");
586 if (usb_port_status.connected) {
587 port_status |= (1 << USB_PORT_FEAT_CONNECTION);
588 dev_dbg(dev, " CONNECTION\n");
591 if (usb_port_status.port_enabled) {
592 port_status |= (1 << USB_PORT_FEAT_ENABLE);
593 dev_dbg(dev, " ENABLE\n");
596 if (usb_port_status.port_over_current) {
597 port_status |= (1 << USB_PORT_FEAT_OVER_CURRENT);
598 dev_dbg(dev, " OVER_CURRENT\n");
601 if (usb_port_status.port_powered) {
602 port_status |= (1 << USB_PORT_FEAT_POWER);
603 dev_dbg(dev, " POWER\n");
606 if (usb_port_status.port_speed == CVMX_USB_SPEED_HIGH) {
607 port_status |= USB_PORT_STAT_HIGH_SPEED;
608 dev_dbg(dev, " HIGHSPEED\n");
609 } else if (usb_port_status.port_speed == CVMX_USB_SPEED_LOW) {
610 port_status |= (1 << USB_PORT_FEAT_LOWSPEED);
611 dev_dbg(dev, " LOWSPEED\n");
614 *((__le32 *) buf) = cpu_to_le32(port_status);
617 dev_dbg(dev, "SetHubFeature\n");
618 /* No HUB features supported */
621 dev_dbg(dev, "SetPortFeature\n");
623 dev_dbg(dev, " INVALID\n");
628 case USB_PORT_FEAT_SUSPEND:
629 dev_dbg(dev, " SUSPEND\n");
631 case USB_PORT_FEAT_POWER:
632 dev_dbg(dev, " POWER\n");
634 case USB_PORT_FEAT_RESET:
635 dev_dbg(dev, " RESET\n");
636 spin_lock_irqsave(&priv->lock, flags);
637 cvmx_usb_disable(&priv->usb);
638 if (cvmx_usb_enable(&priv->usb))
639 dev_dbg(dev, "Failed to enable the port\n");
640 spin_unlock_irqrestore(&priv->lock, flags);
642 case USB_PORT_FEAT_INDICATOR:
643 dev_dbg(dev, " INDICATOR\n");
647 dev_dbg(dev, " UNKNOWN\n");
652 dev_dbg(dev, "Unknown root hub request\n");
659 static const struct hc_driver octeon_hc_driver = {
660 .description = "Octeon USB",
661 .product_desc = "Octeon Host Controller",
662 .hcd_priv_size = sizeof(struct octeon_hcd),
663 .irq = octeon_usb_irq,
664 .flags = HCD_MEMORY | HCD_USB2,
665 .start = octeon_usb_start,
666 .stop = octeon_usb_stop,
667 .urb_enqueue = octeon_usb_urb_enqueue,
668 .urb_dequeue = octeon_usb_urb_dequeue,
669 .endpoint_disable = octeon_usb_endpoint_disable,
670 .get_frame_number = octeon_usb_get_frame_number,
671 .hub_status_data = octeon_usb_hub_status_data,
672 .hub_control = octeon_usb_hub_control,
676 static int octeon_usb_driver_probe(struct device *dev)
679 int usb_num = to_platform_device(dev)->id;
680 int irq = platform_get_irq(to_platform_device(dev), 0);
681 struct octeon_hcd *priv;
686 * Set the DMA mask to 64bits so we get buffers already translated for
689 dev->coherent_dma_mask = ~0;
690 dev->dma_mask = &dev->coherent_dma_mask;
692 hcd = usb_create_hcd(&octeon_hc_driver, dev, dev_name(dev));
694 dev_dbg(dev, "Failed to allocate memory for HCD\n");
697 hcd->uses_new_polling = 1;
698 priv = (struct octeon_hcd *)hcd->hcd_priv;
700 spin_lock_init(&priv->lock);
702 tasklet_init(&priv->dequeue_tasklet, octeon_usb_urb_dequeue_work, (unsigned long)priv);
703 INIT_LIST_HEAD(&priv->dequeue_list);
705 status = cvmx_usb_initialize(&priv->usb, usb_num, CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO);
707 dev_dbg(dev, "USB initialization failed with %d\n", status);
712 /* This delay is needed for CN3010, but I don't know why... */
715 spin_lock_irqsave(&priv->lock, flags);
716 cvmx_usb_poll(&priv->usb);
717 spin_unlock_irqrestore(&priv->lock, flags);
719 status = usb_add_hcd(hcd, irq, IRQF_SHARED);
721 dev_dbg(dev, "USB add HCD failed with %d\n", status);
726 dev_dbg(dev, "Registered HCD for port %d on irq %d\n", usb_num, irq);
731 static int octeon_usb_driver_remove(struct device *dev)
734 struct usb_hcd *hcd = dev_get_drvdata(dev);
735 struct octeon_hcd *priv = hcd_to_octeon(hcd);
739 tasklet_kill(&priv->dequeue_tasklet);
740 spin_lock_irqsave(&priv->lock, flags);
741 status = cvmx_usb_shutdown(&priv->usb);
742 spin_unlock_irqrestore(&priv->lock, flags);
744 dev_dbg(dev, "USB shutdown failed with %d\n", status);
751 static struct device_driver octeon_usb_driver = {
753 .bus = &platform_bus_type,
754 .probe = octeon_usb_driver_probe,
755 .remove = octeon_usb_driver_remove,
759 #define MAX_USB_PORTS 10
760 static struct platform_device *pdev_glob[MAX_USB_PORTS];
761 static int octeon_usb_registered;
762 static int __init octeon_usb_module_init(void)
764 int num_devices = cvmx_usb_get_num_ports();
767 if (usb_disabled() || num_devices == 0)
770 if (driver_register(&octeon_usb_driver))
773 octeon_usb_registered = 1;
776 * Only cn52XX and cn56XX have DWC_OTG USB hardware and the
777 * IOB priority registers. Under heavy network load USB
778 * hardware can be starved by the IOB causing a crash. Give
779 * it a priority boost if it has been waiting more than 400
780 * cycles to avoid this situation.
782 * Testing indicates that a cnt_val of 8192 is not sufficient,
783 * but no failures are seen with 4096. We choose a value of
784 * 400 to give a safety factor of 10.
786 if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN56XX)) {
787 union cvmx_iob_n2c_l2c_pri_cnt pri_cnt;
790 pri_cnt.s.cnt_enb = 1;
791 pri_cnt.s.cnt_val = 400;
792 cvmx_write_csr(CVMX_IOB_N2C_L2C_PRI_CNT, pri_cnt.u64);
795 for (device = 0; device < num_devices; device++) {
796 struct resource irq_resource;
797 struct platform_device *pdev;
798 memset(&irq_resource, 0, sizeof(irq_resource));
799 irq_resource.start = (device == 0) ? OCTEON_IRQ_USB0 : OCTEON_IRQ_USB1;
800 irq_resource.end = irq_resource.start;
801 irq_resource.flags = IORESOURCE_IRQ;
802 pdev = platform_device_register_simple((char *)octeon_usb_driver. name, device, &irq_resource, 1);
804 driver_unregister(&octeon_usb_driver);
805 octeon_usb_registered = 0;
806 return PTR_ERR(pdev);
808 if (device < MAX_USB_PORTS)
809 pdev_glob[device] = pdev;
815 static void __exit octeon_usb_module_cleanup(void)
819 for (i = 0; i < MAX_USB_PORTS; i++)
821 platform_device_unregister(pdev_glob[i]);
824 if (octeon_usb_registered)
825 driver_unregister(&octeon_usb_driver);
828 MODULE_LICENSE("GPL");
829 MODULE_AUTHOR("Cavium Networks <support@caviumnetworks.com>");
830 MODULE_DESCRIPTION("Cavium Networks Octeon USB Host driver.");
831 module_init(octeon_usb_module_init);
832 module_exit(octeon_usb_module_cleanup);