Commit 5035e03d authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

general: rework UART driver into a device-struct base driver attached to a…

general: rework UART driver into a device-struct base driver attached to a console driver. Refactor code to use the console driver instead of direct UART calls
parent d6ec3b48
......@@ -135,6 +135,11 @@ config LATENCY_SYSLOG
# The other ones can be set by non-developers
config IPMI_CONSOLE
bool "Support for IPMI remote console"
depends on WR_NODE
default y
config P2P
depends on WR_NODE
default n
......
......@@ -70,4 +70,8 @@ int board_update(void);
#define CONFIG_DISALLOW_LONG_DIVISION
#define BOARD_MAX_CONSOLE_DEVICES 1
#define CONSOLE_UART_BAUDRATE 115200
#endif /* __BOARD_WRC_H */
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2012-2019 CERN (www.cern.ch)
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#include <stdio.h>
#include "board.h"
#include "dev/simple_uart.h"
#include "dev/console.h"
static int puts_direct = 0;
struct console_uart_priv_data
{
struct simple_uart_device uart_dev;
};
static struct console_uart_priv_data console_uart_priv;
struct console_device console_uart_dev;
struct console_device* console_devs[BOARD_MAX_CONSOLE_DEVICES];
static int con_uart_put_string(struct console_device* dev, const char *s)
{
struct console_uart_priv_data* priv = (struct console_uart_priv_data*) dev->priv;
return suart_write_string(&priv->uart_dev, s);
}
static int con_uart_getc(struct console_device* dev)
{
struct console_uart_priv_data* priv = (struct console_uart_priv_data*) dev->priv;
return suart_read_byte(&priv->uart_dev);
}
void console_uart_write_bytes( uint8_t *buf, int count )
{
int i;
for(i=0;i<count;i++)
suart_write_byte( &console_uart_priv.uart_dev, buf[i] );
}
void console_uart_set_crlf_mode(int on)
{
console_uart_priv.uart_dev.crlf_mode = on;
}
#ifdef CONFIG_IPMI_CONSOLE
#define IPMI_CON_TX_BUF_SIZE 1024
#define IPMI_CON_RX_BUF_SIZE 128
#define IPMI_CON_RX_TIMEOUT 1000
struct ring_buffer
{
uint8_t *data;
int head, tail, size, count;
};
struct console_ipmi_priv_data
{
uint8_t tx_buf_mem[IPMI_CON_TX_BUF_SIZE];
uint8_t rx_buf_mem[IPMI_CON_RX_BUF_SIZE];
struct ring_buffer rx_buf;
struct ring_buffer tx_buf;
};
struct console_device console_ipmi_dev;
struct console_ipmi_priv_data console_ipmi_priv;
static inline void rbuf_put( struct ring_buffer* buf, uint8_t c )
{
if (buf->count >= buf->size)
return;
buf->data[buf->head] = c;
buf->head++;
buf->count++;
if (buf->head >= buf->size)
buf->head = 0;
}
static inline int rbuf_get( struct ring_buffer* buf )
{
if( !buf->count )
return -1;
int rv = buf->data[buf->tail];
buf->tail++;
if (buf->tail >= buf->size)
buf->tail = 0;
buf->count--;
return rv;
}
static inline int rbuf_init( struct ring_buffer *buf, int size, uint8_t *mem )
{
buf->head = buf->tail = buf->count = 0;
buf->size = size;
buf->data = mem;
return 0;
}
static inline int rbuf_full(struct ring_buffer *buf)
{
return buf->size == buf->count;
}
static inline int rbuf_purge(struct ring_buffer *buf)
{
buf->head = buf->tail = buf->count = 0;
}
static int con_ipmi_put_string(struct console_device* dev, const char *s)
{
struct console_ipmi_priv_data* priv = (struct console_ipmi_priv_data*) dev->priv;
int c, n = 0;
while( c = *s++ )
{
rbuf_put( &priv->tx_buf, c );
n++;
}
if( rbuf_full(&priv->tx_buf ) )
rbuf_purge(&priv->tx_buf);
return n;
}
static int con_ipmi_getc(struct console_device* dev)
{
struct console_ipmi_priv_data* priv = (struct console_ipmi_priv_data*) dev->priv;
return rbuf_get( &priv->rx_buf );
}
int console_ipmi_process_request(struct console_device* dev, uint8_t *req, int size, uint8_t *rsp, int rsp_size )
{
struct console_ipmi_priv_data* priv = (struct console_ipmi_priv_data*) dev->priv;
int i;
int cnt = priv->tx_buf.count;
for(i = 0; i < size; i++ )
{
puts_direct = 1;
//pp_printf("put %x\n", req[i] );
puts_direct = 0;
rbuf_put( &priv->rx_buf, req[i] );
}
for(i = 0; i < rsp_size; i++)
{
if ( priv->tx_buf.count == 0 )
break;
rsp[i] = rbuf_get( &priv->tx_buf );
}
puts_direct = 1;
//pp_printf("ConIPMIReq in %d out %d txb %d\n", size, i, cnt);
puts_direct = 0;
return i;
}
void console_ipmi_init( )
{
console_ipmi_dev.priv = &console_ipmi_priv;
console_ipmi_dev.get_char = con_ipmi_getc;
console_ipmi_dev.put_string = con_ipmi_put_string;
rbuf_init(&console_ipmi_priv.rx_buf, IPMI_CON_RX_BUF_SIZE, &console_ipmi_priv.rx_buf_mem);
rbuf_init(&console_ipmi_priv.tx_buf, IPMI_CON_TX_BUF_SIZE, &console_ipmi_priv.tx_buf_mem);
console_register_device( &console_ipmi_dev );
}
#endif
int puts(const char *s)
{
if( puts_direct)
{
return con_uart_put_string( &console_uart_dev, s );
}
int i, rv;
for(i = 0; i < BOARD_MAX_CONSOLE_DEVICES; i++)
{
struct console_device *con = console_devs[i];
if(!con)
continue;
rv = con->put_string( con, s);
}
return rv;
}
int console_getc()
{
int i;
for(i = 0; i < BOARD_MAX_CONSOLE_DEVICES; i++)
{
struct console_device *con = console_devs[i];
if(!con)
continue;
int b = con->get_char( con );
if( b > 0 )
return b;
}
return -1;
}
void console_register_device( struct console_device *dev )
{
int i;
for(i = 0; i < BOARD_MAX_CONSOLE_DEVICES; i++)
{
if ( console_devs[i] == NULL )
{
console_devs[i] = dev;
return;
}
}
}
void console_init()
{
int i;
for(i = 0; i < BOARD_MAX_CONSOLE_DEVICES; i++)
console_devs[i] = NULL;
suart_init( &console_uart_priv.uart_dev, BASE_UART, CONSOLE_UART_BAUDRATE );
console_uart_priv.uart_dev.crlf_mode = 1;
console_uart_dev.priv = &console_uart_priv;
console_uart_dev.get_char = con_uart_getc;
console_uart_dev.put_string = con_uart_put_string;
console_register_device( &console_uart_dev );
#ifdef CONFIG_IPMI_CONSOLE
console_ipmi_init();
#endif
}
# Those hardware-specific files should not be built for the host, even if
# most of them give no error no warning. The host has different implementations
obj-$(CONFIG_LM32) += dev/uart.o
obj-$(CONFIG_LM32) += dev/simple_uart.o
obj-$(CONFIG_EMBEDDED_NODE) += \
dev/endpoint.o \
......@@ -16,7 +16,8 @@ obj-$(CONFIG_EMBEDDED_NODE) += \
dev/fram.o \
dev/gpio.o \
dev/bb_spi.o \
dev/bb_i2c.o
dev/bb_i2c.o \
dev/console.o
obj-$(CONFIG_WR_NODE) += \
dev/temperature.o \
......
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2011 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#include <stdint.h>
#include "board.h"
#include "dev/simple_uart.h"
#include <hw/wb_uart.h>
#define SUART_CALC_BAUD(baudrate) \
( ((( (unsigned long long)baudrate * 8ULL) << (16 - 7)) + \
(CPU_CLOCK >> 8)) / (CPU_CLOCK >> 7) )
static inline uint32_t suart_calc_baud( int baudrate )
{
uint64_t n = (((uint64_t) (baudrate)) << 12 ) + (CPU_CLOCK >> 8);
__div64_32(&n, CPU_CLOCK >> 7);
return (uint32_t) n;
}
void suart_init(struct simple_uart_device *dev, uint32_t base_addr, int baudrate)
{
dev->base = (void*) base_addr;
dev->crlf_mode = 0;
writel( suart_calc_baud(baudrate), dev->base + UART_REG_BCR );
}
void suart_init_default_baudrate(struct simple_uart_device *dev, uint32_t base_addr)
{
dev->base = (void*) base_addr;
dev->crlf_mode = 0;
writel( suart_calc_baud(CONSOLE_UART_BAUDRATE), dev->base + UART_REG_BCR );
}
void suart_write_byte(struct simple_uart_device *dev, int b)
{
if (b == '\n' && dev->crlf_mode)
suart_write_byte(dev, '\r');
while (readl(dev->base + UART_REG_SR) & UART_SR_TX_BUSY)
;
writel( b, dev->base + UART_REG_TDR );
}
int suart_write_string(struct simple_uart_device *dev, const char *s)
{
const char *t = s;
while (*s)
suart_write_byte(dev, *(s++));
return s - t;
}
int suart_poll(struct simple_uart_device *dev)
{
return readl( dev->base + UART_REG_SR) & UART_SR_RX_RDY;
}
int suart_read_byte(struct simple_uart_device *dev)
{
if (!suart_poll(dev))
return -1;
return readl(dev->base + UART_REG_RDR) & 0xff;
}
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2011 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#include <inttypes.h>
#include "board.h"
#include "dev/uart.h"
#include <hw/wb_uart.h>
#define CALC_BAUD(baudrate) \
( ((( (unsigned long long)baudrate * 8ULL) << (16 - 7)) + \
(CPU_CLOCK >> 8)) / (CPU_CLOCK >> 7) )
volatile struct UART_WB *uart;
void uart_init_hw()
{
uart = (volatile struct UART_WB *)BASE_UART;
uart->BCR = CALC_BAUD(UART_BAUDRATE);
}
void uart_write_byte(int b)
{
if (b == '\n')
uart_write_byte('\r');
while (uart->SR & UART_SR_TX_BUSY)
;
uart->TDR = b;
}
int uart_write_string(const char *s)
{
const char *t = s;
while (*s)
uart_write_byte(*(s++));
return s - t;
}
static int uart_poll(void)
{
return uart->SR & UART_SR_RX_RDY;
}
int uart_read_byte(void)
{
if (!uart_poll())
return -1;
return uart->RDR & 0xff;
}
int puts(const char *s)
__attribute__((weak,alias("uart_write_string")));
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2012-2019 CERN (www.cern.ch)
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#ifndef __CONSOLE_H
#define __CONSOLE_H
struct console_device {
int (*get_char)( struct console_device *dev );
int (*put_string)( struct console_device *dev, const char *str );
void *priv;
};
extern struct console_device *console;
void console_set_device( struct console_device *dev );
void console_uart_write_bytes( uint8_t *buf, int count );
void console_init(void);
int console_getc(void);
#ifdef CONFIG_IPMI_CONSOLE
int console_ipmi_process_request(struct console_device* dev, uint8_t *req, int size, uint8_t *rsp, int rsp_size );
#endif
#endif
/*
* This work is part of the White Rabbit project
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#ifndef __SIMPLE_UART_H
#define __SIMPLE_UART_H
struct simple_uart_device {
void* base;
uint8_t crlf_mode;
};
#define SUART_CALC_BAUD(baudrate) \
( ((( (unsigned long long)baudrate * 8ULL) << (16 - 7)) + \
(CPU_CLOCK >> 8)) / (CPU_CLOCK >> 7) )
void suart_init(struct simple_uart_device *dev, uint32_t base_addr, int baudrate);
void suart_write_byte(struct simple_uart_device *dev, int b);
int suart_write_string(struct simple_uart_device *dev, const char *s);
int suart_read_byte(struct simple_uart_device *dev);
int suart_poll(struct simple_uart_device *dev);
#endif
/*
* This work is part of the White Rabbit project
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#ifndef __UART_H
#define __UART_H
void uart_init_hw(void);
void uart_write_byte(int b);
int uart_write_string(const char *s);
int puts(const char *s);
int uart_read_byte(void);
#endif
......@@ -3,7 +3,7 @@
* File : wb_uart.h
* Author : auto-generated by wbgen2 from simple_uart_wb.wb
* Created : Wed Mar 1 17:29:58 2017
* Created : Mon Jul 22 17:13:56 2019
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE simple_uart_wb.wb
......@@ -14,7 +14,11 @@
#ifndef __WBGEN2_REGDEFS_SIMPLE_UART_WB_WB
#define __WBGEN2_REGDEFS_SIMPLE_UART_WB_WB
#ifdef __KERNEL__
#include <linux/types.h>
#else
#include <inttypes.h>
#endif
#if defined( __GNUC__)
#define PACKED __attribute__ ((packed))
......@@ -84,20 +88,16 @@
#define UART_HOST_RDR_COUNT_SHIFT 9
#define UART_HOST_RDR_COUNT_W(value) WBGEN2_GEN_WRITE(value, 9, 16)
#define UART_HOST_RDR_COUNT_R(reg) WBGEN2_GEN_READ(reg, 9, 16)
PACKED struct UART_WB {
/* [0x0]: REG Status Register */
uint32_t SR;
/* [0x4]: REG Baudrate control register */
uint32_t BCR;
/* [0x8]: REG Transmit data regsiter */
uint32_t TDR;
/* [0xc]: REG Receive data regsiter */
uint32_t RDR;
/* [0x10]: REG Host VUART Tx register */
uint32_t HOST_TDR;
/* [0x14]: REG Host VUART Rx register */
uint32_t HOST_RDR;
};
/* [0x0]: REG Status Register */
#define UART_REG_SR 0x00000000
/* [0x4]: REG Baudrate control register */
#define UART_REG_BCR 0x00000004
/* [0x8]: REG Transmit data regsiter */
#define UART_REG_TDR 0x00000008
/* [0xc]: REG Receive data regsiter */
#define UART_REG_RDR 0x0000000c
/* [0x10]: REG Host VUART Tx register */
#define UART_REG_HOST_TDR 0x00000010
/* [0x14]: REG Host VUART Rx register */
#define UART_REG_HOST_RDR 0x00000014
#endif
......@@ -14,7 +14,7 @@
#include <errno.h>
#include <wrc.h>
#include "dev/uart.h"
#include "dev/console.h"
#include "dev/syscon.h"
#include "shell.h"
......@@ -160,7 +160,7 @@ int shell_interactive()
return 1;
case SH_INPUT:
c = uart_read_byte();
c = console_getc();
if (c < 0)
return 0;
......
......@@ -16,7 +16,7 @@
#include <temperature.h>
#include <dev/w1.h>
#include <dev/syscon.h>
#include <dev/uart.h>
#include <dev/console.h>
#include <dev/endpoint.h>
#include <dev/minic.h>
#include <dev/pps_gen.h>
......@@ -68,6 +68,7 @@ static void wrc_initialize(void)
uint8_t mac_addr[6];
sdb_find_devices();
console_init();
wrc_board_early_init();
pp_printf("WR Core: starting up...\n");
......@@ -149,7 +150,7 @@ static int ui_update(void)
if (wrc_ui_mode == UI_GUI_MODE) {
ret = wrc_mon_gui();
if (uart_read_byte() == 27 || wrc_ui_refperiod == 0) {
if ( console_getc() == 27 || wrc_ui_refperiod == 0) {
shell_init();
wrc_ui_mode = UI_SHELL_MODE;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment