meta-facebook/meta-fbtp/recipes-fbtp/plat-libs/files/vr/vr.c (1,507 lines of code) (raw):
/*
*
* Copyright 2017-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 <fcntl.h>
#include <errno.h>
#include <syslog.h>
#include <sys/mman.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <openbmc/obmc-i2c.h>
#include <openbmc/kv.h>
#include "vr.h"
#define VR_BUS_ID 0x5
#define VR_FW_PAGE 0x2f
#define VR_FW_PAGE_2 0x6F
#define VR_FW_PAGE_3 0x4F
#define VR_FW_REG1 0xC
#define VR_FW_REG2 0xD
#define VR_FW_REG3 0x3D
#define VR_FW_REG4 0x3E
#define VR_FW_REG5 0x32
#define VR_TELEMETRY_VOLT 0x1A
#define VR_TELEMETRY_CURR 0x15
#define VR_TELEMETRY_POWER 0x2D
#define VR_TELEMETRY_TEMP 0x29
#define DATA_START_ADDR 18
#define VR_UPDATE_IN_PROGRESS "/tmp/stop_monitor_vr"
#define MAX_VR_CHIPS 9
#define VR_TIMEOUT 500
#define MAX_READ_RETRY 10
#define MAX_NEGATIVE_RETRY 3
#define READING_SKIP 1
#define BIT(value, index) ((value >> index) & 1)
// VR status bit
#define VR_STS_OV_FAULT (1 << 5)
#define VR_STS_OC_FAULT (1 << 4)
#define VR_STS_TEMP_FAULT (1 << 2)
#define VR_STS_FAULT (VR_STS_OV_FAULT | VR_STS_OC_FAULT | VR_STS_TEMP_FAULT)
//Used identify VR Chip info. there are 4 vr fw code in EVT3 and after
enum
{
SS_Fairchild = 0x0,
SS_IFX = 0x1,
DS_Fairchild = 0x2,
DS_IFX = 0x3,
UNKNOWN_TYPE = 0xff,
};
//VR Chip info
typedef struct
{
uint8_t SlaveAddr;
uint8_t CRC[4];
int DataLength;
int IndexStartAddr;
int IndexEndAddr;
} VRBasicInfo;
#define VR_BIT0(Din, Dout) ((Din >> 0) ^ (Din >> 6) ^ (Din >> 9) ^ (Din >> 10) ^ (Din >> 12) ^ (Din >> 16) ^ (Din >> 24) ^ (Din >> 25) ^ (Din >> 26) ^ (Din >> 28) ^ (Din >> 29) ^ (Din >> 30) ^ (Din >> 31) ^ (Dout >> 0) ^ (Dout >> 6) ^ (Dout >> 9) ^ (Dout >> 10) ^ (Dout >> 12) ^ (Dout >> 16) ^ (Dout >> 24) ^ (Dout >> 25) ^ (Dout >> 26) ^ (Dout >> 28) ^ (Dout >> 29) ^ (Dout >> 30) ^ (Dout >> 31))
#define VR_BIT1(Din, Dout) ((Din >> 0) ^ (Din >> 1) ^ (Din >> 6) ^ (Din >> 7) ^ (Din >> 9) ^ (Din >> 11) ^ (Din >> 12) ^ (Din >> 13) ^ (Din >> 16) ^ (Din >> 17) ^ (Din >> 24) ^ (Din >> 27) ^ (Din >> 28) ^ (Dout >> 0) ^ (Dout >> 1) ^ (Dout >> 6) ^ (Dout >> 7) ^ (Dout >> 9) ^ (Dout >> 11) ^ (Dout >> 12) ^ (Dout >> 13) ^ (Dout >> 16) ^ (Dout >> 17) ^ (Dout >> 24) ^ (Dout >> 27) ^ (Dout >> 28))
#define VR_BIT2(Din, Dout) ((Din >> 0) ^ (Din >> 1) ^ (Din >> 2) ^ (Din >> 6) ^ (Din >> 7) ^ (Din >> 8) ^ (Din >> 9) ^ (Din >> 13) ^ (Din >> 14) ^ (Din >> 16) ^ (Din >> 17) ^ (Din >> 18) ^ (Din >> 24) ^ (Din >> 26) ^ (Din >> 30) ^ (Din >> 31) ^ (Dout >> 0) ^ (Dout >> 1) ^ (Dout >> 2) ^ (Dout >> 6) ^ (Dout >> 7) ^ (Dout >> 8) ^ (Dout >> 9) ^ (Dout >> 13) ^ (Dout >> 14) ^ (Dout >> 16) ^ (Dout >> 17) ^ (Dout >> 18) ^ (Dout >> 24) ^ (Dout >> 26) ^ (Dout >> 30) ^ (Dout >> 31))
#define VR_BIT3(Din, Dout) ((Din >> 1) ^ (Din >> 2) ^ (Din >> 3) ^ (Din >> 7) ^ (Din >> 8) ^ (Din >> 9) ^ (Din >> 10) ^ (Din >> 14) ^ (Din >> 15) ^ (Din >> 17) ^ (Din >> 18) ^ (Din >> 19) ^ (Din >> 25) ^ (Din >> 27) ^ (Din >> 31) ^ (Dout >> 1) ^ (Dout >> 2) ^ (Dout >> 3) ^ (Dout >> 7) ^ (Dout >> 8) ^ (Dout >> 9) ^ (Dout >> 10) ^ (Dout >> 14) ^ (Dout >> 15) ^ (Dout >> 17) ^ (Dout >> 18) ^ (Dout >> 19) ^ (Dout >> 25) ^ (Dout >> 27) ^ (Dout >> 31))
#define VR_BIT4(Din, Dout) ((Din >> 0) ^ (Din >> 2) ^ (Din >> 3) ^ (Din >> 4) ^ (Din >> 6) ^ (Din >> 8) ^ (Din >> 11) ^ (Din >> 12) ^ (Din >> 15) ^ (Din >> 18) ^ (Din >> 19) ^ (Din >> 20) ^ (Din >> 24) ^ (Din >> 25) ^ (Din >> 29) ^ (Din >> 30) ^ (Din >> 31) ^ (Dout >> 0) ^ (Dout >> 2) ^ (Dout >> 3) ^ (Dout >> 4) ^ (Dout >> 6) ^ (Dout >> 8) ^ (Dout >> 11) ^ (Dout >> 12) ^ (Dout >> 15) ^ (Dout >> 18) ^ (Dout >> 19) ^ (Dout >> 20) ^ (Dout >> 24) ^ (Dout >> 25) ^ (Dout >> 29) ^ (Dout >> 30) ^ (Dout >> 31))
#define VR_BIT5(Din, Dout) ((Din >> 0) ^ (Din >> 1) ^ (Din >> 3) ^ (Din >> 4) ^ (Din >> 5) ^ (Din >> 6) ^ (Din >> 7) ^ (Din >> 10) ^ (Din >> 13) ^ (Din >> 19) ^ (Din >> 20) ^ (Din >> 21) ^ (Din >> 24) ^ (Din >> 28) ^ (Din >> 29) ^ (Dout >> 0) ^ (Dout >> 1) ^ (Dout >> 3) ^ (Dout >> 4) ^ (Dout >> 5) ^ (Dout >> 6) ^ (Dout >> 7) ^ (Dout >> 10) ^ (Dout >> 13) ^ (Dout >> 19) ^ (Dout >> 20) ^ (Dout >> 21) ^ (Dout >> 24) ^ (Dout >> 28) ^ (Dout >> 29))
#define VR_BIT6(Din, Dout) ((Din >> 1) ^ (Din >> 2) ^ (Din >> 4) ^ (Din >> 5) ^ (Din >> 6) ^ (Din >> 7) ^ (Din >> 8) ^ (Din >> 11) ^ (Din >> 14) ^ (Din >> 20) ^ (Din >> 21) ^ (Din >> 22) ^ (Din >> 25) ^ (Din >> 29) ^ (Din >> 30) ^ (Dout >> 1) ^ (Dout >> 2) ^ (Dout >> 4) ^ (Dout >> 5) ^ (Dout >> 6) ^ (Dout >> 7) ^ (Dout >> 8) ^ (Dout >> 11) ^ (Dout >> 14) ^ (Dout >> 20) ^ (Dout >> 21) ^ (Dout >> 22) ^ (Dout >> 25) ^ (Dout >> 29) ^ (Dout >> 30))
#define VR_BIT7(Din, Dout) ((Din >> 0) ^ (Din >> 2) ^ (Din >> 3) ^ (Din >> 5) ^ (Din >> 7) ^ (Din >> 8) ^ (Din >> 10) ^ (Din >> 15) ^ (Din >> 16) ^ (Din >> 21) ^ (Din >> 22) ^ (Din >> 23) ^ (Din >> 24) ^ (Din >> 25) ^ (Din >> 28) ^ (Din >> 29) ^ (Dout >> 0) ^ (Dout >> 2) ^ (Dout >> 3) ^ (Dout >> 5) ^ (Dout >> 7) ^ (Dout >> 8) ^ (Dout >> 10) ^ (Dout >> 15) ^ (Dout >> 16) ^ (Dout >> 21) ^ (Dout >> 22) ^ (Dout >> 23) ^ (Dout >> 24) ^ (Dout >> 25) ^ (Dout >> 28) ^ (Dout >> 29))
#define VR_BIT8(Din, Dout) ((Din >> 0) ^ (Din >> 1) ^ (Din >> 3) ^ (Din >> 4) ^ (Din >> 8) ^ (Din >> 10) ^ (Din >> 11) ^ (Din >> 12) ^ (Din >> 17) ^ (Din >> 22) ^ (Din >> 23) ^ (Din >> 28) ^ (Din >> 31) ^ (Dout >> 0) ^ (Dout >> 1) ^ (Dout >> 3) ^ (Dout >> 4) ^ (Dout >> 8) ^ (Dout >> 10) ^ (Dout >> 11) ^ (Dout >> 12) ^ (Dout >> 17) ^ (Dout >> 22) ^ (Dout >> 23) ^ (Dout >> 28) ^ (Dout >> 31))
#define VR_BIT9(Din, Dout) ((Din >> 1) ^ (Din >> 2) ^ (Din >> 4) ^ (Din >> 5) ^ (Din >> 9) ^ (Din >> 11) ^ (Din >> 12) ^ (Din >> 13) ^ (Din >> 18) ^ (Din >> 23) ^ (Din >> 24) ^ (Din >> 29) ^ (Dout >> 1) ^ (Dout >> 2) ^ (Dout >> 4) ^ (Dout >> 5) ^ (Dout >> 9) ^ (Dout >> 11) ^ (Dout >> 12) ^ (Dout >> 13) ^ (Dout >> 18) ^ (Dout >> 23) ^ (Dout >> 24) ^ (Dout >> 29))
#define VR_BIT10(Din, Dout) ((Din >> 0) ^ (Din >> 2) ^ (Din >> 3) ^ (Din >> 5) ^ (Din >> 9) ^ (Din >> 13) ^ (Din >> 14) ^ (Din >> 16) ^ (Din >> 19) ^ (Din >> 26) ^ (Din >> 28) ^ (Din >> 29) ^ (Din >> 31) ^ (Dout >> 0) ^ (Dout >> 2) ^ (Dout >> 3) ^ (Dout >> 5) ^ (Dout >> 9) ^ (Dout >> 13) ^ (Dout >> 14) ^ (Dout >> 16) ^ (Dout >> 19) ^ (Dout >> 26) ^ (Dout >> 28) ^ (Dout >> 29) ^ (Dout >> 31))
#define VR_BIT11(Din, Dout) ((Din >> 0) ^ (Din >> 1) ^ (Din >> 3) ^ (Din >> 4) ^ (Din >> 9) ^ (Din >> 12) ^ (Din >> 14) ^ (Din >> 15) ^ (Din >> 16) ^ (Din >> 17) ^ (Din >> 20) ^ (Din >> 24) ^ (Din >> 25) ^ (Din >> 26) ^ (Din >> 27) ^ (Din >> 28) ^ (Din >> 31) ^ (Dout >> 0) ^ (Dout >> 1) ^ (Dout >> 3) ^ (Dout >> 4) ^ (Dout >> 9) ^ (Dout >> 12) ^ (Dout >> 14) ^ (Dout >> 15) ^ (Dout >> 16) ^ (Dout >> 17) ^ (Dout >> 20) ^ (Dout >> 24) ^ (Dout >> 25) ^ (Dout >> 26) ^ (Dout >> 27) ^ (Dout >> 28) ^ (Dout >> 31))
#define VR_BIT12(Din, Dout) ((Din >> 0) ^ (Din >> 1) ^ (Din >> 2) ^ (Din >> 4) ^ (Din >> 5) ^ (Din >> 6) ^ (Din >> 9) ^ (Din >> 12) ^ (Din >> 13) ^ (Din >> 15) ^ (Din >> 17) ^ (Din >> 18) ^ (Din >> 21) ^ (Din >> 24) ^ (Din >> 27) ^ (Din >> 30) ^ (Din >> 31) ^ (Dout >> 0) ^ (Dout >> 1) ^ (Dout >> 2) ^ (Dout >> 4) ^ (Dout >> 5) ^ (Dout >> 6) ^ (Dout >> 9) ^ (Dout >> 12) ^ (Dout >> 13) ^ (Dout >> 15) ^ (Dout >> 17) ^ (Dout >> 18) ^ (Dout >> 21) ^ (Dout >> 24) ^ (Dout >> 27) ^ (Dout >> 30) ^ (Dout >> 31))
#define VR_BIT13(Din, Dout) ((Din >> 1) ^ (Din >> 2) ^ (Din >> 3) ^ (Din >> 5) ^ (Din >> 6) ^ (Din >> 7) ^ (Din >> 10) ^ (Din >> 13) ^ (Din >> 14) ^ (Din >> 16) ^ (Din >> 18) ^ (Din >> 19) ^ (Din >> 22) ^ (Din >> 25) ^ (Din >> 28) ^ (Din >> 31) ^ (Dout >> 1) ^ (Dout >> 2) ^ (Dout >> 3) ^ (Dout >> 5) ^ (Dout >> 6) ^ (Dout >> 7) ^ (Dout >> 10) ^ (Dout >> 13) ^ (Dout >> 14) ^ (Dout >> 16) ^ (Dout >> 18) ^ (Dout >> 19) ^ (Dout >> 22) ^ (Dout >> 25) ^ (Dout >> 28) ^ (Dout >> 31))
#define VR_BIT14(Din, Dout) ((Din >> 2) ^ (Din >> 3) ^ (Din >> 4) ^ (Din >> 6) ^ (Din >> 7) ^ (Din >> 8) ^ (Din >> 11) ^ (Din >> 14) ^ (Din >> 15) ^ (Din >> 17) ^ (Din >> 19) ^ (Din >> 20) ^ (Din >> 23) ^ (Din >> 26) ^ (Din >> 29) ^ (Dout >> 2) ^ (Dout >> 3) ^ (Dout >> 4) ^ (Dout >> 6) ^ (Dout >> 7) ^ (Dout >> 8) ^ (Dout >> 11) ^ (Dout >> 14) ^ (Dout >> 15) ^ (Dout >> 17) ^ (Dout >> 19) ^ (Dout >> 20) ^ (Dout >> 23) ^ (Dout >> 26) ^ (Dout >> 29))
#define VR_BIT15(Din, Dout) ((Din >> 3) ^ (Din >> 4) ^ (Din >> 5) ^ (Din >> 7) ^ (Din >> 8) ^ (Din >> 9) ^ (Din >> 12) ^ (Din >> 15) ^ (Din >> 16) ^ (Din >> 18) ^ (Din >> 20) ^ (Din >> 21) ^ (Din >> 24) ^ (Din >> 27) ^ (Din >> 30) ^ (Dout >> 3) ^ (Dout >> 4) ^ (Dout >> 5) ^ (Dout >> 7) ^ (Dout >> 8) ^ (Dout >> 9) ^ (Dout >> 12) ^ (Dout >> 15) ^ (Dout >> 16) ^ (Dout >> 18) ^ (Dout >> 20) ^ (Dout >> 21) ^ (Dout >> 24) ^ (Dout >> 27) ^ (Dout >> 30))
#define VR_BIT16(Din, Dout) ((Din >> 0) ^ (Din >> 4) ^ (Din >> 5) ^ (Din >> 8) ^ (Din >> 12) ^ (Din >> 13) ^ (Din >> 17) ^ (Din >> 19) ^ (Din >> 21) ^ (Din >> 22) ^ (Din >> 24) ^ (Din >> 26) ^ (Din >> 29) ^ (Din >> 30) ^ (Dout >> 0) ^ (Dout >> 4) ^ (Dout >> 5) ^ (Dout >> 8) ^ (Dout >> 12) ^ (Dout >> 13) ^ (Dout >> 17) ^ (Dout >> 19) ^ (Dout >> 21) ^ (Dout >> 22) ^ (Dout >> 24) ^ (Dout >> 26) ^ (Dout >> 29) ^ (Dout >> 30))
#define VR_BIT17(Din, Dout) ((Din >> 1) ^ (Din >> 5) ^ (Din >> 6) ^ (Din >> 9) ^ (Din >> 13) ^ (Din >> 14) ^ (Din >> 18) ^ (Din >> 20) ^ (Din >> 22) ^ (Din >> 23) ^ (Din >> 25) ^ (Din >> 27) ^ (Din >> 30) ^ (Din >> 31) ^ (Dout >> 1) ^ (Dout >> 5) ^ (Dout >> 6) ^ (Dout >> 9) ^ (Dout >> 13) ^ (Dout >> 14) ^ (Dout >> 18) ^ (Dout >> 20) ^ (Dout >> 22) ^ (Dout >> 23) ^ (Dout >> 25) ^ (Dout >> 27) ^ (Dout >> 30) ^ (Dout >> 31))
#define VR_BIT18(Din, Dout) ((Din >> 2) ^ (Din >> 6) ^ (Din >> 7) ^ (Din >> 10) ^ (Din >> 14) ^ (Din >> 15) ^ (Din >> 19) ^ (Din >> 21) ^ (Din >> 23) ^ (Din >> 24) ^ (Din >> 26) ^ (Din >> 28) ^ (Din >> 31) ^ (Dout >> 2) ^ (Dout >> 6) ^ (Dout >> 7) ^ (Dout >> 10) ^ (Dout >> 14) ^ (Dout >> 15) ^ (Dout >> 19) ^ (Dout >> 21) ^ (Dout >> 23) ^ (Dout >> 24) ^ (Dout >> 26) ^ (Dout >> 28) ^ (Dout >> 31))
#define VR_BIT19(Din, Dout) ((Din >> 3) ^ (Din >> 7) ^ (Din >> 8) ^ (Din >> 11) ^ (Din >> 15) ^ (Din >> 16) ^ (Din >> 20) ^ (Din >> 22) ^ (Din >> 24) ^ (Din >> 25) ^ (Din >> 27) ^ (Din >> 29) ^ (Dout >> 3) ^ (Dout >> 7) ^ (Dout >> 8) ^ (Dout >> 11) ^ (Dout >> 15) ^ (Dout >> 16) ^ (Dout >> 20) ^ (Dout >> 22) ^ (Dout >> 24) ^ (Dout >> 25) ^ (Dout >> 27) ^ (Dout >> 29))
#define VR_BIT20(Din, Dout) ((Din >> 4) ^ (Din >> 8) ^ (Din >> 9) ^ (Din >> 12) ^ (Din >> 16) ^ (Din >> 17) ^ (Din >> 21) ^ (Din >> 23) ^ (Din >> 25) ^ (Din >> 26) ^ (Din >> 28) ^ (Din >> 30) ^ (Dout >> 4) ^ (Dout >> 8) ^ (Dout >> 9) ^ (Dout >> 12) ^ (Dout >> 16) ^ (Dout >> 17) ^ (Dout >> 21) ^ (Dout >> 23) ^ (Dout >> 25) ^ (Dout >> 26) ^ (Dout >> 28) ^ (Dout >> 30))
#define VR_BIT21(Din, Dout) ((Din >> 5) ^ (Din >> 9) ^ (Din >> 10) ^ (Din >> 13) ^ (Din >> 17) ^ (Din >> 18) ^ (Din >> 22) ^ (Din >> 24) ^ (Din >> 26) ^ (Din >> 27) ^ (Din >> 29) ^ (Din >> 31) ^ (Dout >> 5) ^ (Dout >> 9) ^ (Dout >> 10) ^ (Dout >> 13) ^ (Dout >> 17) ^ (Dout >> 18) ^ (Dout >> 22) ^ (Dout >> 24) ^ (Dout >> 26) ^ (Dout >> 27) ^ (Dout >> 29) ^ (Dout >> 31))
#define VR_BIT22(Din, Dout) ((Din >> 0) ^ (Din >> 9) ^ (Din >> 11) ^ (Din >> 12) ^ (Din >> 14) ^ (Din >> 16) ^ (Din >> 18) ^ (Din >> 19) ^ (Din >> 23) ^ (Din >> 24) ^ (Din >> 26) ^ (Din >> 27) ^ (Din >> 29) ^ (Din >> 31) ^ (Dout >> 0) ^ (Dout >> 9) ^ (Dout >> 11) ^ (Dout >> 12) ^ (Dout >> 14) ^ (Dout >> 16) ^ (Dout >> 18) ^ (Dout >> 19) ^ (Dout >> 23) ^ (Dout >> 24) ^ (Dout >> 26) ^ (Dout >> 27) ^ (Dout >> 29) ^ (Dout >> 31))
#define VR_BIT23(Din, Dout) ((Din >> 0) ^ (Din >> 1) ^ (Din >> 6) ^ (Din >> 9) ^ (Din >> 13) ^ (Din >> 15) ^ (Din >> 16) ^ (Din >> 17) ^ (Din >> 19) ^ (Din >> 20) ^ (Din >> 26) ^ (Din >> 27) ^ (Din >> 29) ^ (Din >> 31) ^ (Dout >> 0) ^ (Dout >> 1) ^ (Dout >> 6) ^ (Dout >> 9) ^ (Dout >> 13) ^ (Dout >> 15) ^ (Dout >> 16) ^ (Dout >> 17) ^ (Dout >> 19) ^ (Dout >> 20) ^ (Dout >> 26) ^ (Dout >> 27) ^ (Dout >> 29) ^ (Dout >> 31))
#define VR_BIT24(Din, Dout) ((Din >> 1) ^ (Din >> 2) ^ (Din >> 7) ^ (Din >> 10) ^ (Din >> 14) ^ (Din >> 16) ^ (Din >> 17) ^ (Din >> 18) ^ (Din >> 20) ^ (Din >> 21) ^ (Din >> 27) ^ (Din >> 28) ^ (Din >> 30) ^ (Dout >> 1) ^ (Dout >> 2) ^ (Dout >> 7) ^ (Dout >> 10) ^ (Dout >> 14) ^ (Dout >> 16) ^ (Dout >> 17) ^ (Dout >> 18) ^ (Dout >> 20) ^ (Dout >> 21) ^ (Dout >> 27) ^ (Dout >> 28) ^ (Dout >> 30))
#define VR_BIT25(Din, Dout) ((Din >> 2) ^ (Din >> 3) ^ (Din >> 8) ^ (Din >> 11) ^ (Din >> 15) ^ (Din >> 17) ^ (Din >> 18) ^ (Din >> 19) ^ (Din >> 21) ^ (Din >> 22) ^ (Din >> 28) ^ (Din >> 29) ^ (Din >> 31) ^ (Dout >> 2) ^ (Dout >> 3) ^ (Dout >> 8) ^ (Dout >> 11) ^ (Dout >> 15) ^ (Dout >> 17) ^ (Dout >> 18) ^ (Dout >> 19) ^ (Dout >> 21) ^ (Dout >> 22) ^ (Dout >> 28) ^ (Dout >> 29) ^ (Dout >> 31))
#define VR_BIT26(Din, Dout) ((Din >> 0) ^ (Din >> 3) ^ (Din >> 4) ^ (Din >> 6) ^ (Din >> 10) ^ (Din >> 18) ^ (Din >> 19) ^ (Din >> 20) ^ (Din >> 22) ^ (Din >> 23) ^ (Din >> 24) ^ (Din >> 25) ^ (Din >> 26) ^ (Din >> 28) ^ (Din >> 31) ^ (Dout >> 0) ^ (Dout >> 3) ^ (Dout >> 4) ^ (Dout >> 6) ^ (Dout >> 10) ^ (Dout >> 18) ^ (Dout >> 19) ^ (Dout >> 20) ^ (Dout >> 22) ^ (Dout >> 23) ^ (Dout >> 24) ^ (Dout >> 25) ^ (Dout >> 26) ^ (Dout >> 28) ^ (Dout >> 31))
#define VR_BIT27(Din, Dout) ((Din >> 1) ^ (Din >> 4) ^ (Din >> 5) ^ (Din >> 7) ^ (Din >> 11) ^ (Din >> 19) ^ (Din >> 20) ^ (Din >> 21) ^ (Din >> 23) ^ (Din >> 24) ^ (Din >> 25) ^ (Din >> 26) ^ (Din >> 27) ^ (Din >> 29) ^ (Dout >> 1) ^ (Dout >> 4) ^ (Dout >> 5) ^ (Dout >> 7) ^ (Dout >> 11) ^ (Dout >> 19) ^ (Dout >> 20) ^ (Dout >> 21) ^ (Dout >> 23) ^ (Dout >> 24) ^ (Dout >> 25) ^ (Dout >> 26) ^ (Dout >> 27) ^ (Dout >> 29))
#define VR_BIT28(Din, Dout) ((Din >> 2) ^ (Din >> 5) ^ (Din >> 6) ^ (Din >> 8) ^ (Din >> 12) ^ (Din >> 20) ^ (Din >> 21) ^ (Din >> 22) ^ (Din >> 24) ^ (Din >> 25) ^ (Din >> 26) ^ (Din >> 27) ^ (Din >> 28) ^ (Din >> 30) ^ (Dout >> 2) ^ (Dout >> 5) ^ (Dout >> 6) ^ (Dout >> 8) ^ (Dout >> 12) ^ (Dout >> 20) ^ (Dout >> 21) ^ (Dout >> 22) ^ (Dout >> 24) ^ (Dout >> 25) ^ (Dout >> 26) ^ (Dout >> 27) ^ (Dout >> 28) ^ (Dout >> 30))
#define VR_BIT29(Din, Dout) ((Din >> 3) ^ (Din >> 6) ^ (Din >> 7) ^ (Din >> 9) ^ (Din >> 13) ^ (Din >> 21) ^ (Din >> 22) ^ (Din >> 23) ^ (Din >> 25) ^ (Din >> 26) ^ (Din >> 27) ^ (Din >> 28) ^ (Din >> 29) ^ (Din >> 31) ^ (Dout >> 3) ^ (Dout >> 6) ^ (Dout >> 7) ^ (Dout >> 9) ^ (Dout >> 13) ^ (Dout >> 21) ^ (Dout >> 22) ^ (Dout >> 23) ^ (Dout >> 25) ^ (Dout >> 26) ^ (Dout >> 27) ^ (Dout >> 28) ^ (Dout >> 29) ^ (Dout >> 31))
#define VR_BIT30(Din, Dout) ((Din >> 4) ^ (Din >> 7) ^ (Din >> 8) ^ (Din >> 10) ^ (Din >> 14) ^ (Din >> 22) ^ (Din >> 23) ^ (Din >> 24) ^ (Din >> 26) ^ (Din >> 27) ^ (Din >> 28) ^ (Din >> 29) ^ (Din >> 30) ^ (Dout >> 4) ^ (Dout >> 7) ^ (Dout >> 8) ^ (Dout >> 10) ^ (Dout >> 14) ^ (Dout >> 22) ^ (Dout >> 23) ^ (Dout >> 24) ^ (Dout >> 26) ^ (Dout >> 27) ^ (Dout >> 28) ^ (Dout >> 29) ^ (Dout >> 30))
#define VR_BIT31(Din, Dout) ((Din >> 5) ^ (Din >> 8) ^ (Din >> 9) ^ (Din >> 11) ^ (Din >> 15) ^ (Din >> 23) ^ (Din >> 24) ^ (Din >> 25) ^ (Din >> 27) ^ (Din >> 28) ^ (Din >> 29) ^ (Din >> 30) ^ (Din >> 31) ^ (Dout >> 5) ^ (Dout >> 8) ^ (Dout >> 9) ^ (Dout >> 11) ^ (Dout >> 15) ^ (Dout >> 23) ^ (Dout >> 24) ^ (Dout >> 25) ^ (Dout >> 27) ^ (Dout >> 28) ^ (Dout >> 29) ^ (Dout >> 30) ^ (Dout >> 31))
static void
msleep(int msec) {
struct timespec req;
req.tv_sec = 0;
req.tv_nsec = msec * 1000 * 1000;
while(nanosleep(&req, &req) == -1 && errno == EINTR) {
continue;
}
}
// declare the global i2c bus fd,
// so, bmc no need to open the bus frequently
static int vr_i2c_bus_fd = 0;
static int
vr_get_i2c_bus_fd() {
uint8_t retry = MAX_READ_RETRY;
// already opened it, return fd directly
if ( vr_i2c_bus_fd > 0 ) return vr_i2c_bus_fd;
// try to open the bus-5
while (retry > 0) {
vr_i2c_bus_fd = open("/dev/i2c-5", O_RDWR);
if (vr_i2c_bus_fd < 0) {
syslog(LOG_WARNING, "%s() i2c_open failed for bus#5, err:%s\n", __func__, strerror(errno));
retry--;
msleep(100);
} else {
break;
}
}
if ( retry == 0 ) {
syslog(LOG_WARNING, "%s() retired %d but failing to open bus#5\n", __func__, MAX_READ_RETRY);
}
return vr_i2c_bus_fd;
}
static void
vr_close_i2c_bus_fd() {
if ( vr_i2c_bus_fd > 0 ) {
if ( close(vr_i2c_bus_fd) < 0 ) {
syslog(LOG_WARNING, "%s() i2c_close failed for bus#5, err:%s\n", __func__, strerror(errno));
} else {
// re-init vr_i2c_bus_fd
vr_i2c_bus_fd = 0;
}
}
}
static int
vr_log_p12v_off_event(uint8_t vr, uint8_t sts) {
char event_str[64] = {0};
switch (vr) {
case VR_CPU0_VCCIN:
strcpy(event_str, "CPU0_VCCIN/VSA");
break;
case VR_CPU1_VCCIN:
strcpy(event_str, "CPU1_VCCIN/VSA");
break;
case VR_CPU0_VCCIO:
strcpy(event_str, "CPU0_VCCIO");
break;
case VR_CPU0_VDDQ_ABC:
strcpy(event_str, "CPU0_VDDQ_ABC");
break;
case VR_CPU0_VDDQ_DEF:
strcpy(event_str, "CPU0_VDDQ_DEF");
break;
case VR_CPU1_VCCIO:
strcpy(event_str, "CPU1_VCCIO");
break;
case VR_CPU1_VDDQ_GHJ:
strcpy(event_str, "CPU1_VDDQ_ABC");
break;
case VR_CPU1_VDDQ_KLM:
strcpy(event_str, "CPU1_VDDQ_DEF");
break;
case VR_PCH_PVNN:
strcpy(event_str, "PCH_PVNN");
break;
default:
snprintf(event_str, sizeof(event_str), "VR 0x%x", vr);
break;
}
if ((sts & VR_STS_OV_FAULT) > 0) {
strcat(event_str, ", OV");
}
if ((sts & VR_STS_OC_FAULT) > 0) {
strcat(event_str, ", OC");
}
if ((sts & VR_STS_TEMP_FAULT) > 0 ) {
strcat(event_str, ", OT");
}
strcat(event_str, ", turn off P12V_STBY");
syslog(LOG_CRIT, "%s", event_str);
return 0;
}
int
vr_read_ov_ot_status(uint8_t vr) {
uint8_t tbuf[2] = {0}; // go to the main page
uint8_t rbuf[2] = {0};
uint8_t tcount = 0, rcount = 0;
uint8_t sts = 0x0;
int ret = -1;
int fd = 0;
fd = vr_get_i2c_bus_fd();
if ( fd < 0 ) {
return fd;
}
// Select page 0 and get VR status byte
for (int i = 0; i < 2; i++) {
if ( i == 0 ) {
// Select page 0
tbuf[0] = VR_CMD_PAGE;
tbuf[1] = 0x00; //page 0
tcount = 2;
rcount = 0;
} else {
// Get VR status byte
tbuf[0] = VR_CMD_STATUS_BYTE;
tcount = 1;
rcount = 1;
}
for ( int j = MAX_READ_RETRY; j > 0; j-- ) {
ret = i2c_rdwr_msg_transfer(fd, vr, tbuf, tcount, rbuf, rcount);
if ( ret < 0 ) {
syslog(LOG_WARNING, "%s(): i2c_io failed for bus#%x, dev#%x\n", __func__, VR_BUS_ID, vr);
msleep(100);
} else {
break; /* break 2nd for-loop */
}
} /* end of for-loop j */
if ( ret < 0 ) {
syslog(LOG_WARNING, "%s(): failed to access it, idx#%d, bus#%x, dev#%x\n", __func__, i, VR_BUS_ID, vr);
break; /* break 1st for-loop */
}
} /* end of for-loop i */
if ((ret == 0) && (rcount > 0)) {
// Check if VR have OV, OC, or temperature fault
sts = rbuf[0] & VR_STS_FAULT;
if (sts > 0) {
// record P12V off event
ret = vr_log_p12v_off_event(vr, sts);
if (ret < 0) {
syslog(LOG_WARNING, "%s(): Failed to log vr status\n", __func__);
} else {
ret = VR_GET_OV_OC_OT;
}
}
} else {
syslog(LOG_WARNING, "%s(): Failed to get vr status\n", __func__);
ret = -1;
}
return ret;
}
int
vr_read_volt(uint8_t vr, uint8_t loop, float *value) {
int fd;
static int count = 0;
int ret = -1;
unsigned int retry = MAX_READ_RETRY;
uint8_t tcount, rcount;
uint8_t tbuf[16] = {0};
uint8_t rbuf[16] = {0};
// The following block for detecting vr_update is in progress or not
if ( access(VR_UPDATE_IN_PROGRESS, F_OK) == 0 )
{
//Avoid sensord unmonitoring vr sensors due to unexpected condition happen during vr_update
if ( count > VR_TIMEOUT )
{
remove(VR_UPDATE_IN_PROGRESS);
count = 0;
}
syslog(LOG_WARNING, "[%d]Stop Monitor VR Volt due to VR update is in progress\n", count++);
return VR_STATUS_NOT_AVAILABLE;
}
count = 0;
fd = vr_get_i2c_bus_fd();
if ( fd < 0 ) {
return fd;
}
// Set the page to read Voltage
tbuf[0] = 0x00;
tbuf[1] = loop;
tcount = 2;
rcount = 0;
retry = MAX_READ_RETRY;
while (retry) {
ret = i2c_rdwr_msg_transfer(fd, vr, tbuf, tcount, rbuf, rcount);
if (ret) {
#ifdef DEBUG
syslog(LOG_WARNING, "read_vr_volt: i2c_io failed for bus#%x, dev#%x\n", VR_BUS_ID, vr);
#endif
retry--;
msleep(100);
} else {
break;
}
if(retry == 0)
goto error_exit;
}
// Read 2 bytes from Voltage register
tbuf[0] = VR_TELEMETRY_VOLT;
tcount = 1;
rcount = 2;
retry = MAX_READ_RETRY;
while(retry) {
ret = i2c_rdwr_msg_transfer(fd, vr, tbuf, tcount, rbuf, rcount);
if (ret) {
#ifdef DEBUG
syslog(LOG_WARNING, "read_vr_volt: i2c_io failed for bus#%x, dev#%x\n", VR_BUS_ID, vr);
#endif
retry--;
msleep(100);
} else {
break;
}
if (retry == 0)
goto error_exit;
}
// Calculate Voltage
*value = ((rbuf[1] & 0x0F) * 256 + rbuf[0] ) * 1.25;
*value /= 1000;
error_exit:
return ret;
}
int
vr_read_curr(uint8_t vr, uint8_t loop, float *value) {
int fd;
static int count = 0;
int ret = -1;
unsigned int retry = MAX_READ_RETRY;
uint8_t tcount, rcount;
uint8_t tbuf[16] = {0};
uint8_t rbuf[16] = {0};
// The following block for detecting vr_update is in progress or not
if ( access(VR_UPDATE_IN_PROGRESS, F_OK) == 0 )
{
// Avoid sensord unmonitoring vr sensors due to unexpected condition happen during vr_update
if ( count > VR_TIMEOUT )
{
remove(VR_UPDATE_IN_PROGRESS);
count = 0;
}
syslog(LOG_WARNING, "[%d]Stop Monitor VR Curr due to VR update is in progress\n", count++);
return VR_STATUS_NOT_AVAILABLE;
}
count = 0;
fd = vr_get_i2c_bus_fd();
if ( fd < 0 ) {
return fd;
}
// Set the page to read Voltage
tbuf[0] = 0x00;
tbuf[1] = loop;
tcount = 2;
rcount = 0;
retry = MAX_READ_RETRY;
while(retry) {
ret = i2c_rdwr_msg_transfer(fd, vr, tbuf, tcount, rbuf, rcount);
if (ret) {
#ifdef DEBUG
syslog(LOG_WARNING, "read_vr_curr: i2c_io failed for bus#%x, dev#%x\n", VR_BUS_ID, vr);
#endif
retry--;
msleep(100);
} else {
break;
}
if (retry == 0)
goto error_exit;
}
// Read 2 bytes from Voltage register
tbuf[0] = VR_TELEMETRY_CURR;
tcount = 1;
rcount = 2;
retry = MAX_READ_RETRY;
while(retry) {
ret = i2c_rdwr_msg_transfer(fd, vr, tbuf, tcount, rbuf, rcount);
if (ret) {
#ifdef DEBUG
syslog(LOG_WARNING, "read_vr_curr: i2c_io failed for bus#%x, dev#%x\n", VR_BUS_ID, vr);
#endif
retry--;
msleep(100);
} else {
break;
}
if (retry == 0)
goto error_exit;
}
// Calculate Current
if (rbuf[1] < 0x40) {
// Positive value (sign at bit6)
*value = ((rbuf[1] & 0x7F) * 256 + rbuf[0] ) * 62.5;
*value /= 1000;
} else {
// Negative value 2's complement
uint16_t temp = ((rbuf[1] & 0x7F) << 8) | rbuf[0];
temp = 0x7fff - temp + 1;
*value = (((temp >> 8) & 0x7F) * 256 + (temp & 0xFF) ) * -62.5;
*value /= 1000;
}
// Handle illegal values observed
if ((*value < 0) && (*value >= -1.5)) {
*value = 0;
}
error_exit:
return ret;
}
int
vr_read_power(uint8_t vr, uint8_t loop, float *value) {
int fd;
static int count = 0;
int ret = -1;
unsigned int retry = MAX_READ_RETRY;
uint8_t tcount, rcount;
uint8_t tbuf[16] = {0};
uint8_t rbuf[16] = {0};
// The following block for detecting vr_update is in progress or not
if ( access(VR_UPDATE_IN_PROGRESS, F_OK) == 0 )
{
//avoid sensord unmonitoring vr sensors due to unexpected condition happen during vr_update
if ( count > VR_TIMEOUT )
{
remove(VR_UPDATE_IN_PROGRESS);
count = 0;
}
syslog(LOG_WARNING, "[%d]Stop Monitor VR Power due to VR update is in progress\n", count++);
return VR_STATUS_NOT_AVAILABLE;
}
count = 0;
fd = vr_get_i2c_bus_fd();
if ( fd < 0 ) {
return fd;
}
// Set the page to read Power
tbuf[0] = 0x00;
tbuf[1] = loop;
tcount = 2;
rcount = 0;
retry = MAX_READ_RETRY;
while(retry) {
ret = i2c_rdwr_msg_transfer(fd, vr, tbuf, tcount, rbuf, rcount);
if (ret) {
#ifdef DEBUG
syslog(LOG_WARNING, "read_vr_power: i2c_io failed for bus#%x, dev#%x\n", VR_BUS_ID, vr);
#endif
retry--;
msleep(100);
} else {
break;
}
if (retry == 0)
goto error_exit;
}
// Read 2 bytes from Power register
tbuf[0] = VR_TELEMETRY_POWER;
tcount = 1;
rcount = 2;
retry = MAX_READ_RETRY;
while(retry) {
ret = i2c_rdwr_msg_transfer(fd, vr, tbuf, tcount, rbuf, rcount);
if (ret) {
#ifdef DEBUG
syslog(LOG_WARNING, "read_vr_power: i2c_io failed for bus#%x, dev#%x\n", VR_BUS_ID, vr);
#endif
retry--;
msleep(100);
} else {
break;
}
if (retry == 0)
goto error_exit;
}
// Calculate Power
*value = ((rbuf[1] & 0x3F) * 256 + rbuf[0] ) * 0.04;
error_exit:
return ret;
}
int
vr_read_temp(uint8_t vr, uint8_t loop, float *value) {
int fd;
static int count = 0;
int ret = -1;
unsigned int retry = MAX_READ_RETRY;
uint8_t tcount, rcount;
uint8_t tbuf[16] = {0};
uint8_t rbuf[16] = {0};
int16_t temp;
static unsigned int max_negative_retry = MAX_NEGATIVE_RETRY;
// The following block for detecting vr_update is in progress or not
if ( access(VR_UPDATE_IN_PROGRESS, F_OK) == 0 )
{
// Avoid sensord unmonitoring vr sensors due to unexpected condition happen during vr_update
if ( count > VR_TIMEOUT )
{
remove(VR_UPDATE_IN_PROGRESS);
count = 0;
}
syslog(LOG_WARNING, "[%d]Stop Monitor VR Temp due to VR update is in progress\n", count++);
return VR_STATUS_NOT_AVAILABLE;
}
count = 0;
fd = vr_get_i2c_bus_fd();
if ( fd < 0 ) {
return fd;
}
// Set the page to read Temperature
tbuf[0] = 0x00;
tbuf[1] = loop;
tcount = 2;
rcount = 0;
retry = MAX_READ_RETRY;
while (retry) {
ret = i2c_rdwr_msg_transfer(fd, vr, tbuf, tcount, rbuf, rcount);
if (ret) {
#ifdef DEBUG
syslog(LOG_WARNING, "read_vr_temp: i2c_io failed for bus#%x, dev#%x\n", VR_BUS_ID, vr);
#endif
retry--;
msleep(100);
} else {
break;
}
if(retry == 0)
goto error_exit;
}
// Read 2 bytes from Power register
tbuf[0] = VR_TELEMETRY_TEMP;
tcount = 1;
rcount = 2;
retry = MAX_READ_RETRY;
while(retry) {
ret = i2c_rdwr_msg_transfer(fd, vr, tbuf, tcount, rbuf, rcount);
if (ret) {
#ifdef DEBUG
syslog(LOG_WARNING, "read_vr_temp: i2c_io failed for bus#%x, dev#%x\n", VR_BUS_ID, vr);
#endif
retry--;
msleep(100);
} else {
break;
}
if(retry == 0)
goto error_exit;
}
// AN-E1610B-034B: temp[11:0]
// Calculate Temp
temp = (rbuf[1] << 8) | rbuf[0];
if ((rbuf[1] & 0x08))
temp |= 0xF000; // If negative, sign extend temp.
*value = (float)temp * 0.125;
//handle negative temperature value
if( *value < 0 ) {
if ( max_negative_retry > 0 ) {
max_negative_retry--;
ret = READING_SKIP;
}
} else {
max_negative_retry = MAX_NEGATIVE_RETRY;
}
error_exit:
return ret;
}
static int
fetch_vr_info(uint8_t vr, char *key, uint8_t page,
uint8_t reg1, uint8_t reg2, uint8_t *info) {
int fd;
int ret = -1;
unsigned int retry = MAX_READ_RETRY, retry_page = MAX_READ_RETRY;
uint8_t tcount, rcount;
uint8_t tbuf[16] = {0};
uint8_t rbuf[16] = {0};
char value[MAX_VALUE_LEN] = {0};
fd = vr_get_i2c_bus_fd();
if ( fd < 0 ) {
return fd;
}
retry_page = MAX_READ_RETRY;
while(retry_page) {
// Set the page to read FW Info
tbuf[0] = 0x00;
tbuf[1] = page;
tcount = 2;
rcount = 0;
retry = MAX_READ_RETRY;
while(retry) {
ret = i2c_rdwr_msg_transfer(fd, vr, tbuf, tcount, rbuf, rcount);
if (ret) {
#ifdef DEBUG
syslog(LOG_WARNING, "fetch_vr_info: i2c_io failed for bus#%x, dev#%x\n", VR_BUS_ID, vr);
#endif
retry--;
msleep(100);
} else {
break;
}
if(retry == 0)
goto error_exit;
}
// Read 2 bytes from first register
tbuf[0] = reg1;
tcount = 1;
rcount = 2;
retry = MAX_READ_RETRY;
while(retry) {
ret = i2c_rdwr_msg_transfer(fd, vr, tbuf, tcount, rbuf, rcount);
// Treat data 0xFF as failed and return -1
if (ret || rbuf[0] == 0xff || rbuf[1] == 0xff) {
ret = (ret)?ret:-1;
#ifdef DEBUG
syslog(LOG_WARNING, "fetch_vr_info: i2c_io failed for bus#%x, dev#%x\n", VR_BUS_ID, vr);
#endif
retry--;
msleep(100);
} else {
break;
}
if(retry == 0)
goto error_exit;
}
info[0] = rbuf[1];
info[1] = rbuf[0];
if (reg2) {
tbuf[0] = reg2;
tcount = 1;
rcount = 2;
retry = MAX_READ_RETRY;
while(retry) {
ret = i2c_rdwr_msg_transfer(fd, vr, tbuf, tcount, rbuf, rcount);
// Treat data 0xFF as failed and return -1
if (ret || rbuf[0] == 0xff || rbuf[1] == 0xff) {
ret = (ret)?ret:-1;
#ifdef DEBUG
syslog(LOG_WARNING, "fetch_vr_info: i2c_io failed for bus#%x, dev#%x\n", VR_BUS_ID, vr);
#endif
retry--;
msleep(100);
} else {
break;
}
if(retry == 0)
goto error_exit;
}
info[2] = rbuf[1];
info[3] = rbuf[0];
}
// Get the page to confirm if page is switched by other program
tbuf[0] = 0x00;
tcount = 1;
rcount = 1;
retry = MAX_READ_RETRY;
while(retry) {
ret = i2c_rdwr_msg_transfer(fd, vr, tbuf, tcount, rbuf, rcount);
if (ret) {
#ifdef DEBUG
syslog(LOG_WARNING, "fetch_vr_info: i2c_io failed for bus#%x, dev#%x\n", VR_BUS_ID, vr);
#endif
retry--;
msleep(100);
} else {
break;
}
if(retry == 0)
goto error_exit;
}
// page is incorrect, previous data might be wrong
if (rbuf[0] != page) {
#ifdef DEBUG
syslog(LOG_WARNING, "fetch_vr_info: incorrect page for bus#%x, dev#%x\n", VR_BUS_ID, vr);
#endif
retry_page--;
} else {
break;
}
if (retry_page == 0)
goto error_exit;
}
if (reg2)
sprintf(value, "%08X", *(unsigned int*)info);
else
sprintf(value, "%04X", *(unsigned int*)info);
kv_set(key, value, 0, 0);
error_exit:
vr_close_i2c_bus_fd();
return ret;
}
static int
get_vr_ver(uint8_t vr, uint8_t *ver) {
char key[MAX_KEY_LEN] = {0}, value[MAX_VALUE_LEN] = {0};
sprintf(key, "vr_%02Xh_ver", vr);
if (kv_get(key, value, NULL, 0) < 0)
return fetch_vr_info(vr, key, VR_FW_PAGE, VR_FW_REG1, VR_FW_REG2, ver);
*(unsigned int*)ver = (unsigned int)strtoul(value, NULL, 16);
return 0;
}
static int
get_vr_checksum(uint8_t vr, uint8_t *checksum) {
char key[MAX_KEY_LEN] = {0}, value[MAX_VALUE_LEN] = {0};
sprintf(key, "vr_%02Xh_checksum", vr);
if (kv_get(key, value, NULL, 0) < 0)
return fetch_vr_info(vr, key, VR_FW_PAGE_2, VR_FW_REG4, VR_FW_REG3, checksum);
*(unsigned int*)checksum = (unsigned int)strtoul(value, NULL, 16);
return 0;
}
static int
get_vr_deviceId(uint8_t vr, uint8_t *deviceId) {
char key[MAX_KEY_LEN] = {0}, value[MAX_VALUE_LEN] = {0};
sprintf(key, "vr_%02Xh_deviceId", vr);
if (kv_get(key, value, NULL, 0) < 0)
return fetch_vr_info(vr, key, VR_FW_PAGE_3, VR_FW_REG5, 0, deviceId);
*(unsigned short*)deviceId = (unsigned short)strtoul(value, NULL, 16);
return 0;
}
int vr_fw_version(uint8_t vr, char *outvers_str)
{
uint8_t ver[32];
char tmp_str[32];
*outvers_str = '\0';
if (get_vr_ver(vr, ver)) {
strcat(outvers_str, "Version: NA");
} else {
sprintf(tmp_str, "Version: %02X%02X%02X%02X", ver[0], ver[1], ver[2], ver[3]);
strcat(outvers_str, tmp_str);
}
if (get_vr_checksum(vr, ver)) {
strcat(outvers_str, ", Checksum: NA");
} else {
sprintf(tmp_str, ", Checksum: %02X%02X%02X%02X", ver[0], ver[1], ver[2], ver[3]);
strcat(outvers_str, tmp_str);
}
if (get_vr_deviceId(vr, ver)) {
strcat(outvers_str, ", DeviceID: NA");
} else {
sprintf(tmp_str, ", DeviceID: %02X%02X", ver[0], ver[1]);
strcat(outvers_str, tmp_str);
}
return 0;
}
static int
i2c_io_master_write(char *BusName, uint8_t addr, uint8_t *buf, uint8_t count) {
int fd;
int Retry = MAX_READ_RETRY;
int RetVal = -1;
//open device
while ( Retry )
{
fd = open(BusName, O_RDWR);
if ( fd < 0 ) {
syslog(LOG_WARNING, "[%s] i2c_open failed for bus#%x\n", __func__, VR_BUS_ID);
Retry--;
msleep(100);
#ifdef VR_DEBUG
printf("[%s] i2c_open failed for bus#%x\n", __func__, VR_BUS_ID);
#endif
} else {
break;
}
if ( 0 == Retry ) {
syslog(LOG_WARNING, "[%s] i2c_open failed for bus#%x\n", __func__, VR_BUS_ID);
#ifdef VR_DEBUG
printf("[%s] i2c_open failed for bus#%x\n", __func__, VR_BUS_ID);
#endif
goto error_exit;
}
}
Retry = MAX_READ_RETRY;
//Retry transmission
while ( Retry )
{
RetVal = i2c_rdwr_msg_transfer(fd, addr, buf, count, NULL, 0);
if ( RetVal != 0 )
{
syslog(LOG_WARNING, "[%s] Wrtie Bus#%x Slave address: %x failed.\n", __func__, VR_BUS_ID, addr);
msleep(500);
Retry--;
#ifdef VR_DEBUG
printf("[%s] Wrtie Bus#%x Slave address: %x failed.\n", __func__, VR_BUS_ID, addr);
#endif
} else {
break;
}
}
if ( RetVal != 0 )
{
syslog(LOG_WARNING, "[%s] Wrtie Bus#%x Slave address: %x failed.\n", __func__, VR_BUS_ID, addr);
#ifdef VR_DEBUG
printf("[%s] Wrtie Bus#%x Slave address: %x failed.\n", __func__, VR_BUS_ID, addr);
#endif
goto error_exit;
}
error_exit:
close(fd);
return RetVal;
}
static int
i2c_io_rw(char *BusName, uint8_t addr, uint8_t *txbuf, uint8_t txcount, uint8_t *rxbuf,
uint8_t rxcount)
{
int fd;
int Retry = MAX_READ_RETRY;
int RetVal = -1;
//open device
while ( Retry )
{
fd = open(BusName, O_RDWR);
if (fd < 0)
{
syslog(LOG_WARNING, "[%s] i2c_open failed for bus#%x\n", __func__, VR_BUS_ID);
Retry--;
msleep(100);
#ifdef VR_DEBUG
printf("[%s] i2c_open failed for bus#%x\n", __func__, VR_BUS_ID);
#endif
} else {
break;
}
if ( 0 == Retry )
{
syslog(LOG_WARNING, "[%s] i2c_open failed for bus#%x\n", __func__, VR_BUS_ID);
#ifdef VR_DEBUG
printf("[%s] i2c_open failed for bus#%x\n", __func__, VR_BUS_ID);
#endif
goto error_exit;
}
}
Retry = MAX_READ_RETRY;
//Retry transmission
while ( Retry )
{
RetVal = i2c_rdwr_msg_transfer(fd, addr, txbuf, txcount, rxbuf, rxcount);
if ( RetVal != 0 )
{
Retry--;
syslog(LOG_WARNING, "[%s] Read/Wrtie Bus#%x Slave address: %x failed.\n", __func__, VR_BUS_ID, addr);
#ifdef VR_DEBUG
printf("[%s] Read/Wrtie Bus#%x Slave address: %x failed.\n", __func__, VR_BUS_ID, addr);
#endif
msleep(500);
} else {
break;
}
}
if ( RetVal != 0 )
{
syslog(LOG_WARNING, "[%s] Read/Wrtie Bus#%x Slave address: %x failed.\n", __func__, VR_BUS_ID, addr);
#ifdef VR_DEBUG
printf("[%s] Read/Wrtie Bus#%x Slave address: %x failed.\n", __func__, VR_BUS_ID, addr);
#endif
}
error_exit:
close(fd);
return RetVal;
}
/*
* Board specific version match verfication
*
*/
static int
check_vr_fw_code_match_MB(int startindex, int endindex, uint8_t *BinData, uint8_t BoardInfo)
{
int RetVal = -1;
int j;
uint8_t BOARD_SKU_ID;
uint8_t VR_SKUID; //identify the version which is suitable for MB or not
uint8_t VR_Type = UNKNOWN_TYPE;
//the mapper is defined as below and it is defined by power team
// 0x1 - DS & IFX
// 0x2 - SS & IFX
// 0x3 - DS & Fairchild
// 0x4 - SS & Fairchild
uint8_t DevStageMapper[]=
{
DS_IFX,
SS_IFX,
DS_Fairchild,
SS_Fairchild,
};
//get the type of MB by GPIO
//0x0 - SS & Fairchild
//0x1 - SS & IFX
//0x2 - DS & Fairchild
//0x3 - DS & IFX
BOARD_SKU_ID = BoardInfo >> 3;
#ifdef VR_DEBUG
printf("[%s] BoardInfo:%x, BOARD_SKU_ID:%x\n", __func__, BoardInfo, BOARD_SKU_ID);
#endif
for ( j = startindex; j < endindex; j = j + 4 )// 4 bytes
{
#ifdef VR_DEBUG
printf("[%s] %x %x %x %x\n", __func__, BinData[j], BinData[j+1], BinData[j+2], BinData[j+3]);
#endif
//user data0 - 5e0c address. It represents that the vr fw code version
//we need to check the vr fw code is match MB or not
if ( ( 0x5e == BinData[j] ) && ( 0x0c == BinData[j+1] ) )
{
//it need to map to DevStageMapper or its unknown type!
VR_Type = BinData[j+3];
#ifdef VR_DEBUG
printf("[%s] VR_Type: %x \n", __func__, VR_Type);
#endif
break;
}
}
if (VR_Type == UNKNOWN_TYPE) {
goto error_exit;
}
VR_SKUID = DevStageMapper[VR_Type];
#ifdef VR_DEBUG
printf("[%s] DevStageMapper[%d]\n", __func__, VR_SKUID);
#endif
if ( VR_SKUID == BOARD_SKU_ID )
{
return 0;
}
else
{
syslog(LOG_WARNING, "[%s] VR fw code does not match MB!\n", __func__);
RetVal = -1;
goto error_exit;
}
error_exit:
return RetVal;
}
static int
check_integrity_of_vr_data(uint8_t SlaveAddr, uint8_t *ExpectedCRC, int StartIndex, int EndIndex, uint8_t *Data)
{
int i = StartIndex;
uint32_t CurrentData = 0x0;
uint32_t CRC = 0x0;
uint32_t Dout = 0xffffffff;
for ( ; i < EndIndex; i = i + 4 )
{
//printf("[%d] %x %x %x %x\n", i, Data[i], Data[i+1], Data[i+2], Data[i+3]);
CurrentData = (CurrentData & 0x0) | Data[i+2];//low byte
CRC = (VR_BIT0(Dout, CurrentData) & 0x1 ) + ((VR_BIT1(Dout, CurrentData) & 0x1 ) << 1 ) + ((VR_BIT2(Dout, CurrentData) & 0x1 ) << 2 ) + ((VR_BIT3(Dout, CurrentData) & 0x1 ) << 3 ) + ((VR_BIT4(Dout, CurrentData) & 0x1 ) << 4 ) + ((VR_BIT5(Dout, CurrentData) & 0x1 ) << 5 ) + ((VR_BIT6(Dout, CurrentData) & 0x1 ) << 6 ) + ((VR_BIT7(Dout, CurrentData) & 0x1 ) << 7 ) +
((VR_BIT8(Dout, CurrentData) & 0x1 ) << 8 ) + ((VR_BIT9(Dout, CurrentData) & 0x1 ) << 9 ) + ((VR_BIT10(Dout, CurrentData) & 0x1 ) << 10 ) + ((VR_BIT11(Dout, CurrentData) & 0x1 ) << 11 ) + ((VR_BIT12(Dout, CurrentData) & 0x1 ) << 12 ) + ((VR_BIT13(Dout, CurrentData) & 0x1 ) << 13 ) + ((VR_BIT14(Dout, CurrentData) & 0x1 ) << 14 ) + ((VR_BIT15(Dout, CurrentData) & 0x1 ) << 15 ) +
((VR_BIT16(Dout, CurrentData) & 0x1 ) << 16 ) + ((VR_BIT17(Dout, CurrentData) & 0x1 ) << 17 ) + ((VR_BIT18(Dout, CurrentData) & 0x1 ) << 18 ) + ((VR_BIT19(Dout, CurrentData) & 0x1 ) << 19 ) + ((VR_BIT20(Dout, CurrentData) & 0x1 ) << 20 ) + ((VR_BIT21(Dout, CurrentData) & 0x1 ) << 21 ) + ((VR_BIT22(Dout, CurrentData) & 0x1 ) << 22 ) + ((VR_BIT23(Dout, CurrentData) & 0x1 ) << 23 ) +
((VR_BIT24(Dout, CurrentData) & 0x1 ) << 24 ) + ((VR_BIT25(Dout, CurrentData) & 0x1 ) << 25 ) + ((VR_BIT26(Dout, CurrentData) & 0x1 ) << 26 ) + ((VR_BIT27(Dout, CurrentData) & 0x1 ) << 27 ) + ((VR_BIT28(Dout, CurrentData) & 0x1 ) << 28 ) + ((VR_BIT29(Dout, CurrentData) & 0x1 ) << 29 ) + ((VR_BIT30(Dout, CurrentData) & 0x1 ) << 30 ) + ((VR_BIT31(Dout, CurrentData) & 0x1 ) << 31 );
Dout = CRC;
CurrentData = (CurrentData & 0x0) | Data[i+3];//high byte
CRC = (VR_BIT0(Dout, CurrentData) & 0x1 ) + ((VR_BIT1(Dout, CurrentData) & 0x1 ) << 1 ) + ((VR_BIT2(Dout, CurrentData) & 0x1 ) << 2 ) + ((VR_BIT3(Dout, CurrentData) & 0x1 ) << 3 ) + ((VR_BIT4(Dout, CurrentData) & 0x1 ) << 4 ) + ((VR_BIT5(Dout, CurrentData) & 0x1 ) << 5 ) + ((VR_BIT6(Dout, CurrentData) & 0x1 ) << 6 ) + ((VR_BIT7(Dout, CurrentData) & 0x1 ) << 7 ) +
((VR_BIT8(Dout, CurrentData) & 0x1 ) << 8 ) + ((VR_BIT9(Dout, CurrentData) & 0x1 ) << 9 ) + ((VR_BIT10(Dout, CurrentData) & 0x1 ) << 10 ) + ((VR_BIT11(Dout, CurrentData) & 0x1 ) << 11 ) + ((VR_BIT12(Dout, CurrentData) & 0x1 ) << 12 ) + ((VR_BIT13(Dout, CurrentData) & 0x1 ) << 13 ) + ((VR_BIT14(Dout, CurrentData) & 0x1 ) << 14 ) + ((VR_BIT15(Dout, CurrentData) & 0x1 ) << 15 ) +
((VR_BIT16(Dout, CurrentData) & 0x1 ) << 16 ) + ((VR_BIT17(Dout, CurrentData) & 0x1 ) << 17 ) + ((VR_BIT18(Dout, CurrentData) & 0x1 ) << 18 ) + ((VR_BIT19(Dout, CurrentData) & 0x1 ) << 19 ) + ((VR_BIT20(Dout, CurrentData) & 0x1 ) << 20 ) + ((VR_BIT21(Dout, CurrentData) & 0x1 ) << 21 ) + ((VR_BIT22(Dout, CurrentData) & 0x1 ) << 22 ) + ((VR_BIT23(Dout, CurrentData) & 0x1 ) << 23 ) +
((VR_BIT24(Dout, CurrentData) & 0x1 ) << 24 ) + ((VR_BIT25(Dout, CurrentData) & 0x1 ) << 25 ) + ((VR_BIT26(Dout, CurrentData) & 0x1 ) << 26 ) + ((VR_BIT27(Dout, CurrentData) & 0x1 ) << 27 ) + ((VR_BIT28(Dout, CurrentData) & 0x1 ) << 28 ) + ((VR_BIT29(Dout, CurrentData) & 0x1 ) << 29 ) + ((VR_BIT30(Dout, CurrentData) & 0x1 ) << 30 ) + ((VR_BIT31(Dout, CurrentData) & 0x1 ) << 31 );
Dout = CRC;
}
uint8_t ActualCRC32[4] = {0};
ActualCRC32[0] = ( CRC & 0xff );
ActualCRC32[1] = ( ( CRC >> 8 ) & 0xff );
ActualCRC32[2] = ( ( CRC >> 16 ) & 0xff );
ActualCRC32[3] = ( ( CRC >> 24 ) & 0xff );
if ( (ActualCRC32[3] != ExpectedCRC[0]) || (ActualCRC32[2] != ExpectedCRC[1]) || (ActualCRC32[1] != ExpectedCRC[2]) || (ActualCRC32[0] != ExpectedCRC[3]) )
{
syslog(LOG_WARNING, "[%s] Slave: %x CRC not match !\n", __func__, SlaveAddr);
syslog(LOG_WARNING, "[%s] Slave: %x CRC: %x %x %x %x!\n", __func__, SlaveAddr, ActualCRC32[0], ActualCRC32[1], ActualCRC32[2], ActualCRC32[3]);
syslog(LOG_WARNING, "[%s] Slave: %x Expected CRC: %x %x %x %x!\n", __func__, SlaveAddr, ExpectedCRC[0], ExpectedCRC[1], ExpectedCRC[2], ExpectedCRC[3]);
return -1;
}
#ifdef VR_DEBUG
else
{
printf("[%s] Slave: %x CRC match !\n", __func__, SlaveAddr);
}
#endif
return 0;
}
static int
unlock_vr_register(char *BusName, uint8_t SlaveAddr)
{
int RetVal;
uint8_t TxBuf[3] = {0};
/********* Set Page***********/
TxBuf[0] = 0x00;
TxBuf[1] = 0x3f;
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] UnlockRegister: Change Register Page failed: 0x00 0x3f \n", __func__);
goto error_exit;
}
/*********Write unlock data to 0x27***********/
TxBuf[0] = 0x27;
TxBuf[1] = 0x7c;
TxBuf[2] = 0xb3;
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 3);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Unlock register failed: 0x27 0x7c 0xb3 \n", __func__);
goto error_exit;
}
/*********Write unlock data to 0x2a***********/
TxBuf[0] = 0x2a;
TxBuf[1] = 0xb2;
TxBuf[2] = 0x8a;
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 3);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Unlock register failed: 0x27, 0x7c, 0xb3 \n", __func__);
goto error_exit;
}
error_exit:
return RetVal;
}
static int
check_vr_chip_remaining_times(char *BusName, uint8_t SlaveAddr)
{
int RetVal;
uint16_t ChipRemainTimes = 0;
uint8_t TxBuf[3] = {0};
uint8_t RxBuf[3] = {0};
//set page
TxBuf[0] = 0x00;
TxBuf[1] = 0x50;
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] set page to 0x00 0x50 failed\n", __func__);
goto error_exit;
}
//read two bytes from address 0x82
TxBuf[0] = 0x82;
RxBuf[0] = 0;
RxBuf[1] = 0;
RetVal = i2c_io_rw(BusName, SlaveAddr, TxBuf, 1, RxBuf, 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] CheckChipRemainingTimes: Read data from address 0x82 failed\n", __func__);
goto error_exit;
}
/*get bit 6 ~ bit 11*/
ChipRemainTimes = (RxBuf[1] << 8) + RxBuf[0];
ChipRemainTimes = (ChipRemainTimes >> 6 ) & 0x3f;
//set to page 20
TxBuf[0] = 0x00;
TxBuf[1] = 0x20;
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Change Register Page failed[End]: 0x00 0x20 failed\n", __func__);
goto error_exit;
}
//the remaining time of chip is 0, we cannot flash vr
if ( ChipRemainTimes == 0 )
{
RetVal = -1;
}
error_exit:
return RetVal;
}
static int
write_data_to_vr(char *BusName, uint8_t SlaveAddr, uint8_t *Data)
{
int RetVal;
uint8_t RxBuf[3] = {0};
uint8_t TxBuf[3] = {0};
#ifdef VR_DEBUG
printf("[%s] %x %x %x %x \n", __func__, Data[0], Data[1], Data[2], Data[3]);
#endif
/***set Page***/
TxBuf[0] = 0x00;
TxBuf[1] = (Data[0] >> 1) & 0x3f;
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 2 );
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Change Register Page failed: 0x00, 0x3f \n", __func__);
goto error_exit;
}
#ifdef VR_DEBUG
//Check Page is changed or not
TxBuf[0] = 0x0;
RxBuf[0] = 0x0;
RetVal = i2c_io_rw(BusName, SlaveAddr, TxBuf, 1, RxBuf, 1);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Read page failed: 0x0\n", __func__);
goto error_exit;
}
/***set data to buf***/
//read data from the target address. just for debugging
TxBuf[0] = Data[1];
RxBuf[0] = 0;
RxBuf[1] = 0;
RetVal = i2c_io_rw(BusName, SlaveAddr, TxBuf, 1, RxBuf, 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Read failed: %x , %x, %x \n", __func__, Data[1], Data[2], Data[3]);
goto error_exit;
}
printf("[%s] [Write]Page %x, Addr %x ,low byte %x, high byte %x\n", __func__, (Data[0] >> 1) & 0x3f, Data[1], Data[2], Data[3]);
#endif
//write data to register
TxBuf[0] = Data[1];//addr
TxBuf[1] = Data[2];//low byte
TxBuf[2] = Data[3];//high byte
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 3);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Write failed: %x, %x, %x\n", __func__, TxBuf[0], TxBuf[1], TxBuf[2]);
goto error_exit;
}
//double check -- read the address again
TxBuf[0] = Data[1];
RxBuf[0] = 0;
RxBuf[1] = 0;
RetVal = i2c_io_rw(BusName, SlaveAddr, TxBuf, 1, RxBuf, 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Read failed: %x , %x, %x \n",__func__ ,Data[1], Data[2], Data[3]);
goto error_exit;
}
//printf("[Read2]Page %x, Addr %x ,low byte %x, high byte %x\n", page, TxBuf[0], RxBuf[0], RxBuf[1]);
if ( (RxBuf[0] != Data[2]) || (RxBuf[1] != Data[3]) )
{
syslog(LOG_WARNING, "[%s] The result between Read and Write is DIFFERENT!!!!\n",__func__);
syslog(LOG_WARNING, "[%s] Write: Page %x, Addr %x, LowByte %x, HighByte %x \n",__func__ ,(Data[0] >> 1) & 0x3f ,Data[0] ,Data[1], Data[2] );
syslog(LOG_WARNING, "[%s] Read: Page %x, Addr %x, LowByte %x, HighByte %x \n",__func__ ,(Data[0] >> 1) & 0x3f ,TxBuf[0] ,RxBuf[0], RxBuf[1]);
RetVal = -1;
goto error_exit;
}
error_exit:
return RetVal;
}
static int
write_vr_finish(char *BusName, uint8_t SlaveAddr)
{
int RetVal;
uint8_t TxBuf[3] = {0};
uint8_t RxBuf[3] = {0};
/*********Set Page***********/
TxBuf[0] = 0x00;
TxBuf[1] = 0x3f;
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Change Register Page failed: 0x00, 0x3f \n", __func__);
goto error_exit;
}
#ifdef VR_DEBUG
//check page is changed or not
TxBuf[0] = 0x00;
RxBuf[0] = 0x00;
//check page
RetVal = i2c_io_rw(BusName, SlaveAddr, TxBuf, 1, RxBuf, 1);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Check page failed: 0x3f \n",__func__);
goto error_exit;
}
printf("[%s] Check Page: %x \n",__func__, RxBuf[0]);
#endif
TxBuf[0] = 0x2a;
TxBuf[1] = 0x00;
TxBuf[2] = 0x00;
//write word to the target address
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf,3);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Lock register failed: 0x2a, 0x00, 0x00 \n",__func__);
goto error_exit;
}
//check the writing data from the target address
TxBuf[0] = 0x2a;
RxBuf[0] = 0;
RxBuf[1] = 0;
RetVal = i2c_io_rw(BusName, SlaveAddr, TxBuf, 1, RxBuf, 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Check data failed: 0x2a, 0x00, 0x00 \n",__func__);
goto error_exit;
}
error_exit:
return RetVal;
}
static int
save_data_to_vr_NVM(char *BusName, uint8_t SlaveAddr)
{
int RetVal;
uint8_t TxBuf[3] = {0};
uint8_t RxBuf[3] = {0};
/*********Set Page***********/
TxBuf[0] = 0x00;
TxBuf[1] = 0x3f;
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Change Register Page failed: 0x00, 0x3f \n", __func__);
goto error_exit;
}
TxBuf[0] = 0x00;
RxBuf[0] = 0x00;
/****Check Page is changed or not****/
RetVal = i2c_io_rw(BusName, SlaveAddr, TxBuf, 1, RxBuf, 1);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Check page failed: 0x3f \n", __func__);
goto error_exit;
}
/****lock - fill buf****/
TxBuf[0] = 0x29;
TxBuf[1] = 0xd7;
TxBuf[2] = 0xef;
/****lock - write to the address****/
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 3);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Lock register failed: 0x29, 0xd7, 0xef \n", __func__);
goto error_exit;
}
/****lock - check the data again****/
RxBuf[0] = 0;
RxBuf[1] = 0;
RetVal = i2c_io_rw(BusName, SlaveAddr, TxBuf, 1, RxBuf, 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Check data failed: 0x29, 0xd7, 0xef \n", __func__);
goto error_exit;
}
/*********clear fault flag***********/
TxBuf[0] = 0x2c;
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 1);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Clear fault failed: 0x2c \n",__func__);
goto error_exit;
}
/*********upload data to NVM***********/
//initiates an upload from the register to NVM
TxBuf[0] = 0x34;
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 1);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Lock register failed: 0x34 \n", __func__);
goto error_exit;
}
/*********Set Page***********/
sleep(3);//avoid page failure
TxBuf[0] = 0x00;
TxBuf[1] = 0x60;
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Change Register Page failed: 0x00, 0x60 \n", __func__);
goto error_exit;
}
#ifdef VR_DEBUG
RxBuf[0] = 0;
TxBuf[0] = 0;
//check page
RetVal = i2c_io_rw(BusName, SlaveAddr, TxBuf, 1, RxBuf, 1);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Check page failed: 0x60 \n", __func__);
goto error_exit;
}
#endif
/*********Read Data***********/
//read word from reg 0x01 and 0x02
//read data from reg1
TxBuf[0] = 0x01;
RxBuf[0] = 0;
RxBuf[1] = 0;
RetVal = i2c_io_rw(BusName, SlaveAddr, TxBuf, 1, RxBuf, 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Read data from page 0x60 addr 0x01 failed \n",__func__);
goto error_exit;
}
//read data from reg2
TxBuf[0] = 0x02;
RxBuf[0] = 0;
RxBuf[1] = 0;
RetVal = i2c_io_rw(BusName, SlaveAddr, TxBuf, 1, RxBuf, 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Read data from page 0x60 addr 0x02 failed \n",__func__);
goto error_exit;
}
/*********Page***********/
sleep(1); //avoid page failure
TxBuf[0] = 0x00;
TxBuf[1] = 0x3f;
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Change Register Page failed: 0x00, 0x3f \n",__func__);
goto error_exit;
}
#ifdef VR_DEBUG
//check page
TxBuf[0] = 0x0;
RxBuf[0] = 0x0;
RetVal = i2c_io_rw(BusName, SlaveAddr, TxBuf, 1, RxBuf, 1);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Check page failed: 0x3f \n",__func__);
goto error_exit;
}
//printf("[%s] Check Page: %x \n",__func__, RxBuf[0]);
#endif
/*********End***********/
TxBuf[0] = 0x29;
TxBuf[1] = 0x00;
TxBuf[2] = 0x00;
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 3);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Failed to write 0x29 0x00 0x00 \n",__func__);
goto error_exit;
}
sleep(2);
#ifdef VR_DEBUG
TxBuf[0] = 0x29;
RxBuf[0] = 0x0;
RxBuf[1] = 0x0;
//check write data
RetVal = i2c_io_rw(BusName, SlaveAddr, TxBuf, 1, RxBuf, 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Check data failed: 0x29 0x00 0x00 \n",__func__);
goto error_exit;
}
#endif
error_exit:
return RetVal;
}
static int
check_vr_CRC(char *BusName, uint8_t SlaveAddr, uint8_t *ExpectedCRC)
{
int RetVal=0;
uint8_t TxBuf[3]={0};
uint8_t RxBuf[4]={0};
/****Set Page****/
TxBuf[0] = 0x00;
TxBuf[1] = 0x3f;
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Change Register Page failed: 0x00, 0x3f \n", __func__);
goto error_exit;
}
#ifdef VR_DEBUG
/****Check Page changed or not****/
TxBuf[0] = 0;
RxBuf[0] = 0;
RetVal = i2c_io_rw(BusName, SlaveAddr, TxBuf, 1, RxBuf, 1);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] read page failed: 0x3f \n", __func__);
goto error_exit;
}
#endif
sleep(1);//force sleep
/*********data***********/
TxBuf[0] = 0x27;
TxBuf[1] = 0x7c;
TxBuf[2] = 0xb3;
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 3);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] set data failed: 0x27 0x7c 0xb3 \n", __func__);
goto error_exit;
}
#ifdef VR_DEBUG
//check data
TxBuf[0] = 0x27;
RxBuf[0] = 0;
RxBuf[1] = 0;
RetVal = i2c_io_rw(BusName, SlaveAddr, TxBuf, 1, RxBuf, 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Check data failed: 0x27 0x7c 0xb3 \n", __func__);
goto error_exit;
}
#endif
/*********data***********/
TxBuf[0] = 0x32;
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 1);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] set data failed: 0x32 \n", __func__);
goto error_exit;
}
/*********Page***********/
TxBuf[0] = 0x00;
TxBuf[1] = 0x6f;
RetVal = i2c_io_master_write(BusName, SlaveAddr, TxBuf, 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Change Register Page failed: 0x00, 0x6f \n", __func__);
goto error_exit;
}
#ifdef VR_DEBUG
/*********Check page changed or not***********/
TxBuf[0] = 0x00;
RxBuf[0] = 0x00;
//check page
RetVal = i2c_io_rw(BusName, SlaveAddr, TxBuf, 1, RxBuf, 1);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Check page failed: 0x6f \n", __func__);
goto error_exit;
}
#endif
/********read data*************/
TxBuf[0] = 0x3d;
RxBuf[0] = 0x00;
RxBuf[1] = 0x00;
RetVal = i2c_io_rw(BusName, SlaveAddr, TxBuf, 1, &RxBuf[0], 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] read addr failed: 0x3d \n", __func__);
goto error_exit;
}
TxBuf[0] = 0x3e;
RxBuf[2] = 0x00;
RxBuf[3] = 0x00;
RetVal = i2c_io_rw(BusName, SlaveAddr, TxBuf, 1, &RxBuf[2], 2);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] read addr failed: 0x3e \n",__func__);
goto error_exit;
}
//check CRC match
if ( (RxBuf[3] != ExpectedCRC[0]) || (RxBuf[2] != ExpectedCRC[1]) || (RxBuf[1] != ExpectedCRC[2]) || (RxBuf[0] != ExpectedCRC[3]))
{
syslog(LOG_WARNING, "[%s] CRC cannot MATCH!!\n",__func__);
syslog(LOG_WARNING, "[%s] Expected CRC: %x %x %x %x\n",__func__, ExpectedCRC[0], ExpectedCRC[1], ExpectedCRC[2], ExpectedCRC[3]);
syslog(LOG_WARNING, "[%s] Actual CRC: %x %x %x %x\n",__func__, RxBuf[3], RxBuf[2], RxBuf[1], RxBuf[0]);
RetVal = -1;
goto error_exit;
}
error_exit:
return RetVal;
}
static int
get_vr_update_data(const char *update_file, uint8_t **BinData)
{
FILE *fp;
int FileSize = 0;
int RetVal = 0;
fp = fopen( update_file, "rb" );
if ( fp )
{
//get file size
fseek(fp, 0L, SEEK_END);
FileSize = ftell(fp);
*BinData = (uint8_t*) malloc( FileSize * sizeof(uint8_t));
//recovery the fp to the beginning
rewind(fp);
if (fread(*BinData, sizeof(uint8_t), FileSize, fp) != FileSize)
{
fclose(fp);
return -1;
}
fclose(fp);
#ifdef VR_DEBUG
int i;
for ( i = 0; i < FileSize; i++ )
{
if ( (i % 16 == 0) && (i != 0) )
{
printf("%x ", *BinData[i]);
printf("\n");
}
else
{
printf("%x ", *BinData[i]);
}
}
#endif
printf("Data Size: %d bytes!\n", FileSize);
}
else
{
RetVal = -1;
}
return RetVal;
}
static int vr_fw_update_binary(uint8_t *BinData, uint8_t BoardInfo)
{
VRBasicInfo vr_data[MAX_VR_CHIPS];//there are nine vr chips
int VRDataLength = 0;
int VR_counts = MAX_VR_CHIPS;
int i, j;
int fd;
int RetVal;
int TotalProgress = 0;
int CurrentProgress = 0;
char BusName[64];
uint8_t BOARD_SKU_ID0;
//create a file to inform "vr_read function". do not send req to VR
fd = open(VR_UPDATE_IN_PROGRESS, O_WRONLY | O_CREAT | O_TRUNC, 0700);
if ( -1 == fd )
{
printf("[%s] Create %s file error",__func__, VR_UPDATE_IN_PROGRESS);
RetVal = -1;
goto error_exit;
}
close(fd);
//wait for the sensord monitor cycle end
sleep(3);
snprintf(BusName, sizeof(BusName), "/dev/i2c-%d", VR_BUS_ID);
//init vr array
memset(vr_data, 0, sizeof(vr_data));
#ifdef VR_DEBUG
printf("[%s] VR Counts:%d, Data_Start_Addr: %d\n", __func__, VR_counts, DATA_START_ADDR);
#endif
//before updating vr, we parse data first.
//DataLength = update data header + update data
for ( i = 0 ; i < VR_counts; i++ )
{
vr_data[i].DataLength = (BinData[ (2*i) ] << 8 ) + BinData[ (2*i) + 1 ];
#ifdef VR_DEBUG
printf("[%s] DataLength: %d \n", __func__, vr_data[i].DataLength);
#endif
}
//catch the basic info
for ( i = 0 ; i < VR_counts; i++ )
{
/*need to identify the first one. and set the start address*/
if ( 0 == i )
{
j = DATA_START_ADDR;
VRDataLength = vr_data[ i ].DataLength + DATA_START_ADDR;
}
else
{
j = VRDataLength;
VRDataLength = vr_data[ i ].DataLength + VRDataLength;
}
vr_data[i].SlaveAddr = BinData[ j ];
vr_data[i].IndexStartAddr = j + 5;
//copy crc
memcpy(vr_data[i].CRC, &BinData[ j + 1 ], 4);
vr_data[i].IndexEndAddr = VRDataLength;
#ifdef VR_DEBUG
printf("[%s]: SlaveAddr: %x\n", __func__, vr_data[i].SlaveAddr );
printf("[%s]: CRC %x %x %x %x\n", __func__, vr_data[i].CRC[0], vr_data[i].CRC[1],
vr_data[i].CRC[2], vr_data[i].CRC[3]);
#endif
}
//calculate the reality data length
for ( i = 0 ; i < VR_counts; i++ )
{
TotalProgress += (vr_data[i].IndexEndAddr - vr_data[i].IndexStartAddr);
}
/**Check Chip**/
printf("Check Data...");
//check the remaining times of flashing chip
for ( i = 0 ; i < VR_counts; i++ )
{
RetVal = check_vr_chip_remaining_times( BusName, vr_data[i].SlaveAddr );
if ( RetVal < 0 )
{
//The Remaining Times of Chip is 0!
goto error_exit;
}
}
BOARD_SKU_ID0 = BoardInfo & 0x1; //get FM_BOARD_SKU_ID0
if ( BOARD_SKU_ID0 )
{
//get 0x5e0c-userdata(version) data to compare the
RetVal = check_vr_fw_code_match_MB(vr_data[0].IndexStartAddr, vr_data[0].IndexEndAddr, BinData, BoardInfo);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Please Check vr fw code!\n", __func__);
goto error_exit;
}
}
//check CRC
for ( i = 0 ; i < VR_counts; i++ )
{
RetVal = check_integrity_of_vr_data(vr_data[i].SlaveAddr, vr_data[i].CRC, vr_data[i].IndexStartAddr, vr_data[i].IndexEndAddr, BinData);
if ( RetVal < 0 )
{
//the bin file is incomplete
goto error_exit;
}
}
/**Check Chip**/
printf("Done\n");
for ( i = 0; i < VR_counts; i++ )
{
#ifdef VR_DEBUG
printf("[%s][%d]vr_fw_update: UnlockRegister \n", __func__, i);
#endif
RetVal = unlock_vr_register( BusName, vr_data[i].SlaveAddr );
if ( RetVal < 0 )
{
//unlock register failed
syslog(LOG_WARNING, "[%s] Failed Occurred at Unlocking Register\n", __func__);
goto error_exit;
}
//the starting data index of the current vr
j = vr_data[i].IndexStartAddr;
//the end index of the current vr
int EndAddr = vr_data[i].IndexEndAddr;
for ( ; j < EndAddr; j = j + 4 )// 4 bytes
{
CurrentProgress += 4;
printf("Writing Data: %d/%d (%.2f%%) \r",(CurrentProgress), TotalProgress, (((CurrentProgress)/(float)TotalProgress)*100));
RetVal = write_data_to_vr( BusName, vr_data[i].SlaveAddr, &BinData[j] );
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Failed Occurred at Writing Data\n", __func__);
goto error_exit;
}
}
//After writing data, we need to store it
RetVal = write_vr_finish( BusName, vr_data[i].SlaveAddr );
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Error at Locking register\n", __func__);
goto error_exit;
}
RetVal = save_data_to_vr_NVM( BusName, vr_data[i].SlaveAddr );
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Error at Saving Data\n", __func__);
goto error_exit;
}
RetVal = check_vr_CRC ( BusName, vr_data[i].SlaveAddr, vr_data[i].CRC);
if ( RetVal < 0 )
{
syslog(LOG_WARNING, "[%s] Error at CRC value from the register\n", __func__);
goto error_exit;
}
}
printf("\nUpdate VR Success!\n");
error_exit:
if ( -1 == remove(VR_UPDATE_IN_PROGRESS) )
{
printf("[%s] Remove %s Error\n", __func__, VR_UPDATE_IN_PROGRESS);
RetVal = -1;
}
return RetVal;
}
int vr_fw_update(uint8_t fru, uint8_t board_info, const char *file)
{
uint8_t *BinData=NULL;
int ret;
ret = get_vr_update_data(file, &BinData);
if ( ret < 0 )
{
printf("Cannot locate the file at: %s!\n", file);
return ret;
}
ret = vr_fw_update_binary(BinData, board_info);
if ( ret < 0 )
{
printf("Error Occur at updating VR FW!\n");
return ret;
}
return 0;
}