summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMary Ruthven <mruthven@chromium.org>2016-03-30 10:27:58 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-04-07 13:00:39 -0700
commitfa643a9fc754e6a5c18181ecb928fa9a5c12e7ae (patch)
tree25419df8ec4a379f9eb9fc1108422625299102ca
parent55032aa1236dc4f85485147f5927cfaf513def98 (diff)
downloadchrome-ec-fa643a9fc754e6a5c18181ecb928fa9a5c12e7ae.tar.gz
cr50: add support for creating multiple serial endpoints
CR50 will need three serial endpoints for the streaming AP and EC UART and exporting its own console through USB. This change adds a macro to create endpoints that can be recognized by the usb_serial driver. BUG=chrome-os-partner:50702 BRANCH=none TEST=Verify "/dev/google/Cr50*/serial/Blob" prints capital letters when lower case letters are input. Change-Id: Iddf2c957a00dc3cd5448a6a00de2cf61ef5dd84c Signed-off-by: Mary Ruthven <mruthven@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/336441 Tested-by: Bill Richardson <wfrichar@chromium.org> Reviewed-by: Bill Richardson <wfrichar@chromium.org>
-rw-r--r--board/cr50/board.h2
-rw-r--r--board/cr50/ec.tasklist1
-rw-r--r--chip/g/blob.c74
-rw-r--r--chip/g/build.mk3
-rw-r--r--chip/g/usb-stream.c191
-rw-r--r--chip/g/usb-stream.h192
-rw-r--r--chip/g/usb_blob.c218
-rw-r--r--common/blob.c113
-rw-r--r--common/build.mk1
-rw-r--r--include/blob.h26
10 files changed, 461 insertions, 360 deletions
diff --git a/board/cr50/board.h b/board/cr50/board.h
index 9fde91dca2..83a370b23e 100644
--- a/board/cr50/board.h
+++ b/board/cr50/board.h
@@ -29,6 +29,8 @@
#define CONFIG_USB_HID
#define CONFIG_USB_BLOB
+#define CONFIG_STREAM_USB
+
#define CONFIG_USB_PID 0x5014
/* Enable SPI Slave (SPS) module */
diff --git a/board/cr50/ec.tasklist b/board/cr50/ec.tasklist
index 52f4af3000..c350701b65 100644
--- a/board/cr50/ec.tasklist
+++ b/board/cr50/ec.tasklist
@@ -18,7 +18,6 @@
*/
#define CONFIG_TASK_LIST \
TASK_ALWAYS(HOOKS, hook_task, NULL, TASK_STACK_SIZE) \
- TASK_ALWAYS(BLOB, blob_task, NULL, TASK_STACK_SIZE) \
TASK_NOTEST(TPM, tpm_task, NULL, 8192) \
TASK_NOTEST(HOSTCMD, host_command_task, NULL, TASK_STACK_SIZE) \
TASK_ALWAYS(CONSOLE, console_task, NULL, TASK_STACK_SIZE)
diff --git a/chip/g/blob.c b/chip/g/blob.c
new file mode 100644
index 0000000000..fde66aac9a
--- /dev/null
+++ b/chip/g/blob.c
@@ -0,0 +1,74 @@
+/* Copyright 2015 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.
+ */
+
+/* Handle an opaque blob of data */
+
+#include "common.h"
+#include "console.h"
+#include "consumer.h"
+#include "queue.h"
+#include "queue_policies.h"
+#include "producer.h"
+#include "task.h"
+#include "usb-stream.h"
+
+#define CPRINTS(format, args...) cprints(CC_USB, format, ## args)
+
+struct consumer const blob_consumer;
+struct usb_stream_config const usb_blob;
+
+static struct queue const blob_to_usb = QUEUE_DIRECT(64, uint8_t,
+ null_producer,
+ usb_blob.consumer);
+static struct queue const usb_to_blob = QUEUE_DIRECT(64, uint8_t,
+ usb_blob.producer,
+ blob_consumer);
+
+USB_STREAM_CONFIG(usb_blob,
+ USB_IFACE_BLOB,
+ USB_STR_BLOB_NAME,
+ USB_EP_BLOB,
+ USB_MAX_PACKET_SIZE,
+ USB_MAX_PACKET_SIZE,
+ usb_to_blob,
+ blob_to_usb)
+
+static void blob_written(struct consumer const *consumer, size_t count)
+{
+ int i;
+ uint8_t buf[USB_MAX_PACKET_SIZE];
+
+ count = QUEUE_REMOVE_UNITS(consumer->queue, buf, count);
+
+ CPRINTS("Received: count=%d buf=((%s))", count, buf);
+
+ /*
+ * Just to have something to test to begin with, we'll
+ * implement "tr a-zA-Z A-Za-z" and return the result.
+ */
+ for (i = 0; i < count; i++) {
+ char tmp = buf[i];
+
+ if (tmp >= 'a' && tmp <= 'z')
+ buf[i] = tmp - ('a' - 'A');
+ else if (tmp >= 'A' && tmp <= 'Z')
+ buf[i] = tmp + ('a' - 'A');
+ }
+
+ count = QUEUE_ADD_UNITS(&blob_to_usb, buf, count);
+ CPRINTS("Sending: count=%d buf=((%s))", count, buf);
+}
+
+static void blob_flush(struct consumer const *consumer)
+{
+}
+
+struct consumer const blob_consumer = {
+ .queue = &usb_to_blob,
+ .ops = &((struct consumer_ops const) {
+ .written = blob_written,
+ .flush = blob_flush,
+ }),
+};
diff --git a/chip/g/build.mk b/chip/g/build.mk
index a98f2e3e8f..e3f283c97f 100644
--- a/chip/g/build.mk
+++ b/chip/g/build.mk
@@ -47,7 +47,8 @@ chip-$(CONFIG_WATCHDOG)+=watchdog.o
chip-$(CONFIG_USB)+=usb.o usb_endpoints.o
chip-$(CONFIG_USB_CONSOLE)+=usb_console.o
chip-$(CONFIG_USB_HID)+=usb_hid.o
-chip-$(CONFIG_USB_BLOB)+=usb_blob.o
+chip-$(CONFIG_USB_BLOB)+=blob.o
+chip-$(CONFIG_STREAM_USB)+=usb-stream.o
chip-$(CONFIG_LOW_POWER_IDLE)+=idle.o
diff --git a/chip/g/usb-stream.c b/chip/g/usb-stream.c
new file mode 100644
index 0000000000..21a06c94e3
--- /dev/null
+++ b/chip/g/usb-stream.c
@@ -0,0 +1,191 @@
+/* Copyright 2015 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 "registers.h"
+#include "usb-stream.h"
+
+/* Let the USB HW IN-to-host FIFO transmit some bytes */
+static void usb_enable_tx(struct usb_stream_config const *config, int len)
+{
+ config->in_desc->flags = DIEPDMA_LAST | DIEPDMA_BS_HOST_RDY |
+ DIEPDMA_IOC | DIEPDMA_TXBYTES(len);
+ GR_USB_DIEPCTL(config->endpoint) |= DXEPCTL_CNAK | DXEPCTL_EPENA;
+}
+
+/* Let the USB HW OUT-from-host FIFO receive some bytes */
+static void usb_enable_rx(struct usb_stream_config const *config, int len)
+{
+ config->out_desc->flags = DOEPDMA_RXBYTES(len) | DOEPDMA_LAST |
+ DOEPDMA_BS_HOST_RDY | DOEPDMA_IOC;
+ GR_USB_DOEPCTL(config->endpoint) |= DXEPCTL_CNAK | DXEPCTL_EPENA;
+}
+
+/* True if the HW Rx/OUT FIFO has bytes for us. */
+static inline int rx_fifo_is_ready(struct usb_stream_config const *config)
+{
+ return (config->out_desc->flags & DOEPDMA_BS_MASK) ==
+ DOEPDMA_BS_DMA_DONE;
+}
+
+/*
+ * 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).
+ */
+int rx_stream_handler(struct usb_stream_config const *config)
+{
+ /*
+ * The HW FIFO buffer (rx_ram) is always filled from [0] by the
+ * hardware. The rx_in_fifo variable counts how many bytes of that
+ * buffer are actually valid, and is calculated from the HW DMA
+ * descriptor table. The descriptor is updated by the hardware, and it
+ * and rx_ram remains valid and unchanged until software tells the
+ * the hardware engine to accept more input.
+ */
+ int rx_in_fifo, rx_left;
+
+ /*
+ * The rx_handled variable tracks how many of the bytes in the HW FIFO
+ * we've copied into the incoming queue. The queue may not accept all
+ * of them at once, so we have to keep track of where we are so that
+ * the next time this function is called we can try to shove the rest
+ * of the HW FIFO bytes into the queue.
+ */
+ static int rx_handled;
+
+ /*
+ * How many of the HW FIFO bytes have we not yet handled? We need to
+ * know both where we are in the buffer and how many bytes we haven't
+ * yet enqueued. One can be calculated from the other as long as we
+ * know rx_in_fifo, but we need at least one static variable.
+ */
+ rx_in_fifo = config->rx_size
+ - (config->out_desc->flags & DOEPDMA_RXBYTES_MASK);
+ rx_left = rx_in_fifo - rx_handled;
+
+ /* If we have some, try to shove them into the queue */
+ if (rx_left) {
+ size_t added = QUEUE_ADD_UNITS(
+ config->producer.queue, config->rx_ram + rx_handled,
+ rx_left);
+ rx_handled += added;
+ rx_left -= added;
+ }
+
+ /*
+ * When we've handled all the bytes in the queue ("rx_in_fifo ==
+ * rx_handled" and "rx_left == 0" indicate the same thing), we can
+ * reenable the USB HW to go fetch more.
+ */
+ if (!rx_left) {
+ rx_handled = 0;
+ usb_enable_rx(config, config->rx_size);
+ }
+ return rx_handled;
+}
+
+/* Rx/OUT interrupt handler */
+void usb_stream_rx(struct usb_stream_config const *config)
+{
+ /* Wake up the Rx FIFO handler */
+ hook_call_deferred(config->deferred_rx, 0);
+
+ GR_USB_DOEPINT(config->endpoint) = 0xffffffff;
+}
+
+/* True if the Tx/IN FIFO can take some bytes from us. */
+static inline int tx_fifo_is_ready(struct usb_stream_config const *config)
+{
+ uint32_t status = config->in_desc->flags & DIEPDMA_BS_MASK;
+ return status == DIEPDMA_BS_DMA_DONE || status == DIEPDMA_BS_HOST_BSY;
+}
+
+/* Try to send some bytes to the host */
+int tx_stream_handler(struct usb_stream_config const *config)
+{
+ size_t count;
+
+ if (!*config->is_reset)
+ return 0;
+
+ count = QUEUE_REMOVE_UNITS(config->consumer.queue, config->tx_ram,
+ config->tx_size);
+ if (count)
+ usb_enable_tx(config, count);
+ return count;
+}
+
+/* Tx/IN interrupt handler */
+void usb_stream_tx(struct usb_stream_config const *config)
+{
+ /* Wake up the Tx FIFO handler */
+ hook_call_deferred(config->deferred_tx, 0);
+
+ /* clear the Tx/IN interrupts */
+ GR_USB_DIEPINT(config->endpoint) = 0xffffffff;
+}
+
+void usb_stream_reset(struct usb_stream_config const *config)
+{
+ config->out_desc->flags = DOEPDMA_RXBYTES(config->tx_size) |
+ DOEPDMA_LAST | DOEPDMA_BS_HOST_RDY |
+ DOEPDMA_IOC;
+ config->out_desc->addr = config->rx_ram;
+ GR_USB_DOEPDMA(config->endpoint) = (uint32_t)config->out_desc;
+ config->in_desc->flags = DIEPDMA_LAST | DIEPDMA_BS_HOST_BSY |
+ DIEPDMA_IOC;
+ config->in_desc->addr = config->tx_ram;
+ GR_USB_DIEPDMA(config->endpoint) = (uint32_t)config->in_desc;
+ GR_USB_DOEPCTL(config->endpoint) = DXEPCTL_MPS(64) | DXEPCTL_USBACTEP |
+ DXEPCTL_EPTYPE_BULK |
+ DXEPCTL_CNAK | DXEPCTL_EPENA;
+ GR_USB_DIEPCTL(config->endpoint) = DXEPCTL_MPS(64) | DXEPCTL_USBACTEP |
+ DXEPCTL_EPTYPE_BULK |
+ DXEPCTL_TXFNUM(config->endpoint);
+ GR_USB_DAINTMSK |= DAINT_INEP(config->endpoint) |
+ DAINT_OUTEP(config->endpoint);
+
+ *config->is_reset = 1;
+
+ /* Flush any queued data */
+ hook_call_deferred(config->deferred_tx, 0);
+ hook_call_deferred(config->deferred_rx, 0);
+}
+
+static void usb_read(struct producer const *producer, size_t count)
+{
+ struct usb_stream_config const *config =
+ DOWNCAST(producer, struct usb_stream_config, producer);
+
+ hook_call_deferred(config->deferred_rx, 0);
+}
+
+static void usb_written(struct consumer const *consumer, size_t count)
+{
+ struct usb_stream_config const *config =
+ DOWNCAST(consumer, struct usb_stream_config, consumer);
+
+ hook_call_deferred(config->deferred_tx, 0);
+}
+
+static void usb_flush(struct consumer const *consumer)
+{
+ struct usb_stream_config const *config =
+ DOWNCAST(consumer, struct usb_stream_config, consumer);
+
+ while (tx_fifo_is_ready(config) && queue_count(consumer->queue))
+ ;
+}
+
+struct producer_ops const usb_stream_producer_ops = {
+ .read = usb_read,
+};
+
+struct consumer_ops const usb_stream_consumer_ops = {
+ .written = usb_written,
+ .flush = usb_flush,
+};
diff --git a/chip/g/usb-stream.h b/chip/g/usb-stream.h
new file mode 100644
index 0000000000..761065d8b6
--- /dev/null
+++ b/chip/g/usb-stream.h
@@ -0,0 +1,192 @@
+/* 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_STREAM_H
+#define __CROS_EC_USB_STREAM_H
+
+/* USB STREAM driver for Chrome EC */
+
+#include "compile_time_macros.h"
+#include "consumer.h"
+#include "hooks.h"
+#include "registers.h"
+#include "producer.h"
+#include "queue.h"
+#include "usb_descriptor.h"
+
+/*
+ * Compile time Per-USB stream configuration stored in flash. Instances of this
+ * structure are provided by the user of the USB stream. This structure binds
+ * together all information required to operate a USB stream.
+ */
+struct usb_stream_config {
+ /*
+ * Endpoint index, and pointers to the USB packet RAM buffers.
+ */
+ int endpoint;
+
+ int *is_reset;
+
+ /*
+ * Deferred function to call to handle USB and Queue request.
+ */
+ void (*deferred_tx)(void);
+ void (*deferred_rx)(void);
+
+ int tx_size;
+ int rx_size;
+
+ uint8_t *tx_ram;
+ uint8_t *rx_ram;
+
+ struct consumer consumer;
+ struct producer producer;
+
+ struct g_usb_desc *out_desc;
+ struct g_usb_desc *in_desc;
+};
+
+/*
+ * These function tables are defined by the USB Stream driver and are used to
+ * initialize the consumer and producer in the usb_stream_config.
+ */
+extern struct consumer_ops const usb_stream_consumer_ops;
+extern struct producer_ops const usb_stream_producer_ops;
+
+
+/*
+ * Convenience macro for defining USB streams and their associated state and
+ * buffers.
+ *
+ * NAME is used to construct the names of the packet RAM buffers, trampoline
+ * functions, usb_stream_state struct, and usb_stream_config struct, the
+ * latter is just called NAME.
+ *
+ * INTERFACE is the index of the USB interface to associate with this
+ * stream.
+ *
+ * INTERFACE_NAME is the index of the USB string descriptor (iInterface).
+ *
+ * ENDPOINT is the index of the USB bulk endpoint used for receiving and
+ * transmitting bytes.
+ *
+ * RX_SIZE and TX_SIZE are the number of bytes of USB packet RAM to allocate
+ * for the RX and TX packets respectively. The valid values for these
+ * parameters are dictated by the USB peripheral.
+ *
+ * RX_QUEUE and TX_QUEUE are the names of the RX and TX queues that this driver
+ * should write to and read from respectively.
+ */
+/*
+ * The following assertions can not be made because they require access to
+ * non-const fields, but should be kept in mind.
+ *
+ * BUILD_ASSERT(RX_QUEUE.buffer_units >= RX_SIZE);
+ * BUILD_ASSERT(TX_QUEUE.buffer_units >= TX_SIZE);
+ * BUILD_ASSERT(RX_QUEUE.unit_bytes == 1);
+ * BUILD_ASSERT(TX_QUEUE.unit_bytes == 1);
+ */
+#define USB_STREAM_CONFIG(NAME, \
+ INTERFACE, \
+ INTERFACE_NAME, \
+ ENDPOINT, \
+ RX_SIZE, \
+ TX_SIZE, \
+ RX_QUEUE, \
+ TX_QUEUE) \
+ \
+ static struct g_usb_desc CONCAT2(NAME, _out_desc_); \
+ static struct g_usb_desc CONCAT2(NAME, _in_desc_); \
+ static uint8_t CONCAT2(NAME, _buf_rx_)[RX_SIZE]; \
+ static uint8_t CONCAT2(NAME, _buf_tx_)[TX_SIZE]; \
+ static int CONCAT2(NAME, _is_reset_); \
+ static void CONCAT2(NAME, _deferred_tx_)(void); \
+ static void CONCAT2(NAME, _deferred_rx_)(void); \
+ struct usb_stream_config const NAME = { \
+ .endpoint = ENDPOINT, \
+ .is_reset = &CONCAT2(NAME, _is_reset_), \
+ .in_desc = &CONCAT2(NAME, _in_desc_), \
+ .out_desc = &CONCAT2(NAME, _out_desc_), \
+ .deferred_tx = CONCAT2(NAME, _deferred_tx_), \
+ .deferred_rx = CONCAT2(NAME, _deferred_rx_), \
+ .tx_size = TX_SIZE, \
+ .rx_size = RX_SIZE, \
+ .tx_ram = CONCAT2(NAME, _buf_tx_), \
+ .rx_ram = CONCAT2(NAME, _buf_rx_), \
+ .consumer = { \
+ .queue = &TX_QUEUE, \
+ .ops = &usb_stream_consumer_ops, \
+ }, \
+ .producer = { \
+ .queue = &RX_QUEUE, \
+ .ops = &usb_stream_producer_ops, \
+ }, \
+ }; \
+ const struct usb_interface_descriptor \
+ USB_IFACE_DESC(INTERFACE) = { \
+ .bLength = USB_DT_INTERFACE_SIZE, \
+ .bDescriptorType = USB_DT_INTERFACE, \
+ .bInterfaceNumber = INTERFACE, \
+ .bAlternateSetting = 0, \
+ .bNumEndpoints = 2, \
+ .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
+ .bInterfaceSubClass = USB_SUBCLASS_GOOGLE_SERIAL, \
+ .bInterfaceProtocol = USB_PROTOCOL_GOOGLE_SERIAL, \
+ .iInterface = INTERFACE_NAME, \
+ }; \
+ const struct usb_endpoint_descriptor \
+ USB_EP_DESC(INTERFACE, 0) = { \
+ .bLength = USB_DT_ENDPOINT_SIZE, \
+ .bDescriptorType = USB_DT_ENDPOINT, \
+ .bEndpointAddress = 0x80 | ENDPOINT, \
+ .bmAttributes = 0x02 /* Bulk IN */, \
+ .wMaxPacketSize = TX_SIZE, \
+ .bInterval = 10, \
+ }; \
+ const struct usb_endpoint_descriptor \
+ USB_EP_DESC(INTERFACE, 1) = { \
+ .bLength = USB_DT_ENDPOINT_SIZE, \
+ .bDescriptorType = USB_DT_ENDPOINT, \
+ .bEndpointAddress = ENDPOINT, \
+ .bmAttributes = 0x02 /* Bulk OUT */, \
+ .wMaxPacketSize = RX_SIZE, \
+ .bInterval = 0, \
+ }; \
+ static void CONCAT2(NAME, _deferred_tx_)(void) \
+ { tx_stream_handler(&NAME); } \
+ DECLARE_DEFERRED(CONCAT2(NAME, _deferred_tx_)); \
+ static void CONCAT2(NAME, _deferred_rx_)(void) \
+ { rx_stream_handler(&NAME); } \
+ DECLARE_DEFERRED(CONCAT2(NAME, _deferred_rx_)); \
+ static void CONCAT2(NAME, _ep_tx)(void) \
+ { \
+ usb_stream_tx(&NAME); \
+ } \
+ static void CONCAT2(NAME, _ep_rx)(void) \
+ { \
+ usb_stream_rx(&NAME); \
+ } \
+ static void CONCAT2(NAME, _ep_reset)(void) \
+ { \
+ usb_stream_reset(&NAME); \
+ } \
+ USB_DECLARE_EP(ENDPOINT, \
+ CONCAT2(NAME, _ep_tx), \
+ CONCAT2(NAME, _ep_rx), \
+ CONCAT2(NAME, _ep_reset)); \
+/*
+ * Handle USB and Queue request in a deferred callback.
+ */
+int rx_stream_handler(struct usb_stream_config const *config);
+int tx_stream_handler(struct usb_stream_config const *config);
+
+/*
+ * These functions are used by the trampoline functions defined above to
+ * connect USB endpoint events with the generic USB stream driver.
+ */
+void usb_stream_tx(struct usb_stream_config const *config);
+void usb_stream_rx(struct usb_stream_config const *config);
+void usb_stream_reset(struct usb_stream_config const *config);
+
+#endif /* __CROS_EC_USB_STREAM_H */
diff --git a/chip/g/usb_blob.c b/chip/g/usb_blob.c
deleted file mode 100644
index 8a0f350549..0000000000
--- a/chip/g/usb_blob.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/* Copyright 2015 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 "blob.h"
-#include "common.h"
-#include "link_defs.h"
-#include "printf.h"
-#include "registers.h"
-#include "timer.h"
-#include "usb_descriptor.h"
-
-#define CPRINTS(format, args...) cprints(CC_USB, format, ## args)
-
-static int is_reset;
-
-/* USB-Serial descriptors */
-const struct usb_interface_descriptor USB_IFACE_DESC(USB_IFACE_BLOB) =
-{
- .bLength = USB_DT_INTERFACE_SIZE,
- .bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = USB_IFACE_BLOB,
- .bAlternateSetting = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
- .bInterfaceSubClass = 0, /* TODO(wfrichar): TBD */
- .bInterfaceProtocol = 0, /* TODO(wfrichar): TBD */
- .iInterface = USB_STR_BLOB_NAME,
-};
-const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_BLOB, 0) =
-{
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 0x80 | USB_EP_BLOB,
- .bmAttributes = 0x02 /* Bulk IN */,
- .wMaxPacketSize = USB_MAX_PACKET_SIZE,
- .bInterval = 10
-};
-const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_BLOB, 1) =
-{
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_EP_BLOB,
- .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 g_usb_desc ep_out_desc;
-static struct g_usb_desc ep_in_desc;
-
-/* Let the USB HW IN-to-host FIFO transmit some bytes */
-static void usb_enable_tx(int len)
-{
- ep_in_desc.flags = DIEPDMA_LAST | DIEPDMA_BS_HOST_RDY | DIEPDMA_IOC |
- DIEPDMA_TXBYTES(len);
- GR_USB_DIEPCTL(USB_EP_BLOB) |= DXEPCTL_CNAK | DXEPCTL_EPENA;
-}
-
-/* Let the USB HW OUT-from-host FIFO receive some bytes */
-static void usb_enable_rx(int len)
-{
- ep_out_desc.flags = DOEPDMA_RXBYTES(len) |
- DOEPDMA_LAST | DOEPDMA_BS_HOST_RDY | DOEPDMA_IOC;
- GR_USB_DOEPCTL(USB_EP_BLOB) |= DXEPCTL_CNAK | DXEPCTL_EPENA;
-}
-
-/* True if the HW Rx/OUT FIFO has bytes for us. */
-static inline int rx_fifo_is_ready(void)
-{
- return (ep_out_desc.flags & DOEPDMA_BS_MASK) == DOEPDMA_BS_DMA_DONE;
-}
-
-/*
- * 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).
- */
-static void rx_fifo_handler(void)
-{
- /*
- * The HW FIFO buffer (ep_buf_rx) is always filled from [0] by the
- * hardware. The rx_in_fifo variable counts how many bytes of that
- * buffer are actually valid, and is calculated from the HW DMA
- * descriptor table. The descriptor is updated by the hardware, and it
- * and ep_buf_rx remains valid and unchanged until software tells the
- * the hardware engine to accept more input.
- */
- int rx_in_fifo, rx_left;
-
- /*
- * The rx_handled variable tracks how many of the bytes in the HW FIFO
- * we've copied into the incoming queue. The queue may not accept all
- * of them at once, so we have to keep track of where we are so that
- * the next time this function is called we can try to shove the rest
- * of the HW FIFO bytes into the queue.
- */
- static int rx_handled;
-
- /* If the HW FIFO isn't ready, then we're waiting for more bytes */
- if (!rx_fifo_is_ready())
- return;
-
- /*
- * How many of the HW FIFO bytes have we not yet handled? We need to
- * know both where we are in the buffer and how many bytes we haven't
- * yet enqueued. One can be calculated from the other as long as we
- * know rx_in_fifo, but we need at least one static variable.
- */
- rx_in_fifo = USB_MAX_PACKET_SIZE
- - (ep_out_desc.flags & DOEPDMA_RXBYTES_MASK);
- rx_left = rx_in_fifo - rx_handled;
-
- /* If we have some, try to shove them into the queue */
- if (rx_left) {
- size_t added = put_bytes_to_blob(ep_buf_rx + rx_handled,
- rx_left);
- rx_handled += added;
- rx_left -= added;
- }
-
- /*
- * When we've handled all the bytes in the queue ("rx_in_fifo ==
- * rx_handled" and "rx_left == 0" indicate the same thing), we can
- * reenable the USB HW to go fetch more.
- */
- if (!rx_left) {
- rx_handled = 0;
- usb_enable_rx(USB_MAX_PACKET_SIZE);
- }
-}
-DECLARE_DEFERRED(rx_fifo_handler);
-
-void blob_is_ready_for_more_bytes(void)
-{
- hook_call_deferred(rx_fifo_handler, 0);
-}
-
-/* Rx/OUT interrupt handler */
-static void con_ep_rx(void)
-{
- /* Wake up the Rx FIFO handler */
- hook_call_deferred(rx_fifo_handler, 0);
-
- /* clear the RX/OUT interrupts */
- GR_USB_DOEPINT(USB_EP_BLOB) = 0xffffffff;
-}
-
-/* True if the Tx/IN FIFO can take some bytes from us. */
-static inline int tx_fifo_is_ready(void)
-{
- uint32_t status = ep_in_desc.flags & DIEPDMA_BS_MASK;
- return status == DIEPDMA_BS_DMA_DONE || status == DIEPDMA_BS_HOST_BSY;
-}
-
-/* Try to send some bytes to the host */
-static void tx_fifo_handler(void)
-{
- 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 = get_bytes_from_blob(ep_buf_tx, USB_MAX_PACKET_SIZE);
- if (count)
- usb_enable_tx(count);
-}
-DECLARE_DEFERRED(tx_fifo_handler);
-
-void blob_is_ready_to_emit_bytes(void)
-{
- hook_call_deferred(tx_fifo_handler, 0);
-}
-
-/* Tx/IN interrupt handler */
-static void con_ep_tx(void)
-{
- /* Wake up the Tx FIFO handler */
- hook_call_deferred(tx_fifo_handler, 0);
-
- /* clear the Tx/IN interrupts */
- GR_USB_DIEPINT(USB_EP_BLOB) = 0xffffffff;
-}
-
-static void ep_reset(void)
-{
- ep_out_desc.flags = DOEPDMA_RXBYTES(USB_MAX_PACKET_SIZE) |
- DOEPDMA_LAST | DOEPDMA_BS_HOST_RDY | DOEPDMA_IOC;
- ep_out_desc.addr = ep_buf_rx;
- GR_USB_DOEPDMA(USB_EP_BLOB) = (uint32_t)&ep_out_desc;
- ep_in_desc.flags = DIEPDMA_LAST | DIEPDMA_BS_HOST_BSY | DIEPDMA_IOC;
- ep_in_desc.addr = ep_buf_tx;
- GR_USB_DIEPDMA(USB_EP_BLOB) = (uint32_t)&ep_in_desc;
- GR_USB_DOEPCTL(USB_EP_BLOB) = DXEPCTL_MPS(64) | DXEPCTL_USBACTEP |
- DXEPCTL_EPTYPE_BULK |
- DXEPCTL_CNAK | DXEPCTL_EPENA;
- GR_USB_DIEPCTL(USB_EP_BLOB) = DXEPCTL_MPS(64) | DXEPCTL_USBACTEP |
- DXEPCTL_EPTYPE_BULK |
- DXEPCTL_TXFNUM(USB_EP_BLOB);
- GR_USB_DAINTMSK |= DAINT_INEP(USB_EP_BLOB) | DAINT_OUTEP(USB_EP_BLOB);
-
- is_reset = 1;
-
- /* Flush any queued data */
- hook_call_deferred(tx_fifo_handler, 0);
- hook_call_deferred(rx_fifo_handler, 0);
-}
-
-USB_DECLARE_EP(USB_EP_BLOB, con_ep_tx, con_ep_rx, ep_reset);
diff --git a/common/blob.c b/common/blob.c
deleted file mode 100644
index 5e563598a3..0000000000
--- a/common/blob.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/* Copyright 2015 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.
- */
-
-/* Handle an opaque blob of data */
-
-#include "blob.h"
-#include "common.h"
-#include "console.h"
-#include "printf.h"
-#include "queue.h"
-#include "task.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_USB, format, ## args)
-
-#define INCOMING_QUEUE_SIZE 100
-#define OUTGOING_QUEUE_SIZE 100
-
-
-static void incoming_add(struct queue_policy const *queue_policy, size_t count)
-{
- task_wake(TASK_ID_BLOB);
-}
-
-static void incoming_remove(struct queue_policy const *queue_policy,
- size_t count)
-{
- blob_is_ready_for_more_bytes();
-}
-
-static struct queue_policy const incoming_policy = {
- .add = incoming_add,
- .remove = incoming_remove,
-};
-
-static void outgoing_add(struct queue_policy const *queue_policy, size_t count)
-{
- blob_is_ready_to_emit_bytes();
-}
-
-static void outgoing_remove(struct queue_policy const *queue_policy,
- size_t count)
-{
- /* we don't care */
-}
-
-static struct queue_policy const outgoing_policy = {
- .add = outgoing_add,
- .remove = outgoing_remove,
-};
-
-static struct queue const incoming_q = QUEUE(INCOMING_QUEUE_SIZE, uint8_t,
- incoming_policy);
-
-static struct queue const outgoing_q = QUEUE(OUTGOING_QUEUE_SIZE, uint8_t,
- outgoing_policy);
-
-
-/* Call this to send data to the blob-handler */
-size_t put_bytes_to_blob(uint8_t *buffer, size_t count)
-{
- return QUEUE_ADD_UNITS(&incoming_q, buffer, count);
-}
-
-/* Call this to get data back fom the blob-handler */
-size_t get_bytes_from_blob(uint8_t *buffer, size_t count)
-{
- return QUEUE_REMOVE_UNITS(&outgoing_q, buffer, count);
-}
-
-#define WEAK_FUNC(FOO) \
- void __ ## FOO(void) {} \
- void FOO(void) \
- __attribute__((weak, alias(STRINGIFY(CONCAT2(__, FOO)))))
-
-/* Default callbacks for outsiders */
-WEAK_FUNC(blob_is_ready_for_more_bytes);
-WEAK_FUNC(blob_is_ready_to_emit_bytes);
-
-/* Do the magic */
-void blob_task(void)
-{
- static uint8_t buf[INCOMING_QUEUE_SIZE];
- size_t count, i;
- task_id_t me = task_get_current();
-
- while (1) {
- CPRINTS("task %d waiting for events...", me);
- task_wait_event(-1);
- CPRINTS("task %d awakened!", me);
-
- count = QUEUE_REMOVE_UNITS(&incoming_q, buf, sizeof(buf));
-
- CPRINTS("task %d gets: count=%d buf=((%s))", me, count, buf);
-
- /*
- * Just to have something to test to begin with, we'll
- * implement "tr a-zA-Z A-Za-z" and return the result.
- */
- for (i = 0; i < count; i++) {
- char tmp = buf[i];
- if (tmp >= 'a' && tmp <= 'z')
- buf[i] = tmp - ('a' - 'A');
- else if (tmp >= 'A' && tmp <= 'Z')
- buf[i] = tmp + ('a' - 'A');
- }
-
- count = QUEUE_ADD_UNITS(&outgoing_q, buf, count);
- CPRINTS("task %d puts: count=%d buf=((%s))", me, buf);
- }
-}
diff --git a/common/build.mk b/common/build.mk
index 4995cfe6e8..426f2d412f 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -89,7 +89,6 @@ common-$(CONFIG_USB_PD_TCPC)+=usb_pd_tcpc.o
common-$(CONFIG_VBOOT_HASH)+=sha256.o vboot_hash.o
common-$(CONFIG_VSTORE)+=vstore.o
common-$(CONFIG_WIRELESS)+=wireless.o
-common-$(HAS_TASK_BLOB)+=blob.o
common-$(HAS_TASK_CHIPSET)+=chipset.o
common-$(HAS_TASK_CONSOLE)+=console.o console_output.o uart_buffering.o
common-$(HAS_TASK_CONSOLE)+=memory_commands.o
diff --git a/include/blob.h b/include/blob.h
deleted file mode 100644
index 844e8d638a..0000000000
--- a/include/blob.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Copyright 2015 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.
- */
-
-/* Generic API for handling opaque blobs of data. */
-
-#ifndef __CROS_EC_BLOB_H
-#define __CROS_EC_BLOB_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-/* Call this to send data to the blob-handler */
-size_t put_bytes_to_blob(uint8_t *buffer, size_t count);
-
-/* Call this to get data back fom the blob-handler */
-size_t get_bytes_from_blob(uint8_t *buffer, size_t count);
-
-/* Implement this to be notified when the blob-handler can take more data */
-void blob_is_ready_for_more_bytes(void);
-
-/* Implement this to be notified when the blob-handler has data to give us */
-void blob_is_ready_to_emit_bytes(void);
-
-#endif /* __CROS_EC_BLOB_H */