aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/chipidea/core.c
diff options
context:
space:
mode:
authorAntoine Tenart <antoine.tenart@free-electrons.com>2014-10-30 13:41:19 -0400
committerFelipe Balbi <balbi@ti.com>2014-11-03 11:03:30 -0500
commit1e5e2d3d055436c114e2f16145b83339aed024ff (patch)
tree821eaf3301ecdd322abe8b50e32bad7825c18c73 /drivers/usb/chipidea/core.c
parentef44cb4226d132146e44f8ea562a16b27ff61126 (diff)
usb: chipidea: add support to the generic PHY framework
This patch adds support of the PHY framework for ChipIdea drivers. Changes are done in both the ChipIdea common code and in the drivers accessing the PHY. This is done by adding a new PHY member in ChipIdea's structures and by taking care of it in the code. Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com> Acked-by: Peter Chen <peter.chen@freescale.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/chipidea/core.c')
-rw-r--r--drivers/usb/chipidea/core.c83
1 files changed, 65 insertions, 18 deletions
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 30f89426bf05..60578d9c896d 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -47,6 +47,7 @@
47#include <linux/delay.h> 47#include <linux/delay.h>
48#include <linux/device.h> 48#include <linux/device.h>
49#include <linux/dma-mapping.h> 49#include <linux/dma-mapping.h>
50#include <linux/phy/phy.h>
50#include <linux/platform_device.h> 51#include <linux/platform_device.h>
51#include <linux/module.h> 52#include <linux/module.h>
52#include <linux/idr.h> 53#include <linux/idr.h>
@@ -299,6 +300,49 @@ static void hw_phymode_configure(struct ci_hdrc *ci)
299} 300}
300 301
301/** 302/**
303 * _ci_usb_phy_init: initialize phy taking in account both phy and usb_phy
304 * interfaces
305 * @ci: the controller
306 *
307 * This function returns an error code if the phy failed to init
308 */
309static int _ci_usb_phy_init(struct ci_hdrc *ci)
310{
311 int ret;
312
313 if (ci->phy) {
314 ret = phy_init(ci->phy);
315 if (ret)
316 return ret;
317
318 ret = phy_power_on(ci->phy);
319 if (ret) {
320 phy_exit(ci->phy);
321 return ret;
322 }
323 } else {
324 ret = usb_phy_init(ci->usb_phy);
325 }
326
327 return ret;
328}
329
330/**
331 * _ci_usb_phy_exit: deinitialize phy taking in account both phy and usb_phy
332 * interfaces
333 * @ci: the controller
334 */
335static void ci_usb_phy_exit(struct ci_hdrc *ci)
336{
337 if (ci->phy) {
338 phy_power_off(ci->phy);
339 phy_exit(ci->phy);
340 } else {
341 usb_phy_shutdown(ci->usb_phy);
342 }
343}
344
345/**
302 * ci_usb_phy_init: initialize phy according to different phy type 346 * ci_usb_phy_init: initialize phy according to different phy type
303 * @ci: the controller 347 * @ci: the controller
304 * 348 *
@@ -312,7 +356,7 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
312 case USBPHY_INTERFACE_MODE_UTMI: 356 case USBPHY_INTERFACE_MODE_UTMI:
313 case USBPHY_INTERFACE_MODE_UTMIW: 357 case USBPHY_INTERFACE_MODE_UTMIW:
314 case USBPHY_INTERFACE_MODE_HSIC: 358 case USBPHY_INTERFACE_MODE_HSIC:
315 ret = usb_phy_init(ci->usb_phy); 359 ret = _ci_usb_phy_init(ci);
316 if (ret) 360 if (ret)
317 return ret; 361 return ret;
318 hw_phymode_configure(ci); 362 hw_phymode_configure(ci);
@@ -320,12 +364,12 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
320 case USBPHY_INTERFACE_MODE_ULPI: 364 case USBPHY_INTERFACE_MODE_ULPI:
321 case USBPHY_INTERFACE_MODE_SERIAL: 365 case USBPHY_INTERFACE_MODE_SERIAL:
322 hw_phymode_configure(ci); 366 hw_phymode_configure(ci);
323 ret = usb_phy_init(ci->usb_phy); 367 ret = _ci_usb_phy_init(ci);
324 if (ret) 368 if (ret)
325 return ret; 369 return ret;
326 break; 370 break;
327 default: 371 default:
328 ret = usb_phy_init(ci->usb_phy); 372 ret = _ci_usb_phy_init(ci);
329 } 373 }
330 374
331 return ret; 375 return ret;
@@ -605,23 +649,26 @@ static int ci_hdrc_probe(struct platform_device *pdev)
605 return -ENODEV; 649 return -ENODEV;
606 } 650 }
607 651
608 if (ci->platdata->usb_phy) 652 if (ci->platdata->phy) {
653 ci->phy = ci->platdata->phy;
654 } else if (ci->platdata->usb_phy) {
609 ci->usb_phy = ci->platdata->usb_phy; 655 ci->usb_phy = ci->platdata->usb_phy;
610 else 656 } else {
657 ci->phy = devm_phy_get(dev, "usb-phy");
611 ci->usb_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 658 ci->usb_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
612 659
613 if (IS_ERR(ci->usb_phy)) { 660 /* if both generic PHY and USB PHY layers aren't enabled */
614 ret = PTR_ERR(ci->usb_phy); 661 if (PTR_ERR(ci->phy) == -ENOSYS &&
615 /* 662 PTR_ERR(ci->usb_phy) == -ENXIO)
616 * if -ENXIO is returned, it means PHY layer wasn't 663 return -ENXIO;
617 * enabled, so it makes no sense to return -EPROBE_DEFER 664
618 * in that case, since no PHY driver will ever probe. 665 if (IS_ERR(ci->phy) && IS_ERR(ci->usb_phy))
619 */ 666 return -EPROBE_DEFER;
620 if (ret == -ENXIO)
621 return ret;
622 667
623 dev_err(dev, "no usb2 phy configured\n"); 668 if (IS_ERR(ci->phy))
624 return -EPROBE_DEFER; 669 ci->phy = NULL;
670 else if (IS_ERR(ci->usb_phy))
671 ci->usb_phy = NULL;
625 } 672 }
626 673
627 ret = ci_usb_phy_init(ci); 674 ret = ci_usb_phy_init(ci);
@@ -728,7 +775,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
728stop: 775stop:
729 ci_role_destroy(ci); 776 ci_role_destroy(ci);
730deinit_phy: 777deinit_phy:
731 usb_phy_shutdown(ci->usb_phy); 778 ci_usb_phy_exit(ci);
732 779
733 return ret; 780 return ret;
734} 781}
@@ -741,7 +788,7 @@ static int ci_hdrc_remove(struct platform_device *pdev)
741 free_irq(ci->irq, ci); 788 free_irq(ci->irq, ci);
742 ci_role_destroy(ci); 789 ci_role_destroy(ci);
743 ci_hdrc_enter_lpm(ci, true); 790 ci_hdrc_enter_lpm(ci, true);
744 usb_phy_shutdown(ci->usb_phy); 791 ci_usb_phy_exit(ci);
745 792
746 return 0; 793 return 0;
747} 794}