Messaging 17.9 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
;
; Copyright (c) 2012, RISC OS Open Ltd
; Copyright (c) 2012, John Ballance
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
;     * Redistributions of source code must retain the above copyright
;       notice, this list of conditions and the following disclaimer.
;     * Redistributions in binary form must reproduce the above copyright
;       notice, this list of conditions and the following disclaimer in the
;       documentation and/or other materials provided with the distribution.
;     * Neither the name of RISC OS Open Ltd nor the names of its contributors
;       may be used to endorse or promote products derived from this software
;       without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
; POSSIBILITY OF SUCH DAMAGE.
;
;

        AREA    |ARM$$code|, CODE, READONLY, PIC

        GET     Hdr:ListOpts
34
        GET     Hdr:Macros
35
        GET     Hdr:Proc
36 37 38 39
        GET     Hdr:System
        GET     Hdr:FSNumbers
        GET     Hdr:NewErrors
        GET     Hdr:BCMSupport
40
        $GetMEMM
41 42
        GET     hdr.BCM2835
        GET     hdr.StaticWS
43
        GET     hdr.CastleMacros
44 45 46 47

        IMPORT  workspace

     [ HALDebug
48
        IMPORT  HAL_DebugTX
49 50 51
        IMPORT  HAL_DebugHexTX4
        IMPORT  HAL_DebugTXStrInline
     ]
52
        IMPORT  memcpy
53 54
        EXPORT  HAL_SendHostMessage
        EXPORT  HAL_QueryPlatform
55
        EXPORT  GetVCBuffer
56
        EXPORT  BCMMBox_InitDevices
57

Robert Sprowson's avatar
Robert Sprowson committed
58
; Send a message packet to the host and await the reply
59 60 61 62 63 64 65 66
; on entry, r0 =  message channel to use and/or wholemessage
;           r1 -> message tag buffer, 16 byte aligned. or 0
;
; on exit,  r0 = mailbox response word
;
HAL_SendHostMessage  ROUT
        STMFD   r13!, {r1-r3, lr}
        DoMemBarrier r3
67
        FlushDataCache ; corrupts r2,r3,lr
68 69 70 71 72 73 74 75 76
        LDR     r3, PeriBase
        ADD     r3, r3, #MB_Base
