#include #include #include #include #include #include #include "led_ctl.h" #define EC_CMD_PORT 0x66 #define EC_DATA_PORT 0x62 #define EC_OBF 0x01 // Output Buffer Full #define EC_IBF 0x02 // Input Buffer Full #define CMD_READ_RAM 0x97 #define CMD_WRITE_RAM 0x98 #define OFFSET_COLOR_CTL 0x01 #define OFFSET_BLINK_TIME 0x02 #define OFFSET_BLINK_CTL 0x03 #define OFFSET_TURNOFF_CTL 0x04 #define BIT0 (1 << 0) #define TIMEOUT_LOOPS 100000 static int wait_ibf(void) { int i = 0; while (inb(EC_CMD_PORT) & EC_IBF) { if (++i > TIMEOUT_LOOPS) { fprintf(stderr, "Error: EC IBF Timeout!\n"); return -1; } usleep(1); } return 0; } static int wait_obf(void) { int i = 0; while (!(inb(EC_CMD_PORT) & EC_OBF)) { if (++i > TIMEOUT_LOOPS) { fprintf(stderr, "Error: EC OBF Timeout!\n"); return -1; } usleep(1); } return 0; } static int ec_read_ram(uint8_t offset, uint8_t *data) { if (wait_ibf() < 0) return -1; outb(CMD_READ_RAM, EC_CMD_PORT); if (wait_ibf() < 0) return -1; outb(offset, EC_DATA_PORT); if (wait_obf() < 0) return -1; *data = inb(EC_DATA_PORT); return 0; } static int ec_write_ram(uint8_t offset, uint8_t data) { if (wait_ibf() < 0) return -1; outb(CMD_WRITE_RAM, EC_CMD_PORT); if (wait_ibf() < 0) return -1; outb(offset, EC_DATA_PORT); if (wait_ibf() < 0) return -1; outb(data, EC_DATA_PORT); return 0; } static int oem_ec_read_ram(uint8_t page, uint8_t offset, uint8_t *data) { unsigned char WEC, REC; switch(page) { case 0: { WEC = 0x96; REC = 0x95; break; } case 1: { WEC = 0x98; REC = 0x97; break; } default: { WEC = 0x81; REC = 0x80; break; } } if (wait_ibf() < 0) return -1; outb(REC, EC_CMD_PORT); if (wait_ibf() < 0) return -1; outb(offset, EC_DATA_PORT); if (wait_obf() < 0) return -1; *data = inb(EC_DATA_PORT); return 0; } static int oem_ec_write_ram(uint8_t page, uint8_t offset, uint8_t data) { unsigned char WEC, REC; switch(page) { case 0: { WEC = 0x96; REC = 0x95; break; } case 1: { WEC = 0x98; REC = 0x97; break; } default: { WEC = 0x81; REC = 0x80; break; } } if (wait_ibf() < 0) return -1; outb(WEC, EC_CMD_PORT); if (wait_ibf() < 0) return -1; outb(offset, EC_DATA_PORT); if (wait_ibf() < 0) return -1; outb(data, EC_DATA_PORT); return 0; } // ---------API functions--------- //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>heart led function begin>>>>>>>>>>>>>>>>>>>>>>>>>> void heart_led_turn_off(void) { oem_ec_write_ram(1, OFFSET_TURNOFF_CTL, 0x01); } void heart_led_turn_on(void) { oem_ec_write_ram(1, OFFSET_TURNOFF_CTL, 0x00); } int led_driver_init(void) { if (ioperm(EC_DATA_PORT, 1, 1)) { perror("Failed to get permission for 0x62"); return -1; } if (ioperm(EC_CMD_PORT, 1, 1)) { perror("Failed to get permission for 0x66"); return -1; } return 0; } int led_set_color(led_color_t color) { uint8_t val; if (ec_read_ram(OFFSET_COLOR_CTL, &val) < 0) return -1; if (color == LED_RED) val |= BIT0; else val &= ~BIT0; heart_led_turn_on(); return ec_write_ram(OFFSET_COLOR_CTL, val); } int led_set_blink(int enable, uint8_t interval_unit) { uint8_t ctl; if (enable) { if (ec_write_ram(OFFSET_BLINK_TIME, interval_unit) < 0) return -1; } if (ec_read_ram(OFFSET_BLINK_CTL, &ctl) < 0) return -1; if (enable) ctl |= BIT0; else ctl &= ~BIT0; heart_led_turn_on(); return ec_write_ram(OFFSET_BLINK_CTL, ctl); } int led_print_status(void) { uint8_t color_reg, blink_time, blink_ctl; if (ec_read_ram(OFFSET_COLOR_CTL, &color_reg) < 0) return -1; if (ec_read_ram(OFFSET_BLINK_TIME, &blink_time) < 0) return -1; if (ec_read_ram(OFFSET_BLINK_CTL, &blink_ctl) < 0) return -1; printf(" Color : %s\n", (color_reg & BIT0) ? "RED" : "GREEN"); printf(" Blink : %s\n", (blink_ctl & BIT0) ? "ON" : "OFF"); if (blink_ctl & BIT0) { printf(" Interval : %d ms (%d units)\n", blink_time * 100, blink_time); } return 0; } //<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>bat_led function begin>>>>>>>>>>>>>>>>>>>>>>>>>>>>> void bat_led_ctrl_by_sys(void) { oem_ec_write_ram(2, 0x21, 0x3C); //enable bat led control by system } void bat_led_ctrl_by_ec(void) { oem_ec_write_ram(2, 0x21, 0x00); //enable bat led control by ec } int bat_led_set_color(uint8_t state) { uint8_t val; /* val is led state: off; red; green val bit meaning: bit 2-3: health led bit 4-5: charge led */ switch(state) { case 0: val = 0x10; // charge led green break; case 1: val = 0x20; // charge led red break; case 2: val = 0x04;// health led green break; case 3: val = 0x08;// health led red break; case 4: val = 0x00;//turn off both led break; default: return 0; } oem_ec_write_ram(2, 0x31, val); bat_led_ctrl_by_sys(); return 1; } //<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>bat infor function begin>>>>>>>>>>>>>>>>>>>>>>>>>>>>> void get_bat_info(void) { uint8_t BAT1_RelativeStateOfChgL = 0; uint8_t BAT1_HEALTH = 0; oem_ec_read_ram(2, 0x93, &BAT1_RelativeStateOfChgL); oem_ec_read_ram(2, 0x9D, &BAT1_HEALTH); printf(" BAT1_RelativeStateOfChgL is : %d\n", BAT1_RelativeStateOfChgL); printf(" BAT1_HEALTH is : %d\n", BAT1_HEALTH); } //<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>AC & power function begin>>>>>>>>>>>>>>>>>>>>>>>>>>>>> uint8_t soft_rest_btn(void)//read GPIO of btn SW_HRST1 { uint8_t val = 0x00; if (oem_ec_read_ram(2, 0x34, &val) < 0) return 0; printf(" btn state is : %d\n", (val & 0x01) ? 1 : 0); return (val & 0x01) ? 1 : 0; } uint8_t ac_present(void) //read GPIO of DC IN { uint8_t val = 0x00; if (oem_ec_read_ram(2, 0x36, &val) < 0) return 0; printf(" AC state is : %d\n", (val & 0x03) ? 1 : 0); return (val & 0x08) ? 1 : 0; } void ac_bat_state(void) //read EC state { /* meaning of state bit #define F_BAT1_DISCHRGE BIT(7) #define F_BAT1_CHARGING BIT(6) #define F_BAT1_PRESENT BIT(1) #define F_AC_ON_LINE BIT(0) */ uint8_t state = 0x00; oem_ec_read_ram(2, 0x80, &state); if((state & 0x03) == 0x01) { printf(" DC is in, bat out\n"); } else if((state & 0x03) == 0x02) { printf(" DC is out, bat in\n"); } else if((state & 0x03) == 0x03) { printf(" DC is in, bat in\n"); } else if((state & 0xC2) == 0x82) { printf(" BAT is present and discharge\n"); } else if((state & 0xC2) == 0x42) { printf(" BAT is present and charging\n"); } } //<<<<<<<<<<<<<<<<<<<<<<<<<