bsps: Use new APBUART register block API

This commit is contained in:
Sebastian Huber
2023-06-15 13:24:28 +02:00
parent 49ad450d70
commit 8fdecf6c55
9 changed files with 235 additions and 111 deletions

View File

@@ -34,7 +34,7 @@
#define APBUART_TERMIOS_H #define APBUART_TERMIOS_H
#include <rtems/termiostypes.h> #include <rtems/termiostypes.h>
#include "grlib.h" #include "apbuart.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -42,7 +42,7 @@ extern "C" {
struct apbuart_context { struct apbuart_context {
rtems_termios_device_context base; rtems_termios_device_context base;
struct apbuart_regs *regs; apbuart *regs;
unsigned int freq_hz; unsigned int freq_hz;
rtems_vector_number irq; rtems_vector_number irq;
volatile int sending; volatile int sending;

View File

@@ -82,7 +82,7 @@ static int find_matching_apbuart(struct ambapp_dev *dev, int index, void *arg)
struct ambapp_apb_info *apb = (struct ambapp_apb_info *)dev->devinfo; struct ambapp_apb_info *apb = (struct ambapp_apb_info *)dev->devinfo;
/* Extract needed information of one APBUART */ /* Extract needed information of one APBUART */
apbuarts[uarts].regs = (struct apbuart_regs *)apb->start; apbuarts[uarts].regs = (apbuart *)apb->start;
apbuarts[uarts].irq = apb->common.irq; apbuarts[uarts].irq = apb->common.irq;
/* Get APBUART core frequency, it is assumed that it is the same /* Get APBUART core frequency, it is assumed that it is the same
* as Bus frequency where the UART is situated * as Bus frequency where the UART is situated

View File

@@ -43,9 +43,10 @@
#include <stdio.h> #include <stdio.h>
#include <grlib/apbuart.h> #include <grlib/apbuart.h>
#include <grlib/ambapp.h> #include <grlib/ambapp.h>
#include <grlib/io.h>
int grlib_debug_uart_index __attribute__((weak)) = 0; int grlib_debug_uart_index __attribute__((weak)) = 0;
struct apbuart_regs *grlib_debug_uart = NULL; apbuart *grlib_debug_uart = NULL;
/* Before UART driver has registered (or when no UART is available), calls to /* Before UART driver has registered (or when no UART is available), calls to
* printk that gets to bsp_out_char() will be filling data into the * printk that gets to bsp_out_char() will be filling data into the
@@ -87,13 +88,17 @@ static void bsp_debug_uart_init(void)
VENDOR_GAISLER, GAISLER_APBUART, VENDOR_GAISLER, GAISLER_APBUART,
ambapp_find_by_idx, (void *)&i); ambapp_find_by_idx, (void *)&i);
if (adev) { if (adev) {
uint32_t ctrl;
/* Found a matching debug console, initialize debug uart if present /* Found a matching debug console, initialize debug uart if present
* for printk * for printk
*/ */
apb = (struct ambapp_apb_info *)adev->devinfo; apb = (struct ambapp_apb_info *)adev->devinfo;
grlib_debug_uart = (struct apbuart_regs *)apb->start; grlib_debug_uart = (apbuart *)apb->start;
grlib_debug_uart->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE; ctrl = grlib_load_32(&grlib_debug_uart->ctrl);
grlib_debug_uart->status = 0; ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE;
grlib_store_32(&grlib_debug_uart->ctrl, ctrl);
grlib_store_32(&grlib_debug_uart->status, 0);
} }
} }
@@ -107,10 +112,14 @@ RTEMS_SYSINIT_ITEM(
static void bsp_out_char(char c) static void bsp_out_char(char c)
{ {
if (grlib_debug_uart == NULL) { if (grlib_debug_uart == NULL) {
uint32_t ctrl;
/* Try to assign standard UART address to debug driver to pass some tests */ /* Try to assign standard UART address to debug driver to pass some tests */
grlib_debug_uart = (struct apbuart_regs *) 0x80000100; grlib_debug_uart = (apbuart *) 0x80000100;
grlib_debug_uart->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE; ctrl = grlib_load_32(&grlib_debug_uart->ctrl);
grlib_debug_uart->status = 0; ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE;
grlib_store_32(&grlib_debug_uart->ctrl, ctrl);
grlib_store_32(&grlib_debug_uart->status, 0);
/* Local debug buffer when UART driver has not registered */ /* Local debug buffer when UART driver has not registered */
/* /*
pre_printk_dbgbuf[pre_printk_pos++] = c; pre_printk_dbgbuf[pre_printk_pos++] = c;

View File

@@ -47,11 +47,15 @@
#include <grlib/ambapp_bus.h> #include <grlib/ambapp_bus.h>
#include <grlib/apbuart.h> #include <grlib/apbuart.h>
#include <grlib/ambapp.h> #include <grlib/ambapp.h>
#include <grlib/grlib.h> #include <grlib/io.h>
#include <grlib/cons.h> #include <grlib/cons.h>
#include <rtems/termiostypes.h> #include <rtems/termiostypes.h>
#include <grlib/apbuart_cons.h> #include <grlib/apbuart_cons.h>
#ifdef LEON3
#include <bsp/leon3.h>
#endif
/*#define DEBUG 1 */ /*#define DEBUG 1 */
#ifdef DEBUG #ifdef DEBUG
@@ -60,12 +64,6 @@
#define DBG(x...) #define DBG(x...)
#endif #endif
/* LEON3 Low level transmit/receive functions provided by debug-uart code */
#ifdef LEON3
#include <leon.h>
extern struct apbuart_regs *leon3_debug_uart; /* The debug UART */
#endif
/* Probed hardware capabilities */ /* Probed hardware capabilities */
enum { enum {
CAP_FIFO = 0x01, /* FIFO available */ CAP_FIFO = 0x01, /* FIFO available */
@@ -74,7 +72,7 @@ enum {
struct apbuart_priv { struct apbuart_priv {
struct console_dev condev; struct console_dev condev;
struct drvmgr_dev *dev; struct drvmgr_dev *dev;
struct apbuart_regs *regs; apbuart *regs;
struct rtems_termios_tty *tty; struct rtems_termios_tty *tty;
char devName[52]; char devName[52];
volatile int sending; volatile int sending;
@@ -213,18 +211,23 @@ static const rtems_termios_device_handler handler_polled = {
* can select appropriate routines for the hardware. probecap() return value * can select appropriate routines for the hardware. probecap() return value
* is a CAP_ bitmask. * is a CAP_ bitmask.
*/ */
static int probecap(struct apbuart_regs *regs) static int probecap(apbuart *regs)
{ {
int cap = 0; int cap = 0;
uint32_t ctrl;
/* Probe FIFO */ /* Probe FIFO */
if (regs->ctrl & APBUART_CTRL_FA) { ctrl = grlib_load_32(&regs->ctrl);
if (ctrl & APBUART_CTRL_FA) {
cap |= CAP_FIFO; cap |= CAP_FIFO;
/* Probe RX delayed interrupt */ /* Probe RX delayed interrupt */
regs->ctrl |= APBUART_CTRL_DI; ctrl |= APBUART_CTRL_DI;
if (regs->ctrl & APBUART_CTRL_DI) { grlib_store_32(&regs->ctrl, ctrl);
regs->ctrl &= ~APBUART_CTRL_DI; ctrl = grlib_load_32(&regs->ctrl);
if (ctrl & APBUART_CTRL_DI) {
ctrl &= ~APBUART_CTRL_DI;
grlib_store_32(&regs->ctrl, ctrl);
cap |= CAP_DI; cap |= CAP_DI;
} }
} }
@@ -241,6 +244,7 @@ int apbuart_init1(struct drvmgr_dev *dev)
char prefix[32]; char prefix[32];
unsigned int db; unsigned int db;
static int first_uart = 1; static int first_uart = 1;
uint32_t ctrl;
/* The default operation in AMP is to use APBUART[0] for CPU[0], /* The default operation in AMP is to use APBUART[0] for CPU[0],
* APBUART[1] for CPU[1] and so on. The remaining UARTs is not used * APBUART[1] for CPU[1] and so on. The remaining UARTs is not used
@@ -269,10 +273,12 @@ int apbuart_init1(struct drvmgr_dev *dev)
if (ambadev == NULL) if (ambadev == NULL)
return -1; return -1;
pnpinfo = &ambadev->info; pnpinfo = &ambadev->info;
priv->regs = (struct apbuart_regs *)pnpinfo->apb_slv->start; priv->regs = (apbuart *)pnpinfo->apb_slv->start;
/* Clear HW regs, leave baudrate register as it is */ /* Clear HW regs, leave baudrate register as it is */
priv->regs->status = 0; grlib_store_32(&priv->regs->status, 0);
ctrl = grlib_load_32(&priv->regs->ctrl);
/* leave Transmitter/receiver if this is the RTEMS debug UART (assume /* leave Transmitter/receiver if this is the RTEMS debug UART (assume
* it has been setup by boot loader). * it has been setup by boot loader).
@@ -280,10 +286,10 @@ int apbuart_init1(struct drvmgr_dev *dev)
db = 0; db = 0;
#ifdef LEON3 #ifdef LEON3
if (priv->regs == leon3_debug_uart) { if (priv->regs == leon3_debug_uart) {
db = priv->regs->ctrl & (APBUART_CTRL_RE | db = ctrl & (APBUART_CTRL_RE |
APBUART_CTRL_TE | APBUART_CTRL_TE |
APBUART_CTRL_PE | APBUART_CTRL_PE |
APBUART_CTRL_PS); APBUART_CTRL_PS);
} }
#endif #endif
/* Let UART debug tunnelling be untouched if Flow-control is set. /* Let UART debug tunnelling be untouched if Flow-control is set.
@@ -293,12 +299,12 @@ int apbuart_init1(struct drvmgr_dev *dev)
* guess that we are debugging if FL is already set, the debugger set * guess that we are debugging if FL is already set, the debugger set
* either LB or DB depending on UART capabilities. * either LB or DB depending on UART capabilities.
*/ */
if (priv->regs->ctrl & APBUART_CTRL_FL) { if (ctrl & APBUART_CTRL_FL) {
db |= priv->regs->ctrl & (APBUART_CTRL_DB | db |= ctrl & (APBUART_CTRL_DB |
APBUART_CTRL_LB | APBUART_CTRL_FL); APBUART_CTRL_LB | APBUART_CTRL_FL);
} }
priv->regs->ctrl = db; grlib_store_32(&priv->regs->ctrl, db);
priv->cap = probecap(priv->regs); priv->cap = probecap(priv->regs);
@@ -387,12 +393,13 @@ static int apbuart_info(
sprintf(buf, "FS Name: %s", priv->condev.fsname); sprintf(buf, "FS Name: %s", priv->condev.fsname);
print_line(p, buf); print_line(p, buf);
} }
sprintf(buf, "STATUS REG: 0x%x", priv->regs->status); sprintf(buf, "STATUS REG: 0x%x", grlib_load_32(&priv->regs->status));
print_line(p, buf); print_line(p, buf);
sprintf(buf, "CTRL REG: 0x%x", priv->regs->ctrl); sprintf(buf, "CTRL REG: 0x%x", grlib_load_32(&priv->regs->ctrl));
print_line(p, buf); print_line(p, buf);
sprintf(buf, "SCALER REG: 0x%x baud rate %d", sprintf(buf, "SCALER REG: 0x%x baud rate %d",
priv->regs->scaler, apbuart_get_baud(priv)); grlib_load_32(&priv->regs->scaler),
apbuart_get_baud(priv));
print_line(p, buf); print_line(p, buf);
return DRVMGR_OK; return DRVMGR_OK;
@@ -407,6 +414,8 @@ static bool first_open(
) )
{ {
struct apbuart_priv *uart = base_get_priv(base); struct apbuart_priv *uart = base_get_priv(base);
apbuart *regs = uart->regs;
uint32_t ctrl;
uart->tty = tty; uart->tty = tty;
@@ -418,7 +427,8 @@ static bool first_open(
} }
/* Enable TX/RX */ /* Enable TX/RX */
uart->regs->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE; ctrl = grlib_load_32(&regs->ctrl);
ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE;
if (uart->mode != TERMIOS_POLLED) { if (uart->mode != TERMIOS_POLLED) {
int ret; int ret;
@@ -435,15 +445,15 @@ static bool first_open(
uart->sending = 0; uart->sending = 0;
/* Turn on RX interrupts */ /* Turn on RX interrupts */
ctrl = uart->regs->ctrl;
ctrl |= APBUART_CTRL_RI; ctrl |= APBUART_CTRL_RI;
if (uart->cap & CAP_DI) { if (uart->cap & CAP_DI) {
/* Use RX FIFO interrupt only if delayed interrupt available. */ /* Use RX FIFO interrupt only if delayed interrupt available. */
ctrl |= (APBUART_CTRL_DI | APBUART_CTRL_RF); ctrl |= (APBUART_CTRL_DI | APBUART_CTRL_RF);
} }
uart->regs->ctrl = ctrl;
} }
grlib_store_32(&regs->ctrl, ctrl);
return true; return true;
} }
@@ -454,13 +464,16 @@ static void last_close(
) )
{ {
struct apbuart_priv *uart = base_get_priv(base); struct apbuart_priv *uart = base_get_priv(base);
apbuart *regs = uart->regs;
rtems_interrupt_lock_context lock_context; rtems_interrupt_lock_context lock_context;
uint32_t ctrl;
if (uart->mode != TERMIOS_POLLED) { if (uart->mode != TERMIOS_POLLED) {
/* Turn off RX interrupts */ /* Turn off RX interrupts */
rtems_termios_device_lock_acquire(base, &lock_context); rtems_termios_device_lock_acquire(base, &lock_context);
uart->regs->ctrl &= ctrl = grlib_load_32(&regs->ctrl);
~(APBUART_CTRL_DI | APBUART_CTRL_RI | APBUART_CTRL_RF); ctrl &= ~(APBUART_CTRL_DI | APBUART_CTRL_RI | APBUART_CTRL_RF);
grlib_store_32(&regs->ctrl, ctrl);
rtems_termios_device_lock_release(base, &lock_context); rtems_termios_device_lock_release(base, &lock_context);
/**** Flush device ****/ /**** Flush device ****/
@@ -468,8 +481,8 @@ static void last_close(
/* Wait until all data has been sent */ /* Wait until all data has been sent */
} }
while ( while (
(uart->regs->ctrl & APBUART_CTRL_TE) && (grlib_load_32(&regs->ctrl) & APBUART_CTRL_TE) &&
!(uart->regs->status & APBUART_STATUS_TS) !(grlib_load_32(&regs->status) & APBUART_STATUS_TS)
) { ) {
/* Wait until all data has left shift register */ /* Wait until all data has left shift register */
} }
@@ -480,8 +493,11 @@ static void last_close(
#ifdef LEON3 #ifdef LEON3
/* Disable TX/RX if not used for DEBUG */ /* Disable TX/RX if not used for DEBUG */
if (uart->regs != leon3_debug_uart) if (regs != leon3_debug_uart) {
uart->regs->ctrl &= ~(APBUART_CTRL_RE | APBUART_CTRL_TE); ctrl = grlib_load_32(&regs->ctrl);
ctrl &= ~(APBUART_CTRL_RE | APBUART_CTRL_TE);
grlib_store_32(&regs->ctrl, ctrl);
}
#endif #endif
} }
@@ -497,10 +513,11 @@ static int read_task(rtems_termios_device_context *base)
{ {
rtems_interrupt_lock_context lock_context; rtems_interrupt_lock_context lock_context;
struct apbuart_priv *uart = base_get_priv(base); struct apbuart_priv *uart = base_get_priv(base);
struct apbuart_regs *regs = uart->regs; apbuart *regs = uart->regs;
int cnt; int cnt;
char buf[33]; char buf[33];
struct rtems_termios_tty *tty; struct rtems_termios_tty *tty;
uint32_t ctrl;
uint32_t ctrl_add; uint32_t ctrl_add;
ctrl_add = APBUART_CTRL_RI; ctrl_add = APBUART_CTRL_RI;
@@ -511,10 +528,10 @@ static int read_task(rtems_termios_device_context *base)
do { do {
cnt = 0; cnt = 0;
while ( while (
(regs->status & APBUART_STATUS_DR) && (grlib_load_32(&regs->status) & APBUART_STATUS_DR) &&
(cnt < sizeof(buf)) (cnt < sizeof(buf))
) { ) {
buf[cnt] = regs->data; buf[cnt] = grlib_load_32(&regs->data);
cnt++; cnt++;
} }
if (0 < cnt) { if (0 < cnt) {
@@ -528,9 +545,11 @@ static int read_task(rtems_termios_device_context *base)
* afterwards. * afterwards.
*/ */
rtems_termios_device_lock_acquire(base, &lock_context); rtems_termios_device_lock_acquire(base, &lock_context);
regs->ctrl |= ctrl_add; ctrl = grlib_load_32(&regs->ctrl);
ctrl |= ctrl_add;
grlib_store_32(&regs->ctrl, ctrl);
rtems_termios_device_lock_release(base, &lock_context); rtems_termios_device_lock_release(base, &lock_context);
} while (regs->status & APBUART_STATUS_DR); } while (grlib_load_32(&regs->status) & APBUART_STATUS_DR);
return EOF; return EOF;
} }
@@ -541,7 +560,7 @@ int apbuart_get_baud(struct apbuart_priv *uart)
unsigned int scaler; unsigned int scaler;
/* Get current scaler setting */ /* Get current scaler setting */
scaler = uart->regs->scaler; scaler = grlib_load_32(&uart->regs->scaler);
/* Get APBUART core frequency */ /* Get APBUART core frequency */
drvmgr_freq_get(uart->dev, DEV_APB_SLV, &core_clk_hz); drvmgr_freq_get(uart->dev, DEV_APB_SLV, &core_clk_hz);
@@ -576,7 +595,7 @@ static bool set_attributes(
rtems_termios_device_lock_acquire(base, &lock_context); rtems_termios_device_lock_acquire(base, &lock_context);
/* Read out current value */ /* Read out current value */
ctrl = uart->regs->ctrl; ctrl = grlib_load_32(&uart->regs->ctrl);
switch(t->c_cflag & (PARENB|PARODD)){ switch(t->c_cflag & (PARENB|PARODD)){
case (PARENB|PARODD): case (PARENB|PARODD):
@@ -603,7 +622,7 @@ static bool set_attributes(
ctrl &= ~APBUART_CTRL_FL; ctrl &= ~APBUART_CTRL_FL;
/* Update new settings */ /* Update new settings */
uart->regs->ctrl = ctrl; grlib_store_32(&uart->regs->ctrl, ctrl);
rtems_termios_device_lock_release(base, &lock_context); rtems_termios_device_lock_release(base, &lock_context);
@@ -617,7 +636,7 @@ static bool set_attributes(
scaler = (((core_clk_hz*10)/(baud*8))-5)/10; scaler = (((core_clk_hz*10)/(baud*8))-5)/10;
/* Set new baud rate by setting scaler */ /* Set new baud rate by setting scaler */
uart->regs->scaler = scaler; grlib_store_32(&uart->regs->scaler, scaler);
} }
return true; return true;
@@ -637,7 +656,7 @@ static void get_attributes(
t->c_cflag |= CS8; t->c_cflag |= CS8;
/* Read out current parity */ /* Read out current parity */
ctrl = uart->regs->ctrl; ctrl = grlib_load_32(&uart->regs->ctrl);
if (ctrl & APBUART_CTRL_PE) { if (ctrl & APBUART_CTRL_PE) {
if (ctrl & APBUART_CTRL_PS) if (ctrl & APBUART_CTRL_PS)
t->c_cflag |= PARENB|PARODD; /* Odd parity */ t->c_cflag |= PARENB|PARODD; /* Odd parity */
@@ -673,11 +692,11 @@ static void write_interrupt(
) )
{ {
struct apbuart_priv *uart = base_get_priv(base); struct apbuart_priv *uart = base_get_priv(base);
struct apbuart_regs *regs = uart->regs; apbuart *regs = uart->regs;
int sending; int sending;
unsigned int ctrl; unsigned int ctrl;
ctrl = regs->ctrl; ctrl = grlib_load_32(&regs->ctrl);
if (len > 0) { if (len > 0) {
/* /*
@@ -685,28 +704,30 @@ static void write_interrupt(
* we can tell termios later. * we can tell termios later.
*/ */
/* Enable TX interrupt (interrupt is edge-triggered) */ /* Enable TX interrupt (interrupt is edge-triggered) */
regs->ctrl = ctrl | APBUART_CTRL_TI; ctrl |= APBUART_CTRL_TI;
grlib_store_32(&regs->ctrl, ctrl);
if (ctrl & APBUART_CTRL_FA) { if (ctrl & APBUART_CTRL_FA) {
/* APBUART with FIFO.. Fill as many as FIFO allows */ /* APBUART with FIFO.. Fill as many as FIFO allows */
sending = 0; sending = 0;
while ( while (
((regs->status & APBUART_STATUS_TF) == 0) && ((grlib_load_32(&regs->status) & APBUART_STATUS_TF) == 0) &&
(sending < len) (sending < len)
) { ) {
regs->data = *buf; grlib_store_32(&regs->data, *buf);
buf++; buf++;
sending++; sending++;
} }
} else { } else {
/* start UART TX, this will result in an interrupt when done */ /* start UART TX, this will result in an interrupt when done */
regs->data = *buf; grlib_store_32(&regs->data, *buf);
sending = 1; sending = 1;
} }
} else { } else {
/* No more to send, disable TX interrupts */ /* No more to send, disable TX interrupts */
regs->ctrl = ctrl & ~APBUART_CTRL_TI; ctrl &= ~APBUART_CTRL_TI;
grlib_store_32(&regs->ctrl, ctrl);
/* Tell close that we sent everything */ /* Tell close that we sent everything */
sending = 0; sending = 0;
@@ -722,21 +743,24 @@ static void apbuart_cons_isr(void *arg)
rtems_termios_device_context *base; rtems_termios_device_context *base;
struct console_dev *condev = rtems_termios_get_device_context(tty); struct console_dev *condev = rtems_termios_get_device_context(tty);
struct apbuart_priv *uart = condev_get_priv(condev); struct apbuart_priv *uart = condev_get_priv(condev);
struct apbuart_regs *regs = uart->regs; apbuart *regs = uart->regs;
unsigned int status; unsigned int status;
char buf[33]; char buf[33];
int cnt; int cnt;
if (uart->mode == TERMIOS_TASK_DRIVEN) { if (uart->mode == TERMIOS_TASK_DRIVEN) {
if ((status = regs->status) & APBUART_STATUS_DR) { if ((status = grlib_load_32(&regs->status)) & APBUART_STATUS_DR) {
rtems_interrupt_lock_context lock_context; rtems_interrupt_lock_context lock_context;
uint32_t ctrl;
/* Turn off RX interrupts */ /* Turn off RX interrupts */
base = rtems_termios_get_device_context(tty); base = rtems_termios_get_device_context(tty);
rtems_termios_device_lock_acquire(base, &lock_context); rtems_termios_device_lock_acquire(base, &lock_context);
regs->ctrl &= ctrl = grlib_load_32(&regs->ctrl);
ctrl &=
~(APBUART_CTRL_DI | APBUART_CTRL_RI | ~(APBUART_CTRL_DI | APBUART_CTRL_RI |
APBUART_CTRL_RF); APBUART_CTRL_RF);
grlib_store_32(&regs->ctrl, ctrl);
rtems_termios_device_lock_release(base, &lock_context); rtems_termios_device_lock_release(base, &lock_context);
/* Activate termios RX daemon task */ /* Activate termios RX daemon task */
rtems_termios_rxirq_occured(tty); rtems_termios_rxirq_occured(tty);
@@ -749,10 +773,10 @@ static void apbuart_cons_isr(void *arg)
*/ */
cnt = 0; cnt = 0;
while ( while (
((status=regs->status) & APBUART_STATUS_DR) && ((status=grlib_load_32(&regs->status)) & APBUART_STATUS_DR) &&
(cnt < sizeof(buf)) (cnt < sizeof(buf))
) { ) {
buf[cnt] = regs->data; buf[cnt] = grlib_load_32(&regs->data);
cnt++; cnt++;
} }
if (0 < cnt) { if (0 < cnt) {

View File

@@ -1,8 +1,17 @@
/* SPDX-License-Identifier: BSD-2-Clause */ /* SPDX-License-Identifier: BSD-2-Clause */
/**
* @file
*
* @ingroup RTEMSDeviceGRLIBAPBUART
*
* @brief This source file contains the implementation of
* apbuart_outbyte_wait(), apbuart_outbyte_polled(), and
* apbuart_inbyte_nonblocking().
*/
/* /*
* COPYRIGHT (c) 2010. * Copyright (C) 2021 embedded brains GmbH & Co. KG
* Cobham Gaisler AB.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -27,38 +36,37 @@
*/ */
#include <grlib/apbuart.h> #include <grlib/apbuart.h>
#include <grlib/io.h>
#include <rtems/score/cpuimpl.h> #include <rtems/score/io.h>
void apbuart_outbyte_wait(const struct apbuart_regs *regs) void apbuart_outbyte_wait( const apbuart *regs )
{ {
while ( (regs->status & APBUART_STATUS_TE) == 0 ) { while ( ( grlib_load_32( &regs->status ) & APBUART_STATUS_TE ) == 0 ) {
/* Lower bus utilization while waiting for UART */ _IO_Relax();
_CPU_Instruction_no_operation();
_CPU_Instruction_no_operation();
_CPU_Instruction_no_operation();
_CPU_Instruction_no_operation();
_CPU_Instruction_no_operation();
_CPU_Instruction_no_operation();
_CPU_Instruction_no_operation();
_CPU_Instruction_no_operation();
} }
} }
void apbuart_outbyte_polled(struct apbuart_regs *regs, char ch) void apbuart_outbyte_polled( apbuart *regs, char ch)
{ {
apbuart_outbyte_wait(regs); apbuart_outbyte_wait( regs );
regs->data = (uint8_t) ch; grlib_store_32( &regs->data, (uint8_t) ch );
} }
int apbuart_inbyte_nonblocking(struct apbuart_regs *regs) int apbuart_inbyte_nonblocking( apbuart *regs )
{ {
/* Clear errors */ uint32_t status;
regs->status = ~APBUART_STATUS_ERR;
if ((regs->status & APBUART_STATUS_DR) == 0) { status = grlib_load_32( &regs->status );
/* Clear errors, writes to non-error flags are ignored */
status &= ~( APBUART_STATUS_FE | APBUART_STATUS_PE | APBUART_STATUS_OV |
APBUART_STATUS_BR );
grlib_store_32( &regs->status, status );
if ( ( status & APBUART_STATUS_DR ) == 0 ) {
return -1; return -1;
} }
return (uint8_t) regs->data; return (int) APBUART_DATA_DATA_GET( grlib_load_32( &regs->data ) );
} }

View File

@@ -32,6 +32,7 @@
#include <grlib/apbuart_termios.h> #include <grlib/apbuart_termios.h>
#include <grlib/apbuart.h> #include <grlib/apbuart.h>
#include <grlib/io.h>
#include <bsp.h> #include <bsp.h>
static void apbuart_isr(void *arg) static void apbuart_isr(void *arg)
@@ -42,9 +43,9 @@ static void apbuart_isr(void *arg)
char data; char data;
/* Get all received characters */ /* Get all received characters */
while ((status=uart->regs->status) & APBUART_STATUS_DR) { while ((status=grlib_load_32(&uart->regs->status)) & APBUART_STATUS_DR) {
/* Data has arrived, get new data */ /* Data has arrived, get new data */
data = uart->regs->data; data = (char)grlib_load_32(&uart->regs->data);
/* Tell termios layer about new character */ /* Tell termios layer about new character */
rtems_termios_enqueue_raw_characters(tty, &data, 1); rtems_termios_enqueue_raw_characters(tty, &data, 1);
@@ -52,7 +53,7 @@ static void apbuart_isr(void *arg)
if ( if (
(status & APBUART_STATUS_TE) (status & APBUART_STATUS_TE)
&& (uart->regs->ctrl & APBUART_CTRL_TI) != 0 && (grlib_load_32(&uart->regs->ctrl) & APBUART_CTRL_TI) != 0
) { ) {
/* write_interrupt will get called from this function */ /* write_interrupt will get called from this function */
rtems_termios_dequeue_characters(tty, 1); rtems_termios_dequeue_characters(tty, 1);
@@ -67,23 +68,27 @@ static void apbuart_write_support(
{ {
struct apbuart_context *uart = (struct apbuart_context *) base; struct apbuart_context *uart = (struct apbuart_context *) base;
int sending; int sending;
uint32_t ctrl;
ctrl = grlib_load_32(&uart->regs->ctrl);
if (len > 0) { if (len > 0) {
/* Enable TX interrupt (interrupt is edge-triggered) */ /* Enable TX interrupt (interrupt is edge-triggered) */
uart->regs->ctrl |= APBUART_CTRL_TI; ctrl |= APBUART_CTRL_TI;
/* start UART TX, this will result in an interrupt when done */ /* start UART TX, this will result in an interrupt when done */
uart->regs->data = *buf; grlib_store_32(&uart->regs->data, (uint8_t)*buf);
sending = 1; sending = 1;
} else { } else {
/* No more to send, disable TX interrupts */ /* No more to send, disable TX interrupts */
uart->regs->ctrl &= ~APBUART_CTRL_TI; ctrl &= ~APBUART_CTRL_TI;
/* Tell close that we sent everything */ /* Tell close that we sent everything */
sending = 0; sending = 0;
} }
grlib_store_32(&uart->regs->ctrl, ctrl);
uart->sending = sending; uart->sending = sending;
} }
@@ -134,7 +139,7 @@ static bool apbuart_set_attributes(
rtems_termios_device_lock_acquire(base, &lock_context); rtems_termios_device_lock_acquire(base, &lock_context);
/* Read out current value */ /* Read out current value */
ctrl = uart->regs->ctrl; ctrl = grlib_load_32(&uart->regs->ctrl);
switch (t->c_cflag & (PARENB|PARODD)) { switch (t->c_cflag & (PARENB|PARODD)) {
case (PARENB|PARODD): case (PARENB|PARODD):
@@ -162,7 +167,7 @@ static bool apbuart_set_attributes(
} }
/* Update new settings */ /* Update new settings */
uart->regs->ctrl = ctrl; grlib_store_32(&uart->regs->ctrl, ctrl);
rtems_termios_device_lock_release(base, &lock_context); rtems_termios_device_lock_release(base, &lock_context);
@@ -173,7 +178,7 @@ static bool apbuart_set_attributes(
scaler = (((uart->freq_hz * 10) / (baud * 8)) - 5) / 10; scaler = (((uart->freq_hz * 10) / (baud * 8)) - 5) / 10;
/* Set new baud rate by setting scaler */ /* Set new baud rate by setting scaler */
uart->regs->scaler = scaler; grlib_store_32(&uart->regs->scaler, scaler);
} }
return true; return true;
@@ -184,7 +189,8 @@ static void apbuart_set_best_baud(
struct termios *term struct termios *term
) )
{ {
uint32_t baud = (uart->freq_hz * 10) / ((uart->regs->scaler * 10 + 5) * 8); uint32_t baud = (uart->freq_hz * 10) /
((grlib_load_32(&uart->regs->scaler) * 10 + 5) * 8);
rtems_termios_set_best_baud(term, baud); rtems_termios_set_best_baud(term, baud);
} }
@@ -197,12 +203,15 @@ static bool apbuart_first_open_polled(
) )
{ {
struct apbuart_context *uart = (struct apbuart_context *) base; struct apbuart_context *uart = (struct apbuart_context *) base;
uint32_t ctrl;
apbuart_set_best_baud(uart, term); apbuart_set_best_baud(uart, term);
/* Initialize UART on opening */ /* Initialize UART on opening */
uart->regs->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE; ctrl = grlib_load_32(&uart->regs->ctrl);
uart->regs->status = 0; ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE;
grlib_store_32(&uart->regs->ctrl, ctrl);
grlib_store_32(&uart->regs->status, 0);
return true; return true;
} }
@@ -216,6 +225,7 @@ static bool apbuart_first_open_interrupt(
{ {
struct apbuart_context *uart = (struct apbuart_context *) base; struct apbuart_context *uart = (struct apbuart_context *) base;
rtems_status_code sc; rtems_status_code sc;
uint32_t ctrl;
apbuart_set_best_baud(uart, term); apbuart_set_best_baud(uart, term);
@@ -229,11 +239,13 @@ static bool apbuart_first_open_interrupt(
uart->sending = 0; uart->sending = 0;
/* Enable Receiver and transmitter and Turn on RX interrupts */ /* Enable Receiver and transmitter and Turn on RX interrupts */
uart->regs->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE | ctrl = grlib_load_32(&uart->regs->ctrl);
APBUART_CTRL_RI; ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE | APBUART_CTRL_RI;
grlib_store_32(&uart->regs->ctrl, ctrl);
/* Initialize UART on opening */ /* Initialize UART on opening */
uart->regs->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE; ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE;
uart->regs->status = 0; grlib_store_32(&uart->regs->ctrl, ctrl);
grlib_store_32(&uart->regs->status, 0);
return true; return true;
} }
@@ -246,10 +258,13 @@ static void apbuart_last_close_interrupt(
{ {
struct apbuart_context *uart = (struct apbuart_context *) base; struct apbuart_context *uart = (struct apbuart_context *) base;
rtems_interrupt_lock_context lock_context; rtems_interrupt_lock_context lock_context;
uint32_t ctrl;
/* Turn off RX interrupts */ /* Turn off RX interrupts */
rtems_termios_device_lock_acquire(base, &lock_context); rtems_termios_device_lock_acquire(base, &lock_context);
uart->regs->ctrl &= ~(APBUART_CTRL_RI); ctrl = grlib_load_32(&uart->regs->ctrl);
ctrl &= ~APBUART_CTRL_RI;
grlib_store_32(&uart->regs->ctrl, ctrl);
rtems_termios_device_lock_release(base, &lock_context); rtems_termios_device_lock_release(base, &lock_context);
/**** Flush device ****/ /**** Flush device ****/

View File

@@ -81,7 +81,7 @@ static int find_matching_apbuart(struct ambapp_dev *dev, int index, void *arg)
struct ambapp_apb_info *apb = (struct ambapp_apb_info *)dev->devinfo; struct ambapp_apb_info *apb = (struct ambapp_apb_info *)dev->devinfo;
/* Extract needed information of one APBUART */ /* Extract needed information of one APBUART */
apbuarts[uarts].regs = (struct apbuart_regs *)apb->start; apbuarts[uarts].regs = (apbuart *)apb->start;
apbuarts[uarts].irq = apb->common.irq; apbuarts[uarts].irq = apb->common.irq;
/* Get APBUART core frequency, it is assumed that it is the same /* Get APBUART core frequency, it is assumed that it is the same
* as Bus frequency where the UART is situated * as Bus frequency where the UART is situated

View File

@@ -35,14 +35,17 @@
*/ */
#include <bsp.h> #include <bsp.h>
#include <leon.h> #include <bsp/leon3.h>
#include <rtems/bspIo.h> #include <rtems/bspIo.h>
#include <rtems/sysinit.h> #include <rtems/sysinit.h>
#include <rtems/score/thread.h> #include <rtems/score/thread.h>
#include <grlib/apbuart.h> #include <grlib/apbuart.h>
#include <grlib/io.h>
#include <grlib/ambapp.h>
int leon3_debug_uart_index __attribute__((weak)) = 0; int leon3_debug_uart_index __attribute__((weak)) = 0;
struct apbuart_regs *leon3_debug_uart = NULL; apbuart *leon3_debug_uart = NULL;
static void bsp_debug_uart_init(void); static void bsp_debug_uart_init(void);
@@ -105,15 +108,18 @@ static void bsp_debug_uart_init(void)
ambapp_find_by_idx, (void *)&i); ambapp_find_by_idx, (void *)&i);
if (adev != NULL) { if (adev != NULL) {
struct ambapp_apb_info *apb; struct ambapp_apb_info *apb;
uint32_t ctrl;
/* /*
* Found a matching debug console, initialize debug UART if present for * Found a matching debug console, initialize debug UART if present for
* printk(). * printk().
*/ */
apb = (struct ambapp_apb_info *)adev->devinfo; apb = (struct ambapp_apb_info *)adev->devinfo;
leon3_debug_uart = (struct apbuart_regs *)apb->start; leon3_debug_uart = (apbuart *)apb->start;
leon3_debug_uart->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE; ctrl = grlib_load_32(&leon3_debug_uart->ctrl);
leon3_debug_uart->status = 0; ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE;
grlib_store_32(&leon3_debug_uart->ctrl, ctrl);
grlib_store_32(&leon3_debug_uart->status, 0);
BSP_poll_char = bsp_debug_uart_poll_char; BSP_poll_char = bsp_debug_uart_poll_char;
BSP_output_char = bsp_debug_uart_output_char; BSP_output_char = bsp_debug_uart_output_char;

View File

@@ -0,0 +1,62 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/**
* @file
*
* @ingroup RTEMSBSPsSPARCLEON3
*
* @brief This header file provides interfaces used by the BSP implementation.
*/
/*
* Copyright (C) 2021 embedded brains GmbH & Co. KG
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LIBBSP_SPARC_LEON3_BSP_LEON3_H
#define LIBBSP_SPARC_LEON3_BSP_LEON3_H
#include <grlib/apbuart-regs.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup RTEMSBSPsSPARCLEON3
*
* @{
*/
/**
* @brief This pointer provides the debug APBUART register block address.
*/
extern apbuart *leon3_debug_uart;
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* LIBBSP_SPARC_LEON3_BSP_LEON3_H */