From 84eea7fdc46dd76e84cafbf96813bc826d5e08ad Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sun, 27 Aug 2017 16:20:38 -0500 Subject: Add initial support for the ASpeed 2050 and the ASUS KGPE-D16 Thermal management is functional but expects all fans to be attached Known issues: * BMC has been observed spontaneously rebooting after ~7-8 hours uptime with no logs and no console output. * While kcs has been implemented, the IPMI daemon is only functional enough to report chassis status. --- common/recipes-core/fan-ctrl/fan-ctrl/Makefile | 8 +- common/recipes-core/fan-ctrl/fan-ctrl/fand.cpp | 413 ++++++++++++++++++++- .../fan-ctrl/fan-ctrl/platform_sensor_init.cpp | 138 +++++++ common/recipes-core/fan-ctrl/fan-ctrl/w83795.cpp | 396 ++++++++++++++++++++ common/recipes-core/fan-ctrl/fan-ctrl/w83795.h | 223 +++++++++++ common/recipes-core/fan-ctrl/fan-ctrl/watchdog.cpp | 25 +- common/recipes-core/fan-ctrl/fan-ctrl_0.1.bb | 6 +- .../openbmc-gpio/files/ast2050_gpio_table.py | 220 +++++++++++ .../recipes-utils/openbmc-gpio/openbmc-gpio_0.1.bb | 5 +- 9 files changed, 1420 insertions(+), 14 deletions(-) create mode 100644 common/recipes-core/fan-ctrl/fan-ctrl/platform_sensor_init.cpp create mode 100644 common/recipes-core/fan-ctrl/fan-ctrl/w83795.cpp create mode 100644 common/recipes-core/fan-ctrl/fan-ctrl/w83795.h create mode 100644 common/recipes-utils/openbmc-gpio/files/ast2050_gpio_table.py (limited to 'common') diff --git a/common/recipes-core/fan-ctrl/fan-ctrl/Makefile b/common/recipes-core/fan-ctrl/fan-ctrl/Makefile index da74a34..825fa53 100644 --- a/common/recipes-core/fan-ctrl/fan-ctrl/Makefile +++ b/common/recipes-core/fan-ctrl/fan-ctrl/Makefile @@ -1,3 +1,4 @@ +# Copyright 2017 Raptor Engineering, LLC # Copyright 2014-present Facebook. All Rights Reserved. # # This program file is free software; you can redistribute it and/or modify it @@ -15,12 +16,15 @@ # 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301 USA -all: fand +all: fand platform_sensor_init fand: fand.cpp watchdog.cpp $(CXX) $(CXXFLAGS) -pthread -o $@ $^ $(LDFLAGS) +platform_sensor_init: platform_sensor_init.cpp w83795.cpp + $(CXX) $(CXXFLAGS) -pthread -o $@ $^ $(LDFLAGS) + .PHONY: clean clean: - rm -rf *.o fand + rm -rf *.o fand platform_sensor_init diff --git a/common/recipes-core/fan-ctrl/fan-ctrl/fand.cpp b/common/recipes-core/fan-ctrl/fan-ctrl/fand.cpp index ccfbdb1..a7ebfd6 100644 --- a/common/recipes-core/fan-ctrl/fan-ctrl/fand.cpp +++ b/common/recipes-core/fan-ctrl/fan-ctrl/fand.cpp @@ -1,6 +1,7 @@ /* * fand * + * Copyright 2017 Raptor Engineering, LLC * Copyright 2014-present Facebook. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify @@ -43,10 +44,11 @@ /* XXX: Both CONFIG_WEDGE and CONFIG_WEDGE100 are defined for Wedge100 */ #if !defined(CONFIG_YOSEMITE) && !defined(CONFIG_WEDGE) && \ - !defined(CONFIG_WEDGE100) + !defined(CONFIG_WEDGE100) && !defined(CONFIG_ASUS) #error "No hardware platform defined!" #endif -#if defined(CONFIG_YOSEMITE) && defined(CONFIG_WEDGE) +#if (defined(CONFIG_YOSEMITE) && defined(CONFIG_WEDGE)) || \ + (defined(CONFIG_ASUS) && defined(CONFIG_WEDGE)) #error "Two hardware platforms defined!" #endif @@ -66,6 +68,10 @@ #include #endif +#if defined(CONFIG_ASUS) +#define CONFIG_SLOPPY_FANS 1 +#endif + #include "watchdog.h" /* Sensor definitions */ @@ -77,6 +83,9 @@ #define INTERNAL_TEMPS(x) (x) #define EXTERNAL_TEMPS(x) (x) #define TOTAL_1S_SERVERS 4 +#elif defined(CONFIG_ASUS) +#define INTERNAL_TEMPS(x) ((x) * 1000.0) // stored as C * 1000 +#define EXTERNAL_TEMPS(x) ((x) / 1000.0) #endif /* @@ -93,6 +102,7 @@ #endif #define BAD_TEMP INTERNAL_TEMPS(-60) +#define BAD_VOLTAGE (-50) #define BAD_READ_THRESHOLD 4 /* How many times can reads fail */ #define FAN_FAILURE_THRESHOLD 4 /* How many times can a fan fail */ @@ -162,10 +172,28 @@ #elif defined(CONFIG_YOSEMITE) #define FAN_LED_RED "0" #define FAN_LED_BLUE "1" + +#elif defined(CONFIG_ASUS) +#define PWM_DIR "/sys/class/i2c-adapter/i2c-1/1-002f/" + +#define FAN_READ_RPM_FORMAT "fan%d_input" +#define PWM_UNIT_MAX 255 + +#define CHIPSET_TEMP_DEVICE PWM_DIR "temp1_input" +#define CPU1_TEMP_DEVICE PWM_DIR "temp7_input" +#define CPU2_TEMP_DEVICE PWM_DIR "temp8_input" +#define CPU2_VCORE_DEVICE PWM_DIR "in1_input" + +#define MAIN_POWER_OFF_DIRECTION "/sys/class/gpio/gpio40/direction" +#define MAIN_POWER_OFF_CTL "/sys/class/gpio/gpio40/value" + +#define FAN_LED_RED "1" +#define FAN_LED_BLUE "0" + #endif #if (defined(CONFIG_YOSEMITE) || defined(CONFIG_WEDGE)) && \ - !defined(CONFIG_WEDGE100) + !defined(CONFIG_WEDGE100) && !defined(CONFIG_ASUS) #define PWM_DIR "/sys/devices/platform/ast_pwm_tacho.0" #define PWM_UNIT_MAX 96 @@ -193,12 +221,17 @@ const char *fan_led[] = {FAN0_LED, FAN1_LED, FAN2_LED, FAN3_LED, #define INTAKE_LIMIT INTERNAL_TEMPS(60) #define SWITCH_LIMIT INTERNAL_TEMPS(80) +#define CHIPSET_LIMIT INTERNAL_TEMPS(80) #if defined(CONFIG_YOSEMITE) #define USERVER_LIMIT INTERNAL_TEMPS(110) #else #define USERVER_LIMIT INTERNAL_TEMPS(90) #endif +#if defined(CONFIG_ASUS) +#define CPU_LIMIT INTERNAL_TEMPS(110) +#endif + #define TEMP_TOP INTERNAL_TEMPS(70) #define TEMP_BOTTOM INTERNAL_TEMPS(40) @@ -214,7 +247,7 @@ const char *fan_led[] = {FAN0_LED, FAN1_LED, FAN2_LED, FAN3_LED, #define WEDGE_FAN_LOW 35 #define WEDGE_FAN_MEDIUM 50 #define WEDGE_FAN_HIGH 70 -#if defined(CONFIG_WEDGE100) +#if defined(CONFIG_WEDGE100) || defined(CONFIG_ASUS) #define WEDGE_FAN_MAX 100 #else #define WEDGE_FAN_MAX 99 @@ -252,6 +285,11 @@ int fan_to_pwm_map[] = {0, 1}; // Tacho offset between front and rear fans: #define REAR_FAN_OFFSET 1 +#elif defined(CONFIG_ASUS) +int fan_to_rpm_map[] = {1, 2, 3, 4, 5, 6, 7, 8}; +int fan_to_pwm_map[] = {1, 1, 2, 2, 2, 2, 2, 2}; // 1 == 4 pin fans, 2 == 3 pin fans +#define FANS 8 + #endif @@ -364,6 +402,47 @@ struct rpm_to_pct_map *rpm_rear_map = rpm_map; #define FRONT_MAP_SIZE MAP_SIZE #define REAR_MAP_SIZE MAP_SIZE +#elif defined(CONFIG_ASUS) +struct rpm_to_pct_map rpm_front_map[] = {{15, 1804}, + {20, 1864}, + {25, 2011}, + {30, 2268}, + {35, 2683}, + {40, 3110}, + {45, 3619}, + {50, 4017}, + {55, 4455}, + {60, 4720}, + {65, 5113}, + {70, 5487}, + {75, 5973}, + {80, 6428}, + {85, 6994}, + {90, 7417}, + {95, 7941}, + {100, 8490}}; +#define FRONT_MAP_SIZE (sizeof(rpm_front_map) / sizeof(struct rpm_to_pct_map)) + +struct rpm_to_pct_map rpm_rear_map[] = {{15, 450}, + {20, 600}, + {25, 750}, + {30, 900}, + {35, 1050}, + {40, 1200}, + {45, 1350}, + {50, 1500}, + {55, 1550}, + {60, 1600}, + {65, 1650}, + {70, 1700}, + {75, 1750}, + {80, 1800}, + {85, 1850}, + {90, 1900}, + {95, 1950}, + {100, 2000}}; +#define REAR_MAP_SIZE (sizeof(rpm_rear_map) / sizeof(struct rpm_to_pct_map)) + #endif /* @@ -409,6 +488,45 @@ struct temp_to_pct_map cpu_map[] = {{-28, 10}, #define CPU_MAP_SIZE (sizeof(cpu_map) / sizeof(struct temp_to_pct_map)) #endif +#if defined(CONFIG_ASUS) +struct temp_to_pct_map chipset_map[] = {{30, 1}, + {32, 5}, + {35, 10}, + {37, 15}, + {40, 20}, + {42, 25}, + {45, 30}, + {47, 35}, + {50, 40}, + {52, 45}, + {55, 50}, + {57, 55}, + {60, 60}, + {62, 65}, + {65, 70}, + {67, 80}, + {70, 100}}; +#define CHIPSET_MAP_SIZE (sizeof(chipset_map) / sizeof(struct temp_to_pct_map)) + +struct temp_to_pct_map cpu_map[] = {{38, 1}, + {40, 5}, + {42, 10}, + {44, 15}, + {46, 20}, + {48, 25}, + {50, 30}, + {52, 35}, + {54, 40}, + {56, 45}, + {58, 50}, + {60, 55}, + {62, 60}, + {64, 65}, + {66, 70}, + {68, 80}, + {70, 100}}; +#define CPU_MAP_SIZE (sizeof(cpu_map) / sizeof(struct temp_to_pct_map)) +#endif #define FAN_FAILURE_OFFSET 30 @@ -425,6 +543,14 @@ int temp_top = TEMP_TOP; int report_temp = REPORT_TEMP; bool verbose = false; +#if defined(CONFIG_WEDGE) + int cpu2_installed = 0; +#elif defined(CONFIG_ASUS) + int cpu2_installed = 1; +#else + int cpu2_installed = 0; +#endif + void usage() { fprintf(stderr, "fand [-v] [-l ] [-m ] " @@ -510,6 +636,28 @@ int read_temp(const char *device, int *value) { } #endif +#if defined(CONFIG_ASUS) +int read_temp(const char *device, int *value) { + char full_name[LARGEST_DEVICE_NAME + 1]; + + /* We set an impossible value to check for errors */ + *value = BAD_TEMP; + snprintf( + full_name, LARGEST_DEVICE_NAME, "%s", device); + return read_device(full_name, value); +} +#endif + +int read_voltage(const char *device, int *value) { + char full_name[LARGEST_DEVICE_NAME + 1]; + + /* We set an impossible value to check for errors */ + *value = BAD_VOLTAGE; + snprintf( + full_name, LARGEST_DEVICE_NAME, "%s", device); + return read_device(full_name, value); +} + #if defined(CONFIG_WEDGE) && !defined(CONFIG_WEDGE100) int read_gpio_value(const int id, const char *device, int *value) { char full_name[LARGEST_DEVICE_NAME]; @@ -644,6 +792,9 @@ int fan_rpm_to_pct(const struct rpm_to_pct_map *table, } int fan_speed_okay(const int fan, const int speed, const int slop) { +#if defined(CONFIG_ASUS) + int real_fan_speed; +#endif int front_fan, rear_fan; int front_pct, rear_pct; int real_fan; @@ -656,6 +807,17 @@ int fan_speed_okay(const int fan, const int speed, const int slop) { real_fan = fan_to_rpm_map[fan]; +#if defined(CONFIG_ASUS) + real_fan_speed = 0; + read_fan_value(real_fan, FAN_READ_RPM_FORMAT, &real_fan_speed); + if (fan < 2) { + front_pct = fan_rpm_to_pct(rpm_front_map, FRONT_MAP_SIZE, real_fan_speed); + } + else { + front_pct = fan_rpm_to_pct(rpm_rear_map, REAR_MAP_SIZE, real_fan_speed); + } + front_fan = real_fan_speed; +#else front_fan = 0; read_fan_value(real_fan, FAN_READ_RPM_FORMAT, &front_fan); front_pct = fan_rpm_to_pct(rpm_front_map, FRONT_MAP_SIZE, front_fan); @@ -664,7 +826,7 @@ int fan_speed_okay(const int fan, const int speed, const int slop) { read_fan_value(real_fan + REAR_FAN_OFFSET, FAN_READ_RPM_FORMAT, &rear_fan); rear_pct = fan_rpm_to_pct(rpm_rear_map, REAR_MAP_SIZE, rear_fan); #endif - +#endif /* * If the fans are broken, the measured rate will be rather @@ -683,6 +845,13 @@ int fan_speed_okay(const int fan, const int speed, const int slop) { okay = (abs(front_pct - speed) * 100 / speed < slop); #endif +#if defined(CONFIG_SLOPPY_FANS) + // Don't alert if fan is spinning faster than expected... + if (!okay && (front_pct > speed)) { + okay = 1; + } +#endif + if (!okay || verbose) { syslog(!okay ? LOG_WARNING : LOG_INFO, #ifdef BACK_TO_BACK_FANS @@ -703,6 +872,10 @@ int fan_speed_okay(const int fan, const int speed, const int slop) { return okay; } +#if defined(CONFIG_ASUS) +int averaged_pwm_values[2] = {0, 0}; +#endif + /* Set fan speed as a percentage */ int write_fan_speed(const int fan, const int value) { @@ -717,16 +890,60 @@ int write_fan_speed(const int fan, const int value) { if (value == 0) { #if defined(CONFIG_WEDGE100) return write_fan_value(real_fan, "fantray%d_pwm", 0); +#elif defined(CONFIG_ASUS) + return write_fan_value(real_fan, "pwm%d_enable", 0); #else return write_fan_value(real_fan, "pwm%d_en", 0); #endif } else { - int unit = value * PWM_UNIT_MAX / 100; + int unit = (value * PWM_UNIT_MAX) / 100; int status; +#if defined(CONFIG_ASUS) + // The KGPE-D16 / KCMA-D8 only has two fan outputs; one controls all 4 pin fans, + // and the other controls all 3 pin fans. Average the requested PWM values + // as a middle-of-the-road thermal strategy... + if (fan == 0) { + if (cpu2_installed) { + averaged_pwm_values[0] = unit; + return 0; + } + } + else if (fan == 1) { + if (cpu2_installed) { + averaged_pwm_values[0] += unit; + averaged_pwm_values[0] /= 2; + unit = averaged_pwm_values[0]; + } + else { + return 0; + } + } + else if (fan == 2) { + averaged_pwm_values[1] = unit; + return 0; + } + else if ((fan > 2) && (fan < 7)) { + averaged_pwm_values[1] += unit; + return 0; + } + else if (fan == 7) { + averaged_pwm_values[1] += unit; + averaged_pwm_values[1] /= 6; + unit = averaged_pwm_values[1]; + } +#endif + #if defined(CONFIG_WEDGE100) // Note that PWM for Wedge100 is in 32nds of a cycle return write_fan_value(real_fan, "fantray%d_pwm", unit); +#elif defined(CONFIG_ASUS) + if ((status = write_fan_value(real_fan, "pwm%d_enable", 1)) != 0) { + return status; + } + if ((status = write_fan_value(real_fan, "pwm%d", unit)) != 0) { + return status; + } #else if (unit == PWM_UNIT_MAX) unit = 0; @@ -741,7 +958,7 @@ int write_fan_speed(const int fan, const int value) { } } -#if defined(CONFIG_YOSEMITE) +#if defined(CONFIG_YOSEMITE) || defined(CONFIG_ASUS) int temp_to_fan_speed(int temp, struct temp_to_pct_map *map, int map_size) { int i = map_size - 1; @@ -796,11 +1013,17 @@ int server_shutdown(const char *why) { system("rmmod adm1275"); system("i2cset -y 12 0x10 0x01 00"); } +#elif defined(CONFIG_ASUS) + write_device(MAIN_POWER_OFF_DIRECTION, "out"); + write_device(MAIN_POWER_OFF_CTL, "0"); + sleep(1); + write_device(MAIN_POWER_OFF_CTL, "1"); #else // TODO(7088822): try throttling, then shutting down server. syslog(LOG_EMERG, "Need to implement actual shutdown!\n"); #endif +#if !defined(CONFIG_ASUS) /* * We have to stop the watchdog, or the system will be automatically * rebooted some seconds after fand exits (and stops kicking the @@ -811,6 +1034,7 @@ int server_shutdown(const char *why) { sleep(2); exit(2); +#endif } /* Gracefully shut down on receipt of a signal */ @@ -837,6 +1061,11 @@ int main(int argc, char **argv) { int exhaust_temp; int switch_temp; int userver_temp; +#elif defined(CONFIG_ASUS) + int chipset_temp; + int cpu1_temp; + int cpu2_temp; + int cpu2_vcore_mv; #else float intake_temp; float exhaust_temp; @@ -849,6 +1078,13 @@ int main(int argc, char **argv) { int fan_speed_changes = 0; int old_speed; + int cpu_fan_speed = fan_high; + int chassis_fan_speed = fan_high; + int cpu_fan_speed_changes = 0; + int chassis_fan_speed_changes = 0; + int cpu_old_speed = fan_high; + int chassis_old_speed = fan_high; + int fan_bad[FANS]; int fan; @@ -942,6 +1178,9 @@ int main(int argc, char **argv) { } for (fan = 0; fan < total_fans; fan++) { + if (!cpu2_installed && (fan == 1)) { + continue; + } fan_bad[fan] = 0; write_fan_speed(fan + fan_offset, fan_speed); write_fan_led(fan + fan_offset, FAN_LED_BLUE); @@ -980,6 +1219,8 @@ int main(int argc, char **argv) { while (1) { int max_temp; old_speed = fan_speed; + cpu_old_speed = cpu_fan_speed; + chassis_old_speed = chassis_fan_speed; /* Read sensors */ @@ -998,6 +1239,31 @@ int main(int argc, char **argv) { switch_temp == BAD_TEMP)) { bad_reads++; } +#elif defined(CONFIG_ASUS) + read_temp(CHIPSET_TEMP_DEVICE, &chipset_temp); + read_temp(CPU1_TEMP_DEVICE, &cpu1_temp); + read_temp(CPU2_TEMP_DEVICE, &cpu2_temp); + read_voltage(CPU2_VCORE_DEVICE, &cpu2_vcore_mv); + + /* + * uServer can be powered down, but all of the rest of the sensors + * should be readable at any time. + */ + + if ((chipset_temp == BAD_TEMP) || (cpu1_temp == BAD_TEMP) || + (cpu2_temp == BAD_TEMP) || (cpu2_vcore_mv == BAD_VOLTAGE)) { + bad_reads++; + } + else { + bad_reads = 0; // Only care about continuous bad reads + } + + if (cpu2_vcore_mv == 0) { + cpu2_installed = 0; + } + else { + cpu2_installed = 1; + } #else intake_temp = exhaust_temp = userver_temp = BAD_TEMP; if (yosemite_sensor_read(FRU_SPB, SP_SENSOR_INLET_TEMP, &intake_temp) || @@ -1025,8 +1291,51 @@ int main(int argc, char **argv) { if (bad_reads > BAD_READ_THRESHOLD) { server_shutdown("Some sensors couldn't be read"); + bad_reads = 0; + kick_watchdog(); + continue; } +#if defined(CONFIG_ASUS) + if (log_count++ % report_temp == 0) { + syslog(LOG_DEBUG, + "Temp chipset %f, CPU1 %f, CPU2 %f, " + "CPU fan speed %d, CPU speed changes %d" + "chassis fan speed %d, chassis speed changes %d", + EXTERNAL_TEMPS((float)chipset_temp), + EXTERNAL_TEMPS((float)cpu1_temp), + EXTERNAL_TEMPS((float)cpu2_temp), + cpu_fan_speed, + cpu_fan_speed_changes, + chassis_fan_speed, + chassis_fan_speed_changes); + } + + /* Protection heuristics */ + + if (chipset_temp > CHIPSET_LIMIT) { + server_shutdown("Chipset temp limit reached"); + bad_reads = 0; + kick_watchdog(); + continue; + } + + if (cpu1_temp > CPU_LIMIT) { + server_shutdown("CPU1 temp limit reached"); + bad_reads = 0; + kick_watchdog(); + continue; + } + + if (cpu2_installed) { + if (cpu2_temp > CPU_LIMIT) { + server_shutdown("CPU2 temp limit reached"); + bad_reads = 0; + kick_watchdog(); + continue; + } + } +#else if (log_count++ % report_temp == 0) { syslog(LOG_DEBUG, #if defined(CONFIG_WEDGE) || defined(CONFIG_WEDGE100) @@ -1051,17 +1360,27 @@ int main(int argc, char **argv) { if (intake_temp > INTAKE_LIMIT) { server_shutdown("Intake temp limit reached"); + bad_reads = 0; + kick_watchdog(); + continue; } #if defined(CONFIG_WEDGE) || defined(CONFIG_WEDGE100) if (switch_temp > SWITCH_LIMIT) { server_shutdown("T2 temp limit reached"); + bad_reads = 0; + kick_watchdog(); + continue; } #endif if (userver_temp + USERVER_TEMP_FUDGE > USERVER_LIMIT) { server_shutdown("uServer temp limit reached"); + bad_reads = 0; + kick_watchdog(); + continue; } +#endif /* * Calculate change needed -- we should eventually @@ -1085,9 +1404,31 @@ int main(int argc, char **argv) { } else { fan_speed = cpu_speed; } +#elif defined(CONFIG_ASUS) + int max_cpu_temp = cpu1_temp + USERVER_TEMP_FUDGE; + + if (cpu2_installed) { + if (cpu2_temp + USERVER_TEMP_FUDGE > max_cpu_temp) { + max_cpu_temp = cpu2_temp + USERVER_TEMP_FUDGE; + } + } + + int chassis_speed = temp_to_fan_speed(EXTERNAL_TEMPS(chipset_temp), chipset_map, + CHIPSET_MAP_SIZE); + int cpu_speed = temp_to_fan_speed(EXTERNAL_TEMPS(max_cpu_temp), cpu_map, CPU_MAP_SIZE); + + if (cpu_fan_speed == fan_max && fan_failure != 0) { + /* Don't change a thing */ + } else { + cpu_fan_speed = cpu_speed; + } + if (chassis_fan_speed == fan_max && fan_failure != 0) { + /* Don't change a thing */ + } else { + chassis_fan_speed = chassis_speed; + } #else /* Other systems use a simpler built-in table to determine fan speed. */ - if (switch_temp > userver_temp + USERVER_TEMP_FUDGE) { max_temp = switch_temp; } else { @@ -1125,6 +1466,31 @@ int main(int argc, char **argv) { * earlier, all remaining fans should continue to run at max speed. */ +#if defined(CONFIG_ASUS) + if (fan_failure == 0 && cpu_fan_speed != cpu_old_speed) { + syslog(LOG_NOTICE, + "CPU fan speed changing from %d to %d", + cpu_old_speed, + cpu_fan_speed); + cpu_fan_speed_changes++; + } + if (fan_failure == 0 && chassis_fan_speed != chassis_old_speed) { + syslog(LOG_NOTICE, + "Chassis fan speed changing from %d to %d", + chassis_old_speed, + chassis_fan_speed); + chassis_fan_speed_changes++; + } + for (fan = 0; fan < 2; fan++) { + if (!cpu2_installed && (fan == 1)) { + continue; + } + write_fan_speed(fan + fan_offset, cpu_fan_speed); + } + for (fan = 2; fan < total_fans; fan++) { + write_fan_speed(fan + fan_offset, chassis_fan_speed); + } +#else if (fan_failure == 0 && fan_speed != old_speed) { syslog(LOG_NOTICE, "Fan speed changing from %d to %d", @@ -1132,9 +1498,13 @@ int main(int argc, char **argv) { fan_speed); fan_speed_changes++; for (fan = 0; fan < total_fans; fan++) { + if (!cpu2_installed && (fan == 1)) { + continue; + } write_fan_speed(fan + fan_offset, fan_speed); } } +#endif /* * Wait for some change. Typical I2C temperature sensors @@ -1150,11 +1520,22 @@ int main(int argc, char **argv) { /* Check fan RPMs */ for (fan = 0; fan < total_fans; fan++) { + if (!cpu2_installed && (fan == 1)) { + continue; + } /* * Make sure that we're within some percentage * of the requested speed. */ +#if defined(CONFIG_ASUS) + int desired_fan_speed = cpu_fan_speed; + if (fan > 1) { + desired_fan_speed = chassis_fan_speed; + } + if (fan_speed_okay(fan + fan_offset, desired_fan_speed, FAN_FAILURE_OFFSET)) { +#else if (fan_speed_okay(fan + fan_offset, fan_speed, FAN_FAILURE_OFFSET)) { +#endif if (fan_bad[fan] > FAN_FAILURE_THRESHOLD) { write_fan_led(fan + fan_offset, FAN_LED_BLUE); syslog(LOG_CRIT, @@ -1169,6 +1550,9 @@ int main(int argc, char **argv) { fan_failure = 0; for (fan = 0; fan < total_fans; fan++) { + if (!cpu2_installed && (fan == 1)) { + continue; + } if (fan_bad[fan] > FAN_FAILURE_THRESHOLD) { fan_failure++; write_fan_led(fan + fan_offset, FAN_LED_RED); @@ -1190,8 +1574,13 @@ int main(int argc, char **argv) { */ fan_speed = fan_max; + cpu_fan_speed = fan_max; + chassis_fan_speed = fan_max; for (fan = 0; fan < total_fans; fan++) { - write_fan_speed(fan + fan_offset, fan_speed); + if (!cpu2_installed && (fan == 1)) { + continue; + } + write_fan_speed(fan + fan_offset, fan_max); } #if defined(CONFIG_WEDGE) || defined(CONFIG_WEDGE100) @@ -1206,11 +1595,17 @@ int main(int argc, char **argv) { if (fan_failure == total_fans) { int count = 0; for (fan = 0; fan < total_fans; fan++) { + if (!cpu2_installed && (fan == 1)) { + continue; + } if (fan_bad[fan] > FAN_SHUTDOWN_THRESHOLD) count++; } if (count == total_fans) { server_shutdown("all fans are bad for more than 12 cycles"); + bad_reads = 0; + kick_watchdog(); + continue; } } #endif diff --git a/common/recipes-core/fan-ctrl/fan-ctrl/platform_sensor_init.cpp b/common/recipes-core/fan-ctrl/fan-ctrl/platform_sensor_init.cpp new file mode 100644 index 0000000..512bca0 --- /dev/null +++ b/common/recipes-core/fan-ctrl/fan-ctrl/platform_sensor_init.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2017 Raptor Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "w83795.h" + +#define I2C_BUS_DEVICE_NODE "/dev/i2c-1" +#define I2C_SLAVE_DEVICE_ADDR 0x2f + +int smbus_fd = -1; + +int main() { + struct drivers_i2c_w83795_config platform_configuration; + + // ASUS KGPE-D16 + platform_configuration.fanin_ctl1 = 0xff; + platform_configuration.fanin_ctl2 = 0x00; + platform_configuration.temp_ctl1 = 0x2a; + platform_configuration.temp_ctl2 = 0x01; + platform_configuration.temp_dtse = 0x03; + platform_configuration.volt_ctl1 = 0xff; + platform_configuration.volt_ctl2 = 0xf7; + platform_configuration.temp1_fan_select = 0x00; + platform_configuration.temp2_fan_select = 0x00; + platform_configuration.temp3_fan_select = 0x00; + platform_configuration.temp4_fan_select = 0x00; + platform_configuration.temp5_fan_select = 0x00; + platform_configuration.temp6_fan_select = 0x00; + platform_configuration.temp1_source_select = 0x00; + platform_configuration.temp2_source_select = 0x00; + platform_configuration.temp3_source_select = 0x00; + platform_configuration.temp4_source_select = 0x00; + platform_configuration.temp5_source_select = 0x00; + platform_configuration.temp6_source_select = 0x00; + platform_configuration.tr1_critical_temperature = 85; + platform_configuration.tr1_critical_hysteresis = 80; + platform_configuration.tr1_warning_temperature = 70; + platform_configuration.tr1_warning_hysteresis = 65; + platform_configuration.dts_critical_temperature = 85; + platform_configuration.dts_critical_hysteresis = 80; + platform_configuration.dts_warning_temperature = 70; + platform_configuration.dts_warning_hysteresis = 65; + platform_configuration.temp1_critical_temperature = 80; + platform_configuration.temp2_critical_temperature = 80; + platform_configuration.temp3_critical_temperature = 80; + platform_configuration.temp4_critical_temperature = 80; + platform_configuration.temp5_critical_temperature = 80; + platform_configuration.temp6_critical_temperature = 80; + platform_configuration.temp1_target_temperature = 80; + platform_configuration.temp2_target_temperature = 80; + platform_configuration.temp3_target_temperature = 80; + platform_configuration.temp4_target_temperature = 80; + platform_configuration.temp5_target_temperature = 80; + platform_configuration.temp6_target_temperature = 80; + platform_configuration.fan1_nonstop = 7; + platform_configuration.fan2_nonstop = 7; + platform_configuration.fan3_nonstop = 7; + platform_configuration.fan4_nonstop = 7; + platform_configuration.fan5_nonstop = 7; + platform_configuration.fan6_nonstop = 7; + platform_configuration.fan7_nonstop = 7; + platform_configuration.fan8_nonstop = 7; + platform_configuration.default_speed = 100; + platform_configuration.fan1_duty = 100; + platform_configuration.fan2_duty = 100; + platform_configuration.fan3_duty = 100; + platform_configuration.fan4_duty = 100; + platform_configuration.fan5_duty = 100; + platform_configuration.fan6_duty = 100; + platform_configuration.fan7_duty = 100; + platform_configuration.fan8_duty = 100; + platform_configuration.vcore1_high_limit_mv = 1500; + platform_configuration.vcore1_low_limit_mv = 900; + platform_configuration.vcore2_high_limit_mv = 1500; + platform_configuration.vcore2_low_limit_mv = 900; + platform_configuration.vsen3_high_limit_mv = 1600; + platform_configuration.vsen3_low_limit_mv = 1100; + platform_configuration.vsen4_high_limit_mv = 1600; + platform_configuration.vsen4_low_limit_mv = 1100; + platform_configuration.vsen5_high_limit_mv = 1250; + platform_configuration.vsen5_low_limit_mv = 1150; + platform_configuration.vsen6_high_limit_mv = 1250; + platform_configuration.vsen6_low_limit_mv = 1150; + platform_configuration.vsen7_high_limit_mv = 1250; + platform_configuration.vsen7_low_limit_mv = 1050; + platform_configuration.vsen8_high_limit_mv = 1900; + platform_configuration.vsen8_low_limit_mv = 1700; + platform_configuration.vsen9_high_limit_mv = 1250; + platform_configuration.vsen9_low_limit_mv = 1150; + platform_configuration.vsen10_high_limit_mv = 1150; + platform_configuration.vsen10_low_limit_mv = 1050; + platform_configuration.vsen11_high_limit_mv = 1625; + platform_configuration.vsen11_low_limit_mv = 1500; + platform_configuration.vsen12_high_limit_mv = 1083; + platform_configuration.vsen12_low_limit_mv = 917; + platform_configuration.vsen13_high_limit_mv = 1625; + platform_configuration.vsen13_low_limit_mv = 1500; + platform_configuration.vdd_high_limit_mv = 3500; + platform_configuration.vdd_low_limit_mv = 3100; + platform_configuration.vsb_high_limit_mv = 3500; + platform_configuration.vsb_low_limit_mv = 3100; + platform_configuration.vbat_high_limit_mv = 3500; + platform_configuration.vbat_low_limit_mv = 2500; + platform_configuration.smbus_aux = 1; + + smbus_fd = open(I2C_BUS_DEVICE_NODE, O_RDWR); + if (smbus_fd < 0) { + printf("Unable to open I2C device node %s for read/write!\n", I2C_BUS_DEVICE_NODE); + return 1; + } + + if (ioctl(smbus_fd, I2C_SLAVE, I2C_SLAVE_DEVICE_ADDR) < 0) { + close(smbus_fd); + printf("Unable to set up communication with I2C device at address %02x!\n", I2C_SLAVE_DEVICE_ADDR); + return 1; + } + + w83795_init(MANUAL_MODE, DTS_SRC_AMD_SBTSI, &platform_configuration); + + close(smbus_fd); +} \ No newline at end of file diff --git a/common/recipes-core/fan-ctrl/fan-ctrl/w83795.cpp b/common/recipes-core/fan-ctrl/fan-ctrl/w83795.cpp new file mode 100644 index 0000000..c327957 --- /dev/null +++ b/common/recipes-core/fan-ctrl/fan-ctrl/w83795.cpp @@ -0,0 +1,396 @@ +/* + * Copyright (C) 2012 Advanced Micro Devices, Inc. + * Copyright (C) 2015-2017 Raptor Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include "w83795.h" + +#define BIOS_DEBUG 0 +#define BIOS_INFO 1 +#define BIOS_WARNING 2 +#define BIOS_ERR 3 + +extern int smbus_fd; + +// ========================================================================================================================= +// Taken from lm-sensors +// ========================================================================================================================= +#define I2C_SMBUS_READ 1 +#define I2C_SMBUS_WRITE 0 +#define I2C_SMBUS_BLOCK_MAX 32 +#define I2C_SMBUS_BYTE_DATA 2 +#define I2C_SMBUS 0x0720 + +union i2c_smbus_data { + __u8 byte; + __u16 word; + __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; +}; + +static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command, int size, union i2c_smbus_data *data) { + struct i2c_smbus_ioctl_data args; + + args.read_write = read_write; + args.command = command; + args.size = size; + args.data = data; + return ioctl(file,I2C_SMBUS,&args); +} + +static inline __s32 i2c_smbus_read_byte_data(int file, __u8 command) +{ + union i2c_smbus_data data; + if (i2c_smbus_access(file,I2C_SMBUS_READ,command, I2C_SMBUS_BYTE_DATA,&data)) + return -1; + else + return 0x0ff & data.byte; +} + +static inline __s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value) { + union i2c_smbus_data data; + data.byte = value; + return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, I2C_SMBUS_BYTE_DATA, &data); +} +// ========================================================================================================================= + +int smbus_write_byte(uint8_t addr, uint8_t value) { + return i2c_smbus_write_byte_data(smbus_fd, addr, value); +} + +uint8_t smbus_read_byte(uint8_t addr) { + return i2c_smbus_read_byte_data(smbus_fd, addr); +} + +void printk(int severity, const char* format, ...) { + va_list args; + va_start(args, format); + vprintf(format, args); + va_end(args); +} + +static int w83795_set_bank(uint8_t bank) +{ + return smbus_write_byte(W83795_REG_BANKSEL, bank); +} + +static uint8_t w83795_read(uint16_t reg) +{ + int ret; + + ret = w83795_set_bank(reg >> 8); + if (ret < 0) { + printk(BIOS_DEBUG, "read failed to set bank %x\n", reg >> 8); + return -1; + } + + ret = smbus_read_byte(reg & 0xff); + return ret; +} + +static uint8_t w83795_write(uint16_t reg, uint8_t value) +{ + int err; + + err = w83795_set_bank(reg >> 8); + if (err < 0) { + printk(BIOS_DEBUG, "write failed to set bank %x\n", reg >> 8); + return -1; + } + + err = smbus_write_byte(reg & 0xff, value); + return err; +} + +/* + * Configure Digital Temperature Sensor + */ +static void w83795_dts_configure(uint8_t dts_src) +{ + uint8_t val; + + /* DIS */ + val = w83795_read(W83795_REG_DTSC) & ~0x1; + val |= dts_src & 0x1; + w83795_write(W83795_REG_DTSC, val); + + /* TODO + * Determine if DTS interface needs to be reset + * (W83795_REG_DTSC bit 7) before operation. + */ +} + +static uint32_t w83795_set_fan_mode(w83795_fan_mode_t mode) +{ + if (mode == SPEED_CRUISE_MODE) { + w83795_write(W83795_REG_FCMS1, 0xFF); + printk(BIOS_INFO, "W83795G/ADG work in Speed Cruise Mode\n"); + } else { + w83795_write(W83795_REG_FCMS1, 0x00); + if (mode == THERMAL_CRUISE_MODE) { + w83795_write(W83795_REG_FCMS2, 0x00); + printk(BIOS_INFO, "W83795G/ADG work in Thermal Cruise Mode\n"); + } else if (mode == SMART_FAN_MODE) { + w83795_write(W83795_REG_FCMS2, 0x3F); + printk(BIOS_INFO, "W83795G/ADG work in Smart Fan Mode\n"); + } else { + printk(BIOS_INFO, "W83795G/ADG work in Manual Mode\n"); + return -1; + } + } + + return 0; +} + +static void w83795_set_fan(w83795_fan_mode_t mode) +{ + /* set fan output controlled mode (FCMS)*/ + w83795_set_fan_mode(mode); + + if (mode == SMART_FAN_MODE) { + /* Set the Relative Register-at SMART FAN IV Control Mode Table */ + //SFIV TODO + } + + /* Set Hysteresis of Temperature (HT) */ + //TODO +} + +static uint8_t fan_pct_to_cfg_val(uint8_t percent) +{ + uint16_t cfg = (((unsigned int)percent * 10000) / 3922); + if (cfg > 0xff) + cfg = 0xff; + return cfg; +} + +static uint8_t millivolts_to_limit_value_type1(int millivolts) +{ + /* Datasheet v1.41 pages 44 and 70 (VSEN1 - VSEN11, VTT) */ + return ((millivolts / 2) >> 2); +} + +static uint8_t millivolts_to_limit_value_type2(int millivolts) +{ + /* Datasheet v1.41 page pages 44 and 70 (3VSB, 3VDD, VBAT) */ + return ((millivolts / 6) >> 2); +} + +static uint16_t millivolts_to_limit_value_type3(int millivolts) +{ + /* Datasheet v1.41 page 45 (VSEN12, VSEN13, VDSEN14 - VDSEN17) */ + return (millivolts / 2); +} + +void w83795_init(w83795_fan_mode_t mode, uint8_t dts_src, struct drivers_i2c_w83795_config *config) +{ + uint8_t i; + uint8_t val; + uint16_t limit_value; + + if (smbus_read_byte(0x00) < 0) { + printk(BIOS_ERR, "W83795G/ADG Nuvoton H/W Monitor not found\n"); + return; + } + val = w83795_read(W83795_REG_CONFIG); + if ((val & W83795_REG_CONFIG_CONFIG48) == 0) + printk(BIOS_INFO, "Found 64 pin W83795G Nuvoton H/W Monitor\n"); + else + printk(BIOS_INFO, "Found 48 pin W83795ADG Nuvoton H/W Monitor\n"); + + /* Reset */ + val |= W83795_REG_CONFIG_INIT; + w83795_write(W83795_REG_CONFIG, val); + + /* Fan monitor settings */ + w83795_write(W83795_REG_FANIN_CTRL1, config->fanin_ctl1); + w83795_write(W83795_REG_FANIN_CTRL2, config->fanin_ctl2); + + /* Temperature thresholds */ + w83795_write(W83795_REG_TEMP_CRIT(0), config->tr1_critical_temperature); + w83795_write(W83795_REG_TEMP_CRIT_HYSTER(0), config->tr1_critical_hysteresis); + w83795_write(W83795_REG_TEMP_WARN(0), config->tr1_warning_temperature); + w83795_write(W83795_REG_TEMP_WARN_HYSTER(0), config->tr1_warning_hysteresis); + w83795_write(W83795_REG_TEMP_CRIT(1), config->tr2_critical_temperature); + w83795_write(W83795_REG_TEMP_CRIT_HYSTER(1), config->tr2_critical_hysteresis); + w83795_write(W83795_REG_TEMP_WARN(1), config->tr2_warning_temperature); + w83795_write(W83795_REG_TEMP_WARN_HYSTER(1), config->tr2_warning_hysteresis); + w83795_write(W83795_REG_TEMP_CRIT(2), config->tr3_critical_temperature); + w83795_write(W83795_REG_TEMP_CRIT_HYSTER(2), config->tr3_critical_hysteresis); + w83795_write(W83795_REG_TEMP_WARN(2), config->tr3_warning_temperature); + w83795_write(W83795_REG_TEMP_WARN_HYSTER(2), config->tr3_warning_hysteresis); + w83795_write(W83795_REG_TEMP_CRIT(3), config->tr4_critical_temperature); + w83795_write(W83795_REG_TEMP_CRIT_HYSTER(3), config->tr4_critical_hysteresis); + w83795_write(W83795_REG_TEMP_WARN(3), config->tr4_warning_temperature); + w83795_write(W83795_REG_TEMP_WARN_HYSTER(3), config->tr4_warning_hysteresis); + w83795_write(W83795_REG_TEMP_CRIT(4), config->tr5_critical_temperature); + w83795_write(W83795_REG_TEMP_CRIT_HYSTER(4), config->tr5_critical_hysteresis); + w83795_write(W83795_REG_TEMP_WARN(4), config->tr5_warning_temperature); + w83795_write(W83795_REG_TEMP_WARN_HYSTER(4), config->tr5_warning_hysteresis); + w83795_write(W83795_REG_TEMP_CRIT(5), config->tr6_critical_temperature); + w83795_write(W83795_REG_TEMP_CRIT_HYSTER(5), config->tr6_critical_hysteresis); + w83795_write(W83795_REG_TEMP_WARN(5), config->tr6_warning_temperature); + w83795_write(W83795_REG_TEMP_WARN_HYSTER(5), config->tr6_warning_hysteresis); + + /* DTS temperature thresholds */ + w83795_write(W83795_REG_DTS_CRIT, config->dts_critical_temperature); + w83795_write(W83795_REG_DTS_CRIT_HYSTER, config->dts_critical_hysteresis); + w83795_write(W83795_REG_DTS_WARN, config->dts_warning_temperature); + w83795_write(W83795_REG_DTS_WARN_HYSTER, config->dts_warning_hysteresis); + + /* Configure DTS registers in bank3 before enabling DTS */ + w83795_dts_configure(dts_src); + + /* DTS enable */ + w83795_write(W83795_REG_DTSE, config->temp_dtse); + + /* Temperature monitor settings */ + w83795_write(W83795_REG_TEMP_CTRL1, config->temp_ctl1); + w83795_write(W83795_REG_TEMP_CTRL2, config->temp_ctl2); + + /* Temperature to fan mappings */ + w83795_write(W83795_REG_TFMR(0), config->temp1_fan_select); + w83795_write(W83795_REG_TFMR(1), config->temp2_fan_select); + w83795_write(W83795_REG_TFMR(2), config->temp3_fan_select); + w83795_write(W83795_REG_TFMR(3), config->temp4_fan_select); + w83795_write(W83795_REG_TFMR(4), config->temp5_fan_select); + w83795_write(W83795_REG_TFMR(5), config->temp6_fan_select); + + /* Temperature data source to temperature mappings */ + w83795_write(W83795_REG_T12TSS, ((config->temp2_source_select & 0x0f) << 4) | (config->temp1_source_select & 0x0f)); + w83795_write(W83795_REG_T34TSS, ((config->temp4_source_select & 0x0f) << 4) | (config->temp3_source_select & 0x0f)); + w83795_write(W83795_REG_T56TSS, ((config->temp6_source_select & 0x0f) << 4) | (config->temp5_source_select & 0x0f)); + + /* Set critical temperatures + * If any sensor exceeds the associated critical temperature, + * all fans will be forced to full speed. + */ + w83795_write(W83795_REG_CTFS(0), config->temp1_critical_temperature); + w83795_write(W83795_REG_CTFS(1), config->temp2_critical_temperature); + w83795_write(W83795_REG_CTFS(2), config->temp3_critical_temperature); + w83795_write(W83795_REG_CTFS(3), config->temp4_critical_temperature); + w83795_write(W83795_REG_CTFS(4), config->temp5_critical_temperature); + w83795_write(W83795_REG_CTFS(5), config->temp6_critical_temperature); + + /* Set fan control target temperatures */ + w83795_write(W83795_REG_TTTI(0), config->temp1_target_temperature); + w83795_write(W83795_REG_TTTI(1), config->temp2_target_temperature); + w83795_write(W83795_REG_TTTI(2), config->temp3_target_temperature); + w83795_write(W83795_REG_TTTI(3), config->temp4_target_temperature); + w83795_write(W83795_REG_TTTI(4), config->temp5_target_temperature); + w83795_write(W83795_REG_TTTI(5), config->temp6_target_temperature); + + /* Set fan stall prevention parameters */ + w83795_write(W83795_REG_FAN_NONSTOP(0), config->fan1_nonstop); + w83795_write(W83795_REG_FAN_NONSTOP(1), config->fan2_nonstop); + w83795_write(W83795_REG_FAN_NONSTOP(2), config->fan3_nonstop); + w83795_write(W83795_REG_FAN_NONSTOP(3), config->fan4_nonstop); + w83795_write(W83795_REG_FAN_NONSTOP(4), config->fan5_nonstop); + w83795_write(W83795_REG_FAN_NONSTOP(5), config->fan6_nonstop); + w83795_write(W83795_REG_FAN_NONSTOP(6), config->fan7_nonstop); + w83795_write(W83795_REG_FAN_NONSTOP(7), config->fan8_nonstop); + + /* Set fan default speed */ + w83795_write(W83795_REG_DFSP, fan_pct_to_cfg_val(config->default_speed)); + + /* Set initial fan speeds */ + w83795_write(W83795_REG_FAN_MANUAL_SPEED(0), fan_pct_to_cfg_val(config->fan1_duty)); + w83795_write(W83795_REG_FAN_MANUAL_SPEED(1), fan_pct_to_cfg_val(config->fan2_duty)); + w83795_write(W83795_REG_FAN_MANUAL_SPEED(2), fan_pct_to_cfg_val(config->fan3_duty)); + w83795_write(W83795_REG_FAN_MANUAL_SPEED(3), fan_pct_to_cfg_val(config->fan4_duty)); + w83795_write(W83795_REG_FAN_MANUAL_SPEED(4), fan_pct_to_cfg_val(config->fan5_duty)); + w83795_write(W83795_REG_FAN_MANUAL_SPEED(5), fan_pct_to_cfg_val(config->fan6_duty)); + w83795_write(W83795_REG_FAN_MANUAL_SPEED(6), fan_pct_to_cfg_val(config->fan7_duty)); + w83795_write(W83795_REG_FAN_MANUAL_SPEED(7), fan_pct_to_cfg_val(config->fan8_duty)); + + /* Voltage monitor settings */ + w83795_write(W83795_REG_VOLT_CTRL1, config->volt_ctl1); + w83795_write(W83795_REG_VOLT_CTRL2, config->volt_ctl2); + + /* Voltage high/low limits */ + w83795_write(W83795_REG_VOLT_LIM_HIGH(0), millivolts_to_limit_value_type1(config->vcore1_high_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_LOW(0), millivolts_to_limit_value_type1(config->vcore1_low_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_HIGH(1), millivolts_to_limit_value_type1(config->vcore2_high_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_LOW(1), millivolts_to_limit_value_type1(config->vcore2_low_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_HIGH(2), millivolts_to_limit_value_type1(config->vsen3_high_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_LOW(2), millivolts_to_limit_value_type1(config->vsen3_low_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_HIGH(3), millivolts_to_limit_value_type1(config->vsen4_high_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_LOW(3), millivolts_to_limit_value_type1(config->vsen4_low_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_HIGH(4), millivolts_to_limit_value_type1(config->vsen5_high_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_LOW(4), millivolts_to_limit_value_type1(config->vsen5_low_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_HIGH(5), millivolts_to_limit_value_type1(config->vsen6_high_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_LOW(5), millivolts_to_limit_value_type1(config->vsen6_low_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_HIGH(6), millivolts_to_limit_value_type1(config->vsen7_high_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_LOW(6), millivolts_to_limit_value_type1(config->vsen7_low_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_HIGH(7), millivolts_to_limit_value_type1(config->vsen8_high_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_LOW(7), millivolts_to_limit_value_type1(config->vsen8_low_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_HIGH(8), millivolts_to_limit_value_type1(config->vsen9_high_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_LOW(8), millivolts_to_limit_value_type1(config->vsen9_low_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_HIGH(9), millivolts_to_limit_value_type1(config->vsen10_high_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_LOW(9), millivolts_to_limit_value_type1(config->vsen10_low_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_HIGH(10), millivolts_to_limit_value_type1(config->vsen11_high_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_LOW(10), millivolts_to_limit_value_type1(config->vsen11_low_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_HIGH(11), millivolts_to_limit_value_type1(config->vtt_high_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_LOW(11), millivolts_to_limit_value_type1(config->vtt_low_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_HIGH(12), millivolts_to_limit_value_type2(config->vdd_high_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_LOW(12), millivolts_to_limit_value_type2(config->vdd_low_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_HIGH(13), millivolts_to_limit_value_type2(config->vsb_high_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_LOW(13), millivolts_to_limit_value_type2(config->vsb_low_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_HIGH(14), millivolts_to_limit_value_type2(config->vbat_high_limit_mv)); + w83795_write(W83795_REG_VOLT_LIM_LOW(14), millivolts_to_limit_value_type2(config->vbat_low_limit_mv)); + + /* VSEN12 limits */ + if (config->temp_ctl1 & 0x2) { + limit_value = millivolts_to_limit_value_type3(config->vsen12_high_limit_mv); + w83795_write(W83795_REG_VOLT_LIM_HIGH_2_M(4), limit_value >> 2); + w83795_write(W83795_REG_VOLT_LIM_HIGH_2_L(4), limit_value & 0x3); + limit_value = millivolts_to_limit_value_type3(config->vsen12_low_limit_mv); + w83795_write(W83795_REG_VOLT_LIM_LOW_2_M(4), limit_value >> 2); + w83795_write(W83795_REG_VOLT_LIM_LOW_2_L(4), limit_value & 0x3); + } + + /* VSEN13 limits */ + if (config->temp_ctl1 & 0x8) { + limit_value = millivolts_to_limit_value_type3(config->vsen13_high_limit_mv); + w83795_write(W83795_REG_VOLT_LIM_HIGH_2_M(5), limit_value >> 2); + w83795_write(W83795_REG_VOLT_LIM_HIGH_2_L(5), limit_value & 0x3); + limit_value = millivolts_to_limit_value_type3(config->vsen13_low_limit_mv); + w83795_write(W83795_REG_VOLT_LIM_LOW_2_M(5), limit_value >> 2); + w83795_write(W83795_REG_VOLT_LIM_LOW_2_L(5), limit_value & 0x3); + } + + w83795_set_fan(mode); + + /* Show current fan control settings */ + printk(BIOS_INFO, "Fan\tCTFS(celsius)\tTTTI(celsius)\n"); + for (i = 0; i < 6; i++) { + val = w83795_read(W83795_REG_CTFS(i)); + printk(BIOS_INFO, " %x\t%d", i + 1, val); + val = w83795_read(W83795_REG_TTTI(i)); + printk(BIOS_INFO, "\t%d\n", val); + } + + /* Show current temperatures */ + for (i = 0; i < 8; i++) { + val = w83795_read(W83795_REG_DTS(i)); + printk(BIOS_DEBUG, "DTS%x current value: %x\n", i + 1, val); + } + + /* Start monitoring / fan control */ + val = w83795_read(W83795_REG_CONFIG); + val |= W83795_REG_CONFIG_START; + w83795_write(W83795_REG_CONFIG, val); +} diff --git a/common/recipes-core/fan-ctrl/fan-ctrl/w83795.h b/common/recipes-core/fan-ctrl/fan-ctrl/w83795.h new file mode 100644 index 0000000..25046d2 --- /dev/null +++ b/common/recipes-core/fan-ctrl/fan-ctrl/w83795.h @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2012 Advanced Micro Devices, Inc. + * Copyright (C) 2015-2017 Raptor Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _W83795_H_ +#define _W83795_H_ + +#define W83795_REG_I2C_ADDR 0xFC +#define W83795_REG_BANKSEL 0x00 +#define W83795_REG_CONFIG 0x01 +#define W83795_REG_CONFIG_START 0x01 +#define W83795_REG_CONFIG_CONFIG48 0x04 +#define W83795_REG_CONFIG_INIT 0x80 + +#define W83795_REG_VOLT_CTRL1 0x02 +#define W83795_REG_VOLT_CTRL2 0x03 +#define W83795_REG_TEMP_CTRL1 0x04 /* Temperature Monitoring Control Register */ +#define W83795_REG_TEMP_CTRL2 0x05 /* Temperature Monitoring Control Register */ +#define W83795_REG_FANIN_CTRL1 0x06 +#define W83795_REG_FANIN_CTRL2 0x07 +#define W83795_REG_TEMP_CTRL1_EN_DTS 0x20 /* Enable DTS (Digital Temperature Sensor) interface from INTEL PECI or AMD SB-TSI. */ +#define DTS_SRC_INTEL_PECI (0 << 0) +#define DTS_SRC_AMD_SBTSI (1 << 0) + +#define W83795_REG_TTTI(n) (0x260 + (n)) /* Target temperature W83795G/ADG will try to tune the fan output to keep */ +#define W83795_REG_CTFS(n) (0x268 + (n)) /* Critical Temperature to Full Speed all fan */ +#define W83795_REG_DTSC 0x301 /* Digital Temperature Sensor Configuration */ + +#define W83795_REG_DTSE 0x302 /* Digital Temperature Sensor Enable */ +#define W83795_REG_DTS(n) (0x26 + (n)) +#define W83795_REG_VRLSB 0x3C + +#define W83795_REG_TEMP_TR1 0x21 +#define W83795_REG_TEMP_TR2 0x22 +#define W83795_REG_TEMP_TR3 0x23 +#define W83795_REG_TEMP_TR4 0x24 +#define W83795_REG_TEMP_TR5 0x1F +#define W83795_REG_TEMP_TR6 0x20 + +#define W83795_REG_VOLT_LIM_HIGH(n) (0x70 + (n * 2)) /* Voltage high limit (0 == VSEN1) */ +#define W83795_REG_VOLT_LIM_LOW(n) (0x71 + (n * 2)) /* Voltage low limit (0 == VSEN1) */ +#define W83795_REG_VOLT_LIM_HIGH_2_M(n) (0x96 + (n * 4)) /* Voltage high limit MSB (0 == VDSEN14) */ +#define W83795_REG_VOLT_LIM_LOW_2_M(n) (0x97 + (n * 4)) /* Voltage low limit MSB (0 == VDSEN14) */ +#define W83795_REG_VOLT_LIM_HIGH_2_L(n) (0x98 + (n * 4)) /* Voltage high limit LSB (0 == VDSEN14) */ +#define W83795_REG_VOLT_LIM_LOW_2_L(n) (0x99 + (n * 4)) /* Voltage low limit LSB (0 == VDSEN14) */ + +#define W83795_REG_TEMP_CRIT(n) (0x96 + (n * 4)) /* Temperature critical limit */ +#define W83795_REG_TEMP_CRIT_HYSTER(n) (0x97 + (n * 4)) /* Temperature critical limit hysteresis */ +#define W83795_REG_TEMP_WARN(n) (0x98 + (n * 4)) /* Temperature warning limit */ +#define W83795_REG_TEMP_WARN_HYSTER(n) (0x99 + (n * 4)) /* Temperature warning limit hysteresis */ + +#define W83795_REG_DTS_CRIT 0xB2 /* Temperature critical limit */ +#define W83795_REG_DTS_CRIT_HYSTER 0xB3 /* Temperature critical limit hysteresis */ +#define W83795_REG_DTS_WARN 0xB4 /* Temperature warning limit */ +#define W83795_REG_DTS_WARN_HYSTER 0xB5 /* Temperature warning limit hysteresis */ + +#define W83795_REG_FCMS1 0x201 +#define W83795_REG_FCMS2 0x208 +#define W83795_REG_TFMR(n) (0x202 + (n)) /* Temperature to fan mapping */ +#define W83795_REG_T12TSS 0x209 /* Temperature Source Selection Register 1 */ +#define W83795_REG_T34TSS 0x20A /* Temperature Source Selection Register 2 */ +#define W83795_REG_T56TSS 0x20B /* Temperature Source Selection Register 3 */ +#define W83795_REG_FAN_MANUAL_SPEED(n) (0x210 + n) +#define W83795_REG_DFSP 0x20C + +#define W83795_REG_FAN_NONSTOP(n) (0x228 + (n)) /* Fan Nonstop Value */ + +#define W83795_REG_FTSH(n) (0x240 + (n) * 2) +#define W83795_REG_FTSL(n) (0x241 + (n) * 2) +#define W83795_REG_TFTS 0x250 + +typedef enum w83795_fan_mode { + SPEED_CRUISE_MODE = 0, ///< Fan Speed Cruise mode keeps the fan speed in a specified range + THERMAL_CRUISE_MODE = 1, ///< Thermal Cruise mode is an algorithm to control the fan speed to keep the temperature source around the TTTI + SMART_FAN_MODE = 2, ///< Smart Fan mode offers 6 slopes to control the fan speed + MANUAL_MODE = 3, ///< control manually +} w83795_fan_mode_t; + +struct drivers_i2c_w83795_config { + uint8_t fanin_ctl1; + uint8_t fanin_ctl2; + + uint8_t temp_ctl1; + uint8_t temp_ctl2; + uint8_t temp_dtse; + + uint8_t volt_ctl1; + uint8_t volt_ctl2; + + uint8_t temp1_fan_select; + uint8_t temp2_fan_select; + uint8_t temp3_fan_select; + uint8_t temp4_fan_select; + uint8_t temp5_fan_select; + uint8_t temp6_fan_select; + + uint8_t temp1_source_select; + uint8_t temp2_source_select; + uint8_t temp3_source_select; + uint8_t temp4_source_select; + uint8_t temp5_source_select; + uint8_t temp6_source_select; + + uint32_t vcore1_high_limit_mv; /* mV */ + uint32_t vcore1_low_limit_mv; /* mV */ + uint32_t vcore2_high_limit_mv; /* mV */ + uint32_t vcore2_low_limit_mv; /* mV */ + uint32_t vtt_high_limit_mv; /* mV */ + uint32_t vtt_low_limit_mv; /* mV */ + uint32_t vsen3_high_limit_mv; /* mV */ + uint32_t vsen3_low_limit_mv; /* mV */ + uint32_t vsen4_high_limit_mv; /* mV */ + uint32_t vsen4_low_limit_mv; /* mV */ + uint32_t vsen5_high_limit_mv; /* mV */ + uint32_t vsen5_low_limit_mv; /* mV */ + uint32_t vsen6_high_limit_mv; /* mV */ + uint32_t vsen6_low_limit_mv; /* mV */ + uint32_t vsen7_high_limit_mv; /* mV */ + uint32_t vsen7_low_limit_mv; /* mV */ + uint32_t vsen8_high_limit_mv; /* mV */ + uint32_t vsen8_low_limit_mv; /* mV */ + uint32_t vsen9_high_limit_mv; /* mV */ + uint32_t vsen9_low_limit_mv; /* mV */ + uint32_t vsen10_high_limit_mv; /* mV */ + uint32_t vsen10_low_limit_mv; /* mV */ + uint32_t vsen11_high_limit_mv; /* mV */ + uint32_t vsen11_low_limit_mv; /* mV */ + uint32_t vsen12_high_limit_mv; /* mV */ + uint32_t vsen12_low_limit_mv; /* mV */ + uint32_t vsen13_high_limit_mv; /* mV */ + uint32_t vsen13_low_limit_mv; /* mV */ + uint32_t vdd_high_limit_mv; /* mV */ + uint32_t vdd_low_limit_mv; /* mV */ + uint32_t vsb_high_limit_mv; /* mV */ + uint32_t vsb_low_limit_mv; /* mV */ + uint32_t vbat_high_limit_mv; /* mV */ + uint32_t vbat_low_limit_mv; /* mV */ + + int8_t tr1_critical_temperature; /* °C */ + int8_t tr1_critical_hysteresis; /* °C */ + int8_t tr1_warning_temperature; /* °C */ + int8_t tr1_warning_hysteresis; /* °C */ + int8_t tr2_critical_temperature; /* °C */ + int8_t tr2_critical_hysteresis; /* °C */ + int8_t tr2_warning_temperature; /* °C */ + int8_t tr2_warning_hysteresis; /* °C */ + int8_t tr3_critical_temperature; /* °C */ + int8_t tr3_critical_hysteresis; /* °C */ + int8_t tr3_warning_temperature; /* °C */ + int8_t tr3_warning_hysteresis; /* °C */ + int8_t tr4_critical_temperature; /* °C */ + int8_t tr4_critical_hysteresis; /* °C */ + int8_t tr4_warning_temperature; /* °C */ + int8_t tr4_warning_hysteresis; /* °C */ + int8_t tr5_critical_temperature; /* °C */ + int8_t tr5_critical_hysteresis; /* °C */ + int8_t tr5_warning_temperature; /* °C */ + int8_t tr5_warning_hysteresis; /* °C */ + int8_t tr6_critical_temperature; /* °C */ + int8_t tr6_critical_hysteresis; /* °C */ + int8_t tr6_warning_temperature; /* °C */ + int8_t tr6_warning_hysteresis; /* °C */ + int8_t dts_critical_temperature; /* °C */ + int8_t dts_critical_hysteresis; /* °C */ + int8_t dts_warning_temperature; /* °C */ + int8_t dts_warning_hysteresis; /* °C */ + + int8_t temp1_critical_temperature; /* °C */ + int8_t temp2_critical_temperature; /* °C */ + int8_t temp3_critical_temperature; /* °C */ + int8_t temp4_critical_temperature; /* °C */ + int8_t temp5_critical_temperature; /* °C */ + int8_t temp6_critical_temperature; /* °C */ + + int8_t temp1_target_temperature; /* °C */ + int8_t temp2_target_temperature; /* °C */ + int8_t temp3_target_temperature; /* °C */ + int8_t temp4_target_temperature; /* °C */ + int8_t temp5_target_temperature; /* °C */ + int8_t temp6_target_temperature; /* °C */ + + uint8_t fan1_nonstop; /* % of full speed (0-100) */ + uint8_t fan2_nonstop; /* % of full speed (0-100) */ + uint8_t fan3_nonstop; /* % of full speed (0-100) */ + uint8_t fan4_nonstop; /* % of full speed (0-100) */ + uint8_t fan5_nonstop; /* % of full speed (0-100) */ + uint8_t fan6_nonstop; /* % of full speed (0-100) */ + uint8_t fan7_nonstop; /* % of full speed (0-100) */ + uint8_t fan8_nonstop; /* % of full speed (0-100) */ + + uint8_t default_speed; /* % of full speed (0-100) */ + + uint8_t fan1_duty; /* % of full speed (0-100) */ + uint8_t fan2_duty; /* % of full speed (0-100) */ + uint8_t fan3_duty; /* % of full speed (0-100) */ + uint8_t fan4_duty; /* % of full speed (0-100) */ + uint8_t fan5_duty; /* % of full speed (0-100) */ + uint8_t fan6_duty; /* % of full speed (0-100) */ + uint8_t fan7_duty; /* % of full speed (0-100) */ + uint8_t fan8_duty; /* % of full speed (0-100) */ + + uint8_t smbus_aux; /* 0 == device located on primary SMBUS, + * 1 == device located on first auxiliary + * SMBUS channel, + * == device located on auxiliary + * SMBUS channel + */ +}; + +void w83795_init(w83795_fan_mode_t mode, uint8_t dts_src, struct drivers_i2c_w83795_config *config); + +#endif + diff --git a/common/recipes-core/fan-ctrl/fan-ctrl/watchdog.cpp b/common/recipes-core/fan-ctrl/fan-ctrl/watchdog.cpp index f6e5a45..b2a7a88 100644 --- a/common/recipes-core/fan-ctrl/fan-ctrl/watchdog.cpp +++ b/common/recipes-core/fan-ctrl/fan-ctrl/watchdog.cpp @@ -1,6 +1,7 @@ /* * watchdog * + * Copyright 2017 Raptor Engineering, LLC * Copyright 2014-present Facebook. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify @@ -25,6 +26,11 @@ #include #include #include +#include +#include +#include + +// #define DEBUG_WATCHDOG 1 #define WATCHDOG_START_KEY "x" #define WATCHDOG_STOP_KEY "X" @@ -32,6 +38,10 @@ #define WATCHDOG_PERSISTENT_KEY "V" #define WATCHDOG_NON_PERSISTENT_KEY "a" +#ifdef DEBUG_WATCHDOG +static time_t watchdog_last_kick = 0; +#endif + static int watchdog_dev = -1; /* This is needed to prevent rapid consecutive stop/start watchdog calls from @@ -104,7 +114,7 @@ int start_watchdog(const int auto_mode) { return 0; } - while (((watchdog_dev = open("/dev/watchdog", O_WRONLY)) == -1) && + while (((watchdog_dev = open("/dev/watchdog", O_RDWR)) == -1) && errno == EINTR); /* Fail if watchdog device is invalid or if the user asked for auto @@ -118,6 +128,9 @@ int start_watchdog(const int auto_mode) { while ((status = write(watchdog_dev, WATCHDOG_START_KEY, 1)) == 0 && errno == EINTR); pthread_mutex_unlock(&watchdog_lock); +#ifdef DEBUG_WATCHDOG + watchdog_last_kick = time(NULL); +#endif syslog(LOG_INFO, "system watchdog started.\n"); return 1; @@ -162,6 +175,16 @@ void set_persistent_watchdog(enum watchdog_persistent_en persistent) { static int kick_watchdog_unsafe() { int status = 0; +#ifdef DEBUG_WATCHDOG + int timeout = -1; + if (ioctl(watchdog_dev, WDIOC_GETTIMEOUT, &timeout) < 0) { + syslog(LOG_DEBUG, "Watchdog: WDIOC_GETTIMEOUT ioctl failed with errno %d\n", errno); + } + else { + syslog(LOG_DEBUG, "Watchdog: timeout set to %d seconds (last kick was %d seconds ago)\n", timeout, time(NULL) - watchdog_last_kick); + } + watchdog_last_kick = time(NULL); +#endif if (watchdog_dev != -1) { while ((status = write(watchdog_dev, watchdog_kick_key, 1)) == 0 && errno == EINTR); diff --git a/common/recipes-core/fan-ctrl/fan-ctrl_0.1.bb b/common/recipes-core/fan-ctrl/fan-ctrl_0.1.bb index 1abfaaa..74c388c 100644 --- a/common/recipes-core/fan-ctrl/fan-ctrl_0.1.bb +++ b/common/recipes-core/fan-ctrl/fan-ctrl_0.1.bb @@ -19,18 +19,22 @@ DESCRIPTION = "The utilities to control fan." SECTION = "base" PR = "r1" LICENSE = "GPLv2" -LIC_FILES_CHKSUM = "file://fand.cpp;beginline=6;endline=18;md5=da35978751a9d71b73679307c4d296ec" +LIC_FILES_CHKSUM = "file://fand.cpp;beginline=7;endline=19;md5=da35978751a9d71b73679307c4d296ec" SRC_URI = "file://README \ file://Makefile \ file://fand.cpp \ file://watchdog.h \ file://watchdog.cpp \ + file://w83795.h \ + file://w83795.cpp \ + file://platform_sensor_init.cpp \ " S = "${WORKDIR}" binfiles = "fand \ + platform_sensor_init \ " otherfiles = "README" diff --git a/common/recipes-utils/openbmc-gpio/files/ast2050_gpio_table.py b/common/recipes-utils/openbmc-gpio/files/ast2050_gpio_table.py new file mode 100644 index 0000000..d49dc0b --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/ast2050_gpio_table.py @@ -0,0 +1,220 @@ +# Copyright 2017 Raptor Engineering, LLC +# Copyright 2015-present Facebook. All rights reserved. +# +# This program file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +from openbmc_gpio_table import ( + BitsEqual, BitsNotEqual, And, Or, Function) + + +# The fallowing table is generated using: +# python ast_gpio_parser.py data/ast2050-gpio.csv +# DO NOT MODIFY THE TABLE!!! +# Manual modification will be overridden!!! + +soc_gpio_table = { + 'A10': [ + Function('VBCK', BitsEqual(0x70, [5], 0x1)), + Function('GPIOB5', None) + ], + 'A11': [ + Function('FLBUSY#', BitsEqual(0x74, [2], 0x1)), + Function('GPIOB1', None) + ], + 'A12': [ + Function('SDA7', BitsEqual(0x74, [14], 0x1)), + Function('GPIOH2', None) + ], + 'A13': [ + Function('MII2DIO', BitsEqual(0x74, [20], 0x1)), + Function('SDA5', BitsEqual(0x74, [12], 0x1)), + Function('GPIOC6', None) + ], + 'A8': [ + Function('PWM4', BitsEqual(0x74, [11], 0x1)), + Function('GPIOC5', None) + ], + 'A9': [ + Function('PECIO', BitsEqual(0x74, [7], 0x1)), + Function('GPIOC1', None) + ], + 'B1': [ + Function('OSCCLK', BitsEqual(0x2c, [1], 0x1)), + Function('DDCACLK', BitsEqual(0x74, [18], 0x1)), + Function('GPIOD7', None) + ], + 'B10': [ + Function('VBCS', BitsEqual(0x70, [5], 0x1)), + Function('LRST#', BitsEqual(0x70, [23], 0x1)), + Function('GPIOB4', None) + ], + 'B11': [ + Function('INTA#', BitsEqual(0x78, [4], 0x0)), + Function('GPIOB0', None) + ], + 'B12': [ + Function('SCL7', BitsEqual(0x74, [14], 0x1)), + Function('GPIOH3', None) + ], + 'B13': [ + Function('MII2DC', BitsEqual(0x74, [20], 0x1)), + Function('SCL5', BitsEqual(0x74, [12], 0x1)), + Function('GPIOC7', None) + ], + 'B2': [ + Function('DDCADAT', BitsEqual(0x74, [18], 0x1)), + Function('GPIOD6', None) + ], + 'B8': [ + Function('PWM3', BitsEqual(0x74, [10], 0x1)), + Function('GPIOC4', None) + ], + 'B9': [ + Function('PECII', BitsEqual(0x74, [7], 0x1)), + Function('GPIOC0', None) + ], + 'C11': [ + Function('PHYPD#', BitsEqual(0x74, [25], 0x1)), + Function('GPIOA5', None) + ], + 'C12': [ + Function('SDA6', BitsEqual(0x74, [13], 0x1)), + Function('GPIOH0', None) + ], + 'C8': [ + Function('PWM2', BitsEqual(0x74, [9], 0x1)), + Function('GPIOC3', None) + ], + 'C9': [ + Function('VBDI', BitsEqual(0x70, [5], 0x1)), + Function('GPIOB7', None) + ], + 'D10': [ + Function('FLWP#', BitsEqual(0x74, [2], 0x1)), + Function('GPIOB2', None) + ], + 'D11': [ + Function('PHYLINK', BitsEqual(0x74, [25], 0x1)), + Function('GPIOA4', None) + ], + 'D12': [ + Function('SCL6', BitsEqual(0x74, [13], 0x1)), + Function('GPIOH1', None) + ], + 'D8': [ + Function('PWM1', BitsEqual(0x74, [8], 0x1)), + Function('GPIOC2', None) + ], + 'D9': [ + Function('VBDO', BitsEqual(0x70, [5], 0x1)), + Function('WDTRST', BitsEqual(0x78, [3], 0x1)), + Function('GPIOB6', None) + ], + 'R1': [ + Function('VP2', BitsEqual(0x74, [22], 0x1)), + Function('GPIOE2', None) + ], + 'R2': [ + Function('VP1', BitsEqual(0x74, [22], 0x1)), + Function('GPIOE1', None) + ], + 'R3': [ + Function('VP0', BitsEqual(0x74, [22], 0x1)), + Function('GPIOE0', None) + ], + 'R4': [ + Function('VSYNC', BitsEqual(0x74, [15], 0x1)), + Function('VPAVSYNC', BitsEqual(0x74, [16], 0x1)), + Function('GPIOH5', None) + ], + 'T1': [ + Function('VPACLK', BitsEqual(0x74, [16], 0x1)), + Function('GPIOH7', None) + ], + 'T2': [ + Function('VP5', BitsEqual(0x74, [22], 0x1)), + Function('GPIOE5', None) + ], + 'T3': [ + Function('VP4', BitsEqual(0x74, [22], 0x1)), + Function('GPIOE4', None) + ], + 'T4': [ + Function('VP3', BitsEqual(0x74, [22], 0x1)), + Function('GPIOE3', None) + ], + 'U1': [ + Function('VPADE', BitsEqual(0x74, [16], 0x1)), + Function('GPIOH6', None) + ], + 'U2': [ + Function('HSYNC', BitsEqual(0x74, [15], 0x1)), + Function('VPAHSYNC', BitsEqual(0x74, [16], 0x1)), + Function('GPIOH4', None) + ], + 'U3': [ + Function('VP7', BitsEqual(0x74, [22], 0x1)), + Function('GPIOE7', None) + ], + 'U4': [ + Function('VP6', BitsEqual(0x74, [22], 0x1)), + Function('GPIOE6', None) + ], + 'V1': [ + Function('VP11', BitsEqual(0x74, [22], 0x1)), + Function('GPIOF3', None) + ], + 'V2': [ + Function('VP10', BitsEqual(0x74, [22], 0x1)), + Function('GPIOF2', None) + ], + 'V3': [ + Function('VP9', BitsEqual(0x74, [22], 0x1)), + Function('GPIOF1', None) + ], + 'V4': [ + Function('VP8', BitsEqual(0x74, [22], 0x1)), + Function('GPIOF0', None) + ], + 'W1': [ + Function('VP15', BitsEqual(0x74, [23], 0x1)), + Function('GPIOF7', None) + ], + 'W2': [ + Function('VP14', BitsEqual(0x74, [23], 0x1)), + Function('GPIOF6', None) + ], + 'W3': [ + Function('VP13', BitsEqual(0x74, [23], 0x1)), + Function('GPIOF5', None) + ], + 'W4': [ + Function('VP12', BitsEqual(0x74, [23], 0x1)), + Function('GPIOF4', None) + ], + 'Y3': [ + Function('VP17', BitsEqual(0x74, [23], 0x1)), + Function('GPIOG1', None) + ], + 'Y4': [ + Function('VP16', BitsEqual(0x74, [23], 0x1)), + Function('GPIOG0', None) + ], +} diff --git a/common/recipes-utils/openbmc-gpio/openbmc-gpio_0.1.bb b/common/recipes-utils/openbmc-gpio/openbmc-gpio_0.1.bb index a2b46d4..bd64228 100644 --- a/common/recipes-utils/openbmc-gpio/openbmc-gpio_0.1.bb +++ b/common/recipes-utils/openbmc-gpio/openbmc-gpio_0.1.bb @@ -23,6 +23,7 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=eb723b61539feef013de476e68b5c50a" SRC_URI = " \ file://COPYING \ file://board_gpio_table.py \ + file://ast2050_gpio_table.py \ file://openbmc_gpio.py \ file://openbmc_gpio_table.py \ file://openbmc_gpio_util.py \ @@ -49,7 +50,9 @@ RDEPENDS_${PN} = "python-core python-argparse python-subprocess" do_board_defined_soc_table() { if [ "${OPENBMC_GPIO_SOC_TABLE}" != "soc_gpio_table.py" ]; then - mv -f "${S}/${OPENBMC_GPIO_SOC_TABLE}" "${S}/soc_gpio_table.py" + if [ "${OPENBMC_GPIO_SOC_TABLE}" != "ast2050_gpio_table.py" ]; then + mv -f "${S}/${OPENBMC_GPIO_SOC_TABLE}" "${S}/soc_gpio_table.py" + fi fi } addtask board_defined_soc_table after do_unpack before do_build -- cgit v1.1