ralink: fix mt7620 ohci 3.10
[librecmc/librecmc.git] / target / linux / ramips / patches-3.10 / 0119-USB-phy-add-ralink-SoC-driver.patch
1 From 71e09658d3544143e46ae76e76da8a322cd73e1d Mon Sep 17 00:00:00 2001
2 From: John Crispin <blogic@openwrt.org>
3 Date: Sun, 14 Jul 2013 23:31:19 +0200
4 Subject: [PATCH 119/133] USB: phy: add ralink SoC driver
5
6 Signed-off-by: John Crispin <blogic@openwrt.org>
7 ---
8  drivers/usb/phy/Kconfig      |    8 ++
9  drivers/usb/phy/Makefile     |    1 +
10  drivers/usb/phy/ralink-phy.c |  191 ++++++++++++++++++++++++++++++++++++++++++
11  3 files changed, 200 insertions(+)
12  create mode 100644 drivers/usb/phy/ralink-phy.c
13
14 --- a/drivers/usb/phy/Kconfig
15 +++ b/drivers/usb/phy/Kconfig
16 @@ -210,4 +210,12 @@ config USB_ULPI_VIEWPORT
17           Provides read/write operations to the ULPI phy register set for
18           controllers with a viewport register (e.g. Chipidea/ARC controllers).
19  
20 +config RALINK_USBPHY
21 +       bool "Ralink USB PHY controller Driver"
22 +       depends on MIPS && RALINK
23 +       select USB_OTG_UTILS
24 +       help
25 +         Enable this to support ralink USB phy controller for ralink
26 +         SoCs.
27 +
28  endif # USB_PHY
29 --- a/drivers/usb/phy/Makefile
30 +++ b/drivers/usb/phy/Makefile
31 @@ -31,3 +31,4 @@ obj-$(CONFIG_USB_MXS_PHY)             += phy-mxs-us
32  obj-$(CONFIG_USB_RCAR_PHY)             += phy-rcar-usb.o
33  obj-$(CONFIG_USB_ULPI)                 += phy-ulpi.o
34  obj-$(CONFIG_USB_ULPI_VIEWPORT)                += phy-ulpi-viewport.o
35 +obj-$(CONFIG_RALINK_USBPHY)            += ralink-phy.o
36 --- /dev/null
37 +++ b/drivers/usb/phy/ralink-phy.c
38 @@ -0,0 +1,192 @@
39 +/*
40 + * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
41 + *
42 + * based on: Renesas R-Car USB phy driver
43 + *
44 + * This program is free software; you can redistribute it and/or modify
45 + * it under the terms of the GNU General Public License version 2 as
46 + * published by the Free Software Foundation.
47 + */
48 +
49 +#include <linux/delay.h>
50 +#include <linux/io.h>
51 +#include <linux/usb/otg.h>
52 +#include <linux/of_platform.h>
53 +#include <linux/platform_device.h>
54 +#include <linux/spinlock.h>
55 +#include <linux/module.h>
56 +#include <linux/reset.h>
57 +
58 +#include <asm/mach-ralink/ralink_regs.h>
59 +
60 +#define RT_SYSC_REG_SYSCFG1            0x014
61 +#define RT_SYSC_REG_CLKCFG1            0x030
62 +#define RT_SYSC_REG_USB_PHY_CFG        0x05c
63 +
64 +#define RT_RSTCTRL_UDEV                BIT(25)
65 +#define RT_RSTCTRL_UHST                BIT(22)
66 +#define RT_SYSCFG1_USB0_HOST_MODE      BIT(10)
67 +
68 +#define MT7620_CLKCFG1_UPHY0_CLK_EN    BIT(25)
69 +#define MT7620_CLKCFG1_UPHY1_CLK_EN    BIT(22)
70 +#define RT_CLKCFG1_UPHY1_CLK_EN        BIT(20)
71 +#define RT_CLKCFG1_UPHY0_CLK_EN        BIT(18)
72 +
73 +#define USB_PHY_UTMI_8B60M             BIT(1)
74 +#define UDEV_WAKEUP                    BIT(0)
75 +
76 +static atomic_t usb_pwr_ref = ATOMIC_INIT(0);
77 +static struct reset_control *rstdev;
78 +static struct reset_control *rsthost;
79 +static u32 phy_clk;
80 +
81 +static void usb_phy_enable(int state)
82 +{
83 +       if (state)
84 +               rt_sysc_m32(0, phy_clk, RT_SYSC_REG_CLKCFG1);
85 +       else
86 +               rt_sysc_m32(phy_clk, 0, RT_SYSC_REG_CLKCFG1);
87 +       mdelay(100);
88 +}
89 +
90 +static int usb_power_on(struct usb_phy *phy)
91 +{
92 +       if (atomic_inc_return(&usb_pwr_ref) == 1) {
93 +               u32 t;
94 +
95 +               usb_phy_enable(1);
96 +
97 +//             reset_control_assert(rstdev);
98 +//             reset_control_assert(rsthost);
99 +
100 +               if (OTG_STATE_B_HOST) {
101 +                       rt_sysc_m32(0, RT_SYSCFG1_USB0_HOST_MODE, RT_SYSC_REG_SYSCFG1);
102 +                       reset_control_deassert(rsthost);
103 +               } else {
104 +                       rt_sysc_m32(RT_SYSCFG1_USB0_HOST_MODE, 0, RT_SYSC_REG_SYSCFG1);
105 +                       reset_control_deassert(rstdev);
106 +               }
107 +               mdelay(100);
108 +
109 +               t = rt_sysc_r32(RT_SYSC_REG_USB_PHY_CFG);
110 +               dev_info(phy->dev, "remote usb device wakeup %s\n",
111 +                               (t & UDEV_WAKEUP) ? ("enabbled") : ("disabled"));
112 +               if (t & USB_PHY_UTMI_8B60M)
113 +                       dev_info(phy->dev, "UTMI 8bit 60MHz\n");
114 +               else
115 +                       dev_info(phy->dev, "UTMI 16bit 30MHz\n");
116 +       }
117 +
118 +       return 0;
119 +}
120 +
121 +static void usb_power_off(struct usb_phy *phy)
122 +{
123 +       if (atomic_dec_return(&usb_pwr_ref) == 0) {
124 +               usb_phy_enable(0);
125 +               reset_control_assert(rstdev);
126 +               reset_control_assert(rsthost);
127 +       }
128 +}
129 +
130 +static int usb_set_host(struct usb_otg *otg, struct usb_bus *host)
131 +{
132 +       otg->gadget = NULL;
133 +       otg->host = host;
134 +
135 +       return 0;
136 +}
137 +
138 +static int usb_set_peripheral(struct usb_otg *otg,
139 +               struct usb_gadget *gadget)
140 +{
141 +       otg->host = NULL;
142 +       otg->gadget = gadget;
143 +
144 +       return 0;
145 +}
146 +
147 +static const struct of_device_id ralink_usbphy_dt_match[] = {
148 +       { .compatible = "ralink,rt3xxx-usbphy", .data = (void *) (RT_CLKCFG1_UPHY1_CLK_EN | RT_CLKCFG1_UPHY0_CLK_EN) },
149 +       { .compatible = "ralink,mt7620a-usbphy", .data = (void *) (MT7620_CLKCFG1_UPHY1_CLK_EN | MT7620_CLKCFG1_UPHY0_CLK_EN) },
150 +       {},
151 +};
152 +MODULE_DEVICE_TABLE(of, ralink_usbphy_dt_match);
153 +
154 +static int usb_phy_probe(struct platform_device *pdev)
155 +{
156 +       const struct of_device_id *match;
157 +       struct device *dev = &pdev->dev;
158 +       struct usb_otg *otg;
159 +       struct usb_phy *phy;
160 +       int ret;
161 +
162 +       match = of_match_device(ralink_usbphy_dt_match, &pdev->dev);
163 +       phy_clk = (int) match->data;
164 +
165 +       rsthost = devm_reset_control_get(&pdev->dev, "host");
166 +       if (IS_ERR(rsthost))
167 +               return PTR_ERR(rsthost);
168 +
169 +       rstdev = devm_reset_control_get(&pdev->dev, "device");
170 +       if (IS_ERR(rstdev))
171 +               return PTR_ERR(rstdev);
172 +
173 +       phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
174 +       if (!phy) {
175 +               dev_err(&pdev->dev, "unable to allocate memory for USB PHY\n");
176 +               return -ENOMEM;
177 +       }
178 +
179 +       otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
180 +       if (!otg) {
181 +               dev_err(&pdev->dev, "unable to allocate memory for USB OTG\n");
182 +               return -ENOMEM;
183 +       }
184 +
185 +       phy->dev = dev;
186 +       phy->label = dev_name(dev);
187 +       phy->init = usb_power_on;
188 +       phy->shutdown = usb_power_off;
189 +       otg->set_host = usb_set_host;
190 +       otg->set_peripheral = usb_set_peripheral;
191 +       otg->phy = phy;
192 +       phy->otg = otg;
193 +       ret = usb_add_phy(phy, USB_PHY_TYPE_USB2);
194 +
195 +       if (ret < 0) {
196 +               dev_err(dev, "usb phy addition error\n");
197 +               return ret;
198 +       }
199 +
200 +       platform_set_drvdata(pdev, phy);
201 +
202 +       dev_info(&pdev->dev, "loaded\n");
203 +
204 +       return ret;
205 +}
206 +
207 +static int usb_phy_remove(struct platform_device *pdev)
208 +{
209 +       struct usb_phy *phy = platform_get_drvdata(pdev);
210 +
211 +       usb_remove_phy(phy);
212 +
213 +       return 0;
214 +}
215 +
216 +static struct platform_driver usb_phy_driver = {
217 +       .driver         = {
218 +               .owner  = THIS_MODULE,
219 +               .name   = "rt3xxx-usbphy",
220 +               .of_match_table = of_match_ptr(ralink_usbphy_dt_match),
221 +       },
222 +       .probe          = usb_phy_probe,
223 +       .remove         = usb_phy_remove,
224 +};
225 +
226 +module_platform_driver(usb_phy_driver);
227 +
228 +MODULE_LICENSE("GPL v2");
229 +MODULE_DESCRIPTION("Ralink USB phy");
230 +MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");