Ec specification: Difference between revisions
m (Reverted edits by 62.122.70.28 (Talk) to last revision by Quozl) |
|||
(48 intermediate revisions by 24 users not shown) | |||
Line 1: | Line 1: | ||
{{OLPC}} |
{{OLPC}} |
||
[[Category:Firmware]] |
|||
[[Category:Hardware]] |
|||
= Operational Specification of the XO embedded controller (EC) = |
= Operational Specification of the XO embedded controller (EC) = |
||
These pages will eventually document the commands and responsibilities of the EC in the XO system. |
These pages will eventually document the commands and responsibilities of the [[embedded controller]] (EC) in the XO system. an example of an embedded controller is like one in a washing machine |
||
Currently its not much more than a cut and paste from a variety of emails, trac tickets, and operational info extracted from the way the EC is known to work. Some of the descriptions are a bit odd and terse as the source is from non-native English speakers. More verbosity and better descriptions will be added as time allows. |
Currently its not much more than a cut and paste from a variety of emails, trac tickets, and operational info extracted from the way the EC is known to work. Some of the descriptions are a bit odd and terse as the source is from non-native English speakers. More verbosity and better descriptions will be added as time allows. |
||
== EC |
== EC Port 6c Command List == |
||
These commands are issued using a |
These commands are issued using a simple protocol - See [[Revised EC Port 6C Command Protocol]]. |
||
* 0x03 SPI write protect |
|||
* 0x08 Get Firmware revision byte |
|||
* 0x10 Read voltage (2 bytes) |
* 0x10 Read voltage (2 bytes) |
||
* 0x11 Read current (2 bytes) |
* 0x11 Read current (2 bytes) |
||
Line 23: | Line 23: | ||
** Bit 1: 1: battery full charged |
** Bit 1: 1: battery full charged |
||
** Bit 2: 1: battery low |
** Bit 2: 1: battery low |
||
** Bit 3: 1: battery |
** Bit 3: 1: battery error |
||
** Bit 4: 1: AC in |
** Bit 4: 1: AC in |
||
** Bit 5: 1: battery charging |
|||
** Bits 5-7 Not defined |
|||
** Bit 6: 1: battery discharging |
|||
** Bit 7: 1: battery trickle charging |
|||
* 0x16 Read Battery State of Charge (SOC) (1 byte) |
* 0x16 Read Battery State of Charge (SOC) (1 byte) |
||
* 0x17 Read Battery gas gauge chip serial number (6 bytes) |
* 0x17 Read Battery gas gauge chip serial number (6 bytes) |
||
* 0x18 Read Battery gas gauge |
* 0x18 Read Battery gas gauge EEPROM databyte |
||
** Cmd data is the EEPROM address of the byte requested |
|||
** Result is 1 byte of EEPROM data |
|||
* 0x19 Read board id (1 byte) |
* 0x19 Read board id (1 byte) |
||
* 0x1a Read SCI source (1 byte) |
* 0x1a Read SCI source (1 byte) |
||
Line 37: | Line 42: | ||
*** Battery Low |
*** Battery Low |
||
*** Battery full |
*** Battery full |
||
*** Battery |
*** Battery error |
||
** 0x04 Battery SOC Change |
** 0x04 Battery SOC Change |
||
** 0x08 Battery subsystem error |
** 0x08 Battery subsystem error |
||
** 0x10 Ebook mode change |
** 0x10 Ebook mode change |
||
** 0x20 |
** 0x20 Wake up from Wlan |
||
** 0x40 AC power plug/unplug |
|||
* 0x1b Write SCI mask (1 byte) |
* 0x1b Write SCI mask (1 byte) |
||
* 0x1c Read SCI mask (1 byte) |
* 0x1c Read SCI mask (1 byte) |
||
Line 66: | Line 72: | ||
* 0x20 Init NiMH Battery |
* 0x20 Init NiMH Battery |
||
* 0x21 Init LiFePO4 Battery |
* 0x21 Init LiFePO4 Battery |
||
* 0x22 Init Goldpeak LiFePO4 Battery |
|||
* 0x23 Set WLAN Power on/off |
|||
* 0x23 Set WLAN Power on/off - DEPRECATED! |
|||
* 0x24 Wake up WLAN |
* 0x24 Wake up WLAN |
||
* 0x25 WLAN reset |
* 0x25 WLAN reset (leaving WLAN on) |
||
* 0x26 DCON power enable/disable |
* 0x26 DCON power enable/disable |
||
** Write a 0 to disable |
|||
* 0x27?? Read power rail status |
|||
** Write a 1 to enable |
|||
** DCON status |
|||
* 0x2a Read EBOOK mode |
|||
** WLAN status |
|||
** Bit 0 EBOOK sensor status |
|||
* 0x2b Read power rail status |
|||
The following commands are an ill-considered alternative to [[#Indexed access to EC internal locations]], and might be removed in the future. |
|||
** Bit 0 WLAN status |
|||
** Bit 1 DCON status |
|||
* 0x80 // read address from mailbox |
|||
* 0x2c Read battery type |
|||
* 0x81 // write address to mailbox |
|||
** 1st Nibble (Bits 0-3) |
|||
* 0x82 // read data(word) from mailbox |
|||
*** 0001 NiMH |
|||
* 0x83 // write data(word) to mailbox |
|||
*** 0010 LiFePo4 |
|||
* 0x84 // read data(byte) from mailbox |
|||
** 2nd Nibble (Bits 4- 7) |
|||
* 0x85 // write data(byte) to mailbox |
|||
*** 0001 Goldpeak |
|||
* 0x88 // read EC RAM(word)to mailbox data referring mailbox address |
|||
*** 0010 BYD |
|||
* 0x89 // write mailbox data into EC RAM(word) referring mailbox address |
|||
* 0x2e Read Ambient temp raw |
|||
* 0x8A // read EC RAM(byte)to mailbox data referring mailbox address |
|||
* 0x2f Wakeup keyboard (Future: not-implemented) |
|||
* 0x8B // write mailbox data into EC RAM(byte) referring mailbox address |
|||
* 0x30 Read lid switch (Future: not-implemented) |
|||
* 0x31 Read 1-wire interface type |
|||
* 0x32 Set SCI inhibit |
|||
== EC Old Port 6c Command List == |
|||
** This command must be issued prior to turning off the CPU core voltage |
|||
* 0x33 Enable AutoWak |
|||
See [[#Old Port 6c Command Protocol]]. |
|||
* 0x34 Clear SCI inhibt |
|||
** If a suspend fails and MAIN_ON never goes low this command will clear the SCI inhibit. |
|||
* 0x01 1.: Set MIC_AC to high (write 0x01 to port 6c, read 0 from port 68) <br>This command is obsolete on B2 and later hardware, where MIC_AC is controlled by a 5536 GPIO |
|||
* 0x35 WLAN off |
|||
** Asserts the hardware reset line of the WLAN device. Use command 0x25 to de-assert. |
|||
* 0x02: Set MIC_AC to low (default) (write 0x01 to port 6c, read 0 from port 68) <br>This command is obsolete on B2 and later hardware, where MIC_AC is controlled by a 5536 GPIO |
|||
* 0x84 Read SCI queue |
|||
** 0x0 Empty sci |
|||
* 0x03: Active the SPI write protect (write 0x03 to port 6c, read 0 from port 68)<br> SPIWP# signal is high, then DSPIWP# signal will be low.<br><br> The DSPIWP# signal will be low forever until the ECRST# is asserted.<br> The DSPIWP# signal will not be high even 0x04 command is issued again. |
|||
** 0x01 Key press |
|||
** 0x02 Battery |
|||
* 0x04: Deactivate SPI write protect (write 0x04 to port 6c, read 0 from port 68)<br> SPIWP# signal is low (default), and DSPIWP# signal will be high.<br> Once the DSPIWP# is low, it will not be high even this command is issued again. |
|||
** 0x04 Battery state change |
|||
** 0x08 Batter error |
|||
* 0x05: Reset system (write 0x05 to port 6c, read 0 from port 68)<br> This command forces a hard reset of the EC, so that it is possible to write to SPI flash after the system is turned on again. |
|||
** 0x10 Ebook |
|||
# The SPI flash upgrade tool sends 0x05 command to the EC |
|||
** 0x20 Wlan packet |
|||
# The EC asserts EC_WP# |
|||
** 0x40 AC power |
|||
# EC_WP# will trigger ECRST# |
|||
# The whole system is reset. |
|||
# User needs to press the power button to power on. |
|||
* 0x06: Activate LED light (write 0x06 to port 6c, read 0 from port 68)<br> Sets LED_light# signal to low |
|||
* 0x07: Deactivate LED light (write 0x07 to port 6c, read 0 from port 68)<br> LED_light# signal is high (default) |
|||
* 0x08: Simple EC revision (write 0x08 to port 6c, read revision code from port 68) |
|||
* 0x09: Get chip type (write 0x08 to port 6c, read chip type from port 68) |
|||
** Type = 0x09 for 3920 (A-test boards only) |
|||
** Type = 0x00 for 3700 (B-test and later boards) |
|||
* 0x0A: Set SIRQ Quiet Mode (write 0x0a to port 6c, read 0 from port 68) |
|||
* 0x0B: Set SIRQ Continuous Mode (write 0x0b to port 6c, read 0 from port 68) |
|||
== New Port 6c Command Protocol == |
|||
Here is how the EC Command Protocol works, assuming that you are polling the I/O ports (not using interrupts): |
|||
1. Read port 6c. |
|||
1a. If bit 7 = 1, it means that a previous use of the port failed to |
|||
release it. Since the OLPC Open Firmware is single-threaded, there is no |
|||
other possible "owner" of the port, so OFW can "take it back". Write |
|||
0xff to port 6c, delay 1 millisecond, and go back to step 1. |
|||
1b. At this point, bit 7 = 0 and the port is now "owned". |
|||
1c. If bit OBF = 1, it means that there is a byte in the output buffer, so read port 68 |
|||
to consume that byte, delay 1 millisecond, reread port 6c, repeat step 1c. (This |
|||
happens because when the previous "owner" released the port by writing |
|||
0xff to port 6c, it causes OBF to go to 1 after a few hundred microseconds.) |
|||
(I have not seen any cases where it was necessary to consume more than one byte at this step.) |
|||
1d. At this point, bit 7 = 0 and OBF = 0, indicating that we have |
|||
ownership and the data buffer is empty. |
|||
2. Poll port 6c until IBF = 0 or until a timeout occurs, delaying 4 |
|||
millisecond between polls. If you do not delay between polls, timeouts |
|||
occur frequently. If you omit this step entirely, step 5 often times out. |
|||
3. Send the command by writing the command number to port 6c. |
|||
4. Poll port 6c until IBF =0 or until a timeout occurs, delaying 4 |
|||
milliseconds between polls. (This is David's step 3; after adding it, my |
|||
code started working reliably). |
|||
5. Poll port 6c until OBF=1 or until a timeout occurs, delaying 1 |
|||
millisecond between polls. |
|||
6. Read port 68 to consume the 0xff byte that the command puts in the |
|||
output buffer (this is not the result value from the command itself; it |
|||
is just a byte that seems to occur whenever you write anything to port 6c). |
|||
If you are expecting one or more bytes of return data from the command, |
|||
you must do steps 7-10 for each such byte: |
|||
7. Poll port 6c until IBF =0 or until a timeout occurs, delaying 4 |
|||
milliseconds between polls. |
|||
8. Write 0 to port 68. (Exception: for command 0x18 - Read battery gas gauge data - write 0x31 instead of 0.) |
|||
9. Poll port 6c until IBF=0 or until a timeout occurs, delaying 4 milliseconds between polls. |
|||
10. Poll port 6c until OBF=1 or until a timeout occurs, delaying 1 |
|||
millisecond between polls. |
|||
11. Read the data from port 68. |
|||
If the command requires you to write argument values, you must do steps |
|||
7a-9a for each such byte. |
|||
7a. Poll port 6c until IBF =0 or until a timeout occurs, delaying 4 |
|||
milliseconds between polls. |
|||
8a. Write data byte to port 68. |
|||
9a. Poll port 6c until IBF=0 or until a timeout occurs, delaying 4 milliseconds between polls. |
|||
When you are finished with the command: |
|||
12. Write 0xff to port 6c to release the port. |
|||
A few hundred microseconds after you perform step 11, the OBF bit will |
|||
go to 1, indicating that a data byte was placed in the buffer. You |
|||
cannot poll port 6c to determine when that byte is available for |
|||
consumption, because that will re-acquire the ownership bit. That is why |
|||
step 1b is necessary - you must consume that stray byte at the start of |
|||
the next command sequence. |
|||
== Old Port 6c Command Protocol == |
|||
The Old Port 6c Command Protocol is subset of the New Port 6c Command Protocol You do not need steps 7 - 11. The value from port 68 is step 6 is 0 instead of 0xff, except for commands 0x08 and 0x09, where it is the result data. |
|||
== EC IO Pinout == |
== EC IO Pinout == |
||
=== Model C1 === |
|||
* Pin 1: GPIOE0 EC_WP# |
|||
* Pin 2: GPIOE1 CV_SET |
|||
* Pin 3: GPIOE2 DQ |
|||
* Pin 4: GPIOE3 LED_CHG_G# |
|||
* Pin 6: GPIO00 VR_ON# |
|||
* Pin 9: GPIO01 WLAN_EN |
|||
* Pin 10: GPIO02 SWI# |
|||
* Pin 23: GPIO06 TX |
|||
* Pin 24: GPIO07 RX/BAT_L0 |
|||
* Pin 25: GPIO08 ACIN |
|||
* Pin 26: GPIO09 LED_PWR# |
|||
* Pin 27: GPIO0A LED_CHG_R# |
|||
* Pin 28: GPIO0B WAKEUP |
|||
* Pin 29: GPIO0C PWR_BUT# |
|||
* Pin 30: ECRST# |
|||
* Pin 31: GPIO0E CHG |
|||
* Pin 32: GPIO0F CC0 |
|||
* Pin 33: GPIOE8 BAT_L1 |
|||
* Pin 34: GPIAD3 SUS_ON |
|||
* Pin 35: GPIAD4 CVM |
|||
* Pin 36: GPIAD5 WAKEUP_EC |
|||
* Pin 37: GPIO10 EC->WLAN Wakeup |
|||
** Fix schematic!! |
|||
* Pin 38: GPIAD0 TEMP |
|||
* Pin 39: GPIAD1 EC_ID |
|||
* Pin 40: NC. |
|||
* Pin 43: KBCLK |
|||
* Pin 44: KBDAT |
|||
* Pin 45: TPCLK |
|||
* Pin 46: TPDAT |
|||
* Pin 47: KEY_OUT_3/ISP_CLK |
|||
* Pin 48: KEY_OUT_1/ISP_EN# |
|||
* Pin 49: SPIWP# |
|||
* Pin 50: POWER_BUTTON# |
|||
* Pin 51: WLAN_RESET# |
|||
* Pin 52: ECPWRRQST |
|||
* Pin 53: KEY_OUT_2 |
|||
* Pin 54: WAKE_PRECHG |
|||
* Pin 55: EB_MODE |
|||
* Pin 56: MAIN_ON |
|||
* Pin 57: PWR_BUT_IN |
|||
=== B1 < Model < C1 === |
|||
Not yet complete. |
|||
* Pin 6: GPIO00 VR_ON# |
* Pin 6: GPIO00 VR_ON# |
||
* Pin 9: GPIO01 WLAN_EN |
* Pin 9: GPIO01 WLAN_EN |
||
Line 225: | Line 181: | ||
* Pin 33: GPIOE8 BAT_L1 |
* Pin 33: GPIOE8 BAT_L1 |
||
* Pin |
* Pin 39: GPIAD1 EC_ID |
||
=== Board ID Values === |
=== Board ID Values === |
||
The EC is responsible for determining the motherboard ID of a laptop. At the circuit level, this is specified by the ratio of the values of two resistors (R535 and R534). Known combinations include: |
The EC is responsible for determining the motherboard ID of a laptop. At the circuit level, this is specified by the ratio of the values of two resistors (R535 and R534), providing a voltage on the EC_ID signal input to the EC. Known combinations include: |
||
<table border=1> |
<table border=1> |
||
Line 238: | Line 194: | ||
<tr><td>1/8 * 3.3V</td><td>18-27h</td><td>B4</td><td></td></tr> |
<tr><td>1/8 * 3.3V</td><td>18-27h</td><td>B4</td><td></td></tr> |
||
<tr><td></td><td>28-37h</td><td></td><td>guard band</td></tr> |
<tr><td></td><td>28-37h</td><td></td><td>guard band</td></tr> |
||
<tr><td>1/4 * 3.3V</td><td>38-47h</td><td> |
<tr><td>1/4 * 3.3V</td><td>38-47h</td><td>C1</td><td></td></tr> |
||
<tr><td></td><td>48-57h</td><td></td><td>guard band</td></tr> |
<tr><td></td><td>48-57h</td><td></td><td>guard band</td></tr> |
||
<tr><td>3/8 * 3.3V</td><td>58-67h</td><td> |
<tr><td>3/8 * 3.3V</td><td>58-67h</td><td>C2</td><td></td></tr> |
||
<tr><td></td><td>68-77h</td><td></td><td>guard band</td></tr> |
<tr><td></td><td>68-77h</td><td></td><td>guard band</td></tr> |
||
<tr><td>1/2 * 3.3V</td><td>78-87h</td><td>B2</td><td></td></tr> |
<tr><td>1/2 * 3.3V</td><td>78-87h</td><td>B2</td><td></td></tr> |
||
<tr><td></td><td>88-97h</td><td></td><td>guard band</td></tr> |
<tr><td></td><td>88-97h</td><td></td><td>guard band</td></tr> |
||
<tr><td>5/8 * 3.3V</td><td>98-A7h</td><td> |
<tr><td>5/8 * 3.3V</td><td>98-A7h</td><td>C3</td><td></td></tr> |
||
<tr><td></td><td>A8-B7h</td><td></td><td>guard band</td></tr> |
<tr><td></td><td>A8-B7h</td><td></td><td>guard band</td></tr> |
||
<tr><td>3/4 * 3.3V</td><td>B8-C7h</td><td> |
<tr><td>3/4 * 3.3V</td><td>B8-C7h</td><td>F1</td><td></td></tr> |
||
<tr><td></td><td>C8-D7h</td><td></td><td>guard band</td></tr> |
<tr><td></td><td>C8-D7h</td><td></td><td>guard band</td></tr> |
||
<tr><td>7/8 * 3.3V</td><td>D8-E7h</td><td> |
<tr><td>7/8 * 3.3V</td><td>D8-E7h</td><td>F2</td><td></td></tr> |
||
<tr><td></td><td>E8-F7h</td><td></td><td>guard band</td></tr> |
<tr><td></td><td>E8-F7h</td><td></td><td>guard band</td></tr> |
||
<tr><td>3.3V</td><td>F8-FFh</td><td> |
<tr><td>3.3V</td><td>F8-FFh</td><td>F3</td><td></td></tr> |
||
</table> |
</table> |
||
The F[123] values are place holders in the EC code which prevents EC from bricking a machine that has had the resistors changed because it has to fall back on a B1 layout. B1 IO layout detection fails to work correctly so its the default. |
|||
== KeyCodes for Buttons == |
== KeyCodes for Buttons == |
||
{| cellpadding=4 cellspacing=0 border=1 style="border-collapse:collapse" |
{| cellpadding=4 cellspacing=0 border=1 style="border-collapse:collapse" |
||
|- |
|- |
||
|| Key matrix |
|| Key matrix || Make code || Break code |
||
|- |
|- |
||
||Bit 9: KEY_DN_R, |
||Bit 9: KEY_DN_R, || {0xE0,0x66,0x00} || {0xE0,0xE6,0x00} |
||
|- |
|- |
||
||Bit 8: KEY_UP_R, |
||Bit 8: KEY_UP_R, || {0xE0,0x65,0x00} || {0xE0,0xE5,0x00} |
||
|- |
|- |
||
||Bit 7: |
||Bit 7: ROTATE || {0x69,0x00,0x00} || {0xE9,0x00,0x00} |
||
|- |
|- |
||
||Bit 6: KEY_RT_L, |
||Bit 6: KEY_RT_L, || {0x68,0x00,0x00} || {0xE8,0x00,0x00} |
||
|- |
|- |
||
||Bit 5: KEY_LF_L, |
||Bit 5: KEY_LF_L, || {0x67,0x00,0x00} || {0xE7,0x00,0x00} |
||
|- |
|- |
||
||Bit 4:KEY_DN_L, |
||Bit 4:KEY_DN_L, || {0x66,0x00,0x00} || {0xE6,0x00,0x00} |
||
|- |
|- |
||
||Bit 3: KEY_UP_L, |
||Bit 3: KEY_UP_L, || {0x65,0x00,0x00} || {0xE5,0x00,0x00} |
||
|- |
|- |
||
||Bit 2: KEY_RT_R, |
||Bit 2: KEY_RT_R, || {0xE0,0x68,0x00} || {0xE0,0xE8,0x00} |
||
|- |
|- |
||
||Bit 1: |
||Bit 1:KEY_LF_R || {0xE0,0x67,0x00} || {0xE0,0xE7,0x00} |
||
|} |
|} |
||
Line 324: | Line 282: | ||
* 0xd5 Power Off (write 0xd5 to port 66) |
* 0xd5 Power Off (write 0xd5 to port 66) |
||
* 0xd7 Host Power Cycle |
|||
* 0xd8 Keyboard stop (write 0xd8 to port 66) Useful when updating EC microcode in SPI FLASH |
|||
* |
* 0xd8 Keyboard stop (write 0xd8 to port 66) Useful when updating EC microcode in SPI FLASH (Sets GPIOE0 - EC_WP# - to low, and sets EC state to PRE_RESET). I think the GPIOE0 thing doesn't happen until the 8051 is later reawakened via the 0xff14 register. |
||
* 0xdd Keyboard pause (write 0xdd to port 66) Useful when updating manufacturing data. What this does is put the 8051 into IDLE mode so that it is not fetching instructions from SPI FLASH. It also disables the watchdog timer. However, the 8051 is configured (via the register at 0xff0c) to come out of IDLE mode when an interrupt occurs. This has the good effect that it is possible to issue the 0xdf command to resume activity (because the port 66 IBF event will wake up the 8051), but the bad effect that other interrupts, such as keyboard activity, will also wake it up. The problem with keyboard wakeup is that it could happen during the process of writing to SPI FLASH and thus corrupt the FLASH. The solution might be to mask off some interrupts so only the port66 one is enabled during this mode. |
|||
* 0xdf Keyboard resume (write 0xdf to port 66) Useful when updating manufacturing data |
* 0xdf Keyboard resume (write 0xdf to port 66) Useful when updating manufacturing data |
||
Line 336: | Line 295: | ||
For successive accesses to the same or nearby addresses, you don't have to rewrite address bytes that don't change. |
For successive accesses to the same or nearby addresses, you don't have to rewrite address bytes that don't change. |
||
This feature is disabled when the laptop is in secure mode (WP tag set), since it is a security hole. But indexed I/O will probably continue to be used for updating the SPI FLASH contents, since that has to be done when the 8051 is not running. SPI FLASH updating will be done in a secure firmware mode that happens before the user has the ability to get interactive control. |
|||
We will probably disable this feature in the future, since it is a security hole. |
|||
== Revised Protocol == |
|||
[[Revised EC Port 6C Command Protocol]] |
|||
==Register Settings== |
|||
[[EC Register Settings]] |
|||
[[Category:EC]] |
|||
[[Category:Firmware]] |
|||
[[Category:Keyboard]] |
Latest revision as of 08:33, 13 September 2010
Operational Specification of the XO embedded controller (EC)
These pages will eventually document the commands and responsibilities of the embedded controller (EC) in the XO system. an example of an embedded controller is like one in a washing machine Currently its not much more than a cut and paste from a variety of emails, trac tickets, and operational info extracted from the way the EC is known to work. Some of the descriptions are a bit odd and terse as the source is from non-native English speakers. More verbosity and better descriptions will be added as time allows.
EC Port 6c Command List
These commands are issued using a simple protocol - See Revised EC Port 6C Command Protocol.
- 0x03 SPI write protect
- 0x08 Get Firmware revision byte
- 0x10 Read voltage (2 bytes)
- 0x11 Read current (2 bytes)
- 0x12 Read ACR (2 bytes)
- 0x13 Read battery temperature (2 bytes)
- 0x14 Read ambient temperature (2 bytes)
- 0x15 Read battery status (1 byte)
- Bit 0: 1: battery exists
- Bit 1: 1: battery full charged
- Bit 2: 1: battery low
- Bit 3: 1: battery error
- Bit 4: 1: AC in
- Bit 5: 1: battery charging
- Bit 6: 1: battery discharging
- Bit 7: 1: battery trickle charging
- 0x16 Read Battery State of Charge (SOC) (1 byte)
- 0x17 Read Battery gas gauge chip serial number (6 bytes)
- 0x18 Read Battery gas gauge EEPROM databyte
- Cmd data is the EEPROM address of the byte requested
- Result is 1 byte of EEPROM data
- 0x19 Read board id (1 byte)
- 0x1a Read SCI source (1 byte)
- 0x01 Game button
- 0x02 Battery Status Change. Generated for any of:
- AC plugged/unplugged
- Battery inserted/removed
- Battery Low
- Battery full
- Battery error
- 0x04 Battery SOC Change
- 0x08 Battery subsystem error
- 0x10 Ebook mode change
- 0x20 Wake up from Wlan
- 0x40 AC power plug/unplug
- 0x1b Write SCI mask (1 byte)
- 0x1c Read SCI mask (1 byte)
- 0x1d Game key status (2 bytes) 9 bits of key status. 1 indicates key is depressed.
- Bit 1: KEY_LR_R
- Bit 2: KEY_RT_R
- Bit 3: KEY_UP_L
- Bit 4: KEY_DN_L
- Bit 5: KEY_LF_L
- Bit 6: KEY_RT_L
- Bit 7: KEY_COLOR/MONO
- Bit 8: KEY_UP_R
- Bit 9: KEY_DN_R
- 0x1e Set date (day/mon/year)
- Need details for using this.
- 0x1f Read battery subsystem error code (1 byte)
- 0x02 Pack info fail (LiFePO4 & NiMH)
- 0x04 Over voltage checking fail (LiFePO4)
- 0x05 Over temperature (58C) (LiFePO4)
- 0x06 Gauge stop or sensor break (LiFePO4 & NiMH)
- 0x07 Sensor out of control (NiMH)
- 0x09 Battery ID fail & temperature > 52C
- 0x10 ACR fail (NiMH)
- 0x20 Init NiMH Battery
- 0x21 Init LiFePO4 Battery
- 0x22 Init Goldpeak LiFePO4 Battery
- 0x23 Set WLAN Power on/off - DEPRECATED!
- 0x24 Wake up WLAN
- 0x25 WLAN reset (leaving WLAN on)
- 0x26 DCON power enable/disable
- Write a 0 to disable
- Write a 1 to enable
- 0x2a Read EBOOK mode
- Bit 0 EBOOK sensor status
- 0x2b Read power rail status
- Bit 0 WLAN status
- Bit 1 DCON status
- 0x2c Read battery type
- 1st Nibble (Bits 0-3)
- 0001 NiMH
- 0010 LiFePo4
- 2nd Nibble (Bits 4- 7)
- 0001 Goldpeak
- 0010 BYD
- 1st Nibble (Bits 0-3)
- 0x2e Read Ambient temp raw
- 0x2f Wakeup keyboard (Future: not-implemented)
- 0x30 Read lid switch (Future: not-implemented)
- 0x31 Read 1-wire interface type
- 0x32 Set SCI inhibit
- This command must be issued prior to turning off the CPU core voltage
- 0x33 Enable AutoWak
- 0x34 Clear SCI inhibt
- If a suspend fails and MAIN_ON never goes low this command will clear the SCI inhibit.
- 0x35 WLAN off
- Asserts the hardware reset line of the WLAN device. Use command 0x25 to de-assert.
- 0x84 Read SCI queue
- 0x0 Empty sci
- 0x01 Key press
- 0x02 Battery
- 0x04 Battery state change
- 0x08 Batter error
- 0x10 Ebook
- 0x20 Wlan packet
- 0x40 AC power
EC IO Pinout
Model C1
- Pin 1: GPIOE0 EC_WP#
- Pin 2: GPIOE1 CV_SET
- Pin 3: GPIOE2 DQ
- Pin 4: GPIOE3 LED_CHG_G#
- Pin 6: GPIO00 VR_ON#
- Pin 9: GPIO01 WLAN_EN
- Pin 10: GPIO02 SWI#
- Pin 23: GPIO06 TX
- Pin 24: GPIO07 RX/BAT_L0
- Pin 25: GPIO08 ACIN
- Pin 26: GPIO09 LED_PWR#
- Pin 27: GPIO0A LED_CHG_R#
- Pin 28: GPIO0B WAKEUP
- Pin 29: GPIO0C PWR_BUT#
- Pin 30: ECRST#
- Pin 31: GPIO0E CHG
- Pin 32: GPIO0F CC0
- Pin 33: GPIOE8 BAT_L1
- Pin 34: GPIAD3 SUS_ON
- Pin 35: GPIAD4 CVM
- Pin 36: GPIAD5 WAKEUP_EC
- Pin 37: GPIO10 EC->WLAN Wakeup
- Fix schematic!!
- Pin 38: GPIAD0 TEMP
- Pin 39: GPIAD1 EC_ID
- Pin 40: NC.
- Pin 43: KBCLK
- Pin 44: KBDAT
- Pin 45: TPCLK
- Pin 46: TPDAT
- Pin 47: KEY_OUT_3/ISP_CLK
- Pin 48: KEY_OUT_1/ISP_EN#
- Pin 49: SPIWP#
- Pin 50: POWER_BUTTON#
- Pin 51: WLAN_RESET#
- Pin 52: ECPWRRQST
- Pin 53: KEY_OUT_2
- Pin 54: WAKE_PRECHG
- Pin 55: EB_MODE
- Pin 56: MAIN_ON
- Pin 57: PWR_BUT_IN
B1 < Model < C1
Not yet complete.
- Pin 6: GPIO00 VR_ON#
- Pin 9: GPIO01 WLAN_EN
- Pin 10: GPIO02 SWI#
- Pin 23: GPIO06 TX
- Pin 24: GPIO07 RX/BAT_L0
- Pin 25: GPIO08 EC_EAPD
- Pin 26: GPIO09 LED_PWR#
- Pin 27: GPIO0A LED_CHG_R#
- Pin 28: GPIO0B WAKEUP
- Pin 29: GPIO0C PWR_BUT#
- Pin 31: GPIO0E CHG
- Pin 32: GPIO0F CC0
- Pin 37: GPIO10 EC->WLAN Wakeup
- Fix schematic!!
- Pin 1: GPIOE0 EC_WP#
- Pin 2: GPIOE1 CV_SET
- Pin 3: GPIOE2 DQ
- Pin 4: GPIOE3 LED_CHG_G
- Pin 33: GPIOE8 BAT_L1
- Pin 39: GPIAD1 EC_ID
Board ID Values
The EC is responsible for determining the motherboard ID of a laptop. At the circuit level, this is specified by the ratio of the values of two resistors (R535 and R534), providing a voltage on the EC_ID signal input to the EC. Known combinations include:
Voltage | EC Value | Board ID | Comments |
---|---|---|---|
0 | 00-07h | B3 | |
08-17h | guard band | ||
1/8 * 3.3V | 18-27h | B4 | |
28-37h | guard band | ||
1/4 * 3.3V | 38-47h | C1 | |
48-57h | guard band | ||
3/8 * 3.3V | 58-67h | C2 | |
68-77h | guard band | ||
1/2 * 3.3V | 78-87h | B2 | |
88-97h | guard band | ||
5/8 * 3.3V | 98-A7h | C3 | |
A8-B7h | guard band | ||
3/4 * 3.3V | B8-C7h | F1 | |
C8-D7h | guard band | ||
7/8 * 3.3V | D8-E7h | F2 | |
E8-F7h | guard band | ||
3.3V | F8-FFh | F3 |
The F[123] values are place holders in the EC code which prevents EC from bricking a machine that has had the resistors changed because it has to fall back on a B1 layout. B1 IO layout detection fails to work correctly so its the default.
KeyCodes for Buttons
Key matrix | Make code | Break code |
Bit 9: KEY_DN_R, | {0xE0,0x66,0x00} | {0xE0,0xE6,0x00} |
Bit 8: KEY_UP_R, | {0xE0,0x65,0x00} | {0xE0,0xE5,0x00} |
Bit 7: ROTATE | {0x69,0x00,0x00} | {0xE9,0x00,0x00} |
Bit 6: KEY_RT_L, | {0x68,0x00,0x00} | {0xE8,0x00,0x00} |
Bit 5: KEY_LF_L, | {0x67,0x00,0x00} | {0xE7,0x00,0x00} |
Bit 4:KEY_DN_L, | {0x66,0x00,0x00} | {0xE6,0x00,0x00} |
Bit 3: KEY_UP_L, | {0x65,0x00,0x00} | {0xE5,0x00,0x00} |
Bit 2: KEY_RT_R, | {0xE0,0x68,0x00} | {0xE0,0xE8,0x00} |
Bit 1:KEY_LF_R | {0xE0,0x67,0x00} | {0xE0,0xE7,0x00} |
Firmware Address Map
0x00000 - 0ffff EC 0x10000 - dffff OFW 0xe0000 - ef7ff Reserved 0xef800 - effff Manufacturing data 0xf0000 - fffff Early startup code
Port 66 Commands
There are also some EC commands that use ports 0x66 and 0x62. Some of these are standard ACPI commands as defined in the external ACPI spec, others are custom.
The port 66 protocol is essentially the standard ACPI EC interface protocol.
1. Wait for port66.IBF = 0
2. Write command byte to port 66.
3. For each outgoing data or address byte:
3a. Wait for port66.IBF = 0
3b. Write data or address byte to port 62.
4. For each incoming data byte:
4a. Wait for port66.OBF = 1
4b. Read data byte from port 62.
5. If the command requires no data or address bytes, you can determine when the command was accepted/executed by waiting for port66.IBF=0.
ACPI-defined port 66 commands
- 0x80 Read EC (write 0x80 to port 66, write address byte to port 62, read data byte from port 62)
- 0x81 Write EC (write 0x81 to port 66, write address byte to port 62, write data byte to port 62)
- 0x82 Burst Enable (write 0x82 to port 66, read data byte from port 62 - the data byte is "burst ACK", value 0x90)
- 0x83 Burst Disable (write 0x83 to port 66, wait for port66.IBF=0)
- 0x84 Query EC (i.e. read SCI event queue) (write 0x84 to port 66, read data byte from port 62). When the data byte is 0, it means that the SCI event queue is empty.
OLPC-specific port 66 commands
- 0xd5 Power Off (write 0xd5 to port 66)
- 0xd7 Host Power Cycle
- 0xd8 Keyboard stop (write 0xd8 to port 66) Useful when updating EC microcode in SPI FLASH (Sets GPIOE0 - EC_WP# - to low, and sets EC state to PRE_RESET). I think the GPIOE0 thing doesn't happen until the 8051 is later reawakened via the 0xff14 register.
- 0xdd Keyboard pause (write 0xdd to port 66) Useful when updating manufacturing data. What this does is put the 8051 into IDLE mode so that it is not fetching instructions from SPI FLASH. It also disables the watchdog timer. However, the 8051 is configured (via the register at 0xff0c) to come out of IDLE mode when an interrupt occurs. This has the good effect that it is possible to issue the 0xdf command to resume activity (because the port 66 IBF event will wake up the 8051), but the bad effect that other interrupts, such as keyboard activity, will also wake it up. The problem with keyboard wakeup is that it could happen during the process of writing to SPI FLASH and thus corrupt the FLASH. The solution might be to mask off some interrupts so only the port66 one is enabled during this mode.
- 0xdf Keyboard resume (write 0xdf to port 66) Useful when updating manufacturing data
Indexed access to EC internal locations
You can access some internal locations inside the EC with an index/data protocol. The "address" is a 16-bit number.
Write address.hi_byte to port 0x381, write address.lo_byte to port 0x382, and read or write the data byte at port 0x383.
For successive accesses to the same or nearby addresses, you don't have to rewrite address bytes that don't change.
This feature is disabled when the laptop is in secure mode (WP tag set), since it is a security hole. But indexed I/O will probably continue to be used for updating the SPI FLASH contents, since that has to be done when the 8051 is not running. SPI FLASH updating will be done in a secure firmware mode that happens before the user has the ability to get interactive control.
Revised Protocol
Revised EC Port 6C Command Protocol