mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-09 17:11:42 +00:00
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>
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -197,6 +197,18 @@ void usart_interrupt(struct usart_config const *config);
|
||||
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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,11 +231,56 @@ 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.
|
||||
|
||||
Reference in New Issue
Block a user