blob: b30ca5ae435ef458db8e5ba4d389f7c758d048ee [file]
--
-- Copyright 2019, Data61
-- Commonwealth Scientific and Industrial Research Organisation (CSIRO)
-- ABN 41 687 119 230.
--
-- This software may be distributed and modified according to the terms of
-- the GNU General Public License version 2. Note that NO WARRANTY is provided.
-- See "LICENSE_GPLv2.txt" for details.
--
-- @TAG(DATA61_GPL)
--
include <gum/common/common.cogent>
const_UART_REF_CLK : U32
const_UART_REF_CLK = 50000000
-- UART flags
flag_UART_SR1_RRDY : U32
flag_UART_SR1_RRDY = 1 << 9
flag_UART_SR1_TRDY : U32
flag_UART_SR1_TRDY = 1 << 13
-- CR1
flag_UART_CR1_UARTEN : U32
flag_UART_CR1_UARTEN = 1 << 0
flag_UART_CR1_RRDYEN : U32
flag_UART_CR1_RRDYEN = 1 << 9
-- CR2
flag_UART_CR2_SRST : U32
flag_UART_CR2_SRST = 1 << 0
flag_UART_CR2_RXEN : U32
flag_UART_CR2_RXEN = 1 << 1
flag_UART_CR2_TXEN : U32
flag_UART_CR2_TXEN = 1 << 2
flag_UART_CR2_ATEN : U32
flag_UART_CR2_ATEN = 1 << 3
flag_UART_CR2_RTSEN : U32
flag_UART_CR2_RTSEN = 1 << 4
flag_UART_CR2_WS : U32
flag_UART_CR2_WS = 1 << 5
flag_UART_CR2_STPB : U32
flag_UART_CR2_STPB = 1 << 6
flag_UART_CR2_PROE : U32
flag_UART_CR2_PROE = 1 << 7
flag_UART_CR2_PREN : U32
flag_UART_CR2_PREN = 1 << 8
flag_UART_CR2_RTEC : U32
flag_UART_CR2_RTEC = 1 << 9
flag_UART_CR2_ESCEN : U32
flag_UART_CR2_ESCEN = 1 << 11
flag_UART_CR2_CTS : U32
flag_UART_CR2_CTS = 1 << 12
flag_UART_CR2_CTSC : U32
flag_UART_CR2_CTSC = 1 << 13
flag_UART_CR2_IRTS : U32
flag_UART_CR2_IRTS = 1 << 14
flag_UART_CR2_ESCI : U32
flag_UART_CR2_ESCI = 1 << 15
-- CR3
flag_UART_CR3_RXDMUXDEL : U32
flag_UART_CR3_RXDMUXDEL = 1 << 2
-- FCR
uart_FCR_RFDIV : U32 -> U32
uart_FCR_RFDIV x = x * (1 << 7)
uart_FCR_RFDIV_MASK : () -> U32
uart_FCR_RFDIV_MASK () = uart_FCR_RFDIV 0x7
uart_FCR_RXTL : U32 -> U32
uart_FCR_RXTL x = x * (1 << 0)
uart_FCR_RXTL_MASK : () -> U32
uart_FCR_RXTL_MASK () = uart_FCR_RXTL 0x1F
-- SR2
flag_UART_SR2_RXFIFO_RDR : U32
flag_UART_SR2_RXFIFO_RDR = 1 << 0
flag_UART_SR2_TXFIFO_EMPTY : U32
flag_UART_SR2_TXFIFO_EMPTY = 1 << 14
-- RXD
flag_UART_URXD_READY_MASK : U32
flag_UART_URXD_READY_MASK = 1 << 15
flag_UART_BYTE_MASK : U32
flag_UART_BYTE_MASK = 0xFF
-- External function - implemented in antiquoted C
uart_setup_phase1_ac : SysState -> SysState
-- Register readers
imx_uart_regs_read_rxd : SysState -> (U32, SysState)
imx_uart_regs_read_txd : SysState -> (U32, SysState)
imx_uart_regs_read_cr1 : SysState -> (U32, SysState)
imx_uart_regs_read_cr2 : SysState -> (U32, SysState)
imx_uart_regs_read_cr3 : SysState -> (U32, SysState)
imx_uart_regs_read_cr4 : SysState -> (U32, SysState)
imx_uart_regs_read_fcr : SysState -> (U32, SysState)
imx_uart_regs_read_sr1 : SysState -> (U32, SysState)
imx_uart_regs_read_sr2 : SysState -> (U32, SysState)
imx_uart_regs_read_esc : SysState -> (U32, SysState)
imx_uart_regs_read_tim : SysState -> (U32, SysState)
imx_uart_regs_read_bir : SysState -> (U32, SysState)
imx_uart_regs_read_bmr : SysState -> (U32, SysState)
imx_uart_regs_read_brc : SysState -> (U32, SysState)
imx_uart_regs_read_onems : SysState -> (U32, SysState)
imx_uart_regs_read_ts : SysState -> (U32, SysState)
-- Register writers
imx_uart_regs_write_rxd : (U32, SysState) -> SysState
imx_uart_regs_write_txd : (U32, SysState) -> SysState
imx_uart_regs_write_cr1 : (U32, SysState) -> SysState
imx_uart_regs_write_cr2 : (U32, SysState) -> SysState
imx_uart_regs_write_cr3 : (U32, SysState) -> SysState
imx_uart_regs_write_cr4 : (U32, SysState) -> SysState
imx_uart_regs_write_fcr : (U32, SysState) -> SysState
imx_uart_regs_write_sr1 : (U32, SysState) -> SysState
imx_uart_regs_write_sr2 : (U32, SysState) -> SysState
imx_uart_regs_write_esc : (U32, SysState) -> SysState
imx_uart_regs_write_tim : (U32, SysState) -> SysState
imx_uart_regs_write_bir : (U32, SysState) -> SysState
imx_uart_regs_write_bmr : (U32, SysState) -> SysState
imx_uart_regs_write_brc : (U32, SysState) -> SysState
imx_uart_regs_write_onems : (U32, SysState) -> SysState
imx_uart_regs_write_ts : (U32, SysState) -> SysState
uart_getchar_cg : SysState -> (SysState, U32)
uart_getchar_cg world =
let (rxd, world) = imx_uart_regs_read_rxd world
and (sr2, world) = imx_uart_regs_read_sr2 world
and c = if ( sr2 .&. flag_UART_SR2_RXFIFO_RDR ) /= 0 then rxd else 0
and c = if ( c .&. flag_UART_URXD_READY_MASK ) /= 0 then c else 0
and c = c .&. flag_UART_BYTE_MASK
in (world, c)
imx_uart_set_baud_cg : (U64, SysState) -> SysState
imx_uart_set_baud_cg (bps, world) =
let (fcr, world) = imx_uart_regs_read_fcr world
and fcr = fcr .&. complement (uart_FCR_RFDIV_MASK ())
and fcr = fcr .|. uart_FCR_RFDIV 4
and bir = 0xF
and bmr = const_UART_REF_CLK / (u64_to_u32 bps - 1)
and world = imx_uart_regs_write_fcr (fcr, world)
and world = imx_uart_regs_write_bir (bir, world)
and world = imx_uart_regs_write_bmr (bmr, world)
in world
type Parity = < PARITY_NONE | PARITY_EVEN | PARITY_ODD >
compute_cr2_by_parity : (Parity, U32) -> U32
compute_cr2_by_parity (p, cr2) = p
| PARITY_NONE -> let cr2 = cr2 .&. complement flag_UART_CR2_PREN
in cr2
| PARITY_ODD -> let cr2 = cr2 .|. flag_UART_CR2_PREN
and cr2 = cr2 .|. flag_UART_CR2_PROE
in cr2
| PARITY_EVEN -> let cr2 = cr2 .|. flag_UART_CR2_PREN
and cr2 = cr2 .&. complement flag_UART_CR2_PROE
in cr2
serial_configure_cg : (U64, U32, Parity, U32, SysState) -> SysState
serial_configure_cg (bps, char_size, parity, stop_bits, world) =
let (cr2, world) = imx_uart_regs_read_cr2 world
and cr2 =
-- character size
if | char_size == 8 -> cr2 .|. flag_UART_CR2_WS
| char_size == 7 -> cr2 .&. complement flag_UART_CR2_WS
| else -> 0 -- Need to fail here
and cr2 =
-- stop bits
if | stop_bits == 2 -> cr2 .|. flag_UART_CR2_STPB
| stop_bits == 1 -> cr2 .&. complement flag_UART_CR2_STPB
| else -> 0 -- Need to fail here
and cr2 = compute_cr2_by_parity (parity, cr2)
and world = imx_uart_regs_write_cr2 (cr2, world)
and world = imx_uart_set_baud_cg (bps, world)
in world
uart_sw_reset_cg : SysState -> SysState
uart_sw_reset_cg world =
let (cr2, world) = imx_uart_regs_read_cr2 world
and cr2 = cr2 .&. complement flag_UART_CR2_SRST
and world = imx_uart_regs_write_cr2 (cr2, world)
in world
uart_setup : SysState -> SysState
uart_setup world =
-- Perform a software reset
let world = uart_sw_reset_cg world
and world = uart_setup_phase1_ac world
-- Serial line configuration
and world = serial_configure_cg (11520, 8, PARITY_NONE, 1, world)
-- Enable the UART
and (cr1, world) = imx_uart_regs_read_cr1 world
and cr1 = cr1 .|. flag_UART_CR1_UARTEN
and world = imx_uart_regs_write_cr1 (cr1, world)
-- RX/TX Enable
and (cr2, world) = imx_uart_regs_read_cr2 world
and cr2 = cr2 .|. flag_UART_CR2_RXEN .|. flag_UART_CR2_TXEN
and world = imx_uart_regs_write_cr2 (cr2, world)
-- Ignore RTS
and (cr2, world) = imx_uart_regs_read_cr2 world
and cr2 = cr2 .|. flag_UART_CR2_IRTS
and world = imx_uart_regs_write_cr2 (cr2, world)
-- Configure the RX MUX
and (cr3, world) = imx_uart_regs_read_cr3 world
and cr3 = cr3 .|. flag_UART_CR3_RXDMUXDEL
and world = imx_uart_regs_write_cr3 (cr3, world)
-- Initialise the receiver interrupt
-- Disable recv interrupt
and (cr1, world) = imx_uart_regs_read_cr1 world
and (fcr, world) = imx_uart_regs_read_fcr world
and cr1 = cr1 .&. complement flag_UART_CR1_RRDYEN
and world = imx_uart_regs_write_cr1 (cr1, world)
-- Clear the trigger value
and fcr = fcr .&. complement (uart_FCR_RXTL_MASK ())
and world = imx_uart_regs_write_fcr (fcr, world)
and (cr1, world) = imx_uart_regs_read_cr1 world
and (fcr, world) = imx_uart_regs_read_fcr world
-- Set the rx tigger level to 1
and fcr = fcr .|. uart_FCR_RXTL 1
and world = imx_uart_regs_write_fcr (fcr, world)
-- Enable recv interrupt
and cr1 = cr1 .|. flag_UART_CR1_RRDYEN
and world = imx_uart_regs_write_cr1 (cr1, world)
in world