Skip to content

Commit

Permalink
Copy BL602 Serial
Browse files Browse the repository at this point in the history
  • Loading branch information
lupyuen committed Nov 9, 2023
1 parent 84704c9 commit 18e4518
Show file tree
Hide file tree
Showing 4 changed files with 1,391 additions and 0 deletions.
1 change: 1 addition & 0 deletions arch/risc-v/src/jh7110/Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ HEAD_ASRC = jh7110_head.S
CHIP_CSRCS = jh7110_start.c jh7110_irq_dispatch.c jh7110_irq.c
CHIP_CSRCS += jh7110_timerisr.c jh7110_allocateheap.c
CHIP_CSRCS += jh7110_mm_init.c jh7110_pgalloc.c
CHIP_CSRCS += bl602_lowputc.c bl602_serial.c
361 changes: 361 additions & 0 deletions arch/risc-v/src/jh7110/bl602_lowputc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,361 @@
/****************************************************************************
* arch/risc-v/src/bl602/bl602_lowputc.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/

/****************************************************************************
* Included Files
****************************************************************************/

#include <nuttx/config.h>

#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <debug.h>

#include <nuttx/irq.h>
#include <nuttx/serial/serial.h>

#include <arch/board/board.h>

#include "hardware/bl602_hbn.h"
#include "hardware/bl602_uart.h"

#include "bl602_lowputc.h"
#include "bl602_gpio.h"
#include "bl602_hbn.h"
#include "riscv_internal.h"
#include "bl602_config.h"
#include "chip.h"

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

#define UART_PARITY_NONE (0)
#define UART_PARITY_ODD (1)
#define UART_PARITY_EVEN (2)

/* Select UART parameters for the selected console */

#ifdef HAVE_SERIAL_CONSOLE
#if defined(CONFIG_UART0_SERIAL_CONSOLE)
#define BL602_CONSOLE_IDX 0
#define BL602_CONSOLE_BAUD CONFIG_UART0_BAUD
#define BL602_CONSOLE_BITS CONFIG_UART0_BITS
#define BL602_CONSOLE_PARITY CONFIG_UART0_PARITY
#define BL602_CONSOLE_2STOP CONFIG_UART0_2STOP
#ifdef UART0_IFLOWCONTROL
#define BL602_CONSOLE_IFLOWCTL UART0_IFLOWCONTROL
#else
#define BL602_CONSOLE_IFLOWCTL 0
#endif
#ifdef UART0_OFLOWCONTROL
#define BL602_CONSOLE_OFLOWCTL UART0_OFLOWCONTROL
#else
#define BL602_CONSOLE_OFLOWCTL 0
#endif
#endif
#define HAVE_UART
#elif defined(CONFIG_UART1_SERIAL_CONSOLE)
#define BL602_CONSOLE_IDX 1
#define BL602_CONSOLE_BAUD CONFIG_UART1_BAUD
#define BL602_CONSOLE_BITS CONFIG_UART1_BITS
#define BL602_CONSOLE_PARITY CONFIG_UART1_PARITY
#define BL602_CONSOLE_2STOP CONFIG_UART1_2STOP
#ifdef UART1_IFLOWCONTROL
#define BL602_CONSOLE_IFLOWCTL UART1_IFLOWCONTROL
#else
#define BL602_CONSOLE_IFLOWCTL 0
#endif
#ifdef UART1_OFLOWCONTROL
#define BL602_CONSOLE_OFLOWCTL UART1_OFLOWCONTROL
#else
#define BL602_CONSOLE_OFLOWCTL 0
#endif
#define HAVE_UART
#endif /* HAVE_CONSOLE */

#define _BL602_UART_CLOCK (160 * 1000 * 1000UL) /* UART clock */
#define HBN_UART_CLK_160M (1)

/****************************************************************************
* Private Data
****************************************************************************/

#ifdef HAVE_SERIAL_CONSOLE
static const struct uart_config_s g_bl602_console_config =
{
.idx = BL602_CONSOLE_IDX,
.baud = BL602_CONSOLE_BAUD,
.parity = BL602_CONSOLE_PARITY,
.data_bits = BL602_CONSOLE_BITS,
.stop_bits = BL602_CONSOLE_2STOP,
#ifdef BL602_CONSOLE_IFLOWCTL
.iflow_ctl = BL602_CONSOLE_IFLOWCTL,
#else
.iflow_ctl = 0,
#endif

#ifdef BL602_CONSOLE_OFLOWCTL
.oflow_ctl = BL602_CONSOLE_OFLOWCTL,
#else
.oflow_ctl = 0,
#endif
};
#endif /* HAVE_SERIAL_CONSOLE */

