Platform: Implement UART uninitialize function
This patch introduces an uninitialize function for the UART
peripheral to restore it's default state before passing
execution to runtime image from MCUBoot.
Change-Id: Iaf239b575be82402b9c142e990fb0ea30ffe9a88
Signed-off-by: David Vincze <david.vincze@arm.com>
diff --git a/platform/ext/common/uart_stdout.c b/platform/ext/common/uart_stdout.c
index 75e8b18..7a41f1e 100755
--- a/platform/ext/common/uart_stdout.c
+++ b/platform/ext/common/uart_stdout.c
@@ -77,3 +77,10 @@
ASSERT_HIGH(ret);
}
+void stdio_uninit(void)
+{
+ int32_t ret = ARM_DRIVER_OK;
+ ret = TFM_DRIVER_STDIO.Uninitialize();
+ ASSERT_HIGH(ret);
+}
+
diff --git a/platform/ext/common/uart_stdout.h b/platform/ext/common/uart_stdout.h
index dcced8a..5d79398 100644
--- a/platform/ext/common/uart_stdout.h
+++ b/platform/ext/common/uart_stdout.h
@@ -35,4 +35,9 @@
*/
void stdio_init(void);
+/**
+ * \brief Uninitializes the STDIO.
+ */
+void stdio_uninit(void);
+
#endif /* __UART_STDOUT_H__ */
diff --git a/platform/ext/target/musca_a/CMSIS_Driver/Driver_USART.c b/platform/ext/target/musca_a/CMSIS_Driver/Driver_USART.c
index 79e6428..866ea9e 100755
--- a/platform/ext/target/musca_a/CMSIS_Driver/Driver_USART.c
+++ b/platform/ext/target/musca_a/CMSIS_Driver/Driver_USART.c
@@ -88,6 +88,14 @@
return ARM_DRIVER_OK;
}
+static int32_t ARM_USARTx_Uninitialize(UARTx_Resources* uart_dev)
+{
+ /* Disables and uninitializes generic UART driver */
+ uart_pl011_uninit(uart_dev->dev);
+
+ return ARM_DRIVER_OK;
+}
+
static int32_t ARM_USARTx_PowerControl(UARTx_Resources* uart_dev,
ARM_POWER_STATE state)
{
@@ -100,9 +108,8 @@
case ARM_POWER_FULL:
/* Nothing to be done */
return ARM_DRIVER_OK;
- /* default: The default is not defined intentionally to force the
- * compiler to check that all the enumeration values are
- * covered in the switch.*/
+ default:
+ return ARM_DRIVER_ERROR_PARAMETER;
}
}
@@ -232,8 +239,7 @@
static int32_t ARM_USART0_Uninitialize(void)
{
- /* Nothing to be done */
- return ARM_DRIVER_OK;
+ return ARM_USARTx_Uninitialize(&USART0_DEV);
}
static int32_t ARM_USART0_PowerControl(ARM_POWER_STATE state)
@@ -330,8 +336,7 @@
static int32_t ARM_USART1_Uninitialize(void)
{
- /* Nothing to be done */
- return ARM_DRIVER_OK;
+ return ARM_USARTx_Uninitialize(&USART1_DEV);
}
static int32_t ARM_USART1_PowerControl(ARM_POWER_STATE state)
diff --git a/platform/ext/target/musca_a/Native_Driver/uart_pl011_drv.c b/platform/ext/target/musca_a/Native_Driver/uart_pl011_drv.c
index 829e420..01feaa4 100755
--- a/platform/ext/target/musca_a/Native_Driver/uart_pl011_drv.c
+++ b/platform/ext/target/musca_a/Native_Driver/uart_pl011_drv.c
@@ -152,6 +152,19 @@
#define UART_PL011_UARTDMACR_TX_MASK ( \
0x1u<<UART_PL011_UARTDMACR_TXEN_OFF)
+/* Default register values of UART PL011 */
+#define UART_PL011_DATA_REG_RESET_VALUE (0x0u)
+#define UART_PL011_ECR_REG_CLEAR_VALUE (0xFFu)
+#define UART_PL011_ILPR_REG_RESET_VALUE (0x0u)
+#define UART_PL011_IBRD_REG_RESET_VALUE (0x0u)
+#define UART_PL011_FBRD_REG_RESET_VALUE (0x0u)
+#define UART_PL011_LCR_H_REG_RESET_VALUE (0x0u)
+#define UART_PL011_CR_REG_RESET_VALUE (0x0300u)
+#define UART_PL011_IFLS_REG_RESET_VALUE (0x12u)
+#define UART_PL011_IMSC_REG_RESET_VALUE (0x0u)
+#define UART_PL011_ICR_REG_CLEAR_VALUE (0x7FFu)
+#define UART_PL011_DMACR_REG_RESET_VALUE (0x0u)
+
static void _uart_pl011_enable(struct _uart_pl011_reg_map_t* p_uart)
{
p_uart->uartcr |= UART_PL011_UARTCR_EN_MASK;
@@ -182,6 +195,11 @@
return (bool)(p_uart->uartlcr_h & UART_PL011_UARTLCR_H_FEN_MASK);
}
+static bool _uart_pl011_is_busy(struct _uart_pl011_reg_map_t* p_uart)
+{
+ return (bool)(p_uart->uartfr & UART_PL011_UARTFR_BUSYBIT);
+}
+
static enum uart_pl011_error_t _uart_pl011_set_baudrate(
struct _uart_pl011_reg_map_t* p_uart,
uint32_t clk, uint32_t baudrate)
@@ -318,6 +336,27 @@
}
}
+static void _uart_pl011_reset_regs(struct _uart_pl011_reg_map_t* p_uart)
+{
+ /* Restore the default value of UART registers, the registers which
+ * are not listed below are Read-Only */
+
+ /* Will disable the UART */
+ p_uart->uartcr = UART_PL011_CR_REG_RESET_VALUE;
+ p_uart->uartdr = UART_PL011_DATA_REG_RESET_VALUE;
+ /* Clear all the errors */
+ p_uart->uartecr = UART_PL011_ECR_REG_CLEAR_VALUE;
+ p_uart->uartilpr = UART_PL011_ILPR_REG_RESET_VALUE;
+ p_uart->uartibrd = UART_PL011_IBRD_REG_RESET_VALUE;
+ p_uart->uartfbrd = UART_PL011_FBRD_REG_RESET_VALUE;
+ p_uart->uartlcr_h = UART_PL011_LCR_H_REG_RESET_VALUE;
+ p_uart->uartifls = UART_PL011_IFLS_REG_RESET_VALUE;
+ p_uart->uartimsc = UART_PL011_IMSC_REG_RESET_VALUE;
+ /* Clear all the interrupts */
+ p_uart->uarticr = UART_PL011_ICR_REG_CLEAR_VALUE;
+ p_uart->uartdmacr = UART_PL011_DMACR_REG_RESET_VALUE;
+}
+
enum uart_pl011_error_t uart_pl011_init(struct uart_pl011_dev_t* dev,
uint32_t uart_clk)
{
@@ -364,7 +403,10 @@
struct _uart_pl011_reg_map_t* p_uart =
(struct _uart_pl011_reg_map_t*)dev->cfg->base;
- _uart_pl011_disable(p_uart);
+ while(_uart_pl011_is_busy(p_uart));
+
+ /* Disable and restore the default configuration of the peripheral */
+ _uart_pl011_reset_regs(p_uart);
dev->data->state = UART_PL011_UNINITIALIZED;