riscv32: riscv-privilege: Microsemi Mi-V support

This commit adds support for Microsemi Mi-V RISC-V softcore CPU
running on the M2GL025 IGLOO2 FPGA development board.

signed-off-by: Karol Gugala <kgugala@antmicro.com>
This commit is contained in:
Karol Gugala 2018-06-10 19:02:14 +02:00 committed by Anas Nashif
commit 1765d75ff4
19 changed files with 733 additions and 2 deletions

View file

@ -0,0 +1 @@
zephyr_sources()

View file

@ -0,0 +1,47 @@
if SOC_SERIES_RISCV32_MIV
config SOC_SERIES
string
default "miv"
config SYS_CLOCK_HW_CYCLES_PER_SEC
int
default 660000
config RISCV_SOC_INTERRUPT_INIT
bool
default y
config RISCV_HAS_CPU_IDLE
bool
default y
config RISCV_HAS_PLIC
bool
default y
config NUM_IRQS
int
default 42
config XIP
bool
default y
config RISCV_ROM_BASE_ADDR
hex
default 0x80000000
config RISCV_ROM_SIZE
hex
default 0x40000
config RISCV_RAM_BASE_ADDR
hex
default 0x80040000
config RISCV_RAM_SIZE
hex
default 0x40000
endif # SOC_SERIES_RISCV32_MIV

View file

@ -0,0 +1,11 @@
# Kconfig - RISCV32_MIV implementation
#
# Copyright (c) 2018 Antmicro <www.antmicro.com>
#
config SOC_SERIES_RISCV32_MIV
bool "Microsemi Mi-V implementation"
depends on RISCV32
select SOC_FAMILY_RISCV_PRIVILEGE
help
Enable support for Microsemi Mi-V

View file

@ -0,0 +1,14 @@
# Kconfig - RISCV32_MIV configuration options
#
# Copyright (c) 2018 Antmicro <www.antmicro.com>
#
choice
prompt "Microsemi Mi-V system implementation"
depends on SOC_SERIES_RISCV32_MIV
config SOC_RISCV32_MIV
bool "Microsemi Mi-V system implementation"
select ATOMIC_OPERATIONS_C
endchoice

View file

