USB 6.44 KB
Newer Older
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