819838baa2917b7344ea8b5ecc6c3303abd9e3f2
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc_otg / usbdev_rk30.c
1 #include <linux/kernel.h>\r
2 #include <linux/platform_device.h>\r
3 #include <linux/delay.h>\r
4 #include <linux/dma-mapping.h>\r
5 #include <linux/clk.h>\r
6 \r
7 #include <mach/irqs.h>\r
8 #include <mach/gpio.h>\r
9 #include <mach/iomux.h>\r
10 #include <mach/cru.h>\r
11 \r
12 #include "usbdev_rk.h"\r
13 #ifdef CONFIG_ARCH_RK30\r
14 \r
15 #define GRF_REG_BASE    RK30_GRF_BASE   \r
16 #define USBOTG_SIZE     RK30_USBOTG20_SIZE\r
17 #ifdef CONFIG_ARCH_RK3066B\r
18 #define USBGRF_SOC_STATUS0      (GRF_REG_BASE+0xac)\r
19 #define USBGRF_UOC0_CON2        (GRF_REG_BASE+0x118) // USBGRF_UOC0_CON3\r
20 #define USBGRF_UOC1_CON2        (GRF_REG_BASE+0x128) // USBGRF_UOC1_CON3\r
21 #else\r
22 #define USBGRF_SOC_STATUS0      (GRF_REG_BASE+0x15c)\r
23 #define USBGRF_UOC0_CON2        (GRF_REG_BASE+0x184)\r
24 #define USBGRF_UOC1_CON2        (GRF_REG_BASE+0x190)\r
25 #endif\r
26 //#define USB_IOMUX_INIT(a,b) rk30_mux_api_set(a,b)\r
27 \r
28 #ifdef CONFIG_USB20_OTG\r
29 /*DWC_OTG*/\r
30 static struct resource usb20_otg_resource[] = {\r
31         {\r
32                 .start = IRQ_USB_OTG,\r
33                 .end   = IRQ_USB_OTG,\r
34                 .flags = IORESOURCE_IRQ,\r
35         },\r
36         {\r
37                 .start = RK30_USBOTG20_PHYS,\r
38                 .end   = RK30_USBOTG20_PHYS + RK30_USBOTG20_SIZE - 1,\r
39                 .flags = IORESOURCE_MEM,\r
40         },\r
41 \r
42 };\r
43 \r
44 void usb20otg_hw_init(void)\r
45 {\r
46 #ifndef CONFIG_USB20_HOST\r
47     // close USB 2.0 HOST phy and clock\r
48     unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC1_CON2);\r
49     *otg_phy_con1 = 0x554|(0xfff<<16);   // enter suspend.\r
50 #endif\r
51     // usb phy config init\r
52 \r
53     // other haredware init\r
54 #ifdef CONFIG_ARCH_RK3066B\r
55     rk30_mux_api_set(GPIO3D5_PWM2_JTAGTCK_OTGDRVVBUS_NAME, GPIO3D_OTGDRVVBUS);\r
56 #else\r
57     rk30_mux_api_set(GPIO0A5_OTGDRVVBUS_NAME, GPIO0A_OTG_DRV_VBUS);\r
58 #endif\r
59 }\r
60 void usb20otg_phy_suspend(void* pdata, int suspend)\r
61 {\r
62     struct dwc_otg_platform_data *usbpdata=pdata;\r
63     unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON2);\r
64     if(suspend){\r
65         *otg_phy_con1 = 0x554|(0xfff<<16);   // enter suspend.\r
66         usbpdata->phy_status = 1;\r
67     }\r
68     else{\r
69         *otg_phy_con1 = ((0x01<<2)<<16);    // exit suspend.\r
70         usbpdata->phy_status = 0;\r
71     }\r
72 }\r
73 void usb20otg_soft_reset(void)\r
74 {\r
75 #if 1\r
76     cru_set_soft_reset(SOFT_RST_USBOTG0, true);\r
77     cru_set_soft_reset(SOFT_RST_USBPHY0, true);\r
78     cru_set_soft_reset(SOFT_RST_OTGC0, true);\r
79     udelay(1);\r
80 \r
81     cru_set_soft_reset(SOFT_RST_USBOTG0, false);\r
82     cru_set_soft_reset(SOFT_RST_USBPHY0, false);\r
83     cru_set_soft_reset(SOFT_RST_OTGC0, false);\r
84     mdelay(1);\r
85 #endif\r
86 }\r
87 void usb20otg_clock_init(void* pdata)\r
88 {\r
89     struct dwc_otg_platform_data *usbpdata=pdata;\r
90     struct clk* ahbclk,*phyclk;\r
91     ahbclk = clk_get(NULL, "hclk_otg0");\r
92     phyclk = clk_get(NULL, "otgphy0");\r
93         usbpdata->phyclk = phyclk;\r
94         usbpdata->ahbclk = ahbclk;\r
95 }\r
96 void usb20otg_clock_enable(void* pdata, int enable)\r
97 {\r
98     struct dwc_otg_platform_data *usbpdata=pdata;\r
99     #if 1\r
100     if(enable){\r
101         clk_enable(usbpdata->ahbclk);\r
102         clk_enable(usbpdata->phyclk);\r
103     }\r
104     else{\r
105         clk_disable(usbpdata->phyclk);\r
106         clk_disable(usbpdata->ahbclk);\r
107     }\r
108     #endif\r
109 }\r
110 int usb20otg_get_status(int id)\r
111 {\r
112     int ret = -1;\r
113     unsigned int usbgrf_status = *(unsigned int*)(USBGRF_SOC_STATUS0);\r
114     switch(id)\r
115     {\r
116         case 0x01:\r
117             // bvalid in grf\r
118             ret = (usbgrf_status &0x20000);\r
119             break;\r
120         case 0x02:\r
121             // dpdm in grf\r
122             ret = (usbgrf_status &(3<<18));\r
123             break;\r
124         case 0x03:\r
125             // id in grf\r
126             ret = (usbgrf_status &(1<<20));\r
127             break;\r
128         default:\r
129             break;\r
130     }\r
131     return ret;\r
132 }\r
133 void usb20otg_power_enable(int enable)\r
134 {\r
135 }\r
136 struct dwc_otg_platform_data usb20otg_pdata = {\r
137     .phyclk = NULL,\r
138     .ahbclk = NULL,\r
139     .busclk = NULL,\r
140     .phy_status = 0,\r
141     .hw_init=usb20otg_hw_init,\r
142     .phy_suspend=usb20otg_phy_suspend,\r
143     .soft_reset=usb20otg_soft_reset,\r
144     .clock_init=usb20otg_clock_init,\r
145     .clock_enable=usb20otg_clock_enable,\r
146     .get_status=usb20otg_get_status,\r
147 };\r
148 \r
149 struct platform_device device_usb20_otg = {\r
150         .name             = "usb20_otg",\r
151         .id               = -1,\r
152         .num_resources    = ARRAY_SIZE(usb20_otg_resource),\r
153         .resource         = usb20_otg_resource,\r
154         .dev            = {\r
155                 .platform_data  = &usb20otg_pdata,\r
156         },\r
157 };\r
158 #endif\r
159 #ifdef CONFIG_USB20_HOST\r
160 static struct resource usb20_host_resource[] = {\r
161     {\r
162         .start = IRQ_USB_HOST,\r
163         .end   = IRQ_USB_HOST,\r
164         .flags = IORESOURCE_IRQ,\r
165     },\r
166     {\r
167         .start = RK30_USBHOST20_PHYS,\r
168         .end   = RK30_USBHOST20_PHYS + RK30_USBHOST20_SIZE - 1,\r
169         .flags = IORESOURCE_MEM,\r
170     },\r
171 \r
172 };\r
173 void usb20host_hw_init(void)\r
174 {\r
175     // usb phy config init\r
176 \r
177     // other haredware init\r
178 #ifdef CONFIG_ARCH_RK3066B\r
179     rk30_mux_api_set(GPIO3D6_PWM3_JTAGTMS_HOSTDRVVBUS_NAME, GPIO3D_HOSTDRVVBUS);\r
180 #else\r
181     rk30_mux_api_set(GPIO0A6_HOSTDRVVBUS_NAME, GPIO0A_HOST_DRV_VBUS);\r
182 #endif\r
183 }\r
184 void usb20host_phy_suspend(void* pdata, int suspend)\r
185 {\r
186     struct dwc_otg_platform_data *usbpdata=pdata;\r
187     unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC1_CON2);\r
188     if(suspend){\r
189         *otg_phy_con1 = 0x554|(0xfff<<16);   // enter suspend.\r
190         usbpdata->phy_status = 0;\r
191     }\r
192     else{\r
193         *otg_phy_con1 = ((0x01<<2)<<16);    // exit suspend.\r
194         usbpdata->phy_status = 1;\r
195     }\r
196 }\r
197 void usb20host_soft_reset(void)\r
198 {\r
199 #if 1\r
200     cru_set_soft_reset(SOFT_RST_USBOTG1, true);\r
201     cru_set_soft_reset(SOFT_RST_USBPHY1, true);\r
202     cru_set_soft_reset(SOFT_RST_OTGC1, true);\r
203     udelay(1);\r
204 \r
205     cru_set_soft_reset(SOFT_RST_USBOTG1, false);\r
206     cru_set_soft_reset(SOFT_RST_USBPHY1, false);\r
207     cru_set_soft_reset(SOFT_RST_OTGC1, false);\r
208     mdelay(1);\r
209 #endif\r
210 }\r
211 void usb20host_clock_init(void* pdata)\r
212 {\r
213     struct dwc_otg_platform_data *usbpdata=pdata;\r
214     struct clk* ahbclk,*phyclk;\r
215     ahbclk = clk_get(NULL, "hclk_otg1");\r
216     phyclk = clk_get(NULL, "otgphy1");\r
217         usbpdata->phyclk = phyclk;\r
218         usbpdata->ahbclk = ahbclk;\r
219 }\r
220 void usb20host_clock_enable(void* pdata, int enable)\r
221 {\r
222     struct dwc_otg_platform_data *usbpdata=pdata;\r
223     #if 1\r
224     if(enable){\r
225         clk_enable(usbpdata->ahbclk);\r
226         clk_enable(usbpdata->phyclk);\r
227     }\r
228     else{\r
229         clk_disable(usbpdata->phyclk);\r
230         clk_disable(usbpdata->ahbclk);\r
231     }\r
232     #endif\r
233 }\r
234 int usb20host_get_status(int id)\r
235 {\r
236     int ret = -1;\r
237     unsigned int usbgrf_status = *(unsigned int*)(USBGRF_SOC_STATUS0);\r
238     switch(id)\r
239     {\r
240         case USB_STATUS_BVABLID:\r
241             // bvalid in grf\r
242             ret = (usbgrf_status &(1<<22));\r
243             break;\r
244         case USB_STATUS_DPDM:\r
245             // dpdm in grf\r
246             ret = (usbgrf_status &(3<<23));\r
247             break;\r
248         case USB_STATUS_ID:\r
249             // id in grf\r
250             ret = 0;\r
251             break;\r
252         default:\r
253             break;\r
254     }\r
255     return ret;\r
256 }\r
257 void usb20host_power_enable(int enable)\r
258 {\r
259 }\r
260 struct dwc_otg_platform_data usb20host_pdata = {\r
261     .phyclk = NULL,\r
262     .ahbclk = NULL,\r
263     .busclk = NULL,\r
264     .phy_status = 0,\r
265     .hw_init=usb20host_hw_init,\r
266     .phy_suspend=usb20host_phy_suspend,\r
267     .soft_reset=usb20host_soft_reset,\r
268     .clock_init=usb20host_clock_init,\r
269     .clock_enable=usb20host_clock_enable,\r
270     .get_status=usb20host_get_status,\r
271 };\r
272 \r
273 struct platform_device device_usb20_host = {\r
274     .name             = "usb20_host",\r
275     .id               = -1,\r
276     .num_resources    = ARRAY_SIZE(usb20_host_resource),\r
277     .resource         = usb20_host_resource,\r
278         .dev            = {\r
279                 .platform_data  = &usb20host_pdata,\r
280         },\r
281 };\r
282 #endif\r
283 static int __init usbdev_init_devices(void)\r
284 {\r
285 #ifdef CONFIG_USB20_OTG\r
286         platform_device_register(&device_usb20_otg);\r
287 #endif\r
288 #ifdef CONFIG_USB20_HOST\r
289         platform_device_register(&device_usb20_host);\r
290 #endif\r
291 }\r
292 arch_initcall(usbdev_init_devices);\r
293 #endif