aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/sunxi/patches-4.1/171-musb-add-support-for-a31.patch
blob: af958f2b4f3f06fe6f79f470580e2434a99d66a4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
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", },
 	{}
 };