Commit b9ee9bd8 authored by Adam Wujek's avatar Adam Wujek

sw/petalinux/diot-util: Add fantray command

Add:
- fantray command with subcommands (with help and completion):
  - status
  - reset
  - fan
  - load_fw
- i2c-tools as dependency for diot_util
- print detailed information for PSU's (status command)
Signed-off-by: 's avatarAdam Wujek <dev_public@wujek.eu>
parent 67e6c343
......@@ -15,6 +15,8 @@ SRC_URI = " \
file://diot_util_clk.h \
file://diot_util_error.c \
file://diot_util_error.h \
file://diot_util_fantray.c \
file://diot_util_fantray.h \
file://diot_util_gpio.c \
file://diot_util_gpio.h \
file://diot_util_i2c.h \
......@@ -32,8 +34,8 @@ SRC_URI = " \
file://util.h \
"
DEPENDS = "libgpiod readline lmsensors"
RDEPENDS_${PN} = "lmsensors-libsensors"
DEPENDS = "libgpiod readline lmsensors i2c-tools"
RDEPENDS_${PN} = "lmsensors-libsensors i2c-tools"
S = "${WORKDIR}"
CFLAGS_prepend = "-I ${S}/include"
......
......@@ -5,6 +5,7 @@ APP_OBJS = \
diot_util.o \
diot_util_clk.o \
diot_util_error.o \
diot_util_fantray.o \
diot_util_gpio.o \
diot_util_sensors.o \
diot_util_pts.o \
......@@ -13,7 +14,7 @@ APP_OBJS = \
term.o \
util.o \
LDLIBS+=-lgpiod -lreadline -lsensors
LDLIBS+=-lgpiod -lreadline -lsensors -li2c
CFLAGS+=-Wall -ggdb -g -O2 \
-DSB_VER=$(SB_VER) \
-D__GIT_USR__="\"$(GIT_USR)\"" \
......
......@@ -23,7 +23,11 @@
#include "diot_util_sensors.h"
#include "diot_util_error.h"
#include "diot_util_pts.h"
#include "diot_util_fantray.h"
#include "diot_util_i2c.h"
#include "fru.h"
#include "util.h"
#include "fru_utils.h"
#define DTB_HW_VER_FILE "/sys/firmware/devicetree/base/chosen/hw_ver"
......@@ -36,18 +40,6 @@
#define RED_CHECK(x) x ? COLOR_RED: ""
#define RED_OFF(x) x ? COLOR_OFF: ""
struct command_entry {
char *cmd_name;
int (*cmd_func)(char *params);
char *cmd_help_string;
char *cmd_params;
};
struct string_map {
char *index;
char *label;
};
/* readline related */
char **command_completion(const char *, int, int);
char *command_name_generator(const char *, int);
......@@ -92,14 +84,21 @@ struct command_entry commands_list[] = {
{ .cmd_name = "sensors_refresh", .cmd_func = cmd_sensors_refresh, .cmd_help_string = "Display sensors short version with refresh\n", .cmd_params = NULL},
{ .cmd_name = "clocks", .cmd_func = cmd_clocks, .cmd_help_string = "Display info about clocks\n", .cmd_params = NULL},
{ .cmd_name = "pts", .cmd_func = cmd_pts, .cmd_help_string = "Run PTS basic checks\n", .cmd_params = NULL},
{ .cmd_name = "fantray", .cmd_func = cmd_fantray, .cmd_help_string = "Commands for fantray module. Type \"help "
"fantray\" for more information about "
"subcommands\n", .cmd_params = NULL},
{ .cmd_name = NULL }
};
int cmd_help(char *params)
{
struct command_entry *entry = commands_list;
char buf[50];
/* Print fantray's help if requested */
if (params && !strncmp(params, "fantray", strlen("fantray")))
entry = commands_list_fantray;
printf("diot_util for HW version %d\n", SB_VER);
printf("Avaiable commands:\n");
while (entry->cmd_name) {
......@@ -215,42 +214,6 @@ static void print_fmc_status(void)
free(fru);
}
static char * get_file_content(char *filename, char *buff, size_t buff_size)
{
FILE *file_h;
file_h = fopen(filename, "r");
if (!file_h) {
diot_error_add("Unable to open file (%s)\n", filename);
return "Error";
}
(void)! fread(buff, 1, buff_size, file_h);
/* make sure the last character is 0 */
buff[buff_size - 1] = 0;
if (ferror(file_h)) {
diot_error_add("Error while reading file (%s)\n", filename);
return "Error";
}
fclose(file_h);
return buff;
}
static char *string_map_get(char *name, struct string_map *map, size_t map_size)
{
int i;
for (i = 0; i < map_size; i++)
if (!strcmp(map[i].index, name))
return map[i].label;
return "Unknown";
}
static void print_uboot_info(void)
{
char buff[30];
......@@ -281,6 +244,112 @@ static void print_uboot_info(void)
printf("-------------------+----------------+\n");
}
static int print_psu_hwmon_status(void)
{
char buff_hwmon_psu1[20];
char buff_hwmon_psu2[20];
char buff_psu1[30];
char buff_psu2[30];
char *buff_psu1_p;
char *buff_psu2_p;
char buff_file[100];
int psu1_present = read_psu_presence(1);
int psu2_present = read_psu_presence(2);
if (!psu1_present) {
strcpy(buff_psu1, "N/A");
buff_psu1_p = buff_psu1;
} else if(!get_hwmon_number(PSU1_HWMON_SYS_PATH, buff_hwmon_psu1,
sizeof(buff_hwmon_psu1))) {
diot_error_add("Unable to get hwmon number for PSU1.\n");
psu1_present = 0;
strcpy(buff_psu1, "Error");
buff_psu1_p = buff_psu1;
}
if (!psu2_present) {
strcpy(buff_psu2, "N/A");
buff_psu2_p = buff_psu2;
} else if(!get_hwmon_number(PSU2_HWMON_SYS_PATH, buff_hwmon_psu2,
sizeof(buff_hwmon_psu2))) {
diot_error_add("Unable to get hwmon number for PSU2.\n");
psu2_present = 0;
strcpy(buff_psu2, "Error");
buff_psu2_p = buff_psu2;
}
printf("PSU information\n");
printf("---------+---------------------+---------------------+\n");
printf(" | PSU1 | PSU2 |\n");
printf("---------+---------------------+---------------------+\n");
if (psu1_present) {
sprintf(buff_file, DEBUGFS_PMBUS "/%s/mfr_model", buff_hwmon_psu1);
buff_psu1_p = end_str_at_newline(get_file_content(buff_file, buff_psu1,
sizeof(buff_psu1)));
}
if (psu2_present) {
sprintf(buff_file, DEBUGFS_PMBUS "/%s/mfr_model", buff_hwmon_psu2);
buff_psu2_p = end_str_at_newline(get_file_content(buff_file, buff_psu2,
sizeof(buff_psu2)));
}
printf("Model |%20s |%20s |\n", buff_psu1_p, buff_psu2_p);
if (psu1_present) {
sprintf(buff_file, DEBUGFS_PMBUS "/%s/mfr_revision", buff_hwmon_psu1);
buff_psu1_p = end_str_at_newline(get_file_content(buff_file, buff_psu1,
sizeof(buff_psu1)));
}
if (psu2_present) {
sprintf(buff_file, DEBUGFS_PMBUS "/%s/mfr_revision", buff_hwmon_psu2);
buff_psu2_p = end_str_at_newline(get_file_content(buff_file, buff_psu2,
sizeof(buff_psu2)));
}
printf("Revision |%20s |%20s |\n", buff_psu1_p, buff_psu2_p);
if (psu1_present) {
sprintf(buff_file, DEBUGFS_PMBUS "/%s/mfr_location", buff_hwmon_psu1);
buff_psu1_p = end_str_at_newline(get_file_content(buff_file, buff_psu1,
sizeof(buff_psu1)));
}
if (psu2_present) {
sprintf(buff_file, DEBUGFS_PMBUS "/%s/mfr_location", buff_hwmon_psu2);
buff_psu2_p = end_str_at_newline(get_file_content(buff_file, buff_psu2,
sizeof(buff_psu2)));
}
printf("Location |%20s |%20s |\n", buff_psu1_p, buff_psu2_p);
if (psu1_present) {
sprintf(buff_file, DEBUGFS_PMBUS "/%s/mfr_date", buff_hwmon_psu1);
buff_psu1_p = end_str_at_newline(get_file_content(buff_file, buff_psu1,
sizeof(buff_psu1)));
}
if (psu2_present) {
sprintf(buff_file, DEBUGFS_PMBUS "/%s/mfr_date", buff_hwmon_psu2);
buff_psu2_p = end_str_at_newline(get_file_content(buff_file, buff_psu2,
sizeof(buff_psu2)));
}
printf("Date |%20s |%20s |\n", buff_psu1_p, buff_psu2_p);
if (psu1_present) {
sprintf(buff_file, DEBUGFS_PMBUS "/%s/mfr_serial", buff_hwmon_psu1);
buff_psu1_p = end_str_at_newline(get_file_content(buff_file, buff_psu1,
sizeof(buff_psu1)));
}
if (psu2_present) {
sprintf(buff_file, DEBUGFS_PMBUS "/%s/mfr_serial", buff_hwmon_psu2);
buff_psu2_p = end_str_at_newline(get_file_content(buff_file, buff_psu2,
sizeof(buff_psu2)));
}
printf("Serial |%20s |%20s |\n", buff_psu1_p, buff_psu2_p);
printf("---------+---------------------+---------------------+\n");
return 0;
}
int cmd_print_status(char *params)
{
int hw_version;
......@@ -314,6 +383,9 @@ int cmd_print_status(char *params)
print_uboot_info();
printf("\n");
print_psu_hwmon_status();
printf("\n");
diot_error_print();
return 1;
......@@ -432,6 +504,7 @@ int main(int argc, char **argv)
} else
cmd_len = strlen(cmd_start_p);
ret = 0;
entry = commands_list;
while (entry && entry->cmd_name) {
if (cmd_len == strlen(entry->cmd_name)
......@@ -439,27 +512,42 @@ int main(int argc, char **argv)
) {
ret = entry->cmd_func(params);
if (ret < 0)
printf("Command %s failed with error message \"%s\" (%d)\n",
entry->cmd_name, strerror(errno), ret);
printf("Command %s failed with error code (%d)\n",
entry->cmd_name, ret);
break;
}
entry++;
}
if (!(entry && entry->cmd_name)) {
printf("Commad \"%s\" not found\n", cmd_start_p);
ret = 1;
}
}
if (script_commands)
free(script_commands);
return 0;
return ret;
}
char *
command_name_generator_fantray(const char *text, int state);
char **
command_completion(const char *text, int start, int end)
{
/* Don't add entries from the filesystem to completion list */
rl_attempted_completion_over = 1;
return rl_completion_matches(text, command_name_generator);
/* Call completion function if the first word */
if (start == 0)
return rl_completion_matches(text, command_name_generator);
if (!strncmp(rl_line_buffer, "fantray load_fw", strlen("fantray load_fw"))) {
return rl_completion_matches(text, rl_filename_completion_function);
}
if (!strncmp(rl_line_buffer, "fantray", strlen("fantray"))) {
return rl_completion_matches(text, command_name_generator_fantray);
}
return NULL;
}
char *
......@@ -481,3 +569,23 @@ command_name_generator(const char *text, int state)
return NULL;
}
/* command name generator for fantray */
char *command_name_generator_fantray(const char *text, int state)
{
static int list_index, len;
char *name;
if (!state) {
list_index = 0;
len = strlen(text);
}
while ((commands_list_fantray[list_index].cmd_name) && (name = commands_list_fantray[list_index++].cmd_name)) {
if (strncmp(name, text, len) == 0) {
return strdup(name);
}
}
return NULL;
}
......@@ -9,6 +9,15 @@
#ifndef __DIOT_UTIL_H
#define __DIOT_UTIL_H
struct command_entry {
char *cmd_name;
int (*cmd_func)(char *params);
char *cmd_help_string;
char *cmd_params;
};
int cmd_help(char *params);
#define COLOR_RED "\033[1;31m"
#define COLOR_OFF "\033[0m"
......
......@@ -13,6 +13,7 @@
#include "diot_util_error.h"
#include "diot_util_pts.h"
#include "diot_util_i2c.h"
#include "util.h"
# define INPUT_PRESENT_FILE "/sys/bus/i2c/drivers/si5341/" SI5341_I2C "-00" SI5341_I2C_ADDR "/input_present"
# define PLL_LOCKED_FILE "/sys/bus/i2c/drivers/si5341/" SI5341_I2C "-00" SI5341_I2C_ADDR "/pll_locked"
......@@ -23,26 +24,6 @@
#define SI5341_PREFIX_PATH "/sys/kernel/debug/clk/si5341"
#define SI5341_N_CH_OUT 10
int get_file_content(char *file_name, int *val)
{
int ret;
FILE * fp;
fp = fopen (file_name, "r");
if (!fp) {
diot_error_add("Unable to read file %s\n", file_name);
return -1;
}
ret = fscanf(fp, "%d", val);
fclose(fp);
if (ret <= 0 || ret == EOF) {
diot_error_add("Unable to read value from file %s\n", file_name);
return -1;
}
return ret;
}
int get_selected_input(int *val, char *input_name, char *input_name_dtb)
{
......@@ -126,18 +107,18 @@ void print_clk_rate(void)
printf("-------+------------+\n");
snprintf(path_buff, sizeof(path_buff), "%s/clk_rate", SI5341_PREFIX_PATH);
ret = get_file_content(path_buff, &val);
ret = get_file_content_int(path_buff, &val);
printf("InDiv | %10s |\n", value_float_or_error(buff, ret, val));
snprintf(path_buff, sizeof(path_buff), "%s.N0/clk_rate",
SI5341_PREFIX_PATH);
ret = get_file_content(path_buff, &val);
ret = get_file_content_int(path_buff, &val);
printf("PLLout | %10s |\n", value_float_or_error(buff, ret, val));
for (i = 0; i < SI5341_N_CH_OUT; i++) {
snprintf(path_buff, sizeof(path_buff), "%s.%d/clk_rate",
SI5341_PREFIX_PATH, i);
ret = get_file_content(path_buff, &val);
ret = get_file_content_int(path_buff, &val);
printf("Out%d | %10s |\n", i, value_float_or_error(buff, ret, val));
}
......@@ -167,7 +148,7 @@ int pts_clocks(void)
printf("Test Clocks");
ret = get_file_content(INPUT_PRESENT_FILE, &val);
ret = get_file_content_int(INPUT_PRESENT_FILE, &val);
pts_sensor_p = find_pts_sensor("PLL Input Present");
if (ret < 0 || !pts_sensor_inrange(val, pts_sensor_p)) {
if (errors++ == 0)
......@@ -176,7 +157,7 @@ int pts_clocks(void)
val, pts_sensor_p->allowed_min, pts_sensor_p->allowed_max);
}
ret = get_file_content(PLL_LOCKED_FILE, &val);
ret = get_file_content_int(PLL_LOCKED_FILE, &val);
pts_sensor_p = find_pts_sensor("PLL Locked");
if (ret < 0 || !pts_sensor_inrange(val, pts_sensor_p)) {
if (errors++ == 0)
......@@ -197,7 +178,7 @@ int pts_clocks(void)
for (i = 0; i < SI5341_N_CH_OUT; i++) {
snprintf(path_buff, sizeof(path_buff), "%s.%d/clk_rate",
SI5341_PREFIX_PATH, i);
ret = get_file_content(path_buff, &val);
ret = get_file_content_int(path_buff, &val);
snprintf(path_buff, sizeof(path_buff), "PLL Out%d", i);
pts_sensor_p = find_pts_sensor(path_buff);
if (ret < 0 || !pts_sensor_inrange((float)val/1000000, pts_sensor_p)) {
......@@ -227,9 +208,9 @@ int cmd_clocks(char *params)
diot_error_clear();
printf("----------------+------------+\n");
ret = get_file_content(INPUT_PRESENT_FILE, &val);
ret = get_file_content_int(INPUT_PRESENT_FILE, &val);
printf("Input present |%11s |\n", check_ret_value(ret, val));
ret = get_file_content(PLL_LOCKED_FILE, &val);
ret = get_file_content_int(PLL_LOCKED_FILE, &val);
printf("Pll locked |%11s |\n", check_ret_value(ret, val));
get_selected_input(&val, buff_input_name, buff_input_name_DTB);
printf("Input id |%11s |\n", value_or_error(buff, val, val));
......
/*
* diot_util_fantray - functions specific to fantray (monimod) used in DIOT
* crate
*
* Author: Adam Wujek for CERN
* Copyright CERN 2022
*
*/
#ifndef __DIOT_UTIL_FANTRAY_H
#define __DIOT_UTIL_FANTRAY_H
extern struct command_entry commands_list_fantray[];
int cmd_fantray(char *params);
#endif /* __DIOT_UTIL_FANTRAY_H */
/*
* diot_util_i2c - i2c addresses on DIOT system board
* diot_util_i2c - i2c channels and addresses on DIOT system board
*
* Author: Adam Wujek for CERN
* Copyright CERN 2021
......@@ -30,6 +30,16 @@
#define FANTRAY_I2C PSU_I2C
#define FANTRAY_I2C_ADDR "12"
#define FANTRAY_I2C_REG_WRITTEN_FW_SIZE 0xD1
#define FANTRAY_I2C_REG_WRITTEN_FW_BLOCK 0xD2
#define FANTRAY_I2C_REG_WRITTEN_FW_CHKSUM 0xD3
#define FANTRAY_I2C_REG_LOCAL_FW_CHKSUM 0xD4
#define FANTRAY_I2C_REG_BOOT_NEW_FW 0xD5
#define FANTRAY_I2C_REG_RESET 0xD6
#define FANTRAY_FW_TYPE_BOOTLOADER 0x1
#define FANTRAY_FW_TYPE_MAIN 0x2
#define FMC_EEPROM_I2C "0"
#define FMC_EEPROM_I2C_ADDR "50"
......@@ -49,4 +59,11 @@
#define PB_EEPROM_I2C_ADDR "50"
#define FANTRAY_DRIVER_PATH "/sys/bus/i2c/drivers/monimod"
#define FANTRAY_FULL_I2C_ADDR FANTRAY_I2C "-00" FANTRAY_I2C_ADDR
#define FANTRAY_HWMON_SYS_PATH "/sys/devices/platform/amba/ff030000.i2c/i2c-1/i2c-" FANTRAY_I2C "/" FANTRAY_I2C "-00" FANTRAY_I2C_ADDR "/hwmon"
#define PSU1_HWMON_SYS_PATH "/sys/devices/platform/amba/ff030000.i2c/i2c-1/i2c-" PSU_I2C "/" PSU_I2C "-00" PSU1_I2C_ADDR "/hwmon"
#define PSU2_HWMON_SYS_PATH "/sys/devices/platform/amba/ff030000.i2c/i2c-1/i2c-" PSU_I2C "/" PSU_I2C "-00" PSU2_I2C_ADDR "/hwmon"
#define DEBUGFS_PMBUS "/sys/kernel/debug/pmbus"
#endif /* __DIOT_UTIL_I2C_H */
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include "util.h"
#include "diot_util_error.h"
/* get monotonic number of seconds */
time_t get_monotonic_sec(void)
......@@ -7,3 +13,133 @@ time_t get_monotonic_sec(void)
clock_gettime(CLOCK_MONOTONIC, &tv);
return tv.tv_sec;
}
char *get_file_content(char *filename, char *buff, size_t buff_size)
{
FILE *file_h;
int ret;
file_h = fopen(filename, "r");
if (!file_h) {
diot_error_add("Unable to open file (%s)\n", filename);
return "Error";
}
ret = fread(buff, 1, buff_size, file_h);
if (ret >= buff_size)
ret--;
/* make sure the last character is 0 */
buff[ret] = 0;
if (ferror(file_h)) {
diot_error_add("Error while reading file (%s)\n", filename);
return "Error";
}
fclose(file_h);
return buff;
}
int get_file_content_int(char *file_name, int *val)
{
int ret;
FILE * fp;
fp = fopen (file_name, "r");
if (!fp) {
diot_error_add("Unable to read file %s\n", file_name);
return -1;
}
ret = fscanf(fp, "%d", val);
fclose(fp);
if (ret <= 0 || ret == EOF) {
diot_error_add("Unable to read value from file %s\n", file_name);
return -1;
}
return ret;
}
int set_file_content_int(char *file_name, int val)
{
int ret;
FILE * fp;
fp = fopen (file_name, "w");
if (!fp) {
diot_error_add("Unable to write to file %s\n", file_name);
return -1;
}
ret = fprintf(fp, "%d", val);
fclose(fp);
if (ret <= 0 || ret == EOF) {
diot_error_add("Unable to write value %ld to file %s\n",
val, file_name);
return -1;
}
return ret;
}
char *end_str_at_newline(char *buff)
{
char *p;
p = strchr(buff, '\n');
if (p)
*p = '\0';
return buff;
}
char *string_map_get(char *name, struct string_map *map, size_t map_size)
{
int i;
for (i = 0; i < map_size; i++)
if (!strcmp(map[i].index, name))
return map[i].label;
return "Unknown";
}
char *get_hwmon_number(char *hwmon_sys_dir, char * buff, size_t buff_size)
{
int ret;
DIR *d;
struct dirent *dir;
d = opendir(hwmon_sys_dir);
if (!d) {
return NULL;
}
while ((dir = readdir(d)) != NULL) {
if (!strncmp(dir->d_name, ".", 1))
continue;
ret = snprintf(buff, buff_size, "%s", dir->d_name);
if (ret > buff_size) {
/* buffer not big enough */
diot_error_add("Buffer too short for hwmon number. Written "
"\"%s\"(len %d), wanted \"%s\"(len %d)\n",
buff, strlen(buff), dir->d_name, strlen(dir->d_name)
);
closedir(d);
errno = ENOBUFS;
return NULL;
}
/* assume there is only one entry in the directory like:
* /sys/devices/platform/amba/ff030000.i2c/i2c-1/i2c-9/9-0012/hwmon
*/
break;
}
closedir(d);
return buff;
}
......@@ -8,7 +8,21 @@
#ifndef __UTIL_H
#define __UTIL_H
#include <time.h>
struct string_map {
char *index;
char *label;
};
time_t get_monotonic_sec(void);
char *get_file_content(char *filename, char *buff, size_t buff_size);
int get_file_content_int(char *file_name, int *val);
int set_file_content_int(char *file_name, int val);
char *end_str_at_newline(char *buff);
char *get_hwmon_number(char *hwmon_sys_dir, char * buff, size_t buff_size);
char *string_map_get(char *name, struct string_map *map, size_t map_size);
#endif /* __UTIL_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment