XO 1.75 HOST to EC Protocol

From OLPC
Revision as of 22:55, 24 May 2010 by Wmb@firmworks.com (talk | contribs) (Protocol idea)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Here is a swag at a reliable SPI protocol without races. This depends on the fact that "unsolicited" EC-to-CPU data (keyboard events) is more frequent than commands from the CPU, so the optimization should be for CPU load in the upstream (EC to CPU) case.

Protocol

  • The EC is the SPI master; the CPU is the SPI slave.
  • Two GPIOs in the CPU to EC direction - CPU_ACK and CMD_RQST.
  • The CPU "speaks only when spoken to".
  • The EC can send data upstream whenever CPU_ACK is high except as described below.
  • An upstream data packet can be from 1 to 16 bytes (the CPU's RxFIFO is sixteen 32-bit entries, so maybe it could go up to 64 bytes, but 16 is probably more than enough).
  • The first byte identifies the "data stream" - keyboard data, mouse data, or command data - and the number of following bytes.
  • The CPU puts the SPI interface in device mode, set up to interrupt when a completed frame is received.
  • The interrupt handler forwards the frame to the appropriate module (keyboard, mouse, command, or event) depending on the data stream identifier in the first byte. The handler then clears CPU_ACK and immediately sets it, generating a rising edge.
  • When the EC sees the rising edge on CPU_ACK, it knows that the data has been received and can then send more data later. If the ACK edge is not received within 30 ms, the EC pretends that one was received and returns to the "ready to send more data" state (so long as ACK is high).

Commands from the CPU to the EC require a 3-stage exchange, but still reliable and predictable:

  • When the CPU wants to send a command, it generates a rising edge on CMD_RQST.
  • The EC sees the edge and responds by sending an upstream packet to the command channel. The data is a code that says "please send a command".
  • The CPU must respond within 100 mS by putting a command packet in its transmit FIFO and clearing CMD_RQST.
  • When the EC sees CMD_RQST go low, it performs an SPI transaction to read the command packet.
  • The EC sends its response, if any, as a normal upstream packet addressed to the command channel.

Observations

  • The common case of keyboard and mouse data is very simple from the CPU end. The CPU gets an interrupt, pulls out the data packet, and forwards it to the input module.
  • The command case seems more complicated, but the Linux implementation is actually rather clean. The command module just tells the muxer module (interrupt handler) which command it wants to send. The muxer module sets CMD_RQST and then exits. When an interrupt happens and the upstream command is "please send", the muxer stuffs the command code in the Tx FIFO, clears CMD_RQST, and exits. Eventually another interrupt happens, and the muxer forwards the response to the command module.
  • It's unnecessary to use the complex command mechanism for stuff like SCIs and battery events. The EC can just send them up whenever it gets them, addressed to the event channel.

Alternate protocol with CPU as SPI master

This protocol is a bit simpler in the command case, but has more CPU overhead in the common case of keyboard/mouse events.

  • The CPU is the SPI master, the EC is the slave.
  • Two GPIOs in the EC-to-CPU direction - EC_ACK and EC_RQST
  • The CPU can send a command to the EC at any time except when it is waiting for the EC's response to a previous command.
  • Each command from the CPU to the EC is from 1 to 4 bytes, so it will always fit in the EC FIFO.
  • Each command has a response from the EC, so the CPU can determine when it is okay to send another one.
  • The EC uses its SDCS# rising edge interrupt (SDIRS[4]) to trigger its "incoming command" handler. That interrupt occurs after all command bytes have already been received and are thus waiting in the FIFO.
  • The EC-to-CPU response format consists of from 0 to 3 data bytes. The CPU knows how many bytes to expect because each command has implicit response count. The entire response group fits entirely in the FIFO.
  • When the EC has finished writing an upstream group into the FIFO, it clears EC_ACK then sets it, thus generating an edge. The CPU sees the edge detect status (either by polling or interrupting), then reads the 0 to 4 upstream data bytes.
  • If the EC has unsolicited data to send to the CPU, it asserts EC_RQST. The CPU sees the rising edge and responds by sending a "ReceiveReady" command. The EC sends the unsolicited data as the response to that command.