Skip to content

Commit

Permalink
DellEMC S6100 : Platform2.0 API implementation for PSU (#3132)
Browse files Browse the repository at this point in the history
  • Loading branch information
ArunSaravananBalachandran authored and jleveque committed Jul 10, 2019
1 parent 9764589 commit e520cbe
Show file tree
Hide file tree
Showing 6 changed files with 487 additions and 6 deletions.
133 changes: 132 additions & 1 deletion platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
#define PSU_1_OUTPUT_CURRENT 0x0244
#define PSU_1_INPUT_POWER 0x0246
#define PSU_1_OUTPUT_POWER 0x0248
#define PSU_1_FAN_SPEED 0x023B
#define PSU_1_COUNTRY_CODE 0x024A

/* PSU2 */
#define PSU_2_MAX_POWER 0x026D
Expand All @@ -127,6 +127,7 @@
#define PSU_2_OUTPUT_CURRENT 0x027D
#define PSU_2_INPUT_POWER 0x027F
#define PSU_2_OUTPUT_POWER 0x0281
#define PSU_2_COUNTRY_CODE 0x0283

/* TEMP */
#define TEMP_SENSOR_1 0x0014
Expand All @@ -151,6 +152,20 @@
#define CPU_7_MONITOR_STATUS 0x02E8
#define CPU_8_MONITOR_STATUS 0x02E9

/* EEPROM PPID */
/* FAN and PSU EEPROM PPID format is:
COUNTRY_CODE-PART_NO-MFG_ID-MFG_DATE_CODE-SERIAL_NO-LABEL_REV */
#define EEPROM_COUNTRY_CODE_SIZE 2
#define EEPROM_PART_NO_SIZE 6
#define EEPROM_MFG_ID_SIZE 5
#define EEPROM_MFG_DATE_SIZE 8
#define EEPROM_DATE_CODE_SIZE 3
#define EEPROM_SERIAL_NO_SIZE 4
#define EEPROM_SERVICE_TAG_SIZE 7
#define EEPROM_LABEL_REV_SIZE 3
#define EEPROM_PPID_SIZE 28



unsigned long *mmio;
static struct kobject *dell_kobj;
Expand Down Expand Up @@ -1721,6 +1736,118 @@ static ssize_t show_psu(struct device *dev,
return sprintf(buf, "%u\n", pow);
}

/* FAN and PSU EEPROM PPID format is:
COUNTRY_CODE-PART_NO-MFG_ID-MFG_DATE_CODE-SERIAL_NO-LABEL_REV */
static ssize_t show_psu_ppid(struct device *dev,
struct device_attribute *devattr, char *buf)
{
int index = to_sensor_dev_attr(devattr)->index;
struct smf_data *data = dev_get_drvdata(dev);
char psu_ppid[EEPROM_PPID_SIZE + 1] = {0};
char psu_mfg_date[EEPROM_MFG_DATE_SIZE + 1] = {0};
char psu_mfg_date_code[EEPROM_DATE_CODE_SIZE + 1] = {0};
char temp;
int i, reg, ret = 0, ppid_pos = 0;

switch(index) {

case 1:
// PPID starts from Country Code
reg = PSU_1_COUNTRY_CODE;
break;
case 2:
reg = PSU_2_COUNTRY_CODE;
break;
default:
return ret;
}

// Get Country Code
for( i = 0; i < EEPROM_COUNTRY_CODE_SIZE; i++) {
psu_ppid[ppid_pos++] = (char)smf_read_reg(data,reg++);
}
psu_ppid[ppid_pos++] = '-';

// Get Part Number
for( i = 0; i < EEPROM_PART_NO_SIZE; i++) {
psu_ppid[ppid_pos++] = (char)smf_read_reg(data,reg++);
}
psu_ppid[ppid_pos++] = '-';

// Get Manufacture ID
for( i = 0; i < EEPROM_MFG_ID_SIZE; i++) {
psu_ppid[ppid_pos++] = (char)smf_read_reg(data,reg++);
}
psu_ppid[ppid_pos++] = '-';

// Get Manufacture date
for( i = 0; i < EEPROM_MFG_DATE_SIZE; i++) {
psu_mfg_date[i] = (char)smf_read_reg(data,reg++);
}

/* Converting 6 digit date code [yymmdd] to 3 digit[ymd]
Year Starting from 2010 [0-9] , Day : 1-9 and A-V , Month : 1-9 and A-C */
// Year Validation and Conversion
if( ( psu_mfg_date[0] == '1' ) && ( psu_mfg_date[1] >= '0' ) && ( psu_mfg_date[1] <= '9') )
{
psu_mfg_date_code[0] = psu_mfg_date[1];
}
else
{
psu_mfg_date_code[0] = ' ';
}

// Month Validation and Conversion
temp = ( ( psu_mfg_date[2] - 0x30 ) * 10 ) + ( psu_mfg_date[3] - 0x30 );
if( ( temp >= 1) && ( temp < 10) )
{
psu_mfg_date_code[1] = temp + 0x30; // 0- 9
}
else if ( ( temp >= 10) && ( temp <= 12) )
{
psu_mfg_date_code[1] = temp + 0x37; // A-C
}
else
{
psu_mfg_date_code[1]= ' ';
}

// Date Validation and Conversion
temp = ( ( psu_mfg_date[4] - 0x30 ) * 10 ) + ( psu_mfg_date[5] - 0x30 );
if( ( temp >= 1) && ( temp < 10) )
{
psu_mfg_date_code[2] = temp + 0x30; // 0- 9
}
else if( ( temp >= 10) && ( temp <= 31) )
{
psu_mfg_date_code[2] = temp + 0x37; // A-V
}
else
{
psu_mfg_date_code[2] = ' ';
}

for( i = 0; i < EEPROM_DATE_CODE_SIZE; i++) {
psu_ppid[ppid_pos++] = psu_mfg_date_code[i];
}
psu_ppid[ppid_pos++] = '-';

// Get Serial Number
for( i = 0; i < EEPROM_SERIAL_NO_SIZE; i++) {
psu_ppid[ppid_pos++] = (char)smf_read_reg(data,reg++);
}
psu_ppid[ppid_pos++] = '-';

// Skipping service tag in PPID
reg += EEPROM_SERVICE_TAG_SIZE;

// Get Label Revision
for( i = 0; i < EEPROM_LABEL_REV_SIZE; i++) {
psu_ppid[ppid_pos++] = (char)smf_read_reg(data,reg++);
}

return sprintf(buf, "%s\n",psu_ppid);
}

static umode_t smf_psu_is_visible(struct kobject *kobj,
struct attribute *a, int n)
Expand Down Expand Up @@ -1803,6 +1930,8 @@ static SENSOR_DEVICE_ATTR(iom_presence, S_IRUGO, show_voltage, NULL, 45);

static SENSOR_DEVICE_ATTR(psu1_presence, S_IRUGO, show_psu, NULL, 1);
static SENSOR_DEVICE_ATTR(psu2_presence, S_IRUGO, show_psu, NULL, 6);
static SENSOR_DEVICE_ATTR(psu1_serialno, S_IRUGO, show_psu_ppid, NULL, 1);
static SENSOR_DEVICE_ATTR(psu2_serialno, S_IRUGO, show_psu_ppid, NULL, 2);
static SENSOR_DEVICE_ATTR(current_total_power, S_IRUGO, show_psu, NULL, 10);

/* SMF Version */
Expand Down Expand Up @@ -1833,6 +1962,8 @@ static struct attribute *smf_dell_attrs[] = {
&sensor_dev_attr_iom_presence.dev_attr.attr,
&sensor_dev_attr_psu1_presence.dev_attr.attr,
&sensor_dev_attr_psu2_presence.dev_attr.attr,
&sensor_dev_attr_psu1_serialno.dev_attr.attr,
&sensor_dev_attr_psu2_serialno.dev_attr.attr,
&sensor_dev_attr_current_total_power.dev_attr.attr,
NULL
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@
try:
import os
from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform.psu import Psu
from sonic_platform.fan import Fan
except ImportError as e:
raise ImportError(str(e) + "- required module not found")

MAX_S6100_FAN = 4
MAX_S6100_PSU = 2


class Chassis(ChassisBase):
"""
Expand All @@ -39,19 +44,28 @@ class Chassis(ChassisBase):
def __init__(self):
ChassisBase.__init__(self)

for i in range(MAX_S6100_FAN):
fan = Fan(i)
self._fan_list.append(fan)

for i in range(MAX_S6100_PSU):
psu = Psu(i)
self._psu_list.append(psu)

def get_pmc_register(self, reg_name):
# On successful read, returns the value read from given
# reg_name and on failure returns 'ERR'
rv = 'ERR'
mb_reg_file = self.MAILBOX_DIR+'/'+reg_name
mb_reg_file = self.MAILBOX_DIR + '/' + reg_name

if (not os.path.isfile(mb_reg_file)):
print mb_reg_file, 'not found !'
return rv

try:
with open(mb_reg_file, 'r') as fd:
rv = fd.read()
except Exception as error:
logging.error("Unable to open ", mb_reg_file, "file !")
rv = 'ERR'

rv = rv.rstrip('\r\n')
rv = rv.lstrip(" ")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/usr/bin/env python

########################################################################
# DellEMC
#
# Module contains an implementation of SONiC Platform Base API and
# provides the Fans' information which are available in the platform
#
########################################################################


try:
import os
from sonic_platform_base.fan_base import FanBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")


MAX_S6100_PSU_FAN_SPEED = 18000
MAX_S6100_FAN_SPEED = 16000


class Fan(FanBase):
"""DellEMC Platform-specific FAN class"""

HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/"
HWMON_NODE = os.listdir(HWMON_DIR)[0]
MAILBOX_DIR = HWMON_DIR + HWMON_NODE

def __init__(self, fan_index, psu_fan=False):
self.is_psu_fan = psu_fan
if not self.is_psu_fan:
# Fan is 1-based in DellEMC platforms
self.index = fan_index + 1
self.get_fan_speed_reg = "fan{}_input".format(2*self.index - 1)
self.max_fan_speed = MAX_S6100_FAN_SPEED
else:
# PSU Fan index starts from 11
self.index = fan_index + 10
self.get_fan_speed_reg = "fan{}_input".format(self.index)
self.max_fan_speed = MAX_S6100_PSU_FAN_SPEED

Loading

0 comments on commit e520cbe

Please sign in to comment.