-
Notifications
You must be signed in to change notification settings - Fork 85
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
libplatsupport: separate drivers from platforms
Separate serial drivers Signed-off-by: Axel Heider <axel.heider@hensoldt.net>
- Loading branch information
Showing
7 changed files
with
313 additions
and
183 deletions.
There are no files selected for viewing
100 changes: 100 additions & 0 deletions
100
libplatsupport/include/platsupport/driver/ns16550/ns16550.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
/* | ||
* Copyright 2022, HENSOLDT Cyber GmbH | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
||
/* | ||
* Driver for a 16550 compatible UART. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <stdio.h> | ||
#include <stdint.h> | ||
#include <stdbool.h> | ||
#include <utils/arith.h> | ||
|
||
#define NS16550_IER_ERBFI BIT(0) /* Enable Received Data Available Interrupt */ | ||
#define NS16550_IER_ETBEI BIT(1) /* Enable Transmitter Holding Register Empty Interrupt */ | ||
#define NS16550_IER_ELSI BIT(2) /* Enable Receiver Line Status Interrupt */ | ||
#define NS16550_IER_EDSSI BIT(3) /* Enable MODEM Status Interrupt */ | ||
|
||
#define NS16550_FCR_ENABLE_FIFOS BIT(0) | ||
#define NS16550_FCR_RESET_RX_FIFO BIT(1) | ||
#define NS16550_FCR_RESET_TX_FIFO BIT(2) | ||
#define NS16550_FCR_TRIGGER_1 (0u << 6) | ||
#define NS16550_FCR_TRIGGER_4 (1u << 6) | ||
#define NS16550_FCR_TRIGGER_8 (2u << 6) | ||
#define NS16550_FCR_TRIGGER_14 (3u << 6) | ||
|
||
#define NS16550_LCR_DLAB BIT(7) /* Divisor Latch Access */ | ||
|
||
#define NS16550_LSR_DR BIT(0) /* Data Ready */ | ||
#define NS16550_LSR_THRE BIT(5) /* Transmitter Holding Register Empty */ | ||
|
||
typedef volatile struct { | ||
uint8_t rbr_dll_thr; /* 0x00 Receiver Buffer Register (Read Only) | ||
* Divisor Latch (LSB) | ||
* Transmitter Holding Register (Write Only) | ||
*/ | ||
uint8_t dlm_ier; /* 0x04 Divisor Latch (MSB) | ||
* Interrupt Enable Register | ||
*/ | ||
uint8_t iir_fcr; /* 0x08 Interrupt Identification Register (Read Only) | ||
* FIFO Control Register (Write Only) | ||
*/ | ||
uint8_t lcr; /* 0xC Line Control Register */ | ||
uint8_t mcr; /* 0x10 MODEM Control Register */ | ||
uint8_t lsr; /* 0x14 Line Status Register */ | ||
uint8_t msr; /* 0x18 MODEM Status Register */ | ||
} ns16550_regs_t; | ||
|
||
|
||
/* | ||
******************************************************************************* | ||
* UART access primitives | ||
******************************************************************************* | ||
*/ | ||
|
||
static bool ns16550_is_tx_empty(ns16550_regs_t *regs) | ||
{ | ||
/* The THRE bit is set when the FIFO is fully empty. There seems no way to | ||
* detect if the FIFO is partially empty only, so we can't implement a | ||
* "tx_ready" check. | ||
*/ | ||
return (0 != (regs->lsr & NS16550_LSR_THRE)); | ||
} | ||
|
||
static void ns16550_tx_byte(ns16550_regs_t *regs, uint8_t byte) | ||
{ | ||
/* Caller has to ensure TX FIFO is ready */ | ||
regs->rbr_dll_thr = byte; | ||
} | ||
|
||
static bool ns16550_is_rx_empty(ns16550_regs_t *regs) | ||
{ | ||
return (0 == (regs->lsr & NS16550_LSR_DR)); | ||
} | ||
|
||
|
||
static int ns16550_rx_byte(ns16550_regs_t *regs) | ||
{ | ||
/* Caller has to ensure RX FIFO has data */ | ||
return regs->rbr_dll_thr; | ||
} | ||
|
||
|
||
/* | ||
******************************************************************************* | ||
* UART access helpers | ||
******************************************************************************* | ||
*/ | ||
|
||
/* | ||
* Returns a char from the TX FIFO or EOF if the FIFO is empty. | ||
*/ | ||
static int ns16550_get_char_or_EOF(ns16550_regs_t *regs) | ||
{ | ||
return ns16550_is_rx_empty(regs) ? EOF : ns16550_rx_byte(regs); | ||
} |
117 changes: 117 additions & 0 deletions
117
libplatsupport/include/platsupport/driver/pl011/pl011.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
/* | ||
* Copyright 2022, HENSOLDT Cyber GmbH | ||
* Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
||
/* | ||
* Driver for a ARM PL011 UART. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <stdio.h> | ||
#include <stdint.h> | ||
#include <stdbool.h> | ||
#include <utils/arith.h> | ||
|
||
#define PL011_FR_TXFF BIT(5) | ||
#define PL011_FR_RXFE BIT(4) | ||
|
||
typedef volatile struct { | ||
uint32_t dr; /* 0x00 */ | ||
uint32_t _rfu_04; /* 0x04 */ | ||
uint32_t _rfu_08; /* 0x08 */ | ||
uint32_t _rfu_0c; /* 0x0c */ | ||
uint32_t _rfu_10; /* 0x10 */ | ||
uint32_t _rfu_14; /* 0x14 */ | ||
uint32_t fr; /* 0x18 */ | ||
uint32_t _rfu_1c; /* 0x1c */ | ||
uint32_t _rfu_20; /* 0x20 */ | ||
uint32_t _rfu_24; /* 0x24 */ | ||
uint32_t _rfu_28; /* 0x28 */ | ||
uint32_t _rfu_2c; /* 0x2c */ | ||
uint32_t _rfu_30; /* 0x30 */ | ||
uint32_t _rfu_34; /* 0x34 */ | ||
uint32_t imsc; /* 0x38 */ | ||
uint32_t _rfu_3c; /* 0x3c */ | ||
uint32_t _rfu_40; /* 0x40 */ | ||
uint32_t icr; /* 0x44 */ | ||
uint32_t _rfu_48; /* 0x48 */ | ||
uint32_t _rfu_4c; /* 0x4c */ | ||
} pl011_regs_t; | ||
|
||
|
||
/* | ||
******************************************************************************* | ||
* UART access primitives | ||
******************************************************************************* | ||
*/ | ||
|
||
static bool pl011_is_rx_fifo_empty(pl011_regs_t *regs) | ||
{ | ||
return (0 != (regs->fr & PL011_FR_RXFE)); | ||
} | ||
|
||
static bool pl011_is_tx_fifo_full(pl011_regs_t *regs) | ||
{ | ||
return (0 != (regs->fr & PL011_FR_TXFF)); | ||
} | ||
|
||
static void pl011_write_char(pl011_regs_t *regs, uint8_t c) | ||
{ | ||
/* Caller has to ensure TX FIFO has space */ | ||
regs->dr = c; | ||
} | ||
|
||
static uint8_t pl011_read_char(pl011_regs_t *regs) | ||
{ | ||
return (uint8_t)(regs->dr & 0xFF); | ||
} | ||
|
||
static void pl011_clear_interrupt(pl011_regs_t *regs) | ||
{ | ||
regs->icr = 0x7f0; | ||
} | ||
|
||
static void pl011_init(pl011_regs_t *regs) | ||
{ | ||
regs->imsc = 0x50; | ||
} | ||
|
||
|
||
/* | ||
******************************************************************************* | ||
* UART access helpers | ||
******************************************************************************* | ||
*/ | ||
|
||
/* | ||
* Returns a char from the TX FIFO or EOF if the FIFO is empty. | ||
*/ | ||
int pl011_get_char_or_EOF(pl011_regs_t *regs) | ||
{ | ||
return pl011_is_rx_fifo_empty(regs) ? EOF : pl011_read_char(regs); | ||
} | ||
|
||
/* | ||
* Block until there is space in the TX FIFO, then outputs the char. Optionally | ||
* output a CR (\r) first in case of LF (\n) to support terminal use case. | ||
*/ | ||
void pl011_put_char_blocking(pl011_regs_t *regs, uint8_t c, bool is_auto_cr) | ||
{ | ||
|
||
/* output CR (\r) before LF (\n) automatically if UART is a terminal */ | ||
if ((c == '\n') && is_auto_cr) { | ||
while (pl011_is_tx_fifo_full(regs)) { | ||
/* busy loop */ | ||
} | ||
pl011_write_char(regs, '\r'); | ||
} | ||
|
||
while (pl011_is_tx_fifo_full(regs)) { | ||
/* busy loop */ | ||
} | ||
pl011_write_char(regs, c); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.