summaryrefslogtreecommitdiff
path: root/chip/stm32/usart-stm32l.c
diff options
context:
space:
mode:
authorAnton Staaf <robotboy@chromium.org>2014-07-23 14:25:35 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-09-23 00:04:56 +0000
commit0a147973bb6a16714925cc7d701b9b6cffc73cb2 (patch)
tree94e385317bdff8ccc5d06082429b50d62ae7a2d5 /chip/stm32/usart-stm32l.c
parentccb45ff8a2285fbee6d87c02789dc7b00250dc82 (diff)
downloadchrome-ec-0a147973bb6a16714925cc7d701b9b6cffc73cb2.tar.gz
stm32-USART: Add generic stream based usart driver
This driver can be used to access multiple usarts using an abstract stream interface. The stream interface can also be used in drivers for the host interface and USB console interface, providing a consistent API across all character stream style IO. Signed-off-by: Anton Staaf <robotboy@chromium.org> BRANCH=None BUG=None TEST=make buildall -j Change-Id: Icf567f0b0fa4eb0e9ad4cdb0be8edc31c937a7de Reviewed-on: https://chromium-review.googlesource.com/209671 Reviewed-by: Randall Spangler <rspangler@chromium.org> Tested-by: Anton Staaf <robotboy@chromium.org> Commit-Queue: Anton Staaf <robotboy@chromium.org>
Diffstat (limited to 'chip/stm32/usart-stm32l.c')
-rw-r--r--chip/stm32/usart-stm32l.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/chip/stm32/usart-stm32l.c b/chip/stm32/usart-stm32l.c
new file mode 100644
index 0000000000..6725df3c14
--- /dev/null
+++ b/chip/stm32/usart-stm32l.c
@@ -0,0 +1,117 @@
+/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "usart-stm32l.h"
+
+#include "common.h"
+#include "hooks.h"
+#include "registers.h"
+#include "task.h"
+#include "util.h"
+
+/*
+ * This configs array stores the currently active usart_config structure for
+ * each USART, an entry will be NULL if no USART driver is initialized for the
+ * corresponding hardware instance.
+ */
+static struct usart_config const *configs[STM32_USARTS_MAX];
+
+static void usart_variant_enable(struct usart_config const *config)
+{
+ /* Use single-bit sampling */
+ STM32_USART_CR3(config->hw->base) |= STM32_USART_CR3_ONEBIT;
+
+ /*
+ * Make sure we register this config before enabling the HW.
+ * If we did it the other way around the FREQ_CHANGE hook could be
+ * called before we update the configs array and we would miss the
+ * clock frequency change event, leaving our baud rate divisor wrong.
+ */
+ configs[config->hw->index] = config;
+
+ usart_set_baud_f0_l(config);
+
+ task_enable_irq(config->hw->irq);
+}
+
+static void usart_variant_disable(struct usart_config const *config)
+{
+ task_disable_irq(config->hw->irq);
+
+ configs[config->hw->index] = NULL;
+}
+
+static struct usart_hw_ops const usart_variant_hw_ops = {
+ .enable = usart_variant_enable,
+ .disable = usart_variant_disable,
+};
+
+static void freq_change(void)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(configs); ++i)
+ if (configs[i])
+ usart_set_baud_f0_l(configs[i]);
+}
+
+DECLARE_HOOK(HOOK_FREQ_CHANGE, freq_change, HOOK_PRIO_DEFAULT);
+
+/*
+ * USART interrupt bindings. These functions can not be defined as static or
+ * they will be removed by the linker because of the way that DECLARE_IRQ works.
+ */
+#if defined(CONFIG_STREAM_USART1)
+struct usart_hw_config const usart1_hw = {
+ .index = 0,
+ .base = STM32_USART1_BASE,
+ .irq = STM32_IRQ_USART1,
+ .clock_register = &STM32_RCC_APB2ENR,
+ .clock_enable = STM32_RCC_PB2_USART1,
+ .ops = &usart_variant_hw_ops,
+};
+
+void usart1_interrupt(void)
+{
+ usart_interrupt(configs[0]);
+}
+
+DECLARE_IRQ(STM32_IRQ_USART1, usart1_interrupt, 2);
+#endif
+
+#if defined(CONFIG_STREAM_USART2)
+struct usart_hw_config const usart2_hw = {
+ .index = 1,
+ .base = STM32_USART2_BASE,
+ .irq = STM32_IRQ_USART2,
+ .clock_register = &STM32_RCC_APB1ENR,
+ .clock_enable = STM32_RCC_PB1_USART2,
+ .ops = &usart_variant_hw_ops,
+};
+
+void usart2_interrupt(void)
+{
+ usart_interrupt(configs[1]);
+}
+
+DECLARE_IRQ(STM32_IRQ_USART2, usart2_interrupt, 2);
+#endif
+
+#if defined(CONFIG_STREAM_USART3)
+struct usart_hw_config const usart3_hw = {
+ .index = 2,
+ .base = STM32_USART3_BASE,
+ .irq = STM32_IRQ_USART3,
+ .clock_register = &STM32_RCC_APB1ENR,
+ .clock_enable = STM32_RCC_PB1_USART3,
+ .ops = &usart_variant_hw_ops,
+};
+
+void usart3_interrupt(void)
+{
+ usart_interrupt(configs[2]);
+}
+
+DECLARE_IRQ(STM32_IRQ_USART3, usart3_interrupt, 2);
+#endif