diff options
Diffstat (limited to 'firmware/target/arm/as3525/usb-drv-as3525v2.c')
-rw-r--r-- | firmware/target/arm/as3525/usb-drv-as3525v2.c | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/firmware/target/arm/as3525/usb-drv-as3525v2.c b/firmware/target/arm/as3525/usb-drv-as3525v2.c new file mode 100644 index 0000000000..9afe8255e5 --- /dev/null +++ b/firmware/target/arm/as3525/usb-drv-as3525v2.c | |||
@@ -0,0 +1,261 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright © 2010 Amaury Pouly | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include "usb.h" | ||
23 | #include "usb_drv.h" | ||
24 | #include "as3525v2.h" | ||
25 | #include "clock-target.h" | ||
26 | #include "ascodec.h" | ||
27 | #include "as3514.h" | ||
28 | #include <stdbool.h> | ||
29 | #include "panic.h" | ||
30 | #define LOGF_ENABLE | ||
31 | #include "logf.h" | ||
32 | #include "usb-drv-as3525v2.h" | ||
33 | |||
34 | struct usb_endpoint | ||
35 | { | ||
36 | void *buf; | ||
37 | unsigned int len; | ||
38 | union | ||
39 | { | ||
40 | unsigned int sent; | ||
41 | unsigned int received; | ||
42 | }; | ||
43 | bool wait; | ||
44 | bool busy; | ||
45 | }; | ||
46 | |||
47 | static struct usb_endpoint endpoints[USB_NUM_ENDPOINTS*2]; | ||
48 | |||
49 | void usb_attach(void) | ||
50 | { | ||
51 | usb_enable(true); | ||
52 | } | ||
53 | |||
54 | static void usb_delay(void) | ||
55 | { | ||
56 | int i = 0; | ||
57 | while(i < 0x300) | ||
58 | i++; | ||
59 | } | ||
60 | |||
61 | static void as3525v2_connect(void) | ||
62 | { | ||
63 | logf("usb: init as3525v2"); | ||
64 | /* 1) enable usb core clock */ | ||
65 | CGU_PERI |= CGU_USB_CLOCK_ENABLE; | ||
66 | usb_delay(); | ||
67 | /* 2) enable usb phy clock */ | ||
68 | CGU_USB |= 0x20; | ||
69 | usb_delay(); | ||
70 | /* 3) clear "stop pclk" */ | ||
71 | USB_PCGCCTL &= ~0x1; | ||
72 | usb_delay(); | ||
73 | /* 4) clear "power clamp" */ | ||
74 | USB_PCGCCTL &= ~0x4; | ||
75 | usb_delay(); | ||
76 | /* 5) clear "reset power down module" */ | ||
77 | USB_PCGCCTL &= ~0x8; | ||
78 | usb_delay(); | ||
79 | /* 6) set "power on program done" */ | ||
80 | USB_DCTL |= 0x800; | ||
81 | usb_delay(); | ||
82 | /* 7) core soft reset */ | ||
83 | USB_GRSTCTL |= USB_GRSTCTL_csftrst; | ||
84 | usb_delay(); | ||
85 | /* 8) hclk soft reset */ | ||
86 | USB_GRSTCTL |= USB_GRSTCTL_hsftrst; | ||
87 | usb_delay(); | ||
88 | /* 9) flush and reset everything */ | ||
89 | USB_GRSTCTL |= 0x3f; | ||
90 | usb_delay(); | ||
91 | /* 10) force device mode*/ | ||
92 | USB_GUSBCFG &= ~0x20000000; | ||
93 | USB_GUSBCFG |= 0x40000000; | ||
94 | usb_delay(); | ||
95 | /* 11) Do something that is probably CCU related but undocumented*/ | ||
96 | CCU_USB_THINGY &= ~0x1000; | ||
97 | usb_delay(); | ||
98 | /* 12) reset usb core parameters (dev addr, speed, ...) */ | ||
99 | USB_DCFG = 0; | ||
100 | usb_delay(); | ||
101 | } | ||
102 | |||
103 | static void core_reset(void) | ||
104 | { | ||
105 | unsigned int i = 0; | ||
106 | /* Wait for AHB master IDLE state. */ | ||
107 | while((USB_GRSTCTL & USB_GRSTCTL_ahbidle) == 0); | ||
108 | { | ||
109 | /*udelay(10);*/ | ||
110 | sleep(1); | ||
111 | } | ||
112 | /* Core Soft Reset */ | ||
113 | USB_GRSTCTL |= USB_GRSTCTL_csftrst; | ||
114 | /* Waits for the hardware to clear reset bit */ | ||
115 | while(USB_GRSTCTL & USB_GRSTCTL_csftrst && i < 0x300) | ||
116 | i++; | ||
117 | |||
118 | if(USB_GRSTCTL & USB_GRSTCTL_csftrst) | ||
119 | logf("oops, usb core soft reset hang :("); | ||
120 | |||
121 | /* Wait for 3 PHY Clocks */ | ||
122 | /*mdelay(100);*/ | ||
123 | sleep(1); | ||
124 | |||
125 | logf("%ld endpoints", USB_GHWCFG2_NUM_EP); | ||
126 | for(i = 0; i < USB_GHWCFG2_NUM_EP; i++) | ||
127 | logf(" EP%d: IN=%ld OUT=%ld", i, USB_GHWCFG1_IN_EP(i), USB_GHWCFG1_OUT_EP(i)); | ||
128 | logf("hwcfg1: %08lx", USB_GHWCFG1); | ||
129 | logf("hwcfg2: %08lx", USB_GHWCFG2); | ||
130 | logf("hwcfg3: %08lx", USB_GHWCFG3); | ||
131 | logf("hwcfg4: %08lx", USB_GHWCFG4); | ||
132 | |||
133 | logf("%ld in ep", USB_GHWCFG4_NUM_IN_EP); | ||
134 | logf("tot fifo sz: %ld", USB_GHWCFG3_DFIFO_LEN); | ||
135 | logf("rx fifo sz: %ld", USB_GRXFSIZ); | ||
136 | logf("tx fifo sz: %ld", USB_GNPTXFSIZ >> 16); /* there is no perio ep so print only non-perio */ | ||
137 | } | ||
138 | |||
139 | static void core_init(void) | ||
140 | { | ||
141 | /* Reset the Controller */ | ||
142 | core_reset(); | ||
143 | |||
144 | /* Setup phy for high speed */ | ||
145 | /* 1) select utmi */ | ||
146 | /* fixme: the clip+ hardware support utmi only, this is useless */ | ||
147 | //USB_GUSBCFG &= ~USB_GUSBCFG_ulpi_utmi_sel; | ||
148 | /* 2) select utmi 16-bit wide bus */ | ||
149 | USB_GUSBCFG |= USB_GUSBCFG_phy_if; | ||
150 | /* 3) core reset */ | ||
151 | /* fixme: linux patch says the phy parameters survive the soft reset so | ||
152 | * perhaps this part can be done only one type but I don't know | ||
153 | * what happened when phy goes to standby mode and clock are disabled */ | ||
154 | core_reset(); | ||
155 | |||
156 | /* fixme: at this point, the linux patch sets ulpi bits to 0 on utmi selection | ||
157 | * but the clip+ hardware does not support it so don't bother with | ||
158 | * that */ | ||
159 | |||
160 | /* fixme: the current code is for internal DMA only, the clip+ architecture | ||
161 | * define the internal DMA model */ | ||
162 | /* Set burstlen */ | ||
163 | USB_GAHBCFG |= USB_GAHBCFG_INT_DMA_BURST_INCR << USB_GAHBCFG_hburstlen_bit_pos; | ||
164 | /* Enable DMA */ | ||
165 | USB_GAHBCFG |= USB_GAHBCFG_dma_enable; | ||
166 | /* Disable HNP and SRP, not sure it's useful because we already forced dev mode */ | ||
167 | USB_GUSBCFG &= ~(USB_GUSBCFG_SRP_cap | USB_GUSBCFG_HNP_cap); | ||
168 | } | ||
169 | |||
170 | void usb_drv_init(void) | ||
171 | { | ||
172 | logf("usb_drv_init"); | ||
173 | as3525v2_connect(); | ||
174 | |||
175 | logf("usb: synopsis id: %lx", USB_GSNPSID); | ||
176 | |||
177 | core_init(); | ||
178 | } | ||
179 | |||
180 | void usb_drv_exit(void) | ||
181 | { | ||
182 | logf("usb_drv_exit"); | ||
183 | } | ||
184 | |||
185 | int usb_drv_port_speed(void) | ||
186 | { | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | int usb_drv_request_endpoint(int type, int dir) | ||
191 | { | ||
192 | (void) type; | ||
193 | (void) dir; | ||
194 | return -1; | ||
195 | } | ||
196 | |||
197 | void usb_drv_release_endpoint(int ep) | ||
198 | { | ||
199 | (void) ep; | ||
200 | } | ||
201 | |||
202 | void usb_drv_cancel_all_transfers(void) | ||
203 | { | ||
204 | } | ||
205 | |||
206 | int usb_drv_recv(int ep, void *ptr, int len) | ||
207 | { | ||
208 | (void) ep; | ||
209 | (void) ptr; | ||
210 | (void) len; | ||
211 | return -1; | ||
212 | } | ||
213 | |||
214 | int usb_drv_send(int ep, void *ptr, int len) | ||
215 | { | ||
216 | (void) ep; | ||
217 | (void) ptr; | ||
218 | (void) len; | ||
219 | return -1; | ||
220 | } | ||
221 | |||
222 | int usb_drv_send_nonblocking(int ep, void *ptr, int len) | ||
223 | { | ||
224 | (void) ep; | ||
225 | (void) ptr; | ||
226 | (void) len; | ||
227 | return -1; | ||
228 | } | ||
229 | |||
230 | /* interrupt service routine */ | ||
231 | void INT_USB(void) | ||
232 | { | ||
233 | panicf("USB interrupt !"); | ||
234 | } | ||
235 | |||
236 | /* (not essential? , not implemented in usb-tcc.c) */ | ||
237 | void usb_drv_set_test_mode(int mode) | ||
238 | { | ||
239 | (void) mode; | ||
240 | } | ||
241 | |||
242 | void usb_drv_set_address(int address) | ||
243 | { | ||
244 | (void) address; | ||
245 | } | ||
246 | |||
247 | void usb_drv_stall(int ep, bool stall, bool in) | ||
248 | { | ||
249 | (void) ep; | ||
250 | (void) stall; | ||
251 | (void) in; | ||
252 | } | ||
253 | |||
254 | bool usb_drv_stalled(int ep, bool in) | ||
255 | { | ||
256 | (void) ep; | ||
257 | (void) in; | ||
258 | return true; | ||
259 | return true; | ||
260 | } | ||
261 | |||