-
Notifications
You must be signed in to change notification settings - Fork 87
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Ivan-Velickovic <i.velickovic@unsw.edu.au>
- Loading branch information
1 parent
1bc0e79
commit 1d2db31
Showing
3 changed files
with
156 additions
and
0 deletions.
There are no files selected for viewing
34 changes: 34 additions & 0 deletions
34
libplatsupport/plat_include/p550/platsupport/plat/serial.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,34 @@ | ||
/* | ||
* Copyright 2023, UNSW | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
||
#pragma once | ||
#include <autoconf.h> | ||
|
||
/* The ESWIN EIC7700X SoC contains five 8250 compatible UARTs. */ | ||
|
||
enum chardev_id { | ||
UART0, | ||
UART1, | ||
UART2, | ||
UART3, | ||
UART4, | ||
PS_SERIAL_DEFAULT = UART0 | ||
}; | ||
|
||
#define UART0_PADDR 0x50900000 | ||
#define UART1_PADDR 0x50910000 | ||
#define UART2_PADDR 0x50920000 | ||
#define UART3_PADDR 0x50930000 | ||
#define UART4_PADDR 0x50940000 | ||
|
||
#define UART0_IRQ 100 | ||
#define UART1_IRQ 101 | ||
#define UART2_IRQ 102 | ||
#define UART3_IRQ 103 | ||
#define UART4_IRQ 104 | ||
|
||
#define DEFAULT_SERIAL_PADDR UART0_PADDR | ||
#define DEFAULT_SERIAL_INTERRUPT UART0_IRQ |
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,47 @@ | ||
/* | ||
* Copyright 2023, UNSW | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
||
#include "../../chardev.h" | ||
#include "../../common.h" | ||
#include <utils/util.h> | ||
|
||
static const int uart0_irqs[] = {UART0_IRQ, -1}; | ||
static const int uart1_irqs[] = {UART1_IRQ, -1}; | ||
static const int uart2_irqs[] = {UART2_IRQ, -1}; | ||
static const int uart3_irqs[] = {UART3_IRQ, -1}; | ||
static const int uart4_irqs[] = {UART4_IRQ, -1}; | ||
|
||
/* | ||
* Despite each UART being 0x10000 in size (according to the device tree) we | ||
* only need to map in the first page for the driver to functon. | ||
*/ | ||
#define UART_DEFN(devid) { \ | ||
.id = UART##devid, \ | ||
.paddr = UART##devid##_PADDR, \ | ||
.size = BIT(12), \ | ||
.irqs = uart##devid##_irqs, \ | ||
.init_fn = &uart_init \ | ||
} | ||
|
||
const struct dev_defn dev_defn[] = { | ||
UART_DEFN(0), | ||
UART_DEFN(1), | ||
UART_DEFN(2), | ||
UART_DEFN(3), | ||
UART_DEFN(4), | ||
}; | ||
|
||
struct ps_chardevice * | ||
ps_cdev_init(enum chardev_id id, const ps_io_ops_t *o, struct ps_chardevice *d) | ||
{ | ||
unsigned int i; | ||
for (i = 0; i < ARRAY_SIZE(dev_defn); i++) { | ||
if (dev_defn[i].id == id) { | ||
return (dev_defn[i].init_fn(dev_defn + i, o, d)) ? NULL : d; | ||
} | ||
} | ||
return NULL; | ||
} |
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,75 @@ | ||
/* | ||
* Copyright 2023, UNSW | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <platsupport/serial.h> | ||
#include <platsupport/plat/serial.h> | ||
#include "../../chardev.h" | ||
|
||
#define UART_THR 0x00 /* UART Transmit Holding Register */ | ||
#define UART_IER 0x04 /* UART Interrupt Enable Register */ | ||
#define UART_IER_ERDAI BIT(0) /* Enable Received Data Available Interrupt */ | ||
#define UART_LSR 0x14 /* UART Line Status Register */ | ||
#define UART_LSR_THRE 0x20 /* Transmit Holding Register Empty */ | ||
|
||
#define REG_PTR(base, off) ((volatile uint32_t *)((base) + (off))) | ||
|
||
int uart_getchar(ps_chardevice_t *d) | ||
{ | ||
while ((*REG_PTR(d->vaddr, UART_LSR) & BIT(0))); | ||
return *REG_PTR(d->vaddr, UART_THR); | ||
} | ||
|
||
int uart_putchar(ps_chardevice_t *d, int c) | ||
{ | ||
if (c == '\n' && (d->flags & SERIAL_AUTO_CR)) { | ||
uart_putchar(d, '\r'); | ||
} | ||
|
||
while ((*REG_PTR(d->vaddr, UART_LSR) & UART_LSR_THRE) == 0); | ||
|
||
/* Add character to the buffer. */ | ||
*REG_PTR(d->vaddr, UART_THR) = c; | ||
|
||
return c; | ||
} | ||
|
||
static void uart_handle_irq(ps_chardevice_t *dev) | ||
{ | ||
/* | ||
* This is currently only called when received data is available on the device. | ||
* The interrupt will be acked to the device on the next read to the device. | ||
* There's nothing else we need to do here. | ||
*/ | ||
} | ||
|
||
int uart_init(const struct dev_defn *defn, | ||
const ps_io_ops_t *ops, | ||
ps_chardevice_t *dev) | ||
{ | ||
memset(dev, 0, sizeof(*dev)); | ||
void *vaddr = chardev_map(defn, ops); | ||
if (vaddr == NULL) { | ||
ZF_LOGE("Unable to map chardev"); | ||
return -1; | ||
} | ||
|
||
/* Set up all the device properties. */ | ||
dev->id = defn->id; | ||
dev->vaddr = vaddr; | ||
dev->read = &uart_read; | ||
dev->write = &uart_write; | ||
dev->handle_irq = &uart_handle_irq; | ||
dev->irqs = defn->irqs; | ||
dev->ioops = *ops; | ||
dev->flags = SERIAL_AUTO_CR; | ||
|
||
*REG_PTR(dev->vaddr, 0x8) = 1; | ||
*REG_PTR(dev->vaddr, UART_IER) = UART_IER_ERDAI; | ||
|
||
return 0; | ||
} |