@ -0,0 +1,7 @@
/*
* Copyright (c) 2018 Antmicro <www.antmicro.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <arch/riscv32/common/linker.ld>

View file

@ -0,0 +1,66 @@
#ifndef __RISCV32_MIV_SOC_H_
#define __RISCV32_MIV_SOC_H_
#include <soc_common.h>
/* GPIO Interrupts */
#define MIV_GPIO_0_IRQ (RISCV_MAX_GENERIC_IRQ + 0)
#define MIV_GPIO_1_IRQ (RISCV_MAX_GENERIC_IRQ + 1)
#define MIV_GPIO_2_IRQ (RISCV_MAX_GENERIC_IRQ + 2)
#define MIV_GPIO_3_IRQ (RISCV_MAX_GENERIC_IRQ + 3)
#define MIV_GPIO_4_IRQ (RISCV_MAX_GENERIC_IRQ + 4)
#define MIV_GPIO_5_IRQ (RISCV_MAX_GENERIC_IRQ + 5)
#define MIV_GPIO_6_IRQ (RISCV_MAX_GENERIC_IRQ + 6)
#define MIV_GPIO_7_IRQ (RISCV_MAX_GENERIC_IRQ + 7)
#define MIV_GPIO_8_IRQ (RISCV_MAX_GENERIC_IRQ + 8)
#define MIV_GPIO_9_IRQ (RISCV_MAX_GENERIC_IRQ + 9)
#define MIV_GPIO_10_IRQ (RISCV_MAX_GENERIC_IRQ + 10)
#define MIV_GPIO_11_IRQ (RISCV_MAX_GENERIC_IRQ + 11)
#define MIV_GPIO_12_IRQ (RISCV_MAX_GENERIC_IRQ + 12)
#define MIV_GPIO_13_IRQ (RISCV_MAX_GENERIC_IRQ + 13)
#define MIV_GPIO_14_IRQ (RISCV_MAX_GENERIC_IRQ + 14)
#define MIV_GPIO_15_IRQ (RISCV_MAX_GENERIC_IRQ + 15)
#define MIV_GPIO_16_IRQ (RISCV_MAX_GENERIC_IRQ + 16)
#define MIV_GPIO_17_IRQ (RISCV_MAX_GENERIC_IRQ + 17)
#define MIV_GPIO_18_IRQ (RISCV_MAX_GENERIC_IRQ + 18)
#define MIV_GPIO_19_IRQ (RISCV_MAX_GENERIC_IRQ + 19)
#define MIV_GPIO_20_IRQ (RISCV_MAX_GENERIC_IRQ + 20)
#define MIV_GPIO_21_IRQ (RISCV_MAX_GENERIC_IRQ + 21)
#define MIV_GPIO_22_IRQ (RISCV_MAX_GENERIC_IRQ + 22)
#define MIV_GPIO_23_IRQ (RISCV_MAX_GENERIC_IRQ + 23)
#define MIV_GPIO_24_IRQ (RISCV_MAX_GENERIC_IRQ + 24)
#define MIV_GPIO_25_IRQ (RISCV_MAX_GENERIC_IRQ + 25)
#define MIV_GPIO_26_IRQ (RISCV_MAX_GENERIC_IRQ + 26)
#define MIV_GPIO_27_IRQ (RISCV_MAX_GENERIC_IRQ + 27)
#define MIV_GPIO_28_IRQ (RISCV_MAX_GENERIC_IRQ + 28)
#define MIV_GPIO_29_IRQ (RISCV_MAX_GENERIC_IRQ + 29)
#define MIV_GPIO_30_IRQ (RISCV_MAX_GENERIC_IRQ + 30)
#define MIV_GPIO_31_IRQ (RISCV_MAX_GENERIC_IRQ + 31)
/* UART Configuration */
#define MIV_UART_0_BASE_ADDR 0x70001000
#define MIV_UART_0_LINECFG 0x1
/* GPIO Configuration */
#define MIV_GPIO_0_BASE_ADDR 0x70002000
/* Platform Level Interrupt Controller Configuration */
#define MIV_PLIC_BASE_ADDR 0x40000000
#define MIV_PLIC_PRIO_BASE_ADDR MIV_PLIC_BASE_ADDR
#define MIV_PLIC_IRQ_EN_BASE_ADDR (MIV_PLIC_BASE_ADDR + 0x2000)
#define MIV_PLIC_REG_BASE_ADDR (MIV_PLIC_BASE_ADDR + 0x200000)
#define MIV_PLIC_MAX_PRIORITY 7
/* Clock controller. */
#define PRCI_BASE_ADDR 0x44000000
/* Timer configuration */
#define RISCV_MTIME_BASE 0x4400bff8
#define RISCV_MTIMECMP_BASE 0x44004000
/* lib-c hooks required RAM defined variables */
#define RISCV_RAM_BASE CONFIG_RISCV_RAM_BASE_ADDR
#define RISCV_RAM_SIZE CONFIG_RISCV_RAM_SIZE
#endif /* __RISCV32_MIV_SOC_H_ */

View file

@ -0,0 +1 @@
zephyr_library_include_directories(${PROJECT_SOURCE_DIR}/drivers)

View file

@ -0,0 +1,3 @@
config BOARD_M2GL025_MIV
bool "Microsemi M2GL025 IGLOO2 dev board with Mi-V CPU"
depends on SOC_RISCV32_MIV

View file

@ -0,0 +1,6 @@
if BOARD_M2GL025_MIV
config BOARD
default "m2gl025_miv"
endif

View file

@ -0,0 +1,14 @@
/*
* Copyright (c) 2018 Antmicro <www.antmicro.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __INC_BOARD_H
#define __INC_BOARD_H
#include <soc.h>
#define uart_miv_port_0_clk_freq 66000000
#endif /* __INC_BOARD_H */

View file

@ -0,0 +1,69 @@
.. _m2gl025-miv:
Microsemi M2GL025 Mi-V
######################
Overview
********
The Microsemi M2GL025 board is an IGLOO2 FPGA based development board.
The Mi-V RISC-V soft CPU can be deployed on the MGL025 board.
More information can be found on
`Microsemi's website <https://www.microsemi.com/product-directory/embedded-processing/4406-cpus>`_.
Programming and debugging
*************************
Building
========
Applications for the ``m2gl025_miv`` board configuration can be built as usual
(see :ref:`build_an_application`).
In order to build the application for ``m2gl025_miv``, set the ``BOARD`` variable
to ``m2gl025_miv``.
.. code-block:: bash
export BOARD="m2gl025_miv"
Flashing
========
In order to upload the application to the device, you'll need OpenOCD and GDB
with RISC-V support.
You can get them as a part of SoftConsole SDK.
Download and installation instructions can be found on
`Microsemi's SoftConsole website
<https://www.microsemi.com/product-directory/design-tools/4879-softconsole>`_.
With the necessary tools installed, you can connect to the board using OpenOCD.
To establish an OpenOCD connection run:
.. code-block:: bash
sudo LD_LIBRARY_PATH=<softconsole_path>/openocd/bin \
<softconsole_path>/openocd/bin/openocd --file \
<softconsole_path>/openocd/share/openocd/scripts/board/microsemi-riscv.cfg
Leave it running, and in a different terminal, use GDB to upload the binary to
the board. You can use the RISC-V GDB from a toolchain delivered with
SoftConsole SDK.
Here is the GDB terminal command to connect to the device
and load the binary:
.. code-block:: console
<softconsole_path>/riscv-unknown-elf-gcc/bin/riscv64-unknown-elf-gdb \
-ex "target extended-remote localhost:3333" \
-ex "set mem inaccessible-by-default off" \
-ex "set arch riscv:rv32" \
-ex "set riscv use_compressed_breakpoints no" \
-ex "load" <path_to_executable>
Debugging
=========
Refer to the detailed overview of :ref:`application_debugging`.

View file

@ -0,0 +1,11 @@
identifier: m2gl025_miv
name: Microsemi M2GL025 with MiV target
type: mcu
arch: riscv32
toolchain:
- zephyr
ram: 64
testing:
ignore_tags:
- net
- bluetooth

View file

@ -0,0 +1,16 @@
CONFIG_RISCV32=y
CONFIG_SOC_SERIES_RISCV32_MIV=y
CONFIG_SOC_RISCV32_MIV=y
CONFIG_BOARD_M2GL025_MIV=y
CONFIG_CONSOLE=y
CONFIG_SERIAL=y
CONFIG_UART_MIV=y
CONFIG_UART_MIV_PORT_0=y
CONFIG_UART_MIV_PORT_0_BAUD_RATE=115200
CONFIG_UART_MIV_PORT_0_NAME="uart0"
CONFIG_UART_CONSOLE=y
CONFIG_UART_CONSOLE_ON_DEV_NAME="uart0"
CONFIG_PLIC=y
CONFIG_RISCV_MACHINE_TIMER=y
CONFIG_GPIO=n
CONFIG_XIP=y

View file

@ -7,7 +7,7 @@
/**
* @brief Platform Level Interrupt Controller (PLIC) driver
* for the RISC-V processors
* for RISC-V processors
*/
#include <kernel.h>

View file

