AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
pl011.c
Go to the documentation of this file.
1
16
17#include <core/system.h>
18#include <core/module.h>
19#include <cpu/io.h>
20#include <dev/tty.h>
21#include <dev/uart.h>
22#include <dev/irq.h>
23#include <dev/platform.h>
24
25#define UART_DR 0x00 /* data */
26#define UART_FR 0x18 /* flags */
27#define UART_LCR_H 0x2C /* line control */
28#define UART_IMSC 0x38 /* interrupt mask: a bit set enables it */
29#define UART_ICR 0x44 /* interrupt clear */
30
31#define FR_RXFE (1 << 4) /* receive FIFO empty */
32#define FR_TXFF (1 << 5) /* transmit FIFO full */
33#define INT_RX (1 << 4) /* data received */
34#define INT_RT (1 << 6) /* data received, then a pause */
35#define LCR_H_FEN (1 << 4) /* the FIFOs enabled */
36#define LCR_H_WLEN8 (3 << 5) /* 8-bit characters */
37
38static struct ioaddr io;
39
41
43static ssize_t pl011_transmit(struct uart *u __unused, char c)
44{
45 /* wait a bounded time: a UART that never takes the character
46 * mustn't hang the kernel */
47 for (size_t i = 0; i < 100000 && (io_in32(&io, UART_FR) & FR_TXFF); ++i)
48 ;
49
50 io_out32(&io, UART_DR, (uint8_t) c);
51 return 1;
52}
53
55static char pl011_receive(struct uart *u __unused)
56{
57 return (char) io_in32(&io, UART_DR);
58}
59
62static void pl011_irq(void *arg __unused)
63{
64 /* clear the interrupt first, then take every byte in the FIFO: a byte
65 * that comes meanwhile raises it again. Cleared after, that byte's
66 * interrupt would be lost, and the input with it, since the UART
67 * waits for the byte to be read before raising another. */
69
70 while (!(io_in32(&io, UART_FR) & FR_RXFE)) {
71 if (uart_pl011.tty) /* if it is open */
73 else
75 }
76}
77
80static void pl011_comm_init(struct uart *u __unused)
81{
84}
85
88static int pl011_init(void)
89{
90 const struct platform_device *pd = platform_device_get("pl011", 0);
91
92 if (!pd || !pd->nirq)
93 return -ENODEV;
94
95 int err = platform_device_io(pd, &io);
96
97 if (err || (err = irq_install(pd->irq[0], pl011_irq, NULL)))
98 return err;
99
101 return 0;
102}
103
104struct uart uart_pl011 = {
105 .name = "pl011",
106 .init = pl011_comm_init,
107 .transmit = pl011_transmit,
108 .receive = pl011_receive,
109};
110
#define UART_FR
Definition earlycon.c:13
#define UART_DR
Definition earlycon.c:12
int irq_install(unsigned irq, irq_handler_t fn, void *arg)
Installs a handler for an IRQ.
Definition irq.c:32
static uint32_t io_in32(struct ioaddr *io, uintptr_t off)
Definition io.h:38
static void io_out32(struct ioaddr *io, uintptr_t off, uint32_t val)
Definition io.h:54
int uart_register(int id, struct uart *u)
Registers a UART, as /dev/ttyS<id>.
Definition uart.c:278
void uart_receive_handler(struct uart *u, size_t size)
Takes characters a UART received, and gives them to its terminal.
Definition uart.c:35
#define MODULE_INIT(name, i, f)
Definition module.h:10
static void pl011_comm_init(struct uart *u)
Sets the UART up when it is first opened: 8-bit characters, the FIFOs, and the receive interrupts.
Definition pl011.c:80
static struct ioaddr io
Definition pl011.c:38
static char pl011_receive(struct uart *u)
Takes one received character from the receive FIFO.
Definition pl011.c:55
static void pl011_irq(void *arg)
Handles the UART's interrupt: every received character goes to the terminal, or is dropped if no one ...
Definition pl011.c:62
#define UART_ICR
Definition pl011.c:29
static ssize_t pl011_transmit(struct uart *u, char c)
Sends one character, once the transmit FIFO has room.
Definition pl011.c:43
#define UART_IMSC
Definition pl011.c:28
struct uart uart_pl011
Definition pl011.c:40
#define INT_RX
Definition pl011.c:33
#define LCR_H_FEN
Definition pl011.c:35
#define FR_TXFF
Definition pl011.c:32
#define FR_RXFE
Definition pl011.c:31
#define INT_RT
Definition pl011.c:34
#define UART_LCR_H
Definition pl011.c:27
#define LCR_H_WLEN8
Definition pl011.c:36
static int pl011_init(void)
Finds the platform's PL011, installs its interrupt handler, and registers it as the first UART.
Definition pl011.c:88
int platform_device_io(const struct platform_device *pd, struct ioaddr *io)
Gets a device's registers, ready for io_in8() and the others.
Definition platform.c:38
const struct platform_device * platform_device_get(const char *name, int index)
Finds one of the platform's devices by its driver's name.
Definition platform.c:21
#define NULL
Definition stddef.h:27
unsigned char uint8_t
Definition stddef.h:20
Where a device's registers are.
Definition io.h:95
A device of the platform's table.
Definition platform.h:20
unsigned irq[PLATFORM_IRQS]
Definition platform.h:25
A serial port.
Definition uart.h:17
struct tty * tty
Definition uart.h:23
long int ssize_t
Definition types.h:12