mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-27 18:25:05 +00:00
sweetberry: add dwc usb support
stm32f446 uses a synopsys designware USB block rather than the typical ST one. This change adds driver support for the new block, including usb console support. BUG=chromium:608039 TEST=usb console works BRANCH=None Change-Id: I0e143758ae0b5285f1c94ea2ec5aee159e22e00c Signed-off-by: Nick Sanders <nsanders@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/365448 Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
@@ -12,8 +12,36 @@
|
||||
#include "i2c.h"
|
||||
#include "registers.h"
|
||||
#include "stm32-dma.h"
|
||||
#include "usb_descriptor.h"
|
||||
#include "usb_dwc_hw.h"
|
||||
#include "usb_dwc_console.h"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Define the strings used in our USB descriptors.
|
||||
*/
|
||||
const void *const usb_strings[] = {
|
||||
[USB_STR_DESC] = usb_string_desc,
|
||||
[USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."),
|
||||
[USB_STR_PRODUCT] = USB_STRING_DESC("stm32f446-eval"),
|
||||
[USB_STR_SERIALNO] = USB_STRING_DESC("1234-a"),
|
||||
[USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32),
|
||||
[USB_STR_CONSOLE_NAME] = USB_STRING_DESC("EC Shell"),
|
||||
};
|
||||
|
||||
BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT);
|
||||
|
||||
struct dwc_usb usb_ctl = {
|
||||
.ep = {
|
||||
&ep0_ctl,
|
||||
&ep_console_ctl,
|
||||
},
|
||||
.speed = USB_SPEED_FS,
|
||||
.phy_type = USB_PHY_ULPI,
|
||||
.dma_en = 1,
|
||||
.irq = STM32_IRQ_OTG_HS,
|
||||
};
|
||||
|
||||
/* I2C ports */
|
||||
const struct i2c_port_t i2c_ports[] = {
|
||||
{"i2c1", I2C_PORT_0, 100,
|
||||
@@ -23,9 +51,8 @@ const struct i2c_port_t i2c_ports[] = {
|
||||
};
|
||||
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
|
||||
|
||||
|
||||
#define GPIO_SET_HS(bank, number) \
|
||||
(STM32_GPIO_OSPEEDR(GPIO_##bank) |= (0x3 << (number * 2)))
|
||||
(STM32_GPIO_OSPEEDR(GPIO_##bank) |= (0x3 << ((number) * 2)))
|
||||
|
||||
void board_config_post_gpio_init(void)
|
||||
{
|
||||
@@ -63,8 +90,3 @@ void board_config_post_gpio_init(void)
|
||||
GPIO_SET_HS(C, 7);
|
||||
}
|
||||
|
||||
static void board_init(void)
|
||||
{
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);
|
||||
|
||||
|
||||
@@ -11,9 +11,6 @@
|
||||
/* Use external clock */
|
||||
#define CONFIG_STM32_CLOCK_HSE_HZ 8000000
|
||||
|
||||
/* Optional features */
|
||||
#undef CONFIG_WATCHDOG_HELP
|
||||
#undef CONFIG_LID_SWITCH
|
||||
#define CONFIG_BOARD_POST_GPIO_INIT
|
||||
|
||||
/* Enable console recasting of GPIO type. */
|
||||
@@ -32,6 +29,25 @@
|
||||
#define I2C_PORT_0 0
|
||||
#define FMPI2C_PORT_3 3
|
||||
|
||||
/* USB Configuration */
|
||||
#define CONFIG_USB
|
||||
#define CONFIG_USB_PID 0x500f
|
||||
#define CONFIG_USB_CONSOLE
|
||||
|
||||
#define CONFIG_USB_SELF_POWERED
|
||||
|
||||
#define CONFIG_USB_SERIALNO
|
||||
#define DEFAULT_SERIALNO "Uninitialized"
|
||||
|
||||
/* USB interface indexes (use define rather than enum to expand them) */
|
||||
#define USB_IFACE_CONSOLE 0
|
||||
#define USB_IFACE_COUNT 1
|
||||
|
||||
/* USB endpoint indexes (use define rather than enum to expand them) */
|
||||
#define USB_EP_CONTROL 0
|
||||
#define USB_EP_CONSOLE 1
|
||||
#define USB_EP_COUNT 2
|
||||
|
||||
/* This is not actually an EC so disable some features. */
|
||||
#undef CONFIG_WATCHDOG_HELP
|
||||
#undef CONFIG_LID_SWITCH
|
||||
@@ -40,6 +56,7 @@
|
||||
/* Optional features */
|
||||
#define CONFIG_STM_HWTIMER32
|
||||
#define CONFIG_DMA_HELP
|
||||
#define CONFIG_FLASH
|
||||
|
||||
/*
|
||||
* Allow dangerous commands all the time, since we don't have a write protect
|
||||
@@ -48,12 +65,22 @@
|
||||
#define CONFIG_SYSTEM_UNLOCKED
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#undef CONFIG_FLASH
|
||||
|
||||
/* Timer selection */
|
||||
#define TIM_CLOCK32 5
|
||||
|
||||
#include "gpio_signal.h"
|
||||
|
||||
/* USB string indexes */
|
||||
enum usb_strings {
|
||||
USB_STR_DESC = 0,
|
||||
USB_STR_VENDOR,
|
||||
USB_STR_PRODUCT,
|
||||
USB_STR_SERIALNO,
|
||||
USB_STR_VERSION,
|
||||
USB_STR_CONSOLE_NAME,
|
||||
USB_STR_COUNT
|
||||
};
|
||||
|
||||
#endif /* !__ASSEMBLER__ */
|
||||
#endif /* __CROS_EC_BOARD_H */
|
||||
|
||||
@@ -14,7 +14,35 @@
|
||||
#include "registers.h"
|
||||
#include "stm32-dma.h"
|
||||
#include "task.h"
|
||||
#include "usb_descriptor.h"
|
||||
#include "util.h"
|
||||
#include "usb_dwc_hw.h"
|
||||
#include "usb_dwc_console.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Define the strings used in our USB descriptors.
|
||||
*/
|
||||
const void *const usb_strings[] = {
|
||||
[USB_STR_DESC] = usb_string_desc,
|
||||
[USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."),
|
||||
[USB_STR_PRODUCT] = USB_STRING_DESC("Sweetberry"),
|
||||
[USB_STR_SERIALNO] = USB_STRING_DESC("1234-a"),
|
||||
[USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32),
|
||||
[USB_STR_CONSOLE_NAME] = USB_STRING_DESC("Sweetberry EC Shell"),
|
||||
};
|
||||
|
||||
BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT);
|
||||
|
||||
struct dwc_usb usb_ctl = {
|
||||
.ep = {
|
||||
&ep0_ctl,
|
||||
&ep_console_ctl,
|
||||
},
|
||||
.speed = USB_SPEED_FS,
|
||||
.phy_type = USB_PHY_ULPI,
|
||||
.dma_en = 1,
|
||||
.irq = STM32_IRQ_OTG_HS,
|
||||
};
|
||||
|
||||
/* I2C ports */
|
||||
const struct i2c_port_t i2c_ports[] = {
|
||||
@@ -39,6 +67,11 @@ void board_config_post_gpio_init(void)
|
||||
/* GPIO PC9 to high speed */
|
||||
GPIO_SET_HS(C, 9);
|
||||
|
||||
if (usb_ctl.phy_type == USB_PHY_ULPI)
|
||||
gpio_set_level(GPIO_USB_MUX_SEL, 0);
|
||||
else
|
||||
gpio_set_level(GPIO_USB_MUX_SEL, 1);
|
||||
|
||||
/* Set USB GPIO to high speed */
|
||||
GPIO_SET_HS(A, 11);
|
||||
GPIO_SET_HS(A, 12);
|
||||
|
||||
@@ -36,6 +36,26 @@
|
||||
#define I2C_PORT_2 2
|
||||
#define FMPI2C_PORT_3 3
|
||||
|
||||
/* USB Configuration */
|
||||
#define CONFIG_USB
|
||||
#define CONFIG_USB_PID 0x5020
|
||||
#define CONFIG_USB_CONSOLE
|
||||
|
||||
#undef CONFIG_USB_MAXPOWER_MA
|
||||
#define CONFIG_USB_MAXPOWER_MA 100
|
||||
|
||||
#define CONFIG_USB_SERIALNO
|
||||
#define DEFAULT_SERIALNO "Uninitialized"
|
||||
|
||||
/* USB interface indexes (use define rather than enum to expand them) */
|
||||
#define USB_IFACE_CONSOLE 0
|
||||
#define USB_IFACE_COUNT 1
|
||||
|
||||
/* USB endpoint indexes (use define rather than enum to expand them) */
|
||||
#define USB_EP_CONTROL 0
|
||||
#define USB_EP_CONSOLE 1
|
||||
#define USB_EP_COUNT 2
|
||||
|
||||
/* This is not actually a Chromium EC so disable some features. */
|
||||
#undef CONFIG_WATCHDOG_HELP
|
||||
#undef CONFIG_LID_SWITCH
|
||||
@@ -57,5 +77,16 @@
|
||||
|
||||
#include "gpio_signal.h"
|
||||
|
||||
/* USB string indexes */
|
||||
enum usb_strings {
|
||||
USB_STR_DESC = 0,
|
||||
USB_STR_VENDOR,
|
||||
USB_STR_PRODUCT,
|
||||
USB_STR_SERIALNO,
|
||||
USB_STR_VERSION,
|
||||
USB_STR_CONSOLE_NAME,
|
||||
USB_STR_COUNT
|
||||
};
|
||||
|
||||
#endif /* !__ASSEMBLER__ */
|
||||
#endif /* __CROS_EC_BOARD_H */
|
||||
|
||||
@@ -43,7 +43,6 @@ chip-$(CONFIG_STREAM_USART)+=usart_rx_interrupt-$(CHIP_FAMILY).o
|
||||
chip-$(CONFIG_STREAM_USART)+=usart_tx_interrupt.o
|
||||
chip-$(CONFIG_STREAM_USART)+=usart_rx_dma.o usart_tx_dma.o
|
||||
chip-$(CONFIG_CMD_USART_INFO)+=usart_info_command.o
|
||||
chip-$(CONFIG_STREAM_USB)+=usb-stream.o
|
||||
chip-$(CONFIG_WATCHDOG)+=watchdog.o
|
||||
chip-$(HAS_TASK_CONSOLE)+=uart.o
|
||||
chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o
|
||||
@@ -57,6 +56,14 @@ chip-$(CONFIG_ADC)+=adc-$(CHIP_FAMILY).o
|
||||
chip-$(CONFIG_STM32_CHARGER_DETECT)+=charger_detect.o
|
||||
chip-$(CONFIG_DEBUG_PRINTF)+=debug_printf.o
|
||||
chip-$(CONFIG_PWM)+=pwm.o
|
||||
|
||||
ifeq ($(CHIP_FAMILY),stm32f4)
|
||||
chip-$(CONFIG_USB)+=usb_dwc.o usb_endpoints.o
|
||||
chip-$(CONFIG_USB_CONSOLE)+=usb_dwc_console.o
|
||||
chip-$(CONFIG_STREAM_USB)+=usb_dwc_stream.o
|
||||
chip-$(CONFIG_USB_I2C)+=usb_dwc_i2c.o
|
||||
else
|
||||
chip-$(CONFIG_STREAM_USB)+=usb-stream.o
|
||||
chip-$(CONFIG_USB)+=usb.o usb-$(CHIP_FAMILY).o usb_endpoints.o
|
||||
chip-$(CONFIG_USB_CONSOLE)+=usb_console.o
|
||||
chip-$(CONFIG_USB_GPIO)+=usb_gpio.o
|
||||
@@ -64,3 +71,4 @@ chip-$(CONFIG_USB_HID)+=usb_hid.o
|
||||
chip-$(CONFIG_USB_PD_TCPC)+=usb_pd_phy.o
|
||||
chip-$(CONFIG_USB_SPI)+=usb_spi.o
|
||||
chip-$(CONFIG_USB_I2C)+=usb_i2c.o
|
||||
endif
|
||||
|
||||
1230
chip/stm32/usb_dwc.c
Normal file
1230
chip/stm32/usb_dwc.c
Normal file
File diff suppressed because it is too large
Load Diff
363
chip/stm32/usb_dwc_console.c
Normal file
363
chip/stm32/usb_dwc_console.c
Normal file
@@ -0,0 +1,363 @@
|
||||
/* Copyright 2016 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 "common.h"
|
||||
#include "config.h"
|
||||
#include "console.h"
|
||||
#include "link_defs.h"
|
||||
#include "printf.h"
|
||||
#include "queue.h"
|
||||
#include "registers.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
#include "util.h"
|
||||
#include "usb_dwc_hw.h"
|
||||
#include "usb_descriptor.h"
|
||||
|
||||
/* Console output macro */
|
||||
#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args)
|
||||
#define USB_CONSOLE_TIMEOUT_US (30 * MSEC)
|
||||
|
||||
static int last_tx_ok = 1;
|
||||
|
||||
static int is_reset;
|
||||
static int is_enabled = 1;
|
||||
static int is_readonly;
|
||||
|
||||
/* USB-Serial descriptors */
|
||||
const struct usb_interface_descriptor USB_IFACE_DESC(USB_IFACE_CONSOLE) = {
|
||||
.bLength = USB_DT_INTERFACE_SIZE,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bInterfaceNumber = USB_IFACE_CONSOLE,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 2,
|
||||
.bInterfaceClass = USB_CLASS_VENDOR_SPEC,
|
||||
.bInterfaceSubClass = USB_SUBCLASS_GOOGLE_SERIAL,
|
||||
.bInterfaceProtocol = USB_PROTOCOL_GOOGLE_SERIAL,
|
||||
.iInterface = USB_STR_CONSOLE_NAME,
|
||||
};
|
||||
const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_CONSOLE, 0) = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x80 | USB_EP_CONSOLE,
|
||||
.bmAttributes = 0x02 /* Bulk IN */,
|
||||
.wMaxPacketSize = USB_MAX_PACKET_SIZE,
|
||||
.bInterval = 10
|
||||
};
|
||||
const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_CONSOLE, 1) = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = USB_EP_CONSOLE,
|
||||
.bmAttributes = 0x02 /* Bulk OUT */,
|
||||
.wMaxPacketSize = USB_MAX_PACKET_SIZE,
|
||||
.bInterval = 0
|
||||
};
|
||||
|
||||
static uint8_t ep_buf_tx[USB_MAX_PACKET_SIZE];
|
||||
static uint8_t ep_buf_rx[USB_MAX_PACKET_SIZE];
|
||||
|
||||
static struct queue const tx_q = QUEUE_NULL(256, uint8_t);
|
||||
static struct queue const rx_q = QUEUE_NULL(USB_MAX_PACKET_SIZE, uint8_t);
|
||||
|
||||
|
||||
struct dwc_usb_ep ep_console_ctl = {
|
||||
.max_packet = USB_MAX_PACKET_SIZE,
|
||||
.tx_fifo = USB_EP_CONSOLE,
|
||||
.out_pending = 0,
|
||||
.out_data = 0,
|
||||
.out_databuffer = ep_buf_tx,
|
||||
.out_databuffer_max = sizeof(ep_buf_tx),
|
||||
.in_packets = 0,
|
||||
.in_pending = 0,
|
||||
.in_data = 0,
|
||||
.in_databuffer = ep_buf_rx,
|
||||
.in_databuffer_max = sizeof(ep_buf_rx),
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Let the USB HW IN-to-host FIFO transmit some bytes */
|
||||
static void usb_enable_tx(int len)
|
||||
{
|
||||
struct dwc_usb_ep *ep = &ep_console_ctl;
|
||||
|
||||
ep->in_data = ep->in_databuffer;
|
||||
ep->in_packets = 1;
|
||||
ep->in_pending = len;
|
||||
|
||||
GR_USB_DIEPTSIZ(USB_EP_CONSOLE) = 0;
|
||||
|
||||
GR_USB_DIEPTSIZ(USB_EP_CONSOLE) |= DXEPTSIZ_PKTCNT(1);
|
||||
GR_USB_DIEPTSIZ(USB_EP_CONSOLE) |= DXEPTSIZ_XFERSIZE(len);
|
||||
GR_USB_DIEPDMA(USB_EP_CONSOLE) = (uint32_t)ep->in_data;
|
||||
|
||||
GR_USB_DIEPCTL(USB_EP_CONSOLE) |= DXEPCTL_CNAK | DXEPCTL_EPENA;
|
||||
}
|
||||
|
||||
/* Let the USB HW OUT-from-host FIFO receive some bytes */
|
||||
static void usb_enable_rx(int len)
|
||||
{
|
||||
struct dwc_usb_ep *ep = &ep_console_ctl;
|
||||
|
||||
ep->out_data = ep->out_databuffer;
|
||||
ep->out_pending = 0;
|
||||
|
||||
GR_USB_DOEPTSIZ(USB_EP_CONSOLE) = 0;
|
||||
GR_USB_DOEPTSIZ(USB_EP_CONSOLE) |= DXEPTSIZ_PKTCNT(1);
|
||||
GR_USB_DOEPTSIZ(USB_EP_CONSOLE) |= DXEPTSIZ_XFERSIZE(len);
|
||||
GR_USB_DOEPDMA(USB_EP_CONSOLE) = (uint32_t)ep->out_data;
|
||||
|
||||
GR_USB_DOEPCTL(USB_EP_CONSOLE) |= DXEPCTL_CNAK | DXEPCTL_EPENA;
|
||||
}
|
||||
|
||||
/* True if the HW Rx/OUT FIFO has bytes for us. */
|
||||
static inline int rx_fifo_is_ready(void)
|
||||
{
|
||||
struct dwc_usb_ep *ep = &ep_console_ctl;
|
||||
|
||||
return ep->out_pending;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function tries to shove new bytes from the USB host into the queue for
|
||||
* consumption elsewhere. It is invoked either by a HW interrupt (telling us we
|
||||
* have new bytes from the USB host), or by whoever is reading bytes out of the
|
||||
* other end of the queue (telling us that there's now more room in the queue
|
||||
* if we still have bytes to shove in there).
|
||||
*/
|
||||
char buffer[65];
|
||||
static void rx_fifo_handler(void)
|
||||
{
|
||||
struct dwc_usb_ep *ep = &ep_console_ctl;
|
||||
|
||||
int rx_in_fifo;
|
||||
size_t added;
|
||||
|
||||
if (!rx_fifo_is_ready())
|
||||
return;
|
||||
|
||||
rx_in_fifo = ep->out_pending;
|
||||
added = QUEUE_ADD_UNITS(&rx_q, ep->out_databuffer, rx_in_fifo);
|
||||
|
||||
if (added != rx_in_fifo)
|
||||
CPRINTF("DROP CONSOLE: %d/%d process\n", added, rx_in_fifo);
|
||||
|
||||
/* wake-up the console task */
|
||||
console_has_input();
|
||||
|
||||
usb_enable_rx(USB_MAX_PACKET_SIZE);
|
||||
}
|
||||
DECLARE_DEFERRED(rx_fifo_handler);
|
||||
|
||||
/* Rx/OUT interrupt handler */
|
||||
static void con_ep_rx(void)
|
||||
{
|
||||
struct dwc_usb_ep *ep = &ep_console_ctl;
|
||||
|
||||
if (GR_USB_DOEPCTL(USB_EP_CONSOLE) & DXEPCTL_EPENA)
|
||||
return;
|
||||
|
||||
/* Bytes received decrement DOEPTSIZ XFERSIZE */
|
||||
if (GR_USB_DOEPINT(USB_EP_CONSOLE) & DOEPINT_XFERCOMPL) {
|
||||
ep->out_pending =
|
||||
ep->max_packet -
|
||||
(GR_USB_DOEPTSIZ(USB_EP_CONSOLE) &
|
||||
GC_USB_DOEPTSIZ1_XFERSIZE_MASK);
|
||||
}
|
||||
|
||||
/* Wake up the Rx FIFO handler */
|
||||
hook_call_deferred(&rx_fifo_handler_data, 0);
|
||||
|
||||
/* clear the RX/OUT interrupts */
|
||||
GR_USB_DOEPINT(USB_EP_CONSOLE) = 0xffffffff;
|
||||
}
|
||||
|
||||
/* True if the Tx/IN FIFO can take some bytes from us. */
|
||||
static inline int tx_fifo_is_ready(void)
|
||||
{
|
||||
return !(GR_USB_DIEPCTL(USB_EP_CONSOLE) & DXEPCTL_EPENA);
|
||||
}
|
||||
|
||||
/* Try to send some bytes to the host */
|
||||
static void tx_fifo_handler(void)
|
||||
{
|
||||
struct dwc_usb_ep *ep = &ep_console_ctl;
|
||||
size_t count;
|
||||
|
||||
if (!is_reset)
|
||||
return;
|
||||
|
||||
/* If the HW FIFO isn't ready, then we can't do anything right now. */
|
||||
if (!tx_fifo_is_ready())
|
||||
return;
|
||||
|
||||
count = QUEUE_REMOVE_UNITS(&tx_q,
|
||||
ep->in_databuffer, USB_MAX_PACKET_SIZE);
|
||||
if (count)
|
||||
usb_enable_tx(count);
|
||||
}
|
||||
DECLARE_DEFERRED(tx_fifo_handler);
|
||||
|
||||
static void handle_output(void)
|
||||
{
|
||||
/* Wake up the Tx FIFO handler */
|
||||
hook_call_deferred(&tx_fifo_handler_data, 0);
|
||||
}
|
||||
|
||||
/* Tx/IN interrupt handler */
|
||||
static void con_ep_tx(void)
|
||||
{
|
||||
/* Wake up the Tx FIFO handler */
|
||||
hook_call_deferred(&tx_fifo_handler_data, 0);
|
||||
|
||||
/* clear the Tx/IN interrupts */
|
||||
GR_USB_DIEPINT(USB_EP_CONSOLE) = 0xffffffff;
|
||||
}
|
||||
|
||||
static void ep_reset(void)
|
||||
{
|
||||
GR_USB_DOEPCTL(USB_EP_CONSOLE) = DXEPCTL_MPS(USB_MAX_PACKET_SIZE) |
|
||||
DXEPCTL_USBACTEP | DXEPCTL_EPTYPE_BULK |
|
||||
DXEPCTL_CNAK | DXEPCTL_EPENA;
|
||||
GR_USB_DIEPCTL(USB_EP_CONSOLE) = DXEPCTL_MPS(USB_MAX_PACKET_SIZE) |
|
||||
DXEPCTL_USBACTEP | DXEPCTL_EPTYPE_BULK |
|
||||
DXEPCTL_TXFNUM(USB_EP_CONSOLE);
|
||||
GR_USB_DAINTMSK |= DAINT_INEP(USB_EP_CONSOLE) |
|
||||
DAINT_OUTEP(USB_EP_CONSOLE);
|
||||
is_reset = 1;
|
||||
|
||||
/* Flush any queued data */
|
||||
hook_call_deferred(&tx_fifo_handler_data, 0);
|
||||
hook_call_deferred(&rx_fifo_handler_data, 0);
|
||||
|
||||
usb_enable_rx(USB_MAX_PACKET_SIZE);
|
||||
}
|
||||
|
||||
|
||||
USB_DECLARE_EP(USB_EP_CONSOLE, con_ep_tx, con_ep_rx, ep_reset);
|
||||
|
||||
static int usb_wait_console(void)
|
||||
{
|
||||
timestamp_t deadline = get_time();
|
||||
int wait_time_us = 1;
|
||||
|
||||
if (!is_enabled || !tx_fifo_is_ready())
|
||||
return EC_SUCCESS;
|
||||
|
||||
deadline.val += USB_CONSOLE_TIMEOUT_US;
|
||||
|
||||
/*
|
||||
* If the USB console is not used, Tx buffer would never free up.
|
||||
* In this case, let's drop characters immediately instead of sitting
|
||||
* for some time just to time out. On the other hand, if the last
|
||||
* Tx is good, it's likely the host is there to receive data, and
|
||||
* we should wait so that we don't clobber the buffer.
|
||||
*/
|
||||
if (last_tx_ok) {
|
||||
while (queue_space(&tx_q) < USB_MAX_PACKET_SIZE || !is_reset) {
|
||||
if (timestamp_expired(deadline, NULL) ||
|
||||
in_interrupt_context()) {
|
||||
last_tx_ok = 0;
|
||||
return EC_ERROR_TIMEOUT;
|
||||
}
|
||||
if (wait_time_us < MSEC)
|
||||
udelay(wait_time_us);
|
||||
else
|
||||
usleep(wait_time_us);
|
||||
wait_time_us *= 2;
|
||||
}
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
last_tx_ok = queue_space(&tx_q);
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
static int __tx_char(void *context, int c)
|
||||
{
|
||||
struct queue *state =
|
||||
(struct queue *) context;
|
||||
|
||||
if (c == '\n' && __tx_char(state, '\r'))
|
||||
return 1;
|
||||
|
||||
QUEUE_ADD_UNITS(state, &c, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Public USB console implementation below.
|
||||
*/
|
||||
int usb_getc(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (!is_enabled)
|
||||
return -1;
|
||||
|
||||
if (QUEUE_REMOVE_UNITS(&rx_q, &c, 1))
|
||||
return c;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int usb_puts(const char *outstr)
|
||||
{
|
||||
int ret;
|
||||
struct queue state;
|
||||
|
||||
if (is_readonly)
|
||||
return EC_SUCCESS;
|
||||
|
||||
ret = usb_wait_console();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
state = tx_q;
|
||||
while (*outstr)
|
||||
if (__tx_char(&state, *outstr++))
|
||||
break;
|
||||
|
||||
if (queue_count(&state))
|
||||
handle_output();
|
||||
|
||||
return *outstr ? EC_ERROR_OVERFLOW : EC_SUCCESS;
|
||||
}
|
||||
|
||||
int usb_putc(int c)
|
||||
{
|
||||
char string[2];
|
||||
|
||||
string[0] = c;
|
||||
string[1] = '\0';
|
||||
return usb_puts(string);
|
||||
}
|
||||
|
||||
int usb_vprintf(const char *format, va_list args)
|
||||
{
|
||||
int ret;
|
||||
struct queue state;
|
||||
|
||||
if (is_readonly)
|
||||
return EC_SUCCESS;
|
||||
|
||||
ret = usb_wait_console();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
state = tx_q;
|
||||
ret = vfnprintf(__tx_char, &state, format, args);
|
||||
|
||||
if (queue_count(&state))
|
||||
handle_output();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usb_console_enable(int enabled, int readonly)
|
||||
{
|
||||
is_enabled = enabled;
|
||||
is_readonly = readonly;
|
||||
}
|
||||
13
chip/stm32/usb_dwc_console.h
Normal file
13
chip/stm32/usb_dwc_console.h
Normal file
@@ -0,0 +1,13 @@
|
||||
/* Copyright 2016 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.
|
||||
*/
|
||||
|
||||
#ifndef __CHIP_STM32_USB_DWC_CONSOLE_H
|
||||
#define __CHIP_STM32_USB_DWC_CONSOLE_H
|
||||
|
||||
#include "usb_dwc_hw.h"
|
||||
|
||||
extern struct dwc_usb_ep ep_console_ctl;
|
||||
|
||||
#endif /* __CHIP_STM32_USB_DWC_CONSOLE_H */
|
||||
45
chip/stm32/usb_dwc_hw.h
Normal file
45
chip/stm32/usb_dwc_hw.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* Copyright 2016 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.
|
||||
*/
|
||||
|
||||
#ifndef __CROS_EC_USB_DWC_HW_H
|
||||
#define __CROS_EC_USB_DWC_HW_H
|
||||
|
||||
#include "usb_dwc_registers.h"
|
||||
|
||||
/* Helpers for endpoint declaration */
|
||||
#define _EP_HANDLER2(num, suffix) CONCAT3(ep_, num, suffix)
|
||||
#define _EP_TX_HANDLER(num) _EP_HANDLER2(num, _tx)
|
||||
#define _EP_RX_HANDLER(num) _EP_HANDLER2(num, _rx)
|
||||
#define _EP_RESET_HANDLER(num) _EP_HANDLER2(num, _rst)
|
||||
|
||||
#define USB_DECLARE_EP(num, tx_handler, rx_handler, rst_handler) \
|
||||
void _EP_TX_HANDLER(num)(void) \
|
||||
__attribute__ ((alias(STRINGIFY(tx_handler)))); \
|
||||
void _EP_RX_HANDLER(num)(void) \
|
||||
__attribute__ ((alias(STRINGIFY(rx_handler)))); \
|
||||
void _EP_RESET_HANDLER(num)(void) \
|
||||
__attribute__ ((alias(STRINGIFY(rst_handler))))
|
||||
|
||||
/* Endpoint callbacks */
|
||||
extern void (*usb_ep_tx[]) (void);
|
||||
extern void (*usb_ep_rx[]) (void);
|
||||
extern void (*usb_ep_reset[]) (void);
|
||||
struct usb_setup_packet;
|
||||
/* EP0 Interface handler callbacks */
|
||||
static int (*usb_iface_request[]) (struct usb_setup_packet *req);
|
||||
|
||||
/*
|
||||
* Declare any interface-specific control request handlers. These Setup packets
|
||||
* arrive on the control endpoint (EP0), but are handled by the interface code.
|
||||
* The callback must prepare the EP0 IN or OUT FIFOs and return the number of
|
||||
* bytes placed in the IN FIFO. A negative return value will STALL the response
|
||||
* (and thus indicate error to the host).
|
||||
*/
|
||||
#define _IFACE_HANDLER(num) CONCAT3(iface_, num, _request)
|
||||
#define USB_DECLARE_IFACE(num, handler) \
|
||||
int _IFACE_HANDLER(num)(struct usb_setup_packet *req) \
|
||||
__attribute__ ((alias(STRINGIFY(handler))))
|
||||
|
||||
#endif /* __CROS_EC_USB_DWC_HW_H */
|
||||
7530
chip/stm32/usb_dwc_registers.h
Normal file
7530
chip/stm32/usb_dwc_registers.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,11 @@
|
||||
#ifndef __CROS_EC_USB_HW_H
|
||||
#define __CROS_EC_USB_HW_H
|
||||
|
||||
#if defined(CHIP_FAMILY_STM32F4)
|
||||
#include "usb_dwc_hw.h"
|
||||
#else
|
||||
|
||||
|
||||
/*
|
||||
* The STM32 has dedicated USB RAM visible on the APB1 bus (so all reads &
|
||||
* writes are 16-bits wide). The endpoint tables and the data buffers live in
|
||||
@@ -82,4 +87,5 @@ extern int (*usb_iface_request[]) (usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx);
|
||||
usb_uint *epo_buf_tx) \
|
||||
__attribute__ ((alias(STRINGIFY(handler))));
|
||||
|
||||
#endif
|
||||
#endif /* __CROS_EC_USB_HW_H */
|
||||
|
||||
@@ -2174,6 +2174,12 @@
|
||||
#undef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* stm32f4 dwc usb configs. */
|
||||
|
||||
/* Set USB speed to FS rather than HS */
|
||||
#undef CONFIG_USB_DWC_FS
|
||||
|
||||
/******************************************************************************/
|
||||
/* USB port switch */
|
||||
|
||||
|
||||
@@ -89,6 +89,20 @@ struct usb_contid_caps_descriptor {
|
||||
#define USB_DC_DTYPE_BILLBOARD 0x0d
|
||||
/* RESERVED 0x00, 0xOe - 0xff */
|
||||
|
||||
/* Qualifier Descriptor */
|
||||
struct usb_qualifier_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t bcdUSB;
|
||||
uint8_t bDeviceClass;
|
||||
uint8_t bDeviceSubClass;
|
||||
uint8_t bDeviceProtocol;
|
||||
uint8_t bMaxPacketSize0;
|
||||
uint8_t bNumConfigurations;
|
||||
uint8_t bReserved;
|
||||
} __packed;
|
||||
#define USB_DT_QUALIFIER_SIZE 10
|
||||
|
||||
/* Configuration Descriptor */
|
||||
struct usb_config_descriptor {
|
||||
uint8_t bLength;
|
||||
|
||||
Reference in New Issue
Block a user