#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include uint8_t main_cycle = 0; void external_0(void) __interrupt(0) { TRACE("external_0\n"); } void timer_0(void) __interrupt(1) { TRACE("timer_0\n"); } void external_1(void) __interrupt(2) { TRACE("external_1\n"); } void timer_1(void) __interrupt(3) { TRACE("timer_1\n"); } void serial(void) __interrupt(4) { TRACE("serial\n"); } void timer_2(void) __interrupt(5) { TRACE("timer_2\n"); } void init(void) { gpio_init(); gctrl_init(); kbc_init(); pmc_init(); kbscan_init(); pwm_init(); smbus_init(); //TODO: INTC, PECI // Allow PECI pin to be used GCR2 |= (1 << 4); } void ac_adapter() { static struct Gpio __code ACIN_N = GPIO(B, 6); static struct Gpio __code LED_ACIN = GPIO(C, 7); static bool send_sci = true; static bool last = true; // Check if the adapter line goes low bool new = gpio_get(&ACIN_N); // Set ACIN LED gpio_set(&LED_ACIN, !new); // If there has been a change, print if (new != last) { DEBUG("Power adapter "); if (new) { DEBUG("unplugged\n"); battery_charger_disable(); } else { DEBUG("plugged in\n"); battery_charger_enable(); } battery_debug(); // Reset main loop cycle to force reading PECI and battery main_cycle = 0; // Send SCI to update AC and battery information send_sci = true; } if (send_sci) { // Send SCI 0x16 for AC detect event if (pmc_sci(&PMC_1, 0x16)) { send_sci = false; } } last = new; } void touchpad_event(struct Ps2 * ps2) { if (kbc_second) { *(ps2->control) = 0x07; } else { ps2_reset(ps2); } uint8_t status = *(ps2->status); *(ps2->status) = status; if (status & (1 << 3)) { uint8_t data = *(ps2->data); TRACE("touchpad: %02X\n", data); kbc_mouse(&KBC, data, 1000); } } void lid_event(void) { static struct Gpio __code LID_SW_N = GPIO(D, 1); static bool send_sci = true; static bool last = true; // Check if the adapter line goes low bool new = gpio_get(&LID_SW_N); // If there has been a change, print if (new != last) { DEBUG("Lid "); if (new) { DEBUG("open\n"); //TODO: send SWI if needed } else { DEBUG("closed\n"); } // Send SCI send_sci = true; } if (send_sci) { // Send SCI 0x1B for lid event if (pmc_sci(&PMC_1, 0x1B)) { send_sci = false; } } last = new; } struct Gpio __code LED_SSD_N = GPIO(G, 6); struct Gpio __code LED_AIRPLANE_N = GPIO(G, 6); void main(void) { init(); INFO("\n"); static struct Gpio __code LED_BAT_CHG = GPIO(A, 5); static struct Gpio __code LED_BAT_FULL = GPIO(A, 6); static struct Gpio __code SMI_N = GPIO(D, 3); static struct Gpio __code SCI_N = GPIO(D, 4); static struct Gpio __code SWI_N = GPIO(E, 0); static struct Gpio __code SB_KBCRST_N = GPIO(E, 6); static struct Gpio __code BT_EN = GPIO(F, 3); static struct Gpio __code USB_PWR_EN_N = GPIO(F, 7); static struct Gpio __code CCD_EN = GPIO(G, 0); static struct Gpio __code PM_CLKRUN_N = GPIO(H, 0); static struct Gpio __code BKL_EN = GPIO(H, 2); static struct Gpio __code WLAN_EN = GPIO(H, 5); static struct Gpio __code WLAN_PWR_EN = GPIO(J, 4); // Set the battery full LED (to know our firmware is loading) gpio_set(&LED_BAT_CHG, true); #if GPIO_DEBUG gpio_debug(); #endif // Allow CPU to boot gpio_set(&SB_KBCRST_N, true); // Allow backlight to be turned on gpio_set(&BKL_EN, true); // Enable camera gpio_set(&CCD_EN, true); // Enable wireless gpio_set(&BT_EN, true); gpio_set(&WLAN_EN, true); gpio_set(&WLAN_PWR_EN, true); // Enable right USB port gpio_set(&USB_PWR_EN_N, false); // Assert SMI#, SCI#, and SWI# gpio_set(&SCI_N, true); gpio_set(&SMI_N, true); gpio_set(&SWI_N, true); // Set the battery full LED (to know our firmware is loaded) gpio_set(&LED_BAT_FULL, true); INFO("Hello from System76 EC for %s!\n", xstr(__BOARD__)); for(main_cycle = 0; ; main_cycle++) { // Enables or disables battery charging based on AC adapter ac_adapter(); // Handle power states power_event(); // Scans keyboard and sends keyboard packets kbscan_event(); // Passes through touchpad packets touchpad_event(&PS2_3); // Handle lid close/open lid_event(); // Checks for keyboard/mouse packets from host kbc_event(&KBC); // Only run the following once out of every 256 loops if (main_cycle == 0) { // Updates fan status and temps peci_event(); // Updates battery status battery_event(); } // Handles ACPI communication pmc_event(&PMC_1); } }