Add initial version of OCC sensor driver

Sensor data currently available via 'occcontrol poll'
command at console.
parent 532ecc4e
......@@ -34,6 +34,7 @@ target_sources(app PRIVATE
${KESTREL_SOURCE_DIR}/src/fsi.c
${KESTREL_SOURCE_DIR}/src/kestrel.c
${KESTREL_SOURCE_DIR}/src/redfish.c
${KESTREL_SOURCE_DIR}/src/sbe_fsi.c
${KESTREL_SOURCE_DIR}/src/simple_pwm.c
${KESTREL_SOURCE_DIR}/src/webservice.c
${KESTREL_SOURCE_DIR}/src/webportal.c
......
// © 2020 Raptor Engineering, LLC
// © 2020 - 2021 Raptor Engineering, LLC
//
// Released under the terms of the GPL v3
// See the LICENSE file for full details
......@@ -15,30 +15,6 @@ LOG_MODULE_REGISTER(kestrel_fsi, LOG_LEVEL_DBG);
// #define DEBUG
// General FSI register definitions for IBM CFAM slaves
#define IBM_CFAM_FSI_SMODE 0x0800
#define IBM_CFAM_FSI_SISC 0x0802
#define IBM_CFAM_FSI_SSTAT 0x0805
// Boot-related CFAM register definitions for IBM POWER9 processors
#define IBM_POWER9_FSI_A_SI1S 0x081c
#define IBM_POWER9_LL_MODE_REG 0x0840
#define IBM_POWER9_FSI2PIB_CHIPID 0x100a
#define IBM_POWER9_FSI2PIB_INTERRUPT 0x100b
#define IBM_POWER9_FSI2PIB_TRUE_MASK 0x100d
#define IBM_POWER9_CBS_CS 0x2801
#define IBM_POWER9_SBE_CTRL_STATUS 0x2808
#define IBM_POWER9_SBE_MSG_REGISTER 0x2809
#define IBM_POWER9_ROOT_CTRL0 0x2810
#define IBM_POWER9_PERV_CTRL0 0x281a
#define IBM_POWER9_HB_MBX5_REG 0x283c
#define IBM_POWER9_SCRATCH_REGISTER_8 0x283f
#define IBM_POWER9_ROOT_CTRL8 0x2918
#define IBM_POWER9_ROOT_CTRL1_CLEAR 0x2931
// Platform data
#define IBM_POWER9_SLAVE_ID 0
#define KESTREL_LOG(...) LOG_INF(__VA_ARGS__)
static int check_device_id(void)
......@@ -55,7 +31,7 @@ static int check_device_id(void)
return -1;
}
static int access_fsi_mem(uint8_t slave_id, uint32_t address, fsi_data_length_t data_length, uint8_t write, uint32_t *data)
int access_fsi_mem(uint8_t slave_id, uint32_t address, fsi_data_length_t data_length, uint8_t write, uint32_t *data)
{
int ret = 0;
uint32_t word;
......@@ -134,7 +110,7 @@ static int access_fsi_mem(uint8_t slave_id, uint32_t address, fsi_data_length_t
return ret;
}
static int access_cfam(uint8_t slave_id, uint32_t cfam_address, fsi_data_length_t data_length, uint8_t write, uint32_t *data)
int access_cfam(uint8_t slave_id, uint32_t cfam_address, fsi_data_length_t data_length, uint8_t write, uint32_t *data)
{
// CFAM to FSI address mangling
uint32_t fsi_address = (cfam_address & 0xfc00) | ((cfam_address & 0x3ff) << 2);
......
// © 2020 Raptor Engineering, LLC
// © 2020 - 2021 Raptor Engineering, LLC
//
// Released under the terms of the GPL v3
// See the LICENSE file for full details
......@@ -52,6 +52,30 @@ typedef enum
#define FSI_DIRECTION_READ 0
#define FSI_DIRECTION_WRITE 1
// General FSI register definitions for IBM CFAM slaves
#define IBM_CFAM_FSI_SMODE 0x0800
#define IBM_CFAM_FSI_SISC 0x0802
#define IBM_CFAM_FSI_SSTAT 0x0805
// Boot-related CFAM register definitions for IBM POWER9 processors
#define IBM_POWER9_FSI_A_SI1S 0x081c
#define IBM_POWER9_LL_MODE_REG 0x0840
#define IBM_POWER9_FSI2PIB_CHIPID 0x100a
#define IBM_POWER9_FSI2PIB_INTERRUPT 0x100b
#define IBM_POWER9_FSI2PIB_TRUE_MASK 0x100d
#define IBM_POWER9_CBS_CS 0x2801
#define IBM_POWER9_SBE_CTRL_STATUS 0x2808
#define IBM_POWER9_SBE_MSG_REGISTER 0x2809
#define IBM_POWER9_ROOT_CTRL0 0x2810
#define IBM_POWER9_PERV_CTRL0 0x281a
#define IBM_POWER9_HB_MBX5_REG 0x283c
#define IBM_POWER9_SCRATCH_REGISTER_8 0x283f
#define IBM_POWER9_ROOT_CTRL8 0x2918
#define IBM_POWER9_ROOT_CTRL1_CLEAR 0x2931
// Platform data
#define IBM_POWER9_SLAVE_ID 0
static inline uint32_t read_openfsi_register(unsigned long base_address, uint8_t reg)
{
return *((volatile uint32_t *)(base_address + reg));
......@@ -62,6 +86,9 @@ static inline void write_openfsi_register(unsigned long base_address, uint8_t re
*((volatile uint32_t *)(base_address + reg)) = data;
}
int access_fsi_mem(uint8_t slave_id, uint32_t address, fsi_data_length_t data_length, uint8_t write, uint32_t *data);
int access_cfam(uint8_t slave_id, uint32_t cfam_address, fsi_data_length_t data_length, uint8_t write, uint32_t *data);
int run_pre_ipl_fixups(void);
int start_ipl(int side);
int get_sbe_status(void);
......
This diff is collapsed.
// © 2021 Raptor Engineering, LLC
//
// Released under the terms of the GPL v3
// See the LICENSE file for full details
#ifndef _SBE_FSI_H
#define _SBE_FSI_H
#include <stdint.h>
#define IBM_POWER9_SBE_STATUS_BOOTED (1 << 31)
#define IBM_POWER9_SBE_HW_FFDC_PRESENT (1 << 30)
#define IBM_POWER9_SBE_FIFO_STA_PARITY_ERR (1 << 29)
#define IBM_POWER9_SBE_FIFO_STA_RESET_REQ (1 << 25)
#define IBM_POWER9_SBE_FIFO_STA_GOT_EOT (1 << 23)
#define IBM_POWER9_SBE_FIFO_STA_FULL (1 << 21)
#define IBM_POWER9_SBE_FIFO_STA_EMPTY (1 << 20)
#define IBM_POWER9_SBE_FIFO_STA_EOT_MASK 0xff
#define IBM_POWER9_SBE_FIFO_STA_EOT_SHIFT 0
#define IBM_POWER9_SBE_FIFO_STA_EOT_HIGH_BIT (1 << 7)
#define IBM_POWER9_SBE_STATE_MASK 0xf
#define IBM_POWER9_SBE_STATE_SHIFT 20
#define IBM_POWER9_SBE_STATE_UNKNOWN 0x0
#define IBM_POWER9_SBE_STATE_IPLING 0x1
#define IBM_POWER9_SBE_STATE_ISTEP 0x2
#define IBM_POWER9_SBE_STATE_MPIPL 0x3
#define IBM_POWER9_SBE_STATE_RUNTIME 0x4
#define IBM_POWER9_SBE_STATE_DMT 0x5
#define IBM_POWER9_SBE_STATE_DUMP 0x6
#define IBM_POWER9_SBE_STATE_FAILED 0x7
#define IBM_POWER9_SBE_STATE_QUIESCED 0x8
// IBM_POWER9 SBE FIFO register banks
#define IBM_POWER9_SBE_FIFO_UP 0x00
#define IBM_POWER9_SBE_FIFO_DOWN 0x40
// IBM_POWER9 SBE FIFO registers
#define IBM_POWER9_SBE_FIFO_FIFO 0x00
#define IBM_POWER9_SBE_FIFO_STAT 0x04
// IBM_POWER9_SBE FIFO commands
#define IBM_POWER9_SBE_FIFO_CMD_EOT_RAISE 0x0008
#define IBM_POWER9_SBE_FIFO_CMD_EOT_ACK 0x0014
#define IBM_POWER9_SBE_FIFO_CMD_REQUEST_RESET 0x000c
#define IBM_POWER9_SBE_FIFO_CMD_PERFORM_RESET 0x0010
#define IBM_POWER9_SBE_FIFO_CMD_GET_OCC_SRAM 0xa403
#define IBM_POWER9_SBE_FIFO_CMD_PUT_OCC_SRAM 0xa404
#define IBM_POWER9_SBE_FIFO_CMD_GET_FFDC 0xa801
// IBM POWER9 OCC constants
#define IBM_POWER9_SBE_OCC_FFDC_MAX_SIZE 0x2000
#define IBM_POWER9_SBE_OCC_CMD_SIZE 0xffa
#define IBM_POWER9_SBE_OCC_CMD_HEADER_LEN 0x5
#define IBM_POWER9_SBE_OCC_CMD_MAX_SIZE (IBM_POWER9_SBE_OCC_CMD_SIZE + IBM_POWER9_SBE_OCC_CMD_HEADER_LEN)
#define IBM_POWER9_SBE_OCC_RESPONSE_SIZE 0xff9
#define IBM_POWER9_SBE_OCC_RESPONSE_HEADER_LEN 0x6
#define IBM_POWER9_SBE_OCC_RESPONSE_MAX_SIZE (IBM_POWER9_SBE_OCC_RESPONSE_SIZE + IBM_POWER9_SBE_OCC_RESPONSE_HEADER_LEN)
#define IBM_POWER9_SBE_OCC_STATUS_LEN_BYTES 0x80
#define IBM_POWER9_SBE_FIFO_OCC_SRAM_CMD_ADDR 0xfffbe000
#define IBM_POWER9_SBE_FIFO_OCC_SRAM_RSP_ADDR 0xfffbf000
#define IBM_POWER9_SBE_FIFO_OCC_XFR_MODE_NORMAL 1
#define IBM_POWER9_SBE_FIFO_OCC_XFR_MODE_CIRC 3
#define IBM_POWER9_SBE_FIFO_OCC_CMD_ATTN 0x20010000
// IBM POWER9 OCC command codes
#define IBM_POWER9_OCC_CMD_POLL 0x20
// IBM POWER9 OCC response codes
#define IBM_POWER9_OCC_RESP_SUCCESS 0x00
#define IBM_POWER9_OCC_RESP_CMD_INVAL 0x11
#define IBM_POWER9_OCC_RESP_CMD_LEN_INVAL 0x12
#define IBM_POWER9_OCC_RESP_DATA_INVAL 0x13
#define IBM_POWER9_OCC_RESP_CHKSUM_ERR 0x14
#define IBM_POWER9_OCC_RESP_INT_ERR 0x15
#define IBM_POWER9_OCC_RESP_BAD_STATE 0x16
#define IBM_POWER9_OCC_RESP_CRIT_EXCEPT 0xe0
#define IBM_POWER9_OCC_RESP_CRIT_INIT 0xe1
#define IBM_POWER9_OCC_RESP_CRIT_WATCHDOG 0xe2
#define IBM_POWER9_OCC_RESP_CRIT_OCB 0xe3
#define IBM_POWER9_OCC_RESP_CRIT_HW 0xe4
#define IBM_POWER9_OCC_RESP_CMD_IN_PRG 0xff
#define IBM_POWER9_OCC_MAX_TEMP_SENSORS 256
struct occ_response_t
{
uint8_t sequence_number;
uint8_t cmd_type;
uint8_t return_status;
uint16_t length;
uint16_t checksum;
};
struct __packed ibm_power9_occ_poll_response_header_t
{
uint8_t status;
uint8_t extended_status;
uint8_t occ_present;
uint8_t configuration_data;
uint8_t occ_state;
uint8_t mode;
uint8_t ips_status;
uint8_t error_log_id;
uint32_t error_log_start_address;
uint16_t error_log_length;
uint16_t reserved;
uint8_t occ_version_string[16];
uint8_t label[6];
uint8_t sensor_data_block_count;
uint8_t sensor_data_block_header_version;
void *sensor_block_data;
};
struct __packed ibm_power9_occ_sensor_data_block_header_t {
uint8_t label[4];
uint8_t reserved;
uint8_t sensor_format;
uint8_t sensor_length;
uint8_t sensor_count;
void *sensor_data;
};
struct __packed ibm_power9_occ_sensor_data_temp_v2_t {
uint32_t sensor_id;
uint8_t fru_type;
uint8_t value;
};
struct ibm_power9_occ_sensor_data_t {
uint32_t sensor_id;
uint8_t temperature_c;
};
extern struct ibm_power9_occ_sensor_data_t host_cpu_temperature_sensor_data[IBM_POWER9_OCC_MAX_TEMP_SENSORS];
extern size_t host_cpu_temperature_sensor_count;
int gather_ffdc_dump(int slave_id, uint32_t base_fsi_address);
int occ_putsram(int slave_id, uint32_t base_fsi_address, uint8_t *command_data, size_t length);
int occ_submit(int slave_id, uint32_t base_fsi_address, uint8_t *request_data, size_t request_length, size_t expected_response_length, uint8_t *response_data, size_t *response_length);
int occ_poll(int slave_id, uint32_t base_fsi_address, size_t expected_response_length, uint8_t *response_data, size_t *response_length);
#endif // _SBE_FSI_H
\ No newline at end of file
......@@ -13,6 +13,7 @@
#include "kestrel.h"
#include "simple_pwm.h"
#include "sbe_fsi.h"
#include "flash_filesystem.h"
#include <generated/mem.h>
......@@ -109,6 +110,10 @@ static void print_kestrel_pwmcontrol_command_usage(const struct shell *shell, ch
shell_print(shell, "Usage: %s <channel> <value>", command_name);
}
static void print_kestrel_occcontrol_command_usage(const struct shell *shell, char* command_name) {
shell_print(shell, "Usage: %s [detect]", command_name);
}
static int kestrel_shell_cmd_utility(const struct shell *shell, size_t argc, char **argv)
{
if (argc < 2) {
......@@ -214,6 +219,41 @@ static int kestrel_shell_cmd_pwmcontrol(const struct shell *shell, size_t argc,
return 0;
}
static int kestrel_shell_cmd_occcontrol(const struct shell *shell, size_t argc, char **argv)
{
int sensor_number;
uint8_t response_data[IBM_POWER9_SBE_OCC_RESPONSE_SIZE];
uint8_t occ_version_string[17];
size_t response_length = 0;
struct ibm_power9_occ_poll_response_header_t *occ_response_header;
if (argc < 2) {
print_kestrel_occcontrol_command_usage(shell, argv[0]);
return -1;
}
if (strcmp(argv[1], "poll") == 0) {
if (occ_poll(0, 0x2400, IBM_POWER9_SBE_OCC_RESPONSE_SIZE, response_data, &response_length))
{
shell_print(shell, "OCC not responding!");
}
else
{
occ_response_header = (struct ibm_power9_occ_poll_response_header_t*)response_data;
memcpy(occ_version_string, occ_response_header->occ_version_string, 16);
occ_version_string[16] = 0;
shell_print(shell, "Found OCC version '%s'", occ_version_string);
shell_print(shell, "Found %d temperature sensors", host_cpu_temperature_sensor_count);
for (sensor_number = 0; sensor_number < host_cpu_temperature_sensor_count; sensor_number++)
{
shell_print(shell, "Temperature sensor 0x%08x: %d° C", host_cpu_temperature_sensor_data[sensor_number].sensor_id, host_cpu_temperature_sensor_data[sensor_number].temperature_c);
}
}
}
return 0;
}
static int kestrel_shell_cmd_console(const struct shell *shell, size_t argc, char **argv)
{
const void *active_log_backend = NULL;
......@@ -255,6 +295,8 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_kestrel,
SHELL_CMD(memdump, NULL, "Memory dump tool", kestrel_shell_cmd_memdump),
// PWM commands
SHELL_CMD(pwmcontrol, NULL, "PWM controller", kestrel_shell_cmd_pwmcontrol),
// OCC commands
SHELL_CMD(occcontrol, NULL, "OCC command interface", kestrel_shell_cmd_occcontrol),
// Command list array terminator
SHELL_SUBCMD_SET_END
);
......
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