diff options
Diffstat (limited to 'meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files')
18 files changed, 3257 insertions, 0 deletions
diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/Makefile b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/Makefile new file mode 100644 index 0000000..12cb085 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/Makefile @@ -0,0 +1,11 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +lib: libbic.so + +libbic.so: bic.c + $(CC) $(CFLAGS) -fPIC -c -o bic.o bic.c + $(CC) -lipmb -shared -o libbic.so bic.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libbic.so diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.c b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.c new file mode 100644 index 0000000..55cd56b --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.c @@ -0,0 +1,466 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * This file contains code to support IPMI2.0 Specificaton available @ + * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <stdio.h> +#include <stdint.h> +#include <fcntl.h> +#include "bic.h" + +#define FRUID_READ_COUNT_MAX 0x30 +#define SDR_READ_COUNT_MAX 0x1A + +enum { + IPMB_BUS_SLOT1 = 3, + IPMB_BUS_SLOT2 = 1, + IPMB_BUS_SLOT3 = 7, + IPMB_BUS_SLOT4 = 5, +}; + +#pragma pack(push, 1) +typedef struct _sdr_rec_hdr_t { + uint16_t rec_id; + uint8_t ver; + uint8_t type; + uint8_t len; +} sdr_rec_hdr_t; +#pragma pack(pop) + +// Common IPMB Wrapper function + +static int +get_ipmb_bus_id(uint8_t slot_id) { + int bus_id; + + switch(slot_id) { + case 1: + bus_id = IPMB_BUS_SLOT1; + break; + case 2: + bus_id = IPMB_BUS_SLOT2; + break; + case 3: + bus_id = IPMB_BUS_SLOT3; + break; + case 4: + bus_id = IPMB_BUS_SLOT4; + break; + default: + bus_id = -1; + break; + } + + return bus_id; +} + +static int +bic_ipmb_wrapper(uint8_t slot_id, uint8_t netfn, uint8_t cmd, + uint8_t *txbuf, uint8_t txlen, + uint8_t *rxbuf, uint8_t *rxlen) { + ipmb_req_t *req; + ipmb_res_t *res; + uint8_t rbuf[MAX_IPMB_RES_LEN] = {0}; + uint8_t tbuf[MAX_IPMB_RES_LEN] = {0}; + uint8_t tlen = 0; + uint8_t rlen = 0; + int count = 0; + int i = 0; + int ret; + uint8_t bus_id; + + ret = get_ipmb_bus_id(slot_id); + if (ret < 0) { + printf("bic_ipmb_wrapper: Wrong Slot ID %d\n", slot_id); + return ret; + } + + bus_id = (uint8_t) ret; + + req = (ipmb_req_t*)tbuf; + + req->res_slave_addr = BRIDGE_SLAVE_ADDR << 1; + req->netfn_lun = netfn << LUN_OFFSET; + req->hdr_cksum = req->res_slave_addr + + req->netfn_lun; + req->hdr_cksum = ZERO_CKSUM_CONST - req->hdr_cksum; + + req->req_slave_addr = BMC_SLAVE_ADDR << 1; + req->seq_lun = 0x00; + req->cmd = cmd; + + //copy the data to be send + if (txlen) { + memcpy(req->data, txbuf, txlen); + } + + tlen = IPMB_HDR_SIZE + IPMI_REQ_HDR_SIZE + txlen; + + // Invoke IPMB library handler + lib_ipmb_handle(bus_id, tbuf, tlen, &rbuf, &rlen); + if (rlen == 0) { + printf("bic_ipmb_wrapper: Zero bytes received\n"); + return -1; + } + + // Handle IPMB response + res = (ipmb_res_t*) rbuf; + + if (res->cc) { + printf("bic_ipmb_wrapper: Completion Code: 0x%X\n", res->cc); + return -1; + } + + // copy the received data back to caller + *rxlen = rlen - IPMB_HDR_SIZE - IPMI_RESP_HDR_SIZE; + memcpy(rxbuf, res->data, *rxlen); + + return 0; +} + +// Get Device ID +int +bic_get_dev_id(uint8_t slot_id, ipmi_dev_id_t *dev_id) { + uint8_t rlen = 0; + int ret; + + ret = bic_ipmb_wrapper(slot_id, NETFN_APP_REQ, CMD_APP_GET_DEVICE_ID, NULL, 0, (uint8_t *) dev_id, &rlen); + + return ret; +} + +// Get GPIO value and configuration +int +bic_get_gpio(uint8_t slot_id, bic_gpio_t *gpio) { + uint8_t rlen = 0; + int ret; + + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_GET_GPIO, NULL, 0, (uint8_t*) gpio, &rlen); + + return ret; +} + +int +bic_get_gpio_config(uint8_t slot_id, uint8_t gpio, bic_gpio_config_t *gpio_config) { + uint8_t tbuf[4] = {0}; + uint8_t rlen = 0; + uint8_t tlen = 0; + uint32_t pin; + int ret; + + pin = 1 << gpio; + + tbuf[0] = pin & 0xFF; + tbuf[1] = (pin >> 8) & 0xFF; + tbuf[2] = (pin >> 16) & 0xFF; + tbuf[3] = (pin >> 24) & 0xFF; + + tlen = 4; + + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_GET_GPIO_CONFIG, tbuf, tlen, (uint8_t *) gpio_config, &rlen); + + return ret; +} + +int +bic_set_gpio_config(uint8_t slot_id, uint8_t gpio, bic_gpio_config_t *gpio_config) { + uint8_t tbuf[5] = {0}; + uint8_t rlen = 0; + uint8_t tlen = 0; + uint32_t pin; + uint8_t res; + int ret; + + pin = 1 << gpio; + + tbuf[0] = pin & 0xFF; + tbuf[1] = (pin >> 8) & 0xFF; + tbuf[2] = (pin >> 16) & 0xFF; + tbuf[3] = (pin >> 24) & 0xFF; + tbuf[4] = (*(uint8_t *) gpio_config) & 0x1F; + + tlen = 5; + + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_SET_GPIO_CONFIG, + tbuf, tlen, &res, &rlen); + return ret; +} + +// Get BIC Configuration +int +bic_get_config(uint8_t slot_id, bic_config_t *cfg) { + uint8_t rlen = 0; + int ret; + + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_GET_CONFIG, + NULL, 0x00, (uint8_t *) cfg, &rlen); + return ret; +} + +// Set BIC Configuration +int +bic_set_config(uint8_t slot_id, bic_config_t *cfg) { + uint8_t rlen = 0; + uint8_t rbuf[4] = {0}; + int ret; + + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_SET_CONFIG, + (uint8_t *) cfg, 1, rbuf, &rlen); + return ret; +} + +// Read POST Buffer +int +bic_get_post_buf(uint8_t slot_id, uint8_t *buf, uint8_t *len) { + int ret; + + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_GET_POST_BUF, NULL, 0, buf, len); + + return ret; +} + +// Read 1S server's FRUID +int +bic_get_fruid_info(uint8_t slot_id, uint8_t fru_id, ipmi_fruid_info_t *info) { + int ret; + uint8_t rlen = 0; + + ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_GET_FRUID_INFO, &fru_id, 1, (uint8_t *) info, &rlen); + + return ret; +} + +static int +_read_fruid(uint8_t slot_id, uint8_t fru_id, uint32_t offset, uint8_t count, uint8_t *rbuf, uint8_t *rlen) { + int ret; + uint8_t tbuf[4] = {0}; + uint8_t tlen = 0; + + tbuf[0] = fru_id; + tbuf[1] = offset & 0xFF; + tbuf[2] = (offset >> 8) & 0xFF; + tbuf[3] = count; + + ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_READ_FRUID_DATA, tbuf, 4, rbuf, rlen); + + return ret; +} + +int +bic_read_fruid(uint8_t slot_id, uint8_t fru_id, const char *path) { + int ret; + uint32_t nread; + uint32_t offset; + uint8_t count; + uint8_t rbuf[256] = {0}; + uint8_t rlen = 0; + int fd; + ipmi_fruid_info_t info; + + // Remove the file if exists already + unlink(path); + + // Open the file exclusively for write + fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0666); + if (fd < 0) { + printf("bic_read_fruid: open fails for path: %s\n", path); + goto error_exit; + } + + // Read the FRUID information + ret = bic_get_fruid_info(slot_id, fru_id, &info); + if (ret) { + printf("bic_read_fruid: bic_read_fruid_info returns %d\n", ret); + goto error_exit; + } + + // Indicates the size of the FRUID + nread = (info.size_msb << 8) + (info.size_lsb); + + // Read chunks of FRUID binary data in a loop + offset = 0; + while (nread > 0) { + if (nread > FRUID_READ_COUNT_MAX) { + count = FRUID_READ_COUNT_MAX; + } else { + count = nread; + } + + ret = _read_fruid(slot_id, fru_id, offset, count, rbuf, &rlen); + if (ret) { + printf("bic_read_fruid: ipmb_wrapper fails\n"); + goto error_exit; + } + + // Ignore the first byte as it indicates length of response + write(fd, &rbuf[1], rlen-1); + + // Update offset + offset += (rlen-1); + nread -= (rlen-1); + } + +error_exit: + if (fd > 0 ) { + close(fd); + } + + return ret; +} + +// Read System Event Log (SEL) +int +bic_get_sel_info(uint8_t slot_id, ipmi_sel_sdr_info_t *info) { + int ret; + uint8_t rlen = 0; + + ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_GET_SEL_INFO, NULL, 0, (uint8_t *)info, &rlen); + + return ret; +} + +static int +_get_sel_rsv(uint8_t slot_id, uint16_t *rsv) { + int ret; + uint8_t rlen = 0; + + ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_RSV_SEL, NULL, 0, (uint8_t *) rsv, &rlen); + return ret; +} + +int +bic_get_sel(uint8_t slot_id, ipmi_sel_sdr_req_t *req, ipmi_sel_sdr_res_t *res, uint8_t *rlen) { + + int ret; + + ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_GET_SEL, (uint8_t *)req, sizeof(ipmi_sel_sdr_req_t), (uint8_t*)res, rlen); + + return ret; +} + +// Read Sensor Data Records (SDR) +int +bic_get_sdr_info(uint8_t slot_id, ipmi_sel_sdr_info_t *info) { + int ret; + uint8_t rlen = 0; + + ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_GET_SDR_INFO, NULL, 0, (uint8_t *) info, &rlen); + + return ret; +} + +static int +_get_sdr_rsv(uint8_t slot_id, uint16_t *rsv) { + int ret; + uint8_t rlen = 0; + + ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_RSV_SDR, NULL, 0, (uint8_t *) rsv, &rlen); + + return ret; +} + +static int +_get_sdr(uint8_t slot_id, ipmi_sel_sdr_req_t *req, ipmi_sel_sdr_res_t *res, uint8_t *rlen) { + int ret; + + ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_GET_SDR, (uint8_t *)req, sizeof(ipmi_sel_sdr_req_t), (uint8_t*)res, rlen); + + return ret; +} + +int +bic_get_sdr(uint8_t slot_id, ipmi_sel_sdr_req_t *req, ipmi_sel_sdr_res_t *res, uint8_t *rlen) { + int ret; + uint8_t tbuf[MAX_IPMB_RES_LEN] = {0}; + uint8_t tlen; + uint8_t len; + ipmi_sel_sdr_res_t *tres; + sdr_rec_hdr_t *hdr; + + tres = (ipmi_sel_sdr_res_t *) tbuf; + + // Get SDR reservation ID for the given record + ret = _get_sdr_rsv(slot_id, &req->rsv_id); + if (ret) { + printf("bic_read_sdr: _get_sdr_rsv returns %d\n", ret); + return ret; + } + + // Initialize the response length to zero + *rlen = 0; + + // Read SDR Record Header + req->offset = 0; + req->nbytes = sizeof(sdr_rec_hdr_t); + + ret = _get_sdr(slot_id, req, tbuf, &tlen); + if (ret) { + printf("bic_read_sdr: _get_sdr returns %d\n", ret); + return ret; + } + + // Copy the next record id to response + res->next_rec_id = tres->next_rec_id; + + // Copy the header excluding first two bytes(next_rec_id) + memcpy(res->data, tres->data, tlen-2); + + // Update response length and offset for next request + *rlen += tlen-2; + req->offset = tlen-2; + + // Find length of data from header info + hdr = (sdr_rec_hdr_t *) tres->data; + len = hdr->len; + + // Keep reading chunks of SDR record in a loop + while (len > 0) { + if (len > SDR_READ_COUNT_MAX) { + req->nbytes = SDR_READ_COUNT_MAX; + } else { + req->nbytes = len; + } + + ret = _get_sdr(slot_id, req, tbuf, &tlen); + if (ret) { + printf("bic_read_sdr: _get_sdr returns %d\n", ret); + return ret; + } + + // Copy the data excluding the first two bytes(next_rec_id) + memcpy(&res->data[req->offset], tres->data, tlen-2); + + // Update response length, offset for next request, and remaining length + *rlen += tlen-2; + req->offset += tlen-2; + len -= tlen-2; + } + + return 0; +} + +int +bic_read_sensor(uint8_t slot_id, uint8_t sensor_num, ipmi_sensor_reading_t *sensor) { + int ret; + int rlen = 0; + + ret = bic_ipmb_wrapper(slot_id, NETFN_SENSOR_REQ, CMD_SENSOR_GET_SENSOR_READING, (uint8_t *)&sensor_num, 1, (uint8_t *)sensor, &rlen); + + return ret; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.h b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.h new file mode 100644 index 0000000..47b0baa --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.h @@ -0,0 +1,156 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __BIC_H__ +#define __BIC_H__ + +#include <openbmc/ipmi.h> +#include <openbmc/ipmb.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_GPIO_PINS 32 + +// GPIO PINS +enum { + PWRGOOD_CPU = 0x0, + PWRGD_PCH_PWROK, + PVDDR_VRHOT_N, + PVCCIN_VRHOT_N, + FM_FAST_PROCHOT_N, + PCHHOT_CPU_N, + FM_CPLD_CPU_DIMM_EVENT_CO_N, + FM_CPLD_BDXDE_THERMTRIP_N, + THERMTRIP_PCH_N, + FM_CPLD_FIVR_FAULT, + FM_BDXDE_CATERR_LVT3_N, + FM_BDXDE_ERR2_LVT3_N, + FM_BDXDE_ERR1_LVT3_N, + FM_BDXDE_ERR0_LVT3_N, + SLP_S4_N, + FM_NMI_EVENT_BMC_N, + FM_SMI_BMC_N, + RST_PLTRST_BMC_N, + FP_RST_BTN_BUF_N, + BMC_RST_BTN_OUT_N, + FM_BDE_POST_CMPLT_N, + FM_BDXDE_SLP3_N, + FM_PWR_LED_N, + PWRGD_PVCCIN, + SVR_ID0, + SVR_ID1, + SVR_ID2, + SVR_ID3, + BMC_READY_N, + RESERVED_29, + RESERVED_30, + RESERVED_31, +}; + +// Bridge IC Spec +typedef struct _bic_gpio_t { + uint32_t pwrgood_cpu:1; + uint32_t pwrgd_pch_pwrok:1; + uint32_t pvddr_vrhot_n:1; + uint32_t pvccin_vrhot_n:1; + uint32_t fm_fast_prochot_n:1; + uint32_t pchhot_cpu_n:1; + uint32_t fm_cpld_cpu_dimm_event_c0_n:1; + uint32_t fm_cpld_bdxde_thermtrip_n:1; + uint32_t thermtrip_pch_n:1; + uint32_t fm_cpld_fivr_fault:1; + uint32_t fm_bdxde_caterr_lvt3_n:1; + uint32_t fm_bdxde_err_lvt3_n:3; + uint32_t slp_s4_n:1; + uint32_t fm_nmi_event_bmc_n:1; + uint32_t fm_smi_bmc_n:1; + uint32_t rst_pltrst_bmc_n:1; + uint32_t fp_rst_btn_buf_n:1; + uint32_t bmc_rst_btn_out_n:1; + uint32_t fm_bde_post_cmplt_n:1; + uint32_t fm_bdxde_slp3_n:1; + uint32_t fm_pwr_led_n:1; + uint32_t pwrgd_pvccin:1; + uint32_t svr_id:4; + uint32_t bmc_ready_n:1; + uint32_t bmc_com_sw_n:1; + uint32_t rsvd:2; +} bic_gpio_t; + +typedef union _bic_gpio_u { + uint8_t gpio[4]; + bic_gpio_t bits; +} bic_gpio_u; + +typedef struct _bic_gpio_config_t { + uint8_t dir:1; + uint8_t ie:1; + uint8_t edge:1; + uint8_t trig:2; +} bic_gpio_config_t; + +typedef union _bic_gpio_config_u { + uint8_t config; + bic_gpio_config_t bits; +} bic_gpio_config_u; + +typedef struct _bic_config_t { + uint8_t sol:1; + uint8_t post:1; + uint8_t kcs:1; + uint8_t ipmb:1; + uint8_t rsvd:4; +} bic_config_t; + +typedef union _bic_config_u { + uint8_t config; + bic_config_t bits; +} bic_config_u; + +int bic_get_dev_id(uint8_t slot_id, ipmi_dev_id_t *id); + +int bic_get_bic_config(uint8_t slot_id, bic_config_t *cfg); +int bic_set_bic_config(uint8_t slot_id, bic_config_t *cfg); + +int bic_get_gpio(uint8_t slot_id, bic_gpio_t *gpio); +int bic_get_gpio_config(uint8_t slot_id, uint8_t gpio, bic_gpio_config_t *gpio_config); +int bic_set_gpio_config(uint8_t slot_id, uint8_t gpio, bic_gpio_config_t *gpio_config); +int bic_get_post_buf(uint8_t slot_id, uint8_t *buf, uint8_t *len); + +int bic_get_fruid_info(uint8_t slot_id, uint8_t fru_id, ipmi_fruid_info_t *info); +int bic_read_fruid(uint8_t slot_id, uint8_t fru_id, const char *path); + +int bic_get_sel_info(uint8_t slot_id, ipmi_sel_sdr_info_t *info); +int bic_get_sel_rsv(uint8_t slot_id, uint16_t *rsv); +int bic_get_sel(uint8_t slot_id, ipmi_sel_sdr_req_t *req, ipmi_sel_sdr_res_t *res, uint8_t *rlen); + +int bic_get_sdr_info(uint8_t slot_id, ipmi_sel_sdr_info_t *info); +int bic_get_sdr_rsv(uint8_t slot_id, uint16_t *rsv); +int bic_get_sdr(uint8_t slot_id, ipmi_sel_sdr_req_t *req, ipmi_sel_sdr_res_t *res, uint8_t *rlen); + +int bic_read_sensor(uint8_t slot_id, uint8_t sensor_num, ipmi_sensor_reading_t *sensor); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __BIC_H__ */ diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/pal/Makefile b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/pal/Makefile new file mode 100644 index 0000000..bab4007 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/pal/Makefile @@ -0,0 +1,11 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +lib: libpal.so + +libpal.so: pal.c + $(CC) $(CFLAGS) -fPIC -c -o pal.o pal.c + $(CC) -lbic -lyosemite_common -lyosemite_fruid -lyosemite_sensor -shared -o libpal.so pal.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libpal.so diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/pal/pal.c b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/pal/pal.c new file mode 100644 index 0000000..93a5fbf --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/pal/pal.c @@ -0,0 +1,1151 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * This file contains code to support IPMI2.0 Specificaton available @ + * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <stdio.h> +#include <stdint.h> +#include <stdbool.h> +#include <fcntl.h> +#include <errno.h> +#include <syslog.h> +#include <sys/mman.h> +#include <string.h> +#include "pal.h" + +#define BIT(value, index) ((value >> index) & 1) + +#define YOSEMITE_PLATFORM_NAME "Yosemite" +#define LAST_KEY "last_key" +#define YOSEMITE_MAX_NUM_SLOTS 4 +#define GPIO_VAL "/sys/class/gpio/gpio%d/value" +#define GPIO_DIR "/sys/class/gpio/gpio%d/direction" + +#define GPIO_HAND_SW_ID1 138 +#define GPIO_HAND_SW_ID2 139 +#define GPIO_HAND_SW_ID4 140 +#define GPIO_HAND_SW_ID8 141 + +#define GPIO_RST_BTN 144 +#define GPIO_PWR_BTN 24 + +#define GPIO_USB_SW0 36 +#define GPIO_USB_SW1 37 + +#define GPIO_UART_SEL0 32 +#define GPIO_UART_SEL1 33 +#define GPIO_UART_SEL2 34 +#define GPIO_UART_RX 35 + +#define GPIO_POSTCODE_0 48 +#define GPIO_POSTCODE_1 49 +#define GPIO_POSTCODE_2 50 +#define GPIO_POSTCODE_3 51 +#define GPIO_POSTCODE_4 124 +#define GPIO_POSTCODE_5 125 +#define GPIO_POSTCODE_6 126 +#define GPIO_POSTCODE_7 127 + +#define GPIO_DBG_CARD_PRSNT 137 + +#define PAGE_SIZE 0x1000 +#define AST_SCU_BASE 0x1e6e2000 +#define PIN_CTRL1_OFFSET 0x80 +#define PIN_CTRL2_OFFSET 0x84 + +#define UART1_TXD (1 << 22) +#define UART2_TXD (1 << 30) +#define UART3_TXD (1 << 22) +#define UART4_TXD (1 << 30) + +#define BIT(v, i) ((v >> i) & 1) +#define DELAY_GRACEFUL_SHUTDOWN 1 +#define DELAY_POWER_OFF 5 + +static uint8_t gpio_rst_btn[5] = { 0, 57, 56, 59, 58 }; +static uint8_t gpio_led[5] = { 0, 97, 96, 99, 98 }; +static uint8_t gpio_prsnt[5] = { 0, 61, 60, 63, 62 }; +static uint8_t gpio_power[5] = { 0, 27, 25, 31, 29 }; +const char pal_fru_list[] = "all, slot1, slot2, slot3, slot4, spb, nic"; +const char pal_server_list[] = "slot1, slot2, slot3, slot4"; + +char * key_list[] = { +"pwr_server1_last_state", +"pwr_server2_last_state", +"pwr_server3_last_state", +"pwr_server4_last_state", +"slot1_por_cfg", +"slot2_por_cfg", +"slot3_por_cfg", +"slot4_por_cfg", +/* Add more Keys here */ +LAST_KEY /* This is the last key of the list */ +}; + +// Helper Functions +static int +read_device(const char *device, int *value) { + FILE *fp; + int rc; + + fp = fopen(device, "r"); + if (!fp) { + int err = errno; + + syslog(LOG_INFO, "failed to open device %s", device); + return err; + } + + rc = fscanf(fp, "%d", value); + fclose(fp); + if (rc != 1) { + syslog(LOG_INFO, "failed to read device %s", device); + return ENOENT; + } else { + return 0; + } +} + +static int +write_device(const char *device, const char *value) { + FILE *fp; + int rc; + + fp = fopen(device, "w"); + if (!fp) { + int err = errno; + + syslog(LOG_INFO, "failed to open device for write %s", device); + return err; + } + + rc = fputs(value, fp); + fclose(fp); + + if (rc < 0) { + syslog(LOG_INFO, "failed to write device %s", device); + return ENOENT; + } else { + return 0; + } +} + +// Power On the server in a given slot +static int +server_power_on(uint8_t slot_id) { + char vpath[64] = {0}; + + sprintf(vpath, GPIO_VAL, gpio_power[slot_id]); + + if (write_device(vpath, "1")) { + return -1; + } + + if (write_device(vpath, "0")) { + return -1; + } + + sleep(1); + + if (write_device(vpath, "1")) { + return -1; + } + + return 0; +} + +// Power Off the server in given slot +static int +server_power_off(uint8_t slot_id, bool gs_flag) { + char vpath[64] = {0}; + + if (slot_id < 1 || slot_id > 4) { + return -1; + } + + sprintf(vpath, GPIO_VAL, gpio_power[slot_id]); + + if (write_device(vpath, "1")) { + return -1; + } + + sleep(1); + + if (write_device(vpath, "0")) { + return -1; + } + + if (gs_flag) { + sleep(DELAY_GRACEFUL_SHUTDOWN); + } else { + sleep(DELAY_POWER_OFF); + } + + if (write_device(vpath, "1")) { + return -1; + } + + return 0; +} + +// Debug Card's UART and BMC/SoL port share UART port and need to enable only +// one TXD i.e. either BMC's TXD or Debug Port's TXD. +static int +control_sol_txd(uint8_t slot) { + uint32_t scu_fd; + uint32_t ctrl; + void *scu_reg; + void *scu_pin_ctrl1; + void *scu_pin_ctrl2; + + scu_fd = open("/dev/mem", O_RDWR | O_SYNC ); + if (scu_fd < 0) { + syslog(LOG_ALERT, "control_sol_txd: open fails\n"); + return -1; + } + + scu_reg = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, scu_fd, + AST_SCU_BASE); + scu_pin_ctrl1 = (char*)scu_reg + PIN_CTRL1_OFFSET; + scu_pin_ctrl2 = (char*)scu_reg + PIN_CTRL2_OFFSET; + + switch(slot) { + case 1: + // Disable UART2's TXD and enable others + ctrl = *(volatile uint32_t*) scu_pin_ctrl2; + ctrl |= UART1_TXD; + ctrl &= (~UART2_TXD); //Disable + *(volatile uint32_t*) scu_pin_ctrl2 = ctrl; + + ctrl = *(volatile uint32_t*) scu_pin_ctrl1; + ctrl |= UART3_TXD | UART4_TXD; + *(volatile uint32_t*) scu_pin_ctrl1 = ctrl; + break; + case 2: + // Disable UART1's TXD and enable others + ctrl = *(volatile uint32_t*) scu_pin_ctrl2; + ctrl &= (~UART1_TXD); // Disable + ctrl |= UART2_TXD; + *(volatile uint32_t*) scu_pin_ctrl2 = ctrl; + + ctrl = *(volatile uint32_t*) scu_pin_ctrl1; + ctrl |= UART3_TXD | UART4_TXD; + *(volatile uint32_t*) scu_pin_ctrl1 = ctrl; + break; + case 3: + // Disable UART4's TXD and enable others + ctrl = *(volatile uint32_t*) scu_pin_ctrl2; + ctrl |= UART1_TXD | UART2_TXD; + *(volatile uint32_t*) scu_pin_ctrl2 = ctrl; + + ctrl = *(volatile uint32_t*) scu_pin_ctrl1; + ctrl |= UART3_TXD; + ctrl &= (~UART4_TXD); // Disable + *(volatile uint32_t*) scu_pin_ctrl1 = ctrl; + break; + case 4: + // Disable UART3's TXD and enable others + ctrl = *(volatile uint32_t*) scu_pin_ctrl2; + ctrl |= UART1_TXD | UART2_TXD; + *(volatile uint32_t*) scu_pin_ctrl2 = ctrl; + + ctrl = *(volatile uint32_t*) scu_pin_ctrl1; + ctrl &= (~UART3_TXD); // Disable + ctrl |= UART4_TXD; + *(volatile uint32_t*) scu_pin_ctrl1 = ctrl; + break; + default: + // Any other slots we need to enable all TXDs + ctrl = *(volatile uint32_t*) scu_pin_ctrl2; + ctrl |= UART1_TXD | UART2_TXD; + *(volatile uint32_t*) scu_pin_ctrl2 = ctrl; + + ctrl = *(volatile uint32_t*) scu_pin_ctrl1; + ctrl |= UART3_TXD | UART4_TXD; + *(volatile uint32_t*) scu_pin_ctrl1 = ctrl; + break; + } + + munmap(scu_reg, PAGE_SIZE); + close(scu_fd); + + return 0; +} + +// Display the given POST code using GPIO port +static int +pal_post_display(uint8_t status) { + char path[64] = {0}; + int ret; + char *val; + + syslog(LOG_ALERT, "pal_post_display: status is %d\n", status); + + sprintf(path, GPIO_VAL, GPIO_POSTCODE_0); + + if (BIT(status, 0)) { + val = "1"; + } else { + val = "0"; + } + + ret = write_device(path, val); + if (ret) { + goto post_exit; + } + + sprintf(path, GPIO_VAL, GPIO_POSTCODE_1); + if (BIT(status, 1)) { + val = "1"; + } else { + val = "0"; + } + + ret = write_device(path, val); + if (ret) { + goto post_exit; + } + + sprintf(path, GPIO_VAL, GPIO_POSTCODE_2); + if (BIT(status, 2)) { + val = "1"; + } else { + val = "0"; + } + + ret = write_device(path, val); + if (ret) { + goto post_exit; + } + + sprintf(path, GPIO_VAL, GPIO_POSTCODE_3); + if (BIT(status, 3)) { + val = "1"; + } else { + val = "0"; + } + + ret = write_device(path, val); + if (ret) { + goto post_exit; + } + + sprintf(path, GPIO_VAL, GPIO_POSTCODE_4); + if (BIT(status, 4)) { + val = "1"; + } else { + val = "0"; + } + + ret = write_device(path, val); + if (ret) { + goto post_exit; + } + + sprintf(path, GPIO_VAL, GPIO_POSTCODE_5); + if (BIT(status, 5)) { + val = "1"; + } else { + val = "0"; + } + + ret = write_device(path, val); + if (ret) { + goto post_exit; + } + + sprintf(path, GPIO_VAL, GPIO_POSTCODE_6); + if (BIT(status, 6)) { + val = "1"; + } else { + val = "0"; + } + + ret = write_device(path, val); + if (ret) { + goto post_exit; + } + + sprintf(path, GPIO_VAL, GPIO_POSTCODE_7); + if (BIT(status, 7)) { + val = "1"; + } else { + val = "0"; + } + + ret = write_device(path, val); + if (ret) { + goto post_exit; + } + +post_exit: + if (ret) { + syslog(LOG_ALERT, "write_device failed for %s\n", path); + return -1; + } else { + return 0; + } +} + +// Platform Abstraction Layer (PAL) Functions +int +pal_get_platform_name(char *name) { + strcpy(name, YOSEMITE_PLATFORM_NAME); + + return 0; +} + +int +pal_get_num_slots(uint8_t *num) { + *num = YOSEMITE_MAX_NUM_SLOTS; + + return 0; +} + +int +pal_is_server_prsnt(uint8_t slot_id, uint8_t *status) { + int val; + char path[64] = {0}; + + if (slot_id < 1 || slot_id > 4) { + return -1; + } + + sprintf(path, GPIO_VAL, gpio_prsnt[slot_id]); + + if (read_device(path, &val)) { + return -1; + } + + if (val == 0x0) { + *status = 1; + } else { + *status = 0; + } + + return 0; +} + +int +pal_is_debug_card_prsnt(uint8_t *status) { + int val; + char path[64] = {0}; + + sprintf(path, GPIO_VAL, GPIO_DBG_CARD_PRSNT); + + if (read_device(path, &val)) { + return -1; + } + + // TODO: Logic is reversed until DVT board with h/w fix + if (val == 0x0) { + *status = 0; + } else { + *status = 1; + } + + return 0; +} + +int +pal_get_server_power(uint8_t slot_id, uint8_t *status) { + int ret; + bic_gpio_t gpio; + + ret = bic_get_gpio(slot_id, &gpio); + if (ret) { + return ret; + } + + if (gpio.pwrgood_cpu) { + *status = SERVER_POWER_ON; + } else { + *status = SERVER_POWER_OFF; + } + + return 0; +} + +// Power Off, Power On, or Power Reset the server in given slot +int +pal_set_server_power(uint8_t slot_id, uint8_t cmd) { + uint8_t status; + bool gs_flag = false; + + if (slot_id < 1 || slot_id > 4) { + return -1; + } + + if (pal_get_server_power(slot_id, &status) < 0) { + return -1; + } + + switch(cmd) { + case SERVER_POWER_ON: + if (status == SERVER_POWER_ON) + return 1; + else + return server_power_on(slot_id); + break; + + case SERVER_POWER_OFF: + if (status == SERVER_POWER_OFF) + return 1; + else + return server_power_off(slot_id, gs_flag); + break; + + case SERVER_POWER_CYCLE: + if (status == SERVER_POWER_ON) + return (server_power_off(slot_id, gs_flag) || server_power_on(slot_id)); + else if (status == SERVER_POWER_OFF) + return (server_power_on(slot_id)); + break; + + case SERVER_GRACEFUL_SHUTDOWN: + if (status == SERVER_POWER_OFF) + return 1; + else + gs_flag = true; + return server_power_off(slot_id, gs_flag); + break; + default: + return -1; + } + + return 0; +} + +int +pal_sled_cycle(void) { + // Remove the adm1275 module as the HSC device is busy + system("rmmod adm1275"); + + // Send command to HSC power cycle + system("i2cset -y 10 0x40 0xd9 c"); + + return 0; +} + +// Read the Front Panel Hand Switch and return the position +int +pal_get_hand_sw(uint8_t *pos) { + char path[64] = {0}; + int id1, id2, id4, id8; + uint8_t loc; + // Read 4 GPIOs to read the current position + // id1: GPIOR2(138) + // id2: GPIOR3(139) + // id4: GPIOR4(140) + // id8: GPIOR5(141) + + // Read ID1 + sprintf(path, GPIO_VAL, GPIO_HAND_SW_ID1); + if (read_device(path, &id1)) { + return -1; + } + + // Read ID2 + sprintf(path, GPIO_VAL, GPIO_HAND_SW_ID2); + if (read_device(path, &id2)) { + return -1; + } + + // Read ID4 + sprintf(path, GPIO_VAL, GPIO_HAND_SW_ID4); + if (read_device(path, &id4)) { + return -1; + } + + // Read ID8 + sprintf(path, GPIO_VAL, GPIO_HAND_SW_ID8); + if (read_device(path, &id8)) { + return -1; + } + + loc = ((id8 << 3) | (id4 << 2) | (id2 << 1) | (id1)); + + switch(loc) { + case 1: + case 6: + *pos = HAND_SW_SERVER1; + break; + case 2: + case 7: + *pos = HAND_SW_SERVER2; + break; + case 3: + case 8: + *pos = HAND_SW_SERVER3; + break; + case 4: + case 9: + *pos = HAND_SW_SERVER4; + break; + default: + *pos = HAND_SW_BMC; + break; + } + + return 0; +} + +// Return the Front panel Power Button +int +pal_get_pwr_btn(uint8_t *status) { + char path[64] = {0}; + int val; + + sprintf(path, GPIO_VAL, GPIO_PWR_BTN); + if (read_device(path, &val)) { + return -1; + } + + if (val) { + *status = 0x0; + } else { + *status = 0x1; + } + + return 0; +} + +// Return the front panel's Reset Button status +int +pal_get_rst_btn(uint8_t *status) { + char path[64] = {0}; + int val; + + sprintf(path, GPIO_VAL, GPIO_RST_BTN); + if (read_device(path, &val)) { + return -1; + } + + if (val) { + *status = 0x0; + } else { + *status = 0x1; + } + + return 0; +} + +// Update the Reset button input to the server at given slot +int +pal_set_rst_btn(uint8_t slot, uint8_t status) { + char path[64] = {0}; + char *val; + + if (slot < 1 || slot > 4) { + return -1; + } + + if (status) { + val = "0"; + } else { + val = "1"; + } + + sprintf(path, GPIO_VAL, gpio_rst_btn[slot]); + if (write_device(path, val)) { + return -1; + } + + return 0; +} + +// Update the LED for the given slot with the status +int +pal_set_led(uint8_t slot, uint8_t status) { + char path[64] = {0}; + char *val; + + if (slot < 1 || slot > 4) { + return -1; + } + + if (status) { + val = "1"; + } else { + val = "0"; + } + + sprintf(path, GPIO_VAL, gpio_led[slot]); + if (write_device(path, val)) { + return -1; + } + + return 0; +} + +// Update the USB Mux to the server at given slot +int +pal_switch_usb_mux(uint8_t slot) { + char *gpio_sw0, *gpio_sw1; + char path[64] = {0}; + + // Based on the USB mux table in Schematics + switch(slot) { + case 1: + gpio_sw0 = "1"; + gpio_sw1 = "0"; + break; + case 2: + gpio_sw0 = "0"; + gpio_sw1 = "0"; + break; + case 3: + gpio_sw0 = "1"; + gpio_sw1 = "1"; + break; + case 4: + gpio_sw0 = "0"; + gpio_sw1 = "1"; + break; + default: + // Default is for BMC itself + return 0; + } + + sprintf(path, GPIO_VAL, GPIO_USB_SW0); + if (write_device(path, gpio_sw0) < 0) { + syslog(LOG_ALERT, "write_device failed for %s\n", path); + return -1; + } + + sprintf(path, GPIO_VAL, GPIO_USB_SW1); + if (write_device(path, gpio_sw1) < 0) { + syslog(LOG_ALERT, "write_device failed for %s\n", path); + return -1; + } + + return 0; +} + +// Switch the UART mux to the given slot +int +pal_switch_uart_mux(uint8_t slot) { + char * gpio_uart_sel0; + char * gpio_uart_sel1; + char * gpio_uart_sel2; + char * gpio_uart_rx; + char path[64] = {0}; + int ret; + + // Refer the UART select table in schematic + switch(slot) { + case 1: + gpio_uart_sel2 = "0"; + gpio_uart_sel1 = "0"; + gpio_uart_sel0 = "1"; + gpio_uart_rx = "0"; + break; + case 2: + gpio_uart_sel2 = "0"; + gpio_uart_sel1 = "0"; + gpio_uart_sel0 = "0"; + gpio_uart_rx = "0"; + break; + case 3: + gpio_uart_sel2 = "0"; + gpio_uart_sel1 = "1"; + gpio_uart_sel0 = "1"; + gpio_uart_rx = "0"; + break; + case 4: + gpio_uart_sel2 = "0"; + gpio_uart_sel1 = "1"; + gpio_uart_sel0 = "0"; + gpio_uart_rx = "0"; + break; + default: + // for all other cases, assume BMC + gpio_uart_sel2 = "1"; + gpio_uart_sel1 = "0"; + gpio_uart_sel0 = "0"; + gpio_uart_rx = "1"; + break; + } + + // Diable TXD path from BMC to avoid conflict with SoL + ret = control_sol_txd(slot); + if (ret) { + goto uart_exit; + } + + // Enable Debug card path + sprintf(path, GPIO_VAL, GPIO_UART_SEL2); + ret = write_device(path, gpio_uart_sel2); + if (ret) { + goto uart_exit; + } + + sprintf(path, GPIO_VAL, GPIO_UART_SEL1); + ret = write_device(path, gpio_uart_sel1); + if (ret) { + goto uart_exit; + } + + sprintf(path, GPIO_VAL, GPIO_UART_SEL0); + ret = write_device(path, gpio_uart_sel0); + if (ret) { + goto uart_exit; + } + + sprintf(path, GPIO_VAL, GPIO_UART_RX); + ret = write_device(path, gpio_uart_rx); + if (ret) { + goto uart_exit; + } + +uart_exit: + if (ret) { + syslog(LOG_ALERT, "pal_switch_uart_mux: write_device failed: %s\n", path); + return ret; + } else { + return 0; + } +} + +// Enable POST buffer for the server in given slot +int +pal_post_enable(uint8_t slot) { + int ret; + int i; + bic_config_t config = {0}; + bic_config_u *t = (bic_config_u *) &config; + + ret = bic_get_config(slot, &config); + if (ret) { + syslog(LOG_ALERT, "post_enable: bic_get_config failed\n"); + return ret; + } + + t->bits.post = 1; + + ret = bic_set_config(slot, &config); + if (ret) { + syslog(LOG_ALERT, "post_enable: bic_set_config failed\n"); + return ret; + } + + return 0; +} + +// Disable POST buffer for the server in given slot +int +pal_post_disable(uint8_t slot) { + int ret; + int i; + bic_config_t config = {0}; + bic_config_u *t = (bic_config_u *) &config; + + ret = bic_get_config(slot, &config); + if (ret) { + return ret; + } + + t->bits.post = 0; + + ret = bic_set_config(slot, &config); + if (ret) { + return ret; + } + + return 0; +} + +// Get the last post code of the given slot +int +pal_post_get_last(uint8_t slot, uint8_t *status) { + int ret; + uint8_t buf[MAX_IPMB_RES_LEN] = {0x0}; + uint8_t len; + int i; + + ret = bic_get_post_buf(slot, buf, &len); + if (ret) { + return ret; + } + + // The post buffer is LIFO and the first byte gives the latest post code + *status = buf[0]; + + return 0; +} + +// Handle the received post code, for now display it on debug card +int +pal_post_handle(uint8_t slot, uint8_t status) { + uint8_t prsnt, pos; + int ret; + + // Check for debug card presence + ret = pal_is_debug_card_prsnt(&prsnt); + if (ret) { + return ret; + } + + // No debug card present, return + if (!prsnt) { + return 0; + } + + // Get the hand switch position + ret = pal_get_hand_sw(&pos); + if (ret) { + return ret; + } + + // If the give server is not selected, return + if (pos != slot) { + return 0; + } + + // Display the post code in the debug card + ret = pal_post_display(status); + if (ret) { + return ret; + } + + return 0; +} + + +static int +read_kv(char *key, char *value) { + + FILE *fp; + int rc; + + fp = fopen(key, "r"); + if (!fp) { + int err = errno; + syslog(LOG_ALERT, "read_kv: failed to open %s", key); + return err; + } + + rc = (int) fread(value, 1, MAX_VALUE_LEN, fp); + fclose(fp); + if (rc <= 0) { + syslog(LOG_INFO, "read_kv: failed to read %s", key); + return ENOENT; + } else { + return 0; + } +} + +static int +write_kv(char *key, char *value) { + + FILE *fp; + int rc; + + fp = fopen(key, "w"); + if (!fp) { + int err = errno; + syslog(LOG_ALERT, "write_kv: failed to open %s", key); + return err; + } + + rc = fwrite(value, 1, strlen(value), fp); + fclose(fp); + + if (rc < 0) { + syslog(LOG_ALERT, "write_kv: failed to write to %s", key); + return ENOENT; + } else { + return 0; + } +} + +int +pal_get_fru_id(char *str, uint8_t *fru) { + + return yosemite_common_fru_id(str, fru); +} + +int +pal_get_fru_sensor_list(uint8_t fru, uint8_t **sensor_list, int *cnt) { + + switch(fru) { + case FRU_SLOT1: + case FRU_SLOT2: + case FRU_SLOT3: + case FRU_SLOT4: + *sensor_list = (uint8_t *) bic_sensor_list; + *cnt = bic_sensor_cnt; + break; + case FRU_SPB: + *sensor_list = (uint8_t *) spb_sensor_list; + *cnt = spb_sensor_cnt; + break; + case FRU_NIC: + *sensor_list = NULL; // (uint8_t *) nic_sensor_list; + *cnt = 0; //nic_sensor_cnt; + break; + default: + syslog(LOG_ALERT, "pal_get_fru_sensor_list: Wrong fru id %u", fru); + return -1; + } + return 0; +} + +int +pal_sensor_read(uint8_t fru, uint8_t sensor_num, void *value) { + return yosemite_sensor_read(fru, sensor_num, value); +} + +int +pal_get_sensor_name(uint8_t fru, uint8_t sensor_num, char *name) { + return yosemite_sensor_name(fru, sensor_num, name); +} + +int +pal_get_sensor_units(uint8_t fru, uint8_t sensor_num, char *units) { + return yosemite_sensor_units(fru, sensor_num, units); +} + +int +pal_get_fruid_path(uint8_t fru, char *path) { + return yosemite_get_fruid_path(fru, path); +} + +int +pal_get_fruid_name(uint8_t fru, char *name) { + return yosemite_get_fruid_name(fru, name); +} + + +static int +get_key_value(char* key, char *value) { + + char kpath[64] = {0}; + + sprintf(kpath, KV_STORE, key); + + if (access(KV_STORE_PATH, F_OK) == -1) { + mkdir(KV_STORE_PATH, 0777); + } + + return read_kv(kpath, value); +} + +static int +set_key_value(char *key, char *value) { + + char kpath[64] = {0}; + + sprintf(kpath, KV_STORE, key); + + if (access(KV_STORE_PATH, F_OK) == -1) { + mkdir(KV_STORE_PATH, 0777); + } + + return write_kv(kpath, value); +} + +int +pal_get_key_value(char *key, char *value) { + + int ret; + int i; + + i = 0; + while(strcmp(key_list[i], LAST_KEY)) { + + if (!strcmp(key, key_list[i])) { + // Key is valid + if ((ret = get_key_value(key, value)) < 0 ) { + syslog(LOG_ALERT, "pal_get_key_value: get_key_value failed. %d", ret); + return ret; + } + return ret; + } + i++; + } + + return -1; +} + +int +pal_set_key_value(char *key, char *value) { + + int ret; + int i; + + i = 0; + while(strcmp(key_list[i], LAST_KEY)) { + + if (!strcmp(key, key_list[i])) { + // Key is valid + if ((ret = set_key_value(key, value)) < 0) { + syslog(LOG_ALERT, "pal_set_key_value: set_key_value failed. %d", ret); + printf("pal_set_key_value: ret = %d\n", ret); + return ret; + } + return ret; + } + i++; + } + + return -1; +} + +int +pal_get_fru_devtty(uint8_t fru, char *devtty) { + + switch(fru) { + case FRU_SLOT1: + sprintf(devtty, "/dev/ttyS2"); + break; + case FRU_SLOT2: + sprintf(devtty, "/dev/ttyS1"); + break; + case FRU_SLOT3: + sprintf(devtty, "/dev/ttyS4"); + break; + case FRU_SLOT4: + sprintf(devtty, "/dev/ttyS3"); + break; + default: + syslog(LOG_ALERT, "pal_get_fru_devtty: Wrong fru id %u", fru); + return -1; + } + return 0; +} + +void +pal_dump_key_value(void) { + int i; + int ret; + + char value[MAX_VALUE_LEN] = {0x0}; + + while (strcmp(key_list[i], LAST_KEY)) { + printf("%s:", key_list[i]); + if (ret = get_key_value(key_list[i], value) < 0) { + printf("\n"); + } else { + printf("%s\n", value); + } + i++; + memset(value, 0, MAX_VALUE_LEN); + } +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/pal/pal.h b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/pal/pal.h new file mode 100644 index 0000000..1d9f3b9 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/pal/pal.h @@ -0,0 +1,98 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __PAL_H__ +#define __PAL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <facebook/bic.h> +#include <facebook/yosemite_common.h> +#include <facebook/yosemite_fruid.h> +#include <facebook/yosemite_sensor.h> + +#define MAX_NUM_FRUS 6 +#define MAX_KEY_LEN 64 +#define MAX_VALUE_LEN 64 + +#define KV_STORE "/mnt/data/kv_store/%s" +#define KV_STORE_PATH "/mnt/data/kv_store" + +extern char * key_list[]; +extern const char pal_fru_list[]; +extern const char pal_server_list[]; + +enum { + LED_STATE_OFF, + LED_STATE_ON, +}; + +enum { + SERVER_POWER_OFF, + SERVER_POWER_ON, + SERVER_POWER_CYCLE, + SERVER_GRACEFUL_SHUTDOWN, +}; + +enum { + HAND_SW_SERVER1 = 1, + HAND_SW_SERVER2, + HAND_SW_SERVER3, + HAND_SW_SERVER4, + HAND_SW_BMC +}; + +int pal_get_platform_name(char *name); +int pal_get_num_slots(uint8_t *num); +int pal_is_server_prsnt(uint8_t slot_id, uint8_t *status); +int pal_get_server_power(uint8_t slot_id, uint8_t *status); +int pal_set_server_power(uint8_t slot_id, uint8_t cmd); +int pal_sled_cycle(void); +int pal_is_debug_card_prsnt(uint8_t *status); +int pal_get_hand_sw(uint8_t *pos); +int pal_switch_usb_mux(uint8_t slot); +int pal_switch_uart_mux(uint8_t slot); +int pal_post_enable(uint8_t slot); +int pal_post_disable(uint8_t slot); +int pal_post_get_last(uint8_t slot, uint8_t *post); +int pal_post_handle(uint8_t slot, uint8_t status); +int pal_get_pwr_btn(uint8_t *status); +int pal_get_rst_btn(uint8_t *status); +int pal_set_rst_btn(uint8_t slot, uint8_t status); +int pal_set_led(uint8_t slot, uint8_t status); +int pal_get_fru_id(char *fru_str, uint8_t *fru); +int pal_get_fruid_path(uint8_t fru, char *path); +int pal_get_fruid_name(uint8_t fru, char *name); +int pal_get_sensor_units(uint8_t fru, uint8_t sensor_num, char *units); +int pal_get_fru_sensor_list(uint8_t fru, uint8_t **sensor_list, int *cnt); +int pal_sensor_read(uint8_t fru, uint8_t sensor_num, void *value); +int pal_get_sensor_name(uint8_t fru, uint8_t sensor_num, char *name); +int pal_get_key_value(char *key, char *value); +int pal_set_key_value(char *key, char *value); +void pal_dump_key_value(void); +int pal_get_fru_devtty(uint8_t fru, char *devtty); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __PAL_H__ */ diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_common/Makefile b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_common/Makefile new file mode 100644 index 0000000..76bf61f --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_common/Makefile @@ -0,0 +1,11 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +lib: libyosemite_common.so + +libyosemite_common.so: yosemite_common.c + $(CC) $(CFLAGS) -fPIC -c -o yosemite_common.o yosemite_common.c + $(CC) -shared -o libyosemite_common.so yosemite_common.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libyosemite_common.so diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_common/yosemite_common.c b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_common/yosemite_common.c new file mode 100644 index 0000000..e41690f --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_common/yosemite_common.c @@ -0,0 +1,55 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * This file contains code to support IPMI2.0 Specificaton available @ + * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include <math.h> +#include <fcntl.h> +#include <errno.h> +#include <syslog.h> +#include "yosemite_common.h" + +int +yosemite_common_fru_id(char *str, uint8_t *fru) { + + if (!strcmp(str, "all")) { + *fru = FRU_ALL; + } else if (!strcmp(str, "slot1")) { + *fru = FRU_SLOT1; + } else if (!strcmp(str, "slot2")) { + *fru = FRU_SLOT2; + } else if (!strcmp(str, "slot3")) { + *fru = FRU_SLOT3; + } else if (!strcmp(str, "slot4")) { + *fru = FRU_SLOT4; + } else if (!strcmp(str, "spb")) { + *fru = FRU_SPB; + } else if (!strcmp(str, "nic")) { + *fru = FRU_NIC; + } else { + syslog(LOG_ALERT, "yosemite_common_fru_id: Wrong fru id"); + return -1; + } + + return 0; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_common/yosemite_common.h b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_common/yosemite_common.h new file mode 100644 index 0000000..85d8638 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_common/yosemite_common.h @@ -0,0 +1,44 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __YOSEMITE_COMMON_H__ +#define __YOSEMITE_COMMON_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + FRU_ALL = 0, + FRU_SLOT1 = 1, + FRU_SLOT2 = 2, + FRU_SLOT3 = 3, + FRU_SLOT4 = 4, + FRU_SPB = 5, + FRU_NIC = 6, +}; + +int yosemite_common_fru_id(char *str, uint8_t *fru); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __YOSEMITE_COMMON_H__ */ diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_fruid/Makefile b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_fruid/Makefile new file mode 100644 index 0000000..eda01dc --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_fruid/Makefile @@ -0,0 +1,27 @@ +# 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 + +lib: libyosemite_fruid.so + +libyosemite_fruid.so: yosemite_fruid.c + $(CC) $(CFLAGS) -fPIC -c -o yosemite_fruid.o yosemite_fruid.c + $(CC) -lyosemite_common -shared -o libyosemite_fruid.so yosemite_fruid.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libyosemite_fruid.so diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_fruid/yosemite_fruid.c b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_fruid/yosemite_fruid.c new file mode 100644 index 0000000..226f2f8 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_fruid/yosemite_fruid.c @@ -0,0 +1,86 @@ +/* Copyright 2015-present Facebook. All Rights Reserved. + * + * This file contains code to support IPMI2.0 Specificaton available @ + * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <syslog.h> +#include "yosemite_fruid.h" + +/* Populate char path[] with the path to the fru's fruid binary dump */ +int +yosemite_get_fruid_path(uint8_t fru, char *path) { + char fname[16] = {0}; + + switch(fru) { + case FRU_SLOT1: + sprintf(fname, "slot1"); + break; + case FRU_SLOT2: + sprintf(fname, "slot2"); + break; + case FRU_SLOT3: + sprintf(fname, "slot3"); + break; + case FRU_SLOT4: + sprintf(fname, "slot4"); + break; + case FRU_SPB: + sprintf(fname, "spb"); + break; + case FRU_NIC: + sprintf(fname, "nic"); + break; + default: + syslog(LOG_ALERT, "yosemite_get_fruid_path: wrong fruid"); + return -1; + } + + sprintf(path, YOSEMITE_FRU_PATH, fname); + return 0; +} +/* Populate char name[] with the path to the fru's name */ +int +yosemite_get_fruid_name(uint8_t fru, char *name) { + + switch(fru) { + case FRU_SLOT1: + sprintf(name, "MonoLake Board 1"); + break; + case FRU_SLOT2: + sprintf(name, "MonoLake Board 2"); + break; + case FRU_SLOT3: + sprintf(name, "MonoLake Board 3"); + break; + case FRU_SLOT4: + sprintf(name, "MonoLake Board 4"); + break; + case FRU_SPB: + sprintf(name, "Side Plane Board"); + break; + case FRU_NIC: + sprintf(name, "CX4 NIC"); + break; + default: + syslog(LOG_ALERT, "yosemite_get_fruid_name: wrong fruid"); + return -1; + } + return 0; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_fruid/yosemite_fruid.h b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_fruid/yosemite_fruid.h new file mode 100644 index 0000000..5c01267 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_fruid/yosemite_fruid.h @@ -0,0 +1,37 @@ +/* Copyright 2015-present Facebook. All Rights Reserved. + * + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __YOSEMITE_FRUID_H__ +#define __YOSEMITE_FRUID_H__ + +#include <facebook/yosemite_common.h> + +#define YOSEMITE_FRU_PATH "/tmp/fruid_%s.bin" + +#ifdef __cplusplus +extern "C" { +#endif + +int yosemite_get_fruid_path(uint8_t fru, char *path); +int yosemite_get_fruid_name(uint8_t fru, char *name); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __YOSEMITE_FRUID_H__ */ diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_gpio/Makefile b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_gpio/Makefile new file mode 100644 index 0000000..66c0005 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_gpio/Makefile @@ -0,0 +1,27 @@ +# 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 + +lib: libyosemite_gpio.so + +libyosemite_gpio.so: yosemite_gpio.c + $(CC) $(CFLAGS) -fPIC -c -o yosemite_gpio.o yosemite_gpio.c + $(CC) -shared -o libyosemite_gpio.so yosemite_gpio.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libyosemite_gpio.so diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_gpio/yosemite_gpio.c b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_gpio/yosemite_gpio.c new file mode 100644 index 0000000..ac2c820 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_gpio/yosemite_gpio.c @@ -0,0 +1,116 @@ +/* Copyright 2015-present Facebook. All Rights Reserved. + * + * This file contains code to support IPMI2.0 Specificaton available @ + * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <syslog.h> +#include "yosemite_gpio.h" + +// List of GPIO pins to be monitored +const uint8_t gpio_pin_list[] = { + PWRGOOD_CPU, + PWRGD_PCH_PWROK, + PVDDR_VRHOT_N, + PVCCIN_VRHOT_N, + FM_FAST_PROCHOT_N, + PCHHOT_CPU_N, + FM_CPLD_CPU_DIMM_EVENT_CO_N, + FM_CPLD_BDXDE_THERMTRIP_N, + THERMTRIP_PCH_N, + FM_CPLD_FIVR_FAULT, + FM_BDXDE_CATERR_LVT3_N, + FM_BDXDE_ERR2_LVT3_N, + FM_BDXDE_ERR1_LVT3_N, + FM_BDXDE_ERR0_LVT3_N, + //SLP_S4_N, + FM_NMI_EVENT_BMC_N, + FM_SMI_BMC_N, + RST_PLTRST_BMC_N, + FP_RST_BTN_BUF_N, + BMC_RST_BTN_OUT_N, + FM_BDE_POST_CMPLT_N, + //FM_BDXDE_SLP3_N, + //FM_PWR_LED_N, + PWRGD_PVCCIN, + //SVR_ID0, + //SVR_ID1, + //SVR_ID2, + //SVR_ID3, + //BMC_READY_N, + //RESERVED_29, + //RESERVED_30, + //RESERVED_31, +}; + +size_t gpio_pin_cnt = sizeof(gpio_pin_list)/sizeof(uint8_t); +const uint32_t gpio_ass_val = 0x0 | (1 << FM_CPLD_FIVR_FAULT); + +const char *gpio_pin_name[] = { + "PWRGOOD_CPU", + "PWRGD_PCH_PWROK", + "PVDDR_VRHOT_N", + "PVCCIN_VRHOT_N", + "FM_FAST_PROCHOT_N", + "PCHHOT_CPU_N", + "FM_CPLD_CPU_DIMM_EVENT_CO_N", + "FM_CPLD_BDXDE_THERMTRIP_N", + "THERMTRIP_PCH_N", + "FM_CPLD_FIVR_FAULT", + "FM_BDXDE_CATERR_LVT3_N", + "FM_BDXDE_ERR2_LVT3_N", + "FM_BDXDE_ERR1_LVT3_N", + "FM_BDXDE_ERR0_LVT3_N", + "SLP_S4_N", + "FM_NMI_EVENT_BMC_N", + "FM_SMI_BMC_N", + "RST_PLTRST_BMC_N", + "FP_RST_BTN_BUF_N", + "BMC_RST_BTN_OUT_N", + "FM_BDE_POST_CMPLT_N", + "FM_BDXDE_SLP3_N", + "FM_PWR_LED_N", + "PWRGD_PVCCIN", + "SVR_ID0", + "SVR_ID1", + "SVR_ID2", + "SVR_ID3", + "BMC_READY_N", + "RESERVED_29", + "RESERVED_30", + "RESERVED_31" +}; + +int +yosemite_get_gpio_name(uint8_t fru, uint8_t gpio, char *name) { + + //TODO: Add support for BMC GPIO pins + if (fru < 1 || fru > 4) { + syslog(LOG_ALERT, "yosemite_get_gpio_name: Wrong fru %u", fru); + return -1; + } + + if (gpio < 0 || gpio > MAX_GPIO_PINS) { + syslog(LOG_ALERT, "yosemite_get_gpio_name: Wrong gpio pin %u", gpio); + return -1; + } + + sprintf(name, "%s", gpio_pin_name[gpio]); + return 0; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_gpio/yosemite_gpio.h b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_gpio/yosemite_gpio.h new file mode 100644 index 0000000..77808a8 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_gpio/yosemite_gpio.h @@ -0,0 +1,39 @@ +/* Copyright 2015-present Facebook. All Rights Reserved. + * + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __YOSEMITE_GPIO_H__ +#define __YOSEMITE_GPIO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <facebook/bic.h> + +extern const uint8_t gpio_pin_list[]; +extern const char *gpio_pin_name[]; +extern const uint32_t gpio_ass_val; +extern size_t gpio_pin_cnt; + +int yosemite_get_gpio_name(uint8_t fru, uint8_t gpio, char *name); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __YOSEMITE_GPIO_H__ */ diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_sensor/Makefile b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_sensor/Makefile new file mode 100644 index 0000000..63b334c --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_sensor/Makefile @@ -0,0 +1,11 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +lib: libyosemite_sensor.so + +libyosemite_sensor.so: yosemite_sensor.c + $(CC) $(CFLAGS) -fPIC -c -o yosemite_sensor.o yosemite_sensor.c + $(CC) -lm -lbic -lsdr -lipmi -lipmb -lyosemite_common -shared -o libyosemite_sensor.so yosemite_sensor.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libyosemite_sensor.so diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_sensor/yosemite_sensor.c b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_sensor/yosemite_sensor.c new file mode 100644 index 0000000..0f25e54 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_sensor/yosemite_sensor.c @@ -0,0 +1,778 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * This file contains code to support IPMI2.0 Specificaton available @ + * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include <math.h> +#include <fcntl.h> +#include <errno.h> +#include <syslog.h> +#include "yosemite_sensor.h" + +#define LARGEST_DEVICE_NAME 120 + +#define GPIO_VAL "/sys/class/gpio/gpio%d/value" + +#define I2C_BUS_9_DIR "/sys/class/i2c-adapter/i2c-9/" +#define I2C_BUS_10_DIR "/sys/class/i2c-adapter/i2c-10/" + +#define TACH_DIR "/sys/devices/platform/ast_pwm_tacho.0" +#define ADC_DIR "/sys/devices/platform/ast_adc.0" + +#define SP_INLET_TEMP_DEVICE I2C_BUS_9_DIR "9-004e" +#define SP_OUTLET_TEMP_DEVICE I2C_BUS_9_DIR "9-004f" +#define HSC_DEVICE I2C_BUS_10_DIR "10-0040" + +#define FAN_TACH_RPM "tacho%d_rpm" +#define ADC_VALUE "adc%d_value" +#define HSC_IN_VOLT "in1_input" +#define HSC_OUT_CURR "curr1_input" +#define HSC_TEMP "temp1_input" + +#define UNIT_DIV 1000 + +#define BIC_SENSOR_READ_NA 0x20 + +#define MAX_SENSOR_NUM 0xFF +#define ALL_BYTES 0xFF +#define LAST_REC_ID 0xFFFF + +#define YOSEMITE_SDR_PATH "/tmp/sdr_%s.bin" + +// List of BIC sensors to be monitored +const uint8_t bic_sensor_list[] = { + /* Threshold sensors */ + BIC_SENSOR_MB_OUTLET_TEMP, + BIC_SENSOR_VCCIN_VR_TEMP, + BIC_SENSOR_VCC_GBE_VR_TEMP, + BIC_SENSOR_1V05PCH_VR_TEMP, + BIC_SENSOR_SOC_TEMP, + BIC_SENSOR_MB_INLET_TEMP, + BIC_SENSOR_PCH_TEMP, + BIC_SENSOR_SOC_THERM_MARGIN, + BIC_SENSOR_VDDR_VR_TEMP, + BIC_SENSOR_VCC_GBE_VR_CURR, + BIC_SENSOR_1V05_PCH_VR_CURR, + BIC_SENSOR_VCCIN_VR_POUT, + BIC_SENSOR_VCCIN_VR_CURR, + BIC_SENSOR_VCCIN_VR_VOL, + BIC_SENSOR_INA230_POWER, + BIC_SENSOR_SOC_PACKAGE_PWR, + BIC_SENSOR_SOC_TJMAX, + BIC_SENSOR_VDDR_VR_POUT, + BIC_SENSOR_VDDR_VR_CURR, + BIC_SENSOR_VDDR_VR_VOL, + BIC_SENSOR_VCC_SCSUS_VR_CURR, + BIC_SENSOR_VCC_SCSUS_VR_VOL, + BIC_SENSOR_VCC_SCSUS_VR_TEMP, + BIC_SENSOR_VCC_SCSUS_VR_POUT, + BIC_SENSOR_VCC_GBE_VR_POUT, + BIC_SENSOR_VCC_GBE_VR_VOL, + BIC_SENSOR_1V05_PCH_VR_VOL, + BIC_SENSOR_SOC_DIMMA0_TEMP, + BIC_SENSOR_SOC_DIMMA1_TEMP, + BIC_SENSOR_SOC_DIMMB0_TEMP, + BIC_SENSOR_SOC_DIMMB1_TEMP, + BIC_SENSOR_P3V3_MB, + BIC_SENSOR_P12V_MB, + BIC_SENSOR_P1V05_PCH, + BIC_SENSOR_P3V3_STBY_MB, + BIC_SENSOR_P5V_STBY_MB, + BIC_SENSOR_PV_BAT, + BIC_SENSOR_PVDDR, + BIC_SENSOR_PVCC_GBE, + /* Discrete sensors */ + //BIC_SENSOR_SYSTEM_STATUS, + //BIC_SENSOR_SYS_BOOT_STAT, + //BIC_SENSOR_CPU_DIMM_HOT, + //BIC_SENSOR_PROC_FAIL, + //BIC_SENSOR_VR_HOT, + /* Event-only sensors */ + //BIC_SENSOR_POST_ERR, + //BIC_SENSOR_SPS_FW_HLTH, + //BIC_SENSOR_POWER_THRESH_EVENT, + //BIC_SENSOR_MACHINE_CHK_ERR, + //BIC_SENSOR_PCIE_ERR, + //BIC_SENSOR_OTHER_IIO_ERR, + //BIC_SENSOR_PROC_HOT_EXT, + //BIC_SENSOR_POWER_ERR, + //BIC_SENSOR_CAT_ERR, +}; + +// List of SPB sensors to be monitored +const uint8_t spb_sensor_list[] = { + SP_SENSOR_INLET_TEMP, + SP_SENSOR_OUTLET_TEMP, + //SP_SENSOR_MEZZ_TEMP + SP_SENSOR_FAN0_TACH, + SP_SENSOR_FAN1_TACH, + //SP_SENSOR_AIR_FLOW, + SP_SENSOR_P5V, + SP_SENSOR_P12V, + SP_SENSOR_P3V3_STBY, + SP_SENSOR_P12V_SLOT0, + SP_SENSOR_P12V_SLOT1, + SP_SENSOR_P12V_SLOT2, + SP_SENSOR_P12V_SLOT3, + SP_SENSOR_P3V3, + SP_SENSOR_HSC_IN_VOLT, + SP_SENSOR_HSC_OUT_CURR, + SP_SENSOR_HSC_TEMP, + SP_SENSOR_HSC_IN_POWER, +}; + +size_t bic_sensor_cnt = sizeof(bic_sensor_list)/sizeof(uint8_t); + +size_t spb_sensor_cnt = sizeof(spb_sensor_list)/sizeof(uint8_t); + +enum { + FAN0 = 0, + FAN1, +}; + +enum { + ADC_PIN0 = 0, + ADC_PIN1, + ADC_PIN2, + ADC_PIN3, + ADC_PIN4, + ADC_PIN5, + ADC_PIN6, + ADC_PIN7, +}; + +static sensor_info_t g_sinfo1[MAX_SENSOR_NUM] = {0}; +static sensor_info_t g_sinfo2[MAX_SENSOR_NUM] = {0}; +static sensor_info_t g_sinfo3[MAX_SENSOR_NUM] = {0}; +static sensor_info_t g_sinfo4[MAX_SENSOR_NUM] = {0}; +static sensor_info_t g_sinfo_spb[MAX_SENSOR_NUM] = {0}; +static sensor_info_t g_sinfo_nic[MAX_SENSOR_NUM] = {0}; + +static int +read_device(const char *device, int *value) { + FILE *fp; + int rc; + + fp = fopen(device, "r"); + if (!fp) { + int err = errno; + + syslog(LOG_INFO, "failed to open device %s", device); + return err; + } + + rc = fscanf(fp, "%d", value); + fclose(fp); + + if (rc != 1) { + syslog(LOG_INFO, "failed to read device %s", device); + return ENOENT; + } else { + return 0; + } +} + +static int +read_device_float(const char *device, float *value) { + FILE *fp; + int rc; + char tmp[10]; + + fp = fopen(device, "r"); + if (!fp) { + int err = errno; + + syslog(LOG_INFO, "failed to open device %s", device); + return err; + } + + rc = fscanf(fp, "%s", tmp); + fclose(fp); + + if (rc != 1) { + syslog(LOG_INFO, "failed to read device %s", device); + return ENOENT; + } + + *value = atof(tmp); + + return 0; +} + +static int +read_temp(const char *device, float *value) { + char full_name[LARGEST_DEVICE_NAME + 1]; + int tmp; + + snprintf( + full_name, LARGEST_DEVICE_NAME, "%s/temp1_input", device); + if (read_device(full_name, &tmp)) { + return -1; + } + + *value = ((float)tmp)/UNIT_DIV; + + return 0; +} + +static int +read_fan_value(const int fan, const char *device, float *value) { + char device_name[LARGEST_DEVICE_NAME]; + char full_name[LARGEST_DEVICE_NAME]; + + snprintf(device_name, LARGEST_DEVICE_NAME, device, fan); + snprintf(full_name, LARGEST_DEVICE_NAME, "%s/%s", TACH_DIR, device_name); + return read_device_float(full_name, value); +} + +static int +read_adc_value(const int pin, const char *device, float *value) { + char device_name[LARGEST_DEVICE_NAME]; + char full_name[LARGEST_DEVICE_NAME]; + + snprintf(device_name, LARGEST_DEVICE_NAME, device, pin); + snprintf(full_name, LARGEST_DEVICE_NAME, "%s/%s", ADC_DIR, device_name); + return read_device_float(full_name, value); +} + +static int +read_hsc_value(const char *device, float *value) { + char full_name[LARGEST_DEVICE_NAME]; + int tmp; + + snprintf(full_name, LARGEST_DEVICE_NAME, "%s/%s", HSC_DEVICE, device); + if(read_device(full_name, &tmp)) { + return -1; + } + + *value = ((float) tmp)/UNIT_DIV; + + return 0; +} + +static int +bic_read_sensor_wrapper(uint8_t slot_id, uint8_t sensor_num, void *value) { + int ret; + ipmi_sensor_reading_t sensor; + + ret = bic_read_sensor(slot_id, sensor_num, &sensor); + if (ret) { + return ret; + } + + if (sensor.flags & BIC_SENSOR_READ_NA) { + syslog(LOG_ERR, "bic_read_sensor_wrapper: Reading Not Available"); + syslog(LOG_ERR, "bic_read_sensor_wrapper: sensor_num: 0x%X, flag: 0x%X", + sensor_num, sensor.flags); + return -1; + } + + if (sensor.status) { + //printf("bic_read_sensor_wrapper: Status Asserted: 0x%X\n", sensor.status); + } + + // Check SDR to convert raw value to actual + sdr_full_t *sdr; + + switch (slot_id) { + case 1: + sdr = &g_sinfo1[sensor_num].sdr; + break; + case 2: + sdr = &g_sinfo2[sensor_num].sdr; + break; + case 3: + sdr = &g_sinfo3[sensor_num].sdr; + break; + case 4: + sdr = &g_sinfo4[sensor_num].sdr; + break; + default: + syslog(LOG_ALERT, "bic_read_sensor_wrapper: Wrong Slot ID\n"); + return -1; + } + + // If the SDR is not type1, no need for conversion + if (sdr->type !=1) { + *(float *) value = sensor.value; + return 0; + } + + // y = (mx + b * 10^b_exp) * 10^r_exp + uint8_t x; + uint8_t m_lsb, m_msb, m; + uint8_t b_lsb, b_msb, b; + int8_t b_exp, r_exp; + + x = sensor.value; + + m_lsb = sdr->m_val; + m_msb = sdr->m_tolerance >> 6; + m = (m_msb << 8) | m_lsb; + + b_lsb = sdr->b_val; + b_msb = sdr->b_accuracy >> 6; + b = (b_msb << 8) | b_lsb; + + // exponents are 2's complement 4-bit number + b_exp = sdr->rb_exp & 0xF; + if (b_exp > 7) { + b_exp = (~b_exp + 1) & 0xF; + b_exp = -b_exp; + } + r_exp = (sdr->rb_exp >> 4) & 0xF; + if (r_exp > 7) { + r_exp = (~r_exp + 1) & 0xF; + r_exp = -r_exp; + } + + //printf("m:%d, x:%d, b:%d, b_exp:%d, r_exp:%d\n", m, x, b, b_exp, r_exp); + + * (float *) value = ((m * x) + (b * pow(10, b_exp))) * (pow(10, r_exp)); + + return 0; +} + +/* Returns the all the SDRs for the particular fru# */ +static sensor_info_t * +get_struct_sensor_info(uint8_t fru) { + sensor_info_t *sinfo; + switch(fru) { + case FRU_SLOT1: + sinfo = g_sinfo1; + break; + case FRU_SLOT2: + sinfo = g_sinfo2; + break; + case FRU_SLOT3: + sinfo = g_sinfo3; + break; + case FRU_SLOT4: + sinfo = g_sinfo4; + break; + case FRU_SPB: + sinfo = g_sinfo_spb; + break; + case FRU_NIC: + sinfo = g_sinfo_nic; + break; + default: + syslog(LOG_ALERT, "yosemite_sdr_init: Wrong Slot ID\n"); + return NULL; + } + return sinfo; +} + +int +get_fru_sdr_path(uint8_t fru, char *path) { + + char fru_name[16] = {0}; + + switch(fru) { + case FRU_SLOT1: + sprintf(fru_name, "%s", "slot1"); + break; + case FRU_SLOT2: + sprintf(fru_name, "%s", "slot2"); + break; + case FRU_SLOT3: + sprintf(fru_name, "%s", "slot3"); + break; + case FRU_SLOT4: + sprintf(fru_name, "%s", "slot4"); + break; + case FRU_SPB: + sprintf(fru_name, "%s", "spb"); + break; + case FRU_NIC: + sprintf(fru_name, "%s", "nic"); + break; + default: + syslog(LOG_ALERT, "yosemite_sdr_init: Wrong Slot ID\n"); + return -1; + } + + sprintf(path, YOSEMITE_SDR_PATH, fru_name); + + return 0; +} + +static int +yosemite_sdr_init(uint8_t fru) { + int fd; + uint8_t buf[MAX_SDR_LEN] = {0}; + uint8_t bytes_rd = 0; + uint8_t sn = 0; + char path[64] = {0}; + sensor_info_t *sinfo; + + if (get_fru_sdr_path(fru, path) < 0) { + syslog(LOG_ALERT, "yosemite_sdr_init: get_fru_sdr_path failed\n"); + return -1; + } + sinfo = get_struct_sensor_info(fru); + if (sinfo == NULL) { + syslog(LOG_ALERT, "yosemite_sdr_init: get_struct_sensor_info failed\n"); + return -1; + } + + if (sdr_init(path, sinfo) < 0) { + syslog(LOG_ERR, "yosemite_sdr_init: sdr_init failed for FRU %d", fru); + } + + return 0; +} + +static bool +is_server_prsnt(uint8_t slot_id) { + uint8_t gpio; + int val; + char path[64] = {0}; + + switch(slot_id) { + case 1: + gpio = 61; + break; + case 2: + gpio = 60; + break; + case 3: + gpio = 63; + break; + case 4: + gpio = 62; + break; + default: + return 0; + } + + sprintf(path, GPIO_VAL, gpio); + + if (read_device(path, &val)) { + return -1; + } + + if (val == 0x0) { + return 1; + } else { + return 0; + } +} + +/* Get the units for the sensor */ +int +yosemite_sensor_units(uint8_t fru, uint8_t sensor_num, char *units) { + static bool init_done = false; + uint8_t op, modifier; + sensor_info_t *sinfo; + + if (!init_done) { + + if (is_server_prsnt(1) && (yosemite_sdr_init(FRU_SLOT1) != 0)) { + return -1; + } + if (is_server_prsnt(2) && (yosemite_sdr_init(FRU_SLOT2) != 0)) { + return -1; + } + if (is_server_prsnt(3) && (yosemite_sdr_init(FRU_SLOT3) != 0)) { + return -1; + } + if (is_server_prsnt(4) && (yosemite_sdr_init(FRU_SLOT4) != 0)) { + return -1; + } + init_done = true; + } + + switch(fru) { + case FRU_SLOT1: + case FRU_SLOT2: + case FRU_SLOT3: + case FRU_SLOT4: + sinfo = get_struct_sensor_info(fru); + if (sinfo == NULL) { + syslog(LOG_ALERT, "yosemite_sensor_units: get_struct_sensor_info failed\n"); + return -1; + } + + if (sdr_get_sensor_units(&sinfo[sensor_num].sdr, &op, &modifier, units)) { + syslog(LOG_ALERT, "yosemite_sensor_units: FRU %d: num 0x%2X: reading units" + " from SDR failed.", fru, sensor_num); + return -1; + } + break; + case FRU_SPB: + switch(sensor_num) { + case SP_SENSOR_INLET_TEMP: + sprintf(units, "C"); + break; + case SP_SENSOR_OUTLET_TEMP: + sprintf(units, "C"); + break; + case SP_SENSOR_MEZZ_TEMP: + sprintf(units, "C"); + break; + case SP_SENSOR_FAN0_TACH: + sprintf(units, "RPM"); + break; + case SP_SENSOR_FAN1_TACH: + sprintf(units, "RPM"); + break; + case SP_SENSOR_AIR_FLOW: + sprintf(units, ""); + break; + case SP_SENSOR_P5V: + sprintf(units, "Volts"); + break; + case SP_SENSOR_P12V: + sprintf(units, "Volts"); + break; + case SP_SENSOR_P3V3_STBY: + sprintf(units, "Volts"); + break; + case SP_SENSOR_P12V_SLOT0: + sprintf(units, "Volts"); + break; + case SP_SENSOR_P12V_SLOT1: + sprintf(units, "Volts"); + break; + case SP_SENSOR_P12V_SLOT2: + sprintf(units, "Volts"); + break; + case SP_SENSOR_P12V_SLOT3: + sprintf(units, "Volts"); + break; + case SP_SENSOR_P3V3: + sprintf(units, "Volts"); + break; + case SP_SENSOR_HSC_IN_VOLT: + sprintf(units, "Volts"); + break; + case SP_SENSOR_HSC_OUT_CURR: + sprintf(units, "Amps"); + break; + case SP_SENSOR_HSC_TEMP: + sprintf(units, "C"); + break; + case SP_SENSOR_HSC_IN_POWER: + sprintf(units, "Watts"); + break; + } + break; + case FRU_NIC: + sprintf(units, ""); + break; + } + return 0; +} + +/* Get the name for the sensor */ +int +yosemite_sensor_name(uint8_t fru, uint8_t sensor_num, char *name) { + static bool init_done = false; + uint8_t op, modifier; + sensor_info_t *sinfo; + + if (!init_done) { + + if (is_server_prsnt(1) && (yosemite_sdr_init(FRU_SLOT1) != 0)) { + return -1; + } + if (is_server_prsnt(2) && (yosemite_sdr_init(FRU_SLOT2) != 0)) { + return -1; + } + if (is_server_prsnt(3) && (yosemite_sdr_init(FRU_SLOT3) != 0)) { + return -1; + } + if (is_server_prsnt(4) && (yosemite_sdr_init(FRU_SLOT4) != 0)) { + return -1; + } + init_done = true; + } + + switch(fru) { + case FRU_SLOT1: + case FRU_SLOT2: + case FRU_SLOT3: + case FRU_SLOT4: + sinfo = get_struct_sensor_info(fru); + if (sinfo == NULL) { + syslog(LOG_ALERT, "yosemite_sensor_name: get_struct_sensor_info failed\n"); + return -1; + } + + if (sdr_get_sensor_name(&sinfo[sensor_num].sdr, name)) { + syslog(LOG_ALERT, "yosemite_sensor_name: FRU %d: num 0x%2X: reading units" + " from SDR failed.", fru, sensor_num); + return -1; + } + + break; + case FRU_SPB: + switch(sensor_num) { + case SP_SENSOR_INLET_TEMP: + sprintf(name, "SP_SENSOR_INLET_TEMP"); + break; + case SP_SENSOR_OUTLET_TEMP: + sprintf(name, "SP_SENSOR_OUTLET_TEMP"); + break; + case SP_SENSOR_MEZZ_TEMP: + sprintf(name, "SP_SENSOR_MEZZ_TEMP"); + break; + case SP_SENSOR_FAN0_TACH: + sprintf(name, "SP_SENSOR_FAN0_TACH"); + break; + case SP_SENSOR_FAN1_TACH: + sprintf(name, "SP_SENSOR_FAN1_TACH"); + break; + case SP_SENSOR_AIR_FLOW: + sprintf(name, "SP_SENSOR_AIR_FLOW"); + break; + case SP_SENSOR_P5V: + sprintf(name, "SP_SENSOR_P5V"); + break; + case SP_SENSOR_P12V: + sprintf(name, "SP_SENSOR_P12V"); + break; + case SP_SENSOR_P3V3_STBY: + sprintf(name, "SP_SENSOR_P3V3_STBY"); + break; + case SP_SENSOR_P12V_SLOT0: + sprintf(name, "SP_SENSOR_P12V_SLOT0"); + break; + case SP_SENSOR_P12V_SLOT1: + sprintf(name, "SP_SENSOR_P12V_SLOT1"); + break; + case SP_SENSOR_P12V_SLOT2: + sprintf(name, "SP_SENSOR_P12V_SLOT2"); + break; + case SP_SENSOR_P12V_SLOT3: + sprintf(name, "SP_SENSOR_P12V_SLOT3"); + break; + case SP_SENSOR_P3V3: + sprintf(name, "SP_SENSOR_P3V3"); + break; + case SP_SENSOR_HSC_IN_VOLT: + sprintf(name, "SP_SENSOR_HSC_IN_VOLT"); + break; + case SP_SENSOR_HSC_OUT_CURR: + sprintf(name, "SP_SENSOR_HSC_OUT_CURR"); + break; + case SP_SENSOR_HSC_TEMP: + sprintf(name, "SP_SENSOR_HSC_TEMP"); + break; + case SP_SENSOR_HSC_IN_POWER: + sprintf(name, "SP_SENSOR_HSC_IN_POWER"); + break; + } + break; + case FRU_NIC: + sprintf(name, ""); + break; + } + return 0; +} + + +int +yosemite_sensor_read(uint8_t slot_id, uint8_t sensor_num, void *value) { + static bool init_done = false; + float volt; + float curr; + + if (!init_done) { + + if (is_server_prsnt(1) && (yosemite_sdr_init(FRU_SLOT1) != 0)) { + return -1; + } + + if (is_server_prsnt(2) && (yosemite_sdr_init(FRU_SLOT2) != 0)) { + return -1; + } + + if (is_server_prsnt(3) && (yosemite_sdr_init(FRU_SLOT3) != 0)) { + return -1; + } + + if (is_server_prsnt(4) && (yosemite_sdr_init(FRU_SLOT4) != 0)) { + return -1; + } + + init_done = true; + } + + switch(sensor_num) { + // Inlet, Outlet Temp + + case SP_SENSOR_INLET_TEMP: + return read_temp(SP_INLET_TEMP_DEVICE, (float*) value); + case SP_SENSOR_OUTLET_TEMP: + return read_temp(SP_OUTLET_TEMP_DEVICE, (float*) value); + + // Fan Tach Values + case SP_SENSOR_FAN0_TACH: + return read_fan_value(FAN0, FAN_TACH_RPM, (float*) value); + case SP_SENSOR_FAN1_TACH: + return read_fan_value(FAN1, FAN_TACH_RPM, (float*) value); + + // Various Voltages + case SP_SENSOR_P5V: + return read_adc_value(ADC_PIN0, ADC_VALUE, (float*) value); + case SP_SENSOR_P12V: + return read_adc_value(ADC_PIN1, ADC_VALUE, (float*) value); + case SP_SENSOR_P3V3_STBY: + return read_adc_value(ADC_PIN2, ADC_VALUE, (float*) value); + case SP_SENSOR_P12V_SLOT0: + return read_adc_value(ADC_PIN3, ADC_VALUE, (float*) value); + case SP_SENSOR_P12V_SLOT1: + return read_adc_value(ADC_PIN4, ADC_VALUE, (float*) value); + case SP_SENSOR_P12V_SLOT2: + return read_adc_value(ADC_PIN5, ADC_VALUE, (float*) value); + case SP_SENSOR_P12V_SLOT3: + return read_adc_value(ADC_PIN6, ADC_VALUE, (float*) value); + case SP_SENSOR_P3V3: + return read_adc_value(ADC_PIN7, ADC_VALUE, (float*) value); + + // Hot Swap Controller + case SP_SENSOR_HSC_IN_VOLT: + return read_hsc_value(HSC_IN_VOLT, (float*) value); + case SP_SENSOR_HSC_OUT_CURR: + return read_hsc_value(HSC_OUT_CURR, (float*) value); + case SP_SENSOR_HSC_TEMP: + return read_hsc_value(HSC_TEMP, (float*) value); + case SP_SENSOR_HSC_IN_POWER: + if (read_hsc_value(HSC_IN_VOLT, &volt)) { + return -1; + } + + if (read_hsc_value(HSC_OUT_CURR, &curr)) { + return -1; + } + + * (float*) value = volt * curr; + return 0; + default: + // For all others we assume the sensors are on Monolake + return bic_read_sensor_wrapper(slot_id, sensor_num, value); + } +} + diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_sensor/yosemite_sensor.h b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_sensor/yosemite_sensor.h new file mode 100644 index 0000000..0a33173 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_sensor/yosemite_sensor.h @@ -0,0 +1,133 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __YOSEMITE_SENSOR_H__ +#define __YOSEMITE_SENSOR_H__ + +#include <stdbool.h> +#include <openbmc/ipmi.h> +#include <openbmc/ipmb.h> +#include <openbmc/sdr.h> +#include <facebook/bic.h> +#include <facebook/yosemite_common.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// Sensors under Bridge IC +enum { + BIC_SENSOR_MB_OUTLET_TEMP = 0x01, + BIC_SENSOR_VCCIN_VR_TEMP = 0x02, + BIC_SENSOR_VCC_GBE_VR_TEMP = 0x03, + BIC_SENSOR_1V05PCH_VR_TEMP = 0x04, + BIC_SENSOR_SOC_TEMP = 0x05, + BIC_SENSOR_MB_INLET_TEMP = 0x07, + BIC_SENSOR_PCH_TEMP = 0x08, + BIC_SENSOR_SOC_THERM_MARGIN = 0x09, + BIC_SENSOR_VDDR_VR_TEMP = 0x0B, + BIC_SENSOR_SYSTEM_STATUS = 0x10, //Discrete + BIC_SENSOR_SPS_FW_HLTH = 0x17, //Event-only + BIC_SENSOR_VCC_GBE_VR_CURR = 0x20, + BIC_SENSOR_1V05_PCH_VR_CURR = 0x21, + BIC_SENSOR_VCCIN_VR_POUT = 0x22, + BIC_SENSOR_VCCIN_VR_CURR = 0x23, + BIC_SENSOR_VCCIN_VR_VOL = 0x24, + BIC_SENSOR_INA230_POWER = 0x29, + BIC_SENSOR_POST_ERR = 0x2B, //Event-only + BIC_SENSOR_SOC_PACKAGE_PWR = 0x2C, + BIC_SENSOR_SOC_TJMAX = 0x30, + BIC_SENSOR_VDDR_VR_POUT = 0x32, + BIC_SENSOR_VDDR_VR_CURR = 0x33, + BIC_SENSOR_VDDR_VR_VOL = 0x34, + BIC_SENSOR_VCC_SCSUS_VR_CURR = 0x35, + BIC_SENSOR_VCC_SCSUS_VR_VOL = 0x36, + BIC_SENSOR_VCC_SCSUS_VR_TEMP = 0x37, + BIC_SENSOR_VCC_SCSUS_VR_POUT = 0x38, + BIC_SENSOR_VCC_GBE_VR_POUT = 0x39, + BIC_SENSOR_POWER_THRESH_EVENT = 0x3B, //Event-only + //BIC_SENSOR_1V05_PCH_VR_POUT = 0x40, + BIC_SENSOR_MACHINE_CHK_ERR = 0x40, //Event-only + BIC_SENSOR_PCIE_ERR = 0x41, //Event-only + BIC_SENSOR_OTHER_IIO_ERR = 0x43, //Event-only + BIC_SENSOR_PROC_HOT_EXT = 0x51, //Event-only + BIC_SENSOR_VCC_GBE_VR_VOL = 0x54, + BIC_SENSOR_1V05_PCH_VR_VOL = 0x55, + BIC_SENSOR_POWER_ERR = 0x56, //Event-only + BIC_SENSOR_MEM_ECC_ERR = 0x63, //Event-only + BIC_SENSOR_PROC_FAIL = 0x65, //Discrete + BIC_SENSOR_SYS_BOOT_STAT = 0x7E, //Discrete + BIC_SENSOR_VR_HOT = 0xB2, //Discrete + BIC_SENSOR_CPU_DIMM_HOT = 0xB3, //Discrete + BIC_SENSOR_SOC_DIMMA0_TEMP = 0xB4, + BIC_SENSOR_SOC_DIMMA1_TEMP = 0xB5, + BIC_SENSOR_SOC_DIMMB0_TEMP = 0xB6, + BIC_SENSOR_SOC_DIMMB1_TEMP = 0xB7, + BIC_SENSOR_P3V3_MB = 0xD0, + BIC_SENSOR_P12V_MB = 0xD2, + BIC_SENSOR_P1V05_PCH = 0xD3, + BIC_SENSOR_P3V3_STBY_MB = 0xD5, + BIC_SENSOR_P5V_STBY_MB = 0xD6, + BIC_SENSOR_PV_BAT = 0xD7, + BIC_SENSOR_PVDDR = 0xD8, + BIC_SENSOR_PVCC_GBE = 0xD9, + BIC_SENSOR_CAT_ERR = 0xEB, //Event-only +}; + +// Sensors Under Side Plane +enum { + SP_SENSOR_INLET_TEMP = 0x81, + SP_SENSOR_OUTLET_TEMP = 0x80, + SP_SENSOR_MEZZ_TEMP = 0x82, + SP_SENSOR_FAN0_TACH = 0x46, + SP_SENSOR_FAN1_TACH = 0x47, + SP_SENSOR_AIR_FLOW = 0x4A, + SP_SENSOR_P5V = 0xE0, + SP_SENSOR_P12V = 0xE1, + SP_SENSOR_P3V3_STBY = 0xE2, + SP_SENSOR_P12V_SLOT0 = 0xE3, + SP_SENSOR_P12V_SLOT1 = 0xE4, + SP_SENSOR_P12V_SLOT2 = 0xE5, + SP_SENSOR_P12V_SLOT3 = 0xE6, + SP_SENSOR_P3V3 = 0xE7, + SP_SENSOR_HSC_IN_VOLT = 0xC0, + SP_SENSOR_HSC_OUT_CURR = 0xC1, + SP_SENSOR_HSC_TEMP = 0xC2, + SP_SENSOR_HSC_IN_POWER = 0xC3, +}; + +extern const uint8_t bic_sensor_list[]; + +extern const uint8_t spb_sensor_list[]; + +extern size_t bic_sensor_cnt; + +extern size_t spb_sensor_cnt; + +int yosemite_sensor_read(uint8_t slot_id, uint8_t sensor_num, void *value); +int yosemite_sensor_name(uint8_t fru, uint8_t sensor_num, char *name); +int yosemite_sensor_units(uint8_t fru, uint8_t sensor_num, char *units); +int get_fru_sdr_path(uint8_t fru, char *path); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __YOSEMITE_SENSOR_H__ */ |