; check we can send a message
001     LDR     r2,[r3, #MB_Sta]
        TST     r2, #MB_Sta_Full
        BNE     %BT001                ; write channel full
; send message
        TEQ     r1, #0
        BICNE   r1, r1, #&c0000000
77 78
        LDRNE   r2, FB_CacheMode
        ORRNE   r1, r1, r2
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
        ORR     r2, r0, r1
        AND     r1, r0, #&f            ; isolate channel number
        STR     r2,[r3, #MB_ChWr]
; await response and check it is ours
002     LDR     r0,[r3, #MB_Sta]
        TST     r0, #MB_Sta_Empty
        BNE     %BT002                ; still empty
        LDR     r0,[r3,#MB_ChRd]
        AND     r2, r0, #&f
        CMP     r2, r1                ; check its is our channel
        BNE     %BT002                ; not our reply
        DoMemBarrier r3
        LDMFD   r13!, {r1-r3, pc}     ; returning composite response in r0

; Interrogate the platform and set up basic machine
; Sets up L2 cache addressing mode
;         ARM_Memory_MB (in Megabytes)
;         Frame buffer base address for 32bit fb
;         Board_MAC address
;         Board_Serial
99 100
;         Board model & revision
;         Available DMA channels
101 102
;
HAL_QueryPlatform    ROUT
Robert Sprowson's avatar
Robert Sprowson committed
103
        STMFD   R13!, {r0-r6, lr}
Jeffrey Lee's avatar
Jeffrey Lee committed
104
        CPUDetect r4
Robert Sprowson's avatar
Robert Sprowson committed
105 106 107
        MOVCC   r4, #GPU_L2CnonAl              ; Pi 1 has L2 cache enabled
        MOVCS   r4, #GPU_UnCached              ; Pi 2 has L2 cache disabled
        STR     r4, FB_CacheMode               ; remember base of bus addresses (i.e. memory accessed by GPU and GPU peripherals like DMA and USB)
108

Robert Sprowson's avatar
Robert Sprowson committed
109 110 111
        ADRL    r0, tagbuffer
        ADR     r1, tagb
        MOV     r2, #tagslen
Robert Sprowson's avatar
Robert Sprowson committed
112
        BL      memcpy                         ; copy to workspace buffer
113

Robert Sprowson's avatar
Robert Sprowson committed
114
        MOV     r1, r0
115
        MOV     r0, #MB_Chan_ARM2VC
116
        BL      HAL_SendHostMessage            ; ask the questions
117

118
        ADRL    r5, tagbuffer                  ; now read the answers
119 120 121 122
        LDR     r0, [r5, #emmc_clk-tagb]
        LDR     r1, [r5, #core_clk-tagb]
        STR     r0, EMMCClock
        STR     r1, CoreClock
123 124 125 126
        ADD     r0,r5,#VCbs-tagb               ; VC address and size
        LDMIA   r0, {r1, r2}
        STR     r1, VC_Base
        STR     r2, VC_Size
Robert Sprowson's avatar
Robert Sprowson committed
127 128 129
        ADD     r0,r5,#ARMbs-tagb              ; ARM address and size
        LDMIA   r0, {r1, r2}
        STR     r1, ARM_Base
Ben Avison's avatar
Ben Avison committed
130 131 132 133
        ADD     r2, r1, r2
        STR     r2, ARM_End
        STR     r2, ARM_Base2
        STR     r2, ARM_End2
134 135 136 137 138
        LDR     r0, [r5, #boardmodel-tagb]
        LDR     r1, [r5, #boardrev-tagb]
        LDR     r2, [r5, #dmachans-tagb]
        STR     r0, Board_Model
        STR     r1, Board_Revision
Ben Avison's avatar
Ben Avison committed
139 140 141 142 143 144 145 146 147 148 149 150 151
        ; Presence and size of second bank of general-purpose RAM has to be
        ; established from the board revision bitfield
        TST     r1, #BoardRevision_NewScheme
        BEQ     %FT01
        AND     r1, r1, #BoardRevision_Mem_Mask
        CMP     r1, #BoardRevision_Mem_2G
        BLO     %FT01
        MOV     r0, #&40000000
        MOVEQ   r1, #&80000000
        MOVHI   r1, #IO_Base2_BCM2838
        STR     r0, ARM_Base2
        STR     r1, ARM_End2
01
152 153 154 155
        ; If no channels are reported as available, use channel 4
        ; (Matches default channel mask from Linux)
        CMP     r2, #0
        MOVEQ   r2, #1<<4
156
        STR     r2, ARM_DMAChannels
157

Robert Sprowson's avatar
Robert Sprowson committed
158 159 160
        ; Copy out and construct machine ID from MAC address
        ADRL    a3, tagbuffer
        ADD     a3, a3,#:INDEX:MAClo-:INDEX:tagb
161 162 163 164 165 166 167 168 169 170
        LDR     lr, [a3, #-4]       ; check if message completed
        TST     lr, #&80000000      ; NE if successful
        MOVEQ   a1, #0
        MOVEQ   a2, #0

        LDMNEIA a3, {a1, a2}
        AND     a3, a1, #&ff000000
        MOV     a3, a3, LSR #24
        ORR     a2, a3, a2, LSL #8
        MOV     a1, a1, LSL #8
Robert Sprowson's avatar
Robert Sprowson committed
171
        ORR     a1, a1, #&81           ; make it look like a Dallas unique id
172
        BIC     a2, a2, #&ff000000
Robert Sprowson's avatar
Robert Sprowson committed
173 174

        MOV     a3, #0                 ; compute a Dallas unique id CRC
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
        MOV     a4, #7                 ; number of bytes to do
gbyte                                  ;
        AND     v2, a1, #&ff           ; get next byte. shift reg round 8 byte
        AND     v3, a2, #&ff           ; shift reg round 8 byte
        MOV     v1, v2, lsl #24
        MOV     v3, v3, lsl #24
        ORR     a1, v3, a1,lsr #8      ; shift reg round 8 byte
        ORR     a2, v1, a2,lsr #8      ; shift reg round 8 byte

        EOR     a3, a3, v2             ;
        MOV     v1, #8                 ; number of bits to do
gbit                                   ;
        MOVS    a3, a3, LSR #1         ; shift bit out into carry
        EORCS   a3, a3, #&8C           ; feedback carry into other bits
        SUBS    v1, v1, #1             ; one less bit to do
        BNE     gbit                   ; loop until done whole byte
        SUBS    a4, a4, #1             ; one less byte to do
        BNE     gbyte                  ; loop until done all 7 bytes

        AND     v2, a1, #&ff           ; get next byte. shift reg round 8 byte
        AND     v3, a2, #&ff           ; shift reg round 8 byte
        MOV     v1, v2, lsl #24
        MOV     v3, v3, lsl #24
        ORR     a1, v3, a1,lsr #8      ; shift reg round 8 byte
        ORR     a2, v1, a2,lsr #8      ; shift reg round 8 byte

        ORR     a2, a2, a3, lsl #24    ; insert crc into hi byte
        ADRL    lr,MachineID
        STMIA   lr, {a1, a2}
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226

        ; Check if it's a Compute Module 3, to decide whether to probe CM3 .v. CM3L
        LDR     a4, Board_Revision
        AND     a4, a4, #BoardRevision_Model_Mask
        CMP     a4, #BoardRevision_Model_Compute3
        BNE     %FT10

        ADRL    a1, tagbuffer
        ADR     a2, tagbcm3
        MOV     a3, #tagslencm3
        BL      memcpy                         ; copy to workspace buffer

        MOV     a2, a1
        MOV     a1, #MB_Chan_ARM2VC
        BL      HAL_SendHostMessage            ; ask the questions

        ADRL    a4, tagbuffer                  ; now read the answers
        LDR     a1, [a4, #4]
        TEQ     a1, #&80000000                 ; firmware new enough to accept all the tags?
        LDREQ   a1, [a4, #safcat-tagbcm3]
        MOVNE   a1, #-1
        STR     a1, SafetyCatch
10
Robert Sprowson's avatar
Robert Sprowson committed
227
        LDMFD   R13!, {r0-r6, pc}
228

229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
; In:
;   a1 = GET tag to fetch buffer for
;   a2 = buffer size
;   a3 = corresponding SET tag
; Out:
;   a1 = buffer logical address, 0 if not present
;   a2-a4, ip corrupt
;
; Query the VC for a data buffer. Historically the VC has dictated the locations
; of these buffers, but at some point the ability was added for the ARM to
; dictate the address to the GPU. With recent firmware versions, use of this
; feature is now mandatory, as on systems with 1GB of RAM the firmware will now
; attempt to make use of the upper 16MB of RAM (which overlaps the ARM's IO
; space, making it inaccessible to the ARM)
;
; Annoyingly, the main tags we're interested in don't follow the usual pattern
; of adding &8000 in order to convert a GET request to a SET, so we require both
; the GET and SET values to be explicitly specified.
GetVCBuffer     ROUT
      [ HALDebug
        STR     lr, [sp, #-4]!
        BL      %FT01
        BL      HAL_DebugHexTX4
        BL      HAL_DebugTXStrInline
        DCB     "log",10,0
        ALIGN
        LDR     pc, [sp], #4
01
      ]
        STMFD   sp!, {a1-a2, lr}
      [ HALDebug
        BL      HAL_DebugHexTX4
        BL      HAL_DebugTXStrInline
        DCB     "GetVCBuffer",10,0
        ALIGN
      ]
        MOV     a1, a3                  ; Start off with the SET request
        ; Reserve space for the buffer in NCNB workspace
        LDR     ip, NCNBPhysAddr
        LDR     a4, NCNBAddr
        MOV     a3, a2
        MOV     lr, #0
10
        SUBS    a3, a3, #4
        STRGE   lr, [a4, a3]            ; Ensure buffer memory is zeroed, just in case ARM/VC is confused by any previous content (like a tag buffer from a previous call to GetVCBuffer). E.g. recent firmware versions will allow you to get/set the FT5406 touchscreen buffer, even if the touchscreen isn't connected.
        BGT     %BT10
        ADD     a3, ip, a2
        ADD     a4, a4, a2
        ; Now construct a message tag block after it
        ADD     a3, a3, #15             ; Align for mailbox use
        ADD     a4, a4, #15
        BIC     a3, a3, #15
        BIC     a4, a4, #15
        STR     a1, [a4, #8]            ; Tag
        MOV     a1, #7*4
        MOV     a2, #0
        STMIA   a4!, {a1, a2}           ; Total length, out flags
        MOV     a1, #4
        MOV     a2, #4
        MOV     lr, #ARM2VC_Tag_End
        STMIB   a4, {a1, a2, ip, lr}    ; Tag length, in length, in data, terminator
        MOV     a2, a3
        MOV     a1, #MB_Chan_ARM2VC
        BL      HAL_SendHostMessage
      [ HALDebug
        LDR     a1, [a4, #-8]
        BL      HAL_DebugHexTX4
        LDR     a1, [a4, #-4]
        BL      HAL_DebugHexTX4
        LDR     a1, [a4, #0]
        BL      HAL_DebugHexTX4
        LDR     a1, [a4, #4]
        BL      HAL_DebugHexTX4
        LDR     a1, [a4, #8]
        BL      HAL_DebugHexTX4
        LDR     a1, [a4, #12]
        BL      HAL_DebugHexTX4
        LDR     a1, [a4, #16]
        BL      HAL_DebugHexTX4
        BL      HAL_DebugTXStrInline
        DCB     "set",10,0
        ALIGN
      ]
        ; On success, firmware should overwrite the address with zero
        LDR     a1, [a4, #12]
        CMP     a1, #0
        BNE     %FT50
        ; Buffer set success; update NCNB claim and return the claimed addr
        LDMIA   sp!, {a1-a2, lr}
        LDR     a1, NCNBAddr
        LDR     ip, NCNBPhysAddr
        ADD     a3, a1, a2
        ADD     ip, ip, a2
        STR     a3, NCNBAddr
        STR     ip, NCNBPhysAddr
        MOV     pc, lr
50
        ; Buffer set failure. Try getting the address instead.
        MOV     a1, #7*4
        MOV     a2, #0
        STMDB   a4, {a1, a2}            ; Total length, out flags
        LDR     a1, [sp]
        MOV     a2, #4
        MOV     ip, #0
        MOV     lr, #0
        STMIA   a4, {a1, a2, ip, lr}    ; Tag, tag length, in length, in data
                                        ; n.b. assuming terminator word still in place!
        MOV     a2, a3
        MOV     a1, #MB_Chan_ARM2VC
        BL      HAL_SendHostMessage
      [ HALDebug
        LDR     a1, [a4, #-8]
        BL      HAL_DebugHexTX4
        LDR     a1, [a4, #-4]
        BL      HAL_DebugHexTX4
        LDR     a1, [a4, #0]
        BL      HAL_DebugHexTX4
        LDR     a1, [a4, #4]
        BL      HAL_DebugHexTX4
        LDR     a1, [a4, #8]
        BL      HAL_DebugHexTX4
        LDR     a1, [a4, #12]
        BL      HAL_DebugHexTX4
        LDR     a1, [a4, #16]
        BL      HAL_DebugHexTX4
        BL      HAL_DebugTXStrInline
        DCB     "get",10,0
        ALIGN
      ]
        ; On success, firmware should write non-zero address
        LDR     a1, [a4, #12]
        BICS    a1, a1, #&c0000000      ; Convert to ARM phys addr
        LDMIA   sp!, {a2-a3, lr}        ; Junk stacked a1-a2, but also loads a2 into correct reg for OS_MapInIO
        MOVEQ   pc, lr
        ; Buffer exists, map it in
        MOV     a2, a1
        MOV     a1, #1:SHL:L1_TEXShift  ; VMSA Normal, non-cacheable
        CallOS  OS_MapInIO, tailcall


Robert Sprowson's avatar
Robert Sprowson committed
369
; Series of VC side query tags.
370 371 372
;
tagb    DCD     tagslen
        DCD     0
Robert Sprowson's avatar
Robert Sprowson committed
373 374

        DCD     ARM2VC_Tag_GetBoardMAC
375 376 377 378
        DCD     8
        DCD     0
MAClo   DCD     0
MAChi   DCD     0
Robert Sprowson's avatar
Robert Sprowson committed
379

380 381 382 383 384
        DCD     ARM2VC_Tag_GetBoardSerial
        DCD     8
        DCD     0
SNlo    DCD     0
SNhi    DCD     0
Robert Sprowson's avatar
Robert Sprowson committed
385

386 387 388 389 390
        DCD     ARM2VC_Tag_GetARMMemory
        DCD     8
        DCD     0
ARMbs   DCD     0
ARMsz   DCD     0
Robert Sprowson's avatar
Robert Sprowson committed
391

392 393 394 395 396
        DCD     ARM2VC_Tag_GetVCMemory
        DCD     8
        DCD     0
VCbs    DCD     0
VCsz    DCD     0
Robert Sprowson's avatar
Robert Sprowson committed
397

398 399 400 401
        DCD     ARM2VC_Tag_GetBoardModel
        DCD     4
        DCD     0
boardmodel DCD  0
Robert Sprowson's avatar
Robert Sprowson committed
402

403 404 405 406
        DCD     ARM2VC_Tag_GetBoardRevision
        DCD     4
        DCD     0
boardrev DCD    0
Robert Sprowson's avatar
Robert Sprowson committed
407

408 409 410 411
        DCD     ARM2VC_Tag_GetDMAChannels
        DCD     4
        DCD     0
dmachans DCD    0
412
        DCD     ARM2VC_Tag_FBBlank
413 414
        DCD     4
        DCD     4
415
        DCD     1 ; Start with the screen blanked (avoids firmware displaying an RGB square)
416 417 418 419 420 421 422 423 424 425
        DCD     ARM2VC_Tag_GetClockRate
        DCD     8
        DCD     8
        DCD     BaseClockID_EMMC
emmc_clk DCD    0 ; space for rate in Hz
        DCD     ARM2VC_Tag_GetClockRate
        DCD     8
        DCD     8
        DCD     BaseClockID_CORE
core_clk DCD    0 ; space for rate in Hz
426 427 428
        DCD     ARM2VC_Tag_SetClockRate
        DCD     12
        DCD     12
429
        DCD     BaseClockID_UART
430 431
        DCD     3000000 ; Reset PL011 UART clock to default (Pi 3 has this set to 48MHz for BT, but currently we want to use it for plain serial)
        DCD     0
432
        DCD     ARM2VC_Tag_End
433
tagslen *       . - tagb
434
        ASSERT  tagslen <= ?tagbuffer
435

436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
; Extra series of VC side query tags for CM3.
;
tagbcm3 DCD     tagslencm3
        DCD     0

        DCD     ARM2VC_Tag_SetExtGPIOConfig
        DCD     24
        DCD     0
        DCD     128+6 ; Expander IO6. Only relevant on Compute 3.
        DCD     0     ; Configure pin on FXL6408 (U8) as input with weak pullup
        DCD     0
        DCD     1
        DCD     1
        DCD     -1

        DCD     ARM2VC_Tag_GetExtGPIOState
        DCD     8
        DCD     0
        DCD     128+6
safcat  DCD     -1    ; Sampled state, default high

        DCD     ARM2VC_Tag_End
tagslencm3 *    . - tagbcm3
        ASSERT  tagslencm3 <= ?tagbuffer

461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
        MACRO
$class  HALDeviceField $field, $value
        LCLS    myvalue
      [ "$value" = ""
myvalue SETS    "$field"
      |
myvalue SETS    "$value"
      ]
        ASSERT  . - %A0 = HALDevice_$class$field
     [ ?HALDevice_$class$field = 2
        DCW     $myvalue
   ELIF ?HALDevice_$class$field = 4
        DCD     $myvalue
      |
        %       ?HALDevice_$class$field
      ]
        MEND


; Template for mailbox device

BCMMBox_Dev
0
        HALDeviceField Type,               HALDeviceType_Comms + HALDeviceComms_InterProc
        HALDeviceField ID,                 HALDeviceID_InterProc_BCMMBox
        HALDeviceField Location,           HALDeviceBus_Sys + HALDeviceSysBus_AHB ; Guess
        HALDeviceField Version,            0
        HALDeviceField Description,        BCMMBox_Description
        HALDeviceField Address,            0
        HALDeviceField Reserved1,          0
        HALDeviceField Activate,           BCMMBox_Activate
        HALDeviceField Deactivate,         BCMMBox_Deactivate
        HALDeviceField Reset,              BCMMBox_Reset
        HALDeviceField Sleep,              BCMMBox_Sleep
        HALDeviceField Device,             iDev_ARM_Mbx
        HALDeviceField TestIRQ,            0
        HALDeviceField ClearIRQ,           0
        HALDeviceField Reserved2,          0
        ASSERT  . - %A0 = HALDeviceSize

BCMMBox_Description
        = "BCM283x VideoCore mailboxes", 0

        ALIGN

        ; Initialise our HAL devices
BCMMBox_InitDevices ROUT
        Entry
        ADRL    a1, MBoxDevice
        ADR     a2, BCMMBox_Dev
        MOV     a3, #HALDeviceSize
        BL      memcpy
        ADRL    a2, MBoxDevice
        LDR     a1, PeriBase
        ADD     a1, a1, #MB_Base
        STR     a1, [a2, #HALDevice_Address]
        MOV     a1, #0
        MOV     lr, pc
        LDR     pc, OSentries+4*OS_AddDevice
        EXIT
521

522 523 524 525 526
BCMMBox_Activate
        MOV     a1, #1
BCMMBox_Deactivate
BCMMBox_Reset
        MOV     pc, lr
527

528 529 530
BCMMBox_Sleep
        MOV     a1, #0
        MOV     pc, lr
531 532 533

                END