2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1 +1,3 @@ | ||||
| /build/ | ||||
| backup.rom | ||||
| power.csv | ||||
|   | ||||
							
								
								
									
										63
									
								
								power.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										63
									
								
								power.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| set -e | ||||
|  | ||||
| ./ectool.sh info | ||||
|  | ||||
| header=1 | ||||
| if [ -e power.csv ] | ||||
| then | ||||
|     header=0 | ||||
| fi | ||||
|  | ||||
| while true | ||||
| do | ||||
|     if [ "${header}" == "1" ] | ||||
|     then | ||||
|         F="Time    " | ||||
|         F="${F}\tBAT W" | ||||
|         F="${F}\tCPU W" | ||||
|         F="${F}\tCPU C" | ||||
|         F="${F}\tFAN %" | ||||
|     else | ||||
|         F="$(date "+%T")" | ||||
|  | ||||
|         uV="$(cat /sys/class/power_supply/BAT0/voltage_now)" | ||||
|         V="$(echo "${uV}/1000000" | bc -lq)" | ||||
|         uA="$(cat /sys/class/power_supply/BAT0/current_now)" | ||||
|         A="$(echo "${uA}/1000000" | bc -lq)" | ||||
|         bat_W="$(echo "${V} * ${A}" | bc -lq)" | ||||
|         F="${F}\t$(printf "%.2f" "${bat_W}")" | ||||
|  | ||||
|         last_E="$(cat /sys/class/powercap/intel-rapl\:0/energy_uj)" | ||||
|         sleep 1 | ||||
|         next_E="$(cat /sys/class/powercap/intel-rapl\:0/energy_uj)" | ||||
|         W="$(echo "(${next_E} - ${last_E})/1000000" | bc -lq)" | ||||
|         F="${F}\t$(printf "%.1f" "${W}")" | ||||
|  | ||||
|         T="$(cat /sys/devices/platform/coretemp.0/hwmon/hwmon*/temp1_input)" | ||||
|         C="$(echo "${T}/1000" | bc -lq)" | ||||
|         F="${F}\t$(printf "%.1f" "${C}")" | ||||
|  | ||||
|         D="$(sudo tool/target/release/system76_ectool fan 0)" | ||||
|         P="$(echo "(${D} * 100)/255" | bc -lq)" | ||||
|         F="${F}\t$(printf "%.0f" "${P}")" | ||||
|     fi | ||||
|  | ||||
|     for file in /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq | ||||
|     do | ||||
|         if [ "${header}" == "1" ] | ||||
|         then | ||||
|             id="$(basename "$(dirname "$(dirname "${file}")")")" | ||||
|             F="${F}\t${id}" | ||||
|         else | ||||
|             KHz="$(cat "${file}")" | ||||
|             MHz="$(echo "${KHz}/1000" | bc -lq)" | ||||
|             F="${F}\t$(printf "%.0f" "${MHz}")" | ||||
|         fi | ||||
|     done | ||||
|  | ||||
|     echo -e "${F}" | tee -a power.csv | ||||
|  | ||||
|     header=0 | ||||
| done | ||||
| @@ -7,6 +7,12 @@ | ||||
| #include <ec/gpio.h> | ||||
| #include <ec/pwm.h> | ||||
|  | ||||
| // Fan speed is the lowest requested over HEATUP seconds | ||||
| #define HEATUP 5 | ||||
|  | ||||
| // Fan speed is the highest HEATUP speed over COOLDOWN seconds | ||||
| #define COOLDOWN 10 | ||||
|  | ||||
| // Tjunction = 100C for i7-8565U (and probably the same for all WHL-U) | ||||
| #define T_JUNCTION 100 | ||||
|  | ||||
| @@ -30,7 +36,7 @@ struct FanPoint __code FAN_POINTS[] = { | ||||
|     FAN_POINT(70,  45), | ||||
|     FAN_POINT(75,  55), | ||||
|     FAN_POINT(80,  75), | ||||
|     FAN_POINT(84, 100), | ||||
|     FAN_POINT(84, 100) | ||||
| }; | ||||
|  | ||||
| // Get duty cycle based on temperature, adapted from | ||||
| @@ -51,12 +57,14 @@ uint8_t fan_duty(int16_t temp) { | ||||
|  | ||||
|                 // If in between current temp and previous temp, interpolate | ||||
|                 if (temp > prev->temp) { | ||||
|                     int16_t dtemp = (cur->temp - prev->temp); | ||||
|                     int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty); | ||||
|                     return (uint8_t)( | ||||
|                         ((int16_t)prev->duty) + | ||||
|                         ((temp - prev->temp) * dduty) / dtemp | ||||
|                     ); | ||||
|                     return prev->duty; | ||||
|  | ||||
|                     // int16_t dtemp = (cur->temp - prev->temp); | ||||
|                     // int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty); | ||||
|                     // return (uint8_t)( | ||||
|                     //     ((int16_t)prev->duty) + | ||||
|                     //     ((temp - prev->temp) * dduty) / dtemp | ||||
|                     // ); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -66,6 +74,40 @@ uint8_t fan_duty(int16_t temp) { | ||||
|     return PWM_DUTY(100); | ||||
| } | ||||
|  | ||||
| uint8_t fan_heatup(uint8_t duty) { | ||||
|     static uint8_t history[HEATUP] = { 0 }; | ||||
|     uint8_t lowest = duty; | ||||
|  | ||||
|     int i; | ||||
|     for (i = 0; (i + 1) < ARRAY_SIZE(history); i++) { | ||||
|         uint8_t value = history[i + 1]; | ||||
|         if (value < lowest) { | ||||
|             lowest = value; | ||||
|         } | ||||
|         history[i] = value; | ||||
|     } | ||||
|     history[i] = duty; | ||||
|  | ||||
|     return lowest; | ||||
| } | ||||
|  | ||||
| uint8_t fan_cooldown(uint8_t duty) { | ||||
|     static uint8_t history[COOLDOWN] = { 0 }; | ||||
|     uint8_t highest = duty; | ||||
|  | ||||
|     int i; | ||||
|     for (i = 0; (i + 1) < ARRAY_SIZE(history); i++) { | ||||
|         uint8_t value = history[i + 1]; | ||||
|         if (value > highest) { | ||||
|             highest = value; | ||||
|         } | ||||
|         history[i] = value; | ||||
|     } | ||||
|     history[i] = duty; | ||||
|  | ||||
|     return highest; | ||||
| } | ||||
|  | ||||
| void peci_init(void) { | ||||
|     // Allow PECI pin to be used | ||||
|     GCR2 |= (1 << 4); | ||||
| @@ -123,8 +165,10 @@ void peci_event(void) { | ||||
|         peci_duty = PWM_DUTY(0); | ||||
|     } | ||||
|  | ||||
|     if (peci_duty != DCR2) { | ||||
|         DCR2 = peci_duty; | ||||
|         DEBUG("PECI offset=%d, temp=%d = %d\n", peci_offset, peci_temp, peci_duty); | ||||
|     uint8_t heatup_duty = fan_heatup(peci_duty); | ||||
|     uint8_t cooldown_duty = fan_cooldown(heatup_duty); | ||||
|     if (cooldown_duty != DCR2) { | ||||
|         DCR2 = cooldown_duty; | ||||
|         DEBUG("PECI offset=%d, temp=%d = %d\n", peci_offset, peci_temp, cooldown_duty); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -386,11 +386,10 @@ void power_event(void) { | ||||
|     // state is S3 | ||||
|     static bool ack_last = false; | ||||
|     bool ack_new = gpio_get(&SUSWARN_N); | ||||
|     #if LEVEL >= LEVEL_DEBUG | ||||
|         if (ack_new && !ack_last) { | ||||
|             DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle); | ||||
|     } | ||||
|     #if LEVEL >= LEVEL_DEBUG | ||||
|         else if (!ack_new && ack_last) { | ||||
|         } else if (!ack_new && ack_last) { | ||||
|             DEBUG("%02X: SUSPWRDNACK de-asserted\n", main_cycle); | ||||
|         } | ||||
|     #endif | ||||
|   | ||||
| @@ -9,6 +9,7 @@ | ||||
| #include <common/command.h> | ||||
| #include <common/macro.h> | ||||
| #include <common/version.h> | ||||
| #include <ec/pwm.h> | ||||
|  | ||||
| // Shared memory host semaphore | ||||
| volatile uint8_t __xdata __at(0x1022) SMHSR; | ||||
| @@ -143,6 +144,30 @@ static enum Result cmd_reset(void) { | ||||
|     return RES_ERR; | ||||
| } | ||||
|  | ||||
| static enum Result cmd_fan_get(void) { | ||||
|     // If setting fan 0 | ||||
|     if (smfi_cmd[2] == 0) { | ||||
|         // Get duty of fan 0 | ||||
|         smfi_cmd[3] = DCR2; | ||||
|         return RES_OK; | ||||
|     } | ||||
|  | ||||
|     // Failed if fan not found | ||||
|     return RES_ERR; | ||||
| } | ||||
|  | ||||
| static enum Result cmd_fan_set(void) { | ||||
|     // If setting fan 0 | ||||
|     if (smfi_cmd[2] == 0) { | ||||
|         // Set duty cycle of fan 0 | ||||
|         DCR2 = smfi_cmd[3]; | ||||
|         return RES_OK; | ||||
|     } | ||||
|  | ||||
|     // Failed if fan not found | ||||
|     return RES_ERR; | ||||
| } | ||||
|  | ||||
| void smfi_event(void) { | ||||
|     if (smfi_cmd[0]) { | ||||
|         switch (smfi_cmd[0]) { | ||||
| @@ -174,6 +199,14 @@ void smfi_event(void) { | ||||
|             case CMD_RESET: | ||||
|                 smfi_cmd[1] = cmd_reset(); | ||||
|                 break; | ||||
| #ifndef __SCRATCH__ | ||||
|             case CMD_FAN_GET: | ||||
|                 smfi_cmd[1] = cmd_fan_get(); | ||||
|                 break; | ||||
|             case CMD_FAN_SET: | ||||
|                 smfi_cmd[1] = cmd_fan_set(); | ||||
|                 break; | ||||
| #endif // __SCRATCH__ | ||||
|             default: | ||||
|                 // Command not found | ||||
|                 smfi_cmd[1] = RES_ERR; | ||||
|   | ||||
| @@ -7,6 +7,12 @@ | ||||
| #include <ec/gpio.h> | ||||
| #include <ec/pwm.h> | ||||
|  | ||||
| // Fan speed is the lowest requested over HEATUP seconds | ||||
| #define HEATUP 5 | ||||
|  | ||||
| // Fan speed is the highest HEATUP speed over COOLDOWN seconds | ||||
| #define COOLDOWN 10 | ||||
|  | ||||
| // Tjunction = 100C for i7-8565U (and probably the same for all WHL-U) | ||||
| #define T_JUNCTION 100 | ||||
|  | ||||
| @@ -30,7 +36,7 @@ struct FanPoint __code FAN_POINTS[] = { | ||||
|     FAN_POINT(70,  45), | ||||
|     FAN_POINT(75,  55), | ||||
|     FAN_POINT(80,  75), | ||||
|     FAN_POINT(84, 100), | ||||
|     FAN_POINT(84, 100) | ||||
| }; | ||||
|  | ||||
| // Get duty cycle based on temperature, adapted from | ||||
| @@ -51,12 +57,14 @@ uint8_t fan_duty(int16_t temp) { | ||||
|  | ||||
|                 // If in between current temp and previous temp, interpolate | ||||
|                 if (temp > prev->temp) { | ||||
|                     int16_t dtemp = (cur->temp - prev->temp); | ||||
|                     int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty); | ||||
|                     return (uint8_t)( | ||||
|                         ((int16_t)prev->duty) + | ||||
|                         ((temp - prev->temp) * dduty) / dtemp | ||||
|                     ); | ||||
|                     return prev->duty; | ||||
|  | ||||
|                     // int16_t dtemp = (cur->temp - prev->temp); | ||||
|                     // int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty); | ||||
|                     // return (uint8_t)( | ||||
|                     //     ((int16_t)prev->duty) + | ||||
|                     //     ((temp - prev->temp) * dduty) / dtemp | ||||
|                     // ); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -66,6 +74,40 @@ uint8_t fan_duty(int16_t temp) { | ||||
|     return PWM_DUTY(100); | ||||
| } | ||||
|  | ||||
| uint8_t fan_heatup(uint8_t duty) { | ||||
|     static uint8_t history[HEATUP] = { 0 }; | ||||
|     uint8_t lowest = duty; | ||||
|  | ||||
|     int i; | ||||
|     for (i = 0; (i + 1) < ARRAY_SIZE(history); i++) { | ||||
|         uint8_t value = history[i + 1]; | ||||
|         if (value < lowest) { | ||||
|             lowest = value; | ||||
|         } | ||||
|         history[i] = value; | ||||
|     } | ||||
|     history[i] = duty; | ||||
|  | ||||
|     return lowest; | ||||
| } | ||||
|  | ||||
| uint8_t fan_cooldown(uint8_t duty) { | ||||
|     static uint8_t history[COOLDOWN] = { 0 }; | ||||
|     uint8_t highest = duty; | ||||
|  | ||||
|     int i; | ||||
|     for (i = 0; (i + 1) < ARRAY_SIZE(history); i++) { | ||||
|         uint8_t value = history[i + 1]; | ||||
|         if (value > highest) { | ||||
|             highest = value; | ||||
|         } | ||||
|         history[i] = value; | ||||
|     } | ||||
|     history[i] = duty; | ||||
|  | ||||
|     return highest; | ||||
| } | ||||
|  | ||||
| void peci_init(void) { | ||||
|     // Allow PECI pin to be used | ||||
|     GCR2 |= (1 << 4); | ||||
| @@ -123,8 +165,10 @@ void peci_event(void) { | ||||
|         peci_duty = PWM_DUTY(0); | ||||
|     } | ||||
|  | ||||
|     if (peci_duty != DCR2) { | ||||
|         DCR2 = peci_duty; | ||||
|         DEBUG("PECI offset=%d, temp=%d = %d\n", peci_offset, peci_temp, peci_duty); | ||||
|     uint8_t heatup_duty = fan_heatup(peci_duty); | ||||
|     uint8_t cooldown_duty = fan_cooldown(heatup_duty); | ||||
|     if (cooldown_duty != DCR2) { | ||||
|         DCR2 = cooldown_duty; | ||||
|         DEBUG("PECI offset=%d, temp=%d = %d\n", peci_offset, peci_temp, cooldown_duty); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -383,11 +383,10 @@ void power_event(void) { | ||||
|     // state is S3 | ||||
|     static bool ack_last = false; | ||||
|     bool ack_new = gpio_get(&SUSWARN_N); | ||||
|     #if LEVEL >= LEVEL_DEBUG | ||||
|         if (ack_new && !ack_last) { | ||||
|             DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle); | ||||
|     } | ||||
|     #if LEVEL >= LEVEL_DEBUG | ||||
|         else if (!ack_new && ack_last) { | ||||
|         } else if (!ack_new && ack_last) { | ||||
|             DEBUG("%02X: SUSPWRDNACK de-asserted\n", main_cycle); | ||||
|         } | ||||
|     #endif | ||||
|   | ||||
| @@ -9,6 +9,7 @@ | ||||
| #include <common/command.h> | ||||
| #include <common/macro.h> | ||||
| #include <common/version.h> | ||||
| #include <ec/pwm.h> | ||||
|  | ||||
| // Shared memory host semaphore | ||||
| volatile uint8_t __xdata __at(0x1022) SMHSR; | ||||
| @@ -143,6 +144,30 @@ static enum Result cmd_reset(void) { | ||||
|     return RES_ERR; | ||||
| } | ||||
|  | ||||
| static enum Result cmd_fan_get(void) { | ||||
|     // If setting fan 0 | ||||
|     if (smfi_cmd[2] == 0) { | ||||
|         // Get duty of fan 0 | ||||
|         smfi_cmd[3] = DCR2; | ||||
|         return RES_OK; | ||||
|     } | ||||
|  | ||||
|     // Failed if fan not found | ||||
|     return RES_ERR; | ||||
| } | ||||
|  | ||||
| static enum Result cmd_fan_set(void) { | ||||
|     // If setting fan 0 | ||||
|     if (smfi_cmd[2] == 0) { | ||||
|         // Set duty cycle of fan 0 | ||||
|         DCR2 = smfi_cmd[3]; | ||||
|         return RES_OK; | ||||
|     } | ||||
|  | ||||
|     // Failed if fan not found | ||||
|     return RES_ERR; | ||||
| } | ||||
|  | ||||
| void smfi_event(void) { | ||||
|     if (smfi_cmd[0]) { | ||||
|         switch (smfi_cmd[0]) { | ||||
| @@ -174,6 +199,14 @@ void smfi_event(void) { | ||||
|             case CMD_RESET: | ||||
|                 smfi_cmd[1] = cmd_reset(); | ||||
|                 break; | ||||
| #ifndef __SCRATCH__ | ||||
|             case CMD_FAN_GET: | ||||
|                 smfi_cmd[1] = cmd_fan_get(); | ||||
|                 break; | ||||
|             case CMD_FAN_SET: | ||||
|                 smfi_cmd[1] = cmd_fan_set(); | ||||
|                 break; | ||||
| #endif // __SCRATCH__ | ||||
|             default: | ||||
|                 // Command not found | ||||
|                 smfi_cmd[1] = RES_ERR; | ||||
|   | ||||
| @@ -7,6 +7,12 @@ | ||||
| #include <ec/gpio.h> | ||||
| #include <ec/pwm.h> | ||||
|  | ||||
| // Fan speed is the lowest requested over HEATUP seconds | ||||
| #define HEATUP 5 | ||||
|  | ||||
| // Fan speed is the highest HEATUP speed over COOLDOWN seconds | ||||
| #define COOLDOWN 10 | ||||
|  | ||||
| // Tjunction = 100C for i7-8565U (and probably the same for all WHL-U) | ||||
| #define T_JUNCTION 100 | ||||
|  | ||||
| @@ -30,7 +36,7 @@ struct FanPoint __code FAN_POINTS[] = { | ||||
|     FAN_POINT(70,  45), | ||||
|     FAN_POINT(75,  55), | ||||
|     FAN_POINT(80,  75), | ||||
|     FAN_POINT(84, 100), | ||||
|     FAN_POINT(84, 100) | ||||
| }; | ||||
|  | ||||
| // Get duty cycle based on temperature, adapted from | ||||
| @@ -51,12 +57,14 @@ uint8_t fan_duty(int16_t temp) { | ||||
|  | ||||
|                 // If in between current temp and previous temp, interpolate | ||||
|                 if (temp > prev->temp) { | ||||
|                     int16_t dtemp = (cur->temp - prev->temp); | ||||
|                     int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty); | ||||
|                     return (uint8_t)( | ||||
|                         ((int16_t)prev->duty) + | ||||
|                         ((temp - prev->temp) * dduty) / dtemp | ||||
|                     ); | ||||
|                     return prev->duty; | ||||
|  | ||||
|                     // int16_t dtemp = (cur->temp - prev->temp); | ||||
|                     // int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty); | ||||
|                     // return (uint8_t)( | ||||
|                     //     ((int16_t)prev->duty) + | ||||
|                     //     ((temp - prev->temp) * dduty) / dtemp | ||||
|                     // ); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -66,6 +74,40 @@ uint8_t fan_duty(int16_t temp) { | ||||
|     return PWM_DUTY(100); | ||||
| } | ||||
|  | ||||
| uint8_t fan_heatup(uint8_t duty) { | ||||
|     static uint8_t history[HEATUP] = { 0 }; | ||||
|     uint8_t lowest = duty; | ||||
|  | ||||
|     int i; | ||||
|     for (i = 0; (i + 1) < ARRAY_SIZE(history); i++) { | ||||
|         uint8_t value = history[i + 1]; | ||||
|         if (value < lowest) { | ||||
|             lowest = value; | ||||
|         } | ||||
|         history[i] = value; | ||||
|     } | ||||
|     history[i] = duty; | ||||
|  | ||||
|     return lowest; | ||||
| } | ||||
|  | ||||
| uint8_t fan_cooldown(uint8_t duty) { | ||||
|     static uint8_t history[COOLDOWN] = { 0 }; | ||||
|     uint8_t highest = duty; | ||||
|  | ||||
|     int i; | ||||
|     for (i = 0; (i + 1) < ARRAY_SIZE(history); i++) { | ||||
|         uint8_t value = history[i + 1]; | ||||
|         if (value > highest) { | ||||
|             highest = value; | ||||
|         } | ||||
|         history[i] = value; | ||||
|     } | ||||
|     history[i] = duty; | ||||
|  | ||||
|     return highest; | ||||
| } | ||||
|  | ||||
| void peci_init(void) { | ||||
|     // Allow PECI pin to be used | ||||
|     GCR2 |= (1 << 4); | ||||
| @@ -123,8 +165,10 @@ void peci_event(void) { | ||||
|         peci_duty = PWM_DUTY(0); | ||||
|     } | ||||
|  | ||||
|     if (peci_duty != DCR2) { | ||||
|         DCR2 = peci_duty; | ||||
|         DEBUG("PECI offset=%d, temp=%d = %d\n", peci_offset, peci_temp, peci_duty); | ||||
|     uint8_t heatup_duty = fan_heatup(peci_duty); | ||||
|     uint8_t cooldown_duty = fan_cooldown(heatup_duty); | ||||
|     if (cooldown_duty != DCR2) { | ||||
|         DCR2 = cooldown_duty; | ||||
|         DEBUG("PECI offset=%d, temp=%d = %d\n", peci_offset, peci_temp, cooldown_duty); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -383,11 +383,10 @@ void power_event(void) { | ||||
|     // state is S3 | ||||
|     static bool ack_last = false; | ||||
|     bool ack_new = gpio_get(&SUSWARN_N); | ||||
|     #if LEVEL >= LEVEL_DEBUG | ||||
|         if (ack_new && !ack_last) { | ||||
|             DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle); | ||||
|     } | ||||
|     #if LEVEL >= LEVEL_DEBUG | ||||
|         else if (!ack_new && ack_last) { | ||||
|         } else if (!ack_new && ack_last) { | ||||
|             DEBUG("%02X: SUSPWRDNACK de-asserted\n", main_cycle); | ||||
|         } | ||||
|     #endif | ||||
|   | ||||
| @@ -9,6 +9,7 @@ | ||||
| #include <common/command.h> | ||||
| #include <common/macro.h> | ||||
| #include <common/version.h> | ||||
| #include <ec/pwm.h> | ||||
|  | ||||
| // Shared memory host semaphore | ||||
| volatile uint8_t __xdata __at(0x1022) SMHSR; | ||||
| @@ -143,6 +144,30 @@ static enum Result cmd_reset(void) { | ||||
|     return RES_ERR; | ||||
| } | ||||
|  | ||||
| static enum Result cmd_fan_get(void) { | ||||
|     // If setting fan 0 | ||||
|     if (smfi_cmd[2] == 0) { | ||||
|         // Get duty of fan 0 | ||||
|         smfi_cmd[3] = DCR2; | ||||
|         return RES_OK; | ||||
|     } | ||||
|  | ||||
|     // Failed if fan not found | ||||
|     return RES_ERR; | ||||
| } | ||||
|  | ||||
| static enum Result cmd_fan_set(void) { | ||||
|     // If setting fan 0 | ||||
|     if (smfi_cmd[2] == 0) { | ||||
|         // Set duty cycle of fan 0 | ||||
|         DCR2 = smfi_cmd[3]; | ||||
|         return RES_OK; | ||||
|     } | ||||
|  | ||||
|     // Failed if fan not found | ||||
|     return RES_ERR; | ||||
| } | ||||
|  | ||||
| void smfi_event(void) { | ||||
|     if (smfi_cmd[0]) { | ||||
|         switch (smfi_cmd[0]) { | ||||
| @@ -174,6 +199,14 @@ void smfi_event(void) { | ||||
|             case CMD_RESET: | ||||
|                 smfi_cmd[1] = cmd_reset(); | ||||
|                 break; | ||||
| #ifndef __SCRATCH__ | ||||
|             case CMD_FAN_GET: | ||||
|                 smfi_cmd[1] = cmd_fan_get(); | ||||
|                 break; | ||||
|             case CMD_FAN_SET: | ||||
|                 smfi_cmd[1] = cmd_fan_set(); | ||||
|                 break; | ||||
| #endif // __SCRATCH__ | ||||
|             default: | ||||
|                 // Command not found | ||||
|                 smfi_cmd[1] = RES_ERR; | ||||
|   | ||||
| @@ -16,6 +16,10 @@ enum Command { | ||||
|     CMD_SPI = 5, | ||||
|     // Reset EC | ||||
|     CMD_RESET = 6, | ||||
|     // Get fan speeds | ||||
|     CMD_FAN_GET = 7, | ||||
|     // Set fan speeds | ||||
|     CMD_FAN_SET = 8, | ||||
|     //TODO | ||||
| }; | ||||
|  | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								tool/src/.ec.rs.swp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tool/src/.ec.rs.swp
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -19,12 +19,14 @@ pub enum Cmd { | ||||
|     Print = 4, | ||||
|     Spi = 5, | ||||
|     Reset = 6, | ||||
|     FanGet = 7, | ||||
|     FanSet = 8, | ||||
| } | ||||
|  | ||||
| pub const CMD_SPI_FLAG_READ: u8 = (1 << 0); | ||||
| pub const CMD_SPI_FLAG_DISABLE: u8 = (1 << 1); | ||||
| pub const CMD_SPI_FLAG_SCRATCH: u8 = (1 << 2); | ||||
| pub const CMD_SPI_FLAG_BACKUP: u8 = (1 << 3); | ||||
| pub const CMD_SPI_FLAG_READ: u8 = 1 << 0; | ||||
| pub const CMD_SPI_FLAG_DISABLE: u8 = 1 << 1; | ||||
| pub const CMD_SPI_FLAG_SCRATCH: u8 = 1 << 2; | ||||
| pub const CMD_SPI_FLAG_BACKUP: u8 = 1 << 3; | ||||
|  | ||||
| pub struct Ec<T: Timeout> { | ||||
|     cmd: u16, | ||||
| @@ -181,6 +183,18 @@ impl<T: Timeout> Ec<T> { | ||||
|     pub unsafe fn reset(&mut self) -> Result<(), Error> { | ||||
|         self.command(Cmd::Reset) | ||||
|     } | ||||
|  | ||||
|     pub unsafe fn fan_get(&mut self, index: u8) -> Result<u8, Error> { | ||||
|         self.write(2, index); | ||||
|         self.command(Cmd::FanGet)?; | ||||
|         Ok(self.read(3)) | ||||
|     } | ||||
|  | ||||
|     pub unsafe fn fan_set(&mut self, index: u8, duty: u8) -> Result<(), Error> { | ||||
|         self.write(2, index); | ||||
|         self.write(3, duty); | ||||
|         self.command(Cmd::FanSet) | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub struct EcSpi<'a, T: Timeout> { | ||||
|   | ||||
| @@ -274,9 +274,33 @@ unsafe fn print(message: &[u8]) -> Result<(), Error> { | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| unsafe fn fan_get(index: u8) -> Result<(), Error> { | ||||
|     iopl(); | ||||
|  | ||||
|     let mut ec = Ec::new( | ||||
|         StdTimeout::new(Duration::new(1, 0)), | ||||
|     )?; | ||||
|  | ||||
|     let duty = ec.fan_get(index)?; | ||||
|     println!("{}", duty); | ||||
|  | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| unsafe fn fan_set(index: u8, duty: u8) -> Result<(), Error> { | ||||
|     iopl(); | ||||
|  | ||||
|     let mut ec = Ec::new( | ||||
|         StdTimeout::new(Duration::new(1, 0)), | ||||
|     )?; | ||||
|  | ||||
|     ec.fan_set(index, duty) | ||||
| } | ||||
|  | ||||
| fn usage() { | ||||
|     eprintln!("  console"); | ||||
|     eprintln!("  flash [file]"); | ||||
|     eprintln!("  fan [index] <duty>"); | ||||
|     eprintln!("  info"); | ||||
|     eprintln!("  print [message]"); | ||||
| } | ||||
| @@ -293,6 +317,40 @@ fn main() { | ||||
|                     process::exit(1); | ||||
|                 }, | ||||
|             }, | ||||
|             "fan" => match args.next() { | ||||
|                 Some(index_str) => match index_str.parse::<u8>() { | ||||
|                     Ok(index) => match args.next() { | ||||
|                         Some(duty_str) => match duty_str.parse::<u8>() { | ||||
|                             Ok(duty) => match unsafe { fan_set(index, duty) } { | ||||
|                                 Ok(()) => (), | ||||
|                                 Err(err) => { | ||||
|                                     eprintln!("failed to set fan {} to {}: {:X?}", index, duty, err); | ||||
|                                     process::exit(1); | ||||
|                                 }, | ||||
|                             }, | ||||
|                             Err(err) => { | ||||
|                                 eprintln!("failed to parse '{}': {:X?}", duty_str, err); | ||||
|                                 process::exit(1); | ||||
|                             }, | ||||
|                         }, | ||||
|                         None => match unsafe { fan_get(index) } { | ||||
|                             Ok(()) => (), | ||||
|                             Err(err) => { | ||||
|                                 eprintln!("failed to get fan {}: {:X?}", index, err); | ||||
|                                 process::exit(1); | ||||
|                             }, | ||||
|                         }, | ||||
|                     }, | ||||
|                     Err(err) => { | ||||
|                         eprintln!("failed to parse '{}': {:X?}", index_str, err); | ||||
|                         process::exit(1); | ||||
|                     }, | ||||
|                 }, | ||||
|                 None => { | ||||
|                     eprintln!("no index provided"); | ||||
|                     process::exit(1); | ||||
|                 }, | ||||
|             }, | ||||
|             "flash" => match args.next() { | ||||
|                 Some(path) => match unsafe { flash(&path) } { | ||||
|                     Ok(()) => (), | ||||
|   | ||||
		Reference in New Issue
	
	Block a user