summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Sanders <nsanders@chromium.org>2017-07-11 15:14:37 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-07-13 17:30:40 -0700
commit1106dea40d3b18fbab2f42a2510d0a7899650db9 (patch)
tree11900831f90cbc9f16f213618de360ad110c9cc2
parent9fad1adc800cd950e4bd3f292f83186eb0e4f272 (diff)
downloadchrome-ec-1106dea40d3b18fbab2f42a2510d0a7899650db9.tar.gz
servo_micro: add parity setting
Add a control interface to set parity for USB-UART bridge. BRANCH=None BUG=b:37513705 TEST=parity settable on command line or by servod Signed-off-by: Nick Sanders <nsanders@chromium.org> Change-Id: Ib859a70981162be58edfa79c7cb267e0084e05e6 Reviewed-on: https://chromium-review.googlesource.com/564150 Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
-rw-r--r--board/servo_micro/board.c56
-rw-r--r--chip/stm32/registers.h4
-rw-r--r--chip/stm32/usart.c40
-rw-r--r--chip/stm32/usart.h12
-rw-r--r--chip/stm32/usb-stream.c36
-rw-r--r--chip/stm32/usb-stream.h46
6 files changed, 188 insertions, 6 deletions
diff --git a/board/servo_micro/board.c b/board/servo_micro/board.c
index dedfcfdd7a..505a6d628a 100644
--- a/board/servo_micro/board.c
+++ b/board/servo_micro/board.c
@@ -5,6 +5,7 @@
/* Servo micro board configuration */
#include "common.h"
+#include "console.h"
#include "ec_version.h"
#include "gpio.h"
#include "hooks.h"
@@ -52,14 +53,15 @@ static struct usart_config const usart2 =
usart2_to_usb,
usb_to_usart2);
-USB_STREAM_CONFIG(usart2_usb,
+USB_STREAM_CONFIG_USART_IFACE(usart2_usb,
USB_IFACE_USART2_STREAM,
USB_STR_USART2_STREAM_NAME,
USB_EP_USART2_STREAM,
USB_STREAM_RX_SIZE,
USB_STREAM_TX_SIZE,
usb_to_usart2,
- usart2_to_usb)
+ usart2_to_usb,
+ usart2)
/******************************************************************************
@@ -82,14 +84,15 @@ static struct usart_config const usart3 =
usart3_to_usb,
usb_to_usart3);
-USB_STREAM_CONFIG(usart3_usb,
+USB_STREAM_CONFIG_USART_IFACE(usart3_usb,
USB_IFACE_USART3_STREAM,
USB_STR_USART3_STREAM_NAME,
USB_EP_USART3_STREAM,
USB_STREAM_RX_SIZE,
USB_STREAM_TX_SIZE,
usb_to_usart3,
- usart3_to_usb)
+ usart3_to_usb,
+ usart3)
/******************************************************************************
@@ -112,15 +115,56 @@ static struct usart_config const usart4 =
usart4_to_usb,
usb_to_usart4);
-USB_STREAM_CONFIG(usart4_usb,
+USB_STREAM_CONFIG_USART_IFACE(usart4_usb,
USB_IFACE_USART4_STREAM,
USB_STR_USART4_STREAM_NAME,
USB_EP_USART4_STREAM,
USB_STREAM_RX_SIZE,
USB_STREAM_TX_SIZE,
usb_to_usart4,
- usart4_to_usb)
+ usart4_to_usb,
+ usart4)
+/******************************************************************************
+ * Check parity setting on usarts.
+ */
+static int command_uart_parity(int argc, char **argv)
+{
+ int parity, newparity;
+ struct usart_config const *usart;
+ char *e;
+
+ if ((argc < 2) || (argc > 3))
+ return EC_ERROR_PARAM_COUNT;
+
+ if (!strcasecmp(argv[1], "usart2"))
+ usart = &usart2;
+ else if (!strcasecmp(argv[1], "usart3"))
+ usart = &usart3;
+ else if (!strcasecmp(argv[1], "usart4"))
+ usart = &usart4;
+ else
+ return EC_ERROR_PARAM1;
+
+ if (argc == 3) {
+ parity = strtoi(argv[2], &e, 0);
+ if (*e || (parity < 0) || (parity > 2))
+ return EC_ERROR_PARAM2;
+
+ usart_set_parity(usart, parity);
+ }
+
+ newparity = usart_get_parity(usart);
+ ccprintf("Parity on %s is %d.\n", argv[1], newparity);
+
+ if ((argc == 3) && (newparity != parity))
+ return EC_ERROR_UNKNOWN;
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(parity, command_uart_parity,
+ "usart[2|3|4] [0|1|2]",
+ "Set parity on uart");
/******************************************************************************
* Define the strings used in our USB descriptors.
diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h
index 03a2c3be00..6c9e2608dc 100644
--- a/chip/stm32/registers.h
+++ b/chip/stm32/registers.h
@@ -222,6 +222,8 @@
#define STM32_USART_CR1_RXNEIE (1 << 5)
#define STM32_USART_CR1_TCIE (1 << 6)
#define STM32_USART_CR1_TXEIE (1 << 7)
+#define STM32_USART_CR1_PS (1 << 9)
+#define STM32_USART_CR1_PCE (1 << 10)
#define STM32_USART_CR1_OVER8 (1 << 15)
#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x04)
#define STM32_USART_CR2_SWAP (1 << 15)
@@ -264,6 +266,8 @@
#define STM32_USART_CR1_RXNEIE (1 << 5)
#define STM32_USART_CR1_TCIE (1 << 6)
#define STM32_USART_CR1_TXEIE (1 << 7)
+#define STM32_USART_CR1_PS (1 << 9)
+#define STM32_USART_CR1_PCE (1 << 10)
#define STM32_USART_CR1_UE (1 << 13)
#define STM32_USART_CR1_OVER8 (1 << 15) /* STM32L only */
#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x10)
diff --git a/chip/stm32/usart.c b/chip/stm32/usart.c
index 549769cb48..d47d13e149 100644
--- a/chip/stm32/usart.c
+++ b/chip/stm32/usart.c
@@ -102,6 +102,46 @@ void usart_set_baud_f(struct usart_config const *config, int frequency_hz)
STM32_USART_BRR(config->hw->base) = div;
}
+int usart_get_parity(struct usart_config const *config)
+{
+ intptr_t base = config->hw->base;
+
+ if (!(STM32_USART_CR1(base) & STM32_USART_CR1_PCE))
+ return 0;
+ if (STM32_USART_CR1(base) & STM32_USART_CR1_PS)
+ return 1;
+ return 2;
+}
+
+void usart_set_parity(struct usart_config const *config, int parity)
+{
+ uint32_t ue;
+ intptr_t base = config->hw->base;
+
+ if ((parity < 0) || (parity > 2))
+ return;
+
+ /* Record active state and disable the UART. */
+ ue = STM32_USART_CR1(base) & STM32_USART_CR1_UE;
+ STM32_USART_CR1(base) &= ~STM32_USART_CR1_UE;
+
+ if (parity) {
+ /* Set parity control enable. */
+ STM32_USART_CR1(base) |= STM32_USART_CR1_PCE;
+ /* Set parity select even/odd bit. */
+ if (parity == 2)
+ STM32_USART_CR1(base) &= ~STM32_USART_CR1_PS;
+ else
+ STM32_USART_CR1(base) |= STM32_USART_CR1_PS;
+ } else {
+ STM32_USART_CR1(base) &=
+ ~(STM32_USART_CR1_PCE | STM32_USART_CR1_PS);
+ }
+
+ /* Restore active state. */
+ STM32_USART_CR1(base) |= ue;
+}
+
void usart_interrupt(struct usart_config const *config)
{
config->tx->interrupt(config);
diff --git a/chip/stm32/usart.h b/chip/stm32/usart.h
index 875dbfdc76..cbfd8eca21 100644
--- a/chip/stm32/usart.h
+++ b/chip/stm32/usart.h
@@ -198,6 +198,18 @@ void usart_set_baud_f0_l(struct usart_config const *config, int frequency_hz);
void usart_set_baud_f(struct usart_config const *config, int frequency_hz);
/*
+ * Allow specification of parity for this usart.
+ * parity is 0: none, 1: odd, 2: even.
+ */
+void usart_set_parity(struct usart_config const *config, int parity);
+
+/*
+ * Check parity for this usart.
+ * parity is 0: none, 1: odd, 2: even.
+ */
+int usart_get_parity(struct usart_config const *config);
+
+/*
* Different families provide different ways of clearing the transmit complete
* flag. This function will be provided by the family specific implementation.
*/
diff --git a/chip/stm32/usb-stream.c b/chip/stm32/usb-stream.c
index 313e29e8df..e1ec19d7d4 100644
--- a/chip/stm32/usb-stream.c
+++ b/chip/stm32/usb-stream.c
@@ -12,6 +12,7 @@
#include "task.h"
#include "timer.h"
#include "util.h"
+#include "usart.h"
#include "usb_hw.h"
#include "usb-stream.h"
@@ -143,3 +144,38 @@ void usb_stream_reset(struct usb_stream_config const *config)
(0 << 9) | /* Bulk EP */
(rx_disabled(config) ? EP_RX_NAK : EP_RX_VALID));
}
+
+int usb_usart_interface(struct usb_stream_config const *config,
+ struct usart_config const *usart,
+ int interface,
+ usb_uint *rx_buf, usb_uint *tx_buf)
+{
+ struct usb_setup_packet req;
+
+ usb_read_setup_packet(rx_buf, &req);
+
+ if (req.bmRequestType != (USB_DIR_OUT |
+ USB_TYPE_VENDOR |
+ USB_RECIP_INTERFACE))
+ return -1;
+
+ if (req.wIndex != interface ||
+ req.wLength != 0)
+ return -1;
+
+ switch (req.bRequest) {
+ /* Set parity. */
+ case USB_USART_SET_PARITY:
+ usart_set_parity(usart, req.wValue);
+ break;
+
+ /* TODO(nsanders): support reading parity. */
+ /* TODO(nsanders): support baud. */
+ default:
+ return -1;
+ }
+
+ btable_ep[0].tx_count = 0;
+ STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, EP_STATUS_OUT);
+ return 0;
+}
diff --git a/chip/stm32/usb-stream.h b/chip/stm32/usb-stream.h
index f829009c51..5a584327a5 100644
--- a/chip/stm32/usb-stream.h
+++ b/chip/stm32/usb-stream.h
@@ -16,6 +16,7 @@
#include "hooks.h"
#include "producer.h"
#include "queue.h"
+#include "usart.h"
#include "usb_descriptor.h"
#include "usb_hw.h"
@@ -230,12 +231,57 @@ extern struct producer_ops const usb_stream_producer_ops;
RX_QUEUE, \
TX_QUEUE)
+/* Declare a utility interface for setting parity/baud. */
+#define USB_USART_IFACE(NAME, INTERFACE, USART_CFG) \
+ static int CONCAT2(NAME, _interface_)(usb_uint *rx_buf, \
+ usb_uint *tx_buf) \
+ { return usb_usart_interface(&NAME, &USART_CFG, INTERFACE, \
+ rx_buf, tx_buf); } \
+ USB_DECLARE_IFACE(INTERFACE, \
+ CONCAT2(NAME, _interface_))
+
+/* This is a medium version for declaring Google serial endpoints */
+#define USB_STREAM_CONFIG_USART_IFACE(NAME, \
+ INTERFACE, \
+ INTERFACE_NAME, \
+ ENDPOINT, \
+ RX_SIZE, \
+ TX_SIZE, \
+ RX_QUEUE, \
+ TX_QUEUE, \
+ USART_CFG) \
+ USB_STREAM_CONFIG_FULL(NAME, \
+ INTERFACE, \
+ USB_CLASS_VENDOR_SPEC, \
+ USB_SUBCLASS_GOOGLE_SERIAL, \
+ USB_PROTOCOL_GOOGLE_SERIAL, \
+ INTERFACE_NAME, \
+ ENDPOINT, \
+ RX_SIZE, \
+ TX_SIZE, \
+ RX_QUEUE, \
+ TX_QUEUE); \
+ USB_USART_IFACE(NAME, INTERFACE, USART_CFG)
+
/*
* Handle USB and Queue request in a deferred callback.
*/
void usb_stream_deferred(struct usb_stream_config const *config);
/*
+ * Handle control interface requests.
+ */
+enum usb_usart {
+ USB_USART_REQ_PARITY = 0,
+ USB_USART_SET_PARITY = 1,
+ USB_USART_REQ_BAUD = 2,
+ USB_USART_SET_BAUD = 3,
+};
+int usb_usart_interface(struct usb_stream_config const *config,
+ struct usart_config const *usart,
+ int interface, usb_uint *rx_buf, usb_uint *tx_buf);
+
+/*
* These functions are used by the trampoline functions defined above to
* connect USB endpoint events with the generic USB stream driver.
*/