1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
; Copyright 2009 Castle Technology Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
GET Hdr:ListOpts
GET Hdr:Macros
GET Hdr:System
GET Hdr:Machine.<Machine>
GET Hdr:ImageSize.<ImageSize>
$GetIO
GET Hdr:OSEntries
GET Hdr:HALEntries
GET hdr.omap3530
GET hdr.StaticWS
GET hdr.Timers
GET hdr.PRCM
GET hdr.USB
GET hdr.GPIO
AREA |Asm$$Code|, CODE, READONLY, PIC
EXPORT USB_Init
EXPORT HAL_USBControllerInfo
EXPORT HAL_USBPortPower
EXPORT HAL_USBPortStatus
EXPORT HAL_USBPortIRQ
IMPORT HAL_CounterDelay
IMPORT DebugHALPrintReg
; USB PHY power is controlled via GPIO
USB2_PHY_GPIO * 147
USB2_PHY_Ptr * L4_GPIO_Table+4*(USB2_PHY_GPIO>>5)
USB2_PHY_Pin * 1 :SHL: (USB2_PHY_GPIO :AND: 31)
USB2_PHY_Reset_delay * 10000 ; 10msec
OHCI_IRQ * 76
EHCI_IRQ * 77
USB_Init
Push "lr"
; Initialise USB
; This assumes we're running on a rev C beagleboard, i.e. we're using EHCI via an external PHY
; This provides us with two ports, although the board only has a transceiver & connector for one (port #2)
; This code is roughly the same as omap_start_ehc() in the linux sources
; First program DPLL5
; Like linux, we assume that the input clock is 13MHz!
LDR a1, L4_ClockMan_Log
LDR a2, =(12 :OR: (120:SHL:8))
LDR a3, =CM_CLKSEL4_PLL
STR a2, [a1, a3]
MOV a2, #1
LDR a3, =CM_CLKSEL5_PLL
STR a2, [a1, a3]
MOV a2, #&77
LDR a3, =CM_CLKEN2_PLL
STR a2, [a1, a3]
; Wait for lock
5
LDR a3, =CM_IDLEST2_CKGEN
LDR a2, [a1, a3]
TST a2, #1
BEQ %BT5
; Set up autoidle/sleep mode stuff for USBHOST
MOV a2, #0
LDR a3, =CM_AUTOIDLE_USBHOST
STR a2, [a1, a3]
LDR a3, =CM_SLEEPDEP_USBHOST
STR a2, [a1, a3]
LDR a3, =CM_CLKSTCTRL_USBHOST
STR a2, [a1, a3]
; Enable the clocks
MOV a2, #1
LDR a3, =CM_ICLKEN_USBHOST
STR a2, [a1, a3]
MOV a2, #3
LDR a3, =CM_FCLKEN_USBHOST
STR a2, [a1, a3]
; Bring the external PHY out of reset
LDR a3, USB2_PHY_Ptr
LDR a1, [a3, #GPIO_OE]
MOV a2, #USB2_PHY_Pin
BIC a1, a1, a2
STR a1, [a3, #GPIO_OE] ; Set GPIO pin to output
STR a2, [a3, #GPIO_CLEARDATAOUT] ; Set pin to 0 to place PHY in reset
; Wait a while
LDR a1, =USB2_PHY_Reset_delay
BL HAL_CounterDelay
; Disable the integrated STP pull-up resistor
LDR a1, L4_USB_Host_Log
ADD a2, a1, #EHCI_BASE
LDR a3, =&81870090 ; Write 0x90 to port 1 addr 7 (surely this should be port 2?)
STR a3, [a2, #EHCI_INSNREG05_ULPI]
; Wait
5
LDR a3, [a2, #EHCI_INSNREG05_ULPI]
TST a3, #&80000000
BEQ %BT5
; Force PHY to HS
LDR a3, =&81840040 ; Write 0x40 to port 1 addr 4
STR a3, [a2, #EHCI_INSNREG05_ULPI]
; Wait
5
LDR a3, [a2, #EHCI_INSNREG05_ULPI]
TST a3, #&80000000
BEQ %BT5
; Enable USBHOST TLL clocks
LDR a1, L4_ClockMan_Log
LDR a2, =CM_FCLKEN3_CORE
LDR a3, [a1, a2]
ORR a3, a3, #1:SHL:2 ; EN_USBTLL
STR a3, [a1, a2]
LDR a2, =CM_ICLKEN3_CORE
LDR a3, [a1, a2]
ORR a3, a3, #1:SHL:2 ; EN_USBTLL
STR a3, [a1, a2]
; Disable auto-idle
LDR a2, =CM_AUTOIDLE3_CORE
LDR a3, [a1, a2]
BIC a3, a3, #1:SHL:2
STR a3, [a1, a2]
; Wait for TLL to become active
5
LDR a2, =CM_IDLEST3_CORE
LDR a3, [a1, a2]
TST a3, #1:SHL:2
BNE %BT5
; TLL soft reset
LDR a1, L4_USBTLL_Log
MOV a2, #2
STR a2, [a1, #USBTLL_SYSCONFIG]
5
LDR a2, [a1, #USBTLL_SYSSTATUS]
TST a2, #1
BEQ %BT5
; Disable auto-idle, enable wakeup
MOV a2, #&10C
STR a2, [a1, #USBTLL_SYSCONFIG]
; Now configure UHH
; no auto-idle/standby
LDR a1, L4_USB_Host_Log
LDR a2, =&110C
STR a2, [a1, #UHH_SYSCONFIG]
; Configure for UPLI PHY mode
MOV a2, #&1C ; ULPI bypass enabled, INCR4/8/16 bursts enabled
STR a2, [a1, #UHH_HOSTCONFIG]
5
LDR a2, [a1, #UHH_HOSTCONFIG]
TST a2, #1
BNE %BT5
; Wait for things to settle
LDR a1, =USB2_PHY_Reset_delay
BL HAL_CounterDelay
; Now wake up the PHY
LDR a3, USB2_PHY_Ptr
MOV a2, #USB2_PHY_Pin
STR a2, [a3, #GPIO_SETDATAOUT]
; Success!
Pull "pc"
; a1 = interface #
; a2 = usbinfo ptr
; a3 = sizeof(usbinfo)
; Return sizeof(usbinfo) or 0 for fail
HAL_USBControllerInfo
CMP a1, #0
CMPEQ a3, #USBINFO_SIZEOF
MOVNE a1, #0
MOVNE pc, lr
; Fill in the usbinfo struct
MOV a1, #1 ; EHCI
STR a1, [a2, #USBINFO_TYPE]
MOV a1, #USBINFO_FLAG_32bit_Regs ; EHCI did seem to work OK without forcing 32bit register access, but it is technically needed so I'll leave it set.
STR a1, [a2, #USBINFO_FLAGS]
LDR a1, L4_USB_Host_Log
ADD a1, a1, #EHCI_BASE
STR a1, [a2, #USBINFO_HW]
MOV a1, #EHCI_IRQ
STR a1, [a2, #USBINFO_DEVNO]
MOV a1, #USBINFO_SIZEOF
MOV pc, lr
; These are unused for EHCI
HAL_USBPortPower
HAL_USBPortStatus
HAL_USBPortIRQ
MOV a1, #-1
MOV pc, lr
END