diff options
Diffstat (limited to 'drivers/usb/host/fsl-mph-dr-of.c')
| -rw-r--r-- | drivers/usb/host/fsl-mph-dr-of.c | 118 | 
1 files changed, 75 insertions, 43 deletions
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 574b99ea070..9162d1b6c0a 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -16,6 +16,7 @@  #include <linux/io.h>  #include <linux/of_platform.h>  #include <linux/clk.h> +#include <linux/module.h>  struct fsl_usb2_dev_data {  	char *dr_mode;		/* controller mode */ @@ -23,7 +24,7 @@ struct fsl_usb2_dev_data {  	enum fsl_usb2_operating_modes op_mode;	/* operating mode */  }; -struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = { +static struct fsl_usb2_dev_data dr_mode_data[] = {  	{  		.dr_mode = "host",  		.drivers = { "fsl-ehci", NULL, NULL, }, @@ -41,7 +42,7 @@ struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = {  	},  }; -struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np) +static struct fsl_usb2_dev_data *get_dr_mode_data(struct device_node *np)  {  	const unsigned char *prop;  	int i; @@ -58,7 +59,7 @@ struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np)  	return &dr_mode_data[0]; /* mode not specified, use host */  } -static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type) +static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)  {  	if (!phy_type)  		return FSL_USB2_PHY_NONE; @@ -74,7 +75,7 @@ static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type)  	return FSL_USB2_PHY_NONE;  } -struct platform_device * __devinit fsl_usb2_device_register( +static struct platform_device *fsl_usb2_device_register(  					struct platform_device *ofdev,  					struct fsl_usb2_platform_data *pdata,  					const char *name, int id) @@ -93,7 +94,6 @@ struct platform_device * __devinit fsl_usb2_device_register(  	pdev->dev.parent = &ofdev->dev;  	pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask; -	pdev->dev.dma_mask = &pdev->archdata.dma_mask;  	*pdev->dev.dma_mask = *ofdev->dev.dma_mask;  	retval = platform_device_add_data(pdev, pdata, sizeof(*pdata)); @@ -119,7 +119,45 @@ error:  static const struct of_device_id fsl_usb2_mph_dr_of_match[]; -static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev) +static int usb_get_ver_info(struct device_node *np) +{ +	int ver = -1; + +	/* +	 * returns 1 for usb controller version 1.6 +	 * returns 2 for usb controller version 2.2 +	 * returns 0 otherwise +	 */ +	if (of_device_is_compatible(np, "fsl-usb2-dr")) { +		if (of_device_is_compatible(np, "fsl-usb2-dr-v1.6")) +			ver = FSL_USB_VER_1_6; +		else if (of_device_is_compatible(np, "fsl-usb2-dr-v2.2")) +			ver = FSL_USB_VER_2_2; +		else if (of_device_is_compatible(np, "fsl-usb2-dr-v2.4")) +			ver = FSL_USB_VER_2_4; +		else /* for previous controller versions */ +			ver = FSL_USB_VER_OLD; + +		if (ver > -1) +			return ver; +	} + +	if (of_device_is_compatible(np, "fsl,mpc5121-usb2-dr")) +		return FSL_USB_VER_OLD; + +	if (of_device_is_compatible(np, "fsl-usb2-mph")) { +		if (of_device_is_compatible(np, "fsl-usb2-mph-v1.6")) +			ver = FSL_USB_VER_1_6; +		else if (of_device_is_compatible(np, "fsl-usb2-mph-v2.2")) +			ver = FSL_USB_VER_2_2; +		else /* for previous controller versions */ +			ver = FSL_USB_VER_OLD; +	} + +	return ver; +} + +static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)  {  	struct device_node *np = ofdev->dev.of_node;  	struct platform_device *usb_dev; @@ -166,6 +204,14 @@ static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)  	prop = of_get_property(np, "phy_type", NULL);  	pdata->phy_mode = determine_usb_phy(prop); +	pdata->controller_ver = usb_get_ver_info(np); + +	if (pdata->have_sysif_regs) { +		if (pdata->controller_ver < 0) { +			dev_warn(&ofdev->dev, "Could not get controller version\n"); +			return -ENODEV; +		} +	}  	for (i = 0; i < ARRAY_SIZE(dev_data->drivers); i++) {  		if (!dev_data->drivers[i]) @@ -181,13 +227,13 @@ static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)  	return 0;  } -static int __devexit __unregister_subdev(struct device *dev, void *d) +static int __unregister_subdev(struct device *dev, void *d)  {  	platform_device_unregister(to_platform_device(dev));  	return 0;  } -static int __devexit fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev) +static int fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev)  {  	device_for_each_child(&ofdev->dev, NULL, __unregister_subdev);  	return 0; @@ -212,27 +258,20 @@ static int __devexit fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev)  int fsl_usb2_mpc5121_init(struct platform_device *pdev)  { -	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; +	struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);  	struct clk *clk; -	char clk_name[10]; -	int base, clk_num; - -	base = pdev->resource->start & 0xf000; -	if (base == 0x3000) -		clk_num = 1; -	else if (base == 0x4000) -		clk_num = 2; -	else -		return -ENODEV; +	int err; -	snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num); -	clk = clk_get(&pdev->dev, clk_name); +	clk = devm_clk_get(pdev->dev.parent, "ipg");  	if (IS_ERR(clk)) {  		dev_err(&pdev->dev, "failed to get clk\n");  		return PTR_ERR(clk);  	} - -	clk_enable(clk); +	err = clk_prepare_enable(clk); +	if (err) { +		dev_err(&pdev->dev, "failed to enable clk\n"); +		return err; +	}  	pdata->clk = clk;  	if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) { @@ -252,29 +291,32 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)  static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)  { -	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; +	struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);  	pdata->regs = NULL; -	if (pdata->clk) { -		clk_disable(pdata->clk); -		clk_put(pdata->clk); -	} +	if (pdata->clk) +		clk_disable_unprepare(pdata->clk);  } -struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd = { +static struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd = {  	.big_endian_desc = 1,  	.big_endian_mmio = 1,  	.es = 1, +	.have_sysif_regs = 0,  	.le_setup_buf = 1,  	.init = fsl_usb2_mpc5121_init,  	.exit = fsl_usb2_mpc5121_exit,  };  #endif /* CONFIG_PPC_MPC512x */ +static struct fsl_usb2_platform_data fsl_usb2_mpc8xxx_pd = { +	.have_sysif_regs = 1, +}; +  static const struct of_device_id fsl_usb2_mph_dr_of_match[] = { -	{ .compatible = "fsl-usb2-mph", }, -	{ .compatible = "fsl-usb2-dr", }, +	{ .compatible = "fsl-usb2-mph", .data = &fsl_usb2_mpc8xxx_pd, }, +	{ .compatible = "fsl-usb2-dr", .data = &fsl_usb2_mpc8xxx_pd, },  #ifdef CONFIG_PPC_MPC512x  	{ .compatible = "fsl,mpc5121-usb2-dr", .data = &fsl_usb2_mpc5121_pd, },  #endif @@ -288,20 +330,10 @@ static struct platform_driver fsl_usb2_mph_dr_driver = {  		.of_match_table = fsl_usb2_mph_dr_of_match,  	},  	.probe	= fsl_usb2_mph_dr_of_probe, -	.remove	= __devexit_p(fsl_usb2_mph_dr_of_remove), +	.remove	= fsl_usb2_mph_dr_of_remove,  }; -static int __init fsl_usb2_mph_dr_init(void) -{ -	return platform_driver_register(&fsl_usb2_mph_dr_driver); -} -module_init(fsl_usb2_mph_dr_init); - -static void __exit fsl_usb2_mph_dr_exit(void) -{ -	platform_driver_unregister(&fsl_usb2_mph_dr_driver); -} -module_exit(fsl_usb2_mph_dr_exit); +module_platform_driver(fsl_usb2_mph_dr_driver);  MODULE_DESCRIPTION("FSL MPH DR OF devices driver");  MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");  | 
