[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/lk/platform/stm32f4xx/uart.c b/src/bsp/lk/platform/stm32f4xx/uart.c
new file mode 100644
index 0000000..d1b51f8
--- /dev/null
+++ b/src/bsp/lk/platform/stm32f4xx/uart.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2012 Kent Ryhorchuk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <stdarg.h>
+#include <reg.h>
+#include <debug.h>
+#include <stdio.h>
+#include <assert.h>
+#include <lib/cbuf.h>
+#include <kernel/thread.h>
+#include <platform/debug.h>
+#include <arch/ops.h>
+#include <dev/uart.h>
+#include <target/debugconfig.h>
+#include <stm32f4xx_rcc.h>
+#include <stm32f4xx_usart.h>
+#include <arch/arm/cm.h>
+
+#ifdef ENABLE_UART1
+cbuf_t uart1_rx_buf;
+#ifndef UART1_FLOWCONTROL
+#define UART1_FLOWCONTROL USART_HardwareFlowControl_None
+#endif
+#ifndef UART1_BAUDRATE
+#define UART1_BAUDRATE 115200
+#endif
+#ifndef UART1_RXBUF_SIZE
+#define UART1_RXBUF_SIZE 64
+#endif
+#endif
+
+#ifdef ENABLE_UART2
+cbuf_t uart2_rx_buf;
+#ifndef UART2_FLOWCONTROL
+#define UART2_FLOWCONTROL USART_HardwareFlowControl_None
+#endif
+#ifndef UART2_BAUDRATE
+#define UART2_BAUDRATE 115200
+#endif
+#ifndef UART2_RXBUF_SIZE
+#define UART2_RXBUF_SIZE 64
+#endif
+#endif
+
+#ifdef ENABLE_UART3
+cbuf_t uart3_rx_buf;
+#ifndef UART3_FLOWCONTROL
+#define UART3_FLOWCONTROL USART_HardwareFlowControl_None
+#endif
+#ifndef UART3_BAUDRATE
+#define UART3_BAUDRATE 115200
+#endif
+#ifndef UART3_RXBUF_SIZE
+#define UART3_RXBUF_SIZE 64
+#endif
+#endif
+
+#ifdef ENABLE_UART6
+cbuf_t uart6_rx_buf;
+#ifndef UART6_FLOWCONTROL
+#define UART6_FLOWCONTROL USART_HardwareFlowControl_None
+#endif
+#ifndef UART6_BAUDRATE
+#define UART6_BAUDRATE 115200
+#endif
+#ifndef UART6_RXBUF_SIZE
+#define UART6_RXBUF_SIZE 64
+#endif
+#endif
+
+static void usart_init1_early(USART_TypeDef *usart, uint32_t baud, uint16_t flowcontrol, int irqn)
+{
+ USART_InitTypeDef init;
+
+ init.USART_BaudRate = baud;
+ init.USART_WordLength = USART_WordLength_8b;
+ init.USART_StopBits = USART_StopBits_1;
+ init.USART_Parity = USART_Parity_No;
+ init.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;
+ init.USART_HardwareFlowControl = flowcontrol;
+
+ USART_Init(usart, &init);
+ USART_ITConfig(usart, USART_IT_RXNE, DISABLE);
+ NVIC_DisableIRQ(irqn);
+ USART_Cmd(usart, ENABLE);
+}
+
+static void usart_init1(USART_TypeDef *usart, int irqn, cbuf_t *rxbuf, size_t rxsize)
+{
+ cbuf_initialize(rxbuf, rxsize);
+ USART_ITConfig(usart, USART_IT_RXNE, ENABLE);
+ NVIC_EnableIRQ(irqn);
+ USART_Cmd(usart, ENABLE);
+}
+
+void uart_init_early(void)
+{
+#ifdef ENABLE_UART1
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
+ usart_init1_early(USART1, UART1_BAUDRATE, UART1_FLOWCONTROL, USART1_IRQn);
+#endif
+#ifdef ENABLE_UART2
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
+ usart_init1_early(USART2, UART2_BAUDRATE, UART2_FLOWCONTROL, USART2_IRQn);
+#endif
+#ifdef ENABLE_UART3
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
+ usart_init1_early(USART3, UART3_BAUDRATE, UART3_FLOWCONTROL, USART3_IRQn);
+#endif
+#ifdef ENABLE_UART6
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);
+ usart_init1_early(USART6, UART6_BAUDRATE, UART6_FLOWCONTROL, USART6_IRQn);
+#endif
+}
+
+void uart_init(void)
+{
+#ifdef ENABLE_UART1
+ usart_init1(USART1, USART1_IRQn, &uart1_rx_buf, UART1_RXBUF_SIZE);
+#endif
+#ifdef ENABLE_UART2
+ usart_init1(USART2, USART2_IRQn, &uart2_rx_buf, UART2_RXBUF_SIZE);
+#endif
+#ifdef ENABLE_UART3
+ usart_init1(USART3, USART3_IRQn, &uart3_rx_buf, UART3_RXBUF_SIZE);
+#endif
+#ifdef ENABLE_UART6
+ usart_init1(USART6, USART6_IRQn, &uart6_rx_buf, UART6_RXBUF_SIZE);
+#endif
+}
+
+void uart_rx_irq(USART_TypeDef *usart, cbuf_t *rxbuf)
+{
+ arm_cm_irq_entry();
+
+ bool resched = false;
+ while (USART_GetFlagStatus(usart, USART_FLAG_RXNE)) {
+ if (!cbuf_space_avail(rxbuf)) {
+ // Overflow - let flow control do its thing by not
+ // reading the from the FIFO.
+ USART_ITConfig(usart, USART_IT_RXNE, DISABLE);
+ break;
+ }
+
+ char c = USART_ReceiveData(usart);
+ cbuf_write_char(rxbuf, c, false);
+ resched = true;
+ }
+
+ arm_cm_irq_exit(resched);
+}
+
+#ifdef ENABLE_UART1
+void stm32_USART1_IRQ(void)
+{
+ uart_rx_irq(USART1, &uart1_rx_buf);
+}
+#endif
+
+#ifdef ENABLE_UART2
+void stm32_USART2_IRQ(void)
+{
+ uart_rx_irq(USART2, &uart2_rx_buf);
+}
+#endif
+
+#ifdef ENABLE_UART3
+void stm32_USART3_IRQ(void)
+{
+ uart_rx_irq(USART3, &uart3_rx_buf);
+}
+#endif
+
+#ifdef ENABLE_UART6
+void stm32_USART6_IRQ(void)
+{
+ uart_rx_irq(USART6, &uart6_rx_buf);
+}
+#endif
+
+static void usart_putc(USART_TypeDef *usart, char c)
+{
+ while (USART_GetFlagStatus(usart, USART_FLAG_TXE) == 0);
+ USART_SendData(usart, c);
+ while (USART_GetFlagStatus(usart, USART_FLAG_TC) == 0);
+}
+
+static int usart_getc(USART_TypeDef *usart, cbuf_t *rxbuf, bool wait)
+{
+ unsigned char c;
+ if (cbuf_read_char(rxbuf, (char*) &c, wait) == 0)
+ return -1;
+ if (cbuf_space_avail(rxbuf) > cbuf_size(rxbuf))
+ USART_ITConfig(usart, USART_IT_RXNE, ENABLE);
+
+ return c;
+}
+
+static USART_TypeDef *get_usart(int port)
+{
+ switch (port) {
+#ifdef ENABLE_UART1
+ case 1: return USART1;
+#endif
+#ifdef ENABLE_UART2
+ case 2: return USART2;
+#endif
+#ifdef ENABLE_UART3
+ case 3: return USART3;
+#endif
+#ifdef ENABLE_UART6
+ case 6: return USART6;
+#endif
+ default:
+ ASSERT(false);
+ return 0;
+ }
+}
+
+static cbuf_t *get_rxbuf(int port)
+{
+ switch (port) {
+#ifdef ENABLE_UART1
+ case 1: return &uart1_rx_buf;
+#endif
+#ifdef ENABLE_UART2
+ case 2: return &uart2_rx_buf;
+#endif
+#ifdef ENABLE_UART3
+ case 3: return &uart3_rx_buf;
+#endif
+#ifdef ENABLE_UART6
+ case 6: return &uart6_rx_buf;
+#endif
+ default:
+ ASSERT(false);
+ return 0;
+ }
+}
+
+int uart_putc(int port, char c)
+{
+ USART_TypeDef *usart = get_usart(port);
+ usart_putc(usart, c);
+ return 1;
+}
+
+int uart_getc(int port, bool wait)
+{
+ cbuf_t *rxbuf = get_rxbuf(port);
+ USART_TypeDef *usart = get_usart(port);
+
+ return usart_getc(usart, rxbuf, wait);
+}
+
+void uart_flush_tx(int port) {}
+
+void uart_flush_rx(int port) {}
+
+void uart_init_port(int port, uint baud) {
+ USART_TypeDef *usart = get_usart(port);
+ uint32_t treg = 0;
+ uint32_t apbclk = 0;
+ uint32_t intdiv = 0;
+ uint32_t fracdiv = 0;
+ RCC_ClocksTypeDef RCC_ClksStat;
+
+ RCC_GetClocksFreq(&RCC_ClksStat);
+
+ if ((usart == USART1) || (usart == USART6)) {
+ apbclk = RCC_ClksStat.PCLK2_Frequency;
+ } else {
+ apbclk = RCC_ClksStat.PCLK1_Frequency;
+ }
+
+ if ((usart->CR1 & USART_CR1_OVER8) != 0) {
+ intdiv = ((25 * apbclk) / (2 * (baud)));
+ } else {
+ intdiv = ((25 * apbclk) / (4 * (baud)));
+ }
+ treg = (intdiv / 100) << 4;
+
+ fracdiv = intdiv - (100 * (treg >> 4));
+
+ if ((usart->CR1 & USART_CR1_OVER8) != 0) {
+ treg |= ((((fracdiv * 8) + 50) / 100)) & ((uint8_t) 0x07);
+ } else {
+ treg |= ((((fracdiv * 16) + 50) / 100)) & ((uint8_t) 0x0F);
+ }
+
+ usart->BRR = (uint16_t) treg;
+}
+
+// inject a character into the console uart rx buffer
+void __debugger_console_putc(char c) {
+ cbuf_t *rxbuf = get_rxbuf(DEBUG_UART);
+ if (rxbuf && cbuf_space_avail(rxbuf)) {
+ cbuf_write_char(rxbuf, c, false);
+ }
+}
+