blob: 93dede2fd4ad00e0cfff8610d5ddba9783c02aeb [file] [log] [blame]
/****************************************************************************
* arch/risc-v/src/mpfs/mpfs_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 <stdint.h>
#include <arch/board/board.h>
#include "riscv_internal.h"
#include "hardware/mpfs_memorymap.h"
#include "hardware/mpfs_uart.h"
#include "mpfs.h"
#include "mpfs_clockconfig.h"
#include "mpfs_config.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Select UART parameters for the selected console */
#if defined(CONFIG_UART0_SERIAL_CONSOLE)
# define MPFS_CONSOLE_BASE MPFS_UART0_BASE
# define MPFS_CONSOLE_BAUD CONFIG_UART0_BAUD
# define MPFS_CONSOLE_BITS CONFIG_UART0_BITS
# define MPFS_CONSOLE_PARITY CONFIG_UART0_PARITY
# define MPFS_CONSOLE_2STOP CONFIG_UART0_2STOP
# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_MMUART0
# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_MMUART0
# define HAVE_UART
#elif defined(CONFIG_UART1_SERIAL_CONSOLE)
# define MPFS_CONSOLE_BASE MPFS_UART1_BASE
# define MPFS_CONSOLE_BAUD CONFIG_UART1_BAUD
# define MPFS_CONSOLE_BITS CONFIG_UART1_BITS
# define MPFS_CONSOLE_PARITY CONFIG_UART1_PARITY
# define MPFS_CONSOLE_2STOP CONFIG_UART1_2STOP
# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_MMUART1
# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_MMUART1
# define HAVE_UART
#elif defined(CONFIG_UART2_SERIAL_CONSOLE)
# define MPFS_CONSOLE_BASE MPFS_UART2_BASE
# define MPFS_CONSOLE_BAUD CONFIG_UART2_BAUD
# define MPFS_CONSOLE_BITS CONFIG_UART2_BITS
# define MPFS_CONSOLE_PARITY CONFIG_UART2_PARITY
# define MPFS_CONSOLE_2STOP CONFIG_UART2_2STOP
# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_MMUART2
# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_MMUART2
# define HAVE_UART
# elif defined(CONFIG_UART3_SERIAL_CONSOLE)
# define MPFS_CONSOLE_BASE MPFS_UART3_BASE
# define MPFS_CONSOLE_BAUD CONFIG_UART3_BAUD
# define MPFS_CONSOLE_BITS CONFIG_UART3_BITS
# define MPFS_CONSOLE_PARITY CONFIG_UART3_PARITY
# define MPFS_CONSOLE_2STOP CONFIG_UART3_2STOP
# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_MMUART3
# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_MMUART3
# define HAVE_UART
# elif defined(CONFIG_UART4_SERIAL_CONSOLE)
# define MPFS_CONSOLE_BASE MPFS_UART4_BASE
# define MPFS_CONSOLE_BAUD CONFIG_UART4_BAUD
# define MPFS_CONSOLE_BITS CONFIG_UART4_BITS
# define MPFS_CONSOLE_PARITY CONFIG_UART4_PARITY
# define MPFS_CONSOLE_2STOP CONFIG_UART4_2STOP
# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_MMUART4
# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_MMUART4
# define HAVE_UART
# elif defined(HAVE_UART)
# error "No CONFIG_UARTn_SERIAL_CONSOLE Setting"
# endif
/****************************************************************************
* Private Functions
****************************************************************************/
#if !defined(CONFIG_SUPPRESS_UART_CONFIG)
/****************************************************************************
* Name: config_baud_divisors
*
* Description:
* Configure the UART baudrate divisors.
*
****************************************************************************/
static void config_baud_divisors(void)
{
uint32_t baud_value;
uint32_t baud_value_by_64;
uint32_t baud_value_by_128;
uint32_t fractional_baud_value;
uint64_t pclk_freq;
pclk_freq = MPFS_MSS_APB_AHB_CLK;
/* Compute baud value based on requested baud rate and PCLK frequency.
* The baud value is computed using the following equation:
* baud_value = PCLK_Frequency / (baud_rate * 16)
*/
baud_value_by_128 = (uint32_t)((8UL * pclk_freq) / MPFS_CONSOLE_BAUD);
baud_value_by_64 = baud_value_by_128 / 2U;
baud_value = baud_value_by_64 / 64U;
fractional_baud_value = baud_value_by_64 - (baud_value * 64U);
fractional_baud_value += (baud_value_by_128 - (baud_value * 128U))
- (fractional_baud_value * 2U);
if (baud_value <= (uint32_t)UINT16_MAX)
{
putreg32(baud_value >> 8, MPFS_CONSOLE_BASE + MPFS_UART_DLH_OFFSET);
putreg32(baud_value & 0xff, MPFS_CONSOLE_BASE + MPFS_UART_DLH_OFFSET);
if (baud_value > 1)
{
/* Enable Fractional baud rate */
uint8_t mm0 = getreg32(MPFS_CONSOLE_BASE + MPFS_UART_MM0_OFFSET);
mm0 |= UART_MM0_EFBR;
putreg32(mm0, MPFS_CONSOLE_BASE + MPFS_UART_MM0_OFFSET);
putreg32(fractional_baud_value,
MPFS_CONSOLE_BASE + MPFS_UART_DFR_OFFSET);
}
}
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: riscv_lowputc
*
* Description:
* Output one byte on the serial console
*
****************************************************************************/
void riscv_lowputc(char ch)
{
#if defined HAVE_UART && defined HAVE_SERIAL_CONSOLE
/* Wait for the transmitter to be available */
while ((getreg32(MPFS_CONSOLE_BASE + MPFS_UART_LSR_OFFSET)
& UART_LSR_THRE) == 0);
/* Send the character */
putreg32((uint32_t)ch, MPFS_CONSOLE_BASE + MPFS_UART_THR_OFFSET);
#endif
}
/****************************************************************************
* Name: mpfs_lowsetup
*
* Description:
* This performs basic initialization of the UART used for the serial
* console. Its purpose is to get the console output available as soon
* as possible.
*
****************************************************************************/
void mpfs_lowsetup(void)
{
#if defined(HAVE_UART)
/* Enable and configure the selected console device */
#if defined(HAVE_SERIAL_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG)
uint32_t lcr = 0;
/* reset on */
modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET,
0, MPFS_CONSOLE_RESETBIT);
/* reset off */
modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET,
0, MPFS_CONSOLE_CLOCKBIT);
/* clock on */
modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET,
MPFS_CONSOLE_RESETBIT, 0);
switch (MPFS_CONSOLE_BITS)
{
case 5:
lcr |= UART_LCR_DLS_5BITS;
break;
case 6:
lcr |= UART_LCR_DLS_6BITS;
break;
case 7:
lcr |= UART_LCR_DLS_7BITS;
break;
case 8:
default:
lcr |= UART_LCR_DLS_8BITS;
break;
}
#ifdef MPFS_CONSOLE_2STOP
lcr |= UART_LCR_STOP;
#endif
if (MPFS_CONSOLE_PARITY == 1)
{
lcr |= UART_LCR_PEN;
}
else if (MPFS_CONSOLE_PARITY == 2)
{
lcr |= (UART_LCR_PEN | UART_LCR_EPS);
}
putreg32(lcr | UART_LCR_DLAB, MPFS_CONSOLE_BASE + MPFS_UART_LCR_OFFSET);
config_baud_divisors();
putreg32(lcr, MPFS_CONSOLE_BASE + MPFS_UART_LCR_OFFSET);
#endif /* HAVE_SERIAL_CONSOLE && !CONFIG_SUPPRESS_UART_CONFIG */
#endif /* HAVE_UART */
}