diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248pxe/modules/dell_n3248pxe_platform.c b/platform/broadcom/sonic-platform-modules-dell/n3248pxe/modules/dell_n3248pxe_platform.c index 1c5d07bffab..5fb106f186b 100644 --- a/platform/broadcom/sonic-platform-modules-dell/n3248pxe/modules/dell_n3248pxe_platform.c +++ b/platform/broadcom/sonic-platform-modules-dell/n3248pxe/modules/dell_n3248pxe_platform.c @@ -853,6 +853,41 @@ static ssize_t fan_led_store(struct device *dev, struct device_attribute *devatt return count; } +static ssize_t watchdog_show(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[cpu_cpld].client, 0x7); + if (ret < 0) + return sprintf(buf, "read error"); + data = ret; + + return sprintf(buf, "%x\n", data); +} + +static ssize_t watchdog_store(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + s32 ret, err; + unsigned long val; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 10, &val); + if (err) + return err; + + if (data) + { + ret = i2c_smbus_write_byte_data(pdata[cpu_cpld].client, 0x7, data); + if (ret < 0) + return ret; + } + + return count; +} static ssize_t power_good_show(struct device *dev, struct device_attribute *devattr, char *buf) @@ -947,6 +982,7 @@ static DEVICE_ATTR_RO(psu1_prs); static DEVICE_ATTR_RO(psu0_status); static DEVICE_ATTR_RO(psu1_status); static DEVICE_ATTR_RW(system_led); +static DEVICE_ATTR_RW(watchdog); static DEVICE_ATTR_RW(locator_led); static DEVICE_ATTR_RW(power_led); static DEVICE_ATTR_RW(master_led); @@ -988,6 +1024,7 @@ static struct attribute *n3248pxe_cpld_attrs[] = { &dev_attr_psu0_status.attr, &dev_attr_psu1_status.attr, &dev_attr_system_led.attr, + &dev_attr_watchdog.attr, &dev_attr_locator_led.attr, &dev_attr_power_led.attr, &dev_attr_master_led.attr, diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248pxe/sonic_platform/watchdog.py b/platform/broadcom/sonic-platform-modules-dell/n3248pxe/sonic_platform/watchdog.py index 876aa4beda5..00277c2872f 100644 --- a/platform/broadcom/sonic-platform-modules-dell/n3248pxe/sonic_platform/watchdog.py +++ b/platform/broadcom/sonic-platform-modules-dell/n3248pxe/sonic_platform/watchdog.py @@ -11,7 +11,6 @@ try: import ctypes - import subprocess from sonic_platform_base.watchdog_base import WatchdogBase except ImportError as e: raise ImportError(str(e) + "- required module not found") @@ -29,43 +28,53 @@ class Watchdog(WatchdogBase): Abstract base class for interfacing with a hardware watchdog module """ - TIMERS = [15,20,30,40,50,60,65,70] + TIMERS = [15,20,30,40,50,60,65,70,80,100,120,140,160,180,210,240] armed_time = 0 timeout = 0 CLOCK_MONOTONIC = 1 def __init__(self): + WatchdogBase.__init__(self) self._librt = ctypes.CDLL('librt.so.1', use_errno=True) self._clock_gettime = self._librt.clock_gettime self._clock_gettime.argtypes=[ctypes.c_int, ctypes.POINTER(_timespec)] + self.watchdog_reg = "watchdog" - def _get_command_result(self, cmdline): + def _get_cpld_register(self, reg_name): + # On successful read, returns the value read from given + # reg name and on failure rethrns 'ERR' + cpld_dir = "/sys/devices/platform/dell-n3248pxe-cpld.0/" + cpld_reg_file = cpld_dir + '/' + reg_name try: - proc = subprocess.Popen(cmdline.split(), stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - stdout = proc.communicate()[0] - proc.wait() - result = stdout.rstrip('\n') - except OSError: - result = None + with open(cpld_reg_file, 'r') as fd: + rv = fd.read() + except IOError : return 'ERR' + return rv.strip('\r\n').lstrip(' ') - return result + def _set_cpld_register(self, reg_name, value): + # On successful write, returns the value will be written on + # reg_name and on failure returns 'ERR' + + cpld_dir = "/sys/devices/platform/dell-n3248pxe-cpld.0/" + cpld_reg_file = cpld_dir + '/' + reg_name + + try: + with open(cpld_reg_file, 'w') as fd: + rv = fd.write(str(value)) + except Exception: + rv = 'ERR' + + return rv def _get_reg_val(self): - # 0x31 = CPLD I2C Base Address - # 0x07 = Watchdog Function Register - value = self._get_command_result("/usr/sbin/i2cget -y 601 0x31 0x07") - if not value: - return None - else: - return int(value, 16) + value = self._get_cpld_register(self.watchdog_reg).strip() + if value == 'ERR': return False + + return int(value,16) def _set_reg_val(self,val): - # 0x31 = CPLD I2C Base Address - # 0x07 = Watchdog Function Register - value = self._get_command_result("/usr/sbin/i2cset -y 601 0x31 0x07 %s" - % (val)) + value = self._set_cpld_register(self.watchdog_reg, val) return value def _get_time(self): @@ -93,7 +102,7 @@ def arm(self, seconds): """ timer_offset = -1 for key,timer_seconds in enumerate(self.TIMERS): - if seconds <= timer_seconds: + if seconds > 0 and seconds <= timer_seconds: timer_offset = key seconds = timer_seconds break @@ -101,40 +110,29 @@ def arm(self, seconds): if timer_offset == -1: return -1 - # Extracting 5th to 7th bits for WD timer values - # 000 - 15 sec - # 001 - 20 sec - # 010 - 30 sec - # 011 - 40 sec - # 100 - 50 sec - # 101 - 60 sec - # 110 - 65 sec - # 111 - 70 sec + # Extracting 5th to 8th bits for WD timer values reg_val = self._get_reg_val() - wd_timer_offset = (reg_val >> 4) & 0x7 + wd_timer_offset = (reg_val >> 4) & 0xF if wd_timer_offset != timer_offset: - # Setting 5th to 7th bits + # Setting 5th to 8th bits # value from timer_offset self.disarm() - self._set_reg_val(reg_val | (timer_offset << 4)) + self._set_reg_val((reg_val & 0x0F) | (timer_offset << 4)) if self.is_armed(): # Setting last bit to WD Timer punch # Last bit = WD Timer punch self._set_reg_val(reg_val & 0xFE) - self.armed_time = self._get_time() - self.timeout = seconds else: # Setting 4th bit to enable WD # 4th bit = Enable WD reg_val = self._get_reg_val() self._set_reg_val(reg_val | 0x8) - self.armed_time = self._get_time() - self.timeout = seconds - + self.armed_time = self._get_time() + self.timeout = seconds return seconds def disarm(self): @@ -207,4 +205,3 @@ def get_remaining_time(self): return self.timeout - diff_time return 0 - diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/modules/dell_n3248te_platform.c b/platform/broadcom/sonic-platform-modules-dell/n3248te/modules/dell_n3248te_platform.c index f7a13c2a739..92ee30af312 100644 --- a/platform/broadcom/sonic-platform-modules-dell/n3248te/modules/dell_n3248te_platform.c +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/modules/dell_n3248te_platform.c @@ -572,7 +572,7 @@ static ssize_t system_led_show(struct device *dev, struct device_attribute *deva if (ret < 0) return sprintf(buf, "read error"); - data = (u8)(ret & 0x30) >> 5; + data = (u8)(ret & 0x30) >> 4; switch (data) { @@ -878,6 +878,42 @@ static ssize_t fan_led_store(struct device *dev, struct device_attribute *devatt return count; } +static ssize_t watchdog_show(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[cpu_cpld].client, 0x7); + if (ret < 0) + return sprintf(buf, "read error"); + data = ret; + + return sprintf(buf, "%x\n", data); +} + +static ssize_t watchdog_store(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + s32 ret, err; + unsigned long val; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 10, &val); + if (err) + return err; + + data = (u8) val; + if (data) + { + ret = i2c_smbus_write_byte_data(pdata[cpu_cpld].client, 0x7, data); + if (ret < 0) + return ret; + } + + return count; +} static ssize_t power_good_show(struct device *dev, struct device_attribute *devattr, char *buf) @@ -974,6 +1010,7 @@ static DEVICE_ATTR_RO(psu1_prs); static DEVICE_ATTR_RO(psu0_status); static DEVICE_ATTR_RO(psu1_status); static DEVICE_ATTR_RW(system_led); +static DEVICE_ATTR_RW(watchdog); static DEVICE_ATTR_RW(locator_led); static DEVICE_ATTR_RW(power_led); static DEVICE_ATTR_RW(master_led); @@ -1017,6 +1054,7 @@ static struct attribute *n3248te_cpld_attrs[] = { &dev_attr_psu0_status.attr, &dev_attr_psu1_status.attr, &dev_attr_system_led.attr, + &dev_attr_watchdog.attr, &dev_attr_locator_led.attr, &dev_attr_power_led.attr, &dev_attr_master_led.attr, diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/watchdog.py b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/watchdog.py index ebd4706b421..1e077e45d12 100644 --- a/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/watchdog.py +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/watchdog.py @@ -11,7 +11,6 @@ try: import ctypes - import subprocess from sonic_platform_base.watchdog_base import WatchdogBase except ImportError as e: raise ImportError(str(e) + "- required module not found") @@ -29,43 +28,53 @@ class Watchdog(WatchdogBase): Abstract base class for interfacing with a hardware watchdog module """ - TIMERS = [15,20,30,40,50,60,65,70] + TIMERS = [15,20,30,40,50,60,65,70,80,100,120,140,160,180,210,240] armed_time = 0 timeout = 0 CLOCK_MONOTONIC = 1 def __init__(self): + WatchdogBase.__init__(self) self._librt = ctypes.CDLL('librt.so.1', use_errno=True) self._clock_gettime = self._librt.clock_gettime self._clock_gettime.argtypes=[ctypes.c_int, ctypes.POINTER(_timespec)] + self.watchdog_reg = "watchdog" - def _get_command_result(self, cmdline): + def _get_cpld_register(self, reg_name): + # On successful read, returns the value read from given + # reg name and on failure rethrns 'ERR' + cpld_dir = "/sys/devices/platform/dell-n3248te-cpld.0/" + cpld_reg_file = cpld_dir + '/' + reg_name try: - proc = subprocess.Popen(cmdline.split(), stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - stdout = proc.communicate()[0] - proc.wait() - result = stdout.rstrip('\n') - except OSError: - result = None + with open(cpld_reg_file, 'r') as fd: + rv = fd.read() + except IOError : return 'ERR' + return rv.strip('\r\n').lstrip(' ') - return result + def _set_cpld_register(self, reg_name, value): + # On successful write, returns the value will be written on + # reg_name and on failure returns 'ERR' + + cpld_dir = "/sys/devices/platform/dell-n3248te-cpld.0/" + cpld_reg_file = cpld_dir + '/' + reg_name + + try: + with open(cpld_reg_file, 'w') as fd: + rv = fd.write(str(value)) + except Exception: + rv = 'ERR' + + return rv def _get_reg_val(self): - # 0x31 = CPLD I2C Base Address - # 0x07 = Watchdog Function Register - value = self._get_command_result("/usr/sbin/i2cget -y 601 0x31 0x07") - if not value: - return None - else: - return int(value, 16) + value = self._get_cpld_register(self.watchdog_reg).strip() + if value == 'ERR': return False + + return int(value,16) def _set_reg_val(self,val): - # 0x31 = CPLD I2C Base Address - # 0x07 = Watchdog Function Register - value = self._get_command_result("/usr/sbin/i2cset -y 601 0x31 0x07 %s" - % (val)) + value = self._set_cpld_register(self.watchdog_reg, val) return value def _get_time(self): @@ -93,7 +102,7 @@ def arm(self, seconds): """ timer_offset = -1 for key,timer_seconds in enumerate(self.TIMERS): - if seconds <= timer_seconds: + if seconds > 0 and seconds <= timer_seconds: timer_offset = key seconds = timer_seconds break @@ -101,41 +110,30 @@ def arm(self, seconds): if timer_offset == -1: return -1 - # Extracting 5th to 7th bits for WD timer values - # 000 - 15 sec - # 001 - 20 sec - # 010 - 30 sec - # 011 - 40 sec - # 100 - 50 sec - # 101 - 60 sec - # 110 - 65 sec - # 111 - 70 sec + # Extracting 5th to 8th bits for WD timer values reg_val = self._get_reg_val() - wd_timer_offset = (reg_val >> 4) & 0x7 + wd_timer_offset = (reg_val >> 4) & 0xF if wd_timer_offset != timer_offset: - # Setting 5th to 7th bits + # Setting 5th to 8th bits # value from timer_offset self.disarm() - self._set_reg_val(reg_val | (timer_offset << 4)) + self._set_reg_val((reg_val & 0x0F) | (timer_offset << 4)) if self.is_armed(): # Setting last bit to WD Timer punch # Last bit = WD Timer punch self._set_reg_val(reg_val & 0xFE) - self.armed_time = self._get_time() - self.timeout = seconds - return seconds else: # Setting 4th bit to enable WD # 4th bit = Enable WD reg_val = self._get_reg_val() self._set_reg_val(reg_val | 0x8) - self.armed_time = self._get_time() - self.timeout = seconds - return seconds + self.armed_time = self._get_time() + self.timeout = seconds + return seconds def disarm(self): """ @@ -183,7 +181,7 @@ def get_remaining_time(self): their watchdog timer. If the watchdog is not armed, returns -1. - S5232 doesnot have hardware support to show remaining time. + N3248PXE doesnot have hardware support to show remaining time. Due to this limitation, this API is implemented in software. This API would return correct software time difference if it is called from the process which armed the watchdog timer. @@ -207,4 +205,3 @@ def get_remaining_time(self): return self.timeout - diff_time return 0 -