2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1 +1,3 @@
 | 
				
			|||||||
/build/
 | 
					/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/gpio.h>
 | 
				
			||||||
#include <ec/pwm.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)
 | 
					// Tjunction = 100C for i7-8565U (and probably the same for all WHL-U)
 | 
				
			||||||
#define T_JUNCTION 100
 | 
					#define T_JUNCTION 100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -30,7 +36,7 @@ struct FanPoint __code FAN_POINTS[] = {
 | 
				
			|||||||
    FAN_POINT(70,  45),
 | 
					    FAN_POINT(70,  45),
 | 
				
			||||||
    FAN_POINT(75,  55),
 | 
					    FAN_POINT(75,  55),
 | 
				
			||||||
    FAN_POINT(80,  75),
 | 
					    FAN_POINT(80,  75),
 | 
				
			||||||
    FAN_POINT(84, 100),
 | 
					    FAN_POINT(84, 100)
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Get duty cycle based on temperature, adapted from
 | 
					// 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 in between current temp and previous temp, interpolate
 | 
				
			||||||
                if (temp > prev->temp) {
 | 
					                if (temp > prev->temp) {
 | 
				
			||||||
                    int16_t dtemp = (cur->temp - prev->temp);
 | 
					                    return prev->duty;
 | 
				
			||||||
                    int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty);
 | 
					
 | 
				
			||||||
                    return (uint8_t)(
 | 
					                    // int16_t dtemp = (cur->temp - prev->temp);
 | 
				
			||||||
                        ((int16_t)prev->duty) +
 | 
					                    // int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty);
 | 
				
			||||||
                        ((temp - prev->temp) * dduty) / dtemp
 | 
					                    // 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);
 | 
					    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) {
 | 
					void peci_init(void) {
 | 
				
			||||||
    // Allow PECI pin to be used
 | 
					    // Allow PECI pin to be used
 | 
				
			||||||
    GCR2 |= (1 << 4);
 | 
					    GCR2 |= (1 << 4);
 | 
				
			||||||
@@ -123,8 +165,10 @@ void peci_event(void) {
 | 
				
			|||||||
        peci_duty = PWM_DUTY(0);
 | 
					        peci_duty = PWM_DUTY(0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (peci_duty != DCR2) {
 | 
					    uint8_t heatup_duty = fan_heatup(peci_duty);
 | 
				
			||||||
        DCR2 = peci_duty;
 | 
					    uint8_t cooldown_duty = fan_cooldown(heatup_duty);
 | 
				
			||||||
        DEBUG("PECI offset=%d, temp=%d = %d\n", peci_offset, peci_temp, peci_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
 | 
					    // state is S3
 | 
				
			||||||
    static bool ack_last = false;
 | 
					    static bool ack_last = false;
 | 
				
			||||||
    bool ack_new = gpio_get(&SUSWARN_N);
 | 
					    bool ack_new = gpio_get(&SUSWARN_N);
 | 
				
			||||||
    if (ack_new && !ack_last) {
 | 
					 | 
				
			||||||
        DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    #if LEVEL >= LEVEL_DEBUG
 | 
					    #if LEVEL >= LEVEL_DEBUG
 | 
				
			||||||
        else if (!ack_new && ack_last) {
 | 
					        if (ack_new && !ack_last) {
 | 
				
			||||||
 | 
					            DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle);
 | 
				
			||||||
 | 
					        } else if (!ack_new && ack_last) {
 | 
				
			||||||
            DEBUG("%02X: SUSPWRDNACK de-asserted\n", main_cycle);
 | 
					            DEBUG("%02X: SUSPWRDNACK de-asserted\n", main_cycle);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@
 | 
				
			|||||||
#include <common/command.h>
 | 
					#include <common/command.h>
 | 
				
			||||||
#include <common/macro.h>
 | 
					#include <common/macro.h>
 | 
				
			||||||
#include <common/version.h>
 | 
					#include <common/version.h>
 | 
				
			||||||
 | 
					#include <ec/pwm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Shared memory host semaphore
 | 
					// Shared memory host semaphore
 | 
				
			||||||
volatile uint8_t __xdata __at(0x1022) SMHSR;
 | 
					volatile uint8_t __xdata __at(0x1022) SMHSR;
 | 
				
			||||||
@@ -143,6 +144,30 @@ static enum Result cmd_reset(void) {
 | 
				
			|||||||
    return RES_ERR;
 | 
					    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) {
 | 
					void smfi_event(void) {
 | 
				
			||||||
    if (smfi_cmd[0]) {
 | 
					    if (smfi_cmd[0]) {
 | 
				
			||||||
        switch (smfi_cmd[0]) {
 | 
					        switch (smfi_cmd[0]) {
 | 
				
			||||||
@@ -174,6 +199,14 @@ void smfi_event(void) {
 | 
				
			|||||||
            case CMD_RESET:
 | 
					            case CMD_RESET:
 | 
				
			||||||
                smfi_cmd[1] = cmd_reset();
 | 
					                smfi_cmd[1] = cmd_reset();
 | 
				
			||||||
                break;
 | 
					                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:
 | 
					            default:
 | 
				
			||||||
                // Command not found
 | 
					                // Command not found
 | 
				
			||||||
                smfi_cmd[1] = RES_ERR;
 | 
					                smfi_cmd[1] = RES_ERR;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,12 @@
 | 
				
			|||||||
#include <ec/gpio.h>
 | 
					#include <ec/gpio.h>
 | 
				
			||||||
#include <ec/pwm.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)
 | 
					// Tjunction = 100C for i7-8565U (and probably the same for all WHL-U)
 | 
				
			||||||
#define T_JUNCTION 100
 | 
					#define T_JUNCTION 100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -30,7 +36,7 @@ struct FanPoint __code FAN_POINTS[] = {
 | 
				
			|||||||
    FAN_POINT(70,  45),
 | 
					    FAN_POINT(70,  45),
 | 
				
			||||||
    FAN_POINT(75,  55),
 | 
					    FAN_POINT(75,  55),
 | 
				
			||||||
    FAN_POINT(80,  75),
 | 
					    FAN_POINT(80,  75),
 | 
				
			||||||
    FAN_POINT(84, 100),
 | 
					    FAN_POINT(84, 100)
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Get duty cycle based on temperature, adapted from
 | 
					// 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 in between current temp and previous temp, interpolate
 | 
				
			||||||
                if (temp > prev->temp) {
 | 
					                if (temp > prev->temp) {
 | 
				
			||||||
                    int16_t dtemp = (cur->temp - prev->temp);
 | 
					                    return prev->duty;
 | 
				
			||||||
                    int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty);
 | 
					
 | 
				
			||||||
                    return (uint8_t)(
 | 
					                    // int16_t dtemp = (cur->temp - prev->temp);
 | 
				
			||||||
                        ((int16_t)prev->duty) +
 | 
					                    // int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty);
 | 
				
			||||||
                        ((temp - prev->temp) * dduty) / dtemp
 | 
					                    // 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);
 | 
					    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) {
 | 
					void peci_init(void) {
 | 
				
			||||||
    // Allow PECI pin to be used
 | 
					    // Allow PECI pin to be used
 | 
				
			||||||
    GCR2 |= (1 << 4);
 | 
					    GCR2 |= (1 << 4);
 | 
				
			||||||
@@ -123,8 +165,10 @@ void peci_event(void) {
 | 
				
			|||||||
        peci_duty = PWM_DUTY(0);
 | 
					        peci_duty = PWM_DUTY(0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (peci_duty != DCR2) {
 | 
					    uint8_t heatup_duty = fan_heatup(peci_duty);
 | 
				
			||||||
        DCR2 = peci_duty;
 | 
					    uint8_t cooldown_duty = fan_cooldown(heatup_duty);
 | 
				
			||||||
        DEBUG("PECI offset=%d, temp=%d = %d\n", peci_offset, peci_temp, peci_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
 | 
					    // state is S3
 | 
				
			||||||
    static bool ack_last = false;
 | 
					    static bool ack_last = false;
 | 
				
			||||||
    bool ack_new = gpio_get(&SUSWARN_N);
 | 
					    bool ack_new = gpio_get(&SUSWARN_N);
 | 
				
			||||||
    if (ack_new && !ack_last) {
 | 
					 | 
				
			||||||
        DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    #if LEVEL >= LEVEL_DEBUG
 | 
					    #if LEVEL >= LEVEL_DEBUG
 | 
				
			||||||
        else if (!ack_new && ack_last) {
 | 
					        if (ack_new && !ack_last) {
 | 
				
			||||||
 | 
					            DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle);
 | 
				
			||||||
 | 
					        } else if (!ack_new && ack_last) {
 | 
				
			||||||
            DEBUG("%02X: SUSPWRDNACK de-asserted\n", main_cycle);
 | 
					            DEBUG("%02X: SUSPWRDNACK de-asserted\n", main_cycle);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@
 | 
				
			|||||||
#include <common/command.h>
 | 
					#include <common/command.h>
 | 
				
			||||||
#include <common/macro.h>
 | 
					#include <common/macro.h>
 | 
				
			||||||
#include <common/version.h>
 | 
					#include <common/version.h>
 | 
				
			||||||
 | 
					#include <ec/pwm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Shared memory host semaphore
 | 
					// Shared memory host semaphore
 | 
				
			||||||
volatile uint8_t __xdata __at(0x1022) SMHSR;
 | 
					volatile uint8_t __xdata __at(0x1022) SMHSR;
 | 
				
			||||||
@@ -143,6 +144,30 @@ static enum Result cmd_reset(void) {
 | 
				
			|||||||
    return RES_ERR;
 | 
					    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) {
 | 
					void smfi_event(void) {
 | 
				
			||||||
    if (smfi_cmd[0]) {
 | 
					    if (smfi_cmd[0]) {
 | 
				
			||||||
        switch (smfi_cmd[0]) {
 | 
					        switch (smfi_cmd[0]) {
 | 
				
			||||||
@@ -174,6 +199,14 @@ void smfi_event(void) {
 | 
				
			|||||||
            case CMD_RESET:
 | 
					            case CMD_RESET:
 | 
				
			||||||
                smfi_cmd[1] = cmd_reset();
 | 
					                smfi_cmd[1] = cmd_reset();
 | 
				
			||||||
                break;
 | 
					                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:
 | 
					            default:
 | 
				
			||||||
                // Command not found
 | 
					                // Command not found
 | 
				
			||||||
                smfi_cmd[1] = RES_ERR;
 | 
					                smfi_cmd[1] = RES_ERR;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,12 @@
 | 
				
			|||||||
#include <ec/gpio.h>
 | 
					#include <ec/gpio.h>
 | 
				
			||||||
#include <ec/pwm.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)
 | 
					// Tjunction = 100C for i7-8565U (and probably the same for all WHL-U)
 | 
				
			||||||
#define T_JUNCTION 100
 | 
					#define T_JUNCTION 100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -30,7 +36,7 @@ struct FanPoint __code FAN_POINTS[] = {
 | 
				
			|||||||
    FAN_POINT(70,  45),
 | 
					    FAN_POINT(70,  45),
 | 
				
			||||||
    FAN_POINT(75,  55),
 | 
					    FAN_POINT(75,  55),
 | 
				
			||||||
    FAN_POINT(80,  75),
 | 
					    FAN_POINT(80,  75),
 | 
				
			||||||
    FAN_POINT(84, 100),
 | 
					    FAN_POINT(84, 100)
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Get duty cycle based on temperature, adapted from
 | 
					// 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 in between current temp and previous temp, interpolate
 | 
				
			||||||
                if (temp > prev->temp) {
 | 
					                if (temp > prev->temp) {
 | 
				
			||||||
                    int16_t dtemp = (cur->temp - prev->temp);
 | 
					                    return prev->duty;
 | 
				
			||||||
                    int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty);
 | 
					
 | 
				
			||||||
                    return (uint8_t)(
 | 
					                    // int16_t dtemp = (cur->temp - prev->temp);
 | 
				
			||||||
                        ((int16_t)prev->duty) +
 | 
					                    // int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty);
 | 
				
			||||||
                        ((temp - prev->temp) * dduty) / dtemp
 | 
					                    // 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);
 | 
					    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) {
 | 
					void peci_init(void) {
 | 
				
			||||||
    // Allow PECI pin to be used
 | 
					    // Allow PECI pin to be used
 | 
				
			||||||
    GCR2 |= (1 << 4);
 | 
					    GCR2 |= (1 << 4);
 | 
				
			||||||
@@ -123,8 +165,10 @@ void peci_event(void) {
 | 
				
			|||||||
        peci_duty = PWM_DUTY(0);
 | 
					        peci_duty = PWM_DUTY(0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (peci_duty != DCR2) {
 | 
					    uint8_t heatup_duty = fan_heatup(peci_duty);
 | 
				
			||||||
        DCR2 = peci_duty;
 | 
					    uint8_t cooldown_duty = fan_cooldown(heatup_duty);
 | 
				
			||||||
        DEBUG("PECI offset=%d, temp=%d = %d\n", peci_offset, peci_temp, peci_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
 | 
					    // state is S3
 | 
				
			||||||
    static bool ack_last = false;
 | 
					    static bool ack_last = false;
 | 
				
			||||||
    bool ack_new = gpio_get(&SUSWARN_N);
 | 
					    bool ack_new = gpio_get(&SUSWARN_N);
 | 
				
			||||||
    if (ack_new && !ack_last) {
 | 
					 | 
				
			||||||
        DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    #if LEVEL >= LEVEL_DEBUG
 | 
					    #if LEVEL >= LEVEL_DEBUG
 | 
				
			||||||
        else if (!ack_new && ack_last) {
 | 
					        if (ack_new && !ack_last) {
 | 
				
			||||||
 | 
					            DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle);
 | 
				
			||||||
 | 
					        } else if (!ack_new && ack_last) {
 | 
				
			||||||
            DEBUG("%02X: SUSPWRDNACK de-asserted\n", main_cycle);
 | 
					            DEBUG("%02X: SUSPWRDNACK de-asserted\n", main_cycle);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@
 | 
				
			|||||||
#include <common/command.h>
 | 
					#include <common/command.h>
 | 
				
			||||||
#include <common/macro.h>
 | 
					#include <common/macro.h>
 | 
				
			||||||
#include <common/version.h>
 | 
					#include <common/version.h>
 | 
				
			||||||
 | 
					#include <ec/pwm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Shared memory host semaphore
 | 
					// Shared memory host semaphore
 | 
				
			||||||
volatile uint8_t __xdata __at(0x1022) SMHSR;
 | 
					volatile uint8_t __xdata __at(0x1022) SMHSR;
 | 
				
			||||||
@@ -143,6 +144,30 @@ static enum Result cmd_reset(void) {
 | 
				
			|||||||
    return RES_ERR;
 | 
					    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) {
 | 
					void smfi_event(void) {
 | 
				
			||||||
    if (smfi_cmd[0]) {
 | 
					    if (smfi_cmd[0]) {
 | 
				
			||||||
        switch (smfi_cmd[0]) {
 | 
					        switch (smfi_cmd[0]) {
 | 
				
			||||||
@@ -174,6 +199,14 @@ void smfi_event(void) {
 | 
				
			|||||||
            case CMD_RESET:
 | 
					            case CMD_RESET:
 | 
				
			||||||
                smfi_cmd[1] = cmd_reset();
 | 
					                smfi_cmd[1] = cmd_reset();
 | 
				
			||||||
                break;
 | 
					                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:
 | 
					            default:
 | 
				
			||||||
                // Command not found
 | 
					                // Command not found
 | 
				
			||||||
                smfi_cmd[1] = RES_ERR;
 | 
					                smfi_cmd[1] = RES_ERR;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,10 @@ enum Command {
 | 
				
			|||||||
    CMD_SPI = 5,
 | 
					    CMD_SPI = 5,
 | 
				
			||||||
    // Reset EC
 | 
					    // Reset EC
 | 
				
			||||||
    CMD_RESET = 6,
 | 
					    CMD_RESET = 6,
 | 
				
			||||||
 | 
					    // Get fan speeds
 | 
				
			||||||
 | 
					    CMD_FAN_GET = 7,
 | 
				
			||||||
 | 
					    // Set fan speeds
 | 
				
			||||||
 | 
					    CMD_FAN_SET = 8,
 | 
				
			||||||
    //TODO
 | 
					    //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,
 | 
					    Print = 4,
 | 
				
			||||||
    Spi = 5,
 | 
					    Spi = 5,
 | 
				
			||||||
    Reset = 6,
 | 
					    Reset = 6,
 | 
				
			||||||
 | 
					    FanGet = 7,
 | 
				
			||||||
 | 
					    FanSet = 8,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub const CMD_SPI_FLAG_READ: u8 = (1 << 0);
 | 
					pub const CMD_SPI_FLAG_READ: u8 = 1 << 0;
 | 
				
			||||||
pub const CMD_SPI_FLAG_DISABLE: u8 = (1 << 1);
 | 
					pub const CMD_SPI_FLAG_DISABLE: u8 = 1 << 1;
 | 
				
			||||||
pub const CMD_SPI_FLAG_SCRATCH: u8 = (1 << 2);
 | 
					pub const CMD_SPI_FLAG_SCRATCH: u8 = 1 << 2;
 | 
				
			||||||
pub const CMD_SPI_FLAG_BACKUP: u8 = (1 << 3);
 | 
					pub const CMD_SPI_FLAG_BACKUP: u8 = 1 << 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct Ec<T: Timeout> {
 | 
					pub struct Ec<T: Timeout> {
 | 
				
			||||||
    cmd: u16,
 | 
					    cmd: u16,
 | 
				
			||||||
@@ -181,6 +183,18 @@ impl<T: Timeout> Ec<T> {
 | 
				
			|||||||
    pub unsafe fn reset(&mut self) -> Result<(), Error> {
 | 
					    pub unsafe fn reset(&mut self) -> Result<(), Error> {
 | 
				
			||||||
        self.command(Cmd::Reset)
 | 
					        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> {
 | 
					pub struct EcSpi<'a, T: Timeout> {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -274,9 +274,33 @@ unsafe fn print(message: &[u8]) -> Result<(), Error> {
 | 
				
			|||||||
    Ok(())
 | 
					    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() {
 | 
					fn usage() {
 | 
				
			||||||
    eprintln!("  console");
 | 
					    eprintln!("  console");
 | 
				
			||||||
    eprintln!("  flash [file]");
 | 
					    eprintln!("  flash [file]");
 | 
				
			||||||
 | 
					    eprintln!("  fan [index] <duty>");
 | 
				
			||||||
    eprintln!("  info");
 | 
					    eprintln!("  info");
 | 
				
			||||||
    eprintln!("  print [message]");
 | 
					    eprintln!("  print [message]");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -293,6 +317,40 @@ fn main() {
 | 
				
			|||||||
                    process::exit(1);
 | 
					                    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() {
 | 
					            "flash" => match args.next() {
 | 
				
			||||||
                Some(path) => match unsafe { flash(&path) } {
 | 
					                Some(path) => match unsafe { flash(&path) } {
 | 
				
			||||||
                    Ok(()) => (),
 | 
					                    Ok(()) => (),
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user