diff options
author | Roger Quadros <rogerq@ti.com> | 2012-11-08 10:40:25 -0500 |
---|---|---|
committer | Roger Quadros <rogerq@ti.com> | 2013-02-13 06:22:50 -0500 |
commit | 06ba7dc75fbf1ac731dd3ca08d5f95f552780cb2 (patch) | |
tree | 0a59374e909c2bde2ef204f72666f650605b31ab | |
parent | ccac71a7f063ad31eb99fac37e95b70ff57f1354 (diff) |
mfd: omap-usb-host: cleanup clock management code
All ports have similarly named port clocks so we can
bunch them into a port data structure and use for loop
to enable/disable the clocks.
Dynamically allocate and get clocks based on number of ports
available on the platform
Signed-off-by: Roger Quadros <rogerq@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
-rw-r--r-- | drivers/mfd/omap-usb-host.c | 186 |
1 files changed, 106 insertions, 80 deletions
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 779588be8ab2..9fa0215e3df4 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c | |||
@@ -92,13 +92,12 @@ | |||
92 | 92 | ||
93 | struct usbhs_hcd_omap { | 93 | struct usbhs_hcd_omap { |
94 | int nports; | 94 | int nports; |
95 | struct clk **utmi_clk; | ||
95 | 96 | ||
96 | struct clk *xclk60mhsp1_ck; | 97 | struct clk *xclk60mhsp1_ck; |
97 | struct clk *xclk60mhsp2_ck; | 98 | struct clk *xclk60mhsp2_ck; |
98 | struct clk *utmi_p1_fck; | 99 | struct clk *utmi_p1_gfclk; |
99 | struct clk *usbhost_p1_fck; | 100 | struct clk *utmi_p2_gfclk; |
100 | struct clk *utmi_p2_fck; | ||
101 | struct clk *usbhost_p2_fck; | ||
102 | struct clk *init_60m_fclk; | 101 | struct clk *init_60m_fclk; |
103 | struct clk *ehci_logic_fck; | 102 | struct clk *ehci_logic_fck; |
104 | 103 | ||
@@ -276,22 +275,25 @@ static int usbhs_runtime_resume(struct device *dev) | |||
276 | struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); | 275 | struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); |
277 | struct usbhs_omap_platform_data *pdata = omap->pdata; | 276 | struct usbhs_omap_platform_data *pdata = omap->pdata; |
278 | unsigned long flags; | 277 | unsigned long flags; |
278 | int i, r; | ||
279 | 279 | ||
280 | dev_dbg(dev, "usbhs_runtime_resume\n"); | 280 | dev_dbg(dev, "usbhs_runtime_resume\n"); |
281 | 281 | ||
282 | omap_tll_enable(); | 282 | omap_tll_enable(); |
283 | spin_lock_irqsave(&omap->lock, flags); | 283 | spin_lock_irqsave(&omap->lock, flags); |
284 | 284 | ||
285 | if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck)) | 285 | if (!IS_ERR(omap->ehci_logic_fck)) |
286 | clk_enable(omap->ehci_logic_fck); | 286 | clk_enable(omap->ehci_logic_fck); |
287 | 287 | ||
288 | if (is_ehci_tll_mode(pdata->port_mode[0])) | 288 | for (i = 0; i < omap->nports; i++) { |
289 | clk_enable(omap->usbhost_p1_fck); | 289 | if (!is_ehci_tll_mode(pdata->port_mode[i]) || |
290 | if (is_ehci_tll_mode(pdata->port_mode[1])) | 290 | IS_ERR(omap->utmi_clk[i])) |
291 | clk_enable(omap->usbhost_p2_fck); | 291 | continue; |
292 | 292 | ||
293 | clk_enable(omap->utmi_p1_fck); | 293 | r = clk_enable(omap->utmi_clk[i]); |
294 | clk_enable(omap->utmi_p2_fck); | 294 | if (r) |
295 | dev_err(dev, "Can't enable port %d clk : %d\n", i, r); | ||
296 | } | ||
295 | 297 | ||
296 | spin_unlock_irqrestore(&omap->lock, flags); | 298 | spin_unlock_irqrestore(&omap->lock, flags); |
297 | 299 | ||
@@ -303,20 +305,19 @@ static int usbhs_runtime_suspend(struct device *dev) | |||
303 | struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); | 305 | struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); |
304 | struct usbhs_omap_platform_data *pdata = omap->pdata; | 306 | struct usbhs_omap_platform_data *pdata = omap->pdata; |
305 | unsigned long flags; | 307 | unsigned long flags; |
308 | int i; | ||
306 | 309 | ||
307 | dev_dbg(dev, "usbhs_runtime_suspend\n"); | 310 | dev_dbg(dev, "usbhs_runtime_suspend\n"); |
308 | 311 | ||
309 | spin_lock_irqsave(&omap->lock, flags); | 312 | spin_lock_irqsave(&omap->lock, flags); |
310 | 313 | ||
311 | if (is_ehci_tll_mode(pdata->port_mode[0])) | 314 | for (i = 0; i < omap->nports; i++) { |
312 | clk_disable(omap->usbhost_p1_fck); | 315 | if (is_ehci_tll_mode(pdata->port_mode[i]) && |
313 | if (is_ehci_tll_mode(pdata->port_mode[1])) | 316 | !IS_ERR(omap->utmi_clk[i])) |
314 | clk_disable(omap->usbhost_p2_fck); | 317 | clk_disable(omap->utmi_clk[i]); |
315 | 318 | } | |
316 | clk_disable(omap->utmi_p2_fck); | ||
317 | clk_disable(omap->utmi_p1_fck); | ||
318 | 319 | ||
319 | if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck)) | 320 | if (!IS_ERR(omap->ehci_logic_fck)) |
320 | clk_disable(omap->ehci_logic_fck); | 321 | clk_disable(omap->ehci_logic_fck); |
321 | 322 | ||
322 | spin_unlock_irqrestore(&omap->lock, flags); | 323 | spin_unlock_irqrestore(&omap->lock, flags); |
@@ -458,6 +459,7 @@ static int usbhs_omap_probe(struct platform_device *pdev) | |||
458 | struct resource *res; | 459 | struct resource *res; |
459 | int ret = 0; | 460 | int ret = 0; |
460 | int i; | 461 | int i; |
462 | bool need_logic_fck; | ||
461 | 463 | ||
462 | if (!pdata) { | 464 | if (!pdata) { |
463 | dev_err(dev, "Missing platform data\n"); | 465 | dev_err(dev, "Missing platform data\n"); |
@@ -516,76 +518,91 @@ static int usbhs_omap_probe(struct platform_device *pdev) | |||
516 | } | 518 | } |
517 | } | 519 | } |
518 | 520 | ||
519 | for (i = 0; i < omap->nports; i++) | 521 | i = sizeof(struct clk *) * omap->nports; |
522 | omap->utmi_clk = devm_kzalloc(dev, i, GFP_KERNEL); | ||
523 | if (!omap->utmi_clk) { | ||
524 | dev_err(dev, "Memory allocation failed\n"); | ||
525 | ret = -ENOMEM; | ||
526 | goto err_mem; | ||
527 | } | ||
528 | |||
529 | need_logic_fck = false; | ||
530 | for (i = 0; i < omap->nports; i++) { | ||
520 | if (is_ehci_phy_mode(i) || is_ehci_tll_mode(i) || | 531 | if (is_ehci_phy_mode(i) || is_ehci_tll_mode(i) || |
521 | is_ehci_hsic_mode(i)) { | 532 | is_ehci_hsic_mode(i)) |
522 | omap->ehci_logic_fck = clk_get(dev, "ehci_logic_fck"); | 533 | need_logic_fck |= true; |
523 | if (IS_ERR(omap->ehci_logic_fck)) { | 534 | } |
524 | ret = PTR_ERR(omap->ehci_logic_fck); | 535 | |
525 | dev_warn(dev, "ehci_logic_fck failed:%d\n", | 536 | omap->ehci_logic_fck = ERR_PTR(-EINVAL); |
526 | ret); | 537 | if (need_logic_fck) { |
527 | } | 538 | omap->ehci_logic_fck = clk_get(dev, "ehci_logic_fck"); |
528 | break; | 539 | if (IS_ERR(omap->ehci_logic_fck)) { |
540 | ret = PTR_ERR(omap->ehci_logic_fck); | ||
541 | dev_dbg(dev, "ehci_logic_fck failed:%d\n", ret); | ||
529 | } | 542 | } |
543 | } | ||
530 | 544 | ||
531 | omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); | 545 | omap->utmi_p1_gfclk = clk_get(dev, "utmi_p1_gfclk"); |
532 | if (IS_ERR(omap->utmi_p1_fck)) { | 546 | if (IS_ERR(omap->utmi_p1_gfclk)) { |
533 | ret = PTR_ERR(omap->utmi_p1_fck); | 547 | ret = PTR_ERR(omap->utmi_p1_gfclk); |
534 | dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); | 548 | dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); |
535 | goto err_end; | 549 | goto err_p1_gfclk; |
550 | } | ||
551 | |||
552 | omap->utmi_p2_gfclk = clk_get(dev, "utmi_p2_gfclk"); | ||
553 | if (IS_ERR(omap->utmi_p2_gfclk)) { | ||
554 | ret = PTR_ERR(omap->utmi_p2_gfclk); | ||
555 | dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret); | ||
556 | goto err_p2_gfclk; | ||
536 | } | 557 | } |
537 | 558 | ||
538 | omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); | 559 | omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); |
539 | if (IS_ERR(omap->xclk60mhsp1_ck)) { | 560 | if (IS_ERR(omap->xclk60mhsp1_ck)) { |
540 | ret = PTR_ERR(omap->xclk60mhsp1_ck); | 561 | ret = PTR_ERR(omap->xclk60mhsp1_ck); |
541 | dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret); | 562 | dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret); |
542 | goto err_utmi_p1_fck; | 563 | goto err_xclk60mhsp1; |
543 | } | ||
544 | |||
545 | omap->utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk"); | ||
546 | if (IS_ERR(omap->utmi_p2_fck)) { | ||
547 | ret = PTR_ERR(omap->utmi_p2_fck); | ||
548 | dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret); | ||
549 | goto err_xclk60mhsp1_ck; | ||
550 | } | 564 | } |
551 | 565 | ||
552 | omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck"); | 566 | omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck"); |
553 | if (IS_ERR(omap->xclk60mhsp2_ck)) { | 567 | if (IS_ERR(omap->xclk60mhsp2_ck)) { |
554 | ret = PTR_ERR(omap->xclk60mhsp2_ck); | 568 | ret = PTR_ERR(omap->xclk60mhsp2_ck); |
555 | dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret); | 569 | dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret); |
556 | goto err_utmi_p2_fck; | 570 | goto err_xclk60mhsp2; |
557 | } | ||
558 | |||
559 | omap->usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk"); | ||
560 | if (IS_ERR(omap->usbhost_p1_fck)) { | ||
561 | ret = PTR_ERR(omap->usbhost_p1_fck); | ||
562 | dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret); | ||
563 | goto err_xclk60mhsp2_ck; | ||
564 | } | ||
565 | |||
566 | omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk"); | ||
567 | if (IS_ERR(omap->usbhost_p2_fck)) { | ||
568 | ret = PTR_ERR(omap->usbhost_p2_fck); | ||
569 | dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret); | ||
570 | goto err_usbhost_p1_fck; | ||
571 | } | 571 | } |
572 | 572 | ||
573 | omap->init_60m_fclk = clk_get(dev, "init_60m_fclk"); | 573 | omap->init_60m_fclk = clk_get(dev, "init_60m_fclk"); |
574 | if (IS_ERR(omap->init_60m_fclk)) { | 574 | if (IS_ERR(omap->init_60m_fclk)) { |
575 | ret = PTR_ERR(omap->init_60m_fclk); | 575 | ret = PTR_ERR(omap->init_60m_fclk); |
576 | dev_err(dev, "init_60m_fclk failed error:%d\n", ret); | 576 | dev_err(dev, "init_60m_fclk failed error:%d\n", ret); |
577 | goto err_usbhost_p2_fck; | 577 | goto err_init60m; |
578 | } | ||
579 | |||
580 | for (i = 0; i < omap->nports; i++) { | ||
581 | char clkname[] = "usb_host_hs_utmi_px_clk"; | ||
582 | |||
583 | /* clock names are indexed from 1*/ | ||
584 | snprintf(clkname, sizeof(clkname), | ||
585 | "usb_host_hs_utmi_p%d_clk", i + 1); | ||
586 | |||
587 | /* If a clock is not found we won't bail out as not all | ||
588 | * platforms have all clocks and we can function without | ||
589 | * them | ||
590 | */ | ||
591 | omap->utmi_clk[i] = clk_get(dev, clkname); | ||
592 | if (IS_ERR(omap->utmi_clk[i])) | ||
593 | dev_dbg(dev, "Failed to get clock : %s : %ld\n", | ||
594 | clkname, PTR_ERR(omap->utmi_clk[i])); | ||
578 | } | 595 | } |
579 | 596 | ||
580 | if (is_ehci_phy_mode(pdata->port_mode[0])) { | 597 | if (is_ehci_phy_mode(pdata->port_mode[0])) { |
581 | /* for OMAP3 , the clk set paretn fails */ | 598 | /* for OMAP3 , the clk set paretn fails */ |
582 | ret = clk_set_parent(omap->utmi_p1_fck, | 599 | ret = clk_set_parent(omap->utmi_p1_gfclk, |
583 | omap->xclk60mhsp1_ck); | 600 | omap->xclk60mhsp1_ck); |
584 | if (ret != 0) | 601 | if (ret != 0) |
585 | dev_err(dev, "xclk60mhsp1_ck set parent" | 602 | dev_err(dev, "xclk60mhsp1_ck set parent" |
586 | "failed error:%d\n", ret); | 603 | "failed error:%d\n", ret); |
587 | } else if (is_ehci_tll_mode(pdata->port_mode[0])) { | 604 | } else if (is_ehci_tll_mode(pdata->port_mode[0])) { |
588 | ret = clk_set_parent(omap->utmi_p1_fck, | 605 | ret = clk_set_parent(omap->utmi_p1_gfclk, |
589 | omap->init_60m_fclk); | 606 | omap->init_60m_fclk); |
590 | if (ret != 0) | 607 | if (ret != 0) |
591 | dev_err(dev, "init_60m_fclk set parent" | 608 | dev_err(dev, "init_60m_fclk set parent" |
@@ -593,13 +610,13 @@ static int usbhs_omap_probe(struct platform_device *pdev) | |||
593 | } | 610 | } |
594 | 611 | ||
595 | if (is_ehci_phy_mode(pdata->port_mode[1])) { | 612 | if (is_ehci_phy_mode(pdata->port_mode[1])) { |
596 | ret = clk_set_parent(omap->utmi_p2_fck, | 613 | ret = clk_set_parent(omap->utmi_p2_gfclk, |
597 | omap->xclk60mhsp2_ck); | 614 | omap->xclk60mhsp2_ck); |
598 | if (ret != 0) | 615 | if (ret != 0) |
599 | dev_err(dev, "xclk60mhsp2_ck set parent" | 616 | dev_err(dev, "xclk60mhsp2_ck set parent" |
600 | "failed error:%d\n", ret); | 617 | "failed error:%d\n", ret); |
601 | } else if (is_ehci_tll_mode(pdata->port_mode[1])) { | 618 | } else if (is_ehci_tll_mode(pdata->port_mode[1])) { |
602 | ret = clk_set_parent(omap->utmi_p2_fck, | 619 | ret = clk_set_parent(omap->utmi_p2_gfclk, |
603 | omap->init_60m_fclk); | 620 | omap->init_60m_fclk); |
604 | if (ret != 0) | 621 | if (ret != 0) |
605 | dev_err(dev, "init_60m_fclk set parent" | 622 | dev_err(dev, "init_60m_fclk set parent" |
@@ -617,28 +634,30 @@ static int usbhs_omap_probe(struct platform_device *pdev) | |||
617 | 634 | ||
618 | err_alloc: | 635 | err_alloc: |
619 | omap_usbhs_deinit(&pdev->dev); | 636 | omap_usbhs_deinit(&pdev->dev); |
620 | clk_put(omap->init_60m_fclk); | ||
621 | 637 | ||
622 | err_usbhost_p2_fck: | 638 | for (i = 0; i < omap->nports; i++) |
623 | clk_put(omap->usbhost_p2_fck); | 639 | if (!IS_ERR(omap->utmi_clk[i])) |
640 | clk_put(omap->utmi_clk[i]); | ||
624 | 641 | ||
625 | err_usbhost_p1_fck: | 642 | clk_put(omap->init_60m_fclk); |
626 | clk_put(omap->usbhost_p1_fck); | ||
627 | 643 | ||
628 | err_xclk60mhsp2_ck: | 644 | err_init60m: |
629 | clk_put(omap->xclk60mhsp2_ck); | 645 | clk_put(omap->xclk60mhsp2_ck); |
630 | 646 | ||
631 | err_utmi_p2_fck: | 647 | err_xclk60mhsp2: |
632 | clk_put(omap->utmi_p2_fck); | ||
633 | |||
634 | err_xclk60mhsp1_ck: | ||
635 | clk_put(omap->xclk60mhsp1_ck); | 648 | clk_put(omap->xclk60mhsp1_ck); |
636 | 649 | ||
637 | err_utmi_p1_fck: | 650 | err_xclk60mhsp1: |
638 | clk_put(omap->utmi_p1_fck); | 651 | clk_put(omap->utmi_p2_gfclk); |
639 | 652 | ||
640 | err_end: | 653 | err_p2_gfclk: |
641 | clk_put(omap->ehci_logic_fck); | 654 | clk_put(omap->utmi_p1_gfclk); |
655 | |||
656 | err_p1_gfclk: | ||
657 | if (!IS_ERR(omap->ehci_logic_fck)) | ||
658 | clk_put(omap->ehci_logic_fck); | ||
659 | |||
660 | err_mem: | ||
642 | pm_runtime_disable(dev); | 661 | pm_runtime_disable(dev); |
643 | 662 | ||
644 | return ret; | 663 | return ret; |
@@ -653,16 +672,23 @@ err_end: | |||
653 | static int usbhs_omap_remove(struct platform_device *pdev) | 672 | static int usbhs_omap_remove(struct platform_device *pdev) |
654 | { | 673 | { |
655 | struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev); | 674 | struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev); |
675 | int i; | ||
656 | 676 | ||
657 | omap_usbhs_deinit(&pdev->dev); | 677 | omap_usbhs_deinit(&pdev->dev); |
678 | |||
679 | for (i = 0; i < omap->nports; i++) | ||
680 | if (!IS_ERR(omap->utmi_clk[i])) | ||
681 | clk_put(omap->utmi_clk[i]); | ||
682 | |||
658 | clk_put(omap->init_60m_fclk); | 683 | clk_put(omap->init_60m_fclk); |
659 | clk_put(omap->usbhost_p2_fck); | 684 | clk_put(omap->utmi_p1_gfclk); |
660 | clk_put(omap->usbhost_p1_fck); | 685 | clk_put(omap->utmi_p2_gfclk); |
661 | clk_put(omap->xclk60mhsp2_ck); | 686 | clk_put(omap->xclk60mhsp2_ck); |
662 | clk_put(omap->utmi_p2_fck); | ||
663 | clk_put(omap->xclk60mhsp1_ck); | 687 | clk_put(omap->xclk60mhsp1_ck); |
664 | clk_put(omap->utmi_p1_fck); | 688 | |
665 | clk_put(omap->ehci_logic_fck); | 689 | if (!IS_ERR(omap->ehci_logic_fck)) |
690 | clk_put(omap->ehci_logic_fck); | ||
691 | |||
666 | pm_runtime_disable(&pdev->dev); | 692 | pm_runtime_disable(&pdev->dev); |
667 | 693 | ||
668 | return 0; | 694 | return 0; |