forked from mirrors/linux
		
	usb: chipidea: move PHY operation to core
PHY operations are common, so move them to core. Signed-off-by: Peter Chen <peter.chen@freescale.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									df9b17f586
								
							
						
					
					
						commit
						74475ede78
					
				
					 2 changed files with 52 additions and 44 deletions
				
			
		| 
						 | 
					@ -474,6 +474,33 @@ static void ci_get_otg_capable(struct ci_hdrc *ci)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ci_usb_phy_init(struct ci_hdrc *ci)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (ci->platdata->phy) {
 | 
				
			||||||
 | 
							ci->transceiver = ci->platdata->phy;
 | 
				
			||||||
 | 
							return usb_phy_init(ci->transceiver);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							ci->global_phy = true;
 | 
				
			||||||
 | 
							ci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 | 
				
			||||||
 | 
							if (IS_ERR(ci->transceiver))
 | 
				
			||||||
 | 
								ci->transceiver = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void ci_usb_phy_destroy(struct ci_hdrc *ci)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!ci->transceiver)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						otg_set_peripheral(ci->transceiver->otg, NULL);
 | 
				
			||||||
 | 
						if (ci->global_phy)
 | 
				
			||||||
 | 
							usb_put_phy(ci->transceiver);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							usb_phy_shutdown(ci->transceiver);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ci_hdrc_probe(struct platform_device *pdev)
 | 
					static int ci_hdrc_probe(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct device	*dev = &pdev->dev;
 | 
						struct device	*dev = &pdev->dev;
 | 
				
			||||||
| 
						 | 
					@ -501,10 +528,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ci->dev = dev;
 | 
						ci->dev = dev;
 | 
				
			||||||
	ci->platdata = dev->platform_data;
 | 
						ci->platdata = dev->platform_data;
 | 
				
			||||||
	if (ci->platdata->phy)
 | 
					 | 
				
			||||||
		ci->transceiver = ci->platdata->phy;
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		ci->global_phy = true;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = hw_device_init(ci, base);
 | 
						ret = hw_device_init(ci, base);
 | 
				
			||||||
	if (ret < 0) {
 | 
						if (ret < 0) {
 | 
				
			||||||
| 
						 | 
					@ -512,12 +535,19 @@ static int ci_hdrc_probe(struct platform_device *pdev)
 | 
				
			||||||
		return -ENODEV;
 | 
							return -ENODEV;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = ci_usb_phy_init(ci);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							dev_err(dev, "unable to init phy: %d\n", ret);
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ci->hw_bank.phys = res->start;
 | 
						ci->hw_bank.phys = res->start;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ci->irq = platform_get_irq(pdev, 0);
 | 
						ci->irq = platform_get_irq(pdev, 0);
 | 
				
			||||||
	if (ci->irq < 0) {
 | 
						if (ci->irq < 0) {
 | 
				
			||||||
		dev_err(dev, "missing IRQ\n");
 | 
							dev_err(dev, "missing IRQ\n");
 | 
				
			||||||
		return -ENODEV;
 | 
							ret = -ENODEV;
 | 
				
			||||||
 | 
							goto destroy_phy;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ci_get_otg_capable(ci);
 | 
						ci_get_otg_capable(ci);
 | 
				
			||||||
| 
						 | 
					@ -536,11 +566,23 @@ static int ci_hdrc_probe(struct platform_device *pdev)
 | 
				
			||||||
		ret = ci_hdrc_gadget_init(ci);
 | 
							ret = ci_hdrc_gadget_init(ci);
 | 
				
			||||||
		if (ret)
 | 
							if (ret)
 | 
				
			||||||
			dev_info(dev, "doesn't support gadget\n");
 | 
								dev_info(dev, "doesn't support gadget\n");
 | 
				
			||||||
 | 
							if (!ret && ci->transceiver) {
 | 
				
			||||||
 | 
								ret = otg_set_peripheral(ci->transceiver->otg,
 | 
				
			||||||
 | 
												&ci->gadget);
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * If we implement all USB functions using chipidea drivers,
 | 
				
			||||||
 | 
								 * it doesn't need to call above API, meanwhile, if we only
 | 
				
			||||||
 | 
								 * use gadget function, calling above API is useless.
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								if (ret && ret != -ENOTSUPP)
 | 
				
			||||||
 | 
									goto destroy_phy;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) {
 | 
						if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) {
 | 
				
			||||||
		dev_err(dev, "no supported roles\n");
 | 
							dev_err(dev, "no supported roles\n");
 | 
				
			||||||
		return -ENODEV;
 | 
							ret = -ENODEV;
 | 
				
			||||||
 | 
							goto destroy_phy;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ci->is_otg) {
 | 
						if (ci->is_otg) {
 | 
				
			||||||
| 
						 | 
					@ -593,6 +635,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
 | 
				
			||||||
	free_irq(ci->irq, ci);
 | 
						free_irq(ci->irq, ci);
 | 
				
			||||||
stop:
 | 
					stop:
 | 
				
			||||||
	ci_role_destroy(ci);
 | 
						ci_role_destroy(ci);
 | 
				
			||||||
 | 
					destroy_phy:
 | 
				
			||||||
 | 
						ci_usb_phy_destroy(ci);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -604,6 +648,7 @@ static int ci_hdrc_remove(struct platform_device *pdev)
 | 
				
			||||||
	dbg_remove_files(ci);
 | 
						dbg_remove_files(ci);
 | 
				
			||||||
	free_irq(ci->irq, ci);
 | 
						free_irq(ci->irq, ci);
 | 
				
			||||||
	ci_role_destroy(ci);
 | 
						ci_role_destroy(ci);
 | 
				
			||||||
 | 
						ci_usb_phy_destroy(ci);
 | 
				
			||||||
	kfree(ci->hw_bank.regmap);
 | 
						kfree(ci->hw_bank.regmap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,6 @@
 | 
				
			||||||
#include <linux/pm_runtime.h>
 | 
					#include <linux/pm_runtime.h>
 | 
				
			||||||
#include <linux/usb/ch9.h>
 | 
					#include <linux/usb/ch9.h>
 | 
				
			||||||
#include <linux/usb/gadget.h>
 | 
					#include <linux/usb/gadget.h>
 | 
				
			||||||
#include <linux/usb/otg.h>
 | 
					 | 
				
			||||||
#include <linux/usb/chipidea.h>
 | 
					#include <linux/usb/chipidea.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "ci.h"
 | 
					#include "ci.h"
 | 
				
			||||||
| 
						 | 
					@ -1790,34 +1789,9 @@ static int udc_start(struct ci_hdrc *ci)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ci->gadget.ep0 = &ci->ep0in->ep;
 | 
						ci->gadget.ep0 = &ci->ep0in->ep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ci->global_phy) {
 | 
					 | 
				
			||||||
		ci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 | 
					 | 
				
			||||||
		if (IS_ERR(ci->transceiver))
 | 
					 | 
				
			||||||
			ci->transceiver = NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (ci->platdata->flags & CI_HDRC_REQUIRE_TRANSCEIVER) {
 | 
					 | 
				
			||||||
		if (ci->transceiver == NULL) {
 | 
					 | 
				
			||||||
			retval = -ENODEV;
 | 
					 | 
				
			||||||
			goto destroy_eps;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (ci->transceiver) {
 | 
					 | 
				
			||||||
		retval = otg_set_peripheral(ci->transceiver->otg,
 | 
					 | 
				
			||||||
						&ci->gadget);
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * If we implement all USB functions using chipidea drivers,
 | 
					 | 
				
			||||||
		 * it doesn't need to call above API, meanwhile, if we only
 | 
					 | 
				
			||||||
		 * use gadget function, calling above API is useless.
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		if (retval && retval != -ENOTSUPP)
 | 
					 | 
				
			||||||
			goto put_transceiver;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	retval = usb_add_gadget_udc(dev, &ci->gadget);
 | 
						retval = usb_add_gadget_udc(dev, &ci->gadget);
 | 
				
			||||||
	if (retval)
 | 
						if (retval)
 | 
				
			||||||
		goto remove_trans;
 | 
							goto destroy_eps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pm_runtime_no_callbacks(&ci->gadget.dev);
 | 
						pm_runtime_no_callbacks(&ci->gadget.dev);
 | 
				
			||||||
	pm_runtime_enable(&ci->gadget.dev);
 | 
						pm_runtime_enable(&ci->gadget.dev);
 | 
				
			||||||
| 
						 | 
					@ -1827,17 +1801,6 @@ static int udc_start(struct ci_hdrc *ci)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return retval;
 | 
						return retval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
remove_trans:
 | 
					 | 
				
			||||||
	if (ci->transceiver) {
 | 
					 | 
				
			||||||
		otg_set_peripheral(ci->transceiver->otg, NULL);
 | 
					 | 
				
			||||||
		if (ci->global_phy)
 | 
					 | 
				
			||||||
			usb_put_phy(ci->transceiver);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dev_err(dev, "error = %i\n", retval);
 | 
					 | 
				
			||||||
put_transceiver:
 | 
					 | 
				
			||||||
	if (ci->transceiver && ci->global_phy)
 | 
					 | 
				
			||||||
		usb_put_phy(ci->transceiver);
 | 
					 | 
				
			||||||
destroy_eps:
 | 
					destroy_eps:
 | 
				
			||||||
	destroy_eps(ci);
 | 
						destroy_eps(ci);
 | 
				
			||||||
free_pools:
 | 
					free_pools:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue