mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-31 14:04:26 -04:00 
			
		
		
		
	Changelog: * https://www.kernel.org/pub/linux/kernel/v4.x/ChangeLog-4.1.5 Signed-off-by: Jonas Gorski <jogo@openwrt.org> SVN-Revision: 46598
		
			
				
	
	
		
			163 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 132e23775779cc895c37f7883c33a60a1a8a7cdd Mon Sep 17 00:00:00 2001
 | |
| From: Hans de Goede <hdegoede@redhat.com>
 | |
| Date: Wed, 8 Jul 2015 16:41:39 +0200
 | |
| Subject: [PATCH] usb: musb: sunxi: Add support for musb controller in A31 SoC
 | |
| 
 | |
| The A31 SoC uses the same musb controller as found in earlier SoCs, but it
 | |
| is hooked up slightly different. Its SRAM is private and no longer controlled
 | |
| through the SRAM controller, and its reset is controlled via a separate
 | |
| reset controller. This commit adds support for this setup.
 | |
| 
 | |
| Signed-off-by: Hans de Goede <hdegoede@redhat.com>
 | |
| Signed-off-by: Felipe Balbi <balbi@ti.com>
 | |
| ---
 | |
|  .../bindings/usb/allwinner,sun4i-a10-musb.txt      |  3 +-
 | |
|  drivers/usb/musb/sunxi.c                           | 50 +++++++++++++++++++---
 | |
|  2 files changed, 46 insertions(+), 7 deletions(-)
 | |
| 
 | |
| --- a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt
 | |
| +++ b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt
 | |
| @@ -2,9 +2,10 @@ Allwinner sun4i A10 musb DRC/OTG control
 | |
|  -------------------------------------------
 | |
|  
 | |
|  Required properties:
 | |
| - - compatible      : "allwinner,sun4i-a10-musb"
 | |
| + - compatible      : "allwinner,sun4i-a10-musb" or "allwinner,sun6i-a31-musb"
 | |
|   - reg             : mmio address range of the musb controller
 | |
|   - clocks          : clock specifier for the musb controller ahb gate clock
 | |
| + - reset           : reset specifier for the ahb reset (A31 and newer only)
 | |
|   - interrupts      : interrupt to which the musb controller is connected
 | |
|   - interrupt-names : must be "mc"
 | |
|   - phys            : phy specifier for the otg phy
 | |
| --- a/drivers/usb/musb/sunxi.c
 | |
| +++ b/drivers/usb/musb/sunxi.c
 | |
| @@ -26,6 +26,7 @@
 | |
|  #include <linux/of.h>
 | |
|  #include <linux/phy/phy-sun4i-usb.h>
 | |
|  #include <linux/platform_device.h>
 | |
| +#include <linux/reset.h>
 | |
|  #include <linux/soc/sunxi/sunxi_sram.h>
 | |
|  #include <linux/usb/musb.h>
 | |
|  #include <linux/usb/of.h>
 | |
| @@ -70,6 +71,8 @@
 | |
|  #define SUNXI_MUSB_FL_HOSTMODE_PEND		2
 | |
|  #define SUNXI_MUSB_FL_VBUS_ON			3
 | |
|  #define SUNXI_MUSB_FL_PHY_ON			4
 | |
| +#define SUNXI_MUSB_FL_HAS_SRAM			5
 | |
| +#define SUNXI_MUSB_FL_HAS_RESET			6
 | |
|  
 | |
|  /* Our read/write methods need access and do not get passed in a musb ref :| */
 | |
|  static struct musb *sunxi_musb;
 | |
| @@ -78,6 +81,7 @@ struct sunxi_glue {
 | |
|  	struct device		*dev;
 | |
|  	struct platform_device	*musb;
 | |
|  	struct clk		*clk;
 | |
| +	struct reset_control	*rst;
 | |
|  	struct phy		*phy;
 | |
|  	struct platform_device	*usb_phy;
 | |
|  	struct usb_phy		*xceiv;
 | |
| @@ -229,14 +233,22 @@ static int sunxi_musb_init(struct musb *
 | |
|  	musb->phy = glue->phy;
 | |
|  	musb->xceiv = glue->xceiv;
 | |
|  
 | |
| -	ret = sunxi_sram_claim(musb->controller->parent);
 | |
| -	if (ret)
 | |
| -		return ret;
 | |
| +	if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) {
 | |
| +		ret = sunxi_sram_claim(musb->controller->parent);
 | |
| +		if (ret)
 | |
| +			return ret;
 | |
| +	}
 | |
|  
 | |
|  	ret = clk_prepare_enable(glue->clk);
 | |
|  	if (ret)
 | |
|  		goto error_sram_release;
 | |
|  
 | |
| +	if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
 | |
| +		ret = reset_control_deassert(glue->rst);
 | |
| +		if (ret)
 | |
| +			goto error_clk_disable;
 | |
| +	}
 | |
