Revised EC Port 6C Command Protocol: Difference between revisions
(First draft of new EC protocol) |
(added symbol names and 0x in some places) |
||
Line 1: | Line 1: | ||
This is a replacement for an EC command protocol that was giving us problems. |
This is a replacement for an EC command protocol that was giving us problems. |
||
The objective is to transmit information back and forth between the CPU and the embedded controller (EC), via I/O ports 0x68 and 0x6c. This protocol can support: |
The objective is to transmit information back and forth between the CPU and the embedded controller (EC), via CPU I/O ports 0x68 and 0x6c. This protocol can support: |
||
* Commands with no data transfer |
* Commands with no data transfer |
||
Line 12: | Line 12: | ||
It depends on these facts: |
It depends on these facts: |
||
* The EC can receive an interrupt when the CPU writes a byte to either port 0x68 or port 0x6c when IBF=0, i.e. on a 0->1 IBF transition. To enable that interrupt, bit 1 of EC register 0xfe9d must be set. |
* The EC can receive an interrupt when the CPU writes a byte to either port 0x68 or port 0x6c when IBF=0, i.e. on a 0->1 IBF transition. To enable that interrupt, bit 1 of EC register 0xfe9d LPC68CFG must be set. |
||
* The EC can receive an interrupt when the CPU read a byte from port 0x68 when OBF=1, i.e. on a 1->0 OBF transition. To enable that interrupt, bit 0 of EC register 0xfe9d must be set. (The protocol enables the OBF interrupt only as needed, during intermediate stages of multi-byte commands.) |
* The EC can receive an interrupt when the CPU read a byte from port 0x68 when OBF=1, i.e. on a 1->0 OBF transition. To enable that interrupt, bit 0 of EC register 0xfe9d LPC68CFG must be set. (The protocol enables the OBF interrupt only as needed, during intermediate stages of multi-byte commands.) |
||
* The EC can distinguish between a write to port 0x68 and a write to port 0x6c, via bit 6 of EC register 0xfe9e. |
* The EC can distinguish between a write to port 0x68 and a write to port 0x6c, via bit 6 of EC register 0xfe9e LPC68CSR. |
||
The protocol is as follows: |
The protocol is as follows: |
||
Line 24: | Line 24: | ||
- The EC idle state is "IBF interrupt enabled, OBF interrupt disabled, IBF=0, OBF=0" |
- The EC idle state is "IBF interrupt enabled, OBF interrupt disabled, IBF=0, OBF=0" |
||
C1: CPU waits until IBF=0, then sends the command by writing it to port |
C1: CPU waits until IBF=0, then sends the command by writing it to port 0x6c. |
||
E1: EC receives IBF interrupt, checks |
E1: EC receives IBF interrupt, checks register 0xfe9e bit 6 and observes that it |
||
was 1, hence a new command. |
was 1, hence a new command. |
||
Line 32: | Line 32: | ||
to "new command" state. |
to "new command" state. |
||
E3: If OBF=1, EC clears it by writing 0x01 to reg |
E3: If OBF=1, EC clears it by writing 0x01 to reg 0xfe9e. This is the |
||
crucial interlock that makes the protocol predictable - this must |
crucial interlock that makes the protocol predictable - this must |
||
be done prior to clearing IBF in a later step. This step discards |
be done prior to clearing IBF in a later step. This step discards |
||
Line 38: | Line 38: | ||
any tendency for earlier command to continue generating data. |
any tendency for earlier command to continue generating data. |
||
E4: EC reads the command byte from reg |
E4: EC reads the command byte from reg 0xfe9f, clears IBF by writing 2 |
||
to reg |
to reg 0xfe9e, decodes the command, and sets a state variable accordingly. |
||
E5a: If the next step of the command is to send data to the CPU and |
E5a: If the next step of the command is to send data to the CPU and |
||
Line 62: | Line 62: | ||
C2: If the next stage of the command is an EC-to-CPU data byte, the CPU |
C2: If the next stage of the command is an EC-to-CPU data byte, the CPU |
||
polls port |
polls port 0x6c until IBF,OBF=0,1, then reads the data byte from port 0x68. |
||
IBF must be included in the test, since it makes the E3 interlock work. |
IBF must be included in the test, since it makes the E3 interlock work. |
||
If there is leftover data that causes OBF to start out as 1, step E3 will |
If there is leftover data that causes OBF to start out as 1, step E3 will |
||
Line 78: | Line 78: | ||
C3: If the next stage of the command is a CPU-to-EC data byte, the CPU |
C3: If the next stage of the command is a CPU-to-EC data byte, the CPU |
||
polls port 6c until IBF=0, then writes the data byte to port |
polls port 6c until IBF=0, then writes the data byte to port 0x68. |
||
E8: When the CPU writes the byte to the data register, the EC will |
E8: When the CPU writes the byte to the data register, the EC will |
||
receive the IBF interrupt and notice (via reg |
receive the IBF interrupt and notice (via reg 0xfe9e bit 6 = 0) that |
||
the write was to the data register. The EC then reads the byte from |
the write was to the data register. The EC then reads the byte from |
||
reg |
reg 0xfe9f, clears IBF by writing 2 to reg 0xfe9e, handles the byte |
||
according to the command sematics, and goes to step E5 to continue |
according to the command sematics, and goes to step E5 to continue |
||
processing the command. |
processing the command. |
Revision as of 01:36, 18 May 2007
This is a replacement for an EC command protocol that was giving us problems.
The objective is to transmit information back and forth between the CPU and the embedded controller (EC), via CPU I/O ports 0x68 and 0x6c. This protocol can support:
- Commands with no data transfer
- Commands that return data from the EC to the CPU
- Commands that send data from the CPU to the EC
- Commands that send data in both directions
This protocol is intended to be reliable, predictable, and efficient. Every step is interlocked in a coherent fashion, with no arbitrary delays or unnecessary steps and no unnecessary EC interrupts.
It depends on these facts:
- The EC can receive an interrupt when the CPU writes a byte to either port 0x68 or port 0x6c when IBF=0, i.e. on a 0->1 IBF transition. To enable that interrupt, bit 1 of EC register 0xfe9d LPC68CFG must be set.
- The EC can receive an interrupt when the CPU read a byte from port 0x68 when OBF=1, i.e. on a 1->0 OBF transition. To enable that interrupt, bit 0 of EC register 0xfe9d LPC68CFG must be set. (The protocol enables the OBF interrupt only as needed, during intermediate stages of multi-byte commands.)
- The EC can distinguish between a write to port 0x68 and a write to port 0x6c, via bit 6 of EC register 0xfe9e LPC68CSR.
The protocol is as follows:
Starting from a quiescent state, where IBF=0 and OBF=0:
- The EC idle state is "IBF interrupt enabled, OBF interrupt disabled, IBF=0, OBF=0"
C1: CPU waits until IBF=0, then sends the command by writing it to port 0x6c.
E1: EC receives IBF interrupt, checks register 0xfe9e bit 6 and observes that it was 1, hence a new command.
E2: EC cancels any previous commands by setting its state variables to "new command" state.
E3: If OBF=1, EC clears it by writing 0x01 to reg 0xfe9e. This is the crucial interlock that makes the protocol predictable - this must be done prior to clearing IBF in a later step. This step discards any residue from incomplete earlier commands, and step E2 cancels any tendency for earlier command to continue generating data.
E4: EC reads the command byte from reg 0xfe9f, clears IBF by writing 2 to reg 0xfe9e, decodes the command, and sets a state variable accordingly.
E5a: If the next step of the command is to send data to the CPU and there are no more steps after that, EC disables the OBF interrupt, puts the data byte in the data register, sets state to "idle", and returns from the protocol handler.
E5b: If the next step of the command is to send data to the CPU and there are more steps after that, EC enables the OBF interrupt, puts the first data byte in the data register, and returns from the protocol handler. (When the CPU later reads the byte, the EC will receive the OBF interrupt as described in E7.)
E5c: If the next step of the command is to receive data from the CPU, EC disables the OBF interrupt, and returns from the protocol handler. (When the CPU later writes the byte to the data register, the EC will perform step E8.) E5d: If there is no more data to be sent or received, the EC disables OBF interrupt, sets state to idle, and returns from the protocol handler.
C2: If the next stage of the command is an EC-to-CPU data byte, the CPU polls port 0x6c until IBF,OBF=0,1, then reads the data byte from port 0x68. IBF must be included in the test, since it makes the E3 interlock work. If there is leftover data that causes OBF to start out as 1, step E3 will drive OBF to 0 while IBF is still 1, so the IBF,OBF=0,1 test will not succeed until the EC reaches step E5a or E5b.
E6: If that byte was the last thing in the command sequence, the EC will not receive an OBF interrupt because step E5a disabled the interrupt. The EC is already back in idle state, so it does not need notification that the CPU read the byte.
E7: If there are more bytes after this to send or receive, the EC will receive an OBF interrupt (because of step E5b) and go to step E5 to continue processing the command.
C3: If the next stage of the command is a CPU-to-EC data byte, the CPU polls port 6c until IBF=0, then writes the data byte to port 0x68.
E8: When the CPU writes the byte to the data register, the EC will receive the IBF interrupt and notice (via reg 0xfe9e bit 6 = 0) that the write was to the data register. The EC then reads the byte from reg 0xfe9f, clears IBF by writing 2 to reg 0xfe9e, handles the byte according to the command sematics, and goes to step E5 to continue processing the command.
Note that there is no need for arbitrary delays.
Note: The above description of the EC behavior assumes that, if another IBF or OBF interrupt occurs while the EC is processing the steps E1..E8, the handling of that interrupt will be deferred until the end of step E5x where it "returns from the protocol handler". The new interrupt will neither cause premature re-entry to the protocol handler code (E1..E8), nor be lost. If that is not the case, some additional complexity may be necessary.