[device/celestica]: Update DX010 platform APIS on 201911 branch (#5416)
* [device/celestica]: DX010 platform API update (#4608) - Fix fancontrol.service path - Fix return temp format in thermal API - Improve init time in chassis API - Upgrade sfp API * [device/celestica]: Update DX010 reboot cause API (#4678) - Add more cases support in DX010 reboot cause API - Add Thermal Overload reboot cause support - Add new Watchdog reboot cause support * [device/celestica]: using sonic-py-common package
This commit is contained in:
parent
6ae77f87cc
commit
10534a39eb
@ -9,3 +9,5 @@ MINSTOP=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/
|
|||||||
MINPWM=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/pwm5=89 13-004d/pwm1=89 13-004d/pwm2=89 13-004d/pwm3=89 13-004d/pwm4=89 13-004d/pwm5=89
|
MINPWM=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/pwm5=89 13-004d/pwm1=89 13-004d/pwm2=89 13-004d/pwm3=89 13-004d/pwm4=89 13-004d/pwm5=89
|
||||||
MAXPWM=13-002e/pwm1=255 13-002e/pwm2=255 13-002e/pwm3=255 13-002e/pwm4=255 13-002e/pwm5=255 13-004d/pwm1=255 13-004d/pwm2=255 13-004d/pwm3=255 13-004d/pwm4=255 13-004d/pwm5=255
|
MAXPWM=13-002e/pwm1=255 13-002e/pwm2=255 13-002e/pwm3=255 13-002e/pwm4=255 13-002e/pwm5=255 13-004d/pwm1=255 13-004d/pwm2=255 13-004d/pwm3=255 13-004d/pwm4=255 13-004d/pwm5=255
|
||||||
THYST=13-002e/pwm1=3 13-002e/pwm2=3 13-002e/pwm3=3 13-002e/pwm4=3 13-002e/pwm5=3 13-004d/pwm1=3 13-004d/pwm2=3 13-004d/pwm3=3 13-004d/pwm4=3 13-004d/pwm5=3
|
THYST=13-002e/pwm1=3 13-002e/pwm2=3 13-002e/pwm3=3 13-002e/pwm4=3 13-002e/pwm5=3 13-004d/pwm1=3 13-004d/pwm2=3 13-004d/pwm3=3 13-004d/pwm4=3 13-004d/pwm5=3
|
||||||
|
MAXTEMPCRIT=/sys/bus/i2c/devices/7-004a/hwmon/hwmon*/temp1_input=65 /sys/bus/i2c/devices/14-0048/hwmon/hwmon*/temp1_input=75
|
||||||
|
MAXTEMPTYPE=/sys/bus/i2c/devices/7-004a/hwmon/hwmon*/temp1_input=ASIC /sys/bus/i2c/devices/14-0048/hwmon/hwmon*/temp1_input=CPU
|
||||||
|
@ -9,4 +9,5 @@ MINSTOP=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/
|
|||||||
MINPWM=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/pwm5=89 13-004d/pwm1=89 13-004d/pwm2=89 13-004d/pwm3=89 13-004d/pwm4=89 13-004d/pwm5=89
|
MINPWM=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/pwm5=89 13-004d/pwm1=89 13-004d/pwm2=89 13-004d/pwm3=89 13-004d/pwm4=89 13-004d/pwm5=89
|
||||||
MAXPWM=13-002e/pwm1=255 13-002e/pwm2=255 13-002e/pwm3=255 13-002e/pwm4=255 13-002e/pwm5=255 13-004d/pwm1=255 13-004d/pwm2=255 13-004d/pwm3=255 13-004d/pwm4=255 13-004d/pwm5=255
|
MAXPWM=13-002e/pwm1=255 13-002e/pwm2=255 13-002e/pwm3=255 13-002e/pwm4=255 13-002e/pwm5=255 13-004d/pwm1=255 13-004d/pwm2=255 13-004d/pwm3=255 13-004d/pwm4=255 13-004d/pwm5=255
|
||||||
THYST=13-002e/pwm1=3 13-002e/pwm2=3 13-002e/pwm3=3 13-002e/pwm4=3 13-002e/pwm5=3 13-004d/pwm1=3 13-004d/pwm2=3 13-004d/pwm3=3 13-004d/pwm4=3 13-004d/pwm5=3
|
THYST=13-002e/pwm1=3 13-002e/pwm2=3 13-002e/pwm3=3 13-002e/pwm4=3 13-002e/pwm5=3 13-004d/pwm1=3 13-004d/pwm2=3 13-004d/pwm3=3 13-004d/pwm4=3 13-004d/pwm5=3
|
||||||
|
MAXTEMPCRIT=/sys/bus/i2c/devices/7-004a/hwmon/hwmon*/temp1_input=75 /sys/bus/i2c/devices/14-0048/hwmon/hwmon*/temp1_input=75
|
||||||
|
MAXTEMPTYPE=/sys/bus/i2c/devices/7-004a/hwmon/hwmon*/temp1_input=ASIC /sys/bus/i2c/devices/14-0048/hwmon/hwmon*/temp1_input=CPU
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
__all__ = ["platform", "chassis"]
|
import chassis
|
||||||
from sonic_platform import *
|
import platform
|
||||||
|
@ -8,20 +8,10 @@
|
|||||||
#
|
#
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
import sys
|
|
||||||
import re
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import json
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
import sys
|
||||||
from sonic_platform_base.chassis_base import ChassisBase
|
from sonic_platform_base.chassis_base import ChassisBase
|
||||||
from sonic_platform.fan import Fan
|
from helper import APIHelper
|
||||||
from sonic_platform.psu import Psu
|
|
||||||
from sonic_platform.component import Component
|
|
||||||
from sonic_platform.thermal import Thermal
|
|
||||||
from sonic_platform.sfp import Sfp
|
|
||||||
from sonic_platform.eeprom import Tlv
|
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(str(e) + "- required module not found")
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
@ -33,9 +23,9 @@ NUM_SFP = 32
|
|||||||
NUM_COMPONENT = 5
|
NUM_COMPONENT = 5
|
||||||
RESET_REGISTER = "0x103"
|
RESET_REGISTER = "0x103"
|
||||||
HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/"
|
HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/"
|
||||||
PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/"
|
|
||||||
REBOOT_CAUSE_FILE = "reboot-cause.txt"
|
REBOOT_CAUSE_FILE = "reboot-cause.txt"
|
||||||
PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt"
|
PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt"
|
||||||
|
GETREG_PATH = "/sys/devices/platform/dx010_cpld/getreg"
|
||||||
HOST_CHK_CMD = "docker > /dev/null 2>&1"
|
HOST_CHK_CMD = "docker > /dev/null 2>&1"
|
||||||
|
|
||||||
|
|
||||||
@ -44,39 +34,54 @@ class Chassis(ChassisBase):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
ChassisBase.__init__(self)
|
ChassisBase.__init__(self)
|
||||||
self.config_data = {}
|
self._api_helper = APIHelper()
|
||||||
|
self.sfp_module_initialized = False
|
||||||
|
self.__initialize_eeprom()
|
||||||
|
self.is_host = self._api_helper.is_host()
|
||||||
|
|
||||||
|
if not self.is_host:
|
||||||
|
self.__initialize_fan()
|
||||||
|
self.__initialize_psu()
|
||||||
|
self.__initialize_thermals()
|
||||||
|
else:
|
||||||
|
self.__initialize_components()
|
||||||
|
|
||||||
|
def __initialize_sfp(self):
|
||||||
|
from sonic_platform.sfp import Sfp
|
||||||
|
for index in range(0, NUM_SFP):
|
||||||
|
sfp = Sfp(index)
|
||||||
|
self._sfp_list.append(sfp)
|
||||||
|
self.sfp_module_initialized = True
|
||||||
|
|
||||||
|
def __initialize_psu(self):
|
||||||
|
from sonic_platform.psu import Psu
|
||||||
|
for index in range(0, NUM_PSU):
|
||||||
|
psu = Psu(index)
|
||||||
|
self._psu_list.append(psu)
|
||||||
|
|
||||||
|
def __initialize_fan(self):
|
||||||
|
from sonic_platform.fan import Fan
|
||||||
for fant_index in range(0, NUM_FAN_TRAY):
|
for fant_index in range(0, NUM_FAN_TRAY):
|
||||||
for fan_index in range(0, NUM_FAN):
|
for fan_index in range(0, NUM_FAN):
|
||||||
fan = Fan(fant_index, fan_index)
|
fan = Fan(fant_index, fan_index)
|
||||||
self._fan_list.append(fan)
|
self._fan_list.append(fan)
|
||||||
for index in range(0, NUM_PSU):
|
|
||||||
psu = Psu(index)
|
def __initialize_thermals(self):
|
||||||
self._psu_list.append(psu)
|
from sonic_platform.thermal import Thermal
|
||||||
for index in range(0, NUM_THERMAL):
|
for index in range(0, NUM_THERMAL):
|
||||||
thermal = Thermal(index)
|
thermal = Thermal(index)
|
||||||
self._thermal_list.append(thermal)
|
self._thermal_list.append(thermal)
|
||||||
# sfp index start from 1
|
|
||||||
for index in range(0, NUM_SFP):
|
def __initialize_eeprom(self):
|
||||||
sfp = Sfp(index)
|
from sonic_platform.eeprom import Tlv
|
||||||
self._sfp_list.append(sfp)
|
self._eeprom = Tlv()
|
||||||
|
|
||||||
|
def __initialize_components(self):
|
||||||
|
from sonic_platform.component import Component
|
||||||
for index in range(0, NUM_COMPONENT):
|
for index in range(0, NUM_COMPONENT):
|
||||||
component = Component(index)
|
component = Component(index)
|
||||||
self._component_list.append(component)
|
self._component_list.append(component)
|
||||||
|
|
||||||
self._eeprom = Tlv()
|
|
||||||
|
|
||||||
def __is_host(self):
|
|
||||||
return os.system(HOST_CHK_CMD) == 0
|
|
||||||
|
|
||||||
def __read_txt_file(self, file_path):
|
|
||||||
try:
|
|
||||||
with open(file_path, 'r') as fd:
|
|
||||||
data = fd.read()
|
|
||||||
return data.strip()
|
|
||||||
except IOError:
|
|
||||||
pass
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_base_mac(self):
|
def get_base_mac(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the base MAC address for the chassis
|
Retrieves the base MAC address for the chassis
|
||||||
@ -107,44 +112,98 @@ class Chassis(ChassisBase):
|
|||||||
def get_reboot_cause(self):
|
def get_reboot_cause(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the cause of the previous reboot
|
Retrieves the cause of the previous reboot
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A tuple (string, string) where the first element is a string
|
A tuple (string, string) where the first element is a string
|
||||||
containing the cause of the previous reboot. This string must be
|
containing the cause of the previous reboot. This string must be
|
||||||
one of the predefined strings in this class. If the first string
|
one of the predefined strings in this class. If the first string
|
||||||
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
|
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
|
||||||
to pass a description of the reboot cause.
|
to pass a description of the reboot cause.
|
||||||
|
|
||||||
|
REBOOT_CAUSE_POWER_LOSS = "Power Loss"
|
||||||
|
REBOOT_CAUSE_THERMAL_OVERLOAD_CPU = "Thermal Overload: CPU"
|
||||||
|
REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC = "Thermal Overload: ASIC"
|
||||||
|
REBOOT_CAUSE_THERMAL_OVERLOAD_OTHER = "Thermal Overload: Other"
|
||||||
|
REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED = "Insufficient Fan Speed"
|
||||||
|
REBOOT_CAUSE_WATCHDOG = "Watchdog"
|
||||||
|
REBOOT_CAUSE_HARDWARE_OTHER = "Hardware - Other"
|
||||||
|
REBOOT_CAUSE_NON_HARDWARE = "Non-Hardware"
|
||||||
|
|
||||||
"""
|
"""
|
||||||
description = 'None'
|
reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE)
|
||||||
reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER
|
sw_reboot_cause = self._api_helper.read_txt_file(
|
||||||
|
|
||||||
reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE) if self.__is_host(
|
|
||||||
) else PMON_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE
|
|
||||||
prev_reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE) if self.__is_host(
|
|
||||||
) else PMON_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE
|
|
||||||
|
|
||||||
hw_reboot_cause = self._component_list[0].get_register_value(RESET_REGISTER)
|
|
||||||
|
|
||||||
sw_reboot_cause = self.__read_txt_file(
|
|
||||||
reboot_cause_path) or "Unknown"
|
reboot_cause_path) or "Unknown"
|
||||||
prev_sw_reboot_cause = self.__read_txt_file(
|
hw_reboot_cause = self._api_helper.get_cpld_reg_value(
|
||||||
prev_reboot_cause_path) or "Unknown"
|
GETREG_PATH, RESET_REGISTER)
|
||||||
|
|
||||||
if sw_reboot_cause == "Unknown" and (prev_sw_reboot_cause == "Unknown" or prev_sw_reboot_cause == self.REBOOT_CAUSE_POWER_LOSS) and hw_reboot_cause == "0x11":
|
prev_reboot_cause = {
|
||||||
reboot_cause = self.REBOOT_CAUSE_POWER_LOSS
|
'0x11': (self.REBOOT_CAUSE_POWER_LOSS, 'Power on reset'),
|
||||||
elif sw_reboot_cause != "Unknown" and hw_reboot_cause == "0x11":
|
'0x22': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'CPLD_WD_RESET'),
|
||||||
reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE
|
'0x33': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Power cycle reset triggered by CPU'),
|
||||||
description = sw_reboot_cause
|
'0x44': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Power cycle reset triggered by reset button'),
|
||||||
elif prev_reboot_cause_path != "Unknown" and hw_reboot_cause == "0x11":
|
'0x55': (self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU, ''),
|
||||||
reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE
|
'0x66': (self.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC, ''),
|
||||||
description = prev_sw_reboot_cause
|
'0x77': (self.REBOOT_CAUSE_WATCHDOG, '')
|
||||||
elif hw_reboot_cause == "0x22":
|
}.get(hw_reboot_cause, (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Unknown reason'))
|
||||||
reboot_cause = self.REBOOT_CAUSE_WATCHDOG,
|
|
||||||
else:
|
|
||||||
reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER
|
|
||||||
description = 'Unknown reason'
|
|
||||||
|
|
||||||
return (reboot_cause, description)
|
if sw_reboot_cause != 'Unknown' and hw_reboot_cause == '0x11':
|
||||||
|
prev_reboot_cause = (
|
||||||
|
self.REBOOT_CAUSE_NON_HARDWARE, sw_reboot_cause)
|
||||||
|
|
||||||
|
return prev_reboot_cause
|
||||||
|
|
||||||
|
##############################################################
|
||||||
|
######################## SFP methods #########################
|
||||||
|
##############################################################
|
||||||
|
|
||||||
|
def get_num_sfps(self):
|
||||||
|
"""
|
||||||
|
Retrieves the number of sfps available on this chassis
|
||||||
|
Returns:
|
||||||
|
An integer, the number of sfps available on this chassis
|
||||||
|
"""
|
||||||
|
if not self.sfp_module_initialized:
|
||||||
|
self.__initialize_sfp()
|
||||||
|
|
||||||
|
return len(self._sfp_list)
|
||||||
|
|
||||||
|
def get_all_sfps(self):
|
||||||
|
"""
|
||||||
|
Retrieves all sfps available on this chassis
|
||||||
|
Returns:
|
||||||
|
A list of objects derived from SfpBase representing all sfps
|
||||||
|
available on this chassis
|
||||||
|
"""
|
||||||
|
if not self.sfp_module_initialized:
|
||||||
|
self.__initialize_sfp()
|
||||||
|
|
||||||
|
return self._sfp_list
|
||||||
|
|
||||||
|
def get_sfp(self, index):
|
||||||
|
"""
|
||||||
|
Retrieves sfp represented by (1-based) index <index>
|
||||||
|
Args:
|
||||||
|
index: An integer, the index (1-based) of the sfp to retrieve.
|
||||||
|
The index should be the sequence of a physical port in a chassis,
|
||||||
|
starting from 1.
|
||||||
|
For example, 1 for Ethernet0, 2 for Ethernet4 and so on.
|
||||||
|
Returns:
|
||||||
|
An object dervied from SfpBase representing the specified sfp
|
||||||
|
"""
|
||||||
|
sfp = None
|
||||||
|
if not self.sfp_module_initialized:
|
||||||
|
self.__initialize_sfp()
|
||||||
|
|
||||||
|
try:
|
||||||
|
# The index will start from 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)))
|
||||||
|
return sfp
|
||||||
|
|
||||||
|
##############################################################
|
||||||
|
####################### Other methods ########################
|
||||||
|
##############################################################
|
||||||
|
|
||||||
def get_watchdog(self):
|
def get_watchdog(self):
|
||||||
"""
|
"""
|
||||||
@ -159,23 +218,46 @@ class Chassis(ChassisBase):
|
|||||||
|
|
||||||
return self._watchdog
|
return self._watchdog
|
||||||
|
|
||||||
def get_sfp(self, index):
|
##############################################################
|
||||||
"""
|
###################### Device methods ########################
|
||||||
Retrieves sfp represented by (1-based) index <index>
|
##############################################################
|
||||||
Args:
|
|
||||||
index: An integer, the index (1-based) of the sfp to retrieve.
|
|
||||||
The index should be the sequence of a physical port in a chassis,
|
|
||||||
starting from 1.
|
|
||||||
For example, 1 for Ethernet0, 2 for Ethernet4 and so on.
|
|
||||||
Returns:
|
|
||||||
An object dervied from SfpBase representing the specified sfp
|
|
||||||
"""
|
|
||||||
sfp = None
|
|
||||||
|
|
||||||
try:
|
def get_name(self):
|
||||||
# The index will start from 1
|
"""
|
||||||
sfp = self._sfp_list[index-1]
|
Retrieves the name of the device
|
||||||
except IndexError:
|
Returns:
|
||||||
sys.stderr.write("SFP index {} out of range (1-{})\n".format(
|
string: The name of the device
|
||||||
index, len(self._sfp_list)))
|
"""
|
||||||
return sfp
|
return self._api_helper.hwsku
|
||||||
|
|
||||||
|
def get_presence(self):
|
||||||
|
"""
|
||||||
|
Retrieves the presence of the Chassis
|
||||||
|
Returns:
|
||||||
|
bool: True if Chassis is present, False if not
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_model(self):
|
||||||
|
"""
|
||||||
|
Retrieves the model number (or part number) of the device
|
||||||
|
Returns:
|
||||||
|
string: Model/part number of device
|
||||||
|
"""
|
||||||
|
return self._eeprom.get_pn()
|
||||||
|
|
||||||
|
def get_serial(self):
|
||||||
|
"""
|
||||||
|
Retrieves the serial number of the device
|
||||||
|
Returns:
|
||||||
|
string: Serial number of device
|
||||||
|
"""
|
||||||
|
return self.get_serial_number()
|
||||||
|
|
||||||
|
def get_status(self):
|
||||||
|
"""
|
||||||
|
Retrieves the operational status of the device
|
||||||
|
Returns:
|
||||||
|
A boolean value, True if device is operating properly, False if not
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
@ -8,14 +8,13 @@
|
|||||||
#
|
#
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
import json
|
|
||||||
import os.path
|
import os.path
|
||||||
import shutil
|
import shutil
|
||||||
import shlex
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from sonic_platform_base.component_base import ComponentBase
|
from sonic_platform_base.component_base import ComponentBase
|
||||||
|
from helper import APIHelper
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(str(e) + "- required module not found")
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
@ -29,7 +28,8 @@ CPLD_ADDR_MAPPING = {
|
|||||||
GETREG_PATH = "/sys/devices/platform/dx010_cpld/getreg"
|
GETREG_PATH = "/sys/devices/platform/dx010_cpld/getreg"
|
||||||
BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version"
|
BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version"
|
||||||
COMPONENT_NAME_LIST = ["CPLD1", "CPLD2", "CPLD3", "CPLD4", "BIOS"]
|
COMPONENT_NAME_LIST = ["CPLD1", "CPLD2", "CPLD3", "CPLD4", "BIOS"]
|
||||||
COMPONENT_DES_LIST = ["CPLD1", "CPLD2", "CPLD3", "CPLD4", "Basic Input/Output System"]
|
COMPONENT_DES_LIST = ["Used for managing the CPU",
|
||||||
|
"Used for managing QSFP+ ports (1-10)", "Used for managing QSFP+ ports (11-20)", "Used for managing QSFP+ ports (22-32)", "Basic Input/Output System"]
|
||||||
|
|
||||||
|
|
||||||
class Component(ComponentBase):
|
class Component(ComponentBase):
|
||||||
@ -40,24 +40,9 @@ class Component(ComponentBase):
|
|||||||
def __init__(self, component_index):
|
def __init__(self, component_index):
|
||||||
ComponentBase.__init__(self)
|
ComponentBase.__init__(self)
|
||||||
self.index = component_index
|
self.index = component_index
|
||||||
|
self._api_helper = APIHelper()
|
||||||
self.name = self.get_name()
|
self.name = self.get_name()
|
||||||
|
|
||||||
def __run_command(self, command):
|
|
||||||
# Run bash command and print output to stdout
|
|
||||||
try:
|
|
||||||
process = subprocess.Popen(
|
|
||||||
shlex.split(command), stdout=subprocess.PIPE)
|
|
||||||
while True:
|
|
||||||
output = process.stdout.readline()
|
|
||||||
if output == '' and process.poll() is not None:
|
|
||||||
break
|
|
||||||
rc = process.poll()
|
|
||||||
if rc != 0:
|
|
||||||
return False
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def __get_bios_version(self):
|
def __get_bios_version(self):
|
||||||
# Retrieves the BIOS firmware version
|
# Retrieves the BIOS firmware version
|
||||||
try:
|
try:
|
||||||
|
@ -14,6 +14,7 @@ import os.path
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
from sonic_platform_base.fan_base import FanBase
|
from sonic_platform_base.fan_base import FanBase
|
||||||
|
from helper import APIHelper
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(str(e) + "- required module not found")
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
@ -38,13 +39,16 @@ PSU_I2C_MAPPING = {
|
|||||||
"addr": "5b"
|
"addr": "5b"
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
NULL_VAL = "N/A"
|
||||||
|
|
||||||
|
|
||||||
class Fan(FanBase):
|
class Fan(FanBase):
|
||||||
"""Platform-specific Fan class"""
|
"""Platform-specific Fan class"""
|
||||||
|
|
||||||
def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0):
|
def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0):
|
||||||
|
FanBase.__init__(self)
|
||||||
self.fan_index = fan_index
|
self.fan_index = fan_index
|
||||||
|
self._api_helper = APIHelper()
|
||||||
self.fan_tray_index = fan_tray_index
|
self.fan_tray_index = fan_tray_index
|
||||||
self.is_psu_fan = is_psu_fan
|
self.is_psu_fan = is_psu_fan
|
||||||
if self.is_psu_fan:
|
if self.is_psu_fan:
|
||||||
@ -75,16 +79,6 @@ class Fan(FanBase):
|
|||||||
{'prs': 14, 'dir': 19, 'color': {'red': 37, 'green': 38}}, # 4
|
{'prs': 14, 'dir': 19, 'color': {'red': 37, 'green': 38}}, # 4
|
||||||
{'prs': 12, 'dir': 17, 'color': {'red': 33, 'green': 34}}, # 5
|
{'prs': 12, 'dir': 17, 'color': {'red': 33, 'green': 34}}, # 5
|
||||||
]
|
]
|
||||||
FanBase.__init__(self)
|
|
||||||
|
|
||||||
def __read_txt_file(self, file_path):
|
|
||||||
try:
|
|
||||||
with open(file_path, 'r') as fd:
|
|
||||||
data = fd.read()
|
|
||||||
return data.strip()
|
|
||||||
except IOError:
|
|
||||||
pass
|
|
||||||
return ""
|
|
||||||
|
|
||||||
def __write_txt_file(self, file_path, value):
|
def __write_txt_file(self, file_path, value):
|
||||||
try:
|
try:
|
||||||
@ -105,7 +99,7 @@ class Fan(FanBase):
|
|||||||
def __get_gpio_base(self):
|
def __get_gpio_base(self):
|
||||||
for r in os.listdir(GPIO_DIR):
|
for r in os.listdir(GPIO_DIR):
|
||||||
label_path = os.path.join(GPIO_DIR, r, "label")
|
label_path = os.path.join(GPIO_DIR, r, "label")
|
||||||
if "gpiochip" in r and GPIO_LABEL in self.__read_txt_file(label_path):
|
if "gpiochip" in r and GPIO_LABEL in self._api_helper.read_txt_file(label_path):
|
||||||
return int(r[8:], 10)
|
return int(r[8:], 10)
|
||||||
return 216 # Reserve
|
return 216 # Reserve
|
||||||
|
|
||||||
@ -113,7 +107,7 @@ class Fan(FanBase):
|
|||||||
gpio_base = self.dx010_fan_gpio[0]['base']
|
gpio_base = self.dx010_fan_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"
|
gpio_file = gpio_dir + "/value"
|
||||||
retval = self.__read_txt_file(gpio_file)
|
retval = self._api_helper.read_txt_file(gpio_file)
|
||||||
return retval.rstrip('\r\n')
|
return retval.rstrip('\r\n')
|
||||||
|
|
||||||
def __set_gpio_value(self, pinnum, value=0):
|
def __set_gpio_value(self, pinnum, value=0):
|
||||||
@ -154,7 +148,8 @@ class Fan(FanBase):
|
|||||||
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
|
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
|
||||||
fan_speed_sysfs_path = self.__search_file_by_name(
|
fan_speed_sysfs_path = self.__search_file_by_name(
|
||||||
self.psu_hwmon_path, fan_speed_sysfs_name)
|
self.psu_hwmon_path, fan_speed_sysfs_name)
|
||||||
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
|
fan_speed_rpm = self._api_helper.read_txt_file(
|
||||||
|
fan_speed_sysfs_path) or 0
|
||||||
fan_speed_raw = float(fan_speed_rpm)/PSU_FAN_MAX_RPM * 100
|
fan_speed_raw = float(fan_speed_rpm)/PSU_FAN_MAX_RPM * 100
|
||||||
speed = math.ceil(float(fan_speed_rpm) * 100 / PSU_FAN_MAX_RPM)
|
speed = math.ceil(float(fan_speed_rpm) * 100 / PSU_FAN_MAX_RPM)
|
||||||
elif self.get_presence():
|
elif self.get_presence():
|
||||||
@ -164,7 +159,7 @@ class Fan(FanBase):
|
|||||||
sysfs_path = "%s%s/%s" % (
|
sysfs_path = "%s%s/%s" % (
|
||||||
EMC2305_PATH, device, EMC2305_FAN_INPUT)
|
EMC2305_PATH, device, EMC2305_FAN_INPUT)
|
||||||
sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index])
|
sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index])
|
||||||
raw = self.__read_txt_file(sysfs_path).strip('\r\n')
|
raw = self._api_helper.read_txt_file(sysfs_path).strip('\r\n')
|
||||||
pwm = int(raw, 10) if raw else 0
|
pwm = int(raw, 10) if raw else 0
|
||||||
speed = math.ceil(float(pwm * 100 / EMC2305_MAX_PWM))
|
speed = math.ceil(float(pwm * 100 / EMC2305_MAX_PWM))
|
||||||
|
|
||||||
@ -183,19 +178,7 @@ class Fan(FanBase):
|
|||||||
0 : when PWM mode is use
|
0 : when PWM mode is use
|
||||||
pwm : when pwm mode is not use
|
pwm : when pwm mode is not use
|
||||||
"""
|
"""
|
||||||
target = 0
|
return 'N/A'
|
||||||
if not self.is_psu_fan:
|
|
||||||
chip = self.emc2305_chip_mapping[self.fan_index]
|
|
||||||
device = chip['device']
|
|
||||||
fan_index = chip['index_map']
|
|
||||||
sysfs_path = "%s%s/%s" % (
|
|
||||||
EMC2305_PATH, device, EMC2305_FAN_TARGET)
|
|
||||||
sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index])
|
|
||||||
raw = self.__read_txt_file(sysfs_path).strip('\r\n')
|
|
||||||
pwm = int(raw, 10) if raw else 0
|
|
||||||
target = math.ceil(float(pwm) * 100 / EMC2305_MAX_PWM)
|
|
||||||
|
|
||||||
return target
|
|
||||||
|
|
||||||
def get_speed_tolerance(self):
|
def get_speed_tolerance(self):
|
||||||
"""
|
"""
|
||||||
@ -284,11 +267,43 @@ class Fan(FanBase):
|
|||||||
|
|
||||||
def get_presence(self):
|
def get_presence(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the presence of the PSU
|
Retrieves the presence of the FAN
|
||||||
Returns:
|
Returns:
|
||||||
bool: True if PSU is present, False if not
|
bool: True if FAN is present, False if not
|
||||||
"""
|
"""
|
||||||
present_str = self.__get_gpio_value(
|
present_str = self.__get_gpio_value(
|
||||||
self.dx010_fan_gpio[self.fan_tray_index+1]['prs'])
|
self.dx010_fan_gpio[self.fan_tray_index+1]['prs'])
|
||||||
|
|
||||||
return int(present_str, 10) == 0 if not self.is_psu_fan else True
|
return int(present_str, 10) == 0 if not self.is_psu_fan else True
|
||||||
|
|
||||||
|
def get_model(self):
|
||||||
|
"""
|
||||||
|
Retrieves the model number (or part number) of the device
|
||||||
|
Returns:
|
||||||
|
string: Model/part number of device
|
||||||
|
"""
|
||||||
|
if self.is_psu_fan:
|
||||||
|
return NULL_VAL
|
||||||
|
|
||||||
|
model = NULL_VAL
|
||||||
|
return model
|
||||||
|
|
||||||
|
def get_serial(self):
|
||||||
|
"""
|
||||||
|
Retrieves the serial number of the device
|
||||||
|
Returns:
|
||||||
|
string: Serial number of device
|
||||||
|
"""
|
||||||
|
if self.is_psu_fan:
|
||||||
|
return NULL_VAL
|
||||||
|
|
||||||
|
serial = NULL_VAL
|
||||||
|
return serial
|
||||||
|
|
||||||
|
def get_status(self):
|
||||||
|
"""
|
||||||
|
Retrieves the operational status of the device
|
||||||
|
Returns:
|
||||||
|
A boolean value, True if device is operating properly, False if not
|
||||||
|
"""
|
||||||
|
return self.get_presence() and self.get_speed() > 0
|
||||||
|
134
device/celestica/x86_64-cel_seastone-r0/sonic_platform/helper.py
Normal file
134
device/celestica/x86_64-cel_seastone-r0/sonic_platform/helper.py
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import os
|
||||||
|
import struct
|
||||||
|
import subprocess
|
||||||
|
from sonic_py_common import device_info
|
||||||
|
from mmap import *
|
||||||
|
|
||||||
|
HOST_CHK_CMD = "docker > /dev/null 2>&1"
|
||||||
|
EMPTY_STRING = ""
|
||||||
|
|
||||||
|
|
||||||
|
class APIHelper():
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
(self.platform, self.hwsku) = device_info.get_platform_and_hwsku()
|
||||||
|
|
||||||
|
def is_host(self):
|
||||||
|
return os.system(HOST_CHK_CMD) == 0
|
||||||
|
|
||||||
|
def pci_get_value(self, resource, offset):
|
||||||
|
status = True
|
||||||
|
result = ""
|
||||||
|
try:
|
||||||
|
fd = os.open(resource, os.O_RDWR)
|
||||||
|
mm = mmap(fd, 0)
|
||||||
|
mm.seek(int(offset))
|
||||||
|
read_data_stream = mm.read(4)
|
||||||
|
result = struct.unpack('I', read_data_stream)
|
||||||
|
except:
|
||||||
|
status = False
|
||||||
|
return status, result
|
||||||
|
|
||||||
|
def run_command(self, cmd):
|
||||||
|
status = True
|
||||||
|
result = ""
|
||||||
|
try:
|
||||||
|
p = subprocess.Popen(
|
||||||
|
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
raw_data, err = p.communicate()
|
||||||
|
if err == '':
|
||||||
|
result = raw_data.strip()
|
||||||
|
except:
|
||||||
|
status = False
|
||||||
|
return status, result
|
||||||
|
|
||||||
|
def run_interactive_command(self, cmd):
|
||||||
|
try:
|
||||||
|
os.system(cmd)
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def read_txt_file(self, file_path):
|
||||||
|
try:
|
||||||
|
with open(file_path, 'r') as fd:
|
||||||
|
data = fd.read()
|
||||||
|
return data.strip()
|
||||||
|
except IOError:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
def read_one_line_file(self, file_path):
|
||||||
|
try:
|
||||||
|
with open(file_path, 'r') as fd:
|
||||||
|
data = fd.readline()
|
||||||
|
return data.strip()
|
||||||
|
except IOError:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
def write_txt_file(self, file_path, value):
|
||||||
|
try:
|
||||||
|
with open(file_path, 'w') as fd:
|
||||||
|
fd.write(str(value))
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_cpld_reg_value(self, getreg_path, register):
|
||||||
|
cmd = "echo {1} > {0}; cat {0}".format(getreg_path, register)
|
||||||
|
status, result = self.run_command(cmd)
|
||||||
|
return result if status else None
|
||||||
|
|
||||||
|
def ipmi_raw(self, netfn, cmd):
|
||||||
|
status = True
|
||||||
|
result = ""
|
||||||
|
try:
|
||||||
|
cmd = "ipmitool raw {} {}".format(str(netfn), str(cmd))
|
||||||
|
p = subprocess.Popen(
|
||||||
|
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
raw_data, err = p.communicate()
|
||||||
|
if err == '':
|
||||||
|
result = raw_data.strip()
|
||||||
|
else:
|
||||||
|
status = False
|
||||||
|
except:
|
||||||
|
status = False
|
||||||
|
return status, result
|
||||||
|
|
||||||
|
def ipmi_fru_id(self, id, key=None):
|
||||||
|
status = True
|
||||||
|
result = ""
|
||||||
|
try:
|
||||||
|
cmd = "ipmitool fru print {}".format(str(
|
||||||
|
id)) if not key else "ipmitool fru print {0} | grep '{1}' ".format(str(id), str(key))
|
||||||
|
|
||||||
|
p = subprocess.Popen(
|
||||||
|
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
raw_data, err = p.communicate()
|
||||||
|
if err == '':
|
||||||
|
result = raw_data.strip()
|
||||||
|
else:
|
||||||
|
status = False
|
||||||
|
except:
|
||||||
|
status = False
|
||||||
|
return status, result
|
||||||
|
|
||||||
|
def ipmi_set_ss_thres(self, id, threshold_key, value):
|
||||||
|
status = True
|
||||||
|
result = ""
|
||||||
|
try:
|
||||||
|
cmd = "ipmitool sensor thresh '{}' {} {}".format(
|
||||||
|
str(id), str(threshold_key), str(value))
|
||||||
|
p = subprocess.Popen(
|
||||||
|
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
raw_data, err = p.communicate()
|
||||||
|
if err == '':
|
||||||
|
result = raw_data.strip()
|
||||||
|
else:
|
||||||
|
status = False
|
||||||
|
except:
|
||||||
|
status = False
|
||||||
|
return status, result
|
@ -14,6 +14,7 @@ import sonic_platform
|
|||||||
try:
|
try:
|
||||||
from sonic_platform_base.psu_base import PsuBase
|
from sonic_platform_base.psu_base import PsuBase
|
||||||
from sonic_platform.fan import Fan
|
from sonic_platform.fan import Fan
|
||||||
|
from helper import APIHelper
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(str(e) + "- required module not found")
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
@ -41,6 +42,7 @@ class Psu(PsuBase):
|
|||||||
def __init__(self, psu_index):
|
def __init__(self, psu_index):
|
||||||
PsuBase.__init__(self)
|
PsuBase.__init__(self)
|
||||||
self.index = psu_index
|
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 = [
|
self.dx010_psu_gpio = [
|
||||||
{'base': self.__get_gpio_base()},
|
{'base': self.__get_gpio_base()},
|
||||||
@ -54,27 +56,18 @@ class Psu(PsuBase):
|
|||||||
fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index)
|
fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index)
|
||||||
self._fan_list.append(fan)
|
self._fan_list.append(fan)
|
||||||
|
|
||||||
def __read_txt_file(self, file_path):
|
|
||||||
try:
|
|
||||||
with open(file_path, 'r') as fd:
|
|
||||||
data = fd.read()
|
|
||||||
return data.strip()
|
|
||||||
except IOError:
|
|
||||||
pass
|
|
||||||
return ""
|
|
||||||
|
|
||||||
def __search_file_by_contain(self, directory, search_str, file_start):
|
def __search_file_by_contain(self, directory, search_str, file_start):
|
||||||
for dirpath, dirnames, files in os.walk(directory):
|
for dirpath, dirnames, files in os.walk(directory):
|
||||||
for name in files:
|
for name in files:
|
||||||
file_path = os.path.join(dirpath, name)
|
file_path = os.path.join(dirpath, name)
|
||||||
if name.startswith(file_start) and search_str in self.__read_txt_file(file_path):
|
if name.startswith(file_start) and search_str in self._api_helper.read_txt_file(file_path):
|
||||||
return file_path
|
return file_path
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def __get_gpio_base(self):
|
def __get_gpio_base(self):
|
||||||
for r in os.listdir(GPIO_DIR):
|
for r in os.listdir(GPIO_DIR):
|
||||||
label_path = os.path.join(GPIO_DIR, r, "label")
|
label_path = os.path.join(GPIO_DIR, r, "label")
|
||||||
if "gpiochip" in r and GPIO_LABEL in self.__read_txt_file(label_path):
|
if "gpiochip" in r and GPIO_LABEL in self._api_helper.read_txt_file(label_path):
|
||||||
return int(r[8:], 10)
|
return int(r[8:], 10)
|
||||||
return 216 # Reserve
|
return 216 # Reserve
|
||||||
|
|
||||||
@ -82,7 +75,7 @@ class Psu(PsuBase):
|
|||||||
gpio_base = self.dx010_psu_gpio[0]['base']
|
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"
|
gpio_file = gpio_dir + "/value"
|
||||||
retval = self.__read_txt_file(gpio_file)
|
retval = self._api_helper.read_txt_file(gpio_file)
|
||||||
return retval.rstrip('\r\n')
|
return retval.rstrip('\r\n')
|
||||||
|
|
||||||
def get_voltage(self):
|
def get_voltage(self):
|
||||||
@ -104,7 +97,7 @@ class Psu(PsuBase):
|
|||||||
in_num = filter(str.isdigit, basename)
|
in_num = filter(str.isdigit, basename)
|
||||||
vout_path = os.path.join(
|
vout_path = os.path.join(
|
||||||
dir_name, voltage_name.format(in_num))
|
dir_name, voltage_name.format(in_num))
|
||||||
vout_val = self.__read_txt_file(vout_path)
|
vout_val = self._api_helper.read_txt_file(vout_path)
|
||||||
psu_voltage = float(vout_val) / 1000
|
psu_voltage = float(vout_val) / 1000
|
||||||
|
|
||||||
return psu_voltage
|
return psu_voltage
|
||||||
@ -127,7 +120,7 @@ class Psu(PsuBase):
|
|||||||
cur_num = filter(str.isdigit, basename)
|
cur_num = filter(str.isdigit, basename)
|
||||||
cur_path = os.path.join(
|
cur_path = os.path.join(
|
||||||
dir_name, current_name.format(cur_num))
|
dir_name, current_name.format(cur_num))
|
||||||
cur_val = self.__read_txt_file(cur_path)
|
cur_val = self._api_helper.read_txt_file(cur_path)
|
||||||
psu_current = float(cur_val) / 1000
|
psu_current = float(cur_val) / 1000
|
||||||
|
|
||||||
return psu_current
|
return psu_current
|
||||||
@ -150,7 +143,7 @@ class Psu(PsuBase):
|
|||||||
pw_num = filter(str.isdigit, basename)
|
pw_num = filter(str.isdigit, basename)
|
||||||
pw_path = os.path.join(
|
pw_path = os.path.join(
|
||||||
dir_name, current_name.format(pw_num))
|
dir_name, current_name.format(pw_num))
|
||||||
pw_val = self.__read_txt_file(pw_path)
|
pw_val = self._api_helper.read_txt_file(pw_path)
|
||||||
psu_power = float(pw_val) / 1000000
|
psu_power = float(pw_val) / 1000000
|
||||||
|
|
||||||
return psu_power
|
return psu_power
|
||||||
@ -196,7 +189,7 @@ class Psu(PsuBase):
|
|||||||
Returns:
|
Returns:
|
||||||
A string, one of the predefined STATUS_LED_COLOR_* strings above
|
A string, one of the predefined STATUS_LED_COLOR_* strings above
|
||||||
"""
|
"""
|
||||||
status = self.__read_txt_file(self.green_led_path)
|
status = self._api_helper.read_txt_file(self.green_led_path)
|
||||||
status_str = {
|
status_str = {
|
||||||
'255': self.STATUS_LED_COLOR_GREEN,
|
'255': self.STATUS_LED_COLOR_GREEN,
|
||||||
'0': self.STATUS_LED_COLOR_OFF
|
'0': self.STATUS_LED_COLOR_OFF
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,7 @@ import os.path
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
from sonic_platform_base.thermal_base import ThermalBase
|
from sonic_platform_base.thermal_base import ThermalBase
|
||||||
|
from helper import APIHelper
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(str(e) + "- required module not found")
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
@ -27,6 +28,7 @@ class Thermal(ThermalBase):
|
|||||||
|
|
||||||
def __init__(self, thermal_index):
|
def __init__(self, thermal_index):
|
||||||
self.index = thermal_index
|
self.index = thermal_index
|
||||||
|
self._api_helper = APIHelper()
|
||||||
|
|
||||||
# Add thermal name
|
# Add thermal name
|
||||||
self.THERMAL_NAME_LIST.append("Front-panel temp sensor 1")
|
self.THERMAL_NAME_LIST.append("Front-panel temp sensor 1")
|
||||||
@ -48,19 +50,11 @@ class Thermal(ThermalBase):
|
|||||||
self.ss_key = self.THERMAL_NAME_LIST[self.index]
|
self.ss_key = self.THERMAL_NAME_LIST[self.index]
|
||||||
self.ss_index = 1
|
self.ss_index = 1
|
||||||
|
|
||||||
def __read_txt_file(self, file_path):
|
|
||||||
try:
|
|
||||||
with open(file_path, 'r') as fd:
|
|
||||||
data = fd.read()
|
|
||||||
return data.strip()
|
|
||||||
except IOError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __get_temp(self, temp_file):
|
def __get_temp(self, temp_file):
|
||||||
temp_file_path = os.path.join(self.hwmon_path, temp_file)
|
temp_file_path = os.path.join(self.hwmon_path, temp_file)
|
||||||
raw_temp = self.__read_txt_file(temp_file_path)
|
raw_temp = self._api_helper.read_txt_file(temp_file_path)
|
||||||
temp = float(raw_temp)/1000
|
temp = float(raw_temp)/1000
|
||||||
return "{:.3f}".format(temp)
|
return float("{:.3f}".format(temp))
|
||||||
|
|
||||||
def __set_threshold(self, file_name, temperature):
|
def __set_threshold(self, file_name, temperature):
|
||||||
temp_file_path = os.path.join(self.hwmon_path, file_name)
|
temp_file_path = os.path.join(self.hwmon_path, file_name)
|
||||||
|
@ -7,115 +7,79 @@
|
|||||||
#
|
#
|
||||||
#############################################################################
|
#############################################################################
|
||||||
import ctypes
|
import ctypes
|
||||||
import fcntl
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
import array
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from sonic_platform_base.watchdog_base import WatchdogBase
|
from sonic_platform_base.watchdog_base import WatchdogBase
|
||||||
|
from helper import APIHelper
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(str(e) + "- required module not found")
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
""" ioctl constants """
|
PLATFORM_CPLD_PATH = '/sys/devices/platform/dx010_cpld'
|
||||||
IO_WRITE = 0x40000000
|
GETREG_FILE = 'getreg'
|
||||||
IO_READ = 0x80000000
|
SETREG_FILE = 'setreg'
|
||||||
IO_READ_WRITE = 0xC0000000
|
WDT_ENABLE_REG = '0x141'
|
||||||
IO_SIZE_INT = 0x00040000
|
WDT_TIMER_L_BIT_REG = '0x142'
|
||||||
IO_SIZE_40 = 0x00280000
|
WDT_TIMER_M_BIT_REG = '0x143'
|
||||||
IO_TYPE_WATCHDOG = ord('W') << 8
|
WDT_TIMER_H_BIT_REG = '0x144'
|
||||||
|
WDT_KEEP_ALVIVE_REG = '0x145'
|
||||||
WDR_INT = IO_READ | IO_SIZE_INT | IO_TYPE_WATCHDOG
|
ENABLE_CMD = '0x1'
|
||||||
WDR_40 = IO_READ | IO_SIZE_40 | IO_TYPE_WATCHDOG
|
DISABLE_CMD = '0x0'
|
||||||
WDWR_INT = IO_READ_WRITE | IO_SIZE_INT | IO_TYPE_WATCHDOG
|
|
||||||
|
|
||||||
""" Watchdog ioctl commands """
|
|
||||||
WDIOC_GETSUPPORT = 0 | WDR_40
|
|
||||||
WDIOC_GETSTATUS = 1 | WDR_INT
|
|
||||||
WDIOC_GETBOOTSTATUS = 2 | WDR_INT
|
|
||||||
WDIOC_GETTEMP = 3 | WDR_INT
|
|
||||||
WDIOC_SETOPTIONS = 4 | WDR_INT
|
|
||||||
WDIOC_KEEPALIVE = 5 | WDR_INT
|
|
||||||
WDIOC_SETTIMEOUT = 6 | WDWR_INT
|
|
||||||
WDIOC_GETTIMEOUT = 7 | WDR_INT
|
|
||||||
WDIOC_SETPRETIMEOUT = 8 | WDWR_INT
|
|
||||||
WDIOC_GETPRETIMEOUT = 9 | WDR_INT
|
|
||||||
WDIOC_GETTIMELEFT = 10 | WDR_INT
|
|
||||||
|
|
||||||
""" Watchdog status constants """
|
|
||||||
WDIOS_DISABLECARD = 0x0001
|
|
||||||
WDIOS_ENABLECARD = 0x0002
|
|
||||||
|
|
||||||
WDT_COMMON_ERROR = -1
|
WDT_COMMON_ERROR = -1
|
||||||
WD_MAIN_IDENTITY = "iTCO_wdt"
|
|
||||||
WDT_SYSFS_PATH = "/sys/class/watchdog/"
|
|
||||||
|
|
||||||
|
|
||||||
class Watchdog(WatchdogBase):
|
class Watchdog(WatchdogBase):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
# Init helper
|
||||||
|
self._api_helper = APIHelper()
|
||||||
|
|
||||||
|
# Init cpld reg path
|
||||||
|
self.setreg_path = os.path.join(PLATFORM_CPLD_PATH, SETREG_FILE)
|
||||||
|
self.getreg_path = os.path.join(PLATFORM_CPLD_PATH, GETREG_FILE)
|
||||||
|
|
||||||
self.watchdog, self.wdt_main_dev_name = self._get_wdt()
|
|
||||||
self.status_path = "/sys/class/watchdog/%s/status" % self.wdt_main_dev_name
|
|
||||||
self.state_path = "/sys/class/watchdog/%s/state" % self.wdt_main_dev_name
|
|
||||||
self.timeout_path = "/sys/class/watchdog/%s/timeout" % self.wdt_main_dev_name
|
|
||||||
# Set default value
|
# Set default value
|
||||||
self._disable()
|
self._disable()
|
||||||
self.armed = False
|
self.armed = False
|
||||||
self.timeout = self._gettimeout(self.timeout_path)
|
self.timeout = self._gettimeout()
|
||||||
|
|
||||||
def _is_wd_main(self, dev):
|
|
||||||
"""
|
|
||||||
Checks watchdog identity
|
|
||||||
"""
|
|
||||||
identity = self._read_file(
|
|
||||||
"{}/{}/identity".format(WDT_SYSFS_PATH, dev))
|
|
||||||
return identity == WD_MAIN_IDENTITY
|
|
||||||
|
|
||||||
def _get_wdt(self):
|
|
||||||
"""
|
|
||||||
Retrieves watchdog device
|
|
||||||
"""
|
|
||||||
wdt_main_dev_list = [dev for dev in os.listdir(
|
|
||||||
"/dev/") if dev.startswith("watchdog") and self._is_wd_main(dev)]
|
|
||||||
if not wdt_main_dev_list:
|
|
||||||
return None
|
|
||||||
wdt_main_dev_name = wdt_main_dev_list[0]
|
|
||||||
watchdog_device_path = "/dev/{}".format(wdt_main_dev_name)
|
|
||||||
watchdog = os.open(watchdog_device_path, os.O_RDWR)
|
|
||||||
return watchdog, wdt_main_dev_name
|
|
||||||
|
|
||||||
def _read_file(self, file_path):
|
|
||||||
"""
|
|
||||||
Read text file
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
with open(file_path, "r") as fd:
|
|
||||||
txt = fd.read()
|
|
||||||
except IOError:
|
|
||||||
return WDT_COMMON_ERROR
|
|
||||||
return txt.strip()
|
|
||||||
|
|
||||||
def _enable(self):
|
def _enable(self):
|
||||||
"""
|
"""
|
||||||
Turn on the watchdog timer
|
Turn on the watchdog timer
|
||||||
"""
|
"""
|
||||||
req = array.array('h', [WDIOS_ENABLECARD])
|
# echo 0x141 0x1 > /sys/devices/platform/dx010_cpld/setreg
|
||||||
fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False)
|
enable_val = '{} {}'.format(WDT_ENABLE_REG, ENABLE_CMD)
|
||||||
|
return self._api_helper.write_txt_file(self.setreg_path, enable_val)
|
||||||
|
|
||||||
def _disable(self):
|
def _disable(self):
|
||||||
"""
|
"""
|
||||||
Turn off the watchdog timer
|
Turn off the watchdog timer
|
||||||
"""
|
"""
|
||||||
req = array.array('h', [WDIOS_DISABLECARD])
|
# echo 0x141 0x0 > /sys/devices/platform/dx010_cpld/setreg
|
||||||
fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False)
|
disable_val = '{} {}'.format(WDT_ENABLE_REG, DISABLE_CMD)
|
||||||
|
return self._api_helper.write_txt_file(self.setreg_path, disable_val)
|
||||||
|
|
||||||
def _keepalive(self):
|
def _keepalive(self):
|
||||||
"""
|
"""
|
||||||
Keep alive watchdog timer
|
Keep alive watchdog timer
|
||||||
"""
|
"""
|
||||||
fcntl.ioctl(self.watchdog, WDIOC_KEEPALIVE)
|
# echo 0x145 0x1 > /sys/devices/platform/dx010_cpld/setreg
|
||||||
|
enable_val = '{} {}'.format(WDT_KEEP_ALVIVE_REG, ENABLE_CMD)
|
||||||
|
return self._api_helper.write_txt_file(self.setreg_path, enable_val)
|
||||||
|
|
||||||
|
def _get_level_hex(self, sub_hex):
|
||||||
|
sub_hex_str = sub_hex.replace("x", "0")
|
||||||
|
return hex(int(sub_hex_str, 16))
|
||||||
|
|
||||||
|
def _seconds_to_lmh_hex(self, seconds):
|
||||||
|
ms = seconds*1000 # calculate timeout in ms format
|
||||||
|
hex_str = hex(ms)
|
||||||
|
l = self._get_level_hex(hex_str[-2:])
|
||||||
|
m = self._get_level_hex(hex_str[-4:-2])
|
||||||
|
h = self._get_level_hex(hex_str[-6:-4])
|
||||||
|
return (l, m, h)
|
||||||
|
|
||||||
def _settimeout(self, seconds):
|
def _settimeout(self, seconds):
|
||||||
"""
|
"""
|
||||||
@ -123,29 +87,35 @@ class Watchdog(WatchdogBase):
|
|||||||
@param seconds - timeout in seconds
|
@param seconds - timeout in seconds
|
||||||
@return is the actual set timeout
|
@return is the actual set timeout
|
||||||
"""
|
"""
|
||||||
req = array.array('I', [seconds])
|
# max = 0xffffff = 16777.215 seconds
|
||||||
fcntl.ioctl(self.watchdog, WDIOC_SETTIMEOUT, req, True)
|
|
||||||
return int(req[0])
|
|
||||||
|
|
||||||
def _gettimeout(self, timeout_path):
|
(l, m, h) = self._seconds_to_lmh_hex(seconds)
|
||||||
|
set_h_val = '{} {}'.format(WDT_TIMER_H_BIT_REG, h)
|
||||||
|
set_m_val = '{} {}'.format(WDT_TIMER_M_BIT_REG, m)
|
||||||
|
set_l_val = '{} {}'.format(WDT_TIMER_L_BIT_REG, l)
|
||||||
|
|
||||||
|
self._api_helper.write_txt_file(self.setreg_path, set_h_val)
|
||||||
|
self._api_helper.write_txt_file(self.setreg_path, set_m_val)
|
||||||
|
self._api_helper.write_txt_file(self.setreg_path, set_l_val)
|
||||||
|
|
||||||
|
return seconds
|
||||||
|
|
||||||
|
def _gettimeout(self):
|
||||||
"""
|
"""
|
||||||
Get watchdog timeout
|
Get watchdog timeout
|
||||||
@return watchdog timeout
|
@return watchdog timeout
|
||||||
"""
|
"""
|
||||||
req = array.array('I', [0])
|
|
||||||
fcntl.ioctl(self.watchdog, WDIOC_GETTIMEOUT, req, True)
|
|
||||||
|
|
||||||
return int(req[0])
|
h_bit = self._api_helper.get_cpld_reg_value(
|
||||||
|
self.getreg_path, WDT_TIMER_H_BIT_REG)
|
||||||
|
m_bit = self._api_helper.get_cpld_reg_value(
|
||||||
|
self.getreg_path, WDT_TIMER_M_BIT_REG)
|
||||||
|
l_bit = self._api_helper.get_cpld_reg_value(
|
||||||
|
self.getreg_path, WDT_TIMER_L_BIT_REG)
|
||||||
|
|
||||||
def _gettimeleft(self):
|
hex_time = '0x{}{}{}'.format(h_bit[2:], m_bit[2:], l_bit[2:])
|
||||||
"""
|
ms = int(hex_time, 16)
|
||||||
Get time left before watchdog timer expires
|
return int(float(ms)/1000)
|
||||||
@return time left in seconds
|
|
||||||
"""
|
|
||||||
req = array.array('I', [0])
|
|
||||||
fcntl.ioctl(self.watchdog, WDIOC_GETTIMELEFT, req, True)
|
|
||||||
|
|
||||||
return int(req[0])
|
|
||||||
|
|
||||||
#################################################################
|
#################################################################
|
||||||
|
|
||||||
@ -169,12 +139,15 @@ class Watchdog(WatchdogBase):
|
|||||||
try:
|
try:
|
||||||
if self.timeout != seconds:
|
if self.timeout != seconds:
|
||||||
self.timeout = self._settimeout(seconds)
|
self.timeout = self._settimeout(seconds)
|
||||||
|
|
||||||
if self.armed:
|
if self.armed:
|
||||||
self._keepalive()
|
self._keepalive()
|
||||||
else:
|
else:
|
||||||
self._enable()
|
self._enable()
|
||||||
self.armed = True
|
self.armed = True
|
||||||
|
|
||||||
ret = self.timeout
|
ret = self.timeout
|
||||||
|
self.arm_timestamp = time.time()
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -215,19 +188,4 @@ class Watchdog(WatchdogBase):
|
|||||||
watchdog timer. If the watchdog is not armed, returns -1.
|
watchdog timer. If the watchdog is not armed, returns -1.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
timeleft = WDT_COMMON_ERROR
|
return int(self.timeout - (time.time() - self.arm_timestamp)) if self.armed else WDT_COMMON_ERROR
|
||||||
|
|
||||||
if self.armed:
|
|
||||||
try:
|
|
||||||
timeleft = self._gettimeleft()
|
|
||||||
except IOError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return timeleft
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
"""
|
|
||||||
Close watchdog
|
|
||||||
"""
|
|
||||||
|
|
||||||
os.close(self.watchdog)
|
|
||||||
|
@ -2,7 +2,8 @@ dx010/scripts/dx010_check_qsfp.sh usr/local/bin
|
|||||||
dx010/cfg/dx010-modules.conf etc/modules-load.d
|
dx010/cfg/dx010-modules.conf etc/modules-load.d
|
||||||
dx010/systemd/platform-modules-dx010.service lib/systemd/system
|
dx010/systemd/platform-modules-dx010.service lib/systemd/system
|
||||||
dx010/scripts/fancontrol.sh etc/init.d
|
dx010/scripts/fancontrol.sh etc/init.d
|
||||||
services/fancontrol/fancontrol.service lib/systemd/system
|
dx010/scripts/fancontrol.service lib/systemd/system
|
||||||
|
dx010/scripts/thermal_overload_control.sh usr/local/bin
|
||||||
services/fancontrol/fancontrol usr/local/bin
|
services/fancontrol/fancontrol usr/local/bin
|
||||||
dx010/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cel_seastone-r0
|
dx010/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cel_seastone-r0
|
||||||
services/platform_api/platform_api_mgnt.sh usr/local/bin
|
services/platform_api/platform_api_mgnt.sh usr/local/bin
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
haliburton/cfg/haliburton-modules.conf etc/modules-load.d
|
haliburton/cfg/haliburton-modules.conf etc/modules-load.d
|
||||||
haliburton/systemd/platform-modules-haliburton.service lib/systemd/system
|
haliburton/systemd/platform-modules-haliburton.service lib/systemd/system
|
||||||
haliburton/script/fancontrol.sh etc/init.d
|
haliburton/script/fancontrol.sh etc/init.d
|
||||||
services/fancontrol/fancontrol.service lib/systemd/system
|
haliburton/script/fancontrol.service lib/systemd/system
|
||||||
services/fancontrol/fancontrol usr/local/bin
|
services/fancontrol/fancontrol usr/local/bin
|
||||||
haliburton/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cel_e1031-r0
|
haliburton/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cel_e1031-r0
|
||||||
services/platform_api/platform_api_mgnt.sh usr/local/bin
|
services/platform_api/platform_api_mgnt.sh usr/local/bin
|
||||||
|
@ -76,42 +76,52 @@
|
|||||||
#define PORT_SFPP1 33
|
#define PORT_SFPP1 33
|
||||||
#define PORT_SFPP2 34
|
#define PORT_SFPP2 34
|
||||||
|
|
||||||
#define PORT_ID_BANK1 0x210
|
|
||||||
#define PORT_ID_BANK2 0x290
|
|
||||||
#define PORT_ID_BANK3 0x390
|
|
||||||
|
|
||||||
#define OPCODE_ID_BANK1 0x211
|
#define CPLD_I2C_CLK_100Khz_BIT BIT(6)
|
||||||
#define OPCODE_ID_BANK2 0x291
|
#define CPLD_I2C_DATA_SZ_MASK GENMASK(7,4)
|
||||||
#define OPCODE_ID_BANK3 0x391
|
#define CPLD_I2C_CMD_SZ_MASK GENMASK(1,0)
|
||||||
|
#define CPLD_I2C_ERR BIT(7)
|
||||||
|
#define CPLD_I2C_BUSY BIT(6)
|
||||||
|
#define CPLD_I2C_RST_BIT BIT(0)
|
||||||
|
#define CPLD_I2C_RESET 0
|
||||||
|
#define CPLD_I2C_UNRESET 1
|
||||||
|
#define CPLD_I2C_DATA_SZ_MAX 8
|
||||||
|
#define CPLD_I2C_CMD_SZ_MAX 3
|
||||||
|
|
||||||
#define DEVADDR_ID_BANK1 0x212
|
|
||||||
#define DEVADDR_ID_BANK2 0x292
|
|
||||||
#define DEVADDR_ID_BANK3 0x392
|
|
||||||
|
|
||||||
#define CMDBYT_ID_BANK1 0x213
|
#define CPLD_I2C_BANK1_BASE 0x210
|
||||||
#define CMDBYT_ID_BANK2 0x293
|
#define CPLD_I2C_BANK2_BASE 0x290
|
||||||
#define CMDBYT_ID_BANK3 0x393
|
#define CPLD_I2C_BANK3_BASE 0x390
|
||||||
|
|
||||||
#define WRITE_ID_BANK1 0x220
|
#define I2C_PORT_ID 0x0
|
||||||
#define WRITE_ID_BANK2 0x2A0
|
#define I2C_OPCODE 0x1
|
||||||
#define WRITE_ID_BANK3 0x3A0
|
#define I2C_DEV_ADDR 0x2
|
||||||
|
#define I2C_CMD_BYT0 0x3
|
||||||
|
#define I2C_SSR 0x6
|
||||||
|
#define I2C_WRITE_DATA 0x10
|
||||||
|
#define I2C_READ_DATA 0x20
|
||||||
|
|
||||||
#define READ_ID_BANK1 0x230
|
/*
|
||||||
#define READ_ID_BANK2 0x2B0
|
* private data to send to I2C core
|
||||||
#define READ_ID_BANK3 0x3B0
|
*/
|
||||||
|
struct current_xfer {
|
||||||
#define SSRR_ID_BANK1 0x216
|
u8 addr;
|
||||||
#define SSRR_ID_BANK2 0x296
|
u8 cmd[CPLD_I2C_CMD_SZ_MAX];
|
||||||
#define SSRR_ID_BANK3 0x396
|
u8 cmd_len;
|
||||||
|
u8 data_len;
|
||||||
#define HST_CNTL2_QUICK 0x00
|
union i2c_smbus_data *data;
|
||||||
#define HST_CNTL2_BYTE 0x01
|
};
|
||||||
#define HST_CNTL2_BYTE_DATA 0x02
|
|
||||||
#define HST_CNTL2_WORD_DATA 0x03
|
|
||||||
#define HST_CNTL2_BLOCK 0x05
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* private data of I2C adapter
|
||||||
|
* base_addr: Base address of this I2C adapter core.
|
||||||
|
* port_id: The port ID, use to mux an i2c core to a font panel port.
|
||||||
|
* current_xfer: The struct carry current data setup of current smbus transfer.
|
||||||
|
*/
|
||||||
struct dx010_i2c_data {
|
struct dx010_i2c_data {
|
||||||
|
int base_addr;
|
||||||
int portid;
|
int portid;
|
||||||
|
struct current_xfer curr_xfer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dx010_cpld_data {
|
struct dx010_cpld_data {
|
||||||
@ -364,179 +374,210 @@ static struct platform_device cel_dx010_lpc_dev = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: Refactoring this function with helper functions.
|
||||||
|
static s32 cpld_smbus_transfer(struct dx010_i2c_data *priv) {
|
||||||
|
|
||||||
/**
|
u8 val;
|
||||||
* Read eeprom of QSFP device.
|
s32 error;
|
||||||
* @param a i2c adapter.
|
unsigned long ioBase;
|
||||||
* @param addr address to read.
|
short portid, opcode, devaddr, cmdbyte0, ssr, writedata, readdata;
|
||||||
* @param new_data QSFP port number struct.
|
union i2c_smbus_data *data;
|
||||||
* @param cmd i2c command.
|
|
||||||
* @return 0 if not error, else the error code.
|
|
||||||
*/
|
|
||||||
static int i2c_read_eeprom(struct i2c_adapter *a, u16 addr,
|
|
||||||
struct dx010_i2c_data *new_data, u8 cmd, union i2c_smbus_data *data){
|
|
||||||
|
|
||||||
u32 reg;
|
error = -EIO;
|
||||||
int ioBase=0;
|
|
||||||
char byte;
|
|
||||||
short temp;
|
|
||||||
short portid, opcode, devaddr, cmdbyte0, ssrr, writedata, readdata;
|
|
||||||
__u16 word_data;
|
|
||||||
int error = -EIO;
|
|
||||||
|
|
||||||
mutex_lock(&cpld_data->cpld_lock);
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
|
||||||
if (((new_data->portid >= PORT_BANK1_START)
|
ioBase = priv->base_addr;
|
||||||
&& (new_data->portid <= PORT_BANK1_END))
|
data = priv->curr_xfer.data;
|
||||||
|| (new_data->portid == PORT_SFPP1)
|
|
||||||
|| (new_data->portid == PORT_SFPP2))
|
|
||||||
{
|
|
||||||
portid = PORT_ID_BANK1;
|
|
||||||
opcode = OPCODE_ID_BANK1;
|
|
||||||
devaddr = DEVADDR_ID_BANK1;
|
|
||||||
cmdbyte0 = CMDBYT_ID_BANK1;
|
|
||||||
ssrr = SSRR_ID_BANK1;
|
|
||||||
writedata = WRITE_ID_BANK1;
|
|
||||||
readdata = READ_ID_BANK1;
|
|
||||||
}else if ((new_data->portid >= PORT_BANK2_START) && (new_data->portid <= PORT_BANK2_END)){
|
|
||||||
portid = PORT_ID_BANK2;
|
|
||||||
opcode = OPCODE_ID_BANK2;
|
|
||||||
devaddr = DEVADDR_ID_BANK2;
|
|
||||||
cmdbyte0 = CMDBYT_ID_BANK2;
|
|
||||||
ssrr = SSRR_ID_BANK2;
|
|
||||||
writedata = WRITE_ID_BANK2;
|
|
||||||
readdata = READ_ID_BANK2;
|
|
||||||
}else if ((new_data->portid >= PORT_BANK3_START) && (new_data->portid <= PORT_BANK3_END)){
|
|
||||||
portid = PORT_ID_BANK3;
|
|
||||||
opcode = OPCODE_ID_BANK3;
|
|
||||||
devaddr = DEVADDR_ID_BANK3;
|
|
||||||
cmdbyte0 = CMDBYT_ID_BANK3;
|
|
||||||
ssrr = SSRR_ID_BANK3;
|
|
||||||
writedata = WRITE_ID_BANK3;
|
|
||||||
readdata = READ_ID_BANK3;
|
|
||||||
}else{
|
|
||||||
/* Invalid parameter! */
|
|
||||||
error = -EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((inb(ioBase + ssrr) & 0x40));
|
portid = ioBase + I2C_PORT_ID;
|
||||||
if ((inb(ioBase + ssrr) & 0x80) == 0x80) {
|
opcode = ioBase + I2C_OPCODE;
|
||||||
error = -EIO;
|
devaddr = ioBase + I2C_DEV_ADDR;
|
||||||
/* Read error reset the port */
|
cmdbyte0 = ioBase + I2C_CMD_BYT0;
|
||||||
outb(0x00, ioBase + ssrr);
|
ssr = ioBase + I2C_SSR;
|
||||||
udelay(3000);
|
writedata = ioBase + I2C_WRITE_DATA;
|
||||||
outb(0x01, ioBase + ssrr);
|
readdata = ioBase + I2C_READ_DATA;
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte = 0x40 +new_data->portid;
|
/* Wait for the core to be free */
|
||||||
reg = cmd;
|
pr_debug("CPLD_I2C Wait busy bit(6) to be cleared\n");
|
||||||
outb(byte, ioBase + portid);
|
do {
|
||||||
outb(reg,ioBase + cmdbyte0);
|
val = inb(ssr);
|
||||||
byte = 33;
|
if ((val & CPLD_I2C_BUSY) == 0)
|
||||||
outb(byte, ioBase + opcode);
|
break;
|
||||||
addr = addr << 1;
|
|
||||||
addr |= 0x01;
|
|
||||||
outb(addr, ioBase + devaddr);
|
|
||||||
while ((inb(ioBase + ssrr) & 0x40))
|
|
||||||
{
|
|
||||||
udelay(100);
|
udelay(100);
|
||||||
}
|
} while (true); // Risky - add timeout
|
||||||
|
|
||||||
if ((inb(ioBase + ssrr) & 0x80) == 0x80) {
|
/*
|
||||||
/* Read error reset the port */
|
* If any error happen here, we do soft-reset
|
||||||
error = -EIO;
|
* and check the BUSY/ERROR again.
|
||||||
outb(0x00, ioBase + ssrr);
|
*/
|
||||||
|
pr_debug("CPLD_I2C Check error bit(7)\n");
|
||||||
|
if (val & CPLD_I2C_ERR) {
|
||||||
|
pr_debug("CPLD_I2C Error, try soft-reset\n");
|
||||||
|
outb(CPLD_I2C_RESET, ssr);
|
||||||
udelay(3000);
|
udelay(3000);
|
||||||
outb(0x01, ioBase + ssrr);
|
outb(CPLD_I2C_UNRESET, ssr);
|
||||||
goto exit;
|
|
||||||
|
val = inb(ssr);
|
||||||
|
if (val & (CPLD_I2C_BUSY | CPLD_I2C_ERR)) {
|
||||||
|
pr_debug("CPLD_I2C Error, core busy after reset\n");
|
||||||
|
error = -EIO;
|
||||||
|
goto exit_unlock;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
temp = ioBase + readdata;
|
/* Configure PortID */
|
||||||
word_data = inb(temp);
|
val = priv->portid | CPLD_I2C_CLK_100Khz_BIT;
|
||||||
word_data |= (inb(++temp) << 8);
|
outb(val, portid);
|
||||||
|
pr_debug("CPLD_I2C Write PortID 0x%x\n", val);
|
||||||
|
|
||||||
mutex_unlock(&cpld_data->cpld_lock);
|
/* Configure OP_Code */
|
||||||
data->word = word_data;
|
val = (priv->curr_xfer.data_len << 4) & CPLD_I2C_DATA_SZ_MASK;
|
||||||
return 0;
|
val |= (priv->curr_xfer.cmd_len & CPLD_I2C_CMD_SZ_MASK);
|
||||||
|
outb(val, opcode);
|
||||||
|
pr_debug("CPLD_I2C Write OP_Code 0x%x\n", val);
|
||||||
|
|
||||||
exit:
|
/* Configure CMD_Byte */
|
||||||
|
outb(priv->curr_xfer.cmd[0], cmdbyte0);
|
||||||
|
pr_debug("CPLD_I2C Write CMD_Byte 0x%x\n", priv->curr_xfer.cmd[0]);
|
||||||
|
|
||||||
|
/* Configure write data buffer */
|
||||||
|
if ((priv->curr_xfer.addr & BIT(0)) == I2C_SMBUS_WRITE){
|
||||||
|
pr_debug("CPLD_I2C Write WR_DATA buffer\n");
|
||||||
|
switch(priv->curr_xfer.data_len){
|
||||||
|
case 1:
|
||||||
|
outb(data->byte, writedata);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
outb(data->block[0], writedata);
|
||||||
|
outb(data->block[1], ++writedata);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start transfer, write the device address register */
|
||||||
|
pr_debug("CPLD_I2C Write DEV_ADDR 0x%x\n", priv->curr_xfer.addr);
|
||||||
|
outb(priv->curr_xfer.addr, devaddr);
|
||||||
|
|
||||||
|
/* Wait for transfer finish */
|
||||||
|
pr_debug("CPLD_I2C Wait busy bit(6) to be cleared\n");
|
||||||
|
do {
|
||||||
|
val = inb(ssr);
|
||||||
|
if ((val & CPLD_I2C_BUSY) == 0)
|
||||||
|
break;
|
||||||
|
udelay(100);
|
||||||
|
} while (true); // Risky - add timeout
|
||||||
|
|
||||||
|
pr_debug("CPLD_I2C Check error bit(7)\n");
|
||||||
|
if (val & CPLD_I2C_ERR) {
|
||||||
|
error = -EIO;
|
||||||
|
goto exit_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the data from buffer */
|
||||||
|
if ((priv->curr_xfer.addr & BIT(0)) == I2C_SMBUS_READ){
|
||||||
|
pr_debug("CPLD_I2C Read RD_DATA buffer\n");
|
||||||
|
switch (priv->curr_xfer.data_len) {
|
||||||
|
case 1:
|
||||||
|
data->byte = inb(readdata);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
data->block[0] = inb(readdata);
|
||||||
|
data->block[1] = inb(++readdata);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error = 0;
|
||||||
|
|
||||||
|
exit_unlock:
|
||||||
|
pr_debug("CPLD_I2C Exit with %d\n", error);
|
||||||
mutex_unlock(&cpld_data->cpld_lock);
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dx010_i2c_access(struct i2c_adapter *a, u16 addr,
|
/*
|
||||||
unsigned short flags, char rw, u8 cmd,
|
* dx010_smbus_xfer - execute LPC-SMBus transfer
|
||||||
int size, union i2c_smbus_data *data)
|
* Returns a negative errno code else zero on success.
|
||||||
{
|
*/
|
||||||
|
static s32 dx010_smbus_xfer(struct i2c_adapter *adap, u16 addr,
|
||||||
|
unsigned short flags, char read_write,
|
||||||
|
u8 command, int size, union i2c_smbus_data *data) {
|
||||||
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
struct dx010_i2c_data *priv;
|
||||||
|
|
||||||
struct dx010_i2c_data *new_data;
|
priv = i2c_get_adapdata(adap);
|
||||||
|
|
||||||
/* Write the command register */
|
pr_debug("smbus_xfer called RW:%x CMD:%x SIZE:0x%x",
|
||||||
new_data = i2c_get_adapdata(a);
|
read_write, command, size);
|
||||||
|
|
||||||
|
priv->curr_xfer.addr = (addr << 1) | read_write;
|
||||||
|
priv->curr_xfer.data = data;
|
||||||
|
|
||||||
/* Map the size to what the chip understands */
|
/* Map the size to what the chip understands */
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case I2C_SMBUS_QUICK:
|
|
||||||
size = HST_CNTL2_QUICK;
|
|
||||||
break;
|
|
||||||
case I2C_SMBUS_BYTE:
|
case I2C_SMBUS_BYTE:
|
||||||
size = HST_CNTL2_BYTE;
|
priv->curr_xfer.cmd_len = 0;
|
||||||
break;
|
priv->curr_xfer.data_len = 1;
|
||||||
|
break;
|
||||||
case I2C_SMBUS_BYTE_DATA:
|
case I2C_SMBUS_BYTE_DATA:
|
||||||
size = HST_CNTL2_BYTE_DATA;
|
priv->curr_xfer.cmd_len = 1;
|
||||||
break;
|
priv->curr_xfer.data_len = 1;
|
||||||
|
priv->curr_xfer.cmd[0] = command;
|
||||||
|
break;
|
||||||
case I2C_SMBUS_WORD_DATA:
|
case I2C_SMBUS_WORD_DATA:
|
||||||
size = HST_CNTL2_WORD_DATA;
|
priv->curr_xfer.cmd_len = 1;
|
||||||
break;
|
priv->curr_xfer.data_len = 2;
|
||||||
case I2C_SMBUS_BLOCK_DATA:
|
priv->curr_xfer.cmd[0] = command;
|
||||||
size = HST_CNTL2_BLOCK;
|
break;
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
dev_warn(&a->dev, "Unsupported transaction %d\n", size);
|
dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
|
||||||
error = -EOPNOTSUPP;
|
error = -EOPNOTSUPP;
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (size) {
|
error = cpld_smbus_transfer(priv);
|
||||||
case HST_CNTL2_BYTE: /* Result put in SMBHSTDAT0 */
|
|
||||||
break;
|
|
||||||
case HST_CNTL2_BYTE_DATA:
|
|
||||||
break;
|
|
||||||
case HST_CNTL2_WORD_DATA:
|
|
||||||
if( 0 == i2c_read_eeprom(a,addr,new_data,cmd,data)){
|
|
||||||
error = 0;
|
|
||||||
}else{
|
|
||||||
error = -EIO;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Done:
|
Done:
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 dx010_i2c_func(struct i2c_adapter *a)
|
// TODO: Add support for I2C_FUNC_SMBUS_PROC_CALL and I2C_FUNC_SMBUS_I2C_BLOCK
|
||||||
{
|
static u32 dx010_i2c_func(struct i2c_adapter *a) {
|
||||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
return I2C_FUNC_SMBUS_READ_BYTE |
|
||||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
I2C_FUNC_SMBUS_BYTE_DATA |
|
||||||
I2C_FUNC_SMBUS_BLOCK_DATA;
|
I2C_FUNC_SMBUS_WORD_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct i2c_algorithm dx010_i2c_algorithm = {
|
static const struct i2c_algorithm dx010_i2c_algorithm = {
|
||||||
.smbus_xfer = dx010_i2c_access,
|
.smbus_xfer = dx010_smbus_xfer,
|
||||||
.functionality = dx010_i2c_func,
|
.functionality = dx010_i2c_func,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct i2c_adapter * cel_dx010_i2c_init(struct platform_device *pdev, int portid)
|
static struct i2c_adapter *cel_dx010_i2c_init(struct platform_device *pdev, int portid)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
int base_addr;
|
||||||
struct i2c_adapter *new_adapter;
|
struct i2c_adapter *new_adapter;
|
||||||
struct dx010_i2c_data *new_data;
|
struct dx010_i2c_data *priv;
|
||||||
|
|
||||||
|
switch (portid) {
|
||||||
|
case PORT_SFPP1 ... PORT_SFPP2:
|
||||||
|
case PORT_BANK1_START ... PORT_BANK1_END:
|
||||||
|
base_addr = CPLD_I2C_BANK1_BASE;
|
||||||
|
break;
|
||||||
|
case PORT_BANK2_START ... PORT_BANK2_END:
|
||||||
|
base_addr = CPLD_I2C_BANK2_BASE;
|
||||||
|
break;
|
||||||
|
case PORT_BANK3_START ... PORT_BANK3_END:
|
||||||
|
base_addr = CPLD_I2C_BANK3_BASE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(&pdev->dev, "Invalid port adapter ID: %d\n", portid);
|
||||||
|
goto error_exit;
|
||||||
|
}
|
||||||
|
|
||||||
new_adapter = kzalloc(sizeof(*new_adapter), GFP_KERNEL);
|
new_adapter = kzalloc(sizeof(*new_adapter), GFP_KERNEL);
|
||||||
if (!new_adapter)
|
if (!new_adapter)
|
||||||
@ -544,31 +585,39 @@ static struct i2c_adapter * cel_dx010_i2c_init(struct platform_device *pdev, int
|
|||||||
|
|
||||||
new_adapter->dev.parent = &pdev->dev;
|
new_adapter->dev.parent = &pdev->dev;
|
||||||
new_adapter->owner = THIS_MODULE;
|
new_adapter->owner = THIS_MODULE;
|
||||||
new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
new_adapter->class = I2C_CLASS_DEPRECATED;
|
||||||
new_adapter->algo = &dx010_i2c_algorithm;
|
new_adapter->algo = &dx010_i2c_algorithm;
|
||||||
|
|
||||||
snprintf(new_adapter->name, sizeof(new_adapter->name),
|
snprintf(new_adapter->name, sizeof(new_adapter->name),
|
||||||
"SMBus dx010 i2c Adapter portid@%04x", portid);
|
"SMBus dx010 i2c Adapter port %d", portid);
|
||||||
|
|
||||||
new_data = kzalloc(sizeof(*new_data), GFP_KERNEL);
|
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||||
if (!new_data)
|
if (!priv) {
|
||||||
return NULL;
|
goto free_adap;
|
||||||
|
}
|
||||||
|
|
||||||
new_data->portid = portid;
|
priv->portid = portid;
|
||||||
|
priv->base_addr = base_addr;
|
||||||
i2c_set_adapdata(new_adapter,new_data);
|
|
||||||
|
|
||||||
|
i2c_set_adapdata(new_adapter, priv);
|
||||||
error = i2c_add_adapter(new_adapter);
|
error = i2c_add_adapter(new_adapter);
|
||||||
if(error)
|
if(error)
|
||||||
return NULL;
|
goto free_data;
|
||||||
|
|
||||||
return new_adapter;
|
return new_adapter;
|
||||||
|
|
||||||
|
free_adap:
|
||||||
|
kzfree(new_adapter);
|
||||||
|
free_data:
|
||||||
|
kzfree(priv);
|
||||||
|
error_exit:
|
||||||
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int cel_dx010_lpc_drv_probe(struct platform_device *pdev)
|
static int cel_dx010_lpc_drv_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
int ret =0;
|
int ret = 0;
|
||||||
int portid_count;
|
int portid_count;
|
||||||
|
|
||||||
cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct dx010_cpld_data),
|
cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct dx010_cpld_data),
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=fan speed regulator
|
||||||
|
After=platform-modules-dx010.service
|
||||||
|
Before=pmon.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=-/etc/init.d/fancontrol.sh start
|
||||||
|
ExecStop=-/etc/init.d/fancontrol.sh stop
|
||||||
|
RemainAfterExit=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
@ -0,0 +1,75 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Copyright 2020-present Celestica. 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.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
|
||||||
|
SETREG_FILE=/sys/devices/platform/dx010_cpld/setreg
|
||||||
|
TOVERREG=0x140
|
||||||
|
CPUOVER=0xa1
|
||||||
|
ASICOVER=0xa2
|
||||||
|
|
||||||
|
prog="$0"
|
||||||
|
command="$1"
|
||||||
|
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
echo "This script must be run as root"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: thermal_overload_control.sh [option] <command>"
|
||||||
|
echo
|
||||||
|
echo "Options:"
|
||||||
|
echo " -h, --help : to print this message."
|
||||||
|
echo
|
||||||
|
echo "Commands:"
|
||||||
|
echo
|
||||||
|
echo " cpu: To enabling CPU thermal overload handler"
|
||||||
|
echo
|
||||||
|
echo " asic : To enabling ASIC thermal overload handler"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu_overload() {
|
||||||
|
logger "Enable CPU thermal overload control"
|
||||||
|
set_reg=`echo ${TOVERREG} ${CPUOVER} > ${SETREG_FILE}`
|
||||||
|
}
|
||||||
|
|
||||||
|
asic_overload() {
|
||||||
|
logger "Enable ASIC thermal overload control"
|
||||||
|
set_reg=`echo ${TOVERREG} ${ASICOVER} > ${SETREG_FILE}`
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ $# -lt 1 ]; then
|
||||||
|
usage
|
||||||
|
exit -1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$command" in
|
||||||
|
-h | --help)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
cpu)
|
||||||
|
cpu_overload
|
||||||
|
;;
|
||||||
|
asic)
|
||||||
|
asic_overload
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
exit -1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit $?
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user