Commit 932e3f57 authored by Ben Avison's avatar Ben Avison Committed by ROOL

Minimal read-write support for mini-UART

Because the mini-UART clock is derived from the core clock, and this varies
by hardware platform and even firmware version, move the initial mailbox
read to before UART initialisation so that this information is available.
parent 0821d828
......@@ -42,6 +42,15 @@ Debug SETL {FALSE}
GBLL HALDebug
HALDebug SETL {FALSE} :LAND: Debug
; Drive the GPIO serial pins using 16550-like mini-UART, rather than
; the PL011-line UART0. The mini-uart is less capable in many ways
; (less configurable, smaller FIFOs, can't cope with VPU clock varying)
; so we may eventaully want to follow the default Raspbian behaviour of
; only using it for boards where UART0 is better used to drive the
; Bluetooth chip. This would invole changing this to a run-time switch.
GBLL MiniUART
MiniUART SETL {FALSE}
; Enable JTAG support
;
; This reconfigures GPIO22-27 into alt4 mode, which maps the ARM JTAG
......
......@@ -128,6 +128,8 @@ Board_Revision # 4
ARM_DMAChannels # 4
VirtGPIOBuf # 4
SafetyCatch # 4 ; Only valid on Compute Module 3
EMMCClock # 4
CoreClock # 4
; align to 16 byte boundary NB this isnt aligned once hal initialised
# (((:INDEX:@)+15):AND::NOT:15)-(:INDEX:@)
......
......@@ -82,4 +82,77 @@ UI_TX * 5 ; TX FIFO empty threshold crossed
UI_RX * 4 ; RX FIFO full threshold crossed
UI_CTS * 1 ; CTS
; MiniUART register bits
; AUXIRQ, AUXENB bits
AIE_SPI2 * 1:SHL:2
AIE_SPI1 * 1:SHL:1
AIE_MU * 1:SHL:0
; AUX_MU_IER bits
IER_RX * 1:SHL:1
IER_TX * 1:SHL:0
; AUX_MU_IIR bits
IIR_INTID_NONE * 0:SHL:1
IIR_INTID_TX * 1:SHL:1
IIR_INTID_RX * 2:SHL:1
IIR_INTID_MASK * 3:SHL:1
IIR_FIFOCLR_RX * 1:SHL:1
IIR_FIFOCLR_TX * 1:SHL:2
IIR_INTPEND * 1:SHL:0
; AUX_MU_LCR bits
LCR_DLAB * 1:SHL:7
LCR_BREAK * 1:SHL:6
LCR_7BIT * 2:SHL:0
LCR_8BIT * 3:SHL:0
; AUX_MU_MCR bits
MCR_RTS * 1:SHL:1
; AUX_MU_LSR bits
LSR_TXIDLE * 1:SHL:6
LSR_TXEMPTY * 1:SHL:5
LSR_RXORUN * 1:SHL:1
LSR_DATARDY * 1:SHL:0
; AUX_MU_MSR bits
MSR_CTS * 1:SHL:5
; AUX_MU_CNTL bits
CNTL_CTSINV * 1:SHL:7
CNTL_RTSINV * 1:SHL:6
CNTL_RTSLVL3 * 0:SHL:4
CNTL_RTSLVL2 * 1:SHL:4
CNTL_RTSLVL1 * 2:SHL:4
CNTL_RTSLVL4 * 3:SHL:4
CNTL_RTSLVLMASK * 3:SHL:4
CNTL_TXAUTO * 1:SHL:3
CNTL_RXAUTO * 1:SHL:2
CNTL_TXEN * 1:SHL:1
CNTL_RXEN * 1:SHL:0
; AUX_MU_STAT bits
STAT_TXFIFOLVL * &F:SHL:24
STAT_RXFIFOLVL * &F:SHL:16
STAT_TXDONE * 1:SHL:9
STAT_TXFIFOEMPTY * 1:SHL:8
STAT_CTS * 1:SHL:7
STAT_RTS * 1:SHL:6
STAT_TXFIFOFULL * 1:SHL:5
STAT_RXORUN * 1:SHL:4
STAT_TXIDLE * 1:SHL:3
STAT_RXIDLE * 1:SHL:2
STAT_TXFIFONOTFULL * 1:SHL:1
STAT_RXFIFONOTEMPTY * 1:SHL:0
END
......@@ -121,6 +121,10 @@ HAL_QueryPlatform ROUT
BL HAL_SendHostMessage ; ask the questions
ADRL r5, tagbuffer ; now read the answers
LDR r0, [r5, #emmc_clk-tagb]
LDR r1, [r5, #core_clk-tagb]
STR r0, EMMCClock
STR r1, CoreClock
ADD r0,r5,#VCbs-tagb ; VC address and size
LDMIA r0, {r1, r2}
STR r1, VC_Base
......@@ -403,10 +407,20 @@ dmachans DCD 0
DCD 4
DCD 4
DCD 1 ; Start with the screen blanked (avoids firmware displaying an RGB square)
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
DCD ARM2VC_Tag_SetClockRate
DCD 12
DCD 12
DCD 2
DCD BaseClockID_UART
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
DCD ARM2VC_Tag_End
......
......@@ -261,6 +261,9 @@ start
LDRHI r4,=IO_Base2_BCM2838
STRHI r4,PeriBase2
; Query the platform
BL HAL_QueryPlatform
[ HALDebug
mov a1, #0
bl HAL_UARTStartUp ; start early for debug use
......@@ -297,9 +300,6 @@ start
LDR a3, =?SimulatedCMOS
BL memcpy
; Query the platform
BL HAL_QueryPlatform
[ HALDebug
bl HAL_DebugTXStrInline
DCB "HalStartup2",10,0
......@@ -747,16 +747,6 @@ HAL_Init
CallOS OS_MapInIO
STR a1, PeriBase2
06
[ Debug
MOV a1,#0 ; start the uart ..we use it for debug
BL HAL_UARTStartUp ; restart to capture logical io address
[ HALDebug
bl HAL_DebugTXStrInline
DCB "HalStart from OS",10,0
ALIGN
]
]
; Recover various values that are now trapped in ROM from when the workspace
; and ROM overlapped prior to relocation. Copy them into RW memory at sb.
ADRL a4, workspace ; where they are post ROM relocation
......@@ -787,6 +777,20 @@ HAL_Init
MOVS a3, a3
BNE .
LDR a3, [a4, #:INDEX:EMMCClock]
LDR a2, [a4, #:INDEX:CoreClock]
STR a3, EMMCClock
STR a2, CoreClock
[ Debug
MOV a1,#0 ; start the uart ..we use it for debug
BL HAL_UARTStartUp ; restart to capture logical io address
[ HALDebug
bl HAL_DebugTXStrInline
DCB "HalStart from OS",10,0
ALIGN
]
]
[ HALDebug
LDR a1, VC_Base
BL HAL_DebugHexTX4
......
......@@ -82,10 +82,16 @@ r SETS "$reg"
r SETS "a1"
]
LDR $r, PeriBase
[ MiniUART
ADD $r, $r, #AUXIO_Base :AND: :NOT: &FFFF
ADD $r, $r, #AUXIO_Base :AND: &FFFF
|
ADD $r, $r, #UART_Base :AND: :NOT: &FFFF
ADD $r, $r, #UART_Base :AND: &FFFF
]
MEND
[ :LNOT: MiniUART
; Stop the UART and wait for it to become idle
; Required before modifying UARTIBRD, UARTFBRD, UARTLCRH
MACRO
......@@ -106,6 +112,7 @@ r SETS "a1"
ORR $temp, $temp, #CR_UARTEN
STR $temp, [a1,#UARTCR]
MEND
]
; int HAL_UARTPorts(void)
;
......@@ -126,6 +133,34 @@ HAL_UARTStartUp
ORR a2, a2, #8_77000000 ; set GPIO 16 + 17 to alt3 (111)
]
BIC a2, a2, #8_00770000 ;
[ MiniUART
ORR a2, a2, #8_00220000 ; set GPIO 14 + 15 to alt5 (010)
STR a2, [a3, #GPFSel1] ;
DataSyncBarrier a2 ; resync before writing peripheral
BaseAddr
; Enable mini-UART registers
LDR a2, [a1, #AUXEnables]
ORR a2, a2, #AIE_MU
STR a2, [a1, #AUXEnables]
; Configure UART: 8-bit, 115200 baud (mini UART is fixed with 1 start & stop bit, no parity)
MOV a2, #LCR_8BIT
STR a2, [a1, #AUXMULCR]
CPUDetect a2
; https://www.raspberrypi.org/documentation/configuration/uart.md
; says that you need enable_uart=1 and/or core_freq=250 in config.txt to
; fix the VPU core frequency so we get a constant baud rate on the mini UART
LDR a3, CoreClock
LDR a4, =115200 * 8
DivRem a2, a3, a4, ip
SUB a2, a2, #1
STR a2, [a1, #AUXMUBAUD]
; Clear FIFOs
MOV a2, #IIR_FIFOCLR_RX :OR: IIR_FIFOCLR_TX
STR a2, [a1, #AUXMUIIR]
; Enable receive and transmit
MOV a2, #CNTL_TXEN :OR: CNTL_RXEN
STR a2, [a1, #AUXMUCNTL]
|
ORR a2, a2, #8_00440000 ; set GPIO 14 + 15 to alt0 (100)
STR a2, [a3, #GPFSel1] ;
DataSyncBarrier a2 ; resync before writing peripheral
......@@ -143,6 +178,7 @@ HAL_UARTStartUp
STR a2, [a1,#UARTIFLS]
LDR a2, =CR_RXE+CR_TXE+CR_UARTEN
STR a2, [a1,#UARTCR]
]
DataSyncBarrier a2
MOV pc, lr
......@@ -151,10 +187,19 @@ HAL_UARTStartUp
HAL_UARTShutdown ROUT
BaseAddr
DataSyncBarrier a3
[ MiniUART
; Disable receive and transmit
MOV a2, #0
STR a2, [a1, #AUXMUCNTL]
; Clear FIFOs
MOV a2, #IIR_FIFOCLR_RX :OR: IIR_FIFOCLR_TX
STR a2, [a1, #AUXMUIIR]
|
StopUART a2
; Flush FIFO
MOV a3, #0
STR a3, [a1,#UARTLCRH]
]
DataSyncBarrier a3
MOV pc, lr
......@@ -167,10 +212,14 @@ HAL_UARTShutdown ROUT
; Bit 4: Transmitter empty IRQ is actually "TX FIFO under threshold" IRQ
;
HAL_UARTFeatures
[ MiniUART
MOV a1, #2_00001 ; TODO confirm
|
[ ModemControl
MOV a1, #2_11101
|
MOV a1, #2_10001
]
]
MOV pc, lr
......@@ -184,6 +233,16 @@ HAL_UARTFeatures
HAL_UARTReceiveByte ROUT
Entry
BaseAddr
[ MiniUART
LDR a3, [a1, #AUXMUSTAT]
TST a3, #STAT_RXFIFONOTEMPTY
LDRNE ip, [a1, #AUXMUIO]
MOVEQ ip, #0
DataSyncBarrier lr ; resync after reading peripheral
TEQ a2, #0
BEQ %FT90
|
LDR a3, [a1, #UARTFLAG]
ANDS a4, a3, #1:SHL:FLAG_RXFE
MOVNE ip, #0
......@@ -206,12 +265,41 @@ HAL_UARTReceiveByte ROUT
; Status wanted, so clear error bits from UARTLineStatus
TST ip, #(1:SHL:DR_OE)+(1:SHL:DR_BE)+(1:SHL:DR_PE)+(1:SHL:DR_FE)
STRNE ip, [a1, #UARTRSRECR] ; n.b. written value doesn't matter
]
BL calcstatus
STR a1, [a2]
90
AND a1, ip, #255
EXIT
[ MiniUART
; In:
; a3 = AUXMUSTAT
; Out:
; a1 = status flags
; bit 0 rx data ready (fifo not empty)
; bit 1 overrun error
; bit 2 parity error
; bit 3 framing error
; bit 4 break error
; bit 5 tx fifo empty
; bit 6 tx fifo + holding/shift register empty
; bit 7 fifo contains a parity, framing or break error
; bit 8 tx fifo full (may only be reported if HAL_UARTFeatures bit 4 set)
calcstatus
; Mini UART cannot detect parity, frameing or break errors
ANDS a1, a3, #STAT_RXFIFONOTEMPTY
MOVNE a1, #1:SHL:0
TST a3, #STAT_RXORUN
ORRNE a1, a1, #1:SHL:1
TST a3, #STAT_TXFIFOEMPTY
ORRNE a1, a1, #1:SHL:5
TST a3, #STAT_TXDONE
ORRNE a1, a1, #1:SHL:6
TST a3, #STAT_TXFIFOFULL
ORRNE a1, a1, #1:SHL:8
MOV pc, lr
|
; In:
; a3 = UARTFLAG
; a4 = a3 AND 1:SHL:FLAG_RXFE
......@@ -241,13 +329,18 @@ calcstatus
ORR a1, a1, a3, LSR #DR_FE-3
ORRNE a1, a1, #128 ; "FIFO contains PE, FE, BE" - we can only report this for the current byte
MOV pc, lr
]
; void HAL_UARTTransmitByte(int port, int byte)
;
HAL_UARTTransmitByte
BaseAddr
DataSyncBarrier a3 ; resync before writing peripheral
[ MiniUART
STRB a2, [a1, #AUXMUIO]
|
STRB a2, [a1, #UARTDR]
]
MOV pc, lr
; int HAL_UARTLineStatus(int port)
......@@ -273,6 +366,11 @@ HAL_UARTTransmitByte
;
HAL_UARTLineStatus
BaseAddr
[ MiniUART
LDR a3, [a1, #AUXMUSTAT]
DataSyncBarrier a2 ; resync after reading peripheral
B calcstatus ; Exit via calcstatus
|
LDR a3, [a1, #UARTFLAG]
LDR ip, [a1, #UARTRSRECR]
DataSyncBarrier a2 ; resync after reading/before write
......@@ -280,6 +378,7 @@ HAL_UARTLineStatus
AND a4, a3, #1:SHL:FLAG_RXFE
STRNE ip, [a1, #UARTRSRECR] ; Clear any errors, written value doesn't matter
B calcstatus ; Exit via calcstatus
]
; int HAL_UARTInterruptEnable(int port, int eor, int mask)
;
......@@ -294,6 +393,10 @@ HAL_UARTLineStatus
;
HAL_UARTInterruptEnable
Entry
[ MiniUART
; TODO
MOV a1, #0
|
BaseAddr
PHPSEI
LDR a4, [a1, #UARTIMSC]
......@@ -331,6 +434,7 @@ HAL_UARTInterruptEnable
PLP
DataSyncBarrier a2
MOV a1, ip
]
EXIT
......@@ -341,6 +445,9 @@ HAL_UARTInterruptEnable
;
HAL_UARTRate ROUT
Entry "v1"
[ MiniUART
; TODO
|
BaseAddr
DataSyncBarrier a3
PHPSEI v1
......@@ -369,6 +476,7 @@ HAL_UARTRate ROUT
PLP v1
DataSyncBarrier a3
MOV a1, ip
]
EXIT
; int HAL_UARTFormat(int port, int format)
......@@ -386,6 +494,9 @@ HAL_UARTRate ROUT
HAL_UARTFormat ROUT
Entry
[ MiniUART
; TODO
|
BaseAddr
DataSyncBarrier a3
PHPSEI
......@@ -422,6 +533,7 @@ HAL_UARTFormat ROUT
PLP
DataSyncBarrier a3
MOV a1, a4
]
EXIT
; void HAL_UARTFIFOSize(int port, int *rx, int *tx)
......@@ -433,7 +545,11 @@ HAL_UARTFormat ROUT
; should return total FIFO size minus threshold).
;
HAL_UARTFIFOSize
[ MiniUART
MOV a1, #8
|
MOV a1, #16
]
TEQ a2, #0
STRNE a1, [a2]
MOV a1, #8
......@@ -446,6 +562,9 @@ HAL_UARTFIFOSize
; Clears the input FIFO (if bit 0 set) and the output FIFO (if bit 1 set).
;
HAL_UARTFIFOClear
[ MiniUART
; TODO
|
BaseAddr
; We can't individually flush FIFOs, so just flush both of them
DataSyncBarrier a2
......@@ -460,6 +579,7 @@ HAL_UARTFIFOClear
StartUART a3
PLP ip
DataSyncBarrier a2
]
MOV pc, lr
; int HAL_UARTFIFOEnable(int port, int enable)
......@@ -468,6 +588,10 @@ HAL_UARTFIFOClear
; -1 => read status. Returns previous status.
;
HAL_UARTFIFOEnable ROUT
[ MiniUART
; FIFOs cannot be disabled
MOV a1, #1
|
BaseAddr
DataSyncBarrier a3
PHPSEI ip
......@@ -485,6 +609,7 @@ HAL_UARTFIFOEnable ROUT
AND a1, a3, #LCRH_FEN
ASSERT LCRH_FEN = 1:SHL:4
MOV a1, a1, LSR #4
]
MOV pc, lr
; int HAL_UARTFIFOThreshold(int port, int threshold)
......@@ -493,6 +618,10 @@ HAL_UARTFIFOEnable ROUT
;
HAL_UARTFIFOThreshold ROUT
Entry "v1"
[ MiniUART
; TODO
MOV a1, #0
|
BaseAddr
DataSyncBarrier a3
PHPSEI v1
......@@ -520,6 +649,7 @@ HAL_UARTFIFOThreshold ROUT
PLP v1
DataSyncBarrier a2
MOV a1, a4
]
EXIT
fifolevels
......@@ -548,6 +678,10 @@ fifolevels
; are set).
;
HAL_UARTInterruptID ROUT
[ MiniUART
MOV a1, #-1
MOV pc, lr
|
BaseAddr a4
DataSyncBarrier a3
LDR a2, [a4, #UARTMIS]
......@@ -575,6 +709,7 @@ HAL_UARTInterruptID ROUT
]
MOV a1, #1
MOV pc, lr
]
; int HAL_UARTBreak(int port, int enable)
......@@ -583,6 +718,10 @@ HAL_UARTInterruptID ROUT
; returns previous state.
;
HAL_UARTBreak ROUT
[ MiniUART
; TODO
MOV a1, #0
|
BaseAddr
DataSyncBarrier a3
PHPSEI ip
......@@ -600,6 +739,7 @@ HAL_UARTBreak ROUT
DataSyncBarrier a2
ASSERT LCRH_BRK = 1
MOV a1, a4
]
MOV pc, lr
; int HAL_UARTModemControl(int port, int eor, int mask)
......@@ -615,7 +755,7 @@ HAL_UARTBreak ROUT
;
HAL_UARTModemControl
[ ModemControl
[ ModemControl :LAND: :LNOT: MiniUART
Entry
BaseAddr
DataSyncBarrier a4
......@@ -668,7 +808,7 @@ HAL_UARTModemControl
; the modem interrupt status.
;
HAL_UARTModemStatus
[ ModemControl
[ ModemControl :LAND: :LNOT: MiniUART
BaseAddr
DataSyncBarrier a2
PHPSEI a3
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment