You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
90 lines
2.5 KiB
90 lines
2.5 KiB
/* |
|
* Copyright (c) 2023 Efinix Inc. |
|
* |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
|
|
#define DT_DRV_COMPAT efinix_sapphire_uart0 |
|
|
|
#include <zephyr/device.h> |
|
#include <zephyr/drivers/uart.h> |
|
#include <zephyr/init.h> |
|
#include <zephyr/kernel.h> |
|
#include <zephyr/types.h> |
|
|
|
#define UART_IRQ DT_INST_IRQN(0) |
|
#define UART0_BASE_ADDR DT_INST_REG_ADDR(0) |
|
|
|
#define BSP_UART_DATA 0x00 |
|
#define BSP_UART_STATUS 0x04 |
|
#define BSP_UART_CLOCK_DIVIDER 0x08 |
|
#define BSP_UART_FRAME_CONFIG 0x0C |
|
|
|
#define BSP_UART_WRITE_AVAILABILITY_MASK GENMASK(23, 16) |
|
#define BSP_UART_READ_OCCUPANCY_MASK GENMASK(31, 24) |
|
|
|
#define UART0_DATA_REG_ADDR UART0_BASE_ADDR + BSP_UART_DATA |
|
#define UART0_STATUS_REG_ADDR UART0_BASE_ADDR + BSP_UART_STATUS |
|
#define UART0_CLOCK_REG_ADDR UART0_BASE_ADDR + BSP_UART_CLOCK_DIVIDER |
|
#define UART0_FRAME_REG_ADDR UART0_BASE_ADDR + BSP_UART_FRAME_CONFIG |
|
|
|
#define UART0_SAMPLE_PER_BAUD 8 |
|
#define UART0_PARITY 0 /* Off */ |
|
#define UART0_STOP 0 /* 1 stop bit */ |
|
|
|
|
|
struct uart_efinix_sapphire_config { |
|
uint32_t baudrate; |
|
}; |
|
|
|
static void uart_efinix_sapphire_poll_out(const struct device *dev, unsigned char c) |
|
{ |
|
/* uart_writeAvailability */ |
|
while ((sys_read32(UART0_STATUS_REG_ADDR) & BSP_UART_WRITE_AVAILABILITY_MASK) == 0) { |
|
} |
|
|
|
sys_write8(c, UART0_DATA_REG_ADDR); |
|
} |
|
|
|
static int uart_efinix_sapphire_poll_in(const struct device *dev, unsigned char *c) |
|
{ |
|
|
|
if ((sys_read32(UART0_STATUS_REG_ADDR) & BSP_UART_READ_OCCUPANCY_MASK) != 0) { |
|
*c = (unsigned char)sys_read8(UART0_DATA_REG_ADDR); |
|
return 0; |
|
} |
|
|
|
return -1; |
|
} |
|
|
|
static DEVICE_API(uart, uart_efinix_sapphire_api) = { |
|
.poll_in = uart_efinix_sapphire_poll_in, |
|
.poll_out = uart_efinix_sapphire_poll_out, |
|
.err_check = NULL, |
|
}; |
|
|
|
static const struct uart_efinix_sapphire_config uart_efinix_sapphire_cfg_0 = { |
|
.baudrate = DT_INST_PROP(0, current_speed), |
|
}; |
|
|
|
static int uart_efinix_sapphire_init(const struct device *dev) |
|
{ |
|
ARG_UNUSED(dev); |
|
|
|
uint32_t prescaler = ((CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / |
|
(uart_efinix_sapphire_cfg_0.baudrate * UART0_SAMPLE_PER_BAUD)) - |
|
1) & |
|
0xFFFFF; |
|
sys_write32(prescaler, UART0_CLOCK_REG_ADDR); |
|
|
|
/* 8 data bits, no parity, 1 stop bit */ |
|
uint32_t frame_config = (UART0_SAMPLE_PER_BAUD - 1) | UART0_PARITY << 8 | UART0_STOP << 16; |
|
|
|
sys_write32(frame_config, UART0_FRAME_REG_ADDR); |
|
|
|
return 0; |
|
} |
|
|
|
/* Device tree instance 0 init */ |
|
DEVICE_DT_INST_DEFINE(0, uart_efinix_sapphire_init, NULL, NULL, &uart_efinix_sapphire_cfg_0, |
|
PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, (void *)&uart_efinix_sapphire_api);
|
|
|