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