Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cel seastone platform apis #235

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 53 additions & 3 deletions device/celestica/x86_64-cel_seastone-r0/sonic_platform/chassis.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def __initialize_sfp(self):

from sonic_platform.sfp import Sfp
for index in range(0, NUM_SFP):
name_idx = 0 if index+1 == NUM_SFP else index+1
name_idx = 0 if index + 1 == NUM_SFP else index + 1
sfp = Sfp(index, sfputil_helper.logical[name_idx])
self._sfp_list.append(sfp)
self.sfp_module_initialized = True
Expand Down Expand Up @@ -155,7 +155,6 @@ def get_reboot_cause(self):

return prev_reboot_cause


def get_change_event(self, timeout=0):
"""
Returns a nested dictionary containing all devices which have
Expand Down Expand Up @@ -231,7 +230,7 @@ def get_sfp(self, index):

try:
# The index will start from 1
sfp = self._sfp_list[index-1]
sfp = self._sfp_list[index - 1]
except IndexError:
sys.stderr.write("SFP index {} out of range (1-{})\n".format(
index, len(self._sfp_list)))
Expand Down Expand Up @@ -301,3 +300,54 @@ def get_status(self):
def get_thermal_manager(self):
from .thermal_manager import ThermalManager
return ThermalManager

def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return -1

def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return False

def set_status_led(self, color):
"""
Sets the state of the PSU status LED
Args:
color: A string representing the color with which to set the PSU status LED
Note: Only support green and off
Returns:
bool: True if status LED state is set successfully, False if not
"""

set_status_str = {
self.STATUS_LED_COLOR_GREEN: '1',
self.STATUS_LED_COLOR_OFF: '0'
}.get(color, None)

if not set_status_str:
return False

return self._api_helper.write_txt_file(self.stat_led_path, set_status_str)

def get_status_led(self):
"""
Gets the state of the PSU status LED
Returns:
A string, one of the predefined STATUS_LED_COLOR_* strings above
"""
status = self._api_helper.read_txt_file(self.stat_led_path)
status_str = {
'255': self.STATUS_LED_COLOR_GREEN,
'0': self.STATUS_LED_COLOR_OFF
}.get(status, None)

return status_str
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ def _load_eeprom(self):
def get_eeprom(self):
return self._eeprom

def get_pn(self):
return self._eeprom.get('0x22', "Undefined.")

def get_serial(self):
return self._eeprom.get('0x23', "Undefined.")

Expand Down
189 changes: 182 additions & 7 deletions device/celestica/x86_64-cel_seastone-r0/sonic_platform/psu.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#############################################################################

import os
import sonic_platform
import time

try:
from sonic_platform_base.psu_base import PsuBase
Expand All @@ -16,6 +16,9 @@
except ImportError as e:
raise ImportError(str(e) + "- required module not found")

TLV_ATTR_TYPE_MODEL = 2
TLV_ATTR_TYPE_SERIAL = 5
PSU_EEPROM_PATH = "/sys/bus/i2c/devices/{}-00{}/eeprom"
GREEN_LED_PATH = "/sys/devices/platform/leds_dx010/leds/dx010:green:p-{}/brightness"
HWMON_PATH = "/sys/bus/i2c/devices/i2c-{0}/{0}-00{1}/hwmon"
GPIO_DIR = "/sys/class/gpio"
Expand All @@ -25,11 +28,13 @@
PSU_I2C_MAPPING = {
0: {
"num": 10,
"addr": "5a"
"addr": "5a",
"eeprom_addr": "52"
},
1: {
"num": 11,
"addr": "5b"
"addr": "5b",
"eeprom_addr": "53"
},
}

Expand All @@ -41,7 +46,7 @@ def __init__(self, psu_index):
PsuBase.__init__(self)
self.index = psu_index
self._api_helper = APIHelper()
self.green_led_path = GREEN_LED_PATH.format(self.index+1)
self.green_led_path = GREEN_LED_PATH.format(self.index + 1)
self.dx010_psu_gpio = [
{'base': self.__get_gpio_base()},
{'prs': 27, 'status': 22},
Expand All @@ -50,6 +55,7 @@ def __init__(self, psu_index):
self.i2c_num = PSU_I2C_MAPPING[self.index]["num"]
self.i2c_addr = PSU_I2C_MAPPING[self.index]["addr"]
self.hwmon_path = HWMON_PATH.format(self.i2c_num, self.i2c_addr)
self.eeprom_addr = PSU_EEPROM_PATH.format(self.i2c_num, PSU_I2C_MAPPING[self.index]["eeprom_addr"])
for fan_index in range(0, PSU_NUM_FAN[self.index]):
fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index)
self._fan_list.append(fan)
Expand All @@ -71,11 +77,37 @@ def __get_gpio_base(self):

def __get_gpio_value(self, pinnum):
gpio_base = self.dx010_psu_gpio[0]['base']
gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base+pinnum)
gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base + pinnum)
gpio_file = gpio_dir + "/value"
retval = self._api_helper.read_txt_file(gpio_file)
return retval.rstrip('\r\n')

def read_fru(self, path, attr_type):
content = []
attr_idx = 0
attr_length = 0

if(os.path.exists(path)):
with open(path, 'r', encoding='unicode_escape') as f:
content = f.read()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use the api_helper function to read the files?

Copy link
Author

@119064273 119064273 Feb 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better not, I need add " encoding='unicode_escape' " when use open, but in api_helper functions , it don't have it, if add it , i don't know if it will affect other functions

target_offset = ord(content[4])
target_offset *= 8 # spec defined: offset are in multiples of 8 bytes

attr_idx = target_offset + 3
for i in range(1, attr_type):
if attr_idx > len(content):
raise SyntaxError
attr_length = (ord(content[attr_idx])) & (0x3f)
attr_idx += (attr_length + 1)

attr_length = (ord(content[attr_idx])) & (0x3f)
attr_idx += 1
else:
print("[PSU] Can't find path to eeprom : %s" % path)
return SyntaxError

return content[attr_idx:attr_idx + attr_length]

def get_voltage(self):
"""
Retrieves current PSU voltage output
Expand Down Expand Up @@ -209,7 +241,7 @@ def get_presence(self):
Returns:
bool: True if PSU is present, False if not
"""
raw = self.__get_gpio_value(self.dx010_psu_gpio[self.index+1]['prs'])
raw = self.__get_gpio_value(self.dx010_psu_gpio[self.index + 1]['prs'])
return int(raw, 10) == 0

def get_status(self):
Expand All @@ -219,5 +251,148 @@ def get_status(self):
A boolean value, True if device is operating properly, False if not
"""
raw = self.__get_gpio_value(
self.dx010_psu_gpio[self.index+1]['status'])
self.dx010_psu_gpio[self.index + 1]['status'])
return int(raw, 10) == 1

