From 89e3f3894fd95bfc1511c142fb30f5a30b7ba709 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 10 Jan 2020 08:07:18 -0700 Subject: [PATCH] Add IT5570E support with correct I2C channel --- src/board/system76/lemp9/board.mk | 2 +- src/ec/it5570e/.i2c.c.swp | Bin 0 -> 12288 bytes src/ec/it5570e/ec.mk | 1 + src/ec/it5570e/gpio.c | 17 +++ src/ec/it5570e/i2c.c | 132 +++++++++++++++++++++ src/ec/it5570e/include/ec/gctrl.h | 10 ++ src/ec/it5570e/include/ec/gpio.h | 178 +++++++++++++++++++++++++++++ src/ec/it5570e/include/ec/i2c.h | 8 ++ src/ec/it5570e/include/ec/kbc.h | 42 +++++++ src/ec/it5570e/include/ec/kbscan.h | 47 ++++++++ src/ec/it5570e/include/ec/peci.h | 17 +++ src/ec/it5570e/include/ec/pmc.h | 40 +++++++ src/ec/it5570e/include/ec/ps2.h | 37 ++++++ src/ec/it5570e/include/ec/pwm.h | 63 ++++++++++ src/ec/it5570e/include/ec/smbus.h | 85 ++++++++++++++ src/ec/it5570e/kbc.c | 41 +++++++ src/ec/it5570e/pmc.c | 37 ++++++ src/ec/it5570e/ps2.c | 81 +++++++++++++ src/ec/it5570e/signature.c | 7 ++ src/ec/it8587e/i2c.c | 50 ++++---- src/ec/it8587e/include/ec/smbus.h | 4 +- 21 files changed, 874 insertions(+), 25 deletions(-) create mode 100644 src/ec/it5570e/.i2c.c.swp create mode 100644 src/ec/it5570e/ec.mk create mode 100644 src/ec/it5570e/gpio.c create mode 100644 src/ec/it5570e/i2c.c create mode 100644 src/ec/it5570e/include/ec/gctrl.h create mode 100644 src/ec/it5570e/include/ec/gpio.h create mode 100644 src/ec/it5570e/include/ec/i2c.h create mode 100644 src/ec/it5570e/include/ec/kbc.h create mode 100644 src/ec/it5570e/include/ec/kbscan.h create mode 100644 src/ec/it5570e/include/ec/peci.h create mode 100644 src/ec/it5570e/include/ec/pmc.h create mode 100644 src/ec/it5570e/include/ec/ps2.h create mode 100644 src/ec/it5570e/include/ec/pwm.h create mode 100644 src/ec/it5570e/include/ec/smbus.h create mode 100644 src/ec/it5570e/kbc.c create mode 100644 src/ec/it5570e/pmc.c create mode 100644 src/ec/it5570e/ps2.c create mode 100644 src/ec/it5570e/signature.c diff --git a/src/board/system76/lemp9/board.mk b/src/board/system76/lemp9/board.mk index ecd2c32..8fc1762 100644 --- a/src/board/system76/lemp9/board.mk +++ b/src/board/system76/lemp9/board.mk @@ -1,4 +1,4 @@ -EC=it8587e +EC=it5570e # Add keymaps to include INCLUDE+=$(wildcard $(BOARD_DIR)/keymap/*.h) diff --git a/src/ec/it5570e/.i2c.c.swp b/src/ec/it5570e/.i2c.c.swp new file mode 100644 index 0000000000000000000000000000000000000000..b6ec54bd75f1bb17ac9e389ab6819c47934c6c5c GIT binary patch literal 12288 zcmeI2Uu+ab9LEO%DFSLRQKHcdV#w9D+@A(P+Jcl`qz0_CR|yC-dwX;3(!1SecaEb< z5fc;ty@<*ynqYj@=!=QI`2YcZ(5MMMk@#Zt37_-<hsjG^rgo2H63?$$$@9p z!0ZdIb5fYn%L+5=xhCB#xqbVNoXA=QbDO!Ok+d^aAXQ-b3N&Q3Z|4TqU&!a^kI z<_~O~T)v(3jZ}eDfmDH1fmDH1fmDH1fmDH1fjd?KIk$qn3h(a+O=N5C+66g&hT1na?iOUcn8dYqhJ(d!A8&p)`06>@CCdEs$df2 zz)JA<8mu2&2A_Zha14xtLx6)WaN}-h2;KlA;4yG(HDf=6Z@@=Dg5zKe6u~O++bYJc zfe*n2@BugnronUI8L$gH4SGN~$begjf$zXIa1~qxbwIJP3H(2=g@pyiak)Y^T$|%B zP^P47w6`T&mi?T3fu^xN!<3d|XDWs?dU;LQ({iSlSB;t{x(AqLOW&cUYe|u5;Bn`a z_m2&a3=c4B z)K@mk$1x!<&r88{qgCY@a>HMVZVb&+ORzzGncV4oE|=qHcm@h|d(w~%4`S)J=uW%n z3Qx#PuvFbi^GK^MoQC8>Lp(?G={`6%TIIUeG0lc6D!qKxs?~U8uef1Xv@^nW9k*p5 z?r;2wCMjcuvk6Dxk6HoW3b7_id#8qvl!{X$W6u|(zR~N-Ka!1C99#4%dyKmDwZH`; zhv`RsZ%Idj1@k2oqoIqc=6AMxS{xtm?4vIW{|^e%M1dR>JCGxktLnJn*74E8zNyma z!Q$9tX`r=dyLqnl(AO9BjdG{IfaKBJI~23PXkxl_jwvU?$)WvW!;&0M_<~WEf;oyXsel*zQsnX;2e}t3yCKe9m=D;dz+iv}~^!euONYI59iM$o^<9i^hE1p3v6vrC39_uTWNgn#DTq(7DlDwQuade zGyY=2kiew0T{Hp#tIkIfHpo}K)Bc1gcB@#F8g%uQ500xKdO$vuIzNBf2xtqZRu7ev#=| zVCWUh5$Mxa!?Z=ZC&O9y;q}of4+^5Hrc@G9Stt~F-Km79rJqm1UT>u>-aOO_*xT4^ z`Nn7<8M;kriutu@S<*R%lyhY(yC}pu=Tj@z5X0mMX3>e@M;Gh~w`!Pb&8h}b#_PeV z`r^CC707PnO&#Ale&_8|5>icD9_;($!$51!SjfYq9+MMCkapoHc-lH&eOIwVRm--# z_~A$2V%^E&snZ?{rWI2b`rmB2UUt|HHGNnM)VHEvqSO?q2wN%w9ta*pgt`@5&Hk4y zT)_zuZS+f$+J{85ay#0H0}ze)Sqx{3eAjUL%+0ZEwlp>}wu|JzN3%eYIAzot0oR%od-`d=QM&z%4O literal 0 HcmV?d00001 diff --git a/src/ec/it5570e/ec.mk b/src/ec/it5570e/ec.mk new file mode 100644 index 0000000..1aa8151 --- /dev/null +++ b/src/ec/it5570e/ec.mk @@ -0,0 +1 @@ +ARCH=8051 diff --git a/src/ec/it5570e/gpio.c b/src/ec/it5570e/gpio.c new file mode 100644 index 0000000..a0118f8 --- /dev/null +++ b/src/ec/it5570e/gpio.c @@ -0,0 +1,17 @@ +#include + +bool gpio_get(struct Gpio * gpio) { + if (*(gpio->data) & gpio->value) { + return true; + } else { + return false; + } +} + +void gpio_set(struct Gpio * gpio, bool value) { + if (value) { + *(gpio->data) |= gpio->value; + } else { + *(gpio->data) &= ~(gpio->value); + } +} diff --git a/src/ec/it5570e/i2c.c b/src/ec/it5570e/i2c.c new file mode 100644 index 0000000..e1a6557 --- /dev/null +++ b/src/ec/it5570e/i2c.c @@ -0,0 +1,132 @@ +#include + +#include +#include + +//TODO: find best value +#define I2C_TIMEOUT 10000 + +#define HOSTA HOSTAE +#define HOCTL HOCTLE +#define HOCTL2 HOCTL2E +#define HOBDB HOBDBE +#define TRASLA TRASLAE + +void i2c_reset(bool kill) { + if (HOSTA & HOSTA_BUSY) { + // Set kill bit + if (kill) HOCTL |= (1 << 1); + // Wait for host to finish + while (HOSTA & HOSTA_BUSY) {} + } + // Clear status register + HOSTA = HOSTA; + // Clear current command + HOCTL = 0; + // Disable host interface + HOCTL2 = 0; +} + +int i2c_start(uint8_t addr, bool read) { + // If we are already in a transaction + if (HOSTA & HOSTA_BYTE_DONE) { + // If we are switching direction + if ((TRASLA & 1) != read) { + // If we are switching to read mode + if (read) { + // Enable direction switch + HOCTL2 |= (1 << 3) | (1 << 2); + } else { + // Unsupported! + i2c_reset(true); + return -1; + } + } + } else { + i2c_reset(true); + + // Enable host controller with i2c compatibility + HOCTL2 = (1 << 1) | 1; + + // Set address + TRASLA = (addr << 1) | read; + } + + return 0; +} + +void i2c_stop(void) { + // Disable i2c compatibility + HOCTL2 &= ~(1 << 1); + // Clear status + HOSTA = HOSTA; + + i2c_reset(false); +} + +static int i2c_transaction(uint8_t * data, int length, bool read) { + int i; + for (i = 0; i < length; i++) { + if (read) { + // If last byte + if ((i + 1) == length) { + // Set last byte bit + HOCTL |= (1 << 5); + } + } else { + // Write byte + HOBDB = data[i]; + } + + // If we are already in a transaction + if (HOSTA & HOSTA_BYTE_DONE) { + // Clear status to process next byte + HOSTA = HOSTA; + } else { + // Start new transaction + HOCTL = (1 << 6) | (0b111 << 2); + } + + // If we are waiting on direction switch + if (HOCTL2 & (1 << 2)) { + // Complete direction switch + HOCTL2 &= ~(1 << 2); + } + + // Wait for byte done, timeout, or error + uint8_t status; + uint32_t timeout = I2C_TIMEOUT; + for(timeout = I2C_TIMEOUT; timeout > 0; timeout--) { + status = HOSTA; + // If error occured, kill transaction and return error + if (status & HOSTA_ERR) { + i2c_reset(true); + return -(int)(status); + } else + // If byte done, break + if (status & HOSTA_BYTE_DONE) { + break; + } + } + // If timeout occured, kill transaction and return error + if (timeout == 0) { + i2c_reset(true); + return -(0x1000 | (int)status); + } + + if (read) { + // Read byte + data[i] = HOBDB; + } + } + + return i; +} + +int i2c_read(uint8_t * data, int length) { + return i2c_transaction(data, length, true); +} + +int i2c_write(uint8_t * data, int length) { + return i2c_transaction(data, length, false); +} diff --git a/src/ec/it5570e/include/ec/gctrl.h b/src/ec/it5570e/include/ec/gctrl.h new file mode 100644 index 0000000..28882c2 --- /dev/null +++ b/src/ec/it5570e/include/ec/gctrl.h @@ -0,0 +1,10 @@ +#ifndef _EC_GCTRL_H +#define _EC_GCTRL_H + +#include + +volatile uint8_t __xdata __at(0x2006) RSTS; +volatile uint8_t __xdata __at(0x200A) BADRSEL; +volatile uint8_t __xdata __at(0x200D) SPCTRL1; + +#endif // _EC_GCTRL_H diff --git a/src/ec/it5570e/include/ec/gpio.h b/src/ec/it5570e/include/ec/gpio.h new file mode 100644 index 0000000..e9a1605 --- /dev/null +++ b/src/ec/it5570e/include/ec/gpio.h @@ -0,0 +1,178 @@ +#ifndef _EC_GPIO_H +#define _EC_GPIO_H + +#include +#include + +struct Gpio { + volatile uint8_t __xdata * data; + volatile uint8_t __xdata * mirror; + volatile uint8_t __xdata * control; + uint8_t value; +}; + +#define GPIO(BLOCK, NUMBER) { \ + .data = &GPDR ## BLOCK, \ + .mirror = &GPDMR ## BLOCK, \ + .control = &GPCR ## BLOCK ## NUMBER, \ + .value = (1 << NUMBER), \ +} + +bool gpio_get(struct Gpio * gpio); +void gpio_set(struct Gpio * gpio, bool value); + +volatile uint8_t __xdata __at(0x1600) GCR; +volatile uint8_t __xdata __at(0x16F0) GCR1; +volatile uint8_t __xdata __at(0x16F1) GCR2; +volatile uint8_t __xdata __at(0x16F2) GCR3; +volatile uint8_t __xdata __at(0x16F3) GCR4; +volatile uint8_t __xdata __at(0x16F4) GCR5; +volatile uint8_t __xdata __at(0x16F5) GCR6; +volatile uint8_t __xdata __at(0x16F6) GCR7; +volatile uint8_t __xdata __at(0x16F7) GCR8; +volatile uint8_t __xdata __at(0x16F8) GCR9; +volatile uint8_t __xdata __at(0x16F9) GCR10; +volatile uint8_t __xdata __at(0x16FA) GCR11; +volatile uint8_t __xdata __at(0x16FB) GCR12; +volatile uint8_t __xdata __at(0x16FC) GCR13; +volatile uint8_t __xdata __at(0x16FD) GCR14; +volatile uint8_t __xdata __at(0x16FE) GCR15; +volatile uint8_t __xdata __at(0x16E0) GCR16; +volatile uint8_t __xdata __at(0x16E1) GCR17; +volatile uint8_t __xdata __at(0x16E2) GCR18; + +volatile uint8_t __xdata __at(0x1601) GPDRA; +volatile uint8_t __xdata __at(0x1602) GPDRB; +volatile uint8_t __xdata __at(0x1603) GPDRC; +volatile uint8_t __xdata __at(0x1604) GPDRD; +volatile uint8_t __xdata __at(0x1605) GPDRE; +volatile uint8_t __xdata __at(0x1606) GPDRF; +volatile uint8_t __xdata __at(0x1607) GPDRG; +volatile uint8_t __xdata __at(0x1608) GPDRH; +volatile uint8_t __xdata __at(0x1609) GPDRI; +volatile uint8_t __xdata __at(0x160A) GPDRJ; +volatile uint8_t __xdata __at(0x160D) GPDRM; + +volatile uint8_t __xdata __at(0x1661) GPDMRA; +volatile uint8_t __xdata __at(0x1662) GPDMRB; +volatile uint8_t __xdata __at(0x1663) GPDMRC; +volatile uint8_t __xdata __at(0x1664) GPDMRD; +volatile uint8_t __xdata __at(0x1665) GPDMRE; +volatile uint8_t __xdata __at(0x1666) GPDMRF; +volatile uint8_t __xdata __at(0x1667) GPDMRG; +volatile uint8_t __xdata __at(0x1668) GPDMRH; +volatile uint8_t __xdata __at(0x1669) GPDMRI; +volatile uint8_t __xdata __at(0x166A) GPDMRJ; +volatile uint8_t __xdata __at(0x166D) GPDMRM; + +volatile uint8_t __xdata __at(0x1671) GPOTA; +volatile uint8_t __xdata __at(0x1672) GPOTB; +volatile uint8_t __xdata __at(0x1673) GPOTC; +volatile uint8_t __xdata __at(0x1674) GPOTD; +volatile uint8_t __xdata __at(0x1675) GPOTE; +volatile uint8_t __xdata __at(0x1676) GPOTF; +volatile uint8_t __xdata __at(0x1677) GPOTG; +volatile uint8_t __xdata __at(0x1678) GPOTH; +volatile uint8_t __xdata __at(0x1679) GPOTI; +volatile uint8_t __xdata __at(0x167A) GPOTJ; +// GPOTM does not exist + +volatile uint8_t __xdata __at(0x1610) GPCRA0; +volatile uint8_t __xdata __at(0x1611) GPCRA1; +volatile uint8_t __xdata __at(0x1612) GPCRA2; +volatile uint8_t __xdata __at(0x1613) GPCRA3; +volatile uint8_t __xdata __at(0x1614) GPCRA4; +volatile uint8_t __xdata __at(0x1615) GPCRA5; +volatile uint8_t __xdata __at(0x1616) GPCRA6; +volatile uint8_t __xdata __at(0x1617) GPCRA7; + +volatile uint8_t __xdata __at(0x1618) GPCRB0; +volatile uint8_t __xdata __at(0x1619) GPCRB1; +volatile uint8_t __xdata __at(0x161A) GPCRB2; +volatile uint8_t __xdata __at(0x161B) GPCRB3; +volatile uint8_t __xdata __at(0x161C) GPCRB4; +volatile uint8_t __xdata __at(0x161D) GPCRB5; +volatile uint8_t __xdata __at(0x161E) GPCRB6; +volatile uint8_t __xdata __at(0x161F) GPCRB7; + +volatile uint8_t __xdata __at(0x1620) GPCRC0; +volatile uint8_t __xdata __at(0x1621) GPCRC1; +volatile uint8_t __xdata __at(0x1622) GPCRC2; +volatile uint8_t __xdata __at(0x1623) GPCRC3; +volatile uint8_t __xdata __at(0x1624) GPCRC4; +volatile uint8_t __xdata __at(0x1625) GPCRC5; +volatile uint8_t __xdata __at(0x1626) GPCRC6; +volatile uint8_t __xdata __at(0x1627) GPCRC7; + +volatile uint8_t __xdata __at(0x1628) GPCRD0; +volatile uint8_t __xdata __at(0x1629) GPCRD1; +volatile uint8_t __xdata __at(0x162A) GPCRD2; +volatile uint8_t __xdata __at(0x162B) GPCRD3; +volatile uint8_t __xdata __at(0x162C) GPCRD4; +volatile uint8_t __xdata __at(0x162D) GPCRD5; +volatile uint8_t __xdata __at(0x162E) GPCRD6; +volatile uint8_t __xdata __at(0x162F) GPCRD7; + +volatile uint8_t __xdata __at(0x1630) GPCRE0; +volatile uint8_t __xdata __at(0x1631) GPCRE1; +volatile uint8_t __xdata __at(0x1632) GPCRE2; +volatile uint8_t __xdata __at(0x1633) GPCRE3; +volatile uint8_t __xdata __at(0x1634) GPCRE4; +volatile uint8_t __xdata __at(0x1635) GPCRE5; +volatile uint8_t __xdata __at(0x1636) GPCRE6; +volatile uint8_t __xdata __at(0x1637) GPCRE7; + +volatile uint8_t __xdata __at(0x1638) GPCRF0; +volatile uint8_t __xdata __at(0x1639) GPCRF1; +volatile uint8_t __xdata __at(0x163A) GPCRF2; +volatile uint8_t __xdata __at(0x163B) GPCRF3; +volatile uint8_t __xdata __at(0x163C) GPCRF4; +volatile uint8_t __xdata __at(0x163D) GPCRF5; +volatile uint8_t __xdata __at(0x163E) GPCRF6; +volatile uint8_t __xdata __at(0x163F) GPCRF7; + +volatile uint8_t __xdata __at(0x1640) GPCRG0; +volatile uint8_t __xdata __at(0x1641) GPCRG1; +volatile uint8_t __xdata __at(0x1642) GPCRG2; +volatile uint8_t __xdata __at(0x1643) GPCRG3; +volatile uint8_t __xdata __at(0x1644) GPCRG4; +volatile uint8_t __xdata __at(0x1645) GPCRG5; +volatile uint8_t __xdata __at(0x1646) GPCRG6; +volatile uint8_t __xdata __at(0x1647) GPCRG7; + +volatile uint8_t __xdata __at(0x1648) GPCRH0; +volatile uint8_t __xdata __at(0x1649) GPCRH1; +volatile uint8_t __xdata __at(0x164A) GPCRH2; +volatile uint8_t __xdata __at(0x164B) GPCRH3; +volatile uint8_t __xdata __at(0x164C) GPCRH4; +volatile uint8_t __xdata __at(0x164D) GPCRH5; +volatile uint8_t __xdata __at(0x164E) GPCRH6; +volatile uint8_t __xdata __at(0x164F) GPCRH7; + +volatile uint8_t __xdata __at(0x1650) GPCRI0; +volatile uint8_t __xdata __at(0x1651) GPCRI1; +volatile uint8_t __xdata __at(0x1652) GPCRI2; +volatile uint8_t __xdata __at(0x1653) GPCRI3; +volatile uint8_t __xdata __at(0x1654) GPCRI4; +volatile uint8_t __xdata __at(0x1655) GPCRI5; +volatile uint8_t __xdata __at(0x1656) GPCRI6; +volatile uint8_t __xdata __at(0x1657) GPCRI7; + +volatile uint8_t __xdata __at(0x1658) GPCRJ0; +volatile uint8_t __xdata __at(0x1659) GPCRJ1; +volatile uint8_t __xdata __at(0x165A) GPCRJ2; +volatile uint8_t __xdata __at(0x165B) GPCRJ3; +volatile uint8_t __xdata __at(0x165C) GPCRJ4; +volatile uint8_t __xdata __at(0x165D) GPCRJ5; +volatile uint8_t __xdata __at(0x165E) GPCRJ6; +volatile uint8_t __xdata __at(0x165F) GPCRJ7; + +volatile uint8_t __xdata __at(0x16A0) GPCRM0; +volatile uint8_t __xdata __at(0x16A1) GPCRM1; +volatile uint8_t __xdata __at(0x16A2) GPCRM2; +volatile uint8_t __xdata __at(0x16A3) GPCRM3; +volatile uint8_t __xdata __at(0x16A4) GPCRM4; +volatile uint8_t __xdata __at(0x16A5) GPCRM5; +volatile uint8_t __xdata __at(0x16A6) GPCRM6; + +#endif // _EC_GPIO_H diff --git a/src/ec/it5570e/include/ec/i2c.h b/src/ec/it5570e/include/ec/i2c.h new file mode 100644 index 0000000..7b1af45 --- /dev/null +++ b/src/ec/it5570e/include/ec/i2c.h @@ -0,0 +1,8 @@ +#ifndef _EC_I2C_H +#define _EC_I2C_H + +#include + +void i2c_reset(bool kill); + +#endif // _EC_I2C_H diff --git a/src/ec/it5570e/include/ec/kbc.h b/src/ec/it5570e/include/ec/kbc.h new file mode 100644 index 0000000..b8bd8d9 --- /dev/null +++ b/src/ec/it5570e/include/ec/kbc.h @@ -0,0 +1,42 @@ +#ifndef _EC_KBC_H +#define _EC_KBC_H + +#include +#include + +void kbc_init(void); + +struct Kbc { + // Control register + volatile uint8_t * control; + // Interrupt control register + volatile uint8_t * irq; + // Status register + volatile uint8_t * status; + // Keyboard out register + volatile uint8_t * keyboard_out; + // Mouse out register + volatile uint8_t * mouse_out; + // Data in register + volatile uint8_t * data_in; +}; + +extern struct Kbc __code KBC; + +#define KBC_STS_OBF (1 << 0) +#define KBC_STS_IBF (1 << 1) +#define KBC_STS_CMD (1 << 3) + +uint8_t kbc_status(struct Kbc * kbc); +uint8_t kbc_read(struct Kbc * kbc); +bool kbc_keyboard(struct Kbc * kbc, uint8_t data, int timeout); +bool kbc_mouse(struct Kbc * kbc, uint8_t data, int timeout); + +volatile uint8_t __xdata __at(0x1300) KBHICR; +volatile uint8_t __xdata __at(0x1302) KBIRQR; +volatile uint8_t __xdata __at(0x1304) KBHISR; +volatile uint8_t __xdata __at(0x1306) KBHIKDOR; +volatile uint8_t __xdata __at(0x1308) KBHIMDOR; +volatile uint8_t __xdata __at(0x130A) KBHIDIR; + +#endif // _EC_KBC_H diff --git a/src/ec/it5570e/include/ec/kbscan.h b/src/ec/it5570e/include/ec/kbscan.h new file mode 100644 index 0000000..58dc162 --- /dev/null +++ b/src/ec/it5570e/include/ec/kbscan.h @@ -0,0 +1,47 @@ +#ifndef _EC_KBSCAN_H +#define _EC_KBSCAN_H + +#include + +volatile uint8_t __xdata __at(0x1D00) KSOL; +volatile uint8_t __xdata __at(0x1D01) KSOH1; +volatile uint8_t __xdata __at(0x1D02) KSOCTRL; +volatile uint8_t __xdata __at(0x1D03) KSOH2; +volatile uint8_t __xdata __at(0x1D04) KSI; +volatile uint8_t __xdata __at(0x1D05) KSICTRLR; +volatile uint8_t __xdata __at(0x1D06) KSIGCTRL; +volatile uint8_t __xdata __at(0x1D07) KSIGOEN; +volatile uint8_t __xdata __at(0x1D08) KSIGDAT; +volatile uint8_t __xdata __at(0x1D09) KSIGDMRR; +volatile uint8_t __xdata __at(0x1D0A) KSOHGCTRL; +volatile uint8_t __xdata __at(0x1D0B) KSOHGOEN; +volatile uint8_t __xdata __at(0x1D0C) KSOHGDMRR; +volatile uint8_t __xdata __at(0x1D0D) KSOLGCTRL; +volatile uint8_t __xdata __at(0x1D0E) KSOLGOEN; +volatile uint8_t __xdata __at(0x1D0F) KSOLGDMRR; + +volatile uint8_t __xdata __at(0x1D10) KSO0LSDR; +volatile uint8_t __xdata __at(0x1D11) KSO1LSDR; +volatile uint8_t __xdata __at(0x1D12) KSO2LSDR; +volatile uint8_t __xdata __at(0x1D13) KSO3LSDR; +volatile uint8_t __xdata __at(0x1D14) KSO4LSDR; +volatile uint8_t __xdata __at(0x1D15) KSO5LSDR; +volatile uint8_t __xdata __at(0x1D16) KSO6LSDR; +volatile uint8_t __xdata __at(0x1D17) KSO7LSDR; +volatile uint8_t __xdata __at(0x1D18) KSO8LSDR; +volatile uint8_t __xdata __at(0x1D19) KSO9LSDR; +volatile uint8_t __xdata __at(0x1D1A) KSO10LSDR; +volatile uint8_t __xdata __at(0x1D1B) KSO11LSDR; +volatile uint8_t __xdata __at(0x1D1C) KSO12LSDR; +volatile uint8_t __xdata __at(0x1D1D) KSO13LSDR; +volatile uint8_t __xdata __at(0x1D1E) KSO14LSDR; +volatile uint8_t __xdata __at(0x1D1F) KSO15LSDR; +volatile uint8_t __xdata __at(0x1D20) KSO16LSDR; +volatile uint8_t __xdata __at(0x1D21) KSO17LSDR; + +volatile uint8_t __xdata __at(0x1D22) SDC1R; +volatile uint8_t __xdata __at(0x1D23) SDC2R; +volatile uint8_t __xdata __at(0x1D24) SDC3R; +volatile uint8_t __xdata __at(0x1D25) SDSR; + +#endif // _EC_KBSCAN_H diff --git a/src/ec/it5570e/include/ec/peci.h b/src/ec/it5570e/include/ec/peci.h new file mode 100644 index 0000000..65e3a4a --- /dev/null +++ b/src/ec/it5570e/include/ec/peci.h @@ -0,0 +1,17 @@ +#ifndef _EC_PECI_H +#define _EC_PECI_H + +#include + +static volatile uint8_t __xdata __at(0x3000) HOSTAR; +static volatile uint8_t __xdata __at(0x3001) HOCTLR; +static volatile uint8_t __xdata __at(0x3002) HOCMDR; +static volatile uint8_t __xdata __at(0x3003) HOTRADDR; +static volatile uint8_t __xdata __at(0x3004) HOWRLR; +static volatile uint8_t __xdata __at(0x3005) HORDLR; +static volatile uint8_t __xdata __at(0x3006) HOWRDR; +static volatile uint8_t __xdata __at(0x3007) HORDDR; +static volatile uint8_t __xdata __at(0x3008) HOCTL2R; +static volatile uint8_t __xdata __at(0x3009) RWFCSV; + +#endif // _EC_PECI_H diff --git a/src/ec/it5570e/include/ec/pmc.h b/src/ec/it5570e/include/ec/pmc.h new file mode 100644 index 0000000..a1d96c6 --- /dev/null +++ b/src/ec/it5570e/include/ec/pmc.h @@ -0,0 +1,40 @@ +#ifndef _EC_PMC_H +#define _EC_PMC_H + +#include +#include + +struct Pmc { + // Status register + volatile uint8_t * status; + // Data out register + volatile uint8_t * data_out; + // Data in register + volatile uint8_t * data_in; + // Control register + volatile uint8_t * control; +}; + +extern struct Pmc __code PMC_1; +extern struct Pmc __code PMC_2; + +#define PMC_STS_OBF (1 << 0) +#define PMC_STS_IBF (1 << 1) +#define PMC_STS_CMD (1 << 3) + +uint8_t pmc_status(struct Pmc * pmc); +void pmc_set_status(struct Pmc * pmc, uint8_t status); +uint8_t pmc_read(struct Pmc * pmc); +bool pmc_write(struct Pmc * pmc, uint8_t data, int timeout); + +volatile uint8_t __xdata __at(0x1500) PM1STS; +volatile uint8_t __xdata __at(0x1501) PM1DO; +volatile uint8_t __xdata __at(0x1504) PM1DI; +volatile uint8_t __xdata __at(0x1506) PM1CTL; + +volatile uint8_t __xdata __at(0x1510) PM2STS; +volatile uint8_t __xdata __at(0x1511) PM2DO; +volatile uint8_t __xdata __at(0x1514) PM2DI; +volatile uint8_t __xdata __at(0x1516) PM2CTL; + +#endif // _EC_PMC_H diff --git a/src/ec/it5570e/include/ec/ps2.h b/src/ec/it5570e/include/ec/ps2.h new file mode 100644 index 0000000..cb75460 --- /dev/null +++ b/src/ec/it5570e/include/ec/ps2.h @@ -0,0 +1,37 @@ +#ifndef _EC_PS2_H +#define _EC_PS2_H + +#include + +struct Ps2 { + volatile uint8_t * control; + volatile uint8_t * interrupt; + volatile uint8_t * status; + volatile uint8_t * data; +}; + +extern struct Ps2 __code PS2_1; +extern struct Ps2 __code PS2_2; +extern struct Ps2 __code PS2_3; + +void ps2_reset(struct Ps2 * ps2); +int ps2_read(struct Ps2 * ps2, uint8_t * data, int length); +int ps2_write(struct Ps2 * ps2, uint8_t * data, int length); + +volatile uint8_t __xdata __at(0x1700) PSCTL1; +volatile uint8_t __xdata __at(0x1701) PSCTL2; +volatile uint8_t __xdata __at(0x1702) PSCTL3; + +volatile uint8_t __xdata __at(0x1704) PSINT1; +volatile uint8_t __xdata __at(0x1705) PSINT2; +volatile uint8_t __xdata __at(0x1706) PSINT3; + +volatile uint8_t __xdata __at(0x1708) PSSTS1; +volatile uint8_t __xdata __at(0x1709) PSSTS2; +volatile uint8_t __xdata __at(0x170A) PSSTS3; + +volatile uint8_t __xdata __at(0x170C) PSDAT1; +volatile uint8_t __xdata __at(0x170D) PSDAT2; +volatile uint8_t __xdata __at(0x170E) PSDAT3; + +#endif // _EC_PS2_H diff --git a/src/ec/it5570e/include/ec/pwm.h b/src/ec/it5570e/include/ec/pwm.h new file mode 100644 index 0000000..7145404 --- /dev/null +++ b/src/ec/it5570e/include/ec/pwm.h @@ -0,0 +1,63 @@ +#ifndef _EC_PWM_H +#define _EC_PWM_H + +#include + +// Channel 0 clock prescaler register +volatile uint8_t __xdata __at(0x1800) C0CPRS; +// Channel 6 clock prescaler register (low byte) +volatile uint8_t __xdata __at(0x182B) C6CPRS; +// Channel 6 clock prescaler register (high byte) +volatile uint8_t __xdata __at(0x182C) C6MCPRS; + +// Cycle Time 0 +volatile uint8_t __xdata __at(0x1801) CTR0; +// Cycle Time 1 +volatile uint8_t __xdata __at(0x1841) CTR1; +// Cycle Time 2 +volatile uint8_t __xdata __at(0x1842) CTR2; +// Cycle Time 3 +volatile uint8_t __xdata __at(0x1843) CTR3; + +// Duty cycle register 0 +volatile uint8_t __xdata __at(0x1802) DCR0; +// Duty cycle register 1 +volatile uint8_t __xdata __at(0x1803) DCR1; +// Duty cycle register 2 +volatile uint8_t __xdata __at(0x1804) DCR2; +// Duty cycle register 3 +volatile uint8_t __xdata __at(0x1805) DCR3; +// Duty cycle register 4 +volatile uint8_t __xdata __at(0x1806) DCR4; +// Duty cycle register 5 +volatile uint8_t __xdata __at(0x1807) DCR5; +// Duty cycle register 6 +volatile uint8_t __xdata __at(0x1808) DCR6; +// Duty cycle register 7 +volatile uint8_t __xdata __at(0x1809) DCR7; + +// Fan one tachometer least significant byte reading register +volatile uint8_t __xdata __at(0x181E) F1TLRR; +// Fan one tachometer most significant byte reading register +volatile uint8_t __xdata __at(0x181F) F1TMRR; +// Fan two tachometer least significant byte reading register +volatile uint8_t __xdata __at(0x1820) F2TLRR; +// Fan two tachometer most significant byte reading register +volatile uint8_t __xdata __at(0x1821) F2TMRR; + +// PWM polarity register +volatile uint8_t __xdata __at(0x180A) PWMPOL; +// Prescaler clock frequency select register +volatile uint8_t __xdata __at(0x180B) PCFSR; +// Prescaler clock source select group low +volatile uint8_t __xdata __at(0x180C) PCSSGL; +// Prescaler clock source select group high +volatile uint8_t __xdata __at(0x180D) PCSSGH; +// Prescaler clock source gating register +volatile uint8_t __xdata __at(0x180F) PCSGR; +// PWM clock control register with weird name +volatile uint8_t __xdata __at(0x1823) ZTIER; +// Tachometer switch control register +volatile uint8_t __xdata __at(0x1848) TSWCTLR; + +#endif // _EC_PWM_H diff --git a/src/ec/it5570e/include/ec/smbus.h b/src/ec/it5570e/include/ec/smbus.h new file mode 100644 index 0000000..22d9c43 --- /dev/null +++ b/src/ec/it5570e/include/ec/smbus.h @@ -0,0 +1,85 @@ +#ifndef _EC_SMBUS_H +#define _EC_SMBUS_H + +#include + +#define HOSTA_BYTE_DONE (1 << 7) +#define HOSTA_TIMEOUT (1 << 6) +#define HOSTA_NACK (1 << 5) +#define HOSTA_FAIL (1 << 4) +#define HOSTA_BUS_ERR (1 << 3) +#define HOSTA_DEV_ERR (1 << 2) +#define HOSTA_FINISH (1 << 1) +#define HOSTA_BUSY (1 << 0) +#define HOSTA_ERR (HOSTA_TIMEOUT | HOSTA_NACK | HOSTA_FAIL | HOSTA_BUS_ERR | HOSTA_DEV_ERR) + +// Host status for channel A +volatile uint8_t __xdata __at(0x1C00) HOSTAA; +// Host control for channel A +volatile uint8_t __xdata __at(0x1C01) HOCTLA; +// Host command for channel A +volatile uint8_t __xdata __at(0x1C02) HOCMDA; +// Transmit slave address for channel A +volatile uint8_t __xdata __at(0x1C03) TRASLAA; +// Host data 0 for channel A +volatile uint8_t __xdata __at(0x1C04) D0REGA; +// Host data 1 for channel A +volatile uint8_t __xdata __at(0x1C05) D1REGA; +// Host block data byte for channel A +volatile uint8_t __xdata __at(0x1C06) HOBDBA; +// Packet error check for channel A +volatile uint8_t __xdata __at(0x1C07) PECERCA; +// Receive slave address for channel A +volatile uint8_t __xdata __at(0x1C08) RESLADRA; +// Slave data for channel A +volatile uint8_t __xdata __at(0x1C09) SLDAA; +// SMBus pin control for channel A +volatile uint8_t __xdata __at(0x1C0A) SMBPCTLA; +// Slave status for channel A +volatile uint8_t __xdata __at(0x1C0B) SLSTAA; +// Slave interrupt control for channel A +volatile uint8_t __xdata __at(0x1C0C) SICRA; +// Notify device address for channel A +volatile uint8_t __xdata __at(0x1C0D) NDADRA; +// Notify data low byte for channel A +volatile uint8_t __xdata __at(0x1C0E) NDLBA; +// Notify data high byte for channel A +volatile uint8_t __xdata __at(0x1C0F) NDHBA; +// Host control 2 for channel A +volatile uint8_t __xdata __at(0x1C10) HOCTL2A; +// Receive slave address 2 for channel A +volatile uint8_t __xdata __at(0x1C3F) RESLADR2A; +// SMCLK timing setting for channel A +volatile uint8_t __xdata __at(0x1C40) SCLKTSA; + +// Host status for channel E +volatile uint8_t __xdata __at(0x1CA0) HOSTAE; +// Host control for channel E +volatile uint8_t __xdata __at(0x1CA1) HOCTLE; +// Host command for channel E +volatile uint8_t __xdata __at(0x1CA2) HOCMDE; +// Transmit slave address for channel E +volatile uint8_t __xdata __at(0x1CA3) TRASLAE; +// Host data 0 for channel E +volatile uint8_t __xdata __at(0x1CA4) D0REGE; +// Host data 1 for channel E +volatile uint8_t __xdata __at(0x1CA6) D1REGE; +// Host block data byte for channel E +volatile uint8_t __xdata __at(0x1CA7) HOBDBE; +// Packet error check for channel E +volatile uint8_t __xdata __at(0x1CA8) PECERCE; +// SMBus pin control for channel E +volatile uint8_t __xdata __at(0x1CA9) SMBPCTLE; +// Host control 2 for channel E +volatile uint8_t __xdata __at(0x1CAA) HOCTL2E; + +// Timing registers +volatile uint8_t __xdata __at(0x1C22) SMB4P7USL; +volatile uint8_t __xdata __at(0x1C23) SMB4P0USL; +volatile uint8_t __xdata __at(0x1C24) SMB300NS; +volatile uint8_t __xdata __at(0x1C25) SMB250NS; +volatile uint8_t __xdata __at(0x1C26) SMB25MS; +volatile uint8_t __xdata __at(0x1C27) SMB45P3USL; +volatile uint8_t __xdata __at(0x1C28) SMB45P3USH; + +#endif // _EC_SMBUS_H diff --git a/src/ec/it5570e/kbc.c b/src/ec/it5570e/kbc.c new file mode 100644 index 0000000..7a3c935 --- /dev/null +++ b/src/ec/it5570e/kbc.c @@ -0,0 +1,41 @@ +#include + +struct Kbc __code KBC = { + .control = &KBHICR, + .irq = &KBIRQR, + .status = &KBHISR, + .keyboard_out = &KBHIKDOR, + .mouse_out = &KBHIMDOR, + .data_in = &KBHIDIR, +}; + +uint8_t kbc_status(struct Kbc * kbc) { + return *(kbc->status); +} + +uint8_t kbc_read(struct Kbc * kbc) { + return *(kbc->data_in); +} + + +static bool kbc_wait(struct Kbc * kbc, int timeout) { + while (kbc_status(kbc) & KBC_STS_OBF) { + if (timeout == 0) return false; + timeout -= 1; + } + return true; +} + +bool kbc_keyboard(struct Kbc * kbc, uint8_t data, int timeout) { + if (!kbc_wait(kbc, timeout)) return false; + *(kbc->status) &= ~0x20; + *(kbc->keyboard_out) = data; + return true; +} + +bool kbc_mouse(struct Kbc * kbc, uint8_t data, int timeout) { + if (!kbc_wait(kbc, timeout)) return false; + *(kbc->status) |= 0x20; + *(kbc->mouse_out) = data; + return true; +} diff --git a/src/ec/it5570e/pmc.c b/src/ec/it5570e/pmc.c new file mode 100644 index 0000000..424e332 --- /dev/null +++ b/src/ec/it5570e/pmc.c @@ -0,0 +1,37 @@ +#include + +#define PMC(NUM) { \ + .status = &PM ## NUM ## STS, \ + .data_out = &PM ## NUM ## DO, \ + .data_in = &PM ## NUM ## DI, \ + .control = &PM ## NUM ## CTL, \ +} + +struct Pmc __code PMC_1 = PMC(1); +struct Pmc __code PMC_2 = PMC(2); + +uint8_t pmc_status(struct Pmc * pmc) { + return *(pmc->status); +} + +void pmc_set_status(struct Pmc * pmc, uint8_t status) { + *(pmc->status) = status; +} + +uint8_t pmc_read(struct Pmc * pmc) { + return *(pmc->data_in); +} + +static bool pmc_wait(struct Pmc * pmc, int timeout) { + while (pmc_status(pmc) & PMC_STS_OBF) { + if (timeout == 0) return false; + timeout -= 1; + } + return true; +} + +bool pmc_write(struct Pmc * pmc, uint8_t data, int timeout) { + if (!pmc_wait(pmc, timeout)) return false; + *(pmc->data_out) = data; + return true; +} diff --git a/src/ec/it5570e/ps2.c b/src/ec/it5570e/ps2.c new file mode 100644 index 0000000..d9d7465 --- /dev/null +++ b/src/ec/it5570e/ps2.c @@ -0,0 +1,81 @@ +#include + +#include + +#define PS2(NUM) { \ + .control = &PSCTL ## NUM, \ + .interrupt = &PSINT ## NUM, \ + .status = &PSSTS ## NUM, \ + .data = &PSDAT ## NUM, \ +} + +#define PS2_TIMEOUT 10000 + +#define PSSTS_TIMEOUT_ERR (1 << 6) +#define PSSTS_FRAME_ERR (1 << 5) +#define PSSTS_PARITY_ERR (1 << 4) +#define PSSTS_ALL_ERR (PSSTS_TIMEOUT_ERR | PSSTS_FRAME_ERR | PSSTS_PARITY_ERR) +#define PSSTS_DONE (1 << 3) + +struct Ps2 __code PS2_1 = PS2(1); +struct Ps2 __code PS2_2 = PS2(2); +struct Ps2 __code PS2_3 = PS2(3); + +void ps2_reset(struct Ps2 * ps2) { + // Reset interface to defaults + *(ps2->control) = 1; + // Clear status + *(ps2->status) = *(ps2->status); +} + +static int ps2_transaction(struct Ps2 * ps2, uint8_t * data, int length, bool read) { + int i; + for (i = 0; i < length; i++) { + if (read) { + // Begin read + *(ps2->control) = 0x07; + } else { + // Begin write + *(ps2->control) = 0x0D; + *(ps2->data) = data[i]; + // Pull data line low + *(ps2->control) = 0x0C; + // Pull clock line high + *(ps2->control) = 0x0E; + } + + uint32_t timeout; + for (timeout = PS2_TIMEOUT; timeout > 0; timeout--) { + uint8_t status = *(ps2->status); + // If an error happened, clear status and return the error + if (status & PSSTS_ALL_ERR) { + ps2_reset(ps2); + return -(int)status; + } + // If transaction is done, break + if (status & PSSTS_DONE) { + break; + } + } + // If a timeout happened, return the error + if (timeout == 0) { + ps2_reset(ps2); + return -0x1000; + } + if (read) { + data[i] = *(ps2->data); + } + // Set interface to defaults + ps2_reset(ps2); + } + + return i; +} + +int ps2_read(struct Ps2 * ps2, uint8_t * data, int length) { + return ps2_transaction(ps2, data, length, true); +} + +int ps2_write(struct Ps2 * ps2, uint8_t * data, int length) { + return ps2_transaction(ps2, data, length, false); +} diff --git a/src/ec/it5570e/signature.c b/src/ec/it5570e/signature.c new file mode 100644 index 0000000..05ee931 --- /dev/null +++ b/src/ec/it5570e/signature.c @@ -0,0 +1,7 @@ +static __code char __at(0x40) SIGNATURE[32] = { + 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0x94, + 0x85, 0x12, 0x5A, 0x5A, 0xAA, 0x00, 0x55, 0x55, + + 0x49, 0x54, 0x45, 0x20, 0x54, 0x65, 0x63, 0x68, + 0x2E, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x20 +}; diff --git a/src/ec/it8587e/i2c.c b/src/ec/it8587e/i2c.c index ae08476..cb03048 100644 --- a/src/ec/it8587e/i2c.c +++ b/src/ec/it8587e/i2c.c @@ -6,30 +6,36 @@ //TODO: find best value #define I2C_TIMEOUT 10000 +#define HOSTA HOSTAA +#define HOCTL HOCTLA +#define HOCTL2 HOCTL2A +#define HOBDB HOBDBA +#define TRASLA TRASLAA + void i2c_reset(bool kill) { - if (HOSTAA & HOSTA_BUSY) { + if (HOSTA & HOSTA_BUSY) { // Set kill bit - if (kill) HOCTLA |= (1 << 1); + if (kill) HOCTL |= (1 << 1); // Wait for host to finish - while (HOSTAA & HOSTA_BUSY) {} + while (HOSTA & HOSTA_BUSY) {} } // Clear status register - HOSTAA = HOSTAA; + HOSTA = HOSTA; // Clear current command - HOCTLA = 0; + HOCTL = 0; // Disable host interface - HOCTL2A = 0; + HOCTL2 = 0; } int i2c_start(uint8_t addr, bool read) { // If we are already in a transaction - if (HOSTAA & HOSTA_BYTE_DONE) { + if (HOSTA & HOSTA_BYTE_DONE) { // If we are switching direction - if ((TRASLAA & 1) != read) { + if ((TRASLA & 1) != read) { // If we are switching to read mode if (read) { // Enable direction switch - HOCTL2A |= (1 << 3) | (1 << 2); + HOCTL2 |= (1 << 3) | (1 << 2); } else { // Unsupported! i2c_reset(true); @@ -40,10 +46,10 @@ int i2c_start(uint8_t addr, bool read) { i2c_reset(true); // Enable host controller with i2c compatibility - HOCTL2A = (1 << 1) | 1; + HOCTL2 = (1 << 1) | 1; // Set address - TRASLAA = (addr << 1) | read; + TRASLA = (addr << 1) | read; } return 0; @@ -51,9 +57,9 @@ int i2c_start(uint8_t addr, bool read) { void i2c_stop(void) { // Disable i2c compatibility - HOCTL2A &= ~(1 << 1); + HOCTL2 &= ~(1 << 1); // Clear status - HOSTAA = HOSTAA; + HOSTA = HOSTA; i2c_reset(false); } @@ -65,33 +71,33 @@ static int i2c_transaction(uint8_t * data, int length, bool read) { // If last byte if ((i + 1) == length) { // Set last byte bit - HOCTLA |= (1 << 5); + HOCTL |= (1 << 5); } } else { // Write byte - HOBDBA = data[i]; + HOBDB = data[i]; } // If we are already in a transaction - if (HOSTAA & HOSTA_BYTE_DONE) { + if (HOSTA & HOSTA_BYTE_DONE) { // Clear status to process next byte - HOSTAA = HOSTAA; + HOSTA = HOSTA; } else { // Start new transaction - HOCTLA = (1 << 6) | (0b111 << 2); + HOCTL = (1 << 6) | (0b111 << 2); } // If we are waiting on direction switch - if (HOCTL2A & (1 << 2)) { + if (HOCTL2 & (1 << 2)) { // Complete direction switch - HOCTL2A &= ~(1 << 2); + HOCTL2 &= ~(1 << 2); } // Wait for byte done, timeout, or error uint8_t status; uint32_t timeout = I2C_TIMEOUT; for(timeout = I2C_TIMEOUT; timeout > 0; timeout--) { - status = HOSTAA; + status = HOSTA; // If error occured, kill transaction and return error if (status & HOSTA_ERR) { i2c_reset(true); @@ -110,7 +116,7 @@ static int i2c_transaction(uint8_t * data, int length, bool read) { if (read) { // Read byte - data[i] = HOBDBA; + data[i] = HOBDB; } } diff --git a/src/ec/it8587e/include/ec/smbus.h b/src/ec/it8587e/include/ec/smbus.h index 8e328c8..c1d7ffc 100644 --- a/src/ec/it8587e/include/ec/smbus.h +++ b/src/ec/it8587e/include/ec/smbus.h @@ -31,8 +31,6 @@ volatile uint8_t __xdata __at(0x1C06) HOBDBA; volatile uint8_t __xdata __at(0x1C07) PECERCA; // Receive slave address for channel A volatile uint8_t __xdata __at(0x1C08) RESLADRA; -// Receive slave address 2 for channel A -volatile uint8_t __xdata __at(0x1C3F) RESLADR2A; // Slave data for channel A volatile uint8_t __xdata __at(0x1C09) SLDAA; // SMBus pin control for channel A @@ -49,6 +47,8 @@ volatile uint8_t __xdata __at(0x1C0E) NDLBA; volatile uint8_t __xdata __at(0x1C0F) NDHBA; // Host control 2 for channel A volatile uint8_t __xdata __at(0x1C10) HOCTL2A; +// Receive slave address 2 for channel A +volatile uint8_t __xdata __at(0x1C3F) RESLADR2A; // SMCLK timing setting for channel A volatile uint8_t __xdata __at(0x1C40) SCLKTSA;