sunxi: add support for 4.1
[openwrt.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 diff --git a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt
19 index 9254a6c..fde180b 100644
20 --- a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt
21 +++ b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt
22 @@ -2,9 +2,10 @@ Allwinner sun4i A10 musb DRC/OTG controller
23  -------------------------------------------
24  
25  Required properties:
26 - - compatible      : "allwinner,sun4i-a10-musb"
27 + - compatible      : "allwinner,sun4i-a10-musb" or "allwinner,sun6i-a31-musb"
28   - reg             : mmio address range of the musb controller
29   - clocks          : clock specifier for the musb controller ahb gate clock
30 + - reset           : reset specifier for the ahb reset (A31 and newer only)
31   - interrupts      : interrupt to which the musb controller is connected
32   - interrupt-names : must be "mc"
33   - phys            : phy specifier for the otg phy
34 diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
35 index 00d7248..df2f75e 100644
36 --- a/drivers/usb/musb/sunxi.c
37 +++ b/drivers/usb/musb/sunxi.c
38 @@ -26,6 +26,7 @@
39  #include <linux/of.h>
40  #include <linux/phy/phy-sun4i-usb.h>
41  #include <linux/platform_device.h>
42 +#include <linux/reset.h>
43  #include <linux/soc/sunxi/sunxi_sram.h>
44  #include <linux/usb/musb.h>
45  #include <linux/usb/of.h>
46 @@ -70,6 +71,8 @@
47  #define SUNXI_MUSB_FL_HOSTMODE_PEND            2
48  #define SUNXI_MUSB_FL_VBUS_ON                  3
49  #define SUNXI_MUSB_FL_PHY_ON                   4
50 +#define SUNXI_MUSB_FL_HAS_SRAM                 5
51 +#define SUNXI_MUSB_FL_HAS_RESET                        6
52  
53  /* Our read/write methods need access and do not get passed in a musb ref :| */
54  static struct musb *sunxi_musb;
55 @@ -78,6 +81,7 @@ struct sunxi_glue {
56         struct device           *dev;
57         struct platform_device  *musb;
58         struct clk              *clk;
59 +       struct reset_control    *rst;
60         struct phy              *phy;
61         struct platform_device  *usb_phy;
62         struct usb_phy          *xceiv;
63 @@ -229,14 +233,22 @@ static int sunxi_musb_init(struct musb *musb)
64         musb->phy = glue->phy;
65         musb->xceiv = glue->xceiv;
66  
67 -       ret = sunxi_sram_claim(musb->controller->parent);
68 -       if (ret)
69 -               return ret;
70 +       if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) {
71 +               ret = sunxi_sram_claim(musb->controller->parent);
72 +               if (ret)
73 +                       return ret;
74 +       }
75  
76         ret = clk_prepare_enable(glue->clk);
77         if (ret)
78                 goto error_sram_release;
79  
80 +       if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
81 +               ret = reset_control_deassert(glue->rst);
82 +               if (ret)
83 +                       goto error_clk_disable;
84 +       }
85 +
86         writeb(SUNXI_MUSB_VEND0_PIO_MODE, musb->mregs + SUNXI_MUSB_VEND0);
87  
88         /* Register notifier before calling phy_init() */
89 @@ -244,7 +256,7 @@ static int sunxi_musb_init(struct musb *musb)
90                 ret = extcon_register_notifier(glue->extcon, EXTCON_USB_HOST,
91                                                &glue->host_nb);
92                 if (ret)
93 -                       goto error_clk_disable;
94 +                       goto error_reset_assert;
95         }
96  
97         ret = phy_init(glue->phy);
98 @@ -273,10 +285,14 @@ static int sunxi_musb_init(struct musb *musb)
99         if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
100                 extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
101                                            &glue->host_nb);
102 +error_reset_assert:
103 +       if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
104 +               reset_control_assert(glue->rst);
105  error_clk_disable:
106         clk_disable_unprepare(glue->clk);
107  error_sram_release:
108 -       sunxi_sram_release(musb->controller->parent);
109 +       if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
110 +               sunxi_sram_release(musb->controller->parent);
111         return ret;
112  }
113  
114 @@ -296,8 +312,12 @@ static int sunxi_musb_exit(struct musb *musb)
115                 extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
116                                            &glue->host_nb);
117  
118 +       if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
119 +               reset_control_assert(glue->rst);
120 +
121         clk_disable_unprepare(glue->clk);
122 -       sunxi_sram_release(musb->controller->parent);
123 +       if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
124 +               sunxi_sram_release(musb->controller->parent);
125  
126         return 0;
127  }
128 @@ -617,6 +637,12 @@ static int sunxi_musb_probe(struct platform_device *pdev)
129         INIT_WORK(&glue->work, sunxi_musb_work);
130         glue->host_nb.notifier_call = sunxi_musb_host_notifier;
131  
132 +       if (of_device_is_compatible(np, "allwinner,sun4i-a10-musb"))
133 +               set_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags);
134 +
135 +       if (of_device_is_compatible(np, "allwinner,sun6i-a31-musb"))
136 +               set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
137 +
138         glue->clk = devm_clk_get(&pdev->dev, NULL);
139         if (IS_ERR(glue->clk)) {
140                 dev_err(&pdev->dev, "Error getting clock: %ld\n",
141 @@ -624,6 +650,17 @@ static int sunxi_musb_probe(struct platform_device *pdev)
142                 return PTR_ERR(glue->clk);
143         }
144  
145 +       if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
146 +               glue->rst = devm_reset_control_get(&pdev->dev, NULL);
147 +               if (IS_ERR(glue->rst)) {
148 +                       if (PTR_ERR(glue->rst) == -EPROBE_DEFER)
149 +                               return -EPROBE_DEFER;
150 +                       dev_err(&pdev->dev, "Error getting reset %ld\n",
151 +                               PTR_ERR(glue->rst));
152 +                       return PTR_ERR(glue->rst);
153 +               }
154 +       }
155 +
156         glue->phy = devm_phy_get(&pdev->dev, "usb");
157         if (IS_ERR(glue->phy)) {
158                 if (PTR_ERR(glue->phy) == -EPROBE_DEFER)
159 @@ -685,6 +722,7 @@ static int sunxi_musb_remove(struct platform_device *pdev)
160  
161  static const struct of_device_id sunxi_musb_match[] = {
162         { .compatible = "allwinner,sun4i-a10-musb", },
163 +       { .compatible = "allwinner,sun6i-a31-musb", },
164         {}
165  };
166