[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:
Wirut Getbamrung 2020-09-25 00:20:15 +07:00 committed by GitHub
parent 6ae77f87cc
commit 10534a39eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 1985 additions and 1205 deletions

View File

@ -8,4 +8,6 @@ MINSTART=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e
MINSTOP=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
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

View File

@ -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
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
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

View File

@ -1,2 +1,2 @@
__all__ = ["platform", "chassis"]
from sonic_platform import *
import chassis
import platform

View File

@ -8,20 +8,10 @@
#
#############################################################################
import sys
import re
import os
import subprocess
import json
try:
import sys
from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform.fan import Fan
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
from helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
@ -33,9 +23,9 @@ NUM_SFP = 32
NUM_COMPONENT = 5
RESET_REGISTER = "0x103"
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"
PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt"
GETREG_PATH = "/sys/devices/platform/dx010_cpld/getreg"
HOST_CHK_CMD = "docker > /dev/null 2>&1"
@ -44,39 +34,54 @@ class Chassis(ChassisBase):
def __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 fan_index in range(0, NUM_FAN):
fan = Fan(fant_index, fan_index)
self._fan_list.append(fan)
for index in range(0, NUM_PSU):
psu = Psu(index)
self._psu_list.append(psu)
def __initialize_thermals(self):
from sonic_platform.thermal import Thermal
for index in range(0, NUM_THERMAL):
thermal = Thermal(index)
self._thermal_list.append(thermal)
# sfp index start from 1
for index in range(0, NUM_SFP):
sfp = Sfp(index)
self._sfp_list.append(sfp)
def __initialize_eeprom(self):
from sonic_platform.eeprom import Tlv
self._eeprom = Tlv()
def __initialize_components(self):
from sonic_platform.component import Component
for index in range(0, NUM_COMPONENT):
component = Component(index)
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):
"""
Retrieves the base MAC address for the chassis
@ -107,44 +112,98 @@ class Chassis(ChassisBase):
def get_reboot_cause(self):
"""
Retrieves the cause of the previous reboot
Returns:
A tuple (string, string) where the first element is a string
containing the cause of the previous reboot. This string must be
one of the predefined strings in this class. If the first string
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
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 = self.REBOOT_CAUSE_HARDWARE_OTHER
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 = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE)
sw_reboot_cause = self._api_helper.read_txt_file(
reboot_cause_path) or "Unknown"
prev_sw_reboot_cause = self.__read_txt_file(
prev_reboot_cause_path) or "Unknown"
hw_reboot_cause = self._api_helper.get_cpld_reg_value(
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":
reboot_cause = self.REBOOT_CAUSE_POWER_LOSS
elif sw_reboot_cause != "Unknown" and hw_reboot_cause == "0x11":
reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE
description = sw_reboot_cause
elif prev_reboot_cause_path != "Unknown" and hw_reboot_cause == "0x11":
reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE
description = prev_sw_reboot_cause
elif hw_reboot_cause == "0x22":
reboot_cause = self.REBOOT_CAUSE_WATCHDOG,
else:
reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER
description = 'Unknown reason'
prev_reboot_cause = {
'0x11': (self.REBOOT_CAUSE_POWER_LOSS, 'Power on reset'),
'0x22': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'CPLD_WD_RESET'),
'0x33': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Power cycle reset triggered by CPU'),
'0x44': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Power cycle reset triggered by reset button'),
'0x55': (self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU, ''),
'0x66': (self.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC, ''),
'0x77': (self.REBOOT_CAUSE_WATCHDOG, '')
}.get(hw_reboot_cause, (self.REBOOT_CAUSE_HARDWARE_OTHER, '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):
"""
@ -159,23 +218,46 @@ class Chassis(ChassisBase):
return self._watchdog
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
##############################################################
###################### Device methods ########################
##############################################################
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
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
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

View File

@ -8,14 +8,13 @@
#
#############################################################################
import json
import os.path
import shutil
import shlex
import subprocess
try:
from sonic_platform_base.component_base import ComponentBase
from helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
@ -29,7 +28,8 @@ CPLD_ADDR_MAPPING = {
GETREG_PATH = "/sys/devices/platform/dx010_cpld/getreg"
BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version"
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):
@ -40,24 +40,9 @@ class Component(ComponentBase):
def __init__(self, component_index):
ComponentBase.__init__(self)
self.index = component_index
self._api_helper = APIHelper()
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):
# Retrieves the BIOS firmware version
try:

View File

@ -14,6 +14,7 @@ import os.path
try:
from sonic_platform_base.fan_base import FanBase
from helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
@ -38,13 +39,16 @@ PSU_I2C_MAPPING = {
"addr": "5b"
},
}
NULL_VAL = "N/A"
class Fan(FanBase):
"""Platform-specific Fan class"""
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._api_helper = APIHelper()
self.fan_tray_index = fan_tray_index
self.is_psu_fan = 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': 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):
try:
@ -105,7 +99,7 @@ class Fan(FanBase):
def __get_gpio_base(self):
for r in os.listdir(GPIO_DIR):
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 216 # Reserve
@ -113,7 +107,7 @@ class Fan(FanBase):
gpio_base = self.dx010_fan_gpio[0]['base']
gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base+pinnum)
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')
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_path = self.__search_file_by_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
speed = math.ceil(float(fan_speed_rpm) * 100 / PSU_FAN_MAX_RPM)
elif self.get_presence():
@ -164,7 +159,7 @@ class Fan(FanBase):
sysfs_path = "%s%s/%s" % (
EMC2305_PATH, device, EMC2305_FAN_INPUT)
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
speed = math.ceil(float(pwm * 100 / EMC2305_MAX_PWM))
@ -183,19 +178,7 @@ class Fan(FanBase):
0 : when PWM mode is use
pwm : when pwm mode is not use
"""
target = 0
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
return 'N/A'
def get_speed_tolerance(self):
"""
@ -284,11 +267,43 @@ class Fan(FanBase):
def get_presence(self):
"""
Retrieves the presence of the PSU
Retrieves the presence of the FAN
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(
self.dx010_fan_gpio[self.fan_tray_index+1]['prs'])
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

View 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

View File

@ -14,6 +14,7 @@ import sonic_platform
try:
from sonic_platform_base.psu_base import PsuBase
from sonic_platform.fan import Fan
from helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
@ -41,6 +42,7 @@ class Psu(PsuBase):
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.dx010_psu_gpio = [
{'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)
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):
for dirpath, dirnames, files in os.walk(directory):
for name in files:
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 None
def __get_gpio_base(self):
for r in os.listdir(GPIO_DIR):
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 216 # Reserve
@ -82,7 +75,7 @@ class Psu(PsuBase):
gpio_base = self.dx010_psu_gpio[0]['base']
gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base+pinnum)
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')
def get_voltage(self):
@ -104,7 +97,7 @@ class Psu(PsuBase):
in_num = filter(str.isdigit, basename)
vout_path = os.path.join(
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
return psu_voltage
@ -127,7 +120,7 @@ class Psu(PsuBase):
cur_num = filter(str.isdigit, basename)
cur_path = os.path.join(
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
return psu_current
@ -150,7 +143,7 @@ class Psu(PsuBase):
pw_num = filter(str.isdigit, basename)
pw_path = os.path.join(
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
return psu_power
@ -196,7 +189,7 @@ class Psu(PsuBase):
Returns:
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 = {
'255': self.STATUS_LED_COLOR_GREEN,
'0': self.STATUS_LED_COLOR_OFF

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,7 @@ import os.path
try:
from sonic_platform_base.thermal_base import ThermalBase
from helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
@ -27,6 +28,7 @@ class Thermal(ThermalBase):
def __init__(self, thermal_index):
self.index = thermal_index
self._api_helper = APIHelper()
# Add thermal name
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_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):
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
return "{:.3f}".format(temp)
return float("{:.3f}".format(temp))
def __set_threshold(self, file_name, temperature):
temp_file_path = os.path.join(self.hwmon_path, file_name)

View File

@ -7,115 +7,79 @@
#
#############################################################################
import ctypes
import fcntl
import os
import subprocess
import time
import array
try:
from sonic_platform_base.watchdog_base import WatchdogBase
from helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
""" ioctl constants """
IO_WRITE = 0x40000000
IO_READ = 0x80000000
IO_READ_WRITE = 0xC0000000
IO_SIZE_INT = 0x00040000
IO_SIZE_40 = 0x00280000
IO_TYPE_WATCHDOG = ord('W') << 8
WDR_INT = IO_READ | IO_SIZE_INT | IO_TYPE_WATCHDOG
WDR_40 = IO_READ | IO_SIZE_40 | IO_TYPE_WATCHDOG
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
PLATFORM_CPLD_PATH = '/sys/devices/platform/dx010_cpld'
GETREG_FILE = 'getreg'
SETREG_FILE = 'setreg'
WDT_ENABLE_REG = '0x141'
WDT_TIMER_L_BIT_REG = '0x142'
WDT_TIMER_M_BIT_REG = '0x143'
WDT_TIMER_H_BIT_REG = '0x144'
WDT_KEEP_ALVIVE_REG = '0x145'
ENABLE_CMD = '0x1'
DISABLE_CMD = '0x0'
WDT_COMMON_ERROR = -1
WD_MAIN_IDENTITY = "iTCO_wdt"
WDT_SYSFS_PATH = "/sys/class/watchdog/"
class Watchdog(WatchdogBase):
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
self._disable()
self.armed = False
self.timeout = self._gettimeout(self.timeout_path)
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()
self.timeout = self._gettimeout()
def _enable(self):
"""
Turn on the watchdog timer
"""
req = array.array('h', [WDIOS_ENABLECARD])
fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False)
# echo 0x141 0x1 > /sys/devices/platform/dx010_cpld/setreg
enable_val = '{} {}'.format(WDT_ENABLE_REG, ENABLE_CMD)
return self._api_helper.write_txt_file(self.setreg_path, enable_val)
def _disable(self):
"""
Turn off the watchdog timer
"""
req = array.array('h', [WDIOS_DISABLECARD])
fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False)
# echo 0x141 0x0 > /sys/devices/platform/dx010_cpld/setreg
disable_val = '{} {}'.format(WDT_ENABLE_REG, DISABLE_CMD)
return self._api_helper.write_txt_file(self.setreg_path, disable_val)
def _keepalive(self):
"""
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):
"""
@ -123,29 +87,35 @@ class Watchdog(WatchdogBase):
@param seconds - timeout in seconds
@return is the actual set timeout
"""
req = array.array('I', [seconds])
fcntl.ioctl(self.watchdog, WDIOC_SETTIMEOUT, req, True)
return int(req[0])
# max = 0xffffff = 16777.215 seconds
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
@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):
"""
Get time left before watchdog timer expires
@return time left in seconds
"""
req = array.array('I', [0])
fcntl.ioctl(self.watchdog, WDIOC_GETTIMELEFT, req, True)
return int(req[0])
hex_time = '0x{}{}{}'.format(h_bit[2:], m_bit[2:], l_bit[2:])
ms = int(hex_time, 16)
return int(float(ms)/1000)
#################################################################
@ -169,12 +139,15 @@ class Watchdog(WatchdogBase):
try:
if self.timeout != seconds:
self.timeout = self._settimeout(seconds)
if self.armed:
self._keepalive()
else:
self._enable()
self.armed = True
ret = self.timeout
self.arm_timestamp = time.time()
except IOError as e:
pass
@ -215,19 +188,4 @@ class Watchdog(WatchdogBase):
watchdog timer. If the watchdog is not armed, returns -1.
"""
timeleft = WDT_COMMON_ERROR
if self.armed:
try:
timeleft = self._gettimeleft()
except IOError:
pass
return timeleft
def __del__(self):
"""
Close watchdog
"""
os.close(self.watchdog)
return int(self.timeout - (time.time() - self.arm_timestamp)) if self.armed else WDT_COMMON_ERROR

View File

@ -2,7 +2,8 @@ dx010/scripts/dx010_check_qsfp.sh usr/local/bin
dx010/cfg/dx010-modules.conf etc/modules-load.d
dx010/systemd/platform-modules-dx010.service lib/systemd/system
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
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

View File

@ -1,7 +1,7 @@
haliburton/cfg/haliburton-modules.conf etc/modules-load.d
haliburton/systemd/platform-modules-haliburton.service lib/systemd/system
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
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

View File

@ -76,42 +76,52 @@
#define PORT_SFPP1 33
#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 OPCODE_ID_BANK2 0x291
#define OPCODE_ID_BANK3 0x391
#define CPLD_I2C_CLK_100Khz_BIT BIT(6)
#define CPLD_I2C_DATA_SZ_MASK GENMASK(7,4)
#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 CMDBYT_ID_BANK2 0x293
#define CMDBYT_ID_BANK3 0x393
#define CPLD_I2C_BANK1_BASE 0x210
#define CPLD_I2C_BANK2_BASE 0x290
#define CPLD_I2C_BANK3_BASE 0x390
#define WRITE_ID_BANK1 0x220
#define WRITE_ID_BANK2 0x2A0
#define WRITE_ID_BANK3 0x3A0
#define I2C_PORT_ID 0x0
#define I2C_OPCODE 0x1
#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
#define READ_ID_BANK3 0x3B0
#define SSRR_ID_BANK1 0x216
#define SSRR_ID_BANK2 0x296
#define SSRR_ID_BANK3 0x396
#define HST_CNTL2_QUICK 0x00
#define HST_CNTL2_BYTE 0x01
#define HST_CNTL2_BYTE_DATA 0x02
#define HST_CNTL2_WORD_DATA 0x03
#define HST_CNTL2_BLOCK 0x05
/*
* private data to send to I2C core
*/
struct current_xfer {
u8 addr;
u8 cmd[CPLD_I2C_CMD_SZ_MAX];
u8 cmd_len;
u8 data_len;
union i2c_smbus_data *data;
};
/*
* 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 {
int base_addr;
int portid;
struct current_xfer curr_xfer;
};
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) {
/**
* Read eeprom of QSFP device.
* @param a i2c adapter.
* @param addr address to read.
* @param new_data QSFP port number struct.
* @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){
u8 val;
s32 error;
unsigned long ioBase;
short portid, opcode, devaddr, cmdbyte0, ssr, writedata, readdata;
union i2c_smbus_data *data;
u32 reg;
int ioBase=0;
char byte;
short temp;
short portid, opcode, devaddr, cmdbyte0, ssrr, writedata, readdata;
__u16 word_data;
int error = -EIO;
error = -EIO;
mutex_lock(&cpld_data->cpld_lock);
if (((new_data->portid >= PORT_BANK1_START)
&& (new_data->portid <= PORT_BANK1_END))
|| (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;
}
ioBase = priv->base_addr;
data = priv->curr_xfer.data;
while ((inb(ioBase + ssrr) & 0x40));
if ((inb(ioBase + ssrr) & 0x80) == 0x80) {
error = -EIO;
/* Read error reset the port */
outb(0x00, ioBase + ssrr);
udelay(3000);
outb(0x01, ioBase + ssrr);
goto exit;
}
portid = ioBase + I2C_PORT_ID;
opcode = ioBase + I2C_OPCODE;
devaddr = ioBase + I2C_DEV_ADDR;
cmdbyte0 = ioBase + I2C_CMD_BYT0;
ssr = ioBase + I2C_SSR;
writedata = ioBase + I2C_WRITE_DATA;
readdata = ioBase + I2C_READ_DATA;
byte = 0x40 +new_data->portid;
reg = cmd;
outb(byte, ioBase + portid);
outb(reg,ioBase + cmdbyte0);
byte = 33;
outb(byte, ioBase + opcode);
addr = addr << 1;
addr |= 0x01;
outb(addr, ioBase + devaddr);
while ((inb(ioBase + ssrr) & 0x40))
{
/* Wait for the core to be free */
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
if ((inb(ioBase + ssrr) & 0x80) == 0x80) {
/* Read error reset the port */
error = -EIO;
outb(0x00, ioBase + ssrr);
/*
* If any error happen here, we do soft-reset
* and check the BUSY/ERROR again.
*/
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);
outb(0x01, ioBase + ssrr);
goto exit;
outb(CPLD_I2C_UNRESET, ssr);
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;
word_data = inb(temp);
word_data |= (inb(++temp) << 8);
/* Configure PortID */
val = priv->portid | CPLD_I2C_CLK_100Khz_BIT;
outb(val, portid);
pr_debug("CPLD_I2C Write PortID 0x%x\n", val);
mutex_unlock(&cpld_data->cpld_lock);
data->word = word_data;
return 0;
/* Configure OP_Code */
val = (priv->curr_xfer.data_len << 4) & CPLD_I2C_DATA_SZ_MASK;
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);
return error;
}
static int dx010_i2c_access(struct i2c_adapter *a, u16 addr,
unsigned short flags, char rw, u8 cmd,
int size, union i2c_smbus_data *data)
{
/*
* dx010_smbus_xfer - execute LPC-SMBus transfer
* 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;
struct dx010_i2c_data *priv;
struct dx010_i2c_data *new_data;
priv = i2c_get_adapdata(adap);
/* Write the command register */
new_data = i2c_get_adapdata(a);
pr_debug("smbus_xfer called RW:%x CMD:%x SIZE:0x%x",
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 */
switch (size) {
case I2C_SMBUS_QUICK:
size = HST_CNTL2_QUICK;
break;
case I2C_SMBUS_BYTE:
size = HST_CNTL2_BYTE;
break;
priv->curr_xfer.cmd_len = 0;
priv->curr_xfer.data_len = 1;
break;
case I2C_SMBUS_BYTE_DATA:
size = HST_CNTL2_BYTE_DATA;
break;
priv->curr_xfer.cmd_len = 1;
priv->curr_xfer.data_len = 1;
priv->curr_xfer.cmd[0] = command;
break;
case I2C_SMBUS_WORD_DATA:
size = HST_CNTL2_WORD_DATA;
break;
case I2C_SMBUS_BLOCK_DATA:
size = HST_CNTL2_BLOCK;
break;
priv->curr_xfer.cmd_len = 1;
priv->curr_xfer.data_len = 2;
priv->curr_xfer.cmd[0] = command;
break;
default:
dev_warn(&a->dev, "Unsupported transaction %d\n", size);
dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
error = -EOPNOTSUPP;
goto Done;
}
switch (size) {
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;
}
error = cpld_smbus_transfer(priv);
Done:
return error;
}
static u32 dx010_i2c_func(struct i2c_adapter *a)
{
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_BLOCK_DATA;
// 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_READ_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA;
}
static const struct i2c_algorithm dx010_i2c_algorithm = {
.smbus_xfer = dx010_i2c_access,
.smbus_xfer = dx010_smbus_xfer,
.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 base_addr;
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);
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->owner = THIS_MODULE;
new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
new_adapter->class = I2C_CLASS_DEPRECATED;
new_adapter->algo = &dx010_i2c_algorithm;
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);
if (!new_data)
return NULL;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
goto free_adap;
}
new_data->portid = portid;
i2c_set_adapdata(new_adapter,new_data);
priv->portid = portid;
priv->base_addr = base_addr;
i2c_set_adapdata(new_adapter, priv);
error = i2c_add_adapter(new_adapter);
if(error)
return NULL;
goto free_data;
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)
{
struct resource *res;
int ret =0;
int ret = 0;
int portid_count;
cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct dx010_cpld_data),

View File

@ -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

View File

@ -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 $?