From 7614873b1925739395f13e9d963f8ff9f033c4ec Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 15 Nov 2019 16:47:56 -0700 Subject: [PATCH] Enable PNP devices by default, attempt to send/receive data from touchpad --- .../system76/galp3-c/include/board/kbc.h | 3 + src/board/system76/galp3-c/kbc.c | 7 ++- src/board/system76/galp3-c/main.c | 57 +++++++++++++++++- src/ec/it8587e/include/ec/ps2.h | 3 + src/ec/it8587e/ps2.c | 60 +++++++++++++++++++ 5 files changed, 124 insertions(+), 6 deletions(-) diff --git a/src/board/system76/galp3-c/include/board/kbc.h b/src/board/system76/galp3-c/include/board/kbc.h index c404ea8..17765b8 100644 --- a/src/board/system76/galp3-c/include/board/kbc.h +++ b/src/board/system76/galp3-c/include/board/kbc.h @@ -5,6 +5,9 @@ #include +extern bool kbc_first; +extern bool kbc_second; + void kbc_init(void); bool kbc_scancode(struct Kbc * kbc, uint16_t key, bool pressed); void kbc_event(struct Kbc * kbc); diff --git a/src/board/system76/galp3-c/kbc.c b/src/board/system76/galp3-c/kbc.c index 900ee8a..361e163 100644 --- a/src/board/system76/galp3-c/kbc.c +++ b/src/board/system76/galp3-c/kbc.c @@ -3,6 +3,7 @@ #include #include #include +#include void kbc_init(void) { // Disable interrupts @@ -15,9 +16,9 @@ void kbc_init(void) { // System flag static bool kbc_system = false; // Enable first port - TODO -static bool kbc_first = false; +bool kbc_first = false; // Enable second port - TODO -static bool kbc_second = false; +bool kbc_second = false; // Translate from scancode set 2 to scancode set 1 // for basically no good reason static bool kbc_translate = true; @@ -243,7 +244,7 @@ void kbc_event(struct Kbc * kbc) { case KBC_STATE_SECOND_PORT_INPUT: printf(" write second port input\n"); state = KBC_STATE_NORMAL; - // TODO: mouse commands (write to touchpad?) + ps2_write(&PS2_3, &data, 1); break; } } diff --git a/src/board/system76/galp3-c/main.c b/src/board/system76/galp3-c/main.c index 98db03e..c6014c2 100644 --- a/src/board/system76/galp3-c/main.c +++ b/src/board/system76/galp3-c/main.c @@ -79,6 +79,42 @@ void ac_adapter() { last = new; } +volatile uint8_t __xdata __at(0x1200) IHIOA; +volatile uint8_t __xdata __at(0x1201) IHD; +volatile uint8_t __xdata __at(0x1204) IBMAE; +volatile uint8_t __xdata __at(0x1205) IBCTL; +void e2ci_write(uint8_t port, uint8_t data) { + while (IBCTL & ((1 << 2) | (1 << 1))) {} + IHIOA = port; + IHD = data; + IBMAE = 1; + IBCTL = 1; + while (IBCTL & (1 << 2)) {} + IBMAE = 0; + IBCTL = 0; +} + +void pnp_write(uint8_t reg, uint8_t data) { + e2ci_write(0x2E, reg); + e2ci_write(0x2F, data); +} + +void pnp_enable() { + printf("Enable PNP devices\n"); + + // Enable KBC keyboard + pnp_write(0x07, 0x06); + pnp_write(0x30, 0x01); + + // Enable KBC mouse + pnp_write(0x07, 0x05); + pnp_write(0x30, 0x01); + + // Enable SWUC + pnp_write(0x07, 0x04); + pnp_write(0x30, 0x01); +} + void power_button() { static struct Gpio __code PCH_DPWROK_EC = GPIO(A, 3); static struct Gpio __code PCH_PWROK_EC = GPIO(A, 4); @@ -209,6 +245,9 @@ void power_button() { if (value) break; delay_ms(1); } + + // enable pnp devices + pnp_enable(); } else { printf("Disabling power\n"); @@ -275,9 +314,21 @@ void power_button() { last = new; } -// void touchpad_event(struct Ps2 * ps2) { -// //TODO -// } +void touchpad_event(struct Ps2 * ps2) { + if (kbc_second) { + *(ps2->control) = 0x07; + } else { + *(ps2->control) = 0x01; + } + + uint8_t status = *(ps2->status); + *(ps2->status) = status; + if (status & (1 << 3)) { + uint8_t data = *(ps2->data); + printf("touchpad: %02X\n", data); + kbc_mouse(&KBC, data, 1000); + } +} struct Gpio __code LED_SSD_N = GPIO(G, 6); struct Gpio __code LED_AIRPLANE_N = GPIO(G, 6); diff --git a/src/ec/it8587e/include/ec/ps2.h b/src/ec/it8587e/include/ec/ps2.h index cbf29b7..f253a92 100644 --- a/src/ec/it8587e/include/ec/ps2.h +++ b/src/ec/it8587e/include/ec/ps2.h @@ -14,6 +14,9 @@ extern struct Ps2 __code PS2_1; extern struct Ps2 __code PS2_2; extern struct Ps2 __code PS2_3; +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; diff --git a/src/ec/it8587e/ps2.c b/src/ec/it8587e/ps2.c index 467dd00..5fce7cc 100644 --- a/src/ec/it8587e/ps2.c +++ b/src/ec/it8587e/ps2.c @@ -1,3 +1,6 @@ +#include + +#include #include #define PS2(NUM) { \ @@ -7,6 +10,63 @@ .data = &PSDAT ## NUM, \ } +#define TIMEOUT (F_CPU/1000) + +#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); + +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 = 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->status) = status; + return -(int)status; + } + // If transaction is done, break + if (status & PSSTS_DONE) { + break; + } + } + // If a timeout happened, return the error + if (timeout == 0) { + return -1; + } + if (read) { + data[i] = *(ps2->data); + } + } + + 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); +}