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