• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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