kernel: update 4.1 to 4.1.5
[openwrt/svn-archive/archive.git] / target / linux / sunxi / patches-4.1 / 171-musb-add-support-for-a31.patch
1 From 132e23775779cc895c37f7883c33a60a1a8a7cdd Mon Sep 17 00:00:00 2001
2 From: Hans de Goede <hdegoede@redhat.com>
3 Date: Wed, 8 Jul 2015 16:41:39 +0200
4 Subject: [PATCH] usb: musb: sunxi: Add support for musb controller in A31 SoC
5
6 The A31 SoC uses the same musb controller as found in earlier SoCs, but it
7 is hooked up slightly different. Its SRAM is private and no longer controlled
8 through the SRAM controller, and its reset is controlled via a separate
9 reset controller. This commit adds support for this setup.
10
11 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
12 Signed-off-by: Felipe Balbi <balbi@ti.com>
13 ---
14 .../bindings/usb/allwinner,sun4i-a10-musb.txt | 3 +-
15 drivers/usb/musb/sunxi.c | 50 +++++++++++++++++++---
16 2 files changed, 46 insertions(+), 7 deletions(-)
17
18 --- a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt
19 +++ b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt
20 @@ -2,9 +2,10 @@ Allwinner sun4i A10 musb DRC/OTG control
21 -------------------------------------------
22
23 Required properties:
24 - - compatible : "allwinner,sun4i-a10-musb"
25 + - compatible : "allwinner,sun4i-a10-musb" or "allwinner,sun6i-a31-musb"
26 - reg : mmio address range of the musb controller
27 - clocks : clock specifier for the musb controller ahb gate clock
28 + - reset : reset specifier for the ahb reset (A31 and newer only)
29 - interrupts : interrupt to which the musb controller is connected
30 - interrupt-names : must be "mc"
31 - phys : phy specifier for the otg phy
32 --- a/drivers/usb/musb/sunxi.c
33 +++ b/drivers/usb/musb/sunxi.c
34 @@ -26,6 +26,7 @@
35 #include <linux/of.h>
36 #include <linux/phy/phy-sun4i-usb.h>
37 #include <linux/platform_device.h>
38 +#include <linux/reset.h>
39 #include <linux/soc/sunxi/sunxi_sram.h>
40 #include <linux/usb/musb.h>
41 #include <linux/usb/of.h>
42 @@ -70,6 +71,8 @@
43 #define SUNXI_MUSB_FL_HOSTMODE_PEND 2
44 #define SUNXI_MUSB_FL_VBUS_ON 3
45 #define SUNXI_MUSB_FL_PHY_ON 4
46 +#define SUNXI_MUSB_FL_HAS_SRAM 5
47 +#define SUNXI_MUSB_FL_HAS_RESET 6
48
49 /* Our read/write methods need access and do not get passed in a musb ref :| */
50 static struct musb *sunxi_musb;
51 @@ -78,6 +81,7 @@ struct sunxi_glue {
52 struct device *dev;
53 struct platform_device *musb;
54 struct clk *clk;
55 + struct reset_control *rst;
56 struct phy *phy;
57 struct platform_device *usb_phy;
58 struct usb_phy *xceiv;
59 @@ -229,14 +233,22 @@ static int sunxi_musb_init(struct musb *
60 musb->phy = glue->phy;
61 musb->xceiv = glue->xceiv;
62
63 - ret = sunxi_sram_claim(musb->controller->parent);
64 - if (ret)
65 - return ret;
66 + if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) {
67 + ret = sunxi_sram_claim(musb->controller->parent);
68 + if (ret)
69 + return ret;
70 + }
71
72 ret = clk_prepare_enable(glue->clk);
73 if (ret)
74 goto error_sram_release;
75
76 + if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
77 + ret = reset_control_deassert(glue->rst);
78 + if (ret)
79 + goto error_clk_disable;
80 + }
81 +
82 writeb(SUNXI_MUSB_VEND0_PIO_MODE, musb->mregs + SUNXI_MUSB_VEND0);
83
84 /* Register notifier before calling phy_init() */
85 @@ -244,7 +256,7 @@ static int sunxi_musb_init(struct musb *
86 ret = extcon_register_notifier(glue->extcon, EXTCON_USB_HOST,
87 &glue->host_nb);
88 if (ret)
89 - goto error_clk_disable;
90 + goto error_reset_assert;
91 }
92
93 ret = phy_init(glue->phy);
94 @@ -273,10 +285,14 @@ error_unregister_notifier:
95 if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
96 extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
97 &glue->host_nb);
98 +error_reset_assert:
99 + if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
100 + reset_control_assert(glue->rst);
101 error_clk_disable:
102 clk_disable_unprepare(glue->clk);
103 error_sram_release:
104 - sunxi_sram_release(musb->controller->parent);
105 + if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
106 + sunxi_sram_release(musb->controller->parent);
107 return ret;
108 }
109
110 @@ -296,8 +312,12 @@ static int sunxi_musb_exit(struct musb *
111 extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
112 &glue->host_nb);
113
114 + if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
115 + reset_control_assert(glue->rst);
116 +
117 clk_disable_unprepare(glue->clk);
118 - sunxi_sram_release(musb->controller->parent);
119 + if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
120 + sunxi_sram_release(musb->controller->parent);
121
122 return 0;
123 }
124 @@ -617,6 +637,12 @@ static int sunxi_musb_probe(struct platf
125 INIT_WORK(&glue->work, sunxi_musb_work);
126 glue->host_nb.notifier_call = sunxi_musb_host_notifier;
127
128 + if (of_device_is_compatible(np, "allwinner,sun4i-a10-musb"))
129 + set_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags);
130 +
131 + if (of_device_is_compatible(np, "allwinner,sun6i-a31-musb"))
132 + set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
133 +
134 glue->clk = devm_clk_get(&pdev->dev, NULL);
135 if (IS_ERR(glue->clk)) {
136 dev_err(&pdev->dev, "Error getting clock: %ld\n",
137 @@ -624,6 +650,17 @@ static int sunxi_musb_probe(struct platf
138 return PTR_ERR(glue->clk);
139 }
140
141 + if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
142 + glue->rst = devm_reset_control_get(&pdev->dev, NULL);
143 + if (IS_ERR(glue->rst)) {
144 + if (PTR_ERR(glue->rst) == -EPROBE_DEFER)
145 + return -EPROBE_DEFER;
146 + dev_err(&pdev->dev, "Error getting reset %ld\n",
147 + PTR_ERR(glue->rst));
148 + return PTR_ERR(glue->rst);
149 + }
150 + }
151 +
152 glue->phy = devm_phy_get(&pdev->dev, "usb");
153 if (IS_ERR(glue->phy)) {
154 if (PTR_ERR(glue->phy) == -EPROBE_DEFER)
155 @@ -685,6 +722,7 @@ static int sunxi_musb_remove(struct plat
156
157 static const struct of_device_id sunxi_musb_match[] = {
158 { .compatible = "allwinner,sun4i-a10-musb", },
159 + { .compatible = "allwinner,sun6i-a31-musb", },
160 {}
161 };
162