/****************************************************************************
* Private Functions
****************************************************************************/

static void bl602_uart_gpio_init(uint8_t id)
{
if (id == 0)
{
#ifdef BOARD_UART_0_TX_PIN
bl602_config_uart_sel(BOARD_UART_0_TX_PIN, UART_SIG_SEL_UART0_TXD);
bl602_configgpio(BOARD_UART_0_TX_PIN);
#endif
#ifdef BOARD_UART_0_RX_PIN
bl602_config_uart_sel(BOARD_UART_0_RX_PIN, UART_SIG_SEL_UART0_RXD);
bl602_configgpio(BOARD_UART_0_RX_PIN);
#endif
#ifdef BOARD_UART_0_CTS_PIN
bl602_config_uart_sel(BOARD_UART_0_CTS_PIN, UART_SIG_SEL_UART0_CTS);
bl602_configgpio(BOARD_UART_0_CTS_PIN);
#endif
#ifdef BOARD_UART_0_RTS_PIN
bl602_config_uart_sel(BOARD_UART_0_RTS_PIN, UART_SIG_SEL_UART0_RTS);
bl602_configgpio(BOARD_UART_0_RTS_PIN);
#endif
}
else
{
#ifdef BOARD_UART_1_TX_PIN
bl602_config_uart_sel(BOARD_UART_1_TX_PIN, UART_SIG_SEL_UART1_TXD);
bl602_configgpio(BOARD_UART_1_TX_PIN);
#endif
#ifdef BOARD_UART_1_RX_PIN
bl602_config_uart_sel(BOARD_UART_1_RX_PIN, UART_SIG_SEL_UART1_RXD);
bl602_configgpio(BOARD_UART_1_RX_PIN);
#endif
#ifdef BOARD_UART_1_CTS_PIN
bl602_config_uart_sel(BOARD_UART_1_CTS_PIN, UART_SIG_SEL_UART1_CTS);
bl602_configgpio(BOARD_UART_1_CTS_PIN);
#endif
#ifdef BOARD_UART_1_RTS_PIN
bl602_config_uart_sel(BOARD_UART_1_RTS_PIN, UART_SIG_SEL_UART1_RTS);
bl602_configgpio(BOARD_UART_1_RTS_PIN);
#endif
}
}

static void bl602_enable_uart_clk(uint8_t enable, int clk_sel, uint8_t div)
{
/* disable UART clock first */

modifyreg32(BL602_CLK_CFG2, CLK_CFG2_UART_CLK_EN, 0);

/* Set div */

modifyreg32(BL602_CLK_CFG2, CLK_CFG2_UART_CLK_DIV_MASK, div);

/* Select clock source for uart */

bl602_set_uart_clk_sel(clk_sel);

/* Set enable or disable */

if (enable)
{
modifyreg32(BL602_CLK_CFG2, 0, CLK_CFG2_UART_CLK_EN);
}
}

/****************************************************************************
* Public Functions
****************************************************************************/

