Improve fan curve
- Implement fan cooldown and heatup periods - Add fan get/set commands - Fix compilation with logging level lower than debug
This commit is contained in:
		| @@ -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 LEVEL >= LEVEL_DEBUG | ||||||
|         if (ack_new && !ack_last) { |         if (ack_new && !ack_last) { | ||||||
|             DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle); |             DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle); | ||||||
|     } |         } else if (!ack_new && ack_last) { | ||||||
|     #if LEVEL >= LEVEL_DEBUG |  | ||||||
|         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 LEVEL >= LEVEL_DEBUG | ||||||
|         if (ack_new && !ack_last) { |         if (ack_new && !ack_last) { | ||||||
|             DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle); |             DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle); | ||||||
|     } |         } else if (!ack_new && ack_last) { | ||||||
|     #if LEVEL >= LEVEL_DEBUG |  | ||||||
|         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 LEVEL >= LEVEL_DEBUG | ||||||
|         if (ack_new && !ack_last) { |         if (ack_new && !ack_last) { | ||||||
|             DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle); |             DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle); | ||||||
|     } |         } else if (!ack_new && ack_last) { | ||||||
|     #if LEVEL >= LEVEL_DEBUG |  | ||||||
|         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)?; | ||||||
|  |     eprintln!("{}", 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