@ -18,6 +18,12 @@
#define PLIC_IRQ_EN_BASE_ADDR FE310_PLIC_IRQ_EN_BASE_ADDR
#define PLIC_PRIO_BASE_ADDR FE310_PLIC_PRIO_BASE_ADDR
#define PLIC_MAX_PRIORITY FE310_PLIC_MAX_PRIORITY
/* Mi-V definitons for the PLIC */
#elif defined(CONFIG_SOC_SERIES_RISCV32_MIV)
#define PLIC_REG_BASE_ADDR MIV_PLIC_REG_BASE_ADDR
#define PLIC_IRQ_EN_BASE_ADDR MIV_PLIC_IRQ_EN_BASE_ADDR
#define PLIC_PRIO_BASE_ADDR MIV_PLIC_PRIO_BASE_ADDR
#define PLIC_MAX_PRIORITY MIV_PLIC_MAX_PRIORITY
#endif
#endif

View file

@ -1,5 +1,4 @@
zephyr_library()
zephyr_library_sources_ifdef(CONFIG_UART_ALTERA_JTAG uart_altera_jtag_hal.c)
zephyr_library_sources_if_kconfig(uart_imx.c)
zephyr_library_sources_if_kconfig(uart_cc32xx.c)
@ -10,6 +9,7 @@ zephyr_library_sources_if_kconfig(uart_gecko.c)
zephyr_library_sources_if_kconfig(uart_mcux.c)
zephyr_library_sources_if_kconfig(uart_mcux_lpuart.c)
zephyr_library_sources_if_kconfig(uart_mcux_lpsci.c)
zephyr_library_sources_if_kconfig(uart_miv.c)
zephyr_library_sources_if_kconfig(uart_msp432p4xx.c)
zephyr_library_sources_ifdef(CONFIG_NRF_UART_PERIPHERAL uart_nrfx_uart.c)
zephyr_library_sources_if_kconfig(uart_ns16550.c)

View file

@ -73,6 +73,8 @@ source "drivers/serial/Kconfig.mcux_lpsci"
source "drivers/serial/Kconfig.mcux_lpuart"
source "drivers/serial/Kconfig.miv"
source "drivers/serial/Kconfig.imx"
source "drivers/serial/Kconfig.stellaris"

View file

@ -0,0 +1,42 @@
# Kconfig.miv - Mi-V UART configuration option
#
# Copyright (c) 2018 Antmicro <www.antmicro.com>
#
menuconfig UART_MIV
bool "Mi-V serial driver"
depends on SOC_RISCV32_MIV
default n
select SERIAL_HAS_DRIVER
help
This option enables the Mi-V serial driver.
menuconfig UART_MIV_PORT_0
bool "Enable Mi-V Port 0"
default n
depends on UART_MIV
help
This tells the driver to configure the UART port at boot, depending on
the additional configuration options below.
config UART_MIV_PORT_0_NAME
string "Port 0 Device Name"
default "uart0"
depends on UART_MIV_PORT_0
help
This is the device name for UART, and is included in the device
struct.
config UART_MIV_PORT_0_BAUD_RATE
int "Port 0 Baud Rate"
default 0
depends on UART_MIV_PORT_0
help
The baud rate for UART port to be set to at boot.
config UART_MIV_PORT_0_IRQ_PRIORITY
int "Port 0 Interrupt Priority"
default 1
depends on UART_MIV_PORT_0
help
Port 0 Interrupt Priority

415
drivers/serial/uart_miv.c Normal file
View file

