1 /*
2 * drivers/usb/sunxi_usb/udc/sunxi_udc_board.c
3 * (C) Copyright 2010-2015
4 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
5 * javen, 2010-12-20, create this file
6 *
7 * usb board config.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 */
15
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/delay.h>
19 #include <linux/ioport.h>
20 #include <linux/sched.h>
21 #include <linux/slab.h>
22 #include <linux/errno.h>
23 #include <linux/err.h>
24 #include <linux/init.h>
25 #include <linux/timer.h>
26 #include <linux/list.h>
27 #include <linux/interrupt.h>
28 #include <linux/platform_device.h>
29 #include <linux/clk.h>
30 #include <linux/reset.h>
31 #include <linux/io.h>
32 #include "sunxi_udc_config.h"
33 #include "sunxi_udc_board.h"
34
35 #define res_size(_r) (((_r)->end - (_r)->start) + 1)
36
open_usb_clock(sunxi_udc_io_t * sunxi_udc_io)37 u32 open_usb_clock(sunxi_udc_io_t *sunxi_udc_io)
38 {
39 int ret;
40
41 DMSG_INFO_UDC("open_usb_clock\n");
42
43 /* To fix hardware design issue. */
44 #if defined(CONFIG_ARCH_SUN8IW12) || defined(CONFIG_ARCH_SUN50IW3) \
45 || defined(CONFIG_ARCH_SUN50IW6) || defined(CONFIG_ARCH_SUN8IW15) \
46 || defined(CONFIG_ARCH_SUN8IW18)
47 usb_otg_phy_txtune(sunxi_udc_io->usb_vbase);
48 #endif
49
50 if (!sunxi_udc_io->clk_is_open) {
51 if (sunxi_udc_io->reset_phy) {
52 ret = reset_control_deassert(sunxi_udc_io->reset_phy);
53 if (ret) {
54 DMSG_PANIC("[udc]: reset phy err, return %d\n", ret);
55 return ret;
56 }
57 }
58
59 if (sunxi_udc_io->reset_otg) {
60 ret = reset_control_deassert(sunxi_udc_io->reset_otg);
61 if (ret) {
62 DMSG_PANIC("[udc]: reset otg err, return %d\n", ret);
63 return ret;
64 }
65 }
66
67 if (sunxi_udc_io->clk_bus_otg) {
68 ret = clk_prepare_enable(sunxi_udc_io->clk_bus_otg);
69 if (ret) {
70 DMSG_PANIC("[udc]: enable clk_bus_otg err, return %d\n", ret);
71 return ret;
72 }
73 }
74
75 udelay(10);
76
77 if (sunxi_udc_io->clk_phy) {
78 ret = clk_prepare_enable(sunxi_udc_io->clk_phy);
79 if (ret) {
80 DMSG_PANIC("[udc]: enable clk_phy err, return %d\n", ret);
81 return ret;
82 }
83 }
84
85 udelay(10);
86
87 sunxi_udc_io->clk_is_open = 1;
88 }
89
90 #if defined(CONFIG_ARCH_SUN50IW10) || defined(CONFIG_ARCH_SUN50IW11)\
91 || defined(CONFIG_ARCH_SUN8IW20) || defined(CONFIG_ARCH_SUN20IW1)\
92 || defined(CONFIG_ARCH_SUN5OIW12)
93 USBC_PHY_Clear_Ctl(sunxi_udc_io->usb_vbase, USBC_PHY_CTL_LOOPBACKENB);
94 #endif
95
96 #if defined(CONFIG_ARCH_SUN8IW12) || defined(CONFIG_ARCH_SUN50IW3) \
97 || defined(CONFIG_ARCH_SUN8IW6) || defined(CONFIG_ARCH_SUN50IW6) \
98 || defined(CONFIG_ARCH_SUN8IW15) || defined(CONFIG_ARCH_SUN50IW8) \
99 || defined(CONFIG_ARCH_SUN8IW18) || defined(CONFIG_ARCH_SUN8IW16) \
100 || defined(CONFIG_ARCH_SUN50IW9) || defined(CONFIG_ARCH_SUN50IW10) \
101 || defined(CONFIG_ARCH_SUN8IW19) || defined(CONFIG_ARCH_SUN50IW11) \
102 || defined(CONFIG_ARCH_SUN8IW20) || defined(CONFIG_ARCH_SUN20IW1) \
103 || defined(CONFIG_ARCH_SUN50IW12)
104 USBC_PHY_Set_Ctl(sunxi_udc_io->usb_vbase, USBC_PHY_CTL_VBUSVLDEXT);
105 USBC_PHY_Clear_Ctl(sunxi_udc_io->usb_vbase, USBC_PHY_CTL_SIDDQ);
106 #else
107 UsbPhyInit(0);
108 #endif
109
110 #if defined(CONFIG_ARCH_SUN50I) || defined(CONFIG_ARCH_SUN8IW10) \
111 || defined(CONFIG_ARCH_SUN8IW11) || defined(CONFIG_ARCH_SUN8IW12) \
112 || defined(CONFIG_ARCH_SUN8IW15) || defined(CONFIG_ARCH_SUN8IW7) \
113 || defined(CONFIG_ARCH_SUN8IW17) || defined(CONFIG_ARCH_SUN8IW18) \
114 || defined(CONFIG_ARCH_SUN8IW16) || defined(CONFIG_ARCH_SUN8IW19) \
115 || defined(CONFIG_ARCH_SUN8IW8) || defined(CONFIG_ARCH_SUN8IW20)\
116 || defined(CONFIG_ARCH_SUN20IW1) || defined(CONFIG_ARCH_SUN50IW12)
117 /* otg and hci0 Controller Shared phy in SUN50I and SUN8IW10 */
118 USBC_SelectPhyToDevice(sunxi_udc_io->usb_vbase);
119 #endif
120
121 #if defined(CONFIG_ARCH_SUN8IW20) || defined(CONFIG_ARCH_SUN20IW1)
122 usbc_new_phy_init(sunxi_udc_io->usb_vbase);
123 #endif
124
125 return 0;
126 }
127
close_usb_clock(sunxi_udc_io_t * sunxi_udc_io)128 u32 close_usb_clock(sunxi_udc_io_t *sunxi_udc_io)
129 {
130 int ret;
131
132 DMSG_INFO_UDC("close_usb_clock\n");
133
134 if (sunxi_udc_io->clk_is_open) {
135 sunxi_udc_io->clk_is_open = 0;
136
137 if (sunxi_udc_io->clk_phy) {
138 ret = clk_prepare_enable(sunxi_udc_io->clk_phy);
139 if (ret) {
140 DMSG_PANIC("[udc]: enable clk_phy err, return %d\n", ret);
141 return ret;
142 }
143 }
144
145 if (sunxi_udc_io->clk_bus_otg) {
146 ret = clk_prepare_enable(sunxi_udc_io->clk_bus_otg);
147 if (ret) {
148 DMSG_PANIC("[udc]: enable clk_bus_otg err, return %d\n", ret);
149 return ret;
150 }
151 }
152
153 if (sunxi_udc_io->reset_otg) {
154 ret = reset_control_deassert(sunxi_udc_io->reset_otg);
155 if (ret) {
156 DMSG_PANIC("[udc]: reset otg err, return %d\n", ret);
157 return ret;
158 }
159 }
160
161 if (sunxi_udc_io->reset_phy) {
162 ret = reset_control_deassert(sunxi_udc_io->reset_phy);
163 if (ret) {
164 DMSG_PANIC("[udc]: reset phy err, return %d\n", ret);
165 return ret;
166 }
167 }
168
169 udelay(10);
170 }
171 #if defined(CONFIG_ARCH_SUN8IW12) || defined(CONFIG_ARCH_SUN50IW3) \
172 || defined(CONFIG_ARCH_SUN8IW6) || defined(CONFIG_ARCH_SUN50IW6) \
173 || defined(CONFIG_ARCH_SUN8IW15) || defined(CONFIG_ARCH_SUN50IW8) \
174 || defined(CONFIG_ARCH_SUN8IW18) || defined(CONFIG_ARCH_SUN8IW16) \
175 || defined(CONFIG_ARCH_SUN50IW9) || defined(CONFIG_ARCH_SUN50IW10) \
176 || defined(CONFIG_ARCH_SUN8IW19) || defined(CONFIG_ARCH_SUN50IW11)\
177 || defined(CONFIG_ARCH_SUN8IW20) || defined(CONFIG_ARCH_SUN20IW1)
178 USBC_PHY_Set_Ctl(sunxi_udc_io->usb_vbase, USBC_PHY_CTL_SIDDQ);
179 #else
180 UsbPhyInit(0);
181 #endif
182
183 return 0;
184 }
185
sunxi_udc_bsp_init(sunxi_udc_io_t * sunxi_udc_io)186 __s32 sunxi_udc_bsp_init(sunxi_udc_io_t *sunxi_udc_io)
187 {
188 spinlock_t lock;
189 unsigned long flags = 0;
190
191 /* open usb lock */
192 open_usb_clock(sunxi_udc_io);
193
194 #ifdef SUNXI_USB_FPGA
195 clear_usb_reg(sunxi_udc_io->usb_vbase);
196 #endif
197
198 USBC_EnhanceSignal(sunxi_udc_io->usb_bsp_hdle);
199
200 USBC_EnableDpDmPullUp(sunxi_udc_io->usb_bsp_hdle);
201 USBC_EnableIdPullUp(sunxi_udc_io->usb_bsp_hdle);
202 USBC_ForceId(sunxi_udc_io->usb_bsp_hdle, USBC_ID_TYPE_DEVICE);
203 USBC_ForceVbusValid(sunxi_udc_io->usb_bsp_hdle, USBC_VBUS_TYPE_HIGH);
204
205 USBC_SelectBus(sunxi_udc_io->usb_bsp_hdle, USBC_IO_TYPE_PIO, 0, 0);
206
207 USBC_PHY_Clear_Ctl(sunxi_udc_io->usb_vbase, 1);
208
209 /* config usb fifo */
210 spin_lock_init(&lock);
211 spin_lock_irqsave(&lock, flags);
212 USBC_ConfigFIFO_Base(sunxi_udc_io->usb_bsp_hdle, USBC_FIFO_MODE_8K);
213 spin_unlock_irqrestore(&lock, flags);
214
215 return 0;
216 }
217
sunxi_udc_bsp_exit(sunxi_udc_io_t * sunxi_udc_io)218 __s32 sunxi_udc_bsp_exit(sunxi_udc_io_t *sunxi_udc_io)
219 {
220 USBC_DisableDpDmPullUp(sunxi_udc_io->usb_bsp_hdle);
221 USBC_DisableIdPullUp(sunxi_udc_io->usb_bsp_hdle);
222 USBC_ForceId(sunxi_udc_io->usb_bsp_hdle, USBC_ID_TYPE_DISABLE);
223 USBC_ForceVbusValid(sunxi_udc_io->usb_bsp_hdle, USBC_VBUS_TYPE_DISABLE);
224
225 close_usb_clock(sunxi_udc_io);
226 return 0;
227 }
228
sunxi_udc_io_init(__u32 usbc_no,sunxi_udc_io_t * sunxi_udc_io)229 __s32 sunxi_udc_io_init(__u32 usbc_no, sunxi_udc_io_t *sunxi_udc_io)
230 {
231 sunxi_udc_io->usbc.usbc_info.num = usbc_no;
232 sunxi_udc_io->usbc.usbc_info.base = sunxi_udc_io->usb_vbase;
233 sunxi_udc_io->usbc.sram_base = sunxi_udc_io->sram_vbase;
234
235 USBC_init(&sunxi_udc_io->usbc);
236 sunxi_udc_io->usb_bsp_hdle = USBC_open_otg(usbc_no);
237 if (sunxi_udc_io->usb_bsp_hdle == 0) {
238 DMSG_PANIC("ERR: sunxi_udc_init: USBC_open_otg failed\n");
239 return -1;
240 }
241
242 return 0;
243 }
244
sunxi_udc_io_exit(sunxi_udc_io_t * sunxi_udc_io)245 __s32 sunxi_udc_io_exit(sunxi_udc_io_t *sunxi_udc_io)
246 {
247 USBC_close_otg(sunxi_udc_io->usb_bsp_hdle);
248 sunxi_udc_io->usb_bsp_hdle = 0;
249 USBC_exit(&sunxi_udc_io->usbc);
250 sunxi_udc_io->usb_vbase = NULL;
251 sunxi_udc_io->sram_vbase = NULL;
252
253 return 0;
254 }
255
256