summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2012-05-02 12:41:04 -0700
committerSimon Glass <sjg@chromium.org>2012-05-03 14:08:56 -0700
commit59c407517264bc1a1ffa838ac3a7cda21ba1b991 (patch)
tree0f40c0a788c35255e9bc2df23c98c15f24e781b3
parent5ba4576cf3a4bd41ac04b0cb5d05cf7c80d13b8a (diff)
downloadchrome-ec-59c407517264bc1a1ffa838ac3a7cda21ba1b991.tar.gz
daisy: Re-introduce SPI protocol support
The changes in the message protocol break SPI support, so re-introduce these, this time in the driver itself. We add the concept of an option preamble in the message, a length and a trailing byte. BUG=chrome-os-partner:9426 TEST=run U-Boot, see that keyboard works correctly now. Change-Id: I83b4af7e3745b935ffafcd9e2f521fce77e3bc6e Signed-off-by: Simon Glass <sjg@chromium.org>
-rw-r--r--chip/stm32/spi.c63
1 files changed, 52 insertions, 11 deletions
diff --git a/chip/stm32/spi.c b/chip/stm32/spi.c
index f0c67aaebd..a0dda24b35 100644
--- a/chip/stm32/spi.c
+++ b/chip/stm32/spi.c
@@ -33,6 +33,25 @@ enum {
};
/*
+ * Since message.c no longer supports our protocol, we must do it all here.
+ *
+ * We allow a preamble and a header byte so that SPI can function at all.
+ * We also add a 16-bit length so that we can tell that we got the whole
+ * message, since the master decides how many bytes to read.
+ */
+enum {
+ /* The bytes which appear before the header in a message */
+ SPI_MSG_PREAMBLE = 0xff,
+
+ /* The header byte, which follows the preamble */
+ SPI_MSG_HEADER = 0xec,
+
+ SPI_MSG_HEADER_BYTES = 3,
+ SPI_MSG_TRAILER_BYTES = 2,
+ SPI_MSG_PROTO_BYTES = SPI_MSG_HEADER_BYTES + SPI_MSG_TRAILER_BYTES,
+};
+
+/*
* Our input and output buffers. These must be large enough for our largest
* message, including protocol overhead.
*/
@@ -74,6 +93,16 @@ void spi_work_task(void)
* The format of a reply is as per the command interface, with a number of
* preamble bytes before it.
*
+ * The format of a reply is a sequence of bytes:
+ *
+ * <hdr> <len_lo> <len_hi> <msg bytes> <sum> <preamble bytes>
+ *
+ * The hdr byte is just a tag to indicate that the real message follows. It
+ * signals the end of any preamble required by the interface.
+ *
+ * The 16-bit length is the entire packet size, including the header, length
+ * bytes, message payload, checksum, and postamble byte.
+ *
* The preamble is typically 2 bytes, but can be longer if the STM takes ages
* to react to the incoming message. Since we send our first byte as the AP
* sends us the command, we clearly can't send anything sensible for that
@@ -86,12 +115,29 @@ void spi_work_task(void)
* interface faster than the CPU clock with this approach.
*
* @param port Port to send reply back on (STM32_SPI0/1_PORT)
- * @param msg Message to send
- * @param msg_len Length of message in bytes
+ * @param msg Message to send, which starts SPI_MSG_HEADER_BYTES
+ * bytes into the buffer
+ * @param msg_len Length of message in bytes, including checksum
*/
static void reply(int port, char *msg, int msg_len)
{
int dmac;
+ int sum;
+
+ /* Get the old checksumsum */
+ sum = msg[msg_len - 1 + SPI_MSG_HEADER_BYTES];
+
+ /* Add our header bytes */
+ msg_len += SPI_MSG_HEADER_BYTES + SPI_MSG_TRAILER_BYTES -
+ MSG_TRAILER_BYTES;
+ msg[0] = SPI_MSG_HEADER;
+ msg[1] = msg_len & 0xff;
+ msg[2] = (msg_len >> 8) & 0xff;
+
+ /* Update the checksum */
+ sum += msg[0] + msg[1] + msg[2];
+ msg[msg_len - 2] = sum;
+ msg[msg_len - 1] = SPI_MSG_PREAMBLE;
/*
* This method is not really suitable for very large messages. If
@@ -118,7 +164,6 @@ static void reply(int port, char *msg, int msg_len)
static void spi_interrupt(int port)
{
int msg_len;
- char *buff;
int dmac;
int cmd;
@@ -134,15 +179,11 @@ static void spi_interrupt(int port)
dma_start_rx(dmac, sizeof(in_msg), (void *)&STM32_SPI_DR(port),
in_msg);
- /*
- * Process the command and send the reply. We provide our output
- * buffer as a suggested location for reply, since this may stop us
- * needing to copy the message.
- */
- buff = out_msg;
- msg_len = message_process_cmd(cmd, out_msg, sizeof(out_msg));
+ /* Process the command and send the reply */
+ msg_len = message_process_cmd(cmd, out_msg + SPI_MSG_HEADER_BYTES,
+ sizeof(out_msg) - SPI_MSG_PROTO_BYTES);
if (msg_len >= 0)
- reply(port, buff, msg_len);
+ reply(port, out_msg, msg_len);
/* Wake up the task that watches for end of the incoming message */
task_wake(TASK_ID_SPI_WORK);