def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
if not os.path.exists(self.eeprom_addr):
os.system('echo 24c02 0x{} > /sys/bus/i2c/devices/i2c-{}/new_device'.format(PSU_I2C_MAPPING[self.index]["eeprom_addr"], self.i2c_num))
time.sleep(5)
model = self.read_fru(self.eeprom_addr, TLV_ATTR_TYPE_MODEL)
if not model:
return "N/A"
return model

def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
if not os.path.exists(self.eeprom_addr):
os.system('echo 24c02 0x{} > /sys/bus/i2c/devices/i2c-{}/new_device'.format(PSU_I2C_MAPPING[self.index]["eeprom_addr"], self.i2c_num))
time.sleep(5)
serial = self.read_fru(self.eeprom_addr, TLV_ATTR_TYPE_SERIAL)
if not serial:
return "N/A"
return serial

def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return -1

def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True

def get_temperature(self):
"""
Retrieves current temperature reading from PSU
Returns:
A float number of current temperature in Celsius up to nearest thousandth
of one degree Celsius, e.g. 30.125
there are three temp sensors , we choose one of them
"""
psu_temperature = None
temperature_name = "temp{}_input"
temperature_label = "vout1"

vout_label_path = self.__search_file_by_contain(
self.hwmon_path, temperature_label, "in")
if vout_label_path:
dir_name = os.path.dirname(vout_label_path)
basename = os.path.basename(vout_label_path)
in_num = ''.join(list(filter(str.isdigit, basename)))
temp_path = os.path.join(
dir_name, temperature_name.format(in_num))
vout_val = self._api_helper.read_txt_file(temp_path)
psu_temperature = float(vout_val) / 1000

return psu_temperature

def get_temperature_high_threshold(self):
"""
Retrieves the high threshold temperature of PSU
Returns:
A float number, the high threshold temperature of PSU in Celsius
up to nearest thousandth of one degree Celsius, e.g. 30.125
there are three temp sensors , we choose one of them
"""
psu_temperature = None
temperature_name = "temp{}_max"
temperature_label = "vout1"

vout_label_path = self.__search_file_by_contain(
self.hwmon_path, temperature_label, "in")
if vout_label_path:
dir_name = os.path.dirname(vout_label_path)
basename = os.path.basename(vout_label_path)
in_num = ''.join(list(filter(str.isdigit, basename)))
temp_path = os.path.join(
dir_name, temperature_name.format(in_num))
vout_val = self._api_helper.read_txt_file(temp_path)
psu_temperature = float(vout_val) / 1000

return psu_temperature

def get_voltage_high_threshold(self):
"""
Retrieves the high threshold PSU voltage output
Returns:
A float number, the high threshold output voltage in volts,
e.g. 12.1
"""
psu_voltage = 0.0
voltage_name = "in{}_crit"
voltage_label = "vout1"

vout_label_path = self.__search_file_by_contain(
self.hwmon_path, voltage_label, "in")
if vout_label_path:
dir_name = os.path.dirname(vout_label_path)
basename = os.path.basename(vout_label_path)
in_num = ''.join(list(filter(str.isdigit, basename)))
vout_path = os.path.join(
dir_name, voltage_name.format(in_num))
vout_val = self._api_helper.read_txt_file(vout_path)
psu_voltage = float(vout_val) / 1000

return psu_voltage

def get_voltage_low_threshold(self):
"""
Retrieves the low threshold PSU voltage output
Returns:
A float number, the low threshold output voltage in volts,
e.g. 12.1
"""
psu_voltage = 0.0
voltage_name = "in{}_lcrit"
voltage_label = "vout1"

vout_label_path = self.__search_file_by_contain(
self.hwmon_path, voltage_label, "in")
if vout_label_path:
dir_name = os.path.dirname(vout_label_path)
basename = os.path.basename(vout_label_path)
in_num = ''.join(list(filter(str.isdigit, basename)))
vout_path = os.path.join(
dir_name, voltage_name.format(in_num))
vout_val = self._api_helper.read_txt_file(vout_path)
psu_voltage = float(vout_val) / 1000

return psu_voltage