diff --git a/device/celestica/x86_64-cel_e1031-r0/sonic_platform/__init__.py b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/device/celestica/x86_64-cel_e1031-r0/sonic_platform/chassis.py b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/chassis.py new file mode 100644 index 000000000000..33fa88f8e700 --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/chassis.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Chassis information which are available in the platform +# +############################################################################# + +import sys +import re +import os +import subprocess +import json + +try: + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +MMC_CPLD_ADDR = '0x100' +BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version" +CONFIG_DB_PATH = "/etc/sonic/config_db.json" +SMC_CPLD_PATH = "/sys/devices/platform/e1031.smc/version" +MMC_CPLD_PATH = "/sys/devices/platform/e1031.smc/getreg" +NUM_FAN = 3 + + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + + def __init__(self): + self.config_data = {} + for index in range(0, NUM_FAN): + fan = Fan(index) + self._fan_list.append(fan) + ChassisBase.__init__(self) + + def __get_register_value(self, path, register): + cmd = "echo {1} > {0}; cat {0}".format(path, register) + p = subprocess.Popen( + cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err is not '': + return 'None' + else: + return raw_data.strip() + + def __read_config_db(self): + try: + with open(CONFIG_DB_PATH, 'r') as fd: + data = json.load(fd) + return data + except IOError: + raise IOError("Unable to open config_db file !") + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + try: + self.config_data = self.__read_config_db() + base_mac = self.config_data["DEVICE_METADATA"]["localhost"]["mac"] + return str(base_mac) + except KeyError: + raise KeyError("Base MAC not found") + + def get_component_versions(self): + """ + Retrieves platform-specific hardware/firmware versions for chassis + componenets such as BIOS, CPLD, FPGA, etc. + Returns: + A string containing platform-specific component versions + """ + + component_versions = dict() + + # Get BIOS version + try: + with open(BIOS_VERSION_PATH, 'r') as fd: + bios_version = fd.read() + except IOError: + raise IOError("Unable to open version file !") + + # Get CPLD version + cpld_version = dict() + + with open(SMC_CPLD_PATH, 'r') as fd: + smc_cpld_version = fd.read() + smc_cpld_version = 'None' if smc_cpld_version is 'None' else "{}.{}".format( + int(smc_cpld_version[2], 16), int(smc_cpld_version[3], 16)) + + mmc_cpld_version = self.__get_register_value( + MMC_CPLD_PATH, MMC_CPLD_ADDR) + mmc_cpld_version = 'None' if mmc_cpld_version is 'None' else "{}.{}".format( + int(mmc_cpld_version[2], 16), int(mmc_cpld_version[3], 16)) + + cpld_version["SMC"] = smc_cpld_version + cpld_version["MMC"] = mmc_cpld_version + + component_versions["CPLD"] = cpld_version + component_versions["BIOS"] = bios_version.strip() + return str(component_versions) diff --git a/device/celestica/x86_64-cel_e1031-r0/sonic_platform/fan.py b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/fan.py new file mode 100644 index 000000000000..d16290aa4596 --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/fan.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the fan status which are available in the platform +# +############################################################################# + +import json +import math +import os.path + +try: + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +EMC2305_FAN_PATH = "/sys/bus/i2c/drivers/emc2305/" +FAN_PATH = "/sys/devices/platform/e1031.smc/" +SYS_GPIO_DIR = "/sys/class/gpio" +EMC2305_MAX_PWM = 255 +EMC2305_FAN_PWM = "pwm{}" +EMC2305_FAN_TARGET = "fan{}_target" +EMC2305_FAN_INPUT = "pwm{}" + + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, fan_index): + self.index = fan_index + self.config_data = {} + self.fan_speed = 0 + + # e1031 fan attributes + # Single emc2305 chip located at i2c-23-4d + # to control a fan module + self.e1031_emc2305_chip = [ + { + 'device': "23-004d", + 'index_map': [1, 2, 4] + } + ] + + # TODO: Add fan presence status in sysfs + self.fan_e1031_presence = "fan{}_prs" + self.fan_e1031_direction = "fan{}_dir" + self.fan_e1031_led = "fan{}_led" + self.fan_e1031_led_col_map = { + self.STATUS_LED_COLOR_GREEN: "green", + self.STATUS_LED_COLOR_RED: "amber", + self.STATUS_LED_COLOR_OFF: "off" + } + FanBase.__init__(self) + + def get_direction(self): + + direction = self.FAN_DIRECTION_INTAKE + + try: + fan_direction_file = (FAN_PATH + + self.fan_e1031_direction.format(self.index+1)) + with open(fan_direction_file, 'r') as file: + raw = file.read().strip('\r\n') + if str(raw).upper() == "F2B": + direction = self.FAN_DIRECTION_INTAKE + else: + direction = self.FAN_DIRECTION_EXHAUST + except IOError: + return False + + return direction + + def get_speed(self): + """ + E1031 platform specific data: + + speed = pwm_in/255*100 + """ + # TODO: Seperate PSU's fan and main fan class + if self.fan_speed != 0: + return self.fan_speed + else: + speed = 0 + pwm = [] + emc2305_chips = self.e1031_emc2305_chip + + for chip in emc2305_chips: + device = chip['device'] + fan_index = chip['index_map'] + sysfs_path = "%s%s/%s" % ( + EMC2305_FAN_PATH, device, EMC2305_FAN_INPUT) + sysfs_path = sysfs_path.format(fan_index[self.index]) + try: + with open(sysfs_path, 'r') as file: + raw = file.read().strip('\r\n') + pwm.append(int(raw, 10)) + except IOError: + raise IOError("Unable to open " + sysfs_path) + + speed = math.ceil( + float(pwm[0]) * 100 / EMC2305_MAX_PWM) + + return int(speed) + + def get_target_speed(self): + """ + E1031 platform specific data: + + speed_pc = pwm_target/255*100 + + 0 : when PWM mode is use + pwm : when pwm mode is not use + + """ + target = 0 + pwm = [] + emc2305_chips = self.e1031_emc2305_chip + + for chip in emc2305_chips: + device = chip['device'] + fan_index = chip['index_map'] + sysfs_path = "%s%s/%s" % ( + EMC2305_FAN_PATH, device, EMC2305_FAN_TARGET) + sysfs_path = sysfs_path.format(fan_index[self.index]) + try: + with open(sysfs_path, 'r') as file: + raw = file.read().strip('\r\n') + pwm.append(int(raw, 10)) + except IOError: + raise IOError("Unable to open " + sysfs_path) + + target = pwm[0] * 100 / EMC2305_MAX_PWM + + return target + + def get_speed_tolerance(self): + """ + Retrieves the speed tolerance of the fan + Returns: + An integer, the percentage of variance from target speed which is + considered tolerable + """ + return 10 + + def set_speed(self, speed): + """ + Depends on pwm or target mode is selected: + 1) pwm = speed_pc * 255 <-- Currently use this mode. + 2) target_pwm = speed_pc * 100 / 255 + 2.1) set pwm{}_enable to 3 + + """ + pwm = speed * 255 / 100 + emc2305_chips = self.e1031_emc2305_chip + + for chip in emc2305_chips: + device = chip['device'] + fan_index = chip['index_map'] + sysfs_path = "%s%s/%s" % ( + EMC2305_FAN_PATH, device, EMC2305_FAN_PWM) + sysfs_path = sysfs_path.format(fan_index[self.index]) + try: + with open(sysfs_path, 'w') as file: + file.write(str(int(pwm))) + except IOError: + return False + + return True + + def set_status_led(self, color): + + try: + fan_led_file = (FAN_PATH + + self.fan_e1031_led.format(self.index+1)) + with open(fan_led_file, 'r') as file: + file.write(self.fan_e1031_led_col_map[color]) + except IOError: + return False + + return True diff --git a/device/celestica/x86_64-cel_e1031-r0/sonic_platform/platform.py b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/platform.py new file mode 100644 index 000000000000..a632de87e742 --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/platform.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + """Platform-specific Platform class""" + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/__init__.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/chassis.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/chassis.py new file mode 100644 index 000000000000..1d2e9af3757b --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/chassis.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Chassis information which are available in the platform +# +############################################################################# + +import sys +import re +import os +import subprocess +import json + +try: + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version" +GETREG_PATH = "/sys/devices/platform/dx010_cpld/getreg" +CONFIG_DB_PATH = "/etc/sonic/config_db.json" +NUM_FAN = 5 +CPLD_ADDR_MAPPING = { + "CPLD1": "0x100", + "CPLD2": "0x200", + "CPLD3": "0x280", + "CPLD4": "0x300", + "CPLD5": "0x380" +} + + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + + def __init__(self): + self.config_data = {} + for index in range(0, NUM_FAN): + fan = Fan(index) + self._fan_list.append(fan) + ChassisBase.__init__(self) + + def __get_register_value(self, path, register): + cmd = "echo {1} > {0}; cat {0}".format(path, register) + p = subprocess.Popen( + cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err is not '': + return 'None' + else: + return raw_data.strip() + + def __read_config_db(self): + try: + with open(CONFIG_DB_PATH, 'r') as fd: + data = json.load(fd) + return data + except IOError: + raise IOError("Unable to open config_db file !") + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + try: + self.config_data = self.__read_config_db() + base_mac = self.config_data["DEVICE_METADATA"]["localhost"]["mac"] + return str(base_mac) + except KeyError: + raise KeyError("Base MAC not found") + + def get_component_versions(self): + """ + Retrieves platform-specific hardware/firmware versions for chassis + componenets such as BIOS, CPLD, FPGA, etc. + Returns: + A string containing platform-specific component versions + """ + + component_versions = dict() + + # Get BIOS version + try: + with open(BIOS_VERSION_PATH, 'r') as fd: + bios_version = fd.read() + except IOError: + raise IOError("Unable to open version file !") + + # Get CPLD version + cpld_version = dict() + for cpld_name in CPLD_ADDR_MAPPING: + try: + cpld_addr = CPLD_ADDR_MAPPING[cpld_name] + cpld_version_raw = self.__get_register_value( + GETREG_PATH, cpld_addr) + cpld_version_str = "{}.{}".format(int(cpld_version_raw[2], 16), int( + cpld_version_raw[3], 16)) if cpld_version_raw is not None else 'None' + cpld_version[cpld_name] = cpld_version_str + except Exception, e: + cpld_version[cpld_name] = 'None' + component_versions["CPLD"] = cpld_version + component_versions["BIOS"] = bios_version.strip() + return str(component_versions) diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/fan.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/fan.py new file mode 100644 index 000000000000..227c1d2ade52 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/fan.py @@ -0,0 +1,228 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the fan status which are available in the platform +# +############################################################################# + +import json +import math +import os.path + +try: + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CONFIG_DB_PATH = "/etc/sonic/config_db.json" +EMC2305_PATH = "/sys/bus/i2c/drivers/emc2305/" +SYS_GPIO_DIR = "/sys/class/gpio" +EMC2305_MAX_PWM = 255 +EMC2305_FAN_PWM = "pwm{}" +EMC2305_FAN_TARGET = "fan{}_target" +EMC2305_FAN_INPUT = "pwm{}" + + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, fan_index): + self.index = fan_index + self.config_data = {} + self.fan_speed = 0 + FanBase.__init__(self) + + # dx010 fan attributes + # Two EMC2305s located at i2c-13-4d and i2c-13-2e + # to control a dual-fan module. + self.dx010_emc2305_chip = [ + { + 'device': "13-002e", + 'index_map': [2, 1, 4, 5, 3] + }, + { + 'device': "13-004d", + 'index_map': [2, 4, 5, 3, 1] + } + ] + + self.dx010_fan_gpio = [ + {'base': self.get_gpio_base()}, + {'prs': 10, 'dir': 15, 'color': {'red': 31, 'green': 32}}, + {'prs': 11, 'dir': 16, 'color': {'red': 29, 'green': 30}}, + {'prs': 12, 'dir': 17, 'color': {'red': 35, 'green': 36}}, + {'prs': 13, 'dir': 18, 'color': {'red': 37, 'green': 38}}, + {'prs': 14, 'dir': 19, 'color': {'red': 33, 'green': 34}}, + ] + + def get_gpio_base(self): + for r in os.listdir(SYS_GPIO_DIR): + if "gpiochip" in r: + return int(r[8:], 10) + return 216 # Reserve + + def get_gpio_value(self, pinnum): + gpio_base = self.dx010_fan_gpio[0]['base'] + + gpio_dir = SYS_GPIO_DIR + '/gpio' + str(gpio_base+pinnum) + gpio_file = gpio_dir + "/value" + + try: + with open(gpio_file, 'r') as fd: + retval = fd.read() + except IOError: + raise IOError("Unable to open " + gpio_file + "file !") + + retval = retval.rstrip('\r\n') + return retval + + def set_gpio_value(self, pinnum, value=0): + gpio_base = self.dx010_fan_gpio[0]['base'] + + gpio_dir = SYS_GPIO_DIR + '/gpio' + str(gpio_base+pinnum) + gpio_file = gpio_dir + "/value" + + try: + with open(gpio_file, 'w') as fd: + retval = fd.write(str(value)) + except IOError: + raise IOError("Unable to open " + gpio_file + "file !") + + def get_direction(self): + + direction = self.FAN_DIRECTION_INTAKE + raw = self.get_gpio_value(self.dx010_fan_gpio[self.index+1]['dir']) + + if int(raw, 10) == 0: + direction = self.FAN_DIRECTION_INTAKE + else: + direction = self.FAN_DIRECTION_EXHAUST + + return direction + + def get_speed(self): + """ + DX010 platform specific data: + + speed = pwm_in/255*100 + """ + # TODO: Seperate PSU's fan and main fan class + if self.fan_speed != 0: + return self.fan_speed + else: + speed = 0 + pwm = [] + emc2305_chips = self.dx010_emc2305_chip + + for chip in emc2305_chips: + device = chip['device'] + fan_index = chip['index_map'] + sysfs_path = "%s%s/%s" % ( + EMC2305_PATH, device, EMC2305_FAN_INPUT) + sysfs_path = sysfs_path.format(fan_index[self.index]) + try: + with open(sysfs_path, 'r') as file: + raw = file.read().strip('\r\n') + pwm.append(int(raw, 10)) + except IOError: + raise IOError("Unable to open " + sysfs_path) + + speed = math.ceil( + float(pwm[0]) * 100 / EMC2305_MAX_PWM) + + return int(speed) + + def get_target_speed(self): + """ + DX010 platform specific data: + + speed_pc = pwm_target/255*100 + + 0 : when PWM mode is use + pwm : when pwm mode is not use + + """ + target = 0 + pwm = [] + emc2305_chips = self.dx010_emc2305_chip + + for chip in emc2305_chips: + 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.index]) + try: + with open(sysfs_path, 'r') as file: + raw = file.read().strip('\r\n') + pwm.append(int(raw, 10)) + except IOError: + raise IOError("Unable to open " + sysfs_path) + + target = pwm[0] * 100 / EMC2305_MAX_PWM + + return target + + def get_speed_tolerance(self): + """ + Retrieves the speed tolerance of the fan + Returns: + An integer, the percentage of variance from target speed which is + considered tolerable + """ + return 10 + + def set_speed(self, speed): + """ + Depends on pwm or target mode is selected: + 1) pwm = speed_pc * 255 <-- Currently use this mode. + 2) target_pwm = speed_pc * 100 / 255 + 2.1) set pwm{}_enable to 3 + + """ + pwm = speed * 255 / 100 + emc2305_chips = self.dx010_emc2305_chip + + for chip in emc2305_chips: + device = chip['device'] + fan_index = chip['index_map'] + sysfs_path = "%s%s/%s" % ( + EMC2305_PATH, device, EMC2305_FAN_PWM) + sysfs_path = sysfs_path.format(fan_index[self.index]) + try: + with open(sysfs_path, 'w') as file: + file.write(str(int(pwm))) + except IOError: + return False + + return True + + def set_status_led(self, color): + try: + if color == self.STATUS_LED_COLOR_GREEN: + self.set_gpio_value( + self.dx010_fan_gpio[self.index+1]['color']['red'], 1) + self.set_gpio_value( + self.dx010_fan_gpio[self.index+1]['color']['green'], 0) + + elif color == self.STATUS_LED_COLOR_RED: + self.set_gpio_value( + self.dx010_fan_gpio[self.index+1]['color']['red'], 0) + self.set_gpio_value( + self.dx010_fan_gpio[self.index+1]['color']['green'], 1) + + elif color == self.STATUS_LED_COLOR_OFF: + self.set_gpio_value( + self.dx010_fan_gpio[self.index+1]['color']['red'], 1) + self.set_gpio_value( + self.dx010_fan_gpio[self.index+1]['color']['green'], 1) + else: + return False + + except IOError: + return False + + return True diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/platform.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/platform.py new file mode 100644 index 000000000000..a632de87e742 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/platform.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + """Platform-specific Platform class""" + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.init b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.init index 2117ab22b402..aa13d572be78 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.init +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.init @@ -12,7 +12,8 @@ ### END INIT INFO function export_gpio { -label=$2 +label=$3 +gpio_dir=$2 gpio_num=$1 gpio_base=`( cat /sys/class/gpio/gpiochip*/base | head -1 ) 2>/dev/null` gpio_label=`( cat /sys/class/gpio/gpiochip*/label | head -1 ) 2>/dev/null` @@ -27,6 +28,13 @@ if [ $? -ne 0 ]; then echo "Platform driver error: Cannot export gpio$ionum!" exit 1; fi +if [[ "X$gpio_dir" != "X" ]]; then + echo $gpio_dir > /sys/class/gpio/gpio${ionum}/direction + if [ $? -ne 0 ]; then + echo "Platform driver error: Cannot set direction of gpio$ionum!" + exit 1; + fi +fi } case "$1" in @@ -95,27 +103,33 @@ start) sleep 2 # Export platform gpio sysfs - export_gpio 10 # Fan 1 present - export_gpio 11 # Fan 2 present - export_gpio 12 # Fan 3 present - export_gpio 13 # Fan 4 present - export_gpio 14 # Fan 5 present - - export_gpio 22 # PSU L PWOK - export_gpio 25 # PSU R PWOK - export_gpio 27 # PSU L ABS - export_gpio 28 # PSU R ABS - - export_gpio 29 # Fan 1 LED: Red - export_gpio 30 # Fan 1 LED: Yellow - export_gpio 31 # Fan 2 LED: Red - export_gpio 32 # Fan 2 LED: Yellow - export_gpio 33 # Fan 3 LED: Red - export_gpio 34 # Fan 3 LED: Yellow - export_gpio 35 # Fan 4 LED: Red - export_gpio 36 # Fan 4 LED: Yellow - export_gpio 37 # Fan 5 LED: Red - export_gpio 38 # Fan 5 LED: Yellow + export_gpio 10 "in" # Fan 1 present + export_gpio 11 "in" # Fan 2 present + export_gpio 12 "in" # Fan 3 present + export_gpio 13 "in" # Fan 4 present + export_gpio 14 "in" # Fan 5 present + + export_gpio 15 "in" # Fan 1 direction + export_gpio 16 "in" # Fan 2 direction + export_gpio 17 "in" # Fan 3 direction + export_gpio 18 "in" # Fan 4 direction + export_gpio 19 "in" # Fan 5 direction + + export_gpio 22 "in" # PSU L PWOK + export_gpio 25 "in" # PSU R PWOK + export_gpio 27 "in" # PSU L ABS + export_gpio 28 "in" # PSU R ABS + + export_gpio 29 "out" # Fan 1 LED: Red + export_gpio 30 "out" # Fan 1 LED: Yellow + export_gpio 31 "out" # Fan 2 LED: Red + export_gpio 32 "out" # Fan 2 LED: Yellow + export_gpio 33 "out" # Fan 3 LED: Red + export_gpio 34 "out" # Fan 3 LED: Yellow + export_gpio 35 "out" # Fan 4 LED: Red + export_gpio 36 "out" # Fan 4 LED: Yellow + export_gpio 37 "out" # Fan 5 LED: Red + export_gpio 38 "out" # Fan 5 LED: Yellow # Turn off/down lpmod by defult (0 - Normal, 1 - Low Pow) echo 0x00000000 > /sys/devices/platform/dx010_cpld/qsfp_lpmode diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_cpld.c b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_cpld.c index 397361a5edd6..7893220ff6d5 100644 --- a/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_cpld.c +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_cpld.c @@ -30,6 +30,13 @@ #define DRIVER_NAME "dx010_cpld" +#define CPLD1_VERSION_ADDR 0x100 +#define CPLD2_VERSION_ADDR 0x200 +#define CPLD3_VERSION_ADDR 0x280 +#define CPLD4_VERSION_ADDR 0x300 +#define CPLD5_VERSION_ADDR 0x380 + + #define RESET0108 0x250 #define RESET0910 0x251 #define RESET1118 0x2d0 @@ -110,10 +117,36 @@ struct dx010_i2c_data { struct dx010_cpld_data { struct i2c_adapter *i2c_adapter[LENGTH_PORT_CPLD]; struct mutex cpld_lock; + uint16_t read_addr; }; struct dx010_cpld_data *cpld_data; +static ssize_t getreg_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + + uint16_t addr; + char *last; + + addr = (uint16_t)strtoul(buf,&last,16); + if(addr == 0 && buf == last){ + return -EINVAL; + } + cpld_data->read_addr = addr; + return count; +} + +static ssize_t getreg_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + + int len = 0; + mutex_lock(&cpld_data->cpld_lock); + len = sprintf(buf, "0x%2.2x\n",inb(cpld_data->read_addr)); + mutex_unlock(&cpld_data->cpld_lock); + return len; +} + static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -134,6 +167,47 @@ static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, return sprintf(buf,"0x%8.8lx\n", reset & 0xffffffff); } +static ssize_t setreg_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + + uint16_t addr; + uint8_t value; + char *tok; + char clone[count]; + char *pclone = clone; + char *last; + + strcpy(clone, buf); + + mutex_lock(&cpld_data->cpld_lock); + tok = strsep((char**)&pclone, " "); + if(tok == NULL){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + addr = (uint16_t)strtoul(tok,&last,16); + if(addr == 0 && tok == last){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + + tok = strsep((char**)&pclone, " "); + if(tok == NULL){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + value = (uint8_t)strtoul(tok,&last,16); + if(value == 0 && tok == last){ + mutex_unlock(&cpld_data->cpld_lock); + return -EINVAL; + } + + outb(value,addr); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} + static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { @@ -248,12 +322,16 @@ static ssize_t get_modirq(struct device *dev, struct device_attribute *devattr, return sprintf(buf,"0x%8.8lx\n", irq & 0xffffffff); } +static DEVICE_ATTR_RW(getreg); +static DEVICE_ATTR_WO(setreg); static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR, get_reset, set_reset); static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR, get_lpmode, set_lpmode); static DEVICE_ATTR(qsfp_modprs, S_IRUGO, get_modprs, NULL); static DEVICE_ATTR(qsfp_modirq, S_IRUGO, get_modirq, NULL); static struct attribute *dx010_lpc_attrs[] = { + &dev_attr_getreg.attr, + &dev_attr_setreg.attr, &dev_attr_qsfp_reset.attr, &dev_attr_qsfp_lpmode.attr, &dev_attr_qsfp_modprs.attr, @@ -499,6 +577,7 @@ static int cel_dx010_lpc_drv_probe(struct platform_device *pdev) return -ENOMEM; mutex_init(&cpld_data->cpld_lock); + cpld_data->read_addr = CPLD1_VERSION_ADDR; res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (unlikely(!res)) { @@ -558,4 +637,4 @@ module_exit(cel_dx010_lpc_exit); MODULE_AUTHOR("Abhisit Sangjan "); MODULE_AUTHOR("Pariwat Leamsumran "); MODULE_DESCRIPTION("Celestica SeaStone DX010 LPC Driver"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL"); \ No newline at end of file