void bl602_uart_configure(const struct uart_config_s *config)
{
uint32_t div;
uint32_t fraction;
uint32_t tx_cfg;
uint32_t rx_cfg;
uint8_t clk_div = 3;

bl602_enable_uart_clk(1, HBN_UART_CLK_160M, clk_div);

bl602_uart_gpio_init(config->idx);

/* Disable all interrupt */

modifyreg32(BL602_UART_INT_MASK(config->idx), 0, 0xff);

/* Disable uart before config */

modifyreg32(BL602_UART_UTX_CONFIG(config->idx), UART_UTX_CONFIG_CR_EN, 0);
modifyreg32(BL602_UART_URX_CONFIG(config->idx), UART_URX_CONFIG_CR_EN, 0);

/* cal the baud rate divisor */

fraction = (_BL602_UART_CLOCK / (clk_div + 1)) * 10 / config->baud % 10;
div = (_BL602_UART_CLOCK / (clk_div + 1)) / config->baud;
if (fraction >= 5)
{
++div;
}

/* set the baud rate register value */

putreg32(((div - 1) << 0x10) | ((div - 1) & 0xffff),
BL602_UART_BIT_PRD(config->idx));

/* configure parity type */

tx_cfg = getreg32(BL602_UART_UTX_CONFIG(config->idx));
rx_cfg = getreg32(BL602_UART_URX_CONFIG(config->idx));

switch (config->parity)
{
case UART_PARITY_NONE:
tx_cfg &= ~UART_UTX_CONFIG_CR_PRT_EN;
rx_cfg &= ~UART_URX_CONFIG_CR_PRT_EN;
break;
case UART_PARITY_ODD:
tx_cfg |= UART_UTX_CONFIG_CR_PRT_EN;
tx_cfg |= UART_UTX_CONFIG_CR_PRT_SEL;
rx_cfg |= UART_URX_CONFIG_CR_PRT_EN;
rx_cfg |= UART_URX_CONFIG_CR_PRT_SEL;
break;
case UART_PARITY_EVEN:
tx_cfg |= UART_UTX_CONFIG_CR_PRT_EN;
tx_cfg &= ~UART_UTX_CONFIG_CR_PRT_SEL;
rx_cfg |= UART_URX_CONFIG_CR_PRT_EN;
rx_cfg &= ~UART_URX_CONFIG_CR_PRT_SEL;
break;
default:
break;
}

/* Configure data and stop bits */

rx_cfg &= ~UART_URX_CONFIG_CR_BIT_CNT_D_MASK;
rx_cfg |= ((uint32_t)config->data_bits - 1) << \
UART_URX_CONFIG_CR_BIT_CNT_D_SHIFT;

tx_cfg &= ~(UART_UTX_CONFIG_CR_BIT_CNT_D_MASK | \
UART_UTX_CONFIG_CR_BIT_CNT_P_MASK);
tx_cfg |= (((uint32_t)config->data_bits - 1) << \
UART_UTX_CONFIG_CR_BIT_CNT_D_SHIFT) | \
(((uint32_t)config->stop_bits + 1) << \
UART_UTX_CONFIG_CR_BIT_CNT_P_SHIFT);

/* Configure tx cts flow control function */

if (config->oflow_ctl)
{
tx_cfg |= UART_UTX_CONFIG_CR_CTS_EN;
}
else
{
tx_cfg &= ~(UART_UTX_CONFIG_CR_CTS_EN);
}

/* Disable rx input de-glitch function */

rx_cfg &= ~(UART_URX_CONFIG_CR_DEG_EN);

/* Configure rx rts flow control function */

/* TODO: What about UART_URX_CONFIG_CR_RTS_SW_VAL? */

if (config->iflow_ctl)
{
rx_cfg |= UART_URX_CONFIG_CR_RTS_SW_MODE;
}
else
{
rx_cfg &= ~(UART_URX_CONFIG_CR_RTS_SW_MODE);
}

/* Write back */

putreg32(rx_cfg, BL602_UART_URX_CONFIG(config->idx));
putreg32(tx_cfg, BL602_UART_UTX_CONFIG(config->idx));

/* Configure LSB-first */

modifyreg32(BL602_UART_DATA_CONFIG(config->idx),
UART_DATA_CONFIG_CR_UART_BIT_INV, 0);

/* Enable tx free run mode */

modifyreg32(BL602_UART_UTX_CONFIG(config->idx), 0,
UART_UTX_CONFIG_CR_FRM_EN);

/* Configure FIFO thresholds */

modifyreg32(BL602_UART_FIFO_CONFIG_1(config->idx),
(UART_FIFO_CONFIG_1_RX_TH_MASK | \
UART_FIFO_CONFIG_1_TX_TH_MASK),
((0x10 - 1) << UART_FIFO_CONFIG_1_RX_TH_SHIFT) | \
((0x10 - 1) << UART_FIFO_CONFIG_1_TX_TH_SHIFT));

/* Enable UART tx rx unit */

modifyreg32(BL602_UART_UTX_CONFIG(config->idx), 0,
UART_UTX_CONFIG_CR_EN);
modifyreg32(BL602_UART_URX_CONFIG(config->idx), 0,
UART_URX_CONFIG_CR_EN);
}

/****************************************************************************
* Name: riscv_lowputc
*
* Description:
* Output one byte on the serial console
*
****************************************************************************/

void riscv_lowputc(char ch)
{
#ifdef HAVE_SERIAL_CONSOLE
/* Wait for FIFO */

while ((getreg32(BL602_UART_FIFO_CONFIG_1(BL602_CONSOLE_IDX)) & \
UART_FIFO_CONFIG_1_TX_CNT_MASK) == 0);

putreg32(ch, BL602_UART_FIFO_WDATA(BL602_CONSOLE_IDX));
#endif /* HAVE_CONSOLE */
}

void bl602_lowsetup(void)
{
#ifdef HAVE_SERIAL_CONSOLE
/* Configure the console UART (if any) */

bl602_uart_configure(&g_bl602_console_config);

#endif /* HAVE_SERIAL_CONSOLE */
}
Loading

0 comments on commit 18e4518

Please sign in to comment.