diff options
author | David Daney <david.daney@cavium.com> | 2014-02-03 12:39:01 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-02-07 12:11:28 -0500 |
commit | b91619c284e53fec09d502f29c1ad7ee4766e664 (patch) | |
tree | c2baa9259e656196c57e67b112e64af48324e0cc | |
parent | 1ea98e4c440eb497e1af1bce31cbba261b081a7b (diff) |
staging: octeon-usb: Probe via device tree populated platform device.
Extract clocking parameters from the device tree, and remove now dead
code and types.
Signed-off-by: David Daney <david.daney@cavium.com>
Tested-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/staging/octeon-usb/octeon-hcd.c | 273 |
1 files changed, 116 insertions, 157 deletions
diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index 47e0a91238a1..5a001d9b4252 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c | |||
@@ -275,13 +275,6 @@ enum cvmx_usb_pipe_flags { | |||
275 | */ | 275 | */ |
276 | #define MAX_TRANSFER_PACKETS ((1<<10)-1) | 276 | #define MAX_TRANSFER_PACKETS ((1<<10)-1) |
277 | 277 | ||
278 | enum { | ||
279 | USB_CLOCK_TYPE_REF_12, | ||
280 | USB_CLOCK_TYPE_REF_24, | ||
281 | USB_CLOCK_TYPE_REF_48, | ||
282 | USB_CLOCK_TYPE_CRYSTAL_12, | ||
283 | }; | ||
284 | |||
285 | /** | 278 | /** |
286 | * Logical transactions may take numerous low level | 279 | * Logical transactions may take numerous low level |
287 | * transactions, especially when splits are concerned. This | 280 | * transactions, especially when splits are concerned. This |
@@ -471,19 +464,6 @@ struct octeon_hcd { | |||
471 | /* Returns the IO address to push/pop stuff data from the FIFOs */ | 464 | /* Returns the IO address to push/pop stuff data from the FIFOs */ |
472 | #define USB_FIFO_ADDRESS(channel, usb_index) (CVMX_USBCX_GOTGCTL(usb_index) + ((channel)+1)*0x1000) | 465 | #define USB_FIFO_ADDRESS(channel, usb_index) (CVMX_USBCX_GOTGCTL(usb_index) + ((channel)+1)*0x1000) |
473 | 466 | ||
474 | static int octeon_usb_get_clock_type(void) | ||
475 | { | ||
476 | switch (cvmx_sysinfo_get()->board_type) { | ||
477 | case CVMX_BOARD_TYPE_BBGW_REF: | ||
478 | case CVMX_BOARD_TYPE_LANAI2_A: | ||
479 | case CVMX_BOARD_TYPE_LANAI2_U: | ||
480 | case CVMX_BOARD_TYPE_LANAI2_G: | ||
481 | case CVMX_BOARD_TYPE_UBNT_E100: | ||
482 | return USB_CLOCK_TYPE_CRYSTAL_12; | ||
483 | } | ||
484 | return USB_CLOCK_TYPE_REF_48; | ||
485 | } | ||
486 | |||
487 | /** | 467 | /** |
488 | * Read a USB 32bit CSR. It performs the necessary address swizzle | 468 | * Read a USB 32bit CSR. It performs the necessary address swizzle |
489 | * for 32bit CSRs and logs the value in a readable format if | 469 | * for 32bit CSRs and logs the value in a readable format if |
@@ -582,37 +562,6 @@ static inline int __cvmx_usb_get_data_pid(struct cvmx_usb_pipe *pipe) | |||
582 | return 0; /* Data0 */ | 562 | return 0; /* Data0 */ |
583 | } | 563 | } |
584 | 564 | ||
585 | |||
586 | /** | ||
587 | * Return the number of USB ports supported by this Octeon | ||
588 | * chip. If the chip doesn't support USB, or is not supported | ||
589 | * by this API, a zero will be returned. Most Octeon chips | ||
590 | * support one usb port, but some support two ports. | ||
591 | * cvmx_usb_initialize() must be called on independent | ||
592 | * struct cvmx_usb_state. | ||
593 | * | ||
594 | * Returns: Number of port, zero if usb isn't supported | ||
595 | */ | ||
596 | static int cvmx_usb_get_num_ports(void) | ||
597 | { | ||
598 | int arch_ports = 0; | ||
599 | |||
600 | if (OCTEON_IS_MODEL(OCTEON_CN56XX)) | ||
601 | arch_ports = 1; | ||
602 | else if (OCTEON_IS_MODEL(OCTEON_CN52XX)) | ||
603 | arch_ports = 2; | ||
604 | else if (OCTEON_IS_MODEL(OCTEON_CN50XX)) | ||
605 | arch_ports = 1; | ||
606 | else if (OCTEON_IS_MODEL(OCTEON_CN31XX)) | ||
607 | arch_ports = 1; | ||
608 | else if (OCTEON_IS_MODEL(OCTEON_CN30XX)) | ||
609 | arch_ports = 1; | ||
610 | else | ||
611 | arch_ports = 0; | ||
612 | |||
613 | return arch_ports; | ||
614 | } | ||
615 | |||
616 | /** | 565 | /** |
617 | * Initialize a USB port for use. This must be called before any | 566 | * Initialize a USB port for use. This must be called before any |
618 | * other access to the Octeon USB port is made. The port starts | 567 | * other access to the Octeon USB port is made. The port starts |
@@ -628,41 +577,16 @@ static int cvmx_usb_get_num_ports(void) | |||
628 | * Returns: 0 or a negative error code. | 577 | * Returns: 0 or a negative error code. |
629 | */ | 578 | */ |
630 | static int cvmx_usb_initialize(struct cvmx_usb_state *usb, | 579 | static int cvmx_usb_initialize(struct cvmx_usb_state *usb, |
631 | int usb_port_number) | 580 | int usb_port_number, |
581 | enum cvmx_usb_initialize_flags flags) | ||
632 | { | 582 | { |
633 | union cvmx_usbnx_clk_ctl usbn_clk_ctl; | 583 | union cvmx_usbnx_clk_ctl usbn_clk_ctl; |
634 | union cvmx_usbnx_usbp_ctl_status usbn_usbp_ctl_status; | 584 | union cvmx_usbnx_usbp_ctl_status usbn_usbp_ctl_status; |
635 | enum cvmx_usb_initialize_flags flags = 0; | ||
636 | int i; | 585 | int i; |
637 | 586 | ||
638 | /* At first allow 0-1 for the usb port number */ | 587 | /* At first allow 0-1 for the usb port number */ |
639 | if ((usb_port_number < 0) || (usb_port_number > 1)) | 588 | if ((usb_port_number < 0) || (usb_port_number > 1)) |
640 | return -EINVAL; | 589 | return -EINVAL; |
641 | /* For all chips except 52XX there is only one port */ | ||
642 | if (!OCTEON_IS_MODEL(OCTEON_CN52XX) && (usb_port_number > 0)) | ||
643 | return -EINVAL; | ||
644 | /* Try to determine clock type automatically */ | ||
645 | if (octeon_usb_get_clock_type() == USB_CLOCK_TYPE_CRYSTAL_12) { | ||
646 | /* Only 12 MHZ crystals are supported */ | ||
647 | flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI; | ||
648 | } else { | ||
649 | flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND; | ||
650 | |||
651 | switch (octeon_usb_get_clock_type()) { | ||
652 | case USB_CLOCK_TYPE_REF_12: | ||
653 | flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ; | ||
654 | break; | ||
655 | case USB_CLOCK_TYPE_REF_24: | ||
656 | flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ; | ||
657 | break; | ||
658 | case USB_CLOCK_TYPE_REF_48: | ||
659 | flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ; | ||
660 | break; | ||
661 | default: | ||
662 | return -EINVAL; | ||
663 | break; | ||
664 | } | ||
665 | } | ||
666 | 590 | ||
667 | memset(usb, 0, sizeof(*usb)); | 591 | memset(usb, 0, sizeof(*usb)); |
668 | usb->init_flags = flags; | 592 | usb->init_flags = flags; |
@@ -3431,7 +3355,6 @@ static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
3431 | return 0; | 3355 | return 0; |
3432 | } | 3356 | } |
3433 | 3357 | ||
3434 | |||
3435 | static const struct hc_driver octeon_hc_driver = { | 3358 | static const struct hc_driver octeon_hc_driver = { |
3436 | .description = "Octeon USB", | 3359 | .description = "Octeon USB", |
3437 | .product_desc = "Octeon Host Controller", | 3360 | .product_desc = "Octeon Host Controller", |
@@ -3448,15 +3371,74 @@ static const struct hc_driver octeon_hc_driver = { | |||
3448 | .hub_control = octeon_usb_hub_control, | 3371 | .hub_control = octeon_usb_hub_control, |
3449 | }; | 3372 | }; |
3450 | 3373 | ||
3451 | 3374 | static int octeon_usb_probe(struct platform_device *pdev) | |
3452 | static int octeon_usb_driver_probe(struct device *dev) | ||
3453 | { | 3375 | { |
3454 | int status; | 3376 | int status; |
3455 | int usb_num = to_platform_device(dev)->id; | 3377 | int initialize_flags; |
3456 | int irq = platform_get_irq(to_platform_device(dev), 0); | 3378 | int usb_num; |
3379 | struct resource *res_mem; | ||
3380 | struct device_node *usbn_node; | ||
3381 | int irq = platform_get_irq(pdev, 0); | ||
3382 | struct device *dev = &pdev->dev; | ||
3457 | struct octeon_hcd *priv; | 3383 | struct octeon_hcd *priv; |
3458 | struct usb_hcd *hcd; | 3384 | struct usb_hcd *hcd; |
3459 | unsigned long flags; | 3385 | unsigned long flags; |
3386 | u32 clock_rate = 48000000; | ||
3387 | bool is_crystal_clock = false; | ||
3388 | const char *clock_type; | ||
3389 | int i; | ||
3390 | |||
3391 | if (dev->of_node == NULL) { | ||
3392 | dev_err(dev, "Error: empty of_node\n"); | ||
3393 | return -ENXIO; | ||
3394 | } | ||
3395 | usbn_node = dev->of_node->parent; | ||
3396 | |||
3397 | i = of_property_read_u32(usbn_node, | ||
3398 | "refclk-frequency", &clock_rate); | ||
3399 | if (i) { | ||
3400 | dev_err(dev, "No USBN \"refclk-frequency\"\n"); | ||
3401 | return -ENXIO; | ||
3402 | } | ||
3403 | switch (clock_rate) { | ||
3404 | case 12000000: | ||
3405 | initialize_flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ; | ||
3406 | break; | ||
3407 | case 24000000: | ||
3408 | initialize_flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ; | ||
3409 | break; | ||
3410 | case 48000000: | ||
3411 | initialize_flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ; | ||
3412 | break; | ||
3413 | default: | ||
3414 | dev_err(dev, "Illebal USBN \"refclk-frequency\" %u\n", clock_rate); | ||
3415 | return -ENXIO; | ||
3416 | |||
3417 | } | ||
3418 | |||
3419 | i = of_property_read_string(usbn_node, | ||
3420 | "refclk-type", &clock_type); | ||
3421 | |||
3422 | if (!i && strcmp("crystal", clock_type) == 0) | ||
3423 | is_crystal_clock = true; | ||
3424 | |||
3425 | if (is_crystal_clock) | ||
3426 | initialize_flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI; | ||
3427 | else | ||
3428 | initialize_flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND; | ||
3429 | |||
3430 | res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
3431 | if (res_mem == NULL) { | ||
3432 | dev_err(dev, "found no memory resource\n"); | ||
3433 | return -ENXIO; | ||
3434 | } | ||
3435 | usb_num = (res_mem->start >> 44) & 1; | ||
3436 | |||
3437 | if (irq < 0) { | ||
3438 | /* Defective device tree, but we know how to fix it. */ | ||
3439 | irq_hw_number_t hwirq = usb_num ? (1 << 6) + 17 : 56; | ||
3440 | irq = irq_create_mapping(NULL, hwirq); | ||
3441 | } | ||
3460 | 3442 | ||
3461 | /* | 3443 | /* |
3462 | * Set the DMA mask to 64bits so we get buffers already translated for | 3444 | * Set the DMA mask to 64bits so we get buffers already translated for |
@@ -3465,6 +3447,26 @@ static int octeon_usb_driver_probe(struct device *dev) | |||
3465 | dev->coherent_dma_mask = ~0; | 3447 | dev->coherent_dma_mask = ~0; |
3466 | dev->dma_mask = &dev->coherent_dma_mask; | 3448 | dev->dma_mask = &dev->coherent_dma_mask; |
3467 | 3449 | ||
3450 | /* | ||
3451 | * Only cn52XX and cn56XX have DWC_OTG USB hardware and the | ||
3452 | * IOB priority registers. Under heavy network load USB | ||
3453 | * hardware can be starved by the IOB causing a crash. Give | ||
3454 | * it a priority boost if it has been waiting more than 400 | ||
3455 | * cycles to avoid this situation. | ||
3456 | * | ||
3457 | * Testing indicates that a cnt_val of 8192 is not sufficient, | ||
3458 | * but no failures are seen with 4096. We choose a value of | ||
3459 | * 400 to give a safety factor of 10. | ||
3460 | */ | ||
3461 | if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN56XX)) { | ||
3462 | union cvmx_iob_n2c_l2c_pri_cnt pri_cnt; | ||
3463 | |||
3464 | pri_cnt.u64 = 0; | ||
3465 | pri_cnt.s.cnt_enb = 1; | ||
3466 | pri_cnt.s.cnt_val = 400; | ||
3467 | cvmx_write_csr(CVMX_IOB_N2C_L2C_PRI_CNT, pri_cnt.u64); | ||
3468 | } | ||
3469 | |||
3468 | hcd = usb_create_hcd(&octeon_hc_driver, dev, dev_name(dev)); | 3470 | hcd = usb_create_hcd(&octeon_hc_driver, dev, dev_name(dev)); |
3469 | if (!hcd) { | 3471 | if (!hcd) { |
3470 | dev_dbg(dev, "Failed to allocate memory for HCD\n"); | 3472 | dev_dbg(dev, "Failed to allocate memory for HCD\n"); |
@@ -3478,7 +3480,7 @@ static int octeon_usb_driver_probe(struct device *dev) | |||
3478 | tasklet_init(&priv->dequeue_tasklet, octeon_usb_urb_dequeue_work, (unsigned long)priv); | 3480 | tasklet_init(&priv->dequeue_tasklet, octeon_usb_urb_dequeue_work, (unsigned long)priv); |
3479 | INIT_LIST_HEAD(&priv->dequeue_list); | 3481 | INIT_LIST_HEAD(&priv->dequeue_list); |
3480 | 3482 | ||
3481 | status = cvmx_usb_initialize(&priv->usb, usb_num); | 3483 | status = cvmx_usb_initialize(&priv->usb, usb_num, initialize_flags); |
3482 | if (status) { | 3484 | if (status) { |
3483 | dev_dbg(dev, "USB initialization failed with %d\n", status); | 3485 | dev_dbg(dev, "USB initialization failed with %d\n", status); |
3484 | kfree(hcd); | 3486 | kfree(hcd); |
@@ -3492,7 +3494,7 @@ static int octeon_usb_driver_probe(struct device *dev) | |||
3492 | cvmx_usb_poll(&priv->usb); | 3494 | cvmx_usb_poll(&priv->usb); |
3493 | spin_unlock_irqrestore(&priv->lock, flags); | 3495 | spin_unlock_irqrestore(&priv->lock, flags); |
3494 | 3496 | ||
3495 | status = usb_add_hcd(hcd, irq, IRQF_SHARED); | 3497 | status = usb_add_hcd(hcd, irq, 0); |
3496 | if (status) { | 3498 | if (status) { |
3497 | dev_dbg(dev, "USB add HCD failed with %d\n", status); | 3499 | dev_dbg(dev, "USB add HCD failed with %d\n", status); |
3498 | kfree(hcd); | 3500 | kfree(hcd); |
@@ -3500,14 +3502,15 @@ static int octeon_usb_driver_probe(struct device *dev) | |||
3500 | } | 3502 | } |
3501 | device_wakeup_enable(hcd->self.controller); | 3503 | device_wakeup_enable(hcd->self.controller); |
3502 | 3504 | ||
3503 | dev_dbg(dev, "Registered HCD for port %d on irq %d\n", usb_num, irq); | 3505 | dev_info(dev, "Registered HCD for port %d on irq %d\n", usb_num, irq); |
3504 | 3506 | ||
3505 | return 0; | 3507 | return 0; |
3506 | } | 3508 | } |
3507 | 3509 | ||
3508 | static int octeon_usb_driver_remove(struct device *dev) | 3510 | static int octeon_usb_remove(struct platform_device *pdev) |
3509 | { | 3511 | { |
3510 | int status; | 3512 | int status; |
3513 | struct device *dev = &pdev->dev; | ||
3511 | struct usb_hcd *hcd = dev_get_drvdata(dev); | 3514 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
3512 | struct octeon_hcd *priv = hcd_to_octeon(hcd); | 3515 | struct octeon_hcd *priv = hcd_to_octeon(hcd); |
3513 | unsigned long flags; | 3516 | unsigned long flags; |
@@ -3525,85 +3528,41 @@ static int octeon_usb_driver_remove(struct device *dev) | |||
3525 | return 0; | 3528 | return 0; |
3526 | } | 3529 | } |
3527 | 3530 | ||
3528 | static struct device_driver octeon_usb_driver = { | 3531 | static struct of_device_id octeon_usb_match[] = { |
3529 | .name = "OcteonUSB", | 3532 | { |
3530 | .bus = &platform_bus_type, | 3533 | .compatible = "cavium,octeon-5750-usbc", |
3531 | .probe = octeon_usb_driver_probe, | 3534 | }, |
3532 | .remove = octeon_usb_driver_remove, | 3535 | {}, |
3533 | }; | 3536 | }; |
3534 | 3537 | ||
3538 | static struct platform_driver octeon_usb_driver = { | ||
3539 | .driver = { | ||
3540 | .name = "OcteonUSB", | ||
3541 | .owner = THIS_MODULE, | ||
3542 | .of_match_table = octeon_usb_match, | ||
3543 | }, | ||
3544 | .probe = octeon_usb_probe, | ||
3545 | .remove = octeon_usb_remove, | ||
3546 | }; | ||
3535 | 3547 | ||
3536 | #define MAX_USB_PORTS 10 | 3548 | static int __init octeon_usb_driver_init(void) |
3537 | static struct platform_device *pdev_glob[MAX_USB_PORTS]; | ||
3538 | static int octeon_usb_registered; | ||
3539 | static int __init octeon_usb_module_init(void) | ||
3540 | { | 3549 | { |
3541 | int num_devices = cvmx_usb_get_num_ports(); | 3550 | if (usb_disabled()) |
3542 | int device; | 3551 | return 0; |
3543 | |||
3544 | if (usb_disabled() || num_devices == 0) | ||
3545 | return -ENODEV; | ||
3546 | |||
3547 | if (driver_register(&octeon_usb_driver)) | ||
3548 | return -ENOMEM; | ||
3549 | |||
3550 | octeon_usb_registered = 1; | ||
3551 | |||
3552 | /* | ||
3553 | * Only cn52XX and cn56XX have DWC_OTG USB hardware and the | ||
3554 | * IOB priority registers. Under heavy network load USB | ||
3555 | * hardware can be starved by the IOB causing a crash. Give | ||
3556 | * it a priority boost if it has been waiting more than 400 | ||
3557 | * cycles to avoid this situation. | ||
3558 | * | ||
3559 | * Testing indicates that a cnt_val of 8192 is not sufficient, | ||
3560 | * but no failures are seen with 4096. We choose a value of | ||
3561 | * 400 to give a safety factor of 10. | ||
3562 | */ | ||
3563 | if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN56XX)) { | ||
3564 | union cvmx_iob_n2c_l2c_pri_cnt pri_cnt; | ||
3565 | |||
3566 | pri_cnt.u64 = 0; | ||
3567 | pri_cnt.s.cnt_enb = 1; | ||
3568 | pri_cnt.s.cnt_val = 400; | ||
3569 | cvmx_write_csr(CVMX_IOB_N2C_L2C_PRI_CNT, pri_cnt.u64); | ||
3570 | } | ||
3571 | |||
3572 | for (device = 0; device < num_devices; device++) { | ||
3573 | struct resource irq_resource; | ||
3574 | struct platform_device *pdev; | ||
3575 | memset(&irq_resource, 0, sizeof(irq_resource)); | ||
3576 | irq_resource.start = (device == 0) ? OCTEON_IRQ_USB0 : OCTEON_IRQ_USB1; | ||
3577 | irq_resource.end = irq_resource.start; | ||
3578 | irq_resource.flags = IORESOURCE_IRQ; | ||
3579 | pdev = platform_device_register_simple((char *)octeon_usb_driver. name, device, &irq_resource, 1); | ||
3580 | if (IS_ERR(pdev)) { | ||
3581 | driver_unregister(&octeon_usb_driver); | ||
3582 | octeon_usb_registered = 0; | ||
3583 | return PTR_ERR(pdev); | ||
3584 | } | ||
3585 | if (device < MAX_USB_PORTS) | ||
3586 | pdev_glob[device] = pdev; | ||
3587 | 3552 | ||
3588 | } | 3553 | return platform_driver_register(&octeon_usb_driver); |
3589 | return 0; | ||
3590 | } | 3554 | } |
3555 | module_init(octeon_usb_driver_init); | ||
3591 | 3556 | ||
3592 | static void __exit octeon_usb_module_cleanup(void) | 3557 | static void __exit octeon_usb_driver_exit(void) |
3593 | { | 3558 | { |
3594 | int i; | 3559 | if (usb_disabled()) |
3560 | return; | ||
3595 | 3561 | ||
3596 | for (i = 0; i < MAX_USB_PORTS; i++) | 3562 | platform_driver_unregister(&octeon_usb_driver); |
3597 | if (pdev_glob[i]) { | ||
3598 | platform_device_unregister(pdev_glob[i]); | ||
3599 | pdev_glob[i] = NULL; | ||
3600 | } | ||
3601 | if (octeon_usb_registered) | ||
3602 | driver_unregister(&octeon_usb_driver); | ||
3603 | } | 3563 | } |
3564 | module_exit(octeon_usb_driver_exit); | ||
3604 | 3565 | ||
3605 | MODULE_LICENSE("GPL"); | 3566 | MODULE_LICENSE("GPL"); |
3606 | MODULE_AUTHOR("Cavium Networks <support@caviumnetworks.com>"); | 3567 | MODULE_AUTHOR("Cavium, Inc. <support@cavium.com>"); |
3607 | MODULE_DESCRIPTION("Cavium Networks Octeon USB Host driver."); | 3568 | MODULE_DESCRIPTION("Cavium Inc. OCTEON USB Host driver."); |
3608 | module_init(octeon_usb_module_init); | ||
3609 | module_exit(octeon_usb_module_cleanup); | ||