| +
 | |
|  	writeb(SUNXI_MUSB_VEND0_PIO_MODE, musb->mregs + SUNXI_MUSB_VEND0);
 | |
|  
 | |
|  	/* Register notifier before calling phy_init() */
 | |
| @@ -244,7 +256,7 @@ static int sunxi_musb_init(struct musb *
 | |
|  		ret = extcon_register_notifier(glue->extcon, EXTCON_USB_HOST,
 | |
|  					       &glue->host_nb);
 | |
|  		if (ret)
 | |
| -			goto error_clk_disable;
 | |
| +			goto error_reset_assert;
 | |
|  	}
 | |
|  
 | |
|  	ret = phy_init(glue->phy);
 | |
| @@ -273,10 +285,14 @@ error_unregister_notifier:
 | |
|  	if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
 | |
|  		extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
 | |
|  					   &glue->host_nb);
 | |
| +error_reset_assert:
 | |
| +	if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
 | |
| +		reset_control_assert(glue->rst);
 | |
|  error_clk_disable:
 | |
|  	clk_disable_unprepare(glue->clk);
 | |
|  error_sram_release:
 | |
| -	sunxi_sram_release(musb->controller->parent);
 | |
| +	if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
 | |
| +		sunxi_sram_release(musb->controller->parent);
 | |
|  	return ret;
 | |
|  }
 | |
|  
 | |
| @@ -296,8 +312,12 @@ static int sunxi_musb_exit(struct musb *
 | |
|  		extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
 | |
|  					   &glue->host_nb);
 | |
|  
 | |
| +	if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
 | |
| +		reset_control_assert(glue->rst);
 | |
| +
 | |
|  	clk_disable_unprepare(glue->clk);
 | |
| -	sunxi_sram_release(musb->controller->parent);
 | |
| +	if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
 | |
| +		sunxi_sram_release(musb->controller->parent);
 | |
|  
 | |
|  	return 0;
 | |
|  }
 | |
| @@ -617,6 +637,12 @@ static int sunxi_musb_probe(struct platf
 | |
|  	INIT_WORK(&glue->work, sunxi_musb_work);
 | |
|  	glue->host_nb.notifier_call = sunxi_musb_host_notifier;
 | |
|  
 | |
| +	if (of_device_is_compatible(np, "allwinner,sun4i-a10-musb"))
 | |
| +		set_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags);
 | |
| +
 | |
| +	if (of_device_is_compatible(np, "allwinner,sun6i-a31-musb"))
 | |
| +		set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
 | |
| +
 | |
|  	glue->clk = devm_clk_get(&pdev->dev, NULL);
 | |
|  	if (IS_ERR(glue->clk)) {
 | |
|  		dev_err(&pdev->dev, "Error getting clock: %ld\n",
 | |
| @@ -624,6 +650,17 @@ static int sunxi_musb_probe(struct platf
 | |
|  		return PTR_ERR(glue->clk);
 | |
|  	}
 | |
|  
 | |
| +	if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
 | |
| +		glue->rst = devm_reset_control_get(&pdev->dev, NULL);
 | |
| +		if (IS_ERR(glue->rst)) {
 | |
| +			if (PTR_ERR(glue->rst) == -EPROBE_DEFER)
 | |
| +				return -EPROBE_DEFER;
 | |
| +			dev_err(&pdev->dev, "Error getting reset %ld\n",
 | |
| +				PTR_ERR(glue->rst));
 | |
| +			return PTR_ERR(glue->rst);
 | |
| +		}
 | |
| +	}
 | |
| +
 | |
|  	glue->phy = devm_phy_get(&pdev->dev, "usb");
 | |
|  	if (IS_ERR(glue->phy)) {
 | |
|  		if (PTR_ERR(glue->phy) == -EPROBE_DEFER)
 | |
| @@ -685,6 +722,7 @@ static int sunxi_musb_remove(struct plat
 | |
|  
 | |
|  static const struct of_device_id sunxi_musb_match[] = {
 | |
|  	{ .compatible = "allwinner,sun4i-a10-musb", },
 | |
| +	{ .compatible = "allwinner,sun6i-a31-musb", },
 | |
|  	{}
 | |
|  };
 | |
|  
 |