summaryrefslogtreecommitdiff
path: root/chip/stm32/usb_spi.c
diff options
context:
space:
mode:
authorJack Rosenthal <jrosenth@chromium.org>2021-11-04 12:11:58 -0600
committerCommit Bot <commit-bot@chromium.org>2021-11-05 04:22:34 +0000
commit252457d4b21f46889eebad61d4c0a65331919cec (patch)
tree01856c4d31d710b20e85a74c8d7b5836e35c3b98 /chip/stm32/usb_spi.c
parent08f5a1e6fc2c9467230444ac9b582dcf4d9f0068 (diff)
downloadchrome-ec-252457d4b21f46889eebad61d4c0a65331919cec.tar.gz
In the interest of making long-term branch maintenance incur as little technical debt on us as possible, we should not maintain any files on the branch we are not actually using. This has the added effect of making it extremely clear when merging CLs from the main branch when changes have the possibility to affect us. The follow-on CL adds a convenience script to actually pull updates from the main branch and generate a CL for the update. BUG=b:204206272 BRANCH=ish TEST=make BOARD=arcada_ish && make BOARD=drallion_ish Signed-off-by: Jack Rosenthal <jrosenth@chromium.org> Change-Id: I17e4694c38219b5a0823e0a3e55a28d1348f4b18 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3262038 Reviewed-by: Jett Rink <jettrink@chromium.org> Reviewed-by: Tom Hughes <tomhughes@chromium.org>
Diffstat (limited to 'chip/stm32/usb_spi.c')
-rw-r--r--chip/stm32/usb_spi.c627
1 files changed, 0 insertions, 627 deletions
diff --git a/chip/stm32/usb_spi.c b/chip/stm32/usb_spi.c
deleted file mode 100644
index 54caae015e..0000000000
--- a/chip/stm32/usb_spi.c
+++ /dev/null
@@ -1,627 +0,0 @@
-/* Copyright 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 "common.h"
-#include "link_defs.h"
-#include "registers.h"
-#include "spi.h"
-#include "usb_descriptor.h"
-#include "usb_hw.h"
-#include "usb_spi.h"
-#include "util.h"
-
-/* Forward declare platform specific functions. */
-static bool usb_spi_received_packet(struct usb_spi_config const *config);
-static bool usb_spi_transmitted_packet(struct usb_spi_config const *config);
-static void usb_spi_read_packet(struct usb_spi_config const *config,
- struct usb_spi_packet_ctx *packet);
-static void usb_spi_write_packet(struct usb_spi_config const *config,
- struct usb_spi_packet_ctx *packet);
-
-/*
- * Map EC error codes to USB_SPI error codes.
- *
- * @param error EC error code
- *
- * @returns USB SPI error code based on the mapping.
- */
-static int16_t usb_spi_map_error(int error)
-{
- switch (error) {
- case EC_SUCCESS: return USB_SPI_SUCCESS;
- case EC_ERROR_TIMEOUT: return USB_SPI_TIMEOUT;
- case EC_ERROR_BUSY: return USB_SPI_BUSY;
- default: return USB_SPI_UNKNOWN_ERROR | (error & 0x7fff);
- }
-}
-
-/*
- * Read data into the receive buffer.
- *
- * @param dst Destination receive context we are writing data to.
- * @param src Source packet context we are reading data from.
- *
- * @returns USB_SPI_RX_DATA_OVERFLOW if the source packet is too large
- */
-static int usb_spi_read_usb_packet(struct usb_spi_transfer_ctx *dst,
- const struct usb_spi_packet_ctx *src)
-{
- size_t max_read_length = dst->transfer_size - dst->transfer_index;
- size_t bytes_in_buffer = src->packet_size - src->header_size;
- const uint8_t *packet_buffer = src->bytes + src->header_size;
-
- if (bytes_in_buffer > max_read_length) {
- /*
- * An error occurred, we should not receive more data than
- * the buffer can support.
- */
- return USB_SPI_RX_DATA_OVERFLOW;
- }
- memcpy(dst->buffer + dst->transfer_index, packet_buffer,
- bytes_in_buffer);
-
- dst->transfer_index += bytes_in_buffer;
- return USB_SPI_SUCCESS;
-}
-
-/*
- * Fill the USB packet with data from the transmit buffer.
- *
- * @param dst Destination packet context we are writing data to.
- * @param src Source transmit context we are reading data from.
- */
-static void usb_spi_fill_usb_packet(struct usb_spi_packet_ctx *dst,
- struct usb_spi_transfer_ctx *src)
-{
- size_t transfer_size = src->transfer_size - src->transfer_index;
- size_t max_buffer_size = USB_MAX_PACKET_SIZE - dst->header_size;
- uint8_t *packet_buffer = dst->bytes + dst->header_size;
-
- if (transfer_size > max_buffer_size)
- transfer_size = max_buffer_size;
-
- memcpy(packet_buffer, src->buffer + src->transfer_index, transfer_size);
-
- dst->packet_size = dst->header_size + transfer_size;
- src->transfer_index += transfer_size;
-}
-
-/*
- * Setup the USB SPI state to start a new SPI transfer.
- *
- * @param config USB SPI config
- * @param write_count Number of bytes to write in the SPI transfer
- * @param read_count Number of bytes to read in the SPI transfer
- */
-static void usb_spi_setup_transfer(struct usb_spi_config const *config,
- size_t write_count, size_t read_count)
-{
- /* Reset any status code. */
- config->state->status_code = USB_SPI_SUCCESS;
-
- /* Reset the write and read counts. */
- config->state->spi_write_ctx.transfer_size = write_count;
- config->state->spi_write_ctx.transfer_index = 0;
- config->state->spi_read_ctx.transfer_size = read_count;
- config->state->spi_read_ctx.transfer_index = 0;
-}
-
-/*
- * Handle USB events that will reset the USB SPI state.
- *
- * @param config USB SPI config
- */
-static void usb_spi_reset_interface(struct usb_spi_config const *config)
-{
- /* Setup a 0 byte transfer to clear the contexts. */
- usb_spi_setup_transfer(config, 0, 0);
-}
-
-/*
- * Returns if the response transfer is in progress.
- *
- * @param config USB SPI config
- *
- * @returns True if a response transfer is in progress.
- */
-static bool usb_spi_response_in_progress(struct usb_spi_config const *config)
-{
- if ((config->state->mode == USB_SPI_MODE_START_RESPONSE) ||
- (config->state->mode == USB_SPI_MODE_CONTINUE_RESPONSE)) {
- return true;
- }
- return false;
-}
-
-/*
- * Prep the state to construct a new response. This sets the transfer
- * contexts, the mode, and status code. If a non-zero status code is
- * returned, then no payload will be transmitted.
- *
- * @param config USB SPI config
- * @param status_code status code to set for the response.
- */
-static void setup_transfer_response(struct usb_spi_config const *config,
- uint16_t status_code)
-{
- config->state->status_code = status_code;
- config->state->spi_read_ctx.transfer_index = 0;
- config->state->mode = USB_SPI_MODE_START_RESPONSE;
-
- /* If an error occurred, transmit an empty start packet. */
- if (status_code != USB_SPI_SUCCESS)
- config->state->spi_read_ctx.transfer_size = 0;
-}
-
-/*
- * Constructs the response packet containing the SPI configuration.
- *
- * @param config USB SPI config
- * @param packet Packet buffer we will be transmitting.
- */
-static void create_spi_config_response(struct usb_spi_config const *config,
- struct usb_spi_packet_ctx *packet)
-{
- /* Construct the response packet. */
- packet->rsp_config.packet_id = USB_SPI_PKT_ID_RSP_USB_SPI_CONFIG;
- packet->rsp_config.max_write_count = USB_SPI_MAX_WRITE_COUNT;
- packet->rsp_config.max_read_count = USB_SPI_MAX_READ_COUNT;
- /* Set the feature flags. */
- packet->rsp_config.feature_bitmap = 0;
-#ifndef CONFIG_SPI_HALFDUPLEX
- packet->rsp_config.feature_bitmap |=
- USB_SPI_FEATURE_FULL_DUPLEX_SUPPORTED;
-#endif
- packet->packet_size =
- sizeof(struct usb_spi_response_configuration_v2);
-}
-
-/*
- * If we have a transfer response in progress, this will construct the
- * next entry. If no transfer is in progress or if we are unable to
- * create the next packet, it will not modify tx_packet.
- *
- * @param config USB SPI config
- * @param packet Packet buffer we will be transmitting.
- */
-static void usb_spi_create_spi_transfer_response(
- struct usb_spi_config const *config,
- struct usb_spi_packet_ctx *transmit_packet)
-{
-
- if (!usb_spi_response_in_progress(config))
- return;
-
- if (config->state->spi_read_ctx.transfer_index == 0) {
-
- /* Transmit the first packet with the status code. */
- transmit_packet->header_size =
- offsetof(struct usb_spi_response_v2, data);
- transmit_packet->rsp_start.packet_id =
- USB_SPI_PKT_ID_RSP_TRANSFER_START;
- transmit_packet->rsp_start.status_code =
- config->state->status_code;
-
- usb_spi_fill_usb_packet(transmit_packet,
- &config->state->spi_read_ctx);
- } else if (config->state->spi_read_ctx.transfer_index <
- config->state->spi_read_ctx.transfer_size) {
-
- /* Transmit the continue packets. */
- transmit_packet->header_size =
- offsetof(struct usb_spi_continue_v2, data);
- transmit_packet->rsp_continue.packet_id =
- USB_SPI_PKT_ID_RSP_TRANSFER_CONTINUE;
- transmit_packet->rsp_continue.data_index =
- config->state->spi_read_ctx.transfer_index;
-
- usb_spi_fill_usb_packet(transmit_packet,
- &config->state->spi_read_ctx);
- }
- if (config->state->spi_read_ctx.transfer_index <
- config->state->spi_read_ctx.transfer_size) {
- config->state->mode = USB_SPI_MODE_CONTINUE_RESPONSE;
- } else {
- config->state->mode = USB_SPI_MODE_IDLE;
- }
-}
-
-/*
- * Process the rx packet.
- *
- * @param config USB SPI config
- * @param packet Received packet to process.
- */
-static void usb_spi_process_rx_packet(struct usb_spi_config const *config,
- struct usb_spi_packet_ctx *packet)
-{
- if (packet->packet_size < USB_SPI_MIN_PACKET_SIZE) {
- /* No valid packet exists smaller than the packet id. */
- setup_transfer_response(config, USB_SPI_RX_UNEXPECTED_PACKET);
- return;
- }
- /* Reset the mode until we've processed the packet. */
- config->state->mode = USB_SPI_MODE_IDLE;
-
- switch (packet->packet_id) {
- case USB_SPI_PKT_ID_CMD_GET_USB_SPI_CONFIG:
- {
- /* The host requires the SPI configuration. */
- config->state->mode = USB_SPI_MODE_SEND_CONFIGURATION;
- break;
- }
- case USB_SPI_PKT_ID_CMD_RESTART_RESPONSE:
- {
- /*
- * The host has requested the device restart the last response.
- * This is used to recover from lost USB packets without
- * duplicating SPI transfers.
- */
- setup_transfer_response(config, config->state->status_code);
- break;
- }
- case USB_SPI_PKT_ID_CMD_TRANSFER_START:
- {
- /* The host started a new USB SPI transfer */
- size_t write_count = packet->cmd_start.write_count;
- size_t read_count = packet->cmd_start.read_count;
-
- if (!config->state->enabled) {
- setup_transfer_response(config, USB_SPI_DISABLED);
- } else if (write_count > USB_SPI_MAX_WRITE_COUNT) {
- setup_transfer_response(config,
- USB_SPI_WRITE_COUNT_INVALID);
- } else if (read_count == USB_SPI_FULL_DUPLEX_ENABLED) {
-#ifndef CONFIG_SPI_HALFDUPLEX
- /* Full duplex mode is not supported on this device. */
- setup_transfer_response(config,
- USB_SPI_UNSUPPORTED_FULL_DUPLEX);
-#endif
- } else if (read_count > USB_SPI_MAX_READ_COUNT &&
- read_count != USB_SPI_FULL_DUPLEX_ENABLED) {
- setup_transfer_response(config,
- USB_SPI_READ_COUNT_INVALID);
- } else {
- usb_spi_setup_transfer(config, write_count, read_count);
- packet->header_size =
- offsetof(struct usb_spi_command_v2, data);
- config->state->status_code = usb_spi_read_usb_packet(
- &config->state->spi_write_ctx, packet);
- }
-
- /* Send responses if we encountered an error. */
- if (config->state->status_code != USB_SPI_SUCCESS) {
- setup_transfer_response(config,
- config->state->status_code);
- break;
- }
-
- /* Start the SPI transfer when we've read all data. */
- if (config->state->spi_write_ctx.transfer_index ==
- config->state->spi_write_ctx.transfer_size) {
- config->state->mode = USB_SPI_MODE_START_SPI;
- }
-
- break;
- }
- case USB_SPI_PKT_ID_CMD_TRANSFER_CONTINUE:
- {
- /*
- * The host has sent a continue packet for the SPI transfer
- * which contains additional data payload.
- */
- packet->header_size =
- offsetof(struct usb_spi_continue_v2, data);
- if (config->state->status_code == USB_SPI_SUCCESS) {
- config->state->status_code = usb_spi_read_usb_packet(
- &config->state->spi_write_ctx, packet);
- }
-
- /* Send responses if we encountered an error. */
- if (config->state->status_code != USB_SPI_SUCCESS) {
- setup_transfer_response(config,
- config->state->status_code);
- break;
- }
-
- /* Start the SPI transfer when we've read all data. */
- if (config->state->spi_write_ctx.transfer_index ==
- config->state->spi_write_ctx.transfer_size) {
- config->state->mode = USB_SPI_MODE_START_SPI;
- }
-
- break;
- }
- default:
- {
- /* An unknown USB packet was delivered. */
- setup_transfer_response(config, USB_SPI_RX_UNEXPECTED_PACKET);
- break;
- }
- }
-}
-
-/* Deferred function to handle state changes, process USB SPI packets,
- * and construct responses.
- *
- * @param config USB SPI config
- */
-void usb_spi_deferred(struct usb_spi_config const *config)
-{
- int enabled;
- struct usb_spi_packet_ctx *receive_packet =
- &config->state->receive_packet;
- struct usb_spi_packet_ctx *transmit_packet =
- &config->state->transmit_packet;
- transmit_packet->packet_size = 0;
-
- if (config->flags & USB_SPI_CONFIG_FLAGS_IGNORE_HOST_SIDE_ENABLE)
- enabled = config->state->enabled_device;
- else
- enabled = config->state->enabled_device &&
- config->state->enabled_host;
-
- /*
- * If our overall enabled state has changed we call the board specific
- * enable or disable routines and save our new state.
- */
- if (enabled != config->state->enabled) {
- if (enabled) usb_spi_board_enable(config);
- else usb_spi_board_disable(config);
-
- config->state->enabled = enabled;
- }
-
- /* Read any packets from the endpoint. */
-
- usb_spi_read_packet(config, receive_packet);
- if (receive_packet->packet_size) {
- usb_spi_process_rx_packet(config, receive_packet);
- }
-
- /* Need to send the USB SPI configuration */
- if (config->state->mode == USB_SPI_MODE_SEND_CONFIGURATION) {
- create_spi_config_response(config, transmit_packet);
- usb_spi_write_packet(config, transmit_packet);
- config->state->mode = USB_SPI_MODE_IDLE;
- return;
- }
-
- /* Start a new SPI transfer. */
- if (config->state->mode == USB_SPI_MODE_START_SPI) {
- uint16_t status_code;
- int read_count = config->state->spi_read_ctx.transfer_size;
-#ifndef CONFIG_SPI_HALFDUPLEX
- /*
- * Handle the full duplex mode on supported platforms.
- * The read count is equal to the write count.
- */
- if (read_count == USB_SPI_FULL_DUPLEX_ENABLED) {
- config->state->spi_read_ctx.transfer_size =
- config->state->spi_write_ctx.transfer_size;
- read_count = SPI_READBACK_ALL;
- }
-#endif
- status_code = spi_transaction(SPI_FLASH_DEVICE,
- config->state->spi_write_ctx.buffer,
- config->state->spi_write_ctx.transfer_size,
- config->state->spi_read_ctx.buffer,
- read_count);
-
- /* Cast the EC status code to USB SPI and start the response. */
- status_code = usb_spi_map_error(status_code);
- setup_transfer_response(config, status_code);
- }
-
- if (usb_spi_response_in_progress(config) &&
- usb_spi_transmitted_packet(config)) {
- usb_spi_create_spi_transfer_response(config, transmit_packet);
- usb_spi_write_packet(config, transmit_packet);
- }
-}
-
-/*
- * Sets which SPI modes will be enabled
- *
- * @param config USB SPI config
- * @param enabled usb_spi_request indicating which SPI mode is enabled.
- */
-void usb_spi_enable(struct usb_spi_config const *config, int enabled)
-{
- config->state->enabled_device = enabled;
-
- hook_call_deferred(config->deferred, 0);
-}
-
-/*
- * STM32 Platform: Receive the data from the endpoint into the packet and
- * mark the endpoint as ready to accept more data.
- *
- * @param config USB SPI config
- * @param packet Destination packet used to store the endpoint data.
- */
-static void usb_spi_read_packet(struct usb_spi_config const *config,
- struct usb_spi_packet_ctx *packet)
-{
- size_t packet_size;
-
- if (!usb_spi_received_packet(config)) {
- /* No data is present on the endpoint. */
- packet->packet_size = 0;
- return;
- }
-
- /* Copy bytes from endpoint memory. */
- packet_size = btable_ep[config->endpoint].rx_count & RX_COUNT_MASK;
- memcpy_from_usbram(packet->bytes,
- (void *)usb_sram_addr(config->ep_rx_ram), packet_size);
- packet->packet_size = packet_size;
- /* Set endpoint as valid for accepting new packet. */
- STM32_TOGGLE_EP(config->endpoint, EP_RX_MASK, EP_RX_VALID, 0);
-}
-
-/*
- * STM32 Platform: Transmit data from the packet to the endpoint buffer.
- * If a packet is written, the endpoint will be marked valid for transmitting.
- *
- * @param config USB SPI config
- * @param packet Source packet we will write to the endpoint data.
- */
-static void usb_spi_write_packet(struct usb_spi_config const *config,
- struct usb_spi_packet_ctx *packet)
-{
- if (packet->packet_size == 0)
- return;
-
- /* Copy bytes to endpoint memory. */
- memcpy_to_usbram((void *)usb_sram_addr(config->ep_tx_ram),
- packet->bytes, packet->packet_size);
- btable_ep[config->endpoint].tx_count = packet->packet_size;
-
- /* Mark the packet as having no data. */
- packet->packet_size = 0;
-
- /* Set endpoint as valid for transmitting new packet. */
- STM32_TOGGLE_EP(config->endpoint, EP_TX_MASK, EP_TX_VALID, 0);
-}
-
-/*
- * STM32 Platform: Returns the RX endpoint status
- *
- * @param config USB SPI config
- *
- * @returns Returns true when the RX endpoint has a packet.
- */
-static bool usb_spi_received_packet(struct usb_spi_config const *config)
-{
- return (STM32_USB_EP(config->endpoint) & EP_RX_MASK) != EP_RX_VALID;
-}
-
-/* STM32 Platform: Returns the TX endpoint status
- *
- * @param config USB SPI config
- *
- * @returns Returns true when the TX endpoint transmitted
- * the packet written.
- */
-static bool usb_spi_transmitted_packet(struct usb_spi_config const *config)
-{
- return (STM32_USB_EP(config->endpoint) & EP_TX_MASK) != EP_TX_VALID;
-}
-
-/* STM32 Platform: Handle interrupt for USB data received.
- *
- * @param config USB SPI config
- */
-void usb_spi_rx(struct usb_spi_config const *config)
-{
- /*
- * We need to set both the TX and RX endpoints to NAK to prevent
- * transfers. The protocol requires responses to follow a command, but
- * the USB host will request the next packet from the TX endpoint
- * before the USB SPI has updated the memory in the buffer. By setting
- * it to NAK in the ISR, it will not perform a transfer until the
- * next packet is ready.
- *
- * This has a side effect of disabling the endpoint interrupts until
- * they are set to valid or a USB reset events occurs.
- */
- STM32_TOGGLE_EP(config->endpoint, EP_TX_RX_MASK, EP_TX_RX_NAK, 0);
-
- hook_call_deferred(config->deferred, 0);
-}
-
-/*
- * STM32 Platform: Handle interrupt for USB data transmitted.
- *
- * @param config USB SPI config
- */
-void usb_spi_tx(struct usb_spi_config const *config)
-{
- STM32_TOGGLE_EP(config->endpoint, EP_TX_MASK, EP_TX_NAK, 0);
-
- hook_call_deferred(config->deferred, 0);
-}
-
-/*
- * STM32 Platform: Handle interrupt for USB events
- *
- * @param config USB SPI config
- * @param evt USB event
- */
-void usb_spi_event(struct usb_spi_config const *config, enum usb_ep_event evt)
-{
- int endpoint;
-
- if (evt != USB_EVENT_RESET)
- return;
-
- endpoint = config->endpoint;
-
- usb_spi_reset_interface(config);
-
- btable_ep[endpoint].tx_addr = usb_sram_addr(config->ep_tx_ram);
- btable_ep[endpoint].tx_count = 0;
-
- btable_ep[endpoint].rx_addr = usb_sram_addr(config->ep_rx_ram);
- btable_ep[endpoint].rx_count =
- 0x8000 | ((USB_MAX_PACKET_SIZE / 32 - 1) << 10);
-
- STM32_USB_EP(endpoint) = ((endpoint << 0) | /* Endpoint Addr*/
- (2 << 4) | /* TX NAK */
- (0 << 9) | /* Bulk EP */
- (3 << 12)); /* RX Valid */
-}
-
-/*
- * STM32 Platform: Handle control transfers.
- *
- * @param config USB SPI config
- * @param rx_buf Contains setup packet
- * @param tx_buf unused
- */
-int usb_spi_interface(struct usb_spi_config const *config,
- usb_uint *rx_buf,
- usb_uint *tx_buf)
-{
- struct usb_setup_packet setup;
-
- usb_read_setup_packet(rx_buf, &setup);
-
- if (setup.bmRequestType != (USB_DIR_OUT |
- USB_TYPE_VENDOR |
- USB_RECIP_INTERFACE))
- return 1;
-
- if (setup.wValue != 0 ||
- setup.wIndex != config->interface ||
- setup.wLength != 0)
- return 1;
-
- switch (setup.bRequest) {
- case USB_SPI_REQ_ENABLE:
- config->state->enabled_host = 1;
- break;
-
- case USB_SPI_REQ_DISABLE:
- config->state->enabled_host = 0;
- break;
-
- default: return 1;
- }
-
- /*
- * Our state has changed, call the deferred function to handle the
- * state change.
- */
- if (!(config->flags & USB_SPI_CONFIG_FLAGS_IGNORE_HOST_SIDE_ENABLE))
- hook_call_deferred(config->deferred, 0);
-
- usb_spi_reset_interface(config);
-
- btable_ep[0].tx_count = 0;
- STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, EP_STATUS_OUT);
- return 0;
-}