From 5d029123e474e9739e95f00fa787833393315dd8 Mon Sep 17 00:00:00 2001 From: Jimmy Brush Date: Tue, 25 Apr 2023 22:48:10 +1000 Subject: [PATCH 1/5] Add pine64 star64 platform This adds a timer and serial driver to libplatsupport. Co-developed-by: Ivan-Velickovic Signed-off-by: Jimmy Brush --- .../star64/platsupport/plat/serial.h | 39 +++ .../star64/platsupport/plat/timer.h | 71 +++++ libplatsupport/src/plat/star64/chardev.c | 49 ++++ libplatsupport/src/plat/star64/ltimer.c | 265 ++++++++++++++++++ libplatsupport/src/plat/star64/serial.c | 68 +++++ libplatsupport/src/plat/star64/timer.c | 149 ++++++++++ 6 files changed, 641 insertions(+) create mode 100644 libplatsupport/plat_include/star64/platsupport/plat/serial.h create mode 100644 libplatsupport/plat_include/star64/platsupport/plat/timer.h create mode 100644 libplatsupport/src/plat/star64/chardev.c create mode 100644 libplatsupport/src/plat/star64/ltimer.c create mode 100644 libplatsupport/src/plat/star64/serial.c create mode 100644 libplatsupport/src/plat/star64/timer.c diff --git a/libplatsupport/plat_include/star64/platsupport/plat/serial.h b/libplatsupport/plat_include/star64/platsupport/plat/serial.h new file mode 100644 index 000000000..5c23b9cc4 --- /dev/null +++ b/libplatsupport/plat_include/star64/platsupport/plat/serial.h @@ -0,0 +1,39 @@ +/* + * Copyright 2023, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once +#include + +/* The StarFive JH7110 SoC contains five 8250 compatible UARTs. */ + +enum chardev_id { + UART0, + UART1, + UART2, + UART3, + UART4, + UART5, + PS_SERIAL_DEFAULT = UART0 +}; + +#define UART0_PADDR 0x10000000 +#define UART1_PADDR 0x10010000 +#define UART2_PADDR 0x10020000 +#define UART3_PADDR 0x12000000 +#define UART4_PADDR 0x12010000 +#define UART5_PADDR 0x12020000 + +#define UART0_IRQ 32 +#define UART1_IRQ 33 +#define UART2_IRQ 34 +#define UART3_IRQ 45 +#define UART4_IRQ 46 +#define UART5_IRQ 47 + +/* The default serial device corresponds to the UART available via the GPIO + * pins of the Star64 Model-A. */ +#define DEFAULT_SERIAL_PADDR UART0_PADDR +#define DEFAULT_SERIAL_INTERRUPT UART0_IRQ diff --git a/libplatsupport/plat_include/star64/platsupport/plat/timer.h b/libplatsupport/plat_include/star64/platsupport/plat/timer.h new file mode 100644 index 000000000..d6cef86eb --- /dev/null +++ b/libplatsupport/plat_include/star64/platsupport/plat/timer.h @@ -0,0 +1,71 @@ +/* + * Copyright 2023, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#pragma once + +#include +#include + +/* + * The JH7110 SoC contains a timer with four 32-bit counters. Each one of these + * counters is referred to as a "channel". + */ + +/* Channel information */ +#define STARFIVE_TIMER_NUM_CHANNELS 4 +#define STARFIVE_TIMER_CHANNEL_REGISTERS_LEN_IN_BYTES 0x40 +#define STARFIVE_TIMER_CHANNEL_0_IRQ 69 +#define STARFIVE_TIMER_CHANNEL_1_IRQ 70 +#define STARFIVE_TIMER_CHANNEL_2_IRQ 71 +#define STARFIVE_TIMER_CHANNEL_3_IRQ 72 + +/* This information comes from the DTS file */ +#define STARFIVE_TIMER_BASE 0x13050000 +#define STARFIVE_TIMER_REGISTER_WINDOW_LEN_IN_BYTES 0x10000 +#define STARFIVE_TIMER_TICKS_PER_SECOND 0x16e3600 + +#define STARFIVE_TIMER_MAX_TICKS 0xffffffff + +/* Register value constants */ +#define STARFIVE_TIMER_MODE_CONTINUOUS 0 +#define STARFIVE_TIMER_MODE_SINGLE 1 +#define STARFIVE_TIMER_DISABLED 0 +#define STARFIVE_TIMER_ENABLED 1 +#define STARFIVE_TIMER_INTERRUPT_UNMASKED 0 +#define STARFIVE_TIMER_INTERRUPT_MASKED 1 +#define STARFIVE_TIMER_INTCLR_BUSY BIT(1) + +typedef struct { + /* Registers */ + /* this register doesn't seem to do anything */ + uint32_t status; + uint32_t ctrl; + uint32_t load; + uint32_t unknown1; + uint32_t enable; + uint32_t reload; + uint32_t value; + uint32_t unknown2; + uint32_t intclr; + uint32_t intmask; +} starfive_timer_regs_t; + +typedef struct { + volatile starfive_timer_regs_t *regs; + /* + * Stores the number of times the continuous counter timer has elapsed and started over. + * This allows us to count to a higher number than allowed by the hardware. + */ + uint32_t value_h; +} starfive_timer_t; + +void starfive_timer_start(starfive_timer_t *timer); +void starfive_timer_stop(starfive_timer_t *timer); +void starfive_timer_handle_irq(starfive_timer_t *timer); +uint64_t starfive_timer_get_time(starfive_timer_t *timer); +void starfive_timer_reset(starfive_timer_t *timer); +int starfive_timer_set_timeout(starfive_timer_t *timer, uint64_t ns, bool is_periodic); +void starfive_timer_disable_all_channels(void *vaddr); +void starfive_timer_init(starfive_timer_t *timer, void *vaddr, uint64_t channel); diff --git a/libplatsupport/src/plat/star64/chardev.c b/libplatsupport/src/plat/star64/chardev.c new file mode 100644 index 000000000..df48708f4 --- /dev/null +++ b/libplatsupport/src/plat/star64/chardev.c @@ -0,0 +1,49 @@ +/* + * Copyright 2023, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "../../chardev.h" +#include "../../common.h" +#include + +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}; +static const int uart5_irqs[] = {UART5_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), + UART_DEFN(5), +}; + +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; +} diff --git a/libplatsupport/src/plat/star64/ltimer.c b/libplatsupport/src/plat/star64/ltimer.c new file mode 100644 index 000000000..5850cb9c5 --- /dev/null +++ b/libplatsupport/src/plat/star64/ltimer.c @@ -0,0 +1,265 @@ +/* + * Copyright 2023, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "../../ltimer.h" + +enum { + COUNTER_TIMER, + TIMEOUT_TIMER, + NUM_TIMERS +}; + +typedef struct { + void *vaddr; + starfive_timer_t timer[NUM_TIMERS]; + irq_id_t irq_id[NUM_TIMERS]; + timer_callback_data_t callback_data[NUM_TIMERS]; + ltimer_callback_fn_t user_callback; + void *user_callback_token; + ps_io_ops_t ops; +} starfive_ltimer_t; + +/* See timer.h for an explanation of the driver. */ + +/* Each channel IRQ is edge-triggered. */ +static ps_irq_t irqs[] = { + { + .type = PS_TRIGGER, + .trigger.number = STARFIVE_TIMER_CHANNEL_0_IRQ, + .trigger.trigger = 1 + }, + { + .type = PS_TRIGGER, + .trigger.number = STARFIVE_TIMER_CHANNEL_1_IRQ, + .trigger.trigger = 1 + }, +}; + +static pmem_region_t pmems[] = { + { + .type = PMEM_TYPE_DEVICE, + .base_addr = STARFIVE_TIMER_BASE, + .length = STARFIVE_TIMER_REGISTER_WINDOW_LEN_IN_BYTES, + }, +}; + +#define NUM_IRQS ARRAY_SIZE(irqs) +#define NUM_PMEMS ARRAY_SIZE(pmems) + +static size_t get_num_irqs(void *data) +{ + return NUM_IRQS; +} + +static int get_nth_irq(void *data, size_t n, ps_irq_t *irq) +{ + assert(n < NUM_IRQS); + assert(irq); + + *irq = irqs[n]; + return 0; +} + +static size_t get_num_pmems(void *data) +{ + return NUM_PMEMS; +} + +static int get_nth_pmem(void *data, size_t n, pmem_region_t *paddr) +{ + assert(n < NUM_PMEMS); + assert(paddr); + + *paddr = pmems[n]; + return 0; +} + +static int ltimer_handle_irq(void *data, ps_irq_t *irq) +{ + assert(data); + assert(irq); + + starfive_ltimer_t *timers = (starfive_ltimer_t *)data; + long irq_number = irq->irq.number; + ltimer_event_t event; + + if (irq_number == irqs[COUNTER_TIMER].irq.number) { + starfive_timer_handle_irq(&timers->timer[COUNTER_TIMER]); + event = LTIMER_OVERFLOW_EVENT; + } else if (irq_number == irqs[TIMEOUT_TIMER].irq.number) { + starfive_timer_handle_irq(&timers->timer[TIMEOUT_TIMER]); + event = LTIMER_TIMEOUT_EVENT; + } else { + ZF_LOGE("Invalid IRQ number %ld received.", irq_number); + return EINVAL; + } + + if (timers->user_callback) { + timers->user_callback(timers->user_callback_token, event); + } + + return 0; +} + +static int get_time(void *data, uint64_t *time) +{ + assert(data); + assert(time); + + starfive_ltimer_t *timers = (starfive_ltimer_t *)data; + *time = starfive_timer_get_time(&timers->timer[COUNTER_TIMER]); + + return 0; +} + +static int set_timeout(void *data, uint64_t ns, timeout_type_t type) +{ + assert(data); + starfive_ltimer_t *timers = (starfive_ltimer_t *)data; + + switch (type) { + case TIMEOUT_ABSOLUTE: { + uint64_t time = starfive_timer_get_time(&timers->timer[COUNTER_TIMER]); + if (time >= ns) { + ZF_LOGE("Requested time %"PRIu64" earlier than current time %"PRIu64, ns, time); + return ETIME; + } + return starfive_timer_set_timeout(&timers->timer[TIMEOUT_TIMER], ns - time, false); + } + case TIMEOUT_RELATIVE: + return starfive_timer_set_timeout(&timers->timer[TIMEOUT_TIMER], ns, false); + case TIMEOUT_PERIODIC: + return starfive_timer_set_timeout(&timers->timer[TIMEOUT_TIMER], ns, true); + } + + return EINVAL; +} + +static int reset(void *data) +{ + assert(data); + starfive_ltimer_t *timers = (starfive_ltimer_t *)data; + + starfive_timer_stop(&timers->timer[COUNTER_TIMER]); + starfive_timer_reset(&timers->timer[COUNTER_TIMER]); + starfive_timer_start(&timers->timer[COUNTER_TIMER]); + + starfive_timer_stop(&timers->timer[TIMEOUT_TIMER]); + starfive_timer_reset(&timers->timer[TIMEOUT_TIMER]); + + return 0; +} + +static void destroy(void *data) +{ + assert(data); + starfive_ltimer_t *timers = (starfive_ltimer_t *)data; + int error; + + starfive_timer_stop(&timers->timer[COUNTER_TIMER]); + starfive_timer_stop(&timers->timer[TIMEOUT_TIMER]); + + ps_pmem_unmap(&timers->ops, pmems[0], timers->vaddr); + + error = ps_irq_unregister(&timers->ops.irq_ops, timers->irq_id[COUNTER_TIMER]); + ZF_LOGE_IF(error, "Failed to uregister counter timer IRQ"); + + error = ps_irq_unregister(&timers->ops.irq_ops, timers->irq_id[TIMEOUT_TIMER]); + ZF_LOGE_IF(error, "Failed to uregister timeout timer IRQ"); + + error = ps_free(&timers->ops.malloc_ops, sizeof(*timers), timers); + ZF_LOGE_IF(error, "Failed to free device struct memory"); +} + +static int register_interrupt(ltimer_t *ltimer, + ps_io_ops_t ops, + starfive_ltimer_t *timers, + int id) +{ + assert(timers); + assert(id >= 0 && id < NUM_TIMERS); + + timers->callback_data[id].ltimer = ltimer; + timers->callback_data[id].irq = &irqs[id]; + timers->callback_data[id].irq_handler = ltimer_handle_irq; + + timers->irq_id[id] = ps_irq_register(&ops.irq_ops, + irqs[id], + handle_irq_wrapper, + &timers->callback_data[id]); + + if (timers->irq_id[id] < 0) { + ZF_LOGE("Unable to register irq %lu", irqs[id].trigger.number); + return EINVAL; + } + + return 0; +} + +int ltimer_default_init(ltimer_t *ltimer, + ps_io_ops_t ops, + ltimer_callback_fn_t callback, + void *callback_token) +{ + assert(ltimer); + + ltimer->get_num_irqs = get_num_irqs; + ltimer->get_nth_irq = get_nth_irq; + ltimer->get_num_pmems = get_num_pmems; + ltimer->get_nth_pmem = get_nth_pmem; + ltimer->get_time = get_time; + ltimer->set_timeout = set_timeout; + ltimer->reset = reset; + ltimer->destroy = destroy; + + int error = ps_calloc(&ops.malloc_ops, 1, sizeof(starfive_ltimer_t), <imer->data); + if (error) { + ZF_LOGE("Memory allocation failed with error %d", error); + return error; + } + + starfive_ltimer_t *timers = ltimer->data; + + timers->ops = ops; + timers->user_callback = callback; + timers->user_callback_token = callback_token; + + error = register_interrupt(ltimer, ops, timers, COUNTER_TIMER); + if (error) { + return error; + } + + error = register_interrupt(ltimer, ops, timers, TIMEOUT_TIMER); + if (error) { + return error; + } + + timers->vaddr = ps_pmem_map(&ops, pmems[0], false, PS_MEM_NORMAL); + if (timers->vaddr == NULL) { + ZF_LOGE("Unable to map physical memory at 0x%"PRIx64" length 0x%"PRIx64, + pmems[0].base_addr, + pmems[0].length); + destroy(ltimer->data); + return EINVAL; + } + + starfive_timer_disable_all_channels(timers->vaddr); + + starfive_timer_init(&timers->timer[COUNTER_TIMER], timers->vaddr, COUNTER_TIMER); + starfive_timer_start(&timers->timer[COUNTER_TIMER]); + + starfive_timer_init(&timers->timer[TIMEOUT_TIMER], timers->vaddr, TIMEOUT_TIMER); + + return 0; +} diff --git a/libplatsupport/src/plat/star64/serial.c b/libplatsupport/src/plat/star64/serial.c new file mode 100644 index 000000000..54f1dad8e --- /dev/null +++ b/libplatsupport/src/plat/star64/serial.c @@ -0,0 +1,68 @@ +/* + * Copyright 2023, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include "../../chardev.h" + +#define UART_THR 0x00 /* UART Transmit Holding Register */ +#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 UART driver is not interrupt driven, there is nothing 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; + + return 0; +} diff --git a/libplatsupport/src/plat/star64/timer.c b/libplatsupport/src/plat/star64/timer.c new file mode 100644 index 000000000..ba25e972e --- /dev/null +++ b/libplatsupport/src/plat/star64/timer.c @@ -0,0 +1,149 @@ +/* + * Copyright 2023, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include + +#define MAX_TIMEOUT_NS (STARFIVE_TIMER_MAX_TICKS * (NS_IN_S / STARFIVE_TIMER_TICKS_PER_SECOND)) + +static void print_regs(starfive_timer_t *timer) +{ + printf(" Timer Channel Register State\n"); + printf(" Interrupt status: 0x%08x @ [%p]\n", timer->regs->status, &timer->regs->status); + printf(" Control: 0x%08x @ [%p]\n", timer->regs->ctrl, &timer->regs->ctrl); + printf(" Load: 0x%08x @ [%p]\n", timer->regs->load, &timer->regs->load); + printf(" Enable: 0x%08x @ [%p]\n", timer->regs->enable, &timer->regs->enable); + printf(" Reload: 0x%08x @ [%p]\n", timer->regs->reload, &timer->regs->reload); + printf(" Value: 0x%08x @ [%p]\n", timer->regs->value, &timer->regs->value); + printf(" Clear Interrupt: 0x%08x @ [%p]\n", timer->regs->intclr, &timer->regs->intclr); + printf(" Mask Interrupt: 0x%08x @ [%p]\n", timer->regs->intmask, &timer->regs->intmask); +} + +void starfive_timer_start(starfive_timer_t *timer) +{ + assert(timer); + assert(timer->regs); + + timer->regs->enable = STARFIVE_TIMER_ENABLED; +} + +void starfive_timer_stop(starfive_timer_t *timer) +{ + assert(timer); + assert(timer->regs); + + timer->regs->enable = STARFIVE_TIMER_DISABLED; +} + +void starfive_timer_handle_irq(starfive_timer_t *timer) +{ + assert(timer); + assert(timer->regs); + + timer->value_h += 1; + + while (timer->regs->intclr & STARFIVE_TIMER_INTCLR_BUSY) { + /* + * Hardware will not currently accept writes to this register. + * Wait for this bit to be unset by hardware. + */ + } + + timer->regs->intclr = 1; +} + +uint64_t starfive_timer_get_time(starfive_timer_t *timer) +{ + assert(timer); + assert(timer->regs); + + /* the timer value counts down from the load value */ + uint64_t value_l = (uint64_t)(STARFIVE_TIMER_MAX_TICKS - timer->regs->value); + uint64_t value_h = (uint64_t)timer->value_h; + + /* Include unhandled interrupt in value_h */ + if (timer->regs->intclr == 1) { + value_h += 1; + } + + uint64_t value_ticks = (value_h << 32) | value_l; + + /* convert from ticks to nanoseconds */ + uint64_t value_whole_seconds = value_ticks / STARFIVE_TIMER_TICKS_PER_SECOND; + uint64_t value_subsecond_ticks = value_ticks % STARFIVE_TIMER_TICKS_PER_SECOND; + uint64_t value_subsecond_ns = + (value_subsecond_ticks * NS_IN_S) / STARFIVE_TIMER_TICKS_PER_SECOND; + uint64_t value_ns = value_whole_seconds * NS_IN_S + value_subsecond_ns; + + return value_ns; +} + +void starfive_timer_reset(starfive_timer_t *timer) +{ + assert(timer); + assert(timer->regs); + assert(timer->regs->enable == STARFIVE_TIMER_DISABLED); + + timer->regs->ctrl = STARFIVE_TIMER_MODE_CONTINUOUS; + timer->regs->load = STARFIVE_TIMER_MAX_TICKS; + timer->value_h = 0; +} + +int starfive_timer_set_timeout(starfive_timer_t *timer, uint64_t ns, bool is_periodic) +{ + starfive_timer_stop(timer); + timer->value_h = 0; + + if (is_periodic) { + timer->regs->ctrl = STARFIVE_TIMER_MODE_CONTINUOUS; + } else { + timer->regs->ctrl = STARFIVE_TIMER_MODE_SINGLE; + } + + uint64_t ticks_whole_seconds = (ns / NS_IN_S) * STARFIVE_TIMER_TICKS_PER_SECOND; + uint64_t ticks_remainder = (ns % NS_IN_S) * STARFIVE_TIMER_TICKS_PER_SECOND / NS_IN_S; + uint64_t num_ticks = ticks_whole_seconds + ticks_remainder; + + if (num_ticks > STARFIVE_TIMER_MAX_TICKS) { + ZF_LOGE("Requested timeout of %"PRIu64" ns exceeds hardware limit of %"PRIu64" ns", + ns, + MAX_TIMEOUT_NS); + return -EINVAL; + } + + timer->regs->load = num_ticks; + starfive_timer_start(timer); + + return 0; +} + +void starfive_timer_disable_all_channels(void *vaddr) +{ + assert(vaddr); + + for (int x = 0; x < STARFIVE_TIMER_NUM_CHANNELS; x++) { + uint32_t *enable = vaddr + 0x10 + x * STARFIVE_TIMER_CHANNEL_REGISTERS_LEN_IN_BYTES; + *enable = STARFIVE_TIMER_DISABLED; + } +} + +void starfive_timer_init(starfive_timer_t *timer, void *vaddr, uint64_t channel) +{ + assert(timer); + assert(vaddr); + assert(channel >= 0 && channel < STARFIVE_TIMER_NUM_CHANNELS); + + timer->regs = vaddr + STARFIVE_TIMER_CHANNEL_REGISTERS_LEN_IN_BYTES * channel; + timer->regs->enable = STARFIVE_TIMER_DISABLED; + timer->regs->ctrl = STARFIVE_TIMER_MODE_CONTINUOUS; + timer->regs->load = STARFIVE_TIMER_MAX_TICKS; + timer->regs->intmask = STARFIVE_TIMER_INTERRUPT_UNMASKED; + timer->value_h = 0; +} From 523cd4019d0aff9ca8b02d49205af2c4ef6c8315 Mon Sep 17 00:00:00 2001 From: Jimmy Brush Date: Thu, 24 Aug 2023 16:01:10 -0400 Subject: [PATCH 2/5] star64: Enable serial data available interrupt The interrupt is enabled on init. Nothing needs to be done in the IRQ handler as the next read will acknowledge the interrupt to the device. Signed-off-by: Jimmy Brush --- libplatsupport/src/plat/star64/serial.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libplatsupport/src/plat/star64/serial.c b/libplatsupport/src/plat/star64/serial.c index 54f1dad8e..be0d14c67 100644 --- a/libplatsupport/src/plat/star64/serial.c +++ b/libplatsupport/src/plat/star64/serial.c @@ -11,6 +11,8 @@ #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 */ @@ -38,7 +40,11 @@ int uart_putchar(ps_chardevice_t *d, int c) static void uart_handle_irq(ps_chardevice_t *dev) { - /* This UART driver is not interrupt driven, there is nothing to do here. */ + /* + * 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, @@ -63,6 +69,7 @@ int uart_init(const struct dev_defn *defn, dev->flags = SERIAL_AUTO_CR; *REG_PTR(dev->vaddr, 0x8) = 1; + *REG_PTR(dev->vaddr, UART_IER) = UART_IER_ERDAI; return 0; } From 0eee6472f06153a4df235e98fd6970962fe6c722 Mon Sep 17 00:00:00 2001 From: Ivan Velickovic Date: Wed, 12 Jun 2024 00:04:57 +0800 Subject: [PATCH 3/5] star64: clarify comment Signed-off-by: Ivan Velickovic --- libplatsupport/src/plat/star64/timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libplatsupport/src/plat/star64/timer.c b/libplatsupport/src/plat/star64/timer.c index ba25e972e..ceaa867a8 100644 --- a/libplatsupport/src/plat/star64/timer.c +++ b/libplatsupport/src/plat/star64/timer.c @@ -51,7 +51,7 @@ void starfive_timer_handle_irq(starfive_timer_t *timer) while (timer->regs->intclr & STARFIVE_TIMER_INTCLR_BUSY) { /* - * Hardware will not currently accept writes to this register. + * Hardware does not accept writes to this register while BUSY is set. * Wait for this bit to be unset by hardware. */ } From dfea2582f3349fc6010d9b591ca2aed76d153cfa Mon Sep 17 00:00:00 2001 From: Ivan Velickovic Date: Wed, 12 Jun 2024 00:07:35 +0800 Subject: [PATCH 4/5] star64: use UINT32_MAX for MAX_TICKS Signed-off-by: Ivan Velickovic --- libplatsupport/plat_include/star64/platsupport/plat/timer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libplatsupport/plat_include/star64/platsupport/plat/timer.h b/libplatsupport/plat_include/star64/platsupport/plat/timer.h index d6cef86eb..3296ce821 100644 --- a/libplatsupport/plat_include/star64/platsupport/plat/timer.h +++ b/libplatsupport/plat_include/star64/platsupport/plat/timer.h @@ -26,7 +26,7 @@ #define STARFIVE_TIMER_REGISTER_WINDOW_LEN_IN_BYTES 0x10000 #define STARFIVE_TIMER_TICKS_PER_SECOND 0x16e3600 -#define STARFIVE_TIMER_MAX_TICKS 0xffffffff +#define STARFIVE_TIMER_MAX_TICKS UINT32_MAX /* Register value constants */ #define STARFIVE_TIMER_MODE_CONTINUOUS 0 From 94a725de198ff0cef77c54389005dd67a090c2fb Mon Sep 17 00:00:00 2001 From: Ivan Velickovic Date: Wed, 12 Jun 2024 00:08:48 +0800 Subject: [PATCH 5/5] star64: add comment to clarify #define Signed-off-by: Ivan Velickovic --- libplatsupport/plat_include/star64/platsupport/plat/timer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libplatsupport/plat_include/star64/platsupport/plat/timer.h b/libplatsupport/plat_include/star64/platsupport/plat/timer.h index 3296ce821..cffbe514b 100644 --- a/libplatsupport/plat_include/star64/platsupport/plat/timer.h +++ b/libplatsupport/plat_include/star64/platsupport/plat/timer.h @@ -24,6 +24,7 @@ /* This information comes from the DTS file */ #define STARFIVE_TIMER_BASE 0x13050000 #define STARFIVE_TIMER_REGISTER_WINDOW_LEN_IN_BYTES 0x10000 +/* This is 24MHz */ #define STARFIVE_TIMER_TICKS_PER_SECOND 0x16e3600 #define STARFIVE_TIMER_MAX_TICKS UINT32_MAX