@ -0,0 +1,415 @@
/*
* Copyright (c) 2018 Antmicro <www.antmicro.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <kernel.h>
#include <arch/cpu.h>
#include <uart.h>
#include <board.h>
/* UART REGISTERS DEFINITIONS */
/* TX register */
#define TXDATA_REG_OFFSET 0x0
#define TXDATA_OFFSET 0x0
#define TXDATA_MASK 0xFF
#define TXDATA_SHIFT 0
/* RX register */
#define RXDATA_REG_OFFSET 0x4
#define RXDATA_OFFSET 0x4
#define RXDATA_MASK 0xFF
#define RXDATA_SHIFT 0
/* Control1 register */
#define CTRL1_REG_OFFSET 0x8
/* Baud value lower 8 bits */
#define CTRL1_BAUDVALUE_OFFSET 0x8
#define CTRL1_BAUDVALUE_MASK 0xFF
#define CTRL1_BAUDVALUE_SHIFT 0
/* Control2 register */
#define CTRL2_REG_OFFSET 0xC
/* Bit length */
#define CTRL2_BIT_LENGTH_OFFSET 0xC
#define CTRL2_BIT_LENGTH_MASK 0x01
#define CTRL2_BIT_LENGTH_SHIFT 0
/* Parity enable */
#define CTRL2_PARITY_EN_OFFSET 0xC
#define CTRL2_PARITY_EN_MASK 0x02
#define CTRL2_PARITY_EN_SHIFT 1
/* Odd/even parity configuration */
#define CTRL2_ODD_EVEN_OFFSET 0xC
#define CTRL2_ODD_EVEN_MASK 0x04
#define CTRL2_ODD_EVEN_SHIFT 2
/* Baud value higher 5 bits */
#define CTRL2_BAUDVALUE_OFFSET 0xC
#define CTRL2_BAUDVALUE_MASK 0xF8
#define CTRL2_BAUDVALUE_SHIFT 3
/* Status register */
#define StatusReg_REG_OFFSET 0x10
#define STATUS_REG_OFFSET 0x10
/* TX ready */
#define STATUS_TXRDY_OFFSET 0x10
#define STATUS_TXRDY_MASK 0x01
#define STATUS_TXRDY_SHIFT 0
/* Receive full - raised even when 1 char arrived */
#define STATUS_RXFULL_OFFSET 0x10
#define STATUS_RXFULL_MASK 0x02
#define STATUS_RXFULL_SHIFT 1
/* Parity error */
#define STATUS_PARITYERR_OFFSET 0x10
#define STATUS_PARITYERR_MASK 0x04
#define STATUS_PARITYERR_SHIFT 2
/* Overflow */
#define STATUS_OVERFLOW_OFFSET 0x10
#define STATUS_OVERFLOW_MASK 0x08
#define STATUS_OVERFLOW_SHIFT 3
/* Frame error */
#define STATUS_FRAMERR_OFFSET 0x10
#define STATUS_FRAMERR_MASK 0x10
#define STATUS_FRAMERR_SHIFT 4
/* Data bits length defines */
#define DATA_7_BITS 0x00
#define DATA_8_BITS 0x01
/* Parity defines */
#define NO_PARITY 0x00
#define EVEN_PARITY 0x02
#define ODD_PARITY 0x06
/* Error Status definitions */
#define UART_PARITY_ERROR 0x01
#define UART_OVERFLOW_ERROR 0x02
#define UART_FRAMING_ERROR 0x04
#define BAUDVALUE_LSB ((u16_t)(0x00FF))
#define BAUDVALUE_MSB ((u16_t)(0xFF00))
#define BAUDVALUE_SHIFT ((u8_t)(5))
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
static struct k_thread rx_thread;
static K_THREAD_STACK_DEFINE(rx_stack, 512);
#endif
struct uart_miv_regs_t {
u8_t tx;
u8_t reserved0[3];
u8_t rx;
u8_t reserved1[3];
u8_t ctrlreg1;
u8_t reserved2[3];
u8_t ctrlreg2;
u8_t reserved3[3];
u8_t status;
};
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
typedef void (*irq_cfg_func_t)(struct device *dev);
#endif
struct uart_miv_device_config {
u32_t uart_addr;
u32_t sys_clk_freq;
u32_t line_config;
u32_t baud_rate;
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
irq_cfg_func_t cfg_func;
#endif
};
struct uart_miv_data {
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
uart_irq_callback_t callback;
#endif
};
#define DEV_CFG(dev) \
((const struct uart_miv_device_config * const) \
(dev)->config->config_info)
#define DEV_UART(dev) \
((struct uart_miv_regs_t *)(DEV_CFG(dev))->uart_addr)
#define DEV_DATA(dev) \
((struct uart_miv_data * const)(dev)->driver_data)
static unsigned char uart_miv_poll_out(struct device *dev,
unsigned char c)
{
volatile struct uart_miv_regs_t *uart = DEV_UART(dev);
while (!(uart->status & STATUS_TXRDY_MASK))
;
uart->tx = c;
return c;
}
static int uart_miv_poll_in(struct device *dev, unsigned char *c)
{
volatile struct uart_miv_regs_t *uart = DEV_UART(dev);
if (uart->status & STATUS_RXFULL_MASK) {
*c = (unsigned char)(uart->rx & RXDATA_MASK);
return 0;
}
return -1;
}
static int uart_miv_err_check(struct device *dev)
{
volatile struct uart_miv_regs_t *uart = DEV_UART(dev);
u32_t flags = uart->status;
int err = 0;
if (flags & STATUS_PARITYERR_MASK) {
err |= UART_PARITY_ERROR;
}
if (flags & STATUS_OVERFLOW_MASK) {
err |= UART_OVERFLOW_ERROR;
}
if (flags & STATUS_FRAMERR_MASK) {
err |= UART_FRAMING_ERROR;
}
return err;
}
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
static int uart_miv_fifo_fill(struct device *dev,
const u8_t *tx_data,
int size)
{
volatile struct uart_miv_regs_t *uart = DEV_UART(dev);
int i;
for (i = 0; i < size && (uart->status & STATUS_TXRDY_MASK); i++) {
uart->tx = tx_data[i];
}
return i;
}
static int uart_miv_fifo_read(struct device *dev,
u8_t *rx_data,
const int size)
{
volatile struct uart_miv_regs_t *uart = DEV_UART(dev);
int i;
for (i = 0; i < size; i++) {
if (uart->status & STATUS_RXFULL_MASK) {
rx_data[i] = (unsigned char)(uart->rx & RXDATA_MASK);
} else {
break;
}
}
return i;
}
static void uart_miv_irq_tx_enable(struct device *dev)
{
ARG_UNUSED(dev);
}
static void uart_miv_irq_tx_disable(struct device *dev)
{
ARG_UNUSED(dev);
}
static int uart_miv_irq_tx_ready(struct device *dev)
{
volatile struct uart_miv_regs_t *uart = DEV_UART(dev);
return !(uart->status & STATUS_TXRDY_MASK);
}
static int uart_miv_irq_tx_complete(struct device *dev)
{
ARG_UNUSED(dev);
return 1;
}
static void uart_miv_irq_rx_enable(struct device *dev)
{
ARG_UNUSED(dev);
}
static void uart_miv_irq_rx_disable(struct device *dev)
{
ARG_UNUSED(dev);
}
static int uart_miv_irq_rx_ready(struct device *dev)
{
volatile struct uart_miv_regs_t *uart = DEV_UART(dev);
return !!(uart->status & STATUS_RXFULL_MASK);
}
static void uart_miv_irq_err_enable(struct device *dev)
{
ARG_UNUSED(dev);
}
static void uart_miv_irq_err_disable(struct device *dev)
{
ARG_UNUSED(dev);
}
static int uart_miv_irq_is_pending(struct device *dev)
{
volatile struct uart_miv_regs_t *uart = DEV_UART(dev);
return !!(uart->status & STATUS_RXFULL_MASK);
}
static int uart_miv_irq_update(struct device *dev)
{
return 1;
}
static void uart_miv_irq_handler(void *arg)
{
struct device *dev = (struct device *)arg;
struct uart_miv_data *data = DEV_DATA(dev);
if (data->callback) {
data->callback(dev);
}
}
/*
* This thread is a workaround for IRQs that are not connected in Mi-V.
* Since we cannot rely on IRQs, the rx_thread is working instead and
* polling for data. The thread calls the registered callback when data
* arrives.
*/
void uart_miv_rx_thread(void *arg1, void *arg2, void *arg3)
{
struct device *dev = (struct device *)arg1;
volatile struct uart_miv_regs_t *uart = DEV_UART(dev);
const struct uart_miv_device_config *const cfg = DEV_CFG(dev);
/* Make it go to sleep for a period no longer than
* time to receive next character.
*/
u32_t delay = 1000000 / cfg->baud_rate;
while (1) {
if (uart->status & STATUS_RXFULL_MASK) {
uart_miv_irq_handler(dev);
}
k_sleep(delay);
}
}
static void uart_miv_irq_callback_set(struct device *dev,
uart_irq_callback_t cb)
{
struct uart_miv_data *data = DEV_DATA(dev);
data->callback = cb;
}
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
static int uart_miv_init(struct device *dev)
{
const struct uart_miv_device_config *const cfg = DEV_CFG(dev);
volatile struct uart_miv_regs_t *uart = DEV_UART(dev);
/* Calculate divider value to set baudrate */
u16_t baud_value = (cfg->sys_clk_freq / (16 * cfg->baud_rate)) - 1;
/* Set baud rate */
uart->ctrlreg1 = (u8_t)(baud_value & BAUDVALUE_LSB);
uart->ctrlreg2 = (u8_t)(cfg->line_config) |
(u8_t)((baud_value & BAUDVALUE_MSB) >> BAUDVALUE_SHIFT);
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
/* Setup thread polling for data */
cfg->cfg_func(dev);
#endif
return 0;
}
static const struct uart_driver_api uart_miv_driver_api = {
.poll_in = uart_miv_poll_in,
.poll_out = uart_miv_poll_out,
.err_check = uart_miv_err_check,
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
.fifo_fill = uart_miv_fifo_fill,
.fifo_read = uart_miv_fifo_read,
.irq_tx_enable = uart_miv_irq_tx_enable,
.irq_tx_disable = uart_miv_irq_tx_disable,
.irq_tx_ready = uart_miv_irq_tx_ready,
.irq_tx_complete = uart_miv_irq_tx_complete,
.irq_rx_enable = uart_miv_irq_rx_enable,
.irq_rx_disable = uart_miv_irq_rx_disable,
.irq_rx_ready = uart_miv_irq_rx_ready,
.irq_err_enable = uart_miv_irq_err_enable,
.irq_err_disable = uart_miv_irq_err_disable,
.irq_is_pending = uart_miv_irq_is_pending,
.irq_update = uart_miv_irq_update,
.irq_callback_set = uart_miv_irq_callback_set,
#endif
};
#ifdef CONFIG_UART_MIV_PORT_0
static struct uart_miv_data uart_miv_data_0;
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
static void uart_miv_irq_cfg_func_0(struct device *dev);
#endif
static const struct uart_miv_device_config uart_miv_dev_cfg_0 = {
.uart_addr = MIV_UART_0_BASE_ADDR,
.sys_clk_freq = uart_miv_port_0_clk_freq,
.line_config = MIV_UART_0_LINECFG,
.baud_rate = CONFIG_UART_MIV_PORT_0_BAUD_RATE,
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
.cfg_func = uart_miv_irq_cfg_func_0,
#endif
};
DEVICE_AND_API_INIT(uart_miv_0, CONFIG_UART_MIV_PORT_0_NAME,
uart_miv_init, &uart_miv_data_0, &uart_miv_dev_cfg_0,
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
(void *)&uart_miv_driver_api);
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
static void uart_miv_irq_cfg_func_0(struct device *dev)
{
/* Create a thread which will poll for data - replacement for IRQ */
k_thread_create(&rx_thread, rx_stack, 500,
uart_miv_rx_thread, dev, NULL, NULL, K_PRIO_COOP(2),
0, K_NO_WAIT);
}
#endif
#endif /* CONFIG_MIV_UART_0 */