XO 1.75 HOST to EC Protocol: Difference between revisions
Jump to navigation
Jump to search
(Protocol idea) |
|||
Line 4: | Line 4: | ||
* The EC is the SPI master; the CPU is the SPI slave. |
* The EC is the SPI master; the CPU is the SPI slave. |
||
* Two GPIOs in the CPU to EC direction - |
* Two GPIOs in the CPU to EC direction - CPU_RDY and CMD_RQST. |
||
* The CPU "speaks only when spoken to". |
* The CPU "speaks only when spoken to". |
||
* The EC can send data upstream whenever |
* The EC can send data upstream whenever CPU_RDY 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). |
* 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 |
* The first byte identifies the "data channel" - keyboard, mouse, event, send_command or command_response - and the number of following bytes. |
||
* The CPU puts the SPI interface in device mode, |
* The CPU puts the SPI interface in device mode, sets up to interrupt when a completed frame is received, and sets CPU_RDY to let the EC know that it can fire at will. |
||
* The interrupt handler forwards the frame to the appropriate module (keyboard, mouse, command, or event) depending on the data |
* The interrupt handler forwards the ustream frame to the appropriate module (keyboard, mouse, command, or event) depending on the data channel identifier in the first byte. The handler then clears CPU_RDY and immediately sets it, generating a rising edge. |
||
* When the EC sees the rising edge on |
* When the EC sees the rising edge on CPU_RDY, it knows that the data has been received and can then send more data later. If the RDY edge is not received within 30 ms, but RDY is still high, the EC pretends that an edge was received and returns to the "ready to send more data" state. |
||
Commands from the CPU to the EC require a 3-stage exchange, but still reliable and predictable: |
Commands from the CPU to the EC require a 3-stage exchange, but are still reliable and predictable: |
||
* When the CPU wants to send a command, it |
* When the CPU wants to send a command, it sets CMD_RQST. |
||
* The EC sees the edge and responds by sending an upstream packet to the |
* The EC sees the rising edge and responds by sending an upstream packet to the send_command channel. The EC enters "waiting for CMD" state and waits for either a falling edge on CMD_RQST or a 100 mS timeout. |
||
* The CPU must respond within 100 mS by putting a command packet in its transmit FIFO and clearing CMD_RQST. |
* 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. |
* When the EC sees CMD_RQST go low, it performs an SPI transaction to read the command packet. If CMD_RQST does not go low within 100 mS, the EC sends a "command aborted" response to the command channel and returns to "ready to send" state. |
||
* The EC sends its response, if any, as a normal upstream packet addressed to the command channel. |
* The EC sends its response, if any, as a normal upstream packet addressed to the command channel. |
||
Revision as of 03:07, 25 May 2010
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_RDY and CMD_RQST.
- The CPU "speaks only when spoken to".
- The EC can send data upstream whenever CPU_RDY 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 channel" - keyboard, mouse, event, send_command or command_response - and the number of following bytes.
- The CPU puts the SPI interface in device mode, sets up to interrupt when a completed frame is received, and sets CPU_RDY to let the EC know that it can fire at will.
- The interrupt handler forwards the ustream frame to the appropriate module (keyboard, mouse, command, or event) depending on the data channel identifier in the first byte. The handler then clears CPU_RDY and immediately sets it, generating a rising edge.
- When the EC sees the rising edge on CPU_RDY, it knows that the data has been received and can then send more data later. If the RDY edge is not received within 30 ms, but RDY is still high, the EC pretends that an edge was received and returns to the "ready to send more data" state.
Commands from the CPU to the EC require a 3-stage exchange, but are still reliable and predictable:
- When the CPU wants to send a command, it sets CMD_RQST.
- The EC sees the rising edge and responds by sending an upstream packet to the send_command channel. The EC enters "waiting for CMD" state and waits for either a falling edge on CMD_RQST or a 100 mS timeout.
- 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. If CMD_RQST does not go low within 100 mS, the EC sends a "command aborted" response to the command channel and returns to "ready to send